I tried a different approach based on traffic lights
Lets assume one way roads for the beginning (or just mirror the traffic lights)
For a simple North-South West-East Crossing I need at least 2 traffic lights
A traffic light has 3 LEDs.
In most European countries a traffic light has (at least) four states:
- red
- red yellow
- green
- yellow
To avoid crashes on my crossing I considered following states with following faces for my two traffic lights
/* State NorthWest WestEast
NorthGo green red // North-South can go
NorthAwaitRed yellow red // North-South will be informed that red will come soon
NorthRed red red // North-South has to stop
WestAwaitGreen red red yellow // West-East should be prepared to get green soon
WestGo red green // West-East can go
WestAwaitRed red yellow // West-East will be informed that red will come soon
WestRed red red // West-East has to stop
NorthAwaitGreen red yellow red // North-East should be prepared to get green soon
*/
so I came up with 8 phases for a full circle.
Each phase can have an individual interval.
The two traffic lights are represented by two objects of a TrafficLight class.
Each Traffic Light cares about its LED pins/colors.
There is one "Traffic Light Controller" who does ... controll the lights & does the time keeping.
This approach got longer than expected. Nevertheless I think its understandable and very open for adoptions.
You don't like the phases? ... delete what you don't need
You want to add yellow blinking ... great, add a new blink method to the traffic object
You are from Austria or Ukraine? ... add green blinking before your yellow phase.
// Traffic Lights
// for https://forum.arduino.cc/index.php?topic=649027.0
// by noiasca
/* State NorthWest WestEast
NorthGo green red
NorthAwaitRed yellow red
NorthRed red red
WestAwaitGreen red red yellow
WestGo red green
WestAwaitRed red yellow
WestRed red red
NorthAwaitGreen red yellow red
*/
enum trafficLightColor {red, redyellow, green, yellow}; // available colors/colorcombinations on a traffic lights
// Possible states for a crossing
enum trafficStates {northGo, // North-South can go
northAwaitRed, // North-South will be informed that red will come soon
northRed, // North-South has to stop
westAwaitGreen, // West-East should be prepared to get green soon
westGo, // West-East can go
westAwaitRed, // West-East will be informed that red will come soon
westRed, // West-East has to stop
northAwaitGreen, // North-East should be prepared to get green soon
noOftrafficStates // the last state is just a counter
};
byte trafficStateCurrent = northAwaitRed; // the current state of the traffic
const uint8_t trafficStateIntervall[] = {8, 2, 2, 2, 8, 2, 2, 2}; // The time for each State
const uint16_t factorIntervall = 1000; // a factor for the intervall
class TrafficLight {
trafficLightColor state = red;
unsigned long previousMillis;
const byte ledPinRed;
const byte ledPinYellow;
const byte ledPinGreen;
public:
TrafficLight(byte red, byte yellow, byte green):
ledPinRed(red),
ledPinYellow(yellow),
ledPinGreen(green)
{}
void begin()
{
pinMode(ledPinRed, OUTPUT);
pinMode(ledPinYellow, OUTPUT);
pinMode(ledPinGreen, OUTPUT);
}
void setState(trafficLightColor _state)
{
state = _state;
switch (state)
{
case red :
digitalWrite(ledPinRed, HIGH);
digitalWrite(ledPinYellow, LOW);
digitalWrite(ledPinGreen, LOW);
break;
case redyellow :
digitalWrite(ledPinRed, HIGH);
digitalWrite(ledPinYellow, HIGH);
digitalWrite(ledPinGreen, LOW);
break;
case green :
digitalWrite(ledPinRed, LOW);
digitalWrite(ledPinYellow, LOW);
digitalWrite(ledPinGreen, HIGH);
break;
case yellow :
digitalWrite(ledPinRed, LOW);
digitalWrite(ledPinYellow, HIGH);
digitalWrite(ledPinGreen, LOW);
break;
}
}
};
TrafficLight trafficLightNorth(2, 3, 4); // the traffic light North-South and the LED pins for red, yellow, green
TrafficLight trafficLightWest(5, 6, 7); // the traffic light West-East and the LED pins for red, yellow,
void setup() {
Serial.begin(115200);
Serial.println(F("traffic lights"));
trafficLightNorth.begin();
trafficLightWest.begin();
}
void runTrafficController() {
static uint32_t lastMillis = -10000; // last update
if (millis() - lastMillis >= trafficStateIntervall[trafficStateCurrent] * factorIntervall) // do something by time
{
lastMillis = millis();
trafficStateCurrent++; // --> simple switch to next state
if (trafficStateCurrent >= noOftrafficStates) trafficStateCurrent = northGo;
switch (trafficStateCurrent)
{
case northGo:
Serial.println(F("NorthGo (WestStop)"));
trafficLightNorth.setState(green);
trafficLightWest.setState(red);
break;
case northAwaitRed:
Serial.println(F("NorthAwaitRed (WestStop)"));
trafficLightNorth.setState(yellow);
trafficLightWest.setState(red);
break;
case northRed:
Serial.println(F("NorthRed (WestAwaitGreen))"));
trafficLightNorth.setState(red);
trafficLightWest.setState(redyellow);
break;
case westGo:
Serial.println(F("WestGo (NorthRed)"));
trafficLightNorth.setState(red);
trafficLightWest.setState(green);
break;
case westAwaitRed:
Serial.println(F("WestAwaitRed (NorthRed)"));
trafficLightNorth.setState(red);
trafficLightWest.setState(yellow);
break;
case westRed:
Serial.println(F("WestRed (NorthRed)"));
trafficLightNorth.setState(red);
trafficLightWest.setState(red);
break;
case northAwaitGreen:
Serial.println(F("NorthAwaitGreen (WestRed)"));
trafficLightNorth.setState(redyellow);
trafficLightWest.setState(red);
break;
}
}
}
void loop()
{
runTrafficController();
// do what ever you want unblocked here
}