- -
- 100%
- +
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:

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:

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?

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 nicht mehr in der Lage zu verarbeiten.
Es wurden drei weitere Variablen eingefügt, die folgende Aufgabe haben:
interval: Nimmt die Zeit im ms auf, die für das Blinkintervall zuständig ist.
prev: Nimmt die aktuell verstrichene Zeit in ms auf. prev kommt von previous und bedeutet übersetzt vorher.
ledStatus: In Abhängigkeit des Status von HIGH oder LOW der Variablen wird die Blink-LED angesteuert.
Dann sehen wir mal, wie das Ganze so abläuft. Das folgende Diagramm soll den zeitlichen Verlauf der Intervallsteuerung verdeutlichen:

Abb. 5: Der zeitliche Verlauf der Intervallsteuerung
Ich analysiere einmal das Diagramm, wobei ich markante Zeitpunkte zur Verdeutlichung herausgegriffen habe. Natürlich läuft die Zeit nicht real in diesen Schritten ab:
Tabelle 2: Variableninhalte im zeitlichen Verlauf Zeitpunkt Erklärung



Während des gesamten Sketch-Ablaufs wurde an keiner Stelle im Quellcode ein Halt in Form einer Pause eingelegt, sodass das Abfragen des digitalen Pins 8 zur Steuerung der Taster-LED nicht beeinträchtigt wurde. Ein Druck auf den Taster wird fast unmittelbar ausgewertet und angezeigt.
Eine Zeile im Sktech könnte vielleicht noch ein wenig Kopfschmerzen bereiten. Was bedeutet ledStatus = !ledStatus? Und was heißt toggeln, wie ich es im Kommentar hinter dem Befehl genannt habe? In der Variablen ledStatus wird der Pegel gespeichert, der die rote LED ansteuert oder für das Blinken zuständig ist (HIGH bedeutet aufleuchten und LOW bedeutet dunkel). Über die nachfolgende Zeile wird die LED dann angesteuert:
digitalWrite(ledPinBlink, ledStatus);
Das Blinken wird gerade dadurch erreicht, dass du zwischen den beiden Zuständen HIGH bzw. LOW hin- und herschaltest. Das wird auch Toggeln genannt. Ich werde die Zeile etwas umformulieren, dann wird der Sinn deutlicher:
if(ledStatus == LOW) ledStatus = HIGH; else ledStatus = LOW;
In der ersten Zeile wird abgefragt, ob der Inhalt der Variablen ledStatus gleich LOW ist. Falls ja, setze ihn auf HIGH andernfalls auf LOW. Das bedeutet ebenfalls ein Toggeln des Status. Viel kürzer geht es mit der folgenden einzeiligen Variante, die ich im Sketch verwendet habe:
ledStatus = !ledStatus; // Toggeln des LED-Status
Ich benutze dabei den logischen Not-Operator, der ja durch das Ausrufezeichen repräsentiert wird. Wie wir schon in Kapitel 3 gelernt haben, wird er häufig bei booleschen Variablen verwendet, die nur die Wahrheitswerte true oder false annehmen können. Der Not-Operator ermittelt ein Ergebnis, das einen entgegengesetzten Wahrheitswert aufweist wie der Operand. Es funktioniert aber auch bei den beiden Pegeln HIGH und LOW. Am Schluss wird ganz normal und ohne Verzögerung der Taster an Port 8 abgefragt:
tasterStatus = digitalRead(tasterPin); if(tasterStatus == HIGH) digitalWrite(ledPinTaster, HIGH); else digitalWrite(ledPinTaster, LOW);
Troubleshooting
Falls die LED nicht leuchtet, wenn du den Taster drückst, oder die LED ständig leuchtet, dann geh bitte folgende Dinge durch:
Überprüf deine Steckverbindungen auf dem Breadboard, ob sie wirklich der Schaltung entsprechen.
Sind die LEDs richtig herum eingesteckt worden? Denk an die richtige Polung.
Achte auf den Taster mit zwei beziehungsweise vier Anschlüssen. Mach gegebenenfalls einen Durchgangstest mit einem Multimeter und überprüfe damit die Funktionsfähigkeit des Tasters und der entsprechenden Beinchen.
Haben die beiden Widerstände die korrekten Werte und wurden auch nicht vertauscht?
Überprüfe noch einmal den Sketch-Code auf Richtigkeit.
Was haben wir gelernt?
Du hast die Verwendung mehrerer Variablen gesehen, die für die unterschiedlichsten Zwecke genutzt wurden (Deklaration für Eingangs- und Ausgangs-Pin und Aufnahme von Statusinformationen).
Der Befehl delay unterbricht die Ausführung des Sketches und erzwingt eine Pause, so dass alle nachfolgenden Befehle nicht berücksichtigt werden, bis die Wartezeit verstrichen ist.
Du hast über die Intervallsteuerung mittels der millis-Funktion einen Weg kennengelernt, dennoch den kontinuierlichen Sketch-Ablauf der loop-Endlosschleife aufrechtzuerhalten, sodass weitere Befehle der loop-Schleife ausgeführt wurden und damit eine Auswertung weiterer Sensoren, wie zum Beispiel der angeschlossene Taster, möglich waren.
Du hast verschiedene Impulsdiagramme kennen und lesen gelernt, die grafisch unterschiedliche Pegelzustände im zeitlichen Verlauf sehr gut darstellen.
Bastelprojekt 5:
Der störrische Taster
In diesem Bastelprojekt wirst du erkennen, dass sich ein Taster oder ein Schalter nicht immer so verhält, wie du es dir erwünschst. Nehmen wir für dieses Bastelprojekt einen Taster, der – so die Theorie – eine Unterbrechung des Stromflusses aufhebt, solange er gedrückt bleibt, und die Unterbrechung wiederherstellt, wenn du ihn loslässt. Das ist nichts Neues und absolut einfach zu verstehen. Doch bei elektronischen Schaltungen, deren Aufgabe beispielsweise im Ermitteln der exakten Anzahl von Tastendrücken liegt, um sie später auszuwerten, bekommen wir es mit einem Problem zu tun, das zunächst überhaupt nicht augenfällig ist.
Ich wurde geprellt!
In der Elektromechanik gibt es einen Störeffekt, den man Prellen nennt. Wenn du einen ganz normalen Taster drückst und gedrückt hältst, sollte man meinen, dass der mechanische Kontakt im Taster dauerhaft geschlossen wird. Das ist jedoch meistens nicht der Fall, denn wir haben es mit einem Bauteil zu tun, das innerhalb einer sehr kurzen Zeitspanne – im Millisekundenbereich – den Kontakt mehrfach öffnet und wieder schließt. Die Kontaktflächen eines Tasters sind in der Regel nicht vollkommen glatt, und wenn wir sie uns unter einem Elektronenmikroskop ansähen, sähen wir viele Unebenheiten und Verunreinigungen. Das führt dazu, dass die Berührungspunkte der leitenden Materialien bei Annäherung nicht sofort und nicht auf Dauer zueinanderfinden. Eine weitere Ursache für den hier angeführten Effekt, den man Prellen nennt, kann im Schwingen oder Federn des Kontaktmaterials liegen, wodurch bei Berührung kurzzeitig der Kontakt mehrfach hintereinander geschlossen und wieder geöffnet wird.

Diese Impulse, die der Taster liefert, werden vom Mikrocontroller registriert und korrekt verarbeitet, nämlich so, als ob du den Taster absichtlich ganz oft und schnell hintereinander drücken würdest. Das Verhalten ist natürlich störend und muss in irgendeiner Weise verhindert werden. Dazu sehen wir uns das Impulsdiagramm in Abbildung 1 einmal etwas genauer an.
Ich habe einen Taster einmal gedrückt und dann gedrückt gehalten, doch bevor er den stabilen Zustand des Durchschaltens erreicht hatte, zickte er ein wenig und unterbrach die gewünschte Verbindung mehrfach. Das Ein- und Ausschalten, bis der endgültige gewünschte HIGH-Pegel erreicht ist, wird also Prellen genannt. Das Verhalten kann auch in entgegengesetzter Richtung auftreten. Auch wenn ich den Taster wieder loslasse, werden unter Umständen mehrere Impulse generiert, bis ich endlich den gewünschten LOW-Pegel erhalte. Das Prellen des Tasters ist für das menschliche Auge kaum oder überhaupt nicht wahrnehmbar, und wenn wir eine Schaltung aufbauen, die bei gedrücktem Taster eine LED ansteuern soll, stellen sich die einzelnen Impulse aufgrund der Trägheit der Augen als ein HIGH-Pegel dar. Ich schlage eine Schaltung mit einem entsprechenden Sketch vor, bei dem die einzelnen Impulse eines Prellens gezählt werden, denn das menschliche Auge kann diese Impulse nicht differenzieren.

Abb. 1: Ein prellender Taster – Schlimmer Finger!
Was wir brauchen
Für dieses Bastelprojekt benötigen wir die folgenden Bauteile:
Tabelle 1: Bauteilliste Bauteil Bild Widerstand 10KΩ 1x

Der Schaltplan
Der Schaltplan und der Schaltungsaufbau dazu ist recht einfach und sieht wie folgt aus:

Abb. 2: Die Abfrage des Tasterstatus an Pin 8
Der entsprechende Schaltungsaufbau auf dem Arduino Discoveryboard sieht so aus:

Abb. 3: Die Abfrage des Tasterstatus an Pin 8
Der Arduino-Sketch
Der folgende Code bringt die einzelnen Impulse zur Anzeige:
int tasterPin = 8; // Taster-Pin int impulse = 0; // Zähler boolean prevTasterState; // Änderung erkennen void setup(){ Serial.begin(9600); // Serielle Schnittstelle } void loop() { boolean tasterStatus = digitalRead(tasterPin); if(tasterStatus != prevTasterState){ // Änderung wurde erkannt prevTasterState = tasterStatus; if(tasterStatus == HIGH) { impulse++; // Impulse zählen Serial.println(impulse); } } }
Den Code verstehen
Die Variable tasterPin wird mit dem Wert 8 initialisiert, da dort der Mikrotaster angeschlossen ist. Um später die Anzahl der Impulse zu speichern, wird eine Variable mit Namen impulse deklariert und mit dem Wert 0 initialisiert. Die Initialisierung der seriellen Schnittstelle erfolgt über ein entsprechendes Objekt innerhalb der setup-Funktion. Zuerst wird die Klasse genannt und im Anschluss – durch einen Punkt voneinander getrennt – die Methode mit dem Parameter. Die genauere Erläuterung erfolgt im Bastelprojekt über die objektorientierte Programmierung, wo es um Objekte, Klassen und Methoden geht.

Wichtig ist hier die Baudrate, die mit 9600 Baud angegeben wurde. Wird von einem Terminalprogramm wie dem Serial Monitor darauf zugegriffen, muss die Baudrate dort ebenfalls mit 9600 Baud angegeben werden, was dort in der linken unteren Ecke über eine Liste mit unterstützten Baudraten erfolgt:

Innerhalb der loop-Funktion wird nun die Variable prevTasterState genutzt, die dazu da ist, um immer den letzten Tasterstatus zu speichern. Sie ist notwendig, da immer nur ein Wechsel des Status berücksichtig werden soll und auch nur dann, wenn ein HIGH-Pegel am Taster vorherrscht. Wenn du nun den Taster betätigst, sollte je nach Tastendruck die Variable impulse immer um den Wert 1 erhöht werden. Im Serial Monitor kannst du die Ergebnisse ablesen. Zur Anzeige der ermittelten Impulse wird die folge Syntax der seriellen Schnittstelle verwendet, wobei die Methode println den angegebenen Wert versendet:

Theoretisch sollte pro einzelnem Tastendruck der angezeigte Wert um 1 erhöht werden. Das scheint auch teilweise zu stimmen, doch nicht immer. Manchmal wird der Wert je Tastendruck um mehr als 1 erhöht, was auf das angesprochene Prellen hinweist. Öffne den Serial Monitor und beobachte die Anzeige. Man sollte meinen, dass bei jedem Tastendruck der Zähler um den Wert 1 erhöht wird, was jedoch nicht immer der Fall ist.

Abb. 4: Der Serial Monitor bringt das Prellen ans Licht
Gleich beim ersten Tastendruck zeigte die Anzeige hintereinander die Werte 1 und 2. Danach ging es stabil weiter und dann traten wieder 6 und 7 gleichzeitig in Erscheinung. Prellt ein Taster wirklich heftig, können pro Tastendruck auch mal mehr als zwei Impulse registriert werden. Probiere es einfach einmal aus. Wenn du keinen Zugang zu einem Oszilloskop hast, um dir das Prellen eines Tasters grafisch darzustellen, ist das auch kein Problem, denn die Arduino-Entwicklungsumgebung verfügt über ein interessantes Feature, den sogenannten Serial Plotter. Er kann anstelle des Serial Monitors den zeitlichen Verlauf von Pegeln darstellen. Verwende dazu den folgenden Sketch und öffne im Anschluss den Serial Plotter über den Menüpunkt Werkzeuge | Serieller Plotter:
int tasterPin = 8; // Taster-Pin void setup() { Serial.begin(9600); // Serielle Schnittstelle } void loop() { Serial.println(digitalRead(tasterPin)); }
Was ist eine serielle Schnittstelle?

Eine serielle Schnittstelle ist eine Einrichtung zur Datenübertragung zwischen zwei Geräten, bei denen die zu übertragende Information in Form einzelner Bits zeitlich hintereinander – also seriell – übertragen wird. Die Rate, mit der die Information über den Kommunikationskanal übertragen wird, wird Baudrate genannt. Je höher diese Baudrate ist, desto mehr Bits werden pro Sekunde übertragen.
Den Code verstehen
Der Code ist übersichtlich, aber für das Anzeigen des Prellvorgangs vollkommen ausreichend. Es wird innerhalb der loop-Schleife der gemessene Pegel am Taster-Pin an die serielle Schnittstelle übertragen. Sowohl der Serial Monitor als auch der Serial Plotter können diese Daten darstellen. Bei mir sah das Prellen nach mehreren Versuchen wie in der folgenden Abbildung aus. Es ist sehr gut zu erkennen, dass der HIGH-Pegel nach dem Loslassen des Tasters nicht sofort auf einen LOW-Pegel geht, sondern erst noch einmal kurz in Richtung HIGH-Pegel zuckt, bevor er endgültig einen stabilen LOW-Pegel vorweist. Das ist der Beweis dafür, dass ein Taster nicht nur beim Schließen, sondern auch beim Öffnen prellen kann.

Abb. 5: Der Serial Plotter bringt das Prellen ans Licht
Das ist zwar jetzt alles schön und gut, doch wie kann dem unerwünschten Prellen nun begegnet werden? Es gibt diesbezüglich mehrere Ansätze, die sowohl über Soft- als auch über Hardware realisierbar sind. Da es mir in diesem Bastelprojekt vor allem um den Softwareaspekt geht, lasse ich eine Hardwarelösung außen vor.
Anti-Prell-Lösung #1
Eine sehr einfache Lösung besteht im Einfügen einer kurzen Pause in der Verarbeitung durch einen delay-Befehl von zum Beispiel 10ms, wie das hier innerhalb der loop-Funktion zu sehen ist:
void loop() { boolean tasterStatus = digitalRead(tasterPin); if(tasterStatus != prevTasterState) { // Änderung erkannt prevTasterState = tasterStatus; delay(10); // Entprellen if(tasterStatus == HIGH) { impulse++; // Impuls zählen Serial.println(impulse); } } }
Anti-Prell-Lösung #2
Versuchen wir es nun mit einer anderen Lösung. Was hältst du davon, wenn wir eine Schaltung aufbauen, die einen Taster an einem digitalen Eingang besitzt und eine LED an einem anderen digitalen Ausgang? Bei jedem Tastendruck soll die angeschlossene LED an- oder ausgeschaltet werden. Sie toggelt im Takt des Tastendrucks. Ohne eine Gegenmaßnahme des Entprellens würde die LED bei einem Tastendruck entweder an oder aus bleiben, weil zum Beispiel kurz hintereinander ein AN-AUS oder AUS-AN erfolgt. Wenn also mehrere Impulse beim Drücken des Tasters von der Schaltung beziehungsweise der Software registriert werden, wechselt die LED mehrfach ihren Zustand. Bei einem prellfreien Taster sollten sich die Zustände wie im folgenden Diagramm darstellen:

Abb. 6: Das Toggeln der LED durch den Taster
Es ist zu sehen, dass sich immer bei der ansteigenden Flanke des Tasterimpulses der Zustand der LED ändert.
Was wir brauchen
Für dieses Bastelprojekt benötigen wir die folgenden Bauteile:
Tabelle 2: Bauteilliste Bauteil Bild LED rot 1x


