Tinkercad Übung 7 - LED Lauflicht (1)

Animiere ein LED-Blinkmuster

In dieser Übung animierst du 10 LEDs, dokumentierst deinen Programmcode und machst ihn konfiguierbar.
  • Empfohlenes Vorwissen: Bedienung Tinkercad Circuits, Pin als Ausgang konfigurieren sowie ein- und ausschalten
  • Neue Inhalte: Code-Kommentare schreiben, #define, Konstanten

Schritt 1 - Alle LEDs einschalten

Baue folgende Schaltung auf oder kopiere sie von hier:
https://www.tinkercad.com/things/lF842Kx57rx-kkg-robotik-ubung-7-lauflicht-1-starter
Abbildung 1 - Schaltung mit 10 LEDs und 1 Taster

Die LEDs sind an Pins 4 bis 13 angeschlossen.
Schreibe ein Programm, dass alle LEDs als Ausgang konfiguriert und dann einschaltet.

Schritt 2 - Kommentare

Du wirst bemerken: Das Programm wird schon ein bisschen größer. Und das ist erst der Anfang!

Ganz nach der Devise „Hast du Kopf wie Sieb, musst du aufschreiben!“, hinterlässt man oft Kommentare im Programm-Code, die beschreiben, was dort genau passiert. Oft kommentiert man sogar einzelne Befehlszeilen und beschreibt, was sie bewirken. Das hilft auch anderen, wenn sie Teile deines Programms verstehen müssen.

Kommentare werden bei der Ausführung des Programms übersprungen. Man kann dort fast jeden Text verfassen und sogar Umlaute sowie ß verwenden.

Einzeiliges Kommentar (beginnt mit  // ):

// das hier ist ein einzeiliges Kommentar
hier ist das Kommentar aber schon wieder zu Ende

tonAbspielen(A5, 1, 100, 0); // hier därf ich sogär Umläüte benützen
// tonAbspielen(A5, 1, 100, 0); Diese Befehlszeile wird ignoriert

Wie oben gezeigt, kann man auch einzelne Befehlszeilen auskommentieren und so „überspringen“, wenn man den Code nicht löschen will, aber auch nicht will, dass er ausgeführt wird. (Zum Testen nützlich.)

Mehrzeiliges Kommentar (Beginn: /* , Ende: */ ):

/* das hier
   ist ein
   mehrzeiliges
   Kommentar. */

Mehrere auskommentierte Befehlszeilen (werden übersprungen):

/*
tonAbspielen(A5, 1, 100, 0);
tonAbspielen(A5, 1, 100, 0);
*/

Hinterlasse Kommentare im Programmcode, damit dein Ich der Zukunft noch etwas damit anzufangen wüsste (also z.B. generell was das Programm macht und dann einige Programmzeilen, wozu sie da sind).

Schritt 3 - Animation

Schreibe nun ein Programm im, dass nacheinander einzelne LEDs ein- und ausschaltet (den Verzögerungsbefehl delay() nicht vergessen). Das Programm wird recht umfangreich. Kommentiere dein Programm ausführlich. Verschiebe deine Animation in den loop()-Bereich, damit sie immer wiederholt wird.

Zur Inspiration hier ein paar Beispiel-Animationen:

Streifen

Lösungsvorschlag: https://www.tinkercad.com/things/7KDfrHr9pcB-kkg-robotik-ubung-7-lauflicht-1-streifen



Einfaches  Lauflicht

Lösungsvorschlag: https://www.tinkercad.com/things/eQYXrSrdYUI-kkg-robotik-ubung-7-lauflicht-1-rundum


Einfaches Lauflicht An/Aus

Lösungsvorschlag: https://www.tinkercad.com/things/iptR6sW2GSQ-kkg-robotik-ubung-7-lauflicht-1-rundum-anaus


Doppeltes Lauflicht:

Lösungsvorschlag: https://www.tinkercad.com/things/9yXqzgRDgFt-kkg-robotik-ubung-7-lauflicht-1-rundum-doppel



Schritt 4 - Geschwindigkeit einstellen

Dein Programm enthält jetzt sehr viele Verzögerungsbefehle, z.B.:

delay(100);

Wenn du jetzt die Animationsgeschwindigkeit ändern wollen würdest, müsstest du alle diese Zeilen ändern. Um die Animation doppelt so langsam zu machen z.B.:

delay(200);

Bei größeren Programmen tritt dieses Problem andauernd auf. Zum Glück können wir den Parameter "Verzögerungsdauer" des delay()-Befehls nicht nur als Zahl angeben, sondern auch einen Platzhalter verwenden.

Dafür gibt es 2 Möglichkeiten.

1. Präprozessor-Makros:

Das sind streng genommen keine echten Programmier-Befehle, sondern sie werden ausgewertet, bevor das Programm in Maschinencode übersetzt (kompiliert) wird. Mit ihnen kann man Textmanipulation vornehmen. Diese Makros beginnen immer mit einem Hashtag (#).

Das Präprozessor-Makro, dass für uns momentan in Frage kommt, heißt #define und man kann damit Text suchen und ersetzen.

#define GESUCHTER_TEXT ERSETZTER_TEXT

ersetzt alle Vorkommnisse von GESUCHTER_TEXT durch ERSETZTER_TEXT.

Damit kann man ganz spaßige Dinge tun, z.B. kann man sich seine eigene Programmiersprache schreiben:

setup() {
  pinMode(4, OUTPUT);
}

kann man zum Beispiel so umschreiben:

#define tom_tom setup
#define konfiguriere  pinMode
#define AUSGANG OUTPUT

tom_tom() {
  konfiguriere(4, AUSGANG);
}

Sind alle Vorkommnisse von tom_tom, konfiguriere und AUSGANG durch ihre jeweiligen Ersetzungstexte ersetzt worden, ist der Programmcode wieder korrekt und kann kompiliert werden.

Die #defines müssen definiert werden, bevor sie verwendet werden. Das Programm wird von oben nach unten gelesen. Die #defines stehen am besten also immer am Anfang des Programms. Das ist auch übersichtlicher so.

Das ist hier in dem Lösungsvorschlag für Schritt 1 einmal demonstriert:
https://www.tinkercad.com/things/86oYTt9ibs7-kkg-robotik-ubung-7-lauflicht-1-alle-an

Sollte man natürlich vermeiden, da sonst andere Leute das Programm verwirrend finden, da nicht die Standard-Befehle verwendet werden.

Sinnvoll ist dies allerdings im Fall von delay():

delay(100);
delay(100);
delay(100);

Sowas wie die "100" Millisekunden nennt man "Magic Numbers". Das sind alle unveränderlichen (konstanten) Zahlen und Texte, die direkt im Programmcode auftauchen und nicht vorher schon definiert wurden. Es ist guter Stil, Magic Numbers generell zu vermeiden, wenn es nicht zu viel Arbeit macht.

Im Beispiel von delay() könnte das so aussehen:

// Einstellungen:
// Animationsgeschwindigkeit
#define WARTEZEIT_MS 100  // Wartezeit in Millisekunden

delay(WARTEZEIT_MS);
delay(WARTEZEIT_MS);
delay(WARTEZEIT_MS);

Baue dein Programm so um, dass alle Verzögerungszeiten durch ein #define ersetzt werden. Jetzt kannst du die Animationsgeschwindigkeit schnell verändern, indem du nur eine einzige Zahl änderst. Probiere dies aus.

Schritt 5 - Konstanten

Eine weitere Möglichkeit sind Konstanten. Diese sind keine Präprozessor-Makros, sondern echte Programm-Befehle, die kompiliert werden. Sie können unter einem Namen einen Wert im RAM des Mikrocontrollers abspeichern, in unserem Fall 100 Millisekunden. Dieser kann mit dem Namen wieder nachgeschlagen werden.

// Einstellungen:
// Animationsgeschwindigkeit
const int WARTEZEIT_MS = 100// Wartezeit in Millisekunden

delay(WARTEZEIT_MS);
delay(WARTEZEIT_MS);
delay(WARTEZEIT_MS);

  • const sagt dem Compiler, dass es sich um eine Konstante handelt, der Wert sich also nie ändern wird. Kann man aber auch weglassen.
  • int ist ein Datentyp (dazu später mehr). Wir haben bisher die Datentypen "Zahl" und "Text" verwendet. "int" sagt dem Compiler, dass unsere Konstante eine Zahl abspeichern soll.
  • WARTEZEIT_MS: Der Name der Konstante. Es ist Konvention, dass man alles, was konstant ist (also nicht den Wert ändern kann), mit Großbuchstaben benennt. Das muss man nicht so machen, aber es machen die meisten Programmierer so.
  •  = 100 der Wert der Konstante.
Der Vorteil gegenüber #define ist hier eindeutig der Datentyp. Mit #define geht alles und es ist leicht Fehler zu machen, die man schwer findet. Im Falle von "const int" weiß aber der Compiler, dass es sich um eine Zahl handelt und wird rummeckern, wenn wir zum Beispiel folgendes schreiben würden:

const int WARTEZEIT_MS = "Wartezeit in Millisekunden";

Man kann einen Text nicht in einer Konstante vom Typ int (Zahl) abspeichern. Der Compiler denkt mit und sagt uns das in der Fehlermeldung.

Baue dein Programm so um, dass es anstatt von #define eine Konstante zur Geschwindigkeitseinstellung verwendet.

Zusammenfassung

In dieser Übung hast du eine LED-Animation erstellt, dein Programm kommentiert und Magic Numbers entfernt. Dein Code ist nun wesentlich besser verständlich.

Weiter zu Übung 8



Kommentare

Beliebte Posts aus diesem Blog

Tinkercad Übung 6 - LED mit Taster ansteuern

Tinkercad Übung 11 - LED dimmen

Tinkercad Übung 15 - Ultraschallsensor auslesen