Невозможно ввести клавишу клавиатуры в цикл while

Я новичок в Arduino, поэтому у меня возникла небольшая проблема: я пытаюсь выполнить обратный отсчет на ЖК-дисплее, используя цикл while, но я также пытаюсь получить ввод ключа внутри того же цикла while. Проблема в том, что в это время сложно получить ввод, потому что из-за таймера есть задержка. Пытался поискать в интернете решение, но не нашел. Если у кого-нибудь есть хорошее решение, я буду очень рад, если вы его опубликуете :) Еще раз спасибо!

Вот мой код:

while (gameInProgress) {

    lcd.clear();
    lcd.setCursor(0, 0);
    lcd.print("Until boom! ");
    lcd.print(timer);
    lcd.setCursor(0, 1);
    lcd.print(passwordInputed);

    char key = keypad.getKey();
    if (key && gameInProgress) {
      passwordInputed += key;
    }

    analogWrite(buzzerPin, 145);
    delay(200);
    analogWrite(buzzerPin, 0);
    delay(800);
    timer--;
    if (timer == 0){
      gameInProgress = false;
      lcd.clear();
      lcd.setCursor(0, 0);
      lcd.print("Boom happend!");
      lcd.setCursor(0, 1);
      lcd.print("You lost :(");
    }
  }

, 👍0

Обсуждение

Напишите неблокирующий код: https://docs.arduino.cc/built-in-examples/digital/BlinkWithoutDelay., @VE7JRO

Изучите стиль «Моргание без задержки». Если вы хотите, чтобы вам было легче, отложите этот код на некоторое время, пока вы действительно не поймете, что происходит с этим стилем расчета времени. Затем вернитесь и добавьте это сюда. Если вы попытаетесь просто скопировать этот код, не понимая, как он работает, вам придется плохо., @Delta_G

Почему вы отметили проблему решенной? Каково решение? Это не форум, решения (то есть ответы) опубликованы ниже., @Nick Gammon

Я голосую за закрытие этого вопроса, потому что [РЕШЕНО] не является ответом., @VE7JRO

Я удалил \[РЕШЕНО\] из темы - это не имеет никакого смысла., @Nick Gammon

*Пытался поискать в Интернете решение, но не нашел* - Вы не наткнулись на [пост, который я написал](http://www.gammon.com.au/blink) именно об этом?, @Nick Gammon


1 ответ


Лучший ответ:

0

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

По сути, удалите все вызовы задержки(). Вместо этого запишите значение, возвращаемое функцией millis(), вне цикла. Если вы отслеживаете интервал, скажем, в 1 секунду (1000 мс), добавьте 1000 к записанному значению. Каждый раз при выполнении цикла проверяйте, превышает ли mills() записанное значение. Когда это произойдет, измените состояние, снова прибавьте 1000 к записанному значению и сделайте все необходимое, когда состояние, указывающее, что прошла 1 секунда, изменилось. Теперь очистите состояние и дождитесь повторения цикла.

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

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

,