0% found this document useful (0 votes)
1 views8 pages

State Code Examples 2

The document describes a state machine implemented in Arduino code that controls an LED's color based on button presses. It uses a switch/case structure to manage states (off, red, blue, green) and includes functions for pulsing LEDs and blinking a status LED. Additionally, it addresses a bug where button presses were ignored during LED pulsing by modifying the PulseLed function to read button states concurrently.

Uploaded by

fitrianiangkri
Copyright
© All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
1 views8 pages

State Code Examples 2

The document describes a state machine implemented in Arduino code that controls an LED's color based on button presses. It uses a switch/case structure to manage states (off, red, blue, green) and includes functions for pulsing LEDs and blinking a status LED. Additionally, it addresses a bug where button presses were ignored during LED pulsing by modifying the PulseLed function to read button states concurrently.

Uploaded by

fitrianiangkri
Copyright
© All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd

state code examples #2 1/8

Using switch/case as the core of your state machine

// a state machine with an on/off switch and a button that changes the
// LED color each time you press the button.

// our states. We could do these with #defines once we've learned


// them "static" means this variable's value cannot be changed once
// it's set, it's a good way to prevent yourself from accidentally
// changing the value in your code.
//
// These *must* be declared "const int" and not just "int", don't ask
// why, just do it or your code will not compile.
//
const int sOff = 0;
const int sRed = 1;
const int sBlue = 2;
const int sGreen = 3;

// the current state we're in at any given time. We want to start in


// "off", so we set the variable to sOff when we declare it.
int currentState = sOff;

// we need to have somewhere to go when we leave sOff, so let's pick


// red
int nextState = sRed;

// our on/off switch


int onOffPin = 2;

// the momentary switch we use to change the color


int colorPin = 4;

// the LEDs
int redLed = 10;
int greenLed = 11;
int blueLed = 9;
int statusLed = 13;

void setup()
{

pinMode(onOffPin, INPUT);
pinMode(colorPin, INPUT);
pinMode(statusLed, OUTPUT);
pinMode(redLed, OUTPUT);
pinMode(blueLed, OUTPUT);
pinMode(greenLed, OUTPUT);

// if we didn't set the initial state when we created the variable,


// we'd do it here. The initial state is "off" or "start" in most
// state machines, but if you only have active/on states, pick an
// appropriate starting state.
state code examples #2 2/8

//
// currentState = sOff;
[Link](9600);
}

void loop()
{

BlinkStatusLed();

// Every time through the loop we check the state we're in with a
// switch/case statement.

// switch/case statements are replacement for using lots of


// if/else statements. Instead of doing this:
// if (a == 1) then { /* statements*/}
// else if (a == 2) then { /* statements*/}
// else if (a == 3) then { /* statements*/}

//we can use switch/case and do this:


// switch(a) { // start of the switch statement
// case 1:
// /* statements */
// break;
// case 2:
// /* statements */
// break;
// case 3:
// /* statements */
// break;
// default:
// /* statements */
// break;
// } // the end of the switch statement.

//You *have* to have a "break;" at the end of each "case".


//When the Arduino gets to a "break" statement, it exits the switch
//statement

// the "default" case is what the switch statement should do if


// nothing is matched. In the above example, if a is 1, 2, or 3 we do
// something. But if a was 4, it wouldn't match the first three cases
// and the "default" case is used. For our state machines, we should
// not have a default case that does anything other than generate an
// error message and reset the state machine

// for our state machine, each state is contained in its own case
// statement. in each case, the first thing we do is check to see
// if we should be in a different state. If not, then we go ahead
// and do whatever we need to do in this state.

switch(currentState) { // this is the start of the switch


case sOff: // this starts the state of "sOff"
// and this is what we do if currentState == sOff
state code examples #2 3/8

[Link]("off");
if (digitalRead(onOffPin) == HIGH) {
currentState = nextState;
}
break; // this ends the state of "sOff"

case sRed: // start of the "red" case


[Link]("red");
if (digitalRead(onOffPin) == LOW) {
currentState = sOff;
nextState = sRed;
}
else if (digitalRead(colorPin) == HIGH) {
currentState = sBlue;
}
else {
PulseLed(redLed);
}
break; // end of the red case.

case sBlue:
[Link]("blue");
if (digitalRead(onOffPin) == LOW) {
currentState = sOff;
nextState = sRed;
}
else if (digitalRead(colorPin) == HIGH) {
currentState = sGreen;
}
else {
PulseLed(blueLed);
}
break;

case sGreen:
[Link]("green");
if (digitalRead(onOffPin) == LOW) {
currentState = sOff;
nextState = sRed;
}
else if (digitalRead(colorPin) == HIGH) {
currentState = sRed;
}
else {
PulseLed(greenLed);
}
break;

default: // the default case, which is an error for us


[Link]("ERROR: default state");
currentState = sOff;
nextState = sRed;
break;
} // this is the end of the case, where we go after we hit a break;
state code examples #2 4/8

void PulseLed(int pin) {


for (int i=0; i<=255; i++) {
analogWrite(pin, i);
delay(2);
}
for (int i=255; i>=0; i--) {
analogWrite(pin, i);
delay(2);
}
}

void BlinkStatusLed()
{
digitalWrite(statusLed,HIGH);
delay(100);
digitalWrite(statusLed,LOW);
;
delay(100);
}
state code examples #2 5/8

Reading a Switch While Pulsing an LED


// a state machine with an on/off switch and a button that changes the
// LED color each time you press the button.

// as was demonstrated in class with state_machine_switch.pde, there's


// a bug: if some pushes the "change" button while the PulseLed()
// subroutine is happening, the button is ignored. PulseLed() is busy
// making the LED get brighter and darker and does not actually read
// the button.
//
// one solution is to read the button while you're in PulseLed(). But
// if you read the button, how do you get that information back to
// your state machine so it can do the right thing?
//
// We will solve this by changing PulseLed so that it reads the button
// while pulsing, then returns a value of "true" if the button was
// pushed. Compare this program with state_machine_switch.pde and
// look at the differences in what we do. We're still implementing
// the same state machine as before, but we read the button more often
// and have a better interaction experience with the button pusher.
//
// Also, see the case for sRed for some comments on how we change
// reading the button in our state machine now that we can read the
// button while pulsing the LED.

const int sOff = 0;


const int sRed = 1;
const int sBlue = 2;
const int sGreen = 3;

// the current state we're in at any given time. We want to start in


// "off", so we set the variable to sOff when we declare it.
int currentState = sOff;

// we need to have somewhere to go when we leave sOff, so let's pick


// red
int nextState = sRed;

// our on/off switch


int onOffPin = 2;

// the momentary switch we use to change the color


int colorPin = 4;

// the LEDs
int redLed = 10;
int greenLed = 11;
int blueLed = 9;
int statusLed = 13;

void setup()
{
state code examples #2 6/8

pinMode(onOffPin, INPUT);
pinMode(colorPin, INPUT);
pinMode(statusLed, OUTPUT);
pinMode(redLed, OUTPUT);
pinMode(blueLed, OUTPUT);
pinMode(greenLed, OUTPUT);

// if we didn't set the initial state when we created the variable,


// we'd do it here. The initial state is "off" or "start" in most
// state machines, but if you only have active/on states, pick an
// appropriate starting state.
//
// currentState = sOff;
[Link](9600);
}

void loop()
{

BlinkStatusLed();

switch(currentState) {
case sOff:
[Link]("off");
if (digitalRead(onOffPin) == HIGH) {
currentState = nextState;
}
break;

case sRed:
[Link]("red");
if (digitalRead(onOffPin) == LOW) {
currentState = sOff;
nextState = sRed;
}
// now that we can read the colorPin while we're pulsing
// the LED, we no longer need to explicitly read it here.
// We just pulse the LED, and if the button was pushed
// while we were reading, we change the state.
else if (PulseLedReadButton(redLed, colorPin) == true) {
currentState = sBlue;
}
break;

case sBlue:
[Link]("blue");
if (digitalRead(onOffPin) == LOW) {
currentState = sOff;
nextState = sRed;
}
else if (PulseLedReadButton(blueLed, colorPin) == true) {
currentState = sGreen;
}
state code examples #2 7/8

break;

case sGreen:
[Link]("green");
if (digitalRead(onOffPin) == LOW) {
currentState = sOff;
nextState = sRed;
}
else if (PulseLedReadButton(greenLed, colorPin) == true) {
currentState = sRed;
}
break;

default: // the default case, which is an error for us


[Link]("ERROR: default state");
currentState = sOff;
nextState = sRed;
break;
}

// we've made two major changes to PulseLed (which is still here so


// you can compare them)
//
// 1) our new function returns a value. Just like digitalRead()
// returns a value of HIGH or LOW, our new function can return "true"
// or "false". We use a "boolean" variable for this, can only be
// "true" or "false". Anything that calls PulseLedReadButton has to
// do something with this value. (If you want to pulse an led but not
// check the button, call PulseLed() instead.)
//
// 2) When you call PulseLedReadButton, you have to tell it what pin
// the button is on.
//
//
boolean PulseLedReadButton(int lPin, int bPin) {
// we need to keep track of whether or not a button was pushed.
// The default is that it was not pushed.
boolean buttonPushed = false;

// now, every time through each loop, we read the pin to see if
// the button is being pushed. If it is, save that information.
//
// we also do something a bit clever to make the program more
// efficient. If the button *has* been pushed, there's no need to
// read it again
for (int i=0; i<=255; i++) {
analogWrite(lPin, i);
if (buttonPushed == false) {
if ( digitalRead(bPin) == HIGH) {
buttonPushed = true;
}
}
state code examples #2 8/8

delay(2);
}
for (int i=255; i>=0; i--) {
analogWrite(lPin, i);
if (buttonPushed == false) {
if ( digitalRead(bPin) == HIGH) {
buttonPushed = true;
}
}
delay(2);
}
// the "return" statement is how we get the information back to
// the code that called us.
return buttonPushed;
}

// the previous version of PulseLed


void PulseLed(int pin) {
for (int i=0; i<=255; i++) {
analogWrite(pin, i);
delay(2);
}
for (int i=255; i>=0; i--) {
analogWrite(pin, i);
delay(2);
}
}

void BlinkStatusLed()
{
digitalWrite(statusLed,HIGH);
delay(100);
digitalWrite(statusLed,LOW);
;
delay(100);
}

You might also like