imho braucht man da keinen Interrupt und keine direkten Portzugriffe.
Ich arbeite gerade an einer Ampel, daher kann ich eine Variante zeigen.
Jede Ampel ist ein Objekt
Die Nord-Ampel ist rot gelb grün für Autos und kennt die Bilder rot rot-gelb, grün, gelb
Die Fußgänger-Ampel ist rot grün (war zu faul für eine eigene Klasse, daher zweimal der gleiche GPIO)
Eine Statemachine "traffic Manager" kümmert sich um den Ablauf.
Im Idle läuft das Muster durch,
Drückt ein Fußgänger auf den Button wird für die Fußgänger eine Grün-Phase forciert.
Genau genommen spring es in den Ablauf sodass die Autofahrer Gelb erhalten, dann Rot und erst dann schaltet die Fußgängerampel auf Grün (gem. Ablauf).
Für Österreicher und Ukrainer soll es leicht sein, ein "grün blinken" einzuführen.
// Traffic Lights
// by noiasca
// introduce the taffic manager and a walking light with push button
// https://forum.arduino.cc/index.php?topic=650985.0
enum trafficLightColor {red, redyellow, green, yellow}; // available colors/colorcombinations on a traffic lights
// row, colum
const uint8_t sequenceA [][3] //interval, north, walk
{
{ 8, green, red}, // 0 Fahrt - stehen
{ 2, yellow, red}, // 1 Anhalten - stehen
{ 2, red, red}, // 2 Stop - stehen
{ 4, red, green}, // 3 Stop - gehen
{ 2, red, red}, // 4 Stop - stehen
{ 2, redyellow, red} // 5 BereitMachen - stehen
};
const byte noOftrafficStates = 6;
byte trafficStateCurrent = 0; // the current state of the traffic
const uint16_t factorIntervall = 1000; // a factor for the intervall
const byte northWalkRequestPin = 12; // force Green for West
const byte northWalkRequestState = 1; // status if west Requests
class TrafficLight {
byte 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(byte newState)
{
state = newState;
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 trafficLightNorthWalk(5, 6, 6); // the traffic light for walkway and the LED pins for red, green (no yellow
void setup() {
Serial.begin(115200);
Serial.println(F("traffic lights"));
pinMode(northWalkRequestPin, INPUT_PULLUP);
trafficLightNorth.begin();
trafficLightNorthWalk.begin();
}
void runTrafficController() {
static uint32_t lastMillis = -10000; // last update
static uint8_t trafficStateIntervall = 0; // current intervall for this state
if (millis() - lastMillis >= trafficStateIntervall * factorIntervall) // do something by time
{
lastMillis = millis();
trafficStateCurrent++; // --> simple switch to next state
trafficStateCurrent = trafficStateCurrent % noOftrafficStates;
Serial.print(F("sequenceA:")); Serial.println(trafficStateCurrent);
trafficStateIntervall = sequenceA[trafficStateCurrent][0];
trafficLightNorth.setState(sequenceA[trafficStateCurrent][1]);
trafficLightNorthWalk.setState(sequenceA[trafficStateCurrent][2]);
}
if (!digitalRead(northWalkRequestPin) && (trafficStateCurrent == 0 || trafficStateCurrent == 4 || trafficStateCurrent == 5))
{
Serial.println(F("West Request"));
lastMillis = millis();
trafficStateCurrent = northWalkRequestState;
Serial.print(F("sequenceA:")); Serial.println(trafficStateCurrent);
trafficStateIntervall = sequenceA[trafficStateCurrent][0];
trafficLightNorth.setState(sequenceA[trafficStateCurrent][1]);
trafficLightNorthWalk.setState(sequenceA[trafficStateCurrent][2]);
delay(50); // Dirty debounce
}
}
void loop()
{
runTrafficController();
// do what ever you want unblocked here
}