[[uc-welt:gscheiduino:03-blinklicht|← Kapitel 3: Blinklicht]] | [[uc-welt:gscheiduino:00-uebersicht|↑ Übersicht]] | [[uc-welt:gscheiduino:05-eingaenge|Kapitel 5: Eingänge →]] ====== Kapitel 4: Übungsaufgabe Ampelsteuerung ====== ===== Schaltung ===== Wir ändern unseren ersten Versuchsaufbau um eine gelbe und eine grüne LED: {{:uc-welt:gscheiduino:gscheiduino_breadboard_kap4-ampel.png?direct&300|Aufbau Ampel}} Die Pinbelegungen sind wie folgt: Drei 120R-Widerstände: * D3 und G3 * D6 und G6 * D9 und G9 Die rote LED: Plus auf J3, Minus auf die Masseschiene Die gelbe LED: Plus auf J6, Minus auf die Masseschiene Die grüne LED: Plus auf J9, Minus auf die Masseschiene Die Kabel: blau: GND und Masseschiene rot: 13 und A3 gelb: 12 und A6 grün: 11 und A9 Wir erhalten dadurch folgenden Schaltplan: {{:uc-welt:gscheiduino:004-schaltung.png?direct&200|}} ===== Definitionssache ===== Um den ganzen Code ein wenig übersichtlicher zu gestalten lernen wir vor der Übung noch eine wichitge Componente der Programmiersprache: //Defines// Mit diesen Defines können wir den Code deutlich lesbarer machen. Das funktioniert so: #define KONSTANTENNAME Wert Jetzt wenden wir diese Definition auf unser erstes Beispiel mit der LED an: #define LED_ROT 13 Soweit so gut. Jetzt passiert vorerst nichts, wir verwenden also unsere Definition: digitalWrite(LED_ROT, HIGH); Was nun passiert ist folgendes: Der Compiler (Das war das Teil, das unseren Code in Maschinensprache übersetzt) arbeitet den Code von oben nach unten ab. Ganz oben schreiben wir unser //#define// hin. Wenn der Compiler zu dieser Stelle kommt weiß er "Ah, LED_ROT bedeutet in Wirklichkeit 13". Nun arbeitet er den Code weiter ab und macht dabei etwas geniales: An jeder Stelle, an der //LED_ROT// steht, schreibt der Compiler //13// hin. Um solche #defines schnell zu erkennen, werden sie in der Regel mit Großbuchstaben geschrieben. Wir erkennen jetzt also, dass zum Beispiel //HIGH// auch eine Konstante ist, die von Arduino bereits definiert wurde. Warum definieren wir das aber? Ganz einfach: Wenn wir die rote LED mehrfach in unserem Code verwenden müssen, können wir jedesmal LED_ROT schreiben. Sollte sich irgendwann der Pin ändern (Und jeder der jetzt denkt: "Warum sollte sich ein Pin ändern?" sei gewarnt: Das passiert sehr häufig, meistens aus Bequemlichkeit) kann diese Anpassung am Anfang des Codes in der Definition gemacht werden. Einmal und nicht X-mal im gesamten Quellcode. ===== Programmablauf ===== Das Ziel dieser Aufgabe ist es, eine Ampelsteuerung zu simulieren. Das Timing dieser Steuerung soll wie folgt aussehen: * Die Ampel startet rot * Nach 2 Sekunden rot wird gelb eingeschaltet * Nach 1 Sekunde erlischt rot und gelb, grün leuchtet * Nach 3 Sekunden schaltet die Ampel von grün auf gelb * Nach 1 Sekunde erlischt gelb und der Zyklus beginnt von vorne ===== Kleine Hilfestellung ===== Da die Defines noch neu sind gibt es hier das Grundgerüst des Codes, der erweitert werden soll: #define LED_ROT 13 #define LED_GELB 12 #define LED_GRUEN 11 void setup() { pinMode(LED_ROT, OUTPUT); } void loop() { digitalWrite(LED_ROT, HIGH); } Die Aufgabe besteht nun darin, den Code an den entsprechenden Stellen so zu erweitern, dass die Ampelsteuerung wie oben beschrieben, funktioniert. Als Vergleich zur selbst erstellten Lösung gibt es [[uc-welt:gscheiduino:04-ampelsteuerung-loesung|hier die Musterlösung]], die aber natürlich nicht benötigt wird! Jetzt wo wir wissen, wie Ausgänge funktionieren, kommen wir logischerweise zur anderen Richtung: [[uc-welt:gscheiduino:05-eingaenge|Kapitel 5: Eingänge]]