Правильная позиция для 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);
  }
}

, 👍0

Обсуждение

Я не уверен, что отвечаю на вопрос: «Где мне поставить buttonState». Вы читаете кнопку внутри функции и позволяете ей решить, какой статус принять дальше. Это звучит вполне разумно. Что происходит или не происходит прямо сейчас, что не соответствует вашим ожиданиям? Сравните и немного сопоставьте симптом и ожидаемое поведение., @Delta_G


1 ответ


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

0

Вы также должны ввести состояние кнопки, чтобы 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