Подскажите как работает программа для кнопки

guJI9X
Offline
Зарегистрирован: 30.10.2018

Я новичок.

Задача была такой, при нажатии на кнопку светодиод должен гореть 2с (но не важно как нажимали на кнопку, многократно, или долгим удержанием).

я нашел скетч про кнопку. Считаем его оригиналом.

void setup() 

{
Serial.begin(9600);
pinMode(3, INPUT_PULLUP);
}

bool flag = false;
uint32_t btnTimer = 0;

void loop() {

// читаем инвертированное значение для удобства
bool btnState = !digitalRead(3);
if (btnState && !flag && millis() - btnTimer > 100)

 {
flag = true;
btnTimer = millis();
Serial.println("press");
}

if (btnState && flag && millis() - btnTimer > 500)

 {
btnTimer = millis();
Serial.println("press hold");
}

if (!btnState && flag && millis() - btnTimer > 500)

 {
flag = false;
btnTimer = millis();
//Serial.println("release");
}
}

Я его немного подогнал для своей задачи

int LED = 4;
int BUT = 3;
boolean flag = false;
unsigned long btnTimer = 0;

void setup() 

{
Serial.begin(9600);
pinMode(BUT, INPUT_PULLUP);
pinMode(LED, OUTPUT);
digitalWrite(LED, HIGH);
}

void loop()
 
{
// читаем инвертированное значение для удобства
boolean btnState = !digitalRead(BUT);
if (btnState && !flag && millis() - btnTimer > 200)
 
{
flag = true;
digitalWrite(LED, LOW);
btnTimer = millis();
Serial.println("press");
}

if (btnState && flag && millis() - btnTimer >= 2000 && digitalRead(BUT) == LOW)
 
{
digitalWrite(LED, HIGH);
Serial.println("press hold");
}

if (!btnState && flag && millis() - btnTimer >= 2000) 

{
flag = false;
digitalWrite(LED, HIGH);
Serial.println("release");
}
}

Как работает условие на 20 строке в оригинальном скетче? Она подавливает дребезг контактов?

Если кнопка нажата и флаг не поднят и Timer>100 (где Timer=0 или это другое значение после нажатия кнопки и 100 миллисекунд).

И 29 строчка в измененном скетче. Кнопка нажата и флаг поднят и светодиод горит и прошло 2с, то светодиод гасим и переходим 36 строчке проверяем условие и опускаем флажок и еще раз гасим светодиод(условно)? Но если в 29 строке написать что будем гасить светодиод и опускать флажок, то светодиод будет гореть столько сколько будем держать кнопку +2с. Почему?

Помогите разобраться.

 

mykaida
mykaida аватар
Offline
Зарегистрирован: 12.07.2018

ой   в 20 строке просто защита от дребезга

apg_777
Offline
Зарегистрирован: 22.09.2020

Для данной задачи защита от дребезга не нужна, поскольку светодиод должен гореть 2с и не важно как нажимали на кнопку, многократно, или долгим удержанием.

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

TC нужен программный одновибратор, значит надо обрабатывать не только нажатие кнопки но и отжатие и если есть отжатие и светодиод не горит взводить флаг готовности обрабатывания нажатия кнопки

nik182
Offline
Зарегистрирован: 04.05.2015

Поставленная задача решается одной строчкой кода. Оператором if проверяем нажатие кнопки и если кнопка нажата, то включаем светодиод , ждем 2 секунды и выключаем. Не надо ничего больше. Гореть светодиод будет пока нажата кнопка, потому что цикл после окончания будет запускаться снова. Условия повторного нажатия на кнопку изначально не было.

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

nik182 пишет:
Поставленная задача решается одной строчкой кода. Оператором if проверяем нажатие кнопки и если кнопка нажата, то включаем светодиод , ждем 2 секунды и выключаем. Не надо ничего больше. Гореть светодиод будет пока нажата кнопка, потому что цикл после окончания будет запускаться снова. Условия повторного нажатия на кнопку изначально не было.

RE должен гореть 2с (но не важно как нажимали на кнопку, многократно, или долгим удержанием)

nik182
Offline
Зарегистрирован: 04.05.2015

Зажечь, делэй 2секунды, погасить. Будет гореть 2 секунды, что бы с кнопкой не делали.

Гриша
Offline
Зарегистрирован: 27.04.2014

nik182 пишет:
Зажечь, делэй 2секунды, погасить. Будет гореть 2 секунды, что бы с кнопкой не делали.

секундомер нужен и тазик с водой - иначе можно пережечь :))))))))))))

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

Гриша пишет:

секундомер нужен и тазик с водой - иначе можно пережечь :))))))))))))

И ко всему этому толковый майор.

guJI9X
Offline
Зарегистрирован: 30.10.2018

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

Да если вы знаете как одной строчкой if написать код чтоб так работало то подскажите. Да еще в 29 строке ошибку нашел

int LED = 4;
int BUT = 3;
boolean flag = false;
unsigned long btnTimer = 0;

void setup() 

{
Serial.begin(9600);
pinMode(BUT, INPUT_PULLUP);
pinMode(LED, OUTPUT);
digitalWrite(LED, HIGH);
}

void loop()
 
{
// читаем инвертированное значение для удобства
boolean btnState = !digitalRead(BUT);
if (btnState && !flag && millis() - btnTimer > 200)
 
{
flag = true;
digitalWrite(LED, LOW);
btnTimer = millis();
Serial.println("press");
}

if (btnState && flag && millis() - btnTimer >= 2000 && digitalRead(LED) == LOW)
 
{
digitalWrite(LED, HIGH);
Serial.println("press hold");
}

if (!btnState && flag && millis() - btnTimer >= 2000) 

{
flag = false;
digitalWrite(LED, HIGH);
Serial.println("release");
}
}

 

apg_777
Offline
Зарегистрирован: 22.09.2020

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

int LED = 4;

void setup()
{
pinMode(LED, OUTPUT);
digitalWrite(LED, HIGH);
delay(2000);
digitalWrite(LED, LOW);
}

void loop() 
{
delay(100000); // так, чисто символически, можно усыплять
}

И не обращать внимания что при включении будет срабатывать, можно назвать это контролем работы.

guJI9X
Offline
Зарегистрирован: 30.10.2018

Можно без delay, на этой ардуине ещё будут другие задачи выполнять rfid висеть, ethernet и реле света. Ложное срабатывание недопустимо, т.к. надо выходить на улицу и открывать и закрывать калитку( после нажатия кнопки замок надо заново взвести (условно говоря)).
Но я спрашивал почему в условие строка 29

if (btnState && flag && millis() - btnTimer >= 2000 && digitalRead(LED) == LOW)

{
digitalWrite(LED, HIGH);
Serial.println("press hold");
flag = 0;
}
Кнопка при долгом удержании больше 2с светодиод не выкл
И постоянно hold печатает?

Гриша
Offline
Зарегистрирован: 27.04.2014

guJI9X пишет:
Можно без delay,

можно, вы умеете флагами пользоваться? Если да, то напишите программу счетчик от 0 до 10 на миллис с шагом 500 мсек. Потом к счетчику флаги прикрутить не сложно - это пока самый простой вариант для вас. Ну и шаг счетчика под задачу потом настроить. 

UPD. byte count; // используйте эту переменную  для счетчика.

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

guJI9X пишет:
Можно без delay, на этой ардуине ещё будут другие задачи выполнять rfid висеть, ethernet и реле света. Ложное срабатывание недопустимо, т.к. надо выходить на улицу и открывать и закрывать калитку( после нажатия кнопки замок надо заново взвести (условно говоря)). Но я спрашивал почему в условие строка 29 if (btnState && flag && millis() - btnTimer >= 2000 && digitalRead(LED) == LOW) { digitalWrite(LED, HIGH); Serial.println("press hold"); flag = 0; } Кнопка при долгом удержании больше 2с светодиод не выкл И постоянно hold печатает?

а я же вам уже выше писал, надо отслеживать отжатие кнопки и пока она не отжата и повторно не нажата (после 2 секундной выдержки) флаг возможности повторного  запуска одновибратора держать в OFF

как то так, в лоб, DetSimen при желании поправит на правильно и красиво:
 

uint8_t LEDS = 13;
uint8_t BUT = 6;
boolean flag_on = false;
boolean flag_off = false;

unsigned long btnTimer = 0;
unsigned long LED_ON = 2000;

void setup() 

{
Serial.begin(9600);
pinMode(BUT, INPUT_PULLUP);
pinMode(LEDS, OUTPUT);
digitalWrite(LEDS, HIGH);
delay(1000);
digitalWrite(LEDS, LOW);
}



void loop(){

if(digitalRead(BUT) && !flag_off && !flag_on){flag_off = HIGH;} // есть отжатие кнопки
if(!digitalRead(BUT) && flag_off && !flag_on) {
flag_on = HIGH; // есть нажатие кнопки  
btnTimer = millis(); 
  }
if(flag_on && millis() - btnTimer < LED_ON){
  digitalWrite(LEDS, HIGH);
  }
if(flag_on && millis() - btnTimer >= LED_ON){
  digitalWrite(LEDS, LOW);
  flag_off = LOW;
  flag_on = LOW;
  }

}

 

sadman41
Offline
Зарегистрирован: 19.10.2016

Как вы планируете справится с RFID и Ethernet, если только с кнопкой проблем на целый день?

b707
Онлайн
Зарегистрирован: 26.05.2017

sadman41 пишет:
Как вы планируете справится с RFID и Ethernet, если только с кнопкой проблем на целый день?

думает, ему на форумах все напишут... вот ua6em уже начал

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

sadman41 пишет:
Как вы планируете справится с RFID и Ethernet, если только с кнопкой проблем на целый день?

с эзернетом думаю никак, тут некоторые (не буду пальцем показывать) 4-ре года на форуме и то не замахиваются )))

А защиту от дребезга контактов я не реализовал, это уже сам пусть попробует...

guJI9X
Offline
Зарегистрирован: 30.10.2018

Rfid программу нашел более менее разобрался и с кнопкой тоже получилось все, только не совсем понимаю почему с флагом сразу не работает в 29 строке условие или совпадение условий происходит в 29 строке.
Ethernet только удаленное выкл вкл света и открытие калитки через приложение arducontroller тоже попробовал нашильде 5100 заработало, но w5500 пока не понятно.

guJI9X
Offline
Зарегистрирован: 30.10.2018

Я не прошу за меня код писать, я прошу мойже код прокомментировать, с той целью чтоб убедиться, правильно ли я его понимаю.

b707
Онлайн
Зарегистрирован: 26.05.2017

guJI9X пишет:
Я не прошу за меня код писать, я прошу мойже код прокомментировать, с той целью чтоб убедиться, правильно ли я его понимаю.

и что не так в 29 строке?

sadman41
Offline
Зарегистрирован: 19.10.2016

guJI9X пишет:
я прошу мойже код прокомментировать, с той целью чтоб убедиться, правильно ли я его понимаю.

Не треснет ничего?

Просто не пишите код, который потом не можете понять без посторонней помощи. Это сэкономит кучу времени всем.

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

мой код точно работает, иногда подглючивает из-за дребезга кноки

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

guJI9X пишет:
Я не прошу за меня код писать, я прошу мойже код прокомментировать, с той целью чтоб убедиться, правильно ли я его понимаю.

Гораздо проще Вам самим прокомментировать свой код.

А если комментарии не будут совпадать с кодом, Вам на это укажут.

guJI9X
Offline
Зарегистрирован: 30.10.2018

b707 пишет:

guJI9X пишет:
Я не прошу за меня код писать, я прошу мойже код прокомментировать, с той целью чтоб убедиться, правильно ли я его понимаю.

и что не так в 29 строке?

int LED = 4;
int BUT = 3;
boolean flag = false;
unsigned long btnTimer = 0;
void setup()
{
Serial.begin(9600);
pinMode(BUT, INPUT_PULLUP);
pinMode(LED, OUTPUT);
digitalWrite(LED, HIGH);
}
void loop()
{
// читаем инвертированное значение для удобства
boolean btnState = !digitalRead(BUT);
if (btnState && !flag && millis() - btnTimer > 200)
{
flag = true;
digitalWrite(LED, LOW);
btnTimer = millis();
Serial.println("press");
}
if (btnState && flag && millis() - btnTimer >= 2000 && digitalRead(LED) == LOW)
{
flag = false;
digitalWrite(LED, HIGH);
Serial.println("press hold");
}
if (!btnState && flag && millis() - btnTimer >= 2000)
{
flag = false;
digitalWrite(LED, HIGH);
Serial.println("release");
}
}

Если условие выполняется стр 23

То выполняется флаг опускаем и светодиод гасим при удерживании кнопки в теории, на практике кнопку держим светодиод горит, как только отпускаем сведоид гасится в течении 2с

 

guJI9X
Offline
Зарегистрирован: 30.10.2018

Как тогда учиться))) и разбираться

guJI9X
Offline
Зарегистрирован: 30.10.2018

andriano пишет:

guJI9X пишет:
Я не прошу за меня код писать, я прошу мойже код прокомментировать, с той целью чтоб убедиться, правильно ли я его понимаю.

Гораздо проще Вам самим прокомментировать свой код.

А если комментарии не будут совпадать с кодом, Вам на это укажут.

Ок

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

Может так попробуйте

int ledPin = 4;                      // номер пина со светодиодом
bool f_kn = 0;
bool f_led = 0;
uint32_t btnTimer = 0;
//----------------------------------------------------------------------------
void setup() {
  pinMode(ledPin, OUTPUT);
  pinMode(6, INPUT_PULLUP);   //Кнопка
}

void loop() {
  if (!digitalRead(6) && !f_kn)
  {
    f_kn = 1;
    f_led = 1;
    btnTimer = millis();
    digitalWrite(ledPin, HIGH);
  }
  else if (!f_led && digitalRead(6)) f_kn = 0;

  if (f_led && millis() - btnTimer > 2000)
  {
    digitalWrite(ledPin, LOW);
    f_led = 0;
  }
}

 

guJI9X
Offline
Зарегистрирован: 30.10.2018

Спасибо всем за помощь