Как выйти из цикла while с помощью клавиатуры?

Кажется, я не могу выйти из цикла while с помощью кнопки на клавиатуре. Я пробовал решение из этой темы: https://forum.arduino.cc/index.php?topic= 79932.0

Вот мой код:

void alarm(){
  char customKey = customKeypad.getKey();

  while (customKey == NO_KEY){
    customKey = customKeypad.getKey();
    lcd.noDisplay();
    delay(750);// изменить для более быстрой вспышки
    lcd.display();
    delay(750);// изменить для более быстрой вспышки
  }
  lcd_home_screen();
}

Я попробовал и ==, и != некоторое время (customKey == NO_KEY)

Дополнительная информация: Я вызываю эту функцию будильника из другой функции внутри моего цикла. Вот полный код:

void loop() {
  // клавиатура
  char customKey = customKeypad.getKey();    
  if (customKey == 'A'){
    main_program(5);
  }
}

int main_program(int duration){
  timer(duration);
  alarm();
}

, 👍0


2 ответа


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

1

Поскольку вы используете delay() в цикле while, вы должны убедиться, что нажимаете клавишу именно в тот момент, когда она считывается.

Вы не должны использовать delay().

Вместо этого взгляните на пример BlinkWithoutDelay в среде IDE. А также рассмотрите возможность реализации Конечного автомата, чтобы знать, моргаете ли вы и в каком состоянии находитесь. мигает в настоящее время.

,

Ваше решение BlinkWithoutDelay имеет большой смысл и более доступно для моего уровня знаний, спасибо. Моя блокировка сейчас заключается в том, что я не могу использовать функции lcd.Display и noDisplay. В примере с BlinkWithoutDelay код проверяет низкий или высокий уровень выходного сигнала, но в моем случае я должен проверить, включен ли мой ЖК-дисплей на Display или noDisplay. Как я могу это проверить? Я опубликую новый код, если то, что я только что написал, непонятно., @Vincent Labrecque

Неважно, я заставил это работать с фиктивной булевой переменной. BlinkWithoutDelay — это то, что нужно. Спасибо!, @Vincent Labrecque


0

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

enum EAlarmState 
{
   On,
   Off
};

EAlarmState _alarmState = EAlarmState::Off;

enum EBlinkState
{
    BlinkOn,
    BlinkOff,
};

EBlinkState _blinkState = EBlinkState::BlinkOff;

unsigned int long _lastBlinkTime = 0;

Состояние _blinkState и _lastBlinkTime не будет проверяться, если _alarmState выключено.

Теперь вы можете использовать что-то вроде этого для проверки состояний и клавиатуры (псевдокод):

void loop()
{
    checkKeypad();

    switch (_alarmState)
    {
    case EAlarmStateOn:
       if (millis() - _lastBlinkTime) >= 750)
       {
          `Blink off code`
          switch(_blinkState)
          {
          case EBlinkStateOn:
             _lastBlinkTime = millis();
             'Blink off code'
             _blinkState = EBlinkState::Off;
             break;

          `same for case EBlinkStateOff'
             break;

          default: // Error
             break;
          }
       }

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

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

,

Я попытался скопировать/вставить ваш код, но, поскольку я не понимаю, что происходит, я не смог заставить его работать. Я вставил верхнюю часть вашего кода перед функцией Setup(), а нижнюю часть в цикле while внутри моей функции alarm(). Теперь я сталкиваюсь со следующей ошибкой msg "ожидаемый инициализатор до '_blinkState', @Vincent Labrecque

Я забыл точку с запятой после второго перечисления. компилятора под рукой нет, @Michel Keijzers

Вы также должны избавиться от оператора while. Не блокируйте свой код на долгое или неопределенное время., @Michel Keijzers