/* Ampelschaltung * * für die Microcontroller Entwicklungsplatine NODEMCU ESP32 mit der Arduino-IDE * * Die Led-Muster entsprechen Rot Gelb Grün Hauptampel * Rot Gelb Grün Nebenampel * Rot Grün Nebenfußgängerampel * Rot Gelb Grün Hauptampel * Rot Gelb Grün Nebenampel * Rot Grün Hauptfußgängerampel * jeweils getrennt duch ein Leerzeichen im Muster. * * Die Anordnung der Ampeln ist ohne Probleme variierbar. Man kann bei geeigneter * Verstärkung der Ausgänge des Boards die Hauptampeln auf 3 statt auf 6 Pins legen, * falls sie synchron geschaltet werden, ebenso die Nebenampeln und hat damit * weitere 6 Ausgänge zur freien Verfügung, z.B. für Abbiegerampeln, blinkende * Warnlichter bei Fußgängergrün mund vieles mehr. * * Der Ablauf im Einzelnen (Es werden nur Wechsel aufgeführt): * Rot an allen Ampeln incl. Fußgängerampeln 2 Sekunden * Rot Gelb an den Hauptampeln, gleichzeitig grün an der Nebenfußgängerampel 1 Sekunde * Grün an den Hauptampeln 10 Sekunden * Rot an der Nebenfußgängerampel 1 Sekunde * Gelb an den Hauptampeln 1 Sekunde * Rot an allen Ampeln incl. Fußgängerampeln 2 Sekunden * Rot Gelb an den Nebenampeln, gleichzeitig grün an der Hauptfußgängerampel 1 Sekunde * Grün an den Nebenampeln 10 Sekunden * Rot an der Hauptfußgängerampel 1 Sekunde * Gelb an den Nebenampeln 1 Sekunde * * Die Idee ist von mir, wesentliche Teile der Programmierung sind von Ulrich Wienker * Herbert Nieder im März 2021 */ // Die Nummerierung der Pins in ledPin entspricht der physischen Reihenfolge // auf dem Board, die "0" als Dummy-Nummer steht überall dort, wo in "pattern" ein // Leerzeichen zur optischen Trennung der Ampeln eingefügt ist int ledPin[] = { 2, 4, 5, 0, 18, 19, 21, 0, 22, 23, 0, // Seite 1 des Boards 13, 12, 14, 0, 27, 26, 25, 0, 33, 32}; // Seite 2 des Boards #define NUM_OF_STATES 3 // drei verschiedene Zustände, gezählt von 0 bis 2 #define IN_PIN 15 // An Pin 15 ist ein Taster angeschlossen int inPinVal = 1; // der mit 1 (= nicht verbunden) initialisiert wird int pressed = 0; // Der Zustand des Tasters beim Start ist "nicht gedrückt" int state = 0; // Nummer der Abfolge beim beim Einschalten #define PIN_COUNT 21 // Zahl der angesteuerten Pins plus Dummypins struct PATTERN { char single_pattern [PIN_COUNT+1]; long milli_sec; } patterns [] = { { "xxx xxx xx xxx xxx xx", 2000 }, // #0 Testmuster alle Leds an { "ooo ooo oo ooo ooo oo", 2000 }, // #1 Testmuster alle Leds aus { "xoo xoo xo xoo xoo xo", 2000 }, // #2 Abfolge 0: Normale Ampelphase { "xxo xoo ox xxo xoo xo", 1000 }, // #3 { "oox xoo ox oox xoo xo", 10000 }, // #4 { "oox xoo xo oox xoo xo", 1000 }, // #5 { "oxo xoo xo oxo xoo xo", 1000 }, // #6 { "xoo xoo xo xoo xoo xo", 2000 }, // #7 { "xoo xxo xo xoo xxo ox", 1000 }, // #8 { "xoo oox xo xoo oox ox", 10000 }, // #9 { "xoo oox xo xoo oox xo", 1000 }, // #10 { "xoo oxo xo xoo oxo xo", 1000 }, // #11 { "oxo ooo oo oxo ooo oo", 1000 }, // #12 Abfolge 1: Gelb an den Nebenampeln { "ooo ooo oo ooo ooo oo", 1000 }, // #13 blinkend { "oxo oxo oo oxo oxo oo", 1000 }, // #14 Abfolge 2: Gelb an allen Ampeln { "ooo ooo oo ooo ooo oo", 1000 } }; // #15 blinkend int begin_pats[NUM_OF_STATES] = { 2, 12, 14 }, end_pats[NUM_OF_STATES] = { 11, 13, 15 }; // Anfänge und Ende der Abläufe void setup () // Festlegung der Pins als Eingang bzw. Ausgang { // Die Arrayelemente sind von 0 bis (pinCount - 1) nummeriert. // Durch die for-Schleife werden alle Led-Pins als Ausgänge festgelegt: for (int thisPin = 0; thisPin < PIN_COUNT; pinMode (ledPin[thisPin++], OUTPUT)); // Pin 15 wird als Eingang festgelegt pinMode (IN_PIN, INPUT); // Die Anzeige der Testmuster kann bei fertigen Schaltungen entfallen // Testmuster 1: Alle an für 2 Sekunden, sind wirklich alle angeschlossen? writePattern (patterns[0].single_pattern); delay (2000); // Testmuster 2: Alle aus für 2 Sekunden, bevor es losgeht writePattern (patterns[1].single_pattern); delay (2000); } void loop () // Hauptprogramm: Musteranzeige { for (int nn = begin_pats[state]; nn <= end_pats[state]; nn++) { writePattern (patterns[nn].single_pattern); // Muster werden geschrieben if (waitAndListen (patterns[nn].milli_sec)) break; // bei Tastendruck wird abgebrochen und } // sofort der nächste Ablauf angefangen } void writePattern (char *pattern) // Umsetzung eines Einzelmusters in Led-Anzeigen { for (int thisPin = 0; thisPin < PIN_COUNT; thisPin++) { if (pattern[thisPin] != ' ') digitalWrite (ledPin[thisPin], pattern[thisPin] == 'x' ? HIGH : LOW); } } int waitAndListen (long time) // Alle 50 Millisekunden wird der Taster abgefragt { long cnt = 0; long offset = 50; // in Millisekunden while (cnt < time) // time: maximaler Verbleib in diesem Unterprogramm in Millisekunden { cnt = cnt + offset; if (digitalRead (IN_PIN) == 0 && !pressed) // Taste gedrückt? { delay (10); // Entprellung: Taste immer noch gedrückt if (digitalRead (IN_PIN) == 0 && !pressed) // innerhalb von 10 Millisekunden? { state++; state %= NUM_OF_STATES; // Ja, gehe zum nächsten Muster pressed = true; return pressed; // gib pressed = true an loop weiter } } if (digitalRead (IN_PIN) == 1 && pressed) // pressed = true und Taste gelöst? { delay (10); if (digitalRead (IN_PIN) == 1 && pressed) // nach 10 Millisekunden immer noch? { pressed = false; // Zustand von pressed ändern } } delay (offset); // wenn nichts passiert ist, warte 50ms } return pressed; // gib Zustand von pressed an loop weiter }