Проблема с состоянием кнопки

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

Я пытаюсь использовать кнопки и состояния кнопок для установки часов и минут будильника, поэтому я пытаюсь сохранить состояние кнопок таким образом, чтобы после нажатия они запоминали это состояние, а не менялись при отпускании. Я пытаюсь получить его так, нажимая кнопки в моем коде идет в будильник установлен порядок, затем до c кнопка нажата, он будет цикл, чтобы установить часы, затем минуты (я не добавила минут процедуру пока), так что кнопка запускает процедуру и кнопку C завершает его, А B кнопка увеличивает часов/минут переменную на единицу.

Я окончательно запутался. У меня есть две переменные "lastButtonState", которые могут быть ненужными, но это было единственное, что я мог придумать.

Прямо сейчас с моим кодом он входит в цикл button C while, но не выходит из него при нажатии кнопки. Моя логика для этого состояла в том, что цикл while должен завершаться при нажатии кнопки C, поэтому я не думаю, что мне нужно что-то внутри цикла, чтобы вырваться из него.

У меня работает часть часов настройки кнопки В, она просто не выходит из цикла кнопки С.

В конце концов я помещу этот код в соответствующую функцию и добавлю область заданных минут после области заданных часов.

Вот мой код:

#include <LiquidCrystal.h>

LiquidCrystal lcd(7, 8, 9, 10, 11, 12);
//Constants
//const int buttonPin = 9;
const int buttonApin = 3;
const int buttonBpin = 2;
const int buttonCpin = 5;
int buttonState = 0;
int buttonState2 = 0;
int buttonState3 = 0;
//int flag = 0;
int alarmHoursInner = 1;
int lastButtonState = 0;
int lastButtonState3 = 0;
void setup() {
  // put your setup code here, to run once:
  lcd.begin(16, 2);
  Serial.begin(9600);
  //Input or output?
  pinMode(buttonApin, INPUT_PULLUP);
  pinMode(buttonBpin, INPUT_PULLUP);
  pinMode(buttonCpin, INPUT_PULLUP);
}

void loop() {
  // put your main code here, to run repeatedly:
  buttonState = digitalRead(buttonApin);
  buttonState2 = digitalRead(buttonBpin);
  buttonState3 = digitalRead(buttonCpin);

  if (buttonState == HIGH) {
    while (buttonState3 == LOW) {

      buttonState2 = digitalRead(buttonBpin);
      if (lastButtonState != buttonState2) { // last button state starts at 0 (or OFF) this line tests current state against last state
        if (buttonState2 == LOW) { // if buttonState is HIGH it went from OFF to ON
          // Serial.print("Button B works!");
          ++alarmHoursInner; // increments variable for hours
          Serial.print(alarmHoursInner); // prints hours
          Serial.println("  "); // blank line
          delay(50); // delay
        }
        else {

          Serial.print("Please push button B");
          Serial.println("  ");
        }
      }  

      lastButtonState = buttonState2;
    }
      lastButtonState3 = buttonState3;
  }
}

, 👍1

Обсуждение

начните с переименования кнопок в некоторые полезные имена, которые описывают функцию.... вместо "ButtonA", "ButtonB", "buttonC" назовите их чем-то вроде "mode", "advance", exit .... modeButton и др., @jsotola

исследование Arduino state machine, @jsotola

Ок ваш ввод о переименовании отмечен, спасибо! Я уже довольно тщательно изучил изменения состояния. Не могли бы вы указать мне на что-то конкретное о state machine, что могло бы помочь? Я погуглил его и посмотрел на несколько ссылок, но на какой части state machine я должен сосредоточиться? До сих пор это похоже на то, что я уже знал о состояниях, когда разрабатывал свой код. Что именно не так с моим кодом?, @user2565352

lastButtonState3 = buttonState3; ... эта строка имеет слишком большой отступ, что делает ее похожей на часть оператора " if "... она находится в конце цикла "while" ... "buttonState3" всегда будет НИЗКИМ при выполнении этой строки, @jsotola


1 ответ


0

Вы можете начать с библиотеки отключения кнопок, такой как Bounce2. Этот скетч иллюстрирует, как обнаружить несколько нажатий кнопок от одной кнопки до цикла, используя 3 различных варианта.

Возможно, будет хорошей идеей записать шаги вашей "Процедуры настройки будильника" в виде обычного текста, прежде чем писать какой-либо код. Это поможет вам определить структуры управления, необходимые для вашего скетча.

Альтернативой использованию нескольких кнопок может быть поворотный энкодер со встроенным кнопочным переключателем. Для них существуют библиотеки, которые обнаруживают нажатие кнопки, двойное нажатие, нажатие и удержание, и, конечно, они могут увеличивать/уменьшать переменную счетчика, "поворачивая диск" CW и CCW.

// Подсоедините один конец кнопочного переключателя N. O. к
// GND и другой конец для подключения 4 к Arduino.
#include <Bounce2.h>

byte buttonState = 0;
byte lastButtonState = 0;  // Используется только для отладки.
const byte modeButtonPin = 4;
const unsigned long debouncerInterval = 50;  // Time in ms.

Bounce modeButton = Bounce();

void setup(){

  Serial.begin(9600);
  pinMode(modeButtonPin, INPUT_PULLUP);
  modeButton.attach(modeButtonPin);
  modeButton.interval(debouncerInterval);

}

void loop(){

  if(modeButton.update()){

    if(modeButton.read() == 0){
      buttonState++;
      if(buttonState > 2){buttonState = 0;}
    }

  }

  // Используется только для отладки.
  // Распечатайте содержимое переменной buttonState при ее изменении.
  if(buttonState != lastButtonState){
    if(buttonState == 0){Serial.println("Clock Mode - Current Time Displayed");}
    else if(buttonState == 1){Serial.println("Alarm Mode - Set Hours");}
    else{Serial.println("Alarm Mode - Set Minutes");}
    lastButtonState = buttonState;
  }

}
,