Счетчик количества сигналов

rrr111
Offline
Зарегистрирован: 04.10.2016

Доброго времени суток!
Подскажите, пожалуйста, новичку как запрограммировать счетчик количества сигналов на входе: т.е на несколько входов с рандомной и не постойнной частотой будут приходить сигналы, нужно посчитать количество пришедших сигналов на каждый вход и выводить сигнал на экран компьютера...
Я попытался написать скетч, но сегодня начал анализировать работу и понял, что ошибка моя в том, что я проверяю в "сработанном" ли состоянии входной сигнал, а сигнал может просто быть длительно подан и при этом мой счетчик будет постоянно считать, т.е работать скетч будет не верно...

Прошу подсказать, как правильно сделать счетчик импульсов для нескольких входных сигналов.

 

int vhod_A = 13; 

int vhod_B= 8; 

/*входы для принятия сигналов мигания того или иного выхода счетчика.*/


void setup ()

{

pinMode (vhod_A, INPUT);


pinMode (vhod_B, INPUT);


Serial.begin (9600);
}
void loop()

{

kol_A=0;

kol_B=0;


If (digitalRead (vhod_A) == HIGH)
{

kol_A++;
}

If (digitalRead (vhod_B) == HIGH)
{

kol_B++;

Serial.println (“kol_A”);
Serial.println (“kol_B”);
}

 

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Ну, если у Вас только два входа, повесьте их на прервания по RISING и считайте на здоровье.

rrr111
Offline
Зарегистрирован: 04.10.2016

входа всего будет 4... спасибо за информацию, посмотрю как использовать  RISING...
 

Будет ли работать скетч, если его подправить так:

If (digitalRead (vhod_A) == HIGH && digitalRead (vhod_A) == CHANGE)
{

kol_A++;
}

 

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Нет, конечно, с чего бы это digitalRead  возвращал что-либо отличное от HIGH и LOW.

если не пользоваться прерываниями, то Вам просто надо отдельно обрабатывать появление сигнала и ео исчезновение.

vvadim
Offline
Зарегистрирован: 23.05.2012

rrr111 пишет:

входа всего будет 4... спасибо за информацию, посмотрю как использовать  RISING...
 

Будет ли работать скетч, если его подправить так:

If (digitalRead (vhod_A) == HIGH && digitalRead (vhod_A) == CHANGE)
{

kol_A++;
}

 

 

почитайте

http://arduino.ru/Reference/AttachInterrupt

vosara
vosara аватар
Offline
Зарегистрирован: 08.02.2014

Попробуйте так

#define vhod_A 13
#define vhod_B 8
bool f_A;
bool f_B;

int kol_A;
int kol_B;

/*входы для принятия сигналов мигания того или иного выхода счетчика.*/


void setup () {
  pinMode (vhod_A, INPUT);
  pinMode (vhod_B, INPUT);
  Serial.begin (9600);
}
void loop() {

  if (digitalRead(vhod_A) == HIGH && f_A == 0) {
    f_A = 1;
    kol_A++;
  }
  else {
    f_A = 0;
  }

  if (digitalRead(vhod_B) == HIGH && f_B == 0) {
    f_B = 1;
    kol_B++;
  }
  else {
    f_B = 0;
  }

  Serial.print("kol_A - ");
  Serial.println(kol_A);
  Serial.print("kol_B - ");
  Serial.println(kol_B);
}

 

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

vosara. C флагом не очень удачно получилось. Не когда на входе O то счета не будет. А вот если 1 , то считать будет не сигналы а проходы loop(). Точнее 2 прохода +1 на счетчик.

  
  f2_A = f1_A;
  f1_A = digitalRead(vhod_A);
  if ( !f2_A && f1_A ) {
    kol_A++;
    Serial.print("kol_A - ");
    Serial.println(kol_A);
 }

 

vosara
vosara аватар
Offline
Зарегистрирован: 08.02.2014

qwone - Да Вы правы просмртрел исправил

#define vhod_A 13
#define vhod_B 8
bool f_A =0;
bool f_B=0;

int kol_A;
int kol_B;

/*входы для принятия сигналов мигания того или иного выхода счетчика.*/


void setup () {
  pinMode (vhod_A, INPUT_PULLUP);
  pinMode (vhod_B, INPUT_PULLUP);
  Serial.begin (9600);
}
void loop() {

  if (digitalRead(vhod_A) == LOW && f_A == 0) {
    f_A = 1;
    kol_A++;
 Serial.print("kol_A - ");
  Serial.println(kol_A);
  }
  else if (f_A == 1 && digitalRead(vhod_A) == HIGH) {
    f_A = 0;
  }

  if (digitalRead(vhod_B) == LOW && f_B == 0) {
    f_B = 1;
    kol_B++;
Serial.print("kol_B - ");
  Serial.println(kol_B);
  }
  else if (f_B == 1 && digitalRead(vhod_B) == HIGH) {
    f_B = 0;
  }

 
  
}

 

rrr111
Offline
Зарегистрирован: 04.10.2016

Спасибо за ответы!

при помощи attachInterrupt() можно на плате UNO сделать счетчик только для 2х входов , как я понял из описания.

Спасибо большое vosara  за скетч, проверю в ближайшие дни работоспособность счетчика, основанного на логике данного скетча.

 

Любопытно, какую максимальную частоту сможет "уследить" ардуино...

rrr111
Offline
Зарегистрирован: 04.10.2016

Попробовал залить скетч и что-то пошло не так...

Немного усложнил задачу - добавил дополнительное условие: при условии достижения счетчика (kol_A) мигания до 10 - записываем новое значение - количество детятков "миганий" (импульсов на входе), причем если мы запросим вводом любого значения в окно программы  - выдавать количество десятков импульсов, полученных на входе...

Скетч добавляю.

#define vhod_A 5
#define mig_A 10
float k=0;
int kol_A=0;
bool f_A=1;

void setup() {
  pinMode (vhod_A, INPUT);
  Serial.begin(9600); 
}
void loop()
{   
k= k+map(kol_A, 0, mig_A, 0, 1);

if (digitalRead (vhod_A) == HIGH && kol_A < mig_A && f_A==1)
{
kol_A++;
f_A=0;
}
else if (digitalRead (vhod_A) == LOW && kol_A < mig_A && f_A==0)
{
f_A=1;
}
if (kol_A == mig_A)
{
kol_A=0;
k++;
}
if (Serial.available())
    {
      Serial.println(k);
    }
}

 

 

1) Подаю 3,3 вольта с выхода ардуинки перемычкой на вход 5.

ПНапример, по моей логике, например, если я "закорочу" 3,3 В и 5вход 15 раз - должно на экране показать значение 1,5..

Выводит неверные значения - в чем ошибка, как исправить, подскажите, пожалуйста?

 

2) второй вопрос: как сделать чтобы выводилось значение на экран только однократно, а не постоянным потоком сообщений в диалоговом окне?

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

rrr111 пишет:

1) Подаю 3,3 вольта с выхода ардуинки перемычкой на вход 5.Например, по моей логике, например, если я "закорочу" 3,3 В и 5вход 15 раз - должно на экране показать значение 1,5.Выводит неверные значения - в чем ошибка, как исправить, подскажите, пожалуйста?

Вы что дурку гоняете. На вход надо подавать логический сигнал, а не напряжение 3,3V. Логический сигнал это 1 (5V) логический 0 (0V , точнее GND) . И вот у вас идет счет сколько раз был переход с 1 в 0. Не можете перемычкой, повесте кнопку с подтяжкой резистором на 5V/

rrr111
Offline
Зарегистрирован: 04.10.2016

Спасибо большое за ответ!

возможно "гоняю дурку")))) (пишу свою первую программу для ардуино), но при этом какие-то значения же выдает программа, но только не те, которые должна..

П.С. попробовал "закорачивать" 5В и вход 5 - аналогичная картина, не верные значения..

 

по поводу логического 0 - т.е логический ноль - это соединение 5 входа в GND, а не просто разрыв цепи (не просто раскорачивание 5В и входа №5)?

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

ну да 0 это когда на землю.   А вообще надо  5V -> резистор 10 кОм- > на вход 5 и вход 5-> кнопка -> GND. На кнопку нажимаешь. сигнал подаешь на вход.

Ну или так

 

vosara
vosara аватар
Offline
Зарегистрирован: 08.02.2014

"2) второй вопрос: как сделать чтобы выводилось значение на экран только однократно, а не постоянным потоком сообщений в диалоговом окне?"

Строчки с 29 по 32 меняем

static float f_k = 0;
if (f_k != k)
{
  Serial.println(k);
  f_k = k;
}

 

vosara
vosara аватар
Offline
Зарегистрирован: 08.02.2014

Я не совсем понял Вашу задачу но попробуйте такой код (хотя подтяжку нужно обязательно, так ка Вам подсказали выше)

#define vhod_A 5
#define mig_A 10
float k = 0;
float f_k = k;
int kol_A = 0;
bool f_A = 1;

void setup() {
  pinMode (vhod_A, INPUT);
  Serial.begin(9600);
}
void loop()
{
  //k= k+map(kol_A, 0, mig_A, 0, 1);

  if (digitalRead (vhod_A) == HIGH && kol_A < mig_A && f_A == 1)
  {
    kol_A++;
    if (kol_A == mig_A)
    {
      kol_A = 0;
      k++;
    }
    f_A = 0;
  }
  else if (digitalRead (vhod_A) == LOW && f_A == 0)
  {
    f_A = 1;
  }

  if (f_k != k)
  {
    Serial.println(k);
    f_k = k;
  }
}



 

rrr111
Offline
Зарегистрирован: 04.10.2016

vosara пишет:

 

  //k= k+map(kol_A, 0, mig_A, 0, 1);
эта строка обязательна. Например,при наличии 17-ти входных импульсов, переменная "к" должна быть равна 1,7.
vosara пишет:
if (digitalRead (vhod_A) == HIGH && kol_A < mig_A && f_A == 1) { kol_A++; if (kol_A == mig_A) { kol_A = 0; k++; } f_A = 0; }

Эти два условия, как я понимаю, противоречат друг другу, поэтому не будет работать второй цикл "if", т.к один цикл находится внутри другого...

Поэтому второй вопрос (как сделать вывод информации однократным) остался пока что открытым..

П.с. пока что не пробовал  правильно подключить плату через сопротивление и кнопку, возможно, это поможет выводить значение с десятыми долями (как , например, я выше писал в примере 1,7 при количестве входных сигналов =17)

 

п.п.с. можно ли сделать так: если с клавиатуры вводим 1, то выводим в окне значение "к" и сразу же "присваиваем" введенному значению !=1  ?

#define vhod_A 5
#define mig_A 10
float k=0;
int kol_A=0;
bool f_A=1;

void setup() {
  pinMode (vhod_A, INPUT);
  Serial.begin(9600); 
}
void loop()
{   

if (digitalRead (vhod_A) == HIGH && kol_A < mig_A && f_A==1)
{
kol_A++;
f_A=0;
}
else if (digitalRead (vhod_A) == LOW && kol_A < mig_A && f_A==0)
{
f_A=1;
}
if (kol_A == mig_A)
{
kol_A=0;
k++;
}
k= k+map(kol_A, 0, mig_A, 0, 1);
if (Serial.available() == '1')
    {
      Serial.println(k);
      Serial.available() != '1'; /*возможно, этот кусокс 29 строки поможет однократно выводить показания "k"*/
    }
}

также переставил значение в конец сскетча - так будет более правильно, как мне кажется

k= k+map(kol_A, 0, mig_A, 0, 1);

 

vosara
vosara аватар
Offline
Зарегистрирован: 08.02.2014

Однократный вывод я описал в №13пост а в 14 это реализовано. Вы что не смотрели? По поводу счетчика: kol_A - у Вас единицы а к- десятки, как их обьеденить это просто математика - умножте додайте разделите и получите при 17 тиках 1,7 

ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

qwone пишет:

rrr111 пишет:

1) Подаю 3,3 вольта с выхода ардуинки перемычкой на вход 5.Например, по моей логике, например, если я "закорочу" 3,3 В и 5вход 15 раз - должно на экране показать значение 1,5.Выводит неверные значения - в чем ошибка, как исправить, подскажите, пожалуйста?

Вы что дурку гоняете. На вход надо подавать логический сигнал, а не напряжение 3,3V. Логический сигнал это 1 (5V) логический 0 (0V , точнее GND) . И вот у вас идет счет сколько раз был переход с 1 в 0. Не можете перемычкой, повесте кнопку с подтяжкой резистором на 5V/

вообще-то для TTL 5V логики логический ноль это напряжение от 0,8 до 1,2 вольта, логическая единица, от 2,4 вольта до 5 (4,8) вольт

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

ua6em пишет:

вообще-то для TTL 5V логики логический ноль это напряжение от 0,8 до 1,2 вольта, логическая единица, от 2,4 вольта до 5 (4,8) вольт

И что вы остановились. Раскажите про устройство входных и выходных каскадов логическим микросхем, про втекающие и вытекающие тока и также многое другое в 10 тысяч знаков. Спросите зачем? Просветите человека, подающего сигнал с 3,3В. Я просто прикинул объем информации который надо освоить ТС, и на который он тупо "забъет".  Может вы продолжите "просвещать новичков", которые не знают что такое Гугл и как надо "добывать информацию".

ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

qwone пишет:

ua6em пишет:

вообще-то для TTL 5V логики логический ноль это напряжение от 0,8 до 1,2 вольта, логическая единица, от 2,4 вольта до 5 (4,8) вольт

И что вы остановились. Раскажите про устройство входных и выходных каскадов логическим микросхем, про втекающие и вытекающие тока и также многое другое в 10 тысяч знаков. Спросите зачем? Просветите человека, подающего сигнал с 3,3В. Я просто прикинул объем информации который надо освоить ТС, и на который он тупо "забъет".  Может вы продолжите "просвещать новичков", которые не знают что такое Гугл и как надо "добывать информацию".

Не запутывайте человека, логические 0 и 1 это не 5V и GND я об этом. В какой-то момент он всё равно полезет с тестером по ножкам и будет сильно удивлён, а знание направления токов убережёт от схемотехнических ошибок, это я вам как наладчик станков с чпу 8 разряда по сетке СССР говорю )))

rrr111
Offline
Зарегистрирован: 04.10.2016

Решил начать с малого: для начала попробовать собрать "счетчик десятков" через RISING.

скетч:

int mig_A=10.00;
float k=0.00;

int kol_A=0.00;
void setup() {
  Serial.begin(9600);
  attachInterrupt(1, blink, RISING);
}
void loop()
{
}
void blink()
{

kol_A+=1.00;
k= kol_A/10.00;

      Serial.println(k);
}

Получилось все, если не считать малого:

выводит значения не " +0,1 ", а "+0.2...0,5" - я так понимаю, из-за дребезга кнопки... Схему в принципе собрал с учетом советов в данной ветке "надо  5V -> резистор 10 кОм- > на вход 5 и вход 5-> кнопка -> GND.", добавил еще один резистор между выводом 3 и землей резистор в 10 кОм (правильно ли подключил подтягивающий резистор?)

Подскажите, пожалуйста, как избавиться (возможно программно или при помощи верного подключения схемы) от излишних прибавлений (дребезга контактов)?

 

Еще раз всем спасибо за помощь и наставления!

p.masyukov
p.masyukov аватар
Offline
Зарегистрирован: 14.11.2015

Если импульсы должны обязательно менять состояние - то вешай флаги (можно в прерываниях) и отключать при смене состояния, всё зависит от частоты импульсов.

// Нажатие кнопки
if(digitalRead(2) == LOW && flag_block == 0)  flag_block = 1; 

 // Отпускание кнопки
 if(digitalRead(2) == HIGH && flag_block == 1) 
{
flag_block = 0;
// тут твой сигнал завершился, независимо от длинны
}

Так же можно и на аналоговых входах.

Kairos
Offline
Зарегистрирован: 21.09.2016

Если в конечной схеме дребезга не будет, то вместо кнопок запрограмьте во вторую ардуину генератор импульсов. 

 

rrr111
Offline
Зарегистрирован: 04.10.2016

Здравствуйте!
Решил проблему с дребезгом. Установил выдержку времени и дополнительную проверку на наличие сигнала на входе. Итоговый скетч получился такой:

int mig_A=10.00;

float k=0.00;
int x=0.00;
int kol_A=0.00;

void setup() {

  Serial.begin(9600);

  attachInterrupt(1, blink, RISING);

}

void loop()

{

}

void blink()

{
  delay(100);//выдержка от дребезга кнопки
  if (digitalRead(3) == HIGH)//дополнительная проверка
  {
kol_A+=1.00;

k= x+kol_A/10.00;
if (kol_A == 10.00)
{
  kol_A=0.00;
  x++;
}
  
Serial.println(k);
  }
}

Всем спасибо за консультации по данному вопросу, очень помогли!

rrr111
Offline
Зарегистрирован: 04.10.2016

Возник еще один вопрос, будьте добры, подскажите..
Если контроллер будет выполнять какую-либоо функцию (например, отправлять смс - занимает около 4,5 секунды, т.к имеются delay(500) 5 раз и в конце отправки delay (2000) ) в момент когда произойдет прерывание, то какова логика работы ?

1) Остановится отправка смс и программа перейдет в цикл RISING, затем продолжит отправку смс

2) Остановится отправка смс и программа перейдет в цикл RISING, затем продолжит не отправку смс, а пойдет программа по общему циклу loop сначала

3) НЕ остановится отправка смс, но программа увидит прерывание и перейдет в цикл RISING сразу после заверщения отправки смс

4) НЕ остановится отправка смс, и это прерывание программа не увидит

5) Другой вариант (подскажите какой)

 

Благодарен вам за помощь в ответе на вопрос

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

Не знаю, что есть "цикл RISING", но голосую за вариант № 1.

Аргументирую : https://sites.google.com/site/vanyambauseslinux/arduino/ispolzovanie-preryvanij-arduino

"При возврате из функции, вызванной по прерыванию, происходит так называемый возврат из прерывания, и управление передаётся тому шагу программы, который должен был быть выполнен следующим до прерывания."

rrr111
Offline
Зарегистрирован: 04.10.2016

Спасибо за ответ и ссылку, почитал стало понятнее (функция внешнего прерывания является в приоритете над другими функциями).
Да, спасибо за поправку, не цикл RISING, а функция attachInterrupt()

Но осталось небольшое сомнение, будет ли программа переходить к функции attachInterrupt(), если программа находится в "режиме ожидания" (т.е если уже успело задаться delay(500), но прошло еще только 300 мс, например, и появилось внешнее прерывание) , тогда программа перейдет к функции прерывания, а затем вернется к delay и выждет оставшиеся 200 мс? или же сначала выполнит до конца delay(500), а затем уже перейдет к ф-ции внешнего прерывания?

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

rrr111 пишет:

Спасибо за ответ и ссылку, почитал стало понятнее (функция внешнего прерывания является в приоритете над другими функциями).
Да, спасибо за поправку, не цикл RISING, а функция attachInterrupt()

Но осталось небольшое сомнение, будет ли программа переходить к функции attachInterrupt(), если программа находится в "режиме ожидания" (т.е если уже успело задаться delay(500), но прошло еще только 300 мс, например, и появилось внешнее прерывание) , тогда программа перейдет к функции прерывания, а затем вернется к delay и выждет оставшиеся 200 мс? или же сначала выполнит до конца delay(500), а затем уже перейдет к ф-ции внешнего прерывания?

У Вас каша в голове.

Программа никогда не переходит к функции attachInterrupt, кроме как естественным последовательным путём.

Переходит к функции обрабочику.

По поводу же Ваших сомнений - они тоже следствие каши. Запомните просто правило:

Когда происходит прерывание (если они разрешены), то программа, чтобы она не делала, немедленно прерывается и исполняется обработчик прерывания. Сразу же после завершения исполнения обработчика, программа продолжает своё исполнение в точности с того места где прервалась.

Всё! Больше там нет ничего и не надо ничего дополнительного выдумывать.

А теперь сами ответьте на свои смонения.

rrr111
Offline
Зарегистрирован: 04.10.2016

ЕвгенийП пишет:

Запомните просто правило:

Когда происходит прерывание (если они разрешены), то программа, чтобы она не делала, немедленно прерывается и исполняется обработчик прерывания. Сразу же после завершения исполнения обработчика, программа продолжает своё исполнение в точности с того места где прервалась.

 

Понял, доступно объяснили, Правило запомнил. Спасибо!))

rrr111
Offline
Зарегистрирован: 04.10.2016

Отстраиваюсь от дребезга кнопки при blink'ах и не получается добиться правильной работы счетчика количества сигналов пришедших на второй пин ардуино уно (скетч в сообщении #23 не верно считает). Сделал новый кусок скетча, который отстраивает от дреезга кнопки (использует не работоспособность миллис в цикле блинк и отстраивается 100 миллисекундами от дребезга). НО остался "глюк" программы - иногда проскакивает добавление к переменной "К" в момент перехода кнопки из HIGH в LOW - с чем это может быть связано (возможно, это происходит при перещелкивании кнопки с задержкой в состоянии HIGH менее 100 мс?)? Подскажите, пожалуйста, в чем может быть ошибка (скетч прикрепляю)?

int K=0;
void setup()
{
  Serial.begin(9600);
  attachInterrupt(0, blink, RISING);
}
void loop()
{ 
}

void blink()
{
  static unsigned long millis_prev;
  if(millis()-100 > millis_prev) 
  {
  K++;    
  millis_prev = millis();
  Serial.println(K);  
 }        
}

 

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

Принципиальная ошибка.Ну кто так организовывает антидребезг.

//rrr111.ino
int K = 0;
void setup() {
  Serial.begin(9600);
  attachInterrupt(0, blink, RISING);
}
void loop() {
}

void blink() {
  static unsigned long past;
  if (millis() - past > 5) {// если пошел сигнал и время дребезга от пред сигнала прошло
    past = millis();
    K++;
    Serial.println(K);
  }
}

 

rrr111
Offline
Зарегистрирован: 04.10.2016

qwone пишет:

Принципиальная ошибка.Ну кто так организовывает антидребезг.

//rrr111.ino
int K = 0;
void setup() {
  Serial.begin(9600);
  attachInterrupt(0, blink, RISING);
}
void loop() {
}

void blink() {
  static unsigned long past;
  if (millis() - past > 5) {// если пошел сигнал и время дребезга от пред сигнала прошло
    past = millis();
    K++;
    Serial.println(K);
  }
}

 

 

У меня в скетче то же самое, Вы слагаемые лишь местами поменяли (и выдержку меньше взяли). Загрузив Ваш скетч, проблема (иногда добавляет единицу при размыкании кнопки - это не совсем дребезг получается, т.к добавляется стабильно ровно 1 при замыкании кнопки. А проблема именно в том, что иногда добавляется единица при размыкании) осталась, к сожалению. В чем может быть еще загвоздка (подключение как в сообщении #12 - фото добавляю)?

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

Это полный П**Ц.  Ну у вас не кнопка, а ПЕРЕКЛЮЧАТЕЛЬ.  И дребезг у него не только при нажатии, но и отжатии.  И только полный Д***Н(зачеркто) "новичок" использует при этом прерывание, а не просто опрос.

/*//rrr111_v2.ino
  #1 кнопка1 -> 2 (btn1_pin) 0 нажата /1 нет
*/
// #1
const int btn1_pin = 2; // вывод кнопки
bool btn1, btn1_old; // значение на кнопке без дребезга, тоже но стар значение
bool bounce_btn1 = 0; // антидребезговый флаг
int K = 0;
void setup() {
  Serial.begin(9600);
  // #1
  pinMode(btn1_pin, INPUT_PULLUP); // подключить кнопку 1 с подтяжкой
  btn1 = digitalRead(btn1_pin);

}

void loop() {
  // #1
  static uint32_t past_1 = 0 ;
  if (! bounce_btn1 && btn1 != digitalRead(btn1_pin)) { // если прошел фронт изм на выводн
    bounce_btn1 = 1;                                 // выставить флаг
    past_1 = millis();                          // сделать временую засветку
  }
  else if ( bounce_btn1 && millis() - past_1 >= 5 ) { // если прошло антидребезговое время
    bounce_btn1 = 0;      // то снять флаг
    btn1_old = btn1;
    btn1 = digitalRead(btn1_pin) ;           // прочитать реальное значение на выводе
    if (btn1_old && ! btn1) {
      K++;
      Serial.println(K);
    }
  }
}

 

rrr111
Offline
Зарегистрирован: 04.10.2016

Спасибо за ответ (отдельное спасибо- за критику ))))
Буду подключать внешнее реле с оптронами и пока не знаю как оно будет считаться (как кнопка или как переключатель) , т.к еще реле не пробовал подключать , хотел испытать сначала на кнопке (вернее на переключателе)

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

Ну и с прерыванием. Которое тут как собаке 5 нога.

/*//rrr111_v2.ino
  #1 кнопка1 -> 2 (btn1_pin) 0 нажата /1 нет
*/
// #1
const int btn1_pin = 2; // вывод кнопки
bool btn1, btn1_old; // значение на кнопке без дребезга, тоже но стар значение
bool bounce_btn1 = 0; // антидребезговый флаг
int K = 0;
volatile unsigned long past;
void blink() {
  past = millis();
  bounce_btn1 = 1; // выставить флаг
}
void setup() {
  Serial.begin(9600);
  // #1
  attachInterrupt(0, blink, RISING);
  pinMode(btn1_pin, INPUT_PULLUP); // подключить кнопку 1 с подтяжкой
  btn1 = digitalRead(btn1_pin);
}
void loop() {
  // #1
  if ( bounce_btn1 && millis() - past >= 5 ) { // если прошло антидребезговое время
    bounce_btn1 = 0;      // то снять флаг
    btn1_old = btn1;
    btn1 = digitalRead(btn1_pin) ;           // прочитать реальное значение на выводе
    if (!btn1_old && btn1) {
      K++;
      Serial.println(K);
    }
  }
}

ПС: глючная конструкция.

В этом случает я использую такую конструкцию полный скеч здесь https://yadi.sk/d/TKzsHCyL3Bbehz

А головной файл без довеска такой.

/* Class_do_btn_dn_up_dn_up.ino
 *  https://yadi.sk/d/TKzsHCyL3Bbehz
  #1 кнопка ->2
  Принцип кода:нажал на кнопку , отправилось одно сообщение в сериал
               отпустил  кнопку , отправилось другое сообщение в сериал
*/
//#1 кнопка 1
#include "Cl_do_btn_dn_up.h"
const byte btn1_pin = 2;
Cl_do_btn_dn_up Do_btm1; // создать
void func_down() {
  Serial.println("Press Bottom 1 Down");
}
void func_up() {
  Serial.println("Press Bottom 2 Up");
}
void setup() {
  Serial.begin(9600);
  //#1 кнопка 1
  Do_btm1.logic=0;// когда 0 это нажатая кнопка
  Do_btm1.setup(btn1_pin);
}
void loop() {
  //#1 кнопка 1
  Do_btm1.loop(& func_down , & func_up );
}

 

rrr111
Offline
Зарегистрирован: 04.10.2016

Спасибо большое за скетчи!
Где можно подробнее почитать про использованную в последнем скетче библиотеку (интересно как будет вести себя программа при наличии двух переключателях и одновременном их переключении - будут выполняться функции для 2х переключателей поочередно(если да, то в каком порядке - который раньше объявлен в программе? если нет, то как поведет себя программа)?

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

Ну вы загнули. Библиотека самопал. Одновременно кнопки не сработают никогда. Может они и сработают, но опрос будет не одновременно. Так что та что 1 опросили , та и первая будет. Опять же алгоритм псевдопараллельный. Это значит, что если поставите тормоза в виде делай на 1 день, или час, то работа зависнет на этот же час.

Вот еще вариант  Полный скетч здесь https://yadi.sk/d/WT0l3qE23AKXKx , а головной файл сюда кину.

/* class_do_keys_4х4.ino
 *  https://yadi.sk/d/WT0l3qE23AKXKx
  #1 клавиатура 4x4
          строки->2,3,4,5 выхода
          колонки->6,7,8,9 входа
           {'1','2','3','A'},
           {'4','5','6','B'},
           {'7','8','9','C'},
           {'*','0','#','D'}
 Принцип кода:При нажатии на соответствующую кнопку выполняется соответсвующее действие
*/
//#1 клавиатура 4x4
#include "Cl_do_keys_4x4.h"
Cl_do_keys_4x4 do_keys_4x4; // создать клавиатуру 4х4
void func_1(void) {
  Serial.println("do Func 1");
}
void func_2(void) {
  Serial.println("do Func 2");
}
void func_3(void) {
  Serial.println("do Func 3");
}
void func_4(void) {
  Serial.println("do Func A");
}
void func_5(void) {
  Serial.println("do Func 4");
}
void func_6(void) {
  Serial.println("do Func 5");
}
void func_7(void) {
  Serial.println("do Func 6");
}
void func_8(void) {
  Serial.println("do Func B");
}
void func_9(void) {
  Serial.println("do Func 7");
}
void func_10(void) {
  Serial.println("do Func 8");
}
void func_11(void) {
  Serial.println("do Func 9");
}
void func_12(void) {
  Serial.println("do Func C");
}
void func_13(void) {
  Serial.println("do Func *");
}
void func_14(void) {
  Serial.println("do Func 0");
}
void func_15(void) {
  Serial.println("do Func #");
}
void func_16(void) {
  Serial.println("do Func D");
}
void setup() {
  Serial.begin(9600);
  //#1 клавиатура 4x4
  do_keys_4x4.setup(2, 3, 4, 5, 6, 7, 8, 9);
}
void loop() {
  //#1 клавиатура 4x4
  do_keys_4x4.loop(& func_1, & func_2, & func_3, & func_4,
          & func_5, & func_6, & func_7, & func_8,
          & func_9, & func_10, & func_11, & func_12,
          & func_13, & func_14, & func_15, & func_16);
}

ПС: Повторяю , этот код псевдопаралельный. А это значит, что можно совмещать нескольно независимых программ написаных в таком стиле на 1 Ардуине. Что убыстряет разработку рабочих программ. Правда надо правильно написать и отладить такие куски.