Правильная позиция для buttonState в моем FSM
Я написал FSM с помощью нескольких учебных пособий из всемирной паутины, и на данный момент он делает то, что мне нужно.
Одна вещь, которую я не хочу, - это выйти из состояния noLightPause во время неблокирующей задержки с помощью кнопки, чтобы снова войти в состояние yellowLight. Я не могу понять, куда поместить buttonState внутри моего кода, если должно быть так просто выйти из этого состояния, потому что мне было достаточно сложно заставить мою машину перейти к этой точке: D.
Не запутайтесь, я припаял кнопку от земли к пину, так что НИЗКИЙ получает вход :).
Надеюсь, вы, ребята, поможете мне с этой проблемой, чтобы я мог дальше работать с моей машиной.
Заранее спасибо за вашу помощь, вот мой код:
#include <FastLED.h>
#define NUM_LEDS 16
CRGB ledStrip [NUM_LEDS];
const int buttonPin = 4;
const int ledStripPin = 8;
const int ledOnBoard = 13;
const int interval = 100;
int buttonState = 0;
int lastButtonState = 0;
int ledOnBoardState = LOW;
unsigned long previousMillis = 0;
static unsigned long noDelayPause;
enum statusType {whiteLight, yellowLight, noLightPause, noLight};
statusType currentStatus = whiteLight;
void setup() {
pinMode(buttonPin, INPUT_PULLUP);
pinMode(ledStrip, OUTPUT);
pinMode(ledOnBoard, OUTPUT);
FastLED.addLeds<NEOPIXEL, 8>(ledStrip, NUM_LEDS).setCorrection(DirectSunlight);
FastLED.show();
}
void loop() {
//-------------------------------------------------------
// просто чтобы посмотреть, не блокирует ли что-то машина
unsigned long currentMillis = millis();
if (currentMillis - previousMillis >= interval) {
previousMillis = currentMillis;
if (ledOnBoardState == LOW) {
ledOnBoardState = HIGH;
} else {
ledOnBoardState = LOW;
}
digitalWrite(ledOnBoard, ledOnBoardState);
}
//-------------------------------------------------------
switch (currentStatus) {
case whiteLight:
currentStatus = whiteLightFunction();
break;
case yellowLight:
currentStatus = yellowLightFunction();
break;
case noLightPause:
noDelayPause = millis();
currentStatus = noLightPauseFunction();
break;
case noLight:
if (millis() - noDelayPause > 1000) {
currentStatus = noLightFunction();
break;
}
}
}
statusType whiteLightFunction() {
if (digitalRead(buttonPin) == LOW) {
return (yellowLight);
} else {
fill_solid(ledStrip, NUM_LEDS, CRGB::White);
FastLED.setBrightness(100);
FastLED.show();
return (whiteLight);
}
}
statusType yellowLightFunction() {
if (digitalRead(buttonPin) == LOW) {
fill_solid(ledStrip, NUM_LEDS, CRGB::Yellow);
FastLED.setBrightness(100);
FastLED.show();
return (yellowLight);
} else {
return (noLightPause);
}
}
statusType noLightPauseFunction() {
fill_solid(ledStrip, NUM_LEDS, CRGB::Black);
FastLED.show();
if (digitalRead(buttonPin) == LOW) {
return (yellowLight);
} else {
if (digitalRead(buttonPin) == HIGH) {
return (noLight);
}
}
}
statusType noLightFunction() {
if (digitalRead(buttonPin) == LOW) {
return (yellowLight);
} else {
return (whiteLight);
}
}
@Marvin, 👍0
Обсуждение1 ответ
Лучший ответ:
Вы также должны ввести состояние кнопки, чтобы FSM работал как FSM
bool buttonState = false;
в цикле вы проверяете нажатие/отпускание и меняете состояние:
if (digitalRead(buttonPin) == LOW && buttonState == true) buttonState == false;
if (digitalRead(buttonPin) == HIGH && buttonState == false) buttonState == true;
внутри вашей функции вы выбираете только buttonState, например
statusType noLightFunction() {
if (buttonState == false) { // Кнопка НЕ нажата
return (yellowLight);
} else { // Кнопка нажата
return (whiteLight);
}
}
Кнопка действует как переключатель, пока вы держите ее нажатой (или отпущенной), ничего не изменится, только состояние изменится, если произойдет действие. Я лично использую «говорящие» вары, которые я все еще знаю спустя годы, поэтому вместо
buttonState
Я использую buttonIsPressed
, но это вкус
Спасибо за совет Codebreaker. Я сделаю это, чтобы завершить свой FSM, и я нашел решение, которое делает то, что вы здесь описываете. Состояние yellowLight возвращается с помощью простого: if (millis() - noDelayPause > 1000 || digitalRead(buttonPin) == LOW). Или по истечении времени переходит в состояние белого света., @Marvin
Имейте в виду, что решение с прямым чтением вывода в функции не будет работать в более сложных сценариях из-за времени обработки и других проблем. Пожалуйста, закройте вопрос как решенный/принятый, @Codebreaker007
при сравнении логических значений не используйте if (buttonState == true)
... используйте if (buttonState)
или if (!buttonState)
, @jsotola
- Кнопка с таймером переключения и функцией сброса времени + светодиод обратной связи
- Двигатель постоянного тока Arduino с 2 кнопками
- Нужна помощь с программой для кнопки смены отображения на OLED-дисплее
- Использование switch case с 5-позиционным переключателем и последовательным выходом
- Arduino UNO С Переключателем Модуля Вкл / Выкл + Совет По Батарее
- Один светодиод управляется двумя кнопками - одна из которых действует как тумблер
- Кнопочный переключатель ардуино
- Узнать статус, подключен ли коммутатор к arduino или нет?
Я не уверен, что отвечаю на вопрос: «Где мне поставить buttonState». Вы читаете кнопку внутри функции и позволяете ей решить, какой статус принять дальше. Это звучит вполне разумно. Что происходит или не происходит прямо сейчас, что не соответствует вашим ожиданиям? Сравните и немного сопоставьте симптом и ожидаемое поведение., @Delta_G