Abb. 7: Die Schaltzeichen einer Leuchtdiode
Kommen wir zurück zu unserer ursprünglichen Konfiguration, wo die Pins 8, 9 und 10 als Eingänge konfiguriert sind. Wie testen wir das Verhalten? Dazu muss ich ein wenig ausholen. In der Digitaltechnik gibt es nichts Schlimmeres als einen Schaltkreis, der als Eingang definiert ist und an dem nichts angeschlossen wurde. Wie ist das zu verstehen? Sehen wir uns die folgenden Schaltungen etwas genauer an:
Abb. 8: Ein offener Eingang
Ist der Taster geschlossen, liegen +5V am Eingangs-Pin an und öffnen wir den Taster, sollten man meinen, dass nun 0V dort anliegen. Das stimmt jedoch nicht, denn über den offenen Eingang, dem kein definierter Pegel zugewiesen wurde, können Störsignale einfließen. Es reicht schon aus, wenn mit dem Finger der Eingangs-Pin berührt wird, um einen sich ständig wechselnden Pegel zu erreichen. Aus diesem Grund verwenden wir die folgende Schaltung mit einem sogenannten Pulldown-Widerstand.
Abb. 9: Ein offener Eingang mit Pulldown-Widerstand
Ist der Taster geschlossen, ändert sich zur vorherigen Situation nichts und die +5V liegen am Eingangs-Pin an beziehungsweise fallen über dem Pulldown-Widerstand von 10KΩ nach Masse ab. Wird der Taster losgelassen, wird über den Widerstand das Massepotential an den Eingang geleitet, so dass dort ein LOW-Pegel von 0V anliegt. Wir haben also in beiden Tastersituationen ein definiertes Signal am Eingangs-Pin vorherrschen. Für das nun folgende Bastelprojekt wird wieder das Arduino Discoveryboard genutzt, das über fest verdrahtete Pulldown-Widerstände verfügt. Der Schaltplan für das kommende Bastelprojekt sieht wie folgt aus:
Abb. 10: Der Schaltplan mit drei LEDs und drei Tastern
Sehen wir uns den entsprechenden Versuchsaufbau mit den zusätzlichen drei Tastern an:
Abb. 11: Der Versuchsaufbau mit zusätzlichen Tastern
Natürlich müssen wir die Programmierung anpassen:
void setup() { DDRB = 0b11111000; // Pin 8, 9, 10 als INPUT. Pin 11, 12, 13 als OUTPUT PORTB = 0b00111000; // Pin 11, 12, 13 auf HIGH-Pegel setzen Serial.begin(9600); // Serielle Schnittstelle mit 9600 Baud vorbereiten } void loop() { // Binäre Ausgabe von Register PINB über // die serielle Schnittstelle Serial.println(PINB, BIN); delay(1000); // Pause von 1 Sekunde }
Bevor wir den Code besprechen, müssen wir noch ein weiteres Register besprechen. Es nennt sich PINx, wobei das x wieder für den entsprechenden Port steht:
Abb. 12: Das Register PINx
Bei dem Register PINB (Input Pin Address) handelt es sich quasi um ein Statusregister, das den Zustand des Ports widerspiegelt. Es kann nur lesend darauf zugegriffen werden. Wir verwenden es, um den Status aller Pins auf dem sogenannten Serial Monitor anzuzeigen. In der setup-Funktion wird die serielle Schnittstelle mit ihrer Übertragungsrate von 9600 Baud initialisiert. Die spätere Ausgabe erfolgt innerhalb der loop-Funktion über println (Print Linefeed) mit dem zusätzlichen Parameter BIN, der eine binäre Ausgabe des Wertes erzwingt.
Der sogenannte Serial Monitor wird über ein Symbol in der Entwicklungsumgebung geöffnet, das ich rot umrandet habe:
Abb. 13: Das Öffnen des Serial Monitors
Nach einem Mausklick darauf öffnet sich der Monitor:
Abb. 14: Das Fenster des Serial Monitors
Die drei niedrigsten Bits auf der rechten Seite im Serial Monitor spiegeln den Status der drei Taster wider. Welche Taster oder welchen Taster habe ich wohl gedrückt, um die hier gezeigten Bitkombinationen zu erreichen?
Was ist beim Input-Register PINx zu beachten?
Hinsichtlich des Input-Registers PINx werden alle Statusinformationen des jeweiligen Ports auf einmal gelesen.
Register und C++-Befehle
Zur Programmierung und Ansteuerung der verschiedenen Pins ist diese Art der Programmierung vielleicht etwas umständlich und deswegen stehen verschiedene Befehle in der Programmiersprache C++ zur Verfügung, die uns die Sache etwas vereinfachen. Wir kommen im Detail im nächsten Bastelprojekt 3 darauf zu sprechen, aber ich möchte dennoch den direkten Zusammenhang an dieser Stelle verdeutlichen:
Tabelle 2: Register und ihre Entsprechungen | ||
Register | C++-Befehl | Beispiel |
---|---|---|
DDRB | pinMode | pinMode(13, OUTPUT); |
PORTB | digitalWrite | digitalWrite(10, HIGH); |
PINB | digitalRead | digitalRead(8); |
Hier noch einige Informationen zu den verwendeten Befehlen:
pinMode
Der Befehl pinMode programmiert die Datenflussrichtung eines digitalen Pins, wobei zwei Parameter notwendig sind. Der erste gibt den gewünschten Pin an und der zweite die Richtung, wobei OUTPUT für Ausgang und INPUT für Eingang steht.
digitalWrite
Der Befehl digitalWrite beeinflusst den Zustand eines digitalen Pins, wobei zwei Parameter notwendig sind. Der erste gibt den gewünschten Pin an und der zweite den Pegel, wobei HIGH 5V und LOW 0V entspricht.
digitalRead
Der Befehl digitalRead liest den Zustand eines digitalen Pins, wobei das Ergebnis entweder HIGH oder LOW sein kann.
Was ist beim Input-Register PINx zu beachten?
Hinsichtlich der beiden Pins RX und TX der seriellen Schnittstelle, die in ihren Datenflussrichtungen nicht verändert werden sollten und sich auf Port D befinden, gibt es eine sicherere Methode. Das nachfolgende Beispiel programmiert Pin 2 bis 7 als Ausgänge und verändert Pin 0 und 1 nicht: DDRD |= 0b11111100;
Warum ist das so? Wir verwenden eine binäre Oder-Verknüpfung des binären Wertes mit dem gezeigten Register.