Как заблокировать вход кнопки с возможностью выбора задержки?
У меня есть программа, над которой я работаю, в которой реле включается -> ждет задержки -> затем выключается после того, как происходит одно из двух: 1) достигается заданное время r ИЛИ 2) кто-то нажимает кнопку, чтобы активировать его.
Сейчас 90% моего кода работает, и я застрял на том, как «заблокировать» кнопку, чтобы она не срабатывала при срабатывании реле, на выбираемое время задержки.
Часть кода с таймером, с выбираемым временем, работает. В зависимости от того, что видит аналоговый 1, он соответствующим образом включит реле после выбранного времени.
Я попытался реализовать этот же подход для таймера блокировки, используя аналоговый 2, чтобы определить длительность задержки. Я использовал переменную, которую назвал LOK, чтобы либо прочитать кнопку, если она разблокирована (LOK = 0), либо, если она заблокирована (LOK = 1), подождать отведенное время задержки перед разблокировкой и повторным считыванием кнопки.
Я перепробовал все виды вещей, но это все еще не работает правильно. Возможно, есть лучший или более простой способ сделать это, но я сломал голову, и поиск по ключевым словам не помогает.
Код ниже - простите за случайные комментарии. Я что-то резал и перемещал, я не редактировал комментарии, поэтому некоторые из них могут быть из других фрагментов кодов из других проектов.
int DUMP = 2; // Контакт подключен к большому реле дампа
int BUTTON = 3; // Контакт подключен к кнопке ручного сброса.
int BUTTONlight = 4; // Контакт подключен к кнопочной подсветке.
int BUTstate; // Текущее показание с контакта BUTTON
int lastBUTstate = LOW; // Предыдущее чтение с контакта BUTTON
long lastDebounce = 0; // Последний раз вывод был изменен
long Delay = 50; // Время дребезга
unsigned long DUMPTIME;
unsigned long LOT;
unsigned long prevTIME;
int a=0;
int d=0;
int LOK = 0;
void setup()
{
pinMode(A1, INPUT);
pinMode(A2, INPUT);
pinMode (BUTTON, INPUT);
pinMode (BUTTONlight, OUTPUT);
pinMode (DUMP, OUTPUT);
digitalWrite(DUMP, HIGH);
delay(10000);
digitalWrite(DUMP, LOW);
digitalWrite(BUTTONlight, HIGH);
}
int readTselector(int pin)
// возвращает номер нажатой кнопки или ноль, если кнопка не нажата
// int pin — номер аналогового контакта для считывания
{
int b,c = 1;
c=analogRead(pin); // получить аналоговое значение
if (c>1000)
{
b=0; // кнопки не были нажаты
}
else
if (c<1000 && c>600)
{
b=1; // кнопка 1 нажата
}
else
if (c<520 && c>400)
{
b=2; // кнопка 2 нажата
}
else
if (c>100 && c<400)
{
b=3; // кнопка 3 нажата
}
else
if (c<100)
{
b=4; // кнопка 4 нажата
}
return b;
}
void loop()
{
int DUMPTIME = DTselect();
int LOT = LOselect();
int reading = digitalRead(BUTTON);
unsigned long currTIME = millis();
if ((currTIME - prevTIME) >= DUMPTIME) // Считаем до 2 минут
{
LOK = 1;
digitalWrite(BUTTONlight, LOW);
digitalWrite(DUMP, HIGH);
delay(10000);
digitalWrite(DUMP, LOW);
prevTIME = currTIME;
}
if (reading != lastBUTstate)
{
lastDebounce = millis();
}
if (LOK == 1)
{
delay(LOT);
digitalWrite(BUTTONlight, HIGH);
LOK = 0;
}
if ((millis() - lastDebounce) > Delay && LOK == 0)
{
BUTstate = reading;
}
if (BUTstate == HIGH)
{
digitalWrite(BUTTONlight, LOW);
digitalWrite(DUMP, HIGH);
delay(10000);
digitalWrite(DUMP, LOW);
prevTIME = currTIME;
}
lastBUTstate = reading;
}
int DTselect()
{
a=readTselector(1);
if (a==0) // кнопки не нажаты
{
DUMPTIME = 210000;
}
else
if (a==1) // кто-то нажал кнопку!
{
DUMPTIME = 180000;
}
else
if (a==2) // кто-то нажал кнопку!
{
DUMPTIME = 150000;
}
else
if (a==3) // кто-то нажал кнопку!
{
DUMPTIME = 120000;
}
else
if (a==4) // кто-то нажал кнопку!
{
DUMPTIME = 90000;
}
return DUMPTIME;
}
int LOselect()
{
d=readTselector(2);
if (d==0) // кнопки не нажаты
{
delay(20000);
}
else
if (d==1) // кто-то нажал кнопку!
{
delay(15000);
}
else
if (d==2) // кто-то нажал кнопку!
{
delay(10000);
}
else
if (d==3) // кто-то нажал кнопку!
{
delay(5000);
}
else
if (d==4) // кто-то нажал кнопку!
{
delay(0);
}
}
@Adam Alexander, 👍2
Обсуждение1 ответ
Лучший ответ:
Я взял ваш код и немного отредактировал. У вас были некоторые бесполезные переменные, и вы переопределяли DUMPTIME и LOT странным образом. Я также определил некоторые из ваших констант как #define, потому что именно так вы всегда должны это делать.
#define DUMP 2 // Контакт подключен к большому реле дампа
#define BUTTON 3 // Контакт подключен к кнопке ручного сброса.
#define BUTTONlight 4 // Контакт, подключенный к кнопочной подсветке.
#define DELAY 50 // Время дребезга
int BUTstate; // Текущее показание с контакта BUTTON
int lastBUTstate = LOW; // Предыдущее чтение с контакта BUTTON
long lastDebounce = 0; // Последний раз вывод был изменен
unsigned long DUMPTIME;
unsigned long LOT;
unsigned long prevTIME;
int LOK = 0;
int readTselector(int pin)
// возвращает номер нажатой кнопки или ноль, если кнопка не нажата
// int pin — номер аналогового контакта для считывания
{
int c = analogRead(pin); // получить аналоговое значение
if (c > 1000){
return 0; // кнопки не были нажаты
}
else if (c<1000 && c>600){
return 1; // кнопка 1 нажата
}
else if (c<520 && c>400){
return 2; // кнопка 2 нажата
}
else if (c>100 && c<400){
return 3; // кнопка 3 нажата
}
else if (c<100){
return 4; // кнопка 4 нажата
}
else return 0; // на всякий случай
}
long DTselect()
{
switch(readTselector(1)){
case 0: return 210000; // кнопки не нажаты
break;
case 1: return 180000; // кто-то нажал кнопку!
break;
case 2: return 150000;
break;
case 3: return 120000;
break;
case 4: return 90000;
break;
default: return 210000; // по умолчанию
break;
}
}
int LOselect()
{
switch( readTselector(2) ){
case 0: return 20000; // кнопки не нажаты
break;
case 1: return 15000; // кто-то нажал кнопку!
break;
case 2: return 10000;
break;
case 3: return 5000;
break;
case 4: return 0;
break;
default: return 20000; // по умолчанию
break;
}
}
void setup()
{
pinMode(A1, INPUT);
pinMode(A2, INPUT);
pinMode (BUTTON, INPUT);
pinMode (BUTTONlight, OUTPUT);
pinMode (DUMP, OUTPUT);
digitalWrite(DUMP, HIGH);
delay(10000);
digitalWrite(DUMP, LOW);
digitalWrite(BUTTONlight, HIGH);
}
void loop()
{
DUMPTIME = DTselect();
LOT = LOselect();
int reading = digitalRead(BUTTON);
unsigned long currTIME = millis();
if ((currTIME - prevTIME) >= DUMPTIME){// отсчитывать до 2 минут
LOK = 1;
digitalWrite(BUTTONlight, LOW);
digitalWrite(DUMP, HIGH);
delay(10000);
digitalWrite(DUMP, LOW);
prevTIME = currTIME;
}
if (reading != lastBUTstate){
lastDebounce = millis();
}
if (LOK){
delay(LOT);
digitalWrite(BUTTONlight, HIGH);
LOK = 0;
}
if ((millis() - lastDebounce) > DELAY && !LOK){
BUTstate = reading;
}
if (BUTstate == HIGH){
digitalWrite(BUTTONlight, LOW);
digitalWrite(DUMP, HIGH);
delay(10000);
digitalWrite(DUMP, LOW);
prevTIME = currTIME;
}
lastBUTstate = reading;
}
Другая версия с переменной BUTflag для отслеживания нажатия и отпускания кнопки. Я не имел дела с переменной DUMPTIME, но надеюсь, это даст вам представление о том, как использовать флаги, чтобы логика не дала сбой.
#define DUMP 2 // Контакт подключен к большому реле дампа
#define BUTTON 3 // Контакт подключен к кнопке ручного сброса.
#define BUTTONlight 4 // Контакт, подключенный к кнопочной подсветке.
#define DELAY 50 // Время дребезга
int BUTstate; // Текущее показание с контакта BUTTON
int BUTflag = 0;
int go = 0;
long lastDebounce = 0; // Последний раз вывод был изменен
unsigned long DUMPTIME;
unsigned long LOT;
unsigned long prevTIME;
int LOK = 0;
int readTselector(int pin)
// возвращает номер нажатой кнопки или ноль, если кнопка не нажата
// int pin — номер аналогового контакта для считывания
{
int c = analogRead(pin); // получить аналоговое значение
if (c > 1000){
return 0; // кнопки не были нажаты
}
else if (c<1000 && c>600){
return 1; // кнопка 1 нажата
}
else if (c<520 && c>400){
return 2; // кнопка 2 нажата
}
else if (c>100 && c<400){
return 3; // кнопка 3 нажата
}
else if (c<100){
return 4; // кнопка 4 нажата
}
else return 0; // на всякий случай
}
long DTselect()
{
switch(readTselector(1)){
case 0: return 210000; // кнопки не нажаты
break;
case 1: return 180000; // кто-то нажал кнопку!
break;
case 2: return 150000;
break;
case 3: return 120000;
break;
case 4: return 90000;
break;
default: return 210000; // по умолчанию
break;
}
}
int LOselect()
{
switch( readTselector(2) ){
case 0: return 20000; // кнопки не нажаты
break;
case 1: return 15000; // кто-то нажал кнопку!
break;
case 2: return 10000;
break;
case 3: return 5000;
break;
case 4: return 0;
break;
default: return 20000; // по умолчанию
break;
}
}
void setup()
{
pinMode(A1, INPUT);
pinMode(A2, INPUT);
pinMode (BUTTON, INPUT);
pinMode (BUTTONlight, OUTPUT);
pinMode (DUMP, OUTPUT);
digitalWrite(DUMP, HIGH);
delay(10000);
digitalWrite(DUMP, LOW);
digitalWrite(BUTTONlight, HIGH);
}
void loop()
{
DUMPTIME = DTselect();
LOT = LOselect();
BUTstate = digitalRead(BUTTON);
unsigned long currTIME = millis();
/*
if ((currTIME - prevTIME) >= DUMPTIME && !LOK){
LOK = 1;
digitalWrite(BUTTONlight, LOW);
digitalWrite(DUMP, HIGH);
delay(10000);
digitalWrite(DUMP, LOW);
prevTIME = currTIME;
}
else */
if (LOK){
delay(LOT);
digitalWrite(BUTTONlight, HIGH);
LOK = 0;
}
else if(!LOK){
if(!go && BUTstate && !BUTflag){
lastDebounce = millis();
BUTflag = 1;
}
else if (!go && BUTstate && BUTflag==1 && (millis() - lastDebounce) > DELAY){
BUTflag = 2;
}
else if (!go && !BUTstate && BUTflag==2){
BUTflag = 0;
go = 1;
}
else if (go){
digitalWrite(BUTTONlight, LOW);
digitalWrite(DUMP, HIGH);
delay(10000);
digitalWrite(DUMP, LOW);
prevTIME = currTIME;
go = 0;
LOK = 1;
}
}
}
Спасибо, но он все равно не работает правильно, когда выбран любой другой случай, кроме 0 на A2. Похоже, кнопка полностью блокируется от срабатывания вообще., @Adam Alexander
Что вы подразумеваете под A2? Я не менял никакой логики. Просто привел в порядок функции и переменные. Теперь код должен выглядеть немного компактнее., @crowie
Ах, ладно, и то, что я имел в виду под A2, было аналоговым входом 2. Теперь, что происходит, если любое другое значение, кроме 0, считывается с A2, то, похоже, процесс проходит цикл дважды после каждого нажатия кнопки. Так что с LOT, равным 5000 или 5 секундам, он проходит цикл, ждет 5 секунд, и вместо того, чтобы сбросить светодиод и ждать нового нажатия кнопки, он проходит цикл второй раз, ждет 5 секунд, затем сбрасывает светодиод. Также он иногда будет продолжать застревать в цикле и сбрасываться., @Adam Alexander
@AdamAlexander Я добавил другую версию, @crowie
Не могу достаточно отблагодарить вас! Мне нужно немного логически продумать флаг, чтобы понять концепцию, но флаги работают отлично! Мне удалось немного отредактировать логику DUMPTIME, чтобы использовать флаги, и теперь она также работает в сочетании с задержкой LOT! Респект!, @Adam Alexander
Нет проблем. Использование модели конечного автомата — это действительно путь к этому в долгосрочной перспективе. Вам следует изучить теорию конечного автомата, чтобы понять идею. Не забудьте проголосовать за меня., @crowie
- Как переключить светодиод при нажатии кнопки?
- Определение того, была ли нажата и отпущена кнопка
- Нажать клавишу Windows, используя «keyboard.press();»
- Устранение дребезга кнопки с помощью прерывания
- Хорошая кнопка debouncing/Библиотека StateChange
- Напряжение меняется, но цифровой поток всегда HIGH
- Остановить мигание светодиодов
- Интеграция 2 кнопок для включения и выключения светодиода.
что случилось с аккаунтом ОП?, @crowie