int btn1 = 11; // кнопка №1 — порт 11
int btn2 = 12; // кнопка №2 — порт 12
int led1 = 13; // порт 13, для светодиода
int led2 = 14; // порт 14, для светодиода
// статусы состояний
#define B1HOLD B00000001 // нажата первая кнопка
#define B2HOLD B00000010 // нажата вторая кнопка
#define B1TO B00000100 // у первой кнопки произошёл таймаут
#define B2TO B00001000 // у второй кнопки произошёл таймаут
// таймеры кнопок
unsigned long timer1;
unsigned long timer2;
byte flags = 0; // флаг состояния
void setup()
{
// Установим порты кнопок как входящие:
pinMode(btn1, INPUT_PULLUP);
pinMode(btn2, INPUT_PULLUP);
// Установим порт светодиода как исходящий:
pinMode(led1, OUTPUT);
pinMode(led2, OUTPUT);
// Выключим светодиоды
digitalWrite(led1, LOW);
digitalWrite(led2, LOW);
}
void loop()
{
if (digitalRead(btn1)) {
// первая кнопка не нажата
switch (flags) {
case 0: // никаких событий не зафиксировано, кнопка 1 проверена, проверяем вторую кнопку
if (!digitalRead(btn2)) {
// вторая кнопка только что нажата - сохраняем, включаем, взводим таймер
flags |= B2HOLD;
digitalWrite(led2, HIGH);
timer2 = millis();
}
break;
case B2TO|B1TO|B2HOLD|B1HOLD:
// таймаут обеих кнопок, (оба LED выключены) первая кнопка отжимается, выключаем таймаут,
// обрабатываем отпускание кнопки 1 без таймаута
case B1TO|B2HOLD|B1HOLD:
// кнопка 1 в таймауте (LED1 выключен), отжимается, вторая кнопка нажата (LED2 включен) -
// выключаем таймаут кнопки 1, отрабатываем отпускание кнопки 1 без таймаута
case B1TO|B1HOLD:
// кнопка 1 в таймауте (LED1 выключен), кнопка 2 отжата (LED2 выключен),
// отжимается кнопка 1 - выключаем таймаут и отрабатываем отпускание кнопки без таймаута
flags &= ~B1TO;
case B2TO|B2HOLD|B1HOLD:
// таймаут второй кнопки (LED2 выключен), первая кнопка нажата (LED1 включен)
// отжимается первая кнопка отжата - отрабатываем отжатие
case B1HOLD:
// кнопка 1 нажата (LED1 включен), отжимается кнопка 1 - сохраняем, выключаем
flags &= ~B1HOLD;
digitalWrite(led1, LOW);
break;
case B2HOLD:
// кнопка 2 нажата (LED2 включен), проверяем изменение кнопки 2
if (digitalRead(btn2)) {
// кнопку 2 отжали - сохраняем, выключаем
flags &= ~B2HOLD;
digitalWrite(led2, LOW);
} else {
// кнопка 2 удержана
if (millis() - timer2 >= TIMEOUT) {
// таймаут кнопки 2 - сохраняем, выключаем
flags |= B2TO;
digitalWrite(led2, LOW);
}
}
break;
case B2TO|B2HOLD:
// таймаут второй кнопки (LED2 выключен), проверяем изменение кнопки 2
if (digitalRead(btn2)) {
// отжата вторая кнопка - сохраняем
flags &= ~(B2TO|B2HOLD);
}
break;
/* с этого момента можно удалить */
case B2HOLD|B1HOLD:
// нажаты две кнопки без таймаута - невозможная комбинация
case B1TO:
// таймаут первой кнопки, но кнопка не нажата - невозможная комбинация
case B1TO|B2HOLD:
// таймаут первой кнопки, нажата вторая кнопка, но первая кнопка не нажата
// невозможная комбинация
case B2TO:
// таймаут второй кнопки, но она не нажата - невозможная комбинация
case B2TO|B1HOLD:
// таймаут второй кнопки, но она не нажата, первая кнопка нажата -
// невозможная комбинация
case B2TO|B1TO:
// произошёл таймаут обеих кнопок без их нажатия - невозможная комбинация
case B2TO|B1TO|B1HOLD:
// произошёл таймаут обеих кнопок без нажатия второй кнопки - невозможная комбинация
case B2TO|B1TO|B2HOLD:
// произошёл таймаут обеих кнопок без нажатия первой кнопки - невозможная комбинация
break;
/* до этого момента можно удалить */
}
else {
// первая кнопка нажата
switch (flags) {
case B2TO|B2HOLD:
// таймаут второй кнопки (LED2 выключен), отрабатываем нажатие кнопки 1
case 0:
// никаких событий не зафиксировано, первая кнопка только что нажата
// сохраняем, включаем, взводим таймер
flags |= B1HOLD;
digitalWrite(led1, HIGH);
timer1 = millis();
break;
case B2TO|B2HOLD|B1HOLD:
// произошёл таймаут второй кнопки, она была нажата, первая кнопка была нажата
case B1HOLD:
// удерживаем кнопку 1 (LED1 включен), проверяем таймаут
if (millis() - timer1 >= TIMEOUT) {
// произошёл таймаут нажатия кнопки - сохраняем, выключаем
flags |= B1TO;
digitalWrite(led1, LOW);
}
case B1TO|B2HOLD|B1HOLD:
// таймаут кнопки 1 (LED1 выключен), кнопка 2 нажата (LED2 включен)
case B2HOLD:
// нажата вторая кнопка (LED2 включен)
if (digitalRead(btn2)) {
// вторая кнопка отжата - сохраняем, выключаем
flags &= ~B2HOLD;
digitalWrite(led2, LOW);
} else {
if (millis()-timer2 >= TIMEOUT) {
// произошёл таймаут нажатия кнопки 2 - сохраняем, выключаем
flags |= B2TO;
digitalWrite(led2, LOW);
}
}
break;
case B1TO|B1HOLD:
// таймаут кнопки 1 (LED1 выключен) - разрешено нажать вторую кнопку
if (!digitalRead(btn2)) {
// вторая кнопка нажата
flags |= B2HOLD;
digitalWrite(led2, HIGH);
timer2 = millis();
}
break;
case B2TO|B1TO|B2HOLD|B1HOLD:
// произошёл таймаут обеих кнопок и они обе нажаты, кнопка 1 проверена
if(digitalRead(btn2)) {
// вторая кнопка отжата
flags &= ~(B2TO|B2HOLD);
}
break;
/* с этого момента можно удалить */
case B1HOLD|B2HOLD:
// были нажаты две кнопки и не было таймаута - невозможная комбинация
case B1TO:
// произошёл таймаут первой кнопки, но кнопка не нажата - невозможная комбинация
case B1TO|B2HOLD:
// произошёл таймаут первой кнопки, удерживается вторая кнопка, но первая кнопка не нажата
// невозможная комбинация
case B2TO:
// произошёл таймаут второй кнопки, но она не нажата - невозможная комбинация
case B2TO|B1HOLD:
// произошёл таймаут второй кнопки, но она не нажата, первая кнопка нажата -
// невозможная комбинация
case B2TO|B1TO:
// произошёл таймаут обеих кнопок без их нажатия - невозможная комбинация
case B2TO|B1TO|B1HOLD:
// произошёл таймаут обеих кнопок без нажатия второй кнопки - невозможная комбинация
case B2TO|B1TO|B2HOLD:
// произошёл таймаут обеих кнопок без нажатия первой кнопки - невозможная комбинация
break;
/* до этого момента можно удалить */
}
}
}