The code-version below shows a lot of programming techniques at once.
It might be that this is a little bit overwhelming.
I decided to post this code-version as some kind of experiment.
I would like to know your absolutelyhonest opinion especially regarding the aspect
if this code is easy, medium, hard, or very hard to understand.
Usually tutorials would take smaller code-examples and pages long explanations for each small demo-code.
Take some time to read each line of code.
I have added explanation and I'm very interested in if you are able to understand this rather complex code and if the explanations are sufficient.
If you have questions just post your questions. I will answer them.
I'm interested in learning what complexity of code and what kind of explanations give a good balance between still understandable and proceeding fast in learning programming.
Here is the code and below a link to the WOKWI-simulator
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(" ");
}