32 | So funktioniert’s
Arduino Ar duino Teil 1
www.elvjournal.de
So funktioniert’s | 33
verstehen und anwenden Einstieg in die Hardware: Arduino und AVR-Mikrocontroller
Dies ist der erste Teil einer Artikelserie zum Thema Arduino. In diesem Beitrag werden zunächst die Kapitel · Ard Arduino uino – das erfolgreich erfolgreichste ste Mikrocontr Mikrocontroller oller-Boar -Board d der Welt · Das ArduinoArduino-Board Board als als Basis für µC-Anwen µC-Anwendun dungen gen · Ard Arduinouino-Var Variant ianten en – vom Mikr Mikro o zum Mega Mega · Schne Schneller ller Einstieg Einstieg mit der Arduin Arduino-Ent o-Entwickl wicklungs ungs-umgebung behandelt. In weiteren Beiträgen Beiträgen werden dann u. a. die Themen Themen · Prog Programm rammieru ierung ng und und Programm Programmierp ierpraxis raxis · Prog Programm rammbibli bibliothe otheken ken und Shiel Shields ds · Schnit Schnittstel tstellen len wie USB, RS232 und I2C, Ethernet und WLAN · Sens Sensortech ortechnik nik und und Mess Messwerte werterfas rfassung sung · Int Interr errupt uptss und und Poll Polling ing · Di Disp spla layt ytec echni hnikk · Ph Physi ysical cal Com Comput puting ing vorgestellt.
Arduino – das erfolgreichste Mikrocontroller-Board der Welt Die Idee zum Arduino wurde im Jahr 2005 am Institut für Interaktives Design in Ivrea (Italien) geboren. Die erste Version des Arduinos bestand aus einem Bausatz mit wenigen Einzelkomponenten und dem damals sehr populären ATmega8 als zentralem Mikrocontroller. Nachdem diese ersten Bausätze innerhalb kürzester Zeit verkauft waren, folgten rasch weitere Auflagen. Künstler und Designer aus anderen Regionen nahmen die Idee auf, und das Arduino-Prinzip verbreitete sich über Italien und Europa schließlich in der ganzen Welt.
Das Konzept einer unkomplizierten und preisgünstigen Hardwareplattform Hardwareplattform zusammen mit einer frei verfügbaren, leicht zu beherrschenden Programmieroberfläche (die (die sogenannte sogenannte IDE = Integ Integrated rated Developm Development ent Environment) fand auch bei anderen Anwendergruppen Anwendergruppen wie etwa Hobbyisten oder Technikakademien Technikakademien Anklang. Schließlich erkannten auch Schulen und Hochschulen im wissenschaftlichen und technischen Bereich das enorme Potenzial der Arduino-Idee. Neben immer neuen Hardwar Hardware-Version e-Versionen en entstanden auch aufsteckbare Erweiterungsplatinen, sogenannte Shields, und die Erfolgsgeschichte folgsgeschich te des Arduinos nahm ihren Lauf. Inzwischen sind die Verkaufszahlen der einzelnen Arduino-Versionen recht beachtlich, und der Arduino kann mittlerweile sicherlich als das erfolgreichs erfolgreichste te Mikrocontroller-Board krocontrollerBoard aller Zeiten gelten. Für diesen überragenden Erfolg des Arduinos gibt es mehrere Gründe. Einerseits wird durch das komplett aufgebaute Prozessorboard der Einstieg in die Hardware enorm erleichtert. Die typischen Anfängerprobleme wie falsche Spannungsversorgungen, Probleme mit dem Quarzoszillator oder ungültige Konfigurationsparameter gurationspar ameter,, sogenannte Fuse-Bits, sind beim Arduino unbekannt. Das Board wird einfach mit der USB-Schnittstelle des PCs oder Laptops verbunden und kann innerhalb weniger Minuten programmiert werden. Die einfache Handhabung führte insbesondere bei Jugendlichen, aber auch bei Angehörigen der älteren Generation, die noch niemals mit Elektronik in Berührung gekommen sind, zu einer ungeahnten Begeisterung für die Mikrocontroll Mikrocontrollertechnik. ertechnik. Ein weiterer Erfolgsfaktor ist die zugehörige Programmieroberfläche.. Diese steht als kostenlose Opengrammieroberfläche Source-Version Source-Versi on zur Verfügung. Eine langwierige InstalELVjournal 5/2013
So funktioniert’s | 33
verstehen und anwenden Einstieg in die Hardware: Arduino und AVR-Mikrocontroller
Dies ist der erste Teil einer Artikelserie zum Thema Arduino. In diesem Beitrag werden zunächst die Kapitel · Ard Arduino uino – das erfolgreich erfolgreichste ste Mikrocontr Mikrocontroller oller-Boar -Board d der Welt · Das ArduinoArduino-Board Board als als Basis für µC-Anwen µC-Anwendun dungen gen · Ard Arduinouino-Var Variant ianten en – vom Mikr Mikro o zum Mega Mega · Schne Schneller ller Einstieg Einstieg mit der Arduin Arduino-Ent o-Entwickl wicklungs ungs-umgebung behandelt. In weiteren Beiträgen Beiträgen werden dann u. a. die Themen Themen · Prog Programm rammieru ierung ng und und Programm Programmierp ierpraxis raxis · Prog Programm rammbibli bibliothe otheken ken und Shiel Shields ds · Schnit Schnittstel tstellen len wie USB, RS232 und I2C, Ethernet und WLAN · Sens Sensortech ortechnik nik und und Mess Messwerte werterfas rfassung sung · Int Interr errupt uptss und und Poll Polling ing · Di Disp spla layt ytec echni hnikk · Ph Physi ysical cal Com Comput puting ing vorgestellt.
Arduino – das erfolgreichste Mikrocontroller-Board der Welt Die Idee zum Arduino wurde im Jahr 2005 am Institut für Interaktives Design in Ivrea (Italien) geboren. Die erste Version des Arduinos bestand aus einem Bausatz mit wenigen Einzelkomponenten und dem damals sehr populären ATmega8 als zentralem Mikrocontroller. Nachdem diese ersten Bausätze innerhalb kürzester Zeit verkauft waren, folgten rasch weitere Auflagen. Künstler und Designer aus anderen Regionen nahmen die Idee auf, und das Arduino-Prinzip verbreitete sich über Italien und Europa schließlich in der ganzen Welt.
Das Konzept einer unkomplizierten und preisgünstigen Hardwareplattform Hardwareplattform zusammen mit einer frei verfügbaren, leicht zu beherrschenden Programmieroberfläche (die (die sogenannte sogenannte IDE = Integ Integrated rated Developm Development ent Environment) fand auch bei anderen Anwendergruppen Anwendergruppen wie etwa Hobbyisten oder Technikakademien Technikakademien Anklang. Schließlich erkannten auch Schulen und Hochschulen im wissenschaftlichen und technischen Bereich das enorme Potenzial der Arduino-Idee. Neben immer neuen Hardwar Hardware-Version e-Versionen en entstanden auch aufsteckbare Erweiterungsplatinen, sogenannte Shields, und die Erfolgsgeschichte folgsgeschich te des Arduinos nahm ihren Lauf. Inzwischen sind die Verkaufszahlen der einzelnen Arduino-Versionen recht beachtlich, und der Arduino kann mittlerweile sicherlich als das erfolgreichs erfolgreichste te Mikrocontroller-Board krocontrollerBoard aller Zeiten gelten. Für diesen überragenden Erfolg des Arduinos gibt es mehrere Gründe. Einerseits wird durch das komplett aufgebaute Prozessorboard der Einstieg in die Hardware enorm erleichtert. Die typischen Anfängerprobleme wie falsche Spannungsversorgungen, Probleme mit dem Quarzoszillator oder ungültige Konfigurationsparameter gurationspar ameter,, sogenannte Fuse-Bits, sind beim Arduino unbekannt. Das Board wird einfach mit der USB-Schnittstelle des PCs oder Laptops verbunden und kann innerhalb weniger Minuten programmiert werden. Die einfache Handhabung führte insbesondere bei Jugendlichen, aber auch bei Angehörigen der älteren Generation, die noch niemals mit Elektronik in Berührung gekommen sind, zu einer ungeahnten Begeisterung für die Mikrocontroll Mikrocontrollertechnik. ertechnik. Ein weiterer Erfolgsfaktor ist die zugehörige Programmieroberfläche.. Diese steht als kostenlose Opengrammieroberfläche Source-Version Source-Versi on zur Verfügung. Eine langwierige InstalELVjournal 5/2013
34 | So funktioniert’s
USBBuchse
Reset Button
„L”„L”-LE LED D
Rx-/ Rx-/T Tx-L x-LED
On-LED
a) 6 Analog-E Analog-Eing ingäng ängee b) 14 digi digitale tale EinEin- und Ausgäng Ausgängee c) Buch Buchsen sen für di diee Stromverso Stromversorgun rgungg (GND, 3,3 V und 5 V) d) Eingä Eingänge nge für Referenzsp Referenzspannun annungg und Reset Über diese Buchsenreihen kann auf alle für die Anwendungen relevanten Controllerpins zugegriffen werden.
Externe Spannungsversorgung
Anschluss für eine externe Spannungsversorgung
Eine über eine Hohlbuchse zugeführte externe Versorgungsspannung wird auf dem Board geregelt und geglättet. Eine USB-Schnittstelle Controller
Bild 1: Arduino Uno
Die USB-Schnittstelle dient zur Programmierung des Controllers. Darüber hinaus kann diese Schnittstelle auch für die Kommunikation des Mikrocontrollers mit einem PC während der Programmausführung eingesetzt werden.
lation ist nicht erforderlich, und einfache Einstiegsbeispiele sorgen für den schnellen Erfolg. Komplizierte Parametereinstellungen Parametereinstellungen wie bei anderen Entwicklungstools sind nicht erforderlich. Die ersten Beispielprogramme können so im Handumdrehen auf den Arduino geladen und getestet werden. Der letzte Grund für die große Popularität des Arduinos findet sich in der ganz eigenen Philosophie des Projekts. Alle Hard- und Softwarekom Softwarekom-ponenten unterliegen dem sogenannten Open-Source-Prinzip. So werden die Schaltpläne und Layouts aller Arduino-Varianten im Internet veröffentlicht. Gleiches gilt für die Software und die zugehörigen Quellcodes. Weiterhin wird der Arduino-Anwender durch eine Fülle von Software-Bibliotheken unterstützt. Diese nützlichen Libraries werden zum Teil direkt mit der Standard-IDE mitgeliefert. Beispiele hierfür sind Anwendungen zur Thema Ethernet, LC-Displays oder die Ansteuerung von Schrittmotoren und Modellbauservos. Darüber hinaus hat die Arduino-Community Arduino-Community eine nahezu unüberschaubare Fülle von Bibliotheken für alle möglichen Mikrocontroller-Applikationen hervorgebracht. hervorgebracht. Damit lassen lass en sich auch komplex komplexere ere Aufgaben wie etwa die Detektion von IR-Fernbedienungssignalen, das Ansteuern von Ultraschallsensoren oder das Auslesen von SD-Speicherkarten problemlos und schnell bewältigen.
Der wichtigste Baustein auf dem Arduino ist der Mikrocontroller. Hierbei handelt es sich um einen Halbleiterchip, der neben einer Prozessoreinheit auch verschiedene Peripheriefunktionen in einem einzigen IC vereinigt. Meist ist auch der Arbeits- und Programmspeicher auf dem gleichen Chip integriert. Ein Mikrocontroller ist somit mit einem kompletten Ein-Chip-Computersystem vergleichbar [1] [1].. Die bekannten Kriterien für Prozessoren bestimmen auch die Einsatzmöglichkeiten eines Mikrocontrol Mikrocontrollers. lers. Tabe abelle lle 1 fasst die wesentlichen Leistungsmerkmale des ATmega328 zusammen. Auf modernen Mikrocontrollern der ATmega-Reihe finden sich zusätzlich zu den einfachen Eingabe-/ Ausgabe-Ports auch komplexere Peripheriefunktionen wiee z. B. wi · seri seriell ellee Schni Schnitts ttstel tellen len · I²C-(I I²C-(Inter nter-Inte -Integrat grated-Ci ed-Circuit rcuit-)Bus -)Bus · PW PWMM-AAus usgä gäng ngee · Ana Analog log-di -digit gitalal-Wa Wand ndler ler
Arduino-Boards als Basis für µC-Anwendungen
Damit lassen sich alleine mit dem Controller bereits umfangreiche Praxisprojekte realisieren. Als Beispiel für die Leistungsfähigkeit eines modernen Controllers zeigt Bild 2 eine selbst gefertigte Digitaluhr, die allein mit einem ATmega als integriertem Baustein auskommt. Es sind keinerlei weitere ICs erforderli erforderlich ch [2] [2]..
Das aktuell am weitesten verbreitete Board ist der Arduino Uno (B (Bil ildd 1) 1).. Dieses Board arbeitet mit dem ATmega328 und ergänzt ihn zu einem universellen Mikrocontr Mikrocontroller-System. oller-System. Neben dem Prozessor selbst weist das Board hierfür noch die folgenden Hauptfunktionseinheiten auf: Resetschaltung mit Taster
Mit dem Taster kann der Controller manuell neu gestartet werden. Resets sind aber im Gegensatz zu einem Windows-PC nur sehr selten erforderli erforderlich. ch.
ATmega328 32
Quarz für eine zuverlässige und präzise Tak Taktversorgu tversorgung ng
Falsch angeschlossene Quarze oder Lastkapazitäten sind die häufigste Ursache bei selbst entwickelten Controllerboards. Durch den fest installierten Quarz entfällt diese Fehlerursache beim Arduino vollständig. Buchsenreihen für den Anschluss externer elektronischer Bauelemente
Die Buchsen sind in vier Hauptgruppen unterteilt: www.elvjournal.de
1 e l l e b a T
KByt KB ytes es Fla Flash sh-S -Spe peic iche herr
1
KByte EEPROM
2
KBytes SRAM
2
8-Bi 8Bitt-Ti Tim mer er//-Co Coun unte terr
1
16-Bit-Timer
6
Kanä Ka näle le fü fürr 10 10-B -Bit it-A -ADC DC
23
prog pr ogra ramm mmie ierb rbar aree I/Os I/Os
So funktioniert’s | 35
Die Stromversorgung des Arduino-Boards kann über zwei verschiedene Wege erfolgen: · Über die USB-Schnittstelle: Dabei wird die Versorgungsspannung direkt dem angeschlossenen Computer entnommen. · Über eine externe Spannungsquelle: Ist der Arduino fertig programmiert, kann er auch ohne angeschlossenen PC arbeiten. Dazu muss er nur mit einer externen Spannungsquelle versorgt werden. Diese kann sowohl aus einem einfachen, unstabilisierten Steckernetzteil (Spannungsbereich 7–12 V) oder auch aus einem Batteriesatz (5x 1,5 V oder 9-V-Block) bestehen. An dieser Stelle noch zwei wichtige Hinweise: TIPP I: Das Arduino-Board muss stets auf einer elektrisch isolierenden Unterlage liegen. Andernfalls kann es zu Kurzschlüssen kommen, und sowohl der USB-Port des Rechners als auch der Arduino können Schaden nehmen (Bild 3). TIPP II: Will man den USB-Port des Rechners schützen, kann man einen USB-Hub mit eigener Spannungsversorgung einsetzen. Diese Hubs sind meist gut gegen Überlastung abgesichert, und das „Durchschlagen“ eines Kurzschlusses über den Hub hinweg zum Rechner ist sehr unwahrscheinlich.
Bild 2: Selbst gefertigte Digitaluhr – aufgebaut nur mithilfe eines Mikrocontrollers
Bild 3: Das Board „steht unter Strom“.
Arduino-Varianten – vom Mikro zum Mega
Außer dem Klassiker Arduino Uno existiert noch eine Vielzahl weiterer Boardvarianten. Neben dem Uno selbst sollen hier zwei weitere interessante Vertreter dieser Familie genauer besprochen werden. Eine Nummer kleiner als der Uno ist der Arduino Mikro (Bild 4). Dieser hat den Vorzug, dass er direkt in ein Breadboard gesteckt werden kann. Er eignet sich daher hervorragend für den Aufbau von Prototypen oder fertigen Kleingeräten. Im Rahmen dieser Artikelserie wird der Arduino
Mini-USB-Buchse
„L”-LED
Controller
Reset
Mikro noch bei verschiedenen Projekten zum Einsatz kommen. Falls mehr Rechenleistung oder eine höhere Anzahl von Ports benötigt wird, kann der Arduino Mega (Bild 5) eingesetzt werden. Dieser ist wesentlich größer als der Uno und bietet zusätzliche Pins für umfangreichere Projekte. Ansonsten existiert noch eine Fülle weiterer Bauformen, wie etwa das runde Lillypad oder der Esplora, der bereits über mehrere fest verdrahtete Taster, Sensoren etc. verfügt. Weitere Details zu den einzelnen Boards finden sich unter [3].
Schneller Einstieg mit der Arduino-Entwicklungsumgebung Bild 4: Arduino Mikro
USB-Buchse
„L”-LED
Rx-/Tx-LED
Externe Spannungsversorung Bild 5: Arduino Mega
Controller Reset
Neben der standardisierten Hardware liegt der große Vorteil des Arduino-Systems in der benutzerfreundlichen IDE. Im Gegensatz zu einer klassischen „ToolChain“ kann diese ohne umfangreiche Vorkenntnisse bedient werden. Außerdem erfordert sie keine langwierige Installation. Die ersten Programme können so direkt nach dem Start der Entwicklungsumgebung auf den Mikrocontroller geladen werden. Die aktuelle Version der IDE kann gratis heruntergeladen werden unter: arduino.cc/en/Main/Software Es stehen verschiedene Versionen für die gebräuchlichsten Betriebssysteme (Windows, Mac OS und Linux) zur Verfügung. Für Linuxfreunde ist die Arbeit unter Ubuntu besonders einfach, da bereits bei der Systeminstallation ein Download-Icon im APPs-Bereich zur Verfügung gestellt wird. Die Bedienoberfläche der Ubuntu-IDE ist weitgehend identisch mit der Windows-Variante, sodass die hier dargestellte Vorgehensweise auch für Ubuntu anwendbar ist. ELVjournal 5/2013
36 | So funktioniert’s
Bild 6: Typisches Arduino-Verzeichnis
Bild 7: Icon für den Start der Arduino-IDE
Unter Windows liegen die vollständigen Programmpakete als komprimierte ZIP-Archive vor und können in ein beliebiges Verzeichnis extrahiert werden (Bild 6). Das Verzeichnis enthält dann alle zur Programmierung erforderlichen Komponenten. Weiterhin werden unter „examples“ noch verschiedene Beispielprogramme mitgeliefert. Darüber hinaus können die Möglichkeiten des Arduinos mit sogenannten Bibliotheken ergänzt werden. Mehr zu diesem Thema findet sich in späteren Beiträgen dieser Artikelserie. Nach dem Entpacken des ZIP-Archivs steht im Verzeichnis ..\arduino-1.0.x. das Startprogramm für die IDE, arduino.exe, zur Verfügung (Bild 7). Nach erfolgreichem Start erscheint kurz ein Informationsfenster mit den üblichen Angaben zu den Eckdaten der verwendeten Programmversion (Bild 8). Anschließend wird die Oberfläche der IDE angezeigt. Jetzt kann der Arduino über ein USB-Kabel mit dem PC verbunden werden. Das USB-Kabel sollte nicht zu lang sein. Kabellängen von mehr als 0,5 m können zu Übertragungsproblemen führen. Insbesondere der Arduino Micro reagiert auf längere Kabel sehr empfindlich und verweigert unter Umständen den Verbindungsaufbau. TIPP III:
Bild 8: Leeres IDE-Fenster
Bild 9: Aufforderung zur Treiberinstallation
Bild 10: Auswahl des COM-Ports
www.elvjournal.de
Der Arduino meldet sich mit einer Aufforderung zum Installieren eines Treibers (Bild 9). Diese Installation ist nach wenigen Schritten abgeschlossen und nimmt nur einige Minuten Zeit in Anspruch. Falls es dabei wider Erwarten zu Problemen kommen sollte, finden sich unter [4] Hinweise zur Fehlerbehebung. Nach erfolgreicher Treiberinstallation kann mit der IDE weitergearbeitet werden. Zunächst muss die richtige Arduino-Boardvariante ausgewählt werden. Dies erfolgt unter den Menüeinträgen „Tools“ und dann „Board“. Dann ist die Selektion des verwendeten virtuellen COM-Ports erforderlich. Meist ist dies die letzte Position in der Liste. Falls mehrere Ports angeboten werden, hilft das Durchtesten aller angezeigten COMNummern (Bild 10). Alle für die Programmentwicklung notwendigen Steuersymbole finden sich unterhalb der Menüleiste am oberen Rand der IDE. Diese Icons werden im nächsten Beitrag der Artikelserie genauer erläutert. Zunächst sind nur die für das Laden eines ersten Programms erforderlichen Icons wichtig. Mit dem Symbol „OPEN“ wird ein bereits vorhandenes Programm geöffnet. Bitte wählen Sie hierfür den Sketch „blink.ino“. Dieser ist unter examples\01.Basics\ Blink zu finden. Nach dem Laden des Programms sollte die IDE so aussehen wie in Bild 11. Mit dem Button „UPLOAD“ wird das Programm in den Speicher des Mikrocontrollers übertragen. Die mit
So funktioniert’s | 37
Rx/Tx bezeichneten LEDs leuchten dabei in unregelmäßigen Abständen auf und zeigen den Datenverkehr auf der seriellen Schnittstelle an. Gleichzeitig wird am PC die Meldung Uploading to I/O Board eingeblendet. Der Abschluss der Übertragung wird mit der Nachricht Done Uploading angezeigt. Danach beginnt die LED „L“ regelmäßig zu blinken und die beiden Rx-/Tx-LEDs erlöschen (Bild 12). Nach Abschluss der Datenübertragung wird also ein Reset durchgeführt und automatisch mit der Ausführung des Programms „Blink“ begonnen. Damit wurde bereits ein erstes Programm auf einen Mikrocontroller übertragen, und weiteren Projekten zum Thema Mikrocontroller und Arduino steht nichts mehr im Wege. TIPP IV: Weitere Details zur Inbetriebnahme
und zur Fehlerbeseitigung finden sich auch im Mikrocontroller-Onlinekurs [5]. Ausblick
Im nächsten Artikel zu dieser Serie werden die Details zur Arduino-Entwicklungsumgebung genauer besprochen. Daneben wird das Thema Fehlersuche und -beseitigung im Vordergrund stehen. Im Praxisteil entstehen dann bereits erste eigene Programme wie ein Alarmanlagensimulator oder eine Morsesignalbake.
Bild 11: Blink.ino ist geladen.
Weitere Infos:
[1] G. Spanner: AVR-Mikrocontroller in C programmieren, Franzis-Verlag, 2010 [2] G. Spanner: Arduino – Schaltungsprojekte für Profis, Elektor-Verlag, 2012 [3] arduino.cc/en/Main/Products [4] forum.arduino.cc/ [5] Mikrocontroller-Onlinekurs, Franzis-Verlag, exklusiv für ELV, 2011 Bild 12: Die LED „L“ blinkt im Sekundentakt.
Alle Infos zu den Produkten/Bauteilen finden Sie im Web-Shop.
Empfohlene Produkte/Bauteile:
Best.-Nr.
Arduino-Uno-Platine R3 Arduino Micro Arduino-Mega-2560-Platine Hama-USB-Hub, 7fach mit Netzteil USB-2.0-Verbindungskabel A auf B
JY-10 29 70 JY-10 97 74 JY-10 69 18 JY-08 25 54 JY-09 55 56
Preis
29,95 € 24,95 € 49,95 € 24,95 € 0,95 €
Preisstellung August 2013 – aktuelle Preise im Web-Shop
ELVjournal 5/2013
62 So funktioniert‘s
Arduino verstehen und anwenden Teil 2: Die Programmierumgebung
www.elvjournal.de
So funktioniert‘s 63
Im zweiten Teil der Beitragsreihe zum Thema Arduino wird die IDE (Integrated Development E nvironment), also die sogenannte Entwicklungsumgebung, genauer betrachtet. In den Abschnitten · Die Entwicklungsumgebung auf dem PC, · „Arduino-Processing“ und „C“: ein Vergleich, · Die Funktionen der IDE, · Die Standard-Beispielprogramme der IDE, · Fehlerbeseitigung werden zunächst alle wichtigen Eigenschaften dieser Entwicklungsumgebung dargestellt. Abschließend entstehen dann mit den Abschnitten · Der Alarmanlagensimulator, · Intuitive Programmierung: der Arduino sendet Morsesignale erste eigene Programme.
// blink int led = 13; void setup() { pinMode(led, OUTPUT); } void loop() { digitalWrite(led, HIGH); delay(1000); digitalWrite(led, LOW); delay(1000); }
Hier kann man ohne große Vorkenntnisse schon vermuten, dass eine Leuchtdiode (LED) in einem bestimmten Rhythmus geschaltet wird. Ein entsprechendes Standard-C-Programm sieht da schon wesentlich kryptischer aus:
Die Entwicklungsumgebung auf dem PC Die Programmierung des Arduino erfolgt über eine speziell für die Arduino-Boards entwickelte IDE. Diese Entwicklungsumgebung ist mit Sicherheit einer der wesentlichen Erfolgsfaktoren des ArduinoProjektes. Die Oberfläche kann einerseits sehr intuitiv bedient werden und erleichtert daher den Einstieg in die Welt der Mikrocontrollerprogrammierung ganz erheblich. Andererseits basiert sie auf der im Controllerbereich am weitesten verbreiteten Programmiersprache „C“. Anders als beispielsweise beim Einsatz von BASCOM kann der Anwender später somit problemlos auf professionelle IDEs wie etwa das ATMEL-Studio umsteigen. Die mit der Arduino-Umgebung erlernten Befehle und Strukturen können dort weitestgehend wiederverwendet werden. Das bereits erlernte Programmierfachwissen ist also nicht verloren. Für die Programmierung der Arduino-Boards kommt „Processing“ zum Einsatz. Dabei handelt es sich aber eben nicht um eine spezielle Anfänger-Programmiersprache, sondern prinzipiell um klassisches „C“. Um den Einstieg zu erleichtern, wurden aber einige spezielle Prozeduren und Routinen implementiert. Die bei vielen Einsteigern gefürchtete „Unlesbarkeit“ von C-Code wurde so wesentlich entschärft.
Insbesondere die für C typischen Bitmanipulationen und die logischen Operatoren (|, &, ~, << etc.) lassen den embedded C-Code schwer lesbar erscheinen. Andererseits wird aber auch bereits bei diesem einfachen Programmbeispiel die enge Verwandtschaft zwischen Arduino-Processing und C deutlich. In der Tat ist es sogar so, dass sich im Hintergrund der einfachen Arduino-IDE ein kompletter AVR-GCC-Compiler verbirgt. Die simplen „Einstiegsanweisungen“ wie „digitalWrite()“ sind dabei nur vorgefertigte Funktionen und Unterprogramme von der gleichen Art, wie sie in späteren Abschnitten zu dieser Artikelreihe noch näher erläutert werden.
„Arduino-Processing“ und „C“: ein Vergleich Der direkte Vergleich zeigt die Ähnlichkeit von Processing mit C. Es wird aber auch deutlich, dass Processing-Programme für Einsteiger wesentlich leichter zu lesen sind. Die in C so beliebten Abkürzungen werden vermieden, sie werden durch wesentlich leichter verständliche Anweisungen ersetzt. So ist ein einfaches Arduino-Programm mit Grundkenntnissen in Englisch bereits recht gut lesbar:
Die Funktionen der IDE Wie bereits im ersten Teil dieser Artikelserie er wähnt, kann die jeweils aktuelle Version der Entwicklungsumgebung kostenlos unter http://arduino.cc/en/Main/Software heruntergeladen werden [1]. Nach dem Download liegt das komplette Programmpaket als komprimiertes ZIP-Archiv vor und kann in ein beliebiges Verzeichnis extrahiert werden (Bild 1). Das Verzeichnis enthält dann alle zur Programmierung des Arduinos erforderlichen Komponenten.
// blink
#include
#include int main(void) { DDRB = 0b1; while (1) { PORTB|=(1<<0);
PORTB&=~(1<<0);
} return 0; }
ELVjournal 1/2014
64 So funktioniert‘s TIPP I: Beachten Sie, dass die IDE-Releases oft nicht abwärtskompatibel sind. Das heißt, ein Sketch, der mit Version 1.0.3 tadellos funktionierte, kann beispielsweise mit der Version 1.0.5 Probleme bereiten. Man sollte also immer im Auge behalten, welcher Sketch mit welcher IDE-Release erstellt wurde.
Darüber hinaus sind unter „examples“ noch verschiedene Beispielprogramme verfügbar. Das Unterverzeichnis „libraries“ enthält nützliche Programmbibliotheken, die unter anderem die Ansteuerung von · Modellbauservos. · Schrittmotoren. · LCD-Anzeigen. · externen EEPROM-Speichern · und vielem mehr … unterstützen. Dieses Verzeichnis ist für den Anwender auch deshalb von besonderer Bedeutung, da hier später weitere nützliche Software-Bibliotheken eingestellt werden können. Weitere Details dazu finden sich z. B. im Mikrocontroller-Onlinekurs [2]. Der Start der IDE erfolgt über die Datei arduino.exe. Natürlich kann man sich dazu auch eine Verknüpfung auf dem Desktop erstellen. Nach dem Starten meldet sich das Programm mit einem Infobild (Bild 2). Danach wird die Programmierumgebung angezeigt (Bild 3). Da das erste, noch leere Programm noch keinen Namen hat, wird ein DefaultWert verwendet: sketch_MonatTagx X steht dabei für einen Buchstaben aus der for tlaufenden Buchstabenreihe x = a, b, c … für den 1., 2., 3. … neuen Sketch des aktuellen Tages. Zur Info: Anwendungsprogramme werden im Arduino-Umfeld auch als „Sketch“ bezeichnet.
Bild 1: Das Arduino-Verzeichnis
Die für die Programmierung eines Arduino erforderlichen nächsten Schritte sind bereits aus dem ersten Beitrag bekannt: 1. Auswahl der richtigen Arduino-Board-Version 2. Auswahl des verwendeten virtuellen COM-Ports Sollte es beim Start der IDE unerwartete Probleme geben, so kann man im Arduino-Online-Forum kompetente Hilfe erhalten [3]. Die Funktionen der IDE
Bild 2: Start der Programmierumgebung mit den Credentials
Bild 3: Programmierumgebung mit Default-Einstellungen
www.elvjournal.de
In Ergänzung zum ersten Beitrag sollen hier nun auch die anderen Funktionen der IDE detaillierter dargestellt werden. Die Bedeutungen der Symbole am oberen Rand der IDE können Bild 4 entnommen werden. Die zum Teil bereits im ersten Beitrag verwendeten Icons haben die folgenden Funktionen: · Prüfen/Compilieren Mit dieser Schaltfläche kann der aktuell geöffnete Sketch compiliert, d. h. in Maschinensprache übersetzt werden. Dies ist insbesondere nützlich, wenn man ein Programm z. B. auf Syntaxfehler hin testen möchte, ohne dass ein Arduino-Board mit dem PC verbunden ist. · Aktuellen Sketch zum Controller senden Dieses Icon compiliert und sendet den aktuellen Sketch direkt zum Arduino. Ein vorheriges, separates Übersetzen ist also nicht erforderlich. · Neuer Sketch Hier kann ein neuer Sketch begonnen werden. · Sketch öffnen Mit diesem Icon wird ein bereits abgespeicherter Sketch in die IDE geladen. · Aktuellen Sketch speichern Das Speichern eines Sketches erfolgt mit diesem Icon.
So funktioniert‘s 65
·
Seriellen Datenmonitor st arten
Hier kann der ser ielle Datenmonitor gestartet werden. Er dient zur Kommunikation zwischen Controller und PC und wird häufig auch zu Test- und Prüfzwecken eingesetzt.
Die Standard-Beispielprogramme der IDE Die Standard-IDE enthält bereits eine umfangreiche Sammlung von Beispielprogrammen (Bild 5). Es ist sicher immer eine gute Idee, diese Beispielprogramme genauer unter die Lupe zu nehmen. Sehr häufig findet sich hier bereits eine geeignete Basis für neue Projekte. Die Erfahrung zeigt sogar, dass auch der fortgeschrit tene Programmierer bei der Entwicklung komplexer Projekte häufig einen Einstieg über diese Beispielprogramme findet. Die nachfolgenden ersten eigenen Programme werden auch aus diesen Standardbeispielen abgeleitet werden. Wie Bild 1 zeigt, kann man die Beispielprogramme auch problemlos in der Verzeichnisstruktur wiederfinden.
Fehlerbeseitigung Bereits im ersten Beitrag wurde gezeigt, wie man einen Sketch auf den Arduino lädt. Im Erfolgsfall wird dies mit einer Meldung (Bild 6) quittiert. Obwohl die Arduino-IDE sehr benutzerfreundlich ist, können natürlich Probleme nicht immer ausgeschlossen werden. Der häufigste Fehler ist die Auswahl des falschen seriellen Ports. In diesem Fall wird eine Fehlermeldung ausgegeben (Bild 7). An zweiter Stelle der Fehlerstatistik steht die Auswahl des falschen Boardtyps. In diesem Fall sieht die Fehlermeldung so wie in Bild 8 aus. Man erkennt, dass die Fehlermeldungen oft nicht sehr spezifisch sind. Allerdings geben sie in den meisten Fällen doch recht brauchbare Hinweise auf die Ursache des Problems. Neben diesen beiden häufigsten Fehlern treten in der Praxis öfter auch „seltsame“ Fehler ohne definierte Ursache auf. Oft hilft es dann, den zuletzt ausgeführten Vorgang noch mal zu starten. TIPP II Falls der Arduino einmal nicht mehr ansprechbar sein sollte, hilft es oft, die USB-Verbindung zu lösen und das Board wieder neu mit dem Computer zu verbinden.
Bild 4: Symbole der IDE
Bild 5: Die Standard-Beispielprogramme
Weitere Tipps und Tricks zur Arbeit mit der IDE sind u. a. in der Literatur zum Arduino-Projekt zu finden [4]. Tiefergehende Informationen zur Programmierung und zum Controller selbst finden sich in [5].
Der Alarmanlagensimulator
Bild 6: Upload o. k.
Das Arbeiten mit der IDE sollte nun keine Schwierigkeiten mehr bereiten. Es ist jetzt also an der Zeit, erste eigene Sketche zu entwickeln. Hierfür bietet sich der Aufbau eines Alarmanlagensimulators an. Solche Geräte werden durchaus auch in der Praxis eingesetzt. Sie bestehen letz tendlich nur aus einer LED (Bild 9), die in regelmäßigen
Bild 7: Fehlermeldung bei falschem Port
ELVjournal 1/2014
66 So funktioniert‘s Bild 8: Fehlermeldung bei falsch gewählter Boardversion
Bild 9: Geeignete LEDs für Mikrocontroller-Schaltungen
Bild 10: Aufbau zum Alarmanlagensimulator
Abständen kurz aufblitzt. Wird ein solches Gerät an geeigneter Stelle eingebaut, beispielsweise in einem Fahrzeug, so entsteht der Eindruck einer scharf geschalteten Alarmanlage. Zumindest Gelegenheitsdiebe lassen sich damit von einem Einbruch abschrecken. Neben einem Arduino Micro werden hierfür noch vier weitere Bauelemente benötigt: 1. Rote LED 2. 150--Widerstand 3. Ca. 5 cm Klingeldraht 4. Ein lötfreies Steckbrett Der Aufbau der kleinen Schaltung ist in Bild 10 zu sehen.
2. Der Pin für die LED wurde von 13 auf 2 geändert. Damit ist nun die dort angeschlossene externe LED aktiv. 3. Die Werte in der Funktion „delay“ wurden von jeweils 1000 auf 100 bzw. 3000 geändert. Damit wird aus dem regelmäßigen Blinken ein kurzes Aufblitzen.
Das zugehörige Programm sieht so aus: // Alarmanlagensimulator
Wenn die Schaltung korrekt aufgebaut wurde und der neue Sketch geladen wird, blitzt die angeschlossene LED im Abstand von jeweils 3 Sekunden kurz auf. Der Alarmanlagensimulator ist einsatzbereit (Bild 11). Will man die elektronischen Komponenten nicht einzeln besorgen, so kann man beispielsweise auf das Lernpaket „Mikrocontroller in C programmieren“ [6] zurückgreifen. In diesem Lernpaket sind neben einem Arduino auch alle weiteren für den Einstieg in die Mikrocontroller-Welt erforderlichen Bauelemente (Widerstände, Kondensatoren, LEDs etc.) enthalten. Darüber hinaus finden sich in diesem Lernpaket weitere interessante Komponenten wie etwa ein 4-stelliges 7-Segment-Display oder eine LED-Punktmatrix für die mikrocontrollergesteuerte Anzeige von Zahlen und Zeichen (Bild 12).
int led = 2; void setup() { pinMode(led, OUTPUT); } void loop() { digitalWrite(led, HIGH); delay(100); digitalWrite(led, LOW); delay(3000); }
Man kann das Programm in ein leeres Sketchfenster eintippen oder man modifiziert den bereits bekannten Blink-Sketch. Die Unterschiede zum Blink-Sketch bestehen in den folgenden Änderungen: 1. Die Kommentarzeilen, welche mit „//“ beginnen, wurden angepasst. www.elvjournal.de
Intuitive Programmierung: der Arduino sendet Morsesignale
Hier können die bereits erworbenen Kenntnisse praxisnah eingesetzt werden. Die Aufgabe besteht darin, den Alarmanlagensimulator in eine automatische SOS-Bake umzubauen. Das heißt, die LED soll zunächst 3x kurz, dann 3x lang und schließlich wieder 3x kurz aufblinken. Dann soll sich die Signalfolge wiederholen. Versuchen Sie zunächst, den Code für den Alarmanlagensimulator so abzuändern, dass die LED das gewünschte Signal sendet. Anschließend können Sie dann Ihre Lösung mit dem folgenden Musterprogramm vergleichen. // SOS int led = 2; void setup() { pinMode(led, OUTPUT);
So funktioniert‘s 67
} void loop() { digitalWrite(led, HIGH); delay(100); digitalWrite(led, LOW); delay(500); digitalWrite(led, HIGH); delay(100); digitalWrite(led, LOW); delay(500); digitalWrite(led, HIGH); delay(100); digitalWrite(led, LOW);
delay(1000);
digitalWrite(led, HIGH); delay(400); digitalWrite(led, LOW); delay(500); digitalWrite(led, HIGH); delay(400); digitalWrite(led, LOW); delay(500); digitalWrite(led, HIGH); delay(400); digitalWrite(led, LOW);
Bild 11: Der Alarmanlagensimulator ist scharf geschaltet.
delay(1000);
digitalWrite(led, HIGH); delay(100); digitalWrite(led, LOW); delay(500); digitalWrite(led, HIGH); delay(100); digitalWrite(led, LOW); delay(500); digitalWrite(led, HIGH); delay(100); digitalWrite(led, LOW);
delay(1000);
d elay(2000); }
Natürlich ist dies nicht die eleganteste Methode, aber man sieht, dass so bereits ohne genaue Kenntnis der verwendeten Programmiersprache eigene Projekte realisierbar sind. In späteren Beiträgen zu dieser Reihe wird natürlich noch genauer darauf eingegangen, wie man ein derartiges Programm wesentlich effizienter implementieren kann.
Empfohlene Produkte/Bauteile: Arduino Micro Mikrocontroller-Onlinekurs LEDs, z. B. Kemo Leuchtdioden, ca. 30 Stück Widerstände, Kemo-Sortiment, ca. 200 Stück
Bild 12: Zahlendarstellung mit dem Dot-Matrix-Display aus dem Lernpaket „AVR-Mikrocontroller in C programmieren“ [6]
Best.-Nr. JQ-10 97 74 JQ-10 20 44 JQ-10 66 60 JQ-10 66 57
Preis € 24,95 € 99,– € 1,65 € 1,85
Steckbretter sind in verschiedenen Franzis Lernpaketen enthalten oder im WebShop unter www.elv.de/experimentierboards.html erhältlich.
Dennoch erfüllt das Programm seinen Zweck. Verwendet man als LED einen besonders lichtstarken Typ, so kann die Schaltung beispielsweise in Seeoder Bergnot durchaus nützlich sein. Weitere Anwendungen und Projekte mit dem Arduino wie verschiedene LED-Effekte etc. finden sich beispielsweise in [2] und [6]. Ausblick Nachdem nun die Arbeit mit der Arduino-IDE problemlos von der Hand geht, wird im nächsten Beitrag zu dieser Reihe die eigentliche Programmiersprache im Vordergrund stehen. Dabei sollen dann neben einigen grundlegenden Betrachtungen zur Programmstruktur insbesondere die Arduino-spezifischen Befehle besprochen werden.
Alle ARDUINO-Produkte wie Mikrocontroller-Platinen, Shields, Fachbücher und Zubehör finden Sie unter: www.arduino.elv.de Preisstellung November 2013 – aktuelle Preise im Web-Shop.
Weitere Infos:
[1] http://arduino.cc ist die offizielle Homepage des Arduino-Projektes [2] Mikrocontroller-Onlinekurs, Franzis-Verlag, exklusiv für ELV, 2011, Best.-Nr.: JQ-10 20 44 [3] http://forum.arduino.cc [4] G. Spanner: Arduino – Schaltungsprojekte für Profis, Elektor-Verlag, 2012, Best.-Nr.: JQ-10 94 45 [5] G. Spanner: AVR-Mikrocontroller in C programmieren, Franzis-Verlag, 2010, Best.-Nr.: JQ-09 73 52 [6] Lernpaket „AVR-Mikrocontroller in C programmieren“, Franzis-Verlag, 2012, Best.-Nr.: JQ-10 68 46
ELVjournal 1/2014
72 So funktioniert‘s
Arduino verstehen und anwenden Teil 3: Einführung in die Programmierung
www.elvjournal.de
So funktioniert‘s 73
Der dritte Teil der Artikelreihe zum Arduino führt in die Struktur der Programmiersprache „Processing“ ein. Die Themen in diesem Beitrag sind: · Die Grundstruktu Grundstrukturr eines Processin Processing-P g-Progra rogramms mms · Praxisbeis Praxisbeispiel piel LED-Anste LED-Ansteuerun uerung: g: 12-Kanal-Lauflicht Im Praxisteil wird diesmal bereits ein etwas komplexerer Aufbau realisiert. Mit 12 LEDs entsteht ein ein flexibel einsetzbares Lauflicht. Als Anwendungsübung können verschiedene Laufgeschwindigkeiten und unterschiedliche Lichtmuster programmiert werden.
Die Grundstruktur eines ProcessingProcessingProgramms Im Folgenden soll das schon aus dem ersten Beitrag bekannte Programm „Blink“ genau analysiert werden. // Blink: Using LED „L“
}
}
Die erste Zeile // Blink: Using LED „L“ stellt einen sogenannten Kommentar dar. Kommentare werden durch den doppelten Slash „//“ gekennzeichnet. Der nach diesem Zeichen stehende Text wird vom Compiler nicht beachtet. Er dient also nur dazu, Programme leichter lesbar zu gestalten.
Nicht zu sparsam mit Kommentaren umgehen! Langfristig sind nur gut kommentierte Programme wirklich nützlich.
TIPP I:
Die nächste Zeile int ledPin = 13; // Definitions definiert den Pin 13 als „ledPin“. „ledPin“. Damit kann man nun überall im Sketch ledPin schreiben, wenn der Pin 13 gemein gemeintt ist.
Es ist sicher leicht einzusehen, dass durch solche Definitionen die Programmierarbeit erheblich erleichtert wird. Kommen im Laufe der Programmentwicklung mehrere LEDs ins Spiel, so kann man sich deren Pin-Nummern kaum mehr merken. Sinnvolle Bezeichnungen dagegen können wesentlich leichter im Kopf behalten werden. Die Anweisung void setup() ist eine Spezialität von Processing. Processing. Hier w ird unter anderem festgelegt, welche Aufgaben die einzelnen Arduino-Pins erfüllen sollen. In unserem Fall wird der oben definierte ledPin als Ausgang genutzt: pinMode(ledPin, pinMode(ledPin, OUTPUT); In einem Processing-Sketch muss immer auch die Anweisung void setup() enthalten sein, selbst wenn sie überhaupt keine Definitionen enthält. Durch ihren Aufruf werden nämlich verschiedene interne Zuordnungen ausgeführt, die die Arbeit mit dem Arduino erleichtern. Mit void loop() startet das Hauptprogramm. Typisch für Mikrocontroller ist, dass das Hauptprogramm praktisch immer innerhalb einer Endlosschleife („loop“) abläuft. Da ein Mikrocontroller nicht über ein eigenes Betriebssystem verfügt, würde er am Ende eines Programms einfach stehenbleiben oder undefinierte Aktionen ausführen. Erst nach einem Reset könnte die sinnvolle Abarbeitung von Befehlen wieder aufgenommen werden. Um dieses Verhalten zu verhindern, muss das Hauptprogramm also in einer Endlosschleife ablaufen, die dafür sorgt, dass der Prozessor so lange arbeitet, bis die Betriebsspannung abgeschaltet wird. Mit der Anweisung digitalWrite(ledPin, HIGH); HIGH); wird nun der ledPin auf „HIGH“, d. h. hohes Potential, in unserem Fall auf 5 V geschaltet. Damit beginnt die LED zu leuchten. Mit der Anweisung delay(1000); erhält der Prozessor den Auftrag, 1000 ms = 1 s zu warten. Schließlich wird mit digitalWrite(ledPin, LOW); die LED wieder ausgeschaltet und das Spiel beginnt nach einer Pause von 1 s von vorne, da wir uns ja in einer Endlosschleife befinden. Die LED blinkt also nun mit einer Periodendauer Periodendauer von von 2 s oder einer Frequenz von 0,5 0,5 Hz. Im Projekt „Alarmanlagensimulator“ „Alarmanlagensimulator“ im letzten Beitrag wurde ja bereits gezeigt, wie man die Blinkfrequenz und -dauer den gegebenen Erfordernissen anpassen kann.
Praxisbeispiel: Lauflicht für Modellflughäfen oder -eisenbahnen Wie bereits beim Alarmanlagensimulator Alarmanlagensimulator werden auch hier externe LEDs verwendet. Nachdem bislang aber immer mit nur einer externen LED gearbeitet wurde, soll der Arduino nun mehrere LEDs steuern. Mit 12 LEDs kann bereits ein eindrucksvolles Lauflicht aufgebaut werden. Derartige Lauflichter sind z. B. auf den Landebahnen Landebahnen von Großflughäfen oder an Autobahnbaustellen zu finden. Dort soll der laufende ELVjournal 2/2014
74 So funktioniert‘s
Mit den gewählten 220- -Widerständen (Farbringfolge Rot-RotBraun) liegt man also auf der sicheren Seite. Will man Lichtmuster Lichtmuster erzeugen, in welchen welchen alle 12 LEDs gleichzeitig gleichzeitig betrieben betrieben werden werden,, so so ergibt ergibt sich ein Gesamtstro Gesamtstrom m von von 12 x 20 mA = 240 mA. Dies stellt bereits eine eine erhebliche Belastung für den USB-Port USB-Port dar. In diesem Fall sollte man darüber nachdenken, den Arduino mit einem externen Netzteil zu betreiben. Eine andere Möglichkeit wäre die Verwendung von sogenannten LowCurrent-LEDs. Current-LEDs. Diese benötigen bei sehr guten Helligkeitswerten nur einen Strom von 4 mA. D Die ie Vorwiderstände ergeben sich in diesem Falle zu: Rv = (5 V – 1,7 V) / 4 mA = 825 Mit 1-k-Widerständen erreicht man immer noch eine gute Helligkeit und der Gesamtstromverbrauch bei 12 aktiven LEDs reduziert sich auf unter 50 mA.
Das Steuerprogramm zum Lauflichteffek Lauflichteffek t
Bild 1: LED-Lauflicht
Lichtpunkt Flug- oder Fahrzeugen den richtigen Weg weisen. Aber auch in Part ykellern, Diskotheken Diskotheken oder auf Volksfesten erfreuen sich entsprechende Lichteffekte großer Beliebtheit. Jede der 12 LEDs bekommt bekommt ihren eigenen eigenen Vorwiderstand. Prinzipiell wäre es auch möglich, mit einem einzigen Widerstand auszukommen. Dieser müsste dann in die gemeinsame Masseleitung aller Dioden eingesetzt werden. Falls immer nur eine LED aktiv sein soll, ist die Lösung mit nur einem Vorwiderstand durchaus akzeptabel. Allerdings ergibt sich ein Problem, wenn mehr als eine LED leuchten soll. In diesem Fall müssen sich alle aktiven LEDs sozusagen einen Widerstand teilen. Je mehr LEDs eingeschaltet werden, desto größer wäre der Gesamtstrom durch den Widerstand. Dies würde aber natürlich zu einem immer höheren Spannungsabfall am Widerstand f ühren, so dass die verbleibende LED-Spannung immer weiter abnehmen würde. Je mehr LEDs also eingeschaltet würden, desto dunkler würde jede einzelne LED werden. Wird für jede LED ein eigener Vorwiderstand verwendet, tritt dieser meist unerwünschte Effekt nicht auf. Weitere Details und Informationen zum Ansteuern von LEDs finden sich auch in [1]. Bild Bild 1 zeigt den Aufbau.
TIP II: Falls eine oder mehrere LEDs nicht leuchten, sind sie wahrscheinlich falsch herum eingebaut. Ein Umpolen der entsprechenden LEDs behebt das Problem.
Vorwiderstä Vo rwiderstände nde und Low-C Low-Current-LE urrent-LEDs Ds Noch ein Wort zur Berechung der Vorwiderstände. Die meisten einfachen LEDs benötigen einen Strom von ca. 20 mA. Der Spannungsabfall Spannungsabfall über einer einer roten roten LED LED beträgt immer etwa 1,7 1,7 V. Damit Damit ergibt sich: Rv = (5 V – 1,7 V) / 20 mA = 165 www.elvjournal.de
Um den Code etwas kompakter zu gestalten, soll hier kurz auf eine neue Anweisung vorgegriffen werden. Die Anweisung for(int for(int i= a; i<= b; i++) sorgt dafür, dass der nachfolgende Befehlsblock wiederholt ausgeführt wird. Zudem kann die sogenannte Laufvar iable i in diesem Befehl sblock zu Steuerzwecken verwendet werden. So werden beispielsweise mit for(int i=1; i<=3; i++) die nachfolgenden Anweisungen 3-mal ausgeführt. Die genaue Beschreibung, wie diese und andere sogenannte Kontrollstrukturen arbeiten, folgt im nächsten Beitrag zu dieser Art ikelserie. Hier genügt es zunächst zu wissen, dass die „for“-Anweisung zum definierten Wiederholen von Befehlen angewendet werden kann. Damit sollte das Programm zum Lauflichteffekt keine Verständnisprobleme mehr bereiten:
}
} }
Im Setup werden zunächst die Ports 2 bis 13 als Ausgänge geschaltet: void setup() { for(int i= 2; i< =13; i++) pinMode(i, OUTPUT); //…. //…. }
Tipp III: Die Digital-Pins 0 und 1 besitzen eine zusätzliche Sonderfunktion. Neben der einfachen Portfunktion dienen sie auch als Ein- und Ausgang für die serielle Schnittstelle. Dies kann bei einigen Anwendungen zu unerwarteten Ergebnissen führen. Es ist daher sinnvoll, diese Ports nicht zu verwenden, solange dies nicht unbedingt erforderlich ist.
Im Hauptprogramm wird dann zunächst mit digitalWr ite(i, HIGH); HIGH); // set the LED on
So funktioniert‘s 75 die erste LED in der Kette eingeschaltet. Nach einer Wartezeit von 100 ms – delay(100); delay(100); – wird sie wieder ausgeschaltet. Dann folgt die zweite LED, bis sich das Spiel nach der zwölften LED wiederholt. Auf diese Weise entsteht der gewünschte Lauflichteffekt.
}
Natürlich ist dies nur eine Möglichkeit, um ein Lauflicht zu realisieren. Im nächsten Beitrag zu dieser Artikelreihe lernen Sie die sogenannten Kontrollstrukturen von C kennen. Damit kann das obenstehende LED-Lauflicht-Beispiel elegant und einfach um weitere interessante Lichteffekte ergänzt werden. Aber auch bei dieser einfachen Version sind wieder verschiedene Varianten realisierbar. So können beispielsweise die folgenden Übungen durchgeführt werden.
}
} }
1. Verändern Sie Sie die Geschwindigkei Geschwindigkeitt des Lauflichts 2. Programmieren Programmieren Sie ein sogenanntes sogenanntes Pendel-LaufPendel-Lauflicht. Das bedeutet, dass der Lichtpunkt nicht nur in eine Richtung laufen und dann wieder bei der ersten LED starten soll, sondern dass er hin und her pendelt.
LED-Band Abschließend soll noch eine weitere Programm-Variante vorgestellt werden. Hier wird ein sich in der Länge veränderndes Lichtband erzeugt (Bild 2). 2). In der Praxis werden solche Lichtbänder in ähnlicher Form häufig für die Anzeige von analogen Messwerten wie etwa Ladezuständen von Akkumulatoren oder Maschinendrehzahlen Maschinendrehzahlen eingesetz t. Der Vorteil der einzelnen Vorwiderstände Vorwiderstände tritt tr itt dabei deutlich zu Tage. Selbst wenn alle 12 LEDs leuchten, ist die Helligkeit jeder LED gegenüber gegenübe r der Helligkeit bei nur einer aktiven LED unverändert.
Ausblick In diesem Beitrag kam erstmals eine etwas umfangreichere umfangreichere externe Beschaltung des Arduinos zum Einsatz. Die grundlegende Programmstruktur und einige Arduino-spezifische Befehle wurden genauer erläutert. Der nächste Beitrag in der Reihe wird näher auf die Programmierung eingehen und es werden weitere Befehle im Detail vorgestellt. Damit können dann auch komplexere Programme für eigene Projekte erstellt werden.
Empfohlenes Material Im Mikrocontroller-Onlinekurs [2] [2] werden werden die hier vorgestellten Grundlagen weiter vertieft. Das Hardwarepaket zu diesem Kurs enthält ein umfangreiches Bauteilesortiment für den erfolgreichen Einstieg in die Mikrocontrollertechnik. Auch viele Franzis Lernpakete wie etwa „Elektronik“ enthalten geeignetes Material – wie ein lötfreies Steckbrett, Widerstände, LEDs etc. –, das für den Aufbau von Schaltungen mit dem Arduino Micro gut geeignet ist.
Weite Weitere re Info Infos: s:
[1] [1] G. Spanner: Spanner: Arduino Arduino – Schaltungspro Schaltungsprojekte jekte für Profis, Profis, Elektor-Verlag, 2012, Best.-Nr. J2-10 J2-10 94 45 [2] [2] Mikroco Mikrocontrol ntroller ler-Onl -Onlinek inekurs, urs, Franzis-Verlag, exklusiv für ELV, 2011, Best.-Nr. J2-10 20 44
Preisstellung Februar 2014 – aktuelle Preise im Web-Shop
Empfohlene Produkte/Bauteile :
Best .-Nr.
Preis
Arduino-Uno-Platine R3 USB-2 B-2.0-V 0-Verbi erbind nduungskabe kabell A auf auf B Mikrocontroller-Onlinekurs LEDs, z. B. Kemo Leuchtdioden, ca. 30 Stück Widerstände, Kemo-Sortiment, ca. 200 Stück
J2-10 29 70 J2-09 -09 55 55 56 56 J2-10 20 4 4
€
J2-10 66 60
€
1,65
J2-10 66 57
€
1,85
27,95 € 0,95 € 99,–
Steckbretter sind in verschiedenen verschiedenen Franzis Lernpaketen enthalten oder im Web-Shop unter www.elv.de/experimentierboards.html erhältlich.
Bild 2: Das variable LED-Band in Aktion
Alle ARDUINO-Produkte wie Mikrocontroller-Platinen, Mikrocontroller-Platinen, Shields, Fachbücher Fachbücher und Zubehör finden Sie unter: www.arduino.elv.de
ELVjournal 2/2014
92 So funktioniert‘s
Arduino verstehen und anwenden Teil 4: Programmierpraxis: Befehle, Variablen und Funktionen
www.elvjournal.de
So funktioniert‘s 93 Im vierten Teil der Serie „Arduino verstehen und anwenden“ geht es um den Einstieg in die Programmierpraxis. Hier werden die Strukturen vorgestellt, ohne die keine höhere Programmiersprache auskommt: · Syntaxelemente · Konstanten und Variablen · Operatoren · Kontrollstrukturen Wie sonst auch soll in diesem Beitrag die Prax is nicht zu kurz kommen. So werden die einzelnen Abschnitte wieder durch Anwendungsbeispiele für den Arduino ergänzt und vertieft.
Die Sprachelemente von „Processing“ bzw. „C“
Nach dem Durcharbeiten der ersten drei Artikel dieser Serie ist man nun bereits in der Lage, einfachere Programme zu verstehen, zu modifizieren und in den Controllerchip des Arduinos zu laden. Es ist nun also an der Zeit, sich etwas näher mit den Details der Programmierung zu beschäftigen. Nachfolgend werden daher die wesentlichen allgemeinen Sprachelemente von Processing erläutert. Weitere Erklärungen zu speziellen Befehlen und Anweisungen folgen in den jeweiligen Anwendungen.
Programm-Struktur
Wie wir in vorhergehenden Artikeln am Beispiel „Blink“ schon gesehen haben, besteht ein Sketch aus zwei Hauptteilen: 1) void setup() 2) void loop() Die Setup-Funktion wird beim Programmstart genau einmal aufgerufen. Hier werden Schnittstellen und Pin-Funktionen etc. initialisiert. Void setup() muss immer im Programm stehen, auch wenn nichts explizit definiert werden muss. Die Routine hat nämlich auch die Aufgabe, Standardfunktionen zur Verfügung zu stellen. In der Endlosschleife loop() wird der eigentliche Programmcode festgelegt. Alle in der „loop“ enthaltenen Anweisungen und Befehle werden nacheinander immer wieder ausgeführt, bis der Controller von der Versorgungsspannung getrennt wird.
Einfache Syntaxelemente
· INPUT/OUPUT Sind für die pinMode()-Funktion vorgesehen und legen fest, ob ein PIN als Eingang (INPUT) oder Ausgang (OUTPUT) genutzt werden soll.
Variablendefinition Die Festlegung von Variablen ist bereits aus fr üheren Artikeln bekannt, z. B. wird mit der Programmzeile: int ledPin = 10; eine Variable „ledPin“ festgelegt und auch gleich auf den Wert 10 gesetzt. Variablen zeichnen sich dadurch aus, dass sie während des Programmablaufes verändert werden. Da Variablen in der Programmierung von höchster Wichtigkeit sind, wurden verschiedene Variablen-Typen festgelegt. Diese sind in Tabelle 1 zusammengefasst. Die verschiedenen Typen dienen dazu, die begrenzten Speicherplatzressourcen eines Mikrocontrollers optimal zu nutzen. Man sollte also immer den Typen auswählen, der nicht mehr Speicher belegt als notwendig. Außerdem ergeben sich bei der korrekten Auswahl von Variablen-Typen auch Geschwindigkeitsvorteile. So kann der Arduino Integer-Berechnungen deutlich schneller ausführen als Float-Operationen. Bei einfachen Programmen, die nur wenige Berechnungen enthalten, fällt das natürlich kaum ins Gewicht. Wenn allerdings komplexere Rechenvorgänge mit umfangreichen Daten erforderlich sind, so kann die Verwendung einer reinen Integer-Arithmetik über den Erfolg oder Misserfolg eines Projektes entscheiden. Klassische Beispiele, die eine hohe Rechengeschwindigkeit erfordern, sind schnelle digitale Regelungen. Wird hier mit optimierten Integer-Werten gearbeitet, kann der Arduino bereits recht komplexe Aufgaben wie etwa die Lageregelung eines Quadrokopters übernehmen.
Ähnlich wie eine natürliche Sprache ihre Satzzeichen hat, so benötigt auch Processing einen gewissen Grundvorrat an Syntaxelementen: · Semicolon ; Variablenfelder Das Semicolon schließt jeden Befehl ab. · Geschweifte Klammern {} Variablenfelder, auch als „arrays“ bezeichnet, stellen Geschweifte Klammern fassen einen Befehlsblock zusammen. Beieine Zusammenfassung von Variablen dar, auf die mit spiele hierzu finden sich weiter unten bei den Kontrollstrukturen. Hilfe einer Index-Zahl zugegriffen werden kann. · Einzeiliger Kommentar // Alle nachfolgenden Anweisungen legen jeweils ein Mit dem Doppel-Slash wird ein einzeiliger Kommentar gekennzeichnet. Array fest: · Mehrzeiliger Kommentar /* */ int myIntegers[4]; Erstreckt sich ein Kommentar über mehrere Zeilen muss dieser mit int OutPins[] = {1, 3, 5, 7, 9}; /* begonnen und mit */ beendet werden. int mySpecialValues[6] = {1, 3 ,3, -4, -1, 5}; Konstanten und Variablen char infotext[6] = „hallo“; Zu den wichtigsten Elementen einer Programmiersprache gehören die Konstanten und Variablen. Konstanten dienen zur Kennzeichnung unveränderlicher Werte. In Processing wurden einige vordefinierte KonDie wichtigsten Variablen-Typen stanten festgelegt. Diese machen den Programmcode einfacher lesbar Typ Bytes Bereich und erleichtern zudem den Einstieg in die Arduino-Programmierung. Die wichtigsten vordefinierten Konstanten sind: Byte 1 0 bis 255 · TRUE/FALSE Char 1 -127 bis 127 1 FALSE ist als 0 (Null) definiert, 2 -32.768 bis 32.767 e Int l l TRUE ist ungleich 0. 4 -2.147.483.648 bis 2.147.483.647 e Long · HIGH/LOW b a Float 4 -3,4028235E+38 bis 3,4028235E+38 HIGH bedeutet Logiclevel 1, d. h. ON oder 5 V, T LOW bedeutet Logiclevel 0, d. h. OFF oder 0 V. ELVjournal 3/2014
94 So funktioniert‘s Mit diesen Definitionen werden jeweils Felder mit 4, 5, 6 und wieder 6 Variablen erzeugt. Der Zugriff auf ein Feldelement erfolgt durch Zuweisungen unter Benutzung des jeweiligen Index, z. B: OutPins[0] = 1; x = mySpecialValues[4]; Wichtig:
Die Indizes eines Array beginnen mit 0, das heißt, das erste Feldelement hat immer den Index „0“. Daraus ergibt sich, dass für ein Feld mit beispielsweise 4 Variablen der letzte Index 3 lautet. Wird eine Feldvariable mit dem Index 4 abgerufen, ergibt sich ein zufälliger Wert! Beispiel: int myNumbers[4]={1,4,5,2}; // myArray[3] enthält den Wert 2, // myArray[4] ist ungültig und liefer t einen zufälligen Wert!
Mathematische Operatoren Um mit Variablen rechnen zu können, werden Operatoren benötigt. Die wichtigsten Operatoren sind die Rechenzeichen. Sie haben in Processing die üblichen mathematischen Bedeutungen: + Addition - Subtraktion * Multiplikation / Division % Modulo, d. h. Rest der Division Auch für die Vergleichsoperatoren gelten die normalen mathematischen Bedeutungen: = = ist gleich != ungleich < kleiner > größer <= kleiner gleich >= größer gleich =
Zuordnung
Lediglich die Zeichen wie etwa „“ für „kleiner gleich“ wurden durch ASCII-kompatible Doppelzeichen wie „<=“ ersetzt. Hinweis:
Die Zuordnung „=“ darf nicht mit dem Gleichheitsoperator „= =“ verwechselt werden! Im ersten Fall wird einer Variablen ein Wert zugewiesen, z. B.: ledPin = 10; Im zweiten Fall wird auf Gleichheit überprüft, z. B.: if (a == 1) Die Boole’schen Logikoperatoren werden durch die folgenden Zeichen realisiert: && (and) || (or) ! (not) www.elvjournal.de
Auch sie besitzen die aus der Mathematik bekannte Bedeutung. Die in C üblichen Abkürzungen, auch als Compound-Operatoren bekannt, sind in Processing ebenfalls verfügbar: + + Increment: x+ + steht für x = x+1 -- Decrement: x-steht für x = x-1 + = Compound Addition: x + = y steht für x = x+y -= Compound Subtraktion: x -= y steht für x = x-y *= Compound Multiplikation: x*= y steht für x = x*y /= Compound Division: x/= y steht für x = x/y
Kontrollstrukturen Zur Steuerung von Programmabläufen sind in Processing bzw. C verschiedene Strukturen vorgesehen. IF/ELSE und FOR sind die beiden wichtigsten. · if überprüft ob eine bestimme Bedingung erfüllt ist: if (Variable > 99) { // Anweisungen… } · if...else gestattet eine weitergehende Kontrolle des Programmflusses. Es können mehrer Bedingungen unterschieden werden: if (Input < 500) { // Aktion A } else { // Aktion B } · for erlaubt es, eine Anweisung zu wiederholen. Die Anzahl der Wiederholungen ist dabei nicht von irgendwelchen Bedingungen abhängig: for (init; cond; inc) { //Anweisungen… } Zunächst wird eine Startbedingung „init“ gesetzt. Jedesmal wenn die Schleife durchlaufen wurde, wird die Bedingung „cond“ geprüft und die Aktion „inc“ ausgeführt. Wenn die Bedingung nicht mehr erfüllt ist, wird die Schleife beendet. · while () while-Schleifen werden so lange durchlaufen, bis die Abbruchbedingung erfüllt ist: while(logischer Ausdruck) { // Anweisungen… } · do... while Die do…while-Schleife funktioniert ähnlich wie die while-Schleife mit dem Unterschied, dass die Bedingung erst am Ende der Schleife geprüft wird. Die do…while-Schleife wird also immer mindestens einmal durchlaufen. · do {// Anweisungen… } while (logischer Ausdruck); · break Mit break kann jede do-, for-, oder while-Schleife verlassen werden.
Programmierpraxis Nachdem nun verschiedene Programmelemente theoretisch beleuchtet wurden, sollen diese in einem Praxisbeispiel umgesetzt werden. Das folgende Programm „squares“ soll eine Tabelle der Quadrat zahlen von 1 bis 9 in gut lesbarer Form ausgeben.
So funktioniert‘s 95
// sqares int x; int y[10]; void setup() {
Serial.begin(9600); Serial.println("Squares table"); Serial.println();
} void loop() { for (int x = 1; x<=9; x++) {
y[x] = x*x; Serial.print(x, DEC);
Serial.print("
");
Serial.println(y[x], DEC); } while(1); }
Zunächst wird eine Variable vom Typ Integer definiert. Dann folgt die Deklaration eines Arrays y, für das 10 Elemente reserv iert werden. Die Anweisungen im Setup-Teil sorgen für die Kommunikation zum PC. Sie werden etwas weiter unten erläutert. Die Zeile for (int x = 1; x<=9; x++) definiert eine Schleife, welche die Zahlen 1 bis 9 durchläuft. Mit y[x] = x*x; werden den Elementen des Arrays y die Quadrate des Laufindex x zugewiesen. Der Laufindex der Schleife wird zudem in der nächsten Programmzeile, Serial.print(x, DEC); an den PC ausgegeben. Die Zeile Serial.print(" "); sorgt durch Einfügen von Leerzeichen für eine lesbare Formatierung der ausgegebenen Werte. Schließlich werden die im Array gespeicherten Quadratzahlen ausgegeben: Serial.println(y[x], DEC); Die Anweisung while(1) sorgt dafür, dass das Programm hier stehenbleibt. Bild 1 zeigt den Code nach erfolgreicher Compilierung in der IDE. Nach dem Laden des Programms in den Arduino muss noch der sogenannte „Serielle Monitor“ gestartet werden. Dazu muss auf das Lupensymbol rechts oben in der IDE geklickt werden (siehe Bild 2). Hier erfolgt dann die Ausgabe der gewünschten Quadratzahlen-Tabelle, so wie in Bild 3 dargestellt. Um den Ausgabekanal zu aktivieren, wurde im setup die Zeile Serial.begin(9600); eingefügt. Danach können dann über die Serial.print-Anweisung Werte und Texte wie beispielsweise Serial.println("Squares table"); am PC-Bildschirm ausgegeben werden. Über Serial.print(x, DEC); wird der Wert der Variablen x zum seriellen Monitor gesendet. Der Zusatz „DEC“ sorgt dabei dafür, dass die Variable im Dezimalsystem ausgegeben wird. Wird dem Pr int-Befehl die Endung „ln“ (für engl. „line“) angefügt, so wird eine neue Ausgabezeile begonnen. Weitere Details zu Nutzung dieser seriellen Schnittstelle folgen in einem späteren Artikel.
Bild 1: Das Programm „squares“ in der IDE
Bild 2: Start des seriellen Monitors
Bild 3: Ausgabe von Quadratzahlen
ELVjournal 3/2014
96 So funktioniert‘s
Übungen und Variationen
Falls Sie mit den Programmelementen von C noch nicht besonders gut vertraut sind, sollten Sie die folgenden Übungen durchführen: · Lassen Sie sich die Quadratzahlen von 10 bis 100 berechnen und ausgeben. · Ersetzen Sie die for-Schleife durch eine whileSchleife. · Ersetzen Sie den Compound-Operator x++ durch die entsprechende Langschreibweise. · Berechnen Sie nur die Quadrate der ungeraden Zahlen zwischen 11 und 25! · Für Zahlen größer 4 soll nicht das Quadrat, sondern die 3. Potenz ausgegeben werden (Hinweis: if-Verzweigung!).
· pow(base, exponent); sqrt(x) berechnen die Potenzfunktion und die Quadratwurzel · sin(rad); cos(rad); tan(rad) liefern entsprechend die Sinus-, Kosinus- und Tangenswerte im Bogenmaß
Zufallszahlen
Die Funktion · randomSeed(seed) startet den Pseudo-Zufallsgenerator; mit seed wird dabei der Startpunkt in einer pseudo-zufälligen Zahlenreihe festgelegt · long random(min, max) erzeugt eine Pseudo-Zufallszahl Spezielle Funktionen Processing verfügt über spezielle Funktionen, die vor zwischen min und max allem den Einstieg in die Programmiersprache C sehr erleichtern. Diese Funktionen werden der Übersicht- Praxisübungen lichkeit halber im Folgenden zusammengefasst: · Ändern Sie das Programm · pinMode(pin, mode) „squares“ so ab, dass es die konfiguriert den „pin“ entweder als Eingang oder Quadratwurzeln der ganzen als Ausgang (mode = INPUT oder mode = OUTPUT) Zahlen zwischen 0 und 9 be· digitalWrite(pin, value) rechnet! setzt den „pin“ auf high oder low (value = HIGH Welcher Variablentyp ist dabei oder value = LOW) für y sinnvoll? · int digitalRead(pin) · Erstellen Sie eine Tabelle der Bild 4: Arduino zeichnet eine Sinus-Kurve! liest den Pegel von „pin“ und gibt entsprechend Sinuswerte für die Winkel zwiHIGH oder LOW zurück schen 0° und 360° in 10°-Schritten! · Dass der Arduino auch einfache Grafiken ausgeben kann, zeigt Bild 4. Schaffen Sie es, das zugehörige Programm zu erstellen? Zeitsteuerung Bereits im Programm „Blink“ wurde von Zeitverzögerungen Gebrauch gemacht. Die folgenden Befehle Ausblick stehen dafür zu Verfügung. Im nächsten Artikel wird erklärt, wie Programm-Bibliotheken für den · unsigned long millis() Arduino nutzbringend eingesetzt werden können. Auch die Erstellung gibt die Anzahl der Millisekunden an, die vergan- eigener Bibliotheken wird erläutert werden. gen sind, seit das aktuelle Programm gestartet wurde Empfohlenes Material Natürlich können die Programmelemente einer so umfangreichen Sprache wie C bzw. Processing in Rahmen eines einzelnen Beitrags nicht in Hinweis Die Variable millis springt nach ca. 50 Tagen auf allen Details dargelegt werden. Weitergehende Informationen zum Thenull zurück. Bei Langzeitanwendungen ist dies ma finden sich jedoch im Mikrocontroller-Onlinekurs [1]. Weiterführenunbedingt zu beachten, da es sonst zu unerwarde praktische Beispielprogramme und interessante Anwendungen sind teten Effekten kommen kann! in [2] zu finden. Die bereits in mehreren Beispielen verwendete Funktion · delay(ms) bewirkt eine Verzögerung von ms, also Millisekunden, im Programmablauf · delayMicroseconds(us) sorgt für eine Verzögerung von us, also Mikrosekunden, im Programmablauf
Mathematische und trigonometrische Funktionen
Abschließend sollen hier noch die wichtigsten mathematischen Funktionen angesprochen werden. Diese haben auch in Processing ihre übliche Bedeutung: · min(x, y); max(x, y); abs(x) liefern das Minimum, das Maximum von x und y bzw. den Absolutwert von x www.elvjournal.de
Weitere Infos:
[1] Mikrocontroller-Onlinekurs, Franzis-Verlag, exklusiv für ELV, 2011, Best.-Nr. J3-10 20 44 [2] G. Spanner: Arduino – Schaltungsprojekte für Profis, Elektor-Verlag, 2012, Best.-Nr. J3-10 94 45 Preisstellung April 2014 – aktuelle Preise im Web-Shop
Empfohlene Produkte/Bauteile:
Best.-Nr.
Arduino-Uno-Platine R3 USB-2.0-Verbindungskabel A auf B Mikrocontroller-Onlinekurs
J3-10 29 70 J3-09 55 56 J3-10 20 44
Preis
27,95 € 0,95 € 99,– €
Alle ARDUINO-Produkte wie Mikrocontroller-Platinen, Shields, Fachbücher und Zubehör finden Sie unter: www.arduino.elv.de
92 So funktioniert‘s
Arduino verstehen und anwenden Teil 5: Nutzung und Erstellung von Programmbibliotheken
www.elvjournal.de
So funktioniert‘s 93 Bild 1: „LiquidCrystal“ in der Arduino-IDE
Der fünfte Teil der Artikelserie „Arduino verstehen und anwenden“ dreht sich um das Thema Programmbibliotheken. Sogenannte Bibliotheken oder Libraries gehören zu den besonderen Stärken der Arduino-Idee. Diese Programmierhilfen erleichtern das Erstellen komplexerer Projekte ganz erheblich. So muss man nicht immer das Rad neu erfinden, sondern man kann auf bereits vorhandenen Grundlagen aufbauen. Zu den sogenannten Standardbibliotheken zählen u. a: · EEPROM – Schreiben und Lesen des EEPROMSpeichers im Controllerchip · LiquidCrystal – Ansteuerung eines textbasierten LC-Displays · SD – Schreiben und Lesen einer SD-Speicherkarte (erfordert ein entsprechendes Shield) · Servo – Ansteuerung von Modellbauservos · SoftwareSerial – ermöglicht die Nutzung einer softwarebasierten seriellen Schnittstelle an einem beliebigen Digitalpin des Arduinos · Stepper – Steuerung von Schrittmotoren (erfordert passende Treiberbausteine)
· Wire – ermöglicht die Kommunikation mit Two-Wire- bzw. I2C-Interface-Bausteinen und -Sensoren wie z. B. DACs oder Echtzeituhren-ICs Eine der besonders häufig genutzten Bibliotheken ist die LiquidCrystal-Library. Sie ermöglicht das einfache Ansteuern eines LC-Displays. Damit kann der Arduino auch unabhängig vom PC Zahlen und Texte ausgeben. Hochinteressanten praktischen Anwendungen wie etwa einer Digitaluhr oder einem digitalen Innen-und-Außenthermometer mit LCD-Anzeige steht damit nichts mehr im Weg. Diese nützliche Bibliothek soll daher im Folgenden als einführendes Beispiel dienen. Einbinden einer Bibliothek in einen Arduino-Sketch Die LCD-Bibliothek wird bereits mit der Standard-Arduino-IDE mitgeliefert. Sie arbeitet mit allen LC-Displays, die mit dem bekannten HD44780-Treiber von Hitachi kompatibel sind. Die Anschlusskonfiguration dieser Module hat sich als Quasi-Standard durchgesetzt. Pr aktisch alle gängigen Anzeigeeinheiten mit 14 oder 16 Pins und 1 oder 2 Zeilen à 16 Zeichen sind somit mit der hier vorgestellten Bibliothek verwendbar. Bild 1 zeigt, wie die Beispielprogramme der Bibliothek „LiquidCrystal“ im Hauptmenü der IDE ausgewählt werden können. Im zugehörigen Untermenü finden sich dann verschiedene Beispielprogramme dieser Library.
Bild 2: Anschluss eines LC-Displays an den Arduino Micro
ELVjournal 4/2014
94 So funktioniert‘s Bild 3: Die LCDBibliothek in Aktion
Zunächst muss aber natürlich das LC-Display mit dem Arduino verbunden werden. Bild 2 zeigt das zugehörige Aufbaubild. Eine praktische Ausführung des Aufbaus ist in Bild 3 zu sehen. Nachfolgend sind die notwendigen Verbindungen der Deutlichkeit halber nochmals in Tabellenform angegeben: LCD RS Digitalpin 12 LCD Enable Digitalpin 11 LCD D4 Digitalpin 5 LCD D5 Digitalpin 4 LCD D6 Digitalpin 3 LCD D7 Digitalpin 2 LCD R/W Ground
entsprechend 16 Zeichen in 2 Zeilen, kann im Setup bereits direkt auf das LC-Display geschrieben werden.
Anwendung der Bibliothek LiquidCrystal.h
Hier zeigt sich deutlich, wie die Verwendung einer Bibliothek die Programmierung ganz wesentlich vereinfacht. Nur wenige Programmzeilen genügen, um ein alphanumerisches Display anzusteuern. Wollte man diese Aufgabe ohne die Hilfe der Bibliotheksfunktionen lösen, so würde daraus ein Projekt, das auch einen erf ahrenen Programmierer viele Stunden lang beschäftigen würde. Wenn man sich einen ersten Eindruck verschaffen möchte, wie die Ansteuerung eines LC-Displays im Detail aussieht, dann kann man die Datei „LiquidCrystal.cpp“ im Verzeichnis …Arduino\arduino-1.0.5\libraries\LiquidCrystal mit einem Editor, wie etwa dem Windows-WordPad, öffnen. Hier zeigt sich, welcher Aufwand durch den Einsatz der fertigen Bibliothek eingespart werden konnte.
Unter Verwendung der Bibliothek LiquidCrystal.h kann das zugehörige Hauptprogramm sehr einfach ausfallen: // Hallo Arduino MICRO #include
LiquidCrystal lcd(12, 11, 5, 4, 3, 2); void setup() { lcd.begin(16, 2); lcd.setCursor(5, 0); lcd.print("Hallo, ");
Mit lcd.setCursor(5, 0); wird die aktuelle Schreibposition auf das 5. Zeichen in der 1. Zeile gesetzt (die Zeilenzählung beginnt wie in der IT üblich mit 0). Dann erfolgt die Ausgabe des Textes einfach mit lcd.print("Hallo, "); und lcd.print(" Arduino MICRO! ");
lcd.setCursor(0, 1); lcd.print(" Ardui no MICRO!
");
} void loop() {}
Nach dem Einbinden der Bibliothek mit #include müssen also nur noch die Pin-Verbindungen zum LCD angegeben werden: LiquidCrystal lcd(12, 11, 5, 4, 3, 2); Nach der Initialisierung mit lcd.begin(16, 2); www.elvjournal.de
Erstellen eigener Bibliotheken Fertige Bibliotheken sind aber natürlich nur die eine Seite der Medaille. Während der Einsteiger sicherlich überwiegend bereits vorgefertigte Libraries nutzt, wird der fortgeschrit tene Anwender irgendwann den Punkt erreichen, an welchem eine eigene Bibliothek erstellt werden soll. Nachfolgend werden daher die Schritte zur Erstellung eigener Bibliotheken vorgestellt. Bereits im 2. Teil zu dieser Beitragsreihe wurde ein einfaches Programm zum Senden des SOS-Notfallsignals im Morsecode entwickelt. Hier soll dieses Beispiel noch einmal aufgegriffen werden, um die Erstellung einer Programmbibliothek zu erläutern.
So funktioniert‘s 95
Da alle erforderlichen Programmstrukturen und Befehle aus dem 3. und 4. Teil dieser Artikelserie bekannt sind, kann das SOS-Programm nun schon deutlich kompakter und eleganter aufgebaut werden als noch im früheren Beitrag: // SOS int pin = 13; void setup() { pinMode(pin, OUTPUT); } void loop() { S();O();S(); delay(1000);}
vate Teile kann nur innerhalb der Klasse zugegriffen werden. Jede Klasse verfügt über eine spezielle Funktion, den sogenannten Constructor. Dieser wird benutzt, um jeweils eine Instanz einer Klasse zu erzeugen. Der Constructor hat den gleichen Namen wie die zugehörige Klasse und gibt kein Argument zurück. In einen klassischen Sketch wird das Standard-File Arduino.h immer automatisch mit eingebunden. Bei einer Bibliotheksdatei dagegen muss man dies manuell erledigen, um sicherzustellen, dass alle erforderlichen arduinospezifischen Definitionen zur Verfügung stehen. Um Probleme mit der Mehrfacheinbindung einer Bibliothek zu vermeiden, wird der gesamte Code in eine entsprechende if-Abfrage eingebettet. Damit muss die Datei MorseCode.h wie folgt aussehen:
void S() { for(int i = 1; i <= 3; i++)
// morse code generation
{ digitalWrite(pin, HIGH); delay(200); digitalWrite(pin, LOW);
delay(200);
}
#ifndef MorseCode_h
delay(500); }
#include "Arduino.h"
void O()
class Morse
{ for(int i = 1; i <= 3; i++)
{ public:
{
digitalWrite(pin, HIGH); delay(1000);
Morse(int pin);
digitalWrite(pin, LOW);
void S();
delay(200);
} delay(500);
void O(); private:
}
int _pin; };
SOS_short.ino #endif
Nun sollen verschiedene Teile des Sketches in eine Library ausgegliedert werden. Hierfür bieten sich natürlich die beiden Routinen S() und O() an. Diese beiden Programmteile übernehmen die Aufgabe, die Morsesequenzen für die Buchstaben S und O zu erzeugen. Nachdem die Prozeduren über void S() und void O() definiert wurden, können sie über die Anweisungen S() und O() aufgerufen werden. Die Bibliothek soll aber auch noch eine einfache Möglichkeit bieten, den Port, an welchen das Signal ausgegeben werden soll, zu wählen.
MorseCode.h
Nun muss noch die zugehörige .ccp-Datei erstellt werden. Hier muss natürlich zunächst die zugehörige .h-Datei eingebunden werden. Auch die Arduino.h ist nochmals manuell zu aktivieren. Dann folgt die Definition der einzelnen Funktionen. Um festzulegen, dass diese Teil einer Klasse sind, muss man den Namen der Klasse gefolgt von einem doppelten Doppelpunkt voranstellen (::). Damit sieht die ccp.-Datei so aus: // morse code generation
Aufbau einer Bibliothek Eine Library muss immer mindestens zwei Dateien enthalten: 1. das Header-File mit der Extension .h 2. das Source-File mit der Extension .cpp Im Header-File werden alle für die Library erforderlichen Definitionen festgelegt. Hierfür wird zunächst eine sogenannte Class (engl. für „Klasse“) benötigt. In einer Klasse können mehrere Funktionen und Variablen zusammengefasst werden. Hier hat man zwei Möglichkeiten zu unterscheiden: Public Class („öffentliche Klasse“) und Private Class („private Klasse“) Die als öf fentlich definierten Teile können von allen Nutzern der Bibliothek verwendet werden. Auf pri-
#include "Arduino.h" #include "MorseCode.h" Morse::Morse(int pin) { pinMode(pin, OUTPUT); _pin = pin; } void Morse::S() { for(int i = 1; i <= 3; i++) { digitalWrite(_pin, HIGH); delay(200); digitalWrite(_pin, LOW); delay(200); }
ELVjournal 4/2014
96 So funktioniert‘s
delay(500); } void Morse::O() { for(int i = 1; i <= 3; i++) {
digitalWrite(_ pin, HIGH); delay(1000); digitalWrite(_pin, LOW); delay(200);
} delay(500);
In diesem Verzeichnis müssen sich die Dateien MorseCode.h MorseCode.cpp keywords.txt befinden.
}
MorseCode.cpp
Mit diesen beiden Dateien ist die Bibliothek bereits fertiggestellt. Das SOS-Programm wird damit unschlagbar einfach:
Zusätzlich sollte noch ein Unterverzeichnis „examples“ angelegt werden, in welches die Beispieldatei SOS_w_lib.ino abgelegt wird. Damit ist die Bibliothek prinzipiell vollständig.
// SOS #include Morse morse(13); void setup(){} void loop() { morse.S(); morse.O(); morse.S(); delay(1000); }
Ideal ist es natürlich, wenn dazu noch weitere Informationen geliefert werden, in welchen alle Funktionen genau dokumentiert sind. Die Erfahrung zeigt allerdings, dass diese Dokumentation bei den meisten im Internet veröffentlichten Libraries fehlt. Trotzdem können viele dieser kleinen Helfer nach kurzer Einarbeitung und dem Studium der einzelnen Dateien, insbesondere der Beispieldatei, sehr nutzbringend angewendet werden.
SOS_w_lib.ino
Ausblick Man muss also nur noch die Bibliothek einbinden, und die darin enthaltenen Funktionen stehen für die freie Verwendung zur Verfügung. Der Arduino hat nun sozusagen das Morsealphabet gelernt und sendet beispielsweise auf den Befehl morse.S(); automatisch drei kurze Lichtimpulse, also das optische Morsezeichen für „S“ aus. Natürlich kann man auch den Rest des Alphabets in die Bibliothek integrieren und ist dann in der Lage, sehr komfortabel ganze Texte in Morsecode mit dem Arduino zu versenden. Abschließend sei noch auf die Datei keywords.txt hingewiesen. Diese ist für die Funktion der Bibliothek nicht unbedingt erforderlich, bietet aber den Komfort, dass die in der Bibliothek verwendeten Schlüsselwörter in der gewohnten Farbcodierung erscheinen. Hierzu muss man die verwendeten Funktionsnamen in eine keywords.txt-Datei eintragen und mit „KEYWORD1“ für die Klasse bzw. „KEYWORD2“ für die Funktionen kennzeichnen:
Die Arbeit mit Programmbibliotheken sollte nun keine Probleme mehr bereiten. Der Einsatz dieser nützlichen Hilfsmittel ist immer dann zu empfehlen, wenn es darum geht, Standardprobleme zu lösen. Es ist in jedem Fall lohnend, vor der Implementierung eines neuen Projekts zu prüfen, ob entweder für das gesamte Vorhaben oder aber auch nur für wichtige Teile geeignete Bibliotheken existieren. Der nächste Artikel wird sich um das Thema „Sensortechnik und Messwerterfassung“ drehen. Auch dazu sind umfangreiche Bibliotheken vorhanden. Allerdings erfordert der Einsatz spezieller thermischer oder optoelektronischer Sensoren, etwa im Bereich der Hausautomatisierung oder der Robotersteuerung, doch auch entsprechende Kenntnisse im Bereich der Erfassung und Wandlung analoger Daten.
Empfohlenes Material · Arduino Micro, Best.-Nr. J4-10 97 74, € 24,95 · Mikrocontroller-Onlinekurs, Best.-Nr. J4-10 20 44, € 99,– · Auch viele Lernpakete von Franzis wie etwa „Elektronik mit ICs“ enthalten Materialien wie ein lötfreies Steckbrett , Widerstände und LEDs etc., die für den Aufbau von Schaltungen mit dem Arduino Micro gut geeignet sind.
Morse KEYWORD1 S
KEYWORD2
O
KEYWORD2
Preisstellung Juni 2014 – aktuelle Preise im Web-Shop
Weitere Infos: keywords.txt
Will man nun die erzeugte Bibliothek der Allgemeinheit zur Verfügung stellen, so muss man nur die drei Dateien (xxx.h, xxx.ccp und xxx.txt) weitergeben. Zusätzlich wird meist noch eine Beispieldatei mitgeliefert, die die Anwendung der Bibliotheksfunktionen demonstriert. Die Bibliothek besteht also aus einem Verzeichnis „Morsecode“. www.elvjournal.de
· G. Spanner: Arduino – Schaltungsprojekte für Profis, Elektor-Verlag, 2012, Best.-Nr. J4-10 94 45, € 39,80 · AVR-Mikrocontroller in C programmieren, Franzis-Verlag, 2012, Best.-Nr. J4-09 73 52, € 39,95 Alle Arduino-Produkte wie Mikrocontroller-Platinen, Shields, Fachbücher und Zubehör finden Sie unter: www.arduino.elv.de
62 So funktioniert‘s
Arduino verstehen und anwenden Teil 6: Sensortechnik und Messwerterfassung
www.elvjournal.de
So funktioniert‘s 63
Der sechste Teil der Artikelserie „Arduino verstehen und anwenden“ hat das weite Gebiet der Sensortechnik und der controllerbasierten Messwerterfassung zum Thema.
V
Hier ist der Mikrocontroller voll in seinem Element. Denn in diesem Anwendungsbereich unterscheiden sich Controller ganz wesentlich von ihren technischen Gegenspielern, den Prozessoren. Mikrocontroller zeichnen sich insbesondere dadurch aus, dass sie über integrierte Messwandlereinheiten verfügen. So besitzen auch die Controller der Arduino-Serie mehrere Analogeingänge. Damit lassen sich die unterschiedlichsten Messanwendungen realisieren. Zu den Themen dieses Beitrags zählen entsprechend die folgenden Aufgaben: · Erfassung analoger Messdaten · Auswertung von Sensorsignalen · Ausgabe und Verarbeitung von Messwerten
4
818
3
614
5
bit
1023
e l p m a s
t
n
hold
U = 2,58 V = 527 bit n
2
409
1
205
0
t
Bild 1: Erfassung analoger Messwerte
lern sind meist noch sogenannte Analogmultiplexer vorhanden. Diese Im Rahmen der Praxisbeispiele werden die folgenden erlauben dann die nahezu simultane Erfassung von 6, 8 oder sogar mehr Anwendungen vorgestellt: analogen Kanälen. · Erfassung einer Potentiometerposition durch ADCs sind wichtige Bestandteile vieler Geräte der modernen KommuMessung analoger Spannungswerte nikations-, Unterhaltungs- und Haushaltselektronik. Digitale Thermo· Elektronisches Computer-Thermometer mit meter oder Wetterstationen können auf ADCs ebenso wenig verzichten Übertemperaturalarm wie MP3-Player, Mobiltelefone oder digitale Kameras. Zudem werden die · Elektronisches Luxmeter Wandler in der Messwerterfassung in industriellen Anwendungen, zur Steuerung von Maschinen und in Kraftf ahrzeugen benötigt. Die Auflösung eines ADCs bestimmt die maximale Genauigkeit, mit Erfassung von Messwerten Die Erfassung von elektronischen Messdaten gehört der das analoge Eingangssignal digitalisiert werden kann. Die ef fektive mit zu den zentralen Aufgaben eines Mikrocontrol- Präzision ist durch weitere Fehlerquellen des ADCs jedoch geringer als lers. Das Einlesen von digitalen Signalen stellt die die theoretische Auflösung. So führen etwa Nichtlinearitäten oder Abeinfachste Möglichkeit dar. Binäre Spannungspegel gleichfehler zu zusätzlichen Abweichungen. (0 V oder 5 V) können von jedem I/O-Pin erfasst Die Wandlungsdauer für einen einzelnen Messwert hängt vom Wandwerden. Allerdings muss man auch bei dieser ver- lungsverfahren ab. Neben extrem schnellen Verfahren existieren auch gleichsweise einfachen Aufgabe häufig verschiedene langsame, integrierende Methoden, die sich dafür durch hervorragende Probleme beachten. So stellt etwa das sogenannte Unterdrückung von Störeinkopplungen auszeichnen. „Prellen“, also die Mehrfacherfassung eines SchaltDie Auflösung, mit der die analoge Größe gemessen wird, bewegt sich vorgangs aufgrund von mechanischen Effekten, ein zwischen 1 und 24 Bit. Die durch die Wandlung entstehende Abweichung nicht zu unterschätzendes Problem bei der Ansteue- zwischen dem tatsächlichen Messwert und dem digitalen Ausgabewert rung von einfachen Tastern dar. bezeichnet man als Quantisierungsfehler. Er entsteht u. a. durch unAber auch analoge Spannungswerte können von vermeidbare Rundung, Nichtlinearitäten sowie Störeinstreuungen etc. modernen Mikrocontrollern direkt gemessen werden. Bild 1 zeigt, wie der rot dargestellte analoge Spannungsverlauf mit Die meisten gängigen Controllertypen haben dazu einem ADC digitalisiert wird. Der ADC führt zu bes timmten Zeitpunkten einen sogenannten A/D-Wandler (Analog-zu- digital- tn eine Spannungsmessung durch. Dieser Spannungswert wird dann in Umsetzer, auch ADC für engl. Analog to Digital Con- einen Digitalwert umgewandelt. Bei einer Auflösung von 10 Bit und verter) integriert. In den entsprechenden Control- einer Referenzspannung von 5 V ergibt sich so für eine Spannung von ELVjournal 5/2014
64 So funktioniert‘s
ADC-Wandlerverfahren
1 e l l e b a T
Verfahren
Arbeitsweise
Vorteile
Nachteile
Anwendung
Flash- oder Parallelwandler
pro Ausgangswert 1 Komparator
sehr schnell
teuer, hohe Leistungsaufnahme
Digitaloszilloskope, Forschung und Entwicklung
Sukzessive Approximation
stufenweise Annäherung, Wägeverfahren
s chn el l, ge na u
te chn is ch au fw en dig
Standardverfahren, interne A/D-Wandler von Mikrocontrollern
Single Slope, Dual Slope
Spannungsmessung erfolgt über Zeitmessung von Ladevorgängen
preisgünstig, gute Linearitäten
langsam
Multimeter
Delta-Sigma
Komparator und Logik-Elemente
preisgünstig
langsam
Präzisionsmessungen bis zu 24 Bit, Audio
beispielsweise 2,58 V ein abgerundeter digitaler Ergebniswert von Q = 527: Q = 2,58 V / 5 V * 1023 = 527 Je nach Anwendungsfall werden unterschiedliche Anforderungen an einen ADC gestellt. Für die verschiedenen Aufgaben wurden daher unterschiedliche Verfahren entwickelt und implementiert. Die wichtigsten ADC-Verfahren sind in Tabelle 1 zusammengefasst. Wie diese zeigt, besitzen alle Verfahren ihre spezifischen Vor- und Nachteile. Die sukzessive Approximation stellt aber einen guten Kompromiss für viele Anwendungen dar. Sie wird daher in vielen Mikrocontrollern und insbesondere auch bei den im Arduino verwendeten AVR-Typen eingesetzt. Die im Arduino verwendeten ADCs zeichnen sich durch die in Tabelle 2 aufgeführten Leistungsmerkmale aus.
Praktische Anwendung: Erfassung einer Potentiometerposition Nachdem nun die prinzipiellen Eigenschaften von ADCs dargelegt wurden, soll die Funktionsweise der Analog-digital-Converter anhand eines Anwendungsbeispiels verdeutlicht werden. Hierzu sollen die von einem Potentiometer erzeugten analogen Spannungswerte vom Arduino erfasst und zum PC übertragen werden. Als Messkanal kommt der Analog-Eingang ADC0 zum Einsatz. Die dort anliegenden Spannungswerte sollen erfasst und in digitale Messwerte gewandelt werden. Anschließend werden die Werte an einen PC übertragen und am seriellen Monitor dargestellt. Das Programm dazu kann so aussehen:
Eigenschaften des ADC-Wandlers im Arduino
2 e l l Analogeingänge e b Auflösung a T Wandlungszeit
10 Bit max. 260 µs
Die zugehörige Schaltung ist in Bild 2 zu sehen. Das Potentiometer sollte einen Bahnwiderstand von ca. 100 k besitzen. Nach dem Laden des Programms und dem Starten des seriellen Monitors werden die Messwerte sichtbar (Bild 3). Da direkt der ADC-Wert ausgegeben wird, liegen die angezeigten Zahlenwerte im Bereich von 0 bis 210-1 = 1023.
Temperaturmessung Temperaturfühler zählen zu den wichtigsten Sensoren in der elektronischen Messtechnik. Sie überwachen die Temperaturen in den Prozessoren moderner PCs genauso wie in Automotoren, Großrechenanlagen oder in den Prozess-Steuerungen der chemischen Industrie. Einfache Temperatursensoren bestehen meist aus mit Bindemitteln versetzten, gepressten und gesinterten Metalloxiden. Der Nominalwiderstand eines solchen Messelements lässt sich durch das Mischverhältnis verschiedener Materialien in weiten Bereichen einstellen. So entstehen sogenannte NTCs, also Temperatursensoren mit negativem Temperaturkoeffizienten. Ein Standardtyp dieses Bauelements
// ADC int AD C0=0; int value; void setup() { Serial.begin(9600); } void loop() { value=analogRead(ADC0); Serial.print("ADC0 = "); Serial.println(value); delay(5000); }
Bild 2: Aufbau für die Erfassung analoger Messwerte
www.elvjournal.de
6 (A0 –A5)
So funktioniert‘s 65 weist beispielsweise beispielsweise einen Widerstandswert Widerstandswert von 4,7 4,7 k bei einer Temperatur von 25 °C auf.
Elektronisches Thermometer mit Übertemperatu Übertemperaturalarm ralarm Ein solcher NTC eignet sich hervorragend zum Aufbau eines elektronischen Computer-Thermometers. Die Temperaturmesswerte sollen dabei über den Mikrocontroller erfasst und am PC dargestellt werden. Neben der Darstellung der aktuellen Temperatur ermöglicht ein solches Thermometer auch die zeitaufgelöste Messung von Temperaturen. Typische Anwendungen dafür sind die Temperaturüberwachung von Leistungstransistoren, Mikroprozessoren oder ganzen klimatisierten Serverräumen. Zusätzlich kann ein Übertemperaturalarm integriert werden, über welchen im Ernstfall ein zusätzliches Kühlaggregat aktiviert oder aber sogar die Leistung einer kompletten Serverfarm heruntergefahren werden könnte. Die Umrechnung des ADC-Werts in eine Temperatur erfolgt über 2 Konstanten: cal = 6.8 offset = 296 Die beiden Werte ergeben sich aus dem Offset sowie aus der Steilheit der Kennlinie des NTCs. Falls die Temperatur nicht korrekt angezeigt wird, können die beiden Konstanten an das verwendete Sensorexemplar angepasst werden. Prinzipiell ist die Kalibrationsfunktion eines NTCs nichtlinear. Für einen Temperaturbereic Temperaturbereichh von ca. 0 bis etwa 50 °C können können die Abweichu Abweichunngen aber weitgehend vernachlässigt werden. Für höchste Ansprüche bezüglich der Messpräzision kann selbstverständlich auch eine nichtlineare Funktion zur Berechnung der Temperatur implementiert werden. Der nachfolgende Sketch zeigt, wie ein Programm zur Temperaturmessung inklusive eines Übertemperaturalarms aussehen könnte. // Te mperature sensor // for serial interface // using NTC temperature sensor // incl. overtemp indication int ADC0=0;
// select ADC channel
Bild 3: Darstellung der Messwerte im seriellen Monitor
Den Schaltungsaufbau dazu zeigt Bild 4. Der Temperatursensor wird hier in einer einfachen Spannungsteiler-Schaltung betrieben. Der 4,7-k-Festwiderstand sorgt dafür, dass die Eingangsspannung für den ADC bei Raumtemperatur bei ca. der halben halben Betriebsspannung, Betriebsspannung, d. d. h. bei etwa 2,5 V, liegt. Damit Damit lässt sich der Temperaturbereich Temperaturbereich von 0 bis 50 °C gut abdecken. Nach dem Starten des Programms und des seriellen Monitors werden die jeweils aktuellen Temperaturwerte im Abstand von ca. 1 s auf dem Bildschirm Bildschirm angezeigt. Berührt man den Sensor mit den Fingerspitzen, wird der damit einhergehende Temperaturanstieg unverzüglich unver züglich sichtbar. Überschreitet die Temperatur den in der Zeile float overtemp = 30; festgelegten Schwellwert Schwellwert von 30 °C, so wird die LED LED als Warnanzeige Warnanzeige aktiviert. aktivier t.
int AD C_value C_value; ;
void setup() { Serial.begin(9600); pinMode(overtempLED,OUTPUT); } void loop() { ADC_value=analogRead(ADC0); Serial.print("Temp Serial.print( "Temp = ") "); ; Serial.print(temp); Serial.print Seri al.println(" ln(" C ") "); ; if(temp>overtemp)digitalWrite(overtempLED,HIGH); if(temp
Bild 4: Aufbau für ein elektronisches Computer-Thermometer mit Übertemperaturalarm
ELVjournal 5/2014
66 So funktioniert‘s Bild 5 zeigt ein Temperaturüberwachungsgerät Bil für eine kleine Klimakammer. Hier wurden 5 der 6 vorhandenen Analogkanäle mit Temperatursensoren ausgestattet. Der jeweils akt ive Kanal wird über eine LED angezeigt. Als Display für die Temperaturwerte kam hier eine 4-stellige 7-Segment-Anzeige zum Einsatz. Weitere Details zur Ansteuerung einer solchen Anzeige werden in einem späteren Beitrag in dieser Artikelserie erläutert. Der Phototransistor als optischer Sensor
Ein weiterer sehr interessanter Sensor ist der Phototransistor. Dieser gestattet die Erfassung von Helligkeitswerten. Typische Anwendungen dieses Bauelements sind Lichtschranken Lichtschranken,, Belichtungsmesser für Fotokameras oder Empfänger für Infrarotfernbedienungen.
Elektronisches Elektronisch es Luxmeter Luxmet er Mit dem Phototransistor kann die Umgebungshelligkeit bestimmt und der aktuelle Helligkeitswert auf einem PC-Bildschirm dargestellt werden. Der Sensortyp BPW40 eignet sich bestens für diese Aufgabe. Anstelle einer numerischen Anzeige kann man für die Helligkeiten auch eine grafische Darstellung wählen. Im Beispiel wird eine sogenannte ASCIIGrafik verwendet. Das bedeutet, dass eine Zeile aus X-Zeichen ihre Länge proportional zur aktuellen Umgebungshelligkeit gebungshell igkeit verändert. Das Prinzip Pr inzip dieser einfachen Grafikausgabe wurde bereits im Artikel Art ikel „Programmierpraxis: „Programmierpraxis: Befehle, Variablen und Funktionen“ erläutert, sodass das Arduino-Programm dazu keine Verständnissch Verständnisschwierigkeiten wierigkeiten mehr bereitet. // Luxmeter
int AD C_value C_value; ; int ADC _0=0 _0=0; ;
void setup() { Serial.begin(9600); pinMode(AlarmLED, OUTPUT) OUTPUT); ; } void loop() { ADC_value=analogRead(ADC_0); if (ADC_value (ADC_value>0) >0) {
for(int i=0; i<=(ADC_v i<=(ADC_value/10) alue/10); ; i++) Serial.print("X");
Bild 5: Im Eigenbau erstelltes µC-basiertes Computer-Thermometer mit Übertemperaturalarm und 5 Alarmausgängen zur Überwachung von Serverräumen
Den Hardwareaufbau dazu zeigt Bild 6. Im Gegensatz zum NTC weist der Phototransistor eine Polung auf. auf. Falls sich die Messwerte also nicht wie erwartet mit der Umgebungshelligkeit verändern, sollte man den Lichtsensor umpolen. Bild 7 zeigt, wie w ie sich die Länge des Anzeigebalkens verändert, wenn der Sensor mit einer Lampe L ampe beleuchtet wird. Unterschreitet die Umgebungshelligkeit bungshelli gkeit einen einen festgelegten Schwellwert, Schwellwert, wird die LED 13 als „Zusatzbeleuchtung“ eingeschaltet. Natürlich könnte man auf diese Weise auch eine leuchtstarke Power-LED als echte Zusatzlichtquelle ansteuern.
Grafische Darstellung von Messwerten auf dem PC-Bildschirm Wenn man die Messwerte von Sensoren nicht nur über den seriellen Monitor in numerischer Form oder als al s einfache ASCII-Grafike A SCII-Grafikenn darstellen will, sondern echte grafische Ausgaben erwünscht sind, so kann man das Programm „Processing“ einsetzen. Dieses äußerst nützliche und universell einsetzbare Programm kann unter [1 [1]] kostenlos aus dem Internet geladen werden. Dass das Programm der Arduino-IDE stark ähnelt, ist kein Zufall. Die Arduino-Programmieroberfläche ist sehr eng an das am Massachusetts Institute for Technology (MIT) entwickelte Processing angelehnt. Dies hat den Vorteil, dass sich routinierte ArduinoArduino-Anwender Anwender schnell zurechtfinden. Zudem werden ähnlich wie bei der Arduino-IDE auch bei Processing viele v iele interessante Beispielanwendungen mitgeliefert. Alleine das Austesten dieser Beispielprogramme ist schon eine sehr interessante und lehrreiche Beschäftigung und erleichtert den Einstieg in dieses Programm ganz erheblich. Durch vorgefertigte Bibliotheken wird die Einbindung des Arduinos in Processing wesentlich vereinfacht. So können über die virtuelle serielle Schnittstelle problemlos Messdaten übertragen und dann sehr ansprechend auf einem PC-Bildschirm dargestellt werden. Bi Bild ld 8 zeigt beispielsweise die simultane s imultane Darstellung aller 6 ArduinoArduino-Analogkanä Analogkanäle le in Form einer Balkengrafik. Aber auch die zeitliche Veränderung von Messwerten kann grafisch aufbereitet werden. So zeigt Bi Billd 9 einen sogenannten Temperatur-Logger. Damit können Temperaturverläufe über Stunden oder Tage hinweg aufgezeichnet und dargestellt werden. Der Überwachung und Optimierung der hauseigenen Heizungsanlage steht so nichts mehr im Wege.
Serial.println("");
Ausblick
} if(ADC if( ADC_value _value < thresh threshold) old) { digitalWrite(Alarm digitalWrite(AlarmLED,HIGH) LED,HIGH); } else digitalWrite(Alarm digitalWrite(AlarmLED,LOW) LED,LOW); ;
}
www.elvjournal.de
In diesem Artikel wurde gezeigt, wie man verschiedene Sensorwerte über die Analogkanäle des Arduinos auslesen und verarbeiten kann. Die Anwendungen dieses weiten Teilbereichs der Mikrocontrollertechnik sind nahezu unbeschränkt. Von einfachen Temperaturüberwachungen über die Steuerung von Solarzellenanlagen bis hin zu komplexen Aufgaben in der Mess- und Regelungstechnik – überall werden Sensoren benötigt und eingesetzt.
So funktioniert‘s 67
Bild 6: Aufbau für das elektronische Luxmeter
Bild 7: Ausgabe von Helligkeitswerten als ASCII-Grafik
In neuerer Zeit hat sich für diese Anwendungen auch der Begriff „Physical Computing“ etabliert. Hierunter versteht man die Erfassung und physikalische Beeinflussung bzw. Steuerung der Umwelt mittels elektronischer Sensoren und Aktuatoren. Der erste Teil, die Sensorik, wurde bereits in diesem Artikel behandelt. Die Ansteuerung von Aktuatoren wie Schrittmotoren oder Servos folgt in einem späteren Beitrag. Ein weiterer wichtiger Teilbereich des Physical Computing ist die Übertragung von Daten über Schnittstellen und Interfaces wie USB, RS232 und I2C. Diese Themen werden im nächsten Artikel dieser Serie behandelt.
Empfohlenes Material
Franzis-Lernpakete wie etwa „Elektronik mit ICs“ enthalten Materialien wie ein lötfreies lötfreie s Steckbrett, Steckbrett , Widerstände und LEDs etc., die für den Aufbau von Schaltungen mit dem Arduino gut geeignet sind.
Weite We itere re Info Infos: s: Bild 8: Darstellung von Analogkanälen als Balkengrafik
[1] www. www.proc processi essing. ng.org org G. Spanner: Arduino – Schaltungsprojekte für Profis, Elektor-Verlag, 2012, Best.-Nr.: Bes t.-Nr.: J5-10 J5-10 94 45 G. Spanner: AVR-Mikrocontroller in C programmieren, Franzis-Verlag, 2010, Best.-Nr.: J5-09 73 52
Preisstellung August 2014 – aktuelle Preise im Web-Shop
Empfohlene Produkte/Bauteile :
Arduino-Uno-Plat ine R3 Mikrocontroller-Onlinekurs Lernp Ler npak aket et Mikr Mikroc ocon ontro trolle llerr prog program rammi miere erenn
Bild 9: Temperatur-Logger mit Processing
Best .-Nr.
J5-10 29 70 J5-10 20 44 J5--10 68 46 J5
Preis
27,95 € 99,– € 129,– €
Alle Arduino-Produkte wie Mikrocontroller Mikrocontroller-Platinen, -Platinen, Shields, Fachbüche Fachbücherr und Zubehör finden Sie unter: www.arduino.elv.de
ELVjournal 5/2014
32 So funktioniert’s
Arduino verstehen und anwenden Teil 7: Schnittstellenpraxis – Kommunikation mit Laptop und PC
www.elvjournal.de
So funktioniert’s 33
Im siebten Teil der Artikelserie „Arduino verstehen und anwenden“ geht es um die Übertragung von Daten über Schnittstellen. Die zentrale Schnittstelle des Arduino ist das USB-Interface, über das jeder aktuelle Arduino verfügt.
Auch im Arduino Micro kommt dieser Chip zum Einsatz. Erst aufgrund der besonders kleinen Gehäusebauform des Chips konnte der Micro auf die Größe eines klassischen DIL-ICs reduziert werden. Die USB-Schnittstelle ist natürlich auch ein weiterer Grund für die große Beliebtheit der ArduinoÜber die USB-Buchse wird der Arduino nicht nur mit Boards. Durch diese Schnittstelle kann der Arduino Strom versorgt, sondern auch die gesamte Datenkom- an praktisch jeden modernen PC oder Laptop probmunikation läuft über diese Schnittstelle. Dabei sind lemlos angeschlossen werden. Der Anwender braucht zwei grundlegende Methoden zu unterscheiden: sich um Schnittstellenwandler etc. keine Gedanken · Übertragung von Sketchen zum Arduino mehr zu machen. · Austausch von Daten zwischen PC und Arduino, Aber auch wenn die RS232-Schnittstelle in der während auf dem Prozessor ein Programm abläuft modernen PC-Technik praktisch ausgestorben ist, so ist sie doch in anderen Bereichen noch weit verbreiIn diesem Artikel werden die Funktion dieser Schnitt- tet. So ist RS232-Kommunikation noch sehr häufig in stelle und ihre möglichen Anwendungen genauer be- folgenden Anwendungen zu finden: handelt. · Externe GPS-Module, sogenannte „GPS-Mäuse“ · Seriell angesteuerte LC-Displays · Messgerätetechnik Serielle Datenübertragung Wenn Daten zwischen einem Mikrocontroller und · Industrielle Steuerungen etc. einem PC ausgetauscht werden sollen, so ist dafür die serielle Schnittstelle noch immer das Mittel der Auch bei der Verbindung von einzelnen MikrocontWahl. Dies mag in Zeiten der allgegenwärtigen USB- rollern untereinander spielt die serielle Schnittstelle Schnittstelle etwas überraschen, und schließlich ist noch eine große Rolle. der Arduino ja auch über eine USB-Schnittstelle mit Außerdem können gerade auch sehr preisgünsdem PC verbunden. tig erhältliche oder noch vorhandene ältere PCs mit Wenn man den Aufbau des Arduino-Boards aber et- RS232-Schnittstelle in Kombination mit Mikroconwas genauer betrachtet, so stellt man fest, dass der trollern nutzbringend eingesetzt werden. Da hier Mikrocontroller tatsächlich nur über eine klassische meist keine sehr hohen Anforderungen an die Leisserielle Verbindung kommuniziert. Erst ein weiterer tungsfähigkeit des Rechners gestellt werden, bieten Baustein sorgt für die Umsetzung der RS232-Signale sich solche Rechner als „Terminaleinheiten“ für den auf ein USB-kompatibles Format. Arduino an. In den früheren Arduino-Versionen wie dem Duemillenove wurde die Umsetzung von einem Spezial- Grundlagen der seriellen baustein übernommen, dem FT232RL der Firma Future Kommunikation Technologies. Prinzipiell kann man zwei Methoden der DatenübertraDa der FT323RL verhältnismäßig teuer ist, wurde gung unterscheiden: dieser Baustein beim aktuellen Arduino Uno durch · Parallele Kommunikation einen zweiten AVR-Controller, den ATmega16U2, er- · Serielle Kommunikation setzt. Dieser Controllertyp verfügt über eine integrierte USB-Schnittstelle und kann mittels einer spe- Bei der parallelen Datenkommunikation werden mehziellen Firmware USB-Signale in das RS232-Format rere, meist acht Bit, gleichzeitig übertragen. Dies umwandeln. erfordert aber immer eine parallele Verlegung von Noch einen Schritt weiter ist der Arduino Leo- acht Leitungen bzw. acht Adern in einem Kabel (plus nardo. Hier wurde der Controllertyp ATmeg32U4 als eine Masseverbindung), d. h. einen vergleichsweise Hauptcontroller eingesetzt. Dieser kann, wie der hohen technischen Aufwand. Insbesondere bei sehr Mega16U4, ebenfalls direkt USB-Signale verarbeiten. hohen Datenraten treten erhebliche Probleme mit ELVjournal 6/2014
34 So funktioniert’s
t i B t r a t S
0 B S L
1 t i B
2 t i B
3 t i B
4 t i B
5 t i B
y t t i 7 i r B 6 a t P p i B S d o B M d t o S
0
1
0
0
0
1
t i B t r a t S
L ogis ch 1 L ogis ch 0 1
0 1
0
1
1
1
..
0
+ 15 V
+ 15 V
+3 V
+3 V
-3 V
-3 V
-1 5 V
-1 5 V
0 V
Bild 1: RS232-Protokoll
Bild 2: Ausgabe einer ASCII-Tabelle auf die serielle Schnittstelle
der Synchronisierung der acht Kanäle auf, so dass alle moderneren Übertragungsverfahren, wie etwa auch USB, nur noch seriell ausgeführt werden. Bei der seriellen Übertragung werden die Datenbits zeitlich nacheinander übertragen. Im einfachsten Fall kommt man daher mit einer Signalleitung aus. Für eine bidirektionale Verbindung sind zwei Leitungen ausreichend (plus Masse). Um eine korrekte Interpretation der über tragenen Daten zu gewährleisten, müssen Datensender und -empfänger ein gemeinsames Protokoll benutzen. In diesem Protokoll müssen die wichtigsten Parameter festgelegt sein wie: · Übertragungsgeschwindigkeit · Bitdefinition · Start- und Endbedingung für die Übertragung Auf PC-Seite werden die verfügbaren seriellen Schnittstellen mit COM bezeichnet. So verfügen die meisten PCs intern noch über diese Schnittstelle, auch wenn sie nicht mehr über eine Buchse am Gehäuse zur Verfügung gestellt wird. Bei der Installat ion von sogenannten „virtuellen“ COM-Schnittstellen sind die internen Ports dann aber oft noch als COM1 oder COM2 vorbelegt. Die serielle Datenübertragung haben wir prinzipiell schon bei der ersten Programmierung des Arduino kennengelernt. Ein Anwendungsprogramm wird nämlich ebenfalls über das ser ielle Protokoll zum µC übertragen. Deshalb war es auch notwendig, bei der Installation der Entwicklungsumgebung eine spezielle COMSchnittstelle auszuwählen. Bild 1 zeigt die prinzipielle Funktion der seriellen Schnittstelle. Die Übertragung beginnt mit einem sogenannten Startbit. Dann folgen die Datenbits, wobei mit dem niedrigstwertigen Bit, dem sogenannten Least Significant Bit (LSB), begonnen wird. Den Abschluss der Daten bildet entsprechend das höchstwertige Bit (MSB: Most Significant Bit). Abschließend folgen das Parity- und ein oder 2 StoppBits. Ursprünglich wurden für die Übertragung auf elektrischer Ebene Spannungen zwischen ±15 V verwendet (siehe Bild 1 unten). Bei Controller-Anwendungen kommt dagegen meist die sogenannte TTL-kompatible Version zum Einsatz. Diese verwendet Spannungen von 0 und +5 V für die Bitübertragung. Die serielle Schnitt stelle am Mikrocontroller
Bild 3: So sieht die Ausgabe mit falsch eingestellter Baudrate aus!
www.elvjournal.de
Beim Arduino-Board steht die serielle Schnittstelle an den Pins 0 und 1 zur Verfügung Diese Pins sind deshalb auch mit RX und TX für Receive (Empfangen) und Transmit (Senden) gekennzeichnet. Diese beiden Pins sind auf dem Board direkt mit dem RS232-zuUSB-Wandler verbunden. Damit wird die Kommunikation des Controllers mit einem PC sehr einfach. Der einzige Parameter, der noch eingestellt werden muss, ist die Über tragungsgeschwindigkeit. Diese wird auch als „Baudrate“ bezeichnet.
So funktioniert’s 35
Folgende Datenraten stehen zur Verfügung: 300 2400 9600 19.200 38.400 115.200
1200 4800 14.400 28.800 54.760
Die Standard-Einstellung ist 9600 Baud.
Die Befehle zur Steuerung der seriellen Schnittstelle Für die Steuerung der seriellen Schnittstelle können die folgenden Befehle eingesetzt werden: Serial.begin(baudrate); Hier wird die serielle Schnittstelle initialisiert. Die Baudrate ist der einzige hierfür erforderliche Parameter. Es ist lediglich darauf zu achten, dass die hier angegebene Baudrate mit der im Empfänger auf der PC-Seite identisch ist. Mit Serial.print(); können dann bereits Informationen an den PC über tragen werden. Serial.println(); fügt nach der Ausgabe einen Zeilenneuanfang („Line“) ein. Liefert die Abfrage von Serial.available() einen Wert > 0, so stehen Daten an der Schnittstelle bereit. Diese können dann mit Serial.read(); eingelesen werden.
Der Arduino geht auf Sendung: Übertragung von Daten vom Arduino an den PC Als erstes Praxisbeispiel soll eine ASCII-Tabelle vom Arduino zum PC gesendet werden. Der Sketch dazu kann wie folgt aussehen:
Neben dem ASCII-Zeichen selbst werden hier noch die zugehörigen Codes in dezimaler (dec), hexadezimaler (hex), oktaler (oct) und binärer (bin) Form dargestellt. Bild 2 zeigt die Ausgabe im Ser iellen Monitor der Arduino-IDE. Einer der häufigsten Fehler bei der Arbeit mit der seriellen Schnittstelle ist, dass die Baudraten auf Sender- und Empfängerseite nicht übereinstimmen. Bild 3 zeigt das Ergebnis, wenn die Sendebaudrate wie im obigen Code-Beispiel auf 9600 gesetzt ist, die Empfangsbaudrate am Seriellen Monitor jedoch auf 4800 steht. Sollten Sie also in Zukunft unverständliche Zeichenfolgen auf Ihrem Bildschirm haben, ist es immer eine gute Idee, zu prüfen, ob die Baudraten auf Sender- und Empfängerseite übereinstimmen.
Der Arduino an der kurzen Leine: direkte Steuerung des Controllers mit dem PC Eine sehr wichtige Aufgabe in der Technik ist die Steuerung von Hardware-Komponenten von einem Rechner aus. Diese Aufgabe ist gewissermaßen die Umkehrung des let zten Praxisbeispiels. Das folgende Programmbeispiel zeigt, wie man vom PC aus eine LED ein- und ausschalten kann. Nach dem Laden des Programms kann die LED 13 über den Datenmonitor geschaltet werden. Das Senden einer „1“ schaltet die LED ein. Wird eine „0“ gesendet, so erlischt die LED. Für das Senden der Werte kann wieder der Serielle Monitor eingesetzt werden (Bild 4). Die gewünschten Werte werden dort in das oberste Feld eingetragen und mit dem „Senden“-Button zum Arduino übertragen. // receive serial data int recData = 0; int LED = 13;
//on-board LED
void setup() { pinMode(LED, OUTPUT);
// ASCII table to RS232
digitalWrite(LED, LOW); Serial.begin(9600);
void setup() {
}
Serial.begin(9600); Serial.println("ASCII Tabelle");
void loop() { if (Serial.available() > 0)
for (int myByte = 65; myByte <= 126; myByte++)
{ recData = Serial.read();
{ Serial.write(myByte); Serial.print(",
if (recData == '0')
dec: ");
digitalWrite(LED, LOW);
Serial.print(myByte); Serial.print(",
if (recData == '1')
hex: ");
digitalWrite(LED, HIGH);
Serial.print(myByte, HEX); Serial.print(",
oct: ");
Serial.print(myByte, OCT); Serial.print(",
} delay(100); }
bin: ");
Serial.println(myByte, BIN); } } void loop() {}
Selbstverständlich können nicht nur die logischen Pegel „0“ und „1“ gesendet werden. Auch beliebige andere Werte sind übertragbar. Das folgende Programmbeispiel zeigt, wie ein LED-Dimmer vom PC aus gesteuert werden kann. ELVjournal 6/2014
36 So funktioniert’s
Durch die exponentiell zugeordneten Helligkeitswerte wird das logarithmische Verhalten des Auges dagegen kompensiert und die Helligkeitsstufen erscheinen nahezu gleich groß.
Ausblick
Bild 4: Senden eines ASCII-Wertes zum Arduino
// remote controlled LED dimmer int recData = 0; int LED = 3;
// PWM-LED
void setup() { pinMode(LED, OUTPUT); digitalWrite(LED, LOW); Serial.begin(9600); }
Nachdem in diesem Artikel die klassischen Punkt-zu-Punkt-Schnittstellen behandelt wurden, steht im nächsten Artikel die Netzwerktechnik im Vordergrund. Der Arduino wird dann über die Ethernet-Schnittstelle in das Heimnetzwerk eingebunden. Dafür ist ein spezielles Shield erforderlich, oder man verwendet gleich eine Arduino-Version mit integriertem EthernetAnschluss. Ist der Arduino erst einmal in das Heimnetzwerk integriert, so kann man mit einem beliebigen Browser wie etwa dem Internet Explorer oder Google Chrome auf den Controller zugreifen. Alle im Artikel „Sensortechnik und Messwerterfassung“ vorgestellten Sensoren können dann in das heimische Netzwerk integriert werden. Dem modernen Thema „Heimautomatisierung“ sind so keine Grenzen mehr gesetzt. Der Arduino kann etwa Rollläden in Abhängigkeit von der Sonneneinstrahlung steuern. Aber auch eine effektive Kontrolle oder sogar die raumindividuelle Steuerung der hauseigenen Heizungsanlage kann so realisiert werden.
void loop() { if (Serial.available() > 0) { recData = Serial.read(); if (recData == '0') analog Write(LED, 0); if (recData == '1') analogWrite(LED, 1); if (recData == '2') analogWrite(LED, 2); if (recData == '3') analogWrite(LED, 4); if (recData == '4') analogWrite(LED, 8); if (recData == '5') analogWrite(LED, 16); if (recData == '6') analog Write(LED, 32);
Empfohlenes Material · Arduino Micro, Best.-Nr. J6-10 97 74, € 24,95 · Mikrocontroller-Onlinekurs, Best.-Nr. J6-10 20 44, € 99,– · Auch viele Lernpakete von Franzis wie etwa „Elektronik mit ICs“ enthalten Materialien wie ein lötfreies Steckbrett , Widerstände und LEDs etc., die für den Aufbau von Schaltungen mit dem Arduino Micro gut geeignet sind.
if (recData == '7') analog Write(LED, 64); if (recData == '8') analog Write(LED, 128); if (recData == '9') analog Write(LED, 255); } delay(100); }
Nachdem das Programm geladen ist, können Werte zwischen 0 und 9 zum Arduino gesendet werden. Eine an Pin 3 angeschlossene externe LED kann so in ihrer Helligkeit gesteuert werden. Der Einsatz einer externen LED an Pin 3 ist erforderlich, da die interne LED 13 nicht über den analogWrite angesteuert werden kann. Diese Möglichkeit bieten nur die mit einer Tilde (~) gekennzeichneten sogenannten PWM-Ausgänge. PWM steht dabei für Pulsweitenmodulation. Weitere Details zu diesem Thema werden in einem späteren Artikel zu dieser Ser ie behandelt. Betrachtet man das Programm genauer, so fällt auf, dass die Werte im analogWrite-Befehl nicht linear vom übertragenen Datenwert abhängen, sondern exponentiell. Dies hängt damit zusammen, dass das menschliche Auge ein „logarithmischer Empfänger“ ist. Würde man die Helligkeit der LED linear ändern, so würden Helligkeitsstufen bei geringer Helligkeit der LED zunächst sehr groß erscheinen. Bei größeren Helligkeitswerten dagegen könnte das Auge kaum mehr Unterschiede wahrnehmen. www.elvjournal.de
Weitere Infos: · Mikrocontroller-Onlinekurs, Franzis-Verlag, exklusiv für ELV, 2011, Best.-Nr. J6-10 20 44, € 99,– · G. Spanner: Arduino – Schaltungsprojekte für Profis, Elektor-Verlag 2012, Best.-Nr. J6-10 94 45, € 39,80 · Lernpaket „AVR-Mikrocontroller in C programmieren“, Franzis-Verlag 2012, Best.-Nr. J6-09 73 52, € 39,95
Preisstellung Oktober 2014 – aktuelle Preise im Web-Shop
Empfohlene Produkte/Bauteile: Arduino Micro Arduino-Uno-Platine R3 Mikrocontroller-Onlinekurs NEU: Lernpaket Arduino Projects
Best.-Nr. J6-10 97 74 J6-10 29 70 J6-10 20 44 J6-11 51 22
Preis € 24,95 € 27,95 € 99,– € 79,95
Alle Arduino-Produkte wie Mikrocontroller-Platinen, Shields, Fachbücher und Zubehör finden Sie unter: www.arduino.elv.de
16 So funktioniert’s
Arduino verstehen und anwenden Teil 8: Arduino im Heimnetzwerk
www.elvjournal.de
So funktioniert’s 17
Der achte Teil der Art ikelserie „Arduino verstehen und anwenden“ hat die Integration des Arduino in ein Heimnetzwerk zum Thema. Pr inzipiell besteht ein solches Heimnetzwerk heute praktisch immer aus einem LAN (für Local Area Network).
Da der klassische Arduino nicht über einen LANAnschluss verfügt, kann er nicht direkt mit einem Heimnetzwerk verbunden werden. Um dennoch die Vorteile eines lokal vernetzten Arduino nutzen zu können, gibt es mehrere Möglichkeiten. Besitzt man bereits einen Arduino, beispielsweise vom Typ UNO oder Leonardo, so kann man auf diese Platinen ein Ethernet-Shield aufstecken. Falls noch kein Arduino vorhanden ist, bietet sich alternativ auch der Einsatz eines Arduino-Ethernet an. Diese Boardversion verfügt bereits über einen fest integrierten LAN-Anschluss (Bild 1). Sowohl von der Hard- als auch von der Softwareseite her verhalten sich die Lösungen praktisch identisch. Sketche, die auf einem Arduino-Ethernet laufen, funktionieren auch auf einem Arduino UNO mit aufgestecktem Ethernet-Shield. Falls der Arduino-Ethernet zum Einsatz kommt, ist zu beachten, dass dieser nicht über eine USB-Programmierschnittstelle verfügt. Für die Übertragung der Programme ist also zusätzlich noch ein externer USB-RS232-Wandler erforderlich. Auch die Versorgungsspannung muss beim Arduino-Ethernet immer extern zugeführt werden. Dies ist aber keine wirkliche Einschränkung, da diese Arduino-Version ohnehin meist als Stand-alone-Server eingesetzt wird. Um dem Anwender die Einbindung des Arduino zu erleichtern, werden in diesem Beitrag die folgenden Themen behandelt: · Was ist ein Netzwerk? · Wie kann man den Arduino in ein Netzwerk einbinden? · Was ist ein Webserver?
Bild 1: Arduino-Ethernet
Händler oder einfach um das Nachschlagen eines Begriffes in „Wikipedia“ geht, das Internet ist für die meisten Menschen zu einem integralen Bestandteil ihres beruflichen und privaten Lebens geworden. Letztendlich besteht das World Wide Web aus einer Vielzahl von Rechnersystemen, die global miteinander in Verbindung stehen. Prinzipiell entsteht aber schon durch den Zusammenschluss von zwei Computern über ein geeignetes Kabel ein einfaches Netzwerk. Werden immer mehr Rechner miteinander verbunden, entstehen immer komplexere Strukturen, die über verschiedene Netzwerkkomponenten wie Hubs, Router und Switches miteinander verbunden werden können. Bei diesen Netzwerkkomponenten handelt es sich im Prinzip um Verteiler bzw. Netzwerkweichen, welche die Daten auf intelligente Weise an alle Netzteilnehmer versenden. Die einzelnen Rechnersysteme müssen dabei über Netzwerkkarten verfügen. Diese Karten werden wiederum über geeignete Kabel mit den Switches oder Routern verbunden. In Bild 2 ist ein sogenannter RJ45-Stecker dargestellt. Dieser Steckertyp findet sich heutzutage an jedem gängigen Netzwerkkabel.
Netzwerktechnik
Das World Wide Web, häufig auch kurz als „Internet“ bezeichnet, ist ein weltumspannendes Netzwerk. Es wird heutzutage von den meisten Menschen der zivilisierten Welt mehrmals täglich genutzt. Egal ob es um die Buchung der nächsten Urlaubsreise, um die Bestellung neuer Waren bei einem der großen Online-
Bild 2: RJ45-Stecker
ELVjournal 1/2015
18 So funktioniert’s Der Arduino-Ethernet bzw. das Ethernet-Shield verfügen über eine dazu passende Buchse (Bild 3). Damit kann über ein sogenanntes Patch-Kabel eine Verbindung mit einem Heimnetzwerk hergestellt werden. Soll der Arduino mit einem Router verbunden werden, so ist ein normales Patch-Kabel zu verwenden. Steht kein Router zur Verfügung, kann der Arduino auch direkt an die Ethernet-Buchse eines Rechners angeschlossen werden. Hierfür ist dann aber ein sogenanntes Cross-over-Kabel erforderlich. In einem solchen Kabel sind die Empfangs- bzw. Sendeleitungen über Kreuz verbunden. Solche Kabel sind meist farblich entsprechend gekennzeichnet (häufig rot oder neongelb).
LAN, Ethernet und TCP/IP
Seit Anfang der 1990er Jahre ist der Begriff „Ethernet“ die Standardbezeichnung für eine ganze Familie von kabelgebundenen LAN-Technologien (Local Area Network). Die elektrische Verbindung der einzelnen Rechner und Netzwerkkomponenten erfolgt dabei über sogenannte Twisted-Pair-Kabel. Diese Kabel enthalten verdrillte Adernpaare, über die die Daten gegenphasig übertragen werden. Diese Technik erlaubt eine besonders störunempfindliche Signalübertragung, da Störeinstrahlungen gleichphasig erfolgen und so das gegenphasige Signal praktisch nicht beeinflussen. Zudem sind Kabel des Standards CAT.5 oder besser mehrfach abgeschirmt, was die Qualität der Übertragung weiter verbessert. Wie bereits im Beitrag „Schnittstellenpraxis“ (ELVjournal 6/2014) erläutert wurde, benötigt jede Datenübertragung ein bestimmtes Protokoll. Das Standardprotokoll im Ethernet wird als TCP (Transfer Control Protocol) bezeichnet. Dieses Protokoll erlaubt die Übertragung von Daten über lokale oder auch globale Netzwerke und sorgt für eine nahezu fehlerfreie Datenkommunikation. Die hohe Übertragungsqualität wird über besondere Verfahren garantiert. So werden durch verschiedene Fehlererkennungs- und Korrekturverfahren Datenverluste vermieden. Wird beispielsweise über ein Kontrollbit ein drohender Datenverlust erkannt, dann können die betroffenen Datenpakete korrigiert werden. Ist eine Korrektur nicht mehr möglich, so werden die Daten erneut angefordert und übertragen. Der zweite Teil des Protokolls trägt die Bezeichnung IP (für Internet Protocol). In diesem Protokollteil erfolgt die Adressierung der zu übertragenden Datenpakete, die vom Sender zu einem ganz bestimmten Empfänger geleitet werden sollen. Bei einer einfachen Zweipunktübertragung wie der bereits in einem früheren Artikel vorgestellten RS232Schnittstelle ist dieser Teil nicht erforderlich, da die Daten hier nur von einem Sender an genau einen Empfänger übermittelt werden. In einem echten Netzwerk sind aber stets mehrere Sender und Empfänger vorhanden. Damit wird ein Verfahren notwendig, das es gestattet, die zu übertragenden Datenpakete immer an genau den richtigen Empfänger zu senden. Das IP-Protokoll ist exakt für diese Aufgabe zuständig. Es hat die Aufgabe, für eine korrekte Adressierung der zu übertragenden Datenpakete zu sorgen. www.elvjournal.de
Bild 3: RJ45-Buchse am Arduino-Ethernet
Beim IP-Protokoll wird jeder Netzwerkkomponente eine eindeutige Adresse zugeordnet. Diese Adresse kann mit den Postleitzahlen, Straßennamen und Hausnummern eines Landes verglichen werden. Ähnlich wie die Postadresse die Zustellung von Briefen ermöglicht, erlaubt die IP-Adresse also die effiziente Zustellung von Daten.
IP-Adressen, Netzwerkmasken, Gateways und MAC-Adresse Damit ein postalischer Zustelldienst in der Lage ist, Pakete immer an die korrekte Adresse zu liefern, darf landesweit keine Adresse doppelt vorhanden sein. Ebenso muss die IP-Adresse eines Netzwerkteilnehmers innerhalb eines Netzwerks absolut eindeutig sein. Die IP-Adresse muss also jedem in einem Netz befindlichen Gerät zugewiesen werden und stellt dann sicher, dass das zugehörige Gerät adressierbar bzw. erreichbar ist. Die IP-Adressen der IPv4-Notation setzen sich aus 4 Byte zu je 8 Bit, insgesamt also 32 Bit, zusammen. Damit stehen theoretisch 232 = 4.294.967.296 Adressen zur Verfügung. Das ist zwar eine vergleichsweise große Anzahl, dennoch werden verfügbare Internetadressen mittlerweile so knapp, dass das System auf IPv6 erweitert werden muss. Im Heimnetz wird aber vorläufig weiterhin mit 4 Byte langen Adressen gearbeitet. Daher weist der Router im Netz jedem angeschlossenen netzwerkfähigen Gerät eine Adresse der Form xxx.xxx.xxx.xxx also z. B. die IP-Adresse 172.142.154.126 zu. Hinweis:
Aus Datenschutzgründen wurden die IP-Adressen in diesem Ar tikel teilweise verändert oder ausgeblendet. In realen Anwendungen müssen natürlich wieder gültige IP-Adressen eingesetzt werden. Eine derartige IP-Adresse besteht aus einem sogenannten Netzwerkanteil und einem Host-Anteil. Über die Netzwerkmaske wird festgelegt, welche Adressen direkt angesprochen werden können und welche Adressbereiche sich in anderen Netzwerken befinden. Für die Einbindung des Arduino ist es in den meisten Fällen ausreichend, wenn man eine Adresse wählt, die in den ersten drei Bytes mit
So funktioniert’s 19
Bild 4: Netzwerkübersicht eines typischen Heimnetzes
bereits vorhandenen Netzadressen übereinstimmt. Leitung mit dem Internet verbunden ist, wird er auch Wichtig ist aber, dass sich dann das vierte Byte von als Gateway bezeichnet. Dem Gateway ist ebenfalls allen bereits vergebenen Adressen unterscheidet. eine spezielle IP-Adresse zugeordnet, und DatenpaHierzu kann man sich alle im Heimnetz vorhande- kete, die an diese Adresse gesendet werden, leitet nen Adressen anzeigen lassen. Details dazu finden der Gateway über den Provider an das allgemeine Insich in der Betriebsanweisung zum verwendeten Rou- ternet weiter. Auf diese Art und Weise kann man mit ter. Bild 4 zeigt einen typischen Fall. dem lokalen Rechner zuhause im gesamten globalen Schließlich gibt es noch die sogenannte MAC- Internet „surfen“. Adresse (für Media Access Control). Hierbei handelt Gibt man in der Kommandozeile des Heim-PCs den es sich um eine weltweit eindeutige Adresse, die je- Befehl ipconfig ein, kann man die Gateway-Adresse in dem netzwerkfähigen Gerät zugewiesen werden muss. Erfahrung bringen. Bild 5 zeigt die zugehörige AusSie besteht aus 6 Byte, wobei die ersten drei 3 Byte gabe. einen herstellerspezifischen Identifizierungs-Code darstellen. Die verbleibenden Bytes werden individuell vom Hersteller vergeben. Eine typische MAC-Adresse sieht also so aus: 1A-6C-22-67-B3-2C Die MAC-Adresse wird immer benötigt, wenn Netzwerkkomponenten explizit adressiert werden sollen, um Dienste auf höheren Schichten anzubieten. Da dies auch auf einen netzwerkfähigen Arduino zutriff t, muss diesem also auch eine MAC-Adresse zugeordnet sein. Wenn der Router eines Heimnetzwerks auch über eine DSL- Bild 5: ipconfig-Ausgabe ELVjournal 1/2015
20 So funktioniert’s Der Arduino als Webserver
In einem Netzwerk kann man sogenannte Server (engl. für „Anbieter“) und Clients („Kunden“) unterscheiden. Bei einem Ser ver handelt es sich um einen Rechner, der auf die Kontaktanfrage eines Clients reagiert und Informationen liefert. Der folgende Sketch verwandelt den Arduino-Ethernet in einen Webserver.
// Arduino simple web server #include #include byte mac[] = {0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED }; IPAddress ip(172,…,…,…); EthernetServer server(80); void setup() { Serial.begin(9600); Ethernet.begin(mac, ip); // start Ethernet connection server.begin(); Serial.print("server is at "); Serial.println(Ethernet.localIP()); } void loop() { EthernetClient client = server.available(); if (client) { Serial.println("new client"); boolean currentLineIsBlank = true; while (client.conne cted()) { if (client.available()) {
char c = client.read(); Serial.write(c); if (c == '\n' && currentLineIsBla nk) {
client.println("HTTP/1.1 200 OK"); client.println("Content-Typ e: text/html"); // close connection after completion of response client.println("Connection: close"); // refresh page automatically every 3 secs client.println("Refresh: 3");
client.println(); client.println("");
client.println(""); // output the value of each analog input pin for (int analogChan nel=0; analogChan nel<2; analogChan nel++) { int sensorReading = analogRead(analogChannel); client.print("analog sensor #"); client.print(analog Channel); client.print(" = "); client.print(sensorReading); client.println("
"); } client.println(""); break; } if (c == '\n') { currentLineIsBlank = true; // start a new line } else if (c != '\r') { currentLineIsBlank = false; // character on the current line } } }
delay(1); client.stop(); Serial.println("client disonnected"); }
}
www.elvjournal.de
So funktioniert’s 21
Bild 7: Ausgabe im seriellen Monitor mit zugewiesener IP-Adresse
Bild 6: Aufbau eines Webservers zur Übermittlung von Analogwerten
Dieses Programm gestattet es, zwei Analogkanäle über das Ethernet an einen Web-Client zu übertragen. Damit definierte Werte an den Analogkanälen anliegen, ist die Hardware-Schaltung in Bild 6 nützlich. Über die beiden Potentiometer lassen sich feste Spannungswerte einstellen. Je nach Potentiometerstellung liefern die A/D-Wandler Werte zwischen 0 und 1024. Diese Werte können in einem beliebigen Webbrowser ausgelesen werden. Will man auf den Arduino-Webserver zugreifen, muss man die im Sketch angegebene IP-Adresse in die Adresszeile des Browsers eingeben. Diese Adresse wird auch im seriellen Monitor der Arduino-IDE angezeigt. Falls die Adresse für einen bestimmten Arduino-Server also einmal nicht mehr bekannt sein sollte, kann man sie dort wieder in Erfahrung bringen (Bild 7). Die Darstellung der Messwerte kann in jedem gängigen Browser erfolgen. Bild 8 zeigt beispielhaft, wie die Werte in Google Chrome und im Internet Explorer dargestellt werden. Dass der Arduino nicht nur numerische Werte in das Netzwerk senden kann, zeigt das folgende Programmbeispiel. Hier werden die Analogmesswerte als Balkengrafik dargestellt. Dies erlaubt eine übersichtliche Darstellung, auch wenn mehrere Werte, wie beispielsweise die Temperaturen in verschiedenen Räumen, simultan angezeigt werden sollen.
Bild 8: Die ermittelten Messwerte in zwei Browsern (Google Chrome und Internet Explorer)
ELVjournal 1/2015
22 So funktioniert’s
// graphical WebServer for analog inputs #include #include byte MACAddress[] = {0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED}; byte IPAddress[] = {172, …, …, …}; EthernetServer myServer(80); void setup() { Ethernet.begin(MACAddress, IPAddress); myServer.begin(); } void loop() { EthernetClient client = myServer.available(); if(client) { client.println("HTTP/1.1 200 OK"); client.println("Content-Type: text/html");
client.println(); client.println("\nArduino Web-Server\n"); client.print("Kanal 0:
");
client.print(analogRead(0)/10.23);
client.print(" %");
client.print("; width:"); client.print("Kanal 1:
client.print(analogRead(0)); client.println("px; \">");
");
client.print(ana logRead(1)/10.23);
client.print(" %");
client.print("; width:");
client.print(analogRead(1)); client.println("px; \">
");
client.println("\n"); }
delay(1); client.stop(); }
Natürlich ist es auch möglich, wesentlich ausgefeiltere grafische Oberflächen zu erarbeiten, der Fantasie sind hier keine Grenzen gesetzt. Bild 9 zeigt, wie die Messwerte in einem Browser dargestellt werden.
Im nächsten Teil der Artikelserie geht es noch einen Schritt weiter. Durch Verwendung der WLAN-Technologie kann dann sogar auf das Ethernet-Kabel verzichtet werden. Wird der Arduino zusätzlich noch mit einem leistungsfähigen Akku-Pack ausgestattet, kann er an nahezu jedem Ort, unabhängig von Strom oder Datenkabeln, eingesetzt werden.
Ausblick
In diesem Artikel wurde gezeigt, wie man den Arduino in ein Heimnetzwerk einbinden kann. Der Über tragung von Messwerten aus beliebigen Sensoren (siehe Teil 6 dieser Reihe in ELVjournal 5/2014) in das heimische Intranet steht so nichts mehr im Wege. Dieses kann so als Basis für eine Heimautomatisierung dienen. Spezielle zusätzliche Leitungen oder Bussysteme sind nicht erforderlich. Das ohnehin meist vorhandene lokale Ethernet kann so auf das aktuell vieldiskutierte IoT, also das „Internet of Things“ erweitert werden.
Weitere Infos:
· Mikrocontroller-Onlinekurs, Franzis-Verlag, exklusiv für ELV, 2011, Best.-Nr. J7-10 20 44, € 99,– · G. Spanner: Arduino – Schaltungsprojekte für Profis, Elektor-Verlag 2012, Best.-Nr. J7-10 94 45, € 39,80 · Buch „AVR-Mikrocontroller in C programmieren“, Franzis-Verlag 2012, Best.-Nr. J7-09 73 52, € 39,95 Preisstellung Dezember 2014 – aktuelle Preise im Web-Shop
Empfohlene Produkte/Bauteile:
Arduino-Ethernet Ethernet-Shield Bild 9: Grafische Anzeige der Kanäle in einem Browser
www.elvjournal.de
Best.-Nr.
J7-10 69 17 J7-10 97 73
Preis
49,95 € 39,95 €
Alle Arduino-Produkte wie Mikrocontroller-Platinen, Shields, Fachbücher und Zubehör finden Sie unter: www.arduino.elv.de
48 So funktioniert’s
Arduino verstehen und anwenden Teil 9: WLAN und Micro-Server-Technik
www.elvjournal.de
So funktioniert’s 49
Nachdem im letzen Beitrag zu dieser Artikelserie der Anschluss des Arduino an das lokale, drahtgebundene Heimnetzwerk im Vordergrund stand, geht es nun noch einen Schritt weiter. Auf die Kabelverbindung wird verzichtet und der Arduino wird drahtlos in ein WLAN (Wireless Local Area Network) eingebunden.
Eine solche Einheit kann überall in Haus, Keller oder Garten positioniert werden. Je nach Reichweite des WLAN kann so ein Bereich von bis zu 30 m oder mehr rund um den aktiven WLAN-Router abgedeckt werden. Von den vielen Möglichkeiten, die ein Arduino mit WLAN-Anschluss bietet, wird sich dieser Artikel auf die folgenden Themen konzentrieren:
Natürlich muss dazu der eingesetzte Router über eine geeignete WLAN-Funktion (LAN 802.11b/g-Standard) verfügen. Diese ist aber mittlerweile bei allen aktuellen und gängigen Routern vorhanden. Durch die Unabhängigkeit von einem LAN-Kabel erhält der Arduino eine bislang ungekannte Freiheit. Anstelle eines Netzwerkanschlusses ist nun nur noch eine Steckdose für die Spannungsversorgung erforderlich. Dies erweitert die Positionierungsmöglichkeiten in einem klassischen Haushalt ganz erheblich, da hier üblicherweise in jedem Raum mehrere Steckdosen zu finden sind. Ein Netzwerkanschluss ist dagegen, wenn überhaupt, häufig nur einmal in einem Zimmer vorhanden. Die nahezu grenzenlose Freiheit erhält man, wenn der Arduino mit Batterien oder Akkus versorgt wird.
1. Inbetriebnahme eines Wi-Fi-Shields 2. Funktionen und Anwendungen der Wi-Fi-Bibliothek 3. Der Arduino im WLAN 4. Drahtlose Übertragung von Sensordaten Oft führt der Begriff „Wi-Fi“, der auch bei drahtlosen Arduino-Anwendungen häufig auftaucht (z. B. „Wi-FiBibliothek“), zu Verwirrungen und Missverständnissen. Wi-Fi ist ein Kunstwort, das oftmals als Abkürzung für „Wireless Fidelity“ aufgefasst wird. Hier kommt die Anlehnung an den Hi-Fi-Begriff der Audiotechnik zum Ausdruck. Mit einem Wi-Fi-Netzwerk soll so ein Funkstandard für höchste Ansprüche assoziiert werden. Meist wird Wi-Fi aber einfach als Synonym für WLAN benutzt, obwohl genau genommen der Begriff WLAN das Funknetzwerk, Wi-Fi dagegen den Funkstandard bezeichnet. Das Arduino Wi-Fi Shield
Bild 1: Arduino mit aufgestecktem Wi-Fi-Shield und Proto-Board
Im Gegensatz zum Ethernet-Anschluss hat man beim WLAN nicht die Auswahl zwischen einem Arduino mit integriertem WLAN-Interface und einem WLANShield. Will man einen Arduino in ein drahtloses Netzwerk integrieren, wird immer ein klassischer Arduino und ein zusätzliches WLAN-Shield benötigt. Bild 1 zeigt die fertig montierte Kombination. Zusätzlich wurde hier noch ein kleines Proto-Board eingesetzt, welches einen Temperatursensor trägt. Beim Aufstecken des Shields auf das Arduino-Board ist zu beachten, dass nicht nur die Pins der oberen und unteren Stiftleiste verbunden werden müssen, sondern zusätzlich auch noch die sechs Anschlüsse der ICSP-Schnittstelle. Diese Kombination bietet die folgenden Leistungsmerkmale: · Betriebsspannung: 5 V (Versorgung des Wi-FiShields erfolgt über den Arduino) · WLAN-Protokoll: 802.11b/g · Verschlüsselung: WEP und WPA2 ELVjournal 2/2015
50 So funktioniert’s
Die Wi-Fi-Library
Wie im Arduino-Umfeld üblich, wird auch zum Wi-FiShield eine umfangreiche Bibliothek mit mehreren Beispielen zur Verfügung gestellt. Die Bibliothek gehört bei den aktuellen IDE-Versionen bereits mit zur Standardausstattung. Bild 2 zeigt, wie die Wi-Fi-Biliothek aufgerufen wird. Eine sehr interessante und durchaus auch nützliche Anwendung aus der Standard-Beispielsammlung ist der Sketch „ScanNetworks“. Wie üblich kann der Sketch über die Menüauswahl geladen werden (siehe Bild 2). Nach dem Start des Sketches und des seriellen Monitors wird eine Übersicht über alle lokal verf ügbaren Drahtlosnetze angezeigt. Neben dem Funktionstest des Shields kann man mit dieser Anwendung auch die Signalstärken in der Umgebung des WLAN-Routers ausmessen. Mit einem etwas längeren USB-Kabel oder mit einem Laptop können so die günstigsten Positionierungen für WLAN-Elemente bestimmt werden. Wie entsprechende Messungen zeigen, liegt die Empfindlichkeit und Reichweite des Arduino-Wi-FiShields im mittleren Bereich. Mit einem modernen, mit integriertem WLAN ausgerüsteten Laptop erhält Bild 2: Das Menü zur Wi-Fi-Library man deutlich bessere Reichweiten. Dies ist insbesondere dadurch begründet, dass in derartigen Laptops großflächige Empfangsantennen integriert sind. Zusätzlich verfügt das Wi-Fi-Shield genau wie die Ethernet-Versionen Smartphones dagegen sind von der WLAN-Empdes Arduino über einen Onboard-microSD-Karten-Slot. Eine separate fangsleistung oftmals nicht deutlich besser als Mini-USB-Buchse erlaubt die Aktualisierung der Firmware auf der Wi- das WLAN-Shield. Kleine und preisgünstige MiniFi-Karte. WLAN-USB-Adapter erreichen dagegen sogar of tmals Das Wi-Fi-Shield enthält einen eigenen ATmega-32UC3-Chip. Dieser nicht die Reichweite des Shields. Dies ergibt sich beinhaltet einen IP-Stack, welcher sowohl TCP als auch UDP unterstützt. natürlich auch aus der Tatsache, dass in die kleine (Nähere Details zu den Netzwerkprotokollen wurden bereits im letzten Bauform der Sticks keine effektiven Antennen integArtikel dargelegt.) riert werden können. Die Anschlüsse des Arduino sind über die Buchsenleisten des Wi-FiBild 3 zeigt die Ausgabe von Signalfeldstärken im Shields durchgeführt, so dass die meisten Pins f ür eigene Anwendungen seriellen Monitor der Arduino-IDE. Wie ebenfalls zu weiterhin zur Verfügung stehen. Im Bedarfsfall können auch weitere erkennen ist, werden alle am Standort verfügbaren Shields auf das Wi-Fi-Board aufgesteckt werden. WLAN-Netze angezeigt. So eignet sich der Arduino Auf den im Wi-Fi-Shield integrierten microSD-Karten-Steckplatz kann mit Wi-Fi-Shield also auch für den Einsatz als Netzüber die normale SD-Bibliothek zugegriffen werden. Auf diese Weise ist werkscanner. es möglich, auch umfangreichere Webseiten zu erstellen und auf einer entsprechend großen SD-Karte abzulegen. Da der Arduino sowohl mit dem Prozessor des Wi-Fi-Shields als auch Hinweis: mit der integrierten SD-Karte über den SPI-Bus kommuniziert, muss Wie bereits im Beitrag zur LAN-Einbindung des auch der ICSP-Stecker elektrisch mit dem Shield verbunden werden. Arduino wurden auch hier wieder MAC- und EtherÜber den I/O-Pin Nummer 10 wird der Chip-Select des Wi-Fi-Controllers net-Adressen sowie Passwörter etc. aus DatenHDG104, über Pin 4 der Select für die SD-Karte gesteuert. Diese beiden schutzgründen ausgeblendet. Pins stehen also nicht mehr für externe Aufgaben zur Verfügung. Der Digitalpin 7 wird für das Handshake zwischen dem Wi-Fi-Shield und dem Arduino eingesetzt und sollte daher ebenfalls nicht für andere Die Signalstärke wird hier in dBm angegeben. Diese Aufgaben verwendet werden. Einheit steht für Dezibel Milliwatt und bezeichnet Neben dem Zugriff auf offene und unverschlüsselte drahtlose Netz- den Leistungspegel in Dezibel, bezogen auf 1 mW werke ermöglicht das Wi-Fi-Shield auch die Einbindung in WLANs mit Leistung. Zwischen der Leistung (P) in Milliwatt (mW) WPA2- oder WEP-Verschlüsselung. und dem dBm-Wert besteht folgender ZusammenFür die Anzeige der Betriebszustände verfügt das Wi-Fi-Shield über hang: 4 Status-LEDs: · L9 (gelb): Diese LED ist mit Digitalpin 9 verbunden P/dBm = 10*log(P/1 mW) · LINK (grün): Diese LED dient als Indikator für die Netzwerkverbindung Ein Milliwatt entspricht also 0 dBm. Größere Leis· ERROR (rot): Die rote LED zeigt Kommunikationsfehler an tungswerte haben positive, kleinere negative dBm· DATA (blau): Die blaue Data-LED blinkt, wenn Datenpakete gesendet Werte. Negativen dBm-Werten sind damit Leistungen oder empfangen werden zugeordnet, die kleiner sind als 1 mW. www.elvjournal.de
So funktioniert’s 51
So entsprechen: 100 µW -10 dBm 10 µW -20 dBm 1 µW -30 dBm 0,1 µW -40 dBm 0,01 µW -50 dBm 1 nW -60 dBm Die in Bild 3 angegebenen Leistungen liegen also erwartungsgemäß deutlich unterhalb von einem Milliwatt, sind aber für einen brauchbaren WLAN-Empfang durchaus noch ausreichend. Hat man so einen Standort mit gutem WLAN-Empfang gefunden, kann man den nächsten Schritt in Angriff nehmen und den Arduino in das drahtlose Netzwerk einbinden. Der Arduino im WLAN
Für den Aufbau einer aktiven WLAN-Verbindung kann man den Arduino zunächst als Wi-Fi-Webserver konfigurieren. Ein entsprechender Sketch (WiFiWebServer. ino) findet sich in der Wi-Fi-Library. Bevor dieser Sketch auf den Arduino geladen wird, müssen noch einige Konfigurationen ausgeführt werden. Ein Heimnetzwerk sollte keinesfalls ohne Verschlüsselung betrieben werden. Eine weit verbreitete Verschlüsselungsmethode ist WPA2. Das Wi-Fi-Shield ist in der Lage, über diesen Standard zu kommunizieren. Im Sketch müssen dafür zwei Angaben gemacht werden: 1. In char ssid[] = "yourNetwork"; muss die Netzwerk-SSID eingetragen werden. Angaben dazu finden sich im Manual zum verwendeten Router. 2. Das Passwort wird dem Arduino unter char pass[] = "secretPassword"; übergeben. Dann kann der entsprechende Sketch zum Arduino übertragen werden. An dieser Stelle ist jedoch ein wichtiger Hinweis angebracht:
Bild 3: WLAN-Netzwerkscan mit dem Wi-Fi-Shield
kontrollieren. Zudem ist auch zu bedenken, dass, wie bereits erläutert, die Empfangsleistung des Wi-Fi-Shields nicht ganz so optimal ist wie die eines Tablets oder eines Laptops mit integrierter WLAN-Einheit. Hier kann es also hilfreich sein, weitere Tests in direkter Umgebung des WLAN-Routers durchzuführen. War die Verbindungsaufnahme schließlich erfolgreich (grüne LED leuchtet permanent), kann man in der Arduino-IDE den seriellen Monitor öffnen (Bild 4). Hier wird nun die akt ive Kommunikation mit dem Drahtlos-Netzwerk nochmals bestätigt. Außerdem wird die IP-Adresse angegeben, welche über das Netzwerk dem Arduino zugeordnet wurde. Das folgende Bild zeigt die Ausgabe (zur Wahrung des Datenschutzes wurden wieder einige Angaben ausgegraut). Die an den seriellen Monitor ausgegebene IP-Adresse kann man nun in einen Browser (z. B. Explorer, Chrome oder Firefox) eingeben und so Kontakt zum Arduino aufnehmen. Details dazu wurden bereits im letzten Beitrag dieser Ser ie erläutert. An dieser Stelle macht es keinen Unterschied, ob der Arduino über LAN oder WLAN eingebunden ist.
Hinweis
Die WLAN-Shields arbeiten nicht mit allen IDE-Versionen. Die besten Ergebnisse wurden mit der IDE-Version 1.0.2 erzielt. Insbesondere mit den aktuellen Versionen 1.0.5 bzw. 1.0.6 scheint es mit dem Wi-Fi-Shield Probleme zu geben. Dazu gibt es Beiträge in verschiedenen Foren und auch eigene Versuche haben dies bestätigt.
Wurden die notwendigen Angaben zur SSID und zum Passwort korrekt eingegeben, kann der Sketch, vorzugsweise mit der Arduino-IDE 1.0.2, auf den Arduino übertragen werden. Ist der Sketch erfolgreich geladen, versucht das WiFi-Shield Verbindung zum angegebenen WLAN-Router aufzunehmen. Sobald die Verbindung steht, leuchtet die grüne „LINK“-LED. Falls der Versuch fehlschlägt, wird die rote „ERROR“-LED aktiviert. In diesem Fall sollte man die Angaben im Sketch nochmals genau
Bild 4: Verbindung zum WLAN-Router ist aufgebaut.
ELVjournal 2/2015
52 So funktioniert’s
Wenn alles korrekt funktioniert, sollte im Browser-Fenster folgende Ausgabe erscheinen:
analog input 0 is 411 analog input 1 is 398 analog input 2 is 207 analog input 3 is 173 analog input 4 is 297 analog input 5 is 350
Akkuversorgung kommen entweder NiMH- oder Li-Ionen-Zellen in Frage. Die durchschnittliche Stromaufnahme des Arduino mit WLAN-Shield beträgt ca. 120 mA bei 8,4 V (z. B 2x Li-Ion- oder 7x NiMH-Zellen). Damit lassen sich problemlos Laufzeiten von mehreren Stunden bis zu einigen Tagen erreichen. Ein Sketch für den Betrieb des Enviro-Servers kann dann so aussehen: // web
Server using WiFi with WPA encryption - temperature sensor using NTC
int ADC0=0, int ADC_value;
// select and init ADC channel
Die Werte der Analogeingänge sind zufällig und ändern sich in rascher Folge, da die offenen Eingänge lediglich elektromagnetische Störungen einfangen (siehe dazu auch Teil 6 der Artikelserie „Sensortechnik und Messwerterfassung“ im ELVjournal 5/2014). Der Enviro-Server Will man auch sinnvollere Daten als elektromagnetische Störungen empfangen, dann kann man den Arduino mit WLAN-Shield zu einem Server für Umweltmessdaten, einem sogenannten „Environmental-“ oder kurz „Enviro"-Server, erweitern. Die Grundlagen hierfür sind ebenfalls bereits aus dem Artikel zu Sensortechnik und Messwerterfassung bekannt. Will man beispielsweise Umgebungs- oder Raumtemperaturen messen und via WLAN übertragen, kann man dazu einen NTC-Temperatursensor einsetzen. Bild 5 zeigt eine Schaltung dazu. Zusätzlich kann man nun den Arduino mit einem Akku betreiben. Da der Arduino UNO bereits einen Spannungsregler an Board hat, kann man den Akku direkt an die Hohlbuchse des Controllerboards anschließen (Bild 6). Man erhält so einen vollkommen autarken Micro-Server, da nunmehr weder Daten noch Stromversorgungsleitungen erforderlich sind. Für die
N TC 4k 7
int status = WL _IDLE_STATUS;
5 V A0 4k7 G ND
Bild 5: Schaltung für einen NTC-Temperatur sensor am Wi-Fi-Shield
www.elvjournal.de
So funktioniert’s 53
WiFi-Shield
Ard uin o
Akk u-Pack
Bild 6: Autonomer WLAN-Server mit Akku-Pack
Bild 7: Anzeige der Temperatur in einem Browser
Nachdem der Sketch auf den Arduino übertragen wurde, kann der Enviro-Server über einen beliebigen Browser aufgerufen werden, wie in Bild 7 zu sehen. Natürlich ist es nun auch möglich, den Server beispielsweise über ein WLAN-fähiges Smartphone aufzurufen. Hierzu ist wieder lediglich ein beliebiger Webbrowser zu starten. Dann muss nur noch die korrekte IP-Adresse angegeben werden, und der Enviro-Server kann drahtlos von jedem beliebigen Punkt innerhalb der WLAN-Reichweite ausgelesen werden. Bild 8 zeigt die entsprechende Darstellung auf einem Android-Smartphone.
erlauben, nahezu verzögerungsfrei auf unvorhergesehene Ereignisse zu reagieren. Typische Anwendungen der Interrupt-Technologie reichen dabei von komfortablen manuellen Eingabemethoden bis hin zur Alarmauslösung in Gefahrensituationen.
Ausblick
Nach der Einbindung des Arduino in ein drahtgebundene s LAN im letzten Teil der Artikelserie wurde in diesem Beitrag die drahtlose WLAN-Technologie genutzt, um einen autarken, Arduino-basierten Micro-Server abzufragen. Damit ist der Ausflug in den Bereich der Netzwerktechnik zunächst abgeschlossen. Der nächste Teil der Artikelserie wird sich um das Thema „Interrupts und Polling“ drehen. Hier kommen dann bereits recht fortgeschrittene Programmiertechniken zum Einsatz, die es beispielsweise
Weitere Infos: · G. Spanner: Arduino – Schaltungsprojekte für Profis, Elektor-Verlag 2012, Best.-Nr. J8-10 94 45, € 39,80 · Mikrocontroller-Onlinekurs, Franzis-Verlag, exklusiv für ELV, 2011, Best.-Nr. J8-10 20 44, € 99,– · Grundlagen zur elektronischen Schaltungstechnik finden sich in der E-Book-Reihe „Elektronik!“ (www.amazon.de/dp/B00OXNCB02) · Buch „AVR-Mikrocontroller in C programmieren“, Franzis-Verlag 2012, Best.-Nr. J8-09 73 52, € 39,95
Preisstellung Februar 2015 – aktuelle Preise im Web-Shop
Empfohlene Produkte/ Bauteile: Arduino-Wi-Fi-Shield Arduino UNO Mikrocontroller Online-Kurs
Bild 8: Ablesen der Server-Daten auf einem Mobilgerät
Best.-Nr. J8-11 02 51 J8-10 29 70 J8-10 20 44
Preis € 89,95 € 27,95 € 99,–
Alle Arduino-Produkte wie Mikrocontroller-Platinen, Shields, Fachbücher und Zubehör finden Sie unter: www.arduino.elv.de
ELVjournal 2/2015
42 So funktioniert’s
Arduino verstehen und anwenden Teil 10: Richtig auf unerwartete Ereignisse reagieren – Interrupts und Polling
www.elvjournal.de
So funktioniert’s 43
Der zehnte Artikel der Beitragsreihe „Arduino verstehen und anwenden“ dreht sich um den Bereich „Interrupts und Polling“. Dabei stehen die folgenden Themen im Vordergrund: · Was ist ein Interrupt und wozu wird er benötigt? · Was ist der Unterschied zwischen Interrupts und „Polling“ · Welche Interruptquellen stehen auf einem Mikrocontroller zur Verfügung
gaben beschäftigt ist, bleibt der Tastendruck ohne Wirkung. Natürlich kann ein solches „Verschlucken“ von Eingabewerten in der Praxis nicht toleriert werden. Auf rein softwaretechnischem Weg ist das Problem nicht zu beheben. Hier ist eine zusätzliche controllerinterne Hardware-Schaltung erforderlich, die kontinuierlich und ohne Unterbrechung einen Schaltpegel an einem bestimmten Pin überwachen kann. Da dieses Problem sehr häufig auftritt, wurde dafür eine spezielle Lösung implementiert, die sogenannte Interruptsteuerung. Interrupts unterbrechen unmittelbar das Hauptprogramm und springen in eine soWie in dieser Serie üblich, wird wieder besonderer genannte Interruptroutine. Erst nach dem Abarbeiten dieser speziellen Wert auf praktische Anwendungen gelegt. Dazu wer- Befehlsfolge erfolgt wieder ein Rücksprung in das Hauptprogramm. den die folgenden Praxisübungen durchgeführt: Damit kann z. B. ein Tastendruck zu keinem Zeitpunkt mehr verloren · Tasterabfrage mit Polling gehen. Bild 1 veranschaulicht diesen Vorgang. · LED-Steuerung mit Interrupts · Wirkung verschiedener Interrupt-Modi · „Multitasking“: simultanes Blinken und Schalten von LEDs · Blinken ohne Delay!
Wozu benötigt man Interrupts?
Gerade in der Mikrocontroller-Technik ist es oftmals erforderlich, dass ein Programm auf unerwar tete Ereignisse schnell und sicher reagiert. Ein klassisches Beispiel ist die Auslösung von Alarmen beim Vorliegen eines Fehlers. Hier ist eine schnelle und unverzügliche Reaktion erforderlich. Aber auch bei Eingaben über Tastaturen will der Anwender nicht warten, bis das laufende Programm zu irgendeinem Zeitpunkt in die Tastenabfrage springt, sondern jede Eingabe soll unverzüglich übernommen werden. Zudem liefern Sensoren oftmals unvorhersehbare Werte. Soll z. B. beim Überschreiten einer bestimmten Temperatur ein Gerät abgeschaltet werden, so muss der Mikrocontroller (µC) unverzüglich reagieren. Ist er gerade mit komplizierten Berechnungen ausgelastet, kann das betroffene Gerät bereits überlastet sein, bis der Controller einen bestimmten Eingang abfragt und die vorprogrammierte Aktion star tet. Prinzipiell könnte man einen Taster oder auch einen Sensorwert in regelmäßigen Abständen über digitalRead(pushButton); abfragen. Dieses Abfragen eines Schaltzustandes in regelmäßigen Abständen wird als „Polling“ (engl. für „Abfragen“) bezeichnet. Wird der betreffende Taster allerdings gedrückt, während das Anwendungsprogramm mit anderen Auf-
Programmstart
Interrupts aktivieren mit sei;
Interrupt
Abarbeiten der Interrupt-Sequenz
Hauptprogrammschleife Rücksprungin das Hauptprogramm
Bild 1: Programmablauf mit Interruptaufruf
ELVjournal 3/2015
44 So funktioniert’s
Interruptquellen
Das folgende Programm zeigt, wie eine LED über einen Interrupt gesteuert werden kann:
Mikrocontroller besitzen meist mehrere Interruptquellen. Dadurch kann ein µC auf verschiedene unvorhergesehene Ereignisse reagieren. Einzelne Interrupts werden über sogenannte Interruptvektoren angesprochen. Diese Vektoren sorgen dafür, dass die Ausführung immer // LED control via interrupt an der korrekten Adresse startet. Deshalb muss man sich beim Programmieren mit Processing nicht um spezielle Adressierungen kümmern. Es int ledpin = 13; ist vollkommen ausreichend, wenn man die r ichtigen Interruptvektoren volatile int state = L OW; kennt. Die wichtigsten Interruptquellen sind: · Reset void blink() // Change state of LED · Externer Interrupt 0 { state = !state; · Externer Interrupt 1 digitalWrite(ledpin, state); · Timer-/Counter-Ereignisse } · UART-Zeichen empfangen Für sogenannte externe Interrupts steht die Funktion void setup() attachInterrupt(interrupt, function, mode) { pinMode(ledpin, OUTPUT); attachInterrupt(0, blink, RISING); zur Verfügung. } Auf dem Arduino stehen zwei Pins für Interruptzwecke bereit: 1. Für Interrupt0 der Digital Pin 2 void loop() 2. Für Interrupt1 der Digital Pin 3 { Die Parameter der Funktion at tachInterrupt haben dabei die folgenden } Bedeutungen: interrupt: Nummer des Interrupts (0 oder 1) function: Diese Funktion wird aufgerufen, wenn der Interrupt ausgelöst wurde, sie wird auch als Interrupt-Service-Routine (ISR) bezeichnet Die LED 13 kann nun über den Drucktaster ein- und mode: Legt den Auslösemodus fest ausgeschaltet werden. Das Programm weist eine Besonderheit auf: Für die Funktion „mode“ sind 4 Varianten vordefiniert: Die Hauptprogrammschleife ist völlig leer! LOW: Auslösung, sobald der Interrupt-Pin auf LOW geht Dies demonstriert, dass die Interruptaufrufe abCHANGE: Interrupt wird bei jedem Signalwechsel am Interrupt-Pin solut unabhängig von einem Hauptprogramm erausgelöst folgen können. Wenn die Interruptbehandlung mit RISING: Übergänge von LOW nach HIGH lösen den Interrupt aus attachInterrupt erst einmal initialisiert ist, werden FALLING: Übergänge von HIGH nach LOW lösen den Interrupt aus die Interrupt-Pins völlig unabhängig von anderen Programmteilen überwacht. Der Programmcode innerhalb einer ISR sollte keine größeren VerzögerunDen zugehörigen Aufbau zeigt Bild 2. Der 100-nFgen enthalten. Triff t nämlich ein neuer Interrupt ein, während der alte Kondensator parallel zum Taster reduziert das sogenoch nicht abgeschlossen ist, so kann dieser nicht korrekt abgearbeitet nannte „Tasterprellen“. Wird der Kondensator entwerden. Zwar ist es prinzipiell möglich, mehrere Interruptebenen zuzu- fernt, dann kann es bei einem einzelnen Tastendruck lassen, jedoch sollte diese Technik aufgrund ihrer Fehlerträchtigkeit nur zu mehreren Umschaltvorgängen kommen. Weitere angewendet werden, wenn es keine anderen Möglichkeiten mehr gibt. Details zu diesem meist unerwünschten Effekt werden in einem späteren Beitrag zu dieser Artikelserie behandelt. TIPP:
Interrupt-Service-Routinen sollten immer möglichst kurz und einfach gehalten werden!
Wirkung der verschiedenen Interrupt-Modi
Ersetzen Sie den Interrupt-Modus „RISING“ nacheinander durch die anderen drei Betriebsarten: · LOW · CHANGE · FALLING und beobachten Sie, wann genau die LED jeweils geschaltet wird. Der nächste Sketch demonstriert ein einfaches „Multitasking“. Während im Hauptprogramm eine LED kontinuierlich blinkt, kann eine weitere LED unabhängig davon ein- und ausgeschaltet werden. Die zweite LED muss dazu an Port 12 angeschlossen werden (über einen geeigneten Vorwiderstand). Bild 2: Aufbau zur Interruptsteuerung
www.elvjournal.de
So funktioniert’s 45
// // // //
LED control via interrupt Blink a LED and simultaneously switch another one Interrupt 0 on DigitalPin 2
int led1pin = 13; int led2pin = 12; volatile int state = LOW; // Status LED_1
// Blink without using delay-function #include "TimerOne.h" // include timer lib int ledpin = 13; double tc = 1000000; // timeCounter = 1000000 μs = 1 s volatile int state = L OW;
void switch_led1() // Change state of LED { state = !state; digitalWrite(led1pin, state); }
void setup() { pinMode(ledpin, OUTPUT); Timer1.initialize(tc); Timer1.attachInterrupt(switch_led); }
void setup() { pinMode(led1pin, OUTPUT); pinMo de(led2pin, OUTPUT); attachInterrupt(0, switch_led1, RISING); }
void switch_led() // Change state of LED { state = !state; digitalWrite(ledpin, state); }
void loop() { digitalWrite(led2pin, HIGH); delay(100); delay(100); }
// LED on
void loop() { // main loop empty! }
Der Interrupt wird hier durch einen µC-internen Timer ausgelöst. Durch den Befehl
„Flüchtige“ Variablen Eventuell ist Ihnen in den beiden obenstehenden Programmen der Zusatz „volatile“ bei der Variablendeklaration bereits aufgefallen. „Volatile“ bedeutet „veränderlich, flüchtig“. Nun sind Variablen naturgemäß veränderlich, was ist also das Besondere an einer als „volatile“ definierten Variablen? Wird eine Variable nur innerhalb einer Interruptroutine verändert, so ist diese Veränderung im Hauptprogramm nicht sichtbar. Je nach Compilereinstellung wäre es bei der Übersetzung des Quellcodes möglich, dass die Variable durch eine Speicherplatz sparende Konstante ersetzt wird. Im Normalfall würde dies zu einem kompakteren und schnelleren Code führen. Ist aber eine Interruptroutine vorhanden, so muss dies ausgeschlossen werden, damit das Programm korrekt arbeitet. Der Zusatz „volatile“ bei einer Variablendefinition sorgt dafür, dass immer eine „echte“ Variable erzeugt wird, auch wenn diese scheinbar im Hauptprogramm gar nicht verändert wird. Das Schlüsselwort „volatile“ teilt dem Compiler also mit, dass die damit deklarierte Variable durch Ereignisse außerhalb der Kontrolle des Hauptprogramms verändert werden kann.
Timer1.attachInterrupt(switch_led);
wird festgelegt, dass nach Ablauf des Timers die Interruptroutine „switch_led“ aufgerufen wird. Diese Routine sorgt dann wie im vorhergehenden Beispiel dafür, dass die LED ein- bzw. ausgeschaltet wird. Dies hat den großen Vorteil, dass der Controller auf diese Weise nicht blockiert wird. Wird die „delay()“-Funktion verwendet, kann der Arduino in dieser Verzögerungsphase keine anderen Aufgaben ausführen. Er ist praktisch vollständig mit „Warten“ ausgelastet. In einem einfachen Blink-Programm spielt das keine große Rolle. Bei komplexeren Anwendungen möchte man den Controller aber selbstverständlich nicht mit Wartebefehlen auslasten. Man erkennt, dass auch hier die Hauptschleife vollkommen leer ist. Diese Programmebene kann also weiterhin unabhängig genutzt werden. In dieser Anwendung kommt auch bereits ein Counter zum Einsatz. Die Verwendung dieser nützlichen controllerinternen Funktionseinheiten wird im nächsten Artikel dieser Reihe näher erläutert werden. Die für diesen Sketch erforderliche Bibliothek TimerOne kann unter http://code.google.com/p/arduino-timerone/ downloads/list
kostenlos aus dem Internet geladen werden. Die Praxisübung: Blinken ohne Delay! Details zur Installation von Bibliotheken wurden In diesem Beispiel wird eine weitere Interruptquel- bereits im Arduino-Artikel Teil 5 „Nutzung und Erle vorgestellt. Nicht nur externe Ereignisse, wie der stellung von Programmbibliotheken“ erläutert (ELVPegelwechsel an einem Pin, können Interrupts aus- journal 4/2014). lösen, sondern auch controllerinterne Auslösungen sind möglich. Praxisprojekt: Fahrradrücklicht Das folgende Beispiel zeigt, wie eine LED zum mit Interruptsteuerung Blinken gebracht werden kann, ohne dass die De- Zum Abschluss soll hier noch das Modell eines Fahrradlay-Funktion zum Einsatz kommt. rücklichts mit verschiedenen Betriebsmodi vorgestellt ELVjournal 3/2015
46 So funktioniert’s
// Bike-Light with polling byte ledPin[5] = {8, 9, 10, 11, 12}; int switchPin = 2; int checkSwitch, switchState=0; int mode = 0;
Bild 3: Fahrradrücklicht mit verschiedenen Betriebsmodi
werden. Moderne akkubetriebene Fahrradrücklichter verfügen über mehrere LEDs. Diese können meist in verschiedene Betriebsmodi geschaltet werden. Neben einem einfachen Dauerlicht sind auch unterschiedliche Blink- und Lauflichteffekte aktivierbar. Bild 3 zeigt ein solches Rücklicht in Aktion. Das Modell eines solchen Rücklichts eignet sich bestens als Demonstrationsbeispiel für den Einsatz von Interrupttechniken. Bild 4 zeigt einen Aufbauvorschlag für die ArduinoHardware dazu. Der Wert für den eingezeichneten Kondensator kann zwischen 100 nF und ca. 10 µF liegen. Der Kondensator hat hier wieder die Aufgabe, das Tastenprellen zu reduzieren. Den optimalen Wert für den Kondensator bestimmt man am besten experimentell. So können bei bestimmten Tastern bereits mit Werten im Nanofarad-Bereich gute Ergebnisse erzielt werden, während stark prellende Taster Kondensatoren von bis zu einigen Mikrofarad erfordern. Das zugehörige Programm „Bike-Light“ zeigt, wie ein passender Sketch dazu aussehen kann. Hierbei wurde zunächst auf den Einsatz von Interrupts verzichtet. Stattdessen wird am Anfang der Endlosschleife void loop() der aktuelle Tasterstatus über checkSwitch abgefragt (sogenanntes „Polling“). Stellt das Programm fest, dass der Taster gedrückt ist, wird die Variable „mode“ zyklisch in der Form 0 -> 1 -> 2 -> 3 - > 0 weitergeschaltet. Entsprechend werden die Betriebsmodi: · Alle LEDs aus · Alle LEDs an · Alle LEDs blinken · Lauflichteffekt aktiviert. Soweit funktioniert das Fahrradrücklicht ganz zufriedenstellend. Allerdings stellt man bei genauerer Betrachtung fest, dass das Weiterschalten der Betriebszustände nicht ganz optimal abläuft. Insbesondere wenn der Modus „Lauflicht“ aktiv ist, kommt es vor, dass ein Tastendruck „verschluckt“ wird. Die Ursache für dieses Verhalten liegt darin, dass während des Ablaufs der Funktion „Lauflicht“ keine Tasterabfrage erfolgt. Erst wenn der Programmablauf wieder den Anfang der Hauptschleife erreicht hat, kann der Tastendruck erkannt werden. Ein solches Verhalten ist in der Praxis natürlich nicht erwünscht. www.elvjournal.de
// LEDs on pins 8 to 12 // switch on pin 2 // variables for switch control // display mode
void setup() { for (int n=0; n<5; n++) { pinMode(ledPin[n], OUTPUT); } pinMode(switchPin, INPUT); digitalWrite(switchPin, HIGH); // activate internal pull-up } void loop() { checkSwitch = digitalRead(switchPin); // check switch if (checkSwitch != switchState) // switch status changed! { if (checkSwitch == LOW) { mode++; if (mode > 3) mode=0; } } switchState = checkS witch; // save switch status switch (mode) { case 0:
for (int n=0; n<5; n++) { digitalWrite(ledPin[n], LOW); } } break; case 1: { // all LEDs on for (int n=0; n<5; n++) { digitalWrite(led Pin[n], HIGH); } } break; case 2: { // blink for (int n=0; n<5; n++) { digitalWrite(led Pin[n], HIGH); }delay(100); for (int n=0; n<5; n++) { digitalWrite(led Pin[n], LOW); }delay(100); } break; case 3: { // chaser for (int n=0; n<5; n++) { digitalWrite(ledPin[n], HIGH); delay(100); digitalWrite(ledPin[n], LOW); } } break; } }
Abhilfe kann hier der Einsatz der Interruptfunktionalität des Controllers schaffen. Der nächste Sketch zeigt, wie die Interrupttechnologie hier nutzbringend eingesetzt werden kann. Über die Programmzeile attachInterrupt(0, switch_update, RISING);
wird hier wieder ein Interrupt aktiviert. Damit wird, immer wenn der Taster betätigt wird, ein Interrupt ausgelöst. In der Interruptroutine void switch_update() { … mode++; if (mode > 3) mode=0; … }
// Change mode
So funktioniert’s 47
wird unverzüglich die Variable „mode“ um eins erhöht bzw. auf null zurückgesetzt. Um das Tasterprellen zu reduzieren, wurden zusätzlich während des Routineablaufs neue Interrupts deaktiv iert. Zusätzlich wurde in der Chaser-Schleife eine „mode“-Abfrage eingefügt. Nun reagiert das Programm wie gewünscht verzögerungsfrei auf jeden Tastendruck. Das „Verschlucken“ eines Tastendrucks ist jet zt ausgeschlossen. Falls dagegen gelegentlich ein Modus übersprungen wird, muss der Kondensatorwert angepasst werden. Durch Verwendung der Interrupttechnik und nach Optimierung des Entprellkondensators kann ein sehr bedienerfreundliches Schaltverhalten erreicht werden. Wie bereits weiter oben erwähnt, wird das Thema Entprellen und sicheres Schalten in einem späteren Beitrag zu dieser Serie nochmals eingehend diskutiert werden.
// Bike-Light with interrupt control byte ledPin[5] = {8, 9, 10, 11, 12}; int switchPin = 2; volatile int mode = 1; void switch_update() { noInterrupts(); mode++; if (mode > 3) mode=0; delay(100); interrupts(); }
// LEDs on pins 8 to 12 // switch on pin 2 // display mode // Change mode
void setup() { for (int n=0; n<5; n++) { pinMode(ledPin[n], OUTPUT); } pinMode(switchPin, INPUT); digitalWrite(switchPin, HIGH); // activate internal pull-up attachInterrupt(0, switch_update, FALLING); } void loop() { while (mode == 1) // all LEDs on { for (int n=0; n<5; n++) digitalWrite(led Pin[n], HIGH); } while (mode == 2) // blink { for (int n=0; n<5; n++) { digitalWrite(ledPin[n], HIGH); } delay(100); for (int n=0; n<5; n++) { digitalWrite(led Pin[n], LOW); } delay(100); } while (mode == 3) // chaser { for (int n=0; n<5; n++) { digitalWrite(ledPin[n], HIGH); delay(100); digitalWrite(led Pin[n], LOW); if (mode != 3) break; } }
{for (int n=0; n<5; n++) digitalWrite(ledPin[n], LOW); }
Bild 4: Arduino-basiertes Fahrradrücklicht mit verschiedenen Betriebsmodi
erhält man einen präzisen Timer, der den Aufbau von hochgenauen Frequenzzählern, Stoppuhren oder Digitalchronometern erlaubt. Auch im nächsten Beitrag werden dazu, wie gewohnt, neben den theoretischen Grundlagen wieder viele Prax isprojekte vorgestellt.
Weitere Infos: · G. Spanner: Arduino – Schaltungsprojekte für Profis, Elektor-Verlag 2012, Best.-Nr. J9-10 94 45, € 39,80 · Grundlagen zur elektronischen Schaltungstechnik finden sich in der E-Book-Reihe „Elektronik!“ (www.amazon.de/dp/B00OXNCB02) · Buch „AVR-Mikrocontroller in C programmieren“, Franzis-Verlag 2012, Best.-Nr. J9-09 73 52, € 39,95
} Preisstellung April 2015 – aktuelle Preise im Web-Shop
Ausblick
Nachdem in diesem Kapitel das Thema „Interrupts und Polling“ ausführlich behandelt wurde, wird im nächsten Beitrag der Einsatz von Timern und Countern erläutert. Diese Technologien basieren zu einem großen Teil ebenfalls auf der Erzeugung von Interrupts. Wird etwa über einen controllerinternen Hardwarezähler in regelmäßigen Zeitabständen ein Interrupt ausgelöst,
Empfohlene Produkte/ Bauteile: Arduino UNO Mikrocontroller Online-Kurs
Best.-Nr. J9-10 29 70 J9-10 20 44
Preis € 27,95 € 99,–
Alle Arduino-Produkte wie Mikrocontroller-Platinen, Shields, Fachbücher und Zubehör finden Sie unter: www.arduino.elv.de
ELVjournal 3/2015
26 So funktioniert’s
Arduino verstehen und anwenden Teil 11: Timer und Counter
www.elvjournal.de
So funktioniert’s 27
Timer und Counter gehören zu den wichtigsten Funktionseinheiten eines Mikrocontrollers. Obwohl ihre Aufgabe vergleichsweise einfach ist, erschließen sie eine Fülle von Anwendungen. Auch die in den verschiedenen Arduino-Versionen eingesetzten Controllertypen verfügen über diese nützlichen Funktionseinheiten. Im Rahmen dieses Beitrags werden die Counter- und Timereinheiten genauer unter die Lupe genommen und auch in praktischen Anwendungen eingesetzt.
Funktion und Verwendung Prinzipiell bestehen Counter aus einem controller-internen Zählregister. Wird dieses Zählregister in regelmäßigen Zeitabständen um den Wert eins erhöht oder reduziert, dann ent steht ein sogenannter Timer. Die Aufgabe eines Timers könnte theoretisch auch von einer konventionell programmierten while-Schleife übernommen werden. Diese würde aber den gesamten Programmablauf blockieren und der Arduino könnte keine weiteren Aufgaben parallel dazu ausführen. Das ist natürlich in den meisten Fällen nicht akzeptabel. Ein Counter dagegen verfügt über eine eigene Hardwareeinheit innerhalb des Controllers. Wenn er einmal gestartet ist, arbeitet er völlig unabhängig von anderen Controllereinheiten. Ein wichtiger Punkt ist dabei, dass der Counter bei einem bestimmten Zählstand einen Interrupt auslösen kann. Counter können sowohl von externen Ereignissen, wie etwa dem Pegelwechsel an einem bestimmten Prozessorpin als auch von internen Signalen gesteuert werden. Wird der Counter über das interne Taktsignal des Controllers gesteuert, entsteht ein präziser Timer. Dieser erlaubt die sehr exakte Erzeugung von Zeittakten. Die Genauigkeit, mit der diese Takte zu Verfügung stehen, wird letztlich nur durch den Quarzoszillator des Mikrocontrollers bestimmt. Neben dem Hauptoszillator des Controllers ist häufig auch noch ein sogenannter Uhren-Oszillator vorhanden. Dieser kann mit sehr präzise abgestimmten Uhrenquarzen angesteuert werden. Diese Quarze arbeiten meist mit einer Frequenz von 32.768 Hz (= 2 15 Hz). Mithilfe dieser Quarze können Uhren realisiert werden, die innerhalb von vielen Monaten nur Zeitabweichungen von wenigen Sekundenbruchteilen aufweisen.
Neben ihrer eigentlichen Funktion als Timer kommen Counter auch bei der Erzeugung von Analogsignalen mithilfe der Pulsweitenmodulation zum Einsatz. Auch hier gestatten sie eine sehr präz ise Einstellung der entsprechenden Signale, die mit anderen Mitteln nicht realisierbar wäre. Dieses Thema wird im nächsten Ar tikel eingehender behandelt.
Einfache Uhr mit programmgesteuerter Verzögerung In diesem Anwendungsbeispiel wird eine einfache Uhr programmiert. Die Ausgabe erfolgt direkt auf die serielle Schnittstelle. Die Zeitanzeige kann also auf jedem RS232-Terminal ausgegeben werden. Natürlich ist auch der serielle Monitor aus der Processing-IDE dafür einsetzbar. // Simple Clock int cnt, hours = 17, mins = 30, secs = 00; // hours, minutes, seconds int LED=13; void setup() { Serial.begin(9600); pinMode(LED,OUTPUT); } void loop() { cnt++; if(cnt==50)digitalWrite(LED,LOW); if(cnt==100) { digitalWrite(LED,HIGH); Serial.print("Current Time: "); if (hours < 10) Serial.print("0"); Serial.print(hours); Serial.print(":");
if (mins
< 10) Serial.print("0"); Serial.print(mins); Serial.print(":");
if (secs
< 10) Serial.print("0"); Serial.print(secs); Serial.println();
secs++; if(secs==60) { secs=0; mins++; if(mins==60) { mins=0; hours++; if(hours==24) hours=0; } } cnt=0; } delay(10);
}
Das Prinzip dieser Uhr ist simpel: Es wird einfach kontinuierlich eine Endlosschleife durchlaufen. Die Durchlaufzeit dieser Schleife soll mit delay(10); ELVjournal 4/2015
28 So funktioniert’s
auf 10 ms festgelegt werden. Bei jedem Schleifendurchlauf wird eine Zählvariable (cnt) um eins erhöht. Immer wenn diese Variable den Wert 50 erreicht hat, w ird die LED ausgeschaltet. Wird der Wert 100 erreicht, d. h. nach 100 x 10 ms = 1000 ms = 1 s wird die LED wieder aktiviert und die Uhr um eine Sekunde weitergeschaltet. Die LED blinkt also im Sekundentakt und die Uhr sollte nach jeder abgelaufenen Sekunde um eine Sekunde weiter zählen. Nach jeweils 60 Sekunden wird der Minutenwert um eins erhöht, nach 60 Minuten der Stundenwert und nach 24 Stunden wird der Stundenwert auf 0 zurückgesetzt. Da es üblich ist, Uhrzeiten im Format hh:mm: ss anzugeben, wurde im Programm noch für die „führenden Nullen“ gesorgt. Ansonsten würde die Zeit 17:30:05 im eher ungewöhnlichen Format 17:3:5 angezeigt. Wenn man die Uhr laufen lässt, kann man feststellen, dass soweit alles bestens funktioniert. Bild 1 zeigt die zugehörige Ausgabe der Uhrzeit auf dem seriellen Monitor.
Die Time-Library
Bild 1: Zeitausgabe im seriellen Monitor
Wie im Arduino-Umfeld üblich existiert auch f ür die Arbeit mit Uhrzeiten eine Library. Der folgende Sketch zeigt, wie diese Library eingesetzt wird.
Zeitmessung mit Timern
// clock using time lib char str[2]; #include
void setup() { Serial.begin(9600); setTi me(20, 0, 0, 1, 1, 15); // set time to 20:00:00 at 1. Jan. 2015 } void loop() { sprintf(str,"%02d", hour());
Serial.print(str); Serial.print(":");
sprintf(str,"%02d", minute()); Serial.print(str);
Serial.print(":");
sprintf(str,"%02d", second()); Serial.print(str);
Serial.println();
delay(1000);
Wirklich präzise Zeitmessungen sind am besten mithilfe eines Timers umsetzbar. Wie bereits erwähnt ist ein Timer nichts anderes als ein im Controller mit separater Hardware integrierter Zähler. Die Taktfrequenz des Zählers kann direkt aus dem Prozessortakt gewonnen werden. Der Timer läuft dann völlig unabhängig von der Programmausführung mit stabiler Quarzpräzision. Immer wenn der Timer abgelaufen ist, kann ein Interr upt ausgelöst werden. Dieser Interrupt erfolgt damit immer in präzise definierten Zeitabständen. Die zugehörige Bibliothek kann unter http://code.google.com/p/arduino-timerone/ downloads/list aus dem Internet geladen werden.
}
Die Time-Library kann unter http://playground.arduino.cc/code/time kostenlos aus dem Internet geladen werden. Zusätzlich wurde hier auch noch die Funktion „sprintf“ verwendet. Diese gestattet die Formatierung von Ausgaben an die serielle Schnittstelle. Hier sorgt die Angabe „%02“ für das einfügen der führenden Nullen. Weitere Details dazu finden sich in [1]. Lässt man die Arduino-Uhren eine gewisse Zeit laufen, so wird man schnell bemerken, dass sie erheblich nachgehen. Warum? Das Problem liegt darin, dass auch die Anweisungen für die Ausgabe auf die Schnittstelle oder die Befehle für die Anzeige der Sekunden und Minuten eine gewisse Zeit erfordern. Der delay-Wert im ersten Sketch müsste also etwas kleiner als 10 ms sein. Entsprechend müsste der Wert im zweiten Sketch weniger als 1000 ms betragen. Natürlich könnte man jetzt versuchen, durch Vergleich mit einer präzisen Uhr die korrekten delay-Werte zu best immen. Dieses „experimentelle“ Vorgehen ist allerdings recht aufwendig und wird auch nie zu einem präzisen Ergebnis führen, da die Durchlaufzeiten für die verschiedenen Programmteile stark und kaum vorhersehbar schwanken. www.elvjournal.de
Ein Timer kann so mit zwei Befehlen festgelegt werden: Timer1.initialize(i); und Timer1.attachInterrupt(procedure); Mit Timer1.initialize(); wird der Zeitabstand definiert, in welchem ein Interrupt ausgelöst wird. Die Variable i muss dabei in µs angegeben werden. Für einen Sekundentakt muss i = 1.000.000 µs = 1000 ms = 1 s gewählt werden. Dann wir die in Timer1.attachInterrupt(procedure); festgelegte „procedure“ exakt alle 1,000000 Sekunden aufgerufen, unabhängig von irgendwelchen anderen Aktivitäten des Mikrocontrollers.
Präzise Real Time Clock In diesem Anwendungsbeispiel soll der Timer praktisch eingesetzt werden. In der ersten Programmzeile wird dazu die Funktions-Bibliothek für TimerOne eingebunden: #include "TimerOne.h" // include timer
So funktioniert’s 29
Nach der Initialisierung des Timerinterrupts mit Timer1.initialize(1000000); Timer1.attachInterrupt(update_time); wird die update_time()-Routine immer in einem Zeitabstand von exakt 1 Sekunde aufgerufen.
Die Hauptprogramm-Schleife kann in diesem Beispiel wieder völlig leer bleiben. Wenn man nun die Ganggenauigkeit dieser Uhr mit den einfachen Uhrversionen mit Delay-Zeitverzögerung vergleicht, kann man schnell die deutlich verbesserte Ganggenauigkeit feststellen.
// precise interrupt controlled real time clock #include "TimerOne.h" #include char str[2]; void setup() { Serial.begin(9600); setTi me(15, 20, 0, 1, 1, 15); Timer1.initialize(1000000); // timeCounter = 1000000 μs = 1.000000 s Timer1.attachInterrupt(update_time); } void update_time() { sprintf(str,"%02d", hour()); Serial.print(str); Serial.print(":"); sprintf(str,"%02d", minute()); Serial.print(str); Serial.print(":"); sprintf(str,"%02d", second()); Serial.print(str); Serial.println(); } void loop() { /* main loop empty!*/ }
Countdown-Timer mit LEDs Natürlich möchte man die Zeit nicht nur am PC anzeigen, hier steht ja ohnehin meist eine integrierte Uhr zur Verfügung. In diesem Beispiel werden deshalb sechs LEDs als Anzeigeelemente verwendet. Um einen möglichst großen Bereich abzudecken, werden zur Anzeige nicht die einzelnen LEDs direkt verwendet, sondern es kommt die binäre Zahlendarstellung zum Einsatz. Damit kann man mit nur sechs LEDs immerhin 26 = 64 verschiedene Zustände anzeigen. Einem Sekunden-Countdown für Zeiten bis über eine Minute steht damit nichts mehr im Weg. Die LEDs werden der Reihe nach an Port B angeschlossen, d. h. an den Digitalpins 8 bis 13. Die einzelnen Pins werden hier direkt als Port angesprochen: // PORT B as output DDRB = 0b1111111; definiert alle Portpins des Ports B als Ausgänge. DDR steht dabei für Data DiRection. Weitere Details zur Verwendung der PORT-Anweisung finden sich in [1]. Im Sekundentakt wird dann der Wert seconds per Timerinterrupt um jeweils eins reduziert: void update_time() { if (seconds >0) seconds--; } Der aktuelle Wert von seconds wird im Hauptprogramm direkt als Binärzahl entsprechend dem Muster in Bild 2 ausgegeben. Aus Platzgründen wurden hier nur die Werte von 0 bis 31 angegeben. Wenn die Zeit abgelaufen ist, blinken alle LEDs simultan mit einer Frequenz von 10 Hz: if (seconds == 0) { PORTB = 0b111111; delay (100); PORTB = 0; delay (100);}
Bild 2: Zeitausgabe im Binärformat
Durch die Verwendung der PORT-Befehle fällt das Programm sehr kompakt aus: ELVjournal 4/2015
30 So funktioniert’s
// binary LED countdown timer #include "Timer One.h"
// include timer
double tc = 1000000; int seconds = 60;
// time Counter = 1000000 μs = 1.000000 s // start value
void setup() { DDRB = 0b1111111; // PORT B as output Timer1.initialize(tc); Timer1.attachInterrupt(update_time); } void update_time() { if (seconds >0) seconds--; } void loop() { PORTB = seconds; if (seconds == 0) { PORTB = 0b111111; delay (100); PORTB = 0; delay (100);} }
Den Aufbau zum Binärtimer zeigt Bild 3. Bild 3: Binärer Countdowntimer
Digitaluhren mit individueller Gestaltung
Bild 4: Individuell gestaltete Digitaluhr
Nachdem nun klar ist, wie man mithilfe von Timern präzise Zeiträume messtechnisch erfassen kann, kommt vielleicht der Wunsch auf, eine „richtige“ Digitaluhr mit echter Ziffernanzeige anstelle einer Binäranzeige aufzubauen. Diese Aufgabe ist mit dem Arduino durchaus lösbar. Allerdings muss man dafür noch das Problem der Ansteuerung von Siebensegment-Displays lösen. In einem späteren Beitrag zu dieser Reihe werden verschiedene Möglichkeiten aufgezeigt werden, wie eine solche Ansteuerung aussehen kann. In Kombination mit den hier vorgestellten Timerfunktionen stellt dann aber der Bau von individuellen Digitaluhren kein Problem mehr dar. Natürlich kann man solche Uhren auch käuflich erwerben. Der Eigenbau hat aber den Vorteil, dass man eigene Ideen realisieren kann . So stehen inzwischen Anzeigelemente in den verschiedensten Formen, Größen und Farben zur Verfügung. Bild 4 zeigt ein Beispiel für eine Eigenbau-Uhr mit blauer Anzeige.
Ausblick Weitere Infos: [1] Mikrocontroller-Onlinekurs, Franzis-Verlag, exklusiv für ELV, 2011, Best.-Nr. VA-10 20 44, € 99,– [2] G. Spanner: Arduino – Schaltungsprojekte für Profis, Elektor-Verlag 2012, Best.-Nr. VA-10 94 45, € 39,80 [3] Grundlagen zur elektronischen Schaltungstechnik finden sich in der E-Book-Reihe „Elektronik!“ (www.amazon.de/dp/B00OXNCB02) [4] Lernpaket „AVR-Mikrocontroller in C programmieren“, Franzis-Verlag 2012, Best.-Nr. VA-09 73 52, € 39,95 Preisstellung Juni 2015 – aktuelle Preise im Web-Shop
www.elvjournal.de
Eine weitere Anwendung von Timern und Countern ist die sogenannte Pulsweitenmodulation (PWM). Sie gestattet es, quasi-analoge Spannungen zu erzeugen und an einen Arduino-Pin auszugeben. Diese Technik wird im Mittelpunkt des nächsten Beitrags zu dieser Art ikelserie stehen. Darüber hinaus werden auch die Möglichkeiten des Einsatzes von Digital-Analog-Konvertern (DACs, für engl. Digital/Analog-Converter) diskutiert werden. Diese bilden das Gegenstück zu den bereits im Artikel VI, „Sensortechnik und Messwerterf assung“ besprochenen ADCs. Neben der präzisen Steuerung von Aktoren gestatten DACs auch die Ausgabe von Tönen und Musik.
Empfohlene Produkte/ Bauteile: Arduino UNO Mikrocontroller-Onlinekurs
Best.-Nr. VA-10 29 70 VA-10 20 44
Preis € 27,95 € 99,–
Alle Arduino-Produkte wie Mikrocontroller-Platinen, Shields, Fachbücher und Zubehör finden Sie unter: www.arduino.elv.de
18 So funktioniert’s
Arduino verstehen und anwenden Teil 12: Ausgabe von analogen Spannungen
www.elvjournal.de
So funktioniert’s 19
Im letzten Beitrag wurde die Anwendung von Countern und Timern erläutert. Dabei wurde bereits angesprochen, dass diese universellen controllerinternen Hardware-Einheiten auch zur Erzeugung von analogen Ausgangspannungen dienen können. Bislang konnte ein Arduino-Pin als klassischer digitaler Ausgang nur die Werte 0 V („0“ bzw. LOW) oder 5 V („1“ bzw. HIGH) annehmen. In vielen Anwendungen ist es aber wünschenswert oder sogar notwendig, dass auch analoge Spannungswerte, d. h. Werte zwischen 0 und 5 V ausgegeben werden können. Anwendungsbeispiele dazu sind die Helligkeitssteuerung von LEDs, die Drehzahlkontrolle von Motoren, oder aber auch die Ansteuerung von anderen Aktoren wie Peltierelementen oder Heizdrähten etc. Für die Erzeugung von Analogspannungen stehen mehrere Methoden zur Verfügung. Die beiden wichtigsten sind: · die Puls weitenmodulation (PWM) · der Digital-Analog-Konverter (DAC, von engl. D igital/ Analog- Converter)
Immer wenn der Zählerstand den Vergleichswert erreicht, wird ein festgelegter Ausgangspin des Arduinos umgeschaltet. Bild 1 zeigt den Zusammenhang zwischen dem Zähler-Vergleichswert und dem generierten PWM-Signal. Dabei zeigt die gestrichelte rote Linie den aktuellen Stand des Counters an. Wird der vorgegebene Vergleichswert erreicht, ändert der PWM-Ausgangspin seinen Pegel (siehe grün dargestellte Rechteckfläche). Der Pin wird bei aufwärts zählendem Counter auf HIGH, bei abwärts zählendem Counter auf LOW geschaltet. Es handelt sich in diesem Fall um eine sogenannte invertierende PWM, da der Mittelwert der Rechteckspannung mit zunehmendem Counter-Vergleichswert abnimmt.
100 %
V ergleichsw ert
50 %
U
In diesem Artikel werden beide Verfahren vorgestellt und Anwendungen wie · Ausgabe von Analogwerten über PWM · Mood-Light mit Multicolor-LED · Aufwachlicht · Von digital nach analog: der DAC · Digitale Funktionsgeneratoren beschrieben.
Ausgabe von Analogwerten über PWM Bei der PWM spielen Counter eine zentrale Rolle. Sie werden hier eingesetzt, um die Pulsbreite einer Rechteckspannung zu verändern. Kurze Pulse mit langen Pausen führen so zu einer geringen durchschnittlichen Spannung. Lange Pulse mit kurzen Pausen dazwischen entsprechen dagegen einem hohen Spannungsmittelwert. Die Frequenz der Rechteckspannung bleibt dabei immer konstant. Zur Erzeugung der unterschiedlichen Pulslängen wird ein sogenannter Vergleichswert in ein Counter-Register geladen. Dann wird der Counter in regelmäßigen Zeitabständen hochgezählt. Der Zähler ändert jeweils beim Zählerstand Null bzw. bei seinem Maximalwert die Zählrichtung.
50 %
t
V ergleichsw ert
100 % 90 %
t
U
10%
t
100 %
V ergleichsw ert
U
10 %
90 %
t Bild 1: Invertierende PWM
ELVjournal 5/2015
20 So funktioniert’s Bei Verwendung von Processing ist der Einsatz der PWM sehr einfach. Mit analogWrite (Pin_x, value) kann ein quasi-analoger Spannungswert der Höhe „value“ (0…255) erzeugt werden. Pin_x kann dabei einer der sechs PWM-Pins mit den Nummern 3, 5, 6, 9, 10 und 11 auf dem UNO-Board sein. Diese Pins sind mit einer Tilde (~) gekennzeichnet. Für eine echte Analogspannung müsste diese Rechteckschwingung noch elektronisch gefiltert werden. In vielen Fällen kann aber auch auf eine solche Filterung verzichtet werden, da die Mittelung des Signals an anderer Stelle erfolgt. Bei der folgenden Praxisanwendung ergibt sich die Mittelwertbildung beispielsweise im Auge des Betrachters. Das schnelle Schalten der LED verschwimmt dort zu einem kontinuierlichen Helligkeitseindruck.
Mood-Light mit Multicolor-LED
Eine interessante Anwendung der PWM-Steuerung stellt das sogenannte Stimmungslicht dar, das auch als „Mood-Light“ bekannt ist (Bild 2). Dabei wechselt eine Multicolor-LED kontinuierlich ihre Farben. Die Farbübergänge sollen dabei nicht abrupt sondern mit fließendem Übergang erfolgen. Hierzu wird jeweils eine Anode der Farb-LED über einen Vorwiderstand mit einem PWM-Ausgang des Arduinos verbunden. Im Programm werden dann nacheinander die Analogausgänge über die PWM langsam hoch- und wieder heruntergefahren. Durch die additive Farbmischung ergeben sich die unterschiedlichsten Summenfarben, einschließlich nahezu weißer Farbtöne.
Bild 2: Mood-Light
// Mood lamp for RGB LED int red, green, blue; int RedPin = 9; int GreenPin = 10; int BluePin = 11; int del = 10; void setup(){} void loop() {
for(red = 0; red < 255; red++)
{analogWrite (RedPin, red); delay(del);}
for(blue = 0; blue < 255; blue++)
{analogWrite (BluePin, blue); delay(del);}
for(green = 0; green < 255; green++)
{analogWrite (GreenPin, green); delay(del);}
for(blue = 255; blue > 0; blue--)
{analogWrite (BluePin, blue); delay(del);}
for(red = 255; red > 0; red--)
{analogWrite (RedPin, red); delay(del);}
for(green = 255; green > 0; green--)
{analogWrite (GreenPin, green); delay(del);}
for(blue = 0; blue < 255; blue++)
{analogWrite (BluePin, blue); delay(del);}
for(red = 0; red < 255; red++)
{analogWrite (RedPin, red); delay(del);}
for(red = 255; red > 0; red--)
{analogWrite (RedPin, red); delay(del);}
for(blue = 255; blue > 0; blue--)
{analogWrite (BluePin, blue); delay(del);}
}
Aufwachlicht
trollerausgang sollte nicht mit mehr als ca. 20 mA Mann kann sich mit den verschiedensten Methoden, wie etwa mit Musik belastet werden. Dagegen kann selbst ein einfacher oder mit Licht, wecken lassen. Geschieht das Wecken mit Licht, sollte Universaltransistor problemlos bis zu 100 mA verdieses nicht plötzlich eingeschaltet werden. Wesentlich angenehmer kraften. Damit lassen sich bereits mehrere recht ist es, wenn die Lichtintensität langsam zunimmt. Dies entspricht viel leuchtstarke LEDs ansteuern. mehr dem Helligkeitsverlauf eines natürlichen Sonnenaufgangs. In diesem Anwendungsbeispiel (Bild 3) zeigt sich Mittels PWM ist es möglich, nahezu natürliche Helligkeitsverläufe zu auch ein weiterer Vorteil der PWM. Im Gegensatz erzeugen. Für ein echtes Aufwachlicht liefert eine einzelne LED natür- zu einer rein analogen Steuerung wird bei der PWM lich eine zu geringe Helligkeit. kaum Leistung in einem Steuerelement umgesetzt. Mithilfe eines npn-Transistors (z. B. BC547 o. ä.) können aber meh- Da der Transistor entweder sperrt (Port auf „LOW“) rere LEDs simultan angesteuert werden, da der Transistor den Strom des oder voll durchgesteuert ist (PORT auf „HIGH)“, fällt Controller-Pins entsprechend verstärken kann. Ein einzelner Mikrocon- an ihm kaum Verlustleistung ab. www.elvjournal.de
So funktioniert’s 21
// wakeup light int LED, LEDPin = 11, del = 100; void setup() {} void loop() { for(LED = 0; LED < 255; LED++) {analogWrite (LEDPin, LED); delay(del);} for(LED = 255; LED > 0; LED--) {analogWrite (LEDPin, LED); delay(del);} analog Write (LEDPin, 0); delay(3000); }
Von digital nach analog: der DAC Die Messwerterfassung mit ADCs wurde bereits in Teil 6 „Sensortechnik und Messwerterfassung“ dieser Artikelserie (ELVjournal 5/2014) ausführlich behandelt. Der umgekehrte Weg – die Ausgabe von analogen Spannungen über den Arduino – soll hier näher beschrieben werden. Da die meisten Arduino-Varianten nicht über einen echten Digital/Analog-Converter (DAC) verfü- Bild 3: Aufwachlicht gen, muss man sich hier mit einer externen Beschaltung behelfen. Bild 4 zeigt eine Schaltung, die als „R-2R-Leiter“ bekannt ist. sind dann Funktionen wie Sinus, Rechteck oder DreiDie Ausgangsspannung dieser Schaltung ist: eck darstellbar. Man kann aber auch einzelne Werte U = U(D7) / 2 + U(D6) / 4 + U (D5) / 8 + … + U(D0) / 256 des Arrays manuell verändern und beliebige Werte zwischen 0 und 255 eintragen. Damit kann also über einen 8-Bit-Port eine AnalogIm nachfolgenden Beispielsketch wurden in den spannung mit einer Auflösung von 5 V/256 20 mV vier Zellen welche die Maximal- (255) bzw. Minimalausgegeben werden. werte (0) einer Sinusfunktion enthalten hatten, die Eine praktische Anwendung dieses DAC-Prinzips Zahl 128 eingetragen. wird im folgenden Praxisbeispiel erläutert.
Digitale Funktionsgeneratoren
In der Welt der Analogelektronik existieren sogenannte Funktionsgeneratoren. Die damit erzeugbaren „Funktionen“ umfassen meist ein Sinus-, ein Rechteck- und ein Dreiecksignal. Diese Signalformen sind mit analog-elektronischen Mitteln sehr leicht zu erzeugen. Andere Signalformen dagegen sind bei solchen Geräten kaum zu finden. Mithilfe eines Arduinos kann man diese Einschränkung leicht umgehen. Hier können nahezu beliebige Signalformen mit hoher Präzision erzeugt werden. Die gewünschte Kurvenform kann dabei als Datensequenz in digitaler Form im Speicher des Arduino-Controllers abgelegt werden. Die Ausgabe erfolgt über einen Parallelport mit angeschlossenem DAC. Im zugehörigen Sketch werden die gewünschten Funktionswerte in einem eindimensionalen Array „value[]“ abgelegt. Die Hauptschleife sorgt lediglich dafür, dass die Werte nacheinander an die Pins des Arduinos ausgegeben werden. Dort erfolgt mit dem R2R-Netzwerk die Umwandlung in eine analoge Spannung. Die Werte für das Array können mit einem Tabellenkalkulationsprogramm wie beispielsweise EXCEL oder LibreOffice erzeugt werden. Über Copy und Paste
D7
D6
2 k
2 k
A n a lo g Out 1 k
1 k D5
2 k 1 k
D4
2 k 1 k
D3
D2
D1
D0
2 k
2 k
2 k
2 k
1 k
1 k
1 k
2 k
Bild 4: R-2R-Leiter als DAC
ELVjournal 5/2015
22 So funktioniert’s
Bild 5: Spezialfunktion als Excel-Graphik
Bild 6: Zugehöriges Oszillogramm
Dadurch entsteht die in Bild 5 gezeigte „gestörte“ Sinusfunktion, die jeweils an den Scheitelwerten „Aussetzer“ aufweist. Damit kann man nun beispielsweise die Reaktion einer Analogschaltung auf dieses „fehlerhafte“ Sinussignal prüfen. Bild 6 zeigt das so erzeugte Signal auf einem Analog-Oszilloskop. Man erkennt deutlich, dass der Funktionsgenerator die eingegebene Kurvenform inklusive der „Glitches“ mit hoher Genauigkeit wiedergibt.
// a rbitrary function generator #include int value[] = {128,131,134,137,141,144,147,150,153,156,159,162,165,168,171,174, 177,180,183,186,189,191,194,197,199,202,205,207,209,212,214,217, 219,221,223,225,227,229,231,233,235,236,238,240,241,243,244,245, 246,247,248,249,250,251,252,253,253,254,254,255,255, 128,128,255,
Ausblick
Über die Analogausgabe lassen sich die verschiedensten Anwendungen realisieren. Bereits in diesem Artikel wurde das Dimmen von LEDs und die Erzeugung beliebiger Kurvenformen diskutiert. Im nächsten Artikel werden verschiedene periphere Geräte über den Arduino angesteuert. Insbesondere wird der Arduino dann nicht mehr nur optische Signale senden, sondern über einen Piezo-Schallwandler oder einen geeigneten Lautsprecher mit vorgeschaltetem Verstärker auch Töne erzeugen. Darüber hinaus steht auch die Ansteuerung anderer Verbraucher, wie Elektromagneten oder Gleichstrommotoren, auf dem Programm. Dabei können die in diesem Artikel erworbenen Kenntnisse zum Thema Analogausgabe wieder nutzbringend eingesetzt werden.
255,255,255,255,255,254,254,254,253,253,252,251,250,249,248,247, 246,245,243,242,240,239,237,236,234,232,230,228,226,224,222,220, 218,215,213,211,208,206,203,201,198,195,193,190,187,184,181,179, 176,173,170,167,164,161,158,155,152,148,145,142,139,136,133,130, 126,123,120,117,114,111,108,104,101,98,95,92,89,86,83,80, 77,75,72,69,66,63,61,58,55,53,50,48,45,43,41,38, 36,34,32,30,28,26,24,22,20,19,17,16,14,13,11,10, 9,8,7,6,5,4,3,3,2,2,1,1,0,0,128,128, 0,0,0,1,1,1,2,2,3,4,4,5,6,7,8,10, 11,12,13,15,16,18,20,21,23,25,27,29,31,33,35,37, 39,42,44,47,49,51,54,57,59,62,65,67,70,73,76,79,
Weitere Infos:
82,85,88,91,94,97,101,103,106,109,112,115,119,122,125 }; int main(void) {
DDRD = 0b11111111; while (1) {
for (unsigned int i = 0; i<=254; i++) PORTD = value[i];
}
[2] Mikrocontroller-Onlinekurs, Franzis-Verlag, exklusiv für ELV, 2011, Best.-Nr. CB-10 20 44, € 99,–
}
Empfohlene Produkte/ Bauteile:
Arduino UNO Mikrocontroller-Onlinekurs
[3] Grundlagen zur elektronischen Schaltungstechnik finden sich in der E-Book-Reihe „Elektronik!“ (www.amazon.de/dp/B00OXNCB02) Best.-Nr.
CB-10 29 70 CB-10 20 44
Preis
27,95 € 99,– €
Alle Arduino-Produkte wie Mikrocontroller-Platinen, Shields, Fachbücher und Zubehör finden Sie unter: www.arduino.elv.de
www.elvjournal.de
[1] G. Spanner: Arduino – Schaltungsprojekte für Profis, Elektor-Verlag 2012, Best.-Nr. CB-10 94 45, € 39,80
[4] Lernpaket „AVR-Mikrocontroller in C programmieren“, Franzis-Verlag 2012, Best.-Nr. CB-09 73 52, € 39,95 Preisstellung August 2015 – aktuelle Preise im Web-Shop
14 So funktioniert’s
Arduino verstehen und anwenden Teil 13: Peripheriegeräte: Piezos, Taster, Motoren und Elektromagnete
www.elvjournal.de
So funktioniert’s 15
Bislang wurden überwiegend LEDs als Ausgabemedien für den Arduino eingesetzt. Beginnend mit der bereits auf dem Arduino vorhandenen „LED 13“ über eine einzelne externe LED bis hin zu Lauflichtern mit einer Vielzahl von Leuchtdioden konnten so viele interessante Versuche aber auch nützliche kleine Pro jekte umgesetzt werden. In diesem Beitrag sollen nun weitere Ausgabe-Einheiten an das Arduino-Board angeschlossen werden. Neben Komponenten, die vom Arduino gesteuert werden können, wie etwa Elektromotoren oder -magnete, wird die Verwendung von Eingabegeräten wie Taster und Schalter erläutert. Sogenannte Piezokristalle nehmen hier eine Sonderstellung ein, da sie sowohl als Eingabe- als auch als Ausgabemedien dienen können. Zusammenfassend werden diese Ein- und Ausgabemedien auch als Peripheriegeräte oder -komponenten bezeichnet. Sie erlauben eine gewisse Einflussnahme des arduino-internen Microcontrollers auf seine Umgebung. Insofern führt dieser Artikel auch in das weite und überaus interessante Gebiet des „Physical Computings“ ein.
Arduino musikalisch Im Bereich der Mikrocontrolleranwendungen möchte man häufig Daten oder Signale nicht nur visuell darstellen sondern auch akustisch ausgeben. Mit dem Arduino ist das problemlos möglich. Dazu wird lediglich ein einfacher Schallwandler benötigt. Die einfachste Version eines solchen Wandlers stellt eine piezoelektrische Keramik dar. Legt man eine Wechselspannung an diese Keramik, so beginnt sie im Takt der Spannung zu schwingen und gibt so einen hörbaren Ton ab. Bild 1 zeigt zwei verschiedene Versionen von gängigen Schallwandlern, einmal ohne Gehäuse und einmal mit einlötbaren Pins und schwarzem Rundgehäuse. Da ein piezoelektrischer Schallwandler eine vergleichsweise hohe Impedanz aufweist, kann er direkt mit einem Mikrocontrollerausgang verbunden werden.
Bild 1: Piezoelektrische Schallwandler
bunden werden. Nach dem Laden des Programms ertönt die Melodie aus dem Piezo-Lautsprecher.
// Melody int speaker=9;
// select speaker channel
int len = 300, del = 200; // tone length and delay // tone frequencies int A = 440, H = 494; int C =
523, d = 587, e =
659, f =
698;
int g = 784, a = 880, h = 988, c = 1047; void setup() { pinMode(speaker, OUTPUT); } void loop() { tone(speaker,C,len);
delay(del);
tone(speaker,d,len); delay(del);
tone(speaker,e,len);
delay(del);
tone(speaker,f,len);
delay(del);
tone(speaker,g,len);
delay(del);
tone(speaker,f,len);
delay(del);
tone(speaker,e,len);
delay(del);
tone(speaker,d,len);
delay(del);
tone(speaker,d,len);
delay(del);
tone(speaker,e,len);
delay(del);
tone(speaker,C,len);
delay(del);
delay(3*del);
}
Praxisanwendung: Arduino als elektronische Grußkarte
Alarmsignale
Das folgende Programm spielt eine Melodie auf dem Piezo-Lautsprecher ab. Der piezoelektrische Schallwandler muss hierfür mit GND und Digital-Pin D9 ver-
Das folgende Programm zeigt, wie man mit dem Arduino ein durchdringendes Alarmsignal erzeugen kann. Die Belegung der Anschlüsse ist unverändert. ELVjournal 6/2015
16 So funktioniert’s
// ALARM! int Speaker=9; int i=0; void setup() { pinMode(Speaker, OUTPUT);
Welchen Wert zeigt die Anzeige im seriellen Monitor, wenn man den Taster beispielsweise 10-mal schnell hintereinander betätigt? Vermutlich liegt der Anzeigewert irgendwo zwischen 12 und 15! Was ist passiert? Eigentlich sollte doch der Anzeigewert genau mit der Anzahl der Tastendrucke übereinstimmen! Mit
}
{ if(!digitalRead(SW1)) void loop() { for(i=120;i<1600;i++) { tone(Speaker,i,10);
//delay(100); }
wird gewartet, bis der Taster den Pin3 auf LOW-Signal zieht. Dann wird das Programm weiter durchlaufen, bis in der Zeile
}
do {} while(!digitalRead(SW1));
Diese Praxisübung demonstriert, dass die Tonausgabe sehr flexibel programmierbar ist. Es gibt keinerlei Beschränkungen auf einfache Tonfolgen, mit etwas Phantasie und Geduld können auch sehr eindrucksvolle Klänge erzeugt werden. Umgekehrt erzeugt ein Piezo-Element eine elektrische Spannung, wenn es mechanisch belastet wird. Wie diese Spannung als Steuersignal für den Arduino verwendet werden kann, ist beispielsweise in [1] erläutert.
darauf gewartet wird, bis der Taster wieder frei gegeben ist. Wie kann es also dabei zu einem mehrfachen Durchlauf der Zählschleife bei einem einzelnen Tastendruck kommen? Das Problem liegt im Taster selbst. Die elektrischen Kontakte des Tasters liefern beim Betätigen nicht nur einen einmaligen Kontakt, sondern federn mehrmals zurück. Das Resultat ist kein einzelner Pegelwechsel, sondern ein ganzer Pulszug. Bild 2 zeigt das Oszillogramm eines Ausschaltvorgangs. Deutlich sind mehrere „spikes“ zu erkennen, die der Mikrocontroller natürlich korrekterweise als separate TastenTaster und Tasterprellen Tastenabfragen durch einen µC sind ein typisches drucke interpretiert. Dieses problematische VerhalBeispiel dafür, dass auch scheinbar einfache Schal- ten von mechanischen Tastern und Schaltern ist auch tungen ihre Tücken haben. als „Bouncing“ (engl. für „Prellen“) bekannt. Testen Sie das Programm der folgenden PraxisDieses Fehlverhalten kann auf verschiedene Weiübung. Schließen Sie den Taster zwischen Digital- sen verbessert werden. Neben speziellen schaltungsPin 3 und GND an. Führen Sie dann das Programm aus technischen Änderungen, wie entsprechend dimenund beobachten Sie dabei LED 13 und gleichzeitig sionierten RC-Gliedern, kann insbesondere auch eine die Ausgabe auf dem seriellen Monitor. sogenannte Software-Entprellung eingesetzt werden. Im nachfolgenden Sketch wird nach einer Wartezeit von 50 ms der Taster-Status erneut abgefragt. // Bouncing Nur wenn sich zweimal der gleiche Pegel ergibt, wird die Zählvariable erhöht. Spikes innerhalb der 50 ms byte n=0; haben damit keinen Einfluss auf das Zählergebnis. int SW1=3; int LED=13; int Toggle=0; void setup() {
Serial.begin(9600);
pinMode(SW1,INPUT);
digitalWrite(SW1,HIGH); Serial.println("Bouncing");
} void loop() { if(!digitalRead(SW1)) {
n++; Serial.print("Switch pressed ");
Serial.print(n,DEC); Serial.println(" times");
Toggle=!Toggle;
digitalWrite(LED,Toggle); do {} while(!digitalRead(SW1)); }
}
Bild 2: Kontaktprellen
www.elvjournal.de
So funktioniert’s 17
// Debouncing byte n=0; // counter int SW1=3; int LED=13; int Toggle=0; byte value_1, value_2=0;
void setup() { Serial.begin(9600); pinMode(SW1,INPUT); digitalWrite(SW1,HIGH); pinMode(LED,OUTPUT); Serial.println("Debounce"); } void loop() { value_1=digitalRead(SW1); if(!value_1) { delay(50); value_2=digitalRead(SW1); if(!value_2) { n++; Serial.print("Switch was pessed "); Serial.print(n,DEC); Serial.println(" times"); Toggle=!Toggle; digitalWrite(LED,Toggle); do{}while(!digitalRead(SW1)); } } }
Der Anzeigewert und die tatsächliche Anzahl von Tastenaktionen sollten nun deutlich besser übereinstimmen.
Ansteuerung von Relais und Elektromagneten
Ähnlich wie mit Tastern verhält es sich auch mit Relais. Obwohl es sich hier um Bauelemente handelt,
Bild 3: Relais am Arduino
! Wichtiger Hinweis: Vorsicht! Aufgrund der im Gerät frei geführten Netzspannung dürfen Aufbau und Inbetriebnahme ausschließlich von unterwiesenen Elektrofachkräften durchgeführt werden, die aufgrund ihrer Ausbildung dazu befugt sind. Die einschlägigen Sicherheits- und VDE-Bestimmungen sind unbedingt zu beachten.
die seit Jahrzehnten erfolgreich in der Elektrotechnik eingesetzt werden, treten in der Kombination mit Mikrocontrollern unerwartete Probleme auf. Relais sollten aus mehreren Gründen nicht direkt an den Port eines Mikrocontrollers angeschlossen werden. Gängige Relais ziehen Ströme von 100 mA und mehr. Wie bereits aus früheren Artikeln bekannt ist, sollte ein Port nicht mit mehr als 20 mA belastet werden. Außerdem erzeugen die in einem Relais enthaltenen Spulen starke Induktionsspitzen, welche die interne Treiberschaltung eines Controllerausgangs leicht zerstören können. Beide Probleme können mithilfe eines einfachen Kleinleistungstransistors gelöst werden. Geeignete Typen sind hier etwa der BC547 oder der 2N2222. Zum Abfangen der Induktionsspitzen ist dann noch eine sogenannte Freilaufdiode erforderlich. Universaltypen wie 1N4148 oder 1N4007 sind hier meist vollkommen ausreichend. Bild 3 zeigt die zugehörige Schaltung. An U_relais muss die für das verwendete Relais erforderliche Schaltspannung, meist 5 bis 12 V, angelegt werden. Mit diesem einfachen Aufbau können nun auch Ströme von mehreren Ampere oder Netzspannungen geschaltet werden. Hierbei ist natürlich immer darauf zu achten, dass die Schaltkontakte des verwendeten Relais für die gewünschten Stromstärken und Spannungen ausgelegt sein müssen. Bild 4 zeigt den zugehörigen Aufbau mit einem klassischen einpoligen Relais.
Bild 4: Relais am Arduino
ELVjournal 6/2015
18 So funktioniert’s
Der Sketch dazu sieht so aus:
int button = 2, relay = 13; int stateRelay = LOW, stateButton, previous = LOW; long time = 0, debounce = 500; int stayON = 5000; //stay on for 5000 ms void setup() { pinMode(button, INPUT_PULLUP); pinMode(relay, OUTPUT); } void loop() { stateButton = digitalRead(button); if(stateButton == LOW && previous == HIGH && millis() - time > debounce) { if(stateRelay == HIGH) { delay(stayON); stateRelay = LOW; } else stateRelay = HIGH; time = millis(); } digitalWrite(relay, stateRelay); previous = stateButton;
Bild 5: Ventilatorsteuerung via Arduino
}
Man erkennt, dass auch hier wieder eine softwaretechnische Entprellung vorgenommen wurde. Neben der einfachen Relaissteuerung enthält der Sketch auch eine Ausschaltverzögerung. Diese lässt etwa das Licht in einem Treppenhaus nach den Tastendruck noch einige Zeit nachleuchten. Ist die Ausschaltverzögerung nicht erwünscht, so kann die Programm-Zeile delay(stayON);
einfach gelöscht werden. Neben Relais können so auch Elektromagneten angesteuert werden. Auf diese Weise kann der Arduino beispielsweise auch die Entriegelung einer Türschließanlage betätigen.
Drehzahlsteuerung von Elektromotoren Analog zu den Elektromagneten können auch Gleichstrommotoren über den Arduino gesteuert werden. Motoren geringer Leistung können wieder über Kleinsignaltransistoren angesteuert werden. Für stärkere Motoren sind entsprechend ausgelegte Transistoren oder FETs er forderlich. Ein großer Vorteil bei der Ansteuerung von Gleichstrommotoren mit dem Arduino besteht darin, dass die Motoren nicht nur ein- und ausgeschaltet werden können, sondern sogar eine Drehzahlsteuerung möglich ist. Wird der Motor über einen PWM-Ausgang mit dem Arduino verbunden, kann die Motorleistung in weiten Grenzen eingestellt werden. www.elvjournal.de
Bild 6: Aufbaubild zur Ventilatorsteuerung
Die Pulsweitenmodulation hat zudem den Vorteil, dass im Steuertransistor im Vergleich zu einer linearen Spannungssteuerung sehr wenig Leistung verloren geht. Zudem erreicht ein PWM-gesteuerter Motor auch bei geringen Drehzahlen bereits ein großes Drehmoment. So können Roboterfahrzeuge, Rollladensteuerungen oder Wasserpumpen sehr feinfühlig angesteuert werden.
So funktioniert’s 19 Die Ansteuerung des Motors er folgt wieder über einen Transistor, je nach Stromaufnahme des Motors kann hier auch ein Leistungstransistor wie etwa der BD135 erforderlich sein. Als Temperatursensor wurde hier ein einfacher NTC eingesetzt. Details zu diesem Sensortyp finden sich im Artikel 6: „Sensortechnik und Messwerterfassung“ zu dieser Serie (ELVjournal 5/2014). Der zugehörige Sketch liest den Spannungswert am Analogeingang A1 aus und rechnet diesen in einen Temperaturwert um. Über einen Vergleich mit dem Schwellwert „tempLimit“ wird dann der Ventilator ein- bzw. ausgeschaltet. Bei Bedarf kann hier natürlich auch noch eine gewisse Hysterese vorgesehen werden, um übermäßig häufiges Schalten in der Nähe der Umschalttemperatur zu verhindern. Möchte man die Motorleistung in Abhängigkeit von der Temperatur regeln, so kann man den Steuertransistor auch an einen PWM-Ausgang anschließen und die Pulsweite der Spannung entsprechend der gemessenen Umgebungstemperatur erhöhen oder reduzieren.
// fan conrol // using P5V to 4k7 NTC temperature sensor @ ADC1, 4k7 to GND int fanPin = 2; int AD C_value; void setup() { pinMode(fanPin, OUTPUT); pinMode(13, OUTPUT); Serial.begin(9600); } void loop() { ADC_value=analogRead(1); Serial.print("Temp = "); Serial.print(temp,1); Serial.println(" delay(1000);
");
if (temp > tempLimit) { digitalWrite(13, HIGH); digitalWrite(fanPin, HIGH); } else { digitalWrite(13, LOW); digitalWrite(fanPin, LOW); }
}
Empfohlenes Material
Best.-Nr.
Preis
Arduino UNO MikrocontrollerOnlinekurs
CD-10 29 70
€
CD-10 20 44
€
27,95 99,–
Alle Arduino-Produkte wie Mikr ocontroller-Platinen, Shields, Fachbücher und Zubehör finden Sie unter: www.arduino.elv.de
Weitere Infos:
[1] Lernpaket „AVR-Microcontroller in C programmieren“, Franzis-Verlag, 2012 Mikrocontroller-Onlinekurs, Franzis-Verlag, exklusiv für ELV, 2011, Best.-Nr.: CD-10 20 44
Ausblick
Nachdem in diesem Beitrag der Anschluss von verschiedenen Peripheriegeräten erläutert und diskutiert wurde, stehen im nächsten Artikel Sieben-Segment-Displays im Vordergrund. Diese weit verbreiteten Anzeigetypen gestatten die einfache und gut lesbare Anzeige von Zahlen und Ziffern. Aber auch auf die Steuerung weiterer peripherer Komponenten wird ein späterer Artikel nochmals genauer eingehen. Dort wird es dann auch darum gehen, wie ein Elektromotor in beiden Drehrichtungen gesteuert werden kann und wie sogenannte Schrittmotoren zur präz isen Positionierung von Druckerköpfen oder Roboterarmen eingesetzt werden.
G. Spanner: Arduino – Schaltungsprojekte für Profis, Elektor-Verlag, 2012 Best.-Nr.: CD-10 94 45 Grundlagen zur elektronischen Schaltungstechnik finden sich in der E-Book-Reihe „Elektronik!“ (http://www.amazon.de/dp/B00OXNCB02) G. Spanner: Coole Projekte mit dem Arduino Micro, Franzis-Verlag, 2014 ELVjournal 6/2015
66 So funktioniert’s
Arduino verstehen und anwenden Teil 14: 7-Segment-Displays am Arduino
www.elvjournal.de
So funktioniert’s 67
Neben dem Arduino selbst sind meist nur noch wenige Bauelemente erforderlich, um ein vollständiges Gerät aufzubauen. Wird der Controller beispielsweise mit einer 7-Segment-LED-Anzeige kombiniert, so entsteht eine sehr universell nutzbare Plattform, auf der sich viele interessante Projekte realisieren lassen. Einige Beispiele dazu wie · eine einzelne 7-Segment-Anzeige · ein 4-stelliges Display · eine Digitaluhr werden im folgenden Artikel ausführlicher beschrieben.
CA/CC f g ab a f
b g
e
c d DP
e d c DP CA/CC Bild 1: Typische Pin-Belegung einer einzelnen 7-Segment-An zeige
Einfach und preisgünstig: 7-Segment-Displays Ziffern können mit sogenannten 7-Segment-Anzeigen einfach und effizient dargestellt werden. Derartige Anzeigen bestehen häufig aus acht LED-Elementen (sieben S egmente plus Dez imalpunkt). Die LED-Segmente sind in der Form einer Acht angeordnet. Durch entsprechende Aktivierung bestimmter Elemente können so die Ziffern von 0 bis 9 in gut lesbarer Form dargestellt werden. Darüber hinaus lassen sich auch noch einige Großbuchstaben anzeigen (z. B. A, C, E, F etc.). Möchte man weitere Buchstaben anzeigen, müsste man Sechzehn-Segment-Anzeigen einsetzen. Diese sind aber vergleichsweise wenig verbreitet und daher teuer. Eine andere Möglichkeit, um Buchstaben und einfache Grafiken anzuzeigen, bieten die sogenannten Punktmatrix-Displays. Diese werden in einem späteren Artikel zu dieser Serie beschrieben. 7-Segment-Anzeigen werden in den verschiedensten Formen, Farben und Anschlussbelegungen hergestellt. Ein weit verbreiteter Typ ist in Bild 1 dargestellt. Die einzelnen Segmente werden üblicherweise mit den Buchstaben a bis g bezeichnet. Die Anschlüsse sind entweder die gemeinsame Anode (Common Anode: CA) oder die gemeinsame Katode (Common Cathode, CC) der Segmente, je nach Displaytyp. Bild 2 und 3 zeigen, wie die 7-Segment-Anzeige an einen Arduino UNO angeschlossen werden kann. Unter Anwendung des sogenannten Multiplex-Verfahrens kann man hier mit nur einem einzigen gemeinsa-
Bild 2: Ansteuerung einer einzelnen 7-Segment-Anzeige
Bild 3: Die 7-Segment-Anzeige zeigt die Ziffer 7.
Anschluss der Display-Pins an die Arduino-Ausgänge D0 bis D7 1 e l l e b a T
Arduino-Pin
D0
D1
D2
D3
D4
D5
D6
D7
Display-Pin
a
b
DP
c
d
e
f
g
men Vorwiderstand für alle LED-Segmente auskommen. Tabelle 1 verdeutlicht nochmals den Anschluss der Display-Pins an die Arduino-Ausgänge D0 bis D7. ELVjournal 1/2016
68 So funktioniert’s
Der Sketch dazu sieht so aus:
Die „for“-Schleife in der Loop zählt die Ziffern 0 bis 9 ab. Die Darstellung der Ziffern erfolgt in der Routine „showDigit“. Dort werden die Segmente einzeln aktiviert. Je nachdem, ob im „numbers“-Array eine Null oder eine Eins steht, wird das aktuelle Segment eingeschaltet oder nicht. Obwohl man bei einer Einzelziffer noch mit einer statischen Ansteuerung arbeiten könnte, wurde hier bereits ein Multiplexverfahren implementiert. Das bedeutet, dass zu einem gegebenen Zeitpunkt immer nur ein Segment aktiv ist. Erst durch die rasche Abfolge der Segmentumschaltung entsteht der Eindruck einer stehenden Ziffer.
// 7 seg ment LED d isplay // seven seg ment codes int numbers[10][8] = //a b D c d e f g {{1,1,0,1,1,1,1,0}, // 0 {0,1,0,1,0,0,0,0}, // 1 {1,1,0,0,1,1,0,1}, // 2 {1,1,0,1,1,0,0,1}, // 3 {0,1,0,1,0,0,1,1}, // 4 {1,0,0,1,1,0,1,1}, // 5 {1,0,0,1,1,1,1,1}, // 6 {1,1,0,1,0,0,0,0}, // 7
Das 4x7-Segment-LED-Display
{1,1,0,1,1,1,1,1}, // 8
Zu den Hauptvorteilen von 7-Segment-LED-Anzeigen zählt, dass sie auch aus größerer Entfernung noch gut ablesbar sind. Durch die Lichtemission der LEDs sind die Anzeigen selbst bei Dämmerung und Dunkelheit gut erkennbar. Ein vierstelliges Display mit zusätzlichen Dezimalpunkten ist dabei sehr universell einsetzbar. Zum einen lassen sich damit gut Stunden und Minuten für eine Uhr oder Minuten und Sekunden für einen Timer darstellen. Andererseits ist auch eine Anzeige mit zwei Vor- und zwei Nachkommastellen realisierbar. Damit lassen sich Spannungen oder Stromstärken gut anzeigen. Für eine Temperaturanzeige in Grad Celsius kann man sogar einen einfachen Trick anwenden, um ein Grad-Zeichen darzustellen. Ein übliches 4x7-Segment-Display enthält 32 LEDElemente. 4 x 7 = 28 LEDs sind für die Zifferndarstellung erforder lich. Dazu kommen dann noch beispielsweise 4 Dezimalpunkte. Meist sind jedoch entweder alle Anoden oder alle Katoden jeweils einer Ziffer zusammengeführt. Darüber hinaus werden auch alle Anoden bzw. Katoden der jeweiligen Segmente verbunden. Ein solches Display weist dann nur 12 Pins auf: – 7 Pins für die Katoden der Displaysegmente a, b, c, d, e, f und g – 1 Pin für die Dezimalpunkte (DP) – 4 Anoden für die Einer- (E), Zehner- (Z), Hunderter- (H) und Tausender-Stelle (T) Je nachdem, ob die Anoden oder Katoden zusammengefasst sind, spricht man auch hier von CommonAnode- (CA) oder Common-Cathode-Displays (CC). Neben der Einsparung von Pins hat die gemeinsame Herausführung von Anschlüssen noch den Vorteil, dass die betreffenden Anzeigen sehr leicht im sogenannten Zeitmultiplex betrieben werden können. Bild 4 zeigt wieder das Pinning einer gängigen Displayversion, diesmal jedoch mit 4 Digits. Das Bauelement selbst ist in Bild 5 zu sehen. Bild 6 zeigt, wie mit diesem Display-Typ Uhrzeiten bzw. Messwerte oder Temperaturen, inklusive des Sonderzeichens „°“, dargestellt werden können.
{1,1,0,1,1,0,1,1}, // 9 }; void showDigit(int Digit) { // clear all seg ments for (int i=0; i<=7; i++)
digitalWrite(i, LOW);
for(int i=0; i<=7; i++) // select one seg ment after another { if(numbers[Digit][i]==1) { digitalWrite(i, HIGH); // segment on
delay(3); digitalWrite(i, LOW); } else delay(3); // for time equalization }
} void setup() { // pins 0 to 7 as outputs for (int i=0; i<=7; i++) pinMode(i, OUTPUT); } void loop() { for (int n=0; n<=9; n++) for (int i=0; i<=30; i++)
showDigit(n);
}
Hier wird zunächst die Pin-Belegung in einem Array „numbers“ festgelegt.
Tipp: Angaben zur Pin-Belegung einer 7-Segment-Anzeige finden sich im Datenblatt. Unterscheidet sich die Pin-Belegung eines bestimmten Displays von der hier verwendeten Displayversion, dann kann entweder die Pin-Tabelle in der Software (Array „numbers“) oder aber die Schaltung angepasst werden.
Im Setup werden alle erforderlichen Pins als Ausgänge aktiviert. www.elvjournal.de
4-stellige 7-Segment-Displays als Basis für Messgeräte und Uhren Mit einer einzelnen 7-Segment-Anzeige kann man bereits verschiedene Betriebszustände, etwa einer Wasch- oder Spülmaschine, anzeigen oder längere
So funktioniert’s 69
Zahlenreihen sequenziell ausgeben. Für die meisten Anwendungen sind aber mehrere Ziffern erforderlich. Mit 4-stelligen Displays sind viele praxistaugliche Geräte wie Volt- und Amperemeter, Ohm-Meter oder auch Temperaturanzeigen realisierbar.
T
T
b
f
c
e
H
Z
H
f
c
e
d
Z
a b
f
c
e
c
g
b
c d
d DP
E g
g
d e
b
a b
g
g d
In einem ersten Programm soll nun die Anzeige zunächst getestet werden. Mit Hilfe der Include-Datei display_driver.h fällt das Programm sehr kurz aus:
f
a
a f
e
Displaytest
a
E
Bild 4: Anschlussbelegung eines typischen 4x7-Segment-LEDDisplays
// 4x7 display test #include “display_driver.h” void setup() { DDRB = 0xFF; DDRD = 0x0F; }
// set ports B & D as output
void loop() { send_int_to_LCD(1234, 2); } Bild 5: 4x7-Segment-LED-Display
Es müssen lediglich die mit dem Display verbundenen Ports als Ausgänge konfiguriert werden. Dies erfolgt durch die direkten C-Anweisungen DDRB = 0xFF; DDRD = 0x0F
da hier auch Pins genutzt werden, die nicht direkt über den klassischen Arduino-Befehl „pinMode()“ erreichbar sind. Dann kann über send_int_to_LCD(1234, 2); eine beliebige Zahl (hier beispielsweise „1234“) an das Display gesendet werden. Das 2. Argument dieser Funktion legt fest, an welcher Stelle der Dezimalpunkt gesetzt werden soll. Dabei beginnt die Zählung mit null für die ganz linke Position. Die Hauptarbeit wird natürlich in der Include-Datei display_driver.h erledigt. Diese Datei wird im übernächsten Abschnitt näher erläutert. Zunächst soll hier aber noch eine praktische Anwendung des LED-Displays in Form einer Digitaluhr vorgestellt werden.
Bild 6: Die 4x7-Segment-LED-Anzeige als Uhrendisplay oder zur Anzeige von Temperaturen
Digitaluhr mit LED-Display Eine der klassischen Anwendungen von 4-stelligen 7-Segment-Anzeigen sind Digitaluhren. Der Eigenbau einer solchen Uhr hat den großen Reiz, dass man bei der Gestaltung völlig freie Hand hat. Bild 7 zeigt eine Variante, die unter Verwendung eines Arduino MICRO entstanden ist. Auf den Boards ist die gesamte Elektronik, einschließlich des Arduino MICRO, untergebracht. Hier zeigt sich wieder der große Vorteil der Bauform des Arduino MICRO. Ein derartig kompakter Aufbau wäre mit einem Arduino UNO nicht möglich.
Bild 7: Digitaluhr mit Arduino MICRO
ELVjournal 1/2016
70 So funktioniert’s
Das Schaltbild zur Digitaluhr ist in Bild 8 zu sehen. Man erkennt, dass neben dem Arduino und dem Display selbst nur noch wenige Bauteile notwendig sind: 4x PNP-Universaltransistoren, z. B. BC557 8x Widerstand 1 k 4x Widerstand 10 k Diese insgesamt 4 Transistoren und 8 Widerstände reichen aus, um eine hochwertige Uhr aufzubauen. Wenn man die Beiträge dieser Ar tikel-Serie bislang aufmerksam durchgearbeitet hat, bietet das Programm zur Uhr (siehe unten) keine Verständnisprobleme. Die drei Variablen sc, mn und hr sind die jeweiligen Zähler für Sekunden, Minuten und Stunden. Ein Zeitzähler „timeCounter“ wird zu jeder vollen Sekunde um den Wert eins erhöht. Innerhalb der Sekunde wird die aktuelle Uhrzeit laufend an das Display gesendet:
Der Display-Treiber Der Vollständigkeit halber wird hier noch der zugehörige Display-Treiber erläutert. Dieses Include-File ist auch wieder ein schönes Beispiel dafür, dass man bei der Programmierung des Arduino nicht ausschließlich mit den Befehlen der Arduino-IDE arbeiten muss. Man kann auch durchaus klassische C-Befehle einsetzen. Im Programm werden im Array „numbers“ zunächst die einzelnen Ziffern gemäß der nachfolgenden Tabelle 2 codiert:
while (sc==tc) send_int_to_LCD(hr*100+mn, dotPos);
Erst wenn tc um eins weiterzählt, wird der Dezimalpunkt umgeschaltet: dotPos = 5 - dotPos; Dabei bedeutet dotPos=1, dass der Punkt an der mittleren Position leuchtet, während dotPos = 4 den Dezimalpunkt löscht, da diese Position physikalisch nicht vorhanden ist. Dann wird nur geprüft, ob jeweils 60 Minuten vergangen sind und der Stundenzähler erhöht werden muss bzw. ob nach 24 Stunden der Stundenzähler auf null zurückzusetzen ist.
// digital clock #include “display_dr iver.h” #include “TimerOne.h” #define intTime 1e6
// include display driv er // include timer lib // interr upt time = 1000000 us = 1.000 s
byte timeCounter = 0; byte sc= 00, mn=30, hr=17; byte dotPosition = 1;
// timeCounter // seconds, minutes, hours // position of decimal dot
void setup() { DDRB = 0xFF; DDRD = 0x0F; // set Port s B & D as output Timer1.initialize(intTime); Timer1.attachInterrupt(tick); }
void loop() { sc=timeCounter; if (sc==60) { timeCounter=0; sc= 0; mn++; if (mn==60) { mn=0; hr++; if (hr== 24) hr=0 ; } } while (sc== timeCounter) send_int_to_LCD(hr*100+mn, dotPosition); dotPosition = 5 - dotPosition ; // blink decimal dot @ position 1 } void tick() {timeCounter++;}
www.elvjournal.de
2 e l l e b a T
Zif fer
Binär
a
f
b
g
c
DP
d
e
0 1 2 3 4 5 6 7 8 9
0b00010100 0b11010111 0b01001100 0b01000101 0b10000111 0b00100101 0b00100100 0b01010111 0b00000100 0b00000101
0 1 0 0 1 0 0 0 0 0
0 1 1 1 0 0 0 1 0 0
0 0 0 0 0 1 1 0 0 0
1 1 0 0 0 0 0 1 0 0
0 0 1 0 0 0 0 0 0 0
1 1 1 1 1 1 1 1 1 1
0 1 0 0 1 0 0 1 0 0
0 1 0 1 1 1 0 1 0 1
Soll z. B. die Ziffer „0“ dargestellt werden, so müssen alle Segmente bis auf das g-Segment leuchten. Da eine Anzeige mit gemeinsamer Anode gewählt wurde, bedeutet dies, dass alle Ausgänge, bis auf den am g-Segment angeschlossenen Pin, auf „low“ liegen müssen. Daraus ergibt sich ein Binärmuster für die „0“ von: 0b00010100 entsprechend der ersten Zeile der Tabelle. Analog können so auch alle anderen Ziffern codiert werden. Auch andere Zeichen sind auf diese Weise darstell bar. So kann das °-Zeichen binär als 0b00001111 geschrieben und in einer Temperaturanzeige entsprechend eingesetzt werden.
Die Routine void send_int_to_LCD(int n, int dot)
verteilt die einzelnen Ziffern einer 4-stelligen Zahl an die Digits des Displays. Danach werden zyklisch die Digits 1 bis 4 für die Einer-, Zehner-, Hunderterund Tausender-Stelle aktiviert. Dabei wird über die Routine void digit (unsigned int value, unsigned int pin)
jeweils eine Ziffer dargestellt.
So funktioniert’s 71
Der vollständige Treiber sieht damit so aus:
// display driver #include
T a
const int numbers [10] = { 0b00010100, 0b11010111, 0b01001100, 0b01000101, 0b10000111, 0b00100101, 0b00100100, 0b01010111, 0b00000100, 0b00000101}; char DX000, D0X00, D00X0, D000X; char act_dig = 0;
f H Z b
e d DP c
g E
// store single digits
// Write numb er at ind icated position to display void digit (unsigned int value, unsigned int pin) { PORTB = num bers[value]; // send number to output PORTD &= ~(1 << pin); // PinLow => current digit on }
5x 1k
3x 1k
VCC
10k
10k 10k 10k
// set decim al dot, pos = 0 leftmost ... pos = 3 rightmost // pos > 3 no dot void set_dot (int pos) { if (pos < 4) { PORTB = 0b11111011; PORTD &= ~(1 << pos); } } void send_int_to_L CD(int n, int dot) { // distribute number to digits DX000 = n/1000; n %= 1000; D0X00 = n/100; n %= 100; D00X0 = n/10; n %= 10; D000X = n; // activate digits one after another switch(act_dig) { case 0: digit (D000X, 3); break; case 1: digit (D00X0, 2); break; case 2: digit (D0X00, 1); break; case 3: digit (DX000, 0); brea k; case 4: set_dot(dot); } act_dig++; if (act_dig == 5) act_dig = 0; }
3 U 2 4
Bild 8: Schaltbild zur Digitaluhr
Weitere Infos:
[1] G. Spanner: Arduino – Schaltungsprojekte für Profis, Elektor-Verlag 2012, Best.-Nr. CF-10 94 45, € 39,80 [2] Mikrocontroller-Onlinekurs, Franzis-Verlag, exklusiv für ELV, 2011, Best.-Nr. CF-10 20 44, € 99,– [3] Grundlagen zur elektronischen Schaltungstechnik finden sich in der E-Book-Reihe „Elektronik!“ (www.amazon.de/dp/B00OXNCB02) [4] Lernpaket „AVR-Mikrocontroller in C programmieren“, Franzis-Verlag 2012, Best.-Nr. CF-09 73 52, € 39,95
Ausblick
Nachdem in diesem Beitrag die Anwendung und Ansteuerung von ein- und mehrstelligen 7-Segment-Anzeigen ausführlich diskutiert wurde, geht es im nächsten Beitrag um die Ansteuerung größerer LED-Displays mittels einer flexiblen Library. Damit lassen sich auch Anzeigeeinheiten mit bis zu 12 Digits ansteuern. Neben Ziffern und Zahlen können dann auch kurze Textnachrichten ausgegeben werden. Darüber hinaus stellt die Library auch Funktionen f ür die Ansteuerung von Dezimaltrennungszeichen und Doppelpunkten zur Verfügung. Damit lassen sich praktisch alle gängigen Displayeinheiten effizient und komfortabel ansteuern.
Preisstellung Dezember 2015 – aktuelle Preise im Web-Shop
Empfohlene Produkte/ Bauteile: Arduino UNO Arduino MICRO Mikrocontroller-Onlinekurs
Best.-Nr. CF-10 29 70 CF-10 97 74 CF-10 20 44
Preis € 27,95 € 24,95 € 99,–
Alle Arduino-Produkte wie Mikrocontroller-Platinen, Shields, Fachbücher und Zubehör finden Sie unter: www.arduino.elv.de
ELVjournal 1/2016
56 So funktioniert’s
Arduino verstehen und anwenden Teil 15: Multidigit-LED-Displays
www.elvjournal.de
So funktioniert’s 57
Im letzten Beitrag wurden Anwendung und Funktionsweise von 7-Segment-Anzeigen ausführlich beschrieben. Durch den Einsatz der sogenannten Multiplextechnik konnten Anzeigen mit bis zu 4 Digits aufgebaut werden. Hierzu wurde ein Displaytreiber entwickelt, welcher für die Ansteuerung der einzelnen LED-Segmente verantwortlich war. Wie aber aus früheren Artikeln bereits bekannt ist, stehen für Arduino-Anwendungen häufig umfangreiche Programmbibliotheken zur Verfügung. Dies trifft auch auf die Ansteuerung von LED-Displays zu. Für die Displaysteuerung existieren sogar mehrere Varianten. Eine der umfangreichsten und ausgereiftesten ist die SevenSeg-Library. Wie üblich kann diese unter http://sim.marebakken.com/SevenSeg.zip kostenlos aus dem Internet geladen werden. Mittels dieser Bibliothek können auch komplexe Displays mit bis zu 12 Digits angesteuert werden. Genau genommen ist die Anzahl der Digits theoretisch sogar unbegrenzt, in der Praxis zeigt sich jedoch, dass Anzeigen mit mehr als 12 Stellen zu Problemen führen. Im Rahmen dieses Artikels soll diese Bibliothek etwas ausführlicher diskutiert werden. Natürlich werden auch wieder Praxisbeispiele und Anwendungen vorgestellt, u. a. · Ansteuerung von Anzeigeeinheiten mit bis zu 12 Digits · Numerische und alphanumerische Zeichendarstellung · Digitale Counter und Frequenzzähler mit d ig 1 hoher Auflösung
leicht durch Ausmessen bestimmen. Hierzu benutzt man einfach eine Spannungsquelle mit geeignetem Vorwiderstand (z. B. 1 k) und testet die verschiedenen Pins. Man muss dann nur noch notieren, welches Segment bei einer bestimmten Kontaktierung aufleuchtet.
Die Funktionen der Library Die SevenSeg-Library gestattet es, verschiedenste Informationsformate zu benutzen. Es werden alle gängigen Arten von Displays unterstützt. D ie Bibliothek kann für einfache Aufgaben genutzt werden, sie enthält aber auch Funktionen, die den fortgeschrittenen Anwender ansprechen. Zu den Leistungsmerkmalen der Library gehören insbesondere: · Unterstützung von Displays mit Dezimalpunkten, Trennungsdoppelpunkten oder Apostrophen · Es sind sowohl CC- als auch CA-Displays ansprechbar
d ig 2
d ig 3
d ig 4
d ig 2
d ig 3
d ig 4
Multiplexbetrieb größerer Displayeinheiten Im letzten Artikel wurde das Prinzip des Zeitmultiplex erläutert. Dabei kam auch ein Displaytreiber zum Einsatz, der an verschiedene Anzeigeeinheiten angepasst werden konnte. Hier soll nun die Anwendung der Bibliotheksfunktionen im Vordergrund stehen. Zunächst kann man mehrstellige 7-Segment-Anzeigen in zwei Gruppen einteilen: · CA: Bauelemente mit gemeinsamer Anode (für Common Anode) – siehe Bild 1 (zugehöriges Schaltbild) · CC: Bauelemente mit gemeinsamer Katode (für Common Cathode) – siehe Bild 2 (zugehöriges Schaltbild) Den internen Aufbau eines speziellen Displays kann man dem zugehörigen Datenblatt entnehmen. Falls zu einem bestimmten Display keine Informationen erhältlich sind, kann man das Pinning aber auch sehr
A
B
C
D
E
F
G
Bild 1: Display mit gemeinsamer Anode (CA)
A
B
C
D
E
F
G
d ig 1
Bild 2: Display mit gemeinsamer Katode (CC)
ELVjournal 2/2016
58 So fun funktioniert’s tioniert’s
Bild 3: Nahezu mathematische Genauigkeit: die ersten 12 Ziffern der Zahl Pi
Darüber hinaus sind Routinen enthalten, welche die folgenden Anzeigeformate unter stützen: · Verschiedene Zahlenformate wie Ganzzahlen, Festkomma- oder Fließkommazahlen · Textausgabe · Anzeigen von Uhrzeiten im hh:mm- oder mm:ss-Format · Automatisches Multiplexing mit einstellbarer Wiederholrate · Einstellung der Displayhelligkeit über das PWM-Taktverhältnis der Ansteuerung · Einsatz von Timer-Interrupts in der Multiplexsteuerung · Vermeidung sogenannter Schattenartefakte
Ansteuerung einer 12-stelligen Anzeige In einem ersten Anwendungsbeispiel soll eine 12-stellige CA-Anze ige (siehe Bild 3) mittels der Bibliothek angesteuert werden. Die gemeinsamen Anoden können direkt mit den Arduino-Ports verbunden werden. Die Segment-Pins des Displays werden über geeignete Vorwiderstände mit den Arduino-Ausgängen verbunden. Für erste Experimente können hier 1-k -Widerstände verwendet werden. Falls die Anzeige damit zu dunkel erscheint, können die Widerstandswerte reduziert werden. Wenn ein Datenblatt zum Anzeigemodul vorliegt, kann man die Widerstandswerte natürlich auch aus den erlaubten Maximalströmen berechnen und so die optimale Helligkeit des Displays nutzen. Weitere Details zum Anschluss des Displays an den Arduino finden sich auch im letzten Beitrag zu dieser Ar tikelserie. Der Sketch dazu sieht folgendermaßen aus: // 12x7-segment LED display #include // segments
a
b
c
d
e
f
g
SevenSeg disp (7 ,5 ,3 ,1 ,0 ,6 ,4); const int numOfDigits=12; // Ardui no pins
A4
A3
A2
A5
A0
// digit
12
11
10
9
8
A1
D12 D13 D8 D9 D10 D11 7
int digitPins [numOfDigits]={ 18, 17, 16, 19, 14, 15,
6 12,
5 13,
8,
4
2
9,
10,
2
1
11};
char str[12]; void setup () { disp.setDigitPins (numOfDigits, digitPins); } void loop () { disp.write("314159265359"); }
Die Segmente a bis g werden also der Reihe nach an die Digital-Pins D7, D5, D3, D1, D0, D6 und D4 des Arduinos angeschlossen. Die gemeinsamen Digit-Pins 1 bis 12 des Displays werden entsprechend mit den noch freien Arduino-Ausgängen D8 bis D12 sowie mit den Analog-Ports A0 bis A5 verbunden. Dabei ist zu beachten, dass in diesem Fall die Analog-Pins A0 bis A5 als Digitalausgänge D14 bis D19 geschaltet werden.
Hardware-Varianten Eine besondere Stärke der SevenSeg-Bibliothek ist die Möglichkeit zur Einstellung verschiedenster Hardware-Varianten. So kann die Belegung der Digit- und Segment-Pins mit www.elvjournal.de www.e vjourna . e
So fun funktioniert’s tioniert’s 59 Bild 4: CC-Display mit Transistor-Treibern
A
B
C
d ig 1
D
E
F
G
d ig 2
d ig 3
d ig 4
der Funktion SevenSeg(A, B, C, D, E, F, G); beliebig festgelegt werden. Für A bis G sind lediglich die Port-Pins anzugeben, an welche die Segmente A bis G angeschlossen sind. Entsprechend kann mit void setDigitPins(numOfDigits, DigitPins); die Anzahl der Digits und deren Anschlussreihenfolge festgelegt werden. Die Anzahl der anzuzeigenden Stellen ist dabei in numOfDigits anzugeben, die PinReihenfolge wird durch das Array DigitPins definiert. Über die Funktionen void setCommonAnode(); void setCommonCathode(); wird die Topologie des Displays festgelegt. Wird keine Topologie angegeben, dann wird ein CA-Display als voreingestellter Wert angenommen. Die Funktion void setActivePinState(segActive, digActive); legt fest, ob die Segmente high- oder low-aktiv sind. Diese Funktionen werden benötigt, wenn Treibertransistoren zum Einsatz kommen. Dies wird erforderlich, wenn ein Arduino-Pin nicht genügend Strom für ein komplettes Digit liefern kann. Bild 4 zeigt, wie in diesem Fall NPN-Transistoren eingesetzt werden können, um höhere Ströme zu treiben. Während ein Arduino-Pin nur maximal mit 20 mA belastet werden sollte, können mit Kleinsignal-Transistoren (z. B. BC547 o. Ä.) problemlos 100 mA oder mehr geschaltet werden. Hier müsste dann die zugehörige Programmzeile setActivePinState (HIGH,HIGH); eingefügt werden.
Darstellung alphanumerischer Zeichen
Wie bereits im letzten Artikel erwähnt wurde, können mit 7-Segment-Anzeigen nicht nur Ziffern, sondern auch einige Buchstaben angezeigt werden. Allerdings hat dieses Verfahren den Nachteil, dass nicht alle Buchstaben gut erkennbar dargestellt werden können. So kann beispielsweise der Großbuchstabe B nicht von der Ziffer 8 unterschieden werden, da in beiden Fällen alle 7 Segmente leuchten müssen. Auch die Buchstaben K oder W lassen sich praktisch nicht in leserlicher Form erzeugen. Für viele System-
Bild 5: Darstellung von Informationstexten mit 7-Segment-An zeigen
a
f
b
g e
c d
Bild 6: Darstellung des Buchstaben W in der SevenSeg-Library
anzeigen kann man sich allerdings gut behelfen, indem man geeignete Texte wählt. Damit kann man bei Messgeräten auch Statusanzeigen oder Systemzustände ausgeben, ohne dass ein zusätzliches Display eingebaut werden muss. Bild 5 zeigt ein Anwendungsbeispiel für die Ausgabe der Information „System full up“ in einem 7-Segment-Display. Die SevenSeg-Library unterstützt diese Anwendung. Für die nicht eindeutig darstellbaren Zeichen werden dabei Ersatzcodes verwendet. Für den Buchstaben W werden beispielsweise die Segmente B, D und F aktiviert (siehe Bild 6).
Digitale Frequenzzähler
Anwendungen, welche viele Anzeigestellen benötigen, sind beispielsweise Frequenzzähler und Counter. Da Frequenzen durch Verwendung von Quarzen mit hoher Genauigkeit erfasst werden können, ist es sinnvoll, auch entsprechend viele Stellen anzuzeigen. Ein ELVjournal LVjourna 2 2/2016 2016
60 So funktioniert’s
Voltmeter kommt meist mit 3 bis 4 Stellen aus, da Spannungen mit moderatem Aufwand meist nur bis auf 0,1 % genau gemessen werden können. Entsprechendes gilt für Strom- und Widerstandsmessungen. Elektronische Quarze liefern dagegen problemlos eine Genauigkeit im ppm-Bereich, d. h. Abweichungen liegen in der Größenordnung von 1:1.000.000 (parts per million). Damit man diese Präzision auch anzeigen kann, sind Displays mit einer entsprechenden Stellenzahl er forderlich. Die Frequenzmessung selbst wird wiederum durch eine Library vereinfacht. Unter http://interface.khm.de/index.php/ lab/interfaces-advanced/ arduino-frequency-counter-library/ kann diese wieder kostenlos aus dem Netz geladen werden. Die Library erfasst Frequenzimpulse über den Arduino-Pin D5, da dieser in der Sekundärfunktion als T1 dient. T1 ist der Eingang für den 16-Bit-Hard-
// // // //
ware-Counter des Controllers auf dem Arduino. Mit Hilfe dieses Counters können Impulse mit hoher Präzision erfasst werden. Weitere Informationen zu den internen Hardware-Timern des Arduino-Controllers finden sich in [5] und im Teil 11: „Timer und Counter“ zu dieser Artikelserie (siehe ELVjournal August/September 2015) unter Webcode #1433. Die Impulszählung erfolgt mit einer Torzeit von 1000 ms = 1,000 s. Die Anzahl der Impulse gibt also direkt die an D5 angelegte Frequenz in Hz wieder. Die Torzeit wird in der Programmzeile FreqCounter::start(1000) // … angegeben. Im Setup wird eine erste Dummy-Messung ausgeführt, um Fehlmessungen aufgrund von undefinierten Werten im Zählerpuffer zu vermeiden. In der Hauptschleife wird dann kontinuierlich die anliegende Frequenz gemessen und an das 7-Segment-Display ausgegeben.
Frequency display using 12x7-segment LED display **** for ATmega328, i. e. Arduino UNO **** use A0 as D14, A1 as D15, ...
#include #include
// a b c d e f g SevenSeg disp (7 ,8 ,3 ,1 ,0 ,6 ,4); const int numOfDigits =10; int digitPins [numOfDigits]={ 18, 17, 16, 19, 14, 15, 12, 13, 10, 11}; char buf[14]; void setup () { disp.setDigitPins (numOfDigits, digitPins); for (int i = 0; i < 300; i++) // dry run for settling FreqCounter::f_com p=100; // Cal Value FreqCounter::start(1000); // 1000 ms Gate Time while (FreqCounter::f_ready == 0) disp.write("counter up"); delay(10); } void loop () { FreqCounter::f_comp=100; FreqCounter::start(1000); while (FreqCounter::f_ready == 0) { frq = FreqCounter::f_freq; dtostrf(frq, 7, 0, buf); disp.write(buf); disp.write(" Hz"); } }
www.elvjournal.de
So funktioniert’s 61 Der Frequenzzähler in Aktion
Der Frequenz-Messwert „frq“ wird dazu über die Funktionen dtostrf(frq, 7, 0, buf); in eine Puffer-Zeichenkette „buf “ umgewandelt. Beim Befehl „dtostr f“ handelt es sich um eine Standart-C-Funktion, die eine Dezimalzahl in eine ASCII-Zeichenkette umwandelt. Die Parameter 7 und 0 steuern die Format ierung. Der neue String enthält so mindestens 7 Zeichen und 0 Nachkommastellen. Auf diese Weise wird die Frequenz rechtsbündig im LED-Display dargestellt. Fehlende Stellen werden durch „Blanks“ aufgefüllt, so dass keine unschönen führenden Nullen entstehen. Weitere Details zu diesen Funktionen finden sich in [5] und [6]. Durch die Kombination dieser beiden Funktionen wird erreicht, dass die Frequenz an der korrekten Position im Display ausgegeben wird. Der Wert wird dann in disp.write(buf); angezeigt.
Weitere Infos: [1] G. Spanner: Arduino – Schaltungsprojek te für Profis, Elektor-Verlag 2012, Best.-Nr. CG-10 94 45, € 39,80 [2] Mikrocontroller-Onlinekurs, Franzis-Verlag, exklusiv für ELV, 2011, Best.-Nr. CG-10 20 44, € 99,– [3] Grundlagen zur elektronischen Schaltungstechnik finden sich in der E-Book-Reihe „Elektronik!“ (www.amazon.de/dp/B00OXNCB02) [4] Lernpaket „AVR-Mikrocontroller in C programmieren“, Franzis-Verlag 2012, Best.-Nr. CG-10 68 46, € 129,– [5] G. Spanner: AVR-Mikrocontroller in C programmieren, Franzis-Verlag 2010, Best.-Nr. CG-09 73 52, € 39,95 [6] G. Spanner: AVR-XMEGA-Mikrocontroller, Elektor-Verlag 2015, Best.-Nr. CG-12 07 62, € 39,80 Preisstellung Februar 2016 – aktuelle Preise im Web-Shop
Schließlich wird noch über disp.write(" Hz"); die Einheit der Frequenzmessung (Hz für Hertz) eingeblendet. Die maximal messbare Frequenz liegt bei ca. 4 MHz; ein Wert, der für viele Anwendungen vollkommen ausreichend ist. Die Messgenauigkeit wird lediglich durch den 16-MHz-Quarz des Arduino begrenzt. Sie beträgt typischerweise nur wenige ppm und ist somit für die meisten nicht professionellen Anwendungen vollkommen ausreichend. Ausblick
Nachdem in diesem Beitrag die Anwendung und Ansteuerung von mehrstelligen 7-Segment-Anzeigen ausführlich diskutiert wurde, wird im nächsten Serienbeitrag die sogenannte LED-Punktmatrix-Displaytechnologie im Vordergrund stehen. Im Gegensatz zu den 7-Segment-Anzeigen erlaubt dieser Displaytyp auch die klar lesbare Darstellung aller Buchstaben des Alphabets. Darüber hinaus ist sogar die Anzeige einfacher Grafiken möglich. Durch Zusammenfügen mehrerer Matrixeinheiten können auf diese Weise auch größere Displays aufgebaut werden, bis hin zu den bekannten Mega-Werbeflächen auf öf fentlichen Plätzen, Flughäfen oder Bahnhöfen.
Empfohlene Produkte
Arduino UNO Mikrocontroller-Onlinekurs
Best.-Nr.
Preis
CG-10 29 70 CG-10 20 44
€ 27,95 € 99,–
Alle Arduino-Produkte w ie Mikrocontroller-Platinen, Shields, Fachbücher und Zubehör finden Sie unter: www.arduino.elv.de
ELVjournal 2/2016
64 So funktioniert’s
Arduino verstehen und anwenden Teil 16: Einsatz und Anwendung von LED-Matrizen
www.elvjournal.de
So funktioniert’s 65
Die LED-Punktmatrix als universelle Displayeinheit Nachdem in den beiden letzten Teilen dieser Artikelserie der Einsatz von 7-Segment-Anzeigen ausführlich dargestellt wurde, soll in diesem Beitrag ein weiteres sehr populäres Display im Vordergrund stehen. Im Gegensatz zu den 7-Segment-Anzeigen können mit sogenannten Punktmatrix-Anzeigen nicht nur Ziff ern, sondern auch alle Buchstaben des Alphabets gut lesbar dargestellt werden. Darüber hinaus ist auch die Erzeugung einfacher Symbole und Grafiken möglich. LED-Punktmatrizen, oft auch als Dot-Matrix-Displays bezeichnet, sind inzwischen weit verbreitet. Man findet sie an öffentlichen Verkehrsmitteln genauso wie in allen Großflughäfen der Welt, in Börsensälen zeigen sie als sogenannte „Live-Ticker“ aktuelle Wertpapierkurse an. Aus naheliegenden Gründen erfreuen sich Dot-Matrizen insbesondere im asiatischen Raum großer Beliebtheit (Bild 1). Matrix-Displays sind in den verschiedensten Bauformen erhältlich. Bild 2 zeigt beispielsweise eine LED-Matrix mit 5 x 7 = 35 LEDs.
Bild 1: Insbesondere in asiatischen Ländern sind LED-Punkt-Matri zen sehr beliebt.
LED-Punktmatrix im Multiplexbetrieb Die Ansteuerung der 5x7-Punktmatrix könnte mit 36 Leitungen erfolgen: z. B. mit 35 Anodenanschlüssen und einer gemeinsamen Kathode. Wesentlich einfacher ist es aber, die LEDs als echte Matrix anzusteuern. Hierbei werden jeweils die 5 LEDs in einer Spalte bzw. die 7 LEDs in eine Zeile zusammengeschaltet. Anstelle der 36 Anschlussleitungen sind nun nur noch 5 + 7 = 12 Anschlüsse zu beschalten. Das Ansteuerungsprinzip der Matrix ist in Bild 3 dargestellt. Zur Vereinfachung wurde hier eine 3x4-Matrix gewählt. Statt der 13 Anschlüsse für eine Einzelansteuerung der LEDs sind hier nur 7 Verbindungen er forderlich. Um nun beispielsweise die zweite LED in der zweiten Zeile zu aktivieren, müssen bis auf den zweiten alle Zeilenanschlüsse auf „High“ gelegt werden. Der zweite Anschluss dagegen muss GND-Potential führen. Bei den Spalten darf ausschließlich die zweite Spalte High-Potential aufweisen.
Bild 2: 5x7-LED-Matri x: Die „1“ links unten kennzeichnet meist Pin 1.
GND
5V
GND
GND
5V
GND
5V
Bild 3: Prinzip der Punktmatrix-Ansteuerung
ELVjournal 3/2016
66 So funktioniert’s
Anschluss der LED-Punktmatrix an den Arduino Die Bilder 4 und 5 zeigen, wie die Matrix an den Arduino angeschlossen werden kann. Beim Einbau der Matrix ist darauf zu achten, dass Pin 1 auf den nachfolgenden Aufbaubildern links unten liegt.
WICHTIG: Sie sollten die Ansteuerschaltung mit größter Sorgfalt aufbauen. Falls ein erforderlicher Widerstand fehlt oder falsch eingesetzt ist, kann das zur Zerstörung einzelner Matr ix-LEDs führen!
Am besten geht man beim Anschluss der Matrix an den Arduino in der Reihenfolge der Controllerpins vor. Verbinden Sie also zunächst den Digital-Pin D1 mit dem Dot-Matrix-Pin 4, dann den Digital-Pin D2 mit dem Dot-Matrix-Pin 5 usw. Nicht vergessen, die Vorwiderstände korrekt mit einzuschleifen!
Der „springende Punkt“ Das folgende Programm aktiviert eine Matrix-LED nach der anderen. Dabei wird in der linken oberen Ecke begonnen und dann jeweils eine Spalte durchlaufen. Anschließend folgt die nächste Spalte. Auf diese Weise entsteht der Eindruck, dass ein Lichtpunkt ähnlich wie ein Ball von links nach rechts durch die Anzeige springt. Falls Ihr Display ein anderes Verhalten zeigt, sollten Sie nochmals die Verbindungen zum Mikrocontroller prüfen.
// running dot on 7x5 m atrix LED display
void setup()
void loop()
Darstellung von Ziffern und Buchstaben auf dem LED-Display
Bild 4: Schaltbild zum Anschluss der LED-Matrix an den Arduino
Natürlich kann man das Matrix-Display auch sinnvoller nutzen. Eine sehr wichtige Anwendung von Matrix-Anzeigen ist die Darstellung von alphanumerischen Zeichen. Dazu müssen nur die Zahlen als grafische Muster codiert werden. Will man beispielsweise eine 1 darstellen, so müssen die Spalten nacheinander die folgenden Muster zeigen: 0 1 0 1 1 0 0 1 0 0 1 0 0 1 0
Bild 5: Aufbaubild zu Bild 4
www.elvjournal.de
D. h., in die Spalten müssen die Werte 00010, 11111, 00000 geschrieben werden (die Zählung der Zeilen muss hier von unten nach oben erfolgen, da der „Nullpunkt“ links unten liegt). Wandelt man die Binärcodes in Dezimalzahlen um: 00010 -> 2 11111 -> 31 00000 -> 0 ergibt sich der Code für die 1: int n[][3] = … { 0, 31, 2}, // 1 …
So funktioniert’s 67
Wenn man das Programm „Number Display“ genau analysiert, kann man feststellen, dass das Feld n [][3] genau diese Zahlenfolge enthält. Im Hauptprogramm muss dann nur noch dafür gesorgt werden, dass die Spalten nacheinander in schneller Reihenfolge angezeigt werden. Das Verfahren, einzelne LED-Segmente (in unserem Fall die Spalten des Displays) schnell nacheinander anzuzeigen, ist weit verbreitet und entspricht wieder dem bekannten Zeitmultiplexing. Beträgt die Frequenz, mit der die einzelnen LEDs angesteuert werden, mehr als ca. 70 Hz, so kann das Auge dem schnellen Wechsel nicht mehr folgen und es entsteht der Eindruck einer kontinuierlichen Anzeige. Bild 6 zeigt die Matrix-Anzeige in Aktion. Will man neben den Ziffern auch Buchstaben (Bild 7) anzeigen, so kann man die zugehörigen Codes analog zu den Ziffern erzeugen. Auf diese Weise lassen sich die Buchstaben des Alphabets sehr viel besser darstellen als mit nur 7 Segmenten. Will man die Lesbarkeit noch weiter steigern, so muss man pro Buchstabe ein volles 7x5-Matrixelement verwenden. Dann können auch breite Buchstaben wie M oder W problemlos angezeigt werden. Natürlich kann man auf diese Weise auch einfache Grafiken wie Sternchen oder Smileys erzeugen.
Bild 6: Zifferndarstellung
Bild 7: Alphanumerische Zeichendarstellung mit einer LED-Matrix
// num ber display on 7x5 dot matrix
void loop()
void setup()
ELVjournal 3/2016
68 So funktioniert’s
In den nächsten beiden Beiträgen wird dabei das LC-Display im Vordergrund stehen. Die einfachere Form stellen dabei alphanumerische Anzeigeeinheiten dar. Sie können beispielsweise 2 Textzeilen zu je 16 Zeichen darstellen. Diese können über wenige Leitungen angesteuert werden. Mit geeigneten Bibliotheken stellt die Ansteuerung derartiger Displays mit dem Arduino kein Problem dar. Aber auch grafikfähige Anzeigen sind vom Arduino aus steuerbar. Mit vergleichsweise geringem Aufwand können damit sehr ansprechende Anzeigeeinheiten realisiert werden. Auf diese Weise lassen sich bereits professionell Bild 8: 8x16-Matrix, angesteuert über MAX7219-Treiber wirkende Kleingeräte für die unterschiedlichsten Anwendungen aufbauen. Temperaturen, Spannungen oder andere Messwerte können damit genauso einfach und präzise dargestellt werden wie Uhrzeiten Verwendung von Displaytreibern Ein Nachteil der direkten Ansteuerung von Punktmatrizen mit dem Ar- und kurze Textnachrichten. duino ist, dass dafür bereits ein großer Teil der Rechenleistung des Controllers benötigt wird. Wenn zusätzlich noch andere Aufgaben wie beispielsweise das Auslesen von Sensorwerten erledigt werden sollen, dann stößt der Arduino schnell an seine Grenzen. Auch die Ansteuerung von größeren Displays mit hundert oder mehr LEDs bereitet schnell Probleme. Zum einen aufgrund der erforderlichen Rechenleistung, zum anderen stellt auch die Anzahl der verfügbaren Pins eine Limitierung dar. Weitere Infos: Der Einsatz von kostengünstigen Displaytreibern kann hier Abhilfe schaffen. Ein geeigneter Typ ist z. B. ein IC des Typs MAX7219. Diese integrierte Schaltung von Maxim ist in der Lage, eine 8 x 8 = 64 Punkte G. Spanner: Arduino – Schaltungsprojekte große Matrix anzusteuern. Alternativ können auch bis zu 8 Ziffern einer für Profis, Elektor-Verlag 2012, 7-Segment-Anzeige angeschlossen werden. Die Treiber verfügen über Best.-Nr. CH-10 94 45, € 39,80 eine SPI-kompatible Schnittstelle, die am Arduino lediglich 3 digitale Ausgänge belegt. Ein umfangreiches Datenblatt zu den ICs ist auf der Mikrocontroller-Onlinekurs, Franzis-Verlag, Homepage des Herstellers Maxim al s PDF-Datei verfügbar. exklusiv für ELV, 2011, Eine geeignete Library zur Ansteuerung der Maxim-ICs findet sich Best.-Nr. CH-10 20 44, € 99,– unter: Grundlagen zur elektronischen Schaltungshttps://github.com/riyas-org/max7219/tree/master/MaxMatrix technik finden sich in der E-Book-Reihe „Elektronik!“ (www.amazon.de/dp/B00OXNCB02) Passende Beispiele, etwa für die Darstellung von Laufschriften oder Tickern, sind auf dieser Web-Page unter „Example“ zu finden. Lernpaket „AVR-Mikrocontroller in C Der Anschluss des Treiberbausteins ist ebenfalls sehr einfach. Ledigprogrammieren“, Franzis-Verlag 2012, lich 3 Pins sind mit dem Arduino zu verbinden: Best.-Nr. CH-10 68 46, € 129,– MAX7219_data Arduino D12 Lernpaket „Physical Computing“, MAX7219_load Arduino D10 Franzis-Verlag, 2015, MAX7219_clock Arduino D11 Best.-Nr. CH-12 21 81, € 99,– Die Zeilen- und Spaltenpins der Matrix werden entsprechend ihrer Polarität an die Segment- bzw. Digitanschlüsse geschaltet. Schließlich ist G. Spanner: AVR-XMEGA-Mikrocontroller, am Pin I_set noch ein einzelner Widerstand von ca. 10 k erforderlich, Elektor-Verlag 2015, über welchen die LED-Ströme eingestellt werden. Best.-Nr. CH-12 07 62, € 39,80 Damit können nahezu beliebig große Displays aufgebaut werden. Der Arduino wird kaum mehr belastet, da nur noch einzelne Kommandos über den SPI-Bus gesendet werden müssen. Zudem bleiben noch ausreichend Pins frei, um externe S ensoren oder Preisstellung April 2016 – aktuelle Preise im Web-Shop andere Peripherie zu betreiben. Der Realisierung von großflächigen Anzeigen, etwa für Werbezwecke Empfohlene Produkte Best.-Nr. Preis oder Sportveranstaltungen, steht nun nichts mehr im Wege (Bild 8). Arduino UNO CH-10 29 70 € 27,95 Mikrocontroller-Onlinekurs CH-10 20 44 € 99,– Ausblick Nachdem in den letzten Beiträgen verschiedene LED-Displays in 7-Segment- bzw. Dot-Matrix-Form erläutert und angewendet wurden, wird es Alle Arduino-Produkte wie Mikrocontroller-Platinen, im nächsten Beitrag um den Einsatz von weiteren Displaytechnologien Shields, Fachbücher und Zubehör finden Sie unter: www.arduino.elv.de gehen.
www.elvjournal.de
54 So funktioniert’s
Arduino verstehen und anwenden Teil 17: Alphanumerische LC-Displays
www.elvjournal.de
So funktioniert’s 55
Will man mit einem Mikrocontroller umfangreichere Informationen darstellen, sind LC-Displays das Mittel der Wahl. Im Gegensatz zu 7-Segment-Displays können LCD-Punktmatrix-Anzeigen neben Ziffern auch Buchstaben und andere Zeichen gut lesbar anzeigen. Derartige Displays sind weit verbreitet und finden sich an Kaffee- oder Fahrkartenautomaten, Getränkemaschinen, Geschäftstelefonen usw. Entsprechend groß ist die Vielfalt der am Markt ver fügbaren Typen. Ein Display mit zwei Zeilen und 16 Zeichen pro Zeile kann bereits 32 Zeichen darstellen. Meist werden für die Anzeige eines einzelnen Zeichens 5 x 8 = 40 Pixel verwendet. Damit verfügt bereits ein kleines, zweizeiliges Display über 32 x 40 = 1280 Bildpunkte. Hier wird sofort klar, dass diese nicht mehr alle einzeln über die Arduino-Pins angesteuert werden können. Deshalb werden im Arduino-Umfeld auch praktisch ausnahmslos LC-Displays mit integrierten Hardware-Treibern eingesetzt.
Der Displaytyp HD44780 als Quasi-Standard
Für kleinere Displays mit ein bis vier Zeilen und 16 Zeichen pro Zeile hat sich hierfür im Lauf der Zeit ein gewisser Quasi-Standard etabliert. Die meisten LC-Displays dieser Größe verwenden den Controllertyp HD44780. Dieser Typ wurde ursprünglich von der Firma Hitachi entwickelt, ist aber inzwischen von vielen anderen Herstellern übernommen worden. Dieser Displaytyp wird über 14 Pins angesteuert, bei vielen Modellen sind zwei weitere Pins für den Anschluss einer Hintergrundbeleuchtung vorgesehen. Die Standard-Pinbelegung zeigt Tabelle 1. LCD-Anzeigemodule mit Hitachi-HDD44780-kompatiblen Controllern existieren in zwei unterschiedlichen Varianten. Die eine verfügt über 16 Pins und über eine Hintergrundbeleuchtung. Die einfachere Version kommt ohne Beleuchtung aus und besitzt entsprechend nur 14 Pins. Die 14 Pins können von einem Arduino wieder problemlos angesteuert werden. Die Spannung VEE sollte idealerweise über ein 10-k-Potentiometer zwischen GND und 5 V geschaltet werden, dann lässt sich der Displaykontrast gut einstellen. Bei vielen Displaytypen genügt aber auch bereits ein Widerstand von etwa 1 k nach Ground für einen guten Kontrast.
Das Display kann auf zwei verschiedene Arten angesteuert werden, im 8-Bit- oder im 4-Bit-Mode: · Im 8-Bit-Mode werden alle acht Datenleitungen zur Ansteuerung verwendet, somit kann immer ein komplettes Byte übert ragen werden. · Im 4-Bit-Mode werden nur die oberen vier Datenleitungen (D4 bis D7) verwendet. Für die Übertragung eines Bytes sind somit zwei Zugriffe erforderlich. Dabei wird zunächst das höherwertige „Nibble“ (= 4 Bits), also Bit 4 bis Bit 7 übertragen, dann folgt das Niederwertige, also Bit 0 bis Bit 3. Die Datenleitungen D0 bis D3 des LCDs bleiben unbeschaltet. Der 4-Bit-Mode hat den Vorteil, dass vier IO-Pins weniger benötigt werden. Der Nachteil der etwas geringeren Schreibgeschwindigkeit spielt meist keine Rolle, sodass die 4-Bit-Ansteuerung sehr häufig zum Einsatz kommt. Für die Displaysteuerung sind neben den vier Datenleitungen (D4, D5, D6 und D7) noch die Anschlüsse RS, R/W und E erforderlich. · Über RS (Register Select) wird ausgewählt, ob man einen Befehl oder ein Datenbyte an das LCD schicken möchte. Ist RS low, dann wird das ankommende Byte als Befehl interpretiert, ist RS high, dann wird das Byte direkt auf dem LCD als Zeichen angezeigt. · R/W (Read/Write) legt fest, ob geschrieben oder gelesen werden soll. High Potential bedeutet lesen, bei Low können Daten auf die Displayeinheit geschrieben werden. Da man in den meisten Fällen nur Daten zum LCD sendet, kann man R/W fest auf GND legen und
1 e l l e b a T
Pin
Symbol
Level
Funktion
1
VSS
L
Stromversorgung OV (GND)
2
VDD
H
Stromversorgung + 5 V
3
VEE
analog
Kontrastspannung
4
RS
H/L
Umschaltung Befehl / Daten
5
R/W
H/L
H = Read, L = Write
6
E
H
Enable (fallende Flanke)
7
DO
H/L
Display Data, LSB
8
D1
H/L
Display Data
9
D2
H/L
Display Data
10
D3
H/L
Display Data
11
D4 (DO)
H/L
Display Data
12
D5 (D1)
H/L
Display Data
13
D6 (D2)
H/L
Display Data
14
D7 (D3)
H/L
Display Data, MSB
15
–
frei
(evtl. LED-Hintergrundbeleuchtung)
16
–
frei
(evtl. LED-Hintergrundbeleuchtung)
ELVjournal 4/2016
56 So funktioniert’s Bild 1: Anschluss eines zweizeiligen LCDs an den Arduino UNO
D N R G A
1 1 2
1 1 9 8 1 0
7 6
5 4
D IG I A L
M M W W P P
US B
2 1
M W P
ARDUINO
D
T E S 3 V D D N N . E 3 5 G G 9 R
n
A N A L O G I N 0 1
2
3 4
5
10 k
4
s e s d e V V V R
5
6
1 2
1 4
1 6
16 2
5 6 7 D D
:
so einen weiteren IO-Pin am Controller einsparen. Man sollte dann jedoch nach jedem Befehl eine kurze Wartepause einlegen, um dem LCD-Controller Zeit zum Ausführen des Befehls zu geben. · Der E-(Enable)-Anschluss signalisiert dem LCD, dass die Datenleitungen die korrekten Pegel angenommen haben und die Daten übernommen werden können. Bereits in Teil 5 „Nutzung und Erstellung von Programmbibliotheken“ im ELVjournal 04/2014 wurde gezeigt, wie ein Arduino Micro mit einer LCD-Einheit verbunden werden kann. Bild 1 zeigt eine häufig verwendete Möglichkeit zur Verbindung eines LCDs mit dem Arduino UNO.
Wie arbeitet die LCD-Anzeige? Im Rahmen des Beitrags zu den LED-7-Segment-Anzeigen und -Punktmatrizen wurde bereits diskutiert, wie einzelne Ziffern oder auch Buchstaben angezeigt werden können. Doch wenn es darum geht, das gesamte Alphabet oder auch Sonderzeichen wie z. B. *, #, % etc. auf diese Weise darzustellen, dann haben www.elvjournal.de
diese Anzeigetypen die Grenzen des Möglichen erreicht. Immer wenn es erforderlich ist, kleine Datenmengen in Form von kurzen Textmitteilungen oder Zahlenreihen auszugeben, kommen deshalb häufig LCD-Anzeigen zum Einsatz (Bild 2). LCDs weisen in ihrem Inneren Flüssigkristalle auf, die in Abhängigkeit von einer angelegten Spannung ihre Ausrichtung ändern. Dadurch wird auf das Display tref fendes Licht polarisiert. Unter Verwendung geeigneter, fest eingebauter Polarisationsfilter kann so erreicht werden, dass ein bestimmter Displaybereich hell oder dunkel erscheint. Auf diese Weise kann man ähnlich wie bei der LED Matrix-Displays nahezu beliebiger Größe aufbauen. Solche Anzeigeelemente nutzen meist aus einzelnen Punkten zusammengesetzte Matrizen. Damit lassen sich alle Arten von Zeichen (Ziffern, Buchstaben oder Sonderzeichen) darstellen. Darüber hinaus existieren auch Sonderformen, bei welchen die anzuzeigenden Muster bereits fest vorgegeben sind. Diese finden u. a. in Anzeigen für bestimmte Betriebszustände einer Maschine, in der Unterhaltungselektronik und in der Kfz-Technik Anwendung. Bei Punktmatrix-Displays können durch geeignete Ansteuerung der einzelnen Punkte alle alphanumerischen Zeichen, d. h. alle Buchstaben und Zahlen, gut lesbar dargestellt werden. Darüber hinaus können auch einfache Grafiksymbole angezeigt werden (siehe A bschnitt „Erzeugung von Sonderzeichen“).
So funktioniert’s 57 Echte großflächige Grafiken bleiben dagegen den sogenannten Grafikdisplays vorbehalten. Diese werden ausführlich im nächsten Beitrag zu dieser Artikelserie beschrieben.
Darstellung von Zeichen und Texten
Für die Ansteuerung des LC-Displays muss die Library LiquidCrystal eingebunden werden (siehe Teil 5 „Nutzung und Erstellung von Programmbibliotheken“). Für die Erzeugung eines LCD-Objekts müssen die folgenden Parameter übergeben werden: • Pin Register Select (RS) • Pin Enable (E) • Pins der Datenleitungen D4 bis D7 Dies erfolgt über die Programmzeile LiquidCrystal lcd(RS, E, D4, D5, D6, D7);
Die Klasse LiquidCrystal stellt dann eine Reihe von Methoden zur Verfügung, die die Ausgabe von Texten ermöglichen. Die Methode „begin“ teilt dem LCD-Objekt die Anzahl der Spalten und der Zeilen des angeschlossenen Displays mit. Über lcd.begin(COLS, ROWS);
wird die Anzahl der Zeichen pro Zeile (COLS) und die Zeilenzahl übergeben. Für ein 16-stelliges Display mit zwei Zeilen ist also
zu setzen. Die Methode „print“ teilt dem LCD-Objekt mit, welche Zeichen an das Display gesendet werden sollen. Sie ist vergleichbar mit der Printanweisung des Serial-Monitors. Werden keine Angaben zur Position des anzuzeigenden Textes gemacht, wird er am Anfang der ersten Zeile gestartet. Die Methode „setCursor“ positioniert den Cursor an die Stelle, an der die nachfolgende Textausgabe starten soll. Die Methode ist nullbasiert, d. h., die erste Zeile bzw. Spalte ist mit dem Index 0 versehen. Um in die zweite Zeile zu gelangen, ist daher der Wert 1 im Zeilenindex anzugeben:
Die LCD-Methode „clear“ besitzt keine Parameter, löscht alle Zeichen aus der Anzeige und positioniert den Cursor in der linken oberen Ecke an der Koordinate 0, 0. Es gibt HD44780-Varianten mit integriertem Vorwiderstand für die Hintergrundbeleuchtung. Hier können die Versorgungspins (Pins 15 und 16) direkt mit +5 V und GND verbunden werden. Im Allgemeinen ist allerdings ein Vorwiderstand erforderlich. Ein Blick in das entsprechende Datenblatt hilft in diesem Falle weiter. Liegt kein Datenblatt vor, so kann man testweise einen 1-k-Vorwiderstand einsetzen. Falls die Anzeige dann noch sehr dunkel erscheint, kann der Widerstandswert entsprechend angepasst werden. Natürlich muss man sich bei diesem Vorgehen bewusst sein, dass man das Display eventuell außerhalb seiner Spezifikationen betreibt und deshalb mit einer verkürzten Lebensdauer der Hintergrundbeleuchtung rechnen muss. Will man die Helligkeit der Displaybeleuchtung softwareseitig steuern, so kann man die Versorgungsspannung der Hintergrund-LEDs mit einem PWM-Pin verbinden (z. B. Pin 9). Über
Bild 2: LCD-Anzeige in Aktion
Liquid Crystal lcd(RS, E, D4, D5, D6, D7); void setup()
lcd.begin(COLS, ROWS);
} void loop(){}
Erzeugung von Sonderzeichen Eine weitere interessante Methode ist
Damit ist es möglich, eigene Zeichen zu erstellen und diese auf dem Display auszugeben. Das Pixelmuster eines beliebigen Zeichens ist hier einfach als binäres Feld zu definieren, ähnlich wie es bereits bei den LED-Punktmatrizen (siehe vorhergehenden Artikel) zur Anwendung kam: byte smiley[8] = { B00000, B00000,
B00000, B00000,
B00000 };
…
Über
kann man die Helligkeit der Hintergrundbeleuchtung softwaretechnisch steuern. Falls das verwendete Display eine sehr hohe Stromstärke benötigt (> 20 mA), ist ein entsprechender Treibertransistor vorzusehen. Das vollständige Programm zur Ansteuerung eines zweizeiligen LCDs sieht damit so aus:
wird dann der entsprechende Charakter erzeugt. Dieser kann dann wieder mit lcd.write();
auf dem Display dargestellt werden. Der folgende Sketch gibt so eine ganze Reihe von Sonderzeichen aus: ELVjournal 4/2016
58 So funktioniert’s Bild 4: Großer Font byte smiley[8] = { B00000, B00000,
Mithilfe selbst definierter Fonts ist sogar die Darstellung großer Ziffern und Zeichen möglich (Bild 4). Hierzu müssen lediglich die erforderlichen Sonderzeichen festgelegt werden. Daraus können dann die großen Schriftzeichen zusammengesetzt werden. Eine Library hierzu findet sich unter [2].
B00000, B00000,
B00000
Ausblick
};
}; byte cross[8] =
};
void setup()
} void loop()
Wie in diesem Artikel gezeigt wurde, eignen sich textbasierte LC-Displays nicht nur zur Anzeige von einfachen Ziffern und Zeichen, sondern sie erlauben darüber hinaus, wenn auch in beschränktem Umfang, die Darstellung einfacher Grafiken. Will man dagegen umfangreichere grafische Darstellungen anzeigen, kann man ein Display des Typs KS108 einsetzen. Ähnlich wie das HD44780 werden KS108-Typen von verschiedenen Herstellern angeboten und es existiert eine Vielzahl von kompatiblen Modellen. Dieser Displaytyp bietet eine Grafikauflösung von immerhin 128 x 64 Pixeln. Der nächste Artikel wird sich eingehend mit den Möglichkeiten der Grafikdarstellung auf diesem Displaytyp beschäftigen. Es w ird dann u. a. eine Quasi-Analoguhr entstehen, und auf einem PC erzeugte Bitmaps werden vom Arduino auf das Display gezaubert werden.
Weitere Infos:
[1] Die Geschichte des braven Iren: [2] Library für große Fonts: http://code.google.com/p/phi-big-font/ G. Spanner: Arduino – Schaltungsprojekte für Profis, Elektor-Verlag 2012, Best.-Nr. CI-10 94 45, € 39,80
{ lcd.setCursor(0, 0);
lcd.print("* "); lcd.write(love); lcd.print(" ");
}
Mikrocontroller-Onlinekurs, Franzis-Verlag, exklusiv für ELV, 2011, Best.-Nr. CI-10 20 44, € 99,– Grundlagen zur elektronischen Schaltungstechnik finden sich in der E-Book-Reihe „Elektronik!“ (www.amazon.de/dp/B00OXNCB02) Lernpaket „AVR-Mikrocontroller in C programmieren“, Franzis-Verlag 2012, Best.-Nr. CI-10 68 46, € 129,–
Aus Platzgründen wurden hier die Bitmaps für „Heart“ und „Cross“ in komprimierter Form dargestellt. Das Ergebnis auf dem Display sieht so aus wie in Bild 3 dargestellt. Es stellt die Geschichte eines braven Iren in Kurzform dar [1].
G. Spanner: Lernpaket „Physical Computing“, Franzis-Verlag 2015, Best.-Nr. CI-12 21 81, € 99,–
Preisstellung Mai 2016 – aktuelle Preise im Web-Shop
Empfohlene Produkte
Arduino UNO Mikrocontroller-Onlinekurs STN-LCD-Anzeigemodul, 2x 16 Zeichen Bild 3: LCD-Anzeige mit selbst definierten Sonderzeichen
www.elvjournal.de
Best.-Nr.
CI-10 29 70 CI-10 20 44 CI-05 41 84
Preis
27,95 € 99,– € 9,95 €
Alle Arduino-Produkte wie Mikrocontroller-Platinen, Shields, Fachbücher und Zubehör finden Sie unter: www.arduino.elv.de
56 So funktioniert’s
Arduino verstehen und anwenden Teil 18: Grafikdisplays
www.elvjournal.de
So funktioniert’s 57
Im letzten Artikel zu dieser Serie wurde die Ansteuerung von alphanumerischen Displays ausführlich behandelt. Diese Displays sind f ür die Ausgabe von Texten, einfachen Daten und Messwerten vollkommen ausreichend. Über Sonderzeichen ermöglichen sie sogar in sehr beschränktem Umfang grafische Darstellungen. Möchte man allerdings echte hochauflösende Grafiken erzeugen, so müssen entsprechend aufwendigere Displaytypen eingesetzt werden. Ähnlich wie bei den zeichenorientierten Anzeigen der TYP HD44780 hat bei den grafischen Displays die Controllerversion KS0108 eine Quasi-Standardfunktion übernommen. Dieser Displaytyp bietet eine Auflösung von 128 x 64 Pixeln. Dies mag Bild 1: Arduino-Testausgabe auf dem Grafikdisplay im Zeitalter der Megapixel-Kameras und HD-Monitore wenig erscheinen, für viele Mikrocontrolleranwendungen ist diese Auflösung aber vollkommen ausreichend. Displays vom Typ KS0108 oder einer kompatible Ver- KS0108-kompatible Anzeigen eine Library verfügbar. sion sind bereits für deutlich unter 20 Euro erhältlich und stellen damit Die Lib kann unter [1] kostenlos aus dem Internet eine kostengünstige Möglichkeit dar, einen Arduino zu einem grafikfä- geladen werden. higen System aufzurüsten. Die Bibliothek enthält mehrere Beispielprogramme. Um die korrekte Funktion des Displays zu testen Anschluss des Grafikdisplays an den Arduino kann der Beispielsketch Im Vergleich zum zeichenbasierten Display sind beim Grafikdisplay ks0108example.ino deutlich mehr Verbindungsleitungen erforderlich. Zudem gibt es beim geladen werden. Er zeigt nach einem BegrüßungsKS0108 mehrere Varianten, die in der Tabelle mit Typ 1 bis Typ 3 ge- bildschirm verschiedene Fonts und schließlich eine kennzeichnet sind. sich bewegende Grafik an. Wenn das Display diese Die Tabelle 1 zeigt, wie die Anzeigeeinheit mit dem Arduino Uno zu Ausgaben korrekt anzeigt, kann man davon ausgeverbinden ist. Für ein Display vom Typ 1 gilt dementsprechend z. B., hen, dass die Verbindung zwischen Displayeinheit dass der Digital-Pin Nr. 8 des Arduinos mit dem Pin Nr. 7 des Displays und Arduino einwandfrei ist (siehe Bild 1). verbunden werden muss usw. Die meisten KS0108-Varianten verfügen über ein Wenn man methodisch vorgeht, ist der Anschluss des Grafikdisplays eingebautes Backlight. Dieses kann über die Pins trotz der 16 erforderlichen Verbindungsleitungen rasch erledigt. LED_A und LED_K versorgt werden. Sie müssen über einen geeigneten Vorwiderstand Die GLCD-Library (z. B. 220 ) mit 5 V bzw. Ground des Arduinos verDie Ansteuerung eines Grafikdisplays ist natürlich mit erheblichem bunden werden. Die mit „Pot“ bezeichneten DisAufwand verbunden. Wie im Arduino-Umfeld üblich, ist aber auch für play-Pins sind über ein Potentiometer (z. B. 10 K) Digital-Pin Arduino-Pin
5V
Gnd
Pot
8
9
10
11
4
5
6
7
Display-Typ 1
2
1
3
7
8
9
10
11
12
13
14
Display-Typ 2
1
2
3
4
5
6
7
8
9
10
11
Display-Typ 3
13
14
12
1
2
3
4
5
6
7
8
Analog-Pin 1 e l l e b a T
Backlight-Versorgung
Arduino-Pin
0
1
2
3
4
LED_A
LED_K
Rst
Display-Typ 1
15
16
5
4
6
19
20
17
Display-Typ 2
12
13
15
16
17
19
20
14
Display-Typ 3
15
16
10
11
9
19
20
18
ELVjournal 5/2016
58 So funktioniert’s mit dem Arduino zu verbinden. Der Schleifer des Potentiometers ist dabei an den jeweiligen Display-Pin zu legen. Die anderen beiden Anschlüsse kommen an die Versorgungsspannung bzw. den Ground des Arduinos. Damit kann dann der Kontrast des Displays manuell eingestellt werden. Im Zweifelsfall sollte man hierzu auch das Datenblatt der Anzeigeeinheit zu Rate ziehen. Weitere Informationen zum Anschluss von Displays mit Kontrastreglern finden sich auch im let zten Arduino-Beitrag „Alphanumerische LC-Displays“ (ELVjournal 4/2016). Nachdem das Grafikdisplay erfolgreich getestet wurde, können weitere interessante und nützliche Anwendungen auf den Arduino geladen werden.
Die Analog-Uhr Obwohl die Digitaltechnik in alle Lebensbereiche eingezogen ist, erfreuen sich quasi-analoge Technologien immer noch großer Beliebtheit. Ein bekanntes Beispiel hierfür sind Analog-Uhren. Obgleich die eigentliche Zeittaktung vollkommen digital erfolgt, ist die Anzeige der aktuellen Uhrzeit mit Zeigern auf einem Ziffernblatt immer noch aktuell. Auch der Arduino kann auf dem Grafikdisplay eine Analog-Uhr anzeigen. Der Sketch dazu findet sich ebenfalls unter den Beispielen zur GLCD-Library. Zusätzlich ist hier noch die Time-Bibliothek erforderlich. Diese kann unter [2] als time.zip geladen werden. Nachdem die Bibliothek wie üblich installier t wurde, kann der Analoguhr-Sketch clockFace.ino geladen werden. Bild 2 zeigt die Darstellung der Uhr auf dem Display.
Ausgabe von Bitmap-Grafiken
Bild 2: Analog-Uhr
Auf dem Display können nicht nur Messwerte und Daten in grafischer Form ausgegeben werden, sondern auch beliebige Abbildungen in Form von Bitmaps. Um die Grafik anzeigen zu können, muss zunächst eine Bitmap (z. B. image.bmp) erzeugt werden. Hierfür können die bekannten Programme wie etwa Paint verwendet werden. Dabei ist darauf zu achten, dass die Datei bereits ein Format von 128 x 64 Pixel enthält (siehe Bild 3). Dann muss diese Datei in ein Include-File (*.h-Datei) umgewandelt werden. Hierfür steht ein Programm namens glcdMakeBitmap zur Verfügung. Das in der GLCD-Bibliothek unter /bitmaps/utils/glcdMakeBitmap enthaltene Programm glcdMakeBitmap.pde
ist nicht für die Arduino-IDE gedacht, sondern muss in „Processing“ gestartet werden. Dabei handelt es sich um ein leistungsfähiges Grafikprogramm unter Windows. Es kann unter [3] kostenlos aus dem Internet geladen werden. Processing wurde bereits in Teil 6 zu dieser Artikelserie (Sensortechnik und Messwerterfassung) kurz vorgestellt. Es weist starke Ähnlichkeiten mit der Arduino-IDE auf. Das ist kein Zufall, da die Arduino-Programmieroberfläche sehr eng an das ursprünglich am Massachusetts Institute for Technology (MIT) entwickelte Processing angelehnt ist. Nachdem das Programm glcdMakeBitmap in Processing geladen und gestartet wurde, erscheint ein Fenster, in welches die zu konvertierende Grafik per Drag & Drop geladen werden kann (siehe Bild 4). Auf diese Weise wird eine Datei „image.h“ erzeugt, welche die Daten der Bitmap in einer für den Arduino verständlichen Form enthält. Die Anweisungen #include "image.h" und GLCD.DrawBitmap(image, x, y); sorgen dann dafür, dass die Bitmap an der Position x, y auf dem Display erscheint. Die Datei image.h muss dazu natürlich mit in das Verzeichnis des aktuellen Sketches kopiert werden. Das vollständige Programm dazu sieht so aus: Bild 3: Erzeugung einer Bitmap
// Arduino graphics display #include #include "image.h" void setup() { GLCD.Init(NON_INVERTED); GLCD.ClearScreen(); GLCD.DrawBitmap(image, 0,0, BLACK); } void loop() {}
Bild 4: Das Konvertierungsfenster des Processing-Programms
www.elvjournal.de
Bild 5 zeigt das Ergebnis auf dem Display.
So funktioniert’s 59
Der Thermograf Moderne Heizungsanlagen verfügen über die vielfältigsten Steuer- und Regeleinrichtungen. Neben Zeitsteuerung und Vorlauftemperatur werden auch Parameter wie Innen- und Außentemperatur berücksichtigt. Hier kann es schnell einmal vorkommen, dass ein kleiner Fehler in den Einstellungsparametern der Heizanlage zu unerwünschten Raumtemperaturprofilen führt. Dies ist natürlich neben dem mangelnden Komfort auch mit erhöhten Heizkosten verbunden. Hier ist es deshalb sinnvoll, die Raumtemperatur unabhängig von der Heizanlage selbst zu überwachen. Dabei ist nicht nur die aktuelle Temperatur wichtig, sondern insbesondere auch der Temperaturverlauf über einen längeren Zeitraum wie etwa 24 oder 48 Stunden. Hier kommt das Grafikdisplay ins Spiel. Es erlaubt, eine Temperaturkurve (Bild 6) automatisch über einen l ängeren Zeitraum hinweg darzustellen. Unerwünschte Temperaturverläufe, wie etwa eine überflüssige nächtliche Heizperiode, können so schnell erkannt werden. Die Programmierung einer solchen Anwendung kann mit den Kenntnissen aus diesem Beitrag in kurzer Zeit durchgeführt werden.
Mini-Monitoren wurden die vielfältigen Möglichkeiten dieses wichtigen und interessanten Gebiets vorgestellt. Im nächsten Beitrag wird es um das Thema Messtechnik gehen. Neben einfachen Messaufgaben wie die Erfassung von Strömen, Spannungen und Widerständen werden auch komplexere Geräte wie ein einfaches Oszilloskop und sogar ein Logic-Analyzer auf Arduino-Basis vorgestellt.
Komplettgerät mit Grafikdisplay Abschließend zeigt Bild 7 den kompletten Aufbau eines Geräts mit Grafikdisplay. Links unten ist das Potentiometer für die Einstellung des Kontrastes zu sehen. Ein solches Gerät macht durchaus einen bereits recht professionellen Eindruck und kann et wa als Thermograph auch in einem Wohnzimmer eingesetzt werden.
Ausblick Mit diesem Artikel wird das umfassende Thema Displaytechnik abgeschlossen. Beginnend mit Sieben-Segmentanzeigen über LED-Matrizen und Alphanumerische LCD-Einheiten bis hin zu voll grafikfähigen
Weitere Infos:
[1] http://code.google.com/p/glcd-arduino/downloads/list [2] http://playground.arduino.cc/Code/Time [3] http://processing.org/ Bild 5: Ausgabe einer Bitmap auf dem Grafikdisplay
G. Spanner: Lernpaket „Physical Computing”, Franzis-Verlag, 2015, Best.-Nr. CJ-12 21 81, € 99,– G. Spanner: Arduino – Schaltungsprojekte für Profis, Elektor-Verlag, 2012, Best.-Nr. CJ-10 94 45, € 39,80 Mikrocontroller-Onlinekurs, Franzis-Verlag, exklusiv für ELV, 2011, Best.-Nr. CJ-10 20 44, € 99,– G. Spanner: Elektor Praxiskurs AVR-XMEGA-Mikrocontroller, 2015, Best.-Nr. CJ-12 07 62, € 39,80 Grundlagen zur elektronischen Schaltungstechnik finden sich in der E-Book-Reihe „Elektronik!“ (www.amazon.de/dp/B00OXNCB02)
Bild 6: Der Thermograf in Aktion
Lernpaket „AVR-Mikrocontroller in C programmieren“, Franzis-Verlag 2012, Best.-Nr. CJ-10 68 46, € 129,– Preisstellung August 2016 – aktuelle Preise im Web-Shop
Empfohlene Produkte Arduino Uno Mikrocontroller-Onlinekurs
Best.-Nr. CJ-10 29 70 CJ-10 20 44
Preis € 27,95 € 99,–
Alle Arduino-Produkte wie Mikrocontroller-Platinen, Shields, Fachbücher und Zubehör finden Sie unter: www.arduino.elv.de
Bild 7: Komplettgerät mit grafischem Display
ELVjournal 5/2016
16 So funktioniert’s
Arduino verstehen und anwenden Teil 19: Messtechnik – von der Spannungsmessung zum Logic-Analyzer
www.elvjournal.de
So funktioniert’s 17
Bereits in Teil 6 dieser Artikelserie („Sensortechnik und Messwerterfassung“ im ELVjournal Okt/Nov 2014) wurden einige Grundlagen der Erfassung von messtechnischen Größen diskutiert. In diesem Beitrag sollen nun auch komplexere Messaufgaben betrachtet werden. Zunächst stehen einfache Strom-, Spannungs- und Widerstandsmessungen im Vordergrund. Im Anschluss sollen · ein Kapazitätsmessgerät und · ein Halbleitertester sowie Geräte mit zeitaufgelöster Messwerterfassung wie etwa · ein Oszilloskop oder auch · ein Logic-Analyzer diskutiert werden.
Messung von Spannungen, Strömen und Widerständen mit dem Arduino
Die prinzipiell einfachste Messung ist hier die Spannungsmessung. Mit dem Analog-digital-Wandler eines Arduinos können Spannungen zwischen 0 und +5 V direkt gemessen werden. Der Arduino verfügt hierfür über eine interne Spannungsreferenz. Für diese können mehrere Optionen gewählt werden: · DEFAULT: voreingestellte Analog-Referenz von 5 V (auf 5 V ArduinoBoards) oder 3,3 V (auf 3,3 V Arduinos) · INTERNAL: interne Referenz: – 1,1 V für ATmega168 oder ATmega328 (z. B. Arduino Uno) – 2,56 V für den ATmega8 (ältere Arduino-Varianten) – INTERNAL1V1: 1,1 V Referenz (nur Arduino Mega) · INTERNAL2V56: eingebaute 2,56-V-Referenz (nur Arduino Mega) · EXTERNAL: für den Anschluss einer externen Referenzspannung am AREF-Pin (0–5 V) Hinweis:
Bild 1: Eingangsschaltung für das Arduino-Voltmeter
Möchte man Spannungen bis zu beispielsweise 20 V messen, ist ein Spannungsteiler erforderlich. Bild 1 zeigt einen entsprechenden Aufbau. Aufgrund ihrer höheren Präzision sollten hier Metallschicht-Widerstände (± 1 % Toleranz) eingesetzt werden. Zusätzlich wurde noch ein 100-nF-Kondensator eingefügt, um stabile Messwerte zu erhalten. Eine 5V1-Zenerdiode schützt den Arduino-Eingang vor unerwünschten Überspannungen.
An den AREF-Eingang dürfen nur Spannungen zwischen 0 und 5 V angelegt werden! Mehr als 5 V oder negative Spannungen können den Arduino zerstören.
Der folgende Aufbau erlaubt mit R1 = 1 M R2 = 50 k Soll eine externe Referenz zum Einsatz kommen, muss diese im Sketch die präzise Messung von Spannungen zwischen 0 und ausgewählt werden, bevor analogRead() aufgerufen wird, sonst werden 20 V. Der Wert von 50 k entsteht durch Parallelinterne und externe Referenz kurzgeschlossen, was zu einer Zerstörung schaltung von zwei 100-k -Widerständen. des Arduino-internen Controllers führen kann. Für präzise Ergebnisse müssen die WiderstandsAlternativ kann man AREF über einen Schutzwiderstand anschließen, werte genau vermessen und die Ergebnisse in den dann ist allerdings zu beachten, dass die exter ne Referenz mit ca. 32 k Sketch eingesetzt werden. Gleiches gilt für die interbelastet wird. ne Referenzspannung. Benutzt man die interne Referenz, muss man berücksichtigen, dass Eine Mittelung über 10 Werte führt zu einer weitediese bei einem Nominalwert von 1,1 V ± 10 % zwischen 1,0 und 1,2 V ren Verbesserung der Präzision, da sich statistische liegt. Für präzise Messungen ist es daher erforderlich, den genauen Wert Messfehler der Einzelmessungen herausmitteln. Der mit einem Referenzvoltmeter zu bestimmen. vollständige Sketch sieht damit wie folgt aus: ELVjournal 6/2016
18 So funktioniert’s
// digital voltmeter const int a nalogInPin = A0;
} \t voltage = ”
”
}
Mittels eines geeigneten Shunts können so auch Stromstärken bestimmt werden. Widerstandsmessungen sind ebenfalls möglich. Hierzu muss lediglich einer der Widerstände im Spannungsteiler als Referenz, der andere als Messobjekt definiert werden. Die Eingangsspannung muss in diesem Fall natürlich ebenfalls bekannt sein. Man kann hier auch auf die 3,3 V des Arduinos zurückgreifen.
Bestimmung von Kapazitäten und Halbleiterparametern Bedingt durch ihren inneren Aufbau weisen Elektrolytkondensatoren eine vergleichsweise hohe Ausfallwahrscheinlichkeit auf und zählen deshalb zu den problematischsten Bauelementen der Elektronik. Meist liegt die Hauptursache für den Ausfall im Austrocknen des Elektrolyts und dem damit verbundenen erheblichen Kapazitätsverlust. Viele Ausfälle
von Netzteilen, PCs oder Audioverstärkern sind auf dieses Problem zurückzuführen. Mit dem Arduino kann die Kapazität eines Elkos ohne zusätzliche Hardware mit guter Genauigkeit bestimmt werden (siehe Bild 2). Achtung: Kondensatoren sind vor dem Anschluss an den Arduino unbedingt zu entladen, da die Digitaleingänge sonst zerstör t werden könnten!
Das Messprinzip ist simpel: Zunächst wird der Pluspol des Elkos auf LOW-Potenzial gelegt. Danach wird dieser Pin als Eingang geschaltet, d. h. der Pin wird hochohmig. Wenn nun dieser Input-Pin den Befehl digitalWrite(activePin,HIGH); erhält, wird dadurch der interne Pull-up-Widerstand des Arduinos aktiviert und der Kondensator lädt sich über diesen Widerstand auf. Dabei wird gemessen, wie lange es dauert, bis sich der Kondensator auf etwa die halbe Versorgungsspannung aufgeladen hat. Dies e Zeit ist ein direktes Maß für die Kapazität des Kondensators: T = R * Cx R ist hier der interne Pull-up. Dieser hat einen Wert von ca. 60 k . Durch die Kalibrationskonstante „cal“ wird die Ladezeit direkt in einen Kapazitätswert in nF umgerechnet. Ist der berechnete Wert größer als 1000, erfolgt die Anzeige automatisch in µF. So lassen sich nicht nur Elkos im µF-Bereich vermessen, sondern auch kleinere ungepolte Kondensatoren bis zu einem Minimalwert von ca. 10 nF. Bei noch kleineren Kapazitäten werden die Messzeiten zu kurz und das Ergebnis ungenau. Im Programm wird zunächst die Kalibrationskonstante „cal“ definiert. Durch Vermessung genau bekannter Kapazitäten kann diese Konstante nachjustiert werden. In der Main-Loop wird die bereits oben beschriebene Messprozedur ausgeführt. Schließlich wird der ermittelte Messwert unter Verwendung einer Autorange-Funktion auf die serielle Schnittstelle ausgegeben.
} else
} }
Bild 2: Arduino als Kapazitätsmessgerät
www.elvjournal.de
So funktioniert’s 19 Aber nicht nur passive Bauelemente können mit einfachen Mitteln ausgemessen werden. Auch aktive Komponenten wie Transistoren können mit dem Arduino geprüft werden. Die Schaltung nach Bild 3 misst die wichtigsten Transistorparameter. Die Basisspannung Ube liefert eine Aussage über das Transistorgrundmaterial: Ube 0,3 V: Germaniumtransistor Ube 0,7 V: Siliziumtransistor Aus der Kollektorspannung Uce lässt sich der Kollektorstrom Ic berechnen, entsprechend aus Ube der Basisstrom Ib. Damit ergibt sich nach B = Ic / Ib die Gleichstromverstärkung B des Transistors. Typische Werte für Kleinsignaltransistoren liegen im Bereich von 100 bis ca. 800.
} Bild 3: Transistortester
}
Das Programm ermittelt die Werte für Uce und Ube. Daraus werden die Parameter für Kollektor- und Basisstrom berechnet. Abschließend werden die Ergebnisse auf die serielle Schnitt stelle ausgegeben. Die Anwendung ist sehr praktisch, wenn man eine größere Anzahl von Transistoren prüfen will. Man erhält hier sehr schnell nicht nur die Information, ob ein spezieller Transistor funktionsfähig ist, sondern auch den genauen Wert der Stromverstärkung. Es ist also mit diesem Sketch leicht möglich, Transistoren gleichen Typs nach ihrer Stromverstärkung zu sortieren. So kann man etwa für Stromspiegel oder ähnliche Applikationen leicht sogenannte „matched pairs“ selektieren, d. h. Transistorpärchen mit möglichst identischen Stromverstärkungen.
Oszilloskop und Logic-Analyzer
Nach dem Multimeter ist das Oszilloskop das wichtigste Messgerät im Elektronik-Labor. Wenn man häufig mit der Analyse digitaler Schaltungen oder von Mikrocontroller-Projekten befasst ist, dann weiß man auch einen Logic-Analyzer zu schätzen. Damit lassen sich problemlos z. B. Codes von IR-Sendern, Signale auf seriellen Schnittstellen, I2C-Bussen oder die Übertragungsprotokolle von Funksignalen überprüfen. Sowohl ein Oszilloskop als auch ein Logic-Analyzer lassen sich mit einem Arduino aufbauen. Natürlich können diese Arduino-basierten Geräte nicht mit kommerziellen Gegenspielern mit Anschaffungskosten von € 10.000,– und mehr mithalten. Dennoch ist es erstaunlich, was man auch mit sehr einfachen Mitteln erreichen kann. Für den Hobbybereich, aber auch für einfachere professionelle Einsätze sind die erreichbaren Leistungsmerkmale dieser Arduino-basierten Messgeräte häufig durchaus ausreichend.
Für den Arduino Uno existieren verschiedene Oszilloskop-Emulatoren wie etwa Girino oder ArduinoScope. Eine sehr gute und leistungsfähige Anwendung ist XOscillo. Dieses Programmpaket kann unter http://code.google.com/p/xoscillo/ kostenlos aus dem Internet geladen werden. Damit werden die folgenden Leistungsmerkmale erreicht: · Es ist keine zusätzliche Hardware erforderlich · Maximale Abtastfrequenz: 7 kHz · Bis zu 4 Kanäle (bei entsprechend niedrigerer Sample-Rate) · 8 bit vertikale Auflösung · Variable Trigger-Spannung auf Kanal 0 · Theoretisch unbeschränkte Anzahl von Messpunkten Sicher liegt die maximale Abtastfrequenz von 7 kHz im Vergleich zu einem kommerziellen Speicheroszilloskop sehr niedrig. Für einfache Messungen im Niederfrequenz- und Audiobereich ist die XOscillo-Applikation aber durchaus nützlich. Das XOscillo-Programmpaket besteht aus einem Arduino-Sketch und einer grafischen Benutzeroberfläche für den PC. Nach dem Laden des Sketches auf den Arduino kann die Windows-Applikation (XOscillo. exe) gestartet werden. Danach wird im File-Menü die Option „New Analog Arduino“ ausgewählt. ELVjournal 6/2016
20 So funktioniert’s
Bild 4: Das Arduino-basierte Oszilloskop zeigt ein Rechtecksignal
Es erscheint die in Bild 4 dargestellte Oberfläche eines Digitalen Speicheroszilloskops (DSO). Mit CH0 (rot) und CH1 (blau) können bis zu zwei analoge Kanäle ausgewählt werden. Die Zeitbasis kann zwischen 1 s/div und 500 µs/div eingestellt werden. Die Aufzeichnungszeit ist frei in Millisekunden wählbar. XOscillo verfügt zwar auch über die Möglichkeit zur Aufzeichnung mehrerer Digitalkanäle, jedoch steht für die Logic-Analyse eine noch etwas professionellere Anwendung zur Verfügung. Diese kann unter https://github.com/gillham/logic_analyzer geladen werden. Das Programmpaket enthält wieder Arduino-Sketche und Windows-Programme.
Bild 5: Arduino als 5-Kanal-Logic-Analyzer
www.elvjournal.de
Zusätzlich wird das Programm „Logic Sniffer“ benötigt. D ieses ist Java-basiert und kann also sowohl unter Windows als auch unter Linux verwendet werden. Für die Verwendung unter Windows muss natürlich Java installiert sein. Unter https://www.lxtreme.nl/ols/#download kann die jeweils neueste Version heruntergeladen werden. Jetzt muss nur noch die Datei ols.profile-agla.cfg aus dem Download-Paket in den Ordner „plugins“ kopiert werden. Dann sollte nach dem Start des Programms die Benutzeroberfläche des Logic-Analyzers erscheinen. Der Analyzer basiert auf dem SUMP-Software-Modul, welches verschiedene Hardware-Frontends, unter anderem eben auch den Arduino, unterstützt. Bild 5 zeigt die Oberfläche des Analyzers.
So funktioniert’s 21 Bild 6: Triggermenü Logic-Analyzer
Mit dem Arduino können bis zu 6 Kanäle parallel dargestellt werden. Die Pins D7 bis D13 sind als Eingänge voreingestellt. Natürlich können durch entsprechende Änderungen im Sketch auch andere Pins verwendet werden. Kanal 0 zeigt hier ein Clock-Signal das jeweils mit einem Flip-Flop in der Frequenz herunter geteilt wird. Die Signale der Kanäle 1 bis 4 weisen daher jeweils die halbe Frequenz auf. In Kanal 5 wird schließlich das invertierte Clock-Signal dargestellt. Bild 6 zeigt als Beispiel für den umfangreichen Funktionsumfang des SUMP-kompatiblen Analyzers das Triggermenü. Hier lassen sich nicht nur Pre-Triggeroptionen einstellen, sondern auch bestimmte Bitmasken wählen, bei welchen dann die Triggerung ausgelöst werden soll. Ähnlich umfangreich sind auch die Optionen und Möglichkeiten in den anderen Untermenüs. Der Logic-Analyzer lässt sich so sehr vielseitig auch für professionelle Messaufgaben einsetzten. Ausblick
Die Beispiele in diesem Beitrag zeigen, wie vielseitig Mikrocontroller und damit auch Arduino-Boards einsetzbar sind. Von der einfachen Spannungsmessung bis hin zu Logic-Analyzern mit nahezu professionellen Leistungsmerkmalen können viele Messaufgaben abgedeckt werden. Nachdem in diesem Beitrag nützliche Anwendungen und Geräte für das Elektronik-Labor im Vordergrund standen, werden sich die nächsten beiden Themen wieder eher um allgemein einsetzbare Technikanwendungen drehen.
Dort soll es nämlich um die Audiotechnik, die Ton- und Klangerzeugung sowie um die digitale Synthesizertechnik gehen. Darüber hinaus wird im Rahmen dieser Beiträge das Abspielen von Audiodateien auch in einem frei programmierbaren, im Eigenbau erstellten MP3-Spieler thematisiert.
Weitere Infos:
[1] Mikrocontroller-Onlinekurs, Franzis-Verlag, exklusiv für ELV, 2011, Best.-Nr. CK-10 20 44 [2] G. Spanner: Arduino – Schaltungsprojekte für Profis, Elektor-Verlag, 2012, Best.-Nr. CK-10 94 45 [3] Grundlagen zur elektronischen Schaltungstechnik finden sich in der E-Book-Reihe „Elektronik!“ (http://www.amazon.de/dp/B00OXNCB02) [4] Lernpaket „AVR-Microcontroller in C programmieren“, Franzis-Verlag, 2012, Best.-Nr. CK-10 68 46 [5] Lernpaket „Physical Computing”, Franzis-Verlag, 2015, Best.-Nr. CK-12 21 81 Preisstellung Oktober 2016 – aktuelle Preise im Web-Shop
Empfohlene Produkte
Arduino Uno Mikrocontroller-Onlinekurs
Best.-Nr.
CK-10 29 70 CK-10 20 44
Preis
27,95 € 99,– €
Alle Arduino-Produkte wie Mikrocontroller-Platinen, Shields, Fachbücher und Zubehör finden Sie unter: www.arduino.elv.de
ELVjournal 6/2016
36 So funktioniert’s
Arduino verstehen und anwenden Teil 20: Digitale Soundeffekte und Synthesizer
www.elvjournal.de
So funktioniert’s 37
Dass der Arduino in der Lage ist, auch Töne und Signale wiederzugeben, wurde bereits in Teil 13 „Peripheriegeräte“ dieser Artikelserie erl äutert. Dort wurden über die Tone-Funktion einfache Signale und Töne erzeugt und über einen Piezo-Lautsprecher ausgegeben. Der Arduino ist allerdings in der Lage, auch komplexe Tonfolgen und Klänge zu synthetisieren. Erfolgt die Tonausgabe über ein hochwertiges Audiosystem, können äußerst eindrucksvolle „Klangwolken“ erzeugt werden, die einem professionellen Synthesizer durchaus das Wasser reichen können. Darüber hinaus ist die Rechenleistung eines Arduinos sogar ausreichend, um synthetische Sprache zu erzeugen. Dazu ist nicht einmal zusätzliche Hardware, etwa in Form eines speziellen Shields, erforderlich. Auch der Arduino allein ist in der Lage, nicht nur verständliche Sprache zu erzeugen, sondern sogar ein Lied zu „singen“. Den Abschluss dieses Art ikels bildet ein kurzer A briss zum Thema Text-to-Speech, also die automatische Umsetzung von geschriebenem Text in verständliche Sprache. In diesem Beitrag werden so die folgenden Themen und Praxisbeispiele erläutert: · Einfache Töne und Klänge · Digitale Soundeffekte · Synthesizertechnik · Der singende Arduino · Text-to-Speech
Bild 1: Einfacher Audioverstärker
Audio-Wiedergabe Eine der einfachsten Möglichkeiten, elektrische Signale hörbar zu machen, besteht in der Verwendung eines sogenannten piezoelektrischen Schallwandlers. Dieser kann direkt an einen Arduino-Pin angeschlossen werden. Weitere Details dazu finden sich in Teil 13 zu dieser Reihe. Allerdings kann ein solcher Schallwandler nur eine sehr geringe Lautstärke liefern und auch die Tonqualität lässt sehr zu wünschen übrig. Deutlich bessere Ergebnisse lassen sich mit einem sogenannten dynamischen Lautsprecher erzielen. Dieser hat jedoch einen erheblich höheren Leistungsbedarf, sodass hier ein Audioverstärker erforderlich ist. Dieser kann jedoch mit geringem Aufwand im Eigenbau erstellt werden. Der integrierte Verstärker-Baustein LM 386 ist für wenige Eurocent erhältlich und leistet hervorragende D ienste. Bild 1 zeigt, wie ein solcher einfacher Verstärker aufgebaut und an den Arduino angeschlossen werden kann. Als Lautsprecher ist praktisch jeder dynamische Schallwandler mit 8 Impedanz und einer Leistung von mindestens 300 mW geeignet. Bild 2 zeigt ein Gesamts ystem. Der Lautsprecher wurde hier in ein einfaches Gehäuse eingebaut. Dieses Gehäuse dient nicht nur dem Schutz der Lautsprechermembran, sondern es führt auch zu einer wesentlichen Klangverbesserung, da es „akustische Kurzschlüsse“ zwischen der Vorder- und Rückseite der L autsprechermembran verhindert.
Bild 2: Audiosystem für den Arduino
ELVjournal 1/2017
38 So funktioniert’s Alternativ können auch Aktivboxen eingesetzt werden. Hier ist allerdings zu beachten, dass diese Systeme nicht mit zu großen Eingangsspannungspegeln belastet werden dürfen. Ein Spannungspegel mit einer Amplitude von maximal 0,5 V sollte bei den meisten Aktivboxen nicht überschritten werden. Im Zweifelsfall muss im Datenblatt des Systems nachgeschlagen werden. Will man also einen Arduino anschließen, so muss man einen geeigneten Spannungsteiler von etwa 1:10 vorschalten. Zusätzlich empfiehlt es sich, einen Tiefpass zu integrieren, um aus dem PWM-Signal einen nahezu analogen Spannungsverlauf zu erzeugen. Bild 3 zeigt einen entsprechenden Schaltungsvorschlag.
Bild 3: Anschluss an Aktivboxen
// Bell
Einfache Töne und Klänge
Wie einfache Signaltöne mit dem Befehl tone() erzeugt werden können, wurde bereits in früheren Beiträgen erläutert. Über die PWM-Ausgänge können jedoch auch komplexere Signalmuster ausgegeben werden. So kann man beispielsweise über eine Sinustabelle auch weich und harmonisch klingende Töne erzeugen. Wenn diese Töne noch mit einer sogenannten Hüllkurve versehen werden, ist es möglich, eine Vielzahl von Klängen zu erzeugen. Bild 4 zeigt den Signalverlauf, wie er für einen glockenähnlichen Klang typisch ist. Entsprechende Klangmuster sind heute allgegenwärtig. Neben den Klingeltönen bei Mobiltelefonen weisen sie auch auf sich schließende Türen an Liftanlagen oder Schienenfahrzeugen hin oder warnen den Autofahrer bei nicht angelegten Sicherheitsgurten. Der folgende Sketch liefert ein Beispiel für die Erzeugung eines Zweiklangs. Für die Wiedergabe sind entweder der Verstärker nach Bild 1 oder Aktivboxen wie in Bild 3 an Pin D3 anzuschließen
int audioPin = 3; void analogOut(byte val) { OCR1A = (val);} byte value[] = {
128,131,134,137,141,144,147,150,153,156,159,162,165,168,171,174,
177,180,183,186,189,191,194,197,199,202,205,207,209,212,214,217,
219,221,223,225,227,229,231,233,235,236,238,240,241,243,244,245,
246,247,248,249,250,251,252,253,253,254,254,255,255,255,255,255,
255,255,255,255,255,254,254,254,253,253,252,251,250,249,248,247,
246,245,243,242,240,239,237,236,234,232,230,228,226,224,222,220,
218,215,213,211,208,206,203,201,198,195,193,190,187,184,181,179,
176,173,170,167,164,161,158,155,152,148,145,142,139,136,133,130,
126,123,120,117,114,111,108,104,101,98,95,92,89,86,83,80,
77,75,72,69,66,63,61,58,55,53,50,48,45,43,41,38,
36,34,32,30,28,26,24,22,20,19,17,16,14,13,11,10,
9,8,7,6,5,4,3,3,2,2,1,1,0,0,0,0,
0,0,0,1,1,1,2,2,3,4,4,5,6,7,8,10,
11,12,13,15,16,18,20,21,23,25,27,29,31,33,35,37,
39,42,44,47,49,51,54,57,59,62,65,67,70,73,76,79,
82,85,88,91,94,97,101,103,106,109,112,115,119,122,125,
}; void setup() {
pinMode(audioPin, OUTPUT); TCCR1A = 0b10000001; TCCR1B = 0b00001001;
} void loop() {
for (int ampl = 10; ampl >=0 ; ampl--) { for (unsigned int d = 0; d < 40; d++) {
for (unsigned int j = 0; j < 256; j++) {
analogOut(value[j]/10*ampl); delayMicroseconds(5);
} } } delay(100); for (int ampl = 10; ampl >=0 ; ampl--) { for (unsigned int d = 0; d < 20; d++) {
for (unsigned int j = 0; j < 256; j++) {
analogOut(value[j]/10*ampl); delayMicroseconds(10);
} } } delay(300); }
Bild 4: Glockenähnlicher Klang
www.elvjournal.de
So funktioniert’s 39
Digitale Soundeffekte Die Weiterentwicklung dieser Technik führt zu den sogenannten digitalen Soundeffekten. Diese ermöglichen die Erzeugung hochkomplexer Klangstrukturen. Hierzu werden verschiedene Komponenten wie etwa · Oszillatoren · Hüllkurvengeneratoren · Taktgeneratoren auf rein digitalem Wege implementiert. Auf diese Weise ist es möglich, das gesamte Spektrum eines klassischen Analogsynthesizers in einen einzigen Mikrocontroller zu implementieren. Darüber hinaus können Effekte wie Nachhall oder Echo digital wesentlich einfacher umgesetzt werden, als dies allein mit analogen Komponenten wie Transistoren oder Operationsverstärkern möglich wäre.
Synthesizertechnik
Um sich mit den Möglichkeiten der Synthesizertechnik vertraut zu machen, kann man ein recht eindrucksvolles Programm auf den Arduino laden. Dieses ist unter http://code.google.com/p/tinkerit/downloads/ detail?name=auduino_v5.pde
kostenlos downloadbar. Wie Bild 5 zeigt, müssen nur noch fünf Potentiometer an den Arduino angeschlossen werden, und der Erzeugung von eigenen Klangwolken steht nichts mehr im Weg. Bekanntermaßen sind die Arduino-Entwicklungsumgebungen (IDEs) häufig nicht abwärtskompatibel. Das heißt, ältere Sketche können nicht auf den aktuellen IDEs kompiliert werden. Prinzipiell sollte es zwar immer möglich sein, alte Sketche auf die neuesten IDEs zu portieren, jedoch ist dies häufig mit erheblichem Aufwand verbunden, der oft nicht gerechtfertigt ist, wenn man einen alten Sketch einfach nur testen will. In diesem Fall ist es wesentlich einfacher, die ältere IDE aus dem Internet zu laden und mit dieser zu arbeiten. Die Sketche in diesem Beitrag arbeiten beispielsweise alle problemlos mit der IDE-Version 1.0. Falls man den ein oder anderen Sketch nach eingehenden Tests doch weiterverwenden möchte, kann man ihn dann immer noch auf die jeweils aktuelle IDE-Version portieren. Wenn man für die Potentiometer Schieberegler einsetzt, lässt sich der Synthesizer besonders gut bedienen bzw. „spielen“, da die Linearregler mit nur einem Finger verstellt werden können. Dadurch lassen sich alle Regler elegant simultan variieren, und es entsteht ein flüssiges Spiel. Einen entsprechenden Aufbauvorschlag zeigt Bild 6. Die Tonausgabe erfolgt wieder über den PWM-fähigen Digital-Pin D3. Die Klänge dieser Synthesizervariante werden durch ein breitbandiges Rauschspektrum erzeugt. Dieses Rauschen wird in schneller Abfolge moduliert. Bei analogen Synthesizern können ähnliche Klänge mit resonanten Bandpassfiltern erzeugt werden. Das Rauschen selbst wird aus zwei kontinuierlichen Signalen abgeleitet, welche zusätzlich mit unterschiedlichen Abklingraten und Hüllkurven versehen sind. Über die fünf Potentiometer können die folgenden Klangparameter variiert werden: P1: Rauschspektrum 1 P2: Abklingrate 1 P3: Rauschspektrum 2 P4: Abklingrate 2 P5: Wiederholfrequenz des Rauschspektrums
Bild 5: Schaltbild zum Synthesizer
Hinweis:
Der singende Arduino
Eine erstaunliche und zugleich sehr interessante Anwendung moderner Klangerzeugungstechnik ist die Sprachsynthese. Dabei ist der Arduino nicht nur in der Lage zu sprechen, sondern sogar zu singen. Ein entsprechendes Programmbeispiel ist unter https://code.google.com/p/tinkerit/wiki/Cantarino
zu finden. Wird dieses Programm auf den Arduino geladen und das Wiedergabesystem nach Bild 1 an Pin D3 angeschlossen, gibt der Arduino das Lied „Daisy Bell“ wieder. Wer den Text nicht ganz versteht, kann den Wortlaut dazu z. B. unter [1] nachlesen. Dieses Lied war eines der ersten, das durch automatische Sprachsynthese auf einem IBM-7094-Computer im Jahre 1961 wiedergegeben wurde [2]. Später fand es auch eine entsprechende Würdigung im Kinoklassiker „2001: A Space Odyssey“ [3]. Wohlgemerkt – hier handelt es sich nicht um die Wiedergabe einer menschlichen Stimmenaufzeichnung, sondern um eine vollständige Klangsynthese auf Basis rein digital erzeugter Lautsequenzen!
Text-to-Speech
Noch einen Schritt weiter gehen sogenannte Textto-Speech-Anwendungen. Hier müssen gesprochene Worte nicht mehr durch einzelne Laute zusammengesetzt werden, sondern ein geschriebener Text wird vollautomatisch „vorgelesen“. Auch hierfür ist die Rechenleistung des Arduino UNO vollkommen ausreichend. Mit diesen fünf Reglern kann bereits eine erstaunliche Klangfülle erz ielt Eine Library ermöglicht die Umsetzung dieses Verwerden. Natürlich ist der Synthesizer nahezu beliebig erweiterbar. So ist fahrens ohne großen Aufwand. Sie kann unter es möglich, die Grundparameter zu ändern, um so völlig andere Tonlagen https://github.com/jscrane/TTS zu erzeugen. kostenlos aus dem Internet geladen werden. ELVjournal 1/2017
40 So funktioniert’s
Bild 6: Arduino als Synthesizer
Nach der Installation der Library gibt der folgende Beispielsketch eine kurze Begrüßung aus.
den Arduino sind so individuelle Geräte realisierbar, wie beispielsweise ein MP3-Wecker mit Wochentagfunktion oder ein programmgesteuertes Hi-Fi-Stereo-Mediacenter.
// text t o speech greeting #include TTS text2speech(3);
Weitere Infos:
void setup() {} void loop() { text2sp eech.setPitch(5); text2speech.sayText("Good morning, doctor Einstein"); delay(500); }
Das Programm ist in der Lage, englischsprachige Texte in relativ guter Sprachqualität wiederzugeben. Auch Ziffern werden korrekt gesprochen. Hieraus ergibt sich eine Fülle von Anwendungsmöglichkeiten. So kann man etwa Messwerte oder Systemzustände akustisch ausgeben. Ein sprechendes Voltmeter oder Thermometer kann so problemlos realisiert werden. Ausblick
Nachdem in diesem Beitrag die Grundlagen der Klang- und Sprachsynthese erläutert wurden, soll im nächsten Beitrag die Wiedergabe von aufgezeichneten Klängen und von Musik im Vordergrund stehen. Neben der Verwendung des Arduinos als Wiedergabegerät soll insbesondere auch ein MP3-Shield vorgestellt werden. Dieses Shield ermöglicht die Wiedergabe von Musik in Hi-Fi-Qualität. Im Gegensatz zu den teilweise etwas schwer verständlichen Sprachausgaben kann mit dem MP3-Shield Tonwiedergabe in höchster Qualität erfolgen. Durch die Steuerung über www.elvjournal.de
[1] Songtext „Daisy Bell“: www.metrolyrics.com/ daisy-bell-bicycle-built-for-two-lyrics-tyler-the-creator.html [2] IBM 7094 singt „Daisy Bell“: www.youtube.com/watch?v=41U78QP8nBk [3] HAL singt „Daisy Bell“: www.youtube.com/watch?v=XiIFeru-ufQ Mikrocontroller-Onlinekurs, Franzis-Verlag, exklusiv für ELV, 2011, Best.-Nr. CL-10 20 44 G. Spanner: Arduino – Schaltungsprojekte für Profis, Elektor-Verlag, 2012, Best.-Nr. CL-10 94 45 Grundlagen zur elektronischen Schaltungstechnik finden sich in der E-Book-Reihe „Elektronik!“ (www.amazon.de/dp/B00OXNCB02) Lernpaket „AVR-Mikrocontroller in C programmieren“, Franzis-Verlag, 2012, Best.-Nr. CL-10 68 46 Eine Einführung in die Audiotechnik findet sich im E-Book „Audiotechnik I“ (www.amazon.de/dp/B013NSPPY6) Preisstellung November 2016 – aktuelle Preise im Web-Shop
Empfohlene Produkte Arduino UNO Mikrocontroller-Onlinekurs
Best.-Nr. CL-10 29 70 CL-10 20 44
Preis € 27,95 € 99,–
Alle Arduino-Produkte wie Mikrocontroller-Platinen, Shields, Fachbücher und Zubehör finden Sie unter: www.arduino.elv.de
2 So funktioniert’s
Arduino verstehen und anwenden Teil 21: Audiotechnik und Sound-Wiedergabe
www.elvjournal.de
So funktioniert’s 3
Im letzten Artikel zu dieser Serie wurden dem Arduino verschiedene Töne und Klänge entlockt. Bis hin zu einer synthet ischen Spracherzeugung reichen die Möglichkeiten, die bereits ein einfacher AVR-Mikrocontroller auf dem Arduino bietet. Dabei wurden die Audioausgaben jedoch immer direkt vom Prozessor erzeugt. In diesem Artikel soll es dagegen um die Wiedergabe von aufgezeichneten Tönen gehen. In einem ersten Schritt wird dazu gezeigt, wie man den Arduino als Mini-Soundkarte einsetzen kann. Dazu werden Daten über die serielle Schnittstelle an den Arduino gesendet. Dort werden sie in analoge Signale umgewandelt. Diese können dann über einen Lautsprecher wiedergegeben werden. Natürlich darf man bei dieser einfachen Anwendung keine Hi-Fi-Ergebnisse erwarten. Für eine einfache Ausgabe von WAV-Dateien ist die Methode aber durchaus brauchbar. In einem zweiten Schritt sollen dann sogar MP3-Dateien abgespielt werden. Dazu reicht die Rechenleistung des Arduinos selbst nicht mehr aus. Deshalb wird hierfür ein Shield verwendet. Dieses verfügt über einen speziellen Decoder, der die im MP3-Format codierten Daten in analoge Tonsignale umwandelt. Zusätzlich enthält das Shield auch noch einen Audioverstärker, sodass man direkt Kopfhörer oder sogar kleine Lautsprecher anschließen kann. Damit lässt sich eine hervorragende Klangqualität erzielen, die für die meisten praktischen Anwendungen ausreichend sein sollte.
Bild 1: Einfache Audioausgabe mit dem Arduino
Der Arduino als Mini-Soundkarte
WAV-Dateien konvertieren
Im ersten Projekt wird gezeigt, wie mit geringem Hardware-Aufwand eine auf einem PC oder Laptop gespeicherte WAV-Datei mit einem Arduino abgespielt werden kann. Im einfachsten Fall benötigt man hierfür neben dem Arduino nur drei weitere Bauteile: · 1x 100 µF-Kondensator · 1x Widerstand oder Trimmer (ca. 100 Ω) · 1x Lautsprecher (8–32 Ω)
Um die WAV-Dateien auf dem Arduino abspielen zu können, müssen diese ein spezielles Format aufweisen. Die Daten sollten im RIFF-WAVE-Format/PCM mit den folgenden Parametern vorliegen: · 8-bit · mono · 11,025 kHz Samplingrate
Bild 1 zeigt den zugehörigen Schaltplan. Die gesamte Schaltung kann leicht auf einem kleinen Breadboard aufgebaut werden. Um mit einer minimalen Anzahl von Bauelementen auszukommen, wurde auf einen Tiefpass am PWM-Ausgang des Arduinos verzichtet. Möchte man die Tonqualität verbessern, empfiehlt es sich ohnehin, einen kleinen Audioverstärker einzusetzen. Ein passender Schaltungsvorschlag findet sich im letzten Artikel dieser Serie (Teil 20: Digitale Soundeffekte und Synthesizer, ELV Journal Feb./März). Hier wird stattdessen ein kleiner Lautsprecher direkt über einen Elko und einen Vorwiderstand angeschlossen. Zu beachten ist, dass an diesen einfachen Audioausgang kein kommerzieller Verstärker und keine Aktivboxen angeschlossen werden dürfen. Die im Signal vorhandenen hochfrequenten Störungen aus der Pulsweitenmodulation des Arduinos könnten diese Audiogeräte beschädigen.
Wenn die abzuspielende Datei noch nicht in diesem Format vorliegt, kann sie beispielsweise mit Audacity konvertiert werden. Dieses äußerst nützliche Programm kann unter [1] kostenlos aus dem Internet geladen werden. Die Datei wird in Audacity geöffnet und unten links unter Projektrate dann 11.025 Hz ausgewählt. Um bei Stereoformat auf Mono zu wechseln, klickt man im Kästchen mit dem Dateinamen auf den kleinen Pfeil und wählt Stereotonspur aufteilen. Anschließend kann man z. B. den rechten Tonkanal durch Klick auf das X löschen und beim linken Tonkanal durch erneuten Klick auf den kleinen Pfeil Mono auswählen. Das Speichern der Datei erfolgt ELV Journal 2/2017
4 So funktioniert’s Nun kann durch Klick auf den Button Send file die gewünschte WAV-Datei ausgewählt und dann durch Aktivieren von Start übertragen werden (Bild 4). Aus dem Lautsprecher sollte nun die WAV-Datei zu hören sein. Je nach Auslastung des PCs kann es z. B. beim Verschieben von Fenstern zu Lücken im Datenstrom und damit zu hörbaren Aussetzern kommen. Der Sketch dazu sieht so aus: // wavPlayer.ino
Bild 2: Exportieren der WAV-Datei
unter Export Audio. Die Datei muss im unkomprimierten Exportformat · WAV · 8-bit PCM gespeichert werden (siehe Bild 2). Die Datei sollte jetzt im korrekten Format vorliegen.
Ein Sketch verwandelt den Arduino in eine Soundkarte
Die WAV-Dateien müssen binär als kontinuierlicher Datenstrom, also ohne Pausen zwischen den Datenbytes, an den Arduino übertragen werden. Da beim Arduino ein virtueller COM-Port via USB geöffnet wird, ist es wichtig, dass das Sendetool die Daten nicht in einzelnen Bytes, sondern blockweise an den COM-Port-Softwaretreiber übergibt, da es sonst zu Lücken in der Wiedergabe kommen kann. Hierfür kann z. B. das Freewaretool HTerm [2] verwendet werden. Zunächst wird in HTerm in der Auswahlbox Port der entsprechende COM-Port des Arduinos ausgewählt. Die serielle Schnittstelle muss dann auf · 115.200 Baud, · 8 Datenbits, · 1 Stoppbit, · keine Parität, · keine Flusskontrolle eingestellt werden (siehe Bild 3). Durch einen Klick auf den Button Connect wird die Schnittstelle geöffnet.
void setup() { Serial.begin(115200); pinMo de(6, OUTPUT); TCCR0A=0x83; TCCR0B=0x01; TCNT0=0x00; OCR0A=0x00; OCR0B=0x00; } void loop() { for(int i = 0; i < 44; i++) { // skip 44 bytes header while(Serial.available() == 0); Serial.read(); } while(1) { while(Serial.available() == 0); OCR0A = (unsigned char)Serial.read(); } }
Das zu diesem Artikel verfügbare Download-Paket (siehe „Download-Paket zum Artikel“ am Ende des Beitrags) enthält zwei Probedateien im korrekten Format. Damit kann der Sketch getestet werden.
So funktioniert’s
In der Funktion setup wird die serielle Schnittstelle auf 115.200 Baud konfiguriert. Bei 16-MHz-Quarztakt ergibt sich bei dieser Baudrate zwar ein relativ großer Fehler, dieser wirkt sich jedoch kaum noch auf die Datenübertragung aus. Der Digitalpin 6 wird als PWM-Ausgang verwendet. Anschließend wird der Timer 0 des Arduinos für 8-bit-Auflösung konfiguriert. So ergibt sich ein PWM-Signal mit einer Frequenz von 16 MHz/256 = 62,5 kHz. Der Wert von OCR0A bestimmt das Puls-/
Bild 3: Die Einstellungen im Terminal programm
www.elvjournal.de
So funktioniert’s 5 Pausenverhältnis. Weitere Details zu Konfiguration von Timern finden sich in [3 oder 4]. In der Main-Loop wird zunächst mittels einer for-Schleife gewartet, bis 44 Bytes über die serielle Schnittstelle empfangen wurden, da eine WAV-Datei einen 44 Bytes großen Header mit Dateiinfos aufweist. Würden diese Bytes auf den PWM-Ausgang übertragen, könnte dies Störgeräusche im Lautsprecher verursachen. Anschließend wird in einer while(1)-Endlosschleife jedes über die serielle Schnittstelle empfangene Datenbyte in ein Timer-Register geschrieben und so auf den PWM-Ausgang ausgegeben. Wenn ein kontinuierlicher Datenstrom mit 115.200 Baud empfangen wird, werden bei 10 Bit (1 Startbit, 8 Datenbits, 1 Stoppbit) also 11.520 Bytes pro Sekunde ausgegeben, was in etwa 11 kHz, also der WAV-Datenrate, entspricht. Der Lautsprecher selbst wirkt wie ein Tiefpass und filtert den größten Teil der PWM-Frequenz von 62,5 kHz heraus.
Wiedergabe von Sound-Dateien Die Wiedergabe von Klangdateien über den PWM-Ausgang des Arduinos stellt natürlich nur eine sehr einfache Möglichkeit dar, den Arduino als Tonwiedergabemedium einzusetzen. Neben der Übertragung über die serielle Schnittstelle könnten die Tondaten auch im Flash des Arduinos gespeichert werden. Mit 16 Kilobyte kann man auf diese Weise allerdings gerade mal drei bis vier Sekunden lange Audiodateien speichern. Zwar könnte man die Speicherkapazität mit einer externen SD-Karte erheblich erweitern, wenn man aber schon zusätzliche Hardware einsetzt, kann auch ein wesentlich effizienteres Tonwiedergabeverfahren verwendet werden. Genau hier kommt das MP3-Verfahren zum Zug, welches die verlustbehaftete Kompression digital gespeicherter Tondaten erlaubt. MP3 verwendet dafür verschiedene Methoden der Psychoakustik. So sollen nur die relevanten, also für den Menschen wahrnehmbaren Signalanteile abgespeichert werden. So wird bei kaum verr ingerter Audioqualität eine starke Reduktion des Datenumfangs ermöglicht. Eine häufig verwendete Datenrate ist 192 Kilobit/Sekunde. Damit kann bereits eine hohe Wiedergabequalität erreicht werden. Die Datenkompression einer MP3-Audiodatei beträgt dabei bereits etwa 85 % gegenüber einer konventionellen Audio-CD. MP3 ist mittlerweile das am weitesten verbreitete Verfahren zur Speicherung und Übertragung von Musik auf Computern, Smartphones und im Internet. Entwickelt wurde das Format ab 1982 am Fraunhofer-Institut für Integrierte Schaltungen in Zusammenarbeit mit der Friedrich-Alexander-Universität Erlangen-Nürnberg, den AT&T Bell Labs und der Firma Thomson. Bereits Mitte der 1990er-Jahre waren Abspielgeräte und Software für PCs im Umlauf, die es ermöglichten, komprimierte MP3-Dateien zu speichern und abzuspielen. Auch der Austausch solcher Dateien über das Internet vereinfachte sich. Selbst bei einfacher ISDN-Geschwindigkeit benötigte man für die Übertragung lediglich das Zwei- bis Dreifache der Abspielzeit. Mit DSL-Leitungen liegt die Übertragungsdauer sogar weit unterhalb der Spieldauer. Ab 1998 erschienen im Handel die ersten tragbaren MP3-Player. Mit einem Audio-Shield steht seit einiger Zeit auch eine Möglichkeit zur Verfügung, MP3-Dateien Arduino-gesteuert wiederzugeben. Der besondere Reiz dieser Möglichkeit besteht darin, dass man nun in der Lage ist, MP3-Spieler nach eigenen Vorstellungen aufzubauen. Am Ende dieses Artikels wird dazu ein spezieller MP3-Wecker vorgestellt, der in weitem Rahmen individuell gestaltet und variiert werden kann.
Bild 4: HTerm sendet Audiodaten
Diese Library enthält bereits einige einfache Beispiele, welche die Funktionen des Audio-Shields erläutern. Die wichtigste Funktion ist das Abspielen einer MP3-Datei von einer SD-Karte. Der Decoder wird entsprechend über die Library VS10xx angesprochen, dabei muss diese am Anfang mit VS1011.begin() initialisiert werden. Über VS1011.Reset() wird der MP3-Decoder zurückgesetzt, dann können die Daten in 32-Byte-Paketen übertragen werden. Um die Audiosignale hörbar zu machen, muss entsprechend die Mute-Schaltung deaktiviert werden. Damit wird auch gleichzeitig der Verstärker aktiviert. Die Library des Audio-Shields stellt für die Ansteuerung des MP3-Decoders das Objekt „VS1011“ bereit, welches die folgenden Funktionen enthält. Dabei sind den Funktionen die Objektnamen mit einem Punkt voranzustellen, beispielsweise zur Initialisierung der Library: VS1011.begin();
Der auf dem Shield integrierte Verstärker kann über eine Mute-Funktion gesteuert werden. Über void UnsetMute( void );
wird der Verstärker aktiviert, über void SetMute( void );
kann er deaktiviert werden.
Die Funktionen des Audio-Shields
Zunächst sollen hier aber die wesentlichen Funktionen des Shields (siehe Bild 5) vorgestellt werden. Wie bei Arduino-Anwendungen üblich, wird zum Audio-Shield eine Library zur Verfügung gestellt. Diese kann von der Website des ELV Shops geladen werden [6].
Bild 5: Shield und LC-Display am Arduino
ELV Journal 2/2017
6 So funktioniert’s Die eigentliche Initialisierung des Audio-Shields erfolgt über void begin( void );
des MP3-Decoders. Zwischen zwei Audiodateien sollte jeweils ein Software-Reset ausgeführt werden: void SoftReset( void );
Ein besondere Vorzug des Shields ist, dass die Lautstärke über die Funktion void SetVolume( unsigned char leftchannel, unsi gned char rightchannel );
programmgesteuert einstellbar ist. Zu beachten ist allerdings, dass die maximale Lautstärke beim Einstellwert 0, die minimale Lautstärke bei 254 erreicht wird. Über den Wert 255 kann die Ausgangsstufe vollständig deaktiviert werden. So kann man etwa über zwei Taster die Lautstärke einstellbar machen. Ein analoges Potentiometer ist dann nicht mehr erforderlich. Aber auch bei einem Wecker kann man so zunächst mit geringer Lautstärke beginnen und diese dann langsam steigern. Mit der Anweisung unsigned char* Send32( unsigned char* pBuffer );
wird ein 32-Byte-Datenblock an den MP3-Decoder übertragen. Der Puffer des MP3-Decoders kann über void Send2048Zeros( void );
geleert werden. Um die SD-Karte nutzen zu können, muss die SD-Library des Arduinos hinzugefügt werden, dabei ist zu beachten, dass der ChipSelect der SD-Karte beim Audio-Shield von der SD-Library abweicht und deshalb beim Initialisieren diese als Parameter zu übergeben ist: SD.begin( SD_CS );
Damit ergibt sich das folgende Minimalprogramm zum Abspielen der Datei 001.mp3:
nischen Artikel in einer früheren Ausgabe des ELV Journals entnommen werden [6]. Weitere Detailinformationen sind auch dem im Datenblatt des auf dem Shield verwendeten Bausteins VS1011 der Firma VLSI Solution zu finden. Zudem befinden sich auf dem Shield noch mehrere LEDs, die softwaregesteuert ein- oder ausgeschaltet werden können. Für den Betr ieb der LEDs sind verschiedene Wischverbinder auf dem Shield zu schließen. Allerdings sind die LEDs nicht sichtbar, sobald der Aufbau in ein Gehäuse eingebaut wird. Deshalb wird die Verwendung dieser LEDs hier nicht weiter betrachtet. Bei entsprechendem Interesse können Details dazu wiederum in [6] nachgelesen werden. Nachdem eine MP3-Datei auf die SD-Karte kopiert wurde und die Karte in den Slot des Shields eingesteckt ist, steht einem ersten Test nichts mehr im Weg. Man muss lediglich noch zwei Lautsprecher an die Schraubklemmen anschließen und nach dem Laden des Sketches wird die Datei abgespielt.
Tipp: Die Verwendung des Audio Shields sollte mit einer externen Stromversorgung am Arduino erfolgen, da es sonst bei größeren Lautstärken zu Problemen mit der USB-Stromversorgung kommen kann.
Anschluss von Aktivboxen Auf dem MP3-Shield ist zwar ein Audioverstärker vorhanden, dieser liefert jedoch nur eine relativ geringe Ausgangsleistung. Für Kopfhörerbetrieb ist diese durchaus ausreichend. Will man jedoch Lautsprecher anschließen, bietet sich der Einsatz von Aktivboxen an. Diese können direkt mit den Schraubklemmen verbunden werden. Für eine optimale Klangqualität ist in diesem Falle der Lautstärkepegel entsprechend anzupassen, sodass es nicht zu Übersteuerungen kommt. Natürlich kann man sich geeignete Verstärker auch selbst bauen. Hinweise zum Aufbau eines einfachen Stereoverstärkers finden sich z. B. in [7].
Musikwecker
// play "001.mp3" from SD-card #include #include #include void setup() { SD.begin(SD_CS); VS1011.begin(); VS1011.SetVolume(0,0); } void loop() { unsigned char buer[32]; if( File SoundFile = SD.open("001.mp3", FILE_REA D)) { VS1011.UnsetMute(); while(SoundFile.available()) { Sound File.read(buer, sizeof(buer)); VS1011.Send32(buer); } VS1011.Send2048Zeros(); VS1011.SetMute(); SoundFile.close(); } }
Wie die Register des MP3-Decoders im Einzelnen ausgelesen oder beschrieben werden, kann einem techwww.elvjournal.de
Lässt man sich von einem gewöhnlichen Radiowecker aus dem Schlaf holen, hat das verschiedene Nachteile. Häufig wird man dann nicht von angenehmer Musik geweckt, sondern von nervigen Werbeeinblendungen, die sich im Halbschlaf ja besonders gut einprägen sollen. Außerdem verfügen kommerzielle Radiowecker meist nur über eine einzige Weckzeit. Deutlich komfortabler wäre es doch, wenn man für jeden Tag eine andere Zeit einprogrammieren könnte. So wäre für Wochentage beispielsweise 7:00 Uhr angemessen, während man am Samstag oder Sonntag erst um 9:00 Uhr geweckt werden will. Hier kommen die Vorteile eines Eigenbaus zum Tragen. Mit dem MP3Shield und einem Arduino kann man sich alle oben genannten Wünsche problemlos erfüllen. Man muss sich nur seine Lieblingssongs auf die SD-Karte kopieren und kann sich dann ganz individuell mit seinen Lieblingsliedern wecken lassen.
Für vollen Komfort: Display für Uhr- und Weckzeit
Natürlich gehört zu einem ordentlichen Wecker auch die Anzeige der Uhr- und Weckzeit. Hierfür kann ein Display mit dem Arduino verbunden werden. Da das MP3-Shield allerdings bereits eine Vielzahl von Pins belegt, ist der Anschluss eines klassischen HD44780-Displays, wie es in Artikel „Alphanumerische LC-Displays“ im ELV Journal 4/2016 vorgestellt wurde, mit erheblichen Problem verbunden. Eine Lösung bietet die Verwendung eines „I2C“-Displays, das mit nur zwei aktiven Pins gesteuert werden kann. Zudem bleiben auch bei akt ivem Shield die beiden Pins für den I2C-Bus frei, sodass dieser Displaytyp hier ohne Zusatzaufwand verwendet werden kann. Bild 6 zeigt den zugehörigen Aufbau.
So funktioniert’s 7
Der Sketch dazu sieht so aus: // MP3Clock.ino #include #include #include #include #include #include
LiquidCrysta Liquid Crystal_I2C l_I2C lcd(0x27, 16, 2); int startHour = 7; int startMinute = 15; 15; void printDigits( p rintDigits(int int d igits igits) ) { // print leading zeros if(digits if(dig its < 10) lcd.p lcd.prin rint(' t('0' 0'); ); lcd.print(digits); }
Bild 6: Aufbau mit MP3-Shield, LC-Display und Arduino
void setup() { lcd.be lcd.begin() gin(); ; lcd.ba lcd.backlig cklight() ht(); lcd.setCur lcd.set Cursor(0, sor(0, 1) 1); ; lcd.print(" Wake at: ") "); ; printDigits(sta prin tDigits(startH rtHour); our); lcd.pri lcd.print(" nt(":" :"); ); prin printDigits(sta tDigits(start rtMin Minute); ute); // 07:14:45 am 1. Januar 2017. setTi me(07 me(07, , 14, 45, 45, 01, 01, 01, 2017) 2017); ; // setup MP3 shield if( SD.begin( SD_CS ) == false ) { return; } VS1011.begin(); } void loop() { // // show current time lcd.setCur lcd.set Cursor(4, sor(4, 0); 0); print Digits(hou Digits(hour( r() )); lcd.print(" lcd.pr int(":" :"); ); printDigits(mi prin tDigits(mi nute() nute()); ); lcd.pri lcd.print(" nt(":" :"); ); prin printDigits(sec tDigits(second() ond()); );
if ((hour( (hour() ) == start startHour Hour && minute() == startMinute) startM inute)) ) // Start MP3 { lcd.se lcd.setCu tCursor(0, rsor(0, 0) 0); ; lcd.prin lcd.print(" t(" Playing MP3 "); ") ; unsigned unsigne d char buer[32 buer[32]; ]; // generate bue buer r if( File Sound File = SD.open( "00 "001.mp3" 1.mp3", FILE_ REA D ) ) { VS10 VS1011. 11.UnsetM UnsetMute( ute(); ); // powe power r up ampli er while( Sound SoundFile.available( File.available() ) ) { Sound SoundFile.read( File.read( buer, sizeof(buer) ); VS1011.Send VS1011 .Send32( 32( bu buer er ); } VS1011.Send VS1011 .Send2048Zero 2048Zeros( s(); ); // ll bu buer er VS1011.Set VS1011 .SetMute(); Mute(); // am ampli plier er o SoundFile.close(); } lcd.se tCursor(0, lcd.setCu rsor(0, 0) 0); ; lcd.prin lcd.print(" t(" "); ") ; }
}
ELV Journal 2/201 2/2017 7
8 So funktioniert’s
Bild 7: Das Display zeigt die aktuelle Zeit und den Systemstatus.
Bild 8: Der MP3-Wecker mit Display und Aktivboxen
Zusätzlich zu den bereits genannten Bibliotheken sind noch die folgenden Libs erforderlich: · Ti Time me-L -Lib ibra rary ry · Wi Wire re.h .h-L -Lib ibra rary ry · Li Liqui quidCry dCrystal_I stal_I2C 2C-L -Lib ibrary rary Die Bibliotheken können wie üblich kostenfrei aus dem Internet geladen werden. Informationen zu den jeweiligen Links finden sich am Ende des Art Artikels. ikels. Wenn man den Arduino samt dem aufgesteckten aufgeste ckten MP3Shield in ein formschönes Gehäuse einbaut, dann steht dem morgendlichen Musikgenuss nichts mehr im Weg. Die Bilder 7 und 8 zeigen 8 zeigen einen entsprechenden Aufbauvorschlag dazu.
Ausblick Mit diesem Artikel ist der Ausflug in die Klangerzeugung und Musikwiedergabe mit dem Arduino beendet. Mit dem Anschluss des I2C-Displays wurde jedoch bereits das nächste Thema gestreift. Wie man bereits erkennen konnte, kann man durch den Einsatz von Bussen Pins und andere Ressourcen in einem Mikrocontrollersystem Mikroco ntrollersystem einsparen einsparen.. So ist es möglich, die Funktionalität des Arduinos oder von Mikrocontrollersystemen allgemein durch Bussysteme wie I2C oder SPI ganz erheblich zu erweitern. Auch der SPI-Bus kam ja bereits bei der Ansteuerung der SD-Karte im Hintergrund zum Einsatz. Aus diesem Grunde werden sich die nächsten Art ikel genauer mit den bei Mikrocontrolleranwendungen so beliebten Bussystemen wie · I2C · SPI · Onee-W W ir e befassen. Wie immer werden dabei neben den theoretischen Hintergründen auch praktische Anwendungen vorgestellt. Insbesondere die Anbindung von Sensoren und Aktoren an die verschiedenen Busse wird w ird dabei eine zentrale Rolle spielen. www.elvjournal.de
Download-Paket zum Artikel: Die Sketche und Beispieldateien zu diesem Artikel können unter www.elv.de: Webcode #10071 heruntergeladen werden.
Weite We itere re Info Infos: s: [1] Audacity findet sich unter: http://www.audacityteam.org/download/ [2] Das Terminalprogramm kann aus dem Internet geladen werden unter: http://www.der-hammer.info/terminal/ [3] Mikrocontroll Mikrocontroller-Onlinekurs, er-Onlinekurs, Franzis-Verlag, exklusiv exklusi v für ELV, ELV, 2011, Best.-Nr. CM-10 20 44 [4] Elektor Praxiskurs AVR-XMEGA-Mikrocontroller Best.-Nr. CMC M-12 12 07 62 [5] G. Spanner: Arduino – Schaltungsprojekte für Profis, Elektor-Verlag, 2012 [6] Art Artikel ikel „ Audio Shield for Arduino“ im ELV Journal 1/2013 1/2013 [7] Im E-Book „Audiotechnik“ (siehe https://www.amazon.de/dp/B013NSPPY6) finden sich Grundlagen zum Bau von Audioverstärkern Preisstellung Februar 2017 – aktuelle Preise im Web-Shop
Empfohlene Produkte
Arduino UNO Audio Shield
Best.-Nr. Best .-Nr.
CM-10 29 70 CM-10 CM-111 06 48 CM-1
Preis
27,95 € 9,95 €
Alle Arduino-Produkte wie Mikrocon Mikrocontroller-Platinen, troller-Platinen, Shields, Fachbücher und Zubehör finden Sie unter: www.arduino.elv.de
2 So funktioniert’s
Arduino verste Ardui verstehe hen n und anwenden Teil 22 22:: I ² C – der Inter Inter-IC-Bus -IC-Bus – Grundlagen und Anwendungen A nwendungen
www.elvjournal.de
So funktioniert’s 3
Bild 1: Prinzipieller Aufbau des I²C-Busses
Der Arduino verfügt zwar über 14 digitale I/O-Pins und diese sind für viele kleinere Projekte durchaus ausreichend. Bei größeren Praxisanwendungen stößt man jedoch schnell an Grenzen. Insbesondere wenn Shields, wie etwa das im letzten Beitrag vorgestellte MP3-Shield, benutzt werden, sind oft nur noch wenige Pins frei verfügbar, da die Shields selbst bereits viele Pins belegen. Eine Lösung wäre, eine größere Arduino-Version einzusetzen, etwa den Arduino Mega oder den Due. Dies ist allerdings mit erheblichen Kosten verbunden und in vielen Fällen auch gar nicht notwendig. Sogenannte Bus-Systeme bieten die Möglichkeit, umfangreiche Funktionen mit nur wenigen Pins zu steuern. Ein klassisches Beispiel ist die Verwendung eines I²C-Displays. Dieses benötigt nur zwei I/O-Pins im Gegensatz zu den sechs Pins, die ein klassisches HD44780-LCD belegt. In diesem Beitrag soll daher der I²C-Bus im Vordergrund stehen. Weitere häufig verwendete Bus-Systeme wie etwa SPI oder One-Wire werden in späteren Beiträgen behandelt.
Inzwischen ist der I²C-Bus nicht mehr auf einzelne Platinen beschränkt. Vielmehr kommt er auch in größeren Systemen mit mehreren Boards zum Einsatz. Die einfache Steuersoftware macht den Bus sehr flexibel. Da keine festen Taktzeiten eingehalten werden müssen, können sowohl langsame als auch sehr schnelle Busteilnehmer simultan betrieben werden. Auf der Softwareseite ist so auch der Einsatz langsamerer Programmiersprachen wie etwa Python möglich.
Elektrischer Anschluss und Takt
I²C ist als Master-Slave-Bus konzipiert. Ein Datentransfer wird immer durch einen Master gestartet. Anschließend reagiert der über seine Adresse angesprochene Slave auf die Anfrage. Im sogenannten Multimaster-Mode können aber auch mehrere Master Der I²C-Bus an einem Bus betrieben werden. Hier können dann Der I²C-Bus (Inter Integrated Circuit, meist als „I-squared-C-Bus“ oder auch zwei Master direkt miteinander kommunizieren, deutsch „I-Quadrat-C-Bus“ ausgesprochen) ist ein serieller Zweidraht- indem ein Gerät kurzzeitig als Slave arbeitet. Die ZuBus, der vor über 30 Jahren in der Entwicklungsabteilung der Firma griffsregelung auf den Bus ist über eine ent sprechenPhilips, heute NXP, entstand. Rasch entwickelte sich das System zum de Spezifikation detailliert geregelt. Industriestandard für Steuerungs-, Diagnose- und ÜberwachungslösunBild 1 zeigt, wie die einzelnen Buskomponenten gen in unzähligen Embedded-Applikationen. hardwaremäßig miteinander verbunden werden. Durch die einfache Implementierung, niedrige Kosten und eine Über- Beide Busleitungen (Takt und Daten) liegen mit den tragungsrate von bis zu 3,4 MBit/s hat der Bus bis heute nichts von Pull-up-Widerständen (typischerweise 4,7 bis 10 kΩ) seiner Aktualität verloren. an der Versorgungsspannung Vdd, die üblicherweise Ursprünglich sollte ein Bus-System entstehen, über das mehrere ICs 5 V beträgt. Sämtliche daran angeschlossene Geräauf einer Leiterplatte mit geringem Aufwand miteinander kommunizie- te haben Open-Collector-Ausgänge. Zusammen mit ren sollten. Daher wurde eine serielle Struktur bevorzugt, um mit weni- den Pull-up-Widerständen ergibt sich so eine Wigen Leiterbahnen auszukommen. red-AND-Schaltung. Der High-Pegel der Bussignale So entstand ein bidirektionaler Zweidraht-Bus in Master/Slave-Archi- sollte mindestens 0,7×Vdd betragen, der Low-Pegel tektur mit integriertem Übertragungsprotokoll und Software-Adressie- soll höchstens bei 0,3×Vdd liegen. Falls es zu Überrung, der nur zwei Verbindungsleitungen erfordert: tragungsfehlern kommt, ist es immer eine gute Idee, • die Taktleitung SCL (Serial Clock), wenn man diese Spannungen mit einem Oszilloskop • die Datenleitung SDA (Serial Data). nachmisst und eventuell die Pull-up-Widerstände anEin Mikrocontroller kann so ein ganzes Netzwerk von Komponenten passt. Einige Controller haben auch bereits interne mit nur zwei I/O-Pins ansteuern. Bevorzugte Anwendungen finden sich Pull-ups eingebaut, sodass die externen Widerstände insbesondere im Bereich der Unterhaltungselektronik, z. B. in der Ab- entfallen können. Im Zweifelsfall hilft hier ein Blick stimmung von Autoradios oder TV-Geräten oder bei vollelektronischen ins Datenblatt weiter. Lautstärkereglern. Der I²C-Bus arbeitet mit positiver Logik. Das beZunächst genügte hierfür eine Übertragungsrate von lediglich deutet, dass ein High-Pegel auf der Datenleitung 100 kBit/s. Aufgrund zunehmender Leistungsanforderungen wurde die einer logischen „Eins“, der Low-Pegel einer „Null“ Übertragungsrate dann aber immer weiter angehoben. Ein großer Vorteil entspricht. des I²C-Busses besteht darin, dass auch langsamere Komponenten am Der Bustakt wird immer vom Master ausgegeben. Bus betrieben werden können. Hierfür kann das sogenannte Clock-Stret- Für die verschiedenen Modi ist jeweils ein maximal ching eingesetzt werden (s. u.). erlaubter Bustakt vorgegeben. In der Regel können ELV Journal 3/2017
4 So funktioniert’s Bild 2: Aufbau eines I²C-Telegramms Geräte
Adresse
Start
0
1
0
Subadresse
0
x
x
x
R/W
1
Daten
ACK
x
x
x
x
x
x
x
x
Stopp
Bild 3: I²C-Timing
aber auch beliebig langsamere Taktraten verwendet werden, falls diese vom Master-Interface unterstützt werden. Einige ICs (z. B. Analog-digital-Umsetzer) benötigen jedoch eine bestimmte minimale Taktfrequenz, um ordnungsgemäß zu funktionieren. Die folgende Tabelle listet die gängigsten Taktraten auf: 100-kHz-Takt 400-kHz-Takt 1,0-MHz-Takt 3,4-MHz-Takt
Standard-Mode Fast-Mode Fast-Mode-Plus High-Speed-Mode
Wenn der Slave mehr Zeit benötigt, als durch den Takt des Masters vorgegeben ist, kann er zwischen der Übertragung einzelner Bytes die Taktleitung auf „low“ halten. Über dieses im letzten Abschnitt bereits erwähnte Clock-Stretching kann der Mastertakt reduziert werden, falls dies er forderlich sein sollte. In einem I²C-System sind Daten nur gültig, wenn sich ihr logischer Pegel während einer Clock-HighPhase nicht ändert. Ausnahmen von dieser Regel sind das Start- und Stoppsignal. Das Startsignal wird durch eine fallende Flanke auf SDA gekennzeichnet, während SCL „high“ ist. Das Stoppsignal dagegen wird durch eine steigende Flanke auf SDA signalisiert, die SCL-Leitung bleibt dabei auf High-Pegel. Eine Dateneinheit besteht aus 8 Datenbits und wird häufig auch als Oktett bezeichnet. Ein Oktett kann entweder als Wert oder als Adresse interpretiert werden. Dazu kommt noch ein ACK-Bit als Bestätigung (von engl. Acknowledge). Dieses wird vom Slave durch einen Low-Pegel auf der Datenleitung erzeugt.
Protokoll und Adressierung Eine Standard-I²C-Adresse ist das erste vom Master gesendete Byte, wobei die ersten sieben Bit die eigentliche Adresse darstellen und das achte Bit (R/W-Bit) dem Slave mitteilt, ob er Daten vom Master empfangen soll (LOW) oder Daten an den Master zu übertragen hat (HIGH). In I²C-Systemen ist daher ein Adressraum von 7 Bit verfügbar. Da 16 der 27 = 128 möglichen Adressen für Sonderzwecke reserviert www.elvjournal.de
sind, können so bis zu 112 Teilnehmer an einem Bus betrieben werden. Dazu hat jedes I²C-fähige IC eine vom Hersteller festgelegte Adresse, von der häufig drei Bits, die sogenannte Subadresse, über drei Steuerpins individuell festgelegt werden können (siehe Bild 2 und 3). In diesem Fall können bis zu acht ICs des gleichen Typs an einem I²C-Bus betrieben werden. Im Praxisteil w ird dies anhand eines Temperatursensors vom Typ LM75 genauer erläutert. Für Hobbyanwendungen sind 112 Teilnehmer sicherlich in den meisten Fällen ausreichend. Bei großen, professionellen Systemen dagegen kann es durchaus zu Adressknappheit kommen. Deshalb wurde eine 10-Bit-Adressierung eingeführt. Sie ist abwärtskompatibel zum 7-Bit-Standard durch Nutzung von 4 der 16 reservierten Adressen. Beide Adressierungsarten sind gleichzeitig verwendbar, sodass nun bis zu 1136 Komponenten auf einem Bus erlaubt sind. Die Übertragung beginnt mit einem Startsignal des Masters. Dann folgt die Adresse. Diese wird durch das ACK-Bit des angesprochenen Slaves bestätigt. Abhängig vom R/W-Bit werden nun Daten byteweise geschrieben oder gelesen. Beim Schreiben wird das ACK vom Slave gesendet, beim Lesen vom Master. Eine Übertragung wird durch das Stoppsignal beendet. Die Datenübertragung startet mit dem höchstwertigen Bit (MSB first). Für den High-Speed-Mode wird zuerst im Fast- oder Standard-Mode ein Master-Code geschickt, bevor auf die erhöhte Frequenz umgeschaltet wird.
Anwendungen
Einer der wichtigsten Vorteile von Bus-Systemen wie I²C ist, dass ein Mikrocontroller ein ganzes Netzwerk an integrierten Schaltungen mit nur zwei I/O-Pins und einfacher Software ansteuern kann. Systeme mit einer möglichst geringen Anzahl von erforderlichen I/OPins sind deshalb so vorteilhaft, da ein erheblicher Teil der Kosten einer integrierten Schaltung und der verwendeten Leiterplatte von der Größe des IC-Gehäuses und der Anzahl der Pins abhängt. Ein großer Chip mit vielen Pins benötigt mehr Platz auf der Leiterplat te. Zudem stellen zusätzliche Verbindungen immer ein Ausfallrisiko dar und erfordern so einen erhöhten Prüfaufwand. All das steigert die Entwicklungs-, Produktions- und Testkosten. Obwohl das System langsamer ist als neuere Busse, ist die I²C-Schnittstelle wegen des geringen Aufwands vorteilhaft für Peripheriegeräte, die keine hohen Datenraten erfordern. Häufig wird sie f ür die Übertragung von Steuer- und Konfigurationsdaten verwendet. Beispiele sind Lautstärkeregler, Analog-digital- oder Digital-analog-Wandler mit niedriger Abtastrate, Echtzeituhren, kleine, nichtflüchtige Speicher oder
So funktioniert’s 5 bidirektionale Schalter und Multiplexer. Auch elektronische Sensoren haben oft einen Analog-digital-Wandler mit I²C-Schnittstelle integriert. In der folgenden Tabelle sind einige der am meisten verwendeten I²C-fähigen Chips zusammengefasst. IC / Komponente
Funktion
LM75 BMP180 DS1307 MAX127 PCF8574 PCF8583 LC-I2C AZDelivery-Display AT24C256
Temperatursensor Barometrischer Luftdrucksensor Echtzeituhr mit Batteriepufferung A/D-Wandler Portexpander Echtzeituhr 4x14-Segment-LC-Display OLED-Graphik-Display 0,96” EEPROM
Natürlich ist diese Tabelle bei Weitem nicht vollständig, sie liefert jedoch einen guten Überblick über die wichtigsten und am häufigsten verwendeten I²C-Bausteine. Ein weiterer Vorteil des Busses ist, dass Bauelemente während des Betriebs zum Bus hinzugefügt oder entfernt werden können (sog. Hot-Plug-Fähigkeit). Allerdings muss diese Eigenschaft durch besondere Vorkehrungen in der Programmierung berücksichtigt werden. Ansonsten kann es auch zu unerwünschten Programmabbrüchen kommen, wenn Elemente vom Bus getrennt werden. Eine gewisse Bedeutung hat das I²C-Protokoll auch im Chipkartenbereich. So wurde das System für Krankenversichertenkarten eingesetzt. Unter den Kontaktflächen der Chipkarte befand sich ein einfaches I²C-EEPROM, das vom Kartenleser ausgelesen und beschrieben werden konnte. Allerdings werden hier zunehmend auch andere Technologien eingesetzt.
Sensoren am I²C-Bus Zu den wichtigsten Anwendungen des I²C-Busses zählt die Erfassung von Sensorwerten. Hierfür steht eine fast unüberschaubare Vielfalt von Komponenten zur Verfügung. So lassen sich praktisch alle physikalischen Größen mit I²C-Sensoren erfassen. Im nichtprofessionellen Bereich haben sich allerdings einige Bauelemente besonders etabliert. Die wichtigsten davon sollen al s Anwendungsbeispiele für das Bus-System im Folgenden vorgestellt werden.
Präzise Temperaturmessung Eine der einfachsten Möglichkeiten, Temperaturen zu erfassen, ist die Verwendung von NTC-Sensoren (Negative Temperature Coefficient). Diese Methode ist allerdings mit mehreren Nachteilen verbunden. Zunächst sind diese einfachen Bauelemente herstellungsbedingt mit großen Toleranzen behaftet. Deshalb muss man jeden Sensor individuell kalibrieren, wenn eine gewisse Genauigkeit erreicht werden soll. Was im Hobbybereich durchaus noch möglich ist, wäre bei professionellen Anwendungen viel zu aufwendig. Ein weiterer Nachteil ist, dass die Messungen sehr ungenau werden können, sobald zwischen dem Sensor und dem Controller bzw. dem Arduino größere Distanzen liegen. Eine Ferntemperaturerfassung wird mit einfachen analogen Sensoren sehr unzuverlässig. Thermospannungen, Leitungswiderstände oder elektromagnetische Einstreuungen führen zu erheblichen Messfehlern. Digitale Sensoren sind hier deutlich weniger störanfällig. Der Messwert wird damit direkt am Ort der Messung in ein digitales Signal umgewandelt. Dieses ist gegenüber den oben genannten Einflüssen wesentlich unempfindlicher. Auf diese Weise kann man auch größere Distanzen zwischen dem Sensor und einer zentralen Messstation überbrücken. Ein weit verbreiteter Sensortyp mit integrierter A/D-Wandlung ist der LM75. Dieses Bauelement wandelt die aktuell gemessene Umge-
Bild 4: Sensoren und Display via I²C-Bus am Arduino
bungstemperatur direkt in ein I²C-Signal um. Damit wird es auch sehr einfach möglich, mehrere Sensoren mit einem einzigen Controller auszuwerten. Auf diese Weise kann man auch eine Vielzahl von Sensoren an einen Arduino anschließen, ohne dass die Analogeingänge belegt werden. Diese bleiben so für andere Anwendungen frei. Bild 4 zeigt, wie zwei LM75-Sensoren parallel am I²C-Bus eines Arduinos betrieben werden können. Zusätzlich ist hier bereits auch noch ein I²C-fähiges LCD-Modul und ein Drucksensor eingezeichnet. Diese beiden Komponenten werden weiter unten genauer erläutert. Die beiden Temperatursensoren müssen auf unterschiedliche Adressen konfiguriert werden. Dazu werden die Adresspins A0 bis A2 in geeigneter Weise mit Vcc oder GND verbunden. Bild 5 zeigt ein Beispiel.
Bild 5: Einstellung von I²C-Adressen am LM75
ELV Journal 3/2017
6 So funktioniert’s Daraus ergeben sich die folgenden Adressen für die beiden Bausteine: LM75 – 1: A2 = 0, A1 = 0, A0 = 0 LM75 – 2: A2 = 0, A1 = 1, A0 = 1 Da der fest eingestellte Teil der Adresse 1001 lautet, ergeben sich die vollständigen Adressen zu: LM75 – 1: 1001000 = 48 hex LM75 – 2: 1001011 = 4B hex Sollen weitere Sensoren angeschlossen werden, müssen für diese natürlich andere Adressen gewählt werden.
I²C-fähiger Luftdrucksensor Wie bereits aus der oben stehenden Tabelle ersichtlich ist, steht mit dem BMP180 auch für die Messung des Luftdrucks ein I²C-fähiger Baustein zur Verfügung. Dieser kann problemlos gemeinsam mit den beiden LM75-Sensoren am Arduino betrieben werden, da seine Adresse fest auf den Wert 1110111 = 77 hex eingestellt ist. Zusätzlich zum Luftdruck liefert dieser Sensor auch noch einen präzisen Temperaturmesswert. Zusammen mit den beiden LM75-ICs stünden damit dann bereits drei Temperatursensoren zur Verfügung, mit denen Messwerte an verschiedenen Orten erfasst werden könnten. Beispielsweise ist es so möglich, die Temperatur in einem Wohnraum, im Keller und im Außenbereich zu erfassen.
Einfacher Anschluss von Displaymodulen
Auch Displaymodule verfügen häufig über einen I²C-Anschluss. So kann beispielsweise ein alphanumerisches LC-Display über lediglich zwei aktive Pins gesteuert werden. Ein solches Display wurde bereits im letzten Beitrag zu dieser Artikelserie eingesetzt. Beim Audio-Player waren nur noch wenige freie Pins verfügbar, sodass der I²C-Bus dort seine Vorteile voll ausspielen konnte. Natürlich könnte ein derartiges Display auch hier zum Einsatz kommen, allerdings soll an dieser Stelle eine andere Version vorgestellt werden. Das ELV I²C-Displaymodul bietet eine vierstellige 14-Segmentanzeige, die bestens zur Darstellung von Messwerten geeignet ist. Möchte man lediglich Zahlenwerte ausgeben, ist ein derartiges Display voll-
Bild 6: Der I²C-Scanner findet vier Komponenten am Bus
www.elvjournal.de
kommen ausreichend. Die Platine ist unter anderem auch direkt als Arduino-Shield einsetzbar. Der Anschluss des Displays ist ebenfalls aus Bild 4 ersichtlich. Die I²C-Adresse des ELV Displays ist auf 0111011 = 3B hex eingestellt und kann ebenfalls nicht verändert werden.
Test des Bus-Systems Insbesondere wenn eine Vielzahl von Komponenten an einem Bus angeschlossen sind, ist es empfehlenswert, das Ges amtsystem vor der Inbetriebnahme zu testen. Die folgende Tabelle fasst alle im System vorhandenen Adressen zusammen: LM75 – 1 LM75 – 2 BMP180 I²C-Display
binär
hex
0b1001000 0b1001011 0b1110111 0b0111011
0x48 0x4B 0x77 0x3B
Alle am Bus vorhandenen Sensoren können also aufgrund ihrer individuell verschiedenen Adressen problemlos angesprochen werden. Um die Funktion des Busses zu testen, kann ein sogenannter I²C-Scanner verwendet werden. Für den Arduino existiert dazu ein spezielles Programm, das unter [1] aus dem Internet geladen werden kann. Sind die Komponenten korrekt angeschlossen, zeigt der Scanner die jeweiligen Bus-Adressen im seriellen Monitor an (Bild 6).
Klimastation mit I²C-Komponenten Die hier vorgestellten Komponenten ermöglichen den Aufbau einer präzisen und flexibel einsetzbaren Klimastation. Sind alle Komponenten erst einmal mit dem Arduino verbunden, fehlt nur noch ein passendes Auswertungsprogramm. Das ELV I²C-Displaymodul verfügt neben der LCD-Anzeige auch noch über vier LEDs. Durch eine entsprechende Zuordnung und Beschriftung kann man damit jeden aktuell dargestellten Messwert kennzeichnen. Für die Anwendung als Klimastation wurde folgende Zuordnung gewählt: LED 1: aktueller Luftdruck (P) LED 2: Innentemperatur 1 (T1) LED 3: Innentemperatur 2 (T2) LED 4: Außentemperatur (T3) Da die LEDs ebenfalls über den I²C-Bus angesteuert werden können, werden keine zusätzlichen Arduino-Pins belegt. Um das Display anzusteuern, ist wieder eine passende Library er forderlich. Diese kann unter [2] von der ELV Produktseite des Moduls geladen werden. Das Programm dazu ist im folgenden Listing in verkürzter Form dargestellt. Der vollständige Code kann dem Download-Paket (siehe „Download-Paket zum Artikel“ am Ende des Beitrags) entnommen werden. Zunächst werden im Sketch alle erforderlichen Bibliotheken eingebunden. Dann erfolgt die Deklaration der Variablen: P: Luftdruck in mbar T1: z. B. Innentemperatur 1 T2: z. B. Innentemperatur 2 T3: z. B. Außentemperatur Im Set-up werden die einzelnen Module (Wire, LCD und Serial) gestartet. In der Hauptschleife werden dann die Werte aus den jeweiligen Modulen der Reihe nach ausgelesen und sowohl an das Displaymodul als auch an die serielle Schnittstelle ausgegeben. Weitere Details dazu können bei Bedarf in [3] nachgelesen werden. Wenn die Klimastation ohne Verbindung zu einem PC laufen soll, kann auf die Ausgabe zur seriellen Schnitt stelle verzichtet werden und