Why won't this state machine case work?

I think basically this is incredibly simple but i can't work out why it's not working as intended. I want it so that every time the sketch is uploaded or power is cycled it always starts with case STATE 0. However when i upload the sketch or cycle power LED1 does not turn on. Then when i press the button LED1 lights up and every subsequent button press causes it to cycle through the states as expected. So why won't it start with case STATE 0? I can only get it to do this if i hold the button whilst i upload or cycle power. Just can't get my head round it. Any help would be greatly appreciated!

#include <Bounce2.h>

// Define the states
enum State {
  STATE_0,
  STATE_1,
  STATE_2,
  STATE_3
};


Bounce D10 = Bounce(10, 50);

State currentState = STATE_1; // Initial state
bool switchPressed = false;   // Flag to track switch state

void setup() {
   // Ensure currentState starts with STATE_1
  currentState = STATE_0;
  Serial.begin(9600);
  pinMode(10, INPUT_PULLUP);
  pinMode(3, OUTPUT);       // pin 3 (the LED) is an output;
  pinMode(4, OUTPUT);       // pin 4 led
  pinMode(11, OUTPUT);      // pin 11 led
  pinMode(12, OUTPUT);      // pin 12 led

 
}

void loop() {
  // SWITCH STATE CASES
  
  // Check for falling edge of the switch
  if (digitalRead(10) == LOW && !switchPressed) {
    // Flag the switch as pressed
    switchPressed = true;
    
    switch(currentState) {
      case STATE_0:
        digitalWrite(3, HIGH);
        digitalWrite(4, LOW);
        digitalWrite(11, LOW);
        digitalWrite(12, LOW);
        break;
      case STATE_1:
        digitalWrite(3, LOW);
        digitalWrite(4, HIGH);
        digitalWrite(11, LOW);
        digitalWrite(12, LOW);
        break;
      case STATE_2:
        digitalWrite(3, LOW);
        digitalWrite(4, LOW);
        digitalWrite(11, HIGH);
        digitalWrite(12, LOW);
        break;
      case STATE_3:
        digitalWrite(3, LOW);
        digitalWrite(4, LOW);
        digitalWrite(11, LOW);
        digitalWrite(12, HIGH);
        break;
    }
    
    // Increment the state
    currentState = static_cast<State>((currentState + 1) % 4);

    // Debugging output
    Serial.println("Switch pressed. Current state: " + String(currentState));
  }

  // Check for rising edge of the switch
  if (digitalRead(10) == HIGH && switchPressed) {
    // Reset the switch state flag
    switchPressed = false;

    // Debugging output
    Serial.println("Switch released. Current state: " + String(currentState));
  }
}

On a cursory read, your switch statement is only executed once the switch is pressed. So no matter what you initially set currentState to, it won't be acted upon until you press the switch. You'd have to extract the switch statement to a separate function and call that at the end of setup() and when your switch is pressed in loop() to get the result you describe.

1 Like

What @van_der_decken said.

Also

I can't, so do me a favor and try just throttling your loop a bit to see if you are victimized by switch bouncing.

Add one statement to your loop() function

void loop() {

 delay(20);  // poor man's debouncing

// rest of your code

It may not be a problem. On the other hand, you may just be playing nice. See what happens when you act like you are trying to break it… short very short presses, rapid repeated pressing and my favorite, hold the button down for a longish time and see what happens when you let your finger off it.

a7

Your LED states all have an LED on, so this actually starts in an undetermined LED state, with no LED on, and pressing the button changes the LED state to 0, although your program says "state: 1."

Your button debounce missed a step. This is how I have learned to check for a button press.

  1. Read the button pin.
  2. Did the button pin change states
  3. If the button pin state has changed (from noise or a button press)...
  4. ... Start a timer
  5. Update lastRead
  6. If time since last read is greater than debounce time...
  7. ... AND the button WAS pressed...
  8. ... THEN if the button IS released...
  9. Change LED states.
  10. Update thisButtonState to lasatRead
  currentButtonRead = digitalRead(buttonPin); // #1 - bool, byte
  if (currentButtonRead != lastButtonRead) { // #2, #3 - bool, bool
    timer = millis(); // #4 - unsigned long
    lastButtonRead = currentButtonRead; // #5 - bool, bool
  }

  if ((millis() - timer) > debounce) { // #6 - unsigned long, unsigned long, unsigned long
    if (currentButtonState == HIGH && lastButtonRead == LOW) { // #7, #8 - bool, bool
.
.
// change LED states // #9
.
.
    currentButtonState = lastButtonRead; // #10 - bool, bool

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.