Date: 2013-07-15T11:37:27+00:00
Keywords: Elektrotechnik; Messen; Steuern & Regeln; Unix & Linux; Fachbücher; Mikroelektronik; Ingenieurwissenschaften; Computer & Internet
Description: Hauptbeschreibung Der Arduino ist eine preiswerte und flexible Open-Source-Mikrocontroller- Plattform mit einer nahezu unbegrenzten Palette von Add-ons für die Ein- und Ausgänge - wie Sensoren, Displays, Aktoren und vielem mehr. In ""Arduino-Workshops"" erfahren Sie, wie diese Add-ons funktionieren und wie man sie in eigene Projekte integriert. Sie starten mit einem Überblick über das Arduino-System und erfahren dann rasch alles über die verschiedenen elektronischen Komponenten und Konzepte. Hands-on-Projekte im ganzen Buch vertiefen das Gelernte Schritt für Schritt und hel.
Publisher: dpunkt.verlag
Rights: Alle Rechte vorbehalten

ARDUINO-WORKSHOPS

Eine praktische Einführung mit 65 projekten

John Boxall

Übersetzung: G&U Language & Publishing Services GmbH, www.gundu.com

Satz: G&U Language & Publishing Services GmbH, www.gundu.com

Copy-Editing: Alexander Reischert, Köln

Lektorat: Dr. Michael Barabas

Herstellung: Friederike Diefenbacher-Keita

Umschlaggestaltung: Helmut Kraus, www.exclam.de

Druck und Bindung: M.P. Media-Print Informationstechnologie GmbH, 33100 Paderborn

Bibliografische Information der Deutschen Nationalbibliothek

Die Deutsche Nationalbibliothek verzeichnet diese Publikation in der Deutschen National bibliografie; detaillierte bibliografische Daten sind im Internet über http://dnb.d-nb.de abrufbar.

ISBN 978-3-86490-106-5

Deutsche Ausgabe der amerikanischen Auflage 2013

Translation copyright für die deutschsprachige Ausgabe © 2013 dpunkt.verlag GmbH

Wieblinger Weg 17

69123 Heidelberg

Copyright der amerikanischen Originalausgabe © 2013 by John Boxall

Title of American original: Arduino Workshop – A Hands-On Introduction with 65 Projects

No Starch Press, Inc., San Francisco • www.nostarch.com

ISBN: 978-1-59327-448-1

Die vorliegende Publikation ist urheberrechtlich geschützt.

Alle Rechte vorbehalten.

Die Zusammenstellung der Software wurde nach bestem Wissen und Gewissen vorgenommen.

Bitte berücksichtigen Sie die jeweiligen Copyright-Hinweise, die bei den Programmen enthalten sind.

Die Verwendung der Texte und Abbildungen, auch auszugsweise, ist ohne die schriftliche Zustimmung des Verlags urheberrechtswidrig und daher strafbar. Dies gilt insbesondere für die Vervielfältigung, Übersetzung oder die Verwendung in elektronischen Systemen. Es wird darauf hingewiesen, dass die im Buch verwendeten Soft- und Hardware-Bezeich nungen sowie Markennamen und Produktbezeichnungen der jeweiligen Firmen im Allgemeinen warenzeichen-, marken- oder patentrechtlichem Schutz unterliegen.

Alle Angaben und Programme in diesem Buch wurden mit größter Sorgfalt kontrolliert. Weder Autor noch Verlag können jedoch für Schäden haftbar gemacht werden, die im Zusammenhang mit der Verwendung dieses Buches stehen.

5 4 3 2 1 0

Für die beiden Menschen, die stets an mich geglaubt haben: meine Mutter und meine liebste Kathleen

Inhalt

Danksagung

Kapitel 1: Einführung

Kapitel 2: Ein genauerer Blick auf den Arduino und die IDE

Kapitel 3: Erste Schritte

Kapitel 4: Grundbausteine

Kapitel 5: Funktionen

Kapitel 6: Zahlen, Variablen und arithmetische Operationen

Kapitel 7: Flüssigkristallanzeigen

Kapitel 8: Den Arduino erweitern

Kapitel 9: Numerische Tastenfelder

Kapitel 10: Benutzereingaben über einen Touchscreen

Kapitel 11: Gestatten, Familie Arduino!

Kapitel 12: Motoren und Bewegung

Kapitel 13: GPS für den Arduino

Kapitel 14: Drahtlose Datenübertragung

Kapitel 15: Infrarot-Fernbedienungen

Kapitel 16: RFID-Transponder lesen

Kapitel 17: Datenbusse

Kapitel 18: Echtzeituhren

Kapitel 19: Das Internet

Kapitel 20: Mobilfunkkommunikation

Index

Inhaltsverzeichnis

DANKSAGUNG

1

EINFÜHRUNG

Unbegrenzte Möglichkeiten

Die Masse macht’s

Teile und Zubehör

Erforderliche Software

Mac OS X

Windows XP und neuer

Ubuntu Linux 9.04 und höher

Sicherheit

Ausblick

2

EIN GENAUERER BLICK AUF DEN ARDUINO UND DIE IDE

Der Arduino

Die IDE

Der Befehlsbereich

Der Textbereich

Der Meldungsbereich

Ein erster Sketch in der IDE

Kommentare

Die Einrichtungsfunktion

Die Hardware steuern

Die Schleifenfunktion

Den Sketch überprüfen

Den Sketch hochladen und ausführen

Den Sketch bearbeiten

Ausblick

3

ERSTE SCHRITTE

Projekte planen

Elektrizität

Stromstärke

Spannung

Leistung

Elektronische Bauteile

Widerstände

Leuchtdioden (LEDs)

Steckplatinen

Projekt Nr. 1: LED-La-Ola

Der Algorithmus

Die Hardware

Der Sketch

Der Schaltplan

Den Sketch ausführen

Verwenden von Variablen

Projekt Nr. 2: Wiederholungen mit for-Schleifen

Die Helligkeit der LEDs durch Pulsbreitenmodulation ändern

Projekt Nr. 3: PBM-Beispiel

Weitere elektronische Bauteile

Transistoren

Gleichrichterdioden

Relais

Schaltungen mit höherer Spannung

Ausblick

4

GRUNDBAUSTEINE

Schaltpläne

Symbole für die Bauteile

Leitungen in Schaltplänen

Schaltpläne analysieren

Kondensatoren

Die Kapazität von Kondensatoren

Kapazitätswerte ablesen

Arten von Kondensatoren

Digitale Eingänge

Projekt Nr. 4: Beispiel für digitale Eingänge

Der Algorithmus

Die Hardware

Der Schaltplan

Der Sketch

Den Sketch ändern

Den Sketch analysieren

Konstanten mit #define erstellen

Digitale Eingangspins messen

Entscheidungen mit if

Mehr Entscheidungsmöglichkeiten mit if-then-else

Boolesche Variablen

Logische Vergleichsoperatoren

Zwei und mehr Vergleiche

Projekt Nr. 5: Eine Verkehrsampel

Das Ziel

Der Algorithmus

Die Hardware

Der Schaltplan

Der Sketch

Den Sketch ausführen

Analoge und digitale Signale

Projekt Nr. 6: Ein Testgerät für Einzelzellenbatterien

Das Ziel

Der Algorithmus

Die Hardware

Der Schaltplan

Der Sketch

Rechnen mit dem Arduino

Fließkommavariablen

Vergleichsoperatoren für Berechnungen

Die Genauigkeit der Analogmessung durch eine Bezugsspannung verbessern

Externe Bezugsspannung

Interne Bezugsspannung

Regelbare Widerstände

Piezoelektrische Summer

Das Schaltplansymbol

Projekt Nr. 7: Einen Piezosummer ausprobieren

Projekt Nr. 8: Ein Thermometer mit Ampelanzeige

Das Ziel

Die Hardware

Der Schaltplan

Der Sketch

Den Sketch weiterverwenden

Ausblick

5

FUNKTIONEN

Projekt Nr. 9: Eine Funktion zur Wiederholung einer Aktion erstellen

Projekt Nr. 10: Eine Funktion mit einstellbarem Blinkvorgang erstellen

Funktionen zur Rückgabe von Werten

Projekt Nr. 11: Ein Thermometer mit Blinkcodeanzeige

Die Hardware

Der Schaltplan

Der Sketch

Daten vom Arduino im seriellen Monitor anzeigen

Der serielle Monitor

Projekt Nr. 12: Die Temperatur im seriellen Monitor anzeigen

Debugging im seriellen Monitor

Entscheidungen mit while-Anweisungen
do-while

Daten vom seriellen Monitor an den Arduino senden

Projekt Nr. 13: Eine Zahl mit 2 multiplizieren
long-Variablen

Projekt Nr. 14: long-Variablen verwenden

Ausblick

6

ZAHLEN, VARIABLEN UND ARITHMETISCHE OPERATIONEN

Zufallszahlen generieren

Zufallszahlen aus dem Umgebungsstrom generieren

Projekt Nr. 15: Einen elektronischen Würfel erstellen

Die Hardware

Der Schaltplan

Der Sketch

Den Sketch ändern

Schnellkurs in Binärzahlen

Bytevariablen

Erweitern der digitalen Ausgänge mit Schieberegistern

Projekt Nr. 16: Eine Binärzahlenanzeige aus LEDs bauen

Die Hardware

Der Anschluss des 74HC595

Der Sketch

Projekt Nr. 17: Ein Binärzahlenquiz konstruieren

Der Algorithmus

Der Sketch

Arrays

Arrays definieren

Auf Werte in Arrays verweisen

In Arrays lesen und schreiben

Siebensegmentanzeigen

Die LEDs steuern

Projekt Nr. 18: Eine einstellige Anzeige konstruieren

Die Hardware

Der Schaltplan

Der Sketch

Zweistellige Zahlen anzeigen

Projekt Nr. 19: Zwei Siebensegmentanzeigen steuern

Die Hardware

Der Schaltplan

Modulo

Projekt Nr. 20: Ein Digitalthermometer konstruieren

Die Hardware

Der Sketch

LED-Matrixanzeigen

Die LED-Matrix im Schaltplan

Die Verbindungen herstellen

Bitarithmetik

Der bitweise AND-Operator

Der bitweise OR-Operator

Der bitweise XOR-Operator

Der bitweise NOT-Operator

Bitverschiebung nach links und rechts

Projekt Nr. 21: Eine LED-Matrix steuern

Projekt Nr. 22: Bilder auf einer LED-Matrix anzeigen

Projekt Nr. 23: Ein Bild auf einer LED-Matrix darstellen

Projekt Nr. 24: Eine LED-Matrix animieren

Der Sketch

Ausblick

7

FLüSSIGKRISTALLANZEIGEN

LCD-Zeichenmodule

Ein LCD-Zeichenmodul in einem Sketch verwenden

Text anzeigen

Variablen und Zahlen anzeigen

Projekt Nr. 25: Eigene Zeichen definieren

LCD-Grafikmodule

Das LCD-Grafikmodul anschließen

Die Flüssigkristallanzeige verwenden

Die Anzeige steuern

Projekt Nr. 26: Textfunktionen in Aktion

Aufwändigere Anzeigeeffekte hervorrufen

Projekt Nr. 27: Eine Temperaturverlaufskurve aufzeichnen

Der Algorithmus

Die Hardware

Das Ergebnis

Den Sketch ändern

Ausblick

8

DEN ARDUINO ERWEITERN

Shields

ProtoShield

Projekt Nr. 28: Einen eigenen Shield mit acht LEDs konstruieren

Die Hardware

Der Schaltplan

Die Struktur der ProtoShield-Platine

Der Entwurf

Die Bauteile festlöten

Den selbst gebauten Shield ändern

Sketche durch Bibliotheken erweitern

Die Bibliotheken für einen Shield importieren
microSD-Speicherkarten

Die microSD-Karte prüfen

Projekt Nr. 29: Daten auf die Speicherkarte schreiben

Projekt Nr. 30: Ein Gerät zur Temperaturaufzeichnung konstruieren

Die Hardware

Der Sketch

Zeitmessung mit millis() und micros()

Projekt Nr. 31: Eine Stoppuhr konstruieren

Die Hardware

Der Sketch

Interrupts

Interrupt-Modi

Interrupts einrichten

Interrupts aktivieren und deaktivieren

Projekt Nr. 32: Interrupts verwenden

Der Sketch

Ausblick

9

NUMERISCHE TASTENFELDER

Numerische Tastenfelder verwenden

Ein Tastenfeld anschließen

Programme für das Tastenfeld schreiben

Den Sketch testen

Entscheidungen mit switch-case

Projekt Nr. 33: Ein Schloss mit Tastenfeld konstruieren

Der Sketch

Funktionsweise

Den Sketch testen

Ausblick

10

BENUTZEREINGABEN ÜBER EINEN TOUCHSCREEN

Touchscreens

Den Touchscreen anschließen

Projekt Nr. 34: Bereiche auf dem Touchscreen ansprechen

Die Hardware

Der Sketch

Den Sketch testen

Kartierung des Touchscreens

Projekt Nr. 35: Einen Ein/Aus-Schalter mit zwei Zonen entwerfen

Der Sketch

Funktionsweise

Den Sketch testen

Projekt Nr. 36: Einen Schalter mit drei Berührungszonen entwerfen

Die Touchscreen-Karte

Der Sketch

Funktionsweise

Ausblick

11

GESTATTEN, FAMILIE ARDUINO!

Projekt Nr. 37: Einen eigenen Steckplatinen-Arduino bauen

Die Hardware

Der Schaltplan

Die Arduino-Pins

Einen Testsketch ausführen

Anschluss an eine handelsübliche Arduino-Platine

Die zahlreichen verschiedenen Arduino-Platinen

Arduino Uno

Freetronics Eleven

Der Freeduino

Der Boarduino

Der Arduino Nano

Der Arduino LilyPad

Der Arduino Mega 2560

Der Freetronics EtherMega

Der Arduino Due

Ausblick

12

MOTOREN UND BEWEGUNG

Kleine Bewegungen mithilfe von Stellmotoren

Stellmotoren auswählen

Einen Stellmotor anschließen

Den Stellmotor in Bewegung setzen

Projekt Nr. 38: Ein Zeigerthermometer bauen

Die Hardware

Der Schaltplan

Der Sketch

E-Motoren

Der Darlington-Transistor TIP120

Projekt Nr. 39: Den Motor steuern

Die Hardware

Der Schaltplan

Der Sketch

Projekt Nr. 40: Einen Roboter mit Raupenantrieb bauen und steuern

Die Hardware

Der Shield

Der Sketch

Kollisionserkennung

Projekt Nr. 41: Kollisionen mithilfe eines Mikroschalters erkennen

Der Schaltplan

Der Sketch

Infrarotsensoren zur Abstandsmessung

Verkabelung

Den IR-Abstandssensor testen

Projekt Nr. 42: Kollisionen mithilfe eines IR-Abstandssensors verhindern

Ultraschallsensoren

Den Ultraschallsensor anschließen

Den Ultraschallsensor verwenden

Den Ultraschallsensor testen

Projekt Nr. 43: Kollisionen mithilfe eines Ultraschall-Abstandssensors verhindern

Der Sketch

Ausblick

13

GPS FÜR DEN ARDUINO

Was ist GPS?

Den GPS-Shield testen

Projekt Nr. 44: Ein einfaches GPS-Empfangsgerät konstruieren

Die Hardware

Der Sketch

Die Position auf dem LCD-Bildschirm anzeigen

Projekt Nr. 45: Eine genaue GPS-gestützte Uhr konstruieren

Die Hardware

Der Sketch

Projekt Nr. 46: Den Bewegungsverlauf eines Objekts aufzeichnen

Die Hardware

Der Sketch

Standorte auf der Landkarte anzeigen

Ausblick

14

DRAHTLOSE DATENüBERTRAGUNG

Preiswerte Module für die drahtlose Datenübertragung

Projekt Nr. 47: Eine drahtlose Fernbedienung konstruieren

Die Hardware für die Senderschaltung

Der Schaltplan für den Sender

Die Hardware für die Empfängerschaltung

Der Schaltplan für den Empfänger

Der Sketch für den Sender

Der Sketch für den Empfänger

XBee-Module für eine drahtlose Übertragung mit größerer Reichweite und höherer Geschwindigkeit

Projekt Nr. 48: Datenübertragung mit einem XBee-Modul

Der Sketch

Den Computer für den Datenempfang einrichten

Projekt Nr. 49: Ein ferngesteuertes Thermometer bauen

Die Hardware

Der Aufbau

Der Sketch

Betrieb

Ausblick

15

INFRAROT-FERNBEDIENUNGEN

Was ist Infrarot?

Vorbereitung für die Infrarotübertragung

Der IR-Empfänger

Die Fernbedienung

Der Testsketch

Den Sketch testen

Projekt Nr. 50: Den Arduino fernsteuern

Die Hardware

Der Sketch

Den Sketch erweitern

Projekt Nr. 51: Ein Raupenfahrzeug fernsteuern

Die Hardware

Der Sketch

Ausblick

16

RFID-TRANSPONDER LESEN

Das Innenleben von RFID-Transpondern

Die Hardware testen

Der Schaltplan

Die Schaltung prüfen

Projekt Nr. 52: Ein einfaches RFID-Steuerungssystem konstruieren

Der Sketch

Funktionsweise

Daten im eingebauten EEPROM des Arduino speichern

Lesen und Schreiben im EEPROM

Projekt Nr. 53: Ein RFID-Steuerungssystem konstruieren, das sich die letzte Aktion merkt

Der Sketch

Funktionsweise

Ausblick

17

DATENBUSSE

Der I^2C-Bus

Projekt Nr. 54: Einen externen EEPROM verwenden

Die Hardware

Der Schaltplan

Der Sketch

Das Ergebnis

Projekt Nr. 55: Einen IC zur Porterweiterung verwenden

Die Hardware

Der Schaltplan

Der Sketch

Der SPI-Bus

Die Anschlüsse

Den SPI-Bus nutzen

Daten an ein SPI-Gerät senden

Projekt Nr. 56: Ein Digitalpotenziometer verwenden

Die Hardware

Der Schaltplan

Der Sketch

Ausblick

18

ECHTZEITUHREN

Der Anschluss des RTC-Moduls

Projekt Nr. 57: Datum und Uhrzeit mit einem RTC-Modul einstellen und anzeigen

Die Hardware

Der Sketch

Funktionsweise

Projekt Nr. 58: Eine einfache Digitaluhr bauen

Die Hardware

Der Sketch

Funktionsweise

Projekt Nr. 59: Eine Stechuhr konstruieren

Die Hardware

Der Sketch

Funktionsweise

Ausblick

19

DAS INTERNET

Erforderliches Material

Projekt Nr. 60: Eine Fernüberwachungsstation konstruieren

Die Hardware

Der Sketch

Fehlersuche

Funktionsweise

Projekt Nr. 61: Einen Arduino-Tweeter konstruieren

Die Hardware

Der Sketch

Den Arduino vom Web aus steuern

Projekt Nr. 62: Eine Fernsteuerung für den Arduino einrichten

Die Hardware

Der Sketch

Den Arduino fernsteuern

Ausblick

20

MOBILFUNKKOMMUNIKATION

Die Hardware

Den Power-Shield vorbereiten

Die Hardware einrichten und testen

Die Betriebsfrequenz ändern

Projekt Nr. 63: Ein Arduino-Wählgerät bauen

Die Hardware

Der Schaltplan

Der Sketch

Funktionsweise

Projekt Nr. 64: Textnachrichten mit dem Arduino senden

Der Sketch

Funktionsweise

Projekt Nr. 65: Eine SMS-Fernsteuerung einrichten

Die Hardware

Der Schaltplan

Der Sketch

Funktionsweise

Ausblick

INDEX

Danksagung

An erster Stelle ein großes Dankeschön an das Arduino-Team: Massimo Banzi, David Cuartielles, Tom Igoe, Gianluca Martino und David Mellis. Ohne eure Vorstellungskraft, eure Ideen und harte Arbeit wäre all dies nicht möglich.

Vielen Dank auch an meinen Fachgutachter Marc Alexander für seine Beiträge, Fachkenntnisse, Vorschläge, Unterstützung, Ideen und die langen Gespräche – und für seine Zähigkeit, ein so umfangreiches Projekt durchzustehen.

Ich möchte auch den folgenden Organisationen für die Bereitstellung von Bildern und für ihre Ermutigung danken: Adafruit Industries, Agilent Technologies, Gravitech, Freetronics, oomlout, Seeed Studio, Sharp Corporation und SparkFun. An Freetronics geht dabei noch ein zusätzliches Dankeschön für die hervorragenden Hardwareprodukte. Außerdem möchte ich bei all jenen danken, die viel Zeit in die Entwicklung der Arduino-Bibliotheken gesteckt und uns allen damit das Leben erleichtert haben.

Hut ab vor dem Team von Fritzing und ein Dankeschön für das wunderbare Open-Source-Programm zur Konstruktion von Schaltplänen, das ich in diesem Buch benutzt habe.

Außerdem möchte ich (ohne besondere Reihenfolge) den folgenden Personen danken, die mir Ermutigung, Anregung und Unterstützung geboten haben: Iraphne Childs, Limor Fried, Jonathan Oxer, Philip Lindsay, Nicole Kilah, Ken Shirriff, Nathan Kennedy, David Jones und Nathan Seidle.

Abschließend geht mein Dank noch an alle Mitarbeiter von No Starch Press, vor allem an Sondra Silverhawk, die mir dieses Buch vorschlug, an Serena Young für die engagierte Bearbeitung des Textes und an Bill Pollock für seine Unterstützung und Anleitung sowie dafür, dass er mich manchmal davon überzeugen konnte, dass es noch bessere Möglichkeiten gibt, um etwas zu erklären.

1

Einführung

Haben Sie sich beim Anblick eines technischen Geräts – etwa bei einem ferngesteuerten Bootsmodell, einer Liftsteuerung, einem Verkaufsautomaten oder einem elektronischen Spielzeug – jemals gefragt, wie es funktioniert? Haben Sie jemals den Wunsch verspürt, einen eigenen Roboter, einen elektronischen Signalgeber für eine Modelleisenbahn oder ein System zu bauen, um Wetterdaten aufzuzeichnen und zu analysieren?

Die Arduino-Platine (die Sie in Abb. 1–1 sehen) bietet Ihnen Gelegenheit, einige Geheimnisse der Elektronik auf praktische Weise zu erforschen. Das ursprünglich von Massimo Banzi und David Cuartielles erfundene System Arduino stellt eine günstige Möglichkeit dar, um interaktive Projekte wie ferngesteuerte Roboter, GPS-Ortungssysteme und elektronische Spiele zu konstruieren.

Seit der Einführung im Jahr 2005 ist das Arduino-Projekt exponentiell zu einem blühenden Geschäft gewachsen. Unterstützt wird es durch eine Community von Personen, die den gemeinsamen Wunsch haben, Neues zu erschaffen. Einzelpersonen und Gruppen, von Interessengruppen über Vereine und lokale Hackergemeinschaften bis zu pädagogischen Einrichtungen, zeigen Interesse am Experimentieren mit Arduino.

Abb. 1–1 Die Arduino-Platine

Um sich eine Vorstellung von der Vielfalt der Arduino-Projekte zu machen, die bisher realisiert wurden, können Sie einfach im Internet danach suchen. Dabei werden Sie verschiedene Gruppen finden, die Einführungskurse und gemeinsame Arbeiten mit gleichgesinnten, kreativen Menschen anbieten.

Unbegrenzte Möglichkeiten

Schon beim Durchblättern dieses Buches werden Sie feststellen, dass Arduino vielfältige Möglichkeiten bietet – von ganz einfachen Dingen, wie beispielsweise eine Lampe blinken zu lassen, bis zu komplizierten, etwa einer Interaktion mit einem Mobiltelefon.

Sehen Sie sich beispielsweise Philip Lindsays Gerät aus Abbildung 1–2 an. Es kann Textnachrichten von Mobiltelefonen empfangen und sie auf Leuchtbändern darstellen, wie man es in vielen Geschäften sieht. Dieses Gerät enthält eine Arduino-Platine und ein Handy-Shield, um Textnachrichten von einem Mobiltelefon empfangen zu können (ähnlich wie in Projekt 65). Die Nachricht wird dann an ein zwei große, preisgünstige Punktmatrix-Anzeigen geleitet, um sie gut sichtbar darzustellen.

Abb. 1–2 SMS-Lauftext

Große Anzeigetafeln, die mit einem Arduino verbunden werden können, sind käuflich zu erwerben, weshalb Sie sie nicht selbst basteln müssen. (Mehr dazu erfahren Sie auf http://www.labradoc.com/i/follower/p/project-sms-text-scroller.)

Wie wäre es mit einer einzigartigen Form von Heiratsantrag? Tyler Cooper wollte seiner Freundin auf originelle Weise einen Antrag machen, weshalb er ein Gerät konstruierte, das er einen »umgekehrten Geocache« nennt. Es handelt sich dabei um ein kleines Kästchen, das einen Verlobungsring enthält (siehe Abb. 1–3). Wird es in eine bestimmte Gegend getragen (was der interne GPS-Empfänger feststellt), dann entriegelt es sich, um die romantische Nachricht und den Ring freizugeben. Dieses Gerät können Sie mithilfe einer Arduino-Platine, eines GPS-Empfängers und eines LCD-Moduls (wie es in Kapitel 13 verwendet wird) sowie einem kleinen Servomotor leicht nachbauen. Letzterer dient als Riegel, um das Kästchen verschlossen zu halten, bis es sich am richtigen Ort befindet. Der erforderliche Code ist ziemlich einfach und in wenigen Stunden zu schreiben. Am zeitaufwändigsten ist die Auswahl des passenden Kästchens für das System. (Weitere Informationen erhalten Sie unter http://learn.adafruit.com/reverse-geocache-engagement-box/.)

Abb. 1–3 Heiratsantrag via Arduino

Ein weiteres Beispiel: Kurt Schulz wollte den Ladezustand der Batterie in seinem Moped überwachen. Nachdem er aber festgestellt hatte, wie einfach es ist, mit dem Arduino zu arbeiten, entwickelte sich dieses Projekt zu etwas, was er letztlich »Scooterputer« nannte – ein umfassendes Moped-Überwachungssystem. Der Scooterputer misst nicht nur die Batteriespannung, sondern kann auch Geschwindigkeit, zurückgelegte Strecke, Neigungswinkel, Temperatur, Uhrzeit und Datum, GPS-Position usw. anzeigen. Außerdem enthält er einen Mobiltelefon-Shield, der ferngesteuert werden kann. Damit ist es möglich, das Fahrzeug zu verfolgen, wenn es gestohlen werden sollte, und den Motor ferngesteuert abzuschalten. Das gesamte System wird über einen Touchscreen gesteuert (siehe Abb. 1–4). Jede der Funktionen bildet dabei einen einfachen Baustein, und ein ähnliches Gesamtsystem könnte jedermann innerhalb weniger Wochenenden zusammenstellen. (Mehr darüber auf http://www.janspace.com/b2evolution/arduino.php/2010/06/26/scooterputer/.)

Abb. 1–4 Die Anzeige des Scooterputers (mit freundlicher Genehmigung von Kurt Schulz)

Als Nächstes haben wir John Sarik, der sich gern mit den beliebten Sudoku-Rätseln beschäftigt ... und mit Nixie-Röhren zur Anzeige von Ziffern herumspielt. Diese beiden Antriebsfedern regten ihn dazu an, einen großen 81-stelligen Sudoku-Computer zu bauen. Der Benutzer kann das gesamte 9 x 9-Feld bespielen, wobei der Arduino die Zahlenanzeige steuert und die Einträge auf Gültigkeit prüft. Dies ist zwar schon ein Projekt für Fortgeschrittene, aber durchaus realisierbar, und auch die Elektronik ist nicht sehr kompliziert. Das Gerät ist ziemlich groß und sieht an der Wand beeindruckend aus, wie Abbildung 1–5 zeigt. (Mehr darüber auf http://trashbearlabs.wordpress.com/2010/07/09/nixie-sudoku/.)

Abb. 1–5 Ein Sudoku aus Nixie-Röhren

Das Team von Oomlout hat mit dem Arduino sogar eine Schreibmaschine gebaut, den TwypeWriter. Dabei ist ein Arduino über einen Ethernet-Shield mit dem Internet verbunden und durchsucht Twitter nach bestimmten Schlüsselwörtern. Wird ein Begriff gefunden, so wird der entsprechende Tweet an eine elektrische Schreibmaschine gesendet, um ihn auszudrucken. Der Arduino ist mit den Tastaturschaltkreisen der Schreibmaschine verbunden, sodass er einen Menschen simulieren kann, der die Tasten betätigt. Das Gerät sehen Sie in Abbildung 1–6. (Mehr darüber auf http://oomlout.co.uk/blog/twitter-monitoring-typewritter-twypwriter/.)

Abb. 1–6 Der TwypeWriter

Dies waren nur einige willkürlich herausgegriffene Beispiele dessen, was mit einem Arduino möglich ist. Eigene Projekte lassen sich ohne große Schwierigkeiten bauen, und nachdem Sie dieses Buch durchgearbeitet haben, ist die Umsetzung für Sie nicht mehr außer Reichweite.

Die Masse macht’s

Die Arduino-Plattform gewinnt von Tag zu Tag mehr Freunde. Wenn Sie besser in Gesellschaft, also in Kursen lernen, dann suchen Sie im Web nach Cult of Arduino, um zu erfahren, was andere Personen mit dem Arduino anstellen, und um Arduino-Gruppen kennenzulernen. Die Mitglieder solcher Gruppen werden Sie in die Welt des Arduino als einer Kunstform einführen. Viele arbeiten auch gleichzeitig daran, kleine Arduino-kompatible Platinen zu erfinden. Das Zusammensein mit diesen Gruppen kann viel Spaß machen. Sie lernen dabei interessante Leute kennen und können Ihre Arduino-Kenntnisse weitervermitteln.

Teile und Zubehör

Wie andere elektronische Geräte ist auch der Arduino bei vielen Einzelhändlern erhältlich, die zudem viele verschiedene andere Produkte und Zubehörteile anbieten. Achten Sie aber darauf, dass Sie einen Original-Arduino kaufen und keine Imitation, da Sie sonst ein fehlerhaftes und wenig leistungsfähiges Produkt erwerben können. Eine minderwertige Platine kann dazu führen, dass Ihr Projekt unter dem Strich mehr kostet. Eine Liste von Arduino-Anbietern finden Sie auf http://arduino.cc./en/Main/Buy/.

In der folgenden Liste finden Sie eine aktuelle Auswahl der Händler, die ich für den Kauf von Bauteilen und Zubehör rund um den Arduino empfehle (in alphabetischer Reihenfolge):[1]

• Adafruit Industries (http://www.adafruit.com/)

• DigiKey (http://www.digikey.com/)

• Jameco Electronics (http://www.jameco.com/)

• Little Bird Electronics (http://www.littlebirdelectronics.com/)

• Newark (http://www.newark.com/)

• nicegear (http://www.nicegear.co.nz/)

• Oomlout (http://www.oomlout.co.uk/)

• RadioShack (http://www.radioshack.com/)

• RS Components (http://www.rs-components.com/)

• SparkFun Electronics (http://www.sparkfun.com/)

Wie Sie in diesem Buch noch sehen werden, verwende ich verschiedene Arduino-kompatible Produkte von Freetronics (http://www.freetronics.com/). Alle erforderlichen Teile sind jedoch handelsüblich und lassen sich von vielen verschiedenen Einzelhändlern beziehen.

Aber gehen Sie noch nicht los, um einzukaufen! Nehmen Sie sich zunächst die Zeit, die ersten Kapitel zu lesen, um einen Eindruck davon zu bekommen, was sie brauchen, damit Sie kein Geld auf unnötige Dinge verschwenden.

Erforderliche Software

Ihren Arduino können Sie von praktisch jedem handelsüblichen Computer aus programmieren. An Software benötigen Sie dazu eine integrierte Entwicklungsumgebu 0ng (Integrated Development Environment, IDE). Sie kann auf folgenden Betriebssystemen ausgeführt werden:

• Mac OS X und höher

• Windows XP 32 oder 64 Bit oder höher

• Linux 32 oder 64 Bit (Ubuntu o. Ä.)

Um die richtige IDE herunterzuladen, blättern Sie zu der Überschrift für das von Ihnen verwendete Betriebssystem vor und folgen den Anweisungen. Sie brauchen auch ein passendes USB-Kabel für den Arduino. Wenn Sie noch nicht über einen Arduino verfügen, können Sie die IDE trotzdem schon herunterladen und ein bisschen damit herumspielen. Die Versionsnummer kann sich rasch ändern, weshalb die in diesem Buch verwendete Version möglicherweise nicht mehr die aktuellste ist. Die Anleitungen aber sollten nach wie vor gelten.

HINWEIS

Leider gab es bei Drucklegung dieses Buches Probleme mit der Installation unter Windows 8. Wenn Sie dieses Betriebssystem verwenden, schauen Sie im Arduino-Forum unter http://arduino.cc/forum/index.php/topic,94651.15.html nach.

Mac OS X

In diesem Abschnitt finden Sie Anleitungen zum Herunterladen und Einrichten der Arduino-IDE auf Mac OS X.

Die IDE installieren

Um die IDE auf dem Mac zu installieren, gehen Sie wie folgt vor:

1. Öffnen Sie in einem Webbrowser wie Safari die Downloadseite für die Software unter http://arduino.cc/en/Main/Software/ (siehe Abb. 1–7).

Abb. 1–7 Die Downloadseite für die IDE in Safari

2. Klicken Sie auf den Link Mac OS X. Die Datei wird heruntergeladen und erscheint dann im Fenster Downloads, das Sie in Abbildung 1–8 sehen.

Abb. 1–8 Die Datei ist komplett heruntergeladen.

3. Wenn der Download abgeschlossen ist, doppelklicken Sie auf die Datei, um die Installation auszulösen. Angezeigt wird das Fenster aus Abbildung 1–9.

HINWEIS

Das Paket, das sich hinter dem dritten Symbol verbirgt, müssen Sie nur dann installieren, wenn Sie einen Arduino haben, der älter als das UnoModell ist.

Abb. 1–9 Der neue Ordner mit der Arduino-IDE

4. Ziehen Sie das Arduino-Symbol über den Ordner Programme und lassen Sie die Maustaste los. Während die Datei kopiert wird, ist ein Statusfenster zu sehen.

5. Schließen Sie den Arduino über das USB-Kabel an den Mac an. Nach kurzer Zeit erscheint das Dialogfeld aus Abbildung 1–10.

Abb. 1–10 Eine neue Arduino-Platine wurde erkannt. In dem Dialogfeld kann anstelle von »Eleven« auch »Uno« angezeigt werden.

6. Klicken Sie auf Netzwerkeinstellungen und dann im Feld Netzwerk auf Übernehmen. Die Statusmeldung »nicht konfiguriert« können Sie ignorieren.

Die IDE einrichten

Nachdem Sie die IDE heruntergeladen haben, müssen Sie sie anhand der folgenden Anleitung öffnen und konfigurieren:

1. Öffnen Sie im Finder den Ordner Programme (siehe Abb. 1–11) und doppelklicken Sie auf das Arduino-Symbol.

Abb. 1–11 Der Ordner Programme

2. Möglicherweise wird eine Warnmeldung über das Öffnen von Programmen aus dem Web angezeigt. Wenn ja, klicken Sie einfach auf Öffnen, um fortzufahren. Anschließend sehen Sie wie in Abbildung 1–12 die IDE.

Abb. 1–12 Die IDE in Mac OS X

3. Sie sind schon so gut wie fertig. Bevor die Arduino-IDE zur Verfügung steht, müssen Sie nur noch zwei Kleinigkeiten ändern. Als Erstes müssen Sie ihr mitteilen, über welche Art von Anschluss der Arduino mit dem Mac verbunden ist. Wählen Sie Tools > Serial Port und dann die Option /dev/tty.usbmodem1d11 (siehe Abb. 1–13).

Abb. 1–13 Den USB-Port auswählen

4. Der letzte Schritt besteht darin, der IDE mitzuteilen, was für eine Arduino-Platine Sie angeschlossen haben. Das ist von entscheidender Bedeutung, da es Unterschiede zwischen den Platinen gibt. Wenn Sie beispielsweise das gebräuchlichste Modell verwenden, den Uno, dann wählen Sie wie in Abbildung 1–14 Tools > Board > Arduino Uno. Die Unterschiede zwischen den Platinenmodellen werden in Kapitel 11 ausführlicher erläutert.

Abb. 1–14 Das Platinenmodell auswählen

Damit sind Hardware und Software jetzt betriebsbereit. Blättern Sie zum Abschnitt »Sicherheit« auf S. 14 vor.

Windows XP und neuer

In diesem Abschnitt erfahren sie, wie Sie die Arduino-IDE unter Windows herunterladen, wie Sie die Treiber installieren und die IDE einrichten.

Die IDE installieren

Um die IDE für Windows zu installieren, gehen Sie wie folgt vor:

1. Öffnen Sie in einem Webbrowser wie Firefox die Downloadseite für die Software unter http://arduino.cc/en/Main/Software/ (siehe Abb. 1–15).

Abb. 1–15 Die Downloadseite für die IDE in Firefox unter Windows

2. Klicken Sie auf den Link Windows. Dadurch erscheint das Dialogfeld aus Abbildung 1–16. Klicken Sie auf Öffnen mit Windows Explorer und dann auf OK. Die Datei wird heruntergeladen, wie Sie in Abbildung 1–17 sehen.

Abb. 1–16 Die Datei herunterladen

Abb. 1–17 Firefox zeigt den Fortschritt des Downloads an.

3. Wenn der Download abgeschlossen ist, doppelklicken Sie auf die Datei. Angezeigt wird das Fenster aus Abbildung 1–18.

Abb. 1–18 Das IDE-Paket

4. Kopieren Sie den Ordner mit dem Namen arduino-0022 (oder einem ähnlichen Namen) an den Speicherort, an dem Sie Programme ablegen. Öffnen Sie anschließend den Zielordner. Dort sehen Sie jetzt das Programmsymbol Arduino wie in Abbildung 1–19. Um in Zukunft leichter darauf zugreifen zu können, sollten Sie eine Verknüpfung auf dem Desktop platzieren.

Abb. 1–19 Das IDE-Paket mit dem Symbol für die Anwendung Arduino

Die Treiber installieren

Als Nächstes müssen Sie die Treiber für die USB-Schnittstelle des Arduino installieren.

1. Schließen Sie den Arduino über das USB-Kabel an den PC an. Nach kurzer Zeit wird die Fehlermeldung »Die Gerätetreibersoftware wurde nicht installiert« (oder ähnlich) angezeigt. Schließen Sie einfach das Fenster oder die Sprechblase mit der Meldung.

2. Öffnen Sie die Windows-Systemsteuerung und darin den Geräte-Manager. Scrollen Sie nach unten, bis Sie den Arduino finden (siehe Abb. 1–20).

Abb. 1–20 Der Geräte-Manager

3. Rechtsklicken Sie unter Andere Geräte auf Arduino Uno und wählen Treiber aktualisieren. Aktivieren Sie im nächsten Dialogfeld die Option Auf dem Computer nach Treibersoftware suchen. Daraufhin wird das Dialogfeld Ordner suchen geöffnet. Klicken Sie auf Durchsuchen und wechseln Sie dann zu dem Ordner driver in dem Ordner der neu installierten Arduino-Software (siehe Abb. 1–21). Klicken Sie auf OK.

Abb. 1–21 Den Ordner drivers angeben

4. Klicken Sie im nächsten Dialogfeld auf Weiter. Möglicherweise zeigt Windows eine Meldung darüber an, dass der Herausgeber der Treibersoftware nicht überprüft werden kann. Klicken Sie auf die Option, die Software trotzdem zu installieren. Nach kurzer Zeit meldet Windows, dass der Treiber installiert ist, und gibt die Nummer des COM-Anschlusses an, mit dem der Arduino verbunden ist (siehe Abb. 1–22).

Abb. 1–22 Die Treiber wurden erfolgreich aktualisiert.

Die IDE einrichten

Sie sind fast fertig. Es sind nur noch zwei Kleinigkeiten erforderlich, um die IDE einzurichten.

1. Öffnen Sie die Arduino-IDE und teilen Sie ihr mit, über welche Art von Anschluss der Arduino mit dem PC verbunden ist. Wählen Sie Tools > Serial Port und dann die Nummer des COM-Anschlusses, die im Fenster Treibersoftware aktualisieren angezeigt wurde.

2. Der letzte Schritt besteht darin, der IDE mitzuteilen, was für eine Arduino-Platine Sie angeschlossen haben. Das ist von entscheidender Bedeutung, da es Unterschiede zwischen den Platinen gibt. Wenn Sie beispielsweise einen Uno haben, dann wählen Sie Tools > Board > Arduino Uno. Die Unterschiede zwischen den Platinenmodellen werden in Kapitel 11 ausführlicher erläutert.

Damit ist die Arduino-IDE komplett eingerichtet. Blättern Sie zum Abschnitt »Sicherheit« auf S. 14 vor.

Ubuntu Linux 9.04 und höher

In diesem Abschnitt erfahren Sie, wie Sie die Arduino-IDE unter Ubuntu Linux herunterladen und einrichten.

Die IDE installieren

Um die IDE zu installieren, gehen Sie wie folgt vor:

1. Öffnen Sie in einem Webbrowser wie Firefox die Downloadseite für die Software unter http://arduino.cc/en/Main/Software/ (siehe Abb. 1–23).

Abb. 1–23 Die Downloadseite für die IDE in Firefox unter Ubuntu

2. Klicken Sie je nachdem, was für ein System Sie haben, auf den Link 32-bit oder 64-bit für Linux. Wenn das Dialogfeld aus Abbildung 1–24 erscheint, wählen Sie Öffnen mit Archiv-Manager und klicken dann auf OK.

Abb. 1–24 Die Datei herunterladen

3. Nachdem die Datei heruntergeladen ist, wird sie im Archiv-Manager angezeigt (siehe Abb. 1–25). Kopieren Sie den Ordner mit dem Namen arduino-0022 (oder einem ähnlichen Namen) in Ihren gewohnten Programm- oder Benutzerordner.

Abb. 1–25 Das IDE-Paket

Die IDE einrichten

Als Nächstes müssen Sie die IDE einrichten.

1. Schließen Sie den Arduino über das USB-Kabel an den PC an. Öffnen Sie den zuvor kopierten Ordner arduino-0022 und doppelklicken Sie darin auf die Datei arduino, die in Abbildung 1–26 markiert ist.

Abb. 1–26 Der Ordner der Arduino-IDE mit der Datei arduino

2. Wenn das Dialogfeld aus Abbildung 1–27 erscheint, klicken Sie auf Ausführen. Dadurch wird die IDE wie in Abbildung 1–28 angezeigt.

Abb. 1–27 Berechtigungen zum Ausführen der IDE gewähren

Abb. 1–28 Die IDE unter Linux

3. Teilen Sie der IDE mit, über welche Art von Anschluss der Arduino mit dem Computer verbunden ist. Wählen Sie Tools > Serial Port und dann /dev/ttyACMx, wobei x eine einzelne Ziffer ist. (Es sollte nur einen Anschluss mit einem solchen Namen geben.)

4. Geben Sie an, was für einen Arduino Sie angeschlossen haben. Das ist von entscheidender Bedeutung, da es Unterschiede zwischen den Platinen gibt. Wenn Sie beispielsweise einen Uno haben, dann wählen Sie Tools > Board > Arduino Uno. Die Unterschiede zwischen den Platinenmodellen werden in Kapitel 11 ausführlicher erläutert.

Jetzt sind Hardware und Software betriebsbereit.

Sicherheit

Wie bei jedem anderen Hobby oder Handwerk sind Sie für Ihre eigene Sicherheit und die Ihrer Umgebung verantwortlich. Im weiteren Verlauf dieses Buches beschreibe ich Arbeiten mit einfachen Werkzeugen, batteriebetriebenen elektrischen Geräten, scharfen Messern und manchmal auch Lötkolben. Basteln Sie bei der Arbeit an Ihren Projekten niemals an der Hausstromversorgung herum, sondern überlassen Sie so etwas einem ausgebildeten Elektriker. Denken Sie daran, dass Kontakt mit dem Netzstrom tödlich sein kann.

Ausblick

Sie haben einen Weg vor sich, der sehr interessant ist und viel Spaß bereiten kann. Dabei werden Sie Dinge bauen, die Sie niemals für möglich gehalten haben. In diesem Buch finden Sie 65 Arduino-Projekte, von sehr einfachen bis zu ziemlich komplizierten. Alle sind darauf ausgelegt, Ihnen etwas beizubringen und etwas Nützliches zu konstruieren. Fangen wir also an!

2

Ein genauerer Blick auf den Arduino und die IDE

In diesem Kapitel sehen wir uns die Arduino-Platine sowie die IDE genauer an. Letztere dient dazu, sogenannte Sketche (der Arduino-Begriff für ein Programm) zu erstellen und auf den Arduino hochzuladen. Sie lernen den grundlegenden Aufbau von Sketchen und einige einfache Funktionen kennen, die Sie darin verwenden können. Außerdem werden Sie einen ersten Sketch schreiben und hochladen.

Der Arduino

Was genau ist ein Arduino? Laut der Arduino-Website (http://www.arduino.cc/) handelt es sich dabei um ...

[...] eine Open-Source-Plattform zur Erstellung von elektronischen Prototypen auf der Grundlage einer flexiblen, leicht zu verwendenden Hardware und Software. Sie ist für Künstler, Konstrukteure, Hobbybastler und alle anderen Personen gedacht, die ein Interesse daran haben, interaktive Objekte oder Umgebungen zu gestalten.

Einfach ausgedrückt, ist der Arduino ein winziges Computersystem, das Sie mit Anweisungen programmieren können, sodass es auf verschiedene Arten von Eingaben reagiert und verschiedene Arten von Ausgaben hervorruft. Das aktuelle Arduino-Modell, der Uno, ist kleiner als eine Handfläche, wie Sie in Abbildung 2–1 sehen.

Abb. 2–1 Der Arduino Uno ist ziemlich klein.

Für Uneingeweihte mag der Arduino nicht sehr beeindruckend aussehen, allerdings können Sie damit Geräte bauen, die mit der Umgebung in Wechselwirkung treten. Sie können eine fast unbegrenzte Palette von Eingabeund Ausgabegeräten wie Sensoren, Indikatoren, Anzeigen, Motoren usw. verwenden und genau die Art von Wechselwirkung programmieren, die Sie für ein funktionierendes Gerät benötigen. Beispielsweise haben Künstler Installationen mit Mustern aus Blinklichtern geschaffen, die auf die Bewegungen von Passanten reagieren. Highschool-Schüler haben autonome Roboter gebaut, die offenes Feuer erkennen und löschen können. Geografen haben Systeme konstruiert, die Temperatur und Feuchtigkeit überwachen und die Messwerte als Textnachricht ans Büro schicken. Wenn Sie im Internet suchen, werden Sie fast endlos viele weitere Beispiele finden.

Als Erstes wollen wir uns die Hardware des Arduino Uno (also den »physischen Teil«) genauer ansehen. Machen Sie sich keine Sorgen, wenn Sie manche Einzelheiten noch nicht genau verstehen, denn wir werden uns in späteren Kapiteln ausführlicher damit beschäftigen.

Beginnen wir also mit einem kurzen Rundgang um den Uno. An der linken Seite der Platine fallen gleich die beiden Anschlüsse aus Abbildung 2–2 ins Auge.

Abb. 2–2 Der USB- und der Stromanschluss

Links sehen Sie den USB-Anschluss (Universal Serial Bus), über den Sie die Platine mit Ihrem Computer verbinden können. Das dient drei verschiedenen Zwecken: Um die Platine mit Strom zu versorgen, um Ihre Anweisungen auf den Arduino hochzuladen und um Daten zum Computer zu senden und von ihm zu lesen. Rechts liegt der Stromanschluss. Darüber können Sie den Arduino über einen Standardadapter mit der Steckdose verbinden.

Unten rechts finden Sie das Herz der Platine: den Mikrocontroller aus Abbildung 2–3.

Abb. 2–3 Der Mikrocontroller

Dieser Mikrocontroller ist nicht nur das Herz, sondern auch das Gehirn des Arduino. Es handelt sich um einen winzigen Computer mit einem Prozessor zum Ausführen von Anweisungen, verschiedenen Arten von Arbeitsspeichern, um die Anweisungen von Sketchen festzuhalten, und verschiedenen Möglichkeiten zum Senden und Empfangen von Daten. Knapp unterhalb des Mikrocontrollers finden Sie zwei Reihen kleiner Anschlussbuchsen (siehe Abb. 2–4).

Abb. 2–4 Strom-und Analoganschlüsse

Die erste Reihe ist ein Stromanschluss und bietet auch die Möglichkeit zur Verbindung mit einem externen Reset-Schalter. Die zweite umfasst sechs analoge Eingänge, die zur Messung von elektrischen Signalen mit unterschiedlicher Spannung dienen. Außerdem können die Kontakte A4 und A5 verwendet werden, um Daten an andere Geräte zu senden und von ihnen zu empfangen.

An der oberen Kante der Platine befinden sich zwei weitere Anschlussreihen, die Sie in Abbildung 2–5 sehen.

Abb. 2–5 Die Kontakte für den digitalen Eingang und Ausgang

Die von 0 bis 13 durchnummerierten Kontakte (Pins) sind digitale Ein-/Ausgänge (E/A). Darüber können Sie erkennen, ob ein elektrisches Signal anliegt, oder ein solches Signal auf Befehl erzeugen. Die Pins 0 und 1 bilden auch den seriellen Port, der dazu dient, Signale an andere Geräte zu senden oder von ihnen zu empfangen, beispielsweise an einen/von einem Computer über USB. Die mit einer Tilde (~) beschrifteten Kontakte sind auch in der Lage, ein variables elektrisches Signal abzugeben, was für Beleuchtungseffekte und die Steuerung von Elektromotoren praktisch ist.

Des Weiteren gibt es die sehr nützlichen Leuchtdioden (Light Emitting Diodes, LEDs). Diese winzigen Geräte leuchten auf, wenn Strom durch sie hindurchfließt. Der Arduino verfügt über vier LEDs: Die eine mit der Bezeichnung ON liegt ganz rechts und gibt an, ob die Platine Strom hat, die drei anderen sind zu einer Gruppe zusammengefasst (siehe Abb. 2–6).

Abb. 2–6 Die LEDs auf der Platine

Die LEDs TX und RX leuchten, wenn Daten über den seriellen Port oder den USB-Anschluss zwischen dem Arduino und den angeschlossenen Geräten übertragen werden. Die LED L ist für Ihre eigenen Zwecke vorgesehen. (Sie ist mit dem digitalen E/A-Kontakt 13 verbunden.) Das kleine, schwarze, viereckige Bauteil links neben den LEDs ist ein winziger Mikrocontroller, der die USB-Schnittstelle steuert, über die der Arduino Daten an einen Computer senden und von ihm empfangen kann. Darum müssen Sie sich normalerweise aber nicht kümmern.

Schließlich gibt es noch den Reset-Schalter aus Abbildung 2–7.

Abb. 2–7 Der Reset-Schalter

Wie bei einem normalen Computer kann auch auf dem Arduino manchmal etwas schiefgehen. Wenn alle anderen Maßnahmen versagen, haben Sie noch die Möglichkeit, das System zurückzusetzen und den Arduino neu zu starten. Dazu dient der einfache Reset-Schalter auf der Platine (siehe Abb. 2–7).

Einer der großen Vorteile des Arduino-Systems ist die leichte Erweiterbarkeit. Es ist ganz einfach möglich, weitere Hardwarefunktionen hinzuzufügen. Auf die beiden Anschlussreihen an den Kanten des Arduino können Sie einen Shield aufstecken, eine weitere Platine mit Kontaktstiften, die in die Buchsen der Anschlüsse am Arduino passen. Der Shield aus Abbildung 2–8 beispielsweise enthält eine Ethernet-Schnittstelle, mit deren Hilfe der Arduino mit Netzwerken und dem Internet kommunizieren kann. Außerdem enthält er viel Platz für eigene Schaltungen.

Abb. 2–8 Arduino-Shield mit Ethernet-Schnittstelle

Wie Sie sehen, verfügt auch der Ethernet-Shield über die Anschlussreihen, sodass Sie weitere Shields darauf stapeln können. In Abbildung 2–9 wurde beispielsweise ein Shield mit einer großen numerischen Anzeige, einem Temperatursensor, einem zusätzlichen Datenspeicher und einer Riesen-LED aufgesteckt.

Abb. 2–9 Shield mit numerischer Anzeige und Temperatursensor

Sie müssen beachten, welche Shields welche Ein- und Ausgänge nutzen, damit es nicht zu Konflikten kommt. Außerdem ist es möglich, ganz leere Shields zu kaufen, auf denen Sie Ihre eigenen Schaltungen aufbauen. Mehr darüber erfahren Sie in Kapitel 8.

Ergänzt wird die Arduino-Hardware von der Software, einer Zusammenstellung von Anweisungen, die der Hardware sagen, was und wie sie etwas tun soll. Dabei werden zwei Arten von Software verwendet: erstens die integrierte Entwicklungsumgebung (IDE), um die es in diesem Kapitel geht, und zweitens die Arduino-Sketche, die Sie selbst schreiben.

Die IDE

Wie Abbildung 2–10 zeigt, sieht die Arduino-IDE wie ein einfaches Textverarbeitungsprogramm aus. Sie besteht aus drei Hauptbereichen: dem Befehls-, dem Text- und dem Meldungsbereich.

Abb. 2–10 Die Arduino-IDE

Der Befehlsbereich

Der Befehlsbereich, den Sie oben in Abbildung 2–10 sehen, enthält die Titelleiste, das Menü und die Symbole. Die Titelleiste zeigt den Dateinamen des jeweiligen Sketches (sketch_mar22a) sowie die Version der IDE an (Arduino 1.0). Darunter finden Sie eine Reihe von Menüelementen (File, Edit, Sketch, Tools und Help) und Symbole, die im Folgenden beschrieben werden.

Das Menü

Wie bei Textverarbeitungsprogrammen und Editoren können Sie auf die einzelnen Menüelemente klicken, um sich die verfügbaren Optionen anzusehen.

• File Enthält die Optionen zum Speichern, Laden und Drucken von Sketchen. Außerdem finden Sie hier eine umfassende Sammlung von Beispielsketchen, die Sie öffnen können, und das Untermenü Preferences mit Voreinstellungen.

• Edit Enthält die üblichen Befehle zum Kopieren, Einfügen und Suchen, die Sie auch in jeder Textverarbeitung finden.

• Sketch Enthält Funktionen zum Überprüfen der Sketche vor dem Hochladen auf die Platine sowie Optionen für Sketchordner und den Import.

• Tools Enthält verschiedene Funktionen sowie Befehle zur Auswahl des Platinentyps und des USB-Anschlusses.

• Help Enthält Links zu verschiedenen Themen und nennt die Version der IDE.

Die Symbole

Unter der Menüleiste finden Sie sechs Symbole. Wenn Sie mit dem Mauszeiger darüberfahren, werden ihre Namen angezeigt. Von links nach rechts haben wir folgende Symbole:

• Verify Klicken Sie hierauf, um zu prüfen, ob der Arduino-Sketch gültig ist oder irgendwelche Programmierfehler enthält.

• Upload Hiermit wird der Sketch überprüft und auf die Arduino-Platine hochgeladen.

• New Öffnet einen neuen, leeren Sketch in einem neuen Fenster.

• Open Öffnet einen gespeicherten Sketch.

• Save Speichert den geöffneten Sketch. Hat der Sketch noch keinen Namen, werden Sie dazu aufgefordert, einen anzugeben.

• Serial Monitor Öffnet ein neues Fenster zum Übertragen von Daten zwischen Arduino und IDE.

Der Textbereich

Den Textbereich sehen Sie in der Mitte von Abbildung 2–10. Hier schreiben Sie Ihre Sketche. Der Name des aktuellen Sketches wird auf dem Reiter oben links im Textbereich angegeben. (Der Standardname besteht aus dem aktuellen Datum.) Den Inhalt des Sketches geben Sie hier wie in einer Textverarbeitung ein.

Der Meldungsbereich

Den Meldungsbereich sehen Sie unten in Abbildung 2–10. Meldungen der IDE werden auf der schwarzen Fläche angezeigt. Dabei kann es sich um Mitteilungen über die Überprüfung von Sketchen, über Statusmeldungen usw. handeln.

Unten rechts im Meldungsbereich werden der Platinentyp Ihres Arduino sowie der verwendete USB-Anschluss angezeigt – hier Arduino Duemilanove w/ATmega328 on COM6.

Ein erster Sketch in der IDE

Ein Arduino-Sketch ist ein Satz von Anweisungen, die Sie zusammenstellen, um eine bestimmte Aufgabe zu erledigen; mit anderen Worten: ein Programm. In diesem Abschnitt erstellen Sie einen einfachen Sketch, der dafür sorgt, dass eine LED des Arduino (siehe Abb. 2–11) wiederholt blinkt, indem er sie in Abständen von einer Sekunde ein- und ausschaltet. Außerdem laden Sie den Sketch auf die Platine hoch.

Abb. 2–11 Die mit L gekennzeichnete LED auf der Arduino-Platine

HINWEIS

Die einzelnen Befehle in dem hier vorgestellten Beispielsketch müssen Sie noch nicht genau verstehen. Wie wollen Ihnen zunächst nur zeigen, wie einfach es ist, den Arduino etwas tun zu lassen, um Ihr Interesse für die komplizierteren Dinge zu wecken.

Als Erstes schließen Sie den Arduino über das USB-Kabel an den Computer an. Öffnen Sie die IDE, wählen Sie Tools > Serial Port und dann den richtigen USB-Anschluss. Dadurch wird für eine korrekte Verbindung mit dem Arduino gesorgt.

Kommentare

Als Erstes fügen Sie einen Kommentar ein, in dem Sie festhalten, wozu der Sketch dient. Kommentare sind Hinweise von beliebiger Länge, die sich an den Leser des Sketches richten. Damit können Sie Anmerkungen für sich selbst und für andere hinterlegen, Anleitung geben und auf verschiedene Einzelheiten hinweisen. Wenn Sie Ihren Arduino programmieren (also Sketche schreiben), sollten Sie stets Kommentare einfügen, um deutlich zu machen, was Sie tun. Das kann sich als sehr hilfreich erweisen, wenn Sie sich später erneut mit dem Sketch befassen.

Um einen einzeiligen Kommentar hinzuzufügen, geben Sie zwei Schrägstriche ein und schreiben den Kommentar dann dahinter:

// Blink-LED-Sketch von Mary Smtih, erstellt am 09.09.12

Die beiden Schrägstriche weisen die IDE an, den darauf folgenden Text beim Überprüfen des Sketches zu ignorieren. (Wie bereits erwähnt, untersucht die IDE bei diesem Vorgang, ob alles korrekt und fehlerfrei geschrieben ist.)

Soll ein Kommentar mehrere Zeilen umfassen, müssen Sie ihn in der ersten dieser Zeilen mit /* einleiten und in der letzten mit */ abschließen:

/*
Arduino-Blink-LED-Sketch
von Mary Smith, erstellt am 09.09.12
*/

Wie die beiden Schrägstriche, die einen einzeiligen Kommentar einleiten, weisen auch die Zeichenfolgen /* und */ die IDE an, den Text dazwischen zu ignorieren.

Geben Sie mit einer dieser beiden Methoden in einem Kommentar den Zweck des Sketches ein und speichern Sie das Programm über File > Save as. Geben Sie einen kurzen Namen für den Sketch ein (z. B. blinky) und klicken Sie auf OK.

Die Standard-Dateinamenerweiterung für Arduino-Sketche ist .ino, was von der IDE automatisch hinzugefügt wird. Der vollständige Name in unserem Beispiel lautet also blinky.ino und sollte im Sketchbook angezeigt werden.

Die Einrichtungsfunktion

Der nächste Schritt beim Schreiben eines Sketches besteht immer darin, die Funktion void setup() hinzuzufügen. Sie enthält eine Reihe von Anweisungen, die der Arduino einmalig ausführt, wenn er zurückgesetzt oder eingeschaltet wird. Um diese Einrichtungsfunktion zu erstellen, fügen Sie hinter dem Kommentar folgende Zeilen in den Sketch ein:

void setup()
{

}

Die Hardware steuern

Unser Programm soll die Benutzer-LED auf dem Arduino blinken lassen, die mit dem digitalen Pin 13 verbunden ist. Ein solcher Pin kann entweder ein elektrisches Signal erkennen oder selbst ein solches hervorrufen. In diesem Objekt erzeugen wir ein elektrisches Signal, das die LED zum Leuchten bringt. Das mag sich jetzt etwas kompliziert anhören, aber Sie werden in den kommenden Kapiteln noch Genaueres über die digitalen Pins erfahren. Zunächst einmal fahren Sie einfach damit fort, den Sketch zu schreiben.

Geben Sie zwischen die geschweiften Klammern { und } Folgendes ein:

pinMode(13, OUTPUT); // Legt den digitalen Pin 13 als Ausgang fest

Die Nummer 13 gibt den Pin an, den Sie ansprechen wollen. Diesen Kontakt setzen Sie auf OUTPUT, das heißt, Sie legen ihn als Ausgang fest, an dem Sie ein elektrisches Signal generieren (ausgeben). Wenn Sie dagegen ein eingehendes elektrisches Signal erkennen wollen, müssen Sie INPUT verwenden. Beachten Sie, dass die Funktion pinMode mit einem Semikolon abgeschlossen wird. Das gilt für alle Funktionen in Arduino-Sketchen.

Speichern Sie den Sketch erneut, damit Sie die hinzugefügten Teile nicht verlieren.

Die Schleifenfunktion

Da wir die LED wiederholt blinken lassen wollen, müssen wir eine Schleifenfunktion (loop) erstellen, damit der Arduino eine Anweisung immer und immer wieder ausführt, bis der Strom abgeschaltet oder die Reset-Taste betätigt wird.

Geben Sie den fett gedruckten Code ein, der im folgenden Listing hinter dem Abschnitt von void setup() steht, um eine leere Schleifenfunktion zu erstellen. Achten Sie darauf, dass der neue Abschnitt mit einer schließenden geschweiften Klammer (}) endet, und speichern Sie den Sketch.

/*
Arduino Blink LED Sketch
by Mary Smith, created 09/09/12
*/

void setup()
{
pinMode(13, OUTPUT); // Legt den digitalen Pin 13 als Ausgang fest
}

void loop()
{
// Hierhin kommt der Code für die Schleife
}

WARNUNG

Die Arduino-IDE führt keine automatische Zwischenspeicherung Ihrer Sketche durch, weshalb Sie regelmäßig speichern sollten!

Als Nächstes geben Sie in void loop() die Funktionen ein, die der Arduino ausführen soll.

Schreiben Sie den folgenden Code zwischen die geschweiften Klammern der loop-Funktion und klicken Sie dann auf Verify, um sicherzustellen, dass Sie dabei keinen Fehler gemacht haben.

digitalWrite(13, HIGH);   // Schaltet den digitalen Pin 13 ein
delay(1000);              // Wartet eine Sekunde lang
digitalWrite(13, LOW);    // Schaltet den digitalen Pin 13 aus
delay(1000);              // Wartet eine Sekunde lang

Das wollen wir uns im Einzelnen ansehen. Die Funktion digitalWrite() legt die Spannung fest, die an einem digitalen Pin ausgegeben wird, in diesem Fall Pin 13 für die LED. Der zweite Parameter dieser Funktion lautet HIGH, wodurch eine »hohe« Spannung ausgegeben wird. Der Strom fließt von dem Pin zur LED und schaltet diese ein. (Wenn Sie den Parameter auf LOW setzen, wird der Stromfluss zur LED unterbrochen.)

Nachdem die LED eingeschaltet ist, leuchtet sie eine Sekunde lang, was durch delay(1000) erreicht wird. Die Funktion delay() sorgt dafür, dass in dem angegebenen Zeitraum (in unserem Fall also 1000 Millisekunden oder eine Sekunde) nichts geschieht.

Danach wird die Spannung an der LED mit digitalWrite(13, LOW); wieder ausgeschaltet. Abermals warten wir mit delay(1000) eine Sekunde lang. In diesem Zeitraum bleibt die LED ausgeschaltet.

Der vollständige Sketch sieht wie folgt aus:

/*
Arduino Blink LED Sketch
by Mary Smith, created 09/09/12
*/

void setup()
{
pinMode(13, OUTPUT);     // Legt den digitalen Pin 13 als Ausgang fest
}

void loop()
{
digitalWrite(13, HIGH);  // Schaltet den digitalen Pin 13 ein
delay(1000);             // Wartet eine Sekunde lang
digitalWrite(13, LOW);   // Schaltet den digitalen Pin 13 aus
delay(1000);             // Wartet eine Sekunde lang
}

Bevor Sie weiterarbeiten, speichern Sie den Sketch!

Den Sketch überprüfen

Bei der Überprüfung wird untersucht, ob der Sketch auf eine Weise geschrieben ist, die der Arduino verstehen kann. Dazu klicken Sie in der IDE auf Verify und warten einen Augenblick. Nach der Überprüfung erscheint im Meldungsbereich eine Mitteilung wie in Abbildung 2–12.

Abb. 2–12 Der Sketch wurde überprüft.

Die Meldung »Done compiling« (Kompilierung erfolgt) besagt, dass der Sketch in Ordnung ist und auf den Arduino hochgeladen werden kann. Außerdem wird angezeigt, wie viel Arbeitsspeicher er belegt (hier 1076 Byte) und wie viel auf dem Arduino insgesamt zur Verfügung steht (32.256 Byte).

Was aber, wenn der Sketch nicht korrekt ist? Nehmen wir beispielsweise an, Sie haben das Semikolon am Ende der zweiten delay(1000)-Funktion vergessen. Wenn Sie auf Verify klicken und irgendetwas in Ihrem Sketch nicht stimmt, wird eine Fehlermeldung wie die in Abbildung 2–13 ausgegeben.

Abb. 2–13 Ein Überprüfungsfehler im Meldungsbereich

Die Meldung gibt an, dass der Fehler in der Funktion void loop steckt. Außerdem wird die Nummer der Zeile angegeben, in der die IDE den Fehler gefunden hat (blinky:16, also Zeile 16 im Sketch blinky), und der Fehler selbst (das fehlende Semikolon: error: expected ';' bevor '}' token). Des Weiteren markiert die IDE die Position des Fehlers oder eine Stelle gleich dahinter in Gelb. Dadurch können Sie den Fehler schnell finden und beheben.

Den Sketch hochladen und ausführen

Wenn Sie sich vergewissert haben, dass der Sketch korrekt ist, speichern Sie ihn. Stellen Sie sicher, dass der Arduino angeschlossen ist, und klicken Sie in der IDE auf Upload. Möglicherweise überprüft die IDE den Sketch erneut, lädt ihn dann aber auf den Arduino hoch. Während dieses Vorgangs blinken die LEDs TX und RX auf der Platine (siehe Abb. 2–6), um anzuzeigen, dass Informationen zwischen dem Arduino und dem Computer übertragen werden.

Jetzt schlägt die Stunde der Wahrheit: Der Arduino sollte damit beginnen, den Sketch auszuführen. Wenn alles richtig funktioniert, sollte die LED im Sekundentakt blinken.

Herzlichen Glückwunsch! Sie kennen jetzt die Grundlagen, um Arduino-Sketche erstellen, überprüfen und hochladen zu können.

Den Sketch bearbeiten

Nachdem Sie den Sketch ausgeführt haben, können Sie ihn abwandeln, indem Sie beispielsweise die Verzögerung zum Ein- und Ausschalten der LED ändern. Da die IDE ähnlich funktioniert wie eine Textverarbeitung, können Sie den gespeicherten Sketch einfach öffnen, die Werte anpassen, den Sketch wieder speichern und erneut auf den Arduino hochladen. Um beispielsweise den Blinkrhythmus zu beschleunigen, ändern Sie die beiden delay-Funktionen auf einen Wert von 250, sodass die LED im Viertelsekundentakt aufleuchtet und erlischt.

delay(250); // Wartet eine Viertelsekunde lang

Laden Sie den Sketch erneut hoch. Die LED sollte jetzt schneller blinken und jeweils eine Viertelsekunde lang ein- und ausgeschaltet sein.

Ausblick

Mit Ihren neuen Kenntnissen darüber, wie Sie Arduino-Sketche schreiben, bearbeiten, speichern und hochladen, sind Sie nun bereit, in den nächsten Kapiteln zu lernen, wie Sie weitere Funktionen einsetzen, Ihre Projekte sauber gestalten, einfache elektronische Schaltkreise konstruieren usw.

3

Erste Schritte

In diesem Kapitel lernen Sie Folgendes:

• Grundlagen einer sauberen Projektgestaltung

• Grundlagen der Elektrizitätslehre

• Funktion von Widerständen, Leuchtdioden, Transistoren, Gleichrichterdioden und Relais

• Verwendung von Steckplatinen für die Konstruktion von Schaltungen

• Verwendung von Integervariablen, for-Schleifen und digitalen Ausgängen für verschiedene Arten von LED-Effekten

Als Nächstes werden Sie Ihren Arduino zum Leben erwecken. Dabei geht es um mehr als nur um die Platine als solche. Sie werden lernen, wie Sie Ihre Projekte planen, um Ihre Vorstellungen in die Realität umzusetzen. Anschließend erhalten Sie eine Einführung in die Elektrizitätslehre. Elektrischer Strom ist die Grundlage für alles, was wir in diesem Buch tun, weshalb es wichtig ist, für Ihre eigenen Projekte ein solides Verständnis der Grundlagen mitzubringen. Außerdem sehen wir uns die verschiedenen Bauteile an, die dabei helfen, Projekte in der Praxis zu gestalten. Am Ende werfen wir einen Blick auf einige neue Funktionen, die Bausteine für Arduino-Sketche bilden.

Projekte planen

Wenn Sie damit beginnen, eigene Projekte zu entwickeln, sind Sie vielleicht versucht, den Sketch sofort zu schreiben, gleich nachdem Ihnen die Idee dafür gekommen ist. Es ist jedoch sinnvoll, zunächst einige Vorbereitungen zu treffen. Schließlich kann der Arduino keine Gedanken lesen, sondern benötigt genaue Anweisungen. Wenn Sie winzige Details übersehen, kann es sein, dass der Arduino zwar trotzdem in der Lage ist, die Anweisungen auszuführen, allerdings werden dann die Ergebnisse nicht Ihren Erwartungen entsprechen.

Unabhängig davon, ob Sie ein einfaches Projekt erstellen, das nur ein Lämpchen blinken lässt, oder ob Sie ein automatisches Signal für eine Modelleisenbahn konstruieren, ist ein ausführlicher Plan für den Erfolg unverzichtbar. Gehen Sie bei der Umsetzung von Arduino-Projekten stets nach folgenden grundlegenden Schritten vor:

1. Legen Sie das Ziel fest. Bestimmen Sie, was Sie erreichen wollen.

2. Schreiben Sie den Algorithmus. Ein Algorithmus ist eine Reihe von Anweisungen, die beschreiben, wie das Projekt ausgeführt werden soll. Führen Sie in dem Algorithmus die Schritte auf, die notwendig sind, um das Ziel des Projekts zu erreichen.

3. Wählen Sie die Hardware aus. Ermitteln Sie, wie Sie diese Hardware an den Arduino anschließen.

4. Schreiben Sie den Sketch. Erstellen Sie eine erste Version des Programms, das dem Arduino sagt, was er tun soll.

5. Stellen Sie alle Verbindungen her. Schließen Sie die Hardware, die Schaltungen und alle weiteren erforderlichen Elemente an die Arduino-Platine an.

6. Testen Sie das Projekt und beheben Sie Fehler. Funktioniert es? Suchen Sie in dieser Phase nach Fehlern und ihren Ursachen, ob im Sketch, in der Hardware oder im Algorithmus.

HINWEIS

Selbst bei gut geplanten Projekten tritt manchmal eine Krankheit auf, die als »Feature Creep« bezeichnet wird, also als »schleichender Funktionszuwachs«. Das passiert, wenn jemand eine neue Funktion einfällt, die er einem Projekt noch hinzufügen möchte, und deshalb versucht, neue Elemente in eine bereits vorhandene Konstruktion hineinzuzwängen. Wenn Sie ein Design abwandeln müssen, dann versuchen Sie nicht, ihm irgendwelche zusätzlichen Elemente unterzuschieben oder Änderungen in letzter Minute vorzunehmen, sondern beginnen Sie neu, indem Sie das Ziel neu definieren.

Je mehr Zeit Sie auf die Planung des Projekts aufwenden, umso leichter fallen Test und Fehlerbehebung.

Elektrizität

Da Sie in Ihren Arduino-Projekten elektronische Schaltungen bauen werden, wollen wir uns zunächst mit der Elektrizität beschäftigen. Einfach ausgedrückt, ist Elektrizität oder elektrischer Strom eine Form von Energie, die wir nutzen und in Wärme, Licht, Bewegung und Kraft umsetzen können. Elektrischer Strom hat drei Haupteigenschaften, die bei unseren Projekten zum Tragen kommen: Stromstärke, Spannung und Leistung.

Stromstärke

Elektrischer Strom fließt (definitionsgemäß) vom positiven Pol einer Stromquelle, etwa einer Batterie, durch den Stromkreis zum negativen Pol. Hierbei handelt es sich um Gleichstrom. Daneben gibt es noch Wechselstrom, den wir in diesem Buch aber nicht behandeln. In manchen Stromkreisen wird der negative Pol als Masse oder Erdung bezeichnet (GND für ground). Die Stromstärke wird in Ampere (A) gemessen, kleinere Stromstärken in Milliampere (mA), wobei 1000 mA einer Stromstärke von 1 A entsprechen.

Spannung

Die Spannung ist die Differenz zwischen der potenziellen Energie am positiven und negativen Ende des Stromkreises. Gemessen wird sie in Volt. Je höher die Spannung, desto schneller bewegt sich der Strom durch den Stromkreis.

Leistung

Die Leistung ist ein Maß für die Rate, mit der ein elektrisches Gerät Energie einer Form in die andere umwandelt. Gemessen wird sie in Watt (W). So leuchtet beispielsweise eine 100-Watt-Birne heller als eine 60-Watt-Birne, da sie mehr elektrische Energie in Licht umwandelt.

Zwischen Spannung, Stromstärke und Leistung gibt es eine einfache mathematische Beziehung:

Leistung (P) = Spannung (U) x Stromstärke (I)

Elektronische Bauteile

Nachdem Sie jetzt die Grundlagen der Elektrizitätslehre kennen, wollen wir uns ansehen, wie sich dies auf die verschiedenen elektronischen Bauteile und Geräte auswirkt. Elektronische Bauteile sind Einzelteile, die den elektrischen Strom in einem Stromkreis so steuern, wie wir es für unsere Projekte brauchen. So wie die verschiedenen Bauteile in einem Auto zusammenwirken, um Treibstoff, Kraft und Bewegung bereitzustellen, sodass wir fahren können, steuern die elektrischen Bauteile zusammen den Strom und machen ihn für unsere Geräte nutzbar.

Besondere Elemente werde ich in diesem Buch immer dort beschreiben, wo sie zum Einsatz kommen. In den folgenden Abschnitten dagegen lernen Sie die grundlegenden Bauteile kennen.

Widerstände

Mehrere Bauteile, etwa die LEDs des Arduino, benötigen nur eine geringe Stromstärke, gewöhnlich um 10 mA. Wird die Platine mit einer zu hohen Stromstärke beschickt, wandelt sie den Überschuss in Wärme um, was sie letztendlich zerstören kann. Um die Stromstärke zu verringern, die an solchen Bauteilen anliegt, können wir zwischen der Spannungsquelle und der Komponente einen Widerstand platzieren. Im normalen Kupferdraht kann der Strom frei fließen, doch in einem Widerstand wird die Bewegung verlangsamt. Ein Teil des Stroms wird in Wärme umgewandelt. Wie groß dieser Anteil ist, hängt vom Widerstandswert ab. Abbildung 3–1 zeigt typische Widerstände.

Abb. 3–1 Typische Widerstände

Elektrischer Widerstand

Der Widerstandswert eines solchen Bauteils kann fest oder variabel sein. Gemessen wird der elektrische Widerstand in Ohm (Ω), wobei höhere Werte in Kiloohm (kΩ = 1000 Ω) oder Megaohm (MΩ = 1.000.000 Ω) angegeben werden.

Den Widerstandswert ablesen

Widerstände sind sehr klein, weshalb auf diesen der Widerstandswert gewöhnlich nicht in Form von Zahlen abgedruckt ist. Sie können den Widerstandswert mithilfe eines Multimeters messen, aber auch direkt von dem Bauteil ablesen. Oft wird der Wert in Form einer Folge von farbigen Ringen angegeben, die von links nach rechts die folgende Bedeutung haben:

• Erster Ring: gibt die erste Stelle des Widerstandswerts an.

• Zweiter Ring: gibt die zweite Stelle des Widerstandswerts an.

• Dritter Ring: gibt den Multiplikator in Vielfachen von 10 (bei Vier-Ring-Widerständen) oder die dritte Stelle des Widerstandswerts an.

• Vierter Ring: gibt den Multiplikator in Vielfachen von 10 für Fünf-Ring-Widerstände an.

• Fünfter Ring: gibt die Toleranz (Genauigkeit) an.

Tabelle 3–1 führt die auf Widerständen verwendeten Farben und ihre Bedeutungen auf.

Farbe

Wert

Schwarz

0

Braun

1

Rot

2

Orange

3

Gelb

4

Grün

5

Blau

6

Violett

7

Grau

8

Weiß

9

Tab. 3–1 Werte der farbigen Ringe auf einem Widerstand

Der fünfte Ring gibt die Toleranz des Widerstands an, also das Maß für die Genauigkeit. Da es sehr schwer ist, Widerstände mit exakten Werten herzustellen, können Sie beim Kauf zwischen Varianten mit einem unterschiedlichen prozentualen Fehler wählen. Ein brauner Ring steht für eine Toleranz von 1 %, ein goldenes Band für 5 % und ein silbernes für 10 %.

In Abbildung 3–2 sehen Sie die schematische Darstellung eines Widerstands. Der gelbe, der violette und der orangefarbene Ring werden, wie in Tabelle 3–1 angegeben, nacheinander als die Zahlen 4, 7 und 3 gelesen. Das steht für 47.000 Ω oder kurz 47 kΩ.

Abb. 3–2 Beispiel für die Farbkennzeichnung auf einem Widerstand

Chipwiderstände

Auf Widerständen für die Montage auf Oberflächen ist anstelle der Farbringe ein Code aus Zahlen und Buchstaben aufgedruckt, wie Sie in Abbildung 3–3 sehen. Die ersten beiden Zahlen bilden dabei eine Zahl, während die dritte angibt, wie viele Nullen darauf folgen. Der Widerstand in Abbildung 3–3 hat also einen Wert von 10.000 Ω oder 10 kΩ.

Abb. 3–3 Beispiel für einen Widerstand zur Oberflächenmontage

HINWEIS

Wenn auf einem kleinen Chipwiderstand ein Code aus Zahlen und Buchstaben aufgedruckt ist (beispielsweise O1C), dann suchen Sie in Google nach EIA-96 code calculator, um Nachschlagetabellen für diesen Code zu finden.

Multimeter

Ein Multimeter ist ein enorm praktisches und ziemlich preisgünstiges Messgerät, mit dem Sie Spannungen, Widerstände, Stromstärken und mehr bestimmen können. In Abbildung 3–4 sehen Sie beispielsweise ein Multimeter beim Messen eines Widerstands.

Abb. 3–4 Multimeter beim Messen eines 560-Ω-Widerstands mit 1 % Toleranz

Für Farbenblinde ist ein Multimeter unverzichtbar. Wie andere Werkzeuge sollten Sie auch dieses Messgerät von einem renommierten Händler beziehen, anstatt im Internet nach dem billigsten Modell zu suchen.

Leistungsangabe

Die Leistungsangabe eines Widerstands nennt die Leistung (in Watt), die das Bauteil verträgt, ohne sich zu überhitzen und auszufallen. Bei den Modellen in Abbildung 3–1 handelt es sich um 1/4-Watt-Widerstände, die im Arduino-System am häufigsten verwendete Art.

Bei der Auswahl von Widerständen müssen Sie das Verhältnis von Leistung, Stromstärke und Spannung berücksichtigen. Je größer Stromstärke oder Spannung, umso größer ist die Leistung des Widerstands.

Gewöhnlich wird bei wachsender Leistung auch die Bauform von Widerständen immer größer. Bei dem Modell in Abbildung 3–5 handelt es sich um einen 5-Watt-Widerstand, der 26 mm lang und 7,5 mm breit ist.

Abb. 3–5 Ein 5-Watt-Widerstand

Leuchtdioden (LEDs)

Eine LED ist ein weit verbreitetes, ungemein nützliches Bauteil, das elektrischen Strom in Licht umwandelt. Es gibt Leuchtdioden in unterschiedlichen Formen, Größen und Farben. In Abbildung 3–6 sehen Sie eine typische LED.

Abb. 3–6 Rote LED mit einem Durchmesser von 5 mm

Beim Einbau von Leuchtdioden in einen Stromkreis müssen Sie Obacht geben, da diese Bauteile gepolt sind. Das heißt, dass der Strom nur in einer Richtung durch die LED fließen kann. Er tritt an der positiven Seite (Anode) ein und an der negativen (Kathode) wieder aus, wie Abbildung 3–7 zeigt. Wenn Sie zu viel Strom in falscher Richtung durch eine Diode schicken, wird sie dadurch zerstört.

Zum Glück sind LEDs so aufgebaut, dass Sie die beiden Enden unterscheiden können. Das »Bein« der Anode ist länger und der Rand an der Unterseite ist an der Kathodenseite flach abgeschnitten (siehe Abb. 3–8).

Abb. 3–7 Stromfluss durch eine LED

Abb. 3–8 Durch die äußere Gestaltung der LED lassen sich Anode (langes Bein) und Kathode (abgeflachter Rand) unterscheiden.

Wenn Sie für ein Projekt LEDs benötigen, müssen Sie die Betriebsspannung und die Stromstärke berücksichtigen. Beispielsweise sind für übliche rote LEDs etwa 1,7 V und 5 bis 20 mA erforderlich. Das stellt uns vor ein kleines Problem, da der Arduino eine feste Ausgabespannung von 5 V mit einer viel höheren Stromstärke liefert. Glücklicherweise können wir die Stärke des Stroms, der die LED erreicht, mit einem Begrenzungswiderstand verringern.

Welchen Widerstandswert brauchen wir dazu aber? Um das zu berechnen, wenden wir das ohmsche Gesetz an.

Um den erforderlichen Begrenzungswiderstand für eine LED zu bestimmen, verwenden wir die folgende Formel:

R = (UV – UD) / I

Hierbei ist UV die Versorgungsspannung (der Arduino gibt 5 V ab), UD die Durchlassspannung (hier 1,7 V) und I die erforderliche Stromstärke für die LED (10 mA). Der Wert von I muss aber in Ampere angegeben werden, weshalb wir 10 mA zunächst in 0,01 A umrechnen.

Wenn wir die angegebenen Werte für unsere LED in die Formel einsetzen, erhalten wir den Widerstand R = 330 Ω. Die LED leuchtet jedoch auch fröhlich vor sich hin, wenn wir sie mit weniger als 10 mA beschicken. Es ist immer eine gute Idee, die Stromstärke zu senken, um empfindliche elektronische Bauteile zu schonen, weshalb wir einen Widerstand von 560 Ω und 1/4 W verwenden. Dadurch gelangt ein Strom von 6 mA zu unseren LEDs.

HINWEIS

Wählen Sie im Zweifelsfall immer einen Widerstand mit einem leicht höheren Wert – besser eine trübe LED als eine kaputte!

DIE DREIECKSDARSTELLUNG DES OHMSCHEN GESETZES

Das ohmsche Gesetz gibt die Beziehung zwischen Stromstärke, Widerstand und Spannung an:

Spannung (U) = Widerstand (R) x Stromstärke (I)

Wenn Sie zwei dieser Größen kennen, können Sie daraus die dritte berechnen. Eine weit verbreitete Eselsbrücke für das ohmsche Gesetz ist das Dreieck in Abbildung 3–9.

Abb. 3–9 Die Dreiecksdarstellung des ohmschen Gesetzes

Dieses Dreieck ist ein bequemes Hilfsmittel für die Berechnung von Spannung, Stromstärke oder Widerstand, wenn zwei der drei Werte bekannt sind. Wollen Sie beispielsweise den Widerstand berechnen, decken Sie das R mit dem Finger ab. Was übrig bleibt, ist Spannung dividiert durch Stromstärke. Um die Spannung zu berechnen, decken Sie U ab, sodass noch Stromstärke mal Widerstand zu sehen ist.

Steckplatinen

Für unsere wechselnden Schaltungen brauchen wir eine Plattform, die sie zusammenhält und auf der wir sie aufbauen können. Hervorragend für diesen Zweck geeignet sind Steckplatinen. Dabei handelt es sich um ein Kunststoffbrett mit Reihen von Einsteckbuchsen, die über elektrische Leiter miteinander verbunden sind. Wie Sie in Abbildung 3–10 sehen, gibt es sie in unterschiedlichen Größen, Formen und Farben.

Abb. 3–10 Steckplatinen in verschiedenen Formen und Größen

Um eine Steckplatine verwenden zu können, müssen Sie wissen, wie die Buchsen verbunden sind – entlang der kurzen oder der langen Reihen in den einzelnen Abschnitten am Rand und in der Mitte. Das ist je nach Platine unterschiedlich. Beispielsweise sind bei der Platine oben in Abbildung 3–11 jeweils fünf Löcher in vertikaler Richtung verbunden, aber in horizontaler Richtung von den Nachbarn isoliert. Wenn Sie zwei Drähte in Löcher einer vertikalen Reihe stecken, sind sie elektrisch leitfähig verbunden. Die langen Reihen in der Mitte zwischen den horizontalen Abschnitten sind dagegen horizontal verbunden. Häufig werden Sie eine Schaltung an die Versorgungsspannung und an Masse anschließen müssen, und dazu sind diese horizontalen Lochreihen ideal geeignet.

Abb. 3–11 Interne Verbindungen einer Steckplatine

Bei komplizierten Schaltungen kann die Steckplatine schnell überfüllt werden, sodass Sie nicht unbedingt in der Lage sind, Bauteile genau dort zu platzieren, wo Sie sie haben wollen. Dieses Problem lässt sich mit kurzen Verbindungsdrähten jedoch leicht lösen. Anbieter, die Steckplatinen verkaufen, haben gewöhnlich auch Sortimente von Drähten verschiedener Länge im Programm (siehe Abb. 3–12).

Abb. 3–12 Sortiment von Verbindungsdrähten für Steckplatinen

Projekt Nr. 1: LED-La-Ola

Wir wollen nun praktisch mit LEDs und Widerständen arbeiten. In diesem Projekt sollen fünf LEDs ein Lichtmuster anzeigen, das sich in La-Ola-Form weiterbewegt (ähnlich wie vorn an KITT aus der Fernsehserie Knight Rider).

Der Algorithmus

Der Algorithmus für dieses Projekt sieht wie folgt aus:

1. Schalte LED 1 ein.

2. Warte eine halbe Sekunde.

3. Schalte LED 1 aus.

4. Schalte LED 2 ein.

5. Warte eine halbe Sekunde.

6. Schalte LED 2 aus.

7. Fahre fort, bis LED 5 eingeschaltet wird, und kehre den Vorgang dann von LED 5 zu LED 1 um.

8. Wiederhole den Vorgang unendlich oft.

Die Hardware

Für dieses Projekt brauchen Sie folgende Teile:

• fünf LEDs

• fünf 560-Ω-Widerstände

• eine Steckplatine

• Verbindungsdrähte

• Arduino und USB-Kabel

Die LEDs schließen wir über die 560-Ω-Begrenzungswiderstände an die Digitalpins 2 bis 6 an.

Der Sketch

Kommen wir jetzt zu unserem Sketch. Geben Sie in der IDE den folgenden Code ein:

// Projekt 1: LED-La-Ola
void setup()
{
pinMode(2, OUTPUT);      // der Steuerpin für LED 1 wird
// als Ausgang festgelegt
pinMode(3, OUTPUT);      // Dito für LED 2 bis LED 5
pinMode(4, OUTPUT);
pinMode(5, OUTPUT);
pinMode(6, OUTPUT);
}

void loop()
{
digitalWrite(2, HIGH);    // Schaltet LED 1 ein
delay(500);               // Wartet eine halbe Sekunde
digitalWrite(2, LOW);     // Schaltet LED 1 aus
digitalWrite(3, HIGH);    // Wiederholt den Vorgang für LED 2 bis 5
delay(500);
digitalWrite(3, LOW);
digitalWrite(4, HIGH);
delay(500);
digitalWrite(4, LOW);
digitalWrite(5, HIGH);
delay(500);
digitalWrite(5, LOW);
digitalWrite(6, HIGH);
delay(500);
digitalWrite(6, LOW);
digitalWrite(5, HIGH);
delay(500);
digitalWrite(5, LOW);
digitalWrite(4, HIGH);
delay(500);
digitalWrite(4, LOW);
digitalWrite(3, HIGH);
delay(500);
digitalWrite(3, LOW);
// Die Schleife loop() kehrt an den Anfang zurück und
// wird wiederholt ausgeführt
}

In void setup() an der Stelle werden die Digital-E/A-Pins als Ausgänge festgelegt, da wir die LEDs bei Bedarf mit Strom versorgen wollen. Mit der Funktion digitalWrite() im Abschnitt void loop() () schalten wir die einzelnen LEDs ein.

Der Schaltplan

Als Nächstes konstruieren wir die Schaltung. Der Aufbau solcher Schaltungen lässt sich auf verschiedene Weise darstellen. Für die ersten Projekte in diesem Buch verwenden wir fotografische Schaltpläne wie in Abbildung 3–13.

Abb. 3–13 Schaltplan für Projekt 1

Wenn Sie die Verdrahtungsskizze mit den Funktionen im Sketch vergleichen, können Sie erkennen, wie die Schaltung funktioniert. Beispielsweise wird bei der Verwendung von digitalWrite(2, HIGH) eine hohe Spannung von 5 V an den Digitalpin 2 angelegt. Der Strom verläuft durch den Begrenzungswiderstand über die Anode in die LED, über die Kathode wieder heraus und schließlich zurück zum GND-Anschluss des Arduino, um den Kreis zu schließen. Anschließend verwenden wir digitalWrite(2, LOW), um den Strom und damit die LED wieder abzuschalten.

Den Sketch ausführen

Schließen Sie jetzt den Arduino an und laden Sie den Sketch hoch. Nach ein oder zwei Sekunden sollten die LEDs von links nach rechts und zurück aufleuchten. Erfolg ist doch etwas Schönes – genießen Sie ihn!

Wenn nichts geschieht, sollten Sie sofort das USB-Kabel vom Arduino abziehen und prüfen, ob Sie den Sketch richtig eingegeben haben. Falls Sie einen Fehler finden, korrigieren Sie ihn und laden den Sketch erneut hoch. Stimmt der Sketch, blinken die LEDs aber trotzdem nicht, überprüfen Sie die Verkabelung auf der Schaltplatine.

Sie können jetzt zwar mit dem Arduino ein Lichtmuster aus LEDs erzeugen, aber der Sketch ist doch noch recht klobig. Wenn Sie das Lichtsignal beispielsweise schneller hin- und herlaufen lassen wollten, müssten Sie jedes einzelne Vorkommen von delay(500) ändern. Es gibt jedoch bessere Möglichkeiten.

Verwenden von Variablen

Um Daten in Computerprogrammen festzuhalten, verwenden wir Variablen. Im dem Sketch für Projekt 1 haben wir die Funktion delay(500) eingesetzt, damit die LEDs eingeschaltet bleiben. Diese Vorgehensweise ist jedoch nicht sehr flexibel. Wenn wir die Verzögerungszeit ändern wollen, müssen wir jeden Eintrag manuell umschreiben. Besser ist es, eine Variable anzulegen, die den Wert für die Funktion delay() festhalten soll.

Geben Sie im Sketch von Projekt 1 über der Funktion void setup(), unmittelbar hinter dem einleitenden Kommentar, folgende Zeile ein:

int d = 250;

Dadurch wird die Zahl 250 der Variable d zugewiesen.

Ersetzen Sie anschließend jedes Vorkommen von 500 in dem Sketch durch d. Wenn der Sketch jetzt ausgeführt wird, verwendet der Arduino den in d gespeicherten Wert für die delay()-Funktionen. Die LEDs werden jetzt viel schneller ein- und ausgeschaltet, da die Verzögerung mit dem Wert 250 nur noch halb so groß ist.

Das Schlüsselwort int deutet schon an, dass die Variable einen Integer enthält, also eine Ganzzahl zwischen –32.768 und 32.767. Einfach gesagt, ist ein Integer kein Bruch und weist auch keine Dezimalstellen auf.

Wenn Sie die Verzögerung jetzt ändern wollen, müssen Sie lediglich die Variablendeklaration am Anfang des Sketches bearbeiten. Wenn Sie beispielsweise wie folgt den Wert 100 für die Verzögerung festlegen, läuft die Sache noch schneller:

int d = 100;

Spielen Sie ein bisschen mit dem Sketch herum, indem Sie beispielsweise die Verzögerungszeiten oder die Abfolge von HIGH und LOW ändern. Bauen Sie die Schaltung aber noch nicht auseinander, da wir sie noch für weitere Projekte in diesem Kapitel gebrauchen werden.

Projekt Nr. 2: Wiederholungen mit for-Schleifen

In einem Sketch müssen Sie häufig eine Funktion wiederholt ablaufen lassen. Dazu könnten Sie die Funktion einfach kopieren und erneut einfügen, aber das wäre umständlich und außerdem eine Verschwendung des Programmspeichers auf dem Arduino. Stattdessen sollten Sie for-Schleifen verwenden. Deren Vorteil besteht darin, dass Sie bestimmen können, wie oft der Code in der Schleife wiederholt werden soll.

Um sich anzusehen, wie eine for-Schleife funktioniert, geben Sie den folgenden Code als neuen Sketch ein:

// Projekt 2: Wiederholungen mit for-Schleifen
int d = 100;

void setup()
{
pinMode(2, OUTPUT);
pinMode(3, OUTPUT);
pinMode(4, OUTPUT);
pinMode(5, OUTPUT);
pinMode(6, OUTPUT);
}

void loop()
{
for ( int a = 2; a < 7 ; a++ )
{
digitalWrite(a, HIGH);
delay(d);
digitalWrite(a, LOW);
delay(d);
}
}

Die for-Schleife wiederholt den Code, der in den geschweiften Klammern unter dem Schlüsselwort steht, so lange, wie eine bestimmte Bedingung wahr ist. Hier verwenden wir die neue Integervariable a, die zu Anfang den Wert 2 hat. Bei jeder Ausführung des Codes wird der Wert von a mit a++ um 1 erhöht. Die Schleife wird auf diese Weise ausgeführt, solange der Wert von a kleiner als 7 ist (dies ist die Bedingung). Sobald a größer oder gleich 7 ist, fährt der Arduino mit dem Code fort, der hinter der for-Schleife steht.

Wie oft eine for-Schleife ausgeführt werden soll, können Sie auch festlegen, indem Sie von einer höheren zu einer niedrigeren Zahl übergehen. Um das zu veranschaulichen, fügen Sie hinter die erste for-Schleife den folgenden Code in den Sketch von Projekt 2 ein:

for ( int a = 5 ; a > 1 ; a-- )
{
digitalWrite(a, HIGH);
delay(d);
digitalWrite(a, LOW);
delay(d);
}

Hier legt die for-Schleife bei den Wert von a auf 5 fest und zieht dann bei jeder Ausführung der Schleife mithilfe von a-- 1 davon ab. Die Schleife wird durchlaufen, solange der Wert von a größer als 1 ist (a > 1). Fällt der Wert auf oder unter 1, wird die Schleife beendet.

Damit haben wir Projekt 1 mit deutlich weniger Code umgeschrieben. Laden Sie den Sketch hoch und probieren Sie es selbst aus.

Die Helligkeit der LEDs durch Pulsbreitenmodulation ändern

Anstatt die LEDs nur mithilfe von digitalWrite() ein- und auszuschalten, können Sie deren vermeintliche Helligkeit auch ändern, indem Sie die Zeitdauer zwischen dem Ein- und Aus-Zustand mithilfe der Pulsbreitenmodulation (PBM) regeln. Damit können Sie die Illusion einer veränderten Helligkeit der LED hervorrufen, indem Sie die LED extrem schnell, etwa 500 Mal die Sekunde, ein- und ausschalten. Die Helligkeit, die wir wahrnehmen, wird durch das Verhältnis der Zeit bestimmt, in der der digitale Ausgangspunkt ein- bzw. ausgeschaltet ist, also die LED leuchtet bzw. nicht leuchtet. Da unser Auge ein schnelleres Flackern als 50 Mal in der Sekunde nicht mehr wahrnehmen kann, scheint es so, als hätte die LED eine konstante Helligkeit.

Je größer das Tastverhältnis (die Einschaltzeit des Pins im Vergleich zur Ausschaltzeit in jedem Zyklus), umso höher ist die wahrgenommene Helligkeit der an den digitalen Ausgangs-Pin angeschlossenen LED.

Abbildung 3–14 zeigt verschiedene Tastverhältnisse der Pulsbreitenmodulation. Die grau gefüllten Bereiche stehen für die Zeit, in der das Licht leuchtet. Wie Sie sehen, ist die Einschaltzeit länger, je höher das Tastverhältnis ist.

Abb. 3–14 Unterschiedliche PBM-Tastverhältnisse

Auf einem regulären Arduino lassen sich nur die Digitalpins 3, 5, 6, 9, 10 und 11 für die Pulsbreitenmodulation verwenden. Wie Sie in Abbildung 3–15 sehen, sind sie auf der Platine mit einer Tilde (~) markiert.

Abb. 3–15 Die PBM-Pins sind mit einer Tilde gekennzeichnet.

Um ein PBM-Signal zu erzeugen, verwenden wir die Funktion analogWrite(x, y). Dabei ist x die Nummer des Digitalpins und y ein Wert für das Tastverhältnis zwischen 0 (0 %) und 255 (100 %).

Projekt Nr. 3: PBM-Beispiel

Das wollen wir an unserer Schaltung aus Projekt 2 ausprobieren. Geben Sie in der IDE den folgenden Sketch ein und laden Sie ihn auf den Arduino hoch:

// Projekt 3: PBM-Beispiel
int d = 5;

void setup()
{
pinMode(3, OUTPUT); // Der LED-Steuerpin ist Nr. 3, er ist PBM-fähig
}

void loop()
{
for ( int a = 0 ; a < 256 ; a++ )
{
analogWrite(3, a);
delay(d);
}

for ( int a = 255 ; a >= 0 ; a-- )
{
analogWrite(3, a);
delay(d);
}
delay(200);
}

Während das Tastverhältnis ansteigt und sinkt, zeigt die LED an Pin 3 ein »Atmungsverhalten«. Das heißt, sie leuchtet auf, erhöht ihre Helligkeit bis zum Höchstwert und wird dann wieder gedämpft. Spielen Sie mit dem Sketch und mit der Schaltung herum. Beispielsweise können Sie fünf LEDs gleichzeitig oder nacheinander »atmen« lassen.

Weitere elektronische Bauteile

Normalerweise können Sie andere Schaltungen über einen digitalen Ausgang steuern, ohne sich Gedanken darüber machen zu müssen, welche Stromstärke Sie dafür wirklich brauchen. Denken Sie einfach daran, dass jeder einzelne digitale Ausgangspin auf dem Arduino Uno bis zu 40 mA bieten kann, mit 200 mA insgesamt für alle Pins. Es gibt jedoch drei elektronische Bauteile, mit denen Sie die Stromstärke genauer steuern können. Sie bilden unser nächstes Thema.

WARNUNG

Wenn Sie versuchen, höhere Werte als 40 mA an einem einzelnen Pin oder 200 mA insgesamt zu verwenden, können Sie dadurch den Mikrocontroller irreparabel beschädigen.

Transistoren

Das Wort »Transistor« ist in aller Munde, aber die wenigsten haben eine Vorstellung davon, wie ein solches Bauteil wirklich funktioniert. Der Kürze halber werde ich die Erklärung möglichst einfach fassen. Ein Transistor ist in der Lage, Strom einer weit höheren Stärke ein- und auszuschalten, als der Arduino Uno handhaben kann. Allerdings können wir einen Transistor gefahrlos über einen digitalen Ausgangspin des Arduino steuern. Ein weit verbreitetes Beispiel für dieses Bauteil ist der BC548, den Sie in Abbildung 3–16 sehen.

Abb. 3–16 Ein typischer Transistor: der BC548

Ähnlich wie Leuchtdioden weisen auch Transistoren Kontakte mit unterschiedlicher Funktion auf, die richtig herum angeschlossen werden müssen. Wenn die flache Seite des BC548 Ihnen zugewandt ist, dann sind die Anschlüsse von links nach rechts Kollektor (englisch Collector und daher kurz C), Basis und Emitter. (Bei anderen Transistoren können die drei Kontakte anders angeordnet sein!) Wird an die Basis ein Strom geringer Stärke angelegt, beispielsweise von einem digitalen E/A-Pin des Arduino, kann durch den Kollektor der stärkere Strom fließen, den wir steuern wollen, wird mit dem schwachen Strom von der Basis kombiniert und tritt am Emitter aus. Wenn wir den schwachen Strom an der Basis abschalten, fließt kein Strom mehr durch den Transistor.

Der BC548 kann Strom bis zu 100 mA mit maximal 30 V schalten, was sehr viel mehr ist, als am digitalen Ausgang des Arduino anliegt. In späteren Projekten in diesem Buch werden wir noch andere Transistoren verwenden und die Funktionsweise dieser Bauteile ausführlicher erläutern.

HINWEIS

Machen Sie sich immer mit der Anordnung der Anschlüsse für den Transistor vertraut, den Sie verwenden, da sie bei jedem Modell anders ausfallen kann.

Gleichrichterdioden

Eine Diode ist ein sehr einfaches und doch äußerst nützliches Bauteil, durch das Strom nur in einer Richtung fließen kann. Wie Sie in Abbildung 3–17 sehen, ähnelt es rein äußerlich einem Widerstand.

Abb. 3–17 Eine Gleichrichterdiode vom Typ 1N4004

In den Projekten dieses Buchs verwenden wir die Gleichrichterdiode vom Typ 1N4004. Strom tritt über die Anode ein und über die Kathode aus, wobei die Kathode durch einen Ring markiert ist. Mit solchen Dioden können Sie Teile von Schaltungen gegen eine Umkehrung der Stromrichtung schützen, doch das hat seinen Preis: Dioden führen zu einem Spannungsabfall um ca. 0,7 V. Die 1N4004 ist zur Handhabung von 1 A und 400 V ausgelegt, also weit höheren Werten, als wir sie verwenden. Es handelt sich bei ihr um eine robuste, weit verbreitete und preiswerte Diode.

Relais

Relais dienen dem gleichen Zweck wie Transistoren, nämlich der Steuerung von viel höheren Stromstärken und Spannungen. Dabei bieten Relais den Vorteil, dass sie von der Schaltung elektrisch isoliert sind, was es dem Arduino ermöglicht, sehr hohe Stromstärken und Spannungen zu schalten. Eine Isolierung ist manchmal notwendig, um Schaltkreise vor solch hohen Stromstärken und Spannungen zu schützen, die den Arduino beschädigen könnten. Das Innenleben eines Relais besteht aus zwei sehr interessanten Einzelteilen: einem mechanischen Schaltkontakt und einer Niederspannungsspule (siehe Abb. 3–18).

Abb. 3–18 Das Innenleben eines typischen Relais

Wird eine Spannung an die Spule angelegt, so wirkt letztere wie ein Elektromagnet. Sie zieht ein Metallstäbchen an, das als Schalter dient, und lässt es wieder los, wenn sie nicht mehr bestromt wird. Je nachdem, ob Spannung an der Spule anliegt oder nicht, ist der Schalter also in Ein- oder AusStellung. Beim Umspringen des Schalters ist ein charakteristisches Klicken zu hören, das Sie vielleicht noch von den Blinkern älterer Autos kennen.

Schaltungen mit höherer Spannung

Nachdem Sie jetzt einige Kenntnisse über Transistoren, Gleichrichterdioden und Relais gewonnen haben, wollen wir alle drei Bauteile verwenden, um höhere Stromstärken und Spannungen zu steuern. Der Aufbau ist ganz einfach, wie Abbildung 3–19 zeigt.

Abb. 3–19 Relais-Steuerkreis

Diese einfache Beispielschaltung steuert ein Relais mit einer 12-Volt-Spule. Eine mögliche Verwendung besteht darin, eine Lampe oder ein Kühlgebläse zu steuern, das an die Schaltkontakte des Relais angeschlossen wird. Der Digitalpin 10 des Arduino ist über einen 1-kΩ-Widerstand mit der Basis des Transistors verbunden. Der Transistor steuert die Spule des Relais, indem er sie ein- und ausschaltet. Denken Sie daran, dass die Anschlüsse von links nach rechts C, B und E sind, wenn Sie auf die flache Seite des Transistors blicken. Das Ding auf der linken Seite der Steckplatine ist eine 12-Volt-Stromquelle für die Relaisspule. Der negative Pol oder die Masse der Stromquelle, der Emitteranschluss des Transistors und der GND-Anschluss des Arduino sind alle miteinander verbunden. Die 1N4004-Gleichrichterdiode schließlich ist bei über die Spule des Relais hinweg angeschlossen, wobei sich die Kathode an der positiven Seite der Stromquelle befindet. Um die Kontakte am Relais genau zu bestimmen und das zu steuernde Gerät richtig anzuschließen, ziehen Sie das Datenblatt des Relais zurate.

Die Diode dient zum Schutz der Schaltung. Wenn die Relaisspule ausgeschaltet wird, verbleiben Restladungen in ihr, die sich als Hochspannungsspitzen äußern können. Dank der Diode können sich diese Restladungen über die Spule entladen, wo sie als Wärme abgeleitet werden. Dadurch wird verhindert, dass die Abschaltspitze den Transistor oder den Arduino-Pin beschädigt.

WARNUNG

Wollen Sie Strom aus der Steckdose (220 Volt) mit hoher Stromstärke mithilfe eines Relais steuern, müssen Sie einen professionellen Elektriker zurate ziehen. Selbst der kleinste Fehler kann tödlich enden.

Ausblick

Damit sind wir am Ende von Kapitel 3 angelangt. Ich hoffe, Sie hatten Spaß damit, die Beispiele auszuprobieren und mit den LED-Effekten herumzuspielen. In diesem Kapitel haben Sie die Leuchtdioden auf dem Arduino auf verschiedene Weise zum Blinken gebracht, ein bisschen programmiert und dabei die Funktionen und Schleifen kennengelernt, mit denen Sie die an den Arduino angeschlossenen Bauteile steuern können. Die Lektüre dieses Kapitels bildet die Grundlage für das Verständnis der folgenden.

Auch in Kapitel 4 kommt der Spaß nicht zu kurz: Sie werden an praktischen Projekten arbeiten, nämlich einer Ampel, einem Thermometer und einem Batterieprüfgerät. Blättern Sie um!

4

Grundbausteine

In diesem Kapitel lernen Sie Folgendes:

• Lesen von Schaltplänen, der »Sprache« von elektronischen Schaltungen

• Grundlagen von Kondensatoren

• Arbeiten mit Eingangspins

• Verwenden von arithmetischen Operationen und Testwerten

• Entscheidungen mithilfe von if-then-else-Anweisungen

• Unterschied zwischen analog und digital

• Messen von analogen Spannungsquellen mit unterschiedlicher Genauigkeit

• Grundlagen von regelbaren Widerständen, piezoelektrischen Summern und Temperatursensoren

• Anwenden des Gelernten durch die Konstruktion einer Ampel, eines Batterieprüfgeräts und eines Thermometers

Der Stoff in diesem Kapitel hilft Ihnen, das wahre Potenzial des Arduino zu erkennen. Sie lernen noch mehr über Elektronik – über weitere Bauteile, über das Lesen von Schaltplänen (den »Landkarten« von elektronischen Schaltungen) und die Art der Signale, die Sie messen können. Außerdem sehen wir uns weitere Funktionen des Arduino an: das Speichern von Werten, die Durchführung mathematischer Operationen, das Fällen von Entscheidungen. Schließlich wenden Sie das Gelernte in praktischen Projekten an.

Schaltpläne

In Kapitel 3 haben wir den Aufbau der Schaltungen anhand von fotografischen Plänen erklärt, auf denen die Steckplatine und die darauf montierten Bauteile zu sehen waren. Das mag zwar wie die einfachste Möglichkeit aussehen, um eine Schaltung darzustellen, aber je mehr Komponenten Sie hinzufügen, umso unübersichtlicher wird dies. Da die Schaltungen, die wir im Folgenden aufbauen, schon etwas komplizierter sind, verwenden wir zu ihrer Darstellung ab jetzt Schaltpläne wie den aus Abbildung 4–1

Abb. 4–1 Beispiel eines Schaltplans

Schaltpläne sind einfache »Landkarten« elektronischer Schaltungen, die den Weg zeigen, den der Strom durch die einzelnen Bauteile nimmt. Anstelle fotografischer Darstellungen der Elemente und Drähte werden Symbole und Linien verwendet.

Symbole für die Bauteile

Wenn Sie wissen, was die einzelnen Symbole bedeuten, ist das Lesen eines Schaltplans ganz einfach. Als Erstes wollen wir uns die Symbole für die Bauteile ansehen, die wir bereits verwendet haben.

Der Arduino

Abbildung 4–2 zeigt das Symbol für den Arduino. Darin sind alle Anschlüsse eingezeichnet und beschriftet.

Abb. 4–2 Das Symbol für den Arduino Uno

Widerstände

Das Symbol für einen Widerstand sehen Sie in Abbildung 4–3.

Es ist sinnvoll, neben dem Symbol auch den Widerstandswert und die Bezeichnung des Bauteils anzugeben (in diesem Beispiel 220 Ω und R1). Das macht es leichter, dem Schaltplan zu folgen – sowohl für andere als auch für Sie selbst. Es kann vorkommen, dass Sie in Schaltplänen auch R statt Ω lesen, also beispielsweise eine Angabe wie 220 R.

Abb. 4–3 Das Symbol für einen Widerstand (oben die amerikanische Version, unten die in Deutschland übliche)

Gleichrichterdioden

Das Symbol für eine Gleichrichterdiode sehen Sie in Abbildung 4–4.

Abb. 4–4 Das Symbol für eine Gleichrichterdiode

Wie Sie in Kapitel 3 gelernt haben, sind Dioden gepolt: Der Strom fließt von der Anode zur Kathode. Auf dem Symbol in Abbildung 4–4 befindet sich die Anode links und die Kathode rechts. Das lässt sich leicht merken, indem Sie sich das Dreieck als eine Pfeilspitze vorstellen, die die Stromrichtung angibt. In die umgekehrte Richtung kann der Strom nicht fließen, da er von der senkrechten Linie »blockiert« wird.

Leuchtdioden

Das Symbol für eine LED sehen Sie in Abbildung 4–5.

Alle Arten von Dioden haben das gleiche Grundsymbol, das aus einem Dreieck und einer senkrechten Linie besteht. Bei LEDs sind jedoch zusätzlich zwei parallele Pfeile zu sehen, die von dem Dreieck wegzeigen. Damit wird das ausgestrahlte Licht symbolisiert.

Abb. 4–5 Das Symbol für eine Leuchtdiode

Transistoren

Das Symbol für einen Transistor sehen Sie in Abbildung 4–6.

Abb. 4–6 Das Symbol für einen Transistor

Die mit C beschriftete senkrechte Linie oben am Symbol steht für den Kollektor, die waagerechte Linie auf der linken Seite (B) für die Basis und die untere Linie (E) für den Emitter. Da der Pfeil innerhalb des Symbols nach unten rechts zeigt, haben wir es hier mit einem NPN-Transistor zu tun, bei dem der Strom vom Kollektor zum Emitter fließt. (Bei PNP-Transistoren läuft der Strom vom Emitter zum Kollektor.)

Bei der Durchnummerierung von Transistoren verwenden wir den Buchstaben Q (wie das R für Widerstände).

Relais

Das Symbol für ein Relais sehen Sie in Abbildung 4–7.

Abb. 4–7 Das Symbol für ein Relais

Relaissymbole gibt es in verschiedenen Formen und sie können auch mehr als einen Satz Kontakte aufweisen. Ihnen allen sind aber bestimmte Elemente gemeinsam, nämlich erstens die Spule, die als gewundene senkrechte Linie auf der linken Seite dargestellt wird, und zweitens die Kontakte. Der Kontakt COM (für common, also »allgemein« oder »gemeinsam«) dient meistens als Eingang, die Kontakte NO (normally open, »im Normalzustand geöffnet«) und NC (normally closed, »im Normalzustand geschlossen«) als Ausgänge.

Das Relaissymbol wird stets im ausgeschalteten Zustand gezeigt, in dem die Spule nicht bestromt ist. Damit sind die Anschlüsse COM und NC miteinander verbunden. Bei bestromter Spule sind COM und NO verbunden.

Leitungen in Schaltplänen

Sich kreuzende oder miteinander verbundene Drähte werden in Schaltplänen auf eine ganz bestimmte Weise gezeichnet, wie die folgenden Beispiele zeigen.

Nicht verbundene kreuzende Leitungen

Wenn sich zwei Leitungen kreuzen, aber nicht miteinander verbunden sind, wird dies auf die beiden in Abbildung 4–8 dargestellten Weisen dargestellt. Keine davon ist falsch, es handelt sich nur um verschiedene Varianten.

Abb. 4–8 Nicht verbundene kreuzende Leitungen

Verbundene Leitungen

Sind Leitungen physisch verbunden, wird der Kreuzungspunkt durch einen Verbindungspunkt gekennzeichnet, wie Sie in Abbildung 4–9 sehen.

Abb. 4–9 Zwei miteinander verbundene Leitungen

Masseanschluss

Ist eine Leitung mit Erde oder Masse verbunden (GND), wird dies mit dem Symbol aus Abbildung 4–10 ausgedrückt.

Wenn dieses Symbol in einem Schaltplan am Ende einer Linie steht, heißt dies, dass der Draht physisch an den GND-Pin des Arduino angeschlossen ist.

Abb. 4–10 Das GND-Symbol

Schaltpläne analysieren

Nachdem Sie jetzt die Symbole für die verschiedenen Bauteile und Verbindungen kennen, wollen wir uns den Schaltplan für Projekt 1 ansehen. Dabei ging es darum, fünf LEDs nacheinander vorwärts und rückwärts aufleuchten zu lassen.

Wenn Sie den Schaltplan aus Abbildung 4–11 mit der Darstellung in Abbildung 3–13 vergleichen, werden Sie mir wahrscheinlich zustimmen, dass der Schaltplan die übersichtlichere Form der Darstellung bildet.

Abb. 4–11 Schaltplan für Projekt 1

Von jetzt an werden wir den Aufbau von Schaltungen anhand solcher Schaltpläne beschreiben. Bei der Einführung weiterer Bauteile lernen Sie auch gleich die Symbole dafür kennen.

HINWEIS

Wenn Sie Schaltpläne am Computer erstellen möchten, probieren Sie dazu das Programm Fritzing aus, das Sie kostenlos auf http://www.fritzing.org/ erhalten.

Kondensatoren

Ein Kondensator ist ein Gerät, das eine elektrische Ladung speichert. Er besteht aus zwei Metallplatten mit einer Isolierschicht dazwischen, die es ermöglicht, dass sich zwischen den beiden Platten eine elektrische Ladung aufbaut. Fließt kein Strom mehr, verbleibt die Ladung dort und kann aus dem Kondensator austreten (man spricht hier vom Entladen des Kondensators), sobald ein neuer Weg eröffnet wird, den der Strom nehmen kann.

Die Kapazität von Kondensatoren

Die Kapazität eines Kondensators – also die Ladung, die er bei der anliegenden Spannung aufnehmen kann –, wird in Farad angegeben, wobei ein Farad (1 F) schon eine sehr große Menge ist. Daher wird die Kapazität von Kondensatoren meistens in Pico- oder Mikrofarad ausgedrückt. Ein Picofarad (pF) entspricht 0,000000000001 F, ein Mikrofarad (μF) 0,000001 F. Bei der Fertigung werden Kondensatoren auf eine bestimmte Maximalspannung ausgelegt. In diesem Buch arbeiten wir ausschließlich mit Kondensatoren für geringe Spannung, die nicht mehr als 10 V verkraften können. Es ist jedoch kein Problem, in Schaltungen niedriger Spannungen auch Kondensatoren zu verwenden, die für höhere Spannungen gedacht sind. Übliche Werte sind 10, 16, 25 und 50 V.

Kapazitätswerte ablesen

Den aufgedruckten Wert eines Keramikkondensators abzulesen, erfordert ein wenig Übung, da die Angabe gewissermaßen in einem Code vorliegt. Die ersten beiden Stellen stehen für einen Wert in Picofarad, die dritte gibt den Multiplikator in Vielfachen von Zehn an. Der Kondensator in Abbildung 4–12 beispielsweise ist mit 104 beschriftet. Das steht für eine Zehn, gefolgt von vier Nullen, also 100.000 pF. Dieser Wert kann auch als 100 nF (Nanofarad) oder 0,1 μF (Mikrofarad) ausgedrückt werden.

Abb. 4–12 Ein Keramikkondensator mit einer Kapazität von 0,1 μF

HINWEIS

Die Umrechnung zwischen den verschiedenen dezimalen Vielfachen kann etwas verwirrend sein. Auf http://www.justradios.com/uFnFpF.html finden Sie eine hervorragende Umrechnungstabelle, die Sie sich ausdrucken können.

Arten von Kondensatoren

In unseren Projekten verwenden wir zwei Typen von Kondensatoren: Keramik- und Elektrolytkondensatoren.

Keramikkondensatoren

Keramikkondensatoren wie der aus Abbildung 4–12 sind sehr klein und können daher nur wenig Ladung aufnehmen. Sie sind nicht gepolt und lassen sich daher in beiden Richtungen verwenden. Das Schaltplansymbol für nicht gepolte Kondensatoren sehen Sie in Abbildung 4–13. Keramikkondensatoren eignen sich sehr gut für Hochfrequenzschaltungen, da sie aufgrund ihrer geringen Kapazität schnell geladen und entladen werden können.

Abb. 4–13 Das Symbol für einen nicht gepolten Kondensator mit der Angabe der Kapazität oben rechts

Elektrolytkondensatoren

Elektrolytkondensatoren wie der aus Abbildung 4–14 haben eine größere Bauform als die Keramikvariante. Sie bieten eine höhere Kapazität, sind aber gepolt. Auf der Ummantelung ist entweder die positive oder die negative Seite markiert. In Abbildung 4–14 können Sie den Streifen mit dem Minussymbol erkennen, der die negative Seite kennzeichnet. Wie bei Widerständen müssen Sie auch bei den Werten von Kondensatoren mit einer gewissen Toleranz rechnen. Das Bauteil in Abbildung 4–14 hat eine Kapazität von 100 μF und eine Toleranz von 20 %.

Das Symbol für Elektrolytkondensatoren sehen Sie in Abbildung 4–15. Das Pluszeichen dient dazu, die Polung anzugeben.

Abb. 4–14 Elektrolytkondensator

Abb. 4–15 Symbol für einen gepolten Kondensator

Elektrolytkondensatoren werden oft verwendet, um größere elektrische Ladungen zu speichern und die Spannung von Stromquellen auszugleichen. Wie kleine Kurzzeitbatterien können sie in der Nähe von Schaltkreisen oder Bauteilen, die in kurzer Zeit hohe Stromstärken von der Quelle beziehen, für eine gleichmäßige Versorgung und für Stabilität sorgen. Das verhindert unerwartete Aussetzer und Rauschen in Schaltungen. Dankenswerterweise sind die Kapazitätswerte von Elektrolytkondensatoren in Klartext auf der Ummantelung aufgedruckt und erfordern keine Dekodierung oder Deutung.

Am Beispiel der LEDs haben Sie schon den grundlegenden Umgang mit den Ausgängen des Arduino kennengelernt. Jetzt ist es an der Zeit, Signale von außen an den Arduino zu senden und die Messwerte an den digitalen Eingängen für Entscheidungen heranzuziehen.

Digitale Eingänge

In Kapitel 3 haben wir die digitalen E/A-Pins als Ausgänge genutzt, um LEDs ein- und auszuschalten. Dieselben Anschlüsse lassen sich aber auch verwenden, um Eingangssignale zu registrieren, beispielsweise um zu erkennen, ob eine Drucktaste betätigt wurde.

Wie die Ausgänge können auch die digitalen Eingänge zwei Zustände aufweisen, high und low. Die einfachste Form eines digitalen Eingangssignals liefern Drucktasten wie die in Abbildung 4–16. Sie können sie unmittelbar in die Steckplatine einsetzen. Wird eine solche Taste gedrückt, kann eine Spannung oder ein Strom durchgehen. An den digitalen Eingangspins können Sie dann messen, ob eine Spannung anliegt, und somit bestimmen, ob die Taste gedrückt wurde.

Abb. 4–16 Einfache Drucktasten auf einer Steckplatine

Beachten Sie, wie die Taste unten in der Abbildung in die Steckplatine eingeführt ist und dabei die Zeilen 23 und 25 überbrückt. Bei Betätigung der Taste werden die beiden Reihen verbunden. Das Schaltplansymbol für diese Art von Drucktaste sehen Sie in Abbildung 4–17. Es zeigt die beiden Seiten der Taste. Wird die Taste gedrückt, werden die beiden Hälften verbunden, sodass Spannung bzw. Strom durchgelassen wird. Durchnummeriert werden Tasten mit dem Präfix S.

Abb. 4–17 Das Symbol für eine Drucktaste

KONTAKTPRELLEN MIT EINEM DIGITALEN SPEICHEROSZILLOSKOP SICHTBAR MACHEN

Drucktasten weisen ein besonderes Verhalten auf, das sogenannte Kontaktprellen oder kurz Prellen: Sie neigen dazu, mehrmals ein- und auszuschalten, wenn der Benutzer sie ein einziges Mal drückt. Die Metallkontakte im Inneren der Taste sind so winzig, dass sie nach der Freigabe der Taste vibrieren, weshalb es zu den schnellen Schaltvorgängen kommt.

Das Kontaktprellen können Sie mit einem digitalen Speicheroszilloskop sichtbar machen. Dieses Gerät zeigt Spannungsänderungen im Verlauf der Zeit an. In Abbildung 4–18 sehen Sie das Phänomen des Kontaktprellens auf einem solchen Messinstrument.

Abb. 4–18 Kontaktprellen messen

In der oberen Hälfte der Anzeige aus Abbildung 4–18 sehen Sie, was passiert, wenn die Taste mehrmals gedrückt wird. An den oberen Auslenkungen der Spannungskurve (bei 5 V) befindet sich die Taste im Zustand Ein, sodass die Spannung durchgeht. Unter dem Wort Stop in der Anzeige ist durch die beiden senkrechten Linien und den Pfeil die Stelle markiert, an der die Taste ausgeschaltet wurde. Der Verlauf der Spannung ist in der unteren Hälfte der Abbildung mit gestreckter Zeitachse dargestellt. An Punkt A lässt der Benutzer die Taste los, weshalb die Spannung auf 0 V sinkt. Aufgrund der Vibration der Kontakte steigt die Spannung wieder auf 5 V, bis Punkt B erreicht ist, wo der Kontakt zurückschwingt. Bei Punkt C kommen die Kontakte endlich zur Ruhe, sodass die Spannung auf 0 V fällt und endlich der Zustand low (also Aus) erreicht ist. Anstatt also das Signal für eine Tastenbetätigung an den Arduino zu senden, haben wir in diesem Fall unbeabsichtigt gleich drei geschickt.

Projekt Nr. 4: Beispiel für digitale Eingänge

Bei diesem Projekt besteht das Ziel darin, dass eine LED bei Betätigung einer Taste eine halbe Sekunde lang aufleuchtet.

Der Algorithmus

Unser Algorithmus sieht wie folgt aus:

1. Prüfe, ob die Taste gedrückt wurde.

2. Wenn die Taste gedrückt wurde, schalte die LED eine halbe Sekunde lang ein und dann wieder aus.

3. Wenn die Taste nicht gedrückt wurde, tue gar nichts.

4. Wiederhole den Vorgang unendlich oft.

Die Hardware

Für dieses Projekt brauchen Sie folgende Teile:

• eine Drucktaste

• eine LED

• einen 560-Ω-Widerstand

• einen 10-kΩ-Widerstand

• einen 100-nF-Kondensator

• Verbindungsdrähte

• eine Steckplatine

• Arduino und USB-Kabel

Der Schaltplan

Als Erstes bauen wir auf der Steckplatine den Schaltkreis nach dem Schaltplan aus Abbildung 4–19 auf. Beachten Sie, wie der 10-kΩ-Widerstand zwischen GND und Digitalpin 7 angeordnet ist. Es handelt sich hierbei um einen Pulldown-Widerstand, da er die Spannung an dem Digitalpunkt auf fast 0 V senkt (»herabzieht«). Durch den 100-nF-Kondensator, den der 10-kΩ-Widerstand überspannt, haben wir außerdem eine einfache Entprellschaltung gebaut, die das Kontaktprellen der Taste auszufiltern hilft. Wird die Taste gedrückt, geht das Signal am digitalen Pin sofort auf »high«. Beim Loslassen der Taste wird der Pin über den 10-kΩ-Widerstand auf GND-Niveau gesenkt, wobei der Kondensator für eine kleine Verzögerung sorgt. Da das Sinken der Spannung auf GND-Niveau verlangsamt wird, werden effektiv alle Prellpulse abgedeckt und dadurch die meisten Falschmessungen aufgrund schwankender Spannung und unvorhergesehenen Tastenverhaltens ausgeschlossen.

Abb. 4–19 Schaltplan für Projekt 4

Da dies das erste Mal ist, dass Sie eine Schaltung nach einem Schaltplan aufbauen, geben wir zusätzlich die folgende schrittweise Anleitung, mit deren Hilfe Sie genauer nachvollziehen können, wie die einzelnen Teile verbunden sind:

1. Bringen Sie die Drucktaste an der Steckplatine an, wie in Abbildung 4–20 gezeigt.

Abb. 4–20 Die Drucktaste auf der Steckplatine

2. Drehen Sie die Steckplatine um 90° gegen den Uhrzeigersinn und bauen Sie, wie in Abbildung 4–21 gezeigt, den 10-kΩ-Widerstand, einen kurzen Verbindungsdraht und den Kondensator ein.

Abb. 4–21 10-kΩ-Widerstand, Kondensator und Drucktaste

3. Verbinden Sie das Kabel vom 5-Volt-Anschluss des Arduino mit der linken vertikalen Reihe der Steckplatine und das Kabel vom GND-Pin des Arduino mit der vertikalen Reihe rechts daneben (siehe Abb. 4–22).

Abb. 4–22 Das 5-Volt-Kabel (rot) und das GND-Kabel (schwarz)

4. Führen Sie ein Kabel vom Digitalpin 7 des Arduino zur rechten oberen Ecke der Drucktaste auf der Steckplatine (siehe Abbildung 4–23).

Abb. 4–23 Die Drucktaste mit dem digitalen Eingang verbinden

Stecken Sie die LED mit dem kurzen Bein (der Kathode) in die GND-Zeile der Platine und mit dem langen Bein (Anode) in eine Reihe rechts daneben. Bauen Sie anschließend den 560-Ω-Widerstand rechts neben der LED ein (siehe Abbildung 4–24).

Abb. 4–24 Die LED und den 560-Ω-Widerstand einfügen

5. Führen Sie ein Kabel von der rechten Seite des 560-Ω-Widerstands zum Digitalpin 12 am Arduino (siehe Abb. 4–25).

Abb. 4–25 Den LED-Zweig mit dem Arduino verbinden

Bevor Sie weitermachen, schauen Sie sich noch einmal den Schaltplan an und prüfen, ob Sie die Bauteile korrekt verdrahtet haben. Vergleichen Sie den Plan mit der Schaltung auf der Platine.

Der Sketch

Als Sketch geben Sie den Code von Listing 4–1 ein und laden ihn hoch:

// Projekt 4 - Beispiel für digitale Eingänge
#define LED    12
#define BUTTON 7

void setup()
{
pinMode(LED, OUTPUT);          // Ausgang für die LED
pinMode(BUTTON, INPUT);        // Eingang für die Taste
}

void loop()
{
if ( digitalRead(BUTTON) == HIGH )
{
digitalWrite(LED, HIGH);   // Schaltet die LED ein
delay(500);                // Wartet 0,5 s
digitalWrite(LED, LOW);    // Schaltet die LED aus
}
}

Listing 4–1 Digitale Eingänge

Nachdem Sie den Sketch hochgeladen haben, tippen Sie kurz auf die Drucktaste. Die LED sollte jetzt eine halbe Sekunde lang aufleuchten.

Den Sketch ändern

Nach diesem Anfangserfolg versuchen Sie den Sketch zu ändern, indem Sie etwa die Zeit variieren, die die LED eingeschaltet bleibt, oder Projekt 3 eine Drucktastensteuerung hinzufügen. (Bauen Sie diese Schaltung jedoch noch nicht wieder auseinander, denn wir werden sie noch im nächsten Beispiel benötigen.)

Den Sketch analysieren

Als Nächstes sehen wir uns die neuen Elemente in dem Sketch von Projekt 4 detaillierter an – genauer gesagt, #define, die Befehle für die digitalen Eingangspins und die Funktion if-then.

Konstanten mit #define erstellen

Vor void setup() verwenden wir an der Stelle #define-Anweisungen, um feste Variablen zu erstellen. Wenn der Sketch kompiliert wird, ersetzt die IDE jedes Vorkommen des definierten Worts durch die darauf folgende Zahl. Beispielsweise erkennt die IDE bei LED und ersetzt dies durch die Zahl 12.

Im Grunde genommen verwenden wir den Befehl #define hier, um die Digitalpins für die LED und die Taste im Sketch mit Namen zu versehen. Beachten Sie, dass hinter der Wertangabe in #define kein Semikolon steht. Es ist eine gute Idee, Pinnummern und andere feste Werte (etwa eine zeitliche Verzögerung) auf diese Weise zu benennen, denn wenn sie in einem Sketch wiederholt vorkommen, müssen sie so bei einer Änderung nur an einer Stelle bearbeitet werden. In diesem Beispiel wird LED dreimal in dem Sketch verwendet. Um den Wert zu ändern, müssen wir lediglich einmal die Definition in der #define-Anweisung austauschen.

Digitale Eingangspins messen

Um den Status einer Drucktaste zu bestimmen, definieren wir zunächst in void setup() wie folgt einen digitalen E/A-Pin als Eingang:

pinMode(BUTTON, INPUT); // Eingang für die Taste

Um zu ermitteln, ob die Taste eine Spannung an den digitalen Eingang anlegt (ob sie also gedrückt ist), verwenden wir digitalRead(Pin), wobei Pin für die Nummer des abzulesenden Digitalpins steht. Die Funktion gibt entweder HIGH (die Spannung am Pin liegt bei 5 V) oder LOW zurück (die Spannung am Pin liegt bei 0 V).

Entscheidungen mit if

Mit if können wir in unserem Sketch Entscheidungen fällen und den Arduino anweisen, je nachdem, wie die Entscheidung ausgefallen ist, unterschiedlichen Code auszuführen. Beispielsweise haben wir in Projekt 4 den Code aus Listing 4–2 verwendet:

if ( digitalRead(BUTTON) == HIGH )
{
digitalWrite(LED, HIGH);    // Schaltet die LED ein
delay(500);                 // Wartet 0,5 s
digitalWrite(LED, LOW);     // Schaltet die LED aus
}

Listing 4–2 Ein einfaches Beispiel für eine if-then-Anweisung

Die erste Zeile in diesem Code beginnt mit if, um eine Bedingung zu prüfen. Ist die Bedingung wahr (ist die Spannung also HIGH), so bedeutet dies, dass die Taste gedrückt wurde, weshalb der Code in den geschweiften Klammern ausgeführt wird.

Um zu bestimmen, ob die Taste gedrückt worden ist (ob also digitalRead(BUTTON) auf HIGH gesetzt ist), verwenden wir einen Vergleichsoperator, ein doppeltes Gleichheitszeichen (==). Wenn wir in dem Sketch == durch !== (nicht gleich) ersetzen, wird die LED beim Drücken der Taste abgeschaltet. Probieren Sie es aus!

HINWEIS

Ein häufig gemachter Fehler besteht darin, in einer Testanweisung nur ein einzelnes Gleichheitszeiten (=) zu verwenden, was aber »mach dies gleich« bedeutet. Benötigt wird aber ein doppeltes Gleichheitszeichen (==) für »prüfe, ob es gleich ist«. Möglicherweise erhalten Sie bei diesem Versäumnis keine Fehlermeldung, aber die if-Anweisung funktioniert dann trotzdem nicht.

Mehr Entscheidungsmöglichkeiten mit if-then-else

Mit else können Sie einer if-Anweisung noch eine weitere Aktion hinzufügen. Wenn Sie den Code aus Listing 4–1 beispielsweise wie in Listing 4–3 mit zusätzlichem else umschreiben, wird die LED eingeschaltet, wenn (if) die Taste gedrückt wurde, anderenfalls (else) aber ausgeschaltet. Die Verwendung von else zwingt den Arduino dazu, einen anderen Codeausschnitt auszuführen, wenn die in der if-Anweisung geprüfte Bedingung nicht wahr ist.

#define LED    12
#define BUTTON 7

void setup()
{
pinMode(LED, OUTPUT);      // Ausgang für die LED
pinMode(BUTTON, INPUT);    // Eingang für die Taste
}

void loop()
{
if ( digitalRead(BUTTON) == HIGH )
{
digitalWrite(LED, HIGH);
}
else
{
digitalWrite(LED, LOW);
}
}

Listing 4–3 Ergänzung um else

Boolesche Variablen

Manchmal müssen Sie festhalten, ob sich irgendetwas in einem von zwei möglichen Zuständen befindet, etwa ein/aus oder heiß/kalt. Hierzu eignen sich boolesche Variablen, die legendären Computer-»Bits«, deren Wert nur 0 (falsch, false) oder 1 (wahr, true) sein kann. Daher sind boolesche Variablen so nützlich: Sie können nur entweder wahr oder falsch sein. Wie alle anderen Variablen müssen wir sie zunächst deklarieren, bevor wir sie verwenden können:

boolean raining = true;    // Erstellt die Variable "raining" und
// setzt sie auf true

Innerhalb des Sketches können Sie den Zustand der booleschen Variable dann durch eine einfache Neuzuweisung ändern:

raining = false;

Die Verwendung von booleschen Variablen zur Entscheidungsfindung erfolgt ganz einfach mithilfe einer if-Teststruktur. Da boolesche Vergleiche entweder wahr oder falsch ergeben, können dafür wie im folgenden Beispiel die Vergleichsoperatoren herangezogen werden:

if ( raining == true )
{
if ( summer != true )
{
// Es regnet, und es ist nicht Sommer
}
}

Logische Vergleichsoperatoren

Um Entscheidungen über zwei oder mehr boolesche Variablen oder andere Zustände zu treffen, können wir verschiedene Operatoren heranziehen. Dazu gehören not (!), and (&&) und or (||).

Not

Der Operator not wird durch ein Ausrufezeichen ausgedrückt und dient als Abkürzung, um zu prüfen, ob irgendetwas nicht wahr ist. Betrachten Sie dazu das folgende Beispiel:

if ( !raining )
{
// Es regnet nicht (raining == false)
}

And

Der logische Operator and wird durch && ausgedrückt. Er hilft die Anzahl einzelner if-Tests zu verringern. Betrachten Sie dazu das folgende Beispiel:

if (( raining == true ) && ( !summer ))
{
// Es regnet und es ist nicht Sommer
// (raining == true and summer == false)
}

Or

Der logische Operator or wird durch || ausgedrückt. Seine Verwendung ist ganz einfach. Betrachten Sie dazu das folgende Beispiel:

if (( raining == true ) || ( summer == true ))
{
// Es regnet oder es ist Sommer
}

Zwei und mehr Vergleiche

Sie können auch zwei oder mehr Vergleiche in ein und derselben if-Anweisung unterbringen, wie das folgende Beispiel zeigt:

if ( snow == true && rain == true && !hot )
{
// Es schneit, es regnet, und es ist nicht heiß
}

Die Operationsreihenfolge legen Sie mithilfe von Klammern fest. Im nächsten Beispiel wird zuerst der Vergleich in den Klammern verarbeitet und das Ergebnis, true oder false, dann mit dem Rest der if-then-Anweisung verglichen:

if (( snow == true || rain == true ) && hot == false))
{
// Es regnet oder schneit, und es ist nicht heiß
}

Ebenso wie in den Beispielen, in denen der not-Operator (!) unmittelbar vor einem Wert stand, können Sie auch einfache Tests auf true und false durchführen, ohne dabei jedes Mal ausdrücklich == true oder == false schreiben zu müssen. Der folgende Code funktioniert genauso wie das vorhergehende Beispiel:

if (( snow || rain ) && !hot )
{
// Es regnet oder schneit, und es ist nicht heiß
// ( snow is true OR rain is true ) AND it is not hot
}

Wie Sie sehen, kann der Arduino mithilfe von booleschen Variablen und Vergleichsoperatoren eine Menge von Entscheidungen treffen. Wenn Sie zu komplizierteren Projekten übergehen, wird sich diese Möglichkeit als äußerst nützlich erweisen.

Projekt Nr. 5: Eine Verkehrsampel

Wir wollen unsere neuen Kenntnisse jetzt zur Lösung eines hypothetischen Problems einsetzen. Stellen Sie sich vor, Sie sind Stadtplaner in einer ländlichen Gegend und haben ein Problem mit einer einspurigen Brücke über einen Fluss: Dort kommt es jede Woche zu ein oder zwei nächtlichen Unfällen, wenn übermüdete Fahrer über die Brücke rasen, ohne erst anzuhalten und nachzusehen, ob der Weg frei ist. Sie haben schon angeregt, Ampeln zu installieren, aber der Bürgermeister möchte erst eine Vorführung sehen, bevor er das Budget für die Anschaffung der Ampeln absegnet. Nun könnten Sie zwar eine mobile Ampelanlage leihen, aber das wäre zu teuer. Stattdessen bauen Sie mithilfe von LEDs und einem Arduino ein Modell der Brücke mit funktionierenden Ampeln.

Das Ziel

Das Ziel besteht darin, an jedem Ende der einspurigen Brücke eine Dreifarben-Verkehrsampel aufzustellen, sodass der Verkehr immer nur in eine Richtung auf einmal fließen kann. Wenn Sensoren an einem Ende der Brücke erkennen, dass dort ein Auto an einer roten Ampel wartet, springen die Ampeln um, sodass der Verkehr in die entgegengesetzte Richtung fließen kann.

Der Algorithmus

Um die Fahrzeugsensoren an den beiden Enden der Brücke zu simulieren, verwenden wir zwei Drucktasten. Jede Ampel verfügt über eine rote, eine gelbe und eine grüne LED. Zu Anfang soll das System den Verkehr von Westen nach Osten durchlassen, sodass die westliche Ampel Grün zeigt und die östliche Rot.

Wenn sich ein Fahrzeug der Brücke nähert (was wir durch Drücken der Taste simulieren) und die Ampel rot ist, schaltet das System die Ampel auf der gegenüberliegenden Seite von Grün über Gelb auf Rot um und wartet dann einen zuvor festgelegten Zeitraum, damit Fahrzeuge, die sich schon auf der Brücke befinden, noch passieren können. Dann blinkt das gelbe Licht auf der Seite des wartenden Fahrzeugs, um dem Fahrer das Signal zu geben, sich fertig zu machen, und schließlich schaltet die Ampel auf Grün. Sie bleibt grün, bis sich ein Fahrzeug der anderen Seite nähert und sich der Vorgang wiederholt.

Die Hardware

Für dieses Projekt brauchen Sie folgende Teile:

• zwei rote LEDs (LED1 und LED2)

• zwei gelbe LEDs (LED3 und LED4)

• zwei grüne LEDs (LED5 und LED6)

• sechs 560-Ω-Widerstände (R1 bis R6)

• zwei 10-kΩ-Widerstände (R7 und R8)

• zwei 100-nF-Kondensatoren (C1 und C2)

• zwei Drucktasten (S1 und S2)

• eine mittelgroße Steckplatine

• Verbindungsdrähte

• Arduino und USB-Kabel

Der Schaltplan

Da wir nur sechs LEDs steuern und Eingangssignale von zwei Drucktasten empfangen, ist der Aufbau nicht allzu kompliziert. Abbildung 4–26 zeigt den Schaltplan für dieses Projekt.

Abb. 4–26 Schaltplan für Projekt 5

Im Grunde genommen handelt es sich bei dieser Schaltung um eine erweiterte Version des Drucktasten- und LED-Aufbaus von Projekt 4 mit mehr Widerständen, mehr LEDs und einer weiteren Taste.

Achten Sie darauf, die LEDs in der richtigen Richtung einzubauen: Die Anoden müssen mit den Widerständen verbunden sein, die Kathoden mit dem GND-Pin des Arduino (siehe Abb. 4–27).

Abb. 4–27 Die vollständige Schaltung

Der Sketch

Kommen wir jetzt zum Sketch. Können Sie erkennen, wie er den Algorithmus umsetzt?

// Projekt 5 - Eine Verkehrsampel
// Definiert die Pins, mit denen die Tasten und LEDs verbunden sind:
#define westButton 3
#define eastButton 13
#define westRed 2
#define westYellow 1
#define westGreen 0
#define eastRed 12
#define eastYellow 11
#define eastGreen 10
#define yellowBlinkTime 500   // Lässt die gelbe LED 0,5 s blinken

boolean trafficWest = true;   // West = true, Ost = false
int     flowTime = 10000;     // Zeitraum, in dem der Verkehr fließt
int     changeDelay = 2000;   // Zeitraum zwischen Farbwechseln

void setup()
{
// Richtet die digitalen E/A-Pins ein
pinMode(westButton, INPUT);
pinMode(eastButton, INPUT);
pinMode(westRed, OUTPUT);
pinMode(westYellow, OUTPUT);
pinMode(westGreen, OUTPUT);
pinMode(eastRed, OUTPUT);
pinMode(eastYellow, OUTPUT);
pinMode(eastGreen, OUTPUT);

// Legt den Anfangszustand der LEDs fest, im Westen zuerst grün
digitalWrite(westRed, LOW);
digitalWrite(westYellow, LOW);
digitalWrite(westGreen, HIGH);
digitalWrite(eastRed, HIGH);
digitalWrite(eastYellow, LOW);
digitalWrite(eastGreen, LOW);
}

void loop()
{
if ( digitalRead(westButton) == HIGH )   // Fordert Verkehrsfluss
// von West nach Ost an
{
if ( trafficWest != true )
// Fährt nur fort, wenn der Verkehr
// in die entgegengesetzte Richtung fließt (Osten)
{
trafficWest = true; // Ändert Verkehrsflussflag von West nach Ost
delay(flowTime); // Räumt Zeit für den Verkehr ein
digitalWrite(eastGreen, LOW);   // Schaltet die Ostampel
// von Grün über Gelb auf Rot
digitalWrite(eastYellow, HIGH);
delay(changeDelay);
digitalWrite(eastYellow, LOW);
digitalWrite(eastRed, HIGH);
delay(changeDelay);
for ( int a = 0; a < 5; a++ ) // Gelbe LED blinkt
{
digitalWrite(westYellow, LOW);
delay(yellowBlinkTime);
digitalWrite(westYellow, HIGH);
delay(yellowBlinkTime);
}
digitalWrite(westYellow, LOW);
digitalWrite(westRed, LOW); // Schaltet Westampel von Rot auf Grün
digitalWrite(westGreen, HIGH);
}
}
if ( digitalRead(eastButton) == HIGH )   // Fordert Verkehrsfluss
// von Ost nach West an

{
if ( trafficWest == true )
// Fährt nur fort, wenn der Verkehr in die entgegengesetzte
// Richtung fließt (Westen)
{
trafficWest = false; // Ändert Verkehrsflussflag von West nach Ost
delay(flowTime); // Räumt Zeit für den Verkehr ein
digitalWrite(westGreen, LOW);
// Schaltet die Ostampel von Grün über Gelb auf Rot
digitalWrite(westYellow, HIGH);
delay(changeDelay);
digitalWrite(westYellow, LOW);
digitalWrite(westRed, HIGH);
delay(changeDelay);
for ( int a = 0 ; a < 5 ; a++ )   // Gelbe LED blinkt
{
digitalWrite(eastYellow, LOW);
delay(yellowBlinkTime);
digitalWrite(eastYellow, HIGH);
delay(yellowBlinkTime);
}

digitalWrite(eastYellow, LOW);
digitalWrite(eastRed, LOW); // Schaltet Westampel von Rot auf Grün
digitalWrite(eastGreen, HIGH);
}
}
}

Unser Sketch beginnt bei mit #define, um die Nummern der digitalen Pins für die LEDs und die beiden Drucktasten mit Bezeichnungen zu versehen. Für die West- und die Ostseite der Brücke gibt es jeweils eine rote, eine gelbe und eine grüne LED sowie eine Taste. Mit der bei definierten booleschen Variable trafficWest halten wir fest, in welche Richtung der Verkehr fließt – bei true von Westen nach Osten, bei false von Osten nach Westen.

HINWEIS

Beachten Sie, dass wir die Verkehrsrichtung mit einer einzigen Variable festhalten (trafficWest), die entweder true oder false ist. Diese Vorgehensweise anstatt der Verwendung von zwei Variablen (eine für Verkehr Richtung Osten, die andere für Verkehr Richtung Westen) bietet den Vorteil, dass nicht versehentlich beide Richtungen wahr sein können. Das hilft uns, Zusammenstöße zu vermeiden!

Die bei definierte Integervariable flowTime gibt an, wie viel Zeit die Fahrzeuge mindestens haben, um die Brücke zu überqueren. Wenn ein Fahrzeug an einer roten Ampel zum Stehen kommt, wartet das System diesen Zeitraum ab, um dem entgegenkommenden Verkehr die Gelegenheit zu geben, über die Brücke zu fahren. Die bei definierte Integervariable changeDelay enthält den Zeitraum, den die Ampeln brauchen, um von Grün über Geld auf Rot umzuschalten.

Bevor der Sketch in den Abschnitt von void loop() eintritt, wird er in void setup() für die Verkehrsrichtung von West nach Ost eingerichtet.

Den Sketch ausführen

Wenn der Sketch läuft, tut er zunächst nichts, bis eine der Tasten gedrückt wird. Handelt es sich dabei um die Osttaste, sorgt die folgende Zeile dafür, dass die Ampeln nur dann umgeschaltet werden, wenn der Verkehr in die entgegengesetzte Richtung fließt:

if ( trafficWest == true )

Der Rest dieses Codeabschnitts besteht aus einer einfachen Abfolge von Wartevorgängen und Ein-/Aus-Schaltbefehlen für die einzelnen LEDs, um den Betrieb von Verkehrsampeln zu simulieren.

Analoge und digitale Signale

In diesem Abschnitt lernen Sie den Unterschied zwischen analogen und digitalen Signalen kennen und erfahren, wie Sie analoge Signale an den analogen Eingangspins messen.

Bis jetzt haben wir in unseren Sketchen nur digitale elektrische Signale verwendet, die ausschließlich zwei diskrete Pegel annehmen können: Wir haben mit digitalWrite(pin, HIGH) und digitalWrite(pin, LOW) eine LED zum Blinken gebracht und mit digitalRead() gemessen, ob an einem Digitalpin eine Spannung anliegt (HIGH) oder nicht (LOW). Abbildung 4–28 zeigt den Verlauf eines digitalen Signals, das abrupt zwischen hohem und niedrigem Pegel wechselt.

Abb. 4–28 Ein digitales Signal, wobei die beiden möglichen Pegel in Form von horizontalen Linien dargestellt werden, HIGH oben und LOW unten

Im Gegensatz zu den digitalen Signalen können die analogen unendlich viele Werte zwischen hohem und niedrigem Pegel annehmen. In Abbildung 4–29 sehen Sie als Beispiel ein analoges Signal in Form einer Sinuskurve. Im Verlauf der Zeit wechselt der Spannungspegel fließend zwischen hoch und niedrig.

Abb. 4–29 Ein analoges Signal in Form einer Sinuskurve

Beim Arduino liegt der hohe Pegel näher an 5 V und der niedrige näher an 0 V oder GND. Die Spannungswerte von analogen Signalen können wir am Arduino an den sechs analogen Eingangspins messen, die Sie in Abbildung 4–30 sehen. Dies ist gefahrlos im Bereich zwischen 0 V (GND) und maximal 5 V möglich.

Abb. 4–30 Die analogen Eingangspins am Arduino Uno

Wenn Sie die Funktion analogRead() verwenden, gibt der Arduino proportional zu der an dem abgefragten Analogpin anliegenden Spannung eine Zahl zwischen 0 und 1023 zurück. Im folgenden Beispiel sehen Sie, wie Sie mit analogRead() den Wert des Analogpins 0 in der Integervariable a speichern:

a = analogRead(0);   // Liest den analogen Eingangspin 0 (A0)
// Gibt einen Wert zwischen 0 und 1023 zurück,
// was gewöhnlich 0,000 bis 4,995 V entspricht

Projekt Nr. 6: Ein Testgerät für Einzelzellenbatterien

Verbreitung und Verwendung der klassischen Batterien sind zwar zurückgegangen, aber in den meisten Haushalten gibt es immer noch einige Geräte, in denen AA-, AAA-, C- oder D-Zellen zum Einsatz kommen, z. B. für Fernbedienungen, Wanduhren oder Kinderspielzeuge. Die Spannung solcher Batterien liegt weit unter 5 V, weshalb wir sie mit unserem Arduino messen können, um den Zustand der Batterie zu ermitteln. In diesem Projekt bauen wir ein Batterietestgerät.

Das Ziel

Einzelzellenbatterien wie AA-Zellen haben im Neuzustand gewöhnlich eine Spannung von 1,6 V, die im Verlauf der Nutzungsdauer abnimmt. Wir wollen die Spannung messen und den Zustand der Batterie optisch über LEDs anzeigen. Dazu rechnen wir das Messergebnis von analogRead() in Volt um. Die höchste Spannung, die wir messen können, beträgt 5 V, weshalb wir 5 durch 1024 dividieren (die Anzahl der möglichen Werte), was 0,0048 ergibt. Wenn analogRead() beispielsweise 512 zurückgibt, müssen wir diesen Wert mit 0,0048 multiplizieren, wodurch wir auf 2,4576 V kommen.

Der Algorithmus

Der Algorithmus für unseren Batterienprüfer sieht wie folgt aus:

1. Lies von Analogpin 0.

2. Multipliziere den Messwert mit 0,0048, um den Spannungswert in Volt zu erhalten.

3. Ist die Spannung größer oder gleich 1,6 V, dann schalte kurz die grüne LED ein.

4. Ist die Spannung größer als 1,4 V und kleiner als 1,6 V, dann schalte kurz die gelbe LED ein.

5. Ist die Spannung kleiner als 1,4 V, dann schalte kurz die rote LED ein.

6. Wiederhole den Vorgang unendlich oft.

Die Hardware

Für dieses Projekt benötigen Sie folgende Teile:

• drei 560-Ω-Widerstände (R1 bis R3)

• einen 2,2-kΩ-Widerstand (R4)

• eine grüne LED (LED1)

• eine gelbe LED (LED2)

• eine rote LED (LED3)

• eine Steckplatine

• Verbindungsdrähte

• Arduino und USB-Kabel

Der Schaltplan

Den Schaltplan für den Einzelzellenprüfer sehen Sie in Abbildung 4–31. Beachten Sie die beiden mit + und - bezeichneten Anschlusspunkte auf der linken Seite. Verbinden Sie sie mit dem gleichnamigen Pol der zu prüfenden Batterie, also Plus mit Plus und Minus mit Minus.

WARNUNG

Versuchen Sie auf keinen Fall, einen Wert von mehr als 5 V zu messen. Vertauschen Sie auch nicht die Pole! Dadurch beschädigen Sie den Arduino.

Abb. 4–31 Schaltplan für Projekt 5

Der Sketch

Und hier der Sketch:

// Projekt 6: Ein Testgerät für Einzelzellenbatterien
#define newLED 2     // Grüne LED "neu"
#define okLED 4      // Gelbe LED "ok"
#define oldLED 6     // Rote LED "alt"

int analogValue = 0;
float voltage = 0;
int ledDelay = 2000;

void setup()
{
pinMode(newLED, OUTPUT);
pinMode(okLED, OUTPUT);
pinMode(oldLED, OUTPUT);
}

void loop()
{
analogValue = analogRead(0);
voltage = 0.0048*analogValue;
if ( voltage >= 1.6 )
{
digitalWrite(newLED, HIGH);
delay(ledDelay);
digitalWrite(newLED, LOW);
}
else if ( voltage < 1.6 && voltage > 1.4 )
{
digitalWrite(okLED, HIGH);
delay(ledDelay);
digitalWrite(okLED, LOW);
}
else if ( voltage <= 1.4 )
{
digitalWrite(oldLED, HIGH);
delay(ledDelay);
digitalWrite(oldLED, LOW);
}
}

In dem Sketch für Projekt 6 liest der Arduino bei den Wert von Analogpin 0 und wandelt ihn bei in einen Spannungswert um. Was es mit dem neuen Variablentyp float auf sich hat, der bei auftritt, erfahren Sie im nächsten Abschnitt. In dem Sketch sehen Sie einige bereits vertraute Dinge wie die if-else-Funktionen, aber auch Neues wie Berechnungen und Vergleichsoperatoren für Zahlenwerte. All dies besprechen wir ebenfalls im nächsten Abschnitt.

Rechnen mit dem Arduino

Wie ein Taschenrechner kann der Arduino arithmetische Operationen wie Multiplikation, Division, Addition und Subtraktion durchführen:

a = 100;
b = a + 20;
c = b - 200;
d = c + 80;   // d ist gleich 0

Fließkommavariablen

Für Zahlen mit Dezimalstellen können Sie den Variablentyp float verwenden. Damit ist es möglich, Zahlen zwischen 3,4028235 × 10^38 und –3,4028235 × 10^38 zu speichern. Die Genauigkeit ist gewöhnlich auf sechs bis sieben Dezimalstellen beschränkt. In Berechnungen können Sie ganze Zahlen (Integer) und Fließkommazahlen (float) mischen. Im folgenden Beispiel wird erst die Fließkommazahl f zum Integer a addiert und das Ergebnis dann in der float-Variable g gespeichert:

int a = 100;
float f;
float g;

f = a / 3; // f = 33.333333
g = a + f; // g = 133.333333

Vergleichsoperatoren für Berechnungen

Für die if-Anweisungen und digitalen Eingangssignale in Projekt 5 haben wir Vergleichsoperatoren wie == und != verwendet. Daneben gibt es auch noch folgende Operatoren zum Vergleich von Zahlen und numerischen Variablen:

<

kleiner als

>

größer als

<=

kleiner oder gleich

>=

größer oder gleich

Diese Operatoren haben wir im Sketch von Projekt 6 zum Vergleich von Zahlenwerten in den Zeilen , und verwendet.

Die Genauigkeit der Analogmessung durch eine Bezugsspannung verbessern

Wie Sie in Projekt 6 gesehen haben, gibt die Funktion analogRead() einen Wert zurück, der proportional zur Spannung zwischen 0 V und 5 V ist. Der obere Wert (5 V) ist die Bezugsspannung, also die höchste Spannung, die der analoge Eingang des Arduino akzeptiert und für die er den höchsten Wert (1023) zurückgibt.

Um die Genauigkeit bei der Messung niedrigerer Spannungen zu erhöhen, können Sie eine geringere Bezugsspannung verwenden. Beträgt die Bezugsspannung 5 V, so stellt analogRead() mit den Werten zwischen 0 und 1023 den gesamten Bereich bis 5 V dar. Wollen wir aber nur Spannungen mit maximal 2 V messen, können wir die Ausgabe des Arduino so ändern, dass nur der Bereich bis 2 V durch die Werte von 0 bis 1023 wiedergegeben wird, was eine genauere Messung ermöglicht. Dazu können Sie sowohl eine externe als auch eine interne Bezugsspannung heranziehen, wie Sie im folgenden Abschnitt erfahren.

Externe Bezugsspannung

Die erste Methode, um eine Bezugs- oder Referenzspannung vorzugeben, bietet der Pin AREF (für analoge Referenz), den Sie in Abbildung 4–32 sehen.

Abb. 4–32 Der AREF-Pin auf dem Arduino Uno

Um eine neue Bezugsspannung einzuführen, verbinden Sie die Spannungsquelle mit dem AREF-Pin und den zugehörigen GND-Anschluss mit GND auf dem Arduino. Beachten Sie, dass Sie damit nur eine niedrigere und keine höhere Bezugsspannung festlegen können, da eine am Arduino Uno angelegte Spannung nicht höher sein darf als 5 V. Eine einfache Möglichkeit, um eine niedrigere Bezugsspannung einzurichten, besteht darin, aus zwei Widerständen einen Spannungsteiler zu bauen, wie Sie in Abbildung 4–33 sehen.

Abb. 4–33 Spannungsteiler

Die Werte R1 und R2 bestimmen die Bezugsspannung nach folgender Formel:

Dabei ist Vout die Bezugsspannung und Vin die Eingangsspannung, in diesem Fall also 5 V. R1 und R2 sind die Widerstandswerte in Ohm.

Die einfachste Möglichkeit besteht darin, Vin zu halbieren, indem Sie R1 und R2 auf denselben Wert setzen, z. B. je 10 kΩ. Dabei sollen Sie Widerstände mit möglichst geringer Toleranz verwenden, z. B. 1 %. Messen Sie die tatsächlichen Widerstandswerte mit einem Multimeter und verwenden Sie diese Werte in den Berechnungen. Außerdem ist es sinnvoll, zwischen AREF und GND einen 100-nF-Kondensator einzubauen, um ein Rauschen am AREF und instabile analoge Messungen zu verhindern.

Bei der Verwendung einer externen Bezugsspannung müssen Sie in den Abschnitt void setup() im Sketch folgende Zeile einfügen:

analogReference(EXTERNAL); // Wählt den AREF-Pin als Bezugsspannung aus

Interne Bezugsspannung

Der Arduino Uno verfügt auch über eine interne 1,1-Volt-Bezugsspannung. Wenn das für Ihren Bedarf geeignet ist, brauchen Sie keine zusätzliche Hardware. Fügen Sie einfach folgende Zeile zu void setup() hinzu:

analogReference(INTERNAL);   // Wählt die interne
// 1,1-Volt-Bezugsspannung aus

Regelbare Widerstände

Regelbare Widerstände oder Potenziometer (»Poti«) können im Allgemeinen von 0 Ω bis zum Nennwert eingestellt werden. Das Schaltplansymbol sehen Sie in Abbildung 4–34.

Abb. 4–34 Schaltplansymbol für einen regelbaren Widerstand (Potenziometer)

Bei einem regelbaren Widerstand finden Sie drei Kontaktstifte: einen in der Mitte und zwei an den Seiten. Wenn Sie die Mittelachse drehen, wird der Widerstand zwischen der einen Seite und der Mitte erhöht und der Widerstand zwischen der Mitte und der anderen Seite verringert.

Es gibt linear und logarithmisch regelbare Widerstände. Bei den linearen Modellen ändern sich der Widerstandswert beim Drehen mit konstanter Rate, bei den logarithmischen erst langsam und dann immer schneller. In Audioverstärkerschaltkreisen werden meistens logarithmische Potenziometer verwendet, da sie den Verlauf des menschlichen Hörvermögens nachbilden. Dagegen kommen in Arduino-Projekten eher linear regelbare Widerstände wie der aus Abbildung 4–35 zum Einsatz.

Abb. 4–35 Ein typischer linear regelbarer Widerstand

Es gibt auch Miniaturversionen von regelbaren Widerständen, sogenannte Trimmpotenziometer oder Trimmer (siehe Abb. 4–36). Aufgrund ihrer Größe sind sie vor allem für die Widerstandsregelung in »richtigen« Schaltkreisen sehr nützlich. Da sie eingesteckt werden können, eignen sie sich aber auch für die Arbeit auf der Steckplatine.

Abb. 4–36 Verschiedene Modelle von Trimmpotenziometern

HINWEIS

Schauen Sie sich die verschiedenen Modelle genau an, wenn Sie Trimmpotenziometer kaufen. Wahrscheinlich sind für Ihre Zwecke die Varianten geeignet, die sich mit einem handelsüblichen Schraubendreher einstellen lassen. Außerdem sind die in Abbildung 4–36 gezeigten geschlossenen Typen haltbarer als die billigen Versionen mit offenen Kontakten.

Piezoelektrische Summer

Ein piezoelektrischer Summer ist ein kleines rundes Bauteil, mit dem Sie laute und nervtötende Töne erzeugen können – ideal für Alarmanlagen oder um Spaß zu haben. Abbildung 4–37 zeigt ein typisches Beispiel, den TDK PS1240, neben einer Münze, um Ihnen einen Eindruck von der Größe zu geben.

Im Gehäuse eines Piezosummers befindet sich ein sehr dünnes Plättchen, das sich beim Anlegen eines elektrischen Stroms bewegt. Bei Wechselstrom (ein ... aus ... ein ... aus ...) vibriert das Plättchen, was Schallwellen erzeugt.

Abb. 4–37 Der Piezosummer TDK PS1240

Da sich Piezosummer wie LEDs ein- und ausschalten lassen, können Sie sie auf ganz einfache Weise in Arduino-Projekten verwenden. Diese Elemente sind nicht gepolt, sondern können in beliebiger Richtung eingebaut werden.

Das Schaltplansymbol

Das Schaltplansymbol für einen Piezosummer sieht wie ein Lautsprecher aus (siehe Abb. 4–38), was es sehr leicht erkennbar macht.

Abb. 4–38 Das Schaltplansymbol für einen Piezosummer

HINWEIS

Beim Einkauf der Piezosummer für dieses Projekt müssen Sie darauf achten, dass Sie einen Typ erwischen, der nur aus dem Piezoelement besteht. Es gibt auch Modelle, die zwar so aussehen wie das Bauteil in Abbildung 4–38, aber über einen Tonsteuerungsschaltkreis im Gehäuse verfügen. Da wir den Ton direkt vom Arduino aus steuern wollen, können wir diesen Summertyp nicht gebrauchen.

Projekt Nr. 7: Einen Piezosummer ausprobieren

Wenn Sie einen Piezosummer zur Hand haben und ausprobieren wollen, laden Sie den folgenden Sketch auf Ihren Arduino hoch:

// Projekt 7: Einen Piezosummer ausprobieren
#define PIEZO 3   // Pin 3 ist PBM-fähig und eignet sich
// für die Tonsteuerung
int del = 500;

void setup()
{
pinMode(PIEZO, OUTPUT);
}

void loop()
{
analogWrite(PIEZO, 128);   // Tastverhältnis 50%
delay(del);
digitalWrite(PIEZO, LOW);  // Schaltet den Piezosummer aus
delay(del);
}

In diesem Sketch nutzen wir eine Pulsbreitenmodulation am Digitalpin 3. Um die Lautstärke zu ändern, geben Sie bei ein anderes Tastverhältnis in der Funktion analogWrite() an (zurzeit steht es auf 128, also 50 %).

Wollen Sie die Maximallautstärke des Summers erhöhen, müssen Sie eine höhere Spannung anlegen. Sie ist zurzeit auf 5 V beschränkt, aber bei 9 V oder 12 V ist der Summer viel lauter. Da Sie höhere Spannungen nicht vom Arduino beziehen können, brauchen Sie eine externe Stromquelle für den Summer, etwa eine 9-Volt-Batterie, und müssen einen Transistor als elektronischen Schalter verwenden, um die Versorgung des Summers zu regeln. Die erforderliche Schaltung dafür sehen Sie in Abbildung 4–39. Den Sketch für dieses Projekt müssen Sie dazu nicht verändern.

Der mit 12 V beschriftete Teil des Schaltplans stellt den Pluspol der externen Spannungsquelle dar. Den Minuspol müssen Sie mit dem GND-Pin des Arduino verbinden.

Abb. 4–39 Schaltplan für Projekt 7

Projekt Nr. 8: Ein Thermometer mit Ampelanzeige

Temperatur kann durch ein analoges Signal dargestellt werden. Zur Messung verwenden wir den Temperatursensor TMP36 mit Spannungsausgang von Analog Devices (http://www.analog.com/tmp36/), den Sie in Abbildung 4–40 sehen.

Abb. 4–40 Der Temperatursensor TMP36

Der TMP36 sieht so aus wie der Transistor BC548, den wir schon in der Relaissteuerschaltung von Kapitel 3 verwendet haben. Er gibt eine Spannung proportional zur Temperatur aus, sodass Sie mit einer einfachen Berechnung die vorliegende Temperatur bestimmen können. Beispielsweise beträgt die Ausgangsspannung bei 25 °C 750 mV. Jede Temperaturänderung um 1 °C führt zu einer Spannungsänderung von 10 mV. Der TMP36 kann Temperaturen zwischen –40 °C und +125 °C messen.

Die Funktion analogRead() gibt einen Wert zwischen 0 und 1023 zurück, der einer Spannung zwischen 0 mV und knapp unter 5000 mV (5 V) entspricht. Wenn Sie den Rückgabewert von analogRead() mit 5000/1024 multiplizieren, erhalten Sie den vom Sensor ausgegebenen Spannungswert. Anschließend subtrahieren wir davon 500 (dies ist ein Versatz, den der TMP36 nutzt, um auch Temperaturen unter null angeben zu können) und teilen das Ergebnis durch zehn, wodurch wir die Temperatur in Grad Celsius bekommen. (Wenn Sie mit Fahrenheit arbeiten wollen, multiplizieren Sie den Celsius-Wert mit 1,8 und addieren 32 zum Ergebnis.)

Das Ziel

In diesem Projekt bauen wir auf der Grundlage des TMP36 ein Thermometer mit Ampelanzeige. Bei Temperaturen unter 20 °C soll eine blaue LED aufleuchten, zwischen 20 und 26 °C eine grüne und über 26 °C eine rote.

Die Hardware

Für dieses Projekt brauchen Sie folgende Teile:

• drei 560-Ω-Widerstände (R1 bis R3)

• eine rote LED (LED1)

• eine grüne LED (LED2)

• eine blaue LED (LED3)

• einen Temperatursensor TMP36

• eine Steckplatine

• Verbindungsdrähte

• Arduino und USB-Kabel

Der Schaltplan

Der Aufbau der Schaltung ist einfach. Wenn Sie auf die beschriftete Seite des TMP36 blicken, gehört der linke Anschluss an den 5-Volt-Ausgang, der mittlere (der Spannungsausgang) an den Analogeingang und der rechte an GND (siehe Abb. 4–41).

Abb. 4–41 Schaltplan für Projekt 7

Der Sketch

Hier sehen Sie den Sketch:

// Projekt 8: Ein Thermometer mit Ampelanzeige

// Definiert die Pins, mit denen die LEDs verbunden sind:
#define HOT 6
#define NORMAL 4
#define COLD 2

float voltage = 0;
float celsius = 0;
float hotTemp = 26;
float coldTemp = 20;
float sensor = 0;

void setup()
{
pinMode(HOT, OUTPUT);
pinMode(NORMAL, OUTPUT);
pinMode(COLD, OUTPUT);
}

void loop()
{
// Liest den Temperatursensor ab und rechnet das Ergebnis
// in Celsiuswerte um
sensor = analogRead(0);
voltage = (sensor*5000)/1024;    // Rechnet Sensorrohwert in mV um
voltage = voltage-500;           // Entfernt Versatz
celsius = voltage/10;            // Rechnet mV- in Celsiuswert um

// Reagiert je nach Temperaturbereich
if ( celsius < coldTemp )
{
digitalWrite(COLD, HIGH);
delay(1000);
digitalWrite(COLD, LOW);
}
else if ( celsius > coldTemp && celsius <= hotTemp )
{
digitalWrite(NORMAL, HIGH);
delay(1000);
digitalWrite(NORMAL, LOW);
}
else
{
// Temperatur ist > hotTemp
digitalWrite(HOT, HIGH);
delay(1000);
digitalWrite(HOT, LOW);
}
}

In diesem Sketch wird als Erstes die Spannung vom Sensor TMP36 abgelesen und dann bei in Celsius-Temperaturwerte umgerechnet. Danach vergleicht er mit den if-else-Funktionen bei und die vorliegende Temperatur mit den Werten für heiß und kalt und schaltet die jeweils zugehörige LED ein. Mit delay(1000) wird verhindert, dass die Leuchtdioden hektisch blinken, wenn die Temperatur schnell zwischen zwei Bereichen wechselt.

Den Sketch weiterverwenden

Der Sketch ist zwar sehr einfach, aber Sie können ihn als Grundlage für alle möglichen anderen Arten von Messungen nutzen. Dabei können Sie auch einen PowerSwitch Tail anschließen (siehe Abb. 4–42).

Abb. 4–42 Der PowerSwitch Tail kann bis zu 120 V Wechselstrom schalten.

Mit dem PowerSwitch Tail können Sie über den digitalen Ausgang des Arduino gefahrlos Geräte steuern, die über die Wandsteckdose mit Strom versorgt werden, z. B. Heizlüfter, Lampen oder andere Geräte. (Weitere Informationen erhalten Sie auf www.adafruit.com/products/268/.) Beispielsweise können Sie damit einen temperaturgesteuerten Heizlüfter oder Ventilator bauen, das Licht in der Garage steuern, sodass es eine gewisse Zeit lang eingeschaltet bleibt und dann von selbst ausgeht, oder die Weihnachtsaußenbeleuchtung fernsteuern.

Ausblick

Damit sind wir am Ende von Kapitel 4 angelangt. Sie haben jetzt eine Menge weiterer Möglichkeiten kennengelernt, darunter digitale Ein- und Ausgänge, neue Arten von Variablen und verschiedene mathematische Funktionen. Im nächsten Kapitel werden Sie noch mehr mit LEDs arbeiten, lernen, wie Sie eigene Funktionen schreiben können, ein Computerspiel und einen elektronischen Würfel konstruieren usw.

5

Funktionen

In diesem Kapitel lernen Sie Folgendes:

• Erstellen eigener Funktionen

• Entscheidungen mit while und do-while

• Übertragen von Daten zwischen dem Arduino und dem seriellen Monitor

• Umgang mit long-Variablen

Sie lernen eigene Funktionen zu erstellen, um Ihre Arduino-Sketche mit weniger Aufwand zu schreiben und leichter lesbar zu machen. Außerdem können Sie damit modularen, wiederverwendbaren Code erstellen, was bei zukünftigen Projekten Zeit zu sparen hilft. Des Weiteren erfahren Sie, wie Sie Entscheidungen zur Steuerung von Codeblöcken fällen können, und lernen einen neuen Typ von Integervariable kennen, nämlich long. Um das Gelernte anzuwenden, konstruieren Sie mithilfe selbst geschriebener Funktionen eine neue Art von Thermometer.

Eine Funktion besteht aus einem Satz von Anweisungen, den Sie an beliebigen Stellen in Ihren Sketchen einsetzen können. In der Arduino-Sprache stehen zwar schon viele vorgefertigte Funktionen zur Verfügung, doch manchmal ist darunter nicht die passende für das vorliegende Problem zu finden. Es kann auch sein, dass Sie einen Teil eines Sketches immer wieder ausführen müssen, was aber eine Verschwendung von Arbeitsspeicher darstellt. In beiden Fällen wären Sie wahrscheinlich froh, wenn Sie eine Funktion zur Hand hätten, die das tut, was Sie vorhaben. Die gute Nachricht lautet, dass es eine solche Funktion tatsächlich gibt – nämlich eine, die Sie selbst schreiben!

Projekt Nr. 9: Eine Funktion zur Wiederholung einer Aktion erstellen

Um Aktionen bei Bedarf zu wiederholen, können Sie einfache Funktionen schreiben. Beispielsweise schaltet die folgende Funktion die eingebaute LED zweimal ein (bei und ) und aus (bei und ):

void blinkLED()
{
digitalWrite(13, HIGH);
delay(1000);
digitalWrite(13, LOW);
delay(1000);
digitalWrite(13, HIGH);
delay(1000);
digitalWrite(13, LOW);
delay(1000);
}

Das folgende Listing zeigt, wie diese Funktion in einem Sketch eingesetzt wird, den Sie auf den Arduino hochladen können:

// Projekt 9: Eine Funktion zur Wiederholung einer Aktion erstellen

#define LED 13
#define del 200

void setup()
{
pinMode(LED, OUTPUT);
}

void blinkLED()
{
digitalWrite(LED, HIGH);
delay(del);
digitalWrite(LED, LOW);
delay(del);
digitalWrite(LED, HIGH);
delay(del);
digitalWrite(LED, LOW);
delay(del);
}

void loop()
{
blinkLED();
delay(1000);
}

Wenn bei die Funktion blinkLED() in void loop() aufgerufen wird, führt der Arduino die Befehle aus, die im Abschnitt void blinkLED() stehen. Damit haben Sie eine eigene Funktion geschrieben und an der Stelle eingesetzt, wo sie gebraucht wurde.

Projekt Nr. 10: Eine Funktion mit einstellbarem Blinkvorgang erstellen

Die Funktion, die wir im letzten Abschnitt erstellt haben, ist sehr eingeschränkt. Was tun wir, wenn wir die Anzahl der Blinkvorgänge und die Verzögerung einstellen wollen? Das ist kein Problem, denn wir können eine Funktion auch so erstellen, dass wir die Werte ändern können:

void blinkLED(int cycles, int del)
{
for ( int z = 0 ; z < cycles ; z++ )
{
digitalWrite(LED, HIGH);
delay(del);
digitalWrite(LED, LOW);
delay(del);
}
}

Die neue Variante der Funktion void blinkLED() nimmt zwei Integerwerte entgegen: cycles (die Anzahl der Blinkvorgänge) und del (die Verzögerungszeit zwischen Ein- und Ausschalten der LED). Soll die LED also zwölfmal mit einer Verzögerung von je 100 ms blinken, verwenden wir blinkLED(12, 100). Geben Sie den folgenden Sketch in der IDE ein, um mit dieser Funktion zu experimentieren:

// Projekt 10: Eine Funktion mit einstellbarem Blinkvorgang erstellen

#define LED 13

void setup()
{
pinMode(LED, OUTPUT);
}

void blinkLED(int cycles, int del)
{
for ( int z = 0 ; z < cycles ; z++ )
{
digitalWrite(LED, HIGH);
delay(del);
digitalWrite(LED, LOW);
delay(del);
}
}

void loop()
{
blinkLED(12, 100);
delay(1000);
}

Bei werden unserer selbst geschriebenen Funktion blinkLED() die Werte 12 für cycles (die Anzahl der Blinkvorgänge) und 100 für del (die Verzögerung) übergeben. Daher blinkt die LED zwölfmal im Abstand von 100 ms.

Funktionen zur Rückgabe von Werten

Funktionen können nicht nur als Parameter eingegebene Werte annehmen (wie void blinkLED() in Projekt 10), sondern auch Werte ausgeben. So hat analogRead() in Projekt 8 beim Messen eines analogen Eingangs einen Wert zwischen 0 und 1023 ausgegeben. Das Wort void, das bis jetzt immer vor dem Funktionsnamen stand, bedeutet, dass die Funktion nichts zurückgibt, also den Rückgabewert void aufweist. Im Folgenden wollen wir einige nützliche Funktionen erstellen, die jedoch echte Werte zurückgeben.

Die folgende Funktion rechnet Temperaturangaben von Celsius in Fahrenheit um:

float convertTemp(float celsius)
{
float fahrenheit = 0;
fahrenheit = (1.8 * celsius) + 32;
return fahrenheit;
}

In der ersten Zeile definieren wir den Funktionsnamen (convertTemp), den Rückgabetyp (float) und jegliche Variablen, die wir der Funktion übergeben (float celsius). Wenn wir beispielsweise 40 °C in Fahrenheit umrechnen und das Ergebnis in der float-Variable tempf speichern wollen, müssen wir convertTemp wie folgt aufrufen:

tempf = convertTemp(40);

Dadurch wird der Wert 40 in die convertTemp-Variable celsius aufgenommen und in der Berechnung fahrenheit = (1.8 * celsius) + 32 dieser Funktion verwendet. Das Ergebnis wird dann in der Zeile return fahrenheit in der Variable tempf zurückgegeben.

Projekt Nr. 11: Ein Thermometer mit Blinkcodeanzeige

Nachdem Sie jetzt wissen, wie Sie eigene Funktionen schreiben können, wollen wir dies am Beispiel eines Thermometers in die Tat umsetzen, das den Temperatursensor TMP36 aus Kapitel 4 und die eingebaute LED des Arduino nutzt. Bei Temperaturen unter 20 °C soll die LED zweimal blinken, zwischen 20 und 26 °C viermal und über 26 °C sechsmal.

Den Sketch gestalten wir modular, indem wir ihn in einzelne Funktionen aufteilen. Dadurch wird der Sketch leichter verständlich und wir können die Funktionen wiederverwenden. Das Thermometer führt zwei Hauptaufgaben durch: Es misst die Temperatur und ordnet sie einer Kategorie zu und es lässt die LED so oft blinken, wie es die Temperatur verlangt.

Die Hardware

Es ist nur wenig Material erforderlich:

• ein TMP36-Temperatursensor

• eine Steckplatine

• Verbindungsdrähte

• Arduino und USB-Kabel

Der Schaltplan

Der Schaltplan ist sehr einfach, wie Abbildung 5–1 zeigt.

Abb. 5–1 Schaltplan für Projekt 11

Der Sketch

Für diesen Sketch schreiben wir zwei Funktionen. Die erste liest den Wert des TMP36, rechnet ihn in Celsius um und gibt je nachdem, wie oft die LED blinken soll, den Wert 2, 4 oder 6 zurück. Dazu wandeln wir den Sketch aus Projekt 8 ab.

Als zweite Funktion verwenden wir blinkLED() aus Projekt 9. Die Schleife in void loop ruft die Funktionen nacheinander auf und hält dann zwei Sekunden lang an, bevor sie den Vorgang von vorn beginnt.

HINWEIS

Denken Sie daran, die geänderten Projektsketche unter einem anderen Dateinamen zu speichern, damit Sie die früheren Versionen nicht unbeabsichtigt löschen!

Geben Sie als Sketch folgenden Code in der IDE ein:

// Project 11: Ein Thermometer mit Blinkcodeanzeige

#define LED 13

int blinks = 0;

void setup()
{
pinMode(LED, OUTPUT);
}

int checkTemp()
{
float voltage = 0;
float celsius = 0;
float hotTemp = 26;
float coldTemp = 20;
float sensor = 0;
int result;
// Liest den Temperatursensor ab und rechnet das Ergebnis
// in Celsiuswerte um

sensor = analogRead(0);
voltage = (sensor*5000)/1024;   // Rechnet Sensorrohwert in mV um
voltage = voltage-500;          // Entfernt Versatz
celsius = voltage/10;           // Rechnet mV- in Celsiuswert um

// Reagiert je nach Temperaturbereich
if (celsius < coldTemp)
{
result = 2;
}
else if (celsius >= coldTemp && celsius <= hotTemp)
{
result = 4;
}
else
{
result = 6; // Temperatur ist > hotTemp
}
return result;
}

void blinkLED(int cycles, int del)
{
for ( int z = 0 ; z < cycles ; z++ )
{
digitalWrite(LED, HIGH);
delay(del);
digitalWrite(LED, LOW);
delay(del);
}
}

void loop()
{
blinks = checkTemp();
blinkLED(blinks, 500);
delay(2000);
}

Da wir eigene Funktionen verwenden, müssen wir in void loop () nichts anderes tun, als sie aufzurufen und die Verzögerung einzustellen. Die Funktion checkTemp() gibt einen Wert in der Integervariable blinks zurück, und daraufhin lässt blinkLED() die LED im Abstand von 500 ms so oft blinken, wie blinks angibt. Danach hält der Sketch zwei Sekunden lang an, bevor der Vorgang wiederholt wird.

Laden Sie den Sketch hoch und beobachten Sie die LED, um das Thermometer in Aktion zu erleben. (Bauen Sie diese Schaltung noch nicht auseinander, da Sie sie noch in den folgenden Beispielen benötigen werden.)

Daten vom Arduino im seriellen Monitor anzeigen

Bis jetzt haben wir Sketche an den Arduino gesendet und uns die Ausgabe über LEDs anzeigen lassen (sei es die Temperatur oder die Ampelsignale). Mit Blinkzeichen können Sie sehr leicht Rückmeldung vom Arduino einholen, allerdings ist deren Informationsgehalt nicht sehr hoch. In diesem Abschnitt lernen Sie, wie Sie Daten vom Arduino über die Kabelverbindung im Fenster Serial Monitor der IDE anzeigen und von der Computertastatur aus Daten an den Arduino übertragen können.

Der serielle Monitor

Um den seriellen Monitor zu öffnen, starten Sie die IDE und klicken in der Symbolleiste auf das Symbol aus Abbildung 5–2. Anschließend wird das Fenster Serial Monitor geöffnet, das Sie in Abbildung 5–3 sehen.

Abb. 5–2 Das Symbol für den seriellen Monitor in der IDE

Wie Sie in Abbildung 5–3 sehen, zeigt der serielle Monitor oben ein Eingabefeld an, das aus einer einzelnen Eingabezeile sowie einer Sendeschaltfläche besteht, und darunter ein Ausgabefenster, in dem die Daten vom Arduino dargestellt werden. Wenn das Kontrollkästchen Autoscroll aktiviert ist, wird immer nur die jüngste Ausgabe angezeigt. Sobald der Bildschirm voll ist, werden ältere Daten vom sichtbaren Teil des Bildschirms verschoben, um Platz für die neuen zu machen. Ist Autoscroll nicht aktiviert, müssen Sie über den vertikalen Rollbalken zu den aktuellen Daten wechseln.

Abb. 5–3 Der serielle Monitor

Den seriellen Monitor starten

Bevor Sie den seriellen Monitor nutzen können, müssen Sie ihn aktivieren, indem Sie die folgende Funktion in void setup() zu Ihrem Sketch hinzufügen:

Serial.begin(9600);

Der Wert 9600 ist die Geschwindigkeit, mit der die Daten zwischen Computer und Arduino übertragen werden, angegeben in Baud. Dieser Wert muss der Geschwindigkeitseinstellung entsprechen, die unten rechts im seriellen Monitor angezeigt wird (siehe Abb. 5–3).

Text an den seriellen Monitor senden

Um Text an den seriellen Monitor zu senden und im Ausgabefenster anzuzeigen, verwenden Sie Serial.print:

Serial.print("Arduino for Everyone!");

Dadurch wird der Text, der zwischen den Anführungszeichen steht, an das Ausgabefenster des seriellen Monitors gesendet.

Damit jeglicher nachfolgende Text auf der nächsten Zeile beginnt, verwenden Sie Serial.println:

Serial.println("Arduino for Everyone!");

Den Inhalt von Variablen anzeigen

Auf dem seriellen Monitor können Sie auch die Inhalte von Variablen anzeigen. Das folgende Beispiel zeigt diesen Vorgang für die Variable results:

Serial.println(results);

Der Inhalt von float-Variablen wird standardmäßig mit zwei Nachkommastellen angezeigt. Um das zu ändern, können Sie die Anzahl der gewünschten Dezimalstellen in Form einer Zahl zwischen 0 und 6 als zweiten Parameter hinter dem Variablennamen angeben. Um beispielsweise results mit vier Dezimalstellen anzuzeigen, schreiben Sie Folgendes:

Serial.print(results, 4);

Projekt Nr. 12: Die Temperatur im seriellen Monitor anzeigen

Mit dem Aufbau aus Projekt 8 wollen wir die Temperaturdaten nun im Fenster Serial Monitor in Celsius und in Fahrenheit anzeigen. Dazu erstellen wir eine Funktion, die die Temperaturwerte ermittelt, und eine andere, die sie im seriellen Monitor darstellt.

Geben Sie in der IDE folgenden Code ein:

// Projekt 12: Die Temperatur im seriellen Monitor anzeigen

float celsius = 0;
float fahrenheit = 0;

void setup()
{
Serial.begin(9600);
}

void findTemps()
{
float voltage = 0;
float sensor = 0;
// Liest den Temperatursensor ab und rechnet das Ergebnis
// in Celsius- und Fahrenheitwerte um
sensor = analogRead(0);
voltage = (sensor * 5000) / 1024;   // Rechnet Sensorrohwert in mV um
voltage = voltage - 500;            // Entfernt Versatz
celsius = voltage / 10;             // Rechnet mV- in Celsiuswert um
fahrenheit = (1.8 * celsius) + 32;  // Rechnet Celius in Fahrenheit um
}

void displayTemps()
{
Serial.print("Temperature is ");
Serial.print(celsius, 2);
Serial.print(" deg. C / ");
Serial.print(fahrenheit, 2);
Serial.println(" deg. F");
// Wir verwenden hier .println, damit der nächste Wert
// auf einer eigenen Zeile angezeigt wird
}

void loop()
{
findTemps();
displayTemps();
delay(1000);
}

In diesem Sketch passiert eine ganze Menge, aber da wir die beiden Funktionen findTemps() bei und displayTemps() bei erstellt haben, sieht die Sache schon übersichtlicher aus. Diese Funktionen werden in void loop() aufgerufen, sodass die Schleife ganz einfach ist. Hier können Sie ganz deutlich Gründe dafür erkennen, eigene Funktionen zu schreiben: Dadurch werden Ihre Sketche leichter verständlich, der Code wird modularer und lässt sich möglicherweise wiederverwenden.

Nachdem Sie den Sketch hochgeladen haben, warten Sie einige Sekunden lang und öffnen dann den seriellen Monitor. Dort wird jetzt die Temperatur Ihrer Umgebung wie in Abbildung 5–4 angezeigt.

Abb. 5–4 Das Ergebnis von Projekt 12

Debugging im seriellen Monitor

Den seriellen Monitor können Sie auch zum Debuggen Ihres Sketches nutzen (also um Fehler aufzuspüren und zu beheben). Wenn Sie in den Sketch einfache Serial.println()-Anweisungen aufnehmen, die Ihnen mitteilen, welche Stelle des Sketches gerade ausgeführt wird, können Sie verfolgen, wie der Arduino eine Anweisung nach der anderen abarbeitet. Beispielsweise können Sie in die Funktion findTemps() folgende Zeile aufnehmen, um die Meldung auszugeben, dass der Arduino gerade diese Funktion ausführt:

Serial.println("now in findTemps()");

Entscheidungen mit while-Anweisungen

Mit while-Anweisungen können Sie Vorgänge in einem Sketch wiederholt ausführen lassen, solange eine bestimmte Bedingung wahr ist. Die Bedingung wird daher immer geprüft, bevor der Code in der while()-Anweisung ausgeführt wird. Beispielsweise wird bei while ( temperature > 30 ) erst nachgeschaut, ob der Wert von temperature größer als 30 ist. Für die Bedingung können Sie innerhalb der Klammern auch jeden anderen beliebigen Vergleichsoperator verwenden.

Der folgende Code veranlasst den Arduino, bis 10 zu zählen (was 10 s dauert) und dann mit seinem Programm fortzufahren:

int a = 0; // Eine Integervariable
while ( a < 10 )
{
a = a + 1;
delay(1000);
}

Zu Anfang dieses Sketches wird die Variable a auf 0 gesetzt. Anschließend addiert das Programm 1 zu dem Wert von a, wartet eine Sekunde lang (delay(1000)) und wiederholt den Prozess, bis a den Wert 10 hat (while ( a < 10 )). Sobald a gleich 10 ist, ergibt der Vergleich in der while-Anweisung false, weshalb der Arduino mit dem Code fortfährt, der in dem Sketch hinter den Klammern der while-Schleife steht.

do-while

Anders als bei while erfolgt die Prüfung der Bedingung bei einer do-while-Struktur nach der Ausführung des Codes in der Anweisung:

int a = 0; // Eine Integervariable
do
{
delay(1000);
a = a + 1;
} while ( a < 100 );

Hier wird der Code zwischen den geschweiften Klammern ausgeführt, bevor die Bedingung (while ( a < 100 )) geprüft wird. Daher wird die Schleife mindestens einmal ausgeführt, auch wenn die Bedingung nicht erfüllt ist. Ob Sie while oder do-while verwenden, entscheiden Sie jeweils bei der Gestaltung Ihres Projekts.

Daten vom seriellen Monitor an den Arduino senden

Um Daten vom seriellen Monitor an den Arduino senden zu können, müssen wir dafür sorgen, dass der Arduino den seriellen Puffer abhört, also den Teil des Arduino, der über die seriellen Pins (Digitalpin 0 und 1) Daten von außen empfängt. Diese Pins sind über den USB-Schaltkreis und das Kabel auch mit Ihrem Computer verbunden. Der serielle Puffer enthält die Daten, die von der Eingabezeile des seriellen Monitors eingehen.

Projekt Nr. 13: Eine Zahl mit 2 multiplizieren

Um die Übertragung von Daten über den seriellen Monitor zu veranschaulichen, sehen wir uns den folgenden Sketch an. Er nimmt eine einzelne Ziffer vom Benutzer entgegen, multipliziert sie mit 2 und zeigt das Ergebnis im Ausgabefenster des seriellen Monitors an.

// Projekt 13: Eine Zahl mit 2 multiplizieren

int number;

void setup()
{
Serial.begin(9600);
}

void loop()
{
number = 0;       // Setzt number auf 0, um einen neuen Wert
// empfangen zu können
Serial.flush();   // Leert den seriellen Puffer, bevor wieder
// gewartet wird
while (Serial.available() == 0)
{
// Tut nichts, bis etwas im seriellen Puffer ankommt
}
while (Serial.available() > 0)
{
number = Serial.read() - '0';
// Liest die Zahl im seriellen Puffer und stellt sie in number
// und entfernt den ASCII-Textversatz '0' für null.
}
// Zeigt die eingegebene Zahl und das Ergebnis der Multiplikation an
Serial.print("You entered: ");
Serial.println(number);
Serial.print(number);
Serial.print(" multiplied by two is ");
number = number * 2;
Serial.println(number);
}

Der Test Serial.available() in der ersten while-Anweisung bei gibt 0 zurück, wenn der Benutzer im seriellen Monitor nichts eingegeben hat. Die Anweisung teilt dem Arduino also mit: »Tue nichts, bis der Benutzer irgendetwas eingibt.« Die nächste while-Anweisung bei erkennt die Zahl im seriellen Puffer und wandelt den Textcode, als der die Daten dargestellt werden, in eine echte Integerzahl um. Anschließend zeigt der Arduino diese Zahl und das Ergebnis der Multiplikation an.

Die Funktion Serial.flush() zu Beginn des Sketches leert den seriellen Puffer für den Fall, dass sich noch unerwartete Daten darin befinden, und bereitet ihn für den Empfang der nächste verfügbaren Daten vor. Abbildung 5–5 zeigt das Fenster des seriellen Monitors nach Ausführung des Sketches.

Abb. 5–5 Beispiel der Ein- und Ausgabe von Projekt 13

Sie können jetzt zwar über den seriellen Monitor numerische Daten eingeben und vom Arduino verarbeiten lassen, aber die Verwendung von Integervariablen schränkt den Bereich der verfügbaren Zahlen ein. Um diesen Bereich zu vergrößern, können Sie long-Variablen nutzen, wie Sie im folgenden Abschnitt lernen werden.

long-Variablen

Damit der serielle Monitor auch mehr als einstellige Zahlen akzeptiert, müssen wir dem Sketch noch weiteren Code hinzufügen, wie Sie in Kürze sehen werden. Bei der Arbeit mit großen Zahlen jedoch stellt der Variablentyp int eine Einschränkung dar, da er nur Werte bis höchstens 32.767 fassen kann. Zum Glück können wir diese Einschränkung jedoch mit dem Variablentyp long überwinden. Eine long-Variable ist eine ganze Zahl zwischen –2.147.483.648 und 2.147.483.647. Damit bietet sich uns ein sehr viel größerer Bereich als bei int-Variablen (–32.768 bis 32.767).

Projekt Nr. 14: long-Variablen verwenden

Wir wollen den seriellen Monitor nun zur Übergabe von long-Variablen und mehrstelligen Zahlen verwenden. Der folgende Sketch akzeptiert eine Zahl aus vielen Stellen, multipliziert sie mit 2 und gibt das Ergebnis an den seriellen Monitor zurück:

// Projekt 14: long-Variablen verwenden

long number = 0;
long a = 0;

void setup()
{
Serial.begin(9600);
}

void loop()
{
number = 0;       // Setzt number auf 0, um einen neuen Wert
// empfangen zu können
Serial.flush();   // Leert den seriellen Puffer, bevor wieder
// gewartet wird
while (Serial.available() == 0)
{
// Tut nichts, bis etwas im seriellen Puffer ankommt.
// Wenn etwas hineinkommt, gibt Serial.available an,
// wie viele Zeichen im Puffer auf Verarbeitung warten
}
// Ein Zeichen der seriellen Daten ist verfügbar,
// die Berechnung beginnt
while (Serial.available() > 0)
{
// Verschiebt alle bisherigen Stellen um eine Position nach links,
// während sich Daten im Puffer befinden, d. h., 1 wird zu 10.
number = number * 10;
// Liest die nächste Ziffer im Puffer und entfernt das Zeichen 0,
// um sie in eine echte Ganzzahl umzuwandeln
a = Serial.read() - '0';
// Addiert diesen Wert a zu der angesammelten Zahl
number = number + a;
// Sieht eine kurze Verzögerung vor, sodass weitere Daten in
// Serial.available gelangen können
delay(5);
}
Serial.print("You entered: ");
Serial.println(number);
Serial.print(number);
Serial.print(" multiplied by two is ");
number = number * 2;
Serial.println(number);
}

In diesem Beispiel machen es die beiden while-Schleifen möglich, dass der Arduino mehrstellige Zahlen vom seriellen Monitor annimmt. Wenn der Benutzer die erste Ziffer eingibt (die linke Stelle der gesamten Zahl), wird sie in eine Zahl umgewandelt und dann zur Summenvariable number addiert. Gibt es nur eine Ziffer, fährt der Sketch mit dem Code hinter der Schleife fort. Wird eine weitere Ziffer eingegeben (z. B. die 2 von 42), wird die bisherige Summe mit 10 multipliziert, um die erste Stelle nach links zu verschieben, und dann die neue Ziffer addiert. Dieser Vorgang wiederholt sich, bis die rechte Stelle zur Summe addiert wurde.

Abbildung 5–6 zeigt die Ein- und Ausgabe dieses Sketches.

Abb. 5–6 Beispiel der Ein- und Ausgabe von Projekt 14

Ausblick

Dieses Kapitel mag etwas trocken gewirkt haben, aber eigene Funktionen zu erstellen, ist eine wichtige Fertigkeit, mit der Sie Ihre Sketche vereinfachen sowie Zeit und Aufwand sparen können. Diese Kenntnisse werden Sie im nächsten Kapitel gut anwenden können.

6

Zahlen, Variablen und arithmetische Operationen

In diesem Kapitel lernen Sie Folgendes:

• Erzeugung von Zufallszahlen

• Bau elektronischer Würfel

• Binärzahlen

• Verwendung von Schieberegister-ICs (integrierte Schaltkreise) zur Erweiterung der digitalen Ausgangspins

• Erstellen eines Quizspiels zum Thema Binärzahlen

• Arrays aus Variablen

• Ausgaben von Zahlen mit Siebensegmentanzeigen

• Verwenden der mathematischen Modulo-Funktion

• Bau eines Digitalthermometers

• Bitweise Arithmetik

• Erstellen von festen und laufenden Bildern auf LED-Matrixanzeigen

Hier lernen Sie eine breite Palette an nützlichen neuen Funktionen kennen, die Ihre Möglichkeiten für Projekte erweitern. Dazu gehören Zufallszahlen, mathematische Funktionen und die Speicherung von Variablen in geordneten Listen, sogenannten Arrays. Außerdem erfahren Sie, wie Sie LED-Anzeigemodule in numerischer und in Matrixform zur Ausgabe von Daten und einfachen Bildern einsetzen können. Um das Gelernte anzuwenden, konstruieren Sie ein Spiel und ein Digitalthermometer.

Zufallszahlen generieren

Für Spiele und besondere Effekte kann es sehr nützlich sein, wenn ein Programm in der Lage ist, Zufallszahlen zu erzeugen. Beispielsweise können Sie Zufallszahlen nutzen, um mit dem Arduino ein Würfel- oder Lotteriespiel zu spielen, um Lichteffekte mit LEDs hervorzurufen oder um optische und akustische Effekte für ein Arduino-Quizspiel zu gestalten. Leider kann der Arduino von sich aus keine reinen Zufallszahlen erzeugen. Sie müssen ihm helfen, indem Sie ihm einen Startwert angeben, also eine willkürlich ausgewählte Anfangszahl für die Berechnungen, die eine Zufallszahl ausgeben.

Zufallszahlen aus dem Umgebungsstrom generieren

Die einfachste Möglichkeit, auf dem Arduino eine Zufallszahl zu erstellen, besteht darin, ein Programm zu schreiben, dass die Spannung an einem der freien (nicht belegten) analogen Pins abliest (z. B. Analogpin 0). Das ist etwa mit folgender Zeile in void setup() möglich:

randomSeed(analogRead(0))

Auch wenn an den Analogpin nichts angeschlossen ist, sorgt die statische Elektrizität in der Umgebung doch für eine winzige messbare Spannung mit zufälligem Betrag. Wir können diese Umgebungsspannung messen und als Startwert nutzen, um mit random(lower, upper) eine Zufallszahl zu erzeugen, und einer Integervariable zuweisen. Mit den Parametern lower und upper werden dabei die Unter- und die Obergrenze für den Wertebereich der Zufallszahl festgelegt. Um beispielsweise eine Zufallszahl zwischen 100 und 1000 zu generieren, schreiben Sie Folgendes:

int a = 0;
a = random(100, 1001);

Wir gaben als Obergrenze nicht 1000, sondern 1001 an, da die Obergrenze ausschließlich ist, das heißt, der angegebene Wert ist nicht im Wertebereich enthalten.

Um eine Zufallszahl zwischen 0 und einer beliebigen Zahl zu erzeugen, reicht es jedoch, nur die Obergrenze anzugeben. Für eine Zufallszahl zwischen 0 und 6 schreiben Sie also:

a = random(7);

Der Beispielsketch aus Listing 6–1 erzeugt Zufallszahlen zwischen 0 und 1000 sowie zwischen 10 und 50:

int r = 0;

void setup()
{
randomSeed(analogRead(0));
Serial.begin(9600);
}

void loop()
{
Serial.print("Random number between zero and 1000 is: ");
r = random(0, 1001);
Serial.println(r);
Serial.print("Random number between ten and fifty is: ");
r = random(10, 51);
Serial.println(r);
delay(1000);
}

Listing 6–1 Zufallszahlengenerator

Abbildung 6–1 zeigt das Ergebnis im seriellen Monitor.

Abb. 6–1 Die Ausgabe von Listing 6–1

Nun wissen Sie, wie Sie Zufallszahlen erzeugen können. Als Nächstes wollen wir diese neuen Kenntnisse gleich in die Tat umsetzen, indem wir einen elektronischen Würfel konstruieren.

Projekt Nr. 15: Einen elektronischen Würfel erstellen

Unser Ziel besteht darin, willkürlich eine von sechs LEDs zum Leuchten zu bringen, um den Wurf eines Würfels zu simulieren. Dazu erzeugen wir eine Zufallszahl zwischen 1 und 6 und schalten dann die LED der entsprechenden Nummer ein. Für die Aufgabe, eine der sechs LEDs zufällig auszuwählen und eine bestimmte Zeit lang aufleuchten zu lassen, erstellen wir eine Funktion. Wenn der Arduino, auf dem der Sketch läuft, eingeschaltet oder zurückgesetzt wird, soll er eine bestimmte Zeit lang in schneller Folge zufällige LEDs einschalten und den Lichtwechsel dann verlangsamen, bis die endgültige LED leuchtet. Die LED, die der Zufallszahl entspricht, bleibt dann eingeschaltet, bis der Arduino zurückgesetzt oder ausgeschaltet wird.

Die Hardware

Um den Würfel zu bauen, brauchen Sie folgende Teile:

• sechs LEDs beliebiger Farbe (LED1 bis LED6)

• einen 560-Ω-Widerstand

• eine mittelgroße Steckplatine

• Verbindungsdrähte

• Arduino und USB-Kabel

Der Schaltplan

Da immer nur eine LED auf einmal leuchtet, reicht ein Widerstand zur Strombegrenzung zwischen den Kathoden der LEDs und dem GND-Anschluss. Abbildung 6–2 zeigt den Schaltplan für den Würfel.

Abb. 6–2 Schaltplan für Projekt 15

Der Sketch

Der Sketch für den Würfel sieht wie folgt aus:

// Projekt 15: Einen elektronischen Würfel erstellen

void setup()
{
randomSeed(analogRead(0));          // Gibt den Anfangswert für die
// Erzeugung der Zufallszahlen vor
for ( int z = 1 ; z < 7 ; z++ )     // Legt die LEDs an den Pins 1-6
// als Ausgänge fest
{
pinMode(z, OUTPUT);
}
}

void randomLED(int del)
{
int r;
r = random(1, 7);       // Generiert eine Zufallszahl zwischen 1 und 6
digitalWrite(r, HIGH);  // Legt Spannung an die entsprechende LED
// an einem der Digitalpins 1–6 an

if (del > 0)
{
delay(del);          // Lässt die LED die übergebene
// Verzögerungszeit      lang leuchten
}
else if (del == 0)
{
do                   // Lässt die LED dauerhaft leuchten,
// wenn die Verzögerung 0 übergeben wird
{}
while (1);
}
digitalWrite(r, LOW);   // Schaltet die LED aus
}

void loop()
{
int a;
// Bringt willkürliche LEDs zum Leuchten, damit der Vorgang
// spannender aussieht
for ( a = 0 ; a < 100 ; a++ )
{
randomLED(50);
}
// Verlangsamt den Leuchtrhythmus
for ( a = 1 ; a <= 10 ; a++ )
{
randomLED(a * 100);
}
// Hält bei der LED an, die der endgültigen Zufallszahl entspricht
randomLED(0);
}

Um die digitalen Ausgabepins in void setup() zu aktivieren, verwenden wir hier eine Schleife. Die Funktion randomLED() nimmt einen Integerwert entgegen, der in der Funktion delay() bei dazu herangezogen wird, die LED die angegebene Zeit lang eingeschaltet zu lassen. Beträgt der bei empfangene Wert für die Verzögerung 0, hält die Funktion die LED unbegrenzt am Leuchten, denn bei steht:

do {} while (1);

Da 1 stets 1 ist, wird diese Schleife endlos durchlaufen.

Um zu »würfeln«, setzen wir den Arduino zurück, womit der Sketch neu startet. Damit das willkürliche Aufleuchten der LEDs immer langsamer wird, bis schließlich der endgültige Wert angezeigt wird, lassen wir bei zunächst 100 Mal jeweils eine zufällig ausgewählte LED 50 ms lang leuchten. Danach verlangsamen wir diesen Rhythmus, indem wir die Verzögerung zwischen dem Aufblitzen der Leuchtdioden von 100 auf 1000 ms erhöhen und die Leuchtdauer auf 100 ms. Damit simulieren wir die Verlangsamung der Würfelbewegung, bevor er zum Stillstand kommt und den endgültigen Wert anzeigt. An dieser Stelle gibt der Arduino das Ergebnis des Würfelvorgangs wieder, indem er mit der folgenden letzten Zeile eine der LEDs zum Leuchten bringt:

randomLED(0);

Den Sketch ändern

Dieses Projekt können Sie auf verschiedene Weise abändern. Beispielsweise können Sie weitere sechs LEDs hinzufügen, um zwei Würfel auf einmal zu werfen, oder das Ergebnis durch die Anzahl der Blinkvorgänge der eingebauten LED anzeigen. Lassen Sie Ihre Fantasie spielen, um mit Ihren neuen Fertigkeiten Spaß zu haben!

Schnellkurs in Binärzahlen

Die meisten Kinder lernen das Zählen im Dezimalsystem (Basis 10), Computer (und der Arduino) aber verwenden das Binärsystem (Basis 2). Binärzahlen werden nur aus den Ziffern 1 und 0 zusammengesetzt, z. B. 10101010. Jede der Stellen steht dabei für 2n, wobei n die Positionsnummer ist (die Nummerierung verläuft von rechts nach links und beginnt mit 0). Die Produkte aus dem Inhalt und der Zweierpotenz der einzelnen Stellen werden dann addiert, was den Gesamtwert der Zahl ergibt.

Betrachten Sie als Beispiel die Binärzahl 111111 in Tabelle 6–1. Um sie in eine Dezimalzahl umzurechnen, müssen wir die dezimalen Entsprechungen der einzelnen Stellen addieren, die in der unteren Zeile der Tabelle aufgeführt sind:

128 + 64 + 32 + 16 + 8 + 4 + 2 + 1

Das Ergebnis lautet 255. Eine Binärzahl mit acht Stellen (oder Bits) enthält ein Byte Daten. Ein Byte Daten kann einen numerischen Wert zwischen 0 und 255 haben. Das Bit ganz links wird als das signifikanteste Bit (Most Significant Bit, MSB) bezeichnet, das ganz rechts als das am wenigsten signifikante Bit (Least Significant Bit, LSB).

Binärzahlen eignen sich hervorragend für die Speicherung ganz bestimmter Arten von Daten, z. B. der Ein/Aus-Muster für LEDs, Wahr/falsch-Einstellungen und für den Status digitaler Ausgänge. Sie bilden das Grundformat aller Arten von Daten in Computern.

2^7

2^6

2^5

2^4

2^3

2^2

2^1

2^0

1

1

1

1

1

1

1

1

binär

128

64

32

16

8

4

2

1

dezimal

Tab. 6–1 Beispiel für die Umrechnung von Binär- in Dezimalzahlen

Bytevariablen

Eine Möglichkeit zur Speicherung von Binärzahlen besteht in der Verwendung von Bytevariablen. Der folgende Beispielcode legt die Bytevariable outputs an:

byte outputs = B11111111;

Das B weist den Arduino an, die nachfolgende Zahl als Binär- und nicht als Dezimalzahl zu lesen (also als binäre Entsprechung von 255 und nicht als einen Wert von mehr als elf Millionen). Mit Listing 6–2 können Sie das noch weiter veranschaulichen.

byte a;

void setup()
{
Serial.begin(9600);
}

void loop()
{
for ( int count = 0 ; count < 256 ; count++ )
{
a = count;
Serial.print("Base-10 = ");
Serial.print(a, DEC);
Serial.print(" Binary = ");
Serial.println(a, BIN);
delay(1000);
}
}

Listing 6–2 Veranschaulichung von Binärzahlen

Über die Funktion Serial.print() geben wir den Inhalt der Bytevariablen mit DEC als Dezimalzahl aus () und mit BIN als Binärzahl (). Nach dem Hochladen des Sketches wird die Ausgabe im seriellen Monitor angezeigt (siehe Abbildung 6–3).

Abb. 6–3 Ausgabe von Listing 6–2

Erweitern der digitalen Ausgänge mit Schieberegistern

Die Platine des Arduino verfügt über 13 Digitalpins, die wir als Ausgänge nutzen können, aber manchmal reichen 13 einfach nicht aus. Um weitere Ausgänge hinzuzufügen, können wir ein Schieberegister verwenden und haben dabei auf dem Arduino immer noch genug Platz für weitere Ausgänge. Ein Schieberegister ist ein integrierter Schaltkreis (Integrated Circuit, IC) mit acht digitalen Ausgangspins, die durch die Übertragung eines Datenbytes gesteuert werden. In unseren Projekten verwenden wir das Schieberegister 74HC595 aus Abbildung 6–4.

Abb. 6–4 Der Schieberegister-IC 74HC595

Das Schieberegister 74HC595 verfügt über acht digitale Ausgänge, die wie die digitalen Ausgangspins des Arduino verwendet werden können. Der IC selbst belegt drei Pins auf dem Arduino, sodass wir unter dem Strich fünf Ausgangspins hinzubekommen.

Das Prinzip hinter einem Schieberegister ist einfach: Wir senden ihm ein Byte Daten, also acht Bits, wobei jedes Bit einem der Ausgangspins entspricht. Von links nach rechts gesehen, stehen die Bits für die Pins in der Reihenfolge von der höchsten zur niedrigsten Nummer. Das Bit ganz links stellt also Ausgangspin 7 des Registers dar, das Bit ganz rechts Pin 0. Wenn wir also zum Beispiel B10000110 senden, werden die Ausgänge 7, 2 und 1 eingeschaltet und die Ausgänge 0 und 3 bis 6 ausgeschaltet. Das gilt so lange, bis das nächste Datenbyte eintrifft oder der Strom abgeschaltet wird.

Sie können auch mehrere Schieberegister miteinander verbinden, um jeweils weitere acht digitale Ausgangspins zu gewinnen, während am Arduino immer noch lediglich drei Pins belegt sind. Dadurch eignen sich Schieberegister hervorragend, wenn Sie viele LEDs steuern müssen. Das wollen wir nun ausprobieren, indem wir eine Anzeige für Binärzahlen konstruieren.

Projekt Nr. 16: Eine Binärzahlenanzeige aus LEDs bauen

In diesem Projekt verwenden wir acht LEDs, um die Binärzahlen von 0 bis 255 anzuzeigen. In unserem Sketch zählen wir mit einer for-Schleife von 0 bis 255 und senden jeden Wert an das Schieberegister, das die binären Entsprechungen der einzelnen Zahlen über LEDs ausgibt.

Die Hardware

Sie brauchen folgende Teile:

• einen Schieberegister-IC 74HC595

• acht LEDs (LED1 bis LED8)

• acht 560-Ω-Widerstände (R1 bis R8)

• eine Steckplatine

• Verbindungsdrähte

• Arduino und USB-Kabel

Der Anschluss des 74HC595

Abbildung 6–5 zeigt das Schaltplansymbol für den 74HC595.

Abb. 6–5 Das Schaltplansymbol des 74HC595

Das Schieberegister verfügt über 16 Kontakte:

• Die Pins 15 sowie 1 bis 7 sind die Ausgangspins, die wir steuern (bezeichnet mit Q0 bis Q7).

• Q7 gibt das erste Bit aus, das an das Schieberegister gesendet wird, Q0 das letzte.

• Pin 8 ist mit Masse verbunden.

• Pin 9 ist der Datenausgang (data out) und wird verwendet, um ggf. Daten an andere angeschlossene Schieberegister zu senden.

• Pin 10 ist stets mit einem 5-Volt-Stromanschluss verbunden (z. B. dem 5-Volt-Anschluss am Arduino).

• Die Pins 11 und 12 heißen clock (Takt) und latch (Auffangregister).

• Pin 13 ist output enable und wird gewöhnlich mit Masse verbunden.

• Pin 14 dient als Eingang für Bitdaten vom Arduino.

• Pin 16 ist zur Stromversorgung gedacht (5 V vom Arduino)

Damit Sie erkennen können, wie herum die Pins nummeriert sind, befindet sich an einem Ende des Schieberegister-ICs eine halbkreisförmige Einkerbung (siehe Abb. 6–4). Sie liegt zwischen den Pins 1 und 16.

Die Pins sind gegen den Uhrzeigersinn rund um den IC durchnummeriert, wie Sie in dem Schaltplan für unsere Binärzahlenanzeige in Abbildung 6–6 erkennen können.

Abb. 6–6 Schaltplan für Projekt 16

HINWEIS

Lassen Sie die Schaltung aufgebaut. Wir benötigen sie noch für das nächste Projekt.

Der Sketch

Hier sehen Sie den Sketch:

// Projekt 16: Eine Binärzahlenanzeige aus LEDs bauen

#define DATA 6     // Digitalpin 6 an Pin 14 des 74HC595
#define LATCH 8    // Digitalpin 8 an Pin 12 des 74HC595
#define CLOCK 10   // Digitalpin 10 an Pin 11 des 74HC595

void setup()
{
pinMode(LATCH, OUTPUT);
pinMode(CLOCK, OUTPUT);
pinMode(DATA, OUTPUT);
}

void loop()
{
int i;

for ( i = 0; i < 256; i++ )
{
digitalWrite(LATCH, LOW);
shiftOut(DATA, CLOCK, MSBFIRST, i);
digitalWrite(LATCH, HIGH);
delay(200);
}
}

In diesem Sketch legen wir die drei Pins, die mit dem Schieberegister verbunden sind, in void setup() als Ausgänge fest und durchlaufen in void loop() eine Schleife, die wiederholt von 0 bis 255 zählt. In dieser Schleife läuft auch das eigentliche Zauberkunststück ab. Wenn wir darin ein Byte an Daten (z. B. 240, also B11110000) an das Schieberegister senden, geschehen drei Dinge:

• Der Latch-Pin 12 wird auf LOW gesetzt (das heißt, vom digitalen Ausgangspin 8 des Arduino aus wird ein Signal mit niedrigem Pegel daran angelegt). Das dient als Vorbereitung dazu, den Ausgangspin 12 auf HIGH zu setzen, um die Daten an den Ausgangspins zu übernehmen, nachdem shiftOut seine Arbeit erledigt hat.

• Wir senden das Datenbyte (z. B. B11110000) vom digitalen Ausgangspin 6 des Arduino zum Schieberegister und teilen der Funktion shiftOut mit, in welcher Richtung sie die Daten im Byte interpretieren soll. Bei LSBFIRST werden die LEDs 1 bis 4 eingeschaltet und die anderen aus, bei MSBFIRST leuchten die LEDs 5 bis 8, während die anderen ausgeschaltet sind.

• Schließlich wird der Latch-Pin 12 auf HIGH gesetzt (es werden 5 V angelegt). Dadurch wird dem Schieberegister mitgeteilt, dass alle Bits eingegangen und bereit sind. Nun werden die Ausgänge umgeschaltet, um die empfangenen Daten widerzuspiegeln.

Projekt Nr. 17: Ein Binärzahlenquiz konstruieren

In diesem Projekt nutzen wir Zufallszahlen, den seriellen Monitor und die Schaltung aus Projekt 16, um ein Quizspiel zum Thema Binärzahlen zu bauen. Der Arduino zeigt über die LEDs zufällige Binärzahlen an, woraufhin der Benutzer die dezimale Entsprechung im seriellen Monitor eingeben muss. Anschließend kann er im seriellen Monitor ablesen, ob die Antwort richtig war. Das Spiel geht dann mit einer neuen Zahl weiter.

Der Algorithmus

Der Algorithmus lässt sich in drei Funktionen zerlegen. displayNumber() zeigt eine Binärzahl mithilfe der LEDs an, getAnswer() empfängt die eingegebene Zahl vom seriellen Monitor und zeigt sie dem Benutzer an, und checkAnswer() schließlich vergleicht die vom Benutzer eingegebene und die zufällig generierte Zahl und zeigt an, ob die Antwort richtig oder falsch war. Hat der Benutzer falsch geraten, wird außerdem die richtige Zahl angezeigt.

Der Sketch

Der Sketch generiert eine Zufallszahl zwischen 0 und 255, zeigt sie mithilfe der LEDs an, fordert den Benutzer zu einer Antwort auf und präsentiert das Ergebnis schließlich im seriellen Monitor. Alle in diesem Sketch verwendeten Funktionen haben Sie schon gesehen, sodass der Code trotz seines Umfangs vertraut wirken sollte. Um ihn etwas genauer unter die Lupe zu nehmen, haben wir Kommentare eingefügt und werden außerdem im Anschluss noch einige Bemerkungen dazu verlieren.

// Projekt 17: Ein Binärzahlenquiz konstruieren

#define DATA 6      // Verbindung mit Pin 14 am 74HC595
#define LATCH 8     // Verbindung mit Pin 12 am 74HC595
#define CLOCK 10    // Verbindung mit Pin 11 am 74HC595

int number = 0;
int answer = 0;

void setup()
{
pinMode(LATCH, OUTPUT);      // Richtet die Pins am 74HC595 ein
pinMode(CLOCK, OUTPUT);
pinMode(DATA, OUTPUT);
Serial.begin(9600);
randomSeed(analogRead(0));  // Initialisiert den Zufallszahlengenerator
displayNumber(0);           // Setzt die LED-Anzeige zurück
}
void displayNumber(byte a)
{
// Sendet ein Byte, das auf den LEDs angezeigt werden soll
digitalWrite(LATCH, LOW);
shiftOut(DATA, CLOCK, MSBFIRST, a);
digitalWrite(LATCH, HIGH);
}

void getAnswer()
{
// Empfängt die Antwort vom Spieler
int z = 0;
Serial.flush();
while (Serial.available() == 0)
{
// Tut nichts, bis etwas im seriellen Puffer ankommt
}
// Ein Zeichen der seriellen Daten ist verfügbar, die Berechnung beginnt
while (Serial.available() > 0)
{
// Verschiebt alle bisherigen Stellen um eine Position nach links,
// während sich Daten im Puffer befinden, d. h., 1 wird zu 10.
answer = answer * 10;
// Liest die nächste Ziffer im Puffer und entfernt das Zeichen 0,
// um sie in eine echte Ganzzahl umzuwandeln
z = Serial.read() - '0';
// Addiert diese Stelle zu der angesammelten Zahl
answer = answer + z;
// Sieht eine kurze Verzögerung vor, sodass weitere Ziffern in
// Serial.available eingehen können
delay(5);
}
Serial.print("You entered: ");
Serial.println(answer);
}

void checkAnswer()
{
// Prüft die Antwort des Spielers und zeigt das Ergebnis an
if (answer == number) // Richtig!
{
Serial.print("Correct! ");
Serial.print(answer, BIN);
Serial.print(" equals ");
Serial.println(number);
Serial.println();
}
else // Falsch
{
Serial.print("Incorrect, ");
Serial.print(number, BIN);
Serial.print(" equals ");
Serial.println(number);
Serial.println();
}

answer = 0;
delay(10000); // Räumt dem Spieler Zeit ein, die Antwort zu überprüfen
}

void loop()
{
number = random(256);
displayNumber(number);
Serial.println("What is the binary number in base-10? ");
getAnswer();
checkAnswer();
}

Sehen wir uns nun genauer an, wie der Sketch funktioniert. Bei werden die digitalen Ausgangspins zur Verwendung des Schieberegisters eingerichtet. Außerdem wird der serielle Monitor gestartet und ein Anfangswert für den Zufallszahlengenerator festgelegt. Dann nimmt die selbst geschriebene Funktion displayNumber() bei ein Datenbyte entgegen und sendet es an das Schieberegister, das dieses Byte in Binärform über die angeschlossenen LEDs anzeigt (wie in Projekt 16). Bei übernimmt die eigene Funktion getAnswer() die Zahl, die der Benutzer im seriellen Monitor eingegeben hat (wie in Projekt 14), und zeigt sie an (siehe Abb. 6–7).

Anschließend vergleicht die Funktion checkAnswer() bei die vom Spieler eingegebene und mit getAnswer() angerufene Zahl mit der Zufallszahl, die der Sketch in void loop() erstellt hat. Danach wird dem Spieler angezeigt, ob die Antwort richtig oder falsch war, wobei auch die entsprechenden Binär- und Dezimalzahlen ausgegeben werden. In der Hauptschleife void loop() schließlich, in der das Programm abläuft, erzeugt der Arduino die binäre Zufallszahl für das Quiz und ruft die Funktionen auf, um sie anzuzeigen, die Antwort des Spielers abzurufen und zu prüfen.

In Abbildung 6–7 sehen Sie, wie das Spiel im seriellen Monitor abläuft.

Abb. 6–7 Projekt 17 in Aktion

Arrays

Ein Array ist ein Satz von Variablen oder Werten, die zu einer Gruppe zusammengefasst sind, sodass sie als Ganzes angesprochen werden können. Wenn Sie mit großen Mengen zusammenhängender Daten zu tun haben, ist es sinnvoll, sie mithilfe von Arrays zu ordnen.

Arrays definieren

Die einzelnen Inhalte eines Arrays werden als Elemente bezeichnet. Nehmen Sie beispielsweise an, Sie haben sechs float-Variablen, die die Temperaturwerte von Messungen während der letzten sechs Stunden enthalten. Anstatt ihnen allen eigene Namen zu verleihen, können Sie wie folgt das Array temperatures mit sechs Elementen definieren:

float temperatures[6];

Es ist auch möglich, ein Array gleich bei der Definition mit Werten zu füllen. In diesem Fall müssen wir die Größe nicht angeben. Betrachten Sie dazu das folgende Beispiel:

float temperatures[]={11.1, 12.2, 13.3, 14.4, 15.5, 16.6};

Hier haben wir darauf verzichtet, die Größe des Arrays in den eckigen Klammern festzulegen, da sie aus der Anzahl der eingefügten Werte in den geschweiften Klammern geschlossen werden kann.

Auf Werte in Arrays verweisen

Die Elemente in einem Array werden von links und beginnend mit 0 durchnummeriert. Das Array temperatures[] enthält also die Elemente 0 bis 5. Um auf einen einzelnen Wert in einem Array zu verweisen, geben wir die Nummer des Elements in den eckigen Klammern an. Um beispielsweise das erste Element von temperatures[] (das zurzeit den Wert 16,6 hat) in 12,34 zu ändern, schreiben wir Folgendes:

temperatures[0] = 12.34;

In Arrays lesen und schreiben

Listing 6–3 zeigt, wie Sie Werte in ein Array aus fünf Elementen schreiben und darin lesen können. Die erste for-Schleife in diesem Sketch schreibt eine Zufallszahl in die einzelnen Elemente des Arrays, die zweite ruft die Elemente ab und zeigt ihre Werte im seriellen Monitor an.

void setup()
{
Serial.begin(9600);
randomSeed(analogRead(0));
}

int array[5]; // Definiert das Array aus fünf Integerelementen

void loop()
{
int i;
Serial.println();
for ( i = 0 ; i < 5 ; i++ )   // Schreibt in das Array
{
array[i] = random(10);     // Zufallszahl zwischen 0 bis 9
}
for ( i = 0 ; i < 5 ; i++ )   // Zeigt den Inhalt des Arrays an
{
Serial.print("array[");
Serial.print(i);
Serial.print("] contains ");
Serial.println(array[i]);
}
delay(5000);
}

Listing 6–3 Beispiel zum Lesen und Schreiben in Arrays

Abbildung 6–8 zeigt die Ausgabe dieses Sketches im seriellen Monitor.

Abb. 6–8 Die Ausgabe von Listing 6–3

Nachdem Sie nun mit Binärzahlen, Schieberegistern und Arrays umgehen können, ist es an der Zeit, Ihre Kenntnisse in die Tat umzusetzen. Im nächsten Abschnitt bauen wir einige digitale Ziffernanzeigen auf.

Siebensegmentanzeigen

LEDs sind eine schöne Sache, aber mit einzelnen Lämpchen lassen sich nur bestimmte Arten von Daten ausgeben. In diesem Abschnitt werden wir daher mit numerischen Darstellungen in Form von Siebensegmentanzeigen arbeiten, wie Sie sie in Abbildung 6–9 sehen.

Abb. 6–9 Siebensegmentanzeigen

Diese Elemente sind ideal für die Darstellung von Zahlen geeignet, weshalb Sie sie auf Weckern, Tachos und anderen numerischen Anzeigen finden. Ein einzelnes Anzeigemodul besteht aus acht LEDs. Es gibt sie auch in verschiedenen Farben. Um die Anzahl der Anschlüsse an einem solchen Bauteil zu verringern, werden entweder alle Anoden oder alle Kathoden der LEDs zu einer gemeinsamen Anode oder gemeinsamen Kathode zusammengefasst. In unserem Projekt verwenden wir Module mit gemeinsamer Kathode.

Die LEDs eines Anzeigemoduls sind mit A bis G und DP (für den Dezimalpunkt) bezeichnet. Es gibt einen Anodenpin für jedes Segment und einen gemeinsamen Kathodenanschluss für alle Kathoden. Die Struktur einer Siebensegmentanzeige ist immer wie in Abbildung 6–10 definiert: LED-Segment A befindet sich oben, B rechts davon usw. Wenn Sie beispielsweise die Ziffer 7 darstellen möchten, müssen Sie die Segmente A, B und C bestromen.

Je nach Hersteller können die Pinbelegungen von Siebensegmentanzeigen schwanken, allerdings folgen sie immer dem Grundmuster aus Abbildung 6–10. Beziehen Sie vom Händler immer auch das Datenblatt des Moduls, damit Sie nicht erst langwierig herausfinden müssen, welche Pins zu welchem Segment gehören.

Für unsere Siebensegmentanzeigen verwenden wir das Schaltplansymbol aus Abbildung 6–11.

Abb. 6–10 LED-Zuordnung einer typischen Siebensegmentanzeige

Abb. 6–11 Schaltplansymbol für eine Siebensegmentanzeige

Die LEDs steuern

Die LED-Anzeige steuern wir mithilfe der Methoden aus Projekt 17, indem wir die Pins A bis DP mit den Ausgängen Q0 bis Q7 eines Schieberegisters verbinden. Um zu bestimmen, welche Segmente sie ein- und ausschalten müssen, um eine bestimmte Zahl oder einen Buchstaben darzustellen, ziehen Sie Tabelle 6–2 zurate.

SR

Q0

Q1

Q2

Q3

Q4

Q5

Q6

Q7

Segment

A

B

C

D

E

F

G

DP

Decimal

0

1

1

1

1

1

1

0

0

252

1

0

1

1

0

0

0

0

0

96

2

1

1

0

1

1

0

1

0

218

3

1

1

1

1

0

0

1

0

242

4

0

1

1

0

0

1

1

0

102

5

1

0

1

1

0

1

1

0

182

6

1

0

1

1

1

1

1

0

190

7

1

1

1

0

0

0

0

0

224

8

1

1

1

1

1

1

1

0

254

9

1

1

1

1

0

1

1

0

246

A

1

1

1

0

1

1

1

0

238

B

0

0

1

1

1

1

1

0

62

C

1

0

0

1

1

1

0

0

156

D

0

1

1

1

1

0

1

0

122

E

1

0

0

1

1

1

1

0

158

F

1

0

0

0

1

1

1

0

142

Tab. 6–2 Darstellungsmatrix für eine Siebensegmentanzeige

Die erste Zeile der Tabelle gibt die Ausgangspins des Schieberegisters an, die die Segmente in der zweiten Zeile steuern. Alle weiteren Zeilen zeigen die Zeichen, die angezeigt werden können, sowie die zugehörigen Binär- und Dezimalwerte, die Sie dazu an das Schieberegister senden müssen.

Um beispielsweise wie in Abbildung 6–12 die Ziffer 7 anzuzeigen, müssen wir die LED-Segmente A, B und C einschalten, die den Ausgängen Q0, Q1 und Q2 des Schieberegisters entsprechen. Daher müssen wir das Byte B11100000 an das Register senden (wenn shiftOut auf LSBFIRST gesetzt ist), damit die ersten drei Ausgänge und damit die gewünschten LEDs eingeschaltet werden.

Abb. 6–12 Anzeige der Ziffer 7

Im nächsten Beispiel bauen wir eine Schaltung, die nacheinander die Ziffern 0 bis 9 und dann die Buchstaben A bis F anzeigt. Anschließend wird die Folge mit eingeschaltetem Dezimalpunkt wiederholt.

Projekt Nr. 18: Eine einstellige Anzeige konstruieren

In diesem Projekt bauen wir eine Schaltung mit einer einstelligen Anzeige auf.

Die Hardware

Sie benötigen folgende Teile:

• ein Schieberegister-IC 74HC595

• eine Siebensegmentanzeige mit gemeinsamer Kathode

• acht 560-Ω-Widerstände (R1 bis R8)

• eine große Steckplatine

• Verbindungsdrähte

• Arduino und USB-Kabel

Der Schaltplan

Den Schaltplan sehen Sie in Abbildung 6–13.

Abb. 6–13 Schaltplan für Projekt 18

Beim Anschluss der Siebensegmentanzeige an das Schieberegister müssen die LED-Pins A bis G mit den Pins Q0 bis Q6 und DP mit Q7 verbunden werden.

Der Sketch

Im Sketch für Projekt 18 speichern wir die Dezimalwerte (aus Tab. 6–2) im Array int digits[]. In void loop senden wir diese Werte nacheinander an das Schieberegister () und wiederholen den Vorgang dann mit eingeschaltetem Dezimalpunkt, indem wir jeweils 1 zu dem gesendeten Wert addieren ().

// Project 18: Eine einstellige Anzeige konstruieren

#define DATA 6     // Verbindung mit Pin 14 am 74HC595
#define LATCH 8    // Verbindung mit Pin 12 am 74HC595
#define CLOCK 10   // Verbindung mit Pin 11 am 74HC595

// Richtet das Array mit den Segmenten für 0 bis 9 und A bis F ein
// (aus Tab. 6–2)
int digits[] = {252, 96, 218, 242, 102, 182, 190, 224, 254, 246, 238, 62,
156, 122, 158, 142};

void setup()
{
pinMode(LATCH, OUTPUT);
pinMode(CLOCK, OUTPUT);
pinMode(DATA, OUTPUT);
}

void loop()
{
int i;
for ( i = 0 ; i < 16 ; i++ ) // Zeigt 0-9, A-F an
{
digitalWrite(LATCH, LOW);
shiftOut(DATA, CLOCK, LSBFIRST, digits[i]);
digitalWrite(LATCH, HIGH);
delay(250);
}
for ( i = 0 ; i < 16 ; i++ ) // Zeigt 0-9, A-F mit Dezimalpunkt an
{
digitalWrite(LATCH, LOW);
shiftOut(DATA, CLOCK, LSBFIRST, digits[i]+1);
// +1 dient dazu, das Bit für den Dezimalpunkt einzuschalten
digitalWrite(LATCH, HIGH);
delay(250);
}
}

Siebensegmentanzeigen sind hell und gut ablesbar. Abbildung 6–14 zeigt die Ziffer 9 mit Dezimalpunkt, wie sie von diesem Sketch ausgegeben wird.

Abb. 6–14 Eine der in Projekt 18 angezeigten Ziffern

Zweistellige Zahlen anzeigen

Um weitere digitale Ausgänge steuern zu können, müssen Sie ein weiteres Schieberegister hinzufügen. Verbinden Sie Pin 9 des 74HC595 (der seine Daten vom Arduino empfängt) mit Pin 14 des zweiten Schieberegisters. Jetzt müssen wir zwei Datenbytes senden, von denen das erste das zweite Register steuert und das zweite das erste. Betrachten Sie dazu folgendes Beispiel:

digitalWrite(LATCH, LOW);
shiftOut(DATA, CLOCK, MSBFIRST, 254);   // Daten für zweiten 74HC595
shiftOut(DATA, CLOCK, MSBFIRST, 254);   // Daten für ersten 74HC595
digitalWrite(LATCH, HIGH);

Projekt Nr. 19: Zwei Siebensegmentanzeigen steuern

In diesem Projekt lernen Sie, wie Sie zwei Siebensegmentanzeigen steuern, um zweistellige Zahlen auszugeben.

Die Hardware

Sie benötigen folgende Teile:

• zwei Schieberegister-IC 74HC595

• zwei Siebensegmentanzeigen mit gemeinsamer Kathode

• sechszehn 560-Ω-Widerstände (R1 bis R16)

• eine große Steckplatine

• Verbindungsdrähte

• Arduino und USB-Kabel

Der Schaltplan

Den Schaltplan sehen Sie in Abbildung 6–15.

Beachten Sie, dass die Daten- und Taktpins der beiden Schieberegister untereinander und dann mit dem Arduino verbunden sind. Die Datenleitung verläuft vom Digitalpin 6 des Arduino zum ersten Schieberegister und dann von dessen Pin 9 zu Pin 14 des zweiten.

Um Zahlen zwischen 0 und 99 darstellen zu können, brauchen wir einen komplizierteren Sketch. Bei Zahlen unter 10 können wir einfach die Zahl und dann eine 0 senden, sodass die rechte Anzeige die Zahl ausgibt und die linke nichts. Für Zahlen ab 10 müssen wir jedoch die beiden einzelnen Stellen bestimmen und getrennt an die beiden Schieberegister senden. Dazu verwenden wir die mathematische Modulo-Funktion.

Abb. 6–15 Schaltplan für Projekt 19

Modulo

Modulo ist eine Funktion, die den Rest einer Division zurückgibt. Beispielsweise ergibt 10 modulo 7 (oder kurz: 10 mod 7) 3, weil bei der Division von 10 durch 7 der Rest 3 übrig bleibt. Als Symbol für eine Modulo-Operation verwenden wir das Prozentzeichen. Das folgende Beispiel zeigt, wie diese Funktion in einem Sketch angewandt werden kann:

int a = 8;
int b = 3;
c = a % b;

In diesem Beispiel hat c den Wert 2. Diese Modulo-Funktion setzen wir nun ein, um die rechte Stelle einer zweistelligen Zahl zu bestimmen.

Um die Anzeige von ein- und zweistelligen Zahlen zu automatisieren, schreiben wir die Funktion displayNumber(). Wollen wir beispielsweise die Zahl 23 anzeigen, müssen wir als Erstes die linke Stelle isolieren, indem wir 23 durch 10 teilen, was 2 ergibt (und einen Bruchteil, den wir ignorieren). Anschließend bestimmen wir die rechte Stelle mit 23 modulo 10, was 3 ergibt.

// Projekt 19: Zwei Siebensegmentanzeigen steuern

#define DATA 6      // Verbindung mit Pin 14 am 74HC595
#define LATCH 8     // Verbindung mit Pin 12 am 74HC595
#define CLOCK 10    // Verbindung mit Pin 11 am 74HC595

void setup()
{
pinMode(LATCH, OUTPUT);
pinMode(CLOCK, OUTPUT);
pinMode(DATA, OUTPUT);
}

// Richtet das Array mit den Segmenten für 0 bis 9 und A bis F ein
// (aus Tab. 6–2)
int digits[] = {252, 96, 218, 242, 102, 182, 190, 224, 254, 246, 238, 62,
156, 122, 158, 142};

void displayNumber(int n)
{
int left, right=0;
if (n < 10)
{
digitalWrite(LATCH, LOW);
shiftOut(DATA, CLOCK, LSBFIRST, digits[n]);
shiftOut(DATA, CLOCK, LSBFIRST, 0);
digitalWrite(LATCH, HIGH);
}
else if (n >= 10)
{
right = n % 10;   // Rest der Division der anzuzeigenden Zahl
// durch 10
left = n / 10;    // Quotient aus der anzuzeigenden Zahl und 10
digitalWrite(LATCH, LOW);
shiftOut(DATA, CLOCK, LSBFIRST, digits[right]);
shiftOut(DATA, CLOCK, LSBFIRST, digits[left]);
digitalWrite(LATCH, HIGH);
}
}

void loop()
{
int i;
for ( i = 0 ; i < 100 ; i++ )
{
displayNumber(i);
delay(100);
}
}

Bei prüft die Funktion, ob die anzuzeigende Zahl kleiner als 10 ist. Wenn ja, werden die Daten für die Zahl und eine Leerstelle an die Schieberegister gesendet. Bei Zahlen ab 10 werden ihre Stellen bei mithilfe von Division und Modulo getrennt und dann separat an die Register übertragen. Schließlich richten wir in void loop() bei die Funktion zur Anzeige der Zahlen von 0 bis 99 ein und rufen sie auf.

Projekt Nr. 20: Ein Digitalthermometer konstruieren

In diesem Projekt ergänzen wir die Schaltung mit zweistelliger Zahlenanzeige aus Projekt 19 um den Temperatursensor TMP36 aus Kapitel 4, um ein Digitalthermometer zu bauen. Der Algorithmus ist einfach: Wir lesen die vom TMP36 zurückgegebenen Spannungswerte ab (mit den Methoden aus Projekt 12) und rechnen sie in Grad Celsius um.

Die Hardware

Sie benötigen folgende Teile:

• die Schaltung mit zweistelliger Zahlenanzeige aus Projekt 19

• einen Temperatursensor TMP36

Schließen Sie den mittleren Anschluss des TMP36 an den Analogpin 5 an, den linken an 5 V und den rechten an GND. Jetzt ist der Sensor bereit zur Messung.

Der Sketch

Der Sketch sieht wie folgt aus:

// Projekt 20: Ein Digitalthermometer konstruieren

#define DATA 6                       // Verbindung mit Pin 14 am 74HC595
#define LATCH 8                      // Verbindung mit Pin 12 am 74HC595
#define CLOCK 10                     // Verbindung mit Pin 11 am 74HC595

int temp = 0;
float voltage = 0;
float celsius = 0;
float sensor = 0;
int digits[]={252, 96, 218, 242, 102, 182, 190, 224, 254, 246, 238, 62,
156, 122, 158, 142};

void setup()
{
pinMode(LATCH, OUTPUT);
pinMode(CLOCK, OUTPUT);
pinMode(DATA, OUTPUT);
}

void displayNumber(int n)
{
int left, right = 0;
if (n < 10)
{
digitalWrite(LATCH, LOW);
shiftOut(DATA, CLOCK, LSBFIRST, digits[n]);
shiftOut(DATA, CLOCK, LSBFIRST, digits[0]);
digitalWrite(LATCH, HIGH);
}
if (n >= 10)
{
right = n % 10;
left = n / 10;
digitalWrite(LATCH, LOW);
shiftOut(DATA, CLOCK, LSBFIRST, digits[right]);
shiftOut(DATA, CLOCK, LSBFIRST, digits[left]);
digitalWrite(LATCH, HIGH);
}
}

void loop()
{
sensor = analogRead(5);
voltage = (sensor * 5000) / 1024; // Rechnet Sensorrohwert in mV
voltage = voltage - 500;          // um Entfernt Spannungsversatz
celsius = voltage / 10;           // Rechnet mV- in Celsiuswert
temp = int(celsius);              // um Ändert den Fließkommawert
// für die Temperatur
// in einen Integerwert
displayNumber(temp);
delay(500);
}

Der Sketch ist einfach und nutzt Code aus früheren Projekten, nämlich displayNumber() aus Projekt 19 und die Temperaturberechnungen aus Projekt 12. Die Funktion delay(500) in der zweitletzten Zeile verhindert, dass die Anzeige bei schwankender Temperatur zu schnell wechselt.

LED-Matrixanzeigen

Wenn Ihnen die Arbeit mit blinkenden LEDs Spaß gemacht hat, werden Sie LED-Matrixmodule wahrscheinlich lieben! Solche Bauteile bestehen aus LEDs, die in mehreren Zeilen und Spalten angeordnet sind und die Sie sowohl einzeln als auch gruppenweise steuern können. Das Modul, das wir als Beispiel verwenden, verfügt über insgesamt 64 rote LEDs in acht Zeilen und acht Spalten (siehe Abb. 6–16).

Abb. 6–16 Eine LED-Matrix

In diesem Projekt bauen wir eine Schaltung, für die wir mehrere Sketche schreiben, um unterschiedliche Effekte hervorzurufen.

Die LED-Matrix im Schaltplan

Wie Sie in Abbildung 6–17 erkennen können, sieht das Schaltplansymbol für eine Matrix ziemlich verwirrend aus.

Abb. 6–17 Das Schaltplansymbol für eine LED-Matrix

Beachten Sie, dass die Zeilen und Spalten nicht in derselben Reihenfolge durchnummeriert sind wie die darunter liegenden Pins (siehe die eingekreisten Pinnummern in Abb. 6–17). Auf der Unterseite der Matrix ist Pin 1 unten rechts markiert. In Abbildung 6–18 können Sie die kleine aufgedruckte 1 unter dem Pin erkennen.

Abb. 6–18 Die Pins einer LED-Matrix. Nr. 1 ist mit einer kleinen aufgedruckten 1 unten rechts markiert.

Die Pins der LED-Matrix sind im Uhrzeigersinn durchnummeriert, wobei Pin 8 unten links liegt und Pin 16 oben rechts. Wir steuern die Matrix mit zwei Schieberegistern vom Typ 74HC595 auf ähnliche Weise wie die Siebensegmentanzeigen in Projekt 19.

Abbildung 6–19 zeigt den Schaltplan für das Projekt. Die Widerstände R1 bis R8 weisen jeweils einen Wert von 560 Ω auf. Ein Schieberegister steuert die LED-Zeilen, das andere die Spalten. Die LED-Matrix (im Schaltplan nicht dargestellt) wird mit den Anschlüssen unten im Schaltplan verbunden. Die Pinbelegungen entnehmen Sie bitte Tabelle 6–3.

Pin am Zeilen-IC

Matrixpin

Pin am Spalten-IC

Matrixpin

15

9

15

13

1

14

1

3

2

8

2

4

3

12

3

10

4

1

4

6

5

7

5

11

6

2

6

15

7

5

7

16

Tab. 6–3 Tabelle für den Anschluss der Matrix an zwei 74HC595

Die Verbindungen herstellen

Stellen Sie die Verbindungen zwischen den Schieberegistern und der LED-Matrix her (vergessen Sie nicht die Widerstände zwischen den Ausgangspins des Schieberegisters für die Zeilen und den Zeilenpins der Matrix). Richten Sie sich dabei nach Tabelle 6–3.

Abb. 6–19 Schaltplan für den Anschluss einer LED-Matrix

Jetzt müssen wir die Matrix noch zum Leben erwecken. Das in Abbildung 6–19 mit »Zeilen« gekennzeichnete Schieberegister lässt Strom in die einzelnen Zeilen der Matrix fließen, während das mit »Spalten« markierte den Stromfluss von den Matrixspalten zu GND erlaubt. Im nächsten Projekt prüfen wir den Aufbau mit einem einfachen Sketch. Um eine LED einzuschalten, müssen wir die entsprechenden Zeilen- und Spaltenpins der Schieberegister ansteuern.

Bitarithmetik

Mit der Bitarithmetik können wir Integer- und Bytevariablen über ihre binäre Darstellung bearbeiten. Der Vorteil gegenüber der Berechnung mit Dezimalzahlen besteht darin, dass die digitalen Ein- und Ausgangspins hiermit schneller gesteuert werden können. Außerdem ist ein Vergleich von Zahlen in Binärform möglich.

Es gibt sechs Bitoperatoren: AND, OR, XOR, NOT, Links- und Rechtsverschiebung. In den folgenden Abschnitten werden sie genauer beschrieben. (In den Beispielen werden Binärzahlen angegeben, aber die gleichen Operationen lassen sich auch mit Integerwerten und Bytes durchführen.)

Der bitweise AND-Operator

Der Operator AND (&) dient dazu, zwei Binärzahlen Bit für Bit zu vergleichen. Sind die Bits an zwei übereinstimmenden Stellen beide 1, wird das entsprechende Bit des Ergebniswerts ebenfalls auf 1 gesetzt. Wenn nur eines oder gar keins der zwei Bits 1 ist, lautet das Ergebnisbit 0. Betrachten Sie als Beispiel folgende drei Bytevariablen:

byte a = B00110011;
byte b = B01010001;
byte c = 0;

Jetzt können wir folgenden Vergleich durchführen:

c = a & b;

Das Ergebnis ist 00010001. Dies wird deutlicher, wenn wir das Beispiel noch um einige Kommentare erweitern:

byte a = B00110011;
//        ||||||||
byte b = B01010001;
//        ||||||||
//        00010001 c = a & b; // c ist gleich a AND b

Der bitweise OR-Operator

Auch mit dem bitweisen OR-Operator (|) werden zwei Binärzahlen verglichen. Hier wird 1 allerdings nicht nur dann zurückgegeben, wenn beide Bits einer Stelle 1 sind, sondern wenn mindestens einer davon den Wert 1 hat. Sind beide Bits einer Stelle 0, wird 0 zurückgegeben.

Als Beispiel nehmen wir wieder dieselben Bytes wie zuvor:

byte a = B00110011;
byte b = B01010001;
byte c = 0;

Diesmal führen wir folgenden Vergleich durch:

c = a | b;

Das Ergebnis ist 01110011.

Der bitweise XOR-Operator

Der Operator XOR (^) gibt 1 zurück, wenn die Bits einer Stelle verschieden sind, anderenfalls 0.

Abermals betrachten wir unsere Beispielbytes:

byte a = B00110011;
byte b = B01010001;
byte c = 0;

Wiederum führen wir einen Vergleich durch:

c = a ^ b;

Das Ergebnis ist 01100110.

Der bitweise NOT-Operator

Der Operator NOT (~) kehrt einfach die Bits in allen Stellen um: Nullen werden zu Einsen und Einsen zu Nullen. Im folgenden Beispiel wenden wir das bitweise NOT auf Byte a an und speichern das Ergebnis in b:

byte a = B00111100;
byte b = 0;
b = ~a;

Jetzt enthält b den Wert 11000011.

Bitverschiebung nach links und rechts

Die Operatoren für die Verschiebung nach links (<<) und rechts (>>) versetzen die Bits um die angegebene Anzahl von Stellen nach links bzw. rechts. Nehmen wir an, wir wollen den Inhalt von a um vier Stellen nach links verschieben:

byte a = B00100101;
byte b = a << 4;

Als Ergebnis bekommen wir den Wert 01010000 in b. Die Bits von a werden um vier Plätze nach links versetzt und die leeren Stellen mit Nullen gefüllt.

Wir können die Verschiebung auch in die andere Richtung durchführen:

byte a = B11110001;
byte b = a >> 4;

Der Wert von b lautet jetzt 00001111.

Projekt Nr. 21: Eine LED-Matrix steuern

Der Zweck dieses Projekts besteht darin, die Verwendung einer LED-Matrix vorzuführen. Dazu schalten wir die LEDs in jeder zweiten Spalte und Zeile ein, wie Sie in Abbildung 6–20 sehen.

Abb. 6–20 Schachbrettvorlage für die Matrix

Um dieses Anzeigemuster zu erzielen, müssen wir B10101010 an das Schieberegister für die Zeilen und ~B10101010 an das für die Spalten senden. Die einzelnen Einsen und Nullen in den Bytes entsprechen den Zeilen bzw. Spalten der Matrix.

HINWEIS

Beachten Sie die Verwendung des bitweisen NOT-Operators im Spaltenbyte. Um eine LED einzuschalten, muss das zugehörige Zeilenbit 1 lauten – das Spaltenbit aber 0! Da in unseren Datenbytes jedoch immer eine 1 für eine eingeschaltete LED steht, müssen wir das Byte, das an das zweite, für die Spalten zuständige Schieberegister gesendet wird, mit NOT umkehren.

Um die Anzeige aus Abbildung 6–20 hervorzurufen, verwenden Sie folgenden Sketch:

// Projekt 21: Eine LED-Matrix steuern

#define DATA 6     // Verbindung mit Pin 14 am 74HC595
#define LATCH 8    // Verbindung mit Pin 12 am 74HC595
#define CLOCK 10   // Verbindung mit Pin 11 am 74HC595

void setup()
{
pinMode(LATCH, OUTPUT);
pinMode(CLOCK, OUTPUT);
pinMode(DATA, OUTPUT);
}

void loop()
{
digitalWrite(LATCH, LOW);
shiftOut(DATA, CLOCK, MSBFIRST, ~B10101010);   // Spalten
shiftOut(DATA, CLOCK, MSBFIRST, B10101010);    // Zeilen
digitalWrite(LATCH, HIGH);
do {} while (1); // Tut nichts
}

Das Ergebnis sehen Sie in Abbildung 6–21. Hier haben wir in allen Zeilen und Spalten jede zweite LED eingeschaltet, sodass sich ein Schachbrettmuster ergibt.

Abb. 6–21 Das Ergebnis von Projekt 21

Projekt Nr. 22: Bilder auf einer LED-Matrix anzeigen

Um ein Bild oder ein Muster auf der LED-Matrix anzuzeigen, brauchen wir eine Funktion, die eine LED nach der anderen einschaltet, das aber sehr schnell hintereinander, um die Trägheit des Auges auszunutzen. Dadurch nimmt der Betrachter für den Bruchteil einer Sekunde noch ein Nachbild wahr, nachdem das Bild eigentlich schon wieder verschwunden ist. Diesen Effekt können wir dafür ausnutzen, Bilder zu gestalten, indem wir die Matrix »abtasten«, um sehr schnell nacheinander eine LED-Zeile nach der anderen zu aktivieren. Diese Technik eignet sich sehr gut für Animationen, zur Anzeige von Daten und für verschiedene künstlerische Effekte.

In den nächsten beiden Projekten führen wir die Ansteuerung einzelner LEDs vor. Im folgenden Sketch nimmt die Funktion void setLED() eine Zeilen- und eine Spaltennummer und eine Einschaltdauer für die LED an. Anschließend wird diese Funktion genutzt, um willkürlich ausgewählte LEDs eine nach der anderen einzuschalten.

// Projekt 22: Bilder auf einer LED-Matrix anzeigen

#define DATA 6     // Verbindung mit Pin 14 am 74HC595
#define LATCH 8    // Verbindung mit Pin 12 am 74HC595
#define CLOCK 10   // Verbindung mit Pin 11 am 74HC595

void setup()
{
pinMode(LATCH, OUTPUT);
pinMode(CLOCK, OUTPUT);
pinMode(DATA, OUTPUT);
randomSeed(analogRead(0));
}

int binary[] = {1, 2, 4, 8, 16, 32, 64, 128};
int r, c = 0;

void setLED(int row, int column, int del)
{
digitalWrite(LATCH, LOW);
shiftOut(DATA, CLOCK, MSBFIRST, ~binary[column]);   // Spalten
shiftOut(DATA, CLOCK, MSBFIRST, binary[row]);       // Zeilen
digitalWrite(LATCH, HIGH);
delay(del);
}

void loop()
{
r = random(8);
c = random(8);
setLED(r, c, 1);   // Schaltet eine LED in einer willkürlichen Zeile
// und Spalte für 1 ms ein
}

Anstatt unmittelbar Binärzahlen an die Funktion shiftOut() zu senden, um zu steuern, welche Leuchtdioden eingeschaltet werden sollen, verwenden wir bei eine Nachschlagetabelle in Form des Arrays int binary[]. Sie enthält die dezimalen Entsprechungen der einzelnen Bits in den Bytes, die wir an die Schieberegister senden müssen. Um beispielsweise die LED in Zeile 4 und Spalte 4 einzuschalten, senden wir an beide Register binary[3] (dieses Element ist 8 oder binär B000010000). Für das Spaltenbyte müssen wir den Binärwert noch mit ~ umkehren. Das ist eine bequeme Möglichkeit, um die Zeilen- und Spaltennummern in einer Form darzustellen, mit der die Schieberegister etwas anfangen können. Dazu müssen Sie selbst nicht in Binärzahlen denken, sondern sich einfach nur ansehen, welche Zeile oder Spalte Sie einschalten möchten.

Wenn Sie Projekt 22 mit einer Verzögerung von 1 ms ausführen, gehen die LEDs so schnell an und aus, dass das Auge den Eindruck hat, dass mehrere gleichzeitig eingeschaltet sind, obwohl in Wirklichkeit immer nur eine leuchtet. Dies ist ein gutes Beispiel für die Illusionen, die die Trägheit des menschlichen Auges hervorruft. Sehen Sie sich dazu exemplarisch Abbildung 6–22 an.

Abb. 6–22 Eine Momentaufnahme von Projekt 22

Projekt Nr. 23: Ein Bild auf einer LED-Matrix darstellen

In diesem Projekt zeigen wir das Bild aus Abbildung 6–23 auf der LED-Matrix an.

Abb. 6–23 Das Muster für die Beispielanzeige

Die einzelnen Zeilen können wir als Binärzahlen darstellen, die wir dann in einem Array speichern:

byte smile[] = {B00000000,
B00000110,
B01000110,
B00000000,
B00011000,
B00000000,
B11000011,
B01111110};

Die Einsen in diesem Array entsprechen den eingeschalteten LEDs in dem Muster aus Abbildung 6–23. Mithilfe von Binärzahlen wird die Gestaltung von Bildern sehr einfach. Wenn Sie in der Funktion shiftOut() mit den Parametern MSBFIRST und LSBFIRST herumspielen, können Sie die einzelnen Zeilen spiegeln, wie Sie im Folgenden sehen werden. Bei verwenden wir eine for-Schleife, um nacheinander alle Zeilen anzuzeigen:

// Projekt 23: Ein Bild auf einer LED-Matrix darstellen

#define DATA 6     // Verbindung mit Pin 14 am 74HC595
#define LATCH 8    // Verbindung mit Pin 12 am 74HC595
#define CLOCK 10   // Verbindung mit Pin 11 am 74HC595

byte smile[] = {B00000000, B00000110, B01000110, B00000000, B00011000,
B00000000, B11000011, B01111110};
int binary[] = {1, 2, 4, 8, 16, 32, 64, 128};

void setup()
{
pinMode(LATCH, OUTPUT);
pinMode(CLOCK, OUTPUT);
pinMode(DATA, OUTPUT);
}

void loop()
{
int i;
for ( i = 0 ; i < 8 ; i++ )
{
digitalWrite(LATCH, LOW);
shiftOut(DATA, CLOCK, MSBFIRST, ~smile[a]);   // Spalten
shiftOut(DATA, CLOCK, LSBFIRST, binary[a]);   // Zeilen
digitalWrite(LATCH, HIGH);
delay(1);
}
}

Ergebnis ist ein blinzelnder Smiley, wie Abbildung 6–24 zeigt.

Abb. 6–24 Das Ergebnis von Projekt 23

Projekt Nr. 24: Eine LED-Matrix animieren

Mit ein bisschen Bitarithmetik können wir das Bild, das wir in Projekt 23 erstellt haben, in beliebiger Richtung aus der Anzeige herauswandern lassen. Um das Gesicht nach rechts zu verschieben, bis es ganz verschwunden ist, zeigen wir das Bild an, versetzen dann jedes Bit in der Zeile mit >> und zeigen das Bild erneut an.

Der Sketch

Der Sketch für das Animationsbeispiel sieht wie folgt aus:

// Projekt 24: Eine LED-Matrix animieren

#define DATA 6     // Verbindung mit Pin 14 am 74HC595
#define LATCH 8    // Verbindung mit Pin 12 am 74HC595
#define CLOCK 10   // Verbindung mit Pin 11 am 74HC595

byte smile[] = {B00000000, B00000110, B01000110, B00000000, B00011000,
B00000000, B11000011, B01111110};
int binary[] = {1, 2, 4, 8, 16, 32, 64, 128};

void setup()
{
pinMode(LATCH, OUTPUT);
pinMode(CLOCK, OUTPUT);
pinMode(DATA, OUTPUT);
}

void loop()
{
int a, hold, shift;
for ( shift = 0 ; shift < 9 ; shift++ )
{
for ( hold = 0 ; hold < 25 ; hold++ )
{
for ( a = 0 ; a < 8 ; a++ )
{
digitalWrite(LATCH, LOW);
shiftOut(DATA, CLOCK, MSBFIRST, ~smile[a]>>shift); // Spalten
shiftOut(DATA, CLOCK, LSBFIRST, binary[a]);        // Zeilen
digitalWrite(LATCH, HIGH);
delay(1);
}
}
}
}

Die for-Schleife bei hält das Bild für 25 Anzeigezyklen auf der Matrix. Die Variable shift gibt, um welchen Betrag jedes Byte nach rechts verschoben wird. Nach dem Durchlauf der Schleife wird shift bei um 1 erhöht. Daraufhin werden die Anzeigezyklen wiederholt und das Bild wandert um eine LED-Spalte nach rechts. Wenn Sie in der dritten for-Schleife bei die Parameter MSBFIRST und LSBFIRST austauschen, ändern Sie die Richtung, in die das Grinsgesicht läuft.

Ausblick

In diesem Kapitel haben Sie eine Menge grundlegender Fähigkeiten erworben, die Sie in Ihren eigenen Projekten immer wieder benötigen werden. LED-Anzeigen sind relativ robust, weshalb Sie ruhig mit ihnen herumexperimentieren können, um verschiedenartige Effekte zu erzeugen. Den Darstellungsmöglichkeiten sind jedoch Grenzen gesetzt, weshalb wir im nächsten Kapitel eine wesentlich detailliertere zur Anzeige von Text und Grafiken nutzen wollen.

7

Flüssigkristallanzeigen

In diesem Kapitel lernen Sie Folgendes:

• Anzeige von Text und numerischen Daten mit LCD-Zeichenmodulen

• Gestalten eigener Zeichen zur Wiedergabe auf LCD-Zeichenmodulen

• Anzeige von Text und Daten auf großen LCD-Grafikmodulen

• Erstellen einer grafischen Darstellung des von einem Thermometer gemessenen Temperaturverlaufs

Manchmal ist es erforderlich, dem Benutzer an anderer Stelle als dem Monitor des Desktop-Computers Informationen anzuzeigen. Eine der einfachsten und vielseitigsten Möglichkeiten dazu bieten LCD-Module (Liquid Crystal Display, Flüssigkristallanzeige). Auf LCD-Zeichenmodulen können Sie Text, selbst gestaltete Zeichen und numerische Daten wiedergeben, auf LCD-Grafikmodulen Bilder.

LCD-Zeichenmodule

Die preiswerteste und am einfachsten zu verwendende Variante von Flüssigkristallanzeigen sind Zeichenmodule, die Zeichen wie Buchstaben und Zahlen wiedergeben können. Es gibt sie in verschiedenen Größen, die nach Zeilenanzahl und der Anzahl darstellbarer Zeichen pro Zeile unterschieden werden. Manche verfügen über eine Hintergrundbeleuchtung und erlauben es, die Zeichen- sowie die Hintergrundfarbe auszuwählen. Jedes LCDModul mit HD44780- oder KS0066-kompatibler Schnittstelle sollte für die Arbeit mit dem Arduino geeignet sein. Als erstes Modell verwenden wir eines, das in zwei Zeilen je 16 Zeichen anzeigen kann und über eine Hintergrundbeleuchtung verfügt (siehe Abb. 7–1).

Das Trimmpotenziometer (der regelbare Widerstand für das LCD-Modul) hat einen Widerstand von 10 kΩ und wird zur Einstellung des Kontrasts verwendet. Die Pfostenleiste wird in den Löchern oben an der Anzeige festgelötet, um den Anschluss an eine Steckplatine zu vereinfachen. Diese Löcher sind von 1 bis 16 durchnummeriert, wobei Nr. 1 der Ecke des Moduls am nächsten liegt und im Schaltplan von Abb. 7–2 als VSS bezeichnet ist. (Dieser Anschluss wird mit GND verbunden.) Diesen Schaltplan verwenden wir für alle LCD-Beispiele in diesem Buch.

Ein LCD-Zeichenmodul in einem Sketch verwenden

Um das Zeichenmodul aus Abb. 7–1 verwenden zu können, müssen wir zuerst die erforderlichen Funktionen anhand eines einfachen Beispiels kennenlernen. Geben Sie den einfachen Sketch aus Listing 7–1 ein und laden Sie ihn hoch:

#include <LiquidCrystal.h>
LiquidCrystal lcd(4, 5, 6, 7, 8, 9); // Pins für RS, E, DB4, DB5, DB6, DB7

void setup()
{
lcd.begin(16, 2);
lcd.clear();
}

void loop()
{
lcd.setCursor(0, 5);
lcd.print("Hello");
lcd.setCursor(1, 6);
lcd.print("world!");
delay(10000);
}

Listing 7–1 Sketch zur LCD-Demonstration

Abb. 7–1 LCD-Modul mit Trimmpotenziometer und Pfostenleiste

Abb. 7–2 Grundlegender Schaltplan für den LCD-Anschluss

Abb. 7–3 zeigt das Ergebnis von Listing 7–1.

Abb. 7–3 LCD-Demonstration »Hello world!«

Sehen wir uns nun an, wie der Sketch aus Listing 7–1 funktioniert. Als Erstes müssen wir die Bibliothek für LCD-Module einschließen (die automatisch zusammen mit der Arduino-IDE installiert wird) und ihr mitteilen, welche Pins mit dem Arduino verbunden sind. Dazu fügen wir die beiden folgenden Zeilen vor der Methode setup() ein:

#include <LiquidCrystal.h>
LiquidCrystal lcd(4, 5, 6, 7, 8, 9); // Pins für RS, E, DB4, DB5, DB6, DB7

Wenn Sie andere Digitalpins des Arduino verwenden müssen, passen Sie die Nummern in der zweiten Zeile entsprechend an.

Als Nächstes müssen wir dem Arduino in void setup() mitteilen, wie groß die Flüssigkristallanzeige ist, also wie viele Zeilen und Spalten sie hat. Unser Beispielmodul hat zwei Zeilen zu je 16 Zeichen, weshalb wir Folgendes schreiben:

lcd.begin(16, 2);

Text anzeigen

Nachdem das LCD-Modul eingerichtet ist, müssen wir die Anzeige wie folgt leeren:

lcd.clear();

Anschließend platzieren wir wie folgt den Cursor, also den Ausgangspunkt für den Text:

lcd.setCursor(x, y);

Dabei gibt x die Spalte an (0 bis 15) und y die Zeile (0 oder 1). Um jetzt beispielsweise das Wort »Text« anzuzeigen, müssen Sie Folgendes eingeben:

lcd.print("text");

Damit sind Sie in der Lage, Text zu positionieren. Als Nächstes wollen wir Variablendaten anzeigen.

Variablen und Zahlen anzeigen

Um den Inhalt von Variablen auf dem LCD-Bildschirm anzuzeigen, verwenden Sie folgende Zeile:

lcd.print(variable);

Bei Fließkommavariablen können Sie angeben, wie viele Dezimalstellen ausgegeben werden sollen. Beispielsweise wird der Arduino im folgenden Beispiel mit lcd.print(pi, 3) angewiesen, den Wert von Pi auf drei Dezimalstellen genau anzuzeigen, wie Sie in Abb. 7–4 sehen:

float pi = 3.141592654;
lcd.print("pi: ");
lcd.print(pi, 3);

Abb. 7–4 Anzeige einer Fließkommazahl auf einem LCD-Bildschirm

Integerwerte können Sie auch in Hexadezimal- und in Binärform ausgeben, wie Listing 7–2 zeigt.

int zz = 170;
lcd.setCursor(0, 0);
lcd.print("Binary: ");
lcd.print(zz, BIN);     // Zeigt 170 in Binärform an
lcd.setCursor(0, 1);
lcd.print("Hexadecimal: ");
lcd.print(zz, HX);      // Zeigt 170 in Hexadezimalform an

Listing 7–2 Funktionen zur Anzeige von Binär- und Hexadezimalzahlen

Das LCD-Modul zeigt den Text wie in Abb. 7–5 an.

Abb. 7–5 Das Ergebnis von Listing 7–2

Projekt Nr. 25: Eigene Zeichen definieren

Neben den über die Tastatur verfügbaren Standardbuchstaben, -ziffern und -symbolen können Sie pro Sketch auch bis zu acht eigene Zeichen definieren. Im LCD-Modul besteht jedes Zeichen aus acht Zeilen zu je fünf Punkten oder Pixeln. In Abb. 7–6 sehen Sie eine Detailaufnahme.

Abb. 7–6 Jedes Zeichen besteht aus acht Zeilen zu je fünf Pixeln.

Um ein eigenes Zeichen anzeigen zu können, müssen Sie es erst in Form eines Arrays definieren. Für unseren Smiley können wir das folgende Array verwenden:

byte a[8] = { B00000,
B01010,
B01010,
B00000,
B00100,
B10001,
B01110,
B00000 };

Jede Zahl in diesem Array spricht ein einzelnes Pixel der Anzeige an. Mit 0 wird das entsprechende Pixel ausgeschaltet, mit 1 eingeschaltet. Die Elemente im Array stellen die Pixelzeilen der Anzeige dar, wobei das oberste Elemente für die oberste Zeile steht, das nächste für die zweite usw.

HINWEIS

Es kann sehr hilfreich sein, eigene Zeichen auf kariertem Papier zu entwerfen. Jedes ausgefüllte Kästchen müssen Sie dann im Array durch eine 1 darstellen und jedes leere durch eine 0.

In diesem Beispiel sind alle Pixel der obersten Zeile ausgeschaltet, da das erste Element B00000 lautet. In der zweiten Zeile wird mit B01010 jedes zweite Pixel eingeschaltet, wobei die Einsen für die oberen Teile der Augen stehen. Mit allen weiteren Zeilen und Pixeln wird das Zeichen weiter ausgefüllt.

Als Nächstes weisen Sie das Array mit der folgenden Funktion in void setup() der ersten von acht Möglichkeiten für eigene Zeichen zu:

lcd.createChar(0, a); // Weist das Array a[8] dem eigenen Zeichen Nr. 0 zu

Um das Zeichen anzuzeigen, fügen Sie in void loop() folgende Zeile ein:

lcd.write(0);

Insgesamt brauchen wir zur Anzeige unseres eigenen Zeichens folgenden Code:

// Projekt 25: Eigene Zeichen definieren
#include <LiquidCrystal.h>
LiquidCrystal lcd(4, 5, 6, 7, 8, 9); // pins for RS, E, DB4, DB5, DB6, DB7

byte a[8] = { B00000,
B01010,
B01010,
B00000,
B00100,
B10001,
B01110,
B00000 };

void setup()
{
lcd.begin(16, 2);
lcd.createChar(0, a);
}
void loop()
{
lcd.write(byte(0)); // Schreibt das eigene Zeichen Nr. 0
// an die nächste Cursorposition
}

Abb. 7–7 zeigt die Wiedergabe unseres Smileys auf dem LCD-Bildschirm.

Abb. 7–7 Das Ergebnis von Projekt 25

LCD-Zeichenmodule lassen sich einfach verwenden und bieten auch eine gewisse Vielseitigkeit. Mit unseren bisherigen Kenntnissen können wir damit zum Beispiel ein ausgefeiltes Digitalthermometer konstruieren, indem wir den LCD-Bildschirm mit der Temperaturmessung von Projekt 20 kombinieren. Wenn Sie jedoch sehr viele Daten oder grafische Elemente darstellen wollen, brauchen Sie ein LCD-Grafikmodul.

LCD-Grafikmodule

LCD-Grafikmodule sind größer und teurer als die Zeichenmodule, aber auch vielseitiger. Damit können Sie nicht nur Text anzeigen, sondern auch Linien, Punkte und Kreise usw. zeichnen, um grafische Effekte zu erzielen. In diesem Buch verwenden wir ein Modul mit 128 × 64 Pixeln und einer KS0108B-kompatiblen Schnittstelle (siehe Abb. 7–8).

Abb. 7–8 Ein LCD-Grafikmodul

Wie das Zeichen- weist auch das Grafikmodul ein Trimmpotenziometer mit 10 kΩ auf, das zur Einstellung des Kontrasts dient. Die Pfostenleiste wird an die Lochreihe unten an der Anzeige gelötet, um die Verbindung mit einer Steckplatine zu erleichtern. Die Löcher sind von 1 bis 20 durchnummeriert. Der Pin, der der Ecke des Moduls am nächsten liegt, ist Pin 1.

Das LCD-Grafikmodul anschließen

Bevor Sie das LCD-Grafikmodul verwenden können, müssen Sie erst 20 Verbindungen zwischen ihm und dem Arduino herstellen. Die erforderlichen Anschlüsse sind in Tab. 7–1 aufgeführt.

LCD-Pinnummer

Arduino-Pin

Funktion des LCD-Pins

1

5 V

VDD

2

GND

VSS (GND)

3

Mittelanschluss des
10-kΩ-Trimmpotenziometers

VO (Kontrast)

4

D8

DB0

5

D9

DB1

6

D10

DB2

7

D11

DB3

8

D4

DB4

9

D5

DB5

10

D6

DB6

11

D7

DB7

12

A0

CS2

13

A1

CS1

14

RST

RESET

15

A2

R/W

16

A3

D/I

17

A4

E

18

Äußerer Anschluss
des Trimmpotenziometers;
der andere liegt an 5 V

VEE (Trimmpotenziometer-Spannung)

19

5 V über einen
22-Ω-Widerstand

Anode (+)
der Hintergrund-LED

20

GND

Kathode (–)
der Hintergrund-LED

Tab. 7–1 Verbindungen vom LCD-Grafikmodul zum Arduino

Die Flüssigkristallanzeige verwenden

Nachdem Sie den LCD-Bildschirm verkabelt haben, können Sie die neueste Arduino-Bibliothek dafür von http://code.google.de/p/glcd-arduino/downloads/lists/ herunterladen und so installieren, wie es im Abschnitt »Sketche durch Bibliotheken erweitern« im nächsten Kapitel erklärt wird.

Um die Flüssigkristallanzeige zu verwenden, fügen Sie vor void setup() folgende Zeilen ein:

#include <glcd.h>                  // Schließt die LCD-Grafikbibliothek ein
#include "fonts/SystemFont5x7.h"   // Schließt die Standardschriftarten
// dafür ein

Fügen Sie anschließend hinter void setup() die folgenden Zeilen hinzu, um die Anzeige vorzubereiten:

GLCD.Init(NON _ INVERTED);     // Verwenden Sie stattdessen INVERTED,
// um die Pixeldarstellung zu invertieren
GLCD.SelectFont(System5x7);    // Wählt eine Schriftart aus
GLCD.ClearScreen();            // Leert den LCD-Bildschirm

Die Anzeige steuern

Der Bildschirm des LCD-Grafikmoduls kann bis zu acht Zeilen mit je 20 Zeichen Text anzeigen. Um den Textcursor zu positionieren, geben Sie Folgendes ein, wobei Sie x und y durch die gewünschten Koordinaten ersetzen müssen:

GLCD.CursorTo(x,y);

Um Ihren Text anzuzeigen, geben Sie ihn im folgenden Code anstelle des Platzhalters Text ein:

GLCD.Puts("Text");

Wollen Sie einen Integer anzeigen, verwenden Sie den folgenden Code und ersetzen dabei Zahl durch den gewünschten Wert:

GLCD.PrintNumber(Zahl);

Projekt Nr. 26: Textfunktionen in Aktion

Der folgende Sketch führt die Textfunktionen vor:

// Projekt 26: Textfunktionen in Aktion
#include <glcd.h>                  // Schließt die LCD-Grafikbibliothek ein
#include "fonts/SystemFont5x7.h"   // Schließt die Standardschriftarten
// dafür ein

int j = 7;

void setup()
{
GLCD.Init(NON _ INVERTED);
GLCD.ClearScreen();
GLCD.SelectFont(System5x7);
}

void loop()
{
GLCD.ClearScreen();
GLCD.CursorTo(1, 1);
GLCD.Puts("Hello, world.");
GLCD.CursorTo(1, 2);
GLCD.Puts("I hope you are ");
GLCD.CursorTo(1, 3);
GLCD.Puts("enjoying this");
GLCD.CursorTo(1, 4);
GLCD.Puts("book. ");
GLCD.CursorTo(1, 5);
GLCD.Puts("This is from ");
GLCD.CursorTo(1, 6);
GLCD.Puts("chapter ");
GLCD.PrintNumber(j);
GLCD.Puts(".");
do {} while (1);
}

Dieser Sketch sorgt für die Ausgabe, die Sie in Abb. 7–9 sehen.

Abb. 7–9 Die Ausgabe von Projekt 26

Aufwändigere Anzeigeeffekte hervorrufen

Als Nächstes sehen wir uns einige Funktionen für grafische Anzeigeeffekte an. Denken Sie daran, dass der LCD-Bildschirm zwar eine Auflösung von 128 Spalten zu 64 Pixeln hat, dass diese Elemente in den verschiedenen Funktionen aber von 0 bis 127 und (von oben nach unten) von 0 bis 63 angesprochen werden.

Die folgende Grafikfunktion schaltet ein einzelnes Pixel an der Position x, y ein (wenn Sie als Farbe BLACK angeben) bzw. aus (Farbe WHITE):

GLCD.SetDot(x, y, Farbe); // Farbe ist BLACK oder WHITE

Die nächste Funktion zeichnet ein Rechteck, wobei x, y die obere linke Ecke angibt, w die Breite, h die Höhe und Farbe die Farbe der Umrisslinie. Der Inhalt wird dann in der jeweils anderen Farbe dargestellt.

GLCD.DrawRect(x, y, w, h, Farbe);

Die gleichen Parameter gelten auch für die folgende Funktion, die ein ausgefülltes Rechteck zeichnet:

GLCD.FillRect(x, y, w, h, Farbe);

Mit der folgenden Funktion zeichnen Sie ein Rechteck mit abgerundeten Ecken des Radius r. Die anderen Parameter sind die gleichen wie bei den vorherigen Funktionen.

GLCD.DrawRoundRect(x, y, w, h, r, Farbe);

Die nächste Funktion zeichnet einen Kreis mit dem Mittelpunkt x, y und einem Radius von r Pixeln:

GLCD.DrawCircle(x, y, r, Farbe);

Um eine vertikale Linie zu zeichnen, die beim Punkt x, y beginnt und die Länge von l Pixeln aufweist, verwenden Sie folgende Funktion:

GLCD.DrawVertLine(x, y, l, Farbe);

Eine entsprechende Funktion gibt es natürlich auch für horizontale Linien:

GLCD.DrawHoriLine(x, y, l, Farbe);

Mit diesen Funktionen und etwas Vorstellungskraft können Sie eine Reihe von Effekten hervorrufen oder Daten grafisch darstellen. Im nächsten Abschnitt bauen wir unser Digitalthermometer mithilfe eines LCD-Bildschirms und einiger dieser Funktionen weiter aus.

Projekt Nr. 27: Eine Temperaturverlaufskurve aufzeichnen

In diesem Projekt wollen wir die Temperatur alle 20 Minuten messen und die letzten 100 Messwerte als Liniendiagramm ausgeben. Jeder Messwert wird durch ein Pixel dargestellt, wobei die Temperatur auf der vertikalen Achse gegen die Zeit auf der horizontalen aufgetragen wird. Links steht der aktuelle Wert, und die Anzeige der Messungen läuft beständig von links nach rechts. Die aktuelle Temperatur wird auch numerisch angezeigt.

Der Algorithmus

Dieses Projekt hört sich zwar kompliziert an, ist aber ziemlich einfach und erfordert nur die Verwendung von zwei Funktionen. Die erste ruft den Temperaturmesswert vom TMP36 ab und speichert ihn in einem Array aus 100 Werten. Sobald eine neue Messung in das Array aufgenommen wird, werden die vorherigen 99 nach unten verschoben, um Platz zu machen, wobei die älteste gelöscht wird. Die zweite Funktion zeichnet auf den LCD-Bildschirm. Sie zeigt die aktuelle Temperatur, die Skala für den Graphen und die Positionen der einzelnen Pixel für die Temperaturwerte im Zeitverlauf an.

Die Hardware

Für dieses Projekt brauchen Sie folgende Teile:

• ein KSB0108B-LCD-Grafikmodul mit einer Auflösung von 128 × 64 und Anschlusspins für eine Steckplatine

• ein 10-kΩ-Trimmpotenziometer

• einen Temperatursensor TMP36

• eine Steckplatine

• Verbindungsdrähte

• Arduino und USB-Kabel

Schließen Sie das LCD-Grafikmodul wie in Tab. 7–1 beschrieben an und verbinden Sie den TMP36-Sensor mit 5 V, dem Analogpin 5 und GND.

Der Sketch

Geben Sie den folgenden Sketch ein und laden Sie ihn hoch. Er enthält auch erklärende Kommentare über die verwendeten Funktionen.

// Projekt 27: Eine Temperaturverlaufskurve aufzeichnen
#include <glcd.h>                  // Schließt die LCD-Grafikbibliothek ein
#include "fonts/SystemFont5x7.h"   // Schließt die Standardschriftarten
// dafür ein
int tcurrent;
int tempArray[100];

void setup()
{
GLCD.Init(NON _ INVERTED);     // Konfiguriert das LCD-Grafikmodul
GLCD.ClearScreen();            // Schaltet alle LCD-Pixel aus
GLCD.SelectFont(System5x7);
}

void getTemp() // Liest die Temperatur vom TMP36
{
float sum = 0;
float voltage = 0;
float sensor = 0;
float celsius;

// Liest den Temperatursensor ab und rechnet das Ergebnis
// in Celsiuswerte um
sensor = analogRead(5);
voltage = (sensor * 5000) / 1024;
voltage = voltage - 500;

celsius = voltage / 10;
tcurrent = int(celsius);

// Fügt den neuen Temperaturwert am Anfang des Temperatur-Arrays ein
for (int a = 99 ; a >= 0 ; --a )
{
tempArray[a] = tempArray[a-1];
}
tempArray[0] = tcurrent;
}

void drawScreen() // Zeichnet auf den LCD-Bildschirm
{
int q;
GLCD.ClearScreen();
GLCD.CursorTo(5, 0);
GLCD.Puts("Current:");
GLCD.PrintNumber(tcurrent);
GLCD.CursorTo(0, 1);
GLCD.PrintNumber(40);
GLCD.CursorTo(0, 2);
GLCD.PrintNumber(32);
GLCD.CursorTo(0, 3);
GLCD.PrintNumber(24);
GLCD.CursorTo(0, 4);
GLCD.PrintNumber(16);
GLCD.CursorTo(1, 5);
GLCD.PrintNumber(8);
GLCD.CursorTo(1, 6);
GLCD.PrintNumber(0);
for (int a = 28 ; a < 127 ; a++)
{
q = (55 - tempArray[a-28]);
GLCD.SetDot(a, q, BLACK);
}
}

void loop()
{
getTemp();
drawScreen();
for (int a = 0 ; a < 20 ; a++)    // Wartet 20 Minuten bis zur
// nächsten Messung
{
delay(60000);                  // Wartet 1 Minute
}
}

Das Ergebnis

Die Anzeige sieht jetzt ähnlich wie in Abb. 7–10 aus.

Abb. 7–10 Das Ergebnis von Projekt 27

Den Sketch ändern

Manche Menschen können Daten besser in grafischer als in numerischer Form verstehen. Mit Projekten dieser Art können Sie auch andere Daten darstellen, etwa die Spannung von Sensoren, die an analogen Eingangspins gemessen wird. Es ist auch möglich, einen zweiten Temperatursensor hinzuzufügen und beide Werte gleichzeitig anzuzeigen. Fast alles, was einen Wert zurückgibt, lässt sich auf einem LCD-Grafikmodul ausgeben.

Ausblick

Angesichts der Erfahrungen, die Sie jetzt mit LCD-Bildschirmen gemacht haben, können Sie deutlich sehen, dass der Arduino tatsächlich ein Kleincomputer ist: Er kann eingehende Daten entgegennehmen, verarbeiten und der Außenwelt präsentieren. Das ist aber erst der Anfang. Im nächsten Kapitel werden Sie Ihre eigenen Arduino-Shields bauen, Daten auf microSDSpeicherkarten aufzeichnen und die Nutzung von Bibliotheken und Arduino-Funktionen zeitbezogen kennenlernen.

8

Den Arduino erweitern

Im diesem Kapitel lernen Sie Folgendes:

• Die umfangreiche Auswahl an Arduino-Shields

• Konstruktion eines eigenen Arduino-Shields mithilfe eines ProtoShields

• Erweitern des Funktionsumfangs mit Arduino-Bibliotheken

• Aufzeichnen von Daten auf microSD-Karten zur späteren Analyse in einem Tabellenkalkulationsprogramm

• Konstruktion eines Geräts zur Temperaturaufzeichnung

• Konstruktion einer Stoppuhr mit micros() und millis()

• Interrupts und ihre Verwendung

Wir werden uns ansehen, wie Sie Ihren Arduino mit verschiedenen Shields erweitern und wie Sie einen eigenen Shield bauen können. Wenn Sie mehr Erfahrungen mit Elektronik und dem Arduino haben, können Sie dauerhafte Schaltungen auf einer leeren Platine – dem ProtoShield – aufbauen.

Einer der nützlichsten Shields ist der für microSD-Karten. In diesem Kapitel verwenden wir ihn für ein Gerät, das den zeitlichen Verlauf der Temperatur aufzeichnet, um die Daten vom Arduino zu speichern und zur weiteren Analyse an ein anderes Gerät zu übertragen.

Des Weiteren lernen Sie die Funktionen micros() und millis() kennen, die sehr nützlich für die zeitliche Abstimmung sind, wie Sie im Stoppuhr-Projekt sehen werden. Schließlich werden wir uns auch mit Interrupts beschäftigen.

Shields

Durch den Anschluss von Shields können Sie den Funktionsumfang Ihres Arduino erweitern. Ein Shield ist eine Platine, die auf die Anschlüsse an den Seiten der Platine aufgesteckt wird. Auf dem Markt sind Hunderte verschiedener Shields zu finden. Sehr beliebt ist es, mit einem GPS- und einem microSD-Shield ein Gerät zu bauen, das Ortsdaten im Zeitverlauf protokolliert und speichert, z. B. die im Auto zurückgelegte Strecke oder den Verlauf eines neuen Wanderwegs. Ebenfalls weit verbreitet sind Ethernet-Netzwerkadapter, mit denen der Arduino Zugriff auf das Internet bekommt (siehe Abb. 8–1).

Abb. 8–1 Ein Ethernet-Shield auf einem Arduino Uno

Mit einem GPS-Satellitenempfänger können Sie den Standort des Arduino verfolgen (siehe Abb. 8–2). Eine microSD-Schnitstelle erlaubt es, Daten vom Arduino auf einer Speicherkarte abzulegen (siehe Abb. 8–3).

Arduino-Shields sind stapelbar gebaut und können gewöhnlich in Kombination miteinander verwendet werden. Beispielsweise sehen Sie in Abbildung 8–4 einen Stapel aus einem Arduino Uno, einem microSD-Shield zur Datenspeicherung, einem Ethernet-Shield für die Verbindung zum Internet und einem LCD-Shield zur Anzeige von Informationen.

Abb. 8–2 GPS-Empfänger-Shield (mit separatem GPS-Modul) auf einem Arduino Uno

Abb. 8–3 Shield für microSD-Karten

Abb. 8–4 Drei gestapelte Shields auf einem Arduino Uno

WARNUNG

Achten Sie beim Stapeln von Shields darauf, dass die einzelnen Digital- und Analogpins nicht gleichzeitig von mehreren Shields verwendet werden. Wenn mehrere Shields dieselben Pins für unterschiedliche Funktionen nutzen, kann das den Gesamtaufbau beschädigen. Die Anbieter von Shields sollten normalerweise Informationen darüber bereitstellen, welche Pins ihre Produkte jeweils verwenden. Eine großartige, von der Community unterhaltene Liste von Shields mit Angabe der Shield-Pins finden Sie auf http://www.shieldlist.org/.

ProtoShield

Sie können online eine große Vielfalt an Shields erwerben (siehe z. B. http://www.shieldlist.org/), aber auch einen eigenen bauen. Dazu brauchen Sie einen ProtoShield, der sowohl vorgefertigt als auch als Bausatz verkauft wird (siehe Abb. 8–5).

Abb. 8–5 ProtoShield-Bausatz

Ein ProtoShield eignet sich auch gut als Fundament für eine Steckplatine, denn er sorgt dafür, dass Ihre Schaltung die physischen Abmessungen des Arduino nicht überschreitet (wie Sie bei dem Ampelthermometer in Abb. 8–6 sehen). Kleine Steckplatinen, die zwischen die Anschlussleisten passen, können Sie zur vorübergehenden Montage mit Modellbaukitt befestigen, für eine dauerhafte Verwendung auch mit doppelseitigem Klebeband. Ein ProtoShield kann auch als endgültiges Fundament für Schaltungen dienen, die Sie zuvor auf einer Steckplatine ausprobiert haben.

Abb. 8–6 Das Thermometer mit Ampelanzeige aus Projekt 8

Eigene Schaltungen auf einem ProtoShield aufzubauen, erfordert genaue Planung. Dazu müssen Sie die Schaltung entwerfen, den Schaltplan zeichnen und die Anordnung der Bauteile auf dem ProtoShield planen. Dann löten Sie die fertige Schaltung zusammen. Zuvor aber sollten Sie sie immer auf einer Steckplatine ausprobieren, um sicherzustellen, dass sie auch funktioniert. Für einige ProtoShield-Modelle gibt es passende Schaltplanvorlagen im PDF-Format, die Sie herunterladen und ausdrucken können, um darauf den Schaltplan für Ihr Projekt anzulegen.

Projekt Nr. 28: Einen eigenen Shield mit acht LEDs konstruieren

In diesem Projekt bauen wir einen eigenen Shield mit acht LEDs und Widerständen zur Strombegrenzung. Dieser Shield erleichtert Experimente mit LEDs an digitalen Ausgängen.

Die Hardware

Für dieses Projekt brauchen Sie folgende Teile:

• einen leeren Arduino-ProtoShield

• acht LEDs beliebiger Farbe

• acht 560-Ω-Widerstände (R1 bis R8)

• zwei stapelbare Arduino-Pfostenleisten mit sechs Anschlüssen

• zwei stapelbare Arduino-Pfostenleisten mit acht Anschlüssen

Der Schaltplan

Den Schaltplan sehen Sie in Abbildung 8–7.

Abb. 8–7 Schaltplan für Projekt 28

Die Struktur der ProtoShield-Platine

Der nächste Schritt besteht darin, sich mit der Anordnung der Löcher auf dem ProtoShield vertraut zu machen. Die Zeilen und Spalten auf dem ProtoShield sollten mit denen auf der Steckplatine des Arduino übereinstimmen. Auf dem leeren ProtoShield in Abbildung 8–8 sind die Löcher, die elektrisch leitend verbunden sind, mit schwarzen Linien umrandet.

Abb. 8–8 Aufsicht auf einen leeren ProtoShield

Die lange horizontale Reihe unter den Digitalpins ist mit dem 5-Volt-Anschluss verbunden, die horizontale Reihe über die Analog- und sonstigen Pins mit GND. Die Löcher dazwischen sind alle voneinander isoliert. Darüber hinaus gibt es noch zwei weitere Anschlussreihen, nämlich ganz oben und ganz unten am ProtoShield: Die obere besteht aus zwei Gruppen zu acht Kontakten, die untere aus zwei Gruppen zu sechs. Hier löten Sie die Pfostenleisten an, über die der ProtoShield auf den Arduino aufgesteckt wird.

Der Entwurf

Entwerfen Sie Ihre Schaltung auf kariertem Papier, wie Sie in Abbildung 8–9 sehen.

Abb. 8–9 Den Shield planen

Nachdem Sie den Plan für Ihre Schaltung gezeichnet haben, stecken Sie die Bauteile versuchsweise auf dem ProtoShield auf, um sich zu vergewissern, dass sie auch passen und dass die Platine nicht überfüllt ist. Wenn Sie Platz für einen Reset-Schalter haben, sollten Sie ihn vorsehen, da der Shield den Zugang zur Reset-Taste des Arduino blockiert.

Die Bauteile festlöten

Wenn Sie mit dem Aufbau Ihrer Schaltung auf dem ProtoShield zufrieden sind und geprüft haben, dass er funktioniert, können Sie die Bauteile festlöten. Der Umgang mit einem Lötkolben ist gar nicht so schwer, und für diese Art von Arbeit brauchen Sie auch keine teure Ausrüstung. Ein einfacher Lötkolben mit einer Nennleistung von 25 bis 40 W, wie Sie ihn in Abbildung 8–10 sehen, reicht aus.

Abb. 8–10 Ein Lötkolben

HINWEIS

Wenn Sie noch keine Erfahrung mit Lötarbeiten haben, sollten Sie die Anleitung in Comicform von http://mightyohm.com/soldercomic/ herunterladen und lesen.

Beim Löten müssen Sie einige der Bauteile über eine Lötbrücke mit einer geringen Menge Lötzinn verbinden, wie Abbildung 8–11 zeigt. Wie Sie sehen, ist ein Ende eines Widerstands jeweils mit der Anode der zugehörigen LED verbunden.

Abb. 8–11 Eine Lötbrücke

Prüfen Sie alle Lötverbindungen, sobald Sie sie hergestellt haben, denn es ist einfacher, Fehler zu finden und zu korrigieren, bevor das gesamte Projekt fertig gestellt ist. Wenn Sie die vier Pfostenleisten anlöten, halten Sie sie währenddessen mit einem anderen Shield an Ort und Stelle, wie Abbildung 8–12 zeigt.

Abb. 8–12 Anlöten der Pfostenleisten

Abbildung 8–13 zeigt das fertige Produkt: einen selbst konstruierten Arduino-Shield mit acht LEDs.

Abb. 8–13 Der fertige Shield

Den selbst gebauten Shield ändern

Diesen einfachen Shield können wir in komplizierteren Projekten verwenden, z. B. um den Status der Digitalpins 0 bis 7 zu überwachen. Wenn Sie weitere sechs Widerstände und LEDs hinzufügen, können Sie damit sämtliche digitale Ausgänge beobachten. Es gibt viele verschiedene Möglichkeiten, um diesen Shield einzusetzen. Nutzen Sie Ihre Vorstellungskraft!

Sketche durch Bibliotheken erweitern

So wie Sie mit einem Arduino-Shield die Hardware erweitern, können Sie Ihre Sketche mithilfe einer Bibliothek um nützliche Funktionen für bestimmte Aufgaben oder für die Ansteuerung herstellerspezifischer Hardware ergänzen. Jeder kann eine Bibliothek erstellen, und tatsächlich schreiben die Hersteller mancher Arduino-Shields eigene Bibliotheken für ihre Hardware.

Die Arduino-IDE umfasst bereits einen Satz vorinstallierter Bibliotheken. Um sie in Ihre Sketche einzuschließen, wählen Sie Sketch > Import Library, woraufhin eine Aufstellung dieser Bibliotheken angezeigt wird, darunter Ethernet, LiquidCrystal, Servo usw. Viele dieser Namen sind selbsterklärend. Wenn Sie für eines der Projekte in diesem Buch eine Bibliothek benötigen, wird diese genau erklärt.

Die Bibliotheken für einen Shield importieren

Wenn Sie einen Shield kaufen, müssen Sie gewöhnlich die zugehörigen Bibliotheken von der Website des Herstellers oder über einen angegebenen Link herunterladen.

Um Ihnen zu zeigen, wie das geht, wollen wir die Bibliothek für den microSD-Shield aus Abbildung 8–3 herunterladen.

1. Öffnen Sie die Website http://code.google.com/p/sdfatlib/downloads/list/, die Sie in Abbildung 8–14 sehen.

Abb. 8–14 Die Seite mit den verschiedenen Versionen der Bibliothek

2. Klicken Sie in der Liste der Dateinamen auf der linken Seite auf die jüngste Version der Bibliothek. Dadurch wird die Downloadseite aus Abbildung 8–15 geöffnet.

Abb. 8–15 Die Downloadseite für die Bibliothek

3. Klicken Sie auf den Dateinamen mit der Endung .zip. Daraufhin sollte der Download beginnen. Nachdem Sie die Bibliothek vollständig heruntergeladen haben, installieren Sie sie anhand der folgenden Anweisungen in Ihrem Betriebssystem.

Installation unter Mac os x

Wenn Sie die Datei auf ein Mac OS X-System heruntergeladen haben, gehen Sie folgendermaßen vor:

1. Öffnen Sie den Ordner Downloads auf Ihrem Mac und suchen Sie die heruntergeladene .zip-Datei (siehe Abb. 8–16).

Abb. 8–16 Die Bibliotheksdatei im Download-Ordner

2. Doppelklicken Sie auf das Ordnersymbol der heruntergeladenen Datei, um den Inhalt anzuzeigen. Suchen Sie darin nach dem Ordner SdFat (siehe Abb. 8–17).

Abb. 8–17 Der Ordner der heruntergeladenen Bibliothek

3. Kopieren Sie den Ordner SdFat aus dem Fenster in Abbildung 8–17 in Ihren Ordner Arduino/libraries (siehe Abb. 8–18).

Abb. 8–18 Fertigstellen der Installation

4. Stellen Sie sicher, dass die Bibliothek SdFat installiert und verfügbar ist, indem Sie die IDE-Software neu starten und Sketch > Import Library wählen. In der Liste sollte SdFat zu sehen sein. (Wenn nicht, versuchen Sie erneut die Installation durchzuführen.)

Nachdem Sie die Bibliothek installiert haben, blättern Sie vor zum Abschnitt »microSD-Speicherkarten« auf Seite 192.

installation unter Windows xp und höher

Wenn Sie die Datei auf einen PC mit Windows XP oder höher heruntergeladen haben, gehen Sie folgendermaßen vor:

1. Nachdem der Download abgeschlossen ist, öffnen Sie den heruntergeladenen Ordner, um seinen Inhalt anzuzeigen, und suchen darin nach dem Ordner SdFat (siehe Abb. 8–19).

Abb. 8–19 Der Ordner der heruntergeladenen Bibliothek

2. Kopieren Sie den Ordner SdFat aus dem Fenster in Abbildung 8–19 in Ihren Ordner Arduino/libraries (siehe Abb. 8–20).

Abb. 8–20 Fertigstellen der Installation

3. Stellen Sie sicher, dass die Bibliothek SdFat installiert und verfügbar ist, indem Sie die IDE-Software neu starten und Sketch > Import Library wählen. In der Liste sollte SdFat zu sehen sein. (Wenn nicht, versuchen Sie erneut die Installation durchzuführen.)

Nachdem Sie die Bibliothek installiert haben, blättern Sie vor zum Abschnitt »microSD-Speicherkarten« auf Seite 192.

installation unter Ubuntu Linux 11.04 und höher

Wenn Sie die Datei auf einen Computer mit Ubuntu Linux 11.04 oder höher heruntergeladen haben, gehen Sie folgendermaßen vor:

1. Suchen Sie die heruntergeladene Datei und doppelklicken Sie darauf. Daraufhin wird der Archiv-Manager mit dem Ordner SdFat geöffnet (siehe Abb. 8–21).

Abb. 8–21 Der Ordner der heruntergeladenen Bibliothek

2. Rechtsklicken Sie in dem Fenster in Abbildung 8–21 auf den Ordner SdFat und klicken Sie auf Extrahieren, um ihn im Ordner /libraries auszupacken (siehe Abb. 8–22).

Abb. 8–22 Das Ziel des Bibliotheksordners

3. Stellen Sie sicher, dass die Bibliothek SdFat installiert und verfügbar ist, indem Sie die IDE-Software neu starten und Sketch > Import Library wählen. In der Liste sollte SdFat zu sehen sein. (Wenn nicht, versuchen Sie erneut die Installation durchzuführen.)

Nachdem Sie die Bibliothek installiert haben, können Sie mit dem nächsten Abschnitt fortfahren.

microSD-Speicherkarten

Auf microSD-Karten können Sie Daten aus vielen Quellen festhalten, z. B. von dem Temperatursensor TMP36, den wir in Kapitel 4 verwendet haben. Sie können auch Webserverdaten oder irgendwelche andere Daten darauf ablegen, die Sie für ein Projekt brauchen. Um Daten aufzuzeichnen und zu speichern, benötigen Sie einen microSD-Shield, der microSD-Karten (keine microSDHC-Karten!) mit einer Kapazität bis zu 2 GB lesen und beschreiben kann (siehe Abb. 8–23).

Abb. 8–23 Eine microSD-Karte mit einer Kapazität von 2 GB

Bei beliebten Händlern wie SparkFun, Adafruit Industries und Snootlab können Sie verschiedene Speicherkarten-Shields erwerben. Der in diesem Buch verwendete Shield (siehe Abb. 8–3) stammt von SparkFun (Teilenummern DEV-09802 und PRT-10007).

HINWEIS

Bevor Sie eine Speicherkarte in einem Shield verwenden können, müssen Sie sie zunächst formatieren. Schließen Sie die Karte dazu an einen Computer an und folgen den Anweisungen des Betriebssystems zur Formatierung. Achten Sie darauf, dass Sie den Formatierungstyp FAT16 verwenden! Bei manchen Shields müssen Sie auch die Pfostenleisten anlöten. Richten Sie sich dabei nach der Anleitung im Abschnitt »Die Bauteile festlöten« auf Seite 186.

Die microSD-Karte prüfen

Nachdem Sie die microSD-Karte formatiert und den Shield zusammengebaut haben, müssen Sie nachprüfen, ob auch alles richtig funktioniert. Dazu gehen Sie folgendermaßen vor:

1. Schließen Sie den Shield an den Arduino an, legen Sie die Speicherkarte ein und verbinden Sie den Arduino über das USB-Kabel mit dem Computer.

2. Führen Sie die IDE aus und wählen Sie File > Examples > SdFat > SdInfo. Laden Sie den Sketch SdInfo hoch, der daraufhin in der IDE angezeigt wird.

3. Öffnen Sie den seriellen Monitor, stellen Sie die Übertragung auf 9600 Baud ein, drücken Sie eine beliebige Taste und dann . Nach einem Augenblick werden Daten über die microSD-Karte angezeigt, wie Sie in Abbildung 8–24 sehen.

Wenn auf dem seriellen Monitor keine Testergebnisse angezeigt werden, versuchen Sie Folgendes, um das Problem zu lösen:

• Lösen Sie die USB-Verbindung vom Arduino, nehmen Sie die microSDKarte aus dem Shield und setzen Sie sie erneut ein.

• Stellen Sie sicher, dass die Pfostenleisten sauber eingelötet und die Anschlüsse nicht kurzgeschlossen sind.

• Stellen Sie sicher, dass die Übertragungsrate des seriellen Monitors 9600 Baud beträgt und dass Sie eine reguläre Platine verwenden, die mit dem Arduino Uno kompatibel ist. Beim Mega und einigen anderen Platinenmodellen befinden sich die SPI-Pins an einer anderen Stelle.

• Formatieren Sie die microSD-Karte neu.

Abb. 8–24 Ergebnisse eines erfolgreichen microSD-Kartentests

Projekt Nr. 29: Daten auf die Speicherkarte schreiben

Um Daten auf eine Speicherkarte zu schreiben, schließen Sie den Shield an, fügen eine microSD-Karte ein, geben folgenden Sketch ein und laden ihn hoch:

// Projekt 29: Daten auf die Speicherkarte schreiben

int b = 0;

#include <SD.h>

void setup()
{
Serial.begin(9600);
Serial.print("Initializing SD card...");
pinMode(10, OUTPUT);

// Prüft, ob die microSD-Karte vorhanden und verwendbar ist
if (!SD.begin(8))
{
Serial.println("Card failed, or not present");
// Hält die Ausführung des Sketches an
return;

}
Serial.println("microSD card is ready");
}

void loop()
}
// Erstellt die Datei, in die geschrieben werden soll
File dataFile = SD.open("DATA.TXT", FILE _ WRITE);
// Schreibt in die Datei, wenn sie bereit ist
if (dataFile)
{
for ( int a = 0 ; a < 11 ; a++ )
{
dataFile.print(a);
dataFile.print(" multiplied by two is ");
b = a * 2;
dataFile.println(b, DEC);
}
dataFile.close();    // Schließt die Datei, wenn das System mit
// der Bearbeitung fertig ist (obligatorisch)
}
// Zeigt eine Fehlermeldung an, wenn die Datei nicht bereit ist
else
{
Serial.println("error opening DATA.TXT");
}
Serial.println("finished");
do {} while (1);
}

Dieser Sketch erstellt die Textdatei DATA.txt auf der microSD-Karte, die Sie in Abbildung 8–25 sehen.

Abb. 8–25 Die in Projekt 29 erstellte Datei

Schauen wir uns nun den void loop()-Abschnitt genauer an, um zu sehen, wie die Textdatei erstellt wird. Der Code in void loop() zwischen und sowie zwischen und erstellt die Datei und öffnet sie zum Schreiben. Mit dem folgenden Code fügen wir Text in sie ein:

dataFile.print();
oder:

dataFile.println();

Dieser Code funktioniert auf die gleiche Weise wie beispielsweise Serial. println(), sodass Sie den Text genauso schreiben können wie im seriellen Monitor. Bei geben wir den Namen der Textdatei an, der aus maximal acht Zeichen, einem Punkt und einer Erweiterung aus drei Zeichen bestehen muss, z. B. DATA.txt.

Bei verwenden wir als zweiten Parameter DEC, um festzulegen, dass es sich bei der Variable um eine Dezimalzahl handelt, die auch als solche in die Textdatei geschrieben werden soll. Hätten wir stattdessen eine float-Variable verwendet, müssten wir noch eine Stelle für die Anzahl der Nachkommastellen angeben (bis maximal sechs).

Bei sind wir mit dem Schreiben der Datei fertig, weshalb wir sie mit dataFile.close() schließen. Wenn wir das vergessen, ist der Computer nicht in der Lage, die Textdatei zu lesen.

Projekt Nr. 30: Ein Gerät zur Temperaturaufzeichnung konstruieren

Da Sie jetzt wissen, wie Sie Daten aufzeichnen können, wollen wir mit dem in Kapitel 4 eingeführten Temperatursensor TMP36 acht Stunden lang jede Minute die Temperatur messen und die Ergebnisse auf eine microSD-Karte schreiben. Wir kombinieren also die microSD-Funktionen aus Projekt 29 mit der Temperaturmessung aus Projekt 27.

Die Hardware

Sie benötigen folgende Teile:

• einen Temperatursensor TMP36

• einen microSD-Shield und eine microSD-Karte

• eine Steckplatine

• Verbindungsdrähte

• Arduino und USB-Kabel

Führen Sie die microSD-Karte in den Shield ein und montieren Sie den Shield auf dem Arduino. Verbinden Sie den linken Kontakt (5 V) des TMP36 mit dem 5-Volt-Anschluss des Arduino, den mittleren mit einem Analogpin und den rechten mit GND.

Der Sketch

Geben Sie folgenden Sketch ein und laden Sie ihn hoch:

// Projekt 30: Ein Gerät zur Temperaturaufzeichnung konstruieren

#include <SD.h>
float sensor, voltage, celsius;

void setup()
{
Serial.begin(9600);
Serial.print("Initializing SD card...");
pinMode(10, OUTPUT);

// Prüft, ob die microSD-Karte vorhanden und verwendbar ist
if (!SD.begin(8))
{
Serial.println("Card failed, or not present");
// Hält die Ausführung des Sketches an
return;
}
Serial.println("microSD card is ready");
}

void loop()
{
// Erstellt die Datei, in die geschrieben werden soll
File dataFile = SD.open("DATA.TXT", FILE _ WRITE);
// Schreibt in die Datei, wenn sie bereit ist
if (dataFile)
{
for ( int a = 0 ; a < 481 ; a++ )    // 8 h haben 480 min
{
sensor = analogRead(0);
voltage = (sensor * 5000) / 1024; // Rechnet die
// Sensorrohdaten in mv um
voltage = voltage - 500;
celsius = voltage / 10;
dataFile.print(" Log: ");
dataFile.print(a, DEC);
dataFile.print(" Temperature: ");

dataFile.print(celsius, 2);
dataFile.println(" degrees C");
delay(599900); // Wartet knapp eine Minute
}
dataFile.close(); // Obligatorisch
Serial.println("Finished!");
do {} while (1);
}
}

Der Sketch braucht etwas länger als acht Stunden, um durchzulaufen, aber Sie können diesen Zeitraum ändern, indem Sie den Wert in delay(599900) bearbeiten.

Wenn der Sketch komplett abgearbeitet ist, nehmen Sie die microSDKarte heraus, stecken Sie an einem Computer ein und öffnen die Protokolldatei in einem Texteditor, wie Sie in Abbildung 8–26 sehen.

Abb. 8–26 Das Ergebnis von Projekt 30

Um eine anspruchsvollere Analyse der erfassten Daten zu ermöglichen, trennen Sie die einzelnen Elemente in den Textzeilen durch Leerzeichen oder Doppelpunkte, sodass Sie sie in ein Tabellenkalkulationsprogramm importieren können. In OpenOffice Calc beispielsweise können Sie Insert > Sheet From File wählen, um wie in Abbildung 8–27 ein Arbeitsblatt zu erzeugen. Darin können Sie dann die Daten wie in Abbildung 8–28 analysieren.

Abb. 8–27 Daten als Arbeitsblatt importieren

Abb. 8–28 Temperaturanalyse

Dieses Beispiel können Sie entsprechend dem Bedarf Ihrer eigenen Datenanalyseprojekte beliebig abwandeln. Nach den hier gezeigten Grundprinzipien können Sie jede Form von Daten aufzeichnen, die das Arduino-System ausgibt.

Zeitmessung mit millis() und micros()

Wenn der Arduino einen Sketch ausführt, zeichnet er auch die vergangene Zeit in Milli-und Mikrosekunden auf. Eine Millisekunde ist eine Tausendstelsekunde (0,001 s), eine Mikrosekunde eine Millionstelsekunde (0,000001 s). Damit können Sie die Zeit messen, die bei der Ausführung von Sketchen vergeht.

Die folgenden Funktionen geben Ihnen Zugriff auf die Zeitwerte, um sie in einer Variable vom Typ unsigned long zu speichern:

unsigned long a,b;
a = micros();
b = millis();

Aufgrund der Beschränkungen, die für den Typ unsigned long gelten, wird der Wert auf 0 zurückgesetzt, sobald 4.294.967.295 erreicht ist. Damit ist es möglich, die Zeit mit millis() 50 Tage lang zu zählen und mit micro() 70 Minuten lang. Außerdem werden die micros()-Werte aufgrund einer Einschränkung des Arduino-Prozessors nur in Viererschritten angegeben.

Damit wollen wir jetzt ermitteln, wie lange der Arduino braucht, um einen Digitalpin von LOW auf HIGH zu schalten und umgekehrt. Dazu lesen wir micros() vor und nach der Funktion digitalWrite(), ermitteln die Differenz und zeigen sie auf dem seriellen Monitor an. Als Hardware brauchen Sie dazu nur den Arduino und ein Kabel.

Geben Sie den Sketch aus Listing 8–1 ein und laden Sie ihn hoch.

unsigned long start, finished, elapsed;

void setup()
{
Serial.begin(9600);
pinMode(3, OUTPUT);
digitalWrite(3, LOW);
}

void loop()
{
start = micros();
digitalWrite(3, HIGH);
finished = micros();
elapsed = finished – start;
Serial.print("LOW to HIGH: ");
Serial.print(elapsed);
Serial.println(" microseconds");
delay(1000);

start = micros();
digitalWrite(3, LOW);
finished = micros();
elapsed = finished - start;
Serial.print("HIGH to LOW: ");
Serial.print(elapsed);
Serial.println(" microseconds");
delay(1000);
}

Listing 8–1 Die Dauer des Pegelwechsels an den digitalen Pins mit micros() messen

Der Sketch misst micros() bei und , bevor und nachdem die digitalWrite(HIGH)-Funktion ausgeführt wird, berechnet die Differenz und zeigt sie bei auf dem seriellen Monitor an. Dies wird ab für die umgekehrte Funktion wiederholt.

Öffnen Sie jetzt den seriellen Monitor, um sich das Ergebnis anzusehen (siehe Abb. 8–29).

Abb. 8–29 Die Ausgabe von Listing 8–1

Da die Auflösung vier Mikrosekunden beträgt, bedeutet ein Wert von 8 ms, dass der Zeitraum länger als 4 ms, aber kleiner oder gleich 8 ms ist.

Projekt Nr. 31: Eine Stoppuhr konstruieren

Da wir jetzt die Zeit messen können, die zwischen zwei Ereignissen vergeht, sind wir in der Lage, mithilfe des Arduino eine einfache Stoppuhr zu bauen. Sie soll über zwei Tasten verfügen: Die eine löst den Zählvorgang aus oder setzt ihn zurück, die andere beendet ihn und zeigt die verstrichene Zeit an. Der Sketch prüft kontinuierlich den Zustand der beiden Tasten. Beim Drücken der Starttaste wird ein millis()-Wert gespeichert, beim Drücken der zweiten Taste ein weiterer. Die selbst geschriebene Funktion displayResult() rechnet die Angabe für die verstrichene Zeit von Millisekunden in Stunden, Minuten und Sekunden um. Schließlich wird die Zeit auf dem seriellen Monitor angezeigt.

Die Hardware

Für dieses Projekt brauchen Sie folgende Teile:

• zwei Drucktasten (S1 und S2)

• zwei 10-kΩ-Widerstände (R1 und R2)

• eine Steckplatine

• Verbindungsdrähte

• Arduino und USB-Kabel

Der Schaltplan

Den Schaltplan sehen Sie in Abbildung 8–30.

HINWEIS

Da Sie die Schaltung noch für das nächste Projekt brauchen werden, sollten Sie sie nicht gleich wieder auseinanderbauen!

Abb. 8–30 Schaltplan für Projekt 31

Der Sketch

Geben Sie folgenden Sketch ein und laden Sie ihn hoch:

// Projekt 31: Eine Stoppuhr konstruieren

unsigned long start, finished, elapsed;

void setup()
{
Serial.begin(9600);
pinMode(2, INPUT);   // Startaste

pinMode(3, INPUT);   // Stopptaste
Serial.println("Press 1 for Start/reset, 2 for elapsed time");
}

void displayResult()
{
float h, m, s, ms;
unsigned long over;

elapsed = finished - start;

h = int(elapsed / 3600000);
over = elapsed % 3600000;
m = int(over / 60000);
over = over % 60000;
s = int(over / 1000);
ms = over % 1000;

Serial.print("Raw elapsed time: ");
Serial.println(elapsed);
Serial.print("Elapsed time: ");
Serial.print(h, 0);
Serial.print("h ");
Serial.print(m, 0);
Serial.print("m ");
Serial.print(s, 0);
Serial.print("s ");
Serial.print(ms, 0);
Serial.println("ms");
Serial.println();
}

void loop()
{
if (digitalRead(2) == HIGH)
{
start = millis();
delay(200);   // Zum Entprellen
Serial.println("Started...");
}
if (digitalRead(3) == HIGH)
{
finished = millis();
delay(200);   // Zum Entprellen
displayResult();
}
}

Unsere Stoppuhr funktioniert nach einem einfachen Grundprinzip. Bei richten wir die digitalen Eingangspins für die Start- und die Stopptaste ein. Wird die Starttaste gedrückt, merkt sich der Arduino bei den Wert von millis(), um später, nach Betätigung der Stopptaste bei , die verstrichene Zeit ermitteln zu können. Diese Berechnung und die Anzeige im seriellen Monitor erfolgen bei in der Funktion displayResult().

Das Ergebnis wird wie in Abbildung 8–31 auf dem seriellen Monitor ausgegeben.

Abb. 8–31 Die Ausgabe von Projekt 31

Interrupts

In der Welt des Arduino ist ein Interrupt im Grunde genommen ein Signal, das es ermöglicht, eine Funktion in einem Sketch jederzeit aufzurufen, beispielsweise wenn sich der Zustand eines digitalen Eingangspins ändert oder wenn ein Timer-Ereignis ausgelöst wird. Interrupts eignen sich ideal dazu, um Funktionen aufzurufen, mit denen der normale Ablauf eines Sketches unterbrochen wird, z. B. beim Drücken einer Taste.

Wird ein Interrupt ausgelöst, so wird der normale Ablauf des Programms in void loop() vorübergehend angehalten, die Interrupt-Funktion aufgerufen und ausgeführt. Nach Beendigung dieser Funktion wird die Hauptschleife genau dort wieder aufgenommen, wo sie angehalten wurde.

Interrupt-Funktionen sollten kurz und einfach sein und schnell wieder beendet werden. Wenn die Interrupt-Funktion irgendetwas tut, was auch die Hauptschleife gerade macht, dann wird die Hauptschleife vorübergehend überbrückt. Nehmen wir an, die Hauptschleife sendet regelmäßig Hello an den seriellen Port, und nun wird eine Interrupt-Funktion ausgelöst, die --- sendet. Dann kommt am seriellen Port H---ello, He---llo, Hel---lo, Hell---o oder Hello--- heraus.

Auf dem Arduino Uno stehen zwei Interrupts für die digitalen Pins 2 und 3 zur Verfügung. Bei korrekter Einrichtung überwacht der Arduino die Spannung an diesen Pins. Wenn sich diese auf eine ganz bestimmte Weise ändert (z. B. wenn eine Taste gedrückt wird), wird ein Interrupt ausgelöst, der dazu führt, dass eine zugehörige Funktion ausgelöst wird. Das könnte etwas sein wie: »Hör auf, mich zu drücken!«

Interrupt-Modi

Ein Interrupt kann durch die folgenden vier Änderungen (oder Modi) ausgelöst werden:

• LOW: Am Interrupt-Pin liegt keine Spannung an.

• CHANGE: Die Stromversorgung ändert sich, der Strom wird entweder abgeschaltet oder eingeschaltet.

• RISING: Die Spannung steigt vom ausgeschalteten Zustand auf 5 V.

• FALLING: Die Spannung sinkt von 5 V zum ausgeschalteten Zustand.

Um beispielsweise zu ermitteln, ob eine Taste, die an einen Interrupt-Pin angeschlossen ist, gedrückt wurde, können wir den Modus RISING verwenden. Wenn Sie in Ihrem Garten einen elektrischen Sensordraht verlegt haben (der an 5 V und an den Interrupt-Pin angeschlossen ist), können Sie mit dem Modus FALLING erkennen, ob jemand den Draht berührt und die Verbindung unterbrochen hat.

HINWEIS

Die Funktionen delay() und Serial.available() funktionieren nicht in Funktionen, die über einen Interrupt aufgerufen worden sind.

Interrupts einrichten

Um Interrupts zu konfigurieren, müssen wir in void setup() Folgendes schreiben:

attachInterrupt(0, Funktion, Modus);
attachInterrupt(1, Funktion, Modus);

Dabei steht 0 für Digitalpin 2 und 1 für Digitalpin 3, Funktion für den Namen der Funktion, die beim Auslösen des Interrupts aufgerufen werden soll, und Modus für einen der vier Auslösemodi.

Interrupts aktivieren und deaktivieren

Es kann sein, dass Sie die Interrupts an einigen Stellen im Sketch nicht verwenden wollen. Dann können Sie sie wie folgt ausschalten:

noInterrupts(); // Interrupts deaktivieren

Anschließend können Sie sie wie folgt wieder einschalten:

interrupts(); // Interrupts reaktivieren

Interrupts arbeiten schnell und sind sehr empfindlich, weshalb sie sich hervorragend für zeitkritische Anwendungen wie beispielsweise »Not-Aus-Schalter« von Projekten eignen.

Projekt Nr. 32: Interrupts verwenden

Um die Nutzung von Interrupts zu veranschaulichen, verwenden wir die Schaltung von Projekt 31. Dabei lassen wir die eingebaute LED im 500-msTakt blinken, und in dieser Zeit werden beide Interrupt-Pins überwacht. Beim Drücken der Taste an Interrupt 0 wird der Wert von micros() auf dem seriellen Monitor angezeigt, bei der Betätigung der Taste an Interrupt 1 der von millis().

Der Sketch

Geben Sie den folgenden Sketch ein und laden Sie ihn hoch:

// Projekt 32: Interrupts verwenden

#define LED 13

void setup()
{
Serial.begin(9600);
pinMode(13, OUTPUT);
attachInterrupt(0, displayMicros, RISING);
attachInterrupt(1, displayMillis, RISING);
}

void displayMicros()
{
Serial.write("micros() = ");
Serial.println(micros());
}

void displayMillis()
{
Serial.write("millis() = ");
Serial.println(millis());
}

void loop()
{
digitalWrite(LED, HIGH);
delay(500);
digitalWrite(LED, LOW);
delay(500);
}

Der Sketch lässt in void loop() bei die eingebaute LED blinken. Wird Interrupt 0 ausgelöst, so wird die Funktion displayMicros() bei ausgelöst, bei Interrupt 1 ist es die Funktion displayMillis() bei . Nachdem die jeweilige Funktion ausgeführt ist, nimmt der Sketch den Code in void loop wieder auf.

Öffnen Sie den seriellen Monitor und drücken Sie die beiden Tasten, um sich die Werte von millis() und micros() wie in Abbildung 8–32 anzusehen.

Abb. 8–32 Die Ausgabe von Projekt 32

Ausblick

In diesem Kapitel haben Sie noch weitere Handwerkszeuge und Möglichkeiten an die Hand bekommen, um eigene Projekte zu erstellen und zu verbessern. In den kommenden Kapiteln werden wir mit weiteren Arduino-Shields arbeiten und microSD-Karten auch für andere Aufgaben verwenden, bei denen Daten aufgezeichnet werden müssen.

9

Numerische Tastenfelder

In diesem Kapitel lernen Sie Folgendes:

• Anschließen von Tastenfeldern an den Arduino

• Ablesen der Werte von Tastenfeldern in einem Sketch

• Erweiterte Entscheidungsmöglichkeiten mit der Funktion switch-case

• Konstruktion von PIN-gesicherten Schlössern und Schaltern

Numerische Tastenfelder verwenden

Bei anspruchsvolleren Projekten kann es vorkommen, dass Sie numerische Eingaben von den Benutzern einholen möchten, ohne dass der Arduino mit einem PC verbunden ist, beispielsweise um Funktionen über die Eingabe einer Geheimzahl ein- oder auszuschalten. Dazu wäre es zwar durchaus möglich, zehn Drucktasten (für die Ziffern 0 bis 9) mit den digitalen Eingangspins zu verbinden, aber viel einfacher ist das mit einem numerischen Tastenfeld wie dem aus Abbildung 9–1 möglich.

Abb. 9–1 Ein numerisches Tastenfeld

Einer der Vorteile eines solchen Tastenfelds besteht darin, dass es für zwölf Tasten nur sieben Pins belegt. Dank einer intelligenten Arduino-Bibliothek ist es darüber hinaus auch nicht notwendig, Pulldown-Widerstände zum Entprellen einzubauen, wie wir es in Kapitel 4 getan haben. Die Bibliothek Keypad können Sie von http://arduino.cc/playground/uploads/Code/Keypad.zip herunterladen und installieren.

Ein Tastenfeld anschließen

Die Verkabelung eines Tastenfelds mit dem Arduino ist einfach. Auf der Rückseite des Tastenfelds finden Sie sieben Kontakte, wie Sie in Abbildung 9–2 sehen.

Abb. 9–2 Die Kontakte am Tastenfeld

Diese Anschlüsse sind von links nach rechts von 1 bis 7 durchnummeriert. Bei sämtlichen Tastenfeldprojekten in diesem Buch nehmen wir die Verbindungen wie in Tabelle 9–1 vor.

Pin am Tastenfeld

Digitalpin am Arduino

1

5

2

4

3

3

4

2

5

8

6

7

7

6

Tab. 9–1 Verbindung zwischen Tastenfeld und Arduino

Programme für das Tastenfeld schreiben

Wenn Sie einen Sketch für ein Tastenfeld schreiben, müssen Sie bestimmte Codezeilen einfügen, um das Gerät zu aktivieren. Dieser Code ist im folgenden Beispielsketch zwischen und zu finden.

Bevor wir mit anspruchsvolleren Projekten weitermachen, prüfen Sie zunächst das Tastenfeld, indem Sie Listing 9–1 eingeben und hochladen.

// Beginn des erforderlichen Codes für Tastenfelder

#include "Keypad.h"
const byte ROWS = 4;       // Richtet die Anzeige auf vier Zeilen ein
const byte COLS = 3;       // Richtet die Anzeige auf drei Spalten ein
char keys[ROWS][COLS] =
{{'1','2','3'},
{'4','5','6'},
{'7','8','9'},
{'*','0','#'}};
byte rowPins[ROWS] = {5, 4, 3, 2};
byte colPins[COLS] = {8, 7, 6};
Keypad keypad = Keypad( makeKeymap(keys), rowPins, colPins, ROWS, COLS
);

// Ende des erforderlichen Codes für Tastenfelder

void setup()
{
Serial.begin(9600);
}

void loop()
{
char key = keypad.getKey();
if (key != NO _ KEY)
{
Serial.print(key);
}
}

Listing 9–1 Beispielsketch für die Verwendung eines numerischen Tastenfelds

Bei führen wir eine Variable vom Typ char ein. Dieser Typ kann beliebige Zeichen – Buchstaben, Ziffern und Symbole – aufnehmen, wie sie von einer Computertastatur erzeugt werden. In unserem Fall handelt es sich um die Ziffern und Symbole auf dem Tastenfeld. Die Codezeilen und legen die Pins fest, die auf dem Arduino verwendet werden. Damit und mit der Tabelle 9–1 können Sie bei Bedarf die Digitalpins für den Eingang ändern.

Den Sketch testen

Laden Sie den Sketch hoch, öffnen Sie ihn im seriellen Monitor und drücken Sie einige Tasten auf dem Tastenfeld. Auf dem Monitor werden jetzt die zugehörigen Zeichen angezeigt, wie Sie in Abbildung 9–3 sehen.

Abb. 9–3 Das Ergebnis bei der Bedienung des Tastenfelds

Entscheidungen mit switch-case

Wenn Sie zwei oder mehr Variablen vergleichen müssen, ist es oft einfacher, eine switch-case- statt einer if-then-Anweisung zu verwenden, denn mit switch-case können Sie unbegrenzt viele Vergleiche anstellen und für jedes mögliche Ergebnis anderen Code ausführen. Nehmen wir an, wir haben die Integervariable xx, die die möglichen Werte 1, 2 und 3 annehmen kann. Wenn wir je nachdem, welchen Wert die Variable hat, jeweils unterschiedlichen Code ausführen wollen, können wir die folgende Anweisung verwenden:

switch(xx)
{
case 1:
// Macht etwas Bestimmtes, wenn xx den Wert 1 hat
break; // Beendet die Ausführung der Anweisung und fährt
// mit dem Rest des Sketches fort
case 2:
// Macht etwas Bestimmtes, wenn xx den Wert 2 hat
break;
case 3:
// Macht etwas Bestimmtes, wenn xx den Wert 3 hat
break;
default:
// Macht etwas Bestimmtes, wenn xx einen anderen Wert als 1, 2
// oder 3 hat Die Verwendung von default ist optional
}

Mit dem optionalen default:-Abschnitt können Sie Code für den Fall ausführen, dass keiner der Vergleiche in der switch-case-Anweisung true ergibt.

Projekt Nr. 33: Ein Schloss mit Tastenfeld konstruieren

In diesem Projekt legen wir das Fundament für ein Türschloss mit Tastenfeldsteuerung. Dazu verwenden wir die grundlegende Einrichtung aus dem Sketch in Listing 9–1, fügen aber auch einen Geheimcode hinzu, der über das Tastenfeld eingegeben werden muss. Der serielle Monitor teilt dem Benutzer mit, ob die Zahlenkombination korrekt war oder nicht.

Je nachdem, ob der sechsstellige Geheimcode richtig eingegeben wurde oder nicht, werden in diesem Sketch unterschiedliche Funktionen aufgerufen. Die richtige Kombination ist zwar in dem Sketch gespeichert, aber für den Benutzer nicht sichtbar. Um das Schloss zu aktivieren bzw. zu deaktivieren, muss der Benutzer drücken, die Geheimzahl eingeben und dann drücken.

Der Sketch

Geben Sie folgenden Sketch ein und laden Sie ihn hoch:

// Projekt 33: Ein Schloss mit Tastenfeld konstruieren

// Beginn des erforderlichen Codes für Tastenfelder

#include "Keypad.h"
const byte ROWS = 4;       // Richtet die Anzeige auf vier Zeilen ein
const byte COLS = 3;       // Richtet die Anzeige auf drei Spalten ein
char keys[ROWS][COLS] =
{{'1','2','3'},
{'4','5','6'},
{'7','8','9'},
{'*','0','#'}};
byte rowPins[ROWS] = {5, 4, 3, 2};
byte colPins[COLS] = {8, 7, 6};
Keypad keypad = Keypad( makeKeymap(keys), rowPins, colPins, ROWS, COLS );

// Ende des erforderlichen Codes für Tastenfelder

char PIN[6]={'1','2','3','4','5','6'};   // Die Geheimzahl
char attempt[6]={0,0,0,0,0,0};
int z=0;

void setup()
{
Serial.begin(9600);
}

void correctPIN() // Wird bei Eingabe der korrekten PIN ausgeführt
{
Serial.println("Correct PIN entered...");
}

void incorrectPIN() // Wird bei falscher Eingabe ausgeführt
{
Serial.println("Incorrect PIN entered!");
}

void checkPIN()
{
int correct=0;
int i;
for ( i = 0; i < 6 ; i++ )
{
if (attempt[i]==PIN[i])
{
correct++;
}
}
if (correct==6)
{
correctPIN();
}  else
{
incorrectPIN();
}
for (int zz=0; zz<6; zz++) // Entfernt den vorherigen Eingabeversuch
{
attempt[zz]=0;
}
}

void readKeypad()
{
char key = keypad.getKey();
if (key != NO _ KEY)
{
switch(key)
{

case '*':
z=0;
break;
case '#':
delay(100); // Dient zum Entprellen
checkPIN();
break;
default:
attempt[z]=key;
z++;
}
}
}

void loop()
{
readKeypad();
}

Funktionsweise

Nach den üblichen Einrichtungsroutinen (die in Listing 9–1 beschrieben wurden) lauscht der Sketch kontinuierlich auf Signale vom Tastenfeld, indem er bei die Funktion readKeypad() ausführt. Wird eine Taste gedrückt, so wird ihr Wert in der switch-case-Anweisung bei untersucht. Die aufeinanderfolgenden Werte eines Eingabeversuchs werden im Array attemp[] gespeichert, und wenn der Benutzer drückt, wird die Funktion checkPin() aufgerufen.

Bei werden die Werte der gedrückten Tasten mit der PIN verglichen, die bei im Array PIN[] gespeichert wurde. Wurde die richtige Zahlenkombination eingegeben, wird bei die Funktion correctPIN() aufgerufen, die Sie mit Ihrem eigenen Code ausstaffieren können, anderenfalls bei die Funktion incorrectPIN(). Nachdem die Eingabe des Benutzers überprüft wurde, wird sie abschließend aus dem Arbeitsspeicher entfernt, sodass das Programm für den nächsten Vorgang bereit ist.

Den Sketch testen

Laden Sie den Sketch auf den Arduino hoch, öffnen Sie den seriellen Monitor, drücken Sie die Taste auf dem Tastenfeld, geben Sie eine Zahlenkombination ein und drücken Sie abschließend . Probieren Sie sowohl die richtige Geheimzahl als auch falsche Kombinationen aus. Eine Beispielausgabe sehen Sie in Abbildung 9–4.

Abb. 9–4 Anzeige bei der Eingabe richtiger und falscher Zahlenkombinationen

Dieses Beispielprojekt bildet eine hervorragende Grundlage für eigene Konstruktionen von Geräten mit PIN-Freigabe wie Schlösser, Einbruchssicherungen usw. Ersetzen Sie den Inhalt von correctPIN() und incorrectPIN() durch den Code, den Sie ausführen lassen möchten, wenn die richtige bzw. eine falsche Kombination eingegeben wird.

Ausblick

Damit haben Sie eine weitere Möglichkeit kennengelernt, um Eingaben für den Arduino zu erfassen, und Grundkenntnisse darüber erworben, wie Sie die Ausführung eines Sketches über ein Tastenfeld steuern und wie Sie ein Kombinationsschloss für den Zugriff auf alle möglichen Dinge konstruieren, die Sie an den Arduino anschließen können. Des Weiteren haben Sie die sehr nützliche Anweisung switch-case kennengelernt. Im nächsten Kapitel geht es abermals um eine neue Eingabemöglichkeit, nämlich einen Touchscreen.

10

Benutzereingaben über einen Touchscreen

In diesem Kapitel lernen Sie Folgendes:

• Anschluss eines Touchscreens an den Arduino

• Verarbeiten der vom Touchscreen eingehenden Werte

• Konstruktion eines einfachen Ein/Aus-Schalters

• Konstruktion eines Ein/Aus-Schalters mit Dimmer

Touchscreens sind heutzutage allgegenwärtig und auf Smartphones, Tablet-Computern und Spielkonsolen zu finden. Warum also darauf verzichten, über einen Touchscreen Eingaben vom Benutzer abzufragen?

Touchscreens

Touchscreens können ziemlich teuer sein, aber wir verwenden hier ein preisgünstiges Modell von SparkFun (Bestell-Nr. LCD-08977 und BOB-09170), das ursprünglich für die Spielkonsole Nintendo DS entwickelt wurde. Es misst etwa 5 × 7,5 cm. In Abbildung 10–1 sehen Sie diesen Touchscreen auf einer Steckplatine montiert.

Abb. 10–1 Der Touchscreen auf einer Steckplatine

Beachten Sie das kleine Flachbandkabel, das den Touchscreen mit der Miniplatine in der oberen rechten Ecke verbindet (in der Abbildung eingekreist). Dieses sogenannte Breakout-Board (eine Platine mit ähnlicher Funktion wie eine Kabelpeitsche) dient dazu, den Arduino und die Steckplatine mit dem Touchscreen zu verbinden. In Abbildung 10–2 sehen Sie eine Detailaufnahme.

Abb. 10–2 Die Anschlussplatine für den Touchscreen

Den Touchscreen anschließen

Verbinden Sie das Breakout-Board des Touchscreens, wie in Tabelle 10–1 angegeben, mit dem Arduino.

Pin am Breakout-Board

Arduino-Pin

Y1

A0

X2

A1

Y2

A2

X2

A3

Tab. 10–1 Verbindung zwischen Touchscreen und Arduino

Projekt Nr. 34: Bereiche auf dem Touchscreen ansprechen

Zwischen der Kunststoffabdeckung und dem Glasboden des Touchscreens befinden sich zwei elektrisch widerstandsfähige Schichten, von denen die eine als x- und die andere als y-Achse fungiert. Wenn Strom durch diese Schichten fließt, variiert ihr Widerstand je nachdem, wo sie angetippt wurden. Durch die Messung der Stromstärke in beiden Schichten lässt sich daher die x- und y-Koordinate des Berührungspunktes ermitteln.

In diesem Projekt erfassen wir mit dem Arduino die Stellen, an denen der Bildschirm berührt wurde, und wandeln die Messwerte in Integerzahlen um, die wir dazu verwenden können, auf die entsprechenden Flächen auf dem Bildschirm zu verweisen.

Die Hardware

Sie benötigen folgende Hardware:

• Touchscreen mit Breakout-Board

• ein 10-kΩ-Trimmpotenziometer

• ein LCD-Zeichenmodul der Größe 16 × 2

• eine Steckplatine

• Verbindungsdrähte

• Arduino und USB-Kabel

Schließen Sie den Touchscreen nach der Anleitung in Tabelle 10–1 an und das LCD-Modul wie in Abbildung 7–2.

Der Sketch

Geben Sie folgenden Sketch ein und laden Sie ihn hoch. Die wichtigsten Aspekte habe ich mit Kommentaren versehen.

// Projekt 34: Bereiche auf dem Touchscreen ansprechen

#include <LiquidCrystal.h>
LiquidCrystal lcd(4,5,6,7,8,9);

int x,y = 0;

void setup()
{
lcd.begin(16,2);
lcd.clear();
}

int readX()   // Gibt den Wert für die x-Koordinate der Berührung
// zurück
{
int xr=0;
pinMode(A0, INPUT);
pinMode(A1, OUTPUT);
pinMode(A2, INPUT);
pinMode(A3, OUTPUT);
digitalWrite(A1, LOW);   // Setzt A1 auf GND
digitalWrite(A3, HIGH);  // Setzt A3 auf 5 V
delay(5);
xr=analogRead(0);        // Speichert den Wert der x-Koordinate
return xr;
}

int readY() // Gibt den Wert für die x-Koordinate der Berührung zurück
{
int yr=0;
pinMode(A0, OUTPUT);      // A0
pinMode(A1, INPUT);       // A1
pinMode(A2, OUTPUT);      // A2
pinMode(A3, INPUT);       // A3
digitalWrite(14, LOW);    // Setzt A0 auf GND
digitalWrite(16, HIGH);   // Setzt A2 auf 5 V
delay(5);
yr=analogRead(1);         // Speichert den Wert der x-Koordinate
return yr;
}

void loop()
{
lcd.setCursor(0,0);
lcd.print(" x = ");
x=readX();
lcd.print(x);
y=readY();
lcd.setCursor(0,1);
lcd.print(" y = ");
lcd.print(y);
delay (200);
}

Die Funktionen readX() und readY() bei und lesen die Stromstärke in den Widerstandsschichten des Touchscreens mit analogRead() ab und geben den Wert zurück. Dieser Sketch führt diese beiden Funktionen rasch hintereinander aus, um die Position der berührten Fläche in Echtzeit zu ermitteln und bei und auf dem LCD-Bildschirm auszugeben. (Die Verzögerung delay(5) in den Funktionen ist erforderlich, damit die Ein-/Ausgangspins Zeit haben, ihren Zustand zu ändern.)

Den Sketch testen

Um den Sketch zu testen, fahren Sie mit dem Finger über den Touchscreen und beobachten währenddessen auf dem LCD-Bildschirm, wie sich der xund der y-Wert ändern. Beachten Sie auch, welche Werte angezeigt werden, wenn Sie den Touchscreen nicht berühren (siehe Abb. 10–3).

Abb. 10–3 Werte bei nicht berührtem Touchscreen

Es ist wichtig, dass Sie sich diese Werte merken, da Sie damit in Ihrem Sketch ermitteln können, wann der Touchscreen nicht berührt wird.

Kartierung des Touchscreens

Wenn Sie den Touchscreen an den Ecken berühren und sich die dabei zurückgegebenen Werte notieren, können Sie eine »Karte« der Oberfläche entwerfen (siehe Abbildung 10–4). Haben Sie erst einmal die Koordinaten für die Ecken, können Sie die Touchscreen-Karte in kleinere Teilflächen für einzelne Steuerelemente aufteilen.

Nachdem Sie die Touchscreen-Karte zusammengestellt haben, können Sie anhand von readX() und readY() die einzelnen Steuerbereiche ansprechen und dann mit if-then-Anweisungen festlegen, welche Aktionen ausgeführt werden sollen, wenn der Benutzer die entsprechenden Teilflächen berührt. Das werden wir uns in Projekt 35 genauer ansehen.

Abb. 10–4 Die Karte des Touchscreens

Projekt Nr. 35: Einen Ein/Aus-Schalter mit zwei Zonen entwerfen

In diesem Projekt ziehen wir unsere Touchscreen-Karte dazu heran, einen Ein/Aus-Schalter zu erstellen. Dazu teilen Sie die Fläche zunächst horizontal in zwei Hälften auf, wie Sie in Abbildung 10–5 sehen. Die linke Hälfte ist für den Zustand »Ein« da, die rechte für »Aus«.

Abb. 10–5 Karte für den Ein/Aus-Schalter

Der Arduino erkennt, welche Zone des Touchscreens angetippt wurde, indem er die gemessenen Koordinaten der Berührung mit den Grenzen der beiden Bildschirmhälften vergleicht. Anschließend kann er über einen digitalen Ausgang ein Ein- oder Aus-Signal senden. In diesem Sketch wird jedoch einfach nur auf dem seriellen Monitor angezeigt, ob die Ein- oder die Aus-Zone berührt wurde.

Der Sketch

Geben Sie folgenden Sketch ein und laden Sie ihn hoch:

// Projekt 35: Einen Ein/Aus-Schalter mit zwei Zonen entwerfen

int x,y = 0;

void setup()
{
Serial.begin(9600);
pinMode(10, OUTPUT);
}

void switchOn()
{
digitalWrite(10, HIGH);
Serial.print("Turned ON at X = ");
Serial.print(x);
Serial.print(" Y = ");
Serial.println(y);
delay(200);
}

void switchOff()
{
digitalWrite(10, LOW);
Serial.print("Turned OFF at X = ");
Serial.print(x);
Serial.print(" Y = ");
Serial.println(y);
delay(200);
}

int readX() // Gibt den Wert für die x-Koordinate der Berührung zurück
{
int xr=0;
pinMode(A0, INPUT);
pinMode(A1, OUTPUT);
pinMode(A2, INPUT);
pinMode(A3, OUTPUT);
digitalWrite(A1, LOW);   // Setzt A1 auf GND
digitalWrite(A3, HIGH);  // Setzt A3 auf 5 V
delay(5);
xr=analogRead(0);
return xr;
}

int readY() // Gibt den Wert für die y-Koordinate der Berührung zurück
{
int yr=0;
pinMode(A0, OUTPUT);
pinMode(A1, INPUT);
pinMode(A2, OUTPUT);
pinMode(A3, INPUT);
digitalWrite(A0, LOW); // Setzt A0 auf GND
digitalWrite(A2, HIGH); // Setzt A2 auf 5 V
delay(5);
yr=analogRead(1);
return yr;
}

void loop()
{
x=readX();
y=readY();
// Prüft auf Berührung der Zone EIN
if (x<=900 && x>=500)
{
switchOn();
}
// Prüft auf Berührung der Zone AUS
if (x<500 && x>=100)
{
switchOff();
}
}

Funktionsweise

Die beiden if-Anweisungen in void loop() prüfen, ob die rechte oder die linke Bildschirmhälfte berührt wurde. Findet eine Berührung auf der linken Seite statt, wird dies bei als »Ein« erkannt. Das Antippen der Aus-Zone (der linken Seite) wird bei ermittelt.

HINWEIS

Da der Bildschirm nur horizontal aufgeteilt ist, wird die y-Achse ignoriert. Wenn wir eine vertikale Unterteilung haben, müssen wir auch die y-Achse prüfen, wie Sie in Projekt 36 noch sehen werden.

Den Sketch testen

Die Ausgabe dieses Sketches im seriellen Monitor sehen Sie in Abbildung 10–6. Nach jedem Antippen werden der Status der Schalter und die Koordinaten der Berührung ausgegeben.

Abb. 10–6 Die Ausgabe von Projekt 35

Projekt Nr. 36: Einen Schalter mit drei Berührungszonen entwerfen

In diesem Projekt erstellen wir ein Drei-Zonen-Steuerelement für eine an Digitalpin 3 angeschlossene LED, mit dem der Benutzer die Leuchtdiode ein- und ausschalten und ihre Helligkeit durch Pulsbreitenmodulation (siehe Kapitel 3) ändern kann.

Die Touchscreen-Karte

Die Touchscreen-Karte für dieses Projekt sehen Sie in Abbildung 10–7.

Der Touchscreen ist in die Zonen für »Ein« und »Aus« sowie eine Zone für den Helligkeitsregler eingeteilt. Um zu bestimmen, welche Teilflächen berührt wurden, und entsprechend handeln zu können, messen wir die von dem Touchscreen zurückgegebenen Werte.

Abb. 10–7 Touchscreen-Karte für Projekt 36

Der Sketch

Geben Sie folgenden Sketch ein und laden Sie ihn hoch:

// Projekt 36: Einen Schalter mit drei Berührungszonen entwerfen

int x,y = 0;

void setup()
{
pinMode(3, OUTPUT);
}

void switchOn()
{
digitalWrite(3, HIGH);
delay(200);
}

void switchOff()
{
digitalWrite(3, LOW);
delay(200);
}

void setBrightness()
{
int xx, bright;
float br;
xx=x-100;
br=(800-xx)/255;
bright=int(br);
analogWrite(3, bright);
}

int readX() // Gibt den Wert für die x-Koordinate der Berührung zurück
{
int xr=0;
pinMode(A0, INPUT);
pinMode(A1, OUTPUT);
pinMode(A2, INPUT);
pinMode(A3, OUTPUT);
digitalWrite(A1, LOW);    // Setzt A1 auf GND
digitalWrite(A3, HIGH);   // Setzt A3 auf 5 V
delay(5);
xr=analogRead(0);
return xr;
}

int readY() // Gibt den Wert für die y-Koordinate der Berührung zurück
{
int yr=0;
pinMode(A0, OUTPUT);     // A0
pinMode(A1, INPUT);      // A1
pinMode(A2, OUTPUT);     // A2
pinMode(A3, INPUT);      // A3
digitalWrite(A0, LOW);   // Setzt A0 auf GND
digitalWrite(A2, HIGH);  // Setzt A2 auf 5 V
delay(5);
yr=analogRead(1);
return yr;
}

void loop()
{
x=readX();
y=readY();

// Prüft auf Berührung der Zone EIN
if (x<=500 && x>=100 && y>= 150 && y<375)
{
switchOn();
}

// Prüft auf Berührung der Zone AUS
if (x>500 && x<=900 && y>= 150 && y<375)
{
switchOff();
}

// Prüft auf Berührung der Zone für die Helligkeitsregelung
if (y>=375 && y<=900)
{
setBrightness();
}
}

Funktionsweise

Wie im Sketch für die Zwei-Zonen-Karte wird auch hier bei und geprüft, ob die Zone »Ein« bzw. »Aus« berührt wurde (die jetzt beide kleiner sind). Außerdem wird bei ermittelt, ob der Bereich oberhalb der horizontalen Grenzlinie berührt wurde. Ist das der Fall, wird die x-Koordinate bei in einen relativen Wert für die Pulsbreitenmodulation umgewandelt und die LED mit der Funktion setBrightness() entsprechend angesteuert.

Mit diesen grundlegenden Funktionen können Sie beliebig viele Schalter und Schieberegler für diesen einfachen und preiswerten Touchscreen entwerfen.

Ausblick

In diesem Kapitel haben Sie eine weitere Möglichkeit kennengelernt, um Benutzerdaten einzuholen und den Arduino zu steuern. Im nächsten Kapitel konzentrieren wir uns wieder auf die Arduino-Platine selbst. Sie erfahren etwas über die verschiedenen verfügbaren Modelle und lernen, wie Sie auf einer Steckplatine eine eigene Version konstruieren können.

11

Gestatten, Familie Arduino!

In diesem Kapitel lernen Sie Folgendes:

• Bau einer eigenen Arduino-Schaltung auf einer Steckplatine

• Funktionsumfang und Vorteile der verschiedenen Arduino-kompatiblen Platinen

• Open-Source-Hardware

Wir reduzieren hier den Arduino auf eine Handvoll Teile, die Sie auf einer Steckplatine anbringen. Mit einer eigenen Arduino-Schaltung können Sie Geld sparen, vor allem wenn Sie viele neue Projekte und Prototypen in Angriff nehmen. Außerdem erfahren Sie hier etwas über neue Bauteile und Schaltungen und lernen, wie Sie Sketche ohne zusätzliche Hardware auf Ihren Arduino Marke Eigenbau hochladen. Am Ende sehen wir uns die am weitesten verbreiteten Alternativen zum Arduino Uno und die Unterschiede zwischen ihnen an.

Projekt Nr. 37: Einen eigenen Steckplatinen-Arduino bauen

Wenn Sie immer mehr oder immer kompliziertere Projekte und Experimente durchführen, können die Kosten für die Arduino-Platinen schnell aus dem Ruder laufen, vor allem sobald Sie an mehreren Basteleien gleichzeitig arbeiten. Dann ist es billiger und einfacher, wie in diesem Projekt die Schaltung der Arduino-Platine auf einer Steckplatine nachzubauen und dann je nach vorliegender Aufgabe zu erweitern. Die erforderlichen Teile für die Grundschaltung des Arduino kosten keine 10 €. Dies ist auch die einfachere Vorgehensweise, wenn in einem Projekt viele externe Verbindungen benötigt werden, da Sie es sich dann sparen können, viele Drähte vom Arduino zur Steckplatine zu verlegen.

Die Hardware

Um eine minimalistische Version des Arduino zu bauen, benötigen Sie folgende Teile:

• einen linearen Spannungsregler vom Typ 7805

• einen 16-MHz-Quarzoszillator (z. B. den Newark 16C8140)

• einen ATmega328P-PU-Mikrocontroller mit Arduino-Bootloader

• einen 1-μF-Elektrolytkondensator für 25 V (C1)

• einen 100-μF-Elektrolytkondensator für 25 V (C2)

• zwei 22-pF-Keramikkondensatoren für 50 V (C3 und C4)

• einen 100-nF-Keramikkondensator für 50 V (C5)

• zwei 560-Ω-Widerstände (R1 und R2)

• einen 10-kΩ-Widerstand (R3)

• zwei LEDs Ihrer Wahl (LED1 und LED2)

• eine Drucktaste (S1)

• eine Sechser-Pfostenleiste

• einen Clip für 9-Volt-Blockbatterien

• eine 9-Volt-Blockbatterie (PP3)

• Verbindungsdrähte

• Eine Steckplatine

Mit einigen dieser Teile sind Sie vielleicht noch nicht vertraut. In den folgenden Abschnitten erklären wir die einzelnen Elemente und zeigen jeweils ein Beispielmodell und das Schaltplansymbol.

Linearer Spannungsregler 7805

Ein linearer Spannungsregler enthält eine einfache Schaltung, die eine Spannung in eine andere umwandelt. Der in der Teileliste aufgeführte Regler 7805 konvertiert Spannungen zwischen 7 V und 30 V in konstante 5 V mit einer Stromstärke von maximal 1 A, was für den Betrieb unseres Steckplatinen-Arduino ideal ist. Abbildung 11–1 zeigt ein Beispiel des 7805 in der Bauform mit der Bezeichnung TO-220.

Abb. 11–1 Linearer Spannungsregler 7805

In Abbildung 11–2 sehen Sie das Schaltplansymbol für den 7805. Wenn Sie das Bauteil aufrecht halten und auf seine beschriftete Seite blicken, dann ist der linke Kontakt für die Eingangsspannung zuständig, der rechte für den 5-Volt-Ausgang und der mittlere für den Masseanschluss. Die Metalllasche am oberen Rand weist eine Bohrung auf, um den Regler mit einem größeren Metallstück zu verbinden, das als Wärmeableiter dient. Wenn sich die Stromstärke dem Maximum von 1 A nähert, wird der 7805 ziemlich warm, weshalb wir unbedingt eine Möglichkeit brauchen, um diese Wärme abzuführen. Auch die Lasche ist mit Masse verbunden.

Abb. 11–2 Das Schaltplansymbol für den 7805

16-MHz-Quarzoszillator

Ein Quarzoszillator ruft ein elektrisches Signal mit sehr genauer Frequenz hervor. Bei diesem Bauteil beträgt sie 16 MHz. Den Oszillator, den wir verwenden, sehen Sie in Abbildung 11–3.

Abb. 11–3 Quarzoszillator

Vergleichen Sie diese Abbildung mit dem Quarzoszillator auf einem Arduino. Die beiden Bauteile sollten die gleiche Form und Größe aufweisen.

Quarzoszillatoren sind nicht gepolt. Das Schaltplansymbol sehen Sie in Abbildung 11–4.

Abb. 11–4 Das Schaltplansymbol für einen Quarzoszillator

Der Oszillator bestimmt die Arbeitsgeschwindigkeit des Mikrocontrollers. Unser Mikrocontrollerschaltkreis läuft mit 16 MHz, kann also 16 Millionen Prozessoranweisungen pro Sekunde verarbeiten. Das sind jedoch keine 16 Millionen Zeilen oder Funktionen, da zur Interpretation einer einzigen Codezeile viele Prozessoranweisungen erforderlich sind.

Mikrocontroller-IC Atmel Atmega328-PU

Ein Mikrocontroller ist ein winziger Computer, der einen Prozessor zur Verarbeitung von Anweisungen, verschiedene Arten von Arbeitsspeicher zum Festhalten von Daten und Anweisungen sowie Einrichtungen zum Senden und Empfangen von Daten enthält. Wie bereits in Kapitel 2 erwähnt, stellt der Mikrocontroller das Gehirn des Arduino dar. Was wir brauchen, ist der ATmega328P, den Sie in Abbildung 11–5 sehen. Pin Nummer 1 befindet sich unten links an dem IC und ist mit einem kleinen Punkt gekennzeichnet.

Abb. 11–5 Der ATmega328P

Das Schaltplansymbol für den Mikrocontroller sehen Sie in Abbildung 11–6.

Abb. 11–6 Das Schaltplansymbol für einen Mikrocontroller

Nicht alle Mikrocontroller enthalten den Arduino-Bootloader, also das Programm, das die für den Arduino geschriebenen Sketche interpretieren kann. Für einen Eigenbau-Arduino müssen Sie einen Mikrocontroller auswählen, der diesen Bootloader bereits enthält. Zu erwerben gibt es sie im Allgemeinen bei den gleichen Händlern, die auch Arduino-Platinen verkaufen, z. B. Adafruit, Freetronics und SparkFun.

Der Schaltplan

Abbildung 11–7 zeigt den Schaltplan.

Abb. 11–7 Schaltplan für den Steckplatinen-Arduino

Der Schaltplan besteht aus zwei Teilen. Links sehen Sie den Bereich der Stromversorgung, in dem die Spannung auf 5 V verringert wird. Außerdem befindet sich dort eine LED, die bei eingeschaltetem Strom leuchtet. Der Abschnitt auf der rechten Seite besteht aus dem Mikrocontroller, der Reset-Taste, den Pins und einer weiteren LED. Diese ist mit dem Pin des ATmega328 verbunden, der als Arduino-Pin 13 dient. Stellen Sie die Anschlüsse nach dem Schaltplan her. Vergessen Sie dabei nicht die Verkabelung der Sechser-Pfostenleiste (siehe Abb. 11–8), die am unteren Rand des Schaltplans als eine Reihe aus sechs Kreisen dargestellt ist. Diese Verbindung werden wir später verwenden, um einen Sketch auf unseren Eigenbau-Arduino hochzuladen.

Abb. 11–8 Sechser-Pfostenleiste

Die Schaltung wird über eine handelsübliche 9-Volt-Batterie mit passendem Clip mit Strom versorgt (siehe Abb. 11–9). Schließen Sie den roten Draht des Batterieclips an das Ende der Schaltung an, das ganz links im Schaltplan mit einem Pluszeichen markiert ist, und den schwarzen an das Minus-Ende.

Abb. 11–9 9-Volt-Batterie mit Clip

Die Arduino-Pins

Wo aber sind an unserem Eigenbau-Arduino die Pins geblieben? Die analogen, digitalen und sonstigen Anschlüsse der normalen Arduino-Platine stehen uns auch bei unserer Steckplatinen-Version zur Verfügung, befinden sich aber direkt am Mikrocontroller.

Bei unserem Eigenbau-Arduino liegen der Widerstand R2 und die Leuchtdiode LED2 am Digitalpin 13. Tabelle 11–1 stellt die Arduino-Pins und die entsprechenden Pins am ATmega328 gegenüber.

Arduino-Pin

ATmega328-Pin

RST

1

RX/D0

2

TX/D1

3

D2

4

D3

5

D4

6

(nur 5 V)

7

GND

8

D5

11

D6

12

D7

13

D8

14

D9

15

D10

16

D11

17

D12

18

D13

19

(nur 5 V)

20

AREF

21

GND

22

A0

23

A1

24

A2

25

A3

26

A4

27

A5

28

Tab. 11–1 Pinbelegung des ATmega328P

Um Verwechslungen zu vermeiden, bieten Händler wie Adafruit und Freetronics auch Aufkleber mit einer Pinbeschriftung für den Mikrocontroller an (siehe Abb. 11–10; zu beziehen über http://www.freetronics.com/mculabel/).

Abb. 11–10 Aufkleber mit Pinbeschriftung

Einen Testsketch ausführen

Nun ist es an der Zeit, einen ersten Sketch hochzuladen. Als Beispiel nehmen wir einen einfachen Sketch, der die LED blinken lässt:

// Projekt 37: Einen eigenen Steckplatinen-Arduino bauen

void setup()
{
pinMode(13, OUTPUT);
}

void loop()
{
digitalWrite(13, HIGH);
delay(1000);
digitalWrite(13, LOW);
delay(1000);
}

Zum Hochladen des Sketches haben Sie drei Möglichkeiten:

Austausch des Mikrocontrollers

Die preisgünstigste Möglichkeit, einen Sketch hochzuladen, besteht darin, den Mikrocontroller eines anderen Arduino auszubauen, an dessen Stelle den Mikrocontroller der Steckplatinenversion einzusetzen, den Sketch hochzuladen und die Controller dann abermals auszutauschen.

Um einen Mikrocontroller gefahrlos von einem Arduino zu lösen, verwenden Sie einen IC-Abzieher (siehe Abb. 11–11).

Abb. 11–11 Ausbau eines Mikrocontrollers mit einem IC-Abzieher

Achten Sie beim Ausbau des Mikrocontrollers darauf, langsam und gleichmäßig an beiden Enden zugleich zu ziehen. Es kann ein bisschen schwierig sein, das Bauteil zu lösen, aber schließlich wird es sich von seinem Sockel entfernen lassen.

Wenn Sie den Mikrocontroller auf der Steckplatine oder einem Arduino einsetzen, müssen Sie möglicherweise die Anschlussstifte ein wenig biegen, sodass sie im rechten Winkel zum IC-Gehäuse stehen und glatt in die Öffnungen rutschen können. Legen Sie das Bauteil dazu seitlich auf eine ebene Oberfläche und drücken Sie es leicht nach unten (siehe Abb. 11–12). Wiederholen Sie den Vorgang dann für die andere Seite.

Beim Wiedereinbau des ursprünglichen Mikrocontrollers auf der Arduino-Platine müssen Sie darauf achten, dass das Ende mit der Einkerbung nach rechts zeigt, wie Sie in Abbildung 11–13 sehen.

Abb. 11–12 Die Pins am Mikrocontroller zurechtbiegen

Abb. 11–13 Richtige Ausrichtung des Mikrocontrollers auf einem Arduino

Anschluss an eine handelsübliche Arduino-Platine

Über die USB-Schnittstelle eines Arduino Uno können Sie Sketche auf den Mikrocontroller des Steckplatinen-Arduino hochladen. Diese Methode verringert die Abnutzung des Mikrocontroller-Sockels auf der Platine und kommt ohne das besondere USB-Kabel aus, das Sie für die dritte Methode brauchen.

Um einen Sketch hochzuladen, gehen Sie wie folgt vor:

1. Ziehen Sie den Mikrocontroller vom Arduino Uno ab und lösen Sie das USB-Kabel.

2. Unterbrechen Sie die Stromversorgung des Steckplatinen-Arduino.

3. Verbinden Sie Digitalpin 0 des Arduino mit Pin 2 des ATmega328P auf der Steckplatine sowie Digitalpin 1 mit Mikrocontroller-Pin 3.

4. Verbinden Sie den 5-Volt- und den GND-Anschluss des Uno mit den entsprechenden Stellen der Steckplatine.

5. Verbinden Sie den RST-Anschluss des Arduino mit Pin 1 des ATmega328P.

6. Schließen Sie das USB-Kabel wieder an den Arduino Uno an.

Jetzt verhält sich das System wie ein normaler Arduino Uno, sodass Sie Sketche auf die übliche Weise zum Mikrocontroller der Steckplatinenschaltung hochladen und bei Bedarf auch dem seriellen Monitor verwenden können.

Verwendung eines FTDI-Programmierkabels

Die letzte Methode ist die einfachste, doch dafür müssen Sie ein USB-Programmierkabel erwerben, das als FTDI-Kabel bezeichnet wird (weil die USB-Schaltung darin von einer Firma namens FTDI stammt). Achten Sie darauf, dass Sie das 5-Volt-Modell kaufen, da die 3,3-Volt-Version nicht ordnungsgemäß funktioniert. Das Kabel weist an einer Seite einen USB-Stecker und auf der anderen einen sechsadrigen Anschluss auf. Das USB-Ende enthält eine Schaltung, die der USB-Schnittstelle am Arduino Uno entspricht. Das andere wird mit der Pfostenleiste verbunden, die Sie in den Abbildungen 11–7 und 11–8 sehen.

Abb. 11–14 FTDI-Kabel

Achten Sie beim Einstecken des Kabels darauf, dass Sie die Seite mit dem schwarzen Draht mit dem GND-Pin der Pfostenleiste verbinden. Wie bei einem normalen Arduino versorgt das Kabel die Schaltung auch mit Strom.

Bevor sie einen Sketch hochladen oder den seriellen Monitor verwenden, müssen Sie den Platinentyp in Arduino Duemilanove or Nano w/ATmega328 ändern. Rufen Sie dazu Tools > Board auf und wählen Sie die entsprechende Option aus (siehe Abb. 11–15).

Abb. 11–15 Den Platinentyp in der IDE ändern

Entscheiden Sie sich für eine Methode und laden Sie als Testlauf den Sketch für Projekt 37 hoch. Jetzt können Sie auch kompliziertere Schaltungen einzig und allein auf der Steckplatine aufbauen, was mehr Projekte für weniger Geld ermöglicht. Wenn Sie wissen, wie Sie eigene gedruckte Schaltungen herstellen, können Sie damit auch von Grund auf dauerhafte Projekte bauen.

Die zahlreichen verschiedenen Arduino-Platinen

In diesem Buch arbeiten wir zwar ausschließlich mit dem Arduino Uno, doch es stehen auch noch viele alternative Platinen zur Verfügung, die sich in der Baugröße, der Anzahl der Ein- und Ausgangspins, dem Speicherplatz für Sketche und dem Preis unterscheiden.

ATmega-328P

ATmega-328P SMD

ATmega2560

SAM3X8E

Vom Benutzer austauschbar

Ja

Nein

Nein

Nein

Verarbeitungsgeschwindigkeit

16 MHz

16 MHz

16 MHz

84 MHz

Betriebsspannung

5 V

5 V

5 V

3,3 V

Anzahl Digitalpins

14 (davon 6 PBM-fähig)

14 (davon 6 PBM-fähig)

54 (davon 14 PBM-fähig)

54 (davon 14 PBM-fähig)

Anzahl analoger Eingangspins

6

8

16

12

Stromstärke (Gleichstrom) pro E/A-Pin

40 mA

40 mA

40 mA

3 bis 15 mA

Verfügbarer Flash-Speicher

31,5 KB

31,5 KB

248 KB

512 KB

EEPROM-Größe

1 KB

1 KB

4 KB

Kein EEPROM

SRAM-Größe

2 KB

2 KB

8 KB

96 KB

Tab. 11–2 Vergleichstabelle der Mikrocontroller

Einer der entscheidenden Unterschiede ist der verbaute Mikrocontroller. Zurzeit wird gewöhnlich ein ATmega328 oder ATmega2560 verwendet und beim Arduino Due ein weiteres, leistungsfähigeres Modell. Die Hauptunterschiede zwischen diesen Varianten (wobei es zwei Versionen des ATmega328 gibt) sind in Tabelle 11–2 aufgeführt.

Zum Vergleich der verschiedenen Arduino-kompatiblen Platinen werden vor allem Typ und Größe des Arbeitsspeichers herangezogen. Es gibt die folgenden drei Arten:

• Flash-Speicher dient dazu, einen Sketch festzuhalten, nachdem er von der IDE kompiliert und hochgeladen wurde.

• EEPROM (Electrically Erasable Programmable Read-Only Memory, also »elektrisch löschbarer, programmierbarer, schreibgeschützter Speicher«) ist ein kleiner Speicherbereich, der Bytevariablen aufnehmen kann, wie Sie in Kapitel 16 noch lernen werden.

• SRAM ist der Speicherplatz für die Variablen in Ihren Programmen.

HINWEIS

Neben dem Arduino Uno gibt es noch viele andere Arduino-Platinen, wobei die wenigen, die im Folgenden beschrieben werden, nur die Spitze des Eisbergs bilden. Scheuen Sie sich nicht, für umfangreichere oder kompliziertere Projekte auf die größeren Mega-Platinen umzusteigen. Falls Sie dagegen nur wenige E/A-Pins für ein langlebiges Projekt benötigen, sollten Sie dagegen einen Nano oder vielleicht sogar einen LilyPad in Betracht ziehen.

Sehen wir uns nun die Palette der verfügbaren Platinen an.

Arduino Uno

Der Uno gilt zurzeit als der Standard-Arduino. Alle jemals hergestellten Arduino-Shields sollten mit diesem Modell kompatibel sein. Aufgrund der eingebauten USB-Schnittstelle und des austauschbaren Mikrocontrollers wird der Uno auch als der am einfachsten zu benutzende Arduino angesehen.

Freetronics Eleven

Der Markt bietet viele Platinen, die die Funktion des Arduino nachbilden, und einige weisen sogar Verbesserungen gegenüber dem Standardmodell auf. Eine davon ist der Freetronics Eleven, den Sie in Abbildung 11–16 sehen.

Abb. 11–16 Freetronics Eleven

Der Eleven ist mit dem Arduino Uno vollständig kompatibel, weist aber mehrere Verbesserungen auf, die ihn besonders wertvoll machen. Erstens finden Sie unmittelbar unter den digitalen E/A-Pins einen kleinen Bereich zur Prototypkonstruktion, in dem Sie eigene Schaltungen direkt auf der Hauptplatine aufbauen können. Das hilft Zeit und Geld zu sparen, da Sie kein zusätzliches Prototyp-Shield kaufen müssen.

Zweitens befinden sich die LEDs für Senden/Empfangen (TX/RX), Stromversorgung und D13 alle an der rechten Kante der Platine, weshalb sie auch dann noch sichtbar sind, wenn ein Shield aufgesteckt ist. Außerdem weist der Eleven eine Mikro-USB-Buchse auf, die viel kleiner ist als der USB-Standardanschluss des Uno. Das vereinfacht die Konstruktion eigener Shields, da Sie sich keine Gedanken darüber machen müssen, dass Ihre Verbindungen gegen die USB-Buchse stoßen könnten. Den Eleven erhalten Sie auf http://www.freetronics.com/products/eleven/.

Der Freeduino

Der Freeduino stammt aus einem Open-Source-Gemeinschaftsprojekt, das Dateien veröffentlicht, mit deren Hilfe man seine eigenen Arduino-kompatiblen Platinen herstellen kann. Eine der beliebtesten Konstruktionen ist der Bausatz für eine mit dem Duemilanove kompatible Platine (siehe Abb. 11–17).

Abb. 11–17 Die zusammengebaute Duemilanove-kompatible Freeduino-Platine

Den Freeduino können Sie für alle Projekte in diesem Buch verwenden. Zwei seiner Hauptvorteile bestehen darin, dass er preiswert ist und dass es sich naturgemäß als besonders befriedigend erweist, seine Platine selbst zusammenzusetzen. Den Freeduino-Bausatz bekommen Sie bei http://www.seeedstudio.com/ (mit drei e!).

Der Boarduino

Der Boarduino ist eine minimalistische Arduino-Variante für die Arbeit auf Steckplatinen. Er wird als Bausatz geliefert und muss zusammengelötet werden. Abbildung 11–18 zeigt die fertige Platine.

Abb. 11–18 Ein zusammengebauter Boarduino

Den Boarduino-Bausatz erhalten Sie auf http://www.adafruit.com/. Er bietet den gesamten Funktionsumfang des Freeduino, benötigt aber eine separate Stromquelle, wenn Sie mehr als 500 mA brauchen.

Der Arduino Nano

Wenn Sie eine kompakte, vorgefertigte Arduino-kompatible Platine haben wollen, könnte der Nano das Richtige für Sie sein (siehe Abb. 11–19). Er ist für die Arbeit auf Steckplatinen gedacht und erweist sich als winziger, aber trotzdem leistungsfähiger Arduino.

Abb. 11–19 Ein Arduino Nano

Der Nano misst nur 1,8 × 4,3 cm, bietet aber den gesamten Funktionsumfang des Boarduino und des Freeduino. Außerdem enthält er die SMD-Version des ATmega328P, der zwei zusätzliche analoge Eingangspins bietet (A6 und A7). Der Nano kann von http://www.gravitech.us/arna30wiatp.html bezogen werden.

Der Arduino LilyPad

Der LilyPad ist für kreative Projekte wie elektronisch aktive Textilien gedacht. Tatsächlich können Sie einen LilyPad sogar mit Wasser und einem leichten Reinigungsmittel waschen, weshalb er sich ideal eignet, um z. B. ein Sweatshirt mit Lämpchen zu versehen. Die Bauform ist einmalig, wie Sie in Abbildung 11–20 erkennen können.

Abb. 11–20 Ein Arduino LilyPad

Für den Anschluss an die E/A-Pins des LilyPad müssen die Drähte auf die Platine gelötet werden, weshalb sich diese Variante eher für dauerhafte Projekte eignet. Im Rahmen der minimalistischen Gestaltung verfügt sie auch nicht über eine Spannungsregelung, weshalb es Sache des Benutzers ist, für eine eigene Spannungsquelle zwischen 2,7 und 5,5 V zu sorgen. Es gibt auch keinen USB-Anschluss, weshalb Sie zum Hochladen von Sketchen ein 5-Volt-FTDI-Kabel benötigen. Den Arduino LilyPad können Sie bei fast jedem Arduino-Anbieter erwerben.

Der Arduino Mega 2560

Wenn Ihnen auf dem Arduino Uno die E/A-Pins ausgehen oder wenn Sie mehr Speicherplatz für umfangreiche Sketche benötigen, sollten Sie den Mega 2560 aus Abbildung 11–21 in Betracht ziehen. Er misst 11 × 5 cm und ist damit größer als der Uno.

Abb. 11–21 Ein Arduino Mega 2560

Auch wenn der Mega 2560 viel größer ist als der Uno, passen doch die meisten Arduino-Shields auf ihn. Außerdem gibt es Prototyp-Shields in Mega-Baugröße, auf denen sich größere Projekte unterbringen lassen, als der Uno aufnehmen kann. Da der Mega über einen Mikrocontroller vom Typ ATmega2560 verfügt, sind auch sein Arbeitsspeicher und seine E/A-Fähigkeiten viel umfangreicher als die des Uno (siehe Tab. 11–2). Vier getrennte serielle Kommunikationsleitungen erweitern auch die Möglichkeiten zur Datenübertragung. Den Mega 2560 bekommen Sie bei fast allen Arduino-Anbietern.

Der Freetronics EtherMega

Wenn Sie einen Arduino Mega 2560, einen microSD-Shield und einen Ethernet-Shield zur Kommunikation mit dem Internet benötigen, besteht die beste Alternative darin, gleich einen EtherMega zu kaufen (siehe Abb. 11–22), der alle drei Funktionen auf einer einzigen Platine vereint und weniger kostet als ein Einzelkauf der drei Komponenten. Den EtherMega bekommen Sie auf http://www.freetronics.com/ethermega/.

Abb. 11–22 Ein Freetronics EtherMega

Der Arduino Due

Dies ist das leistungsstärkste Arduino-Modell, das je herausgebracht wurde. Mit seinem 84-MHz-Prozessor können Sie Ihre Sketche viel schneller ausführen lassen. Wie Sie in Abbildung 11–23 sehen, ähnelt diese Platine dem Arduino Mega 2560, aber es gibt noch einen zusätzlichen USB-Anschluss für externe Geräte. Außerdem sind die Pins anders belegt.

Darüber hinaus ist der Arbeitsspeicher des Due 16 Mal so groß wie der des Uno, sodass Sie auch sehr vielschichtige und ausführliche Sketche schreiben können. Allerdings läuft der Due nur mit 3,3 V, weshalb alle Schaltungen, Shields und sonstigen Geräte, die Sie an die Analog- oder Digitalpins anschließen, keine höhere Spannung als 3,3 V aufweisen dürfen. Die Vorteile des Due wiegen die Einschränkungen jedoch auf.

Abb. 11–23 Ein Arduino Due

HINWEIS

Wenn Sie nach einer neuen Arduino-Platine oder Zubehör Ausschau halten, sollten Sie sich an einen renommierten Händler wenden, der Kundendienst anbietet und Ihnen eine Garantie einräumt. Das Internet ist zwar voll von Billigvarianten, aber bei deren Herstellung wird oft gespart, um ein Produkt zu einem verboten niedrigen Preis auf den Markt werfen zu können. Wenn Sie dabei ein fehlerhaftes oder den Spezifikationen nicht entsprechendes Teil erwerben, haben Sie keine Chance, Ihr Geld zurückzubekommen.

OPEN-SOURCE-HARDWARE

Die Konstruktion der Arduino-Hardware ist offengelegt worden, sodass jeder sie nach eigenem Gutdünken herstellen, abwandeln, verbreiten und einsetzen kann. Diese Form von Vertrieb fällt unter den Begriff Open-Source-Hardware – eine junge Bewegung, die eine Antithese zum Prinzip des Urheberrechts und des gesetzlich geschützten geistigen Eigentums darstellt. Das Arduino-Team hat sich dazu entschlossen, die Konstruktion zum Nutzen der gesamten Hardware-Community und des Allgemeinwohls freizugeben.

Im Geiste der Open-Source-Hardware veröffentlichen auch viele der Organisationen, die Zubehör oder Varianten der Arduino-Originalplatinen herstellen, ihre Konstruktionen mit der gleichen Lizenz. Dadurch kann das Produkt viel schneller verbessert werden, als es einer einzigen Organisation möglich wäre, die die Hardware allein entwickelt.

Ausblick

Dieses Kapitel hat Ihnen einen umfassenderen Blick auf die verschiedenen Arten verfügbarer Hardware vermittelt. Dabei haben Sie gelernt, aus welchen Einzelteilen ein Arduino besteht und wie Sie einen eigenen Arduino auf einer Steckplatine zusammensetzen. Damit wissen Sie jetzt, wie Sie mehr als ein Arduino-Projekt bauen können, ohne mehrere Platinen kaufen zu müssen. Außerdem kennen Sie die verschiedenen Arduino-Platinen, die auf dem Markt angeboten werden, sodass Sie jeweils diejenige auswählen können, die sich am besten für Ihr Vorhaben eignet. Schließlich haben Sie auch ein Verständnis der Bewegung für Open-Source-Hardware gewonnen, die hinter dem Arduino steckt.

Im nächsten Kapitel lernen Sie verschiedene Motoren kennen und beginnen mit der Arbeit an einem vom Arduino gesteuerten, motorisierten Raupenfahrzeug!

12

Motoren und Bewegung

In diesem Kapitel lernen Sie Folgendes:

• Verwenden eines Stellmotors zum Bau eines Zeigerthermometers

• Steuern der Geschwindigkeit und Drehrichtung von Elektromotoren

• Verwenden eines Motor-Shields für den Arduino

• Erster Bauabschnitt eines motorisierten Raupenroboters

• Kollisionsverhinderung mithilfe einfacher Mikroschalter

• Kollisionsverhinderung mit Infrarot- und Ultraschallsensoren

Kleine Bewegungen mithilfe von Stellmotoren

Ein Stellmotor oder Servomotor enthält einen kleinen Elektromotor, der so gesteuert werden kann, dass er seine Antriebsachse um einen bestimmten Winkel dreht. Beispielsweise können Sie ihn an einem Stellarm, also an einem kleinen Stab oder einer Stange befestigen, um die Lenkung eines ferngesteuerten Autos zu betätigen. Auch die Zeiger einer Uhr sind eine Form von Stellarmen. Abbildung 12–1 zeigt einen Stellmotor mit drei Arten von Stellarmen.

Abb. 12–1 Stellmotor mit verschiedenen Stellarmen

Stellmotoren auswählen

Beachten Sie bei der Auswahl eines Stellmotors folgende Eigenschaften:

• Geschwindigkeit Die Zeit, die der Motor für die Drehung benötigt, gewöhnlich in Sekunden pro Winkelgrad angegeben.

• Drehbereich Der Winkelbereich, den der Stellmotor mit seiner Drehung abdecken kann, z. B. 180° (halbe Umdrehung) oder 360° (volle Umdrehung).

• Stromstärke Die Stromstärke, die der Stellmotor benötigt. In Kombination mit dem Arduino benötigen Sie möglicherweise eine eigene Stromquelle für den Motor.

• Drehmoment Die Kraft, die der Motor beim Drehen aufbringen kann. Je größer das Drehmoment, umso schwerere Dinge kann der Motor bewegen. Im Allgemeinen ist das gelieferte Drehmoment proportional zur erforderlichen Stromstärke.

Der Stellmotor in Abbildung 12–1 ist ein HXT900 von hexTronik. Er ist preiswert und kann Drehungen bis zu 180° vollführen (siehe Abb. 12–2).

Abb. 12–2 Beispiel für den Drehbereich eines Stellmotors

Einen Stellmotor anschließen

Einen Stellmotor an den Arduino anzuschließen, ist einfach, da Sie dabei nur drei Drähte berücksichtigen müssen. Beim HXT900 wird der dunkelste Draht an GND angeschlossen, der mittlere an die 5-Volt-Versorgung und der hellste (der Pulsdraht) an einen Digitalpin. Bei einem anderen Modell schauen Sie auf dem Datenblatt nach, um die korrekte Verdrahtung herauszufinden.

Den Stellmotor in Bewegung setzen

Nachdem der Motor angeschlossen ist, können Sie ihn in Bewegung setzen. Der folgende Sketch sorgt dafür, dass der Motor seinen Drehbereich abfährt. Verbinden Sie den Motor wie beschrieben mit dem Arduino, wobei Sie den Pulsdraht an Digitalpin 4 anlegen, geben Sie dann den Sketch aus Listing 12–1 ein und laden Sie ihn hoch.

#include <Servo.h>
Servo myservo;

void setup()
{
myservo.attach(4);
}

void loop()
{
myservo.write(180);
delay(1000);
myservo.write(90);
delay(1000);
myservo.write(0);
delay(1000);

}

Listing 12–1 Sketch zur Vorführung der Funktion eines Stellmotors

In diesem Sketch binden wir wie folgt die in der Arduino-IDE enthaltene Bibliothek Servo ein und erstellen eine Instanz des Servoobjekts:

#include <Servo.h>
Servo myservo;

Anschließend teilen wir dem Arduino wie folgt in void setup() mit, welche Digitalpins zur Steuerung des Stellmotors dienen:

myservo.attach(4); // Steuerung über Digitalpin 4

Jetzt müssen wir den Stellmotor nur noch auf folgende Weise in Bewegung setzen:

myservo.write(x);

Dabei ist x ein Integer zwischen 0 und 180, der für die Winkelposition steht, auf die sich der Motor dreht. Wenn Sie den Sketch aus Listing 12–1 ausführen, fährt der Motor seinen gesamten Drehbereich ab und hält dabei an den Endpunkten (0° und 180°) sowie in der Mitte (90°) an.

Mit Servomotoren können Sie nicht nur Objekte schieben oder ziehen, sondern auch Daten über einen Zeiger mit Skala ausgeben. Als Beispiel bauen wir in Projekt 38 ein Zeigerthermometer.

Projekt Nr. 38: Ein Zeigerthermometer bauen

Mit dem Stellmotor und dem Temperatursensor TMP36, den wir schon in früheren Kapiteln verwendet haben, wollen wir nun ein Zeigerthermometer bauen. Dazu messen wir die Temperatur und rechnen den Wert in einen Winkel zwischen 0° und 180° um, wobei dieser Winkelbereich einem Temperaturbereich zwischen 0 °C und 30 °C entspricht. Der Stellmotor dreht sich um den Winkel, der dem vorliegenden Temperaturwert entspricht.

Die Hardware

Für dieses Projekt sind nur wenige Teile erforderlich:

• ein Temperatursensor TMP36

• ein kleiner Stellmotor

• eine Steckplatine

• Verbindungsdrähte

• Arduino und USB-Kabel

Der Schaltplan

Auch der Schaltplan ist sehr einfach, wie Sie in Abbildung 12–3 sehen.

Abb. 12–3 Schaltplan für Projekt 38

Der Sketch

Der Sketch ermittelt die Temperatur mit den Methoden, die wir schon in Projekt 8 verwendet haben, und rechnet sie anschließend in den Winkel um, um den sich der Stellmotor drehen muss.

Geben Sie folgenden Sketch ein und laden Sie ihn hoch:

// Projekt 38: Ein Zeigerthermometer bauen

float voltage = 0;
float sensor = 0;
float currentC = 0;
int angle = 0;

#include <Servo.h>
Servo myservo;

void setup()
{
myservo.attach(4);
}

int calculateservo(float temperature)
{
float resulta;
int resultb;
resulta = -6 * temperature;
resulta = resulta + 180;
resultb = int(resulta);
return resultb;
}

void loop()
{
// Ermittelt die aktuelle Temperatur
sensor = analogRead(0);
voltage = (sensor*5000)/1024;
voltage = voltage-500;
currentC = voltage/10;

// Zeigt die aktuelle Temperatur mithilfe des Stellmotors an
angle = calculateservo(currentC);
// Rechnet den Temperaturwert in einen Drehwinkel um
if (angle>=0 && angle <=30)
{
myservo.write(angle); // Bewegt den Stellmotor um den Winkel,
// der dem Temperaturwert entspricht
delay(1000);
}
}

Der Großteil des Sketches sollte Ihnen bekannt vorkommen, aber die Funktion calculateservo() ist neu. Sie rechnet anhand der folgenden Formel den Temperaturwert in den Drehwinkel für den Stellmotor um:

Winkel = (–6 × Temperatur) + 180

Es ist sinnvoll, eine Skala für den Bereich der Temperaturen anzufertigen, die der Stellmotor anzeigen kann, und auch einen kleinen Zeiger an der Drehachse zu befestigen. Ein Beispiel dafür sehen Sie in Abbildung 12–4.

Abb. 12–4 Die Skala dient zur Angabe der Temperaturen.

E-Motoren

Als Nächstes beschäftigen wir uns beim Thema Motorsteuerung mit kleinen Elektromotoren. Sie werden für viele Anwendungen eingesetzt, z. B. für kleine Ventilatoren, Spielzeugautos und Modelleisenbahnen. Wie bei Stellmotoren müssen Sie auch beim Kauf von Elektromotoren verschiedene Eigenschaften beachten:

• Betriebsspannung Sie ist von Modell zu Modell sehr unterschiedlich. Mögliche Werte reichen von 3 V bis zu mehr als 12 V.

• Leerlaufstrom Die Stromstärke, die der Motor bei Betriebsspannung ohne Last zieht, also wenn sich die Motorwelle frei dreht und nichts antreibt.

• Blockierstrom Die Stromstärke, die der Motor zieht, wenn er versucht, sich zu drehen, dies aber aufgrund der Last nicht möglich ist.

• Drehzahl bei Betriebsspannung Die Drehzahl des Motors, angegeben in Umdrehungen pro Minute (U/min, 1/min oder min-1).

In unserem Beispiel verwenden wir einen kleinen, preiswerten Elektromotor mit einer Drehzahl von 8540 U/min bei 3 V (siehe Abb. 12–5).

Zur Steuerung des Motors verwenden wir einen Transistor (siehe Kapitel 3). Da unser Motor Stromstärken bis zu 0,7 A aufnimmt, was mehr ist, als ein Transistor vom Typ BC548 verkraften kann, verwenden wir für dieses Projekt einen sogenannten Darlington-Transistor.

Abb. 12–5 Ein kleiner E-Motor

Der Darlington-Transistor TIP120

Ein Darlington-Transistor kann mit hohen Stromstärken und Spannungen umgehen. Der TIP120 ist in der Lage, bis zu 5 A bei 60 V durchzureichen, was für unseren kleinen E-Motor mehr als genug ist. Das Schaltplansymbol des TIP120 ähnelt dem des BC548, wie Sie in Abbildung 12–6 sehen, aber der Darlington weist eine größere Bauform auf als der normale Transistor.

Abb. 12–6 Schaltplansymbol des TIP120

Das Gehäuse des TIP120 sieht so aus wie das des TO-220 (siehe Abb. 12–7).

Abb. 12–7 Der TIP120

Wenn Sie den TIP120 so halten, dass Sie auf die Beschriftung schauen, sind die Kontakte von links nach rechts die Basis (B), der Kollektor (C) und der Emitter (E). Die Metalllasche für die Wärmeableitung ist ebenfalls mit dem Kollektor verbunden.

Projekt Nr. 39: Den Motor steuern

In diesem Projekt steuern wir den Motor, indem wir seine Drehzahl regeln.

Die Hardware

Sie benötigen folgende Teile:

• einen kleinen 3-Volt-Elektromotor

• einen 1-kΩ-Widerstand (R1)

• eine Diode 1N4004

• einen Darlington-Transistor TIP120

• eine separate 3-Volt-Stromquelle

• eine Steckplatine

• Verbindungsdrähte

• Arduino und USB-Kabel

Für Motoren müssen Sie eine separate Stromquelle verwenden, da der Arduino einen Motor nicht unter allen Umständen mit ausreichend Strom versorgen kann. Wenn der Motor blockiert, zieht er eine Stromstärke bis zur Höhe des Blockierstroms, der mehr als 1 A betragen kann. Das ist mehr, als der Arduino liefern kann, und wenn er es trotzdem versucht, kann das die Platine irreparabel beschädigen.

Eine einfache Lösung besteht darin, eine zusätzliche Batteriepackung zu verwenden. Für eine 3-Volt-Stromversorgung reicht eine Packung aus zwei AA-Zellen mit vorverdrahteten Anschlüssen, wie sie in Abbildung 12–8 zu sehen ist.

Abb. 12–8 Batteriepackung für zwei AA-Zellen

Der Schaltplan

Bauen Sie die Schaltung nach dem Plan in Abbildung 12–9 zusammen.

Abb. 12–9 Schaltplan für Projekt 11

Der Sketch

In diesem Projekt regeln wir die Motordrehzahl vom Stillstand (0 U/min) bis zum Maximum hoch und wieder zurück auf null. Geben Sie den folgenden Sketch ein und laden Sie ihn hoch:

// Projekt 39: Den Motor steuern

void setup()
{
pinMode(5, OUTPUT);
}

void loop()
{
for (int a=0; a<256; a++)
{
analogWrite(5, a);
delay(100);
}
delay(5000);
for (int a=255; a>=0; a--)
{
analogWrite(5,a);
delay(100);
}
delay(5000);
}

Die Motordrehzahl regeln wir mithilfe der Pulsbreitenmodulation (was in Projekt 3 erklärt wurde). Denken Sie daran, dass dies nur über die Digitalpins 3, 5, 6, 9, 10 und 11 möglich ist. Bei dieser Methode wird Strom in kurzen Pulsen an den Motor abgegeben: Je länger der Puls, umso höher die Drehzahl, da der Motor dann während eines gegebenen Zeitraums länger ein- als ausgeschaltet ist. Bei beginnt der Motor daher im Stillstand und beschleunigt langsam, wobei Sie die Beschleunigung über den Wert von delay bei steuern können. Bei läuft der Motor so schnell wie möglich und hält diese Geschwindigkeit fünf Sekunden lang. Danach wird der Vorgang ab umgekehrt, sodass der Motor wieder verlangsamt, bis er anhält.

HINWEIS

Wenn sich der Motor in Bewegung setzt, hören Sie möglicherweise ein Heulen ähnlich wie bei einer E-Lok oder einer Straßenbahn, die von der Haltestelle wegfährt. Das ist ganz normal und kein Grund, sich Sorgen zu machen.

Die Diode wird auf die gleiche Weise eingesetzt wie der Relaissteuerkreis in Abbildung 3–19, nämlich zum Schutz der Schaltung. Wird der Strom für den Motor abgeschaltet, bleiben für einen kurzen Zeitraum noch Restladungen in der Spule des Motors zurück und wandern ab. Die Diode sorgt dafür, dass diese Ströme in einer Schleife durch die Spuleneinheit geführt werden, bis sie sich in Form einer geringen Erwärmung auflösen.

Projekt Nr. 40: Einen Roboter mit Raupenantrieb bauen und steuern

Es kann zwar sehr nützlich sein, die Drehzahl eines Motors zu steuern, aber wir wollen uns im Folgenden mit einer interessanteren Aufgabe beschäftigen, nämlich zwei Motoren gleichzeitig zu steuern und dabei sowohl die Drehzahl als auch die Drehrichtung zu regeln. Das Ziel dabei besteht darin, ein Raupenfahrzeug zu bauen. Die Arbeit daran werden wir in den nächsten Kapiteln noch fortsetzen. Hier geht es zunächst einmal um die Konstruktion und die grundlegende Steuerung.

Unsere Raupe hat zwei Motoren, die jeweils eine Kette steuern. Damit kann das Fahrzeug über kleine Hindernisse hinwegklettern und sich auf dem Teller drehen. Außerdem wollen wir verhindern, dass es bei der Fahrt gegen Hindernisse stößt. In diesem und den folgenden Projekten wird gezeigt, wie Sie Geschwindigkeit und Fahrtrichtung regeln und wie Sie mit zusätzlichen Bauteilen eine Kollisionsverhinderung und eine Fernsteuerung konstruieren. Nach dem Durcharbeiten der Projekte in diesem Buch verfügen Sie über eine solide Grundlage, auf der Sie Ihre eigenen Vorstellungen und Projekte verwirklichen können.

Die Hardware

Sie benötigen folgende Teile:

• einen Pololu-RP5-Bausatz für das Chassis von Raupenfahrzeugen

• eine Pololu-RP5-Chassisplatte

• sechs AA-Alkalibatterien

• eine 9-Volt-Batterie mit Kabel für den Anschluss an den Gleichstromeingang des Arduino

• einen Motor-Shield DFRobot 2A

• Arduino und USB-Kabel

Das Chassis

Grundlage jedes fahrbaren Roboters ist ein solides Fahrgestell, das Motor, Antriebsstrang und Stromversorgung enthält. Bei einem Roboter, der über den Arduino gesteuert wird, muss außerdem Platz zur Montage der Platine und diverser externer Teile vorhanden sein.

Auf dem Markt stehen viele verschiedene Chassismodelle zur Auswahl. Wir verwenden hier ein Fahrgestell für Raupenfahrzeuge, nämlich das aus der Baureihe Pololu RP5 mit zwei Motoren, das Sie in Abbildung 12–10 sehen.

Abb. 12–10 Das Chassis unseres Raupenfahrzeugs

Doppelte Stromversorgung

Im Pololu-Chassis ist ein Halter für sechs AA-Batterien enthalten (siehe Abb. 12–11), den wir als Stromquelle für die Motoren verwenden. Er befinden sich unten im Fahrgestell zwischen den Motoren, was dem Roboter einen niedrigen Schwerpunkt gibt.

Abb. 12–11 Batteriehalter mit sechs AA-Zellen

Die Stromversorgung in Abbildung 12–11 ist zwar kräftig, doch brauchen für den Arduino eine weitere, damit der Sketch auch dann noch ausgeführt werden kann, wenn die Motoren versagen. Den Strom für den Arduino beziehen wir bei diesem Projekt aus einer 9-Volt-Batterie, die Sie über das Kabel aus Abbildung 12–12 mit dem Stromanschluss des Arduino verbinden können.

Abb. 12–12 Kabel zur Verbindung von Batterie und Arduino

Die Grundplatte

Der letzte Teil des Chassis ist die Grundplatte, die Sie in Abbildung 12–13 sehen.

Abb. 12–13 Die Grundplatte

Die Grundplatte deckt die Oberseite des Chassis ab. Auf ihr können andere Elemente mit Distanzstücken und passenden M3-Schrauben befestigt werden. (Schrauben, Distanzstücke und Unterlegscheiben erhalten Sie beim Anbieter des Roboterbausatzes und im Baumarkt.) In Abbildung 12–13 sind auf der Grundplatte bereits Distanzstücke zur Montage des Arduino angebracht. Das Ergebnis sehen Sie in Abbildung 12–14.

Abb. 12–14 Grundplatte mit montiertem Arduino

Der Shield

Als Letztes brauchen wir noch die Elektronik, um die beiden Motoren im Chassis zu steuern. Wir könnten zwar für jeden der Motoren die Schaltung aus Abbildung 12–9 verwenden, aber dabei wären wir nicht in der Lage, die Drehrichtung zu regeln. Außerdem wäre es ziemlich unbequem, die gesamte Verdrahtung selbst herzustellen. Stattdessen verwenden wir einen Motor-Shield. Er enthält nicht nur die erforderlichen Schaltungen, um die von den Motoren genutzten hohen Stromstärken zu handhaben, sondern nimmt auch Befehle vom Arduino entgegen, um sowohl die Drehzahl als auch die Richtung der beiden Motoren zu steuern. Für unser Raupenfahrzeug verwenden wir den Motor-Shield 2A von DFRobot (http://www.dfrobot.com/), den Sie in Abbildung 12–15 sehen.

Abb. 12–15 Der Motor-Shield von DFRobot

Den Motor-Shield anschließen

Es ist nicht schwer, die erforderlichen Verbindungen für den Motor-Shield herzustellen: Schließen Sie die Drähte der Batteriepackung an die Klemmenleiste in der unteren linken Ecke des Shields an (siehe Abb. 12–16). Der schwarze Draht (minus) gehört nach rechts, der rote nach links.

Als Nächstes schließen Sie die beiden Kabelpaare an, die von den Motoren kommen. Achten Sie auf die richtige Anordnung der Drähte (siehe Abb. 12–17).

Abb. 12–16 Gleichstromanschluss

Abb. 12–17 Anschluss der Motoren

Die Jumper stecken

Um den Shield einzurichten, müssen Sie als Letztes die Steckbrücken (Jumper) richtig anordnen. Zwischen dem Gleichstromanschluss und der unteren Reihe von Kontakten auf dem Shield sehen Sie sechs Pins mit zwei schwarzen Steckbrücken. Platzieren Sie sie horizontal, sodass sie die vier Kontaktstifte auf der linken Seite abdecken (siehe Abb. 12–18). Vergewissern Sie sich abschließend, dass die vier Jumper an den PBM-Anschlüssen wie in Abbildung 12–19 vertikal gesteckt sind.

Abb. 12–18 Korrekte Platzierung der Jumper für den Stromanschluss

Abb. 12–19 Korrekte Platzierung der PBM-Jumper

Wenn die Drähte der Motoren nicht farbig gekennzeichnet sind, müssen Sie sie möglicherweise nach dem ersten Probelauf austauschen, um die Vorwärts- und Rückwärtsrichtung korrekt festzulegen.

Nachdem Sie alle Kabelanschlüsse vorgenommen, alle Jumper gesteckt, die Batteriepackung eingesetzt, den Arduino und den Shield auf der Grundplatte montiert und auf dem Chassis befestigt haben, sieht Ihr Raupenfahrzeug wie in Abbildung 12–20 aus.

Abb. 12–20 Unser Raupenroboter ist fahrbereit!

Der Sketch

Nun wollen wir die Raupe in Bewegung setzen. Als Erstes erstellen wir dazu einige Funktionen, um die Bewegungssteuerung zu vereinfachen. Bei zwei Motoren gibt es vier mögliche Bewegungen:

• Vorwärtsfahrt

• Rückwärtsfahrt

• Drehen im Uhrzeigersinn

• Drehen gegen den Uhrzeigersinn

Der Motor-Shield steuert jeden der beiden Motoren über zwei Digitalpins, wobei der eine zur Drehzahlregelung mithilfe der Pulsbreitenmodulation dient (die wir in Projekt 39 vorgeführt haben) und der andere die Drehrichtung des Motors bestimmt.

Für die vier Bewegungen verwenden wir im Sketch die vier Funktionen goForward(), goBackward(), rotateLeft() und rotateRight(). Jede von ihnen nimmt einen Wert in Millisekunden für die Dauer der Bewegung sowie einen PBM-Drehzahlwert zwischen 0 und 255 an. Damit der Roboter beispielsweise zwei Sekunden lang mit Höchstgeschwindigkeit vorwärts fährt, verwenden wir also goForward(2000,255).

Geben Sie den folgenden Sketch ein und speichern Sie ihn, laden Sie ihn aber noch nicht hoch:

// Projekt 40: Einen Roboter mit Raupenantrieb bauen und steuern

int m1speed=6;          // Digitalpins für die Drehzahlregelung
int m2speed=5;
int m1direction=7;      // Digitalpins für die Drehrichtung
int m2direction=4;

void setup()
{
pinMode(m1direction, OUTPUT);
pinMode(m2direction, OUTPUT);
delay(5000);
}

void goForward(int duration, int pwm)
{
digitalWrite(m1direction,HIGH);  // Vorwärts
digitalWrite(m2direction,HIGH);  // Vorwärts
analogWrite(m1speed, pwm);       // Drehzahl
analogWrite(m2speed, pwm);
delay(duration);
analogWrite(m1speed, 0);         // Drehzahl
analogWrite(m2speed, 0);
}

void goBackward(int duration, int pwm)
{
digitalWrite(m1direction,LOW);   // Rückwärts
digitalWrite(m2direction,LOW);   // Rückwärts
analogWrite(m1speed, pwm);       // Drehzahl
analogWrite(m2speed, pwm);
delay(duration);
analogWrite(m1speed, 0);         // Drehzahl
analogWrite(m2speed, 0);
}

void rotateRight(int duration, int pwm)
{
digitalWrite(m1direction,HIGH);  // Vorwärts
digitalWrite(m2direction,LOW);   // Rückwärts
analogWrite(m1speed, pwm);       // Drehzahl
analogWrite(m2speed, pwm);
delay(duration);
analogWrite(m1speed, 0);         // Drehzahl
analogWrite(m2speed, 0);
}

void rotateLeft(int duration, int pwm)
{
digitalWrite(m1direction,LOW);   // Rückwärts
digitalWrite(m2direction,HIGH);  // Vorwärts
analogWrite(m1speed, pwm);       // Drehzahl
analogWrite(m2speed, pwm);
delay(duration);
analogWrite(m1speed, 0);         // Drehzahl
analogWrite(m2speed, 0);
}

void loop()
{
goForward(1000, 255);
rotateLeft(1000, 255);
goForward(1000, 255);
rotateRight(1000, 255);
goForward(1000, 255);
goBackward(2000, 255);
delay(2000);
}

Die Drehrichtung der Motoren legen wir in diesem Sketch jeweils wie folgt fest:

digitalWrite(m1direction,Richtung);

Der Wert für Richtung ist HIGH für vorwärts oder LOW für rückwärts. Damit der Roboter geradeaus fährt, müssen wir beide Motoren in dieselbe Richtung drehen, wie wir es bei und getan haben.

Die Drehzahl regeln wir wie folgt:

analogWrite(m1speed, PBM);

Die Drehzahl steuern wir über den Wert von PBM, der zwischen 0 und 255 liegen kann.

Damit die Raupe nach links oder rechts wendet, müssen sich die beiden Motoren entgegengesetzt zueinander drehen. Das haben wir bei und getan.

WARNUNG

Wenn Sie bereit sind, den Sketch hochzuladen, dann halten Sie den Raupenroboter entweder mit der Hand oberhalb ihres Arbeitstisches fest oder bocken ihn auf, damit die Ketten keinen Kontakt zur Oberfläche haben. Wenn Sie das nicht tun, setzt sich das Fahrzeug sofort nach Hochladen des Sketches in Bewegung und stürzt nach fünf Sekunden vom Tisch.

Laden Sie den Sketch hoch, ziehen Sie das USB-Kabel ab und verbinden Sie das Batteriekabel mit dem Stromanschluss des Arduino. Platzieren Sie die Raupe dann auf dem Fußboden oder einer anderen ebenen Fläche und lassen Sie ihn fahren. Experimentieren Sie mit den Bewegungsfunktionen von Projekt 40, um das Fahrzeug zu steuern. Dadurch machen Sie sich damit vertraut, welche Strecken den Verzögerungswerten entsprechen.

Kollisionserkennung

Nachdem wir es geschafft haben, unseren Roboter in Bewegung zu setzen, können wir ihn mit einer rudimentären Intelligenz ausstatten, z. B. mit einer Kollisionserkennung, die ihm mitteilt, dass er gegen ein Hindernis gestoßen ist, oder mit einer Vorkehrung, die den Abstand zu Hindernissen misst, sodass das Fahrzeug ihnen auszuweichen kann.

Projekt Nr. 41: Kollisionen mithilfe eines Mikroschalters erkennen

Ein Mikroschalter funktioniert wie die einfachen Drucktasten aus Kapitel 4, ist aber größer gebaut und verfügt über eine lange Metallzunge, die als Auslösehebel dient (siehe Abb. 12–21).

Beim Anschluss des Mikroschalters verbinden Sie einen Draht mit dem unteren Kontakt und den zweiten mit dem Kontakt, der mit NO gekennzeichnet ist (Normally Open). Dadurch fließt Strom nur dann, wenn der Auslösehebel gedrückt wurde. Befestigen Sie den Mikroschalter vorn an der Raupe. Wenn der Roboter gegen ein Hindernis stößt, wird der Auslöser gedrückt, woraufhin Strom fließt. Das Fahrzeug ändert dann die Fahrtrichtung (oder führt eine andere festgelegte Aktion durch).

Abb. 12–21 Ein Mikroschalter

Der Schaltplan

Wie Sie in Abbildung 12–22 sehen, wird der Mikroschalter genauso verdrahtet wie eine Drucktaste.

Abb. 12–22 Schaltplan für die Kollisionserkennung mithilfe eines Mikroschalters

Der Sketch

Den Mikroschalter verbinden wir mit einem der Interrupt-Pins (Digitalpin 2). Der Gedanke, über den Interrupt eine Funktion aufzurufen, die den Roboter eine gewisse Zeit lang rückwärts fahren lässt, liegt zwar nahe, doch das ist leider nicht möglich, denn in Funktionen, die von Interrupts aufgerufen werden, können wir delay() nicht anwenden. Daher müssen wir in diesem Fall ein wenig um die Ecke denken.

Stattdessen schaltet die Funktion goForward() die Motoren nur ein, wenn beide Bedingungen für die booleschen Variablen crash und move erfüllt sind. Ist crash dagegen true, werden die Motoren mit einer niedrigeren Drehzahl zwei Sekunden lang rückwärts betrieben, damit das Fahrzeug zurücksetzen kann.

Da wir aufgrund des Interrupts keine delay()-Funktionen verwenden können, messen wir die Laufzeit der Motoren, indem wir zu Anfang millis() ablesen und diesen Startwert mit dem aktuellen Wert von millis() vergleichen. Ist die Differenz größer oder gleich der gewünschten Dauer, wird move auf false gesetzt, sodass die Motoren anhalten.

Geben Sie den folgenden Sketch ein und laden Sie ihn hoch:

// Projekt 41: Kollisionen mithilfe eines Mikroschalters erkennen

int m1speed=6;         // Digitalpins für die Drehzahlregelung
int m2speed=5;
int m1direction=7;     // Digitalpins für die Drehrichtung
int m2direction=4;
boolean crash=false;

void setup()
{
pinMode(m1direction, OUTPUT);
pinMode(m2direction, OUTPUT);
attachInterrupt(0, backOut, RISING);
delay(5000);
}

void backOut()
{
crash=true;
}

void backUp()
{
digitalWrite(m1direction,LOW);  // Rückwärts
digitalWrite(m2direction,LOW);  // Rückwärts
analogWrite(m1speed, 200);      // Drehzahl
analogWrite(m2speed, 200);
delay(2000);
analogWrite(m1speed, 0);        // Drehzahl
analogWrite(m2speed, 0);
}

void goForward(int duration, int pwm)
{
long a,b;
boolean move=true;
a=millis();
do
{
if (crash==false)
{
digitalWrite(m1direction,HIGH);   // Vorwärts
digitalWrite(m2direction,HIGH);   // Vorwärts
analogWrite(m1speed, pwm);        // Drehzahl
analogWrite(m2speed, pwm);
}
if (crash==true)
{
backUp();
crash=false;
}
b=millis()-a;
if (b>=duration)
{
move=false;
}
} while (move!=false);
// Hält die Motoren an
analogWrite(m1speed, 0);
analogWrite(m2speed, 0);
}

void loop()
{
goForward(5000, 255);
delay(2000);
}

In diesem Sketch verwenden wir eine anspruchsvollere Methode für die Vorwärtsbewegung. Dabei werden zwei Variablen beobachtet. Die eine von ihnen ist die boolesche Variable crash. Wenn der Roboter gegen ein Hindernis stößt und den Mikroschalter auslöst, wird ein Interrupt aufgerufen, der bei die Funktion backOut() aufruft. Darin wird der Wert der Variable von false in true geändert. Die zweite überwachte Variable ist ebenfalls eine boolesche Variable und heißt move. In der Funktion goForward() berechnen wir bei anhand von millis() fortlaufend, ob der Roboter die Bewegung für die im Parameter duration festgelegte Zeitdauer abgeschlossen hat.

Bei prüft die Funktion, ob die verstrichene Zeit kleiner ist als die angeforderte Zeitdauer. Wenn ja, wird die Variable move auf true gesetzt. Der Raupenroboter bewegt sich also nur vorwärts, wenn weder eine Kollision erfolgt noch die angeforderte Zeitdauer abgelaufen ist. Wird eine Kollision erkannt, wird die Funktion backUp() aufgerufen, die Sie bei sehen. Der Roboter setzt dann zwei Sekunden lang langsam zurück und nimmt anschließend die Fahrt wieder auf.

HINWEIS

Sie können die übrigen Bewegungsfunktionen aus Projekt 40 hinzufügen, um dieses Beispiel zu erweitern oder abzuwandeln.

Infrarotsensoren zur Abstandsmessung

Bei unserer nächsten Methode zur Kollisionsverhinderung verwenden wir Infrarot-Abstandssensoren (IR). Sie senden ein infrarotes Lichtsignal aus, das an einer Oberfläche reflektiert wird, messen das zurückkommende Signal und geben eine Spannung aus, die in einem bestimmten Verhältnis zur Entfernung von der Oberfläche steht. Zur Kollisionsverhinderung sind Infrarotsensoren aufgrund ihres niedrigen Preises sehr nützlich, aber für eine genaue Abstandsmessung eignen sie sich nicht. Für unser Projekt verwenden wir den GP2Y0A21YK0F von Sharp, den Sie in Abbildung 12–23 sehen.

Abb. 12–23 Der IR-Sensor von Sharp

Verkabelung

Zur Verkabelung des Sensors verbinden Sie seinen roten und seinen schwarzen Draht mit dem 5-Volt-Anschluss bzw. GND und den weißen mit einem analogen Eingangspin des Arduino. Zur Messung der vom Sensor zurückgegebenen Spannung verwenden wir analogRead(). Das Diagramm in Abbildung 12–24 zeigt das Verhältnis zwischen Ausgangsspannung und gemessener Entfernung.

Abb. 12–24 Diagramm der Ausgangsspannung des IR-Sensors in Abhängigkeit von der Entfernung

Den IR-Abstandssensor testen

Da sich das Verhältnis zwischen Entfernung und Ausgangsspannung nicht so leicht in Form einer Gleichung ausdrücken lässt, teilen wir die Messwerte in Stufen zu je 5 cm ein. Das wollen wir an einem einfachen Beispiel veranschaulichen. Schließen Sie den weißen Draht des Infrarotsensors an Analogpin 0 an, den roten an die 5-Volt-Versorgung und den schwarzen an GND. Geben Sie dann den Sketch aus Listing 12–2 ein und laden Sie ihn hoch.

float sensor = 0;
int cm = 0;

void setup()
{
Serial.begin(9600);
}

void loop()
{
sensor = analogRead(0);
if (sensor<=90)
{
Serial.println("Infinite distance!");
} else if (sensor<100) // 80 cm
{
cm = 80;
} else if (sensor<110) // 70 cm
{
cm = 70;
} else if (sensor<118) // 60 cm
{
cm = 60;
} else if (sensor<147) // 50 cm
{
cm = 50;
} else if (sensor<188) // 40 cm
{
cm = 40;
} else if (sensor<230) // 30 cm
{
cm = 30;
} else if (sensor<302) // 25 cm
{
cm = 25;
} else if (sensor<360) // 20 cm
{
cm = 20;
} else if (sensor<505) // 15 cm
{
cm = 15;
} else if (sensor<510) // 10 cm
{
cm = 10;
} else if (sensor>=510) // Zu nah!
{
Serial.println("Too close!");
}
Serial.print("Distance: ");
Serial.print(cm);
Serial.println(" cm");
delay(250);
}

Listing 12–2 Sketch zur Vorführung des IR-Sensors

Der Sketch liest bei die Spannung am IR-Sensor ab und wählt dann ab mit einer Folge von if-Anweisungen den ungefähren Abstand aus, der zurückgegeben werden soll. Diesen Abstand berechnen wir mithilfe von zwei Parametern aus der vom Sensor zurückgegebenen Spannung. Der erste ist das Verhältnis zwischen Spannung und Entfernung aus Abbildung 12–24. Zweitens haben wir in Projekt 6 gelernt, dass analogRead() einen Wert zwischen 0 und 1023 zurückgibt, der einer Spannung zwischen 0 und 5 V entspricht, und können damit die ungefähre Entfernung zum Objekt bestimmen.

Laden Sie den Sketch hoch, öffnen Sie den seriellen Monitor und experimentieren Sie, indem Sie Ihre Hand oder ein Stück Papier in unterschiedlichen Abständen vor den Sensor halten. Auf dem seriellen Monitor wird jeweils die ungefähre Entfernung angegeben, wie Sie in Abbildung 12–25 sehen.

Abb. 12–25 Ergebnis von Listing 12–2

Projekt Nr. 42: Kollisionen mithilfe eines IR-Abstandssensors verhindern

Jetzt bringen wir anstelle des Mikroschalters den IR-Sensor an unserem Raupenroboter an. Außerdem verwenden wir eine Abwandlung des Sketches aus Projekt 41. Anstatt auf einen Interrupt zurückzugreifen, schreiben wir die Funktion checkDistance(), die die Variable crash auf true setzt, wenn die vom IR-Sensor gemessene Entfernung 20 cm oder weniger beträgt. Diese Funktion setzen wir in der do...while-Schleife der Funktion goForward() für die Vorwärtsbewegung ein.

Schließen Sie den Infrarotsensor an die Raupe an, geben Sie folgenden Sketch ein und laden Sie ihn hoch:

// Projekt 42: Kollisionen mithilfe eines IR-Abstandssensors verhindern

int m1speed=6;          // Digitalpins für die Drehzahlregelung
int m2speed=5;
int m1direction=7;      // Digitalpins für die Drehrichtung
int m2direction=4;
boolean crash=false;

void setup()
{
pinMode(m1direction, OUTPUT);
pinMode(m2direction, OUTPUT);
delay(5000);
}

void backUp()
{
digitalWrite(m1direction,LOW);   // Rückwärts
digitalWrite(m2direction,LOW);   // Rückwärts
analogWrite(m1speed, 200);       // Drehzahl
analogWrite(m2speed, 200);
delay(2000);
analogWrite(m1speed, 0);         // Drehzahl
analogWrite(m2speed, 0);
}

void checkDistance()
{
if (analogRead(0)>460)   1
{
crash=true;
}
}

void goForward(int duration, int pwm)
{
long a,b;
boolean move=true;
a=millis();
do
{
checkDistance();
if (crash==false)

{
digitalWrite(m1direction,HIGH);     // Vorwärts
digitalWrite(m2direction,HIGH);     // Vorwärts
analogWrite(m1speed, pwm);          // Drehzahl
analogWrite(m2speed, pwm);
}
if (crash==true)
{
backUp();
crash=false;
}
b=millis()-a;
if (b>=duration)
{
move=false;
}
} while (move!=false);
// Hält die Motoren an
analogWrite(m1speed, 0);
analogWrite(m2speed, 0);
}

void loop()
{
goForward(5000, 255);
delay(2000);
}

Der Sketch nutzt die gleichen Methoden wie der aus Projekt 41, führt bei aber fortlaufend Abstandsmessungen durch und setzt die Variable crash auf true, wenn die Entfernung vom IR-Sensor zu einem Objekt weniger als 20 cm beträgt.

Wenn Sie den Roboter mit dem IR-Sensor in Marsch setzen, werden die Vorteile eines berührungslosen Kollisionssensors sofort deutlich. Es ist auch nicht schwer, das Fahrzeug mit weiteren Sensoren auszustatten, z. B. mit je einem vorn und hinten oder mit Sensoren an allen Ecken. Mit dem, was Sie bereits gelernt haben, sollten Sie in der Lage sein, Code hinzuzufügen, um die Sensoren nacheinander abzufragen und Entscheidungen aufgrund der zurückgegebenen Abstandswerte zu fällen.

Ultraschallsensoren

Als letzte Methode zur Kollisionsverhinderung setzen wir einen Ultraschallsensor ein. Er sendet Schallwellen sehr hoher Frequenz aus (die für das menschliche Ohr nicht wahrnehmbar sind), und misst, wie viel Zeit verstreicht, bis diese Wellen von einer Oberfläche zurückgeworfen werden und wieder beim Sensor eingehen. In diesem Projekt verwenden wir den Sensor Parallax Ping))) aus Abbildung 12–26, da er preiswert ist und eine Genauigkeit bis zu 1 cm aufweist.

Abb. 12–26 Der Ultraschallsensor Ping)))

Die Reichweite dieses Sensors macht es möglich, Entfernungen zwischen 2 cm und 300 cm zu messen. Da die Schallwellen jedoch zum Sensor zurückgeworfen werden müssen, darf der Winkel des Sensors zur Fahrtrichtung nicht mehr als 45° betragen.

Den Ultraschallsensor anschließen

Um den Sensor anzuschließen, verbinden Sie seine 5-Volt- und seine Masseleitung mit den entsprechenden Pins und dann den Signalpin (SIG) mit einem beliebigen Digitalpin des Arduino.

Den Ultraschallsensor verwenden

Der Ultraschallsensor führt Messungen nur auf Anforderung durch. Dazu müssen wir ein sehr kurzes HIGH-Signal von 5 μs Länge an den SIG-Pin senden. Nach einer Weile gibt der Sensor ein HIGH-Signal zurück, dessen Länge der Zeit einspricht, die der Ultraschallton für den Weg vom Sensor zum Objekt und wieder zurück benötigt hat. Um die Entfernung zwischen Sensor und Objekt zu bestimmen, müssen wir diesen Wert halbieren.

Der Digitalpin spielt sowohl die Rolle des Ausgangs als auch die des Eingangs. Außerdem benötigen wir die beiden folgenden neuen Funktionen:

• delayMicroseconds(Dauer)   Hält den Arduino-Sketch für die angegebene Dauer in Mikrosekunden an.

• pulseIn(Pin, HIGH)   Misst die Dauer des HIGH-Pulses am angegebenen Digitalpin und gibt sie in Mikrosekunden zurück.

Wenn wir die Dauer des eingehenden Pulses kennen, müssen wir sie durch 29,412 dividieren, um den Abstand in Zentimetern zu erhalten (da die Schallgeschwindigkeit 340 m/s oder 34 cm/ms beträgt).

Den Ultraschallsensor testen

Um den Einsatz des Sensors zu vereinfachen, verwenden wir die Funktion getDistance() aus Listing 12–3. Verbinden Sie den SIG-Pin des Ultraschallsensors mit Pin 3 am Arduino, geben Sie den folgenden Code ein und laden Sie ihn hoch:

int signal=3;

void setup()
{
pinMode(signal, OUTPUT);
Serial.begin(9600);
}

int getDistance()
// Gibt die vom Ping)))-Sensor gemessene Entfernung in cm zurück
{
int distance;
unsigned long pulseduration=0;

// Ruft die Rohmessdaten vom Ping))) ab
// Legt den Pin als Ausgang fest, sodass wir einen Puls senden können
pinMode(signal, OUTPUT);

// Setzt den Ausgang auf LOW
digitalWrite(signal, LOW);
delayMicroseconds(5);

// Sendet einen 5-µs-Puls, um den Ping))) zu aktivieren
digitalWrite(signal, HIGH);
delayMicroseconds(5);
digitalWrite(signal, LOW);

// Macht den Digitalpin zum Eingang, um eingehende Pulse zu messen
pinMode(signal, INPUT);

// Misst die Länge des eingehenden Pulses
pulseduration=pulseIn(signal, HIGH);

// Teilt die Pulslänge durch 2
pulseduration=pulseduration/2;

// Errechnet den Abstand in cm
distance = int(pulseduration/29);
return distance;
}

void loop()
{
Serial.print(getDistance());
Serial.println(" cm ");
delay(500);
}

Der Abstand wird von der Funktion getDistance() zurückgegeben. Wenn Sie die einzelnen Schritte von bis verfolgen, können Sie erkennen, wie der Puls zum Sensor gesendet, die Rücklaufzeit gemessen und daraus die Entfernung berechnet wird.

Laden Sie den Sketch hoch, öffnen Sie den seriellen Monitor und bewegen Sie ein Objekt vor dem Sensor hin und zurück. Der Abstand zu dem Objekt wird wie in Abbildung 12–27 in Zentimetern angegeben.

Abb. 12–27 Das Ergebnis von Listing 12–3

Projekt Nr. 43: Kollisionen mithilfe eines Ultraschall-Abstandssensors verhindern

Nachdem wir jetzt wissen, wie der Ultraschallsensor funktioniert, wollen wir ihn an unserem Roboter einsetzen.

Der Sketch

Um einen Test auf drohende Zusammenstöße durchzuführen, können wir die Funktion getDistance() aus Listing 12–3 heranziehen. Im folgenden Sketch prüfen wir, ob der Abstand weniger als 10 cm beträgt, und lassen die Raupe in diesem Fall zurücksetzen. Geben Sie den folgenden Sketch ein und laden Sie ihn hoch, um dies auszuprobieren:

// Projekt 43: Kollisionen mithilfe eines Ultraschall-Abstandssensors
verhindern

int m1speed=6;         // Digitalpins für die Drehzahlregelung
int m2speed=5;
int m1direction=7;     // Digitalpins für die Drehrichtung
int m2direction=4;
int signal=3;
boolean crash=false;

void setup()
{
pinMode(m1direction, OUTPUT);
pinMode(m2direction, OUTPUT);
pinMode(signal, OUTPUT);
delay(5000);
Serial.begin(9600);
}

int getDistance()
// Gibt die vom Ping)))-Sensor gemessene Entfernung in cm zurück
{
int distance;
unsigned long pulseduration=0;
// Ruft die Rohmessdaten vom Ping))) ab
// Legt den Pin als Ausgang fest, sodass wir einen Puls senden können
pinMode(signal, OUTPUT);

// Setzt den Ausgang auf LOW
digitalWrite(signal, LOW);
delayMicroseconds(5);

// Sendet einen 5-μs-Puls, um den Ping))) zu aktivieren
digitalWrite(signal, HIGH);
delayMicroseconds(5);
digitalWrite(signal, LOW);

// Macht den Digitalpin zum Eingang, um eingehende Pulse zu messen
pinMode(signal, INPUT);

// Misst die Länge des eingehenden Pulses
pulseduration=pulseIn(signal, HIGH);

// Teilt die Pulslänge durch 2
pulseduration=pulseduration/2;

// Errechnet den Abstand in cm
distance = int(pulseduration/29);
return distance;
}

void backUp()
{
digitalWrite(m1direction,LOW);        // Fährt zurück
digitalWrite(m2direction,LOW);
delay(2000);
digitalWrite(m1direction,HIGH);       // Fährt nach links
digitalWrite(m2direction,LOW);
analogWrite(m1speed, 200);            // Drehzahl
analogWrite(m2speed, 200);
delay(2000);
analogWrite(m1speed, 0);              // Drehzahl
analogWrite(m2speed, 0);
}

void goForward(int duration, int pwm)
{
long a,b;
int dist=0;
boolean move=true;
a=millis();
do
{
dist=getDistance();
Serial.println(dist);
if (dist<10) // Bei einem geringeren Abstand als 10 cm
{
crash=true;
}
if (crash==false)
{
digitalWrite(m1direction,HIGH);    // Vorwärts
digitalWrite(m2direction,HIGH);    // Vorwärts
analogWrite(m1speed, pwm);         // Drehzahl
analogWrite(m2speed, pwm);
}
if (crash==true)
{
backUp();
crash=false;
}
b=millis()-a;
if (b>=duration)
{
move=false;
}
} while (move!=false);
// Hält die Motoren an
analogWrite(m1speed, 0);
analogWrite(m2speed, 0);
}

void loop()
{
goForward(1000, 255);
}

Auch hier messen wir wieder fortlaufend den Abstand. Beträgt die Entfernung zwischen Sensor und Objekt weniger als 10 cm, ändern wir bei die Variable crash in true. Es ist schon erstaunlich, den Roboter dabei zu beobachten, wie er auf wundersame Weise Kollisionen vermeidet oder ein Haustier auszutricksen versucht, um an ihm vorbeizukommen.

Ausblick

In diesem Kapitel haben Sie gelernt, wie Sie Ihre Arduino-Projekte in Bewegung setzen können. Mit einfachen oder paarweise eingesetzten Motoren und dem Motor-Shield können Sie Geräte bauen, die sich eigenständig bewegen und sogar in der Lage sind, Hindernissen auszuweichen. Wir haben drei Arten von Sensoren vorgestellt, um die ganze Skala der Genauigkeiten und Preise abzudecken, sodass Sie jeweils die passende Auswahl für Ihren Bedarf und Ihr Projektbudget treffen können.

Ich hoffe, dass Sie bis jetzt schon viel Spaß dabei gehabt haben, die hier vorgestellten Geräte zu entwerfen und zu bauen. Aber das war noch längst nicht alles. Im nächsten Kapitel gehen wir vor die Haustür, um die Möglichkeiten der Satellitennavigation zu nutzen.

13

GPS für den Arduino

In diesem Kapitel lernen Sie Folgendes:

• Anschluss eines GPS-Shields

• Konstruktion einer einfachen Anzeige für GPS-Koordinaten

• Anzeige der GPS-Koordinaten auf einer Landkarte

• Konstruktion einer genauen Uhr

• Aufzeichnen der Position von bewegten Objekten im Zeitverlauf

In diesem Kapitel erfahren Sie, wie Sie einen preisgünstigen GPS-Shield zur Standortbestimmung einsetzen, wie Sie eine genaue Uhr konstruieren und wie Sie ein Gerät bauen, das Positionsdaten protokolliert und auf einer microSD-Karte speichert, um sie später auf einer Landkarte anzuzeigen und so den Bewegungsverlauf darzustellen.

Was ist GPS?

GPS (Global Positioning System) ist ein satellitengestütztes Navigationssystem, bei dem von Satelliten in der Erdumlaufbahn Daten an GPS-Empfänger am Boden gesendet werden, um die Position und die Uhrzeit zu bestimmen. Wahrscheinlich sind Ihnen die GPS-Navigationsgeräte im Auto oder in Ihrem Mobiltelefon vertraut.

Mit dem Arduino können wir zwar kein umfassendes Navigationssystem konstruieren, aber Standort und Uhrzeit sowie die ungefähre Bewegungsgeschwindigkeit ermitteln. Dazu verwenden wir das GPS-Empfängermodul EM406, das Sie in Abbildung 13–1 sehen.

Abb. 13–1 Der GPS-Empfänger EM406

Um diesen Empfänger nutzen zu können, brauchen Sie den GPS-Satz von SparkFun (Bestell-Nr. RTL-10709) aus Abbildung 13–2. Der Satz enthält einen Empfänger, einen zugehörigen Arduino-Shield und ein Verbindungskabel.

Abb. 13–2 Komplettsatz für einen GPS-Shield

Um die Platzierung des Empfängers zu erleichtern, sollten Sie auch das 30-cm-Kabel aus Abbildung 13–3 kaufen (bei SparkFun unter der Bestell-Nr. GPS-09123 erhältlich).

Abb. 13–3 Ein längeres Kabel für die Verbindung zwischen GPS-Shield und -Empfänger

Den GPS-Shield testen

Es ist eine gute Idee, einen neu gekauften GPS-Satz zunächst zu prüfen, um sicherzugehen, dass er funktioniert und GPS-Signale empfangen kann. GPS-Empfänger benötigen eine ungehinderte Sicht zum Himmel, wobei Fenster jedoch kein Hindernis darstellen. Am besten ist es, den Test draußen durchzuführen, es kann jedoch auch vor einem unverstellten Fenster oder unter einem Oberlicht funktionieren. Um den Empfang zu prüfen, richten Sie den Shield ein und führen einen einfachen Sketch aus, der die empfangenen Rohdaten ausgibt.

Verbinden Sie dazu als Erstes den GPS-Empfänger über das Kabel mit dem Shield und stecken Sie diese Baugruppe dann auf den Arduino auf. Beachten Sie den kleinen Schalter auf dem GPS-Shield, der in Abbildung 13–4 zu sehen ist.

Abb. 13–4 Der Datenschalter auf dem GPS-Shield

Wenn Sie Sketche auf den GPS-Shield hochladen wollen, müssen Sie den Schalter in die Stellung DLINE bringen. Setzen Sie ihn anschließend auf UART zurück und aktivieren Sie den Stromschalter des Empfängers.

Geben Sie den Sketch aus Listing 13–1 ein und laden Sie ihn hoch.

void setup()
{
Serial.begin(4800);
}

void loop()
{
byte a;
if ( Serial.available() > 0 )
{
a = Serial.read(); // Ruft die Datenbytes vom GPS-Empfänger ab
Serial.write(a);
}
}

Listing 13–1 Grundlegender Testsketch

Der Sketch lauscht bei am seriellen Port. Wenn dort ein Byte Daten vom GPS-Modul eintrifft, wird es bei zum seriellen Monitor gesendet. (Beachten Sie, dass wir die serielle Verbindung bei mit einer Übertragungsrate von 4800 Baud starten, um sie an die Übertragungsgeschwindigkeit des GPS-Empfängers anzupassen.)

Nachdem Sie den Sketch hochgeladen haben, drücken Sie den Datenschalter wieder in die Stellung UART. Beobachten Sie jetzt die LED auf dem GPS-Empfänger, die den Status anzeigt. Wenn sie leuchtet, versucht der Empfänger ein Satellitensignal aufzunehmen. Nach etwa 30 s sollte die LED zu blinken beginnen, was bedeutet, dass Daten vom Satelliten eingehen. Öffnen Sie jetzt in der IDE den seriellen Monitor und setzen Sie die Übertragungsrate auf 4800 Baud. In dem Fenster wird nun ein konstanter Datenstrom wie in Abbildung 13–5 angezeigt.

Die Daten gehen zeichenweise vom GPS-Empfänger an den Arduino und von dort zum seriellen Monitor. In diesem Zustand sind sie jedoch nicht sehr aussagekräftig. Um aus diesen Rohdaten Informationen zu gewinnen und in eine nutzbare Form umzuwandeln, müssen wir die Bibliothek TinyGPS verwenden. Laden Sie sie von http://www.arduiniana.org/libraries/tinygps/ herunter und installieren Sie sie. Verwenden Sie dazu die Methoden aus dem Abschnitt »Sketche durch Bibliotheken erweitern« aus Kapitel 8.

Abb. 13–5 Rohdaten von GPS-Satelliten

Projekt Nr. 44: Ein einfaches GPS-Empfangsgerät konstruieren

Als Nächstes wollen wir ein einfaches GPS-Empfangsgerät bauen. Da wir es gewöhnlich draußen einsetzen – und um uns die Arbeit zu erleichtern –, statten wir es zur Anzeige der Daten mit einem LCD-Bildschirm wie dem in Abbildung 13–6 aus.

Abb. 13–6 Der LCD- und Tastenfeld-Shield von Freetronics

HINWEIS

Die Beispiele sind für den LCD- und Tastenfeld-Shield von Freetronics geschrieben (siehe http://www.freetronics.com/collections/display/products/lcd-keypad-shield/). Wenn Sie ein anderes Anzeigemodul verwenden, müssen Sie in Ihren Sketchen in der Funktion LiquidCrystal die Werte entsprechend anpassen.

Im Folgenden bauen wir ein ganz einfaches, von einer 9-Volt-Batterie gespeistes GPS-Empfangsgerät, um die über GPS empfangenen Koordinaten des aktuellen Standorts auf dem LCD-Bildschirm anzuzeigen.

Die Hardware

Es sind nur wenige Teile erforderlich:

• ein LCD-Modul oder LCD-Shield von Freetronics (wie weiter vorne erwähnt)

• eine 9-Volt-Batterie mit Kabel für den Anschluss an den Gleichstromeingang des Arduino

• ein GPS-Satz von SparkFun

• Arduino und USB-Kabel

Der Sketch

Geben Sie den folgenden Sketch ein und laden Sie ihn hoch:

// Projekt 44: Ein einfaches GPS-Empfangsgerät konstruieren
#include <TinyGPS.h>
#include <LiquidCrystal.h>
LiquidCrystal lcd( 8, 9, 4, 5, 6, 7 );

// Erstellt eine Instanz des TinyGPS-Objekts
TinyGPS gps;
void getgps(TinyGPS &gps);

void setup()
{
Serial.begin(4800);
lcd.begin(16, 2);
}
void getgps(TinyGPS &gps)
// Die Funktion getgps zeigt die Daten auf dem LCD-Modul an
{
float latitude, longitude;
// Interpretiert die Positionsdaten und zeigt sie an
gps.f _ get _ position(&latitude, &longitude);
lcd.setCursor(0,0);
lcd.print("Lat:");
lcd.print(latitude,5);
lcd.print(" ");
lcd.setCursor(0,1);

lcd.print("Long:");
lcd.print(longitude,5);
lcd.print(" ");
delay(3000); // Wartet drei Sekunden lang
lcd.clear();
}

void loop()
{
byte a;
if ( Serial.available() > 0 )   // Wenn Daten über die serielle
// Verbindung eingehen
{
a = Serial.read();           // Ruft ein Datenbyte ab
if(gps.encode(a))            // Wenn es sich um gültige GPS-Daten
// handelt ...
{
getgps(gps);              // Ruft die Daten ab und zeigt sie
// auf dem LCD-Modul an
}
}
}

Zwischen und schließt der Sketch die erforderlichen Bibliotheken für den LCD-Bildschirm und den GPS-Empfänger ein. In void loop bei senden wir die vom GPS-Empfänger eingegangenen Zeichen an die Funktion getgps(), die bei gps.f _ get _ position() nutzt, um die Positionswerte in den Bytevariablen &latitude und &longitude zu speichern (die wir dann auf dem LCD-Monitor ausgeben).

Die Position auf dem LCD-Bildschirm anzeigen

Wenn Sie den Sketch hochgeladen haben und beim GPS-Empfänger Daten eingehen, wird die aktuelle Position in Dezimalzahlen für die geografische Breite und Länge auf dem LCD-Monitor angezeigt, wie Sie in Abbildung 13–7 sehen.

Abb. 13–7 Anzeige der Breite und Länge in Projekt 44

Aber wo ist das auf der großen weiten Welt? Den Standort können wir mit Google Maps (http://maps.google.com/) genau bestimmen. Geben Sie auf der Website die Breite und Länge in das Suchfeld ein (getrennt durch ein Komma und ein Leerzeichen). Daraufhin zeigt Google Maps die Position auf einer Karte an. Mit den Koordinaten aus Abbildung 13–7 erhalten Sie die Kartendarstellung aus Abbildung 13–8.

Abb. 13–8 Die Position aus Abbildung 13–7 auf einer Landkarte

Projekt Nr. 45: Eine genaue GPS-gestützte Uhr konstruieren

GPS hilft uns nicht nur, unseren Standort zu bestimmen, sondern überträgt auch Zeitdaten, die wir dazu heranziehen können, eine sehr genaue Uhr zu bauen.

Die Hardware

Für dieses Projekt verwenden wir dieselben Teile wie für Projekt 44.

Der Sketch

Für die GPS-Uhr geben Sie folgenden Sketch ein:

// Projekt 45: Eine genaue GPS-gestützte Uhr konstruieren
#include <TinyGPS.h>

#include <LiquidCrystal.h>
LiquidCrystal lcd( 8, 9, 4, 5, 6, 7 );

// Erstellt eine Instanz des TinyGPS-Objekts
TinyGPS gps;

void getgps(TinyGPS &gps);

void setup()
{
Serial.begin(4800);
lcd.begin(16, 2);
}

void getgps(TinyGPS &gps)
{
int year,a,t;
byte month, day, hour, minute, second, hundredths;
gps.crack _ datetime(&year,&month,&day,&hour,&minute,&second,
&hundredths);
hour=hour+10;             // Passen Sie dies an Ihre Zeitzone an
if (hour>23)
{
hour=hour-24;
}
lcd.setCursor(0,0);       // Gibt Datum und Uhrzeit aus
lcd.print("Current time: ");
lcd.setCursor(4,1);
if (hour<10)
{
lcd.print("0");
}
lcd.print(hour, DEC);
lcd.print(":");
if (minute<10)
{
lcd.print("0");
}
lcd.print(minute, DEC);
lcd.print(":");
if (second<10)
{
lcd.print("0");
}
lcd.print(second, DEC);
}

void loop()
{
byte a;
if ( Serial.available() > 0 )      // Wenn Daten über die serielle
// Verbindung eingehen
{
a = Serial.read();              // Ruft ein Datenbyte ab
if(gps.encode(a))               // Wenn es sich um gültige
// GPS-Daten handelt
{
getgps(gps);                 // Ruft die Daten ab und zeigt
// sie auf dem LCD-Modul an
}
}
}

Dieses Beispiel funktioniert ähnlich wie Projekt 44, allerdings ruft der Sketch hier nicht die Positionsdaten ab, sondern (bei ) die Zeitangabe (in westeuropäischer Zeit, die auch als GMT für »Greenwich Mean Time« und als UTC für »Coordinated Universal Time« bezeichnet wird). Bei müssen Sie die Zeitdifferenz Ihrer Zeitzone addieren oder subtrahieren, um die Uhr richtig einzustellen. Anschließend wird die Zeitangabe bei sauber formatiert und wie in Abbildung 13–9 auf dem LCD-Bildschirm ausgegeben.

Abb. 13–9 Projekt 45 im laufenden Betrieb

Projekt Nr. 46: Den Bewegungsverlauf eines Objekts aufzeichnen

Da Sie GPS-Koordinaten empfangen und in normalen Variablen speichern können, sind Sie auch in der Lage, diese auf einer microSD-Karte abzulegen, wie Sie in Kapitel 8 gelernt haben. Damit können Sie ein GPS-Protokolliergerät bauen, das die GPS-Daten und damit die Position im Verlauf der Zeit aufzeichnet. Mit einem solchen Gerät lässt sich die Bewegung eines Autos, Lastwagens, Bootes oder eines beliebigen anderen bewegten Objekts festhalten, auf dem Sie GPS-Daten empfangen können. Die Informationen können Sie dann später am Computer auswerten.

Die Hardware

Für dieses Projekt ist die gleiche Hardware erforderlich wie für die vorhergehenden, wobei Sie allerdings den LCD- durch den microSD-Shield aus Kapitel 8 ersetzen und eine externe Stromquelle verwenden müssen. In unserem Beispiel zeichnen wir Zeit, Ort und eine geschätzte Geschwindigkeit auf.

Der Sketch

Nachdem Sie die Hardware zusammengebaut haben, geben Sie den folgenden Sketch ein und laden ihn hoch:

// Projekt 46: Den Bewegungsverlauf eines Objekts aufzeichnen
#include <SD.h>
#include <TinyGPS.h>

// Erstellt eine Instanz des TinyGPS-Objekts
TinyGPS gps;

void getgps(TinyGPS &gps);

void setup()
{
pinMode(10, OUTPUT);
Serial.begin(9600);
// Prüft, ob die microSD-Karte eingelegt und verwendbar ist
if (!SD.begin(8)) {
Serial.println("Card failed, or not present");
// Hält die Ausführung des Sketches an
return;
}
Serial.println("microSD card is ready");
}

void getgps(TinyGPS &gps)
{
float latitude, longitude;
int year;
byte month, day, hour, minute, second, hundredths;

// Interpretiert die Positionsdaten und zeigt sie an
gps.f _ get _ position(&latitude, &longitude);
File dataFile = SD.open("DATA.TXT", FILE _ WRITE);

// Beginnt zu schreiben, wenn die Datei bereit ist
if (dataFile)
{
dataFile.print("Lat: ");
dataFile.print(latitude,5);
dataFile.print(" ");
dataFile.print("Long: ");
dataFile.print(longitude,5);
dataFile.print(" ");
// Interpretiert die Zeitdaten und zeigt sie an
gps.crack _ datetime(&year,&month,&day,&hour,
&minute,&second,&hundredths);
// Passen Sie dies wie in Projekt 45 an Ihre Zeitzone an
hour=hour+11;
if (hour>23)
{
hour=hour-24;
}
if (hour<10)
{
dataFile.print("0");
}
dataFile.print(hour, DEC);
dataFile.print(":");
if (minute<10)
{
dataFile.print("0");
}
dataFile.print(minute, DEC);
dataFile.print(":");
if (second<10)
{
dataFile.print("0");
}
dataFile.print(second, DEC);
dataFile.print(" ");
dataFile.print(gps.f _ speed _ kmph());
dataFile.println("km/h");
dataFile.close();
delay(30000); // Zeichnet alle 30 s eine Messung auf
}
}

void loop()
{
byte a;
if ( Serial.available() > 0 )   // Wenn Daten über die serielle
// Verbindung eingehen
{
a = Serial.read();           // Ruft ein Datenbyte ab
if(gps.encode(a))            // Wenn es sich um gültige GPS-Daten handelt
{
getgps(gps);              // Ruft die Daten ab und zeigt sie
// auf dem LCD-Modul an
}
}
}

In void loop() verwendet dieser Sketch den gleichen Code wie in den Projekten 44 und 45, um die Daten vom GPS-Empfänger abzurufen und an die anderen Funktionen zu übergeben. Bei werden sie an die Bibliothek TinyGPS weitergereicht, um sie zu dekodieren und in brauchbarer Form in Variablen zu speichern. Die microSD-Karte wird bei überprüft, um sicherzustellen, dass Daten darauf abgelegt werden können, und anschließend werden zwischen und die GPS-Daten als Textdatei auf die Karte geschrieben. Bevor Sie die microSD-Karte einlegen oder entnehmen, müssen Sie die Stromversorgung vom Arduino trennen. Da die Datei nach jedem Schreibvorgang geschlossen wird, können Sie dies tun, ohne im Sketch vorwarnen zu müssen. Den Abstand zwischen den einzelnen Aufzeichnungsvorgängen legen Sie in fest, indem Sie den Wert der Funktion delay() ändern.

Standorte auf der Landkarte anzeigen

Wenn Sie das GPS-Protokolliergerät in Betrieb nehmen, erhalten Sie eine Textdatei wie in Abbildung 13–10.

Abb. 13–10 Das Ergebnis von Projekt 46

Die Daten aus dieser Datei können Sie nun manuell in Google Maps eingeben, um sich Schritt für Schritt den Weg anzusehen, den das Protokolliergerät genommen hat. Eine interessantere Methode dagegen besteht darin, die gesamte Route auf einer Landkarte anzuzeigen. Öffnen Sie die Textdatei dazu in einem Tabellenkalkulationsprogramm, gliedern Sie die Positionsdaten und fügen Sie Kopfzeilen hinzu (siehe Abb. 13–11). Speichern Sie die Datei dann im CSV-Format.

Abb. 13–11 Die erfassten Positionsdaten

Suchen Sie jetzt die Website GPS Visualizer auf (http://www.gpsvisualizer.com/). Klicken Sie im Bereich Get Started Now auf Durchsuchen und geben Sie Ihre Datendatei an. Wählen Sie als Ausgabeformat Google Maps und klicken Sie dann auf Go!. Die Route, die das GPS-Protokolliergerät genommen hat, wird nun wie in Abbildung 13–12 auf einer Karte angezeigt. Sie können die Darstellung noch anpassen und ein wenig damit herumspielen.

Abb. 13–12 Anzeige der GPS-Daten auf einer Landkarte

Ausblick

Wie Sie sehen, kann auch etwas, was Sie vielleicht für viel zu kompliziert gehalten haben – wie hier die Arbeit mit GPS-Empfängern –, mit dem Arduino ganz einfach sein. Im nächsten Kapitel wollen wir dies erneut unter Beweis stellen, indem wir unsere eigenen drahtlosen Datenverbindungen aufbauen und Geräte ferngesteuert bedienen.

14

Drahtlose Datenübertragung

In diesem Kapitel lernen Sie, wie Sie Anweisungen und Daten mit verschiedenen Arten von Hardware zur drahtlosen Übertragung senden und empfangen. Insbesondere geht es um folgende Themen:

• Senden von digitalen Ausgangssignalen über preiswerte Module für die drahtlose Datenübertragung

• Bau von einfachen und preiswerten drahtlosen Fernsteuerungen

• Verwendung von XBee-Sende- und -Empfangsgeräten für die drahtlose Datenübertragung

• Bau eines ferngesteuerten Thermometers

Preiswerte Module für die drahtlose Datenübertragung

Es ist ganz einfach, Informationen in Textform in einer Richtung über eine drahtlose Verbindung zwischen zwei Arduino-Systemen zu übertragen, die beide über ein preiswertes Funkmodul verfügen (Radio Frequency, RF) – ein Sendemodul wie in Abbildung 14–1 auf der einen Seite und ein Empfangsmodul wie in Abbildung 14–2 auf der anderen. Solche Geräte werden paarweise als RF-Link-Module verkauft. Gute Beispiele finden Sie unter der Bestellnummer WLS107B4B bei Seeed Studio und unter WRL-10534 bei SparkFun. In unseren Projekten verwenden wir die am häufigsten eingesetzten Typen, die eine Funkfrequenz von 433 MHz nutzen.

Bei den Kontakten unten an dem Modul in Abbildung 14–1 handelt es sich von links nach rechts um den 5-Volt-Anschluss, den Masseanschluss (GND), den Dateneingang und den Anschluss für eine externe Antenne. Als Antenne können Sie einfach ein Stück Draht nehmen, auf Kurzstrecken können Sie auch ganz darauf verzichten. Da die Module je nach Hersteller anders aufgebaut sein können, müssen Sie genau prüfen, wie die Anschlüsse bei Ihrem Modell belegt sind.

In Abbildung 14–2 sehen Sie das Empfangsmodul, das etwas größer ist als das Sendemodul.

Abb. 14–1 RF-Link-Sendemodul

Abb. 14–2 RF-Link-Empfangsmodul

Die Kontakte am Empfänger sind ganz unkompliziert: Die Pins V+ und V– werden mit dem 5-Volt-Anschluss bzw. GND verbunden und DATA mit dem Arduino-Pin, der für den Datenempfang vorgesehen ist.

Bevor Sie die Module nutzen können, müssen Sie die neueste Version der Bibliothek VirtualWire von http://www.open.com.au/mikem/arduino/ herunterladen und installieren. Danach können Sie mit dem nächsten Abschnitt fortfahren.

HINWEIS

Die RF-Link-Module sind zwar preisgünstig und leicht zu verwenden, bringen aber keine Fehlerprüfung mit, um sicherzustellen, dass die Daten auch korrekt empfangen werden. Daher sollten Sie sie nur für einfache Aufgaben wie die im Folgenden vorgestellte elementare Fernsteuerung verwenden. Wenn Sie eine genauere und zuverlässigere Datenübertragung benötigen, müssen Sie stattdessen Geräte wie die XBee-Module verwenden, die wir uns später in diesem Kapitel ansehen.

Projekt Nr. 47: Eine drahtlose Fernbedienung konstruieren

In diesem Projekt werden wir zwei digitale Ausgänge fernsteuern. Dabei betätigen Sie Drucktasten, die mit einem Arduino verbunden sind, um dadurch digitale Ausgänge an einem anderen, entfernt davon aufgestellten Arduino zu steuern. Daran können Sie erkennen, wie Sie die RF-Link-Module handhaben müssen, und ein Gefühl dafür entwickeln, über welche Entfernungen hinweg eine solche Fernsteuerung wirkt, bevor Sie sich an kompliziertere Aufgaben wagen. (Im Freien beträgt die Reichweite im Allgemeinen um 100 m, in Innenräumen und bei Hindernissen ist sie geringer.)

Die Hardware für die Senderschaltung

Für die Senderschaltung sind folgende Teile erforderlich:

• eine 9-Volt-Batterie mit Kabel für den Anschluss an den Gleichstromeingang des Arduino (wie in Kapitel 12)

• ein 433-MHz-RF-Link-Sendemodul (z. B. Bestell-Nr. WRL-10534 von SparkFun)

• zwei 10-kΩ-Widerstände (R1 und R2)

• zwei 100-nF-Kondensatoren (C1 und C2)

• zwei Drucktasten

• eine Steckplatine

• Verbindungsdrähte

• Arduino und USB-Kabel

Der Schaltplan für den Sender

Wie Sie in Abbildung 14–3 sehen, besteht die Senderschaltung aus zwei Drucktasten mit Entprellerstromkreis, die an die Digitalpins 2 und 3 angeschlossen sind, sowie dem Sendemodul, das wie zuvor beschrieben verdrahtet ist.

Abb. 14–3 Senderschaltplan für Projekt 47

Die Hardware für die Empfängerschaltung

Für die Empfängerschaltung sind folgende Teile erforderlich:

• eine 9-Volt-Batterie mit Kabel für den Anschluss an den Gleichstromeingang des Arduino (wie in Kapitel 12)

• ein 433-MHz-RF-Link-Empfangsmodul (z. B. Bestell-Nr. WRL-10532 von SparkFun)

• zwei LEDs Ihrer Wahl

• zwei 560-Ω-Widerstände (R1 und R2)

• eine Steckplatine

• Verbindungsdrähte

• Arduino und USB-Kabel

Der Schaltplan für den Empfänger

Wie Sie in Abbildung 14–4 sehen, besteht die Empfängerschaltung aus zwei LEDs an den Digitalpins 6 und 7 sowie dem Empfangsmodul, das an Digitalpin 8 angeschlossen ist.

Abb. 14–4 Empfängerschaltplan für Projekt 47

Anstelle der Steckplatine mit LEDs, Widerständen und Empfangsmodul können Sie auch den 433-MHz-Empfänger-Shield von Freetronics verwenden, den Sie in Abbildung 14–5 sehen.

Abb. 14–5 Der 433-MHz-Empfänger-Shield von Freetronics

Der Sketch für den Sender

Als Nächstes sehen wir uns den Sketch für den Sender an. Geben Sie den folgenden Code ein und laden Sie ihn auf den Arduino in der Senderschaltung hoch:

// Projekt 47: Eine drahtlose Fernbedienung konstruieren, Sendersketch

#include <VirtualWire.h>
uint8 _ t buf[VW _ MAX _ MESSAGE _ LEN];
uint8 _ t buflen = VW _ MAX _ MESSAGE _ LEN;

const char *on2 = "a";
const char *off2 = "b";
const char *on3 = "c";
const char *off3 = "d";

void setup()
{
vw _ set _ ptt _ inverted(true); // Erforderlich für RF-Link-Module
vw _ setup(300);            // Legt die Übertragungsgeschwindigkeit fest
vw _ set _ tx _ pin(8);
pinMode(2, INPUT);
pinMode(3, INPUT);
}

void loop()
{
if (digitalRead(2)==HIGH)
{
vw _ send((uint8 _ t *)on2, strlen(on2)); // Sendet die Daten
// nach draußen
vw _ wait _ tx();                         // Wartet einen Augenblick
// lang
delay(200);
}
if (digitalRead(2)==LOW)
{
vw _ send((uint8 _ t *)off2, strlen(off2));
vw _ wait_tx();
delay(200);
}
if (digitalRead(3)==HIGH)
{
vw _ send((uint8 _ t *)on3, strlen(on3));
vw _ wait_tx();
delay(200);
}

if (digitalRead(3)==LOW)
{
vw _ send((uint8 _ t *)off3, strlen(off3));
vw _ wait_tx();
delay(200);
}
}

Um die RF-Link-Module nutzen zu können, verwenden wir im Sketch bei und die VirtualWire-Funktionen. Bei richten wir Digitalpin 8 ein, der dazu dient, den Arduino mit dem Datenpin des Sendemoduls zu verbinden und die Übertragungsgeschwindigkeit zu regeln. (Bei Bedarf können Sie auch einen der anderen Digitalpins dazu verwenden, allerdings nicht 0 und 1, da es sonst zu Störungen der seriellen Verbindung kommt.)

Der Sendersketch liest den Status der beiden Tasten, die an die Digitalpins 2 und 3 angeschlossen sind, und sendet ein einzelnes Textzeichen zur Angabe dieses Zustands an das RF-Link-Modul. Hat die Taste an Pin 2 den Status HIGH, sendet der Arduino das Zeichen a, bei LOW dagegen b. Die vier möglichen Zustände werden ab deklariert.

Die Übertragung des Textzeichens erfolgt über eine der vier if-Anweisungen, die in dem Bereich ab stehen, z. B. in . Die übertragene Variable wird zweimal verwendet, wie Sie im folgenden Beispiel anhand von on2 sehen:

vw _ send((uint8 _ t *)on2, strlen(on2));

Die Funktion vw _ send sendet den Inhalt der Variable on2, muss dazu aber deren Länge, also die Anzahl der Zeichen kennen. Dazu verwenden wir strlen().

Der Sketch für den Empfänger

Jetzt fügen wir den Empfängersketch hinzu. Geben Sie folgenden Code ein und laden Sie ihn auf den Arduino in der Empfängerschaltung hoch:

// Projekt 47: Eine drahtlose Fernbedienung konstruieren, Empfängersketch
#include <VirtualWire.h>

uint8 _ t buf[VW _ MAX _ MESSAGE _ LEN];
uint8 _ t buflen = VW _ MAX _ MESSAGE _ LEN;

void setup()
{
vw _ set _ ptt _ inverted(true); // Erforderlich für RF-Link-Module
vw _ setup(300);
vw _ set _ rx _ pin(8);
vw _ rx _ start();
pinMode(6, OUTPUT);
pinMode(7, OUTPUT);
}

void loop()
{
if (vw _ get _ message(buf, &buflen))
{
switch(buf[0])
{
case 'a':
digitalWrite(6, HIGH);
break;
case 'b':
digitalWrite(6, LOW);
break;
case 'c':
digitalWrite(7, HIGH);
break;
case 'd':
digitalWrite(7, LOW);
break;
}
}
}

Wie beim Senderschaltkreis verwenden wir auch hier bei die VirtualWire-Funktionen, um das RF-Link-Empfangsmodul einzurichten, die Übertragungsgeschwindigkeit einzustellen und den Digitalpin am Arduino festzulegen (bei ), mit dem der Ausgangspin des Moduls verbunden ist.

Wenn der Sketch läuft, werden die von der Senderschaltung übertragenen Zeichen vom RF-Link-Modul empfangen und an den Arduino weitergereicht. Die Funktion vw _ get _ message() bei übernimmt die empfangenen Zeichen, die dann bei von der switch-case-Funktion interpretiert werden. Wenn Sie beispielsweise in der Senderschaltung Taste S1 drücken, wird das Zeichen a gesendet. Es geht beim Empfänger ein, der daraufhin den Digitalpin 6 auf HIGH setzt und damit die LED einschaltet.

Mit diesem einfachen Paar von Beispielschaltkreisen können Sie auch kompliziertere Systeme zur Fernsteuerung eines Arduino bauen. Das grundlegende Prinzip besteht darin, Codes in Form einfacher Zeichen zu senden, die dann von der Empfängerschaltung interpretiert werden.

XBee-Module für eine drahtlose Übertragung mit größerer Reichweite und höherer Geschwindigkeit

Wenn Sie eine drahtlose Datenverbindung mit größerer Reichweite und höherer Geschwindigkeit brauchen, als die einfachen Geräte aus dem vorherigen Projekt leisten können, sind XBee-Module die richtige Wahl. Sie können serielle Daten direkt zu einem oder mehreren anderen XBee-Modulen senden und von ihnen empfangen oder auch in beiden Richtungen mit Computern austauschen. Es gibt verschiedene XBee-Modelle, von denen wir hier die kombinierten Sende- und Empfangsgeräte (Transceiver) der Serie 1 verwenden (siehe Abb. 14–6).

Abb. 14–6 Ein typischer XBee-Transceiver

Der Anschluss eines solchen Transceivers an einen Arduino ist mit dem XBee-Shield aus Abbildung 14–7 ganz einfach.

Abb. 14–7 XBee-Anschluss an den Arduino über einen XBee-Shield

Zur Kommunikation mit Computern können Sie die Platine XBee Explorer aus Abbildung 14–8 verwenden (SparkFun, Bestell-Nr. WRL-08687).

Abb. 14–8 XBee-Anschluss über USB und Explorer-Platine

Für XBee-Module ist keine eigene Bibliothek erforderlich, da sie als einfache serielle Datenbrücke fungieren, die Daten über die serielle Verbindung des Arduino überträgt.

Projekt Nr. 48: Datenübertragung mit einem XBee-Modul

Dieses Projekt führt die einfache Datenübertragung von einem Arduino mit XBee-Modul zu einem Computer mit einem weiteren XBee-Modul und einer Explorer-Platine vor. Am Arduino sind zwei ganz einfache Montageschritte erforderlich: Erst müssen Sie ein XBee-Modul am XBee-Shield anbringen und dann den Shield am Arduino.

Beachten Sie den winzigen Schalter auf dem Shield, der in Abbildung 14–9 vergrößert dargestellt ist.

Abb. 14–9 Der Datenschalter am XBee-Shield

Dieser Schalter ist identisch mit dem auf dem GPS-Shield aus Kapitel 14 und legt fest, ob Daten vom USB-Anschluss des Arduino oder vom XBee-Modul an den Mikrocontroller gesendet werden. Zum Hochladen des Sketches müssen Sie den Schalter in die Stellung DLINE bringen, zum Ausführen in die Stellung UART.

Der Sketch

Erstellen Sie folgenden Sketch und laden Sie ihn hoch:

// Projekt 48: Datenübertragung mit einem XBee-Modul

void setup()
{
Serial.begin(9600);
}

void loop()
{
Serial.println("Hello, world");
delay(1000);
}

Dieser Code sendet zwar einfach den Text Hello, world über die serielle Verbindung, veranschaulicht aber sehr gut, wie einfach sich XBee-Module zur Datenübertragung nutzen lassen, denn Sie müssen lediglich in die serielle Verbindung schreiben, den Rest erledigt das Modul. Ziehen Sie das USB-Kabel vom Arduino ab und schalten Sie die Platine über eine externe Stromversorgung wie die 9-Volt-Batterie und das Kabel aus Kapitel 12 an. Vergessen Sie nicht, den Schalter wieder auf UART zurückzustellen.

Den Computer für den Datenempfang einrichten

Als Nächstes richten wir den Computer für den Datenempfang ein. Schließen Sie dazu über eine Explorer-Platine (siehe Abb. 14–8) ein weiteres XBee-Modul an den Rechner an. Laden Sie dann das Programm Terminal herunter und installieren Sie es. Die Windows-Version erhalten Sie auf https://sites.google.com/site/terminalbpp/. Wenn Sie Terminal öffnen, wird der Bildschirm aus Abbildung 14–10 angezeigt.

Setzen Sie oben auf dem Bildschirm Baud Rate auf 9600, Data Bits auf 8, Parity auf none, Stop Bits auf 1 und Handshaking auf none. Klicken Sie dann oben links auf die Schaltfläche ReScan, um die Software zu veranlassen, den richtigen USB-Port auszuwählen. Abschließend klicken Sie auf Connect. Nach einem kurzen Augenblick werden im Terminal-Fenster die vom Arduino übertragenen Daten angezeigt, wie Sie in Abbildung 14–11 sehen.

Abb. 14–10 Das Terminal-Emulationsprogramm

Abb. 14–11 Datenempfang vom anderen XBee-Modul

Sie können auf einen Computer auch mehrere XBee-Sender ausrichten, die jeweils ihre eigenen Daten übertragen. Damit können Sie beispielsweise ganz bequem vom Schreibtisch aus mehrere Sensoren, z. B. Temperaturfühler, ablesen, die in der näheren Umgebung verteilt sind. Mit einer ähnlichen Technik können Sie auch mehrere Arduinos mit XBee-Modulen steuern. Diese Möglichkeiten sehen wir uns im nächsten Projekt an.

Projekt Nr. 49: Ein ferngesteuertes Thermometer bauen

In diesem Projekt bauen Sie ein ferngesteuertes Thermometer, das die Temperatur auf Anfrage an einen Computer zurückgibt. Dabei lernen Sie die Grundlagen des Fernabrufs von Sensordaten kennen und erstellen ein Fundament für Projekte zur kabellosen Sensormessung.

Die Hardware

Sie benötigen folgende Teile:

• einen Temperatursensor TMP36

• zwei XBee-Module (Serie 1)

• ein XBee-Shield

• eine XBee-Explorer-Platine mit USB-Kabel

• eine 9-Volt-Batterie mit Kabel für den Anschluss an den Gleichstromeingang des Arduino

• eine Steckplatine

• Verbindungsdrähte

• Arduino und USB-Kabel

Der Aufbau

Setzen Sie ein XBee-Modul in den Shield ein und stecken Sie den Shield auf den Arduino. Bringen Sie den TMP36 auf einer kleinen Steckplatine an und verbinden Sie ihn wie in Projekt 8 mit dem 5-Volt-, dem GND- und dem A0-Anschluss des Shields (siehe Abb. 14–12).

Abb. 14–12 Einrichtung des Arduino für die ferngesteuerte Temperaturmessung

Die USB-Explorer-Platine mit dem anderen XBee-Modul schließen Sie an den PC an, nachdem Sie den folgenden Sketch auf den Arduino hochgeladen haben.

Der Sketch

Geben Sie den folgenden Sketch ein und laden Sie ihn hoch:

// Projekt 49: Ein ferngesteuertes Thermometer bauen

char a;
float voltage=0;
float sensor=0;
float celsius=0;
float fahrenheit=0;
float photocell=0;

void setup()
{
Serial.begin(9600);
}

void sendC()
{
sensor=analogRead(0);
voltage=((sensor*5000)/1024);
voltage=voltage-500;
celsius=voltage/10;
fahrenheit=((celsius*1.8)+32);
Serial.print("Temperature: ");
Serial.print(celsius,2);
Serial.println(" degrees C");
}

void sendF()
{
sensor=analogRead(0);
voltage=((sensor*5000)/1024);
voltage=voltage-500;
celsius=voltage/10;
fahrenheit=((celsius*1.8)+32);
Serial.print("Temperature: ");
Serial.print(fahrenheit,2);
Serial.println(" degrees F");
}

void getCommand()
{
Serial.flush();
while (Serial.available() == 0)
{
// Tut nichts, bis Daten vom XBee-Modul eingehen
}
while (Serial.available() > 0)
{
a = Serial.read();  // Liest die Zahl im seriellen Puffer
}
}

void loop()
{
getCommand();   // Lauscht auf Befehle vom PC
switch (a)
{
case 'c':
// Sendet die Temperatur in Celsius
sendC();
break;
case 'f':
// Sendet die Temperatur in Fahrenheit
sendF();
break;
}
}

Zu Anfang lauscht der Sketch bei mit der Funktion getCommand() an der seriellen Verbindung. Der Code durchläuft eine Schleife, bis er ein Zeichen empfängt, das er dann in der Variable a speichert. Anschließend wird das Zeichen bei durch die switch-case-Funktion interpretiert. Geht der Buchstabe c ein, berechnet die Funktion sendC() bei die Temperatur in Celsius, schreibt sie in die serielle Verbindung und sendet sie über die XBee-Module an den PC. Wird dagegen der Buchstabe f empfangen, berechnet sendF() bei die Temperatur in Fahrenheit und sendet sie an den Computer.

Betrieb

Führen Sie das Programm Terminal wie in dem vorherigen Projekt dieses Kapitels aus und senden Sie c oder f. Nach ungefähr einer Sekunde wird die Temperatur zurückgegeben. Das Ergebnis sehen Sie in Abbildung 14–13.

Abb. 14–13 Das Ergebnis von Projekt 49

Ausblick

In diesem Kapitel haben Sie gesehen, wie einfach es ist, mehrere Arduino-Systeme fernzusteuern. So können Sie die digitalen Ausgänge steuern, indem Sie von einem PC-Terminal oder einem anderen Arduino aus Zeichen senden, aber auch bestimmte Zeichen von einzelnen Arduinos erkennen lassen. Mit den hier gewonnenen Kenntnissen stehen Ihnen viele kreative Möglichkeiten offen.

Es gibt aber noch viel mehr zur drahtlosen Datenübertragung zu sagen. Im nächsten Kapitel lernen Sie, wie Sie den Arduino über eine handelsübliche Fernbedienung für Fernseher steuern.

15

Infrarot-Fernbedienungen

In diesem Kapitel lernen Sie Folgendes:

• Bauen und Testen eines einfachen Infrarot-Empfangsgeräts

• Fernsteuern der digitalen Ausgangspins des Arduino

• Fernsteuerung des Raupenfahrzeugs aus Kapitel 12

Durch die Ergänzung um ein preisgünstiges Empfangsmodul ist der Arduino in der Lage, Signale von einer Infrarot-Fernbedienung zu empfangen und danach zu handeln.

Was ist Infrarot?

Wir verwenden zwar jeden Tag Infrarot-Fernbedienungen für verschiedene Zwecke, aber die wenigsten wissen, wie sie funktionieren. Bei Infrarotsignalen (IR) handelt es sich um Lichtstrahlen einer Wellenlänge, die das menschliche Auge nicht wahrnehmen kann. Wenn Sie auf die kleine Leuchtdiode schauen, die vorn aus einer solchen Fernbedienung herausragt, und eine der Tasten betätigen, sehen Sie daher nicht, dass die LED aufleuchtet.

IR-Fernbedienungen enthalten eine oder mehrere besondere LEDs, die Infrarotlicht erzeugen. Wenn Sie eine Taste auf der Fernbedienung drücken, blinkt die LED in einem charakteristischen Muster für die betreffende Taste. Das Signal wird dann von einem IR-Empfänger aufgefangen und in elektrische Pulse umgewandet, die die Elektronik des Empfängers anschließend in Daten konvertiert. Wenn Sie die Muster erkennen wollen, können Sie sie sich ansehen, indem Sie sich die IR-LED auf der Fernbedienung durch den Sucher einer Handy- oder Digitalkamera anschauen.

Vorbereitung für die Infrarotübertragung

Als Erstes brauchen Sie die Arduino-Bibliothek für die Infrarotübertragung. Laden Sie alle erforderlichen Dateien von https://github.com/shirriff/Arduino-IRremote/ herunter und installieren Sie sie nach der Anleitung im Abschnitt »Sketche durch Bibliotheken erweitern« von Kapitel 8.

Der IR-Empfänger

Der nächste Schritt besteht darin, den IR-Empfänger einzurichten und zu prüfen. Dazu können Sie entweder einen eigenständigen Empfänger wie den aus Abbildung 15–1 verwenden oder ein vorverdrahtetes Modul wie in Abbildung 15–2, was die einfachere Vorgehensweise darstellt.

Abb. 15–1 IR-Empfänger

Abb. 15–2 Vorverdrahtetes IR-Empfangsmodul

Der eigenständige IR-Empfänger in Abbildung 15–1 ist ein Vishay TSOP4138, den Sie bei Anbietern wie Newark (Bestell-Nr. 59K0287) und element14 (Bestell-Nr. 1040743) bekommen. Das in der Abbildung unten liegende Bein wird mit einem Digitalpin am Arduino verbinden, das mittlere mit GND und das obere mit dem 5-Volt-Anschluss.

In Abbildung 15–2 sehen Sie ein vorverdrahtetes IR-Empfangsmodul, wie es bei DFRobot und anderen Anbietern erhältlich ist. Der Vorteil dieser Bauteile besteht darin, dass sie bereits über Verbindungsdrähte verfügen und beschriftet sind, was den Anschluss erleichtert.

Unabhängig vom Empfängertyp wird in allen folgenden Beispielen der Kontakt D (die Datenleitung) mit dem Digitalpin 11 des Arduino verbunden, VCC mit dem 5-Volt-Anschluss und GND mit GND.

Die Fernbedienung

Schließlich benötigen Sie noch eine Fernbedienung. In diesen Projekten verwenden wir eine Fernbedienung für Sony-Fernseher wie die aus Abbildung 15–3. Stattdessen können Sie aber auch jede handelsübliche Universalfernbedienung nehmen, müssen sie allerdings zunächst auf die Sony-Codes einstellen. Wie man dabei vorgeht, erfahren Sie in der mitgelieferten Anleitung.

Abb. 15–3 Ein Beispiel für eine Sony-Fernbedienung

Der Testsketch

Um sicherzustellen, dass alles funktioniert, schließen Sie den IR-Empfänger an den Arduino an, geben den Sketch aus Listing 15–1 ein und laden ihn hoch.

int receiverpin = 11;          // Pin 1 des IR-Empfängers liegt
// am Digitalpin 11 des Arduino
#include <IRremote.h>          // Schließt die Bibliothek ein
IRrecv irrecv(receiverpin);    // Erstellt eine Instanz von irrecv
decode _ results results;

void setup()
{
Serial.begin(9600);
irrecv.enableIRIn();        // Startet den IR-Empfänger
}

void loop()
{
if (irrecv.decode(&results))          // Ist ein IR-Signal eingegangen?
{
Serial.print(results.value, HEX);  // Zeigt den IR-Code auf
// dem seriellen Monitor an
Serial.print(" ");
irrecv.resume();                   // Empfängt den nächsten Wert
}
}

Listing 15–1 Test des IR-Empfängers

Der Sketch ist ziemlich einfach, da die meiste Arbeit im Hintergrund von der IR-Bibliothek erledigt wird. Bei prüfen wir, ob ein Signal von der Fernbedienung eingegangen ist. Wenn ja, wird es bei in hexadezimaler Form auf dem seriellen Monitor angezeigt. Die Zeilen , und schließen die IR-Bibliothek ein und erstellen eine Instanz der Bibliotheksfunktion, auf die im Rest des Sketches verwiesen wird.

Den Sketch testen

Laden Sie den Sketch hoch, öffnen Sie den seriellen Monitor, zielen Sie mit der Fernbedienung auf den Empfänger und drücken Sie beliebige Tasten. Jedes Mal, wenn Sie eine Taste drücken, wird anschließend der zugehörige Code auf dem seriellen Monitor angezeigt. In Abbildung 15–4 sehen Sie beispielsweise das Ergebnis der Betätigung von Taste , und .

Abb. 15–4 Anzeige von Listing 15–1 bei der Betätigung von Tasten

Tabelle 15–1 führt die Codes für die einfache Sony-Fernbedienung auf, die wir in den folgenden Sketchen verwenden. Wenn Sie Listing 15–1 ausführen, werden Sie jedoch feststellen, dass jeder Code dreimal ausgegeben wird. Das ist eine Eigentümlichkeit der IR-Systeme von Sony, die den Code bei jeder Betätigung einer Taste dreimal senden. Mit geschickter Programmierung können Sie diese Wiederholungen verwerfen, wie Sie im nächsten Projekt sehen.

Taste

Code

Ein/Aus

A90

Stummschalten

290

1

10

2

810

3

410

4

C10

5

210

6

A10

7

610

8

E10

9

110

0

910

Lauter

490

Leiser

C90

Einen Kanal weiter

90

Einen Kanal zurück

890

Tab. 15–1 Codes für Sony-Fernbedienungen

Projekt Nr. 50: Den Arduino fernsteuern

Dieses Projekt zeigt Ihnen, wie Sie die digitalen Ausgangspins mithilfe einer IR-Fernbedienung steuern. In unserem Beispiel verwenden wir die Pins 2 bis 7 und die entsprechenden Zahlentasten auf der Sony-Fernbedienung. Wenn Sie eine dieser Tasten drücken, ändert der entsprechende Pin seinen Zustand eine Sekunde lang auf HIGH und fällt dann wieder auf LOW zurück. Dieses Projekt können Sie als Grundlage oder Richtschnur für andere Projekte heranziehen, in denen Sie eine Fernbedienung einsetzen möchten.

Die Hardware

Für dieses Projekt brauchen Sie die Teile für den IR-Test vom Anfang dieses Kapitels und den selbst gebauten LED-Shield, den Sie in Projekt 28 hergestellt haben. (Anstelle dieses Shields können Sie jedoch auch einzelne LEDs, Motoren oder andere Arten von Ausgängen anschließen.)

Der Sketch

Geben Sie den folgenden Sketch ein und laden Sie ihn hoch:

// Projekt 50: Den Arduino fernsteuern

int receiverpin = 11;      // Pin 1 des IR-Empfängers liegt
// am Digitalpin 11 des Arduino

#include <IRremote.h>
IRrecv irrecv(receiverpin);        // Erstellt eine Instanz von irrecv
decode _ results results;

void setup()
{
irrecv.enableIRIn();            // Startet den Empfänger
for (int z = 2 ; z < 8 ; z++)   // Richtet die Digitalpins ein
{
pinMode(z, OUTPUT);
}
}

void translateIR()
// Führt je nach empfangenem IR-Code eine bestimmte Aktion aus
// Verwendet die IR-Codes von Sony
{
switch(results.value)
{
case 0x810: pinOn(2);
break; // 2
case 0x410: pinOn(3);
break; // 3
case 0xC10: pinOn(4);
break; // 4
case 0x210: pinOn(5);
break; // 5
case 0xA10: pinOn(6);
break; // 6
case 0x610: pinOn(7);
break; // 7
}
}

void pinOn(int pin) // Schaltet den angegebenen Pin
// eine Sekunde lang ein
{
digitalWrite(pin, HIGH);
delay(1000);
digitalWrite(pin, LOW);
}

void loop()
{
if (irrecv.decode(&results))      // Ist ein IR-Signal eingegangen?
{
translateIR();
for (int z = 0 ; z < 2 ; z++)  // Ignoriert das 2. und 3. Vorkommen
// des wiederholten Codes
{
irrecv.resume();            // Empfängt den nächsten Wert
}
}
}

Der Sketch besteht aus drei Hauptteilen. Zunächst wartet er bei auf ein Signal von der Fernbedienung. Wenn eines eingeht, wird es in der Funktion bei untersucht, um zu bestimmen, welche Taste gedrückt wurde und welche Aktion ausgeführt werden soll.

Beachten Sie, wie wir ab die von der IR-Bibliothek zurückgegebenen Codes mit den möglichen Fällen vergleichen. Es handelt sich dabei um die gleichen Codes, die wir auch beim Test in Listing 15–1 erhalten haben. Gehen die Codes für die Tasten 2 bis 7 ein, wird die Funktion pinOn() aufgerufen, die Sie bei sehen. Sie schaltet den zugehörigen Digitalpin eine Sekunde lang ein.

Wie bereits erwähnt, senden Sony-Fernbedienungen den Code für jede Taste dreimal, weshalb wir bei eine kleine Schleife verwenden, um das zweite und das dritte Vorkommen zu verwerfen. Beachten Sie außerdem das Präfix 0x vor den Hexadezimalzahlen in den case-Anweisungen bei .

HINWEIS

Hexadezimalzahlen sind Zahlen zur Basis 16, die aus den Ziffern 0 bis 9 sowie den Buchstaben A bis F aufgebaut sind. Der Wechsel zur nächsthöheren Stelle erfolgt erst, wenn der Wert fünfzehn (also F) überschritten ist. Der Dezimalwert 10 entspricht in hexadezimaler Form also A, der Dezimalwert 15 dem hexadezimalen F, der Dezimalwert 16 dem hexadezimalen 10 usw. In einem Sketch müssen Sie Hexadezimalzahlen das Präfix 0x voranstellen.

Den Sketch erweitern

Führen Sie noch Tests auf weitere Tasten durch, um die Möglichkeiten für die Fernsteuerung zu erweitern. Bestimmen Sie anhand von Listing 15–1, welche Tasten welchen Code hervorrufen, und fügen Sie die zusätzlichen Codes zu der switch-case-Anweisung hinzu.

Projekt Nr. 51: Ein Raupenfahrzeug fernsteuern

Um Ihnen zu zeigen, wie Sie die IR-Fernbedienung auch für ein bereits vorhandenes Projekt einsetzen können, erweitern wir das in Projekt 40 beschriebene Raupenfahrzeug um eine Fernsteuerung. Anstatt Fahrtrichtung und Entfernung vorzugeben, ermöglicht es Ihnen der Sketch aus diesem Projekt, den Roboter mit einer einfachen Sony-Fernbedienung zu steuern.

Die Hardware

An Geräten benötigen Sie das Raupenfahrzeug aus Projekt 40 sowie den zuvor in diesem Kapitel verwendeten IR-Empfänger und die Fernbedienung. Der Sketch sorgt dafür, dass das Fahrzeug auf die Betätigung folgender Tasten auf der Fernbedienung reagiert: für Vorwärtsfahrt, für Rückwärtsfahrt, für Drehung nach links und für Drehung nach rechts.

Der Sketch

Nachdem Sie den IR-Empfänger an dem Raupenfahrzeug montiert haben, geben Sie folgenden Sketch ein und laden ihn hoch:

// Projekt 51: Ein Raupenfahrzeug fernsteuern

int receiverpin = 11;       // Pin 1 des IR-Empfängers liegt
// am Digitalpin 11 des Arduino
#include <IRremote.h>

IRrecv irrecv(receiverpin); // Erstellt eine Instanz von irrecv
decode _ results results;

int m1speed     = 6;        // Digitalpins für die Drehzahlregelung
int m2speed     = 5;
int m1direction = 7;        // Digitalpins für die Richtungssteuerung
int m2direction = 4;

void setup()
{
pinMode(m1direction, OUTPUT);
pinMode(m2direction, OUTPUT);
irrecv.enableIRIn();              // Startet den IR-Empfänger
}

void goForward(int duration, int pwm)
{
digitalWrite(m1direction, HIGH);  // Vorwärts
digitalWrite(m2direction, HIGH);  // Vorwärts
analogWrite(m1speed, pwm);        // Vorgesehene Drehzahl
analogWrite(m2speed, pwm);
delay(duration);                  // Vorgesehene Dauer
analogWrite(m1speed, 0);          // Hält anschließend an
analogWrite(m2speed, 0);
}

void goBackward(int duration, int pwm)
{
digitalWrite(m1direction, LOW);   // Rückwärts
digitalWrite(m2direction, LOW);   // Rückwärts
analogWrite(m1speed, pwm);        // Vorgesehene Drehzahl
analogWrite(m2speed, pwm);
delay(duration);
analogWrite(m1speed, 0);          // Hält anschließend an
analogWrite(m2speed, 0);
}

void rotateRight(int duration, int pwm)
{
digitalWrite(m1direction, HIGH);  // Vorwärts
digitalWrite(m2direction, LOW);   // Rückwärts
analogWrite(m1speed, pwm);        // Vorgesehene Drehzahl
analogWrite(m2speed, pwm);
delay(duration);                  // Vorgesehene Dauer
analogWrite(m1speed, 0);          // Hält anschließend an
analogWrite(m2speed, 0);
}

void rotateLeft(int duration, int pwm)
{
digitalWrite(m1direction, LOW);   // Rückwärts
digitalWrite(m2direction, HIGH);  // Vorwärts
analogWrite(m1speed, pwm);        // Vorgesehene Drehzahl
analogWrite(m2speed, pwm);

delay(duration);                  // Vorgesehene Dauer
analogWrite(m1speed, 0);          // Hält anschließend an
analogWrite(m2speed, 0);
}

// translateIR führt je nach empfangenem IR-Code eine bestimmte
// Aktion aus
// Verwendet werden die Sony-IR-Codes
void translateIR()
{
switch(results.value)
{
case 0x810: goForward(250, 255);
break; // 2
case 0xC10: rotateLeft(250, 255);
break; // 4
case 0xA10: rotateRight(250, 255);
break; // 6
case 0xE10: goBackward(250, 255);
break; // 8
}
}
void loop()
{
if (irrecv.decode(&results))      // Ist ein IR-Signal eingegangen?
{
translateIR();
for (int z = 0 ; z < 2 ; z++)  // Ignoriert die Codewiederholungen
{
irrecv.resume();            // Empfängt den nächsten Wert
}
}
}

Der Sketch sollte Ihnen vertraut vorkommen. Anstatt die Digitalpins einzuschalten, ruft er die Funktionen zur Motorsteuerung auf, die wir bereits in Kapitel 12 verwendet haben.

Ausblick

Beim Durcharbeiten der Projekte in diesem Kapitel haben Sie gelernt, wie Sie mit einer Infrarot-Fernbedienung Befehle an einen Arduino senden können. Zusammen mit den Kenntnissen, die Sie bereits erworben haben (und mit denen, die Sie in kommenden Projekten noch erwerben), können Sie damit Eingabegeräte wie Drucktasten durch eine Fernbedienung ersetzen.

Aber der Spaß hört noch nicht auf. Im nächsten Kapitel setzen wir den Arduino für etwas ein, was für den Laien erstaunlich und futuristisch wirkt: Funkidentifizierungssysteme, besser bekannt als RFID.

16

RFID-Transponder lesen

In diesem Kapitel lernen Sie Folgendes:

• Konstruktion eines RFID-Lesegeräts mit dem Arduino

• Speichern von Variablen im EEPROM des Arduino

• Grundgerüst eines Arduino-gestützten RFID-Steuerungssystems

RFID (Radio-Frequency Identification, also »Identifizierung über Funkfrequenzen«) ist ein drahtloses System, bei dem Daten über elektromagnetische Felder berührungsfrei von einem Objekt zu einem anderen übertragen werden. Sie können mit dem Arduino gebräuchliche RFID-Etiketten und -Karten lesen, um darüber die digitalen Ausgänge zu steuern oder um ein Zutrittskontrollsystem zu bauen. Möglicherweise haben Sie schon einmal eine RFID-Karte verwendet, beispielsweise eine Zugangskarte, um eine Tür zu öffnen, oder eine Karte für den öffentlichen Personennahverkehr, die Sie im Bus vor ein Lesegerät halten. Abbildung 16–1 zeigt einige Beispiele für RFID-Etiketten und -Karten.

Abb. 16–1 Beispiele für RFID-Transponder

Das Innenleben von RFID-Transpondern

Innerhalb eines RFID-Transponders befindet sich ein winziger integrierter Schaltkreis, dessen Speicher über ein besonderes Lesegerät zugänglich ist. Die meisten Transponder haben keine Batterie, sondern werden durch die Energie eines elektromagnetischen Feldes angetrieben, das das Lesegerät hervorruft. Das Feld wird über eine feine Drahtspule übertragen, die auch als Antenne für die Übermittlung von Daten zwischen Transponder und Lesegerät dient. Abbildung 16–2 zeigt die Antennenspule des RFID-Lesegeräts, das wir in diesem Kapitel verwenden.

Abb. 16–2 Ein RFID-Lesegerät

Den Kartenleser, den wir in diesem Kapitel einsetzen, können Sie unter der Bestellnummer ELB149C5M bei Seeed Studio unter http://www.seeedstudio.com/ erwerben (mit drei e!). Er ist preisgünstig und einfach zu verwenden. Seine Betriebsfrequenz liegt bei 125 kHz. Achten Sie beim Kauf von RFID-Transpondern darauf, dass sie für dieselbe Frequenz ausgelegt sind. Beispielsweise können Sie die Transponder verwenden, die Sie bei Seeed Studio unter der Nummer RFR103B2B bekommen.

Die Hardware testen

In diesem Abschnitt schließen Sie das RFID-Lesegerät an den Arduino an und prüfen mit einem einfachen Sketch, ob es funktioniert. Dabei liest der Sketch die RFID-Transponder und sendet die Daten an den seriellen Monitor.

Der Schaltplan

Abbildung 16–3 zeigt die Anschlüsse des RFID-Moduls.

Abb. 16–3 Anschlüsse des RFID-Moduls

Die Schaltung prüfen

Bevor Sie das RFID-Lesegerät prüfen können, müssen Sie es an den Arduino anschließen. Setzen Sie dazu zunächst die schwarze Steckbrücke auf den linken und den mittleren Pin des Jumperbereichs und stellen Sie dann wie folgt mit Überbrückungskabeln (weiblich auf männlich) die Verbindung zwischen dem Lesegerät und dem Arduino her:

1. Schließen Sie den mitgelieferten Spulenstecker an der Antennenbuchse an.

2. Verbinden Sie den GND-Anschluss am Lesegerät mit dem GND-Anschluss des Arduino.

3. Verbinden Sie VCC mit dem 5-Volt-Anschluss des Arduino.

4. Verbinden Sie RX mit dem Arduino-Pin D0.

5. Verbinden Sie TX mit dem Arduino-Pin D1.

HINWEIS

Beim Hochladen von Sketchen auf den Arduino müssen Sie die Verbindung zwischen dem RX-Anschluss des Lesegeräts und dem Arduino-Pin D0 lösen. Stellen Sie sie wieder her, nachdem der Sketch hochgeladen ist. Der Grund dafür ist, dass D0 vom Arduino auch zur Kommunikation und zum Empfang von Sketchen dient.

Der Testsketch

Geben Sie jetzt den Code aus Listing 16–1 ein und laden Sie ihn hoch.

int data1 = 0;

void setup()
{
Serial.begin(9600);
}

void loop()
{
if (Serial.available() > 0) {
data1 = Serial.read();
// Zeigt die eingehende Zahl an
Serial.print(" ");
Serial.print(data1, DEC);
}
}

Listing 16–1 RFID-Testsketch

Überprüfung im seriellen Monitor

Öffnen Sie den seriellen Monitor und bewegen Sie einen RFID-Transponder über die Spule. Dadurch erhalten Sie ein Ergebnis wie in Abbildung 16–4.

Abb. 16–4 Beispielausgabe von Listing 16–1

Die 14 Zahlen, die im seriellen Monitor angezeigt werden, stellen die eindeutige ID des RFID-Transponders dar, die wir in künftigen Sketchen zu dessen Identifizierung verwenden. Notieren Sie sich die Zahlen, die bei Ihren Transpondern jeweils angezeigt werden. Sie werden sie in den nächsten Projekten noch brauchen.

Projekt Nr. 52: Ein einfaches RFID-Steuerungssystem konstruieren

Als Nächstes werden wir das RFID-System praktisch einsetzen. In diesem Projekt lernen Sie, wie Sie beim Lesen eines bestimmten Transponders ein Arduino-Ereignis auslösen. Der Sketch speichert zwei Nummern von RFID-Karten. Wird die eine davon vom Lesegerät erfasst, so wird auf dem seriellen Monitor Accepted angezeigt, bei der anderen dagegen Rejected. Dies können Sie als Grundlage nutzen, um Ihren Projekten eine RFID-Zugriffssteuerung hinzuzufügen.

Der Sketch

Geben Sie den folgenden Sketch ein und laden Sie ihn hoch. Ersetzen Sie die Xe in den Arrays bei und jedoch durch die Nummern der RFID-Transponder, die Sie zuvor in diesem Kapitel bestimmt haben. (Arrays wurden in Kapitel 6 behandelt.)

// Projekt 52: Ein einfaches RFID-Steuerungssystem konstruieren

int data1 = 0;
int ok = -1;

// Die Nummern Ihrer Transponder ermitteln Sie mit dem Code
// aus Listing 16–1
int tag1[14] = {x, x, x, x, x, x, x, x, x, x, x, x, x, x};
int tag2[14] = {x, x, x, x, x, x, x, x, x, x, x, x, x, x};

int newtag[14] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0}; // Dient zu Lesevergleichen

void setup()
{
Serial.flush();  // Der serielle Puffer muss geleert werden, da der erste
// Lesevorgang sonst möglicherweise nicht korrekt ist
Serial.begin(9600);
}

boolean comparetag(int aa[14], int bb[14])
{
boolean ff = false;
int fg = 0;
for (int cc = 0 ; cc < 14 ; cc++)
{
if (aa[cc] == bb[cc])
{
fg++;
}
}
if (fg == 14)
{
ff = true;
}
return ff;
}

void checkmytags() // Vergleicht die gerade gelesene Transpondernummer mit
// den gespeicherten
{
ok = 0;  // Diese Variable dient zur Entscheidungsfindung.
// Bei einer 1 liegt eine Übereinstimmung vor, bei 0 wurde
// ein nicht übereinstimmender Wert gelesen, bei -1 wurde
// kein Leseversuch unternommen.
if (comparetag(newtag, tag1) == true)
{
ok++;
}
if (comparetag(newtag, tag2) == true)
{
ok++;
}
}

void loop()
{
ok = -1;
if (Serial.available() > 0) // Wenn ein Leseversuch unternommen wurde
{
// Liest die eingehende Nummer am seriellen RX-Eingang
delay(100); // Räumt Zeit ein, damit die Daten vom seriellen
// Puffer eingehen können
for (int z = 0 ; z < 14 ; z++)   // Liest den Rest
// der Transponderdaten
{
data1 = Serial.read();
newtag[z] = data1;
}
Serial.flush(); // Verhindert mehrfache Lesevorgänge
// Jetzt werden die Transponder verglichen
checkmytags();
}
// Führt je nach Transponder eine bestimmte Aktion durch
if (ok > 0) // Bei Übereinstimmung
{
Serial.println("Accepted");
ok = -1;
}
else if (ok == 0) // Wenn keine Übereinstimmung vorliegt
{
Serial.println("Rejected");
ok = -1;
}
}

Funktionsweise

Ein Transponder, der dem RFID-Lesegerät präsentiert wird, sendet seine Nummer über den seriellen Port. Bei erfassen wir alle 14 Ziffern dieser Nummer und stellen sie in das Array newtag[]. Als Nächstes wird dieses Array in der Funktion checkmytags() bei und mit den beiden Transpondernummern verglichen, die in und gespeichert wurden. Der eigentliche Vergleich wird comparetag() bei überlassen.

Die Funktion comparetag() nimmt zwei Zahlen-Arrays als Parameter entgegen und gibt in Form eines booleschen Werts zurück, ob die Arrays identisch sind (true) oder nicht (false). Bei einer Übereinstimmung wird die Variable OK bei und auf 1 gesetzt. Schließlich stehen bei die Aktionen, die in Abhängigkeit vom Ergebnis des Lesevorgangs ausgeführt werden sollen.

Laden Sie den Sketch hoch, stellen Sie die Verbindung zwischen D0 auf dem Arduino und RX auf dem RFID-Lesegerät wieder her (siehe Abb. 16–3), öffnen Sie den seriellen Monitor und halten Sie einige Transponder vor das Lesegerät. Die Ergebnisse werden wie in Abbildung 16–5 angezeigt.

Abb. 16–5 Das Ergebnis von Projekt 52

Daten im eingebauten EEPROM des Arduino speichern

Wenn Sie in Arduino-Sketchen Variablen definieren, bleiben die darin gespeicherten Daten nur bis zum Zurücksetzen oder Abschalten des Arduino erhalten. Was aber, wenn Sie die Werte für die weitere Verwendung aufbewahren möchten, z. B. die Geheimzahl für das Tastenfeld in Kapitel 9? Hier kommt der EEPROM (Eletrically Erasable Read-Only Memory, also »elektrisch löschbarer, programmierbarer schreibgeschützter Speicher«) ins Spiel. Er hält Variablen im Speicher des ATmega328-Mikrocontrollers fest, sodass sie auch dann nicht verloren gehen, wenn der Strom abgeschaltet wird.

Der EEPROM des Arduino kann 1024 Bytevariablen in den Positionen von 0 bis 1023 speichern. Wenn Sie bedenken, dass ein Byte einen Integer mit einem Wert zwischen 0 und 255 aufnehmen kann, dürfte klar werden, warum dies ideal für die Speicherung von RFID-Transpondernummern geeignet ist. Um den EEPROM in einem Sketch verwenden zu können, müssen Sie zunächst die zugehörige Bibliothek (die in der Arduino-IDE enthalten ist) wie folgt einschließen:

#include <EEPROM.h>

Um einen Wert in den EEPROM zu schreiben, verwenden Sie einfach folgenden Code:

EEPROM.write(a, b);

Hier ist a die Position (zwischen 0 und 1023), in der der Wert gespeichert wird, und b die Variable mit dem Datenbyte, das an der EEPROM-Position a abgelegt werden soll.

Um Daten vom EEPROM abzurufen, verwenden Sie folgende Funktion:

value = EEPROM.read(Position);

Dadurch werden die Daten abgerufen, die sich an der angegebenen EEPROM-Position befinden, und in der Variable value gespeichert.

HINWEIS

Der EEPROM hat eine begrenzte Lebensdauer und ist irgendwann abgenutzt. Laut Angabe des Herstellers Atmel kann er 100.000 Schreib-/Löschvorgänge für jede Position überstehen. Die Anzahl der Lesevorgänge ist dagegen unbegrenzt.

Lesen und Schreiben im EEPROM

Das folgende Beispiel zeigt, wie Sie Daten in den EEPROM schreiben und von ihm lesen. Geben Sie den Code aus Listing 16–2 ein und laden Sie ihn hoch.

#include <EEPROM.h>
int zz;

void setup()
{
Serial.begin(9600);
randomSeed(analogRead(0));
}

void loop()
{
Serial.println("Writing random numbers...");
for (int i = 0; i < 1024; i++)
{
zz = random(255);
EEPROM.write(i, zz);
}

Serial.println();
for (int a = 0; a < 1024; a++)
{
zz = EEPROM.read(a);
Serial.print("EEPROM position: ");
Serial.print(a);
Serial.print(" contains ");
Serial.println(zz);
delay(25);
}
}

Listing 16–2 Sketch zur Veranschaulichung des EEPROM

In der Schleife bei wird an jeder EEPROM-Position eine Zufallszahl zwischen 0 und 255 gespeichert. Diese Werte werden dann in der zweiten Schleife bei abgerufen und bei im seriellen Monitor angezeigt.

Laden Sie den Sketch hoch und öffnen Sie den seriellen Monitor. Dort können Sie dann eine Anzeige wie in Abbildung 16–6 beobachten.

Abb. 16–6 Beispielausgabe von Listing 16–2

Nun sind Sie bereit für ein Projekt, in dem Sie den EEPROM verwenden.

Projekt Nr. 53: Ein RFID-Steuerungssystem konstruieren, das sich die letzte Aktion merkt

In Projekt Nr. 52 haben wir zwar den Zugriff auf eine beliebige Einrichtung gesteuert, z. B. eine Lampe oder ein elektrisches Türschloss, allerdings kann sich das System den Zustand nicht merken, wenn es zurückgesetzt wird oder der Strom ausfällt. Wenn beispielsweise das Licht eingeschaltet war, als der Strom ausging, würde es nach dem Wiederanlaufen der Stromversorgung ausgeschaltet sein. Es wäre natürlich besser, wenn sich der Arduino den Zustand merken und ihn später wiederherstellen könnte. Darum kümmern wir uns jetzt.

In diesem Projekt wird die letzte Aktion (z. B. »geschlossen« oder »geöffnet«) im EEPROM gespeichert. Wenn der Sketch nach einem Stromausfall oder einem Zurücksetzen des Arduino neu gestartet wird, kehrt das System zu dem vorherigen, im EEPROM festgehaltenen Zustand zurück.

Der Sketch

Geben Sie den folgenden Sketch ein und laden Sie ihn hoch. Auch hier müssen Sie wieder die Xe bei und durch die Nummern von zweien Ihrer RFID-Transponder ersetzen, wie Sie es schon in Projekt 52 getan haben.

// Projekt 53: Ein RFID-Steuerungssystem konstruieren, das sich die
// letzte Aktion merkt

#include <EEPROM.h>
int data1 = 0;
int ok = -1;
int lockStatus = 0;

// Die Nummern Ihrer Transponder ermitteln Sie
// mit dem Code aus Listing 16–1
int tag1[14] = {x, x, x, x, x, x, x, x, x, x, x, x, x, x};
int tag2[14] = {x, x, x, x, x, x, x, x, x, x, x, x, x, x};

int newtag[14] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0}; // Dient zu Lesevergleichen

void setup()
{
Serial.flush();
Serial.begin(9600);
pinMode(13, OUTPUT);
checkLock();
}

// comparetag vergleicht zwei Arrays und gibt true zurück,
// wenn sie identisch sind. Das ist eine ideale Möglichkeit
// zum Vergleich von Transpondern.
boolean comparetag(int aa[14], int bb[14])
{
boolean ff = false;
int fg = 0;
for (int cc = 0; cc < 14; cc++)

{
if (aa[cc] == bb[cc])
{
fg++;
}
}
if (fg == 14)
{
ff = true;
}
return ff;
}

void checkmytags()
// Vergleicht die gerade gelesene Transpondernummer mit den gespeicherten
{
ok = 0;
if (comparetag(newtag, tag1) == true)
{
ok++;
}
if (comparetag(newtag, tag2) == true)
{
ok++;
}
}

void checkLock()
{
Serial.print("System Status after restart ");
lockStatus = EEPROM.read(0);
if (lockStatus == 1)
{
Serial.println("- locked");
digitalWrite(13, HIGH);
}
if (lockStatus == 0)
{
Serial.println("- unlocked");
digitalWrite(13, LOW);
}
if ((lockStatus != 1) && (lockStatus != 0))
{
Serial.println("EEPROM fault - Replace Arduino hardware");
}
}

void loop()
{
ok = -1;
if (Serial.available() > 0)   // Wenn ein Leseversuch unternommen wurde
{
// Liest den Serial RX-Eingang
delay(100);
for (int z = 0; z < 14; z++) // Liest den Rest der Transponderdaten
{
data1 = Serial.read();
newtag[z] = data1;
}
Serial.flush(); // Verhindert mehrfache Lesevorgänge
// Jetzt werden die Transponder verglichen
checkmytags();
}
if (ok > 0) // Bei Übereinstimmung
{
lockStatus = EEPROM.read(0);
if (lockStatus == 1) // Wenn das Schloss verriegelt ist,
// wird es geöffnet
{
Serial.println("Status - unlocked");
digitalWrite(13, LOW);
EEPROM.write(0, 0);
}
if (lockStatus == 0)
{
Serial.println("Status - locked");
digitalWrite(13, HIGH);
EEPROM.write(0, 1);
}
if ((lockStatus != 1) && (lockStatus != 0))
{
Serial.println("EEPROM fault - Replace Arduino hardware");
}
}
else if (ok == 0) // Wenn keine Übereinstimmung vorliegt
{
Serial.println("Incorrect tag");
ok = -1;
}
delay(500);
}

Funktionsweise

Dieser Sketch ist eine Variante von Projekt 52. Um den Status einer Einrichtung (z. B. eines Schlosses) zu simulieren, die beim Lesen eines akzeptierten RFID-Transponders ein- oder ausgeschaltet werden soll, verwenden wir die eingebaute LED. Nachdem der Transponder gelesen und überprüft wurde, wird der Status des »Schlosses« bei geändert. Den neuen Status speichern wir in Form einer Zahl an der ersten Position des EEPROM: Dabei steht 0 für geöffnet und 1 für geschlossen. Nach jedem erfolgreichen Transponder-Lesevorgang wird der Status bei oder geändert (von »geschlossen« in »geöffnet« und umgekehrt).

Außerdem haben wir eine Vorsichtsmaßnahme für den Fall getroffen, dass der EEPROM abgenutzt ist. Wenn der beim Lesen des EEPROM zurückgegebene Wert weder 0 noch 1 lautet, werden wir bei darüber benachrichtigt. Des Weiteren wird der Status bei jedem Neustart nach einem Reset durch die Funktion checkLock() bei , , und überprüft. Sie liest den EEPROM-Wert, bestimmt den letzten Status und richtet das Schloss entsprechend ein (d. h. öffnet oder schließt es).

Ausblick

Auch hier haben wir eine sehr kompliziert wirkende Einrichtung mithilfe des Arduino auf einfache Weise nachgestellt. Jetzt verfügen Sie über eine Grundlage, um Ihren Projekten eine professionelle RFID-Zugriffssteuerung hinzuzufügen und um die digitalen Ausgänge dadurch zu steuern, dass Sie einfach eine RFID-Karte vor ein Lesegerät halten. Diese Möglichkeiten werden wir in Kapitel 18 noch weiter vorführen.

17

Datenbusse

In diesem Kapitel lernen Sie Folgendes:

• Grundlagen des I^2C-Busses

• Verwendung eines EEPROM und einer Porterweiterung am I^2C-Bus

• Grundlagen des SPI-Busses

• Verwendung eines Digitalpotenziometers am SPI-Bus

Ein Arduino kommuniziert mit anderen Geräten über einen Datenbus. Dabei handelt es sich um ein System aus Verbindungen, über die zwei oder mehr Geräte Daten auf geordnete Weise austauschen können. Ein Datenbus kann eine Verbindung zwischen dem Arduino und verschiedenen Sensoren, E/A-Erweiterungsgeräten oder anderen Bauteilen herstellen.

Für den Arduino spielen vor allem zwei Busse eine wichtige Rolle: der SPI-Bus (Serial Peripheral Interface) und der I^2C-Bus (Inter-Integrated Circuit). Viele nützliche Sensoren und externe Geräte kommunizieren über diese beiden Busse.

Der I^2C-Bus

Der I^2C-Bus ist ein einfaches und leicht zu nutzendes Gerät für die Datenkommunikation. Die Daten werden zwischen dem Arduino und anderen Geräten über zwei Drähte übertragen (daher auch die Bezeichnung TWI-Bus für Two Wire Interface), die als SDA und SCL bezeichnet werden und bei denen es sich um die Daten- und die Taktleitung (»clock«) handelt. Beim Arduino Uno ist A4 der SDA-Pin und A5 der SCL-Pin (siehe Abb. 17–1). Einige neuere R3-Platinen weisen für den bequemen Zugriff auf den Bus auch zweckbestimmte I^2C-Kontakte in der oberen linken Ecke auf.

Abb. 17–1 Anschlüsse für den I^2C-Bus am Arduino Uno

Der Arduino gilt am I^2C-Bus als Master-Gerät, alle anderen ICs am Bus als Slave. Jeder Slave verfügt über seine eigene Adresse in Form einer Hexadezimalzahl, mit der der Arduino die Geräte ansprechen und mit ihnen kommunizieren kann. Gewöhnlich bringt jedes Gerät einen Bereich von I^2C-Busadressen zur Auswahl mit. Einzelheiten werden im Datenblatt des Herstellers angegeben. Welche Adressen zur Verfügung stehen, hängt von der Verdrahtung der IC-Pins ab.

HINWEIS

Da der Arduino eine Betriebsspannung von 5 V hat, müssen auch die angeschlossenen I^2C-Geräte mit 5 V arbeiten oder eine solche Spannung verkraften. Lassen Sie sich das vor Inbetriebnahme vom Händler oder Hersteller bestätigen.

Um den I^2C-Bus zu nutzen, brauchen Sie die Bibliothek Wire (die in der Arduino-IDE enthalten ist):

#include <Wire.h>

Danach aktivieren Sie den Bus wie folgt in void setup():

Wire.begin();

Die Daten werden Byte für Byte über den Bus übertragen. Um ein Byte Daten vom Arduino an ein Gerät am Bus zu senden, sind drei Funktionen erforderlich:

1. Die erste Funktion leitet die Kommunikation mit der folgenden Codezeile ein. (Dabei steht Adresse für die hexadezimale Busadresse des Slave-Geräts, z. B. 0x50.)

Wire.beginTransmission(Adresse);

2. Die zweite Funktion sendet ein Byte an Daten vom Arduino an das von der vorherigen Funktion angesprochene Gerät. (Daten ist hierbei eine Variable, die ein Byte an Daten enthält. Sie können auch größere Datenmengen senden, müssen dabei aber für jedes Byte eine eigene Wire.write()-Funktion verwenden.)

Wire.write(Daten);

3. Wenn wir mit dem Senden von Daten an das betreffende Gerät fertig sind, müssen wir die Übertragung schließlich wie folgt beenden:

Wire.endTransmission();

Um die Übertragung von Daten vom I^2C-Gerät an den Arduino anzufordern, beginnen Sie mit Wire.beginTransmission(Adresse) und geben dann die folgende Anweisung (wobei x angibt, wie viele Bytes an Daten Sie anfordern):

Wire.requestFrom(Adresse,x);

Danach speichern Sie das eingehende Byte mit der folgenden Funktion in einer Variable:

incoming = Wire.read();      // incoming ist die Variable,
// die das empfangene Datenbyte bekommt

Abermals müssen Sie die Übertragung mit Wire.endTransmission() abschließen. Im folgenden Projekt sehen Sie diese Funktionen im Einsatz.

Projekt Nr. 54: Einen externen EEPROM verwenden

In Kapitel 16 haben wir den internen EEPROM des Arduino verwendet, um zu verhindern, dass Variablendaten bei einem Zurücksetzen der Platine oder bei einem Stromausfall verloren gehen. Dieser interne EEPROM kann aber nur 1024 Bytes an Daten festhalten. Um mehr Daten zu speichern, können Sie einen externen EEPROM verwenden, wie Sie in diesem Projekt sehen werden.

Als externen EEPROM verwenden wir den 24LC512 von Microchip Technology, der bis zu 64 KB (65.536 Bytes) an Daten aufnehmen kann (siehe Abb. 17–2). Sie können ihn bei Anbietern wie Digi-Key (Bestell-Nr. 24LC512-I/P-ND) und element14 (Bestell-Nr. 1660008) erwerben.

Abb. 17–2 Der EEPROM 24LC512 von Microchip Technology

Die Hardware

Für dieses Projekt brauchen Sie folgende Teile:

• einen EEPROM 24LC512 von Microchip Technology

• zwei 4,7-kΩ-Widerstände

• einen 100-nF-Keramikkondensator

• eine Steckplatine

• Verbindungsdrähte

• Arduino und USB-Kabel

Der Schaltplan

Fügen Sie die beiden 4,7-kΩ-Widerstände wie in Abbildung 17–3 gezeigt zwischen dem 5-Volt-Anschluss und SCL bzw. SDA ein.

Die Busadresse des 24LC512 hängt teilweise von der Verdrahtung des EEPROM-ICs im Schaltkreis ab. Die letzten drei Bits der Adresse werden vom Status der Pins A2, A1 und A0 bestimmt. Sind diese Pins an Masse gelegt, haben sie den Wert 0, sind sie dagegen mit dem 5-Volt-Anschluss verbunden, beträgt der Wert 1.

Die ersten vier Bits sind auf 1010 voreingestellt. In unserem Schaltkreis lautet die Busadresse binär 1010000, hexadezimal 0x50. Im Sketch verwenden wir als Adresse also 0x50.

Abb. 17–3 Schaltplan für Projekt 54

Der Sketch

Der externe EEPROM kann zwar bis zu 64 KB an Daten speichern, aber in diesem Sketch wollen wir nur einen Bruchteil davon vorführen, indem wir lediglich in den ersten 20 Speicherpositionen Bytes ablegen und abrufen.

Geben Sie den folgenden Sketch ein und laden Sie ihn hoch:

// Projekt 54: Einen externen EEPROM verwenden
#include <Wire.h>
#define chip1 0x50

unsigned int pointer;
byte d=0;

void setup()
{
Serial.begin(9600);
Wire.begin();
}

void writeData(int device, unsigned int address, byte data)
// Schreibt das Datenbyte "data" im EEPROM mit der I2C-Adresse "device"
// am Speicherort 'address'
{
Wire.beginTransmission(device);
Wire.write((byte)(address >> 8));      // Linker Teil der Zeigeradresse
Wire.write((byte)(address & 0xFF));    // Rechter Teil
Wire.write(data);
Wire.endTransmission();
delay(10);
}

byte readData(int device, unsigned int address)
// Liest das Datenbyte am Speicherort "address"
// im Chip an der I2C-Adresse "device"
{
byte result;                         // Zurückgegebener Wert
Wire.beginTransmission(device);
Wire.write((byte)(address >> 8));    // Linker Teil der Zeigeradresse
Wire.write((byte)(address & 0xFF));  // Rechter Teil
Wire.endTransmission();
Wire.requestFrom(device,1);
result = Wire.read();
return result;     // Gibt das Byte als Ergebnis
// der Funktion readData zurück
}

void loop()
{
Serial.println("Writing data...");
for (int a=0; a<20; a++)
{
writeData(chip1,a,a);
}
Serial.println("Reading data...");
for (int a=0; a<20; a++)
{
Serial.print("EEPROM position ");
Serial.print(a);
Serial.print(" holds ");
d=readData(chip1,a);
Serial.println(d, DEC);
}
}

Gehen wir diesen Sketch nun Schritt für Schritt durch. Bei aktivieren wir die Bibliothek und definieren die I^2C-Busadresse chip1 für den EEPROM. Anschließend starten wir bei den seriellen Monitor und dann den I^2CBus. Die beiden selbst geschriebenen Funktionen writeData() und read-Data() helfen Zeit zu sparen und können außerdem bei zukünftigen Arbeiten mit dem EEPROM-IC wiederverwendet werden. Sie dienen dazu, Daten auf den EEPROM zu schreiben bzw. von ihm zu lesen.

Die Funktion writeData() bei leitet die Übertragung zum EEPROM ein. In den nächsten beiden Wire.write()-Funktionen sendet sie die Speicheradressen, an denen die Datenbytes im EEPROM abgelegt werden soll, schickt dann das zu schreibende Datenbyte und beendet die Übertragung.

Ebenso wie writeData() nutzt auch die Funktion readData() bei den I^2C-Bus, sendet aber keine Datenbytes an den EEPROM, sondern liest bei Daten mithilfe von wire.requestFrom(). Das vom EEPROM empfangene Byte wird schließlich in der Variable result abgelegt und von der Funktion zurückgegeben.

Das Ergebnis

In void loop() durchläuft der Sketch 20 Mal eine Schleife und schreibt dabei immer einen Wert in den EEPROM. Dann tritt das Programm in eine weitere Schleife ein, die die Werte abruft und im seriellen Monitor anzeigt (siehe Abb. 17–4).

Abb. 17–4 Die Ergebnisse von Projekt 54

Projekt Nr. 55: Einen IC zur Porterweiterung verwenden

Eine Porterweiterung ist eine weitere nützliche Art von ICs, die über den I^2C-Bus gesteuert wird und dazu dient, zusätzliche digitale Ausgänge bereitzustellen. In diesem Projekt verwenden wir die 16-Bit-Porterweiterung MCP23017 von Microchip Technology (siehe Abb. 17–5), die über 16 digitale Ausgänge verfügt. Erhältlich ist dieser IC bei Anbietern wie Newark (Bestell-Nr. 31K2959) und element14 (Bestell-Nr. 1332088).

Abb. 17–5 Der Porterweiterungs-IC MCP23017 von Microchip Technology

In diesem Projekt schließen Sie den MCP23017 an den Arduino an und lernen, wie Sie die 16 Erweiterungsausgänge über den Arduino steuern. Jeder dieser Zusatzausgänge kann wie ein regulärer digitaler Ausgang des Arduino behandelt werden.

Die Hardware

Für dieses Projekt brauchen Sie folgende Teile:

• einen Porterweiterungs-IC MCP20317 von Microchip Technology

• zwei 4,7-kΩ-Widerstände

• LEDs und 560-Ω-Widerstände in jeweils gleicher Anzahl (optional)

• eine Steckplatine

• Verbindungsdrähte

• Arduino und USB-Kabel

Der Schaltplan

Abbildung 17–6 zeigt den grundlegenden Schaltplan für einen MCP23017. Wie bei dem EEPROM aus Projekt 54 können wir die I^2C-Busadresse über die Verkabelung festlegen. Beim MCP23017 verbinden wir die Pins 15 bis 17 mit GND, um die Adresse auf 0x20 zu setzen.

Abb. 17–6 Grundschaltplan für Projekt 55

Für die Arbeit mit dem MCP23017 ist das Pindiagramm im Datenblatt des ICs sehr hilfreich (siehe Abb. 17–7). Beachten Sie, dass die 16 Ausgänge in zwei Reihen aufgeteilt sind, GPA7 bis GPA0 auf der rechten Seite und GPB0 bis GPB7 auf der linken. Um eine Anzeige dafür zu haben, wann die Ausgänge aktiviert werden, können Sie an alle oder einige von ihnen LEDs mit vorgeschalteten 560-Ω-Widerständen anschließen.

Abb. 17–7 Pindiagramm für MCP23017

Der Sketch

Geben Sie folgenden Sketch ein und laden Sie ihn hoch:

// Projekt 55: Einen IC zur Porterweiterung verwenden

#include "Wire.h"
#define mcp23017 0x20

void setup()
{
Wire.begin(); // Aktiviert den I2C-Bus
// Richtet den MCP23017 ein
// Richtet die E/A-Pins als Ausgänge ein
Wire.beginTransmission(mcp23017);
Wire.write(0x00); // IODIRA-Register
Wire.write(0x00); // Richtet alle Anschlüsse von Reihe A als Ausgänge ein
Wire.write(0x00); // Richtet alle Anschlüsse von Reihe B als Ausgänge ein
Wire.endTransmission();
}

void loop()
{
Wire.beginTransmission(mcp23017);
Wire.write(0x12);
Wire.write(255); // Reihe A
Wire.write(255); // Reihe B
Wire.endTransmission();
delay(1000);

Wire.beginTransmission(mcp23017);
Wire.write(0x12);
Wire.write(0); // Reihe A
Wire.write(0); // Reihe B
Wire.endTransmission();
delay(1000);
}

Die Zeilen in void setup() zwischen und dienen dazu, den MCP23017 einzurichten. Um die Ausgänge der Reihen ein- und auszuschalten, senden wir nacheinander ein Byte für jede Reihe, zuerst für die Reihe mit den Ausgängen GPA0 bis GPA7 und dann für GPB0 bis GPB7.

Um einzelne Pins einzurichten, müssen Sie sich die Reihe als Binärzahl vorstellen (siehe den Abschnitt »Schnellkurs in Binärzahlen« in Kapitel 6). Wollen Sie also beispielsweise die Pins 7 bis 4 aktivieren, müssen Sie die Binärzahl 11110000 (dezimal 240) senden. Dies geschieht in der Funktion Wire.write(), die Sie bei für die Reihe mit den Ausgängen GPA0 bis GPA7 und bei für GPB0 bis GPB7 sehen.

Hunderte von Geräten nutzen den I^2C-Bus zur Kommunikation. Da Sie jetzt Grundkenntnisse in der Verwendung dieses Busses haben, können Sie all diese Geräte zusammen mit Ihrem Arduino einsetzen.

Der SPI-Bus

Der SPI-Bus unterscheidet sich vom I^2C-Bus dadurch, dass darüber gleichzeitig Daten zu einem Gerät gesendet und von ihm empfangen werden können, wobei die Übertragungsgeschwindigkeit vom verwendeten Microcontroller abhängt und in beiden Richtungen unterschiedlich sein kann. Auch hier erfolgt die Kommunikation jedoch nach dem Master-Slave-Prinzip, wobei der Arduino als Master fungiert und festlegt, mit welchem Slave-Gerät er jeweils kommunizieren möchte.

Die Anschlüsse

SPI-Geräte verwenden zur Kommunikation mit dem Master die vier Pins MOSI (Master Out, Slave In), MISO (Master In, Slave Out), SCK (»Clock«, Takt) und SS oder CS (Slave Select oder Chip Select). Diese SPI-Pins werden wie in Abbildung 17–8 gezeigt mit dem Arduino verbunden.

Abb. 17–8 SPI-Pins auf einem Arduino Uno

Den allgemeinen Aufbau einer Verbindung zwischen einem Arduino und einem einzelnen SPI-Gerät sehen Sie in Abbildung 17–9. Die Arduino-Pins D11 bis D13 sind für SPI reserviert. Den SS-Anschluss können Sie jedoch auf jeden beliebigen anderen Digitalpin legen. (Häufig wird D10 verwendet, da dieser Kontakt gleich neben den SPI-Pins liegt.)

Abb. 17–9 Allgemeiner Aufbau einer Verbindung zwischen Arduino und SPI-Gerät

HINWEIS

Wie I^2C-Geräte müssen auch SPI-Geräte eine Betriebsspannung von 5 V verwenden oder zumindest eine Spannung von 5 V verkraften können, da der Arduino mit 5 V läuft. Lassen Sie sich das vor Gebrauch vom Händler oder Hersteller bestätigen.

Den SPI-Bus nutzen

Als Nächstes wollen wir uns ansehen, wie wir den SPI-Bus in einem Sketch nutzen können. Zuvor jedoch sehen wir uns die verwendeten Funktionen im Einzelnen an. Zu Beginn des Sketches müssen wir die Bibliothek SPI einschließen (die in der Arduino-IDE enthalten ist):

#include "SPI.h"

Danach wählen Sie den Pin aus, den Sie für den SS-Anschluss verwenden möchten, und legen ihn in void setup als digitalen Ausgang fest. Da wir in unserem Beispiel nur ein SPI-Gerät verwenden, nehmen wir D10. Bei den meisten SPI-Geräten ist der SS-Pin im aktiven Zustand LOW, weshalb wir D10 zu Anfang auf HIGH setzen:

pinMode(10, OUTPUT);
digitalWrite(10, HIGH);

Zum Aktivieren des SPI-Busses verwenden wir folgende Funktion:

SPI.begin();

Schließlich müssen wir in dem Sketch noch angeben, in welcher Bitreihenfolge die Daten gesendet und empfangen werden sollen. Bei manchen SPI-Geräten ist es erforderlich, dass die Daten mit dem signifikantesten Bit (Most Significant Bit, MSB) zuerst übertragen werden, bei anderen dagegen muss dieses Bit als letztes gesendet werden. (Mehr über die Bitreihenfolge erfahren Sie im Abschnitt »Schnellkurs in Binärzahlen« in Kapitel 6.) Daher verwenden wir in void setup hinter SPI.begin folgende Funktion:

SPI.setBitOrder(Bitreihenfolge);

Bitreihenfolge kann dabei die Werte MSBFIRST und MSBLAST annehmen.

Daten an ein SPI-Gerät senden

Um Daten an ein SPI-Gerät senden zu können, müssen Sie als Erstes den SS-Pin auf LOW setzen, um dem Gerät mitzuteilen, dass der Master (also der Arduino) mit ihm kommunizieren möchte. Danach übertragen Sie die Datenbytes mit der folgenden Zeile an das Gerät. Da dabei immer nur ein Byte gesendet wird, müssen Sie diese Anweisung so oft verwenden wie nötig:

SPI.transfer(Byte);

Wenn Sie mit der Übertragung fertig sind, setzen Sie den SS-Pin wieder auf HIGH, um dem Gerät mitzuteilen, dass der Arduino die Kommunikation beendet hat.

Für jedes angeschlossene SPI-Gerät benötigen Sie einen eigenen SS-Pin. Wenn Sie also zwei solcher Geräte verwenden, können Sie als dessen SS-Pin beispielsweise D9 verwenden und die Verbindung wie in Abbildung 17–10 herstellen.

Abb. 17–10 Anschluss zweier SPI-Geräte an den Arduino

Zur Kommunikation mit dem zweiten Slave-Gerät müssen Sie am Anfang und am Ende den SS-Pin D9 (statt D10) umschalten.

Die Verwendung des SPI-Busses wird in Projekt 56 anhand eines Digitalpotenziometers veranschaulicht.

Projekt Nr. 56: Ein Digitalpotenziometer verwenden

Ein Digitalpotenziometer hat die gleiche Funktion wie die Potenziometer, die wir uns in Kapitel 4 angesehen haben, verfügt aber über zwei Anschlüsse: einen für den »Schleifer« (die Ansteuerung) und den zweiten für den zurückgegebenen Strom. In diesem Projekt verwenden Sie ein Digitalpotenziometer, um den Widerstand über den Sketch zu regeln, anstatt selbst an einem Einstellknopf zu drehen. Wenn die Lautstärkeregelung an einem Audiogerät über Tasten statt über einen Drehknopf erfolgt, steckt meistens ein Digitalpotenziometer dahinter. Die Toleranz von Digitalpotenziometern ist sehr viel höher als die von Festwiderständen und kann sogar um 20 % liegen.

Für Projekt 56 verwenden wir das Digitalpotenziometer MCP4162 von Microchip Technology, das Sie in Abbildung 17–11 sehen. Es ist mit verschiedenen Widerstandswerten erhältlich, wobei wir die 10-kΩ-Version verwenden. Beziehen können Sie es bei Anbietern wie Newark (Bestell-Nr. 77M2766) und element14 (Bestell-Nr. 1840698). Der Widerstand kann in 255 Stufen zu je 40 Ω geregelt werden. Um eine Stufe auszuwählen, senden wir zwei Datenbytes, das Befehlsbyte (0) und das Wertbyte (0 bis 255). Der Speicher des MCP4162 ist nicht flüchtig. Wird die Stromversorgung nach einem Ausfall wiederhergestellt, ist der zuletzt ausgewählte Wert daher immer noch in Kraft.

Abb. 17–11 Das Digitalpotenziometer MCP4162 von Microchip Technology

Mit diesem Digitalpotenziometer werden wir die Helligkeit einer LED steuern.

Die Hardware

Für dieses Projekt brauchen Sie folgende Teile:

• ein Digitalpotenziometer MCP4162 von Microchip Technology

• einen 560-Ω-Widerstand

• eine LED

• eine Steckplatine

• Verbindungsdrähte

• Arduino und USB-Kabel

Der Schaltplan

Abbildung 17–12 zeigt den Schaltplan. Die Nummerierung der Pins am CP4162 beginnt oben links auf dem Gehäuse, wobei Pin 1 durch die runde Einkerbung links neben dem Microchip-Logo auf dem IC gekennzeichnet ist (siehe Abb. 17–11).

Abb. 17–12 Schaltplan für Projekt 11

Der Sketch

Geben Sie den folgenden Sketch ein und laden Sie ihn hoch:

// Projekt 56: Ein Digitalpotenziometer verwenden

#include "SPI.h"   // Erforderliche Bibliothek
int ss=10;         // Verwendet Digitalpin 10 als
// Slave-Select-Anschluss für SPI
int del=200;       // Sorgt für eine Verzögerung der einzelnen Schritte
// in der Helligkeitsregelung der LED

void setup()
{
SPI.begin();
pinMode(ss, OUTPUT);    // Wird für den SS-Pin verwendet
digitalWrite(ss, HIGH); // Der SS-Pin ist im aktiven Zustand LOW,
// weshalb wir ihn zu Anfang auf HIGH setzen
SPI.setBitOrder(MSBFIRST);
// Beim MCP4162 müssen die Daten mit dem MSB (signifikantestes Byte)
// zuerst gesendet werden
}

void setValue(int value)
{
digitalWrite(ss, LOW);
SPI.transfer(0);        // Sendet das Befehlsbyte
SPI.transfer(value);    // Sendet den Wert (0 to 255)
digitalWrite(ss, HIGH);
}

void loop()
{
for (int a=0; a<256; a++)
{
setValue(a);
delay(del);
}
for (int a=255; a>=0; a--)
{
setValue(a);
delay(del);
}
}

Gehen wir den Code im Einzelnen durch. Als Erstes richten wir den SPI-Bus bei und ein, dann legen wir bei die Bitreihenfolge passend für das MPC4162 fest. Um den Widerstand leichter regeln zu können, verwenden wir die selbst geschriebene Funktion bei , die den Wert für die gewünschte Widerstandsstufe (0 bis 255) annimmt und an das MCP4162 übergibt. Schließlich führt der Sketch zwei Schleifen durch, um das Digitalpotenziometer durch alle Stufen zu schalten – von null zum Maximum bei und dann wieder zurück zu null bei . Dadurch wird dafür gesorgt, dass die LED abwechselnd heller und dunkler leuchtet, solange der Sketch läuft.

Ausblick

In diesem Kapitel haben Sie zwei wichtige Kommunikationsmethoden des Arduino kennengelernt und ausprobiert. Damit können Sie den Arduino nun mit einer Vielfalt von Sensoren und anspruchsvollen Komponenten ausstatten und sind auch schon auf den Anschluss von Elementen vorbereitet, die erst noch auf dem Markt kommen. Eines der beliebtesten Bauteile ist zurzeit ein IC mit einer Echtzeituhr, mit dem Sie Ihre Projekte um eine Zeitüberwachung und -steuerung ergänzen können. Das werden wir uns in Kapitel 18 ansehen.

18

Echtzeituhren

In diesem Kapitel lernen Sie Folgendes:

• Einstellen und Abrufen von Datum und Uhrzeit mit einem Echtzeitmodul

• Weitere Möglichkeiten zum Anschluss von Geräten an den Arduino

• Bau einer Digitaluhr

• Bau einer RFID-Stechuhr

Ein Echtzeit-IC-Modul (Real-Time Clock, RTC) ist ein kleines Gerät zur Zeitmessung, das viele neue Möglichkeiten für Arduino-Projekte eröffnet. Wenn Sie das RTC-Modul auf die aktuelle Uhrzeit und das Datum eingestellt haben, gibt es auf Anfrage genaue Zeitdaten aus.

Auf dem Markt gibt es viele verschiedene RTC-ICs mit unterschiedlicher Genauigkeit. In diesem Kapitel verwenden wir das Maxim DS3232, das außer einer Pufferbatterie keine externen Elemente benötigt, unglaublich genau geht und in seiner Modulbauweise auch sehr robust ist. Sie können es auf einer Breakout-Platine von verschiedenen Anbietern bekommen, unter anderem von Freetronics (http://www.freetronics.com/rtc/). Dieses Modell sehen Sie in Abbildung 18–1.

Abb. 18–1 Echtzeit-IC-Modul

Der Anschluss des RTC-Moduls

Das RTC-Modul lässt sich ganz einfach an den Arduino anschließen, da es den I^2C-Bus nutzt (siehe Kapitel 17). Sie brauchen lediglich vier Kabel: Verbinden Sie GND und VCC mit dem GND- und dem 5-Volt-Anschluss auf dem Arduino und SDA und SCL mit den Arduino-Pins A4 und A5. Dank der Konstruktion des Moduls ist auf dem I^2C-Bus kein zusätzlicher Pullup-Widerstand erforderlich, es sei denn, das Modul und der Arduino sind über ein langes Kabel verbunden. In diesem Fall verlöten Sie die Felder an der Unterseite, die mit Pullups: SDA and SCL gekennzeichnet sind, um die eingebauten I^2C-Pullup-Widerstände zuzuschalten.

Um sich die Arbeit zu erleichtern, sollten Sie das Modul auf einem leeren ProtoShield montieren, sodass Sie es leichter mit anderer Hardware kombinieren können. Denken Sie daran, die Pufferbatterie anzuschließen, da die Zeitdaten sonst beim Ausschalten verloren gehen!

Projekt Nr. 57: Datum und Uhrzeit mit einem RTC-Modul einstellen und anzeigen

In diesem Projekt lernen Sie, wie Sie Datum und Uhrzeit auf dem RTCModul einstellen, anschließend abrufen und auf dem seriellen Monitor anzeigen. Solche Zeitangaben sind für viele Projekte nützlich, z. B. für die Aufzeichnung des Temperaturverlaufs oder für Wecker.

Die Hardware

Für dieses Projekt benötigen Sie folgende Teile:

• ein RTC-Modul Maxim DS3232

• Verbindungsdrähte

• Arduino und USB-Kabel

Der Sketch

Verbinden Sie das Modul wie zuvor beschrieben mit dem Arduino und geben Sie dann den folgenden Sketch ein, laden Sie ihn aber noch nicht hoch!

// Projekt 57: Datum und Uhrzeit mit einem RTC-Modul einstellen
// und anzeigen
#include "Wire.h"
#define DS3232 _ I2C _ ADDRESS 0x68

// Rechnet normale Dezimalzahlen in binärkodierte Dezimalzahlen um
byte decToBcd(byte val)
{
return( (val/10*16) + (val%10) );
}

// Rechnet binärkodierte Dezimalzahlen in Dezimalzahlen um
byte bcdToDec(byte val)
{
return( (val/16*10) + (val%16) );
}

void setup()
{
Wire.begin();
Serial.begin(9600);
// Legt die Startzeit in folgender Reihenfolge fest:
// Sekunden, Minuten, Stunden, Wochentag, Tag im Monat, Monat, Jahr
setDS3232time(0, 56, 23, 3, 30, 10, 12);
}

void setDS3232time(byte second, byte minute, byte hour,
byte dayOfWeek, byte
dayOfMonth, byte month, byte year)
{
// Legt Uhrzeit und Datum im DS3232 fest
Wire.beginTransmission(DS3232 _ I2C _ ADDRESS);
Wire.write(0); // Sorgt dafür, dass die nächste Eingabe
// mit dem Sekundenregister beginnt

Wire.write(decToBcd(second));       // Legt die Sekunden fest
Wire.write(decToBcd(minute));       // Legt die Minuten fest
Wire.write(decToBcd(hour));         // Legt die Stunden fest
Wire.write(decToBcd(dayOfWeek));    // Legt den Wochentag fest
// (1 = Sonntag, 7 = Samstag)
Wire.write(decToBcd(dayOfMonth));   // Legt den Tag im Monat fest
// (1 bis 31)
Wire.write(decToBcd(month));        // Legt den Monat fest
Wire.write(decToBcd(year));         // Legt das Jahr fest (0 bis 99)
Wire.endTransmission();
}

void readDS3232time(byte *second, byte *minute, byte *hour,
byte *dayOfWeek, byte *dayOfMonth,
byte *month, byte *year)
{
Wire.beginTransmission(DS3232 _ I2C _ ADDRESS);
Wire.write(0); // Stellt den DS3232-Registerzeiger auf 00h
Wire.endTransmission();
Wire.requestFrom(DS3232 _ I2C _ ADDRESS, 7);
// Fordert sieben Bytes an Daten vom DS3232 beginnend mit Register 00h an
*second = bcdToDec(Wire.read() & 0x7f);
*minute = bcdToDec(Wire.read());
*hour = bcdToDec(Wire.read() & 0x3f);
*dayOfWeek = bcdToDec(Wire.read());
*dayOfMonth = bcdToDec(Wire.read());
*month = bcdToDec(Wire.read());
*year = bcdToDec(Wire.read());
}

void displayTime()
{
byte second, minute, hour, dayOfWeek, dayOfMonth, month, year;

// Ruft Daten vom DS3232 ab
readDS3232time(&second, &minute, &hour, &dayOfWeek, &dayOfMonth,
&month, &year);
// Sendet sie an den seriellen Monitor
Serial.print(hour, DEC);
// Rechnet die Bytevariable zur Anzeige in eine Dezimalzahl um
Serial.print(":");
if (minute<10)
{
Serial.print("0");
}

Serial.print(minute, DEC);
Serial.print(":");
if (second<10)
{
Serial.print("0");
}
Serial.print(second, DEC);
Serial.print(" ");
Serial.print(dayOfMonth, DEC);
Serial.print("/");
Serial.print(month, DEC);
Serial.print("/");
Serial.print(year, DEC);
Serial.print(" Day of week: ");
switch(dayOfWeek){
case 1:
Serial.println("Sunday");
break;
case 2:
Serial.println("Monday");
break;
case 3:
Serial.println("Tuesday");
break;
case 4:
Serial.println("Wednesday");
break;
case 5:
Serial.println("Thursday");
break;
case 6:
Serial.println("Friday");
break;
case 7:
Serial.println("Saturday");
break;
}
}
void loop()
{
displayTime(); // Zeigt die Echtzeitdaten auf dem seriellen Monitor an,
delay(1000);   // und zwar jede Sekunde
}

Funktionsweise

Der Sketch sieht zwar kompliziert aus, ist aber gar nicht so schwer zu verstehen. Bei importieren wir die I^2C-Bibliothek und setzen die Busadresse des RTC-Moduls auf 0x68. Da das DS3232 Werte im binärkodierten Dezimalformat (BCD) speichert, verwenden wir bei zwei selbst geschriebene Funktionen, um Dezimal- in BCD-Zahlen umzurechnen und umgekehrt.

Bei übergeben wir in der Funktion setDS3232time die Informationen über Uhrzeit und Datum wie folgt an den RTC-IC:

setDS3232time(Sekunde, Minute, Stunde, Wochentag,
Tag im Monat, Monat, Jahr)

Die erforderlichen Daten geben Sie einfach in die entsprechenden Parameter ein. Beim Wochentags-Parameter handelt es sich um eine Zahl zwischen 1 und 7, die für Sonntag bis Samstag steht. Die Jahreszahl wird nur zweistellig angegeben, z. B. durch 13 für 2013. (Es wird stillschweigend angenommen, dass 20 vorausgeht.) Sie können entweder feste Werte eingeben (wie es in diesem Sketch geschieht) oder Bytevariablen, die die Werte für die Parameter enthalten.

Um die Zeit im RTC-Modul einzustellen, geben Sie daher bei die aktuelle Uhrzeit und das Datum in die Funktion setDS3232time ein. Laden Sie jetzt den Sketch hoch, kommentieren Sie die Funktion dann aus, indem Sie // voranstellen, und laden Sie den Sketch erneut hoch. Damit ist sichergestellt, dass die Zeit nicht bei jedem Start des Sketches wieder auf den ursprünglichen Wert zurückgestellt wird.

Die Funktion readDS3232time bei liest schließlich Datum und Uhrzeit vom RTC-Modul und fügt die Daten in Bytevariablen ein. Bei greifen wir darauf zurück, denn hier gibt die Funktion displayTime den Inhalt dieser Variablen aus, um die Informationen auf dem seriellen Monitor anzuzeigen.

Wenn Sie den seriellen Monitor öffnen, sehen Sie eine Anzeige wie in Abbildung 18–2.

Abb. 18–2 Das Ergebnis von Projekt 57

Den Sketch von Projekt 57 können Sie als Grundlage für andere Projekte mit Zeiterfassung nutzen. Die Funktionen decToBcd, bcdToDec, readDS3232time und setDS3232time lassen sich in anderen Projekten übernehmen. Das ist einer der Vorteile der Arduino-Plattform: Wenn Sie einmal ein nützliches Programm geschrieben haben, können Sie es später mit kleinen oder gar keinen Änderungen wiederverwenden!

Projekt Nr. 58: Eine einfache Digitaluhr bauen

In diesem Projekt verwenden wir die Funktionen aus Projekt 57, um Uhrzeit und Datum auf einem LCD-Zeichenmodul wie dem auszugeben, das wir für den GPS-Empfänger in Projekt 44 verwendet haben.

Die Hardware

Für dieses Projekt brauchen Sie folgende Teile:

• einen ProtoScrewShield oder ein ähnliches Produkt

• ein LCD-Modul oder LCD-Shield von Freetronics

• ein RTC-Modul (wie zuvor in diesem Kapitel verwendet)

• eine Steckplatine

• Verbindungsdrähte

• Arduino und USB-Kabel

Als Grundlage nehmen Sie den Aufbau von Projekt 57. Wenn Sie das RTCModul über Kabel mit dem Arduino verbunden haben, verwenden Sie hier stattdessen einen ProtoScrewShield. Stecken Sie dann den LCD-Shield darauf auf.

PROTOSCREWSHIELD

Im Laufe der Zeit werden Sie sich wahrscheinlich zu immer anspruchsvolleren Projekten aus Stapeln mehrerer Arduino-Shields und externen Geräten hocharbeiten, die alle über ein Sammelsurium an Kabeln miteinander verbunden sind. Eine hervorragende Möglichkeit, Ordnung ins Chaos zu bringen, bietet der ProtoScrewShield von WingShield Industries (http://wingshieldindustries.com/), den Sie in Abbildung 18–3 sehen.

Abb. 18–3 Der ProtoScrewShield im Einsatz

Dieser Shield besteht aus zwei Teilen, die auf die beiden Kontaktleisten am Arduino aufgesteckt werden. Anschließend können Sie weitere Shields aufsetzen, haben aber auch die Möglichkeit, Kabel von externen Geräten wie Sensoren oder Stellmotoren über die Schraubklemmen am ProtoScrewShield mit den E/A-Pins des Arduino zu verbinden.

Der Sketch

Geben Sie den folgenden Sketch ein, laden Sie ihn aber noch nicht hoch!

// Projekt 58: Eine einfache Digitaluhr bauen

#include "Wire.h"
#define DS3232 _ I2C _ ADDRESS 0x68

#include <LiquidCrystal.h>
LiquidCrystal lcd( 8, 9, 4, 5, 6, 7 );

// Rechnet normale Dezimalzahlen in binärkodierte Dezimalzahlen um
byte decToBcd(byte val)
{
return( (val/10*16) + (val%10) );
}

// Rechnet binärkodierte Dezimalzahlen in Dezimalzahlen um
byte bcdToDec(byte val)
{
return( (val/16*10) + (val%16) );
}

void setup()
{
Wire.begin();
lcd.begin(16, 2);
// Legt die Startzeit in folgender Reihenfolge fest:
// Sekunden, Minuten, Stunden, Wochentag, Tag im Monat, Monat, Jahr
// setDS3232time(0, 27, 0, 5, 15, 11, 12);
}

void setDS3232time(byte second, byte minute, byte hour, byte dayOfWeek,
byte dayOfMonth, byte month, byte year)
{
// Legt Uhrzeit und Datum im DS3232 fest
Wire.beginTransmission(DS3232 _ I2C _ ADDRESS);
Wire.write(0); // Sorgt dafür, dass die nächste Eingabe mit dem
// Sekundenregister beginnt
Wire.write(decToBcd(second));      // Legt die Sekunden fest
Wire.write(decToBcd(minute));      // Legt die Minuten fest
Wire.write(decToBcd(hour));        // Legt die Stunden fest
Wire.write(decToBcd(dayOfWeek));   // Legt den Wochentag fest
// (1 = Sonntag, 7 = Samstag)
Wire.write(decToBcd(dayOfMonth));  // Legt den Tag im Monat fest
// (1 bis 31)
Wire.write(decToBcd(month));       // Legt den Monat fest
Wire.write(decToBcd(year));        // Legt das Jahr fest (0 bis 99)
Wire.endTransmission();
}

void readDS3232time(byte *second, byte *minute, byte *hour,
byte *dayOfWeek, byte *dayOfMonth,
byte *month, byte *year)
{
Wire.beginTransmission(DS3232 _ I2C _ ADDRESS);
Wire.write(0); // Setzt den Registerzeiger des DS3232 auf 00h
Wire.endTransmission();
Wire.requestFrom(DS3232 _ I2C _ ADDRESS, 7);

// Fordert sieben Bytes an Daten vom DS3232 beginnend
// mit Register 00h an
*second = bcdToDec(Wire.read() & 0x7f);
*minute = bcdToDec(Wire.read());

*hour = bcdToDec(Wire.read() & 0x3f);
*dayOfWeek = bcdToDec(Wire.read());
*dayOfMonth = bcdToDec(Wire.read());
*month = bcdToDec(Wire.read());
*year = bcdToDec(Wire.read());
}

void displayTime()
{
byte second, minute, hour, dayOfWeek, dayOfMonth, month, year;

// Ruft Daten vom DS3232 ab
readDS3232time(&second, &minute, &hour, &dayOfWeek,
&dayOfMonth, &month, &year);
// Sendet sie an den LCD-Shield
lcd.clear();
lcd.setCursor(4,0);
lcd.print(hour, DEC);
lcd.print(":");
if (minute<10)
{
lcd.print("0");
}
lcd.print(minute, DEC);
lcd.print(":");
if (second<10)
{
lcd.print("0");
}
lcd.print(second, DEC);
lcd.setCursor(0,1);
switch(dayOfWeek){
case 1:
lcd.print("Sun");
break;
case 2:
lcd.print("Mon");
break;
case 3:
lcd.print("Tue");
break;
case 4:
lcd.print("Wed");
break;
case 5:
lcd.print("Thu");
break;

case 6:
lcd.print("Fri");
break;
case 7:
lcd.print("Sat");
break;
}
lcd.print(" ");
lcd.print(dayOfMonth, DEC);
lcd.print("/");
lcd.print(month, DEC);
lcd.print("/");
lcd.print(year, DEC);
}

void loop()
{
displayTime(); // Zeigt die Echtzeitdaten auf dem seriellen Monitor an,
delay(1000);   // und zwar jede Sekunde
}

Funktionsweise

Der Sketch läuft so ab wie der von Projekt 57, allerdings haben wir die Funktion displayTime so geändert, dass sie Datum und Uhrzeit nicht an den seriellen Monitor sendet, sondern an einen LCD-Bildschirm. Bei und haben wir die erforderlichen Zeilen für die Einrichtung der Flüssigkristallanzeige hinzugefügt. (Ausführlichere Informationen über LCD-Module finden Sie in Kapitel 7.) Denken Sie daran, dass Sie den Sketch zunächst mit Datums- und Uhrzeitangaben bei hochladen und dann erneut mit auskommentierter setDS3232time-Funktion. Abbildung 18–4 zeigt das Ergebnis.

Abb. 18–4 Anzeige von Projekt 58

Die Projekte 57 und 58 haben Ihnen ein Gefühl dafür vermittelt, wie Sie in Ihren Sketchen Daten vom RTC-IC abrufen und an ihn senden. Im Folgenden wollen wir das Gelernte in einem Projekt mit echtem Gebrauchswert umsetzen.

Projekt Nr. 59: Eine Stechuhr konstruieren

In diesem Projekt bauen wir eine Stechuhr. Dabei können Sie sehen, wie mehrere Arduino-Shields zusammenwirken und wie der ProtoScrewShield Ihnen hilft, elektronische Geräte anzuschließen, die nicht auf einem Shield montiert sind. Die Stechuhr kann von zwei Personen mit RFID-Karten oder -Etiketten genutzt werden, die diese beim Betreten oder Verlassen eines bestimmten Bereichs (z. B. Arbeitsplatz) vor das Lesegerät halten. Uhrzeit und Identifizierung der Karte werden zur späteren Analyse auf einer microSD-Karte gespeichert.

Die Protokollierung von Daten auf einer microSD-Karte haben wir in Kapitel 13 behandelt, RFID in Kapitel 16 und das RTC-Modul in diesem Kapitel. Jetzt kombinieren wir alle diese Einzelteile zu einem großen Ganzen!

Die Hardware

Für dieses Projekt brauchen Sie folgende Teile:

• ein RTC-Modul (wie zuvor in diesem Kapitel verwendet)

• ein LCD-Modul oder LCD-Shield von Freetronics

• ein microSD-Shield und eine microSD-Karte (siehe Kapitel 13)

• einen ProtoScrewShield oder ein ähnliches Produkt

• ein RFID-Lesemodul und zwei Transponder (siehe Kapitel 16)

• eine Steckplatine

• Verbindungsdrähte

• Arduino und USB-Kabel

Beginnen Sie die Montage, indem Sie auf den Arduino Uno den ProtoScrewShield aufsetzen, darauf den microSD-Shield und schließlich den LCD-Shield. Schließen Sie das RFID-Lesegerät nach der Anleitung in Kapitel 16 an und das RTC-Modul so, wie Sie es in diesem Kapitel gelernt haben. Den Gesamtaufbau sehen Sie in Abbildung 18–5.

Abb. 18–5 Aufbau der Stechuhr

Der Sketch

Geben Sie den folgenden Sketch ein und laden Sie ihn hoch. Denken Sie daran, dass Sie die Verbindung zwischen dem RX-Anschluss des RFIDLesegeräts und dem Arduino-Pin D0 vor dem Hochladen trennen und anschließend wiederherstellen müssen.

// Projekt 59: Eine Stechuhr konstruieren

#include "Wire.h" // Für das RTC-Modul
#define DS3232 _ I2C _ ADDRESS 0x68
#include "SD.h" // Für die SD-Karte

#include <LiquidCrystal.h>
LiquidCrystal lcd( 8, 9, 4, 5, 6, 7 );
int data1 = 0;

// Bestimmen Sie die Transpondernummern anhand von Listing 16.1
int Mary[14] = {
2, 52, 48, 48, 48, 56, 54, 67, 54, 54, 66, 54, 66, 3};
int John[14] = {
2, 52, 48, 48, 48, 56, 54, 66, 49, 52, 70, 51, 56, 3};
int newtag[14] = {
0,0,0,0,0,0,0,0,0,0,0,0,0,0}; // Dient zu Lesevergleichen

// Rechnet normale Dezimalzahlen in binärkodierte Dezimalzahlen um
byte decToBcd(byte val)
{
return( (val/10*16) + (val%10) );
}

// Rechnet binärkodierte Dezimalzahlen in Dezimalzahlen um
byte bcdToDec(byte val)
{
return( (val/16*10) + (val%16) );
}

void setDS3232time(byte second, byte minute, byte hour, byte dayOfWeek,
byte dayOfMonth, byte month, byte year)
{
// Legt Uhrzeit und Datum im DS3232 fest
Wire.beginTransmission(DS3232 _ I2C _ ADDRESS);
Wire.write(0); // Sorgt dafür, dass die nächste Eingabe
// mit dem Sekundenregister beginnt
Wire.write(decToBcd(second));      // Legt die Sekunden fest
Wire.write(decToBcd(minute));      // Legt die Minuten fest
Wire.write(decToBcd(hour));        // Legt die Stunden fest
Wire.write(decToBcd(dayOfWeek));   // Legt den Wochentag fest
// (1 = Sonntag, 7 = Samstag)
Wire.write(decToBcd(dayOfMonth));  // Legt den Tag im Monat fest
// (1 bis 31)
Wire.write(decToBcd(month));       // Legt den Monat fest
Wire.write(decToBcd(year));        // Legt das Jahr fest (0 bis 99)
Wire.endTransmission();
}

void readDS3232time(byte *second, byte *minute, byte *hour,
byte *dayOfWeek, byte *dayOfMonth,
byte *month, byte *year)
{
Wire.beginTransmission(DS3232 _ I2C _ ADDRESS);
Wire.write(0); // Setzt den Registerzeiger des DS3232 auf 00h
Wire.endTransmission();
Wire.requestFrom(DS3232 _ I2C _ ADDRESS, 7);

// Fordert sieben Bytes an Daten vom DS3232 beginnend
// mit Register 00h an
*second = bcdToDec(Wire.read() & 0x7f);
*minute = bcdToDec(Wire.read());
*hour = bcdToDec(Wire.read() & 0x3f);
*dayOfWeek = bcdToDec(Wire.read());
*dayOfMonth = bcdToDec(Wire.read());
*month = bcdToDec(Wire.read());
*year = bcdToDec(Wire.read());
}

void setup()
{
Serial.flush(); // Der serielle Puffer muss geleert werden
Serial.begin(9600);
Wire.begin();
lcd.begin(16, 2);
// Legt die Startzeit in folgender Reihenfolge fest:
// Sekunden, Minuten, Stunden, Wochentag, Tag im Monat, Monat, Jahr
// setDS3232time(0, 27, 0, 5, 15, 11, 12);
// Prüft, ob die microSD-Karte vorhanden und verwendbar ist
if (!SD.begin(8))
{
lcd.print("uSD card failure");
// Hält die Ausführung des Sketches an
return;
}
lcd.print("uSD card OK");
delay(1000);
lcd.clear();
}

// Vergleicht zwei Arrays und gibt true zurück, wenn sie identisch sind.
// Das ist ideal für den Vergleich von Transpondernummern geeignet.
boolean comparetag(int aa[14], int bb[14])
{
boolean ff=false;
int fg=0;
for (int cc=0; cc<14; cc++)
{
if (aa[cc]==bb[cc])
{
fg++;
}
}
if (fg==14)
{
ff=true; // Alle 14 Elemente im Array müssen übereinstimmen
}
return ff;
}

void wipeNewTag()
{
for (int i=0; i<=14; i++)
{
newtag[i]=0;
}
}

void loop()
{
byte second, minute, hour, dayOfWeek, dayOfMonth, month, year;
if (Serial.available() > 0) // Wenn ein Leseversuch unternommen wurde
{
// Liest die eingehende Nummer am seriellen RX-Eingang
delay(100);  // Räumt Zeit ein, damit die Daten vom seriellen
// Puffer eingehen können
for (int z=0; z<14; z++) // Liest den Rest der Transponderdaten
{
data1=Serial.read();
newtag[z]=data1;
}
Serial.flush(); // Verhindert mehrfache Lesevorgänge
// Ruft Daten vom DS3232 ab
readDS3232time(&second, &minute, &hour, &dayOfWeek,
&dayOfMonth, &month, &year);
}

// Führt je nach Transponder eine bestimmte Aktion durch
if (comparetag(newtag, Mary) == true)
{
lcd.print("Hello Mary ");
File dataFile = SD.open("DATA.TXT", FILE _ WRITE);
if (dataFile)
{
dataFile.print("Mary ");
dataFile.print(hour);
dataFile.print(":");
if (minute<10) { dataFile.print("0"); }
dataFile.print(minute);
dataFile.print(":");
if (second<10) { dataFile.print("0"); }
dataFile.print(second);
dataFile.print(" ");
dataFile.print(dayOfMonth);
dataFile.print("/");
dataFile.print(month);

dataFile.print("/");
dataFile.print(year);
dataFile.println();
dataFile.close();
}
delay(1000);
lcd.clear();
wipeNewTag();
}
if (comparetag(newtag, John)==true)
{
lcd.print("Hello John ");
File dataFile = SD.open("DATA.TXT", FILE _ WRITE);
if (dataFile)
{
dataFile.print("John ");
dataFile.print(hour);
dataFile.print(":");
if (minute<10) { dataFile.print("0"); }
dataFile.print(minute);
dataFile.print(":");
if (second<10) { dataFile.print("0"); }
dataFile.print(second);
dataFile.print(" ");
dataFile.print(dayOfMonth);
dataFile.print("/");
dataFile.print(month);
dataFile.print("/");
dataFile.print(year);
dataFile.println();
dataFile.close();
}
delay(1000);
lcd.clear();
wipeNewTag();
}
}

Funktionsweise

In diesem Sketch wartet das System zunächst darauf, dass ein RFID-Transponder vor das Lesegerät gehalten wird. Wird ein Transponder erkannt, so werden der Name seines Besitzers, die Uhrzeit und das Datum an eine Textdatei auf der microSD-Karte angehängt.

Bei befinden sich die für den I^2C-Bus und das RTC-Modul erforderlichen Funktionen, bei wird der microSD-Shield eingerichtet. Der Zustand der microSD-Karte wird bei geprüft und gemeldet. Bei wird die gerade gelesene Transpondernummer mit den gespeicherten Nummern für die registrierten Benutzer verglichen, in unserem Fall John und Mary. Bei einer Übereinstimmung werden Daten auf die microSD-Karte geschrieben. Um das System um Transponder für weitere Personen zu erweitern, müssen Sie lediglich bei die zugehörigen Transpondernummern unter den bereits vorhandenen ergänzen und dafür Vergleichsfunktionen wie die in Zeile hinzufügen.

Wenn Sie die aufgezeichneten Daten untersuchen wollen, kopieren Sie einfach die Datei Data.txt von der microSD-Karte. Sie können sie sich dann in einem Texteditor ansehen oder zu einer ausführlicheren Analyse in ein Tabellenkalkulationsprogramm importieren. Die Daten sind in einem lesefreundlichen Format gegliedert, wie Sie in Abbildung 18–6 sehen.

Abb. 18–6 Von Projekt 59 ausgegebene Beispieldaten

Ausblick

In diesem Kapitel haben Sie gesehen, wie Sie mithilfe des RTC-ICs mit Datums- und Uhrzeitwerten arbeiten können. Das in Projekt 59 beschriebene RFID-System stellt ein Grundgerüst dar, mit dem Sie eine eigene Zeiterfassungsanlage bauen oder sogar kontrollieren können, wann Ihre Kinder nach Hause kommen. In den beiden letzten Kapiteln beschäftigen wir uns mit Projekten, in denen wir den Arduino zur Kommunikation über das Internet und das Mobilfunknetz verwenden.

19

Das Internet

In diesem Kapitel lernen Sie Folgendes:

• Bau eines Webservers zur Anzeige von Daten auf einer Webseite

• Senden von Tweets mit dem Arduino

• Fernsteuern der digitalen Ausgänge des Arduino über einen Webbrowser

In diesem Kapitel lernen Sie, wie Sie mit dem Arduino über das Internet eine Verbindung zur Außenwelt herstellen. Damit können Sie Daten vom Arduino senden und umgekehrt den Arduino auch von einem Webbrowser aus fernsteuern.

Erforderliches Material

Als Grundlage für sämtliche Internetprojekte sind einige bestimmte Bauteile, Kabel und Daten erforderlich.

Fangen wir mit der Hardware an. Sie benötigen einen Ethernet-Shield mit dem Controllerchip W5100. Dabei haben Sie zwei Möglichkeiten: Sie können den Ethernet-Shield der Marke Arduino verwenden, den Sie in Abbildung 19–1 sehen, aber auch gleich eine Arduino-Uno-kompatible Platine mit eingebauter Ethernet-Hardware, z. B. den Freetronics EtherTen aus Abbildung 19–2. Letzterer ist eine gute Wahl, wenn Sie neue Projekte angehen oder Geld und Bauraum sparen wollen. Wie Sie sehen, verfügt der EtherTen über Anschlüsse für Arduino-Shields, einen USB-Port, eine Ethernet-Buchse und einen Anschluss für microSD-Karten.

Abb. 19–1 Der Arduino-Ethernet-Shield

Abb. 19–2 Der EtherTen von Freetronics

Daneben brauchen Sie in jedem Fall ein standardmäßiges 10/100-Netzwerkkabel der Kategorie CAT 5, CAT 5E oder CAT 6, um den Ethernet-Shield an Ihren Netzwerkrouter oder Ihr Internetmodem anzuschließen.

Des Weiteren benötigen Sie noch die IP-Adresse des Router-Gateways für Ihr Netzwerk oder des Modems sowie die Ihres Computers. Beide Adressen weisen eine Form wie 192.168.0.1 auf.

Wenn Sie von außerhalb Ihres Heimnetzwerks oder LANs mit Ihrem Arduino kommunizieren möchten, benötigen Sie außerdem noch eine statische, öffentliche IP-Adresse. Dabei handelt es sich um eine feste Adresse, die Ihrem physischen Internetanschluss von Ihrem Internetprovider zugewiesen wird. Wahrscheinlich hat Ihre Internetverbindung noch keine statische IP-Adresse. Wenden Sie sich an Ihren Provider, um sich eine zuweisen zu lassen. Wenn er das nicht kann oder zu viel Geld dafür haben will, können Sie eine solche Adresse auch über einen Drittanbieter wie No-IP (http://www.noip.com/) oder Dyn (http://dyn.com/dns/) beziehen. Diese Anbieter versehen Sie mit einer festen Webadresse und leiten Benutzer zu Ihrer aktuellen IP-Adresse um.

Die Hardware werden wir mit dem folgenden einfachen Projekt auf die Probe stellen.

Projekt Nr. 60: Eine Fernüberwachungsstation konstruieren

In verschiedenen Projekten vorhergehender Kapitel haben wir Daten von Sensoren abgerufen, um Temperaturen zu messen. Jetzt wollen wir solche Messdaten auf einer einfachen Webseite ausgeben, sodass wir von praktisch jedem webfähigen Gerät aus darauf zugreifen können. Als Grundlage für eine Fernüberwachungsanlage zeigen wir in diesem Projekt den Wert der analogen Eingangspins und den Status der digitalen Eingangspins 0 bis 9 auf der Webseite an.

Dieses Grundgerüst können Sie um Sensoren für Temperatur, Licht usw. mit analogen und digitalen Ausgängen erweitern, um ihre Messwerte auf einer Webseite auszugeben.

Die Hardware

Für dieses Projekt brauchen Sie folgende Hardware:

• ein USB-Kabel

• ein Netzwerkkabel

• einen Arduino Uno mit Ethernet-Shield oder einem Freetronics EtherTen

Der Sketch

Geben Sie den folgenden Sketch ein, aber laden Sie ihn noch nicht hoch!

/* Projekt 60: Eine Fernüberwachungsstation konstruieren
Erstellt am 18. Dezember 2009 von David A. Mellis, geändert am 9. April
2012 von Tom Igoe und am 20. März 2013 von John Boxall
*/

#include <SPI.h>
#include <Ethernet.h>

IPAddress ip(xxx,xxx,xxx,xxx); // Ersetzen Sie dies durch
// die tatsächliche IP-Adresse
// für Ihr Projekt
byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };
EthernetServer server(80);

void setup()
{
// Startet die Ethernet-Verbindung und den Server
Ethernet.begin(mac, ip);
server.begin();
for (int z=0; z<10; z++)
{
pinMode(z, INPUT); // Legt die Digitalpins 0 bis 9
// als Eingänge fest
}
}

void loop()
{
// Lauscht auf eingehende Clients (eingehende Anforderungen
// für Webseitenverbindungen)
EthernetClient client = server.available();
if (client) {
// Eine HTTP-Anforderung endet mit einer Leerzeile
boolean currentLineIsBlank = true;
while (client.connected()) {
if (client.available()) {
char c = client.read();
if (c == '\n' && currentLineIsBlank) {
client.println("HTTP/1.1 200 OK");
client.println("Content-Type: text/html");
client.println("Connection: close");
client.println();
client.println("<!DOCTYPE HTML>");
client.println("<html>");

// Fügt ein Meta-Tag zur Aktualisierung hinzu,
// damit der Browser alle 5 s Informationen abruft
client.println("<meta http-equiv=\"refresh\"
content=\"5\">");
// Gibt den Wert der Analogpins auf der Webseite aus
for (int analogChannel = 0; analogChannel < 6;
analogChannel++) {
int sensorReading = analogRead(analogChannel);
client.print("analog input ");
client.print(analogChannel);
client.print(" is ");
client.print(sensorReading);
client.println("<br />");
}
// Gibt den Wert der Digitalpins 0 bis 9
// auf der Webseite aus
for (int digitalChannel = 0; digitalChannel < 10;
digitalChannel++)
{
boolean pinStatus = digitalRead(digitalChannel);
client.print("digital pin ");
client.print(digitalChannel);
client.print(" is ");
client.print(pinStatus);
client.println("<br />");
}
client.println("</html>");
break;
}
if (c == '\n') {
// Beginnt eine neue Zeile
currentLineIsBlank = true;
}
else if (c != '\r') {
// In der aktuellen Zeile befindet sich ein Zeichen
currentLineIsBlank = false;
}
}
}
// Räumt dem Webbrowser Zeit zum Datenempfang ein
delay(1);
// Schließt die Verbindung
client.stop();
}
}

Die Einzelheiten dieses Sketches sehen wir uns weiter hinten noch genauer an. Zunächst jedoch müssen Sie, bevor Sie den Sketch hochladen können, eine IP-Adresse für den Ethernet-Shield eingeben, sodass er in Ihrem lokalen Netzwerk oder über Ihr Modem gefunden werden kann. Die ersten drei Teile der Adresse bestimmten Sie anhand der IP-Adresse Ihres Routers. Wenn sie beispielsweise 192.168.0.1 lautet, ändern Sie die letzte Stelle in einen beliebigen Wert zwischen 1 und 254, der noch nicht von anderen Geräten in Ihrem Netzwerk verwendet wird. Geben Sie diese Adresse nun bei wie folgt in den Sketch ein:

IPAddress ip(192, 168, 0, 69); // IP-Adresse des Ethernet-Shields

Nach dieser Änderung speichern Sie den Sketch und laden ihn hoch. Stecken Sie nun den Ethernet-Shield auf den Arduino auf (falls nötig), verbinden Sie den Router oder das Modem über das Netzwerkkabel mit dem Ethernet-Anschluss und schalten Sie den Arduino ein.

Warten Sie etwa 20 Sekunden lang und geben Sie dann auf einem beliebigen Gerät oder Computer im Netzwerk die IP-Adresse von in den Webbrowser ein. Wenn Sie daraufhin eine Ausgabe wie in Abbildung 19–3 sehen, funktioniert Ihre Grundlage für eine Überwachungsstation korrekt.

Abb. 19–3 Die Werte der von der Station überwachten Pins werden als Webseite im Webbrowser eines mit dem Internet verbundenen Geräts angezeigt.

Fehlersuche

Wenn das Projekt nicht funktioniert, probieren Sie Folgendes aus:

• Stellen Sie sicher, dass Sie die IP-Adresse bei richtig in den Sketch eingegeben haben.

• Überprüfen Sie, ob der Sketch korrekt ist und auf den Arduino hochgeladen wurde.

• Überprüfen Sie sorgfältig das lokale Netzwerk. Probieren Sie aus, ob Sie mit einem der daran angeschlossenen Computer ins Internet gelangen können. Wenn ja, schauen Sie nach, ob der Arduino mit Strom versorgt wird und mit dem Router oder Modem verbunden ist.

• Wenn Sie die Projektwebseite von einem Smartphone aus öffnen, müssen Sie darauf achten, dass Sie auf Ihr lokales WLAN zugreifen und nicht auf das Funknetzwerk des Telefonanbieters.

• Wenn der Arduino mit Strom versorgt wird und der Ethernet-Shield über das Ethernet-Kabel mit dem Router oder Modem verbunden ist, aber keine der LEDs auf dem Shield leuchtet, versuchen Sie es mit einem anderen Verbindungskabel.

Funktionsweise

Wenn der Sketch funktioniert, können wir uns seine wichtigsten Teile jetzt genauer ansehen. Der Code vom Anfang bis zu ist nötig, um die erforderlichen Bibliotheken zu laden und um die Ethernet-Hardware zu aktivieren und in void setup zu starten. Die client.print-Anweisungen vor dienen dazu, die Webseite einzurichten, sodass sie vom Browser gelesen werden kann. Ab werden weitere client.print- und client.println-Funktionen dazu verwendet, Informationen auf der Webseite wie auf dem seriellen Monitor auszugeben. Der folgende Code beispielsweise zeigt die ersten sechs Zeilen der Webseite an, die Sie in Abbildung 19–3 sehen:

client.print("analog input ");
client.print(analogChannel);
client.print(" is ");
client.print(sensorReading);

Bei sehen Sie in dem Sketch ein Beispiel dafür, wie Text und Inhalt einer Variable auf die Webseite geschrieben werden. Solange Sie den Arbeitsspeicher des Arduino nicht überlasten, können Sie HTML verwenden, um das Aussehen der angezeigten Webseite zu steuern. Das heißt, Sie können so viel HTML-Code verwenden, wie die maximale Sketchgröße zulässt, die wiederum vom verfügbaren Arbeitsspeicher des Arduino abhängt. (Die Größen für die einzelnen Platinenmodelle sind in Tabelle 11–2 aufgeführt.)

Beachten Sie auch die MAC-Adresse, mit der einzelne Hardwaregeräte in einem Netzwerk identifiziert werden können. Jedes Netzwerkgerät verfügt über eine eindeutige MAC-Adresse, die Sie über die Hexadezimalwerte bei ändern können. Wenn Sie in einem Netzwerk mehrere Arduino-Projekte verwenden, müssen Sie an dieser Stelle für jedes Gerät eine eigene MACAdresse eingeben.

Wenn Sie die Webseite auf einem Gerät ansehen wollen, das sich nicht in Ihrem lokalen Netzwerk befindet, z. B. auf Tablet-Computern oder Smartphones mit Mobilfunkverbindung, müssen Sie in Ihren Netzwerkrouter oder Modem die Technik der Portweiterleitung für die öffentliche IP-Adresse einsetzen, die Sie von einer Organisation wie No-IP (http://www.no-ip.com/) oder Dyn (http://dyn.com/dns/) bezogen haben. Wie das abläuft, hängt stark vom Hersteller und Modell des Routers ab. Um weitere Informationen darüber zu erhalten, können Sie im Internet nach »Router«, »Portweiterleitung« oder »Port Forwarding« suchen oder eine Website mit einer Anleitung wie http://www.wikihow.com/Port-Forward/ aufsuchen.

Nachdem wir nun wissen, wie wir Text und Variablen an eine Webseite senden können, wollen wir den Arduino benutzen, um Tweets zu verschicken.

Projekt Nr. 61: Einen Arduino-Tweeter konstruieren

In diesem Projekt lernen Sie, wie Sie mit dem Arduino Tweets an Twitter senden. Damit können Sie mit jedem Gerät, das auf Twitter zugreifen kann, alle Arten von Informationen abrufen, die sich mit einem Sketch bereitstellen lassen. Wenn Sie beispielsweise im Urlaub stündlich die Temperaturwerte bei sich zu Hause in Erfahrung bringen oder benachrichtigt werden möchten, wenn die Kinder nach Hause kommen, bietet diese Vorgehensweise eine kostengünstige Lösung.

Da Ihr Arduino sein eigenes Twitter-Konto braucht, müssen Sie zur Vorbereitung Folgendes tun:

1. Suchen Sie http://twitter.com/ auf und legen Sie ein Twitter-Konto für den Arduino an. Merken Sie sich Benutzername und Passwort.

2. Besorgen Sie sich von einem Drittanbieter wie http://arduino-tweet.appspot.com/ ein »Token«, das als Brücke zwischen dem Arduino und dem Dienst Twitter fungiert. Dazu müssen Sie auf der angegebenen Website nur Schritt 1 ausführen.

3. Kopieren Sie das Token (sowie die Angaben zum neuen Twitter-Konto Ihres Arduino) in eine Textdatei auf Ihrem Computer.

4. Laden Sie die Arduino-Bibliothek für Twitter von http://playground.arduino.cc/Code/TwitterLibrary/ herunter und installieren Sie sie.

Die Hardware

Für dieses Projekt brauchen Sie Folgendes:

• ein USB-Kabel

• ein Netzwerkkabel

• einen Arduino Uno mit Ethernet-Shield oder einem Freetronics EtherTen

Der Sketch

Geben Sie den folgenden Sketch ein, aber laden Sie ihn noch nicht hoch!

// Projekt 61: Einen Arduino-Tweeter konstruieren
#include <SPI.h>
#include <Ethernet.h>
#include <Twitter.h>

byte ip[] = { xxx,xxx,xxx,xxx };
byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };
Twitter twitter("token");

char msg[] = "I'm alive!"; // Die als Tweet zu sendende Nachricht

void setup()
{
delay(30000);
Ethernet.begin(mac, ip);
Serial.begin(9600);
}

void loop()
{
Serial.println("connecting ...");
if (twitter.post(msg)) {
int status = twitter.wait();
if (status == 200) {
Serial.println("OK.");
} else {
Serial.print("failed : code ");
Serial.println(status);
}
} else {
Serial.println("connection failed.");
}
do {} while (1);
}

Wie bei Projekt 60 müssen Sie auch hier die IP-Adresse bei eingeben und ggf. bei die MAC-Adresse ändern. Fügen Sie dann zwischen den Anführungszeichen bei das Twitter-Token ein und schließlich den gewünschten Text des Tweets bei . Laden Sie jetzt den Sketch hoch und verbinden Sie Ihre Hardware mit dem Netzwerk. (Vergessen Sie nicht, von Ihrem eigenen Konto aus dem Twitter-Konto des Arduino zu folgen!) Wenn Sie nach etwa einer Minute die Twitter-Seite aufsuchen, sehen Sie dort wie in Abbildung 19–4 die Nachricht.

Abb. 19–4 Der Tweet vom Arduino

Denken Sie daran, dass Sie mit einem Arduino-Tweeter immer nur einen Tweet pro Minute senden können und dass jede Nachricht einzigartig sein muss. (Das sind die Regeln von Twitter.) Wenn Sie einen Tweet senden, antwortet Twitter mit einem Statuscode. Mit dem Code bei empfängt der Sketch diesen Code und zeigt ihn im seriellen Monitor an. Ein Beispiel dafür sehen Sie in Abbildung 19–5. Der dort gezeigte Code »403« bedeutet, dass entweder Ihr Token ungültig ist oder Sie die Tweets zu schnell hintereinander senden. (Eine vollständige Liste von Twitter-Fehlercodes finden Sie auf http://dev.twitter.com/docs/error-codes-responses/.)

Abb. 19–5 Fehlermeldung bei zu schneller Abfolge von gesendeten Tweets

Den Arduino vom Web aus steuern

Es gibt verschiedene Möglichkeiten, um den Arduino von einem Webbrowser aus zu steuern. Nachdem ich mich umgesehen habe, bin ich auf eine zuverlässige, sichere und kostenlose Methode gestoßen: Teleduino.

Teleduino ist ein gebührenfreier Dienst, den der neuseeländische Arduino-Fan Nathan Kennedy gegründet hat. Es handelt sich dabei um ein leistungsstarkes Instrument für die Interaktion mit dem Arduino über das Internet. Dafür sind keine besonderen Sketche und auch keine Anpassungen erforderlich. Geben Sie einfach einen bestimmten URL in den Webbrowser ein, um den Arduino zu steuern. Damit können Sie u. a. digitale Ausgangspins oder Stellmotoren regeln und I^2C-Befehle senden, und es kommen ständig neue Funktionen hinzu. In Projekt 62 lernen Sie, wie Sie Teleduino einrichten, um die digitalen Ausgangspins von einem webfähigen Gerät aus fernzusteuern.

HINWEIS

Teleduino funktioniert nur für den Arduino Uno und kompatible Platinen mit dem Microcontroller ATmega328.

Projekt Nr. 62: Eine Fernsteuerung für den Arduino einrichten

Bevor Sie mit einem ersten Teleduino-Projekt loslegen können, müssen Sie sich erst bei Teleduino registrieren und einen eindeutigen Schlüssel zur Identifizierung Ihres Arduino anfordern. Suchen Sie dazu https://www.teleduino.org/tools/request-key/ auf und geben Sie die verlangten Informationen ein. Anschließend sollten Sie eine E-Mail mit dem Schlüssel erhalten, der eine Form wie beispielsweise 187654321Z9AEFF952ABCDEF8534B2BBF aufweist.

Wandeln Sie den Schlüssel anschließend in eine Array-Variable um. Das können Sie auf https://www.teleduino.org/tools/arduino-sketch-key/ tun. Wenn Sie dort den Schlüssel eingeben, wird auf der Seite wie in Abbildung 19–6 das Array angezeigt.

Abb. 19–6 Ein Teleduino-Schlüssel in Array-Form

Jeder Schlüssel ist eindeutig einem einzelnen Arduino zugewiesen. Wenn Sie mehrere Teleduino-Projekte gleichzeitig ausführen wollen, können Sie jedoch jederzeit weitere Schlüssel abrufen.

Die Hardware

Für das Projekt benötigen Sie folgende Teile:

• einen 560-Ω-Widerstand

• eine LED beliebiger Farbe

• eine Steckplatine

• Verbindungsdrähte

• ein USB-Kabel

• ein Netzwerkkabel

• einen Arduino Uno mit Ethernet-Shield oder einem Freetronics EtherTen

Bauen Sie die Teile zusammen und schließen Sie die LED dabei wie in Abbildung 19–7 gezeigt an Digitalpin 8 an.

Abb. 19–7 Schaltplan für Projekt 62

Der Sketch

Für Teleduino-Projekte wird nur ein Sketch verwendet, der sich in der Teleduino-Bibliothek befindet. Sie können ihn wie folgt abrufen:

1. Laden Sie die Teleduino-Bibliothek von https://www.teleduino.org/downloads/ herunter und installieren Sie sie.

2. Starten Sie die Arduino-IDE neu und wählen Sie File > Examples > Teleduino328 > TeleduinoEthernetClientProxy.

3. Jetzt wird der Teleduino-Sketch angezeigt. Bevor Sie ihn auf Ihren Arduino hochladen, müssen Sie in Zeile 36 den voreingestellten Schlüssel durch Ihr Schlüsselarray ersetzen. Speichern Sie den Sketch und laden Sie ihn hoch.

Schließen Sie Ihre Hardware an das Netzwerk an und beobachten Sie die LED. Nach etwa einer Minute sollte sie blinken und dann Ruhe geben. An der Anzahl der Blinkvorgänge können Sie mithilfe von Tabelle 19–1 den Status des Teleduino-Dienstes ablesen.

Anzahl Blinkvorgänge

Bedeutung

1

Initialisierung

2

Netzwerkverbindung wird gestartet

3

Verbindung zum Teleduino-Server wird hergestellt

4

Authentifizierung erfolgreich

5

Sitzung ist bereits vorhanden

6

Ungültiger oder nicht autorisierter Schlüssel

10

Verbindung abgebrochen

Tab. 19–1 Blinkcodes für den Teleduino-Status

Blinkt die LED fünfmal, ist bereits ein anderer Arduino mit Ihrem Schlüssel programmiert worden und mit dem Teleduino-Server verbunden. Bei zehnmaligem Blinken sollten Sie Ihre Hardware und die Internetverbindung prüfen. Wenn die Verbindung hergestellt ist, blinkt die LED ungefähr alle fünf Sekunden. Da die Leuchtdiode über Digitalpin 8 gesteuert wird, können Sie diesen Pin während der Verwendung von Teleduino nicht für andere Zwecke nutzen.

Den Arduino fernsteuern

Zur Fernsteuerung Ihres Arduino über Teleduino können Sie jedes beliebige Gerät verwenden, das über einen Webbrowser verfügt. Die Steuerbefehle geben Sie in Form des URL nach dem Muster http://us01.proxy.teleduino.org/api/1.0/328.php?k=<IHRSCHLÜSSEL>&r=setDigitalOutput&pin=<X>&output=<S> ein.

In diesem URL müssen Sie drei Parameter ändern. Ersetzen Sie als Erstes <IHRSCHLÜSSEL> durch den langen alphanumerischen Schlüssel, den Sie von Teleduino erhalten haben. Anstelle von <X> geben Sie dann die Nummer des Digitalpins an, den Sie steuern möchten, und anstelle von <S> den Wert 0 für LOW oder 1 für HIGH. Wenn Sie beispielsweise Digitalpin 7 auf HIGH setzen wollen, verwenden Sie den URL http://us01.proxy.teleduino.org/api/1.0/328.php?k=<YOURKEY>&r=setDigitalOutput&pin=7&output=1.

Wenn der Befehl erfolgreich ausgeführt wurde, wird eine Meldung wie die folgende im Webbrowser angezeigt:

{"status":200,"message":"OK","response"
{"result":0,"time":0.22814512252808,"values":[]}}

Schlägt der Befehl fehl, sehen Sie eine Fehlermeldung:

{"status":403,"message":"Key is offline or invalid.","response":[]}

Durch Änderung des URL können Sie also Befehle senden, mit denen die Digitalpins auf HIGH oder LOW geschaltet werden. Nachdem Sie die benötigten URLs für Ihr Projekt erstellt haben, sollten Sie in Ihrem Browser Lesezeichen dafür anlegen oder eine lokale Webseite erstellen, auf denen die Links als Schaltflächen stehen. Beispielsweise können Sie ein Lesezeichen für den URL einrichten, der Digitalpin 7 auf HIGH setzt, und ein anderes für den URL, der ihn wieder auf LOW schaltet.

In einigen Fällen ist der Status der Arduino-Ausgänge von entscheidender Bedeutung. Als Sicherheitsvorkehrung für den Fall, dass sich der Arduino aufgrund eines Stromausfalls oder einer anderen Störung zurücksetzt, sollten Sie einen Standardstatus für die Digitalpins festlegen. Wenn Sie den Teleduino-Dienst nutzen, besuchen Sie dazu https://www.teleduino.org/tools/manage-presets/. Nachdem Sie Ihren eindeutigen Schlüssel eingegeben haben, werden Ihnen wie in Abbildung 19–8 Optionen angezeigt, um Modus und Wert für die Digitalpins auszuwählen.

Abb. 19–8 Webseite zur Einrichtung eines Standardstatus für die Pins

Ausblick

Sie können jetzt nicht nur den Arduino über das Internet überwachen und mit ihm Tweets an Twitter senden, sondern Ihre Arduino-Projekte auch über das Internet steuern – und das alles ohne komplizierte Sketche schreiben zu müssen, ohne umfassende Kenntnisse über Netzwerke mitzubringen oder hohe monatliche Gebühren zahlen zu müssen. Mit der Fernsteuerung über das Web können Sie von überall aus auf den Arduino zugreifen und die Reichweite für die Datenübertragung erhöhen. Die drei Projekte in diesem Kapitel bilden eine Grundlage, auf der Sie aufbauen können, um eigene Fernsteuerungsprojekte zu gestalten.

Im nächsten Kapitel – dem letzten in diesem Buch – lernen Sie, wie Sie mit dem Arduino Befehle über eine Mobilfunkverbindung senden und empfangen.

20

Mobilfunkkommunikation

In diesem Kapitel lernen Sie Folgendes:

• Automatisches Wählen einer Telefonnummer bei Eintritt eines Ereignisses

• Senden von Textnachrichten an ein Mobiltelefon

• Steuern von Geräten, die an den Arduino angeschlossen sind, mithilfe von Textnachrichten von einem Mobiltelefon

Sie können Ihre Arduino-Projekte mit einem Mobilfunknetz verknüpfen, um eine einfache Kommunikation zwischen dem Arduino und einem Mobiltelefon oder einem Festnetzanschluss zu ermöglichen. Mit ein wenig Vorstellungskraft werden Ihnen sicherlich viele Verwendungszwecke für eine solche Art der Kommunikation einfallen. In den Projekten dieses Kapitels stellen wir einige Möglichkeiten vor.

Lesen Sie dieses Kapitel erst gründlich durch, bevor Sie irgendwelche Hardware kaufen, denn der Erfolg hängt vom Mobilfunknetz ab. Es muss folgende Eigenschaften aufweisen:

• Betrieb mit GSM 850 MHz, GSM 900 MHz, DCS 1800 MHz oder PCS 1900 MHz

• Die Verwendung von Geräten, die nicht vom Netzbetreiber bereitgestellt werden, muss zugelassen sein.

Mobilfunknetze in der EU, in Australien und Neuseeland erfüllen diese Bedingungen normalerweise. In den USA und Kanada kann der Netzbetreiber diese Voraussetzungen schaffen. Klären Sie das, bevor Sie Hardware kaufen.

Als Vorsichtsmaßnahme für den Fall, dass aufgrund eines Fehlers in Ihrem Sketch mehrere SMS gesendet werden, sollten Sie für diese Projekte einen Pauschaltarif oder eine Variante wählen, die viele kostenlose Textnachrichten einschließt. Sorgen Sie auch dafür, dass zur Verwendung der SIM-Karte keine PIN eingegeben werden muss. Das sollte bei einem normalen Handy ganz einfach möglich sein, indem Sie die SIM-Karte einlegen und die entsprechende Einstellung dann im Sicherheitsmenü ändern.

Die Hardware

Aufgrund von Hardwareeinschränkungen funktionieren die Projekte in diesem Kapitel nur mit einem Arduino Uno oder einer kompatiblen Platine (also nicht mit einem Arduino Mega). Alle Projekte weisen denselben Hardwareaufbau auf, weshalb wir uns als Erstes darum kümmern.

Für die Projekte in diesem Kapitel benötigen Sie besondere Teile, allen voran einen GSM-Shield SM5100 mit Antenne (siehe Abb. 20–1). Diesen Shield bekommen Sie bei SparkFun und den Partnerhändlern. Suchen Sie nach dem Shield mit der Bestell-Nr. CEL-09607, dem Aufsteck-Anschlusssatz PRT-10007 und der Antenne CEL-00675.

Abb. 20–1 GSM-Shield mit angeschlossener Antenne

Außerdem brauchen Sie einen Power-Shield und eine Stromversorgung. Der GSM-Shield zieht bis zu 2 A, was mehr ist, als der Arduino liefern kann. Wenn Sie ihn ohne externe Stromversorgung einsetzen, können Sie dadurch den Arduino beschädigen. Einen Arduino-kompatiblen Power-Shield erhalten Sie unter der Bestell-Nr. DFR0105 bei DFRobot unter http://www.dfrobot.com/ (siehe Abb. 20–2).

Abb. 20–2 Der Power-Shield von DFRobot

Schließlich benötigen Sie noch eine externe Stromversorgung. Dazu können Sie einen Gleichstromadapter oder ein Netzteil zum Anschluss an die Wandsteckdose verwenden, aber auch eine wiederaufladbare 7,2-Volt-Batterie, einen Solarakku, eine 12-Volt-Batterie oder Ähnliches. Wichtig ist, dass die Stromquelle eine Spannung von 35 V Gleichstrom nicht überschreitet und eine Stromstärke von 2 A liefern kann.

Den Power-Shield vorbereiten

Bereiten Sie den Power-Shield vor, indem Sie die Ausgangsspannung einstellen, bevor Sie irgendwelche andere Teile anbringen (das ist sehr wichtig!). Dazu entfernen Sie die Jumper über den Kontakten oben rechts und unten rechts (rechts in Abb. 20–2 eingekreist) und setzen dann zwei Steckbrücken horizontal über die PWRIN-Kontaktpaare unten links (unten in Abb. 20–2 eingekreist).

Jetzt verbinden Sie die externe Stromquelle mit der PWRIN-Klemmenleiste in der unteren linken Ecke des Shields. Achten Sie darauf, dass Sie Plus- und Minuspol richtig anschließen. Schalten Sie dann den Strom ein und messen Sie mit einem Multimeter die Spannung an der PWROUTKlemmenleiste oben links am Shield. Regeln Sie das Potenziometer, das Sie in Abbildung 20–3 sehen, mit einem kleinen Schraubendreher nach, bis Sie einen Wert von 5,0 V Gleichstrom erhalten. Schalten Sie den Power-Shield nach der Einstellung aus.

Abb. 20–3 Potenziometer zur Einstellung der Spannung

Jetzt können Sie die Einzelteile zusammenbauen:

1. Legen Sie die SIM-Karte in den GSM-Shield ein.

2. Stecken Sie den GSM-Shield auf den Arduino Uno auf.

3. Stecken Sie den Power-Shield zuoberst auf.

4. Verlegen Sie zwei kurze Drähte vom Power-Shield zum GSM-Shield, den einen von der positiven PWROUT-Klemme zum 5-Volt-Anschluss und den zweiten von der negativen nach GND. Durch diese beiden Kabel wird der GSM-Shield vom Power-Shield mit 5 V und höherer Stromstärke versorgt.

WARNUNG

Achten Sie immer darauf, dass der Aufbau mit Strom versorgt wird, bevor Sie die USB-Verbindung zwischen Arduino und Computer herstellen. Ziehen Sie auch immer das USB-Kabel ab, bevor Sie die externe Stromversorgung des Shields abschalten.

Die Hardware einrichten und testen

Als Nächstes werden wir die Hardware einrichten und testen, indem wir überprüfen, ob das GSM-Modul mit dem Mobilfunknetz und dem Arduino kommunizieren kann. Bauen Sie die Hardware zusammen, legen Sie die SIM-Karte ein, geben Sie den Sketch aus Listing 20–1 ein und laden Sie ihn hoch.

// Geschrieben von Ryan Owens - SparkFun CC by v3.0 3/8/10

#include <SoftwareSerial.h> // Virtueller serieller Port
SoftwareSerial cell(2,3);
char incoming _ char = 0;

void setup()
{
//Initialisiert die seriellen Ports für die Kommunikation
Serial.begin(9600);
cell.begin(9600);
Serial.println("Starting SM5100B Communication...");
}

void loop()
{
// Wenn ein Zeichen vom Mobilfunkmodul eingeht
if( cell.available() > 0 )
{
// Ruft das Zeichen vom seriellen Mobilfunkport ab
incoming _ char = cell.read();
// Gibt das empfangene Zeichen am Terminal aus
Serial.print(incoming _ char);
}
// Wenn ein Zeichen vom Terminal zum Arduino geht
if( Serial.available() > 0 )
{
incoming _ char = Serial.read(); // Ruft das vom Terminal
// eingehende Zeichen ab
cell.print(incoming _ char);     // Sendet das Zeichen
// zum Mobilfunkmodul
}
}

Listing 20–1 Testsketch für den GSM-Shield

Dieser Sketch leitet einfach alle Informationen, die vom GSM-Shield kommen, zum seriellen Monitor weiter. Es gibt eine serielle Verbindung zwischen dem GSM-Shield und den Digitalpins 2 und 3 des Arduino, sodass die normale serielle Verbindung zwischen Arduino und PC, die über die Digitalpins 0 und 1 läuft, nicht beeinträchtigt wird. Den virtuellen seriellen Port SoftwareSerial für den GSM-Shield richten wir bei , und ein. Die erforderliche Bibliothek dazu ist in der Arduino-IDE enthalten.

Wenn Sie den Sketch hochgeladen haben, öffnen Sie den seriellen Monitor und warten ca. 30 s. Danach sollten Daten wie in Abbildung 20–4 angezeigt werden.

Abb. 20–4 Beispielausgabe von Listing 20–1

Achten Sie dabei auf Nachrichten, die mit +SIND: beginnen, denn sie geben den Status des GSM-Moduls und seiner Verbindung zum Mobilfunknetz an. Wenn als letzte Meldung +SIND: 4 steht, hat der Shield das Netz gefunden und Verbindung damit aufgenommen, sodass Sie mit Projekt 63 weitermachen können. Steht am Ende dagegen +SIND: 8, müssen Sie die Betriebsfrequenz des Moduls ändern, was im nächsten Abschnitt beschrieben wird.

Die Betriebsfrequenz ändern

Um die Betriebsfrequenz des Moduls zu ändern, gehen Sie folgendermaßen vor:

1. Schließen Sie die Arduino-IDE und den seriellen Monitor und laden Sie die Terminal-Software, die Sie in Projekt 48 verwendet haben.

2. Wählen Sie den COM-Anschluss, den der Arduino verwendet, und klicken Sie auf Connect.

3. Schlagen Sie die Frequenz Ihres Mobilfunknetzes in Tabelle 20–1 nach und merken Sie sich die Bandnummer.

Frequenz

Band

GS 900 MHz

0

DCS 1800 MHz

1

PCS 1900 MHz

2

GSM 850 MHz

3

GSM 900 MHz und DCS 1800 MHz

4

GSM 850 MHz und GSM 900 MHz

5

GSM 850 MHz und DCS 1800 MHz

6

GSM 850 MHz und PCS 1900 MHz

7

GSM 900 MHz und PCS 1900 MHz

8

GSM 850 MHz, GSM 900 MHz und DCS 1800 MHz

9

GSM 850 MHz, GSM 900 MHz und PCS 1900 MHz

10

Tab. 20–1 Betriebsbänder des GSM-Moduls

4. Geben Sie den Befehl AT+SBAND? ein und drücken Sie . Das Modul antwortet darauf mit der aktuellen Bandeinstellung (siehe Abb. 20–5).

Abb. 20–5 Beispiel für die Bandabfrage

5. Um das GSM-Modul auf das erforderliche Band umzustellen, geben Sie den Befehl AT+SBAND=x ein, wobei x für die gewünschte Bandnummer aus Tabelle 20–1 steht. Der Shield gibt darauf OK zurück, wie Sie in Abbildung 20–6 sehen.

Abb. 20–6 Erfolgreiche Bandänderung

6. Setzen Sie den Arduino zurück, indem Sie die Pins GND und RST am Arduino eine Sekunde lang mit einem Überbrückungskabel verbinden. Daraufhin werden auf dem Terminal-Bildschirm wie in Abbildung 20–7 wieder die Statuscodes ausgegeben. Vergewissern Sie sich, dass +SIND: 4 anzeigt wird, was bedeutet, dass der Arduino Verbindung mit dem Funknetz aufgenommen hat.

Abb. 20–7 Erfolgreiche Verbindung mit dem Mobilfunknetz

HINWEIS

Den Wert von SBAND müssen Sie nur einmal ändern, da die Einstellung im EEPROM des GSM-Shields gespeichert wird. Wenn Sie jedoch umziehen oder ein anderes Mobilfunknetz nutzen, müssen Sie diesen Wert unter Umständen erneut anpassen.

Jetzt kommt noch die Probe aufs Exempel: Rufen Sie von einem Telefon aus Ihren GSM-Shield an. Wenn das Telefon so eingerichtet ist, dass es die eigene Rufnummer überträgt, wird diese Nummer in der Ausgabe des GSM-Shields angezeigt, wie Sie in Abbildung 20–8 sehen.

Abb. 20–8 Anzeige beim Anrufen des GSM-Shields

Wenn Ihr Aufbau diesen Test erfolgreich bestanden hat, können Sie sicher sein, dass alles wie erwartet funktioniert, und mit den praktischen Projekten fortfahren!

Projekt Nr. 63: Ein Arduino-Wählgerät bauen

Mit diesem Projekt bringen Sie den Arduino dazu, dass er eine Telefonnummer anruft, wenn ein bestimmtes, im Sketch festgelegtes Ereignis eintritt. Wenn beispielsweise die Temperatur in Ihrer Kühltruhe über einen bestimmten Wert steigt oder der Einbruchsalarm ausgelöst wird, ruft der Arduino zwanzig Sekunden lang eine voreingestellte Nummer an und legt dann auf. Auf der Rufnummernanzeige Ihres Telefons können Sie dann ablesen, dass der Anruf vom Arduino kam.

Die Hardware

Für dieses Projekt verwenden Sie die zu Beginn dieses Kapitels beschriebene Hardware sowie jegliche zusätzliche Schaltungen, die Sie für die von Ihnen geplante praktische Anwendung benötigen. Zur Veranschaulichung des Prinzips greifen wir hier auf eine Drucktaste zurück, um den Anruf auszulösen.

Für das Beispielprojekt brauchen Sie also neben der bereits aufgeführten Hardware noch folgende Teile:

• eine Drucktaste

• einen 10-kΩ-Widerstand

• einen 100-nF-Kondensator

• eine Steckplatine

• Verbindungsdrähte

Der Schaltplan

Schließen Sie die externe Schaltung wie in Abbildung 20–9 an.

Abb. 20–9 Schaltplan für Projekt 11

Der Sketch

Geben Sie den folgenden Sketch ein, aber laden Sie ihn noch nicht hoch!

// Projekt 63: Ein Arduino-Wählgerät bauen

#include <SoftwareSerial.h>
SoftwareSerial cell(2,3);

void setup()
{
pinMode(7, INPUT);
cell.begin(9600);
delay(30000);     // Räumt dem GSM-Modul Zeit zur Initialisierung
// des Netzstandorts ein
}

void callSomeone()
{
cell.println("ATDxxxxxxxxxx");  // Ruft die Telefonnummer
// xxxxxxxxxx an.
// Ersetzen Sie xxxxxxxxxx durch die
// gewünschte Nummer (mit Vorwahl).
delay(20000);            // Wartet 20 s lang
cell.println("ATH");     // Beendet den Anruf
delay(60000);            // Wartet 60 s lang auf das GSM-Modul
}

void loop()
{
if (digitalRead(7) == HIGH)
{
callSomeone();
}
}

Funktionsweise

Das Modul wird in void setup aktiviert, und bei räumen wir ihm Zeit ein, um das Mobilfunknetz zu finden und sich zu registrieren. Für unser »Ereignis« überwacht der Arduino die Drucktaste, die an Digitalpin 7 angeschlossen ist. Wenn Sie diese Taste drücken, wird bei die Funktion callSomeone aufgerufen. Bei sendet der Sketch den Befehl, eine Telefonnummer anzurufen.

Ersetzen Sie xxxxxxxxxx durch die gewünschte Telefonnummer, und zwar in der gleichen Form, in der Sie sie auch von Ihrem Handy aus anrufen würden. Soll der Arduino beispielsweise 030/123456 anrufen, schreiben Sie die Anweisung wie folgt:

cell.println("ATD030123456");

Nachdem Sie die richtige Telefonnummer eingetragen haben, laden Sie den Sketch hoch, warten eine Minute und führen dann den Test durch, indem Sie die Taste drücken. Die Wählfunktion lässt sich sehr leicht in andere Sketche einbauen. Wenn Sie irgendeinen Grund dafür haben, dass der Ardui no eine Telefonnummer wählt, rufen Sie diese Funktion bei Bedarf einfach auf, wie es bei geschieht.

Als Nächstes wollen wir uns ganz modern geben und mit dem Arduino Textnachrichten senden.

Projekt Nr. 64: Textnachrichten mit dem Arduino senden

In diesem Projekt sendet der Arduino eine Textnachricht an ein Mobiltelefon, sobald ein bestimmtes Ereignis auftritt. Zur Vereinfachung des Codes verwenden wir die Arduino-Bibliothek SerialGSM, die auf https://github.com/meirm/SerialGSM/ erhältlich ist. Starten Sie die Arduino-IDE nach der Installation der Bibliothek neu.

Die Hardware für dieses Projekt ist die gleiche wie für Projekt 63.

Der Sketch

Geben Sie den folgenden Sketch in die Arduino-IDE ein, aber laden Sie ihn noch nicht hoch!

// Projekt 64: Textnachrichten mit dem Arduino senden

#include <SerialGSM.h>
#include <SoftwareSerial.h>
SerialGSM cell(2,3);

void setup()
{
pinMode(7, INPUT);
delay(30000); // Wartet auf das GSM-Modul
cell.begin(9600);
}
void textSomeone()
{
cell.Verbose(true); // Dient zum Debuggen
cell.Boot();
cell.FwdSMS2Serial();
cell.Rcpt("+xxxxxxxxxxx"); // Ersetzen Sie xxxxxxxxxxx durch die
// gewünschte Mobilfunknummer
cell.Message("This is the contents of a text message");
cell.SendSMS();
}

void loop()
{
if (digitalRead(7) == HIGH)
{
textSomeone();
}

if (cell.ReceiveSMS())
{
Serial.println(cell.Message());
cell.DeleteAllSMS();
}
}

Funktionsweise

Der GSM-Shield wird bei und in void setup wie üblich eingerichtet. Die Betätigung der Drucktaste wird bei erkannt, woraufhin die Funktion textSomeone aufgerufen wird, die eine einfache Textnachricht an die bei hinterlegte Mobilfunk-Rufnummer sendet.

Bevor Sie den Sketch hochladen, müssen Sie xxxxxxxxxxx durch die gewünschte Mobilfunknummer im internationalen Format ersetzen, also mit Ländercode, Vorwahl und der individuellen Rufnummer ohne Leerzeichen, Schrägstriche und Klammern. Um beispielsweise die Handynummer 0123/456789 in Deutschland anzurufen, geben Sie hier +49123456789 ein.

Der Text der Nachricht steht bei . Beachten Sie die Maximallänge von 160 Zeichen.

Nachdem Sie eine einfache Beispielnachricht und die Zielrufnummer eingegeben haben, laden Sie den Sketch hoch, warten 30 Sekunden und drücken dann die Taste. Einen Augenblick später sollte die SMS auf dem angegebenen Telefon ankommen (siehe Abb. 20–10).

Abb. 20–10 Empfang der Textnachricht

Den Sketch von Projekt 64 können Sie ganz einfach auch in andere Sketche aufnehmen. Mit einem Parametervergleich in einer switch-case-Funktion ist es auch möglich, je nach den Umständen verschiedene Nachrichten zu senden.

HINWEIS

Denken Sie daran, dass sich die Kosten für Textnachrichten schnell summieren können. Zum Experimentieren sollten Sie daher einen Pauschal- oder Prepaid-Tarif nutzen.

Projekt Nr. 65: Eine SMS-Fernsteuerung einrichten

In diesem Projekt steuern Sie die digitalen Ausgangspins des Arduino, indem Sie von einem Mobiltelefon aus Textnachrichten senden. Mit den bisher gewonnenen Kenntnissen sollten Sie in der Lage sein, verschiedene Geräte anzuschließen, die Sie damit steuern können. In diesem Beispiel sehen wir die Fernsteuerung von vier digitalen Ausgängen vor, aber Sie können je nach Bedarf natürlich auch mehr oder weniger verwenden.

Um die digitalen Ausgänge (in diesem Beispiel Pin 10 bis 13) ein- oder auszuschalten, senden Sie eine Textnachricht im Format #axbxcxdx an den Arduino, wobei ein x jeweils den Wert 0 zum Ausschalten oder 1 zum Einschalten annehmen kann. Um beispielsweise alle vier Ausgänge zu aktivieren, senden Sie #a1b1c1d1.

Die Hardware

Für dieses Projekt brauchen Sie die zu Anfang des Kapitels beschriebene Hardware sowie die Schaltung, die Sie fernsteuern möchten. Zur Anzeige des Status der fernbedienten digitalen Ausgänge verwenden wir hier vier LEDs. Dazu benötigen Sie die folgende zusätzliche Hardware:

• vier LEDs

• einen 560-Ω-Widerstand

• eine Steckplatine

• Verbindungsdrähte

Der Schaltplan

Schließen Sie die externe Schaltung wie in Abbildung 20–11 an.

Abb. 20–11 Schaltplan für Projekt 65

Der Sketch

Geben Sie den folgenden Sketch ein und laden Sie ihn hoch:

// Projekt 65: Eine SMS-Fernsteuerung einrichten

#include <SoftwareSerial.h>
SoftwareSerial cell(2,3);
char inchar;

void setup()
{
// Richtet die zu steuernden Digitalpins ein
pinMode(10, OUTPUT);
pinMode(11, OUTPUT);
pinMode(12, OUTPUT);
pinMode(13, OUTPUT);

// Standardstatus für die E/A-Pins beim Einschalten und Zurücksetzen;
// dies können Sie nach Belieben ändern.
digitalWrite(10, LOW);
digitalWrite(11, LOW);
digitalWrite(12, LOW);
digitalWrite(13, LOW);
// Initialisiert den seriellen Port des GSM-Moduls
// für die Kommunikation
cell.begin(9600);
delay(30000);
cell.println("AT+CMGF=1");
delay(200);
cell.println("AT+CNMI=3,3,0,0");
delay(200);
}

void loop()
{
// Wenn ein Zeichen vom Mobilfunkmodul eingeht
if(cell.available() > 0)
{
inchar = cell.read();
if (inchar == '#') // Der Beginn des Befehls
{
delay(10);
inchar = cell.read();
if (inchar == 'a')
{
delay(10);
inchar = cell.read();
if (inchar == '0')
{
digitalWrite(10, LOW);
}
else if (inchar == '1')
{
digitalWrite(10, HIGH);
}
delay(10);
inchar = cell.read();
if (inchar == 'b')
{
inchar = cell.read();
if (inchar == '0')
{
digitalWrite(11, LOW);
}

else if (inchar == '1')
{
digitalWrite(11, HIGH);
}
delay(10);
inchar = cell.read();
if (inchar == 'c')
{
inchar = cell.read();
if (inchar == '0')
{
digitalWrite(12, LOW);
}
else if (inchar == '1')
{
digitalWrite(12, HIGH);
}
delay(10);
inchar = cell.read();
if (inchar == 'd')
{
delay(10);
inchar = cell.read();
if (inchar == '0')
{
digitalWrite(13, LOW);
}
else if (inchar == '1')
{
digitalWrite(13, HIGH);
}
delay(10);
}
}
cell.println("AT+CMGD=1,4"); // Löscht alle SMS
}
}
}
}
}

Funktionsweise

In diesem Projekt untersucht der Arduino alle Textzeichen, die über das GSM-Modul eingehen. Daher weisen wir den GSM-Shield bei an, empfangene SMS-Nachrichten in Text umzuwandeln und den Inhalt bei an den virtuellen seriellen Port zu senden. Der Arduino wartet bei einfach darauf, dass vom GSM-Shield eine Textnachricht eingeht.

Da die Befehle zur Steuerung der Arduino-Pins, die vom Handy gesendet und an das GSM-Modul geleitet werden, mit # beginnen, wartet der Sketch bei darauf, dass in der Textnachricht eben dieses Zeichen auftritt. Bei wird der erste Ausgabeparameter a überprüft. Je nachdem, ob auf ihn eine 0 oder 1 folgt, wird der Pin entsprechend aus- bzw. eingeschaltet. Dieser Vorgang wiederholt sich für die nächsten drei Ausgänge, die über die Parameter b, c und d gesteuert werden.

Überlegen Sie einmal, wie leicht Sie dieses Projekt dazu verwenden können, um alle möglichen Dinge fernzusteuern – Lampen, Pumpen, Alarme usw.!

Ausblick

Mit den drei Projekten in diesem Kapitel haben Sie eine hervorragende Grundlage für eigene Projekte geschaffen, in denen Sie über das Mobilfunknetz kommunizieren. Die einzige Grenze bildet dabei Ihre Vorstellungskraft. So können Sie sich beispielsweise eine SMS schicken lassen, wenn Ihr Keller überflutet ist, oder Ihre Klimaanlage vom Handy aus ein- und ausschalten. Klären Sie aber vorher immer die anfallenden Mobilfunkgebühren ab, bevor Sie ein solches Projekt in die Tat umsetzen.

Nachdem Sie in diesem Buch jetzt 65 Projekte kennengelernt (und hoffentlich nachgebaut) haben, sollten Sie genug Kenntnisse und Selbstvertrauen haben, um eigene Arduino-Projekte anzugehen. Sie kennen jetzt die Grundelemente, die in vielen Projekten zum Tragen kommen, und ich bin sicher, dass Sie die Technik anwenden können, um alle möglichen Arten von Problemen zu lösen und viel Spaß dabei zu haben.

Das ist aber erst der Anfang. Es gibt noch viele andere Arten von Hardware, und mit genügend Überlegung und Planung werden Sie mit allen von ihnen arbeiten können. Im Internet ist auch eine umfangreiche Community von Arduino-Benutzern aktiv (zu finden u. a. im Arduino-Forum auf http://arduino.cc/forum/), und möglicherweise gibt es auch an Ihrem Wohnort einen Club.

Sitzen Sie also nicht einfach herum – bauen Sie etwas!

Index

Symbole

^ 153

! 78

!== 76

& 152

&& 79

<< 153

== 76

>> 153

| 152

|| 79

~ 153

74HC595 129

#define 75

+SIND: 400

A

Abstandsmessung

Infrarot 271

Ultraschall 277

Analoge Signale 86

Analogpins

Ausgangswert für Zufallszahlen 122

Belegung durch Shields 182

Bezugsspannung 92

Eigenbau-Arduino 235

Eingänge 87

Lage 22

Messgenauigkeit verbessern 92
analogRead() 88

Bezugsspannung 92

Genauigkeit verbessern 92
analogWrite() 52, 97

And 79

AND (Bitoperator) 152

Arbeitsspeicher 241

Arduino

Analogpins 22

Anbieter 6

Arbeitsspeicher 241

Arduino Due 246

Arduino LilyPad 244

Arduino Mega 245

Arduino Nano 244

Arduino Uno 20, 241

Aufbau der Platine 20

Boarduino 243

Bootloader 233

Community 6

Digitalpins 22

Drahtlose Fernbedienung 303

Eigenbau auf Steckplatine 229

Erweiterung 24, 179

Fernsteuerung über Infrarot 321

Fernsteuerung über Teleduino 392

Freeduino 243

Freetronics Eleven 242

Freetronics EtherMega 246

Geschichte 1

IDE 7

LEDs 23

Mikrocontroller 22, 232

Modelle 240

Reset-Schalter 23

Schaltplansymbol 60

Serieller Port 22

Sicherheit 17

Stromanschluss 22

Treiber 13

USB-Anschluss 21

Zurücksetzen 402

AREF-Pin 92

Arithmetische Operationen 91

Arrays 137

Steuerung von LED-Matrixanzeigen 158

Transpondernummern vergleichen 335

Zeichen für LCD definieren 168

ATmega328 232, 240

AT+SBAND 401

Auffangregister 131

Autoscroll 111

B

Basis (Transistor) 54

Bauteile

Chipwiderstände 40

Darlington-Transistoren 255

Digitalpotenziometer 356

Dioden 55

Drucktasten 68

Elektrolytkondensatoren 67

Gleichrichterdioden 55

Infrarotsensoren 271

Keramikkondensatoren 66

Kondensatoren 65

LCD-Grafikmodule 170

LCD-Zeichenmodule 163

LED-Matrixanzeigen 149

LEDs 42

Mikrocontroller 232

Mikroschalter 267

Numerische Tastenfelder 209

Piezosummer 95

Potenziometer 94

Quarzoszillatoren 231

Relais 56

RF-Link-Module 301

RTC-Module 361

Siebensegmentanzeigen 139

Spannungsregler 230

Symbole in Schaltplänen 60

Tastenfelder 209

Temperatursensoren 98

Touchscreens 217

Transistoren 54

Ultraschallsensoren 277

Widerstände 38

XBee Explorer 310

XBee-Module 309

BC548 54

BCD 366
beginTransmission() 345

Bezugsspannung 92

Bibliotheken

Einführung 188

I^2C 344

Importieren 188

Infrarotübertragung 318

Installation unter Mac OS X 189

Installation unter Ubuntu Linux 191

Installation unter Windows XP 190

IRremote 318

LCD-Module 166

Shields 188

SPI 354

Teleduino 391

TinyGPS 297

Twitter 386

VirtualWire 302

Wire 344

Binärkodiertes Dezimalformat 366

Binärzahlen 127

Bitarithmetik 152

Bitoperatoren 152

Bitreihenfolge 127, 158, 354

Bitverschiebung 153

Blockierstrom 255

Boarduino 243

Boolesche Variablen 78

Bootloader 233

Breakout-Board 218

Bytevariablen 128

C
char 211

Chipwiderstände 40

CS 353

D

Darlington-Transistoren 255

Datenbus

I^2C 343

Master 344

Slave 344

SPI 353

Debugging 114
delay() 31
delayMicroseconds() 278

Digitale Signale 86

Digitalpins

Als Ausgang festlegen 30

Belegung durch Shields 182

Eigenbau-Arduino 235

Eingänge 68

Eingang messen 76

Ein- und ausschalten 31

Erweitern 129

Interrupt-Modi 205

Lage 22

Porterweiterung 350

Pulsbreitenmodulation 52, 258

SMS-Fernsteuerung 408

Steuern über Teleduino 389

Steuer-URL von Teleduino 392

Zeit für den Pegelwechsel messen 199

Digitalpotenziometer 356
digitalRead() 76
digitalWrite() 31

Dioden 55

DLINE 288
do-while 115

Drahtlose Datenübertragung

Bibliothek 302

Computer vorbereiten 311

Empfängerschaltung 304

Empfängersketch 307

Fehlerprüfung 302

Fernabruf von Sensordaten 312

Fernbedienung 303

Preiswerte Module 301

RF-Link-Module 301

Senderschaltung 303

Sendersketch 306

Terminal 311

Transceiver 309

VirtualWire 302

XBee 309

XBee Explorer 310

Drehmoment 250

Drucktasten

Einführung 68

Interrupts 205

Prellen 69

Status prüfen 76

E

Echtzeit-Modul siehe RTC

EEPROM

Bandeinstellung des GSM-Shields 402

Busadresse 346

Daten schreiben und lesen 337

Einführung 241

Extern 345

Lebensdauer 337

Status speichern 339

Variablen speichern 336

Elektrolytkondensatoren 67

EM406 286

Emitter (Transistor) 54

E-Motoren

Drehzahlregelung 256

Eigenschaften 255

Pulsbreitenmodulation 258
endTransmission() 345

Entprellschaltung 70

Ethernet

Freetronics EtherMega 246

Freetronics EtherTen 379

Shield 379

F

Farad 65

Feature creep 36

Fernsteuerung

Arduino 321

Arduino vom Web aus steuern 388

Befehls-URL (Teleduino) 392

Codes von Sony-Fernbedienungen 320

Drahtlose Fernbedienung 303

Fernabruf von Sensordaten 312

Fernüberwachungsstation 381

Infrarot-Fernbedienung 317

Portweiterleitung 386

Raupenfahrzeug 324

Sensordaten auf einer Webseite anzeigen 381

SMS-Fernsteuerung 408

Teleduino 388, 392

Flash-Speicher 241

Fließkommavariablen 91
float 91

Flüssigkristallanzeigen siehe LCD
for-Schleifen 50

Freeduino 243

Freetronics Eleven 242

Freetronics EtherMega 246

Freetronics EtherTen 379

Fritzing 65

FTDI-Kabel 238

Funktionen

Aktionen wiederholen 104
analogRead() 88
analogWrite() 52, 97

Auskommentieren 366
beginTransmission() 345

Bewegungssteuerung 264
delay() 31
delayMicroseconds() 278
digitalRead() 76
digitalWrite() 31

Eigene Funktionen schreiben 104
endTransmission() 345

Interrupt-Funktionen 204

Parameter 105
pinMode() 30
pulseIn() 278
randomSeed() 122
read() 345
readKeypad() 215
requestFrom() 345

Serial.flush() 117

Temperaturwerte umrechnen 106
void 106

Vorteile 113
vw_get_message() 308
vw_send() 307

Werte zurückgeben 106
write() 345

G

Geocache (umgekehrt) 3

Gleichrichterdioden 55, 61

GMT 294

GND

Schaltplansymbol 64

GPS

Bewegungsverlauf aufzeichnen 294

Definition 285

Empfängermodul 286

Empfangsgerät bauen 289

GPS Visualizer 298

Positionsanzeige auf LCD-Bildschirm 291

Shield 286

Standorte auf Landkarte anzeigen 297

Standort in Google Maps bestimmen 292

Testlauf 287

TinyGPS 297

Uhr 292

GSM-Shield

Betriebsfrequenz ändern 400

H

Hexadezimalzahlen 323

HTML 385

I

I^2C

Befehle über Teleduino senden 389

Bibliothek 344

Busadresse 346

Daten anfordern 345

Einführung 343

Externer EEPROM 346

Porterweiterung 350

Spannung 344

IC-Abzieher 237

ICs

Porterweiterung 350

RTC-Modul 361

Schieberegister 129

IDE

Befehlsbereich 26

Bibliotheken 188

Download und Installation 7

Fehlermeldungen 32

Mac OS X 8

Meldungsbereich 27

Menü 26

Oberfläche 25

Platinentyp ändern 239

Serieller Monitor 110

Sketche hochladen 33

Sketche speichern 29

Sketche überprüfen 32

Symbolleiste 27

Textbereich 27

Ubuntu Linux 15

Upload 33

USB-Anschluss 28

Verify 32

Windows XP 11
if 76

Mehrere Vergleiche 79
if-then-else 77

Infrarot

Bibliothek 318

Empfänger 318

Fernsteuerung für Raupenfahrzeug 324

Grundlagen 317

Sony-Codes 320

TV-Fernbedienung 319

Infrarotsensoren 271
ino 29
int 117

Integrierte Schaltkreise siehe ICs

Internet

Fernüberwachungsstation 381

Freetronics EtherMega 246

Freetronics EtherTen 379

IP-Adresse 380, 384

Portweiterleitung 386

Shields 379

Interrupts 204, 269

IP-Adresse 380, 384

IRremote 318

K

Keramikkondensatoren 66

Kollektor (Transistor) 54

Kollisionswarnung

Infrarotsensoren 271

Mikroschalter 267

Ultraschallsensoren 277

Kommentare 28

Kondensatoren

Elektrolytkondensatoren 67

Kapazität 65

Keramikkondensatoren 66

Konstanten 75

Kontaktprellen 69

L

Latch-Pin 133

LCD

Anzeige steuern 172

Bibliothek 166

Eigene Zeichen definieren 168

Grafikmodul anschließen 171

Grafikmodule 170

Grafische Anzeigeeffekte 174

Kontrasteinstellung 164

LCD- und Tastenfeld-Shield von Freetronics 289

Steuern 164

Text anzeigen 166

Textfunktionen 173

Trimmpotenziometer 164

Variablen anzeigen 167

Verlaufskurven 175

Zeichenmodule 163

Least Significant Bit 127

LED-Matrixanzeigen

Animieren 160

Bilder ausgeben 156, 158

Einführung 149

Pinnummern 150

Steuern 154

LEDs

Acht-LED-Shield 183

Begrenzungswiderstand 42

Binärzahlenanzeige 130

Blinkcodeanzeige 107

Blinken lassen 28

Einführung 42

Helligkeit ändern 51

Helligkeitsregelung auf Touchscreen 225

Helligkeitsregelung mit Digitalpotenziometer 356

Lage auf dem Arduino 23

LED-La-Ola 46

Matrixanzeigen 149

Polung 42

Schaltplansymbol 62

Siebensegmentanzeigen 139

Teleduino-Statuscodes 391

Verkehrsampel 80

Leerlaufstrom 255

Leistung 37

Leuchtdioden siehe LEDs

LilyPad 244

Linearer Spannungsregler 230

Logische Vergleichsoperatoren 78
long 117
loop() 30

Löten 186

LSB 127

LSBFIRST 158

M

MAC-Adresse 385

Masseanschluss siehe GND

Master 344

Maxim DS3232 361

MCP4162 356

MCP23017 350
micros() 199
microSD

Bewegungsverlauf aufzeichnen 294

Daten in Tabellenkalkulationsprogramme importieren 198

Daten schreiben 194

Einführung 192

Freetronics EtherMega 246

Freetronics EtherTen 380

Karten prüfen 193

SdInfo 193

Stechuhr 372

Temperaturdaten aufzeichnen 196

Mikrocontroller

ATmega328 232

Aufkleber mit Pinbelegung 236

Austauschen 237

Bootloader 233

Definition 22

Modelle 241

Pins 235

Mikroschalter 267
millis() 199

MISO 353

Mobilfunk

Arduino-Wählgerät 403

AT+SBAND 401

Betriebsfrequenz ändern 400

GSM-Shield 396

GSM-Shield anrufen 402

Kommunikation testen 398

PIN 396

+SIND: 400

Statusmeldungen 400

Telefonnummer angeben 405, 407

Textnachrichten auf Leuchtbändern anzeigen 2

Textnachrichten senden 406

Voraussetzungen 395

Modulo 145

MOSI 353

Most Significant Bit 127

Motoren

Blockierstrom 255

Drehrichtung 266

Drehzahlregelung 256, 266

Elektromotoren 255

Leerlaufstrom 255

Motor-Shield 262

Stellmotoren 249

Stromquelle 256

MSB 127

MSBFIRST 158, 355

MSBLAST 355

Multimeter 41

N

Nixie-Röhren 4

Not 78

NOT (Bitoperator) 153

Numerische Tastenfelder siehe

Tastenfelder

O

Ohmsches Gesetz 43

Open-Source-Hardware 247

Operatoren

^ 153

! 78

!== 76

& 152

&& 79

<, >, <=, >= 91

<< 153

== 76

>> 153

| 152

|| 79

~ 153

And 79

AND (Bitoperator) 152

Bitoperatoren 152

Größer/kleiner 91

Klammern 79

Logische Vergleichsoperatoren 78

Mehrere Vergleiche 79

Modulo 145

Not 78

NOT (Bitoperator) 153

Or 79

OR (Bitoperator) 152

Reihenfolge 79

Vergleichsoperatoren 76, 91

Verschiebeoperatoren 153

XOR 153

Or 79

OR (Bitoperator) 152

P

Parallax Ping))) 277

Piezosummer 95

Maximallautstärke 97
pinMode() 30

Pololu RP5 259

Porterweiterung 350

Portweiterleitung 386

Potenziometer 94

Digitalpotenziometer 356

Trimmer 95

Power-Shield 397

PowerSwitch Tail 102

Prellen 69
print() 111
println() 111

Projekte

Algorithmus 36

Arduino-Fernsteuerung 321, 389

Arduino-Tweeter 386

Arduino-Wählgerät 403

Batterietestgerät 88

Beispiele 2

Bereiche auf einem Touchscreen ansprechen 219

Bewegungsverlauf aufzeichnen 294

Bilder auf LED-Matrix anzeigen 156, 158

Binärzahlenanzeige 130

Binärzahlenquiz 133

Daten auf microSD-Karten schreiben 194

Datenübertragung mit XBee-Modulen 310

Datum und Uhrzeit auf einem RTC-Modul 362

Digitalpotenziometer 356

Digitalthermometer 147

Digitaluhr bauen 367

Drahtlose Fernbedienung 303

Eigene Zeichen für LCD definieren 168

Ein/Aus-Schalter auf einem Touchscreen 222

Eingaben im seriellen Monitor multiplizieren 116

Einstellige Siebensegmentanzeige 141

Elektronischer Würfel 124

Feature creep 36

Ferngesteuertes Thermometer 312

Fernüberwachungsstation 381

GPS-Empfangsgerät 289

GPS-Uhr 292

Heiratsantrag 3

Interrupts 206

Kollisionserkennung mit Mikroschalter 267

Kollisionsverhinderung mit IR-Sensor 274

Kollisionsverhinderung mit Ultraschallsensor 280

LED-La-Ola 46

LED-Matrix animieren 160

LED-Matrixanzeigen 154

Moped-Überwachungssystem 4

Nixie-Röhren 4

Piezosummer 97

Planung 36

Raupenfahrzeug 259

RFID-Steuerungssystem 333

RFID-Steuerungssystem mit Erinnerung an die letzte Aktion 338

Schloss mit Tastenfeld 213

Scooterputer 4

Shield mit acht LEDs 183

SMS-Fernsteuerung 408

Stechuhr 372

Steckplatinen-Arduino 229

Stoppuhr 201

Sudoku 4

Teleduino 389

Temperaturaufzeichnung 196

Temperaturverlaufskurve 175

Textfunktionen für LCD 173

Textnachrichten auf Leuchtbändern anzeigen 2

Textnachrichten senden 406

Thermometer mit Ampelanzeige 98

Thermometer mit Blinkcodeanzeige 107

Touchscreen-Schalter mit drei Zonen 225

Twitter 5

TwypeWriter 5

Umgekehrter Geocache 3

Verkehrsampel 80

Zeigerthermometer 252

Zweistellige Siebensegmentanzeige 144

ProtoScrewShield 367

ProtoShield 182

Lötarbeiten 186

Struktur 184

Pulldown-Widerstand 70

Pulsbreitenmodulation 51, 97, 258
pulseIn() 278

Q

Quarzoszillatoren 231

R
randomSeed() 122

Raupenfahrzeuge

Bausatz 260

Chassis 260

Fernsteuerung 324

Funktionen zur Bewegungssteuerung 264

Kollisionserkennung 267

Kollisionsverhinderung mit IR-Sensor 274

Kollisionsverhinderung mit Ultraschallsensor 280

Motor-Shield 262

Stromversorgung 260

Wendemanöver 267
read() 345
readKeypad() 215

Relais 56, 62
requestFrom() 345

Reset-Schalter 22, 23

Restladungen 57, 259

RFID

Definition 329

Lesegerät 330

Lesegerät anschließen 331

Status merken 338

Stechuhr 372

Test 332

Transponder 330

Zugriffssteuerung 333

RF-Link-Module 301

RTC

Binärkodiertes Dezimalformat 366

Digitaluhr 367

IC 361

Modul anschließen 362

Stechuhr 372

Uhr stellen 366

Uhrzeit- und Datumsformat 366

S

SAM3X8E 240

Schaltpläne 60

Bauteilsymbole 60

Konstruktionsprogramm Fritzing 65

Leitungen 63

Schieberegister 129

SCK 353

SCL 344

Scooterputer 4

SDA 344

SdInfo 193

Serial.available() 116

Serial.flush() 117

Serieller Monitor

Autoscroll 111

Daten an den Arduino senden 115

Debugging 114

Öffnen 110

Puffer leeren 117

Starten in setup() 111

Text senden 111

Variableninhalt anzeigen 112

Serieller Port

Lage 22

Servomotoren siehe Stellmotoren
setup() 29

Shields

Acht-LED-Shield 183

Bibliotheken 188

Datenschalter 288

Eigene Shields bauen 182

Einführung 24, 180

Ethernet 379

Externe Geräte anschließen 368

Freetronics EtherMega 246

Freetronics EtherTen 379

Gemeinsame Verwendung von Pins 182

GPS-Shield 286

GSM-Shield 396

IP-Adresse 384

Jumper 263

LCD- und Tastenfeld-Shield von Freetronics 289
microSD-Karten 193

Mobilfunk 396

Motor-Shield 262

Power-Shield 397

ProtoScrewShield 367

ProtoShield 182

SM5100 396

Stapeln 180

Sicherheit

Allgemeine Hinweise 17

Netzstrom steuern 58

Siebensegmentanzeigen

Aufbau 139

Einstellig 141

Mehrstellig 144

Pinbelegung 139

Steuern 140

Signifikantestes Bit 127

SIG-Pin 277

Sketche

Bibliotheken 188

Dateinamenerweiterung 29

Debugging 114

#define 75

Definition 28

Eigene Funktionen schreiben 103

Entscheidungen 76, 114, 212

Fehlermeldungen 32
for-Schleifen 50

Hochladen 33

Hochladen ohne USB-Anschluss 236
if 76
if-then-else 77

Kommentare 28

Konstanten 75

LEDs blinken lassen 28
loop() 30

SdInfo 193
setup() 29

Sketch 391

Speichern 29

Überprüfen 32

Variablen 49

Vergleichsoperatoren 76

Zeitmessung 199

Slave 344

SM5100 396

Spannung 37

Spannungsregler 230

Spannungsteiler 93

SPI

Anschlüsse 353

Bibliothek 354

Bitreihenfolge 354

Daten an SPI-Geräte senden 355

Spannung 354

SRAM 241

SS 353, 355

Steckplatinen 44

Arduino-Nachbau auf Steckplatine 229

Boarduino 243

ProtoShield 182

Stellmotoren

Anschließen 251

Bewegen 251

Eigenschaften 250

Über Teleduino steuern 389

Zeigerthermometer 252

Stoppuhr 201

Stromstärke 37

Sudoku 4
switch-case 212

T

Tastenfelder

Anschließen 210

Einführung 209

LCD- und Tastenfeld-Shield von Freetronics 289

Programmierung 210

Schloss 213

Tastverhältnis 51, 97

TDK PS1240 95

Teleduino 388

Befehls-URL 392

Bibliothek 391

Schlüssel 389

Sketch 391

Statuscodes 391

Temperatur

Aufzeichnung auf microSD-Karte 196

Verlaufskurve 175

Werte umrechnen 101, 106

Temperatursensor 98

Daten auf Webseite anzeigen 381

Fernabruf 312

Terminal 311

Textnachrichten 406

Anzeige auf Leuchtbändern 2

SMS-Fernsteuerung 408

TinyGPS 297

TIP120 255

TMP36 98

Touchscreen

Anschließen 218

Berührungspunkt ermitteln 219

Breakout-Board 218

Drei-Zonen-Steuerelement 225

Ein/Aus-Schalter 222

Einführung 217

Helligkeitsregler für LED 225

Kartierung 221

Zwei-Zonen-Steuerelement 222

Trägheit des Auges 156

Transceiver 309

Transistoren 54, 62

Darlington-Transistoren 255

Transponder siehe RFID

Trimmer 95

Twitter

Bibliothek 386

Statuscodes 388

Token 386

Tweets vom Arduino senden 386

TwypeWriter 5

TwypeWriter 5

U

UART 288

Ultraschallsensoren 277

Umgekehrter Geocache 3

Upload 33

USB

Anschluss 21

Anschluss herstellen 28

UTC 294

V

Variablen

Auf LCD anzeigen 167

Boolesche Variablen 78

Bytevariablen 128
char 211

Dauerhaft im EEPROM speichern 336

Einführung 49

Fließkommavariablen 91

Inhalt anzeigen 112

Inhalt drahtlos senden 307
int 117
long 117

Vergleichsoperatoren 76, 91

Verify 32

Verschiebeoperatoren 153

VirtualWire 302
void 106
vw_get_message() 308
vw_send() 307

W
while 114

Widerstände

Begrenzungswiderstand 42

Chipwiderstände 40

Digitalpotenziometer 356

Einführung 38

Farbcode 39

Leistungsangabe 41

Ohmsches Gesetz 43

Potenziometer 94

Pulldown-Widerstand 70

Regelbare Widerstände 94

Schaltplansymbol 61

Spannungsteiler 93

Trimmer 95

Wire 344
write() 345

X

XBee Explorer 310

XBee-Module 309

XOR 153

Z

Zeitmessung

Digitaluhr 367

GPS-Uhr 292

RTC-Module 361

Stechuhr 372

Zeitzonen 294

Zufallszahlen 122

Fußnote

1 Einführung

1 Alle URLs in diesem Buch und passende lokale Anbieter und Websites finden Sie unter www.dpunkt.de/arduino_ws