Erik Bartmann

Mit Arduino die elektronische Welt entdecken


Скачать книгу

Widerstand 330Ω 1x [Bild] Widerstand 10KΩ 1x [Bild]

      Der Schaltplan

      Der Schaltplan zeigt uns zur Gewährleistung eines sicheren Eingangspegels einen externen Pulldown-Widerstand am digitalen Pin 8:

[Bild]

      Abb. 1: Der Schaltplan zur Abfrage des Tasters und Ansteuerung der LEDs

      Der Schaltungsaufbau

      Auf dem Arduino Discoveryboard werden in diesem Bastelprojekt ein paar Bauteile mehr zum Einsatz kommen:

[Bild]

      Abb. 2: Der Schaltungsaufbau zur Tasterabfrage

      Mit diesem Schaltungsaufbau wenden wir uns dem Sketch zu.

      Der Arduino-Sketch

      Vorwarnung: Der folgende Sketch funktioniert nicht so, wie wir es vielleicht erwarten.

      // Der Sketch funktioniert nicht wie erhofft int ledPinBlink = 13; // Rote Blink-LED Pin 13 int ledPinTaster = 10; // Gelbe Taster-LED Pin 10 int tasterPin = 8; // Taster Pin 8 int tasterStatus; // Variable für Tasterstatus void setup() { pinMode(ledPinBlink, OUTPUT); // Blink-LED Pin als Ausgang pinMode(ledPinTaster, OUTPUT); // Taster-LED Pin als Ausgang pinMode(tasterPin, INPUT); // Taster-Pin als Eingang } void loop() { // Blink-LED blinken lassen digitalWrite(ledPinBlink, HIGH); // Rote LED HIGH-Pegel delay(1000); // 1 Sek. warten digitalWrite(ledPinBlink, LOW); // Rote LED LOW-Pegel delay(1000); // 1 Sek. warten // Abfrage des Taster-Status tasterStatus = digitalRead(tasterPin); if(tasterStatus == HIGH) digitalWrite(ledPinTaster, HIGH); // Gelbe LED HIGH-Pegel else digitalWrite(ledPinTaster, LOW); // Gelbe LED LOW-Pegel }

      Warum funktioniert der Sketch denn nicht wie erwartet? Die Ausführung in der Endlosschleife kommt doch irgendwann einmal an der Zeile für die Tasterabfrage vorbei. Dann wird der Status doch korrekt abgefragt. Das entscheidende Wörtchen, das hier verwendet wird, ist irgendwann! Du möchtest aber sicherlich einen Sketch so programmieren, dass zu jedem Zeitpunkt der Verarbeitung auf einen Tastendruck reagiert wird und nicht nur irgendwann einmal, wenn die Ausführung des Codes gerade die betreffende Stelle erreicht. Die delay-Funktion behindert uns bei der Fortführung des Codes und kann hier nicht die erste Wahl sein. Ich zeige dir das Verhalten am besten anhand eines Impulsdiagramms, bei dem die relevanten Signale wie Pin 13 (Blink-LED), Pin 8 (Taster) und Pin 10 (Taster-LED) untereinander zu sehen sind:

[Bild]

      Abb. 3: Das Impulsdiagramm der Signale an Pin 13, Pin 8 und Pin 10

      Das oberste Signal (hier blau) zeigt den Status der blinkenden LED an Pin 13, der unermüdlich im Sekundentakt zwischen HIGH- und LOW-Pegel wechselt. Das darunter liegende Signal (hier lila) zeigt den Pegel am Taster an Pin 8, der nun versucht, die Taster-LED an Pin 10 zu steuern. Das unterste Signal sollte also zeitgleich mit dem Signal am Taster den Pegel wechseln, was aber nicht der Fall ist. Ich habe vier markante rote Punkte in diesem Diagramm platziert. An Punkt (1) halte ich den Taster so lange gedrückt, dass ich die abfallende Flanke des Blink-Signals erwische. Warum reagiert die Taster-LED an Pin 10 hier nicht? Das ist ganz einfach, denn wir haben es mit zwei delay-Aufrufen zu tun. Bei einem Wechsel von HIGH zu LOW wird die erste delay-Funktion abgearbeitet und wir stecken quasi noch in der zweiten delay-Funktion fest. Ein Tastendruck wird also hier nicht abgefragt. Das geschieht erst an Punkt (2), wo ich die Taste beim Pegelwechsel von LOW zu HIGH gedrückt halte. Bevor es zum weiteren Pegelwechsel‌ geht, erfolgt die Abfrage des digitalen Pins 8, an dem sich der Taster befindet. Jetzt kann der Status des Tasters ausgewertet werden und die Taster-LED an Pin 10 leuchtet. Das ist so lange der Fall, bis bei der ansteigenden Flanke der Blink-LED der Taster ein LOW-Signal hat, was erst bei Punkt (4) der Fall ist und nicht schon bei Punkt (3). Aus diesem Grund müssen wir auf die Verwendung der delay-Funktion verzichten und einen anderen Weg wählen.

      Sehen wir uns den folgenden Sketch an und lassen uns nicht durch die Anzahl der Codezeilen irritieren, denn wir gehen alles Schritt für Schritt durch:

      // Der Sketch funktioniert wie erhofft int ledPinBlink = 13; // Rote Blink-LED Pin 13 int ledPinTaster = 10; // Gelbe Taster-LED Pin 10 int tasterPin = 8; // Taster Pin 8 int tasterStatus; // Variable für Tasterstatus int interval = 2000; // Intervalzeit (2 Sekunden) unsigned long prev; // Zeit-Variable int ledStatus = LOW; // Statusvariable für die Blink-LED void setup() { pinMode(ledPinBlink, OUTPUT); // Blink-LED-Pin als Ausgang pinMode(ledPinTaster, OUTPUT); // Taster-LED-Pin als Ausgang pinMode(tasterPin, INPUT); // Taster-Pin als Eingang prev = millis(); // Jetzigen Zeitstempel merken } void loop() { // Blink-LED über Intervalsteuerung blinken lassen if((millis() - prev) > interval) { prev = millis(); ledStatus = !ledStatus; // Toggeln des LED-Status digitalWrite(ledPinBlink, ledStatus); // Toggeln der roten LED } // Abfrage des Tasterstatus tasterStatus = digitalRead(tasterPin); if(tasterStatus == HIGH) digitalWrite(ledPinTaster, HIGH); // Gelbe LED HIGH-Pegel else digitalWrite(ledPinTaster, LOW); // Gelbe LED auf LOW-Pegel }

      Schauen wir uns die Erklärungen zu diesem Sketch an.

      Den Code verstehen

      In diesem Sketch haben wir es mit einigen Variablen zu tun. Ich beginne mit der sogenannten Intervallsteuerung‌. Das folgende Impulsdiagramm zeigt uns das Verhalten der Schaltung und es ist genau so, wie es erwünscht ist:

[Bild]

      Abb. 4: Das Impulsdiagramm der Signale an Pin 13, Pin 8 und Pin 10

      Jedes Mal, wenn der Taster (Taster-Pin) gedrückt wird, folgt der Pegel der Taster-LED. Und das Ganze unabhängig vom Zustand beziehungsweise Pegelwechsel an Pin 13 (Blink-LED). Für die Intervallsteuerung benötigen wir eine neue Funktion, die sich millis nennt und wie folgt aussieht:

[Bild]

      Sie liefert einen Wert in Millisekunden seit dem Starten des Sketches zurück. Dabei ist etwas Wichtiges zu beachten: Der Rückgabedatentyp ist unsigned long, also ein vorzeichenloser 32-Bit-Ganzzahltyp‌, dessen Wertebereich sich von 0 bis 4.294.967.295 (232-1) erstreckt. Dieser Wertebereich ist so groß, weil er über einen längeren Zeitraum (maximal 49.71 Tage) in der Lage sein soll, die Daten aufzunehmen, bevor es zu einem Überlauf kommt.

      Was ist ein Variablenüberlauf‌?

[Bild]

      Ein Überlauf bedeutet bei Variablen, dass der maximal abbildbare Wertebereich für einen bestimmten Datentyp überschritten wurde und anschließend wieder bei 0 begonnen wird. Für den Datentyp byte, der eine Datenbreite von 8 Bits aufweist und demnach 28 = 256 Zustände (0 bis 255) speichern kann, tritt ein Überlauf bei der Aktion 255 + 1 auf. Den Wert 256 ist der Datentyp byte