- -
- 100%
- +
Troubleshooting
Überprüf deine Steckverbindungen auf dem Breadboard, ob sie wirklich der Schaltung entsprechen.
Was haben wir gelernt?
Es wurde der Zusammenhang zwischen Arduino-Pins und internen Mikrocontroller-Register hergestellt.
Über die Register DDRx, PORTx und PINx können Datenflussrichtung, logische Pegel gesetzt und abgefragt werden.
Es wurde die Leuchtdiode angesprochen und was bei der Ansteuerung zu beachten ist.
Wir haben die Problematik eines unbeschalteten digitalen Eingangs besprochen und Abhilfe über einen sogenannten Pulldown-Widerstand geschaffen.
Über geeignete Befehle wurden die internen Pullup-Widerstände aktiviert, so dass eine externe Beschaltung mit zusätzlichen Widerständen entfällt.
Bastelprojekt 3:
Einen Taster sicher abfragen
Warum werden in der Elektronik überhaupt Taster benötigt? Eine einfache Frage, die gar nicht so einfach zu beantworten ist, wie es auf den ersten Blick scheint. Klar, Taster werden dafür verwendet, um von außen Informationen an eine Schaltung zu leiten. Wird ein Taster gedrückt, sollen bestimmte Aktionen erfolgen, die in der Programmierung definiert wurden. Taster bilden also eine Schnittstelle zwischen Mensch und Mikrocontroller. Damit ein Tastendruck genau das bewirkt, was beabsichtigt ist, müssen wir grundlegende Dinge klären: Wann und wie oft wurde ein Taster gedrückt? In diesem Bastelprojekt wenden wir uns der Thematik zu, wann ein Taster gedrückt wurde und dass dieser Impuls auch nur dann weitergeleitet wird, wenn man den Taster schließt. In einem späteren Bastelprojekt – »Der störrische Taster« (Bastelprojekt 5) – geht es darum, wie oft ein Kontakt geschlossen wird, wenn der Taster einmal gedrückt wurde. Das sollte normalerweise auch nur einmal der Fall sein, was aber nicht immer stimmt. Wenn es also darum geht, einen Taster abzufragen, so wie es in der Überschrift steht, geht es darum zu ermitteln, wann dieser gedrückt wurde.
Die Manipulation interner Pullup-Widerstände
Das Problem mit offenen beziehungsweise nicht beschalteten digitalen Eingängen sollte klar sein. Eine externe Beschaltung durch Pullup- bzw. Pulldown-Widerstände ist ein gängiges Verfahren, diesem Problem zu begegnen. Wir haben aber auch gesehen, dass der Mikrocontroller des Arduino Uno über interne Pullup-Widerstände verfügt, die bei Bedarf aktiviert oder deaktiviert werden können. Im zweiten Bastelprojekt, bei dem es um die Low-Level-Programmierung ging, habe ich das Aktivieren dieser Widerstände über das Setzen bestimmter Bits eines internen Registers gezeigt. Wir erinnern uns:
PORTB = 0b00000111; // Pullup für Pin 8, 9 und 10 aktiviert
Für geübte Programmierer, die gerne mit Bits und Bytes hantieren, ist das sicherlich eine tolle Sache, denn am meisten kann man erreichen, wenn man die Innereien eines Mikrocontrollers direkt anspricht. Doch viele – mich eingeschlossen – haben es lieber komfortabler. Ich sprach davon, dass es einen Arduino-Befehl gibt, über den ein interner Pullup-Widerstand aktiviert werden kann. Wie kann man sich einen internen Pullup-Widerstand vorstellen? Werfen wir dazu einen Blick auf das folgende Schaltbild:

Abb. 1: Ein interner Pullup-Widerstand am digitalen Pin 9
In diesem Beispiel habe ich den digitalen Pin 9 ausgesucht, an dem dein Taster angeschlossen wird. Du erkennst auch den internen Pullup-Widerstand R, der über einen elektronischen Schalter den Pin 9 mit der Versorgungsspannung +5V – wenn er denn geschlossen wird – verbindet. Die Frage ist aber, wie du diesen Schalter schließen kannst, damit der Pin 9 bei fehlendem Eingangspegel einen HIGH-Pegel aufweist. Hierzu sind die folgenden Befehle erforderlich, wobei pin den Wert 9 besitzt:
pinMode(pin, INPUT); // Pin als Eingang konfigurieren digitalWrite(pin, HIGH); // Aktivieren des internen Pullup-Widerstandes
Sie bewirken das Schließen des besagten Schalters.

Abb. 2: Der interne Pullup-Widerstand wurde aktiviert
Vielleicht denkst du, dass hier etwas nicht stimmt. Du konfigurierst einen digitalen Pin als Eingang, weil wir daran einen Taster anschließen möchten. Das ist soweit noch klar. Aber dann wird versucht, mit dem Befehl digitalWrite an eben diesem Pin den Pegel zu verändern, der nicht als Ausgang konfiguriert wurde. Was soll das denn bedeuten? Genau das ist ja der Punkt. Über diese Befehlssequenz aktivieren wir den internen Pullup-Widerstand, der übrigens den Wert von 20KΩ besitzt. Damit zwingen wir das Potential des besagten Pins bei offenem Eingang in Richtung +5V und erhalten darüber einen definierten Eingangspegel.
Was ist bei einem Pullup- oder Pulldown-Widerstand zu beachten?

Hinsichtlich der Beschaltung eines digitalen Pins entweder über einen externen Pulldown- oder einen internen Pullup-Widerstand muss bei der Programmierung die Abfrage des Pins bei einem Tastendruck abweichend lauten.
Überlege erst einmal, bevor du hier weiterliest. Bei einem Pulldown-Widerstand liegt bei einem offenen Eingang ein LOW-Pegel an. Um eine Pegeländerung zu bewirken, müssen von außen +5V angelegt werden und das bedeutet, dass die Abfrage des Tasters wie folgt aussehen kann, wobei die Variable tasterStatus natürlich erst einmal initialisiert werden muss:
if(tasterStatus == HIGH) { ... }
So weit, so gut. Jetzt arbeitest du mit einem internen Pullup-Widerstand, der bei offenem Taster einen HIGH-Pegel hervorruft. Der angeschlossene Taster muss nun bei einer gewünschten Pegeländerung von außen ein LOW-Signal, also 0V erwirken, was bedeutet, dass die Abfrage des Tasters jetzt wie folgt aussehen muss:
if(tasterStatus == LOW) { ... }
Es gibt noch eine andere Variante, einen internen Pullup-Widerstand zu manipulieren. Ab der Arduino-Entwicklungsumgebung 1.0.1 ist es möglich, über einen speziellen Mode-Parameter beim pinMode-Befehl den Widerstand zu beeinflussen:

Abb. 3: Der interne Pullup-Widerstand wurde aktiviert
Durch einen einzigen pinMode-Befehl wurde der Schalter geschlossen. Die Deaktivierung erfolgt über den Modus INPUT, wobei der interne Schalter wieder geöffnet wird:

Abb. 4: Der internen Pullup-Widerstand wurde deaktiviert
Auch hier ist nur ein einziger pinMode-Befehl mit gezeigtem Modus erforderlich.
Kommen wir jetzt zu einem konkreten Beispiel, denn es ist immer noch nicht ganz klar, wie der Status eines digitalen Pins abgefragt werden kann. Es wird dazu der Befehl digitalRead verwendet, dessen Syntax wie folgt aussieht und den wir eigentlich schon im Bastelprojekt 1 über das Blinken der LED kennengelernt haben:

Diese Funktion wird aber nicht nur einfach aufgerufen, sondern liefert uns einen Rückgabewert, der für unsere Auswertung herangezogen werden kann. Über den Zuweisungsoperator = wird der Wert an eine Variable mit dem Namen tasterStatus übergeben. Die möglichen Rückgabewerte sind hierbei HIGH oder LOW, die vom System – wir erinnern uns – vordefinierte Konstanten darstellen. Bevor wir uns jedoch den Sketch, die erforderlichen Bauteile und den entsprechende Schaltplan anschauen, möchte ich den Aufbau und die Funktionsweise eines Mikrotasters erklären. Auf der folgenden Abbildung sehen wir einen derartigen Mikrotaster, der über vier Anschlüsse verfügt. Für das Schließen eines einzelnen Kontaktes werden zwei Anschlüsse benötigt, aber auch wenn wir es hier mit vier Anschlüssen zu tun haben, bedeutet das nicht, dass sich in dem Gehäuse zwei unabhängige Taster befinden:

Abb. 5: Der Mikrotaster
Das Schaltbild rechts vom Taster zeigt die interne Verdrahtung und du erkennst, dass immer zwei Beinchen zusammengehören. Du kannst also den Taster über die Beinchen




Was wir brauchen
Für dieses Bastelprojekt wird nicht viel benötigt und im Grunde genommen kommen wir auch ohne zusätzliche Bauteile aus, denn auf dem Arduino-Board befindet sich eine LED mit der Bezeichnung L. Dennoch möchte ich dieses Bastelprojekt mit ein paar Komponenten anreichern, die auch in weiteren Projekten Verwendung finden:
Tabelle 1: Bauteilliste Bauteil Bild LED rot 1x



Der Schaltplan
Der Schaltplan zeigt uns zur Sicherung eines sicheren Eingangspegels einen externen Pulldown-Widerstand am digitalen Pin 8.

Abb. 6: Der Schaltplan zur Tasterabfrage
Der Schaltungsaufbau
Der Schaltungsaufbau geht auf einem entsprechenden Breadboard leicht von der Hand und ist schnell realisiert.

Abb. 7: Der Schaltungsaufbau zur Tasterabfrage auf dem Arduino Discoveryboard
Mit diesen technischen Grundlagen ausgestattet, wenden wir uns jetzt dem Sketch zu.
Der Arduino-Sketch
Der Sketch zur Abfrage des Tasters und Ansteuerung der LED sieht wie folgt aus:
int ledPin = 13; // LED-Pin 13 int tasterPin = 8; // Taster-Pin 8 int tasterStatus; // Variable für den Tasterstatus void setup() { pinMode(ledPin, OUTPUT); // LED-Pin als Ausgang pinMode(tasterPin, INPUT); // Taster-Pin als Eingang } void loop() { tasterStatus = digitalRead(tasterPin); if(tasterStatus == HIGH) digitalWrite(ledPin, HIGH); else digitalWrite(ledPin, LOW); }
Den Code verstehen
Es ist zu erkennen, dass in diesem Sketch mit mehreren Variablen gearbeitet wird, die am Anfang erst einmal deklariert werden müssen. Die Erklärungen dazu befinden sich hinter den Deklarationen im Sketch als Kommentare.
Was ist bei einem digitalen Pin zu beachten?

Ein digitaler Pin arbeitet standardmäßig als Eingang und benötigt deswegen keine explizite Konfiguration über den Befehl pinMode, wie das hier zu sehen ist. Es erhöht jedoch die Lesbarkeit, wenn es trotzdem erfolgt. Es kann weggelassen werden, wenn der Speicherplatz einmal knapp werden sollte.
Werfen wir kurz einen Blick auf das Flussdiagramm:

Abb. 8: Das Flussdiagramm zur LED-Ansteuerung
Das Diagramm liest sich recht einfach. Wenn die Ausführung des Sketches in der loop-Endlosschleife angekommen ist, wird der Zustand des Taster-Pins kontinuierlich abgefragt und in der Variablen tasterStatus abgelegt. Die entsprechende Zeile lautet:
tasterStatus = digitalRead(tasterPin);
Je nach Rückgabewert erfolgt die Auswertung über eine Kontrollstruktur in Form einer if-else-Anweisung (Wenn-Dann-Sonst):
if(tasterStatus == HIGH) digitalWrite(ledPin, HIGH); else digitalWrite(ledPin, LOW);
Die if-Anweisung bewertet den in runden Klammern stehenden Ausdruck, der umgangssprachlich ungefähr so formuliert werden könnte: »Ist der Inhalt der Variablen tasterStatus gleich dem Wert HIGH? Falls ja, dann führe den Befehl aus, der der if-Anweisung unmittelbar folgt. Falls nicht, fahre mit der Anweisung fort, die der else-Anweisung folgt.« Das folgende Flussdiagramm erleichtert das Verständnis dieser Kontrollstruktur:

Abb. 9: Flussdiagramm zur if-else-Kontrollstruktur
Es gibt auch noch eine einfachere Variante dieser Kontrollstruktur, bei der der else-Zweig nicht vorhanden ist. Du siehst, dass ein Programmablauf nicht unbedingt geradlinig verlaufen muss. Es können Verzweigungen eingebaut werden, die anhand von Bewertungsmechanismen unterschiedliche Befehle oder Befehlsblöcke zur Ausführung bringen. Ein Sketch agiert nicht nur, sondern reagiert auf äußere Einflüsse, beispielsweise auf Sensorsignale.
Zuweisungsoperator kontra Gleichheitsoperator

Ein sehr häufiger Anfängerfehler ist die Verwechslung von Gleichheits- und Zuweisungsoperator. Der Gleichheitsoperator == und der Zuweisungsoperator = haben völlig unterschiedliche Aufgaben, werden aber häufig verwechselt. Das Heimtückische ist, dass beide Schreibweisen in einer Bedingung verwendet werden können und gültig sind.
Hier die korrekte Verwendung des Gleichheitsoperators:
if(tasterStatus == HIGH)
Nun die falsche Verwendung des Zuweisungsoperators:
if(tasterStatus = HIGH)
Aber warum erzeugt diese Schreibweise keinen erkennbaren Fehler? Ganz einfach: Es erfolgt eine Zuweisung der Konstanten HIGH (numerischer Wert 1) an die Variable tasterStatus. 1 bedeutet kein Nullwert und wird als true (wahr) interpretiert. Bei einer Codezeile, die if(true)... lautet, wird der nachfolgende Befehl immer ausgeführt. Ein numerischer Wert 0 wird in C/C++ als false (falsch) angesehen und jeder von 0 verschiedene als true. Derartige Fehler haben es in sich und es muss immer wieder sehr viel Zeit darauf ver(sch)wendet werden, sie ausfindig zu machen.
Troubelshooting
Ü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.
Hast du den Taster richtig angeschlossen?
Was haben wir gelernt?
Der Mikrocontroller des Arduino Uno verfügt über interne Pullup-Widerstände, die einen Wert von 20KΩ besitzen.
Diese Widerstände können entweder über eine Sequenz von pinMode- beziehungsweise digitalWrite-Befehlen oder über einen einzigen pinMode-Befehl mit den Modi INPUT_PULLUP oder INPUT aktiviert beziehungsweise deaktiviert werden.
Über den Befehl digitalRead kann der Pegel eines digitalen Pins abgefragt werden.
Über Kontrollstrukturen wie if oder if-else kann Einfluss auf den Programmablauf genommen werden.
Bastelprojekt 4:
Blinken mit Intervallsteuerung
Im Bastelprojekt 1 zur Ansteuerung einer LED hast du gesehen, wie wir über die Verzögerungsfunktion delay eine Unterbrechung in der Ausführung des Sketches an der betreffenden Stelle hervorgerufen haben. Die angeschlossene LED an dem digitalen Pin blinkte in regelmäßigen Abständen. Eine solche Schaltung und Programmierung hat jedoch einen entscheidenden Nachteil, den wir zuerst erkennen und dann beheben wollen. Wir müssen die Blinkschaltung dazu ein wenig modifizieren und erweitern.
Drücke den Taster – und er reagiert
Was geschähe wohl, wenn du an einem anderen digitalen Eingang zusätzlich einen Taster anschließen würdest, um dann seinen Zustand kontinuierlich abzufragen? Wenn du diesen Taster drückst, soll zeitgleich eine weitere LED leuchten. Vielleicht ahnst du schon, worauf ich hinausmöchte. Solange die Sketch-Ausführung in der delay-Funktion gefangen ist, wird die Abarbeitung des Codes unterbrochen und der digitale Eingang kann demnach nicht abgefragt werden. Du drückst also den Taster und es passiert einfach nichts.
Was wir brauchen
Für dieses Bastelprojekt benötigen wir die folgenden Bauteile:
Tabelle 1: Bauteilliste Bauteil Bild LED rot 1x




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

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:

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:

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



