Ищу изящное выполнение кода двух кнопок

Nikomas

✩✩✩✩✩✩✩
25 Дек 2022
9
0
Гуру форума, вопрос к вам. Есть задумка:
  1. Ждем нажатия любой из 2х кнопок.
  2. Если была нажата btn1, то больше ни на что не реагируем и ждем нажатия btn2.
  3. При нажатии на btn2 - идем в п.1
  4. Если была нажата кнопка btn2, то ни на что не реагируем и ждем нажатия btn1.
  5. При нажатии на btn1 - идем в п.1
Вот такой код сейчас набросал:
C++:
uint8_t btn1 0;
uint8_t btn2 1;
uint8_t flag1;
uint8_t flag2;

void setup() {
    pinMode(btn1, INPUT);
    pinmode(btn2, INPUT);
    flag1 = 0;
    flag2 = 0;
}

void loop() {
    int readBtn1 = digitalRead(btn1);
    int readbtn2 = digitalRead(btn2);


    if (readBtn1 == 1) { // если нажата btn1
        delay(100); // delay ставлю для подавления дребезга контактов
        func1();
        flag1 = 1;
    }

    if (readBtn2 == 1 && flag1 == 1) { // если после нажатия btn1 была нажата btn2
        delay(100);
        func2();
        flag1 = 0;
        readBtn1 = 0; // сбрасываем состояние btn1
        readBtn2 = 0; // сбрасываем состояние btn2
    }

    if (readBtn2 == 1) { // если нажата btn2
        delay(100);
        func3();
        flag2 = 1;
    }

    if (readBtn1 == 1 && flag2 == 1) { // если после нажатия btn2 была нажата btn1
        delay(delay);
        func4();
        readBtn1 = 0; // сбрасываем состояние btn1
        readBtn2 = 0; // сбрасываем состояние btn2
    }
}
Каждой функции прописал вывод в Serial своего символа. но если нажимать не следуя коду, то нет-нет да и проскочит выполнение не по порядку. Например,
  • click bnt1
  • click btn2
  • click btn2
  • click btn2
  • autoclick btn1
  • autoclick btn2

Может кто подскажет изящное решение моей проблемы. В перспективе хочу сбрасывать состояние по истечению времени ели не нажата необходимая кнопка.
 

Старик Похабыч

★★★★★★★
14 Авг 2019
4,159
1,267
Москва
Самое главное. Возьмите решение , которое предлагает Алекс Гайвер - его библиотеку по работе с кнопками. Сложность сократиться на порядок.
Будет что то типа:
режим=0

цикл лууп
{
кнопка 1. тик
кнопка 2. тик
если режим 0, то
{

если клик кнопки 1, то режим 1.
если клик кнопки 2, то режим 2
}
если режим 1 то
{
очистить состояние кнопки 1. //(что бы не копилось ничего лишнего
если нажата кнопка 2, то режим 0
}

если режим 2 то
{
очистить состояние кнопки 2. //(что бы не копилось ничего лишнего
если нажата кнопка 1, то режим 0
}
}

Делать что функции кнопок самому можно , но стоит только если надо сократить объем используемой памяти, а пока ее много стоит использовать готовое. Так и логика будет виднее, и запутаться сложнее. И всегда можно потом на свои функции перейти.
 

Nikomas

✩✩✩✩✩✩✩
25 Дек 2022
9
0
Работает.
C++:
void setup() {
  Serial.begin(9600);
  pinMode(8, INPUT);
  pinMode(9, INPUT);
}
bool mode0 = false;
bool mode1 = false;
bool mode2 = false;
uint32_t btnTimer = 0;
void loop() {
  bool btn1State = digitalRead(8);
  bool btn2State = digitalRead(9);
  if (!mode1 && !mode2 && btn1State && millis() - btnTimer > 1000) {
    btnTimer = millis();
    Serial.println("1 ON");
    mode1 = true;
    mode2 = false;
  }
  if (mode1 && !mode2 && btn2State && millis() - btnTimer > 1000) {
    btnTimer = millis();
    Serial.println("1 OFF");
    mode1 = false;
    mode2 = false;
  }
  if (!mode1 && !mode2 && btn2State && millis() - btnTimer > 1000) {
    btnTimer = millis();
    Serial.println("2 ON");
    mode1 = false;
    mode2 = true;
  }
  if (!mode1 && mode2 && btn1State && millis() - btnTimer > 1000) {
    btnTimer = millis();
    Serial.println("2 OFF");
    mode1 = false;
    mode2 = false;
  }
}
След. шаг выходить из mode1 и mode2 по прошествии времени и не нажатии кнопки.
 
Изменено:

Nikomas

✩✩✩✩✩✩✩
25 Дек 2022
9
0
C++:
void setup() {
  Serial.begin(9600);
  pinMode(8, INPUT);
  pinMode(9, INPUT);
}

bool mode1 = false;
bool mode2 = false;
uint32_t btnTimer = 0;
uint32_t offTimer = 0;

void loop() {
  bool btn1State = digitalRead(8);
  bool btn2State = digitalRead(9);

  if (!mode1 && !mode2 && btn1State && millis() - btnTimer > 1000) {
    btnTimer = millis();
    offTimer = millis();
    Serial.println("1 ON");
    mode1 = true;
    mode2 = false;
  }

  if (mode1 && !mode2 && btn2State && millis() - btnTimer > 1000) {
    btnTimer = millis();
    Serial.println("1 OFF");
    mode1 = false;
    mode2 = false;
  }

  if (mode1 && !mode2 && millis() - offTimer > 5000) {
    Serial.println("1 OFF TIMER");
    mode1 = false;
    mode2 = false;
  }

  if (!mode1 && !mode2 && btn2State && millis() - btnTimer > 1000) {
    btnTimer = millis();
    offTimer = millis();
    Serial.println("2 ON");
    mode1 = false;
    mode2 = true;
  }

  if (!mode1 && mode2 && btn1State && millis() - btnTimer > 1000) {
    btnTimer = millis();
    Serial.println("2 OFF");
    mode1 = false;
    mode2 = false;
  }

    if (!mode1 && mode2 && millis() - offTimer > 5000) {
    Serial.println("2 OFF TIMER");
    mode1 = false;
    mode2 = false;
  }

}
Вот и окончательный вариант. Всем спасибо.