Na das ist ja nun nichts mit Sicherheitsschaltung, das ist nur die Unterbrechung der StateMachine mit Rückkehr an einen definierten Punkt.
// basiert auf https://forum.arduino.cc/t/toilettenampel-mit-tasterhaltung/914301/45?u=my_xy_projekt
// erweitert um eine Abfragebedingung in ST_REDyellow
const byte PinLed [] = { 5, 7, 9 };
const byte PinBut = 11;
enum { Off, On };
enum { ST_IDLE, ST_YELLOW, ST_RED, ST_REDwait, ST_REDYellow }; // Das ist eine Aufzaehlung der Stati
byte state = ST_IDLE; // Erster Status mit Programmstart
const unsigned long PeriodYellow = 1000; // Zeit in ms
unsigned long yellowPlus = 0; // Variable zur Berechnung der Verlaengerung der Gelbphase
unsigned long msecLst; // Merker für letzte Zeit
unsigned long msec; // Merker für aktuelle Zeit
// -----------------------------------------------------------------------------
void setLeds ( const bool green, // Funktion zur Ausgabe der Zustände
const bool yellow,
const bool red )
{
digitalWrite (PinLed [0], green);
digitalWrite (PinLed [1], yellow);
digitalWrite (PinLed [2], red);
}
// -----------------------------------------------------------------------------
void kontrol()
{
byte x = 200;
static byte y = 0;
x = (x + digitalRead(5)) << 1;
x = (x + digitalRead(7)) << 1;
x = (x + digitalRead(9));
if (y != x)
{
y = x;
Serial.println(y, BIN);
}
}
void loop ()
{
kontrol();
msec = millis (); // merkt sich die aktuelle Zeit
switch (state) // verzweige je nach Zustand
{
case ST_YELLOW: // Wenn Status gelb
setLeds (Off, On, Off); // stelle die Ampel
if ((msec - msecLst) > PeriodYellow) // wenn Gelbzeit abgelaufen
state = ST_RED; // wechsle zu rot
break;
case ST_RED: // wenn Status rot
setLeds (Off, Off, On); // stelle Ampel
msecLst = msec; // merke die aktuelle Zeit
state = ST_REDwait; // wechsel Status zu rot_warten
break;
case ST_REDwait: // wenn Status rot_warten
if (digitalRead (PinBut)) // wenn Schloss geöffnet
{
yellowPlus = (msec - msecLst); // ermittle die Zeit, die das Schloß zu war
if (yellowPlus < 60000) yellowPlus = 1000; // und setze passend dazu die Verlängerungszeit
if (yellowPlus > 119900) yellowPlus = 119900;
msecLst = msec; // merke die Zeit
state = ST_REDYellow; // wechsel Status zu rot_gelb
}
break;
case ST_REDYellow: // wenn Status rot_gelb
if (!digitalRead (PinBut)) // wenn Schloss wieder geschlossen
{
state = ST_RED;
}
else
{
setLeds (Off, On, On); // stelle die Ampel
if ((msec - msecLst) > (PeriodYellow + yellowPlus)) // Wenn Zeit abgelaufen
{
state = ST_IDLE; // wechsel Status zu gruen
}
}
break;
case ST_IDLE: // Wenn Status gruen
default: // oder Status unbekannt
setLeds (On, Off, Off); // stelle Ampel
if (!digitalRead (PinBut)) // Wenn Schloss zu
{
state = ST_YELLOW; // wechsel zu Status gelb
msecLst = msec; // merke die Zeit
}
break;
}
}
void setup()
{
Serial.begin (115200);
Serial.println(F("Start..."));
for (unsigned n = 0; n < sizeof(PinLed); n++) // Setze alle Pins
{
digitalWrite (PinLed [n], Off); // aus
pinMode (PinLed [n], OUTPUT); // auf Output
}
pinMode (PinBut, INPUT_PULLUP);
}