const byte red_pin = 10;
const byte yellow_pin = 8;
const byte green_pin = 12;
const byte sm_Red = 0; // name "sm_Red" represents value 0
const byte sm_Green = 1; // name "sm_Green" represents value 1
const byte sm_YellowGreen = 2; // name "sm_YellowGreen" represents value 2
byte myStateVar = sm_Red; // variable used for the switch-case-break-stateMachine
// indexed variable (= array of chars) used for printing letters
const char myStateNames[][16] = {
"Red",
"Green",
"YellowGreen"
};
unsigned long myTimerVar; // variable used for non-blocking timing
void setup () {
Serial.begin(115200); // open serial interface with "speed" 115200 baud
Serial.println( F("Setup-Start") );
pinMode (red_pin, OUTPUT);
pinMode (yellow_pin, OUTPUT);
pinMode (green_pin, OUTPUT);
Serial.println( F("exiting Setup infinite looping begins") );
}
void loop () {
myTrafficLight_StateMachine(); // call lines of code defined inside void myTrafficLight_StateMachine()
}
// definition of user-defined function with name "myTrafficLight_StateMachine"
void myTrafficLight_StateMachine() {
printStateWhenChanged(myStateVar); // call lines of code defined inside void printStateWhenChanged (byte p_actualState)
// depending on which value 0,1 or 2 variable myStateVar has
// mutually exclusive execute only the code below/inside
// case sm_Red
// or case sm_Green:
// or sm_YellowGreen:
switch (myStateVar) {
case sm_Red:
digitalWrite (red_pin, HIGH);
digitalWrite (yellow_pin, LOW);
digitalWrite (green_pin, LOW);
// check if more than 5000 milliseconds of time have passed by
if ( TimePeriodIsOver(myTimerVar,5000) ) {
// when REALLY 5000 milliseconds of time HAVE passed by
myStateVar = sm_Green; // change to state sm_Green
}
break; // IMMIDIATELY jump down to END-OF-SWITCH
case sm_Green:
digitalWrite (red_pin, LOW);
digitalWrite (yellow_pin, LOW);
digitalWrite (green_pin, HIGH);
// check if more than 5000 milliseconds of time have passed by
if ( TimePeriodIsOver(myTimerVar,5000) ) {
// when REALLY 5000 milliseconds of time HAVE passed by
myStateVar = sm_YellowGreen; // change to state sm_YellowGreen
}
break; // IMMIDIATELY jump down to END-OF-SWITCH
case sm_YellowGreen:
digitalWrite (red_pin, LOW);
digitalWrite (yellow_pin, HIGH);
digitalWrite (green_pin, HIGH);
// check if more than 2000 milliseconds of time have passed by
if ( TimePeriodIsOver(myTimerVar,2000) ) {
// when REALLY 2000 milliseconds of time HAVE passed by
myStateVar = sm_Red; // change to state sm_Red
}
break; // IMMIDIATELY jump down to END-OF-SWITCH
} // END-OF-SWITCH
}
// easy to use helper-function for non-blocking timing
boolean TimePeriodIsOver (unsigned long &startOfPeriod, unsigned long TimePeriod) {
unsigned long currentMillis = millis();
if ( currentMillis - startOfPeriod >= TimePeriod ) {
// more time than TimePeriod has elapsed since last time if-condition was true
startOfPeriod = currentMillis; // a new period starts right here so set new starttime
return true;
}
else return false; // actual TimePeriod is NOT yet over
}
void printStateWhenChanged (byte p_actualState) {
static byte lastState; // "static makes value of variable lastState persistant
// check if state has CHANGED since last time this function was called
if (p_actualState != lastState ) {
// when state HAS changed
printTimeStampMilliSeconds(); // call lines of code defined under printTimeStampMilliSeconds()
Serial.print( F("state changed from ") );
Serial.print(myStateNames[lastState]);
Serial.print( F(" to ") );
Serial.print(myStateNames[p_actualState]);
Serial.println();
lastState = p_actualState; // update variable lastState
}
}
void printTimeStampMilliSeconds() {
Serial.print("ms:");
Serial.print(millis() );
Serial.print(" ");
}