Weekly Journal 3 – State Machines & Timing (Janosch Spohner)

State Machines

This week in lab we learned about the concept of state machines and how important they are for creating complex behaviors. State machines work by establishing a bunch of states, which when in a specific state can do something.  By using a whole bunch of if statements and some inputs you can control the transition between states which will give you the desired behavior.

Jan. 30

On Monday we started out by doing a simple state machine that controlled the behavior of a single LED. This state machine had 4 states, initially the LED is off so that is one state. Then there was a recorder state that used two button inputs to calculate how long the LED would flash when the other button is pressed. Then there were the last two states which were activated by the push of the other button, the LED would flash on and off between the two states. Below is a visual diagram to show the behavior of the LED.

We do not have a video of the behavior because we struggled with the code for a while before we finally got it to work. Below is the code that we struggled with. Our issue was that the LED would not flash and we could not figure out for the longest time. Every time we pressed the button it would go to the Blink on state and then just stay lit. The problem turned out to be a simple mistake where instead of a = we had ==. To be specific; at the bottom of out blink on state where we were setting the currentState to BlinkOFFState we had two equal signs instead of one so instead of setting the current state to something new it was just checking that and basically not changing anything.

  else if (currentState == BLINK_ON_STATE) {
    if (pressedB) {
      currentState = INITIAL_STATE;
    } else if (currentTime - StartTime > diff) {
      StartTime = millis();
      currentState = BLINK_OFF_STATE;
    }
  }

  else if (currentState == BLINK_OFF_STATE) {
    if (pressedB) {
      currentState = INITIAL_STATE;
    } else if (currentTime - StartTime > diff) {
      StartTime = millis();
      currentState = BLINK_ON_STATE;
    }
  }
}

 

 

Feb. 1 – Diving Deeper

On Wednesday we continued our topic of state machines by developing a much more complicated behavior that was achieved by building three different state machines that all worked together at the same time to create our desired behavior. Below is the visual diagram to the behavior.

 

Since we finished this one by the end of class we remembered to get a video of it.

giphy.gif

The button on the left will change the left two LED’s from flashing between each other to both flashing on and off at the same time. The button on the right changes how fast the three LED’s on the right flash.

The code was similar to our first state machine besides there were more LED’s, many more states and three different state machines. This resulted in many more lines of code and we will need to spend some time cleaning it up and condensing it. Below you can see how we set up our three state machines with all their own states.

//enumerates the States for STATE MACHINE 1
enum State1 {
  LEFT_ON,
  RIGHT_ON,
  BOTH_ON,
  NEITHER_ON,
};

State1 currentState1;

//enumerates the States for STATE MACHINE 2
enum State2 {
  THREE_ON,
  THREE_OFF,
};

State2 currentState2;

//enumerates the States for STATE MACHINE 3
enum State3 {
  PAUSE_ONE,
  PAUSE_TWO,
};

State3 currentState3;

 

Below is our for loop just to show how long it got after getting the behavior to work.

void loop() {
  //Display the current states that we are in (STATE MACHINE 1)
  if (currentState1 == LEFT_ON) {
    digitalWrite(Led1, HIGH);
    digitalWrite(Led2, LOW);
  }
  else if (currentState1 == RIGHT_ON) {
    digitalWrite(Led1, LOW);
    digitalWrite(Led2, HIGH);
  }
  else if (currentState1 == BOTH_ON) {
    digitalWrite(Led1, HIGH);
    digitalWrite(Led2, HIGH);
  }
  else if (currentState1 == NEITHER_ON) {
    digitalWrite(Led1, LOW);
    digitalWrite(Led2, LOW);
  }

  //Display the current statess that we are in (STATE MACHINE 2)
  if (currentState2 == THREE_ON) {
    for (int pin = Led3; pin < Led5 + 1; pin++) {
      digitalWrite(pin, HIGH);
    }
  }
  else if (currentState2 == THREE_OFF) {
    for (int pin = Led3; pin < Led5 + 1; pin++) {
      digitalWrite(pin, LOW);
    }
  }

  //Update and read inputs
  debouncerA.update();
  debouncerB.update();
  int pressedA = debouncerA.rose();
  int btnValueB = debouncerB.read();
  long currentTime = millis();

  //Update state based on the inputs (STATE MACHINE 1)
  //LEFT_ON STATE
  if (currentState1 == LEFT_ON) {
    if (pressedA) {
      startTime1 = currentTime;
      currentState1 = BOTH_ON;
    }
    else if (currentTime - startTime1 > pause1) {
      startTime1 = currentTime;
      currentState1 = RIGHT_ON;
    }
  }

  //RIGHT_ON
  else if (currentState1 == RIGHT_ON) {
    if (pressedA) {
      startTime1 = currentTime;
      currentState1 = BOTH_ON;
    }
    else if (currentTime - startTime1 > pause1) {
      startTime1 = currentTime;
      currentState1 = LEFT_ON;
    }
  }

  //BOTH_ON
  else if (currentState1 == BOTH_ON) {
    if (pressedA) {
      startTime1 = currentTime;
      currentState1 = LEFT_ON;
    }
    else if (currentTime - startTime1 > pause1) {
      startTime1 = currentTime;
      currentState1 = NEITHER_ON;
    }
  }

  //NEITHER_ON
  else if (currentState1 == NEITHER_ON) {
    if (pressedA) {
      startTime1 = currentTime;
      currentState1 = RIGHT_ON;
    }
    else if (currentTime - startTime1 > pause1) {
      startTime1 = currentTime;
      currentState1 = BOTH_ON;
    }
  }

  //Update state based on the inputs (STATE MACHINE 2)
  //THREE_ON STATE
  if (currentState2 == THREE_ON) {
    if (currentTime - startTime2 > pause) {
      startTime2 = currentTime;
      currentState2 = THREE_OFF;
    }
  }
  //THREE_OFF STATE
  else if (currentState2 == THREE_OFF) {
    if (currentTime - startTime2 > pause) {
      startTime2 = currentTime;
      currentState2 = THREE_ON;
    }
  }

   //Update state based on the inputs (STATE MACHINE 2)
  //PAUSE_ONE 
  if (currentState3 == PAUSE_ONE) {
    pause = pause1;
    if (btnValueB) {
      currentState3 = PAUSE_TWO;
      }
    }

    if (currentState3 == PAUSE_TWO) {
    pause = pause2;
    if (!btnValueB) {
      currentState3 = PAUSE_ONE;
      }
    }

}

As you can tell we will need to do some condensing here to make this cleaner and easier to read.

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s