--- /dev/null
+/*
+A traffic light for an intersection of a
+highway and a country road. Normally, the light
+should be green for the highway and red for the
+country road, but when traffic approaches on
+the country road, the highway gets a red light
+and the country road gets a green light.
+
+When a light turns red it transitions from green to
+red it goes through yellow, but a red light changing
+to green transitions directly to green.
+
+A pushbutton represents a car approaching on
+the country road.
+
+Implement the solution with a Finite State
+Machine or FSM.
+
+Following the excellent description at
+http://hacking.majenko.co.uk/finite-state-machine
+first break down the problem into states.
+
+Identify which states are Transitional (T) and
+which are Static (S). A Static state is one in
+which the FSM is waiting for stimulus, and is
+taking no actions. A Transitional State is a
+state which causes actions, but doesn't look
+for stimulus.
+
+A Transitional State runs once and immediately
+moves on to a Static State.
+
+State 0: highway = green, country = red; (T)
+State 1: wait for car on country road (S)
+State 2: highway = yellow, make note of current time (T)
+State 3: wait for yellow time to pass (S)
+State 4: highway = red, country = green, make note of current time (T)
+State 5: wait for highway red time to pass (S)
+State 6: country = yellow, make note of current time (T)
+state 7: wait for yellow time to pass (S) then go to 0
+*/
+
+// Use names for states so it's easier to
+// understand what the code is doing
+const int S_HIGHWAYGREEN = 0;
+const int S_WAITCARCOUNTRY = 1;
+const int S_HIGHWAYYELLOW = 2;
+const int S_WAITHIGHWAYYELLOW = 3;
+const int S_HIGHWAYRED = 4;
+const int S_WAITHIGHWAYRED = 5;
+const int S_COUNTRYYELLOW = 6;
+const int S_WAITCOUNTRYYELLOW = 7;
+
+// Pin numbers
+const int countrySensorPin = 2;
+
+const int highwayGreenLEDPin = 3;
+const int highwayYellowLEDPin = 4;
+const int highwayRedLEDPin = 5;
+
+const int countryGreenLEDPin = 6;
+const int countryYellowLEDPin = 7;
+const int countryRedLEDPin = 8;
+
+void setup()
+{
+ pinMode(highwayGreenLEDPin, OUTPUT);
+ pinMode(highwayYellowLEDPin, OUTPUT);
+ pinMode(highwayRedLEDPin, OUTPUT);
+ pinMode(countryGreenLEDPin, OUTPUT);
+ pinMode(countryYellowLEDPin, OUTPUT);
+ pinMode(countryRedLEDPin, OUTPUT);
+}
+
+void loop()
+{
+
+ // start off with the highway getting green
+ // The keyword "static" makes sure the variable
+ // isn't destroyed after each loop
+ static int state = S_HIGHWAYGREEN ;
+
+ // To store the current time for delays
+ static unsigned long ts;
+
+ switch (state)
+ {
+ case S_HIGHWAYGREEN:
+ // Highway gets green, country road red
+ digitalWrite( highwayGreenLEDPin, HIGH);
+ digitalWrite( highwayYellowLEDPin, LOW);
+ digitalWrite( highwayRedLEDPin, LOW);
+
+ digitalWrite( countryGreenLEDPin, LOW);
+ digitalWrite( countryYellowLEDPin, LOW);
+ digitalWrite( countryRedLEDPin, HIGH);
+
+ state = S_WAITCARCOUNTRY;
+
+ break;
+
+ case S_WAITCARCOUNTRY:
+
+ if ( digitalRead (countrySensorPin) == HIGH) {
+ state = S_HIGHWAYYELLOW;
+ }
+
+ break;
+
+ case S_HIGHWAYYELLOW:
+ digitalWrite( highwayGreenLEDPin, LOW);
+ digitalWrite( highwayYellowLEDPin, HIGH);
+ digitalWrite( highwayRedLEDPin, LOW);
+
+ digitalWrite( countryGreenLEDPin, LOW);
+ digitalWrite( countryYellowLEDPin, LOW);
+ digitalWrite( countryRedLEDPin, HIGH);
+
+ ts = millis(); // Remember the current time
+
+ state = S_WAITHIGHWAYYELLOW; // Move to the next state
+
+ break;
+
+ case S_WAITHIGHWAYYELLOW:
+ // If two seconds have passed, then move on to the next state.
+ if (millis() > ts + 2000)
+ {
+ state = S_HIGHWAYRED;
+ }
+
+ break;
+
+ case S_HIGHWAYRED:
+ // Highway red, country road green
+ digitalWrite( highwayGreenLEDPin, LOW);
+ digitalWrite( highwayYellowLEDPin, LOW);
+ digitalWrite( highwayRedLEDPin, HIGH);
+
+ digitalWrite( countryGreenLEDPin, HIGH);
+ digitalWrite( countryYellowLEDPin, LOW);
+ digitalWrite( countryRedLEDPin, LOW);
+
+ ts = millis(); // Remember the current time
+
+ state = S_WAITHIGHWAYRED;
+
+ break;
+
+ case S_WAITHIGHWAYRED:
+
+ // If five seconds have passed, then start
+ // transition to a red light for the country
+ // road
+ if (millis() > ts + 5000)
+ {
+ state = S_COUNTRYYELLOW;
+ }
+
+ break;
+
+ case S_COUNTRYYELLOW:
+ digitalWrite( highwayGreenLEDPin, LOW);
+ digitalWrite( highwayYellowLEDPin, LOW);
+ digitalWrite( highwayRedLEDPin, HIGH);
+
+ digitalWrite( countryGreenLEDPin, LOW);
+ digitalWrite( countryYellowLEDPin, HIGH);
+ digitalWrite( countryRedLEDPin, LOW);
+
+ ts = millis(); // Remember the current time
+
+ state = S_WAITCOUNTRYYELLOW;
+
+ break;
+
+ case S_WAITCOUNTRYYELLOW:
+
+ // If two seconds have passed, then go
+ // back to the beginning with the highway
+ // getting the green light
+ if (millis() > ts + 2000)
+ {
+ state = S_HIGHWAYGREEN;
+ }
+
+ break;
+
+ } // end of switch
+
+ // other things could go on here, and they would not affect the timing
+ // of the traffic light
+
+} // end of loop