Счетчик импульсов

avgustdon
Offline
Зарегистрирован: 28.02.2016

Задача считать на СОМ порте количество импульсов. Код простой до безобразия, но что-то не так и сам разобраться не могу. Проблема в том, иногда все же проскакивает дребезг ну и к этому тоже иногда тупо не обращает внимания на нажатие кнопки. Подскажите, плиз, что не так. Скетч создал из гругого скетча, где данные выводятся на LCD дисплей. Оригинал работает великолепно. Просто удалил то, что относится к дисплею и начались сбои.


#define button   A1  // вывод контроллера для кнопки
int count = 0;         // переменная для подсчета нажатий на кнопку
int button_old = 1;    // предыдущее значение входа для отлавливания момента нажатия

void setup() 
{  
  //pinMode(button, INPUT_PULLUP);
  Serial.begin(9600); // Запускаем последовательный порт
}
void loop()
  {
  if ((digitalRead(button) == LOW)&&(button_old == 1))
  { 
    count = count + 1;
    //Serial.println("count");
    Serial.println(count);
       delay(200);

   }
  button_old = digitalRead(button); 
  }

вот мой скетч

Araris
Offline
Зарегистрирован: 09.11.2012

Напрасно убрали pinMode(button, INPUT_PULLUP);

andriano
andriano аватар
Offline
Зарегистрирован: 20.06.2015

1. Вы за один проход цикла дважды считываете состояние пина. И нет никаких гарантий, что будет считано одно и то же состояние.

2. Какая-то эклектика у Вас в логических выражениях.

3. А если длительнеость импульса будет менее 0.2с?

qwone
qwone аватар
Онлайн
Зарегистрирован: 03.07.2016

Рабочий код. Извини если помешал вашему творчеству.

#define buttonPin   A1  // вывод кнопки 0 нажата 1 нет
uint8_t count,button,button_old; // переменные: кол-во нажатий клавиш,состояние нажатие клавиши сейчас и раньше

void setup() 
{  
  Serial.begin(9600); // Запускаем последовательный порт
  count =0; // счет с нуля
  pinMode(buttonPin, INPUT_PULLUP); // вывод на ввод с подтягивающим резистром 
  button_old = digitalRead(buttonPin);  
}
void loop()
 {
delay(30); // задержка защита от дребезга
  button = digitalRead(buttonPin);  
  if ((button == 0)&&(button_old ==1 )) //  счет по фронту
   { 
    count = count + 1;
    Serial.println(count);
   };
  button_old=button; 
 }

 

avgustdon
Offline
Зарегистрирован: 28.02.2016

 qwone, низкий поклон. Работает отлично. Еще один пример в мою копилку знаний. Лучше поздно, чем никогда. Это я про себя ))

andriano
andriano аватар
Offline
Зарегистрирован: 20.06.2015

qwone пишет:

Рабочий код. Извини если помешал вашему творчеству.

#define buttonPin   A1  // вывод кнопки 0 нажата 1 нет
uint8_t count,button,button_old; // переменные: кол-во нажатий клавиш,состояние нажатие клавиши сейчас и раньше

void setup() 
{  
  Serial.begin(9600); // Запускаем последовательный порт
  count =0; // счет с нуля
  pinMode(buttonPin, INPUT_PULLUP); // вывод на ввод с подтягивающим резистром 
  button_old = digitalRead(buttonPin);  
}
void loop()
 {
delay(30); // задержка защита от дребезга
  button = digitalRead(buttonPin);  
  if ((button == 0)&&(button_old ==1 )) //  счет по фронту
   { 
    count = count + 1;
    Serial.println(count);
   };
  button_old=button; 
 }

Нет, все нормально, только я бы записал чуть короче:

  button = digitalRead(buttonPin);  
  if (!button&&button_old) //  счет по фронту
    Serial.println(++count);
  button_old=button; 

 

qwone
qwone аватар
Онлайн
Зарегистрирован: 03.07.2016

Вот только ваша запись она для продвинутых. А обычная аудитория не умеет даже писать (хэ- хэ) на Си. Так что пишу как проще. Хотя пусть будет.

Coolerr
Offline
Зарегистрирован: 30.06.2014

andriano

Опа, а подскажите по записи. Как я понял запись (!button) равнозначна (button==0)? Верно? Т.е. если я напишу if(digitalRead(!нога)) будет фактически означать if(digitalRead(нога==0)), а (нога) подразумевает (нога==1)?

 

qwone
qwone аватар
Онлайн
Зарегистрирован: 03.07.2016

Сoolerr  немного не так. 

if 1    // условие выполняется
if 0   // условие не выполняется

А дальше Битовая математика  ! это НЕ   &&  это Битовое И

ПС: вот по этой причине я для постороних так не пишу, хотя короче

ППС : 

 if(digitalRead(!нога)) // не верно
 if(!digitalRead(нога))  // так верно

 

andriano
andriano аватар
Offline
Зарегистрирован: 20.06.2015

Coolerr, в Си нет специального булева типа переменных как, например, а Паскале. Вместо них используются обычные целые, причем равные 0 рассматриваются как "ложь", а все остальное - как "истина". Поэтому, строго говоря, первая ваша гипотеза верна, а вторая - в общем случае нет: если, скажем, (нога==2), то (нога) будет рассматриваться как "истина", хотя выражение (нога==1) явно неверно, и будет рассматриваться как "ложь".

Но т.к. то, что Вы подразумеваете под (нога) может принимать только два значения: 0 и 1, в этом частном случае - да, оба выражения эквивалентны. Но только в частном случае.

PS. Посмотрел опередившее меня сообщение qwone - да, это верно, а я немного поторопился, не вникнув. Если "нога" - это номер пина, то так писать нельзя, а я написал в предположении, что "нога" - это значение, считанное с определенного пина.

Т.е. такое можно делать только для переменных, принимающих только 2 значения (булевых). Для остальных (числовых) - в общем случае нет. Но иногда бывает, что удобно и для числовых. Но это нужно понимать, что делаешь и зачем.

PPS. qwone, только не "битовые", а "булевы(е)". Тут, опять же, специфика Си по сравнению с тем же Паскалем: т.к. в Си целые и булевы не различаются, приходится употреблять разные обозначения для битовых и булевых операций.

Coolerr
Offline
Зарегистрирован: 30.06.2014

qwone

Спасибо. А ещё вопрос, компилятор в том и в другом случае хекс одинаковых размеров накомпилит? И где бы наглядно об этих выкрутасах почитать? Сам пишу только наглядно ибо по другому не умею, но хочется иногда сократить количество писанины.

andriano

Спасибо за более развернутый ответ, про пины понял. То есть если моя переменная может принимать только два значения булевы true или false я могу использовать такой вид записи.

qwone
qwone аватар
Онлайн
Зарегистрирован: 03.07.2016

Мой совет не сокращай писанину. Компактней код - мудреный код. Долго писать, долго отлаживать. Потеря времени в итоге.

andriano
andriano аватар
Offline
Зарегистрирован: 20.06.2015

Coolerr, код будет отличаться по указанной мною причине: при (нога==2) реально будут выполняться другие действия. Т.к. компилятор не знает, что "нога" в Вашей программе не может принимать значение "2", он честно будет отрабатывать и этот вариант. Насчет длины, правда, не скажу, но это легко проверить.

andriano
andriano аватар
Offline
Зарегистрирован: 20.06.2015

qwone пишет:

Мой совет не сокращай писанину. Компактней код - мудреный код. Долго писать, долго отлаживать. Потеря времени в итоге.

Тут я полностью поддержу.

Дело даже не в том, мудреный код или нет, а нужно ХОРОШО понимать, тот код, которых пишешь. Поэтому лучше перестраховаться, если есть сомнения, и написать длиннее, но так, чтобы не оставлять места сомнениям.

Coolerr
Offline
Зарегистрирован: 30.06.2014

Понятно, есть куда совершенствоваться. Спасибо за ответы.