147 14 88MB
German Pages [1963] Year 2023
Claus Kühnel
Arduino Das umfassende Handbuch 2., aktualisierte und erweiterte Auflage 2023
Impressum Dieses E-Book ist ein Verlagsprodukt, an dem viele mitgewirkt haben, insbesondere: Lektorat Christoph Meister
Korrektorat Annika Holtmannspötter, Münster
Covergestaltung Mai Loan Nguyen Duy
Coverbild Shutterstock: 523069681 © Flegere, 1015295419 © daizuoxin, 111089144_ © Krasowit
Herstellung E-Book Nadine Preyl
Satz E-Book III-satz, Flensburg
Bibliografische Information der Deutschen Nationalbibliothek:
Die Deutsche Nationalbibliothek verzeichnet diese Publikation in der Deutschen Nationalbibliografie; detaillierte bibliografische Daten sind im Internet über http://dnb.dnb.de abrufbar. ISBN 978-3-8362-9106-4 2., aktualisierte und erweiterte Auflage 2023
© Rheinwerk Verlag GmbH, Bonn 2023
Liebe Leserin, lieber Leser, mit dem Arduino hat sich eine offene Mikrocontroller-Architektur entwickelt, die industriellen Angeboten in nichts nachsteht. Sie können die unterschiedlichen Arduino-Modelle in der Robotik einsetzen, Ihr eigenes Smarthome automatisieren oder Messdaten mit ihnen auswerten. Arduinos werden sogar für den Bau autonomer Fahrzeuge oder für das Prototyping in der Industrie eingesetzt. Sie sehen schon: Mit der Arduino-Plattform können Sie die unterschiedlichsten Projekte meistern. Wie dies alles funktioniert, erfahren Sie in diesem umfassenden Handbuch. Sie lernen die Arduino-Architektur genauso wie die dazugehörigen Software-Komponenten genau kennen. Viele Beispiele und verständliche Erklärungen bringen Ihnen den kleinen Mikrocontroller näher. Von der Temperaturmessung in der Ostsee bis zum maschinellen Lernen und fortgeschrittenen Bastelprojekten ist alles enthalten. In diese zweite Auflage wurden zudem neue Arduino-Modelle und der Raspberry Pi Pico aufgenommen. Claus Kühnel ist schon seit vielen Jahren fester Bestandteil der Maker-Bewegung. In vielen Artikeln und Büchern zu Hard- und Software von Mikrocontrollern hat er sein enormes Wissen an Interessierte weitergegeben. Es freut mich, dass er hier nun alles über den Arduino für Sie zusammengetragen hat. Abschließend noch ein Hinweis in eigener Sache: Dieses Buch wurde mit großer Sorgfalt geschrieben, geprüft und produziert.
Sollte dennoch einmal etwas nicht so funktionieren, wie Sie es erwarten, freue ich mich, wenn Sie sich direkt mit mir in Verbindung setzen. Ihre Anregungen und Fragen sind uns jederzeit herzlich willkommen! Ihr Christoph Meister
Lektorat Rheinwerk Computing [email protected]
www.rheinwerk-verlag.de
Rheinwerk Verlag • Rheinwerkallee 4 • 53227 Bonn
Inhaltsverzeichnis Aus dem Lektorat Inhaltsverzeichnis
Materialien zum Buch Geleitwort
1 Arduino – was ist das? 1.1 Arduino – etwas Hintergrund 1.2 Open Source: Die Lizenzen des ArduinoProjekts 1.3 Maker und die Arduino-Community 1.4 Arduino Uno Rev3 – der Standard 1.4.1 Ein- und Ausgangspins 1.4.2 Serielle Schnittstellen 1.4.3 Spannungsversorgung 1.4.4 Mikrocontroller ATmega328P 1.4.5 Warum eigentlich die Bezeichnung »Uno«?
1.5 Details zum Mikrocontroller
1.5.1 Mikrocontroller-Kern 1.5.2 Mikrocontroller-Peripherie
2 Arduino-Hardware 2.1 Die Produktfamilie Arduino 2.1.1 Klassische Arduino-Boards 2.1.2 Kompakte Arduino-Boards 2.1.3 Arduino-MKR-Serie 2.1.4 Arduino-Pro-Familie 2.1.5 Arduino Yún
2.2 Arduino-kompatible Boards 2.2.1 Seeeduino v4.2 2.2.2 LilyPad Arduino 2.2.3 Maduino GPRS A6 2.2.4 BBC micro:bit bzw. Calliope mini 2.2.5 SparkFun Pro nRF52840 Mini 2.2.6 STM32 Nucleo 2.2.7 Teensy 4.x 2.2.8 ESP8266 2.2.9 ESP32 2.2.10 M5Stack, M5StickC/M5StickC Plus, M5ATOM und M5Stamp 2.2.11 Raspberry Pi Pico 2.2.12 Seeed XIAO und Wio Terminal 2.2.13 Adafruit Feather und SparkFun Thing Plus
2.2.14 Maixduino
2.3 Arduino-Shields 2.3.1 Arduino-Standard-Shields 2.3.2 Arduino-MKR-Shields
2.4 Expansionsboards 2.4.1 Arduino Portenta H7 2.4.2 Seeeduino XIAO 2.4.3 Raspberry Pi Pico
3 Das Experimentierumfeld 3.1 Elektronische Bauteile 3.1.1 Widerstand, Kondensator und Spule 3.1.2 Taster, Schalter und Relais 3.1.3 Dioden 3.1.4 Transistoren und FETs als Schalter 3.1.5 Operationsverstärker
3.2 Grundlagen zur Schaltungstechnik 3.2.1 Ohmsches Gesetz 3.2.2 Kirchhoffsche Regeln 3.2.3 Reihen- und Parallelschaltung von Widerständen
3.3 Breadboards und Zubehör 3.3.1 Breadboards 3.3.2 Breadboard Holder 3.3.3 Breadboard Power
3.4 Qwiic, Grove und mikroBUS Connection
3.4.1 Qwiic Connection 3.4.2 Grove-System 3.4.3 mikroBUS System
3.5 Spannungsversorgung 3.5.1 USB-Anschluss 3.5.2 USB-Hub mit Schnellladeanschluss 3.5.3 Steckernetzteil 3.5.4 Labornetzgerät 3.5.5 Lithium-Polymer-Akku 3.5.6 Spannungsversorgung mit Solarzellen 3.5.7 Reduzierung des Strombedarfs für Batteriebetrieb
3.6 Messtechnik 3.6.1 Multimeter 3.6.2 Funktionsgenerator 3.6.3 Oszilloskop 3.6.4 BitScope Micro 3.6.5 Saleae Logic Analyzer
3.7 CAD-Software 3.7.1 Fritzing 3.7.2 KiCAD 3.7.3 EAGLE 3.7.4 EasyEDA Standard 3.7.5 Welches Tool soll ich verwenden?
4 Arduino-Software
4.1 Schritte bei der Programmerstellung 4.2 Die Arduino-Entwicklungsumgebung 4.2.1 Legacy IDE: Arduino 1.8 4.2.2 Die neue Arduino IDE 2
4.3 Die Arduino-Create-Plattform 4.3.1 Arduino Web Editor 4.3.2 Arduino IoT Cloud 4.3.3 Arduino Project Hub
4.4 Arduino Create vs. Arduino IDE 4.5 Programmieren in C++ 4.5.1 Empfehlenswerte Online-Tutorials 4.5.2 Einführung in die Grundlagen von C++
4.6 Den Arduino programmieren 4.6.1 Programmstruktur 4.6.2 Arduino-Funktionen 4.6.3 Hello World 4.6.4 Arduino-Librarys
4.7 Arduino-Boards in Betrieb nehmen 4.7.1 Arduino Uno 4.7.2 Arduino Uno WiFi Rev2 4.7.3 Arduino Yún 4.7.4 ESP32 4.7.5 M5Stack bzw. M5StickC/C Plus 4.7.6 Teensy 4.x 4.7.7 Raspberry Pi Pico
4.8 Arduino-Debugging 4.8.1 Debugging mit digitalem Ausgang
4.8.2 printf()-Debugging 4.8.3 MicroDebug-Library 4.8.4 ArduinoTrace-Library 4.8.5 Arduino-Debugging mit SEGGER J-Link Debugger
5 Sensoren 5.1 Der Thermistor als Temperatursensor 5.2 Der Temperatursensor TMP36 5.3 Der Temperatur- und Feuchtigkeitssensor DHTxx/AM23xx 5.4 Der Temperatur- und Feuchtigkeitssensor Si7021 5.5 Der Temperatursensor DS18B20 5.6 Die barometrischen Drucksensoren BMP180, BMP280 und BME280 5.7 Der Luftqualitätssensor MQ135 5.8 Der Grove-Feinstaubsensor PPD42NS 5.9 Der Lichtstärkesensor GY-30 (BH1750FVI) 5.10 Der Farbsensor GY-TCS3200D 5.11 Ultraschall-Entfernungsmessung 5.12 ToF-Entfernungsmessung 5.13 Bewegungsdetektion mit PIR-Sensoren 5.14 Wetterdaten
6 Eingabeelemente 6.1 Taster und Schalter 6.2 Keypads 6.3 Joysticks 6.4 Drehgeber 6.5 Touch-Sensoren 6.6 Touch-Panels 6.7 RFID 6.8 NFC
7 Anzeigeelemente 7.1 LEDs und RGB-LEDs 7.2 Sieben-Segment-Anzeige 7.3 LED-Dot-Matrix-Anzeige 7.4 Seriell gesteuerte RGB-LEDs 7.4.1 NeoPixel 7.4.2 DotStar 7.4.3 NeoPixel vs. DotStar 7.4.4 FastLED
7.5 LCDs 7.5.1 Display mit HD44780
7.5.2 Grove-LCDs mit I2C 7.5.3 LCD Keypad Shield 7.5.4 Arduino-Shield mit EA DOGS102W-6 und EA PCBARDDOG1701 7.5.5 Nokia-5110-Grafik-LCD
7.6 OLED-Display 7.7 Touchscreen 7.7.1 Waveshare 2.8" Touch LCD Shield 7.7.2 Nextion 2.8" HMI LCD Touch Display
8 Aktoren 8.1 Relais 8.2 Motoren 8.2.1 Servo 8.2.2 DC-Motor 8.2.3 Schrittmotor
9 Externe Speicher 9.1 Internes EEPROM 9.2 Externes EEPROM 9.3 FRAM
10 Kommunikation 10.1 Serielles Interface UART, der interne Monitor 10.2 SPI 10.3 I2C-Bus 10.4 1-Wire-Bus 10.5 CAN 10.6 Bluetooth und BLE 10.6.1 Serielle Bluetooth-Module 10.6.2 Mikrocontroller mit BLE
10.7 Der Arduino im Netzwerk 10.7.1 Ethernet 10.7.2 WiFi 10.7.3 Die Performance testen
10.8 LoRa bzw. LoRaWAN 10.8.1 LoRa/LoRaWAN – Begriffe 10.8.2 LoRa-Datenübertragung 10.8.3 The Things Network (TTN) 10.8.4 LoRaWAN-Knoten
10.9 GSM 10.9.1 Module und Provider 10.9.2 Arduino Uno mit SIM800 EVB 10.9.3 Maduino GPRS A6
10.10 3GPP LPWAN
10.10.1 NB-IoT 10.10.2 LTE-M
10.11 Netzwerkverbindungen mit nRF24L01 10.11.1 Transceiver nRF24L01 10.11.2 nRF24L01-Modul 10.11.3 nRF24L01 mit SMA-Antenne 10.11.4 nRF24L01-Reichweitenmessung 10.11.5 Die Netzwerkknoten in der Übersicht 10.11.6 Initialisierung des nRF24L01 10.11.7 Datenübertragung zwischen zwei Sensorknoten 10.11.8 Datenübertragung zwischen mehreren Sensorknoten
11 Datenformate und Kommunikationsprotokolle 11.1 JSON 11.2 MQTT 11.2.1 Grundlagen 11.2.2 MQTT-Broker 11.2.3 MQTT-Client
12 Arduino-Benchmarks
13 Projektideen für den Arduino 13.1 Tragbare Elektronik (Wearables) 13.2 Überwachung des Raumklimas 13.2.1 Sensirion SCD30 13.2.2 Sensirion SGP30 und Bosch BME280 13.2.3 Bosch BME680 13.2.4 Environmental Sensor AZ-Envy
13.3 Open Data aus dem Internet 13.3.1 OpenWeatherMap 13.3.2 Covid-19-Datenbank
13.4 Pushover-Statusmeldungen 13.4.1 Pushover-Server 13.4.2 Pushover-Android-Client 13.4.3 Pushover-Integration ins Arduino-Programm
13.5 Überwachung von Pflanzen 13.5.1 M5Stack ENV.II und EARTH Unit 13.5.2 Kapazitive Bodenfeuchtesensoren 13.5.3 LilyGO-T-HiGrow Kit
13.6 Messung von radioaktiver Strahlung 13.6.1 Messtechnische Voraussetzungen 13.6.2 Auswertung der GMZ-Impulse
13.7 Arduino Yún 13.7.1 Netzwerk-Performance 13.7.2 Zwei Welten verbinden 13.7.3 Erfassen von Messdaten
13.8 M5StickC 13.8.1 M5StickC-Hats 13.8.2 M5StickC-Thermometer 13.8.3 M5StickC – Messung der Wassertemperatur
13.9 Kameraanwendungen 13.9.1 Arducam Shield V2 13.9.2 ArduCAM_ESP32S_UNO_PSRAM Board 13.9.3 M5Stack Camera
13.10 Maschinelles Lernen 13.10.1 TensorFlow Lite 13.10.2 Edge Impulse
14 Gehäuse für den Arduino 14.1 ArduiBox Open – Hutschienengehäuse für den Arduino 14.2 RasPiBox Pico für Raspberry Pi Pico 14.3 AZ-Touch MKR/ESP/Feather 14.4 ESPGateway – ESP32 WiFi/ BLE Gateway
15 Der Arduino in industriellen Anwendungen
15.1 Prototyping mit dem Arduino 15.2 Industrieanwendungen 15.2.1 Controllino 15.2.2 Industrial Controller 15.2.3 Industruino
A Anhang A.1 Arduino-Distributoren A.2 Technische Daten im Vergleich A.3 Spezifikation von Widerständen A.3.1 Bedrahtete Widerstände A.3.2 SMD-Widerstände
Stichwortverzeichnis Rechtliche Hinweise Über den Autor
Meiner Frau Jutta möchte ich auch bei dieser zweiten Auflage Danke sagen für Geduld, Verständnis und Unterstützung bei diesem umfangreichen Projekt.
Materialien zum Buch Auf der Webseite zu diesem Buch stehen folgende Materialien für Sie zum Download bereit: Programmbeispiele Skriptbeispiele Benchmarks Bilder Videos (MP4) Gehen Sie auf www.rheinwerk-verlag.de/5563 und klicken Sie auf den Reiter Materialien zum Buch. Sie sehen die herunterladbaren Dateien samt einer Kurzbeschreibung des Dateiinhalts. Klicken Sie auf den Button Herunterladen, um den Download zu starten. Je nach Größe der Datei (und der Übertragungsrate Ihrer Internetverbindung) kann es einige Zeit dauern, bis der Download abgeschlossen ist. Außerdem pflegt der Autor ein Git-Repository zum Buch, das Sie unter https://github.com/ckuehnel/Arduino2022 finden. Sie können dort das Repository klonen oder einzelne Dateien herunterladen. Außerdem freuen wir uns natürlich über Pull Requests und den Austausch mit Ihnen.
Geleitwort Liebe Leserinnen, liebe Leser, in den vergangenen Jahren habe ich mich überwiegend in der Welt der Single Board Computer bewegt und hier im Speziellen mit dem Raspberry Pi verschiedenen Projekte umgesetzt. Ein Schwerpunkt meiner Projekte waren stets Roboterautos, die frei programmiert werden können oder von einem neuronalen Netz gesteuert werden. Die Welt der Mikrocontroller hat mich aber immer fasziniert. So habe ich mir parallel zu den Single Board Computern auch die Welt des Arduinos und seiner Klone erschlossen. Auf Basis der klassischen Mikrocontroller sind kleine via WIFI-steuerbare Roboterfahrzeuge entstanden, Feinstaubsensoren mit Luftfeuchtesowie Temperatursensoren, Kinder-Musikboxen gesteuert über RFID-Tags und IoT-Smarthome-Lösungen. Das notwendige Wissen für diese kleinen Projekte musste ich mir mühevoll zusammensuchen und durch Ausprobieren erarbeiten. Mir fehlte einfach ein Leitfaden, der mir dabei geholfen hätte z. B. den richtigen Mikrocontroller für mein Projekt zu wählen. Auch meine Fragen rund um die Technik, die in einem Arduino steckt, musste ich mir selbst beantworten, z. B. wie das persistente Schreiben in den Speicher des Arduino funktioniert. So habe ich mich sehr gefreut, als ich erfahren habe, dass dieses Buch bzw. dieses Nachschlagewerk, das Sie gerade in den Händen halten, geschrieben wird und ich es schon in einer frühen Fassung lesen durfte.
Sie ahnen sicherlich schon, dass Sie mit diesem Buch Zugang zu der Welt der Mikrocontroller und deren unzählige Möglichkeiten erhalten. Wirklich begeistert hat mich, wie breit aufgestellt das Buch ist und mit wie viel Hingabe die wirklich wichtigen Details durch den Autor beschrieben werden. So erlangen Sie beim Lesen des Buches ein sehr gutes Verständnis für die elektronischen Komponenten und deren Funktionsweise. Mit diesem Expertenwissen werden Ihre individuellen Projekte mit Sicherheit realisierbar, ohne dass Sie sich (so wie ich) viel durch Ausprobieren und Fehleranalyse selbst erarbeiten müssen. Ich möchte an dieser Stelle ein Beispiel herausgreifen, das mir sehr gut gefallen hat, weil es zeigt, wie gut das Buch Sie mit auf die Reise in die Welt der Elektronik nimmt. In Abschnitt 7.5.5 geht Claus Kühnel detailliert auf ein Display aus dem Mobiltelefon-Bereich ein, das in der Do-it-yourself-Szene weitverbreitet ist. Dabei erklärt er ausführlich die Eigenschaften und technischen Details und zeigt Ihnen, wie dieser Typ von Display aufgebaut ist und durch einen Arduino angesteuert werden kann. Mit diesem Wissen traut man sich dann auch selbst zu, dieses Display zu verwenden und vielleicht sogar ein ähnliches Display einzusetzen. Denn die zugrunde liegende Technik haben Sie generell verstanden und können jetzt abschätzen, wie ein ähnliches Display, vielleicht mit einer höheren Auflösung, an einem Arduino angeschlossen und zum Leben erweckt werden kann. Sind Sie sich vielleicht vor Projektbeginn nicht sicher, welcher Arduino oder auch Arduino-Ableger für Ihr Projekt am besten geeignet ist, finden Sie in diesem Buch sicher die passende Antwort. Es werden sehr viele verschiedene Modelle unterschiedlichster Hersteller mit ihren individuellen Eigenschaften ausführlich vorgestellt. Bedarf es für ein Projekt eventuell eines besonders energiesparenden Aufbaus, dann werden Sie hier das richtige
Modell finden. Dazu dann auch gleich die wichtigen Details, wie Sie z. B. bei der Programmierung des Mikrocontrollers zusätzlich Energie sparen können: Das könnte einmal eine auf das Minimum reduzierte Kommunikation sein oder aber auch das Aktivieren des Schlafmodus des Chips. Das Buch deckt ein sehr breites Spektrum rund um den Arduino und dessen typischen elektronischen Komponenten ab. Dabei wird nicht nur auf Sensoren, Aktoren oder Displays eingegangen, sondern eben auch auf die verschiedensten Kommunikationsarten und Grundlagen in der Programmierung. Aber damit nicht genug! Es wird auch erläutert, welche Arduino-Hardware für das maschinelle Lernen gut geeignet ist und was es mit Tensorflow Lite als Bibliothek für das Machine Learning auf sich hat. Wenn Sie sich noch nicht so richtig getraut haben, einen Arduino in Ihre Projekte zu verbauen, dann werden Sie spätestens jetzt damit loslegen wollen. Mit Sicherheit werden Sie auf Ihre offenen Fragen in diesem umfangreichen Nachschlagewerk die passenden Antworten finden. Jetzt wünsche ich Ihnen aber erst einmal viel Spaß beim Schmökern in den verschiedenen Themenbereichen und viel Erfolg bei der Realisierung Ihrer Projekte!
Ingmar Stapel
1 Arduino – was ist das? Sie interessieren sich für den Arduino? In diesem Buch möchte ich Ihnen zeigen, warum der Arduino so viele Dinge verändert hat und wie Sie an dieser Entwicklung teilhaben und an ihr mitwirken können. Und um es vorwegzunehmen: Mit den neuen Arduinos wird es weitere Veränderungen geben. Es bleibt sehr spannend! Der Name Arduino steht für ein weltweit führendes System an Open-Source-Hard- und -Software. Das Unternehmen Arduino bietet Software-Tools, Hardware-Plattformen und Dokumentationen, mit denen nahezu jeder mit Technologie kreativ umgehen kann. Die Plattform Arduino ist ein beliebtes Tool zur Produktentwicklung für eine Vielzahl unterschiedlicher Anwendungen und das Internet of Things (IoT) sowie eines der erfolgreichsten Tools für die Ausbildung. Hunderttausende von Designern, Ingenieuren, Studenten, Entwicklern und Herstellern auf der ganzen Welt nutzen den Arduino, um Innovationen in den Bereichen Musik, Spiele, Spielzeug, Robotik, Smarthomes, Landwirtschaft, autonome Fahrzeuge und mehr zu entwickeln. Soweit erst einmal eine verkürzte Erklärung dazu, wie der Hersteller selbst sein Arduino-System positioniert. Ich möchte diese Auflistung um die wichtigen Themen Mess-, Steuerungs- und Regelungstechnik, Kommunikation und Automatisierung ergänzen.
1.1 Arduino – etwas Hintergrund In den Jahren 2001 bis 2006 war das Ivrea Interaction Design Institute in Italien aktiv. Dort wurde der Arduino als einfaches Werkzeug für schnelles Prototyping entwickelt. Er richtete sich an Studenten ohne Kenntnisse in Elektronik und Programmierung, die die physische Welt mit der digitalen Welt zu verbinden suchten. Dieses grundlegende Anliegen der Mikrocontroller-Technologie, physikalische Größen in Daten umzusetzen, sie zu verarbeiten und die Ergebnisse dieser Verarbeitung wieder zurückfließen zu lassen, ist heute so gültig wie vor 15 oder mehr Jahren. Sobald das im Jahr 2005 eingeführte Arduino-Board – so nennen wir die Leiterplatte, die den Arduino ausmacht – eine größere Community erreicht hatte, stellte sich die Arduino-Mannschaft auf neue Anforderungen und Herausforderungen ein und differenzierte ihr Angebot von einfachen Boards auf der Basis von 8-BitMikrocontrollern hin zu Produkten für IoT-Anwendungen, Wearables, 3D-Druck und Embedded Systems. Alle Arduino-Boards sind vollständig Open Source und ermöglichen es den Benutzern, sie unabhängig voneinander zu erstellen und auch an ihre jeweiligen Bedürfnisse anzupassen. Auch die Software ist Open Source und wächst durch die Beiträge von Anwendern weltweit. Arduino ist seitdem das beliebteste Prototyping-Tool für die Elektronik, das von einer breit gefächerten Nutzergemeinschaft – sowohl von Makern als auch von Ingenieuren und sogar großen Unternehmen – eingesetzt wird. Heute umfasst das Angebotsspektrum auf der Arduino-Website (https://store.arduino.cc/collections/boards) allein mehr als 34 unterschiedlich ausgestattete Arduino-Boards, die die Auswahl
nicht immer einfach machen. Dazu komme ich später in Kapitel 2, »Arduino-Hardware«, noch detaillierter. Der Arduino Uno Rev3 ist nach wie vor das beste Board, um mit Elektronik und der Mikrocontroller-Programmierung zu beginnen. Der Arduino Uno, wie ich ihn hier kurz nenne, ist ein robustes Board, das übersichtlich und mit weitgehend konventionellen Bauteilen aufgebaut ist. Es verzeiht in der Regel auch kleinere Missgeschicke, die bei Inbetriebnahme und Test schon einmal vorkommen können. Zudem ist der Arduino Uno das am häufigsten verwendete und am besten dokumentierte Board der gesamten Arduino-Familie. Ich komme gleich noch detaillierter darauf zurück. In diesem einleitenden Kapitel sind zwei Begriffe gefallen, die für das Gesamtverständnis der Arduino-Thematik wichtig sind und hier deshalb noch gesondert betrachtet werden: Open Source und Mikrocontroller.
1.2 Open Source: Die Lizenzen des Arduino-Projekts Als Open Source (wörtliche Übersetzung: offene Quelle) wurde ursprünglich Software bezeichnet, deren Quelltext offengelegt ist, der also unter bestimmten Bedingungen (Lizenzen) eingesehen, geändert, genutzt und weitergegeben werden kann. Als Open-Source-Hardware oder Open Hardware wird demgegenüber eine Hardware bezeichnet, die nach freien Bauplänen von Dritten hergestellt werden kann. Was heißt das für unseren Arduino? Für die Hardware ist das recht einfach geregelt. Die Referenzdesigns für die Arduino-Boards finden Sie auf den jeweiligen Produktseiten. Sie sind unter einer Creative Commons Attribution-ShareAlike License (CC-BY-SA) lizenziert, sodass Sie sie verwenden und an Ihre eigenen Bedürfnisse anpassen können, ohne um Erlaubnis bitten oder eine Gebühr zahlen zu müssen. Werden Anpassungen am Referenzdesign vorgenommen, dann müssen der Name des Lizenzgebers genannt und die Veränderungen unter der gleichen Lizenz weitergegeben werden. Kenntlich gemacht wird die Lizenz durch das folgende Symbol (siehe Abbildung 1.1).
Abbildung 1.1 Das Logo der Lizenz »CC-BY-SA«
Für den Arduino Uno sind die Dateien des Referenzdesigns auf der Webseite https://store.arduino.cc/arduino-uno-rev3 unter Documentation zu finden. Sie können dann verschiedene Dateien (Eagle, PDF, DXF) herunterladen. Die im Archiv UNO-TH_Rev3e-reference.zip vorhandenen Dateien UNO-TH_Rev3e-reference.sch und UNO-TH_Rev3e-reference.brd sind Eagle-CAD-Daten, während in der Datei ArduinoUno.dxf die Abmessungen des Arduino-Uno-Boards abgelegt sind. Mit diesen Dateien kann ein Arduino Uno nachgebaut werden. Die Datei UNOTH_Rev3e_sch.pdf enthält den Schaltplan, und das in der Datei A000066-datasheet.pdf mitgelieferte, 13-seitige Datenblatt bietet alle Informationen, die Sie zur Arbeit mit dem Arduino Uno Rev3 benötigen. Hinweis Arduino-Boards sind Open Hardware und können von Dritten nachgebaut werden. Es gibt also keinen Grund, nicht auch auf alternative Hardware zurückzugreifen. Ob die alternative Hardware dann auch 100-prozentig kompatibel zum originalen Arduino-Board ist, wird sich erst im Nachhinein feststellen lassen. Für Neueinsteiger ist der Start mit einem originalen Arduino empfehlenswert, um genau diese Unsicherheit von vornherein auszuschließen.
Die Diskussionen im Internet zum Thema Arduino-Clones sind vielfältig und nicht immer zielführend. Dass Arduino-Clones a priori eine schlechtere Qualität aufweisen, ist inzwischen eine
Legende. In den Anfangszeiten kann das aber durchaus so gewesen sein. Der aktuelle Preis eines Arduinos, der im Allgemeinen höher ist als der eines Klons, hilft bei der Finanzierung der folgenden Aktivitäten des Arduino-Projekts: Entwicklung neuer Open-Source-Hardware Hardware-Dokumentation CE- und FCC-Zertifizierung Qualitätskontrolle Management der Arduino-Community Veröffentlichung von Tutorials Spenden an andere Open-Source-Projekte Hosting und Wartung der Arduino-Website und des ArduinoForums mit Millionen von Nutzern Auf der Software-Seite ist die Lizenzierung nicht ganz so einfach. Die Arduino-Software unterliegt der GNU Public License (GPL) bzw. der Lesser GNU Public License (LGPL). Der Quellcode für die Arduino-Entwicklungsumgebung (Arduino IDE) wird von der GPL abgedeckt, die erfordert, dass alle Änderungen unter derselben Lizenz ausgeführt werden und der geänderte Quelltext offengelegt wird. Änderungen an der Arduino IDE werden Sie, zumindest vorerst, nicht vornehmen – Sie werden diese nur nutzen. In diesem Fall unterliegt die Nutzung keinen Einschränkungen. Wenn Sie den Arduino-Core und die Bibliotheken für die Firmware eines kommerziellen Produkts verwenden, müssen Sie den Quellcode für die Firmware nicht freigeben. Die LGPL erfordert
jedoch, dass Sie Objektdateien zur Verfügung stellen, die das erneute Verknüpfen der Firmware mit aktualisierten Versionen des Arduino-Kerns und der Bibliotheken ermöglichen. Alle Änderungen am Core und den Bibliotheken müssen unter der LGPL veröffentlicht werden (siehe »LGPL and Arduino in Commercial Products« unter https://forum.arduino.cc/index.php? topic=240434.0). Schwieriger wird es dann bei Bibliotheken (Librarys), die nicht von Arduino selbst in das Arduino-Gesamtpaket integriert wurden. So sind derzeit (Stand: September 2022) in der Arduino Library List (https://www.arduinolibraries.info) Arduino-Librarys mit den folgenden Lizenzen zu finden:
0BSD (2)
GPL 3.0 only (1)
AGPL 3.0 (29)
GPL 3.0 or later (2)
Apache 2.0 (219)
ISC (4)
Artistic 2.0 (6)
LGPL 2.1 (166)
BSD 2 Clause (27)
LGPL 3.0 (202)
BSD 3 Clause (138)
MIT (2095)
BSD 3 Clause Clear (3)
MPL 2.0 (11)
BSL 1.0 (2)
MS PL (1)
CC BY SA 3.0 (1)
NOASSERTION (549)
CC BY SA 4.0 (5)
OSL 3.0 (1)
CC0 1.0 (20)
Unlicense (30)
GPL 2.0 (74)
WTFPL (3)
GPL 3.0 (547) NOASSERTION bedeutet, dass keine gültigen Lizenzangaben gefunden wurden. Unlicense und WTFPL sind praktisch PublicDomain-Lizenzen und stellen keine weiteren Anforderungen. Erklärungen zu den einzelnen Lizenzen finden Sie unter: https://opensource.org/licenses/alphabetical
1.3 Maker und die Arduino-Community In diesem Abschnitt erläutere ich Ihnen den Begriff des Makers und gehe auf die Arduino-Community ein. Wenn Sie sich mit dem Arduino beschäftigen, werden Sie rasch von den Vorteilen profitieren, die Ihnen die Maker-Bewegung und die Community bieten. Lernen Sie sie also kennen, und engagieren Sie sich vielleicht selbst dort. Gemäß der Definition laut Wikipedia.de bezeichnet der Begriff Maker eine Subkultur, die man auch als »Do-it-yourself-Kultur unter Nutzung aktueller Technik« beschreiben kann. Es gibt übrigens auch eine alte Definition des Bastlers von Erich Kästner: »Ein Bastler ist jemand, der mit völlig unzureichenden Mitteln völlig überflüssige Dinge herstellt.« Davon sind die Maker jedoch meilenweit entfernt: Maker sind die Entrepreneure der Stunde. Den Begriff des Bastlers werde ich deshalb hier nicht verwenden. Die Maker-Bewegung bewegt sich vom ursprünglichen »Do it yourself« (DIY, dt. »Mach es selbst«) hin zum »Do it together« (DIT, dt. »Macht es gemeinsam«) als Modell für Gegenwart und Zukunft. Voraussetzung für die erfolgreiche Umsetzung von Projekten ist der Kontakt zu Gleichgesinnten. Zusätzliche Intelligenz und Erfahrung (auch aus anderen Wissensgebieten) sind herzlich willkommen. Selbstvertrauen, Neugier, die Bereitschaft, sich einzubringen und im Team ein Projekt voranzubringen – das sind unabdingbare Voraussetzungen für einen Maker. Mit diesen Charakteristika und
einigen technologischen Voraussetzungen sind die Triebkräfte und Eigenschaften der Maker-Bewegung bereits umrissen. Die Maker-Bewegung profitiert außer von den geschilderten Fähigkeiten von ihrer heterogenen Zusammensetzung und den verfügbaren Tools zur Umsetzung ihrer Produktideen. Beide Einflussfaktoren bilden gleichsam die Basis für unkonventionelle Konzepte und Produkte. Überzeugen Sie sich auf einer der zahlreichen Maker-Faires (https://maker-faire.de/) von den interessanten Lösungsansätzen, die die Maker vorstellen. Im Beitrag »Maker – Startups – Unternehmen«[ 1 ] habe ich das Zusammenspiel der verschiedenen Beteiligten beschrieben. Bei den zur Verfügung stehenden Tools können wir unterschiedliche Einflussebenen erkennen, die in starkem Maße durch die Open-Source-Aspekte im weiteren Sinne geprägt werden. Die Offenlegung der Quellcodes von Software begann in der Hackerund Hobbyisten-Bewegung und ist zentraler Bestandteil der OpenSource-Initiative. Neue Projekte lassen sich auf einer breiten Palette von vorhandenen Software-Lösungen aufsetzen, sodass der Projektumfang bei sinkendem Entwicklungsrisiko wesentlich erweitert werden kann. Für Maker steht ein umfangreiches Portfolio an Software zur Verfügung. Neben den klassischen Tools für die Bearbeitung von Texten, Bildern, Videos und Musik stehen die Design-Tools im Vordergrund. Für die Software-Entwicklung stehen leistungsfähige Compiler und Skript-Interpreter ebenfalls als Open Source zur Verfügung. Zur Software-Entwicklung für die bei Makern beliebten ArduinoBoards wird die Arduino IDE eingesetzt, die die Programmierung
der Arduino-Boards in C++ ermöglicht (https://www.arduino.cc). Eine weitere Klasse von Software-Tools sind die CAD- und CAMTools, die den Designprozess für Leiterplatten und mechanische Konstruktionen unterstützen. Die FH Potsdam initiierte das PCBDesigntool Fritzing (https://fritzing.org/), das alle notwendigen Schritte unterstützt – vom Zeichnen von Schaltplänen über das Visualisieren eines Breadboards (Steckbretts) bis zur Erstellung der Fertigungsdaten für die Leiterplatte. In der FritzingFab kann dann der Prototyp auch gleich bestellt und in Deutschland innerhalb Tagesfrist auch geliefert werden. Mechanische Konstruktionen lassen sich mithilfe von FreeCAD (https://www.freecadweb.org/), OpenSCAD (http://www.openscad.org/) und anderen Tools erstellen und direkt in die noch zu betrachtenden Manufacturing-Lösungen überführen. Der Grundgedanke der Open-Source-Software-Entwicklung wurde auch auf die Hardware übertragen: Die Hardware-Grundlagen, wie Layoutdaten für Leiterplatten, Konstruktionsunterlagen oder 3Ddruckbare CAD-Dateien, werden offengelegt und zur weiteren Verwendung zur Verfügung gestellt. So können beispielsweise über die Plattform Thingiverse.com (https://www.thingiverse.com) 3DDrucker, Laser-Cutter, CNC-Fräsen und andere Maschinen mit den dort zur Verfügung gestellten Dateien zur Bearbeitung von Werkstücken benutzt werden. Besonders bekannt wurde die Seite Thingiverse.com durch Web-Communitys, die sich um die 3DDrucker-Projekte RepRap und MakerBot versammeln. Mit den geschilderten Werkzeugen stehen auch dem Maker heute Hilfsmittel zur Verfügung, mit denen er eine Idee recht schnell auf ihre Umsetzbarkeit hin überprüfen kann. Dieser als Proof of Concept bezeichnete Entwicklungsschritt wird nicht nur von den Makern, sondern auch im industriellen Umfeld genutzt. Hier spielen die
erreichbare Einsparung von Entwicklungszeit (Time-to-Market) und die Reduzierung des Entwicklungsrisikos die entscheidende Rolle. Die Maker-Bewegung ist gemäß diesen Schilderungen also eher ein interdisziplinärer Zusammenschluss Gleichgesinnter, während die Arduino-Community diesen Zusammenschluss auf Arduinorelevante Themen bezieht. Die Grundsätze sind dabei aber vergleichbar. Auf der Arduino-Website https://www.arduino.cc/ gibt es Foren und Blogs, die dem Erfahrungsaustausch dienen und bei Problemen Hilfestellung leisten. Im Arduino Blog werden die Informationen nach bestimmten Themen zusammengefasst. Durch Auswahl von BOARDS, CATEGORIES oder ARCHIVE bündeln Sie die Informationen. Wenn Sie unter BOARDS den Arduino Uno auswählen, bekommen Sie die spezifischen Informationen zusammengestellt angezeigt. Die Arduino-Website ist ein guter Startpunkt, um mit der ArduinoCommunity in Kontakt zu treten. Auch in den sozialen Medien bildet sich die Arduino-Community ab. Sie finden verschiedene Arduino-Gruppen auf Facebook und eine auf MeWe.
1.4 Arduino Uno Rev3 – der Standard Arduino Uno ist das Arduino-Board, dessen Kern der von Atmel entwickelte Mikrocontroller ATmega328P ist. Auch nach der Übernahme von Atmel durch Microchip wird dieser verbreitete Controller unverändert gefertigt. Auf dem Board ist alles vorhanden, was zur Unterstützung des Mikrocontrollers benötigt wird. Abbildung 1.2 zeigt einen Arduino Uno Rev3. Die spezielle Form des Arduino Uno Rev3, der Arduino-UnoFormfaktor, ist praktisch standardisiert, sodass andere Boards, die sogenannten Arduino-Shields, egal von welchem Hersteller sie stammen, über die Arduino-Buchsenleisten kontaktiert werden können.
Abbildung 1.2 Arduino Uno Rev3
1.4.1 Ein- und Ausgangspins
Wie Sie in Abbildung 1.2 sehen können, verfügt der Arduino Uno über 20 digitale Eingangs- bzw. Ausgangspins, sechs analoge Eingänge, einen 16-MHz-Quarz, einen USB-Anschluss, eine Netzbuchse, einen ICSP-Header für das In-Circuit Serial Programming (ICSP) und eine Reset-Taste. ICSP ist eine der verschiedenen Methoden zur Programmierung von Arduino-Boards. Normalerweise wird ein Arduino-BootloaderProgramm zum Programmieren eines Arduinos verwendet, der einen seriellen Programm-Upload ermöglicht. Wenn der Bootloader jedoch fehlt oder beschädigt ist, kann stattdessen ICSP verwendet werden. Die nach außen hin verfügbaren Anschlüsse sind den beiden Buchsenleisten (Header) zugeordnet 1. An der linken Seite des Arduino Uno sind oben eine USB-Buchse vom Typ B (USB Jack) 2 und darunter die Buchse zur Spannungsversorgung (Power Jack) 3 angeordnet. Die Pinbelegung der nach außen führenden Buchsenleisten entnehmen Sie Abbildung 1.3. Deutlich zu sehen ist, dass jedem Anschluss mehrere Funktionen zugeordnet sind. Welche Funktion wirksam wird, bestimmt die vor dem Programmstart vorzunehmende Initialisierung.
Abbildung 1.3 Pinbelegung beim Arduino Uno Rev3
Von den insgesamt 20 digitalen I/O-Pins können sechs als PWMAusgang und sechs als analoger Eingang fungieren. PWM bezeichnet die Pulsweitenmodulation (Pulse Width Modulation), bei der die Information im Tastverhältnis (Duty Cycle) gemäß Abbildung 1.4 liegt.
Abbildung 1.4 PWM
PWM-Signale lassen sich sehr gut für die Helligkeitssteuerung von LEDs oder für die Steuerung der Drehzahl von DC-Motoren verwenden. Mit analogWrite(value) steht in Abbildung 1.4 auch bereits die zugehörige Anweisung zur Ausgabe – was es damit genau auf sich hat, erfahren Sie in Abschnitt 4.6.2.
1.4.2 Serielle Schnittstellen Die Pinbelegung zeigt drei serielle Schnittstellen, die für den Einsatz des Arduino sehr wichtig sind: Pins
Bedeutung
TX, RX
Serielle Schnittstelle für Programm-Upload und Kommunikation (UART)
Pins
Bedeutung
SCL, SDA
I2C-Bus
SCK, MISO, MOSI
SPI-Bus
Tabelle 1.1 Arduino Uno – serielle Schnittstellen
Mit diesen Kommunikationsschnittstellen werden Sie immer wieder in Kontakt kommen, denn neben den analogen und digitalen Ein-/Ausgängen stellen diese Schnittstellen Verbindungen zu anderen Komponenten oder Controllern her und ermöglichen erst den für Mikrocontroller-Anwendungen so wichtigen Datenaustausch.
1.4.3 Spannungsversorgung Den Arduino Uno können Sie auf unterschiedlichen Wegen mit Spannung versorgen. Die Spannungsversorgung kann am einfachsten über den USB-Anschluss erfolgen, der ohnehin für den Programm-Upload benötigt wird. Bedenken Sie allerdings, dass die USB-2.0-Ports, die heute noch in vielen PCs verbaut werden, gemäß Spezifikation nur einen Strom von maximal 500 mA liefern. Der USB-Anschluss kann also den Strombedarf in vielen Fällen nicht decken. Spannungsversorgung über USB Die Spannungsversorgung über den USB-Anschluss eines Rechners kann nicht immer zuverlässig die benötigte Spannung bereitstellen. Zum Ausprobieren ist es ein guter Anfang, aber
wenn Sie den Arduino mit Zusatzschaltungen erweitern, brauchen Sie ein richtiges Netzteil.
Bei der Spannungsversorgung über den Power Jack (Hohlstecker) sollte das eingesetzte Steckernetzteil eine Gleichspannung zwischen 7 und 12 V liefern. Die Stromaufnahme des Arduino Uno hängt stark von den angeschlossenen Lasten ab und kann ohne diese nicht zuverlässig angegeben werden. Ein Steckernetzteil, das in der Lage ist, einen Strom von 1 A zu liefern, ist aber erst einmal ein sicherer Anfang. Reichelt bietet ein solches Netzteil unter der Bezeichnung HNP 12-120L6 für unter 10 € an (https://cdn-reichelt.de/documents/datenblatt/D400/HNP12.pdf). Die Spannungszuführung kann aber auch über den Anschluss VIN erfolgen. Wenn Sie den Arduino Uno über ein USB-Kabel mit einem Computer verbinden und die Spannungsversorgung über ein Netzteil oder einen Akku vornehmen, dann sind Sie bereits für das Abenteuer Arduino gerüstet.
1.4.4 Mikrocontroller ATmega328P Der Mikrocontroller ATmega328P ist in einem klassischen DILGehäuse (Dual-in-Line) auf dem Board gesockelt und kann daher ersetzt werden, wenn wirklich einmal alles schiefgegangen ist. Für einen Austausch 1:1 müssen Sie einen ATmega328P mit programmiertem Bootloader[ 2 ] verwenden. Den bekommen Sie (eigentlich) für 6,10 € bei Reichelt. Der ATmega328P ohne Bootloader[ 3 ] kostet bei Reichelt nur 3,45 €.
In der aktuellen Situation müssen Sie allerdings unerfreuliche Lieferfristen berücksichtigen. Der ATmega328P mit programmiertem Bootloader war bei Reichelt nicht lieferbar, beim ATmega328P ohne Bootloader wurde im September 2022 als voraussichtlicher Liefertermin der 11.01.2023 angegeben. Hoffen wir, dass sich Versorgungslage bessert, bis Sie dieses Buch in den Händen halten. Wie Sie später noch sehen werden, gibt es auch einen Arduino Uno mit einem ATmega328P im SMD-Gehäuse. Da ist ein Wechsel aber nicht so einfach.
1.4.5 Warum eigentlich die Bezeichnung »Uno«? Nachdem Sie einen ersten Eindruck von der Hardware des Arduino Uno gewinnen konnten und auch schon angedeutet wurde, dass es weitere Arduinos gibt, noch ein Wort zur Namensgebung. Vor dem Arduino Uno gab es bereits andere Arduinos. Mit dem Uno (»uno« bedeutet auf Italienisch »eins«) wurde die Bereitstellung der Arduino Entwicklungsumgebung 1.0 (Arduino IDE 1.0) markiert. Arduino Uno und die Version 1.0 der Arduino IDE sind also die Referenzversionen von Arduino, die im Laufe der Jahre zu neueren Versionen weiterentwickelt wurden. Heute existiert eine breite Palette von Arduino-Boards, von denen ich Ihnen wegen ihrer unterschiedlichen Ausstattungsmerkmale und Performance noch einige vorstellen werde. Die jetzt als Legacy Arduino bezeichnete Arduino IDE lag im September 2022 in Version 1.8.19 für alle gängigen Betriebssysteme vor.
Der Arduino Uno bleibt damit immer noch die Hardware-Basis des Arduino-Universums und ist mit dem ATmega328P eine ausgezeichnete Ausgangsbasis für die Umsetzung von Programmideen in laufende Mikrocontroller-Anwendungen. Wenn Sie bei der Arbeit mit dem Arduino Uno eine gewisse Sicherheit gewonnen haben, dann ist der Schritt hin zu komplexeren Arduinos wesentlich einfacher. Keine Angst beim Umgang mit dem Arduino Uno! Der Arduino Uno ist ein robustes Board, weshalb Sie keine Angst beim Ausprobieren von Neuem und bislang Unbekanntem aufkommen lassen sollten.
1.5 Details zum Mikrocontroller Um den Arduino besser verstehen zu können, will ich Ihnen einige Grundlagen zum Mikrocontroller allgemein erläutern. Wenn Ihnen das an dieser Stelle zu theoretisch erscheint, dann können Sie diesen Abschnitt auch überblättern – Sie können auch wunderbar mit dem Arduino arbeiten, ohne diese fortgeschrittenen Informationen zu kennen. Vielleicht kommen Sie später doch noch hierher zurück, um das eine oder andere zu vertiefen. Den Arduino Uno hatte ich als Hardware-Basis des ArduinoUniversums bezeichnet. Die folgenden Ausführungen beziehen sich deshalb auch auf den im Arduino Uno eingesetzten Mikrocontroller ATmega328P von Atmel bzw. heute Microchip. Ich werde in späteren Kapiteln noch Arduino-kompatible Mikrocontroller auf der Basis anderer Architekturen vorstellen – die grundlegenden Aussagen gelten aber unabhängig davon.
1.5.1 Mikrocontroller-Kern Abbildung 1.5 zeigt das Blockdiagramm des ATmega328P, entnommen aus dem immerhin 662 Seiten umfassenden Datenblatt der Reihe ATmega48/88/168/328.
Abbildung 1.5 ATmega328P-Blockdiagramm (Quelle: ATmega328 Data Sheet)
Das ATmega328P Data Sheet können Sie von der URL http://ww1.microchip.com/downloads/en/DeviceDoc/ATmega48A-PA88A-PA-168A-PA-328-P-DS-DS40002061A.pdf herunterladen. In der oberen Hälfte des Blockdiagramms sind die eigentliche AVRCPU (Central Processing Unit) sowie Programm- und Datenspeicher angeordnet. Die CPU ist das zentrale Rechen- und Steuerelement eines jeden Mikrocontrollers oder Rechners allgemein. Der Programmspeicher ist als Flash-Memory ausgebildet und kann garantiert bis zu 100.000-mal programmiert werden. FlashMemory ist eine Variante des ROM (Read-Only Memory, dt. NurLese-Speicher), eines nichtflüchtigen Speichers, dessen Inhalt nach der Programmierung nur noch gelesen werden kann.
Getrennte Programm- und Datenspeicher kennzeichnen die sogenannte Harvard-Architektur, die den gleichzeitigen Zugriff auf beide Speicher erlaubt. Des Weiteren besteht die Möglichkeit, die Speicher mit unterschiedlicher Bitbreite auszulegen. Beim ATmega328P sind die Instruktionen 16 und 32 Bit breit, weshalb der Programmspeicher mit einer Breite von 16 Bit angelegt wurde. Mit 16 K (16.384) Zellen Programmspeicher umfasst er dann 32 KByte Flash-Memory. Für die Assembler-Instruktion ADD (»Addiere zwei Registerinhalte«) ist im Folgenden die Befehlsdecodierung im Programmspeicher beispielhaft gezeigt. Die Inhalte der beiden Register r und d werden in einem Zyklus addiert, und das Ergebnis wird im Register d abgelegt. Mit den Bits rrrrr und ddddd wird jeweils eines der Register 0 bis 31 adressiert. 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 Bit 0
0
0
0
1
1
r
d d d d d r
r
r
r
ADD
Der Datenspeicher umfasst eine Breite von 8 Bit. Es kann also genau ein Byte pro Speicherplatz abgelegt werden. Für das Datenbyte 0xA5 (=10100101) sehen Sie das hier: 7 6 5 4 3 2 1 0 Bit 1 0 1 0 0 1 0 1 0xA5 Hinweis In der Folge werden Zahlen häufig als Hexadezimalzahlen in der Form 0xA5 (= 165 dezimal) angegeben. Wenn Ihnen diese Art der
Darstellung fremd ist, dann finden Sie bei den Materialien zum Buch eine hilfreiche Übersicht.
Der als statisches RAM des Speichers (Random Access Memory, dt. Speicher mit wahlfreiem Zugriff zum Lesen und Schreiben) ausgelegte Datenspeicher umfasst das Register File, Ein-/Ausgabe-Register (I/ORegister) und das interne SRAM zur Datenspeicherung mit der in Tabelle 1.2 gezeigten Aufteilung des Speichers (Memory Map). Speicher
Adressbereich
32 Register
0x0000–0x001F
64 I/O-Register
0x0020–0x005F
160 Extended I/O-Register
0x0060–0x00FF
Internes SRAM (2048 × 8 Bit) 0x0100–0x08FF Tabelle 1.2 Speicheraufteilung des SRAM beim ATmega328P
Aus Gründen der Softwaresicherheit ist der Programmspeicher in zwei Teile aufgeteilt. Die Boot Loader Section beinhaltet den sogenannten Bootloader, der den Programm-Upload (das ist das Programmieren des Flash-Memorys über die serielle Schnittstelle) ermöglicht. Die Application Program Section, der eigentliche Programmspeicher, enthält dann das über den Bootloader hochgeladene Programm. Das ist weniger komplex, als es hier vorerst erscheinen mag. Dennoch ist es wichtig, dass Sie die beiden Speicherbereiche und deren unterschiedliche Funktion verstanden haben. Beim Arduino Uno ist der eingesetzte ATmega328P bereits mit dem Bootloader ausgestattet. Sollten Sie den ATmega328P mal ersetzen
müssen, dann können Sie beispielsweise einen mit dem Bootloader vorprogrammierten ATmega328P von einem Distributor beziehen oder Sie programmieren den Bootloader selbst in einen »nackten« ATmega328P. Hinweise, wie Sie hier vorgehen müssen, können Sie unter https://netzmafia.ee.hm.edu/skripten/hardware/Arduino/Bootloader _Flashen/index.html nachlesen. Eine gewisse Erfahrung beim Umgang mit einem Arduino ist hierzu aber Voraussetzung, weshalb ich zumindest anfangs die wenigen Euro für den bereits programmierten Bootloader ausgeben würde. Zurück zum ATmega328P-Blockdiagramm: Zunächst möchte ich Ihnen die Funktion der AVR-CPU näher erläutern. Abbildung 1.6 zeigt die Architektur des AVR-RISC-Mikrocontrollers wiederum anhand eines Blockdiagramms. Die Hauptfunktion der AVR-CPU besteht darin, die korrekte Programmausführung sicherzustellen. Die CPU muss daher in der Lage sein, auf Programm- und Datenspeicher zuzugreifen, Berechnungen durchzuführen, Peripheriegeräte zu steuern und Interrupts (das sind Unterbrechungen des laufenden Programms) zu bearbeiten. Anweisungen im Programmspeicher führt die AVR-CPU im sogenannten Single Level Pipelining aus – d. h., während eine Anweisung ausgeführt wird, wird die nächste Anweisung bereits aus dem Programmspeicher abgerufen. Dieses Konzept ermöglicht die Ausführung von Anweisungen in jedem Taktzyklus.
Abbildung 1.6 AVR-Architektur (Quelle: ATmega328P Data Sheet)
Das Pipelining ist heute in allen modernen Prozessoren meist sogar mehrstufig vorzufinden (siehe Abbildung 1.7).
Abbildung 1.7 Das Prinzip des Pipelinings (Quelle: https://de.wikipedia.org/wiki/ Pipeline_(Prozessor))
Dies ermöglicht den Betrieb der ALU (Arithmetic Logic Unit) in einem Taktzyklus der CPU (siehe Abbildung 1.8). Bei einer typischen ALU-Operation werden zwei Operanden aus dem Register File
geladen, die Operation ausgeführt und das Ergebnis ins Register File zurückgeschrieben. Am Beispiel der ADD-Instruktion hatte ich die Adressierung der Register bereits gezeigt.
Abbildung 1.8 Single-Cycle-ALU-Operation
Die ALU unterstützt arithmetische und logische Operationen zwischen Registern oder zwischen einer Konstanten und einem Register. Einzelregisteroperationen können auch in der ALU ausgeführt werden. Nach einer arithmetischen Operation ist das Statusregister aktualisiert und beinhaltet Informationen über das Ergebnis der Operation. Bedingte und unbedingte Sprung- und Aufrufbefehle steuern den Programmablauf. Diese Befehle sind in der Lage, direkt auf den ganzen Adressraum zuzugreifen. Während Interrupts und Unterprogrammaufrufen wird die jeweilige Rücksprungadresse auf dem Stack gespeichert. Der Stack ist ein Stapelspeicher nach dem FILO-Prinzip (First In Last Out) – d. h., der zuerst abgelegte Inhalt steht erst nach dem Zurücklesen aller nachträglich abgelegten Inhalte wieder zur Verfügung. Daher auch der Name Stapel.
Der Stack wird im statischen RAM (SRAM) eingerichtet und ist folglich nur durch die Gesamtgröße des SRAM und dessen Verwendung durch das Programm begrenzt. Der I/O-Speicherbereich enthält 64 Adressen für CPUPeripheriefunktionen wie Steuerregister, SPI und andere I/OFunktionen. Der ATmega328P verfügt darüber hinaus noch über 160 Extended I/O-Register.
1.5.2 Mikrocontroller-Peripherie Wie aus Abbildung 1.5 und Abbildung 1.6 bereits ersichtlich war, beinhaltet der ATmega328P zahlreiche Peripheriefunktionen, die die Leistungsfähigkeit und Flexibilität dieses Mikrocontrollers gleichermaßen bestimmen. Das in der Folge vorgestellte Interrupt-System ist spezifisch für die AVR-Mikrocontroller. Die anderen Module hingegen haben funktional durchaus eher allgemeingültigen Charakter. Ihre Implementierung in anderen Mikrocontrollern wird sich natürlich unterscheiden. Interrupt-System
Der ATmega328P kann eine Vielzahl unterschiedlicher Interrupts verarbeiten. Interrupts sind Unterbrechungen des laufenden Programms und dienen der speziellen Behandlung von Ereignissen (Events), die einer unmittelbaren Bearbeitung bedürfen. Diese Interrupts sowie der Reset haben einen sogenannten Interruptvektor im Programmspeicher.
Jeder Interrupt kann individuell freigegeben werden. Die Interruptvektoren sind in Form einer Tabelle am unteren Ende des Programmspeichers angeordnet (siehe Tabelle 1.3). Die Priorität des jeweiligen Interrupts ist mit der Position in dieser Tabelle verknüpft. Je niedriger die Adresse des Interruptvektors ist, desto höher ist die Priorität. Reset hat also die höchste Priorität. Wird ein Interrupt angefordert (Interrupt Request), dann wird das Global Interrupt Enable Bit zurückgesetzt. Alle (weiteren) Interrupts sind damit gesperrt (disabled). Das Anwendungsprogramm kann diese Sperre aufheben. Automatisch aufgehoben wird diese Sperre beim Verlassen der betreffenden Interrupt-Serviceroutine (ISR) durch ein Return from Interrupt (reti), wodurch ein Rücksprung ins Hauptprogramm erfolgt. Es gibt grundsätzlich zwei unterschiedliche Typen von Interrupts. Der erste Typ wird durch ein Ereignis getriggert, das das betreffende Interrupt-Flag setzt. Der Programmzähler wird mit der Adresse des betreffenden Interruptvektors geladen, und die zugehörige Interrupt-Serviceroutine wird abgearbeitet. Tritt eine InterruptAnforderung auf, wenn der betreffende Interrupt nicht freigegeben ist, dann wird diese Interrupt-Anforderung gespeichert und erst nach Freigabe des Interrupts bearbeitet. Das gleiche Verhalten gilt auch für den globalen Interrupt. Der zweite Typ triggert nur so lange, wie die Bedingung für den Interrupt existiert. Wird eine solche Bedingung vor der InterruptFreigabe beendet, dann geht dieser Interrupt verloren. Wenn der ATmega328P eine ISR beendet hat, dann wird die Programmabarbeitung nach der Unterbrechungsstelle fortgesetzt. Das Statusregister wird nicht automatisch gesichert, sodass dieser Vorgang manuell vorgenommen werden muss.
Vektor Programmadresse Interrupt Interrupt-Definition Nr. 1
0x0000
RESET
External Pin, Power-on Reset, Brown-out Reset and Watchdog System Reset
2
0x0002
INT0
External Interupt 0
3
0x0004
INT1
External Interupt 1
4
0x0006
PCINT0
Pin Change Interrupt 0
5
0x0008
PCINT1
Pin Change Interrupt 1
6
0x000A
PCINT2
Pin Change Interrupt 2
7
0x000C
WDT
Watchdog Interupt
8
0x000E
TIMER2
Timer2 CompareA Interrupt
COMPA
9 10
0x0010
0x0012
COMPB
Timer2 CompareB Interrupt
TIMER2
Timer2 Overflow Interrupt
TIMER2
OVF
11
0x0014
TIMER1
Timer1 Capture Interrupt
CAPT
12
0x0016
TIMER1 COMPA
13
0x0018
TIMER1 COMPB
Timer1 CompareA Interrupt Timer1 CompareB Interrupt
Vektor Programmadresse Interrupt Interrupt-Definition Nr. 14
0x001A
TIMER1
Timer1 Overflow Interrupt
OVF
15
0x001C
TIMER0 COMPA
16 17
0x001E
0x0020
Timer0 CompareA Interrupt
COMPB
Timer0 CompareB Interrupt
TIMER0
Timer0 Overflow Interrupt
TIMER0
OVF
18
0x0022
SPI, STC
SPI Serial Transfer Complete
19
0x0024
USART, RX
USART Rx Complete
20
0x0026
USART, UDRE
USART, Data Register Empty
21
0x0028
USART, TX
USART Tx Complete
22
0x002A
ADC
ADC Conversion Complete
23
0x002C
EE READY
EEPROM Ready
24
0x002E
ANALOG
Analog Comparator
COMP
25
0x0030
TWI
I2C Bus Interface
26
0x0032
SPM READY
Store Program Memory Ready
Tabelle 1.3 ATmega328P-Interruptvektortabelle
Aus den Blockdiagrammen (siehe Abbildung 1.5 und Abbildung 1.6) und der Interruptvektortabelle (siehe Tabelle 1.3) können Sie entnehmen, welche Ereignisse einen Interrupt auslösen können. Die Anschlussbelegungen (engl. Pinout) haben beim Arduino und beim ATmega328P leider andere Bezeichnungen. Abbildung 1.9 zeigt die Zuordnung dieser Bezeichnungen zu den Anschlüssen (I/O-Pins) des ATmega328P. Interrupts anfordernde Ereignisse (in abnehmender Priorität) sind: Reset – ausgelöst über den Reset-Pin (/RESET), ein Reset beim Zuschalten der Betriebsspannung (Power-on Reset) oder beim Unterschreiten der Betriebsspannung eines bestimmten Schwellenwertes (Brown-out Reset) bzw. ausgelöst durch den Watchdog Timer. External Interrupt 0/1 – ausgelöst durch eine Pegeländerung an einem der digitalen Eingänge INT0 bzw. INT1. Pin Change Interrupt 0/1/2 – ausgelöst durch eine Pegeländerung an einem der digitalen Eingänge PCINT23 bis PCINT0. Watchdog Interrupt – ausgelöst durch einen Überlauf des Watchdog Timers. Dieser Überlauf signalisiert einen Fehlerzustand im Programmablauf, denn im Normalfall wird der Watchdog Timer innerhalb seiner einstellbaren Timer-Periode zyklisch zurückgesetzt, was einen solchen Überlauf verhindert. Timer2/Timer1/Timer0 Interrupts – ausgelöst durch verschiedene Timer-Ereignisse wie Vergleiche mit bestimmten Werten oder Überlauf.
SPI Serial Complete Interrupt – ausgelöst durch eine abgeschlossene Datenübertragung über SPI (SPI-Transfer). Das Serial Peripheral Interface (SPI) erlaubt eine synchrone HighSpeed-Datenübertragung zwischen einem ATmega328P und peripheren Komponenten oder zwischen verschiedenen Mikrocontrollern. USART Interrupts – ausgelöst durch verschiedene Zustände des seriellen Interface. USART bezeichnet ein komplexes Modul für die synchrone und asynchrone serielle Kommunikation (Universal Synchronous and Asynchronous Serial Receiver and Transmitter). Dieses Modul ist vor allem die Basis für die eingesetzte serielle Schnittstelle (RS232). ADC Conversion Complete Interrupt – ausgelöst durch das Ende einer Analog/Digital-Umsetzung (ADC). EEPROM Ready Interrupt – ausgelöst durch das Ende eines Schreibvorgangs auf den internen EEPROM. Analog Comparator Interrupt – ausgelöst durch einen Vergleich des Analog-Comparators. I2C-Bus Interrupt – ausgelöst durch verschiedene Zustände der I2C-Kommunikation. Store Program Memory Ready Interrupt – ausgelöst durch das Ende eines Schreibvorgangs in den Programmspeicher.
Abbildung 1.9 Anschlussbezeichnungen beim Arduino und ATmega328P
Nicht alle hier vorgestellten Interrupts sind für die Arbeit mit dem Arduino wichtig, einige können die Funktionalität jedoch erweitern. Ich werde bei der Programmierung des Arduino noch darauf zurückkommen. I/O-Ports
Neben den Anschlüssen für verschiedene Spannungen (VCC, AVCC und AREF) und Masse (GND) ist eine Vielzahl von I/O-Ports am Mikrocontroller außen verfügbar (siehe Abbildung 1.9). VCC bezeichnet die Versorgungsspannung für die digitalen Schaltungsteile des Mikrocontrollers, AVCC die Versorgungsspannung der analogen. AREF bezeichnet die analoge Referenzspannung für den AD-Umsetzer, und GND steht für das Bezugspotenzial – die Masse. Über diese I/O-Ports können Sie digitale Signale ein- und ausgeben und teilweise sogar analoge Spannungswerte erfassen. Abbildung 1.10 zeigt den recht komplexen Aufbau eines digitalen I/O-Ports im Blockschaltbild. Die Steuerung der Funktionen des I/O-Ports erfolgt durch eine umfangreiche interne Logik.
Abbildung 1.10 Digitaler I/O-Port (Quelle: ATmega328P Data Sheet)
Ob ein Pin als digitaler Eingang oder Ausgang arbeitet, entscheidet das Data Direction Register DDxn 1. Das Zeichen x bezeichnet den betreffenden Port (A bis D) und das Zeichen n die betreffende Pinnummer (0 bis 7). Das Ausgangssignal ist durch das PORTxn Latch 2 zwischengespeichert (gepuffert). Die Zeichen x und n haben die gleiche Bedeutung wie eben. Mit diesen beiden Latches können vier verschiedene Zustände des digitalen I/O-Ports eingestellt werden (siehe Tabelle 1.4). DDxn PORTxn I/O
Pull- Kommentar up
DDxn PORTxn I/O
Pull- Kommentar up
0
0
Eingang
Nein Tri-State (hochohmiger Ausgang)
0
1
Eingang
Ja
1
0
Ausgang Nein Ausgang Low
1
1
Ausgang Nein Ausgang High
Der Pin liefert Strom, wenn der Widerstand gegen GND liegt.
Tabelle 1.4 Logische Zustände am I/O-Port
Ist der betreffende Pin als Eingang konfiguriert (DDxn = 0), dann entscheidet der Zustand von PORTxn, ob der interne Pull-upWiderstand ein- oder ausgeschaltet ist. Der Wert des Pull-upWiderstands kann dabei zwischen 20 und 50 kΩ variieren. Hinweis Als Pull-up-Widerstand bezeichnet man einen vom Pin gegen die Betriebsspannung geschalteten Widerstand (pull up = hochziehen). Ein Pull-down-Widerstand wird hingegen vom Pin nach Masse geschaltet (pull down = herunterziehen).
Beide Latches können beschrieben (gesetzt oder zurückgesetzt) werden, und ihr Status kann zurückgelesen werden. Der I/O-Pin kann auch direkt (ohne Latch) gelesen werden. Die verschiedenen Zustände sind deshalb wichtig, da Sie später bei der Konfiguration von I/O-Pins genau diese Zustände einstellen werden. Jeder Ausgang kann einen Strom von 20 mA liefern. Sie können also eine LED (über einen Vorwiderstand) direkt von einem I/O-Pin
ansteuern. Serial Peripheral Interface (SPI)
Das Serial Peripheral Interface (SPI) erlaubt eine synchrone serielle Kommunikation mit hoher Geschwindigkeit zwischen dem Mikrocontroller und den peripheren Komponenten. Diese peripheren Komponenten können beispielsweise Speicher, Displays oder ein anderer Mikrocontroller sein. Der ATmega328P weist die folgenden Features auf: Full-Duplex, Drei-Draht-Interface Master oder Slave Mode LSB-First- oder MSB-First-Übertragung sieben programmierbare Bitraten End of Transmission Interrupt Write Collision Flag Protection Wakeup vom Idle Mode Double Speed (CK/2) Master SPI Mode Die beiden 8-Bit-Schieberegister im Master und im Slave können als gemeinsames 16-Bit-Schieberegister aufgefasst werden. Wenn Daten vom Master zum Slave geschoben werden, dann werden gleichzeitig Daten vom Slave zum Master transportiert. Abbildung 1.11 zeigt den Datenfluss beim seriellen Datentransfer.
Abbildung 1.11 Datenfluss beim seriellen Datentransfer (Quelle: ATmega328P Data Sheet)
Um einen Datenaustausch über SPI vornehmen zu können, werden typischerweise vier Leitungen benötigt: MOSI – Master Out, Slave In MISO – Master In, Slave Out SCK – Serial Clock /SS – Slave Select Um einen SPI-Baustein zu adressieren, müssen Sie dessen /SS-Pin auf Low setzen. Synchron zum Takt SCK werden die Bits vom Master zum Slave sowie gleichermaßen vom Slave zum Master verschoben. Clock-Polarität und Clock-Phase können sehr flexibel festgelegt werden. Ebenso kann unterschieden werden, ob das MSB oder das LSB zuerst verschoben wird. Durch diese Flexibilität ist es möglich, dass Sie das SPI an ganz unterschiedliche Anforderungen anpassen können. Die Hardware-SPI ist beim ATmega328P verschiedenen Pins von Port B zugeordnet. Ein SPI kann aber auch vollständig in Software implementiert werden, wobei Sie dann die freie Wahl der verwendeten I/O-Pins haben. Auf die Konfiguration und den Datenaustausch über SPI komme ich in Abschnitt 10.2 zurück. An dieser Stelle ist es wichtig, dass Sie den
Datenaustausch über SPI als Schieberegister-Operation verstanden haben. I2C-Bus (TWI-Bus)
Der I2C-Bus wurde von Philips entwickelt, um in einer vernetzten Umgebung Daten zwischen Mikrocontrollern und unterschiedlichen Bausteinen, wie EEPROMs, RAMs, AD- und DAUmsetzern, RTCs (Real Time Clocks, dt. Echtzeit-Uhrenbausteinen) und anderen mehr, übertragen zu können. Das Protokoll erlaubt die Verbindung von bis zu 128 unterschiedlichen Bausteinen (Devices) mithilfe einer Zwei-DrahtLeitung. Die Adressierung der einzelnen Teilnehmer im Netzwerk erfolgt über das Protokoll. An externen Komponenten werden nur zwei Pull-up-Widerstände benötigt. Abbildung 1.12 zeigt die erforderlichen Verbindungen in einem typischen I2C-Bus-Netzwerk. Die Leitungen SDA und SCL, über Pullup-Widerstände an die Betriebsspannung VCC geführt, verbinden alle Mitglieder des Netzwerkes. In einem I2C-Bus-Netzwerk können verschiedene Master mit verschiedenen Slaves verbunden werden (Multi-Master-System).
Abbildung 1.12 I2C-Bus-Netzwerk
Die zu realisierenden Peripheriefunktionen sind wiederum bausteinspezifisch. Neben den von zahlreichen Herstellern angebotenen EEPROMs und RAMs gibt es eine Vielfalt von weiteren I2C-Bus-Bausteinen. Eine sehr nützliche Übersicht zu I2C-BusBausteinen gibt es unter der URL https://i2cdevices.org/devices. Die AVR-Mikrocontroller unterstützen den I 2C-Bus durch eine von Atmel als Two-Wire Interface (TWI) bezeichnete Funktionsgruppe auf dem Chip. Die Hauptmerkmale dieses Hardware-TWI sind: einfaches, leistungsfähiges und flexibles Kommunikationsinterface Master- oder Slave-Betrieb Betrieb als Sender oder Empfänger 128 verschiedene Slave-Adressen sind möglich. Multi-Master Arbitration wird unterstützt. bis zu 400 kHz Transfergeschwindigkeit Ausgangstreiber mit limitierter Slew-Rate Rauschunterdrückung, unterdrückt Spikes auf den Busleitungen. frei programmierbare Slave-Adressen Wakeup nach Adressdecodierung kompatibel zum Philips-I2C-Bus-Protokoll
Abbildung 1.13 Blockdiagramm der »TWI Unit« (Quelle: ATmega328P Data Sheet)
Abbildung 1.13 zeigt ein vereinfachtes Blockdiagramm dieser komplexen Funktionsgruppe mit den zugehörigen Registern. Das TWI kann in vier unterschiedlichen Modi arbeiten: Master Transmitter Mode (MT) Master Receiver Mode (MR) Slave Transmitter Mode (ST) Slave Receiver Mode (SR) Einige dieser Modi können in der gleichen Anwendung zum Einsatz kommen. Das in Abschnitt 9.2 beschriebene Beispiel zum Datenaustausch mit einem I2C-Bus-EEPROM illustriert dies. Das TWI schreibt in diesem Programmbeispiel im Master Transmitter Mode Daten in das EEPROM, und im Master Receiver
Mode liest es Daten vom EEPROM zurück. USART
Der Abkürzung USART steht für die etwas sperrige Bezeichnung Universal Synchronous and Asynchronous serial Receiver and Transmitter. Die in den AVR-Mikrocontrollern implementierten USARTs sind zu den bekannten UARTs der Standard-Controller kompatibel, weisen aber auch weitergehende Funktionen auf. Die Hauptmerkmale eines solchen USART sind: Full-Duplex-Betriebsweise synchroner oder asynchroner Betrieb Master- oder Slave-Synchronbetrieb interner hochauflösender Baudratengenerator hohe Baudraten bei niedrigen Taktfrequenzen 5 bis 9 Datenbits, 1 oder 2 Stoppbits ungerade oder gerade Parität, Paritätscheck durch Hardware Noise-Filter Overrun und Frame Error Detection Interrupts für das Ende der Übertragung bzw. das Empfangsende und Transmit-Register leer Multi-Prozessor-Modus Asynchronmodus mit doppelter Geschwindigkeit Einen Eindruck von der Komplexität eines USART vermittelt ein vereinfachtes Blockdiagramm (siehe Abbildung 1.14).
Damit Sie verstehen können, wie die asynchrone serielle Kommunikation funktioniert, müssen Sie sich darüber im Klaren sein, wie Daten empfangen werden. Alle Zeichen des seriellen Datenstroms, die nicht korrekt empfangen werden, gehen verloren – die Kommunikation ist somit gestört. Der Pin RxD wird mit der sechzehnfachen Baudrate abgetastet. Werden auf der Leitung Daten gesendet, dann geht diese von ihrem Ruhezustand (Hi) nach Lo und übermittelt dann ein Pulspaket entsprechend der Zahl der gesendeten Bits. Abbildung 1.15 zeigt die Abtastung des seriellen Datenstroms.
Abbildung 1.14 Vereinfachtes USART-Blockdiagramm (Quelle: ATmega328P Data Sheet)
Abbildung 1.15 Abtastung des seriellen Datenstroms
Durch den Hi-Lo-Übergang zu Beginn der Pulsfolge wird der Beginn des Startbits signalisiert, dem dann die Datenbits und ein oder zwei Stoppbits folgen. Wie in Abbildung 1.15 angedeutet, weisen die Abtastwerte 8, 9 und 10, die etwa in der Mitte eines jeden Bits liegen, eine Besonderheit auf. Mindestens zwei dieser Abtastwerte müssen den gleichen Wert aufweisen, um den Abtastwert des betreffenden Bits festzulegen. Diese Art der Rauschunterdrückung erhöht die Sicherheit der seriellen Kommunikation. Wurde schließlich das Stoppbit erkannt, dann ist der Empfang des gesendeten Zeichens beendet und es kann in das Register UDR (Receive) gespeichert werden. Dort steht es dann zum Abholen durch das Anwenderprogramm bereit. Das Versenden von Daten wird durch Laden des Registers UDR (Transmit) mit den zu sendenden Daten eingeleitet. Im Synchronmodus dient der Pin XCK für einen Slave als Takteingang und für einen Master als Taktausgang. Die vielfältigen Features des USART werden Sie bei der Verwendung des ATmega328P im Arduino nicht ausnutzen. Sie werden die UARTFunktion zur asynchronen seriellen Datenübertragung nutzen und im Wesentlichen mit verschiedenen Baudraten arbeiten. Der hier betrachtete ATmega328P weist ein USART auf. Andere Mikrocontroller können durchaus mehrere Hardware-U(S)ARTs aufweisen. Es besteht aber auch die Möglichkeit, ein USART in Software zu implementieren. Von dieser Möglichkeit werden wir beim Arduino Uno noch Gebrauch machen. Timer/Counter
Die AVR-Mikrocontroller weisen 8-Bit- und 16-Bit-Timer/Counter auf, die unabhängig als Timer mit einem internen Takt oder als Counter mit externem Trigger arbeiten. Der Prescaler versorgt die Timer mit einem Taktsignal, das vom internen Takt abgeleitet wird. Das Vorteilerverhältnis kann über das Register TCCRx selektiert werden. Abbildung 1.16 zeigt ein Blockdiagramm eines Prescalers für die Timer/Counter0 und 1.
Abbildung 1.16 Timer/Counter0/1-Prescaler (Quelle: ATmega328P Data Sheet)
Der 8-Bit-Timer/Counter0 des ATmega328P ist als einfacher UpCounter mit Schreib-/Lesezugriff aufgebaut. Timer/Counter0 weist die folgenden Eigenschaften auf: zwei unabhängige Output Compare Units doppelt gepufferte Output Compare Register Clear Timer on Compare Match (Auto Reload) Glitch Free, Phase Correct Pulse Width Modulator (PWM) variable PWM-Periode Frequenz-Generator drei unabhängige Interrupt-Quellen (TOV0, OCF0A, OCF0B)
Abbildung 1.17 zeigt das Blockdiagramm von Timer/Counter0.
Abbildung 1.17 Blockdiagramm von Timer/Counter0 (Quelle: ATmega328P Data Sheet)
Die Konfiguration von Timer/Counter0 erfolgt über die beiden Register TCCR0A und TCCR0B. Beim Overflow des Registers TCNT0 (0xFF nach 0x00) kann ein Interrupt angefordert werden. Ein 8-Bit-Comparator vergleicht kontinuierlich das Register TCNT0 mit den Output Compare Registern OCR0A und OCR0B. Ist der Inhalt von Register TCNT0 gleich dem von OCR0A oder OCR0B, dann signalisiert das der Comparator (Match). Ein Match setzt dann das Output Compare Flag (OCF0A oder OCF0B). Ist der betreffende Interrupt freigegeben, dann erzeugt das gesetzte Output Compare Flag außerdem einen Output Compare Interrupt. Der 16-Bit-Timer/Counter1 ist komplexer als der 8-BitTimer/Counter0 und unterstützt Output-Compare- und Input-
Capture-Funktionen. Timer/Counter1 weist die folgenden Eigenschaften auf: echtes 16-Bit-Design (erlaubt 16-Bit-PWM) zwei unabhängige Output Compare Units doppelt gepufferte Output Compare Register eine Input Capture Unit Input-Capture-Noise-Unterdrückung Clear Timer on Compare Match (Auto Reload) Glitch-free, Phase Correct Pulse Width Modulator (PWM) variable PWM-Periode Frequenz-Generator externer Event-Counter vier unabhängige Interrupt-Quellen (TOV1, OCF1A, OCF1B, ICF1) Abbildung 1.18 zeigt zur Verdeutlichung der wesentlich höheren Komplexität das Blockdiagramm von Timer/Counter1. Das Verhalten bei Overflow und Output Compare ist bis auf die Breite der Register von 16 Bit praktisch dasselbe wie beim Timer/Counter0. Die Input-Capture-Funktion wird durch ein externes Ereignis getriggert, in dessen Folge der Inhalt des Registers TCNT1 in das Input-Capture-Register ICR1 geschrieben wird. Die Input-CaptureFunktion kann auch vom Analogkomparator getriggert werden. Des Weiteren kann dieser Timer/Counter als PWM genutzt werden. Interrupts werden vom 16-Bit-Timer/Counter beim Overflow, beim Output Compare sowie beim Input Capture angefordert.
Der 8-Bit-Timer/Counter2 des ATmega328P ist ein einkanaliger, bidirektionaler 8-Bit-Timer/Counter. Timer/Counter2 weist die folgenden Eigenschaften auf: Single Channel Counter Clear Timer on Compare Match (Auto Reload) Glitch-free, Phase Correct Pulse Width Modulator (PWM) Frequenz-Generator 10-Bit-Clock-Prescaler Overflow und Compare Match Interrupt Sources (TOV2, OCF2A, OCF2B) Erlaubt externen Takt von einem 32-kHz-Uhrenquarz unabhängig vom Takt der I/O-Clock.
Abbildung 1.18 Blockdiagramm von Timer/Counter1 (Quelle: ATmega328P Data Sheet)
Auf den ersten Blick ähneln sich Timer/Counter0 und Timer/Counter2. Im Detail betrachtet, bietet Timer/Counter2 zusätzliche Features und dadurch mehr Flexibilität. Watchdog
Watchdogs dienen in von Mikrocontrollern gesteuerten elektronischen Geräten dazu, einem Totalausfall durch Softwareversagen zuvorzukommen. Der Watchdog muss innerhalb einer vorgegebenen Zeit von der Software zurückgesetzt werden, anderenfalls erfolgt nach Ablauf der vorgegebenen Zeit ein Reset des Anwendungsprogramms. Konnte das laufende Programm nicht rechtzeitig den Watchdog bedienen, muss davon ausgegangen werden, dass das Programm »hängen geblieben« oder ausgefallen ist. Der Watchdog setzt daraufhin durch einen Reset das Gerät in einen definierten Ausgangszustand zurück, damit das von der Software gesteuerte System wieder überwacht arbeiten kann. Der Watchdog Timer im ATmega328P wird durch einen separaten On-Chip-Oszillator mit nominal 1 MHz getaktet. Es lassen sich Watchdog-Intervalle zwischen 16 ms und 1,9 s (VCC = 5 V) einstellen. Abbildung 1.19 zeigt das Blockdiagramm des Watchdogs.
Abbildung 1.19 Blockdiagramm des Watchdogs (Quelle: ATmega328P Data Sheet)
Beim Festlegen der Watchdog-Periode muss berücksichtigt werden, dass die Frequenz des internen Oszillators sowohl stark betriebsspannungs- als auch temperaturabhängig ist. Analog/Digital-Umsetzer
Der ATmega328P weist einen internen Analog/Digital-Umsetzer (ADU, auch ADC für Analog/Digital Converter) mit folgenden Merkmalen auf: Auflösung 10 Bit integrale Nichtlinearität 0,5 LSB absolute Genauigkeit ± 2 LSB Umsetzzeit von 65 bis 260 µs Umsatzrate bis zu 76,9 ksps (sps = sample per second) Umsatzrate bis zu 15 ksps bei maximaler Auflösung sechs massebezogene Analogeingänge (single ended)
Ergebnis der AD-Umsetzung rechts- oder linksbündig Eingangsspannungsbereich 0 bis AVCC interne Referenzspannung von 2,56 V kontinuierliche (free running) oder Einzelumsetzung (single shot) interruptgesteuerte Auslösung der AD-Umsetzung durch AutoTriggerung Interrupt am Ende der AD-Umsetzung Rausch-Unterdrückung Abbildung 1.20 zeigt das Blockdiagramm des AD-Umsetzers eines ATmega328P.
Abbildung 1.20 Blockdiagramm des AD-Umsetzers (Quelle: ATmega328P Data Sheet)
Bei einem AD-Umsetzer nach dem Verfahren der sukzessiven Approximation wird die über einen Analogmultiplexer zugeführte analoge Eingangsspannung mit der Ausgangsspannung eines DAUmsetzers verglichen. Die Ausgangsspannung des 10-Bit-DAUmsetzers wird durch die Steuerlogik (Register ADMUX, ADCSRA) sowie durch eine der Referenzspannungen festgelegt. Die Steuerlogik steuert den DA-Umsetzer bitweise an, und das Komparator-Ausgangssignal bestimmt, ob das jeweilige Bit im Ausgaberegister (ADCH, ADCL) gesetzt oder nicht gesetzt wird. Auf diese Weise nähert sich die Ausgangsspannung des DAUmsetzers sukzessive dem zu erfassenden analogen Spannungswert. Daher kommt auch der Name des Verfahrens: sukzessive Approximation. Der zu erfassende Spannungswert darf sich während des Umsetzvorgangs nicht ändern, da sonst ein falscher Inhalt des Ausgaberegisters die Folge wäre. Eine dem Komparator vorgeschaltete Sample-and-Hold-Schaltung, die den abgetasteten Spannungswert für die Zeit der AD-Umsetzung zwischenspeichert, erfüllt hier diese Forderung. Die erforderliche Umsetzungszeit ist unabhängig von der anliegenden Eingangsspannung und richtet sich nur nach der Auflösung des AD-Umsetzers. Ein 10-Bit-AD-Umsetzer benötigt genau zehn Umsetzschritte, deren Zeit durch die Taktung des DAUmsetzers und die Schaltzeit des Komparators bestimmt wird. Die Eingangsspannung wird über einen Analog-Multiplexer an den Komparator geführt. Für Kalibrations- und Testzwecke können zusätzlich die interne Bandgap-Referenzspannung, das Massepotenzial und das Ausgangssignal eines internen Temperatursensors an den Komparator geführt werden.
Wichtig für die eingangsseitige Beschaltung des AD-Umsetzers ist die analoge Eingangsschaltung. Abbildung 1.21 zeigt ein Ersatzschaltbild für die massebezogene Messung.
Abbildung 1.21 Analoge Eingangsschaltung (Quelle: ATmega328P Data Sheet)
Die analoge Spannungsquelle (Eingangsspannung) wird in jedem Fall durch die Eingangsleckströme und eine Eingangskapazität des Anschlusses (hier nicht dargestellt) belastet. Ist der betreffende Multiplexer-Kanal durchgeschaltet, dann muss die Spannungsquelle das RC-Glied aus dem Serienwiderstand und der Sample&Hold-Kapazität aufladen. Die Eingangsschaltung ist für Impedanzen von 10 kΩ und weniger optimiert. Liegen die Impedanzen höher, dann kann eine Entkopplung durch einen Operationsverstärker angezeigt sein. Das Resultat der AD-Umsetzung folgt idealerweise für die massebezogene Messung (single ended) der Beziehung
Eine fehlerfreie AD-Umsetzung ist kaum zu erwarten, weshalb Sie den Abweichungen vom Idealverhalten Beachtung schenken sollten.
Auf diese Weise verlangen Sie von der ausgewählten Baugruppe nur so viel, wie diese auch zu leisten vermag, und können die Fehler in bestimmtem Maße eliminieren. Abbildung 1.22 zeigt die grundsätzlichen Fehler bei der AD-Umsetzung.
Abbildung 1.22 Fehler bei der AD-Umsetzung (Quelle: ATmega328P Data Sheet)
Die Abbildung links oben zeigt einen Offset-Fehler. Ein Offset-Fehler liegt dann vor, wenn der Übergang des Resultats der AD-Umsetzung von 0 auf 1 nicht bei einer Eingangsspannung von ½ LSB (hier VREF/2048) erfolgt. Bei einer Referenzspannung VREF = AVCC = 5 V beträgt das LSB 4,88 mV. Die Abbildung rechts oben zeigt einen Verstärkungsfehler (Gain Error). Ein Verstärkungsfehler liegt dann vor, wenn der Übergang des Resultats der AD-Umsetzung von 0x3FE auf 0x3FF nicht bei einer Eingangsspannung von 1½ LSB unterhalb der Referenzspannung erfolgt. Die Abbildung links unten zeigt die differenzielle Nichtlinearität (DNL). Die DNL kennzeichnet den maximalen Spannungshub pro
Quantisierungsschritt. Ideal ist ein Spannungshub für jede Stufe von genau 1 LSB. Die Abbildung rechts unten zeigt die integrale Nichtlinearität (INL). Die INL ist die maximale Abweichung von der Idealkennlinie des AD-Umsetzers. Neben der statischen Kennlinie des AD-Umsetzers ist auch das Rauschverhalten von Interesse. Hierbei kann aber der AD-Umsetzer nicht isoliert betrachtet werden, sondern die analoge Eingangsschaltung (Leitungslängen etc.) muss Berücksichtigung finden. Sicher werden Sie sofort ahnen, dass die hier angegebenen Fehler nicht isoliert auftreten, sondern sich überlagern. Die Umsetzung eines analogen Sensorsignals kann so schon zur Herausforderung werden. Interne AD-Umsetzer in Mikrocontrollern haben im Allgemeinen weniger gute Eigenschaften als spezielle AD-Umsetzer, die eigenständige Bausteine sind. Das wird bereits anhand der Auflösung deutlich. Wenn also höhere Genauigkeiten und geringere Fehler zwingend sind, dann kann ein Mikrocontroller auch durch einen externen AD-Umsetzer ergänzt werden. Analogkomparator
Ein Analogkomparator vergleicht Spannungen an zwei I/O-Pins. Der Ausgang des Analogkomparators wird bei positivem Vergleichsergebnis gesetzt. Dieses Ereignis kann zur Anforderung eines Interrupts oder zum Triggern der Input-Capture-Funktion des 16-Bit-Timer/Counters dienen. Abbildung 1.23 zeigt das Blockschema des Analogkomparators.
Die Konfiguration des Analogkomparators erfolgt über das Register ACSR. Der Analogkomparator kann ausgeschaltet werden, wodurch die Stromaufnahme reduziert wird. Per Default ist der Analogkomparator aber eingeschaltet. Der Komparatorausgang kann einen Interrupt auslösen. Über das Register ACSR wird das Trigger-Ereignis (fallende Flanke, steigende Flanke, Wechsel an ACI (Toggle)) selektiert. Die Auswertung des Komparatorausgangs kann dann über einen Interrupt oder ein Polling des Registers ACSR Bit ACO erfolgen.
Abbildung 1.23 Blockdiagramm des Analogkomparators (Quelle: ATmega328P Data Sheet)
Es ist außerdem möglich, einen der ADC-Pins auszuwählen, um den negativen Eingang des Analogkomparators AIN1 zu ersetzen. Der ADC-Multiplexer wird verwendet, um diesen Eingang auszuwählen, und folglich muss der AD-Umsetzer ausgeschaltet werden, um diese Funktion nutzen zu können. Interne Referenzspannung
Die Referenzspannung für den AD-Umsetzer (VREF) gibt den Umwandlungsbereich für die AD-Umsetzung an. Eingangssignale, die den Wert VREF überschreiten, führen zu Codes in der Nähe von 0x3FF.
Die Referenzspannung VREF kann entweder als AVCC, als interne 1,1V-Referenz oder als externer AREF-Pin ausgewählt werden. AVCC ist über einen passiven Schalter mit dem ADC verbunden. Die interne 1,1-V-Referenz wird aus der internen Band-Gap-Referenz (VBG) über einen internen Verstärker erzeugt. In beiden Fällen ist der externe AREF-Pin direkt mit dem AD-Umsetzer verbunden. Die Referenzspannung wird unempfindlicher gegen Rauschen, wenn ein Kondensator zwischen den AREF-Pin und der Masse geschaltet wird. Die Spannung VREF kann auch mit einem hochohmigen Voltmeter am AREF-Pin gemessen werden. Beachten Sie, dass VREF eine hochohmige Quelle ist und dass in einem System nur eine kapazitive Last angeschlossen werden sollte. Wenn Sie eine feste Spannungsquelle an den AREF-Pin anschließen, können Sie die anderen Referenzspannungsoptionen in der Anwendung nicht verwenden, da diese mit der externen Spannung kurzgeschlossen werden. Wenn keine externe Spannung an den AREF-Pin angelegt wird, können Sie zwischen AVCC und der Bad-Gap-Referenz (1,1 V) als Referenzauswahl umschalten. Das erste Ergebnis einer AD-Umsetzung nach dem Umschalten der Referenzspannungsquelle ist möglicherweise ungenau und sollte stets verworfen werden. EEPROM
Der ATmega328P enthält 1 KB EEPROM-Speicher. EEPROM steht für Electrically Erasable Programmable Read-Only Memory (dt. elektrisch löschbarer programmierbarer Nur-Lese-Speicher) und
bezeichnet einen nichtflüchtigen Speicher, dessen Inhalt elektrisch gelöscht werden kann. Dieser Speicher ist als separater Speicherbereich organisiert, in den einzelne Bytes gelesen und geschrieben werden können. Das EEPROM hat eine Lebensdauer von mindestens 100.000 Schreib-/Löschzyklen und sollte deshalb nicht für Inhalte eingesetzt werden, die sich rasch ändern. Konfigurationsdaten, Seriennummern, Kalibrierdaten und Ähnliches sind die bevorzugten Inhalte eines solchen Speichers. Der Zugriff der CPU auf ein EEPROM erfolgt unter Angabe der EEPROM-Adressregister (EEARH, EEARL), des EEPROMDatenregisters (EEDR) und des EEPROM-Steuerregisters (EECR). In Abschnitt 9.1 werde ich den Zugriff auf das EEPROM des Arduino Uno erläutern, und Sie werden sehen, dass sich die Zugriffe sehr einfach gestalten, wenn Sie eine geeignete Library nutzen. Die Zugriffszeiten werden dadurch natürlich nicht reduziert.
2 Arduino-Hardware Im ersten Kapitel haben Sie mit dem Arduino Uno die Grundlagen für den Arduino insgesamt kennengelernt. Was die Arduino-Hardware betrifft, so ist es aber bei Weitem nicht beim Arduino Uno geblieben. Neben weiteren Arduino-Boards existiert eine Vielzahl von ArduinoClones, die funktional identisch sind, oft aber auch spezielle Anwendungsaspekte unterstützen. Die Arduino-Hardware ist Open Source – also sind Arduino-Clones absolut legitim. Die Produktfamilie Arduino umfasst Arduino-Boards auf Basis von 8-Bit-AVR-Mikrocontrollern, 32-Bit-ARM-Cortex-Mx-Mikrocontrollern und eine Kombination mit einem Linux-Device. Im Sinne dieser Klassifikation stelle ich Ihnen in diesem Kapitel wichtige Arduino-Boards vor. Da ständig weitere Mitglieder der Produktfamilie entwickelt werden, kann diese Zusammenstellung nicht vollständig sein.
2.1 Die Produktfamilie Arduino Damit Sie die Ausstattung der hier gezeigten Arduinos besser vergleichen können, habe ich im Anhang in Abschnitt A.2 die technischen Daten in einem tabellarischen Vergleich zusammengestellt. Das Angebot im Arduino Store (https://store.arduino.cc/) zeigt deutlich die Weiterentwicklung der Arduino-Produktfamilie. Vom Arduino-Team wird aber sichergestellt, dass die Dokumentation zu älteren Boards nicht verloren geht. Auf der Website https://docs.arduino.cc/retired/ finden Sie Informationen zu allen Boards, Shields, Kits und anderen älteren Produkten, die nicht mehr offiziell unterstützt werden.
2.1.1 Klassische Arduino-Boards Als klassische Arduino-Boards möchte ich die von der Arduino Company vorgestellten Boards mit dem Arduino-Uno-Formfaktor bezeichnen. Den Arduino-Uno-Formfaktor haben Sie beim Arduino Uno Rev3 in Kapitel 1 bereits kennengelernt. Die Arduino-Boards können alle über den Arduino Store oder einen der zahlreichen Distributoren bezogen werden. Hinweis: Versandkosten Im Arduino Store sind die Versandkosten für Länder außerhalb der EU recht hoch. Am Beispiel eines Arduino Uno Rev3, der ca. 22 € kostet, soll das hier verdeutlicht werden (siehe
Tabelle 2.1). Land
Zustelldienst
Versandkosten Gesamtkosten
Österreich
UPS Standard 6,00 €
28,00 €
FedEx
33,05 €
11,05 €
Deutschland UPS Standard 6,00 € FedEx Schweiz
28,00 €
11,05 €
33,05 €
UPS Standard 11,54 €
33,54 €
Tabelle 2.1 Versandkosten des Arduino Stores am Beispiel des Arduino Uno Rev3
Wenn ich den Bezug bei einem lokalen Distributor betrachte, dann komme ich zu dem Ergebnis aus Tabelle 2.2. Die hier angegebenen Distributoren sind willkürlich herausgegriffen. Die Unterschiede sollten bezogen auf das jeweilige Land nicht gravierend sein. Land Lieferant
Arduino Uno Rev3 Versandkosten
Gesamtkosten
D
EXP Tech
20,00 €
26,50 €
CH
RS-Online
25,16 CHF https://ch.rs-online.com/
6,50 € (UPS)
keine (TNT Express) 25,16 CHF
Tabelle 2.2 Distributorenpreise inklusive Versandkosten für Deutschland und die Schweiz
Im Anhang (Abschnitt A.1) ist ein Link zu den von Arduino autorisierten Distributoren aufgelistet. Achten Sie besonders bei Bestellungen aus Nicht-EU-Ländern auf die Versandkosten. Wie bei den meisten Bestellungen kann es oft sinnvoll sein, einzelne Order zusammenzufassen und möglichst viel Versand zu sparen. Bei vielen Elektroteilen werden Sie Händler finden, die in China sitzen und von dort versenden. Bei solchen Bestellungen müssen Sie zudem auf Zollgebühren achten, zudem verlängert sich die Versanddauer entsprechend, wenn der Händler nicht über ein Lager in Europa verfügt.
Arduino Uno Rev3
Den Arduino Uno Rev3 hatte ich schon in Abschnitt 1.4 als das Basismodell der Arduino-Familie bezeichnet, und seine wesentlichen Bestandteile wurden dort bereits erläutert. In Abbildung 2.1 sehen Sie noch einmal die Frontseite des Arduino Uno Rev3, um die noch folgenden Arduinos besser vergleichen zu können.
Abbildung 2.1 Arduino Uno Rev3
In Abbildung 2.1 sind an Ober- und Unterkante des Boards deutlich die Buchsenleisten zu erkennen, die den klassischen Arduino ausmachen. Die Anordnung und die Belegung dieser Buchsenleisten machen einen großen Teil der Arduino-Kompatibilität aus. Die Buchsenleisten sind wie folgt belegt: SCL SDA AREF GND D13 D12 D11 D10 D9 D8 D7
D6
D5
D4
D3
D2
D1
D0
IOREF RESET 3V3 5V GND GND VIN A0
A1
A2
A3 A4
A5
An diesen Buchsenleisten setzen die Erweiterungsboards, die sogenannten Arduino-Shields, an. Wenn Arduino-Shields an unterschiedlichen Arduino-Boards funktionieren sollen, dann ist eine standardisierte Anordnung und Belegung der Buchsenleisten unbedingte Voraussetzung. Ein USB-Anschluss zum Programm-Upload und zur Spannungsversorgung, eine separate Spannungsversorgung durch ein Netzteil und der Reset-Taster sind ebenfalls Elemente, die bei jedem klassischen Arduino vorhanden sind. Nun stellt sich natürlich die Frage nach der Unterschiedlichkeit der verschiedenen ArduinoBoards, wenn doch nach außen hin scheinbar alles gleich ist. Zur Verdeutlichung der Unterschiede möchte ich ein Blockdiagramm des Arduino Uno Rev3 heranziehen, das ich dann an die anderen Arduinos anpassen werde. Abbildung 2.2 zeigt das Blockdiagramm des Arduino Uno Rev3, wobei die von außen zugänglichen Komponenten am Rand des Blockdiagramms angeordnet sind. Das betrifft die Buchsenleisten und die Anschlüsse für USB und Power. Die Buchsenleisten sind weitgehend durch die I/O-Pins des Mikrocontrollers ATmega328P belegt. Eine Buchsenleiste ist mit den internen Spannungen verbunden. Der Power-Control-Block stellt die stabilisierten Spannungen bereit und sorgt damit für die Umschaltung zwischen der externen Betriebsspannung VIN und der durch den USB-Anschluss bereitgestellten Versorgungsspannung VUSB. Zwischen dem USB-Anschluss und dem
ATmega328P dient ein ATmega16U2 als USB-Serial-Bridge (USB-Seriell-Konverter). Eine USBSerial-Bridge hat die Aufgabe, einen USB-Anschluss an die Anschlüsse einer seriellen Schnittstelle (UART) eines Mikrocontrollers anzupassen.
Abbildung 2.2 Blockdiagramm des Arduino Uno Rev3
Beide eingesetzten Mikrocontroller weisen einen mit ICSP bezeichneten Anschluss auf. ICSP bedeutet In-Circuit Serial Programming, also eine direkte serielle Programmierung über SPI unter Umgehung des sonst genutzten Bootloaders. Damit können die Mikrocontroller direkt von einem Programmer, der über diesen standardisierten Anschluss angeschlossen ist, neu programmiert werden. Der ATmega328P ist beim Arduino Uno Rev3 als konventioneller DIL-Baustein gesockelt. In Abbildung 2.1 ist das deutlich zu sehen. Der Baustein kann also mit normalen Mitteln ausgetauscht werden, wenn mal ein Malheur passiert ist. In Abschnitt 1.4.3 finden Sie weitere Informationen dazu. Der Vollständigkeit halber möchte ich aber den Arduino Uno Rev3 SMD nicht unerwähnt lassen. Diese preiswertere Bestückungsvariante kommt dem Anwender durch einen leicht reduzierten Preis zugute. Arduino Leonardo
Beim Arduino Leonardo werden weitgehend SMD-Bauteile eingesetzt, was eine einfachere automatisierte Bestückung ermöglicht. Dadurch ist aber ein Wechsel des Mikrocontrollers mit normalen Mitteln nicht mehr möglich. Abbildung 2.3 zeigt die sehr aufgeräumte Frontansicht des Arduino Leonardo.
Abbildung 2.3 Arduino Leonardo
Beim Arduino Leonardo wurde der ATmega328P durch einen ATmega32U4 ersetzt, der über eine integrierte USB-Kommunikation (USB 2.0 Full-speed/Low Speed Device Module) verfügt, sodass kein zweiter Mikrocontroller als USB-Serial-Bridge erforderlich ist. Auf diese Weise kann der Leonardo neben einem virtuellen COM-Port einem angeschlossenen Computer auch als Maus und Tastatur dienen. Im Blockdiagramm machen sich diese Änderungen folgendermaßen bemerkbar (Abbildung 2.4): Der USB-Typ-B-Anschluss wurde durch einen Micro-USB-Typ-B-Anschluss ersetzt, und es steht nur noch ein ICSP-Anschluss zur Verfügung. Durch den ATmega32U4 bedingt stehen allerdings mehr digitale Ein-/Ausgänge und mehr analoge Eingänge zur Verfügung. Da die Zahl der nach außen geführten Anschlüsse allerdings unverändert ist, bedeutet das Mehrfachbelegungen verschiedener Anschlüsse.
Abbildung 2.4 Blockdiagramm des Arduino Leonardo
Arduino Uno WiFi Rev2
Wollten Sie in der Vergangenheit Ihren Arduino Uno in ein Netzwerk integrieren, dann war ein entsprechendes Ethernet- oder WiFi-Shield für die Netzwerkanbindung erforderlich. Mit dem Arduino Uno WiFi Rev2 können Sie das einfacher haben, denn die Netzwerkanbindung ist in Form des WiFi-Moduls NINA-W132 von u-blox bereits auf dem Board implementiert. Abbildung 2.5 zeigt die Frontseite des Arduino Uno WiFi Rev2. Dort können Sie rechts unten das
WiFi-Modul erkennen. Außerdem wurde dem Board mit dem ATmega4809 ein leistungsfähigerer Mikrocontroller spendiert.
Abbildung 2.5 Arduino Uno WiFi Rev2
Dieser neue Mikrocontroller stellt ein auf 48 KB erweitertes Flash-Memory (Programmspeicher), 6144 Byte SRAM (Datenspeicher), aber nur 256 Byte EEPROM zur Verfügung. Das Blockdiagramm des Arduino Uno WiFi Rev2 ändert sich damit so, wie Sie es in Abbildung 2.6 sehen.
Abbildung 2.6 Blockdiagramm des Arduino Uno WiFi Rev2
Als USB-Serial-Bridge dient ein ATmega32U4, der im Wesentlichen die seriellen Signale vom USBTyp-B-Anschluss an den ATmega4809 weiterleitet. Mit dem ATmega4809 ebenfalls seriell verbunden ist das NINA-W132-BLE-WiFi-Modul, dessen Zustände durch eine RGB-LED angezeigt werden. Hier haben Sie also einen leistungsfähigeren Arduino Uno, der um Bluetooth Low Energy- (BLE) und WiFi-Konnektivität erweitert wurde. Arduino Due
Der Arduino Due war der erste Arduino, der auf einem 32-Bit-ARM-Mikrocontroller basiert. Das Board des Arduino Due ist vergrößert worden und bietet wesentlich mehr Anschlusspins: Mit 54 digitalen Ein-/Ausgängen und 12 analogen Eingängen ist es das perfekte Board für leistungsstarke Arduino-Projekte im größeren Maßstab.
Wie an Abbildung 2.7 zu erkennen ist, bieten die Buchsenleisten oben und unten das bekannte Arduino-Interface, sodass Arduino-Shields da auch eingesetzt werden können. Auf der rechten Seite sind zusätzliche Buchsenleisten hinzugekommen, die D14 bis D53 und A8 bis A11 sowie DAC1 und DAC2 und die CAN-Bus-Anschlüsse aufweisen. Außerdem zeigt die linke Seite einen zweiten USB-Anschluss.
Abbildung 2.7 Arduino Due
In Abbildung 2.8 verdeutlicht das Blockdiagramm des Arduino Due die erweiterten I/OAnschlüsse und die zweite USB-Schnittstelle.
Abbildung 2.8 Blockdiagramm des Arduino Due
Die erste USB-Schnittstelle führt wie gewohnt an die USB-Serial-Bridge (ATmega32U4) und dient als Programmierschnittstelle, während die zweite USB-Schnittstelle (nativer USB-Anschluss) direkt an den AT91SAM3X8E geführt ist. Er ermöglicht die serielle Kommunikation über USB, wie z. B. eine serielle Verbindung zum Serial Monitor oder zu anderen Anwendungen auf Ihrem Computer. Außerdem können Sie damit auch eine USB-Maus oder -Tastatur mit einem angeschlossenen Computer emulieren. Durch Einsatz des AT91SAM3X8E arbeitet der Arduino Due mit einer Betriebsspannung von 3,3 V. Das bedeutet, dass auch alle digitalen I/O-Pins mit einer Spannung von maximal 3,3 V arbeiten. Beim Anschluss von externen Komponenten müssen Sie das beachten. Außerdem sind die I/O-Pins unterschiedlich belastbar. Jeder I/O-Pin kann einen Strom von 3 mA oder 15 mA liefern (Quelle) oder einen Strom von 6 mA oder 9 mA empfangen (Senke). Ein PinMapping mit den jeweiligen Stromwerten ist auf der Arduino-Website unter https://www.arduino.cc/en/Hacking/PinMappingSAM3X zu finden. Die I/O-Pins haben auch einen internen Pull-up-Widerstand von 100 kΩ, der standardmäßig aber nicht aktiviert ist. Der Arduino Due weist insgesamt vier serielle Schnittstellen auf. Die Standard-Schnittstelle an den I/O-Pins 0 und 1 ist mit der USB-Serial-Bridge und dem damit verbundenen USB-Anschluss
(Programmierschnittstelle) verknüpft. Die anderen drei seriellen Schnittstellen arbeiten mit 3,3V-Pegeln und liegen auf den Buchsenleisten. Der Arduino Due unterstützt zwei I2C-Bus-Schnittstellen. SDA und SCL liegen auf D20 und D21, SDA1 und SCL1 hingegen auf eigenen Anschlüssen (links oben in Abbildung 2.7). Der ICSP-Anschluss am AT91SAM3X8E kann nur zur Kommunikation mit anderen SPI-Devices verwendet werden, nicht zur Programmierung des AT91SAM3X8E mit der In-Circuit-SerialProgramming-Technik. Das SPI des Arduino Due verfügt auch über erweiterte Funktionen, die mit den Extended-SPI-Methoden für den Arduino Due verwendet werden können.
2.1.2 Kompakte Arduino-Boards Als »kompakte Arduinos« bezeichne ich hier die Arduino-Boards, die vom ursprünglichen Arduino-Uno-Design abweichen und für den Einsatz auf einem Steckbrett (Breadboard) vorgesehen sind. Eine Ausnahme bilden die Arduino-MKR-Boards, die eine eigenständige Familie von IoT-Boards für Maker (daher der Name MKR) darstellen. Den Arduino-MKR-Boards ist Abschnitt 2.1.3 gewidmet. Arduino Nano
Der Arduino Nano ist ein Breadboard-kompatibler, weitgehend dem Arduino Uno entsprechender kompakter Arduino. Die Versorgungsspannung wird über den Anschluss VIN, 5V der Stiftleiste oder über den Mini-USB-Typ-B-Anschluss vorgenommen. Der USB-Anschluss dient auch hier zum Programm-Upload und zur Spannungsversorgung über USB. Abbildung 2.9 zeigt die Ansicht von oben auf den Arduino Nano.
Abbildung 2.9 Arduino Nano
Der Kontakt zur Außenwelt erfolgt über zwei Stiftleisten zu je 15 Pins. Abbildung 2.10 zeigt das sehr überschaubare Blockdiagramm.
Abbildung 2.10 Blockdiagramm des Arduino Nano
Der Deutlichkeit halber habe ich hier noch die Belegung der Stiftleiste wiedergegeben. Sie werden noch sehen, dass bei den kompakten Arduinos keine einheitliche Belegung dieser Stiftleiste vorliegt. D12
D11 D10
D9 D8 D7 D6 D5 D4 D3 D2 GND RST RX0
TX0
USB D13
3V3 AREF A0 A1 A2 A3 A4 A5 A6 A7 5V
RST GND VIN
Da beim Arduino Nano ein ATmega328P eingesetzt ist, gelten für den Arduino Nano ansonsten die Aussagen zum Arduino Uno. Arduino Pro Mini
Das Arduino Pro Mini Board kann als Minimalversion des Arduino Nano betrachtet werden. Es wurde für Anwendungen entwickelt, bei denen der Platz knapp ist, Projekte als dauerhafte Installationen ausgeführt sind und keiner seriellen Kommunikation bedürfen. Die USB-SerialBridge auf dem Board kann dadurch eingespart werden. Für die Programmierung wird dann ein externer Adapter benötigt. Arduino Pro Mini wird sowohl mit ATmega328 als auch mit ATmega168 ausgestattet und ist in Versionen mit 3,3 V und 5 V erhältlich (Tabelle 2.3). Achten Sie bei der Bestellung unbedingt auf diese Eigenschaften. ATmega328
ATmega168
Ausstattung
32 KB Flash, 2 KB RAM, 16 KB Flash, 1 KB RAM,
1 KB EEPROM 512 KB EEPROM
5 V, 16 MHz
Standard-Version
3,3 V, 8 MHz Low-Power-Version
Standard-Version
mit reduziertem Speicher Low-Power-Version
mit reduziertem Speicher
Tabelle 2.3 Ausstattungsvarianten Arduino Pro Mini Clones
Die mit 5 V betriebenen Standard-Versionen sind für eine Spannungsversorgung aus einem Netzteil vorgesehen. Bei den Low-Power-Versionen ist die Taktfrequenz auf 8 MHz abgesenkt, wodurch der Strombedarf sinkt. Abbildung 2.11 zeigt die Ansicht von oben auf den Arduino Pro Mini.
Abbildung 2.11 Arduino Pro Mini
Die Anschlusspunkte für die Stiftleisten sind hier an drei Seiten des Boards angeordnet. Rechts sind die Anschlüsse für ein FTDI-Breakout-Board, das als USB-Serial-Bridge zur Programmierung und seriellen Kommunikation erforderlich ist. Durch die Reduzierung der Funktionalität ist das in Abbildung 2.12 gezeigte Blockdiagramm wieder sehr überschaubar.
Abbildung 2.12 Blockdiagramm des Arduino Pro Mini
In Kapitel 13, »Projektideen für den Arduino«, zeige ich ein Beispiel für eine Sicherheitsblinkschaltung mit einem LilyPad Arduino, bei dem ein solches FTDI-Breakout-Board für die Programmierung zum Einsatz kommt. Auf die Belegung der Stiftleisten möchte ich hier nicht weiter eingehen, da die angebotenen Arduino Pro Mini Clones, die heute erhältlich sind, kein einheitliches Pinout aufweisen. Arduino Micro
Das Arduino Micro ist ein Breadboard-kompatibler, weitgehend dem Arduino Leonardo entsprechender, kompakter Arduino. Die Versorgungsspannung entspricht dem Arduino Nano. Beim Arduino Micro dient ein MicroUSB-Typ-B-Anschluss zum Programm-Upload und zur Spannungsversorgung über USB. Abbildung 2.13 zeigt die Ansicht von oben auf den Arduino Micro.
Abbildung 2.13 Arduino Micro
Die Stiftleisten wurden rechts um zwei Pins erweitert. Jetzt ist auch die SPI-Schnittstelle über die Stiftleiste zugänglich. Auch für den Arduino Micro ist das in Abbildung 2.14 gezeigte Blockdiagramm sehr überschaubar.
Abbildung 2.14 Blockdiagramm des Arduino Micro
Auch bei der Belegung der Stiftleiste gibt es keine Überraschungen. Sie können sehen, dass es bis auf die zusätzlichen SPI-Pins keine veränderte Belegung der Stiftleiste gibt. D12
D11 D10
D9 D8 D7 D6 D5 D4 D3 D2 GND RST RX0
TX0 SS
MOSI
USB D13
3V3 AREF A0 A1 A2 A3 A4 A5
5V
RST GND VIN MISO SCK
Da beim Arduino Micro ein ATmega32U4 eingesetzt wird, gelten ansonsten für den Arduino Micro die Aussagen zum Arduino Leonardo. Arduino Nano Every
Der Arduino Nano Every weist den beliebten Arduino-Nano-Footprint auf und basiert auf dem AVR-Prozessor ATMega4809. Ein SAMD11-ARM-Cortex-M0+-Prozessor fungiert als leistungsstarke USB-Serial-Bridge. Abbildung 2.15 zeigt die Ansicht von oben auf den Arduino Nano Every.
Abbildung 2.15 Arduino Nano Every
Dank seiner castellated Pads (»castellated«, dt. »mit Zinnen versehen«) kann das Board direkt auf eine Leiterplatte gelötet werden. Sind Stiftleisten montiert, dann kann das Board ganz gewöhnlich in ein Breadboard gesteckt werden. Was sind castellated Pads? Sogenannte Castellations werden durch Löcher oder Durchkontaktierungen an den Rändern einer Leiterplatte erzeugt und später (bei der Vereinzelung der Leiterplatten) durchgeschnitten, um eine Reihe von halben Löchern zu bilden. Diese halben Löcher dienen als Kontaktstellen für eine Verbindung zwischen dem Board und der Basisplatine, auf die das Board aufgelötet werden soll (https://www.pcbunlimited.com/engineering/castellated-mounting-holes-pcbfabrication). Abbildung 2.16 zeigt eine Variante von castellated Pads, die eher für den SMD-Einsatz gedacht ist, während die in Abbildung 2.17 gezeigte Variante auch für die Bestückung mit einer Stiftleiste geeignet ist.
Abbildung 2.16 Castellated Pads – Halbkreis
Abbildung 2.17 Castellated Pads – kleine Öffnung
Das Blockdiagramm des Arduino Nano Every zeigt die zwei eingesetzten Mikrocontroller (Abbildung 2.18).
Abbildung 2.18 Blockdiagramm des Arduino Nano Every
Im Power-Control-Modul wird ein MPM3610-Step-Down-Converter (Schaltregler) eingesetzt, der einen Eingangsspannungsbereich von 4,5 V bis 21 V Gleichspannung bei einem Laststrom von maximal 1,2 A abdeckt. Um Schäden durch thermische Überlastung zu vermeiden, unterbricht der MPM3610 seine Ausgangsspannung, wenn die Chip-Temperatur von 150 °C überschritten wird. Sobald die Temperatur die untere Schwelle von typische 130 °C unterschreitet, nimmt der MPM3610 seinen Betrieb wieder auf. Der Deutlichkeit halber zeige ich hier wieder die Belegung der Stiftleiste. Diese Belegung gilt auch für alle weiteren Arduino Nano 33 und wird nicht wiederholt. MISO
MOSI D10
D9 D8 D7 D6 D5 D4 D3 D2 GND RST RX0
TX0
USB SCK
3V3
AREF A0 A1 A2 A3 A4 A5 A6 A7 5V
RST GND VIN
Arduino Nano 33 IoT
Der Formfaktor des Arduino Nano ist seit Jahren über die Maker-Community hinaus beliebt, da er gemeinsam mit den castellated Pads die Voraussetzung dafür ist, die Boards auf kleinem Raum und in jedes Projekt integrieren zu können. Der Arduino Nano 33 IoT ist Teil der neuen 3,3-V-Variante der Arduino-Familie mit einem SAMD21G18A-ARM-Cortex-M0+-Mikrocontroller und einem vorzertifizierten ESP32-basierten WLAN- und Bluetooth-4.2-Modul NINA-W102 von u-blox, das anspruchsvolle Konnektivität in einem kompakten Modul bietet. Die Integration eines ECC608-Krypto-Chips bedeutet auch, dass IoT-Sicherheitsfunktionen verfügbar sind. Außerdem ist das Board mit einer Einheit zur Trägheitsmessung namens LSM6DS3 (IMU, Inertial Measuring Unit) ausgestattet, die einen digitalen linearen 3D-Beschleunigungssensor und einen digitalen 3D-Winkelgeschwindigkeitssensor umfasst. Abbildung 2.19 zeigt die Ansicht von oben auf den Arduino Nano 33 IoT.
Abbildung 2.19 Arduino Nano 33 IoT
Abbildung 2.20 wiederum zeigt das Blockdiagramm des Arduino Nano 33 IoT – einschließlich der LSM6DS3-IMU und des Krypto-Chips ECC608.
Abbildung 2.20 Blockdiagramm des Arduino Nano 33 IoT
Arduino Nano 33 BLE und Arduino Nano 33 BLE Sense
Der Arduino Nano 33 BLE basiert auf dem NINA-B306-Modul für die BLE- und Bluetooth-5Kommunikation. Das BLE-Modul wiederum basiert auf dem Mikrocontroller nRF52840 von Nordic, der einen leistungsstarken Cortex-M4F enthält. Der Arduino Nano 33 BLE Sense verfügt außerdem über eine Vielzahl von Sensoren, mit denen hochgradig interaktive Designs erstellt werden können. Beide Arduino Nano 33 BLE verfügen über eine 9-Achsen-IMU. Beim Arduino Nano 33 BLE Sense kommen Sensoren für Temperatur, Druck, Luftfeuchtigkeit, Licht, Farbe und sogar Gesten sowie ein Mikrofon hinzu. Auf diese Weise können tragbare Geräte und gestenbasierte Projekte entworfen werden, die aus nächster Nähe mit anderen Geräten kommunizieren können. Abbildung 2.21 zeigt die Draufsicht auf den Arduino Nano 33 BLE Sense. Wenn Sie genau hinsehen, dann können Sie erkennen, dass sich dieses Board nur durch die Sensorbestückung vom Arduino Nano 33 BLE unterscheidet: Beim Arduino Nano 33 BLE sind einige Stellen einfach unbestückt.
Abbildung 2.21 Arduino Nano 33 BLE Sense
Das Blockdiagramm habe ich für den kompletten Ausbau, also den Arduino Nano 33 BLE Sense erstellt. Wie Abbildung 2.22 zeigt, bleibt es wegen der Kompaktheit des NINA-W306-Moduls trotzdem sehr übersichtlich.
Abbildung 2.22 Blockdiagramm des Arduino Nano 33 BLE Sense
Arduino Nano RP2040 Connect
In Abschnitt 2.2.11 stelle ich Ihnen den Raspberry Pi Pico vor, einen neuen, eigenständigen Mikrocontroller der Raspberry Pi Foundation. Der Raspberry Pi Pico ist ein Dual-Core-ARMCortex-M0+ ohne jegliche Netzwerkkommunikation. Es war also zu erwarten, dass die Arduino-Familie nicht lange auf eine Erweiterung warten muss. Mit dem Arduino Nano RP2040 Connect liegt nun ein kompaktes Arduino-Board auf Basis des RP2040 Mikrocontrollers der Raspberry Pi Foundation in Kombination mit dem u-blox NINAModul W102 vor (weitere Informationen finden Sie unter https://docs.arduino.cc/tutorials/nanorp2040-connect/rp2040-01-technical-reference). Abbildung 2.23 zeigt den Arduino Nano RP2040 Connect.
Abbildung 2.23 Arduino Nano RP2040 Connect
Das Board ist mit MEMS-Sensoren von STM (6-Achsen-IMU LSM6DSOXTR, MEMS Mikrofon MP34DT06JTR), einer RGB-LED, einem Crypto Co-Processor ATECC608A, einem sehr effizienten Leistungsteil und reichlich externem Flash (16 MB NOR Flash) ausgestattet. Drahtlose OTAUpdates werden dadurch möglich. Das in Abbildung 2.24 gezeigte Blockdiagramm zeigt die Komplexität des Arduino Nano RP2040 Connect.
Abbildung 2.24 Blockdiagramm Arduino Nano RP2040 Connect
2.1.3 Arduino-MKR-Serie Die Arduino-MKR-Serie (MKR steht für Maker) wurde entwickelt, um schnell IoT-Projekte entwickeln zu können. Die MKR-Boards sind Breadboard-kompatibel und so für das Prototyping geeignet. Außerdem sind sie mit einem leistungsfähigen ARM-Cortex-M0+-Mikrocontroller und Modulen ausgestattet, die WiFi-, SigFox-, LoRaWAN-, GSM- und Narrowband-Kommunikation bieten. Mithilfe spezieller Shields können Ethernet und CAN (Controller Area Network) hinzugefügt werden. Ein Arduino-MKR2UNO-Adapter schlägt die Brücke zu den Arduino-Standard-Shields. Auf der Website der Firma EXP Tech ist eine sehr gute Zusammenstellung der aktuell verfügbaren Mitglieder der Arduino-MKR-Serie und der zugehörigen Shields zu finden (https://www.exp-tech.de/ardunio-mkr-serie). Die folgenden Bilder (Abbildung 2.25 bis Abbildung 2.31) zeigen die verschiedenen Arduino-MKR-Boards. Die Spannungsversorgung aller Boards kann über USB oder VIN erfolgen, die Umschaltung erfolgt automatisch intern. Die Belegung der Buchsenleisten (2 × 14) ist für alle Boards identisch und gemäß der nachfolgenden Darstellung organisiert. 5V
VIN 3V3 GND RST TX RX SCL SDA MISO SCK MOSI D7 D6
USB AREF A0
A1
A2
A3
A4 A5 A6
D0
D1
D2
D3
D4 D5
Alle Boards mit einem JST-Stecker an der Unterkante sind für den Betrieb mit einem LiPo-Akku mit 3,7 V und 700 mAh vorbereitet. Die Ladeschaltung für den LiPo-Akku ist auf dem Board enthalten.
Die beiden Boards mit der grünen Phoenix-Klemme können von zwei AA- oder AAA-Batterien gespeist werden. Eine Ladung ist bei ihnen nicht möglich. Arduino MKRZero ist das einzige Board ohne Kommunikationsmodul, hat aber einen SD-CardAdapter, der beispielsweise das Abspielen von Musik erlaubt (siehe Abbildung 2.25).
Abbildung 2.25 Arduino MKRZero
Der Arduino MKR1000 WiFi (siehe Abbildung 2.26) basiert auf dem Atmel-ATSAMW25-SoC (System-on-a-Chip). Das SoC besteht aus drei Hauptblöcken: SAMD21-Cortex-M0+-32-Bit-ARM-MCU mit niedriger Leistung WINC1500 2,4 GHz 802.11 b/g/n WiFi mit geringem Stromverbrauch ECC508-Kryptoauthentifizierung
Abbildung 2.26 Arduino MKR1000 WiFi
Der Arduino MKR WiFi 1010 (siehe Abbildung 2.27) ist durch den Einsatz des ESP32-basierten NINA-W102-Moduls von u-blox eine signifikante Verbesserung gegenüber dem Arduino MKR1000 WiFi. Das Board besteht wieder aus drei Hauptblöcken: SAMD21-Cortex-M0+-32-Bit-ARM-MCU mit geringer Leistung 2,4 GHz 802.11 b/g/n WiFi der u-blox-NINA-W10-Serie ECC508-Kryptoauthentifizierung
Abbildung 2.27 Arduino MKR WiFi 1010
Wenn Sie die Kommunikation über SigFox ausprobieren wollen, dann hilft Ihnen ein Arduino MKR FOX 1200 (siehe Abbildung 2.28) weiter. Die SigFox-Kommunikation erfolgt über ein ATA8520-SigFox-Modul.
Abbildung 2.28 Arduino MKR Fox 1200
Die Kommunikation über LoRaWAN verbreitet sich zunehmend für IoT-Anwendungen, zumal es kostenfreie Angebote für die Server-Infrastruktur gibt und die Software selbst Open Source ist. Für Maker ist das eine interessante Möglichkeit, im IoT eigene Anwendungen zu betreiben. In meinem Buch »Einfache LoRaWAN-Knoten für das IoT«[ 4 ] habe ich verschiedene Möglichkeiten vorgestellt, einen LoRaWAN-Knoten zu erstellen und mit einem LoRaWAN-Server zu verbinden. Der Arduino MKR WAN 1300 wird als eine Möglichkeit gezeigt, mit der sich LoRaWAN ausprobieren lässt, und ich werde in Abschnitt 10.8 auf das in Abbildung 2.29 gezeigte Board zurückkommen.
Abbildung 2.29 Arduino MKR WAN 1300
Obwohl es schon für tot erklärt und mit Abschaltungsszenarien belegt wurde, stellt das mittlerweile betagte 2G-Netz für IoT-Anwendungen immer noch eine Alternative zu 3G/4G und 5G dar. In meinem Blogbeitrag »2G für IoT-Anwendungen« (https://ckblog2016.net/2019/04/16/2g-furiot-anwendungen/) habe ich gezeigt, wie kostengünstige GSM-Module sowie preiswerte und flexible Tarife für IoT-Anwendungen (M2M) durchaus interessant werden können. Der Arduino MKR GSM 1400 (siehe Abbildung 2.30) bietet durch die Kombination aus einem Atmel SAMD21 und einem SARAU201-GSM-Modul eine globale GSM-Konnektivität.
Abbildung 2.30 Arduino MKR GSM 1400
NB-IoT (NarrowBand-IoT) ist eine spezielle Erweiterung des LTE-Netzes (4G-Netzwerk), die für sehr große Massen und eine große Dichte an Endgeräten geeignet ist. NB-IoT bietet eine hohe Gebäudedurchdringung und ist eine weitere Möglichkeit, im IoT zu kommunizieren. Die Abdeckung der Telekom kann unter der URL https://tmap.telekom.de/tmap/resources/apps/coverage_checker/index.html?lang=de abgefragt werden. Wollen Sie im NB-IoT experimentieren, dann können Sie hierzu den Arduino MKR NB 1500 (siehe Abbildung 2.31) verwenden, der durch die Kombination aus einem Atmel SAMD21 und einem ublox-SARA-R410M-02B NB-IoT-Konnektivität bietet.
Abbildung 2.31 Arduino MKR NB 1500
Ich möchte es hier bei der Vorstellung der verschiedenen Arduino-MKR-Boards und den allgemeinen Bemerkungen belassen. In den Anwendungsbeispielen der folgenden Kapitel werde ich noch einmal auf diese Boards zurückkommen.
2.1.4 Arduino-Pro-Familie Millionen von Nutzern und Tausende von Unternehmen nutzen Arduino mittlerweile als Innovationsplattform. Die Arduino-Pro-Familie besteht aus einer Reihe von leistungsstarken, industrietauglichen Produkten, die direkt auf den professionellen Anwender zielt. Tabelle 2.4 zeigt die Mitglieder der Arduino-Pro-Familie im September 2022. Die Preisspalte habe ich hinzugefügt, um Ihnen zu zeigen, welche Boards auch beim Maker auf Interesse stoßen werden und welche hingegen direkt auf den professionellen Anwender zielen. Boards
Funktion
Preis
Portenta H7
Der Portenta H7 weist eine 32-Bit Dual-Core-Arm-Cortex-M7+M4-MCU STM32H747XI mit geringem Stromverbrauch auf. Der Cortex-M7 wird mit 480 MHz und der Cortex-M4 mit 240 MHz getaktet. An Speicher stehen 2 MB Flash und 1 MB RAM zur Verfügung. Für WiFi- und BLE5.1-Konnektivität sorgt ein Murata 1DX Device. Die On-Chip-GPU des STM32H747, der Chrom-ART Accelerator, ermöglicht den Anschluss eines externen Monitors. Neben der GPU enthält der Chip einen dedizierten JPEG-Encoder und -Decoder.
89,90 €
Portenta H7 Lite
Portenta H7 ohne WiFi/BLE und ohne Grafik
60 €
Boards
Funktion
Preis
Portenta Portenta H7 ohne Grafik H7 Lite Connected
82 €
Portenta X8
199 €
Der Portenta X8 ist ein sehr leistungsstarkes System-on-Module (SOM) mit vorinstalliertem Linux. Er weist die folgenden Ressourcen auf: NXP i.MX 8M Mini Cortex-A53 Quad-Core (1.8 GHz) + Cortex-M4 (400 MHz) und STM STM32H747 Dual-Core Cortex-M7 (480 MHz) + Cotex-M4 32 (240 MHz). Dieses eher industriellen Anwendungen vorbehaltene Board werde ich hier nicht weiter betrachten.
Nicla Nicla Sense ME ist ein Low-Power-Board und neuer Standard für eine Sense ME intelligente Sensorlösung, die sich durch einfache Integration der folgenden Bosch-Sensoren auszeichnet:
59 €
BHI260AP Bewegungssensor BMM150 Magnetometer BMP390 Drucksensor BME688 4-in-1-Gassensor inkl. Druck, Feuchtigkeit und Temperatur Nicla Vision
Nicla Vision ist ein kompaktes Kameraboard für die Analyse und Verarbeitung von Bildern on-board. Das Board verfügt über ein integriertes Mikrofon, einen Abstandssensor, einen intelligenten 6Achsen-Bewegungssensor und MicroPython-Unterstützung.
95 €
Edge Control
Edge Control ist eine für den Außeneinsatz konzipierte Überwachungsund Steuerungslösung. Es können Echtzeitdaten von intelligenten Sensoren erfasst und auf dem Board mit KI-Mitteln vorverarbeitet werden.
169 €
Portenta Breakout
Das Portenta-Breakout-Board macht alle Signale der High-DensitySteckverbinder des Portenta H7 durch herausgeführte Kontakte leicht zugänglich, sodass externe Hardwarekomponenten und Geräte schnell und einfach angeschlossen und getestet werden können. Über einen MIPI-20T-JTAG-Connector kann ein Debugger angeschlossen werden.
37,99 €
Carriers
Boards
Funktion
Preis
Portenta Machine Control
Portenta Machine Control ist eine vollständig zentralisierte, stromsparende Industriesteuereinheit, die Geräte und Maschinen antreiben kann. Die Maschinensteuerung ermöglicht eine Soft-SPS-Steuerung nach Industriestandard und kann an eine Reihe externer Sensoren und Aktoren mit isolierten digitalen I/Os, vier 20-mA-kompatiblen analogen I/Os, drei konfigurierbaren Temperaturkanälen und einem dedizierten I2C-Anschluss angeschlossen werden.
279,92 €
Das Portenta Vision Shield bietet dem Arduino Portenta neue Möglichkeiten, Computer-Vision-Anwendungen ausführen. Es besteht die Möglichkeit, es über WiFi oder Ethernet (Vision Shield LoRa) bzw. LoRa (Vision Shield Ethernet) mit der Cloud oder eigener Infrastruktur zu verbinden. Das Vision Shield Ethernet umfasst:
41 € 55 €
Shields Portenta Vision Shield
320-×-320-Pixel-Kamerasensor 100-Mbit/s-Ethernet-Anschluss Portenta Vision Shield
zwei integrierte Mikrofone für die gerichtete Schallerkennung JTAG-Anschluss zum Low-Level-Debugging SD-Kartenanschluss Beim Portenta Vision Shield LoRa wird 868/915 MHz LoRa-WirelessKonnektivität mit großer Reichweite anstelle des Ethernet-Interface verwendet.
Portenta
Cat. M1/NB IoT GNSS
Shield
Das Portenta Cat. M1/NB IoT GNSS Shield bietet 73 € Mobilfunkkonnektivität zu LTE-M (Cat M1) als auch zu NB-IoTNetzwerken mit der Option, eSIM-Technologie zu verwenden. Das Shield nutzt ein Cinterion-TX62-Funkmodul von Thales, das für hocheffiziente IoT-Anwendungen mit geringem Stromverbrauch entwickelt wurde, um eine optimierte Bandbreite und Leistung zu liefern. Mit diesem Shield können Sie über GPS, GLONASS, Galileo oder Beidou Gegenstände weltweit tracken.
Tabelle 2.4 Arduino-Pro-Familie
Einige Boards bzw. Carrier werde ich Ihnen noch mit Anwendungsbeispielen näherbringen. Auffällig ist, dass die Boards der Arduino-Pro-Familie auf schwarzem Basismaterial aufbauen. Arduino Portenta H7
Der Portenta H7 folgt dem Arduino MKR-Formfaktor, wurde jedoch mit den auf der Rückseite angeordneten 80-poligen High-Density-Steckverbindern der Portenta-Familie erweitert. Die wesentlichen Produktmerkmale hatte ich bereits in Tabelle 2.4 angegeben. Abbildung 2.32 zeigt die Draufsicht auf das Arduino-Portenta-H7-Board.
Abbildung 2.32 Arduino Portenta H7
Anstelle eines Blockdiagramms möchte ich hier das Pinout des Arduino Portenta H7 zeigen, welches ich zusätzlich noch kommentiert habe (Abbildung 2.33).
Abbildung 2.33 Arduino Portenta H7 Pinout (Bild: Arduino.cc)
An den Stiftleisten finden Sie die für Arduino typischen Bezeichnungen der I/O-Pins. Die Belegung der Anschlussleisten entspricht dem Format der MKR-Boards. Zusätzlich weist das Board einen sogenannten ESLOV Connector und einen Anschluss für einen LiPo-Akku auf. Das ESLOV-Protokoll basiert auf I2C. Der ESLOV Connector hat fünf Pins (einen mehr als der Standard I2C). Das zusätzliche Pin kann zur automatischen Konfiguration des Moduls und zur Handhabung von Schlafzuständen verwendet werden, um die Batterielebensdauer zu verlängern. Wenn Sie tiefer in die Hardware des Arduino Portenta H7 einsteigen möchten, dann empfehle ich Ihnen, mit der Dokumentation unter der URL https://docs.arduino.cc/hardware/portenta-h7 zu beginnen. Arduino Nicla Sense ME
Arduino Nicla Sense ME ist ein kompaktes Sensorboard mit vier Low-Power-Sensoren. Das Board ermöglicht leistungsstarke Datenvorverarbeitung von Bewegungs- und Umgebungsdaten mit
industrietauglichen Sensoren von Bosch, die Rotation, Beschleunigung, Druck, Feuchtigkeit, Temperatur, Luftqualität und CO₂-Werte präzise messen können. Folgende Sensoren kommen zum Einsatz: BHI260AP Smart Sensor mit integriertem Accelerometer und Gyroscope BMM150
Magnetometer mit typ. Messbereich von ±1300 μT in X und Y und ±2500 μT in Z
BMP390
Drucksensor mit einem Messbereich von 300 bis 1250 hPa
BME688
Umgebungssensor mit Messbereichen für Temperatur von –40 bis 85 °C, für rel. Luftfeuchtigkeit von 0 bis 100 %, für Druck von 300 bis 1100 hPa und iAQ von 0 bis 500
Tabelle 2.5 Sensoren für den Arduino Nicla Sense ME
Abbildung 2.34 zeigt die Draufsicht auf das Arduino-Nicla-Sense-ME-Board.
Abbildung 2.34 Arduino Nicla Sense ME
Neben den Sensoren ist links unten das ANNA-B112-SiP-Modul von u-blox zu sehen, das einen nRF52832 von Nordic als Controller mit BLE aufweist. Dieser Cortex-M4 gibt dem Arduino Nicla Sense ME genügend Performance für die Datenvorverarbeitung auf dem Board.
Abbildung 2.35 ANNA-B112 Blockdiagramm
Die vom Arduino Nicla Sense ME nach außen hin zur Verfügung gestellten I/O-Funktionen zeigt das Pinout in Abbildung 2.36.
Abbildung 2.36 Arduino Nicle Sense ME Pinout (Bild: Arduino.cc)
Das Pinout der Arduino Nicla Sense ME ist so gestaltet, dass es als Top auf den Arduino Portenta H7, aber auch auf jedes andere MKR-Board aufgesteckt werden kann (Abbildung 2.37). Zur Verdeutlichung habe ich den Arduino Nicla Sense ME eingefärbt.
Abbildung 2.37 Arduino Nicla Sense ME aufgesteckt auf Portenta H7
Wenn Sie tiefer in die Hardware des Arduino Nicla Sense ME einsteigen möchten, dann empfehle ich Ihnen, mit der Dokumentation unter der URL https://docs. arduino.cc/hardware/nicla-senseme zu beginnen. Arduino Nicla Vision
Arduino Nicla Vision ist ein kompaktes Kameraboard für die Analyse und Verarbeitung von Bildern on-board. Das Board verfügt über ein integriertes Mikrofon, einen Abstandssensor, einen intelligenten 6-Achsen-Bewegungssensor und MicroPython-Unterstützung. Nicla Vision kann auch mit einer Batterie betrieben werden und ist somit eigenständig. Folgende Sensoren kommen zum Einsatz: 1/5 UXGA CMOS Image Sensor GC2145
Hochwertiger 2-Megapixel-CMOS-Bildsensor für Kameraanwendungen und Digitalkameras. Der GC2145 verfügt über ein aktives Pixel-Array mit 1616 × 1232, einen On-Chip-10-Bit-ADC und einen Imageprozessor.
LSM6DSOXTR 6-Achsen-IMU ermöglicht die Gewinnung von 3D-Gyroskope- und 3D6-Axis IMU Beschleunigungsmessdaten. Es ist möglich, maschinelles Lernen auf der IMU für die Gestenerkennung durchzuführen und so den Hauptprozessor von Berechnungen zu entlasten. MP34DT06JTR Ultrakompaktes, stromsparendes, digitales MEMS-Mikrofon mit Digital MEMS Kugelcharakteristik, einem kapazitiven Sensorelement und einer ICMicrophone Schnittstelle. Tabelle 2.6 Sensoren für den Arduino Nicla Vision
Abbildung 2.38 zeigt die Draufsicht auf das Arduino-Nicla-Vision-Board.
Abbildung 2.38 Arduino Nicla Vision
Nicla Vision ist mit einem STM32H747AII6 Dual-Core Cortex-M7 (getaktet mit bis zu 480 MHz) und einem Cortex-M4 (getaktet mit bis zu 240 MHz) ausgestattet. Die vom Arduino Nicla Vision nach außen hin zur Verfügung gestellten I/O-Funktionen zeigt das Pinout in Abbildung 2.39.
Abbildung 2.39 Arduino Nicla Vision Pinout (Bild: Arduino.cc)
Das Pinout der Arduino Nicla Vision ist wieder so gestaltet, dass es als Top auf den Arduino Portenta H7, aber auch auf jedes andere MKR-Board aufgesteckt werden kann (Abbildung 2.37). Zur Verdeutlichung hatte ich den dort verwendeten Arduino Nicla Sense ME eingefärbt. Wenn Sie tiefer in die Hardware des Arduino Nicla Vision einsteigen möchten, dann empfehle ich Ihnen, mit der Dokumentation unter der URL https://docs.arduino.cc/hardware/nicla-vision zu beginnen. Arduino-Portenta-Breakout-Board
Das Arduino-Portenta-Breakout-Board führt die auf den rückseitig angeordneten 80-poligen High-Density-Steckverbindern des Arduino Portenta H7 auf handhabbare Anschlüsse bzw. Stiftleisten. Neben den Stiftleisten werden Ethernet- und USB-Anschluss, SD-Karten- und Batteriehalterung, ein Camera Connector sowie ein Anschluss für externe 5-V-DC zur Verfügung gestellt. Abbildung 2.40 zeigt das Arduino-Portenta-Breakout-Board von oben.
Abbildung 2.40 Arduino Portenta Breakout Board
Abbildung 2.41 zeigt stilistisch die Rückseite des Arduino Portenta H7 mit den beiden 80-poligen High-Density-Steckverbindern und deren Belegung. Wollen Sie in einer Anwendung das Potenzial des Arduino Portenta H7 ausschöpfen, dann kommen Sie um die Verwendung dieser beiden Anschlussleisten nicht herum. Auch die Portenta Shields setzen genau da an und erweitern das Board beispielsweise um einen Kamerasensor (Portenta Vision Shield), der über LAN oder LoRa angebunden werden kann.
Abbildung 2.41 Arduino Portenta H7 High-Density Connectors
Abbildung 2.42 zeigt abschließend einen auf das Arduino-Portenta-Breakout-Board aufgesteckten Arduino Portenta H7, den ich zur besseren Sichtbarkeit rot hinterlegt habe. Außerdem ist grün hinterlegt noch der JTAG-Connector markiert, über den ein externer Debugger angeschlossen werden kann. Zum Debugging komme ich in Abschnitt 4.8.
Abbildung 2.42 Arduino Portenta H7 aufgesteckt auf Portenta Breakout Board
2.1.5 Arduino Yún Wollte man bislang einen Arduino so erweitern, dass er netzwerkfähig (LAN) wird, dann konnte man beispielsweise einen Arduino Uno mit einem Ethernet-Shield versehen oder man verwendete gleich einen Arduino Ethernet. Das Ethernet-Shield – aber auch der Arduino Ethernet – stellen ein Ethernet-Interface auf Basis des Bausteins W5100 (WIZnet Hardwired TCP/IP Embedded Ethernet Controller) zur Verfügung. Für eine WiFi-Verbindung ins Netzwerk können Sie aber auch den bereits erwähnten Arduino Uno WiFi Rev2 einsetzen. Der Arduino Yún Rev2 unterscheidet sich von anderen Arduino-Boards dadurch, dass er neben einem ATmega32u4-Mikrocontroller (Arduino Leonardo) noch einen Atheros AR9331 aufweist, auf dem ein Embedded Linux läuft. Die Kommunikation beider Controller macht den Arduino
Yún zu einer leistungsstarken Plattform für vernetzte Linux-Anwendungen und IoT-Projekte, kombiniert mit der Einfachheit des Arduino. Der Arduino Yún ist dem Arduino Leonardo insofern ähnlich, als dieser auch einen ATmega32u4 mit integriertem USB-Controller aufweist, was einen zweiten Controller wie den FT232 unnötig macht. Dies erlaubt es dem Arduino Yún gegenüber einem angeschlossenen Computer zusätzlich zum virtuellen CDC-(Communication Device Class-)COM-Port als Maus, Keyboard oder andere HID-Schnittstelle zu erscheinen. Abbildung 2.43 zeigt die Frontseite des Arduino Yún Rev2, die durch das Dragino HE (engl. Dragino Core) dominiert wird. Dragino HE ist ein Minimalsystem auf Basis eines Atheros-AR9331-Chipsets, das einen MIPS24Kc-Prozessor mit 400 MHz Taktfrequenz sowie 64 MB RAM und 16 MB Flash integriert. Auf dem Dragino HE läuft Linino, eine OpenWrt-Linux-Distribution, die 2,4-GHz-WiFi sowie zahlreiche Schnittstellen wie Ethernet, USB, UART und viele GPIOs unterstützt.
Abbildung 2.43 Arduino Yún – Frontseite
Auf der Rückseite des Arduino Yún Rev2 finden Sie links unten einen SD-Karten-Halter und den zugehörigen USB-HUB-2.0- und SD/MS-Card-Reader-Controller AU6351GL. Darüber ist der ATmega32u4 inklusive Pegelwandler und anderer Bestandteile angeordnet. Technische Detailinformationen zum Dragino HE und zum MIPS-24Kc-Prozessor finden Sie unter den folgenden URLs: https://www.dragino.com/products/linux-module/item/87-he.html https://s3-eu-west-1.amazonaws.com/downloads-mips/documents/ MD00346-2B-24K-DTS04.00.pdf Wenn Sie die Linux-Funktionalität mit einem bestehenden Arduino kombinieren und etwas Geld sparen wollen, dann kann der Einsatz eines Dragino Yún Shields in Betracht gezogen werden. Bei Amazon können Sie das Dragino Yún Shield für unter 50 € kaufen. Abbildung 2.44 zeigt die Frontseite des Dragino Yún Shields (https://www.dragino.com/products/linuxmodule/item/87-he.html).
Abbildung 2.44 Dragino Yún Shield
Im Folgenden gehe ich noch auf einige Besonderheiten des Arduino Yún ein, damit Sie nach der Beschaffung dieses nicht so preiswerten Bauteils keine unliebsamen Überraschungen erleben. Spannungsversorgung
Die Spannungsversorgung über das USB-Interface ist die für den Arduino übliche Art der Versorgung. Außerdem kann über diesen Anschluss mit der Arduino IDE kommuniziert werden. Achtung: Spannungsregler Der Arduino Yún hat keinen Spannungsregler on-board, deshalb müssen Sie bei einer Spannungsversorgung über den Anschluss VIN sicherstellen, dass die angelegte Betriebsspannung 5 V DC geregelt ist.
Details zur Spannungsversorgung: VIN – externer Anschluss zur Versorgung mit 5 V DC 5V – interne 5-V-Spannung, die Spannung kann von VIN oder USB kommen 3V3 – interne 3,3-V-Spannung, erzeugt von einem mit 50 mA belastbaren On-Board-Regler GND – Masse IOREF – Spannung der I/O-Pins (VCC = 5 V)
Speicher
Der im Arduino Yún eingesetzte ATmega32u4 weist 32 KB Flash-Memory auf, wovon 4 KB durch den Bootloader belegt sind. Es stehen außerdem 2,5 KB RAM und 1 KB EEPROM zur Verfügung. Der Dragino HE stellt 64 MB DDR2-RAM und 16 MB Flash-Memory zur Verfügung. Werksseitig ist die Linux-Distribution Linino (OpenWRT) im Flash-Memory installiert. Dieses Factory-Image kann verändert werden. Eine Rückkehr zum Factory-Image ist möglich. Über den SD-Karten- und USB-Anschluss können Sie jederzeit den vorhandenen Speicher entweder durch eine Micro-SDKarte oder einen Memory-Stick erweitern.
I/O
Alle am Arduino Yún nach außen geführten I/O-Pins sind Pins des ATmega32u4. Die Programmierung dieser Pins erfolgt Arduino-konform, wie Sie in Abschnitt 4.7 lernen werden. Alle Pins arbeiten mit 5-V-Pegeln (IOREF) und können pro Pin maximal 40 mA Strom liefern oder aufnehmen. Es sind Pull-up-Widerstände im Bereich von 20 bis 50 kΩ vorhanden, die aber per Default nicht aktiviert (disabled) sind. Einige Pins weisen Alternativfunktionen auf. Tabelle 2.7 stellt diese Belegung im Detail dar. Funktion
Pin
Beschreibung
Serial
0 (RX) 1 (TX)
Empfangen (RX) und Senden (TX) serieller Daten mit TTL-Pegel von der ATmega32u4-Hardware-Schnittstelle
TWI (I2C)
2 (SDA) 3 (SCL)
I2C-Interface
External Interrupts
0 (INT2) 1 (INT3) 2 (INT1) 3 (INT0) 7 (INT4)
Diese Pins können als Interrupt-Leitungen verwendet werden.
PWM
3, 5, 6, 8-Bit-PWM-Ausgang 9, 10, 11, 13
SPI
ICSP- SPI-Kommunikation Header Die SPI-Pins sind beim Arduino Yún nur am ICSP-Header verfügbar. Das kann bei der Verwendung von Arduino-Shields zu Einschränkungen führen. Die SPI-Pins sind auch an den AR9331 geführt. ATmega32u4 und AR9331 können auch über SPI kommunizieren.
LED
13
Das ist die bekannte interne LED, die mit Pin 13 fest kontaktiert ist (Hi = LED an, Lo = LED aus).
Funktion
Pin
Beschreibung
Analogeingang A0–A5, Der Arduino Yún hat 12 analoge Eingänge (A0–A11) mit einer 4 (A6) Auflösung von 10 Bit. 6 (A7) Per Default ist der Eingangsspannungsbereich 0 bis 5 V. 8 (A8) 9 (A9) 10 (A10) 12 (A11) AREF
Referenzspannung für die Analogeingänge.
Yún RST
Lo an diesem Pin erwirkt einen Reset des AR9331. Das LinuxSystem wird einem Reboot unterzogen. Alle im RAM befindlichen Daten gehen verloren. Laufende Programme werden abgebrochen. Dateien können beschädigt werden.
32U4 RST
Lo an diesem Pin bewirkt einen Reset des ATmega32u4.
WLAN RST
Die primäre Funktion ist, das WiFi-Interface auf Werkseinstellung zurückzusetzen. Die Werkseinstellung besteht im Access Point Mode (AP) und der festen IP-Adresse 192.168.240.1. In dieser Einstellung kann der Arduino Yún konfiguriert werden. Das Zurücksetzen der WiFiKonfiguration hat ein Reboot des Linux-Systems zur Folge. Um die WiFi-Konfiguration zurückzusetzen, müssen Sie den Taster WLAN RST über 5 Sekunden gedrückt halten. Die zweite Funktion ist, das Linux-System auf die Werkseinstellungen (Factory-Image) zurückzusetzen. Hierzu muss der Taster WLAN RST für 30 Sekunden gedrückt bleiben. Alle im Flash-Memory gespeicherten Dateien gehen verloren.
Tabelle 2.7 Pinbelegung des Arduino Yún
Zusätzlich verfügt der Arduino Yún über eine Reihe von LEDs auf dem Board, die die folgenden Funktionen anzeigen: Bezeichnung Funktion RX
Serial Receiver
TX
Serial Transmitter
L
LED an IO13
WAN
WAN-(Ethernet-)Indikator
ON
Power-Indikator
Bezeichnung Funktion WLAN
WLAN-(WiFi-)Indikator
USB
USB
Tabelle 2.8 Funktion der Arduino-Yún-LEDs
Kommunikation
Der Arduino Yún hat mehrere Schnittstellen, um mit einem Computer, einem weiteren Arduino oder mit einem anderen Mikrocontroller kommunizieren zu können. Der ATmega32u4 bietet eine Hardware-UART mit TTL-Pegeln für die serielle Kommunikation. Diese Schnittstelle (IO0 und IO1) wird zur seriellen Kommunikation zwischen dem ATmega32u4 und dem Atheros AR9331 verwendet. Die Bridge-Library ist für die softwareseitige Umsetzung der Kommunikation zwischen den beiden Prozessoren zuständig. Die Kommunikation über die Bridge-Library lernen Sie später bei den Anwendungsbeispielen kennen. Außerdem bietet der ATmega32u4 die Möglichkeit der seriellen Kommunikation über USB. Er wird dann von einem angeschlossenen PC als virtueller COM-Port betrachtet. Über diese mit einem Micro-USB-Steckverbinder ausgestattete Schnittstelle erfolgt üblicherweise der SoftwareUpload vom PC zum Arduino. Weiter kann diese Schnittstelle zum Monitoring eingesetzt werden. Alternativ können diese Funktionen auch von der Netzwerkschnittstelle wahrgenommen werden. Der ATmega32u4 unterstützt auch I2C- und SPI-Kommunikation. Die Ethernet- und WiFiSchnittstellen werden vom Atheros AR9331 bereitgestellt. Der Arduino Yún bietet durch die Linux-Unterstützung eine weitere USB-Schnittstelle, die HostFunktionen bereitstellt. Über USB können hier Memory-Sticks zur Speichererweiterung, aber auch Tastatur, Maus und Webcam angeschlossen werden. Eventuell müssen dazu weitere Softwarepakete installiert werden.
2.2 Arduino-kompatible Boards Aufgrund des Open-Source-Charakters des Arduino gibt es zahlreiche Nachbauten (Clones). Es gibt aber auch Arduinokompatible Boards, die nur den einen oder anderen Aspekt des Arduino-Ansatzes umsetzen. Manchmal sind das die Buchsenleisten, um von Arduino-Shields zu profitieren, ein anderes Mal ist es die Programmierbarkeit, um spezielle Hardware in der Arduino-Umgebung betreiben zu können. In diesem Abschnitt zeige ich Ihnen interessante Erweiterungen, die heute unbedingt zum Arduino-Imperium gehören und oft mit neuen und zusätzlichen Leistungsmerkmalen ausgestattet werden. Einige der hier vorgestellten Arduino-kompatiblen Boards werde ich in den folgenden Kapiteln mit Programmbeispielen versehen.
2.2.1 Seeeduino v4.2 Seeed ist eine chinesische Firma, die seit 2008 der globalen MakerCommunity Open-Source-Hardware für deren Projekte zur Verfügung stellt. Kennzeichnend für aktuelle Seeed-Komponenten ist der Einsatz des Grove-Verbindungssystems, eines modularen und standardisierten Steckverbindersystems für das Prototyping. Seeed ist seit Langem eine offizielle Partnerschaft mit Arduino eingegangen. Neben Arduino-Produkten wie den Arduino Uno und anderen bietet Seeed eine Vielzahl von Produkten an, die für Ihre Projektanforderungen mit Arduino kompatibel sind. Ich zeige Ihnen mit dem Seeeduino v4.2 ein Beispiel
(https://wiki.seeedstudio.com/Seeeduino_v4.2/) für einen ArduinoUno-kompatiblen Mikrocontroller (siehe Abbildung 2.45).
Abbildung 2.45 Seeeduino v4.2
Das Seeeduino v4.2 unterscheidet sich in wenigen, aber durchaus wichtigen Punkten vom Arduino Uno. Wenn Sie die Schaltpläne beider Boards vergleichen (keine Angst, ich habe das für Sie getan), dann sehen Sie drei Grove-Anschlüsse 1. Die beiden Anschlüsse links führen an den I2C-Bus und der Anschluss rechts führt an die serielle Schnittstelle (Tx, Rx). Über dem Power-Anschluss finden Sie einen Schalter 2, der die Betriebsspannung des ATmega328P entweder auf 5 V oder auf 3,3 V einstellt. Durch diese Maßnahme bekommt man eine sehr einfache Anpassung an die Spannungsversorgung der Peripherie.
2.2.2 LilyPad Arduino LilyPad ist tragbare Elektronik, die von Leah Buechley (http://leahbuechley.com/) am MIT Media Lab entwickelt und
gemeinsam mit SparkFun in Komponenten umgesetzt wurde. Jede LilyPad-Komponente wurde so entworfen, dass die Platinen keine Ecken aufweisen und mit ihren großen Kontaktflächen in bzw. an die Kleidung genäht werden können. Außerdem sind alle Komponenten waschbar. Um mit LilyPad zu starten, müssen Sie sich zuerst mit einem LilyPad Arduino ausrüsten, den es mittlerweile in unterschiedlichen Bauformen gibt. Ich möchte hier nur auf den klassischen LilyPad Arduino auf Basis des ATmega328 eingehen, da dieser mit dem Arduino Uno vergleichbar ist. Abbildung 2.46 zeigt die Frontseite des LilyPad Arduino. Die runde Bauform soll die Verarbeitung in Textilien erleichtern und ein Verhaken im Gewebe verhindern. Die breiten Anschlusspunkte können Sie an der textilen Unterlage annähen, und mit elektrisch leitenden Fäden können weitere Komponenten verbunden werden.
Abbildung 2.46 LilyPad Arduino
Der LilyPad Arduino besteht aus einem ATmega328 mit ArduinoBootloader und einer minimalen Anzahl externer Komponenten. Die Betriebsspannung des Boards muss zwischen 2 V und 5 V liegen. Mit dem LilyPad Deluxe Kit (siehe Abbildung 2.47) hatte man früher einen guten Ausgangspunkt für erste Experimente. SparkFun hat das Kit aber aus dem Programm genommen, und Sie müssen sich die Komponenten selbst zusammenstellen. Grundsätzlich ist das kein Problem, denn zuerst können Sie mit Standardbauteilen das Projekt starten und nach erfolgreichem Test die Komponenten durch LilyPad-Komponenten ersetzen.
Abbildung 2.47 LilyPad Deluxe Kit
Da der LilyPad Arduino in der Bauform, die Sie in Abbildung 2.46 sehen, keine USB-Serial-Bridge auf dem Board aufweist, muss diese
extern angeschlossen werden. In Kapitel 13, »Projektideen für den Arduino«, zeige ich Ihnen ein Beispiel für eine Sicherheitsblinkschaltung, die beispielsweise auf der Jacke von Kindern angebracht werden kann. Bei Dunkelheit schalten sich blinkende LEDs ein und machen so auf den Passanten aufmerksam.
2.2.3 Maduino GPRS A6 Maduino GPRS A6 ist ein kostengünstiger Netzwerkknoten für das Internet of Things (IoT). Der Hersteller Makerfabs, mit Sitz in Shenzhen, China, hat auf dem Board einen Mikrocontroller ATmega328, ein GPRS/GSM-Modul AI-Thinker A6 und ein integriertes Power-Management zusammengestellt (siehe Abbildung 2.48). Das GPRS/GSM-Modul AI-Thinker A6 unterstützt Quadband mit 850, 900, 1800 und 1900 MHz, das jedes GSM-Netzwerk abdeckt. In Verbindung mit einer SIM-Karte können Daten über GPRS übertragen werden. In Abschnitt 10.9 werde ich auf die GSMKommunikation eingehen und weitere Möglichkeiten aufzeigen. Das Board kann über den USB-Anschluss mit Spannung versorgt werden. Allerdings muss der USB-Port in der Lage sein, mehr als die üblichen 500 mA zu liefern, da das GPRS/GSM-Modul AI-Thinker A6 im Sendemodus recht stromhungrig ist.
Abbildung 2.48 Maduino GPRS A6 mit Stiftleisten und externer Antenne
Außerdem weist das Board einen Anschluss für einen LiPo-Akku auf, der über ein Solarpanel geladen werden kann. Der Anschluss für ein Solarpanel ist ebenfalls vorhanden. Auf der Rückseite des Boards sind Slots für eine Micro-SIM- und eine Micro-SD-Karte vorhanden. Das Modul kann über die Arduino IDE programmiert werden und verhält sich wie ein Arduino Uno. Im Wiki des Herstellers Makerfabs finden Sie Hinweise zur Inbetriebnahme und Programmierung (https://makerfabs.com/wiki/index.php?title=Maduino_GPRS_A6). Hinweise zu einem Firmware-Update des GPRS/GSM-Moduls AIThinker A6 sind unter der URL https://www.iot-experiments.com/aithinker-a6-module-firmware-update/ zu finden.
2.2.4 BBC micro:bit bzw. Calliope mini Seit 2017 ist der BBC micro:bit genannte Mikrocontroller der BBC für den Einsatz in den Schulen Großbritanniens verfügbar. Das deutsche Calliope-Team (https://calliope.cc/) ist mit der Mission angetreten, jedem Schulkind in Deutschland ab der 3. Klasse einen spielerischen Zugang zur digitalen Welt zu ermöglichen. Der
Calliope mini ist ein kleiner Mikrocontroller, der den Anforderungen der Grundschule gerecht werden soll. Beide Mikrocontroller-Boards sind technisch vergleichbar ausgestattet und weisen als Kern einen nRF51822-Mikrocontroller von Nordic Semiconductors auf. Der nRF51822 ist ein Multiprotokoll-System-on-a-Chip (SoC), das sich ideal für Bluetooth-Low-Energy-(BLE-) und Ultra-Low-PowerWireless-Anwendungen bei 2,4 GHz eignet. Kern des nRF51822-SoC ist eine 32-Bit-ARM-Cortex-M0-CPU mit 256 KB Flash-Speicher und 16 KB RAM. Ein eingebetteter 2,4-GHzTransceiver unterstützt sowohl BLE als auch den Nordic-Gazell-2,4GHz-Protokoll-Stack. Zusätzlich ist noch ein NXP MKL26Z (CortexM0+) auf den Boards, der als Interface-Prozessor für den USB-Port dient. Die Stromversorgung der beiden Boards erfolgt über einen Micro-USB-Anschluss, der auch zur Datenübertragung genutzt wird, oder über einen JST-Anschluss für eine Batterie. Auch wenn sie im Kern sehr vergleichbar sind, kommen die beiden Mikrocontroller-Boards doch in sehr unterschiedlicher Form daher. Abbildung 2.49 zeigt beide Boards im direkten Größenvergleich.
Abbildung 2.49 »BBC micro:bit« und »Calliope mini«
Beim BBC micro:bit ist an der Unterkante eine Platinensteckerleiste mit GPIO-Anschlüssen (auch »Goldfinger« genannt) vorhanden, von denen drei eine Verbindung mittels Krokodilklemmen oder Bananensteckern ermöglichen. Verschiedene dieser Anschlüsse sind über einen Analog/Digital-Umsetzer (ADU) als analoge Eingänge sowie für eine Kommunikation über I2C oder SPI nutzbar. Zwei weitere über Krokodilklemmen bzw. Bananenstecker zugängliche Kontakte (3 V/GND) stellen eine Stromversorgung für externe Hardware bereit. Diese Platinensteckerleiste ermöglicht eine einfache Verbindung mit Erweiterungsboards. Das BBC-micro:bit-Edge-ConnectorBreakout-Board ist eine solche Erweiterung. Es gibt aber weitere, auf die ich noch verweisen werde. Beim Calliope mini wurde diese Platinensteckerleiste nicht übernommen, da wegen der viel zu eng liegenden Kontakte im Schuleinsatz damit gerechnet werden müsste, dass die Schüler ständig Kurzschlüsse verursachen. Außerdem konnten bei einer notwendigen Anpassung noch Bauteile vorgesehen werden, die gerade im Schuleinsatz tolle Experimente erlauben. Hier sind insbesondere der Lautsprecher, eine RGB-LED, ein Mikrofon und ein Motortreiber (H-Brücke) zu nennen. Zusätzlich stellen die beiden Grove-Konnektoren einen I2C-Bus, einen UART-Anschluss sowie einen analogen Eingang zur Verfügung, mit dem Sensoren oder Aktoren des umfangreichen Grove-Systems verbunden werden können. Kompatibilität Obwohl bei den Anpassungen großer Wert auf maximale Kompatibilität zum britischen Vorbild gelegt wurde, sorgt die
abweichende Ausstattung und eine veränderte Pinbelegung für einige Änderungen.
Im Artikel »Mikrocontroller nicht nur für die Schule!«[ 5 ] habe ich gezeigt, welche Unterschiede zu beachten sind, wenn Sie für beide Mikrocontroller in MicroPython programmieren. Teilweise sind diese Unterschiede auch in der Arduino IDE zu beachten.
2.2.5 SparkFun Pro nRF52840 Mini Das SparkFun Pro nRF52840 Mini (https://www.sparkfun.com/products/15025) ist ein Entwicklungsboard für das nRF52840-System-on-a-Chip (SoC) von Nordic Semiconductor. Das SoC ist eine Kombination aus einer ARMCortex-M4-CPU und einem 2,4-GHz-Bluetooth-Modul (Raytac MDBT50Q-P1M-Modul). Das kompakte Entwicklungsboard (siehe Abbildung 2.50) weist zahlreiche I/O-Pins sowie Pins für die Spannungsversorgung auf. Die USB-Schnittstelle (mit der nativen USB-Unterstützung des nRF52840) dient zur Programmierung und zur seriellen Kommunikation sowie zur Spannungsversorgung. Ein Anschluss für einen LiPo-Akku, der über ein entsprechendes Ladegerät geladen wird, ist ebenso vorhanden wie der SparkFun-typische QwiicAnschluss. Den Qwiic-Anschluss selbst beschreibe ich in Abschnitt 3.4.1. Ein/Aus-Schalter, Reset-Taste und User-LED bzw. User-Taste ergänzen die extern verfügbaren Ressourcen.
Abbildung 2.50 SparkFun Pro nRF52840 Mini
Das nRF52840 weist zahlreiche Features auf, von denen hier nur einige beispielhaft gelistet werden können. Das über 600 Seiten umfassende Datenblatt https://infocenter.nordicsemi.com/pdf/nRF52840_PS_v1.1.pdf steht auf der Nordic-Website zum Download zur Verfügung. Folgende Features sind wichtig: Bluetooth 5, IEEE 802.15.4-2006, 2,4 GHz Transceiver ARM Cortex-M4-32-Bit-Prozessor mit FPU, 64 MHz zahlreiche Sicherheitsfunktionen flexibles Power-Management Betriebsspannung 1,7 V bis 5,5 V DC 1 MB Flash-Memory und 256 KB RAM USB 2.0, SPI, NFC-A 48 GPIO-Pins Nordic SoftDevice ready 8-Kanal-, 12-Bit-, 200-kSPS-AD-Umsetzer Temperatursensor 4 × 4-Kanal-PWM
I2S 5 × 32-Bit-Timer/Counter bis zu 4 × SPI Master und 3 × SPI Slave bis zu 2 × I2C-Master/Slave 2 × UART Quadrature Decoder (QDEC) 3 × RTC Dieser Auszug aus den technischen Eigenschaften weist den SparkFun Pro nRF52840 Mini als sehr leistungsfähiges Arduinokompatibles Board aus.
2.2.6 STM32 Nucleo Die Mikrocontroller von STMicroelectronics sind in Entwicklerkreisen sehr verbreitet. Wenn Sie in die Website des Herstellers schauen, dann finden Sie unter »STM32 32-bit Arm Cortex MCUs« allein 980 Einträge. Das ist schier unübersichtlich und verwirrend. Durch ein sehr großzügiges Marketingprogramm werden die Mikrocontroller-Boards von ST vielen Nutzern kostenlos zur Verfügung gestellt. Auf Messen, wie der embedded world in Nürnberg, kann man das an den Schlangen vor dem ST-Stand ablesen. Selbst wenn man die Boards über ST direkt oder über einen der zahlreichen Distributoren bezieht, sind die Preise sehr moderat. Entwickler energieeffizienter Embedded Systeme verfügen mit den STM32-Mikrocontrollern über eine große Auswahl an Möglichkeiten, um ein ausgewogenes Verhältnis zwischen Leistung,
Sicherheit und Kosteneffektivität zu erzielen. Diese Reihe umfasst beispielsweise die folgenden Mikrocontroller: STM32L0 (Arm Cortex-M0+) STM32L1 (Arm Cortex-M3) STM32L4 (Arm Cortex-M4) STM32L5 (Arm Cortex-M33) Diese auch in anderen Designs weitverbreiteten Mikrocontroller wird man in der Regel in Form eines Evaluation- oder PrototypingBoards einsetzen. Abbildung 2.51 zeigt ein Nucleo-L476RG-Board als Beispiel für einen 64-Pin-STM32-Mikrocontroller. Beim Nucleo-L476RG handelt es sich um ein Ultra-Low-Power-Board mit ST-Morpho- 1 sowie Arduino-I/O-Anschlüssen 2. Der obere Teil des Boards enthält die ST-Link-Elektronik, die bei allen Nucleo-Boards gleich ist. Diesen Teil könnten Sie entfernen, aber dann verlieren Sie die Möglichkeit, das System über den Mini-USBAnschluss mit Strom zu versorgen. Der untere Teil des Boards ist der eigentliche Mikrocontroller-Teil um den STM32L476RGMikrocontroller. Die Arduino-Steckverbinder 2 bieten die Möglichkeit, Arduino-Shields anzuschließen.
Abbildung 2.51 Nucleo-L476RG
Als weiteres praktisch baugleiches Board mit einem STM32L053R8 (Cortex-M0+) habe ich das Nucleo-L053R8-Board eingesetzt. Bis auf den schwächeren Mikrocontroller ist die Handhabung gleich.
2.2.7 Teensy 4.x Die Teensy-USB-Development-Boards sind komplette, USB-basierte Mikrocontroller-Entwicklungssysteme. Teensy 4.0 ist das erste Teensy-Board mit einem mit 600 MHz getakteten NXP iMXRT1062 Cortex-M7 Mikrocontroller und leistungsstarker Peripherie im Formfaktor Teensy 1,4 × 0,7 Zoll. Abbildung 2.52 zeigt das kompakte Board von oben.
Mit Teensy 4.1 erfolgte eine Erweiterung des Teensy 4.0 um ein Ethernet-Interface.
Abbildung 2.52 Teensy 4.0
Weitere Informationen zu Teensy 4.1 finden Sie unter https://www.pjrc.com/store/teensy41.html. Teensy 4.1 konnte ich bislang noch nicht testen, weshalb die folgenden Aussagen für Teensy 4.0 gelten. Nachdem das Teensyduino-Installationsprogramm die erforderlichen Unterstützungsdateien der Arduino IDE hinzugefügt hat, kann Teensy aus der Arduino IDE heraus programmiert werden. Installation und Inbetriebnahme selbst beschreibe ich in Abschnitt 4.7.6. Durch den Einsatz des NXP iMXRT1062-Mikrocontrollers weist Teensy 4.0 folgende technische Spezifikationen auf: ARM Cortex-M7 mit 600 MHz 2048 KB Flash-Memory, 1024 KB RAM 2 USB-Ports (480 Mbit/s) 3 CAN-Bus 2 I2S Digital Audio, 1 S/PDIF Digital Audio 1 SDIO (4 Bit) native SD
3 SPI, 3 I2C-Bus, 7 Serial Interfaces 32 DMA-Kanäle 31 PWM-Pins, 40 digitale I/O-Pins 14 analoge Eingänge, 2 ADCs On-Chip Cryptographic Acceleration Random Number Generator RTC Mit diesen Merkmalen kann Teensy 4.0 als echtes High-End-Modell der hier vorgestellten Arduino-kompatiblen Boards bezeichnet werden. Die Benchmarks werden das auch verdeutlichen. Für Teensy 4.1 gilt das gleichermassen.
2.2.8 ESP8266 Der ESP8266 der chinesischen Firma Espressif bietet eine vollständige und eigenständige WiFi-Netzwerklösung. Er kann verwendet werden, um WiFi-Netzwerkfunktionen von einem anderen Anwendungsprozessor auszulagern oder eine Anwendung komplett zu hosten. Im ersten Fall kann zu jedem mikrocontroller-basierten Design durch einfache serielle Verbindung ein drahtloser Internetzugang hinzugefügt werden. Im zweiten Fall kann eine gehostete Anwendung direkt von einem externen Flash gestartet werden und selbst einen Zugang zum Internet aufbauen. Der integrierte Cache des ESP8266 verbessert die Leistung des Systems in solchen Anwendungen.
Der ESP8266 gehört mit zu den am stärksten integrierten WiFiChips in der Branche: Antennenschalter, HF-Balun, Leistungsverstärker, rauscharmer Empfangsverstärker, Filter und Power-Management sind integriert. Es ist nur eine minimale externe Beschaltung erforderlich, woraus ein minimaler Bedarf an PCB-Fläche resultiert. Sein Datenblatt, seine Systembeschreibung und seine technische Referenz beschreiben den ESP8266 im Detail und sind auf der Website des Herstellers Espressif unter https://www.espressif.com/en/products/hardware/esp8266ex/resourc es zu finden. ESP8266EX-Chips (siehe Abbildung 2.53) sind die Basis verschiedenster ESP8266-Module.
Abbildung 2.53 ESP8266EX-Chips
Im Folgenden sind nur die Hauptmerkmale des ESP8266EX aufgelistet. Ich bleibe bei den originalen Bezeichnungen, da es dabei kaum zu Missverständnissen kommen dürfte. Für detaillierte
Spezifikationen muss das umfangreiche Datenblatt konsultiert werden. Network standards 802.11 b/g/n Integrated low power 32-bit MCU Integrated 10-bit ADC Integrated TCP/IP protocol stack Integrated PLL, regulators, and power management units WiFi 2,4 GHz, support WPA/WPA2 Support STA/AP/STA+AP operation modes SDIO 2.0, SPI, UART, I2C, I2S, IR Remote Control, PWM, GPIO Deep sleep power < 5 µA Wakeup and transmit packets in < 2 ms Super small module size (11,5 mm × 11,5 mm) Operating temperature range –40 °C ~ 125 °C FCC, CE, TELEC, WiFi Alliance and SRRC certified Die ESP8266EX-Chips werden meist in Modulform verbaut und stehen in sehr unterschiedlichen Bauformen zur Verfügung. Abbildung 2.54 zeigt eine aus https://microcontrollerslab.com/esp8266-pinout-reference-gpio-pins/ entnommene Zusammenstellung verfügbarer ESP8266-Module, von denen vor allem ESP-01 und ESP-12 sehr verbreitet sind.
Abbildung 2.54 ESP8266-Module
Ein Vergleich der ESP8266-Module ESP-01, ESP-05, ESP-12 und anderer ist unter https://blog.squix.org/2015/03/esp8266-modulecomparison-esp-01-esp-05.html zu finden. Zur besseren Handhabung werden der ESP8266EX bzw. die mit ihm erstellten Module durch zusätzliche Schaltungsteile erweitert. Aus der Vielzahl der daraus entstandenen Module will ich zwei herausgreifen, die besonders weitverbreitet sind. Die von den verschiedenen Herstellern angebotenen NodeMCUModule (siehe Abbildung 2.55) haben bereits einen CP2102-USBUART-Converter und einen Spannungsregulator on-board. So ist es außerdem möglich, ein NodeMCU über ein normales USB-Kabel direkt mit einem PC zwecks Kommunikation und Spannungsversorgung zu verbinden.
Abbildung 2.55 NodeMCU
Des Weiteren weist das Modul eine sogenannte Auto-ProgrammSchaltung auf, die die Aktivierung des Bootloaders steuert. Die sonst erforderliche Steuerung von GPIO0 und Reset über Tasten entfällt hier. Die Logikpegel liegen bei 3,3 V und sind nur für die digitale Ein-/Ausgabe zu beachten. Arbeitet das Modul in einer 5-VUmgebung, dann sind Level-Shifter vorzusehen. Die interne LED wird über GPIO16 gesteuert. Weitere technische Daten finden Sie unter anderem hier: http://www.esp8266learning.com/nodemcu-v2-lua-based-esp8266development-kit.php. Das Wemos D1 mini ist hardwareseitig mit dem NodeMCU vergleichbar (siehe Abbildung 2.56). Auf der Website des Herstellers https://docs.wemos.cc/en/latest/d1/d1_mini.html finden Sie die notwendigen Informationen. Zum kompakten Wemos D1 mini gibt es zahlreiche Shields, die das CPU-Modul erweitern. Eine interne LED, wie beim NodeMCU, gibt es nicht. Mit dem ESPduino gibt es auch ein Board im Arduino-UnoFormfaktor, das ich Ihnen nicht vorenthalten möchte. An Abbildung 2.57 können Sie sehen, dass es sich beim ESPduino um
ein ESP-13-Modul von Espressif mit etwas peripherer Beschaltung handelt und dass durch die Anordnung der Buchsenleisten hardwareseitig Arduino-Uno-Kompatibilität erreicht wird.
Abbildung 2.56 D1 mini
Da der ESP8266EX nur einen einkanaligen AD-Umsetzer aufweist, ist lediglich der Analogeingang A0 nutzbar. Die sonst noch vorhandenen Eingänge A1 bis A5 haben beim ESPduino keine Funktion.
Abbildung 2.57 ESPduino
2.2.9 ESP32 Der ESP32 der chinesischen Firma Espressif ist ein leistungsfähiges Single- oder Dual-Core-System (System-on-a-Chip, SoC). Das ESP32SoC enthält zusätzlich zu den WiFi- und Bluetooth-Funktionen und einer umfangreichen Peripherie eine 32-Bit-Single- oder -Dual-CoreXtensa-LX6-CPU mit integriertem SRAM. Abbildung 2.58 zeigt ein Blockdiagramm dieses komplexen SoC. Ergänzend zum ESP32Blockdiagramm möchte ich Ihnen noch einige Merkmale des ESP32 auflisten: Embedded Memory 448 KB Internal ROM 520 KB Internal SRAM 8 KB RTC FAST Memory, 8 KB RTC SLOW Memory External Memory Off-Chip-SPI-Memory kann in den verfügbaren Adressraum als externes Memory gemappt werden. Unterstützt werden bis zu 16 MB Off-Chip-SPI-Flash. Unterstützt werden bis zu 8 MB Off-Chip-SPI-SRAM. Peripherie Insgesamt stehen 41 Peripherals zur Verfügung, die Sie im Blockdiagramm finden.
Abbildung 2.58 ESP32-Blockdiagramm (Autor: Brian Kent, CC BY-SA 4.0)
Der ESP32 ist in QFN-Gehäusen (Quad-Flat-No-Leads) unterschiedlicher Größe mit 49 Pads untergebracht. 48 Anschlusspads befinden sich an den vier Seiten und ein großes, mit Masse verbundenes Wärmeleitpad befindet sich an der Unterseite. Diese beiden Gehäuseformen sind industriellen Verarbeitungsprozessen vorbehalten (siehe Abbildung 2.59 1, 2). Kompakte SMD-Module lassen sich zwar schon konventionell verarbeiten, zielen aber auf die Systemintegration ab. Hier gibt es von zahlreichen Anbietern unterschiedlich ausgestattete Module. Die Unterschiede bestehen dabei vor allem in der Größe des zur Verfügung gestellten Flashs, der Antenne und in der Abschirmung. In Abbildung 2.59 ist beispielhaft das abgeschirmte und mit einer MIFA-Antenne ausgestattete ESP-WROOM-32 3 von Espressif gezeigt.
Abbildung 2.59 ESP32-Chips und -Module
Zahlreichen Anbieter vertreiben unterschiedlich ausgestattete Boards, die auf den Einsatz der SMD-Module verzichten oder aber diese nutzen. In Abbildung 2.59 ist beispielhaft das Modul ESP Thing 4 von SparkFun gezeigt, das aus Einzelkomponenten aufgebaut ist und zusätzlich mit einem Anschluss für eine LiPo-Batterie ausgestattet wurde. Da es recht einfach ist, ein SMD-Modul in ein finales Produkt zu integrieren, sind in dieser Sparte wesentlich mehr Anbieter zu finden. Abbildung 2.59 zeigt wiederum beispielhaft das HUZZAH32Board 5 von Adafruit, das ebenfalls einen LiPo-Anschluss aufweist und so als abgesetzter und batteriebetriebener IoT-Knoten geeignet ist.
Für geringen Stromverbrauch und einen breiten Eingangsspannungsbereich optimiert ist das ePulse – ThingPulse ESP32-DevBoard der Schweizer Firma ThingPulse (https://thingpulse.com/product/epulse-thingpulse-esp32-devboard/). Abbildung 2.60 zeigt die Frontansicht dieses ESP32-Moduls.
Abbildung 2.60 ePulse – ThingPulse ESP32 DevBoard
Der VIN-Pin akzeptiert Spannungen zwischen 3,3 V und 12 V. Wenn sich das ePulse-Board im Tiefschlaf befindet, verbraucht es nur zwischen 25 µA (bei 3,3 V) und 35 µA (bei 12 V). Die meisten ESP32und ESP8266-Boards verbrauchen etwa 100 bis 130 µA. Der integrierte Serial-to-USB-Chip verbraucht nur dann Strom, wenn das Modul über USB mit Spannung versorgt wird. Zur Reduzierung des Standby-Stromverbrauchs besitzt dieses Modul keine Status-LEDs. Der Formfaktor ist für das Prototyping auf einem Steckbrett angepasst und lässt beidseitig eine Pin-Reihe für die Kontaktierung des Moduls frei. Auf dem Modul ist das ESP32-WROVER-B-Modul verbaut, das viele der ESP32-Pins freigibt. Sie haben Zugriff auf nicht weniger als 30 GPIO-Pins. Das ESP32-WROVER-B-Modul bietet als erstes ESP32Modul die Möglichkeit eines extern erweiterten RAMs.
In dem ESPduino-32 (siehe Abbildung 2.61) hat der Hersteller Doit ein ESP-WROOM-32-Modul von Espressif verbaut und stellt auf diese Weise einen ESP32 im Arduino-Uno-Formfaktor bereit.
Abbildung 2.61 ESPduino-32
Die Attraktivität der ESP32 sorgt für zahlreiche weitere Ausführungen von Komplettbaugruppen, von denen ich Ihnen hier einige zeigen möchte. LILYGO T-Call V1.4 ist eine Kombination von ESP32-WROVER und SIM800L-Modul und ist durch seine Kommunikationsoptionen (GSM, WiFi, BLE) eine sehr flexible IoT-Baugruppe (Abbildung 2.62).
Abbildung 2.62 LiLyGO T-Call
Ein LiPo-Akku kann die Spannungsversorgung des in Spitzen stromhungrigen GSM-Moduls decken helfen, da der Strombedarf beim Senden kurzzeitig den Strom eines Standard-USB-Ports überschreiten kann. In den Ruhephasen wird der LiPo-Akku dann nachgeladen. Für die GSM-Kommunikation wird eine Nano-SIM-Card benötigt, die von verschiedenen Anbietern sehr kostengünstig angeboten wird. Für den Anschluss einer externen Antenne ist ein U.FL-Buchse vorgesehen. Weitere Informationen finden Sie im Repository des Herstellers unter https://github.com/Xinyuan-LilyGO/LilyGo-T-Call-SIM800. Die Kombination des ESP32 erfolgt nicht nur mit zusätzlichen Kommunikations-, sondern auch mit Kameramodulen.
In der einfachsten Form ist das beispielsweise die ESP32-Cam, die ein ESP32S-Modul mit einer 2-Megapixel-Kamera Omnivision OV2640 (oder auch OV7670) verknüpft. Eine LED dient als integrierter Blitz (Abbildung 2.63).
Abbildung 2.63 ESP32-Cam
Wie Sie bereits in Abbildung 2.63 sehen können, verfügt die ESP32CAM nicht über einen USB-Anschluss. Sie benötigen daher einen separaten FT232-Seriell-zu-TTL-Konverter, um die ESP32-Cam an Ihren PC anzuschließen. Achten Sie auf die Betriebsspannung von 3,3 V beim ESP32. Eine gute Anleitung für den Einsatz der ESP32-Cam ist unter https://robotzero.one/esp32-cam-arduino-ide/ zu finden. LILYGO T-Kamera ist eine erweiterte Kombination von ESP32 mit PIR-Sensor, OV2040-Kamera und SSD1306-OLED (128 × 64 Pixel) und kann damit bereits das Frontend einer Zutrittskontrolle bilden (Abbildung 2.64). Das in der Abbildung gezeigte Fisheye-Objektiv kann auch durch ein Normalobjektiv ersetzt werden. Ein Mikrofon ist optional.
Abbildung 2.64 TTGO T-Kamera mit ESP32 WROVER & PSRAM, OV2640 Kameramodul (Fischaugenobjektiv mit Mikrofon) und 0,96 OLED
Weitere Informationen finden Sie im Repository des Herstellers unter https://github.com/Xinyuan-LilyGO/LilyGo-Camera-Series. Espressif hat die ESP32 zu einer Familie erweitert, die im September 2022 neben den ESP32 noch die ESP32-S- und die ESP32-C-Reihe umfasst. Tabelle 2.9 vermittelt einen Überblick über die neuen Mitglieder der ESP32-Familie, die auch durch die Arduino IDE unterstützt werden. SOC
CPU
Cores
Memory
Special
SOC
CPU
Cores
Memory
Special
ESP32- Xtensa S2 32-bit LX7
Single- 128 KB ROM, Core 320 KB SRAM, 16 KB RTC SRAM
LCD Interface, Camera Interface, Touch Sensor, WiFi, BT 5.0, Native USB
ESP32S3
DualCore
Vector Instructions Support, WiFi, BT 5.2 (LE), Native USB
384 KB ROM, 512 KB SRAM, 16 KB RTC SRAM
ESP32- 32-bit Single- 400 KB RAM, C3 RISC-V Core 384 KB ROM, 8 KB Processor RTC SRAM ESP32C6
WiFi, BT 5.2 (LE), Native USB
512 KB SRAM, 320 KB ROM
Tabelle 2.9 Die ESP32-Familie im Vergleich
Die in Tabelle 2.9 gelisteten, neuen ESP32-Derivate setzen anstelle des Xtensa LX6 einen Xtensa LX7 mit erweiterten Features ein. Außerdem bringen Sie einen USB-Anschluss mit. Die Leitungen D+/- des USB können direkt angeschlossen werden. Der ESP32-S2 besitzt Interfaces für Display und Kamera, während der ESP32-S3 durch die Unterstützung von Vektoroperationen für KI-Projekte prädestiniert ist.
2.2.10 M5Stack, M5StickC/M5StickC Plus, M5ATOM und M5Stamp Wem es bislang an Baugruppen mit einem vernünftigen Gehäuse für die Entwicklung seiner Prototypen gemangelt hat, dem wird mit M5Stack-Komponenten eine ansprechende Lösung angeboten. M5Stack bietet mit seinem robusten Open-Source-Entwicklungskit eine komfortable IoT-Entwicklungsplattform für Automatisierung, Ausbildung, Rapid Prototyping und vieles mehr. M5StackKomponenten sind sehr preiswert, voll funktionsfähig, vollständig anpassbar und für Entwickler in allen Phasen der Entwicklung neuer Produkte einfach zu handhaben. M5Stack-Komponenten können über M5Stack.com direkt bzw. über die chinesischen Online-Händler AliExpress und Banggood oder über die Marke MakerHawk via Amazon sowie über die Marke MakerFactory via Conrad bezogen werden. Von M5Stack werden eine ganze Reihe Controller angeboten, die sich mit den Bezeichnungen Cores, Stick und Atom unterscheiden lassen. Ich gebe Ihnen hier einen kurzen Überblick, später werden die Geräte auch noch in einigen Projekten eingesetzt. M5Stack-Cores sind Controller, die neben dem ESP32 als steuernden Mikrocontroller ein farbiges 2''HD-IPS-Display aufweisen. Derzeit gibt es drei verschiedene M5Stack-Cores: M5Stack Basic Core (der Schwarze) M5Stack Fire (der Rote) M5Stack Core2 M5Stick (M5StickC, M5StickC Plus) sind kompakte Controller auf Basis eines ESP32-PICO-D4 mit 0,96''- bzw. 1,14''-Farbdisplay. Eine
vergleichende Betrachtung von M5StickC und M5StickC Plus ist in meinem Blog zu finden: https://ckarduino.wordpress.com/2020/09/12/m5stickc-plus-vsm5stickc/. Die M5Atom-Serie umfasst ATOM Matrix ESP32, ATOM Lite ESP32 und ATOM Echo. Die M5Atom Controller sind mit 24 × 24 mm sehr kompakt, weisen aber dennoch einen ESP32-PICO-D4 auf. ATOM Matrix ESP32 bietet eine Infrarot-LED und eine 5×5-RGB-LEDMatrix, einen IMU-Sensor (MPU6886) sowie eine HY2.0Schnittstelle. Unterhalb der RGB-LED-Matrix befindet sich eine programmierbare Schaltfläche für allgemeine Eingaben. Abbildung 2.65 zeigt einen ATOM Matrix ESP32.
Abbildung 2.65 ATOM Matrix ESP32
ATOM Lite ESP32 bietet eine Infrarot-LED, eine RGB-LED, Tasten und eine HY2.0-Schnittstelle.
Abbildung 2.66 ATOM Lite ESP32
ATOM Echo ist ein programmierbarer Smart Speaker basierend auf dem M5ATOM-Design (Abbildung 2.67).
Abbildung 2.67 ATOM Echo
Musik kann mithilfe der Bluetooth-Funktionen des ESP32 von einem Mobiltelefon oder Tablet übertragen und durch den ATOM Echo abgespielt werden. Das eingebaute Mikrofon und der Lautsprecher lassen sich für Sprachinteraktion verwenden. ATOM Echo ist mit einer RGB-LED ausgestattet, die den Verbindungsstatus visuell anzeigen kann. Darüber hinaus stehen sechs GPIOs zum Anschluss externer Sensoren und Aktoren zur Verfügung. Die integrierte USBSchnittstelle (Typ C) ermöglicht das schnelle Hochladen und Ausführen von Programmen. Auf der Rückseite befindet sich ein M2-Schraubenloch für die Montage der Platine. Außerdem neu sind das M5Stack ESP32 Core Ink Development Kit mit einem 1.54'' E-Ink-Display und das M5Paper ESP32 Development Kit mit einem 4.7" E-Ink-Display (960 × 540 Pixel, 235 ppi, Abbildung 2.68). Bei diesen beiden Controllern steht das E-Ink-Display im Vordergrund. Der Strombedarf wird durch diese DisplayTechnologie stark reduziert, sodass diese Controller für den Batteriebetrieb prädestiniert sind.
Abbildung 2.68 M5Paper
Die M5Stamp-Serie umfasst die derzeit kompaktesten Controller M5Stamp-Pico und M5Stamp C3. Während der M5Stamp-Pico einen ESP32-PICO-D4 als Core erwarten lässt, ist das beim M5Stamp-C3 ein 32-Bit RISC-V Single Core Prozessor ESP32-C3 (Abbildung 2.69).
Abbildung 2.69 M5Stamp-C3
Nach diesem Überblick zeige ich Ihnen hier den M5Stack Basic Core und den M5StickC im Detail, da sie als Basiskomponenten angesehen werden können. Mit diesen Angaben erschließen sich dann auch die anderen M5Stack Controller, denn die zugrunde liegenden Controller sind gleich. Später werde ich Ihnen auch Programmbeispiele zur Anwendung vorstellen. Hier aber folgen erst einige Bemerkungen zur Hardware selbst. Wie Abbildung 2.70 zeigt, besteht ein M5Stack Basic Core aus zwei trennbaren Teilen. Der obere Teil enthält alle aktiven Komponenten (Prozessor, Chips und einige andere Bauteile). Das Unterteil weist eine Lithiumbatterie, eine M-BUS-Buchse und beidseitig
zugängliche Buchsen-/Stiftleisten auf. Die technischen Daten des M5Stack Basic Cores sind in Tabelle 2.10 zusammengefasst.
Abbildung 2.70 M5Stack Basic (Ober- und Unterteil)
Ressourcen
Parameter
ESP32
240 MHz Dual Core, 600 DMIPS, 520 KB SRAM, WiFi, Dual Mode Bluetooth
Flash-Memory 4 MB Power Input
5 V bei 500 mA
Port
USB Type C × 1, GROVE (I2C+I/0+UART) × 1
LCD-Screen
2", 320 × 240 Color-TFT LCD, ILI9341
Lautsprecher
1W-0928
Ressourcen
Parameter
Batterie
150 mAh bei 3,7 V
Sensoren
nicht vorhanden
Power Management
IP5306
Buttons
3
LED
nicht vorhanden
Temperatur
0 °C–40 °C
Größe
54 mm × 54 mm × 12,5 mm
Material des Gehäuses
Plastik
Approvals
FCC, CE
Tabelle 2.10 M5Stack Basic Core – technische Daten
Einen ersten Eindruck vom Aufbau des M5Stack-Basic-CoreOberteils vermittelt Abbildung 2.71.
Abbildung 2.71 M5Stack-Basic Core-Ressourcen
Beginnend beim roten Ein-/Ausschalter (RESET/ON-OFF) auf der rechten Seite sind im Uhrzeigersinn die USB-Typ-C-Buchse zur Spannungsversorgung des M5Stack Basic Core und zum ProgrammUpload sowie ein Grove-I2C-Anschluss zu finden. Es folgen ein Slot für eine Micro-SD-Karte (TF-Card) mit einer Speicherkapazität von maximal 16 GB und ein Anschluss für eine externe Batterie. Die 2 × 15 Buchsenleiste für den M-Bus sorgt für die Verbindung zu dem Unterteil, das den LiPo-Akku enthält bzw. zu anderen M5StackModulen, die zwischen Ober- und Unterteil angeordnet (gestapelt) werden können. Der M5StickC ist ein Mini-M5Stack, der mit einem ESP32-PICO-D4 betrieben wird. Der ESP32-PICO-D4 ist ein System-in-Package-Modul (SiP), das die folgenden Peripherie-Komponenten integriert: 4 MB Flash, Quarz-Oszillator, Filterkondensatoren und HFAnpassungsschaltung. Abbildung 2.72 zeigt den kompakten M5StickC mit seinen wichtigsten Merkmalen.
Ein auf der Rückseite des M5StickC angeordnetes Label zeigt alle erforderlichen Anschlussinformationen in sehr kompakter Form. Bei meinem Exemplar, das ich kurz nach dem Launch gekauft hatte, waren die Anschlüsse für LED und IR auf dem Label vertauscht. Es ist also bei der ersten Inbetriebnahme durchaus empfehlenswert, auf solche Punkte zu achten.
Abbildung 2.72 M5StickC
Der M5StickC Plus ist der direkte Nachfolger des M5StickC und unterscheidet sich im Wesentlichen durch das größere Display. Für Peripherie-Erweiterungen steht an der unteren Seite ein GroveAnschluss zur Verfügung, an der oberen Seite ist das eine entsprechend bezeichnete Buchsenleiste. Die technischen Daten von M5StickC und M5StickC Plus sind in Tabelle 2.11 zusammengefasst. Ressourcen
Parameter
Ressourcen
Parameter
ESP32
240 MHz Dual Core, 600 DMIPS, 520 KB SRAM, WiFi, Dual Mode Bluetooth
Flash-Memory 4 MB Power Input
5 V @ 500 mA
Port
USB Type C × 1, GROVE (I2C+I/0+UART) × 1
LCD Screen
0,96", 160 × 80 Color-TFT LCD, ST7735S (M5StickC) 1.14", 240 × 135 Color-TFT LCD, ST7789v2 (M5StickC Plus)
Mikrofon
SPM1423
Batterie
80 mAh @ 3,7 V (M5StickC) 120 mAh @ 3,7 V (M5StickC Plus)
Sensoren
6-Axis MEMS Sensor (SH200Q)
Power Management
AXP192
Buttons
2
LED
Red, IR
Temperatur
0 °C–40 °C
Größe
48 mm × 24 mm × 18 mm
Material des Gehäuses
Plastik
Approvals
FCC, CE
Tabelle 2.11 M5StickC/M5StickC Plus – technische Daten
Die M5Stack-Familie lebt durch zahlreiche PeripherieErweiterungen (M5Stack-Module, M5Stack-Sensors) für die unterschiedlichen Controller. Eine Übersicht über die M5Stack-Module des aktuellen Lieferangebots finden Sie unter https://shop.m5stack.com/collections/m5-modules. Sie werden dort beispielsweise ein GPS-Modul, ein LoRa- und GSM-Modul, Kommunikationserweiterungen (CAN, RS485 USB), Module zur Motoransteuerung und vieles mehr entdecken. Die Aufzählung aller M5Stack-Sensoren muss hier aus Platzgründen unterbleiben. Eine komplette Übersicht über die M5Stack-Sensoren des aktuellen Lieferangebots finden Sie unter https://shop.m5stack.com/collections/m5-sensor. Achten Sie darauf, dass es neben den M5Stack-Sensoren mit Anschlüssen für GrovePortA (I2C) auch solche mit Grove-PortB (I/O) und Grove-PortC (Tx/Rx) gibt. Abschließend möchte ich auf die M5Cameras unter https://shop.m5stack.com/collections/m5-cameras hinweisen. Ich zeige Ihnen in Abbildung 2.73 eine M5CameraF mit FisheyeObjektiv. Grundsätzlich handelt es sich bei den M5Cameras um modifizierte ESP32-Cams, die allerdings versehen mit einem passenden Gehäuse einen Aufbau wirkungsvoll unterstützen.
Abbildung 2.73 M5CameraF
2.2.11 Raspberry Pi Pico Zu Beginn des Jahres 2021 machte die Raspberry Foundation, Entwickler des mittlerweile legendären Raspberry Pi Single Board Computers, den Raspberry Pi Pico bekannt. Der Raspberry Pi Pico ist kein weiteres Modell der Raspberry Pi Familie, sondern ein eigenständiges Mikrocontroller-Board, das als Kern den ebenfalls von der Raspberry Pi Foundation entwickelten Mikrocontroller RP2040 aufweist. Schon nach der Ankündigung des Raspberry Pi Pico wurde sehr kontrovers im Netz debattiert. Während die eine Partei den neuen Controller euphorisch begrüßte, machte die andere Partei sofort auf aus deren Sicht fehlende Funktionalität aufmerksam. Die Bewertung war, wie in dieser Zeit offensichtlich üblich, stark polarisiert und Platz für differenzierte Meinungen war kaum vorhanden. RP2040 Mikrocontroller
Der RP2040 ist der erste Mikrocontroller der Raspberry Pi Foundation. Als Dual-Core-Mikrocontroller (2 × Cortex-M0+) mit ausreichend Speicher on-chip und einer umfangreichen Peripherie weist der RP2040 eine sehr gute Grundausstattung auf. Ergänzt wird diese durch ein programmierbares I/O-Subsystem (PIO), das dem professionellen Anwender beachtliche Leistung und Flexibilität bietet. Eine detaillierte Dokumentation steht seit Markteintritt zur Verfügung. Das immerhin 647 Seiten umfassende RP2040 Datasheet zeigt alle Details des komplexen Controllers. Abbildung 2.74 zeigt ein Blockdiagramm des RP2040 Mikrocontrollers.
Abbildung 2.74 RP2040 Blockdiagramm
Der RP2040 ist mit einem UF2-Bootloader (UF2 – USB Flashing Format) im ROM ausgestattet, wodurch die Programmierung – das Flashen des RP2040 – sehr erleichtert wird. Die UF2-Thematik ist im Beitrag »One chip flash them all« sehr detailliert beschrieben und
kann bei Bedarf vertieft werden: https://makecode.com/blog/onechip-to-flash-them-all. Zusammengefasst ist der RP2040 ein sehr kostengünstiger und leistungsstarker Mikrocontroller mit flexiblen digitalen Schnittstellen und weist die folgenden Merkmale auf: Dual-Core-Cortex-M0+-Prozessor, getaktet mit bis zu 133 MHz 264 KByte SRAM 30 Multifunktions-GPIO sechs dedizierte I/O für SPI-Flash spezielle Hardware für häufig verwendete Peripheriegeräte programmierbare I/O (PIO) für erweiterte Peripherieunterstützung 4-Kanal-12-Bit-ADC mit internem Temperatursensor, 0.5 MSPS USB-1.1 Host/Device Der RP2040 ist mit einem QFN-Gehäuse für die Montage als SMD versehen (Abbildung 2.75).
Abbildung 2.75 Mikrocontroller RP2040
Die Verarbeitung des RP2040 dürfte außerhalb industrieller Fertigung schwierig sein, weshalb wir hier auf fertige Boards zurückgreifen. Boards auf Basis RP2040
Der Raspberry Pi Pico der Raspberry Pi Foundation war das erste Mikrocontroller-Board, das den RP2040 als Mikrocontroller eingesetzt hat. Die in der Maker-Szene bekannten Anbieter Adafruit, SparkFun, Pimoroni u. a. m. stellten nahezu zeitgleich eigene Entwicklungen vor. Eine Übersicht finden Sie im Blogpost »Mikrocontroller im Arduino Nano Formfaktor«, das Sie unter https://ckarduino.wordpress.com/2021/01/23/mikrocontroller-imarduino-nano-formfaktor/ finden. Ergänzend zum Raspberry Pi Pico stelle ich hier nur den Pimoroni Tiny2040 vor. Raspberry Pi Pico
Der Raspberry Pi Pico, den ich im Folgenden als Pi Pico bezeichnen werde, umgibt den RP2040 mit der minimal notwendigen Infrastruktur. Abbildung 2.76 zeigt die Front- und Rückansicht des Pi Pico. Deutlich erkennbar sind die »castellated Pins«, die eine leichte Montage (board-to-board soldering) des Pi Pico auf einem Trägerboard ermöglichen. Castellated Pins werden schon länger bei verschiedenen PCB-Modulen (Bluetooth- oder WiFi-Modulen) verwendet, um diese direkt auf ein Trägerboard zu montieren.
Abbildung 2.76 Raspberry Pi Pico – Front- und Rückansicht
Wie Sie aus Abbildung 2.76 sofort erkennen können, ist die Beschriftung der Pins auf der Rückseite des Pi Pico angeordnet. Für einen Einsatz des Pi Pico auf einem Breadboard ist das recht ungünstig. Daniel Brühlmann hat den in Abbildung 2.77 gezeigten Pinout Breadboard Helper entworfen, der die Orientierung bei der Pinbelegung wieder herstellt.
Abbildung 2.77 Pinout Breadboard Helper (Quelle: https://twitter.com/arduinopraxis/status/1366445420910682118)
Abbildung 2.78 zeigt schließlich die Mehrfachbelegung der I/O-Pins des Pi Pico, wodurch eine hohe Flexibilität bei der Auslegung der Hardware entsteht. Vergleichen Sie die Pinbelegung mit dem Blockdiagramm und Sie erkennen, dass die beiden UARTs, die beiden I2C-Busse und die beiden SPI-Busse mehrfach zur Verfügung stehen. Nur die Anschlüsse des internen Analog-Digital-Umsetzers (ADC) sind festen Pins zugeordnet.
Abbildung 2.78 Raspberry Pi Pico Pinout
Einige GPIOs sind für interne Funktionen reserviert. Tabelle 2.12 zeigt die betreffenden GPIOs und deren Funktion. Pin
I/O Funktion Direction
GPIO29 I
ADC3 erfasst VSYS/3
GPIO25 O
User LED
GPIO24 I
Detektion VBUS – Hi wenn VBUS vorhanden, sonst Lo.
GPIO23 O
Steuert das on-board Switched Mode Power Supply (SMPS)
Tabelle 2.12 GPIOs für interne Funktionen
Neben diesen GPIOs sind sieben weitere Anschlüsse nach außen verfügbar. Tabelle 2.13 zeigt die Bezeichnung der Anschlüsse und deren Funktion. Pin Bezeichnung Funktion
Pin Bezeichnung Funktion 40
VBUS
VBUS ist die USB-Spannung (5 V). Eine externe Spannungsversorgung über USB kann über GPIO24 detektiert werden (GPIO24 = Hi, Spannung vorhanden; GPIO24 = Lo, keine Spannung vorhanden).
39
VSYS
VSYS ist die System-Eingangsspannung und kann zwischen 1,8 V und 5,5 V liegen. Die Betriebsspannung von 3,3 V für den RP2040 und dessen GPIO wird vom On-Board-SMPS erzeugt.
37
3V3_EN
3V3_EN ist über einen Pullup-Widerstand Hi. Wenn mit GND verbunden, werden die 3,3 V abgeschaltet.
36
3V3 (OUT)
3,3 V DC-Spannungsversorgung für externe Komponenten. Belastung sollte kleiner 300 mA bleiben.
35
ADC_VREF
ADC_VREF ist Spannungsversorgung und Referenz für den ADC. Für eine bessere Genauigkeit der AD-Umsetzung kann auch mit einer externen Referenzspannung gearbeitet werden.
33
AGND
AGND ist der Analog-GND für GPIO26-29. Wenn der ADC nicht verwendet wird oder die ADC-Genauigkeit nicht kritisch ist, kann dieser Pin mit der digitalen Masse (GND) verbunden werden.
Pin Bezeichnung Funktion 30
RUN
RUN ist über einen Pullup-Widerstand Hi. Lo an diesem Pin erzeugt einen Reset des RP2040.
Tabelle 2.13 Power- und System-Anschlüsse
Sind die Anforderungen an den ADC nicht sehr hoch, dann kann mit der intern erzeugten Referenzspannung gearbeitet werden. Will man die Genauigkeit verbessern, dann hilft eine externe Referenzspannung, die beispielsweise mit einem LM4040 erzeugt und an den Anschluss ADC_VREF angelegt werden kann (Abbildung 2.79).
Abbildung 2.79 Externe Referenzspannung für den ADC mit LM4040
Es muss an dieser Stelle erwähnt werden, dass der ADC des aktuellen RP2040 noch einige Linearitätsprobleme aufweist. Wohl gemerkt: Es betrifft den RP2040-Mikrocontroller und damit alle darauf aufbauenden Boards. Wenn Sie tiefer in die Thematik eindringen
möchten, dann kann ich Ihnen die folgenden Ausführungen empfehlen: Raspberry Pi Confirms It Is Investigating a Flaw in the Raspberry Pi Pico, RP2040 ADC: https://www.hackster.io/news/raspberry-piconfirms-it-is-investigating-a-flaw-in-the-raspberrypi-pico-rp2040adc-95c393b55dfb Characterizing the Raspberry Pi Pico ADC – Integral and Differential Nonlinearity (INL/DNL): https://picoadc.markomo.me/INL-DNL/#why-does-the-dnl-spike Die Programmierung des Flashs erfolgt über USB. Der Pi Pico meldet sich als Laufwerk und die Datei kann per Drag-and-drop transferiert werden. Sicher haben Sie auch das Debug-Interface gesehen, das durch ein 3Pin ARM Serial Wire Debug (SWD) Port gebildet wird. Über das SWDPort können Sie das System zurücksetzen, den Code laden und ausführen sowie interaktiv debuggen. Die Details hierzu werde ich hier nicht betrachten. Weiterführende Informationen finden Sie im Datenblatt (https://datasheets.raspberrypi.org/pico/picodatasheet.pdf). Pimoroni Tiny2040
Mit dem Tiny2040 stellt Pimoroni ein kleines, aber nicht minder leistungsfähiges Board zur Verfügung, das sogar über 8 MB Flash verfügt (Abbildung 2.80).
Abbildung 2.80 Pimoroni Tiny2040
Das Board ist wieder mit castellated Pins versehen, wodurch eine Direktverbindung zu einer darunterliegenden Leiterplatte erfolgen kann. Als alternative Anschlussformen bleiben natürlich Stiftleisten oder Drähte. Mit Ausnahme der reduzierten Anzahl von Pins bestehen keine weiteren Einschränkungen. Das in Abbildung 2.81 gezeigte Pinout des Tiny2040 zeigt die trotz der reduzierten Anzahl von Pins verbliebene Flexibilität bei der Belegung der Anschlüsse.
Abbildung 2.81 Tiny2040 Pinout
2.2.12 Seeed XIAO und Wio Terminal Seeed XIAO hat sich mittlerweile zur MCU-Familie weiterentwickelt. Begonnen hatte es mit dem Seeeduino XIAO, der heute als Basismodell der Familie gelten kann. Die XIAO-Familie wurde durch den XIAO-RP2040 und den XIAO-nRF52840 ergänzt. Abbildung 2.82 zeigt die drei Mitglieder der XIAO-Familie
Abbildung 2.82 Seeed XIAO Mikrocontroller
Der beim Seeeduino XIAO mit 48 MHz getaktete 32-Bit ARM CortexM0+ (SAMD21G18) weist 256 KB Flash sowie 32 KB SRAM auf. Trotz der kompakten Abmessungen stehen mehrere Schnittstellen zur Außenwelt zur Verfügung: elf digitale/analoge Pins, zehn PWM-Pins, ein DAC-Ausgang, ein I2C, ein UART und ein SPI. Beim XIAO-RP2040 wird der im vorangehenden Abschnitt vorgestellte RP2040 eingesetzt. Dieser Dual-Core-ARM-Cortex-M0+ wird mit 133 MHz getaktet und stellt 2 MB Flash sowie 264 KB SRAM zur Verfügung. Den XIAO-nRF52840 gibt es in zwei Versionen, vergleichbar mit Arduino Nano 33 BLE und Arduino Nano 33 BLE Sense. Der XIAO-nRF52840 ist mit einem leistungsstarken Nordic nRF52840, einem mit 64 MHz getaktetem 32-Bit-ARM-Cortex-M4 mit FPU ausgestattet. Drahtlose Kommunikation – eine Stärke der
Nordic-Controller – kann über Bluetooth 5.0, NFC oder ZigBee erfolgen. Die Antenne befindet sich auf dem Board. Mit einem Strombedarf von 5 μA im Deep Sleep ist der XIAO-nRF52840 hervorragend für den Batteriebetrieb geeignet. Eine Ladeschaltung mit dem BQ25101-Chip unterstützt das Batterie-Management für einen LiPo-Akku. Als Interface stehen zur Verfügung: ein Reset Button, ein UART, ein I2C, ein SPI, ein NFC, ein SWD, elf GPIO, sechs ADC, eine Three-in-one-LED und eine User-LED. Beim XIAOnRF53840 BLE Sense kommen noch ein On-Board-PDM-Microfon und sechs Axis-IMU hinzu. Umfangreiche Informationen sind im Wiki von Seeed Studio zusammengestellt (https://wiki.seeedstudio.com/Seeeduino-XIAO/). Ergänzende Baugruppen (wie z. B. Seeeduino-XIAO-ExpansionBoard, Grove Shield for Seeeduino XIAO with embedded Battery Management Chip) ermöglichen rasches und unkompliziertes Prototyping. Wio Terminal ist, wie der Seeeduino XIAO, ebenfalls ein ATSAMD51basierter Mikrocontroller, der mithilfe eines Realtek RTL8720DN zusätzlich mit drahtloser Konnektivität aufwarten kann. Der CPUTakt liegt bei 120 MHz (Boost bis zu 200 MHz). Der Realtek RTL8720DN unterstützt sowohl Bluetooth als auch WiFi. Wio Terminal ist mit einem 2,4-Zoll-LCD-Bildschirm, integrierter IMU (LIS3DHTR), Mikrofon, Summer, Micro-SD-Kartensteckplatz, Lichtsensor und Infrarot-Emitter (IR 940 nm) ausgestattet (Abbildung 2.83).
Abbildung 2.83 Wio Terminal
Wio Terminal ist das perfekte Gerät zum Experimentieren und Prototyping von TinyML-Anwendungen. Detailinformationen finden Sie wieder im Wiki unter https://wiki.seeedstudio.com/WioTerminal-Getting-Started/.
2.2.13 Adafruit Feather und SparkFun Thing Plus Feather von Adafruit und Thing Plus von SparkFun sind flexible und leistungsstarke Familien von MCU-Boards (Feathers, Thing Plus) mit einem breiten Leistungsspektrum. Sie können für schnelles Prototyping an ein Steckbrett angeschlossen werden, verfügen über integrierte Batterieanschlüsse für Ihre Projekte unterwegs und die meisten haben integrierte LiPo-Ladeschaltungen. Feather und Thing Plus weisen außerdem den gleichen Footprint auf. Für die Erweiterung der Feather-Boards stehen bei Adafruit sogenannte Wings als Extension-Boards zur Verfügung. Bei
SparkFun lassen sich Erweiterungen über deren Qwiic-System (siehe Abschnitt 3.4.1) vornehmen. Beide Familien bieten zahlreiche MCU- und Extension-Boards mit den in diesem Buch vorgestellten Mikrocontrollern. Eine Übersicht über die Komponenten beider Familien finden Sie auf den folgenden Webseiten der Hersteller: https://learn.adafruit.com/adafruit-feather https://www.sparkfun.com/thing_plus Bauteile von Adafruit und SparkFun erhalten Sie in Deutschland u. a. bei EXP-Tech (https://www.exp-tech.de/) und Eckstein (https://eckstein-shop.de/).
2.2.14 Maixduino Maix ist eine von der chinesischen Firma Sipeed entwickelte Produktserie, mit der sich KI-Aufgaben von der Cloud auf die Geräteebene verschieben lassen. Dabei ist Maix nicht nur eine Hardwarelösung, sondern kombiniert kundenspezifische Hardware, offene Software und hochmoderne KI-Algorithmen. Maixduino, ein neues Board aus der Maix-Produktserie von Sipeed, führt Maix-RISC-V-Boards auf Basis des K210-Chips von Kendryte mit der Arduino-IDE und -Librarys zusammen, wodurch eine große Anzahl vorhandener Open-Source-Arduino-Bibliotheken für die schnelle Entwicklung und das Prototyping mit dem SipeedsMaixduino-Board eingesetzt werden kann. Auf dem Board befinden sich ein K210 und ein ESP32. Auch die KPU des K210, ein universeller neuronaler Netzwerkprozessor, wird unterstützt. Zum Lieferumfang
des in Abbildung 2.84 gezeigten Maixduino Kits gehören die folgenden Komponenten: das Kameramodul OV2640 ein 2,4"-TFT-Display das Maixduino-Board
Abbildung 2.84 Die Komponenten des Maixduino Kits
Die Frontseite des Maixduino-Boards (siehe Abbildung 2.85) zeigt anhand der Buchsenleisten Kompatibilität zum Arduino-UnoFormfaktor, und die Rückseite zeigt in einem Blockdiagramm die zur Verfügung stehenden Ressourcen (siehe Abbildung 2.86).
Abbildung 2.85 Maixduino – Frontansicht
Abbildung 2.86 Maixduino – Rückansicht
Maixduino zeichnet sich durch folgende Merkmale aus: CPU: RISC-V-Dual-Core-64-Bit mit FPU; 400 MHz Neuronal Network Processor QVGA@60FPS und VGA@30FPS Bilderkennung Das On-Board-ESP32-Modul unterstützt 2,4 GHz 802.11. b/g/n und Bluetooth 4.2.
Arduino-Uno-Formfaktor und Arduino-kompatibles Interface On-Board-MEMS-Mikrofon mit I 2S-Ausgang FPC-Verbindung für DVP-Kamera FPC-Verbindung für 8-Bit-MCU-LCD Micro-SD-Karte Reset- und Boot-Taster 3 W DAC+PA-Audio-Output USB-Typ-C-Anschluss für den Programm-Upload Machine Vision auf Basis von Convolutional Neuronal Networks Mikrofon-Array mit High-Performance für maschinelles Hören Unterstützung von Tiny-Yolo, Mobilenet und TensorFlow Lite für maschinelles Lernen (Deep Learning) Keine Panik Sicher werden Sie sich im Rahmen dieses Buches nicht mit den letztgenannten Themen auseinandersetzen müssen. Ich will Ihnen aber zeigen, dass Sie bei der Beschäftigung mit dem Arduino nicht in eine Sackgasse geraten, sondern sich auf aktuelle und kommende Themen sehr gut vorbereiten können.
2.3 Arduino-Shields Arduino-Shields sind Boards, die auf Arduino-Boards aufgesteckt werden können, um deren Funktionalität zu erweitern. Die Arduino-Shields weisen wie die Controller-Boards unterschiedliche Formfaktoren auf. Man unterscheidet Arduino-Shields für die klassischen Arduinos und für die Arduino-MKR-Serie.
2.3.1 Arduino-Standard-Shields Als Arduino-Standard-Shield bezeichne ich hier Shields, die dem Arduino-Uno-Formfaktor entsprechen. Achtung: Betriebsspannung beachten! Bitte beachten Sie immer, dass es Arduinos mit einer Betriebsspannung von 3,3 V und Arduinos mit einer Betriebsspannung von 5 V gibt. Die Betriebsspannung und die Logikpegel des eingesetzten Arduino-Shields müssen zum Controller-Board passen. Der Anschluss IOREF teilt dem Arduino-Shield mit, welche Betriebsspannung das Controller-Board aufweist. Wertet das Arduino-Shield diese Information aus, dann gibt es keine Inkompatibilitäten, die zur Zerstörung von Bauteilen führen können.
YwRobot Easy Module Shield
Das Easy Module Shield stellt dem Arduino verschiedene Sensoren und Aktoren zur Verfügung. Abbildung 2.87 zeigt die Frontseite des Easy Module Shield v1.
Abbildung 2.87 YwRobot Easy Module Shield v1
Abbildung 2.88 YwRobot Easy Module Shield v1 – Schaltbild
Beim Einsatz dieses Shields kann die Ansteuerung der vorhandenen LEDs und des Buzzers (Piezo-Tongeber) sowie die Abfrage des DHT11- und des LM35-Sensors, des Fotowiderstandes, des IREmpfängers, des Potenziometers und der zwei Taster ohne zusätzliche Verdrahtung erfolgen. Gerade für die Ausbildung ist das in der Anfangsphase ein nicht zu unterschätzender Vorteil. Abbildung 2.88 zeigt das Schaltbild des Easy Module Shields v1. Sie können darin die Zuordnung der Komponenten des Boards zu den Anschlüssen des Arduino erkennen. Multi-Function Shield
Der gleichen Philosophie folgend, aber mit etwas anderen Komponenten bestückt, präsentiert sich das Multi-Function Shield (siehe Abbildung 2.89).
Abbildung 2.89 Multi-Function Shield
Markant zeigt sich die vierstellige Sieben-Segment-Anzeige an der rechten Seite. Sensoren sind keine vorhanden. Allerdings sind Buchsenleisten für DS1820 und SFH506 vorgesehen, die nachträglich kontaktiert werden können. Bei Eckstein (https://eckstein-shop.de/HIMALAYAMultiFunctionShieldProtoShieldfC3BCrArduino) gibt es das Multi-Function Shield für 5,89 € (Stand: Juni 2022). Von Oliver Kuhlemann gibt es eine sehr aussagekräftige deutschsprachige Website (http://cool-web.de/arduino/multifunction-shield-einrichtung.htm) und eine Library zu diesem Board, die Ihnen bei der Einrichtung und dem Betrieb hilft. Grove Base Shield v2
Zur Kontaktierung der Module des Grove-Systems dient das Base Shield v2 (siehe Abbildung 2.90). Die vierpoligen Stecker auf dem Board bilden das standardisierte Grove-Interface. In Abschnitt 3.4.2 stelle ich das Grove-System noch vor. An dieser Stelle ist es ausreichend, dass Sie das Grove Shield und die Möglichkeit einer standardisierten Erweiterung kennengelernt haben. Die vierpoligen Stecker sind die Grove-Konnektoren. Wichtig zu wissen ist, dass das Raster der Stifte 2 mm beträgt. Es gibt Anbieter, die auf Shields vierpolige Stecker mit einem Stiftabstand von 2,54 mm verbauen. Diese taugen jedoch auch bei identischer Belegung nicht als Grove-Konnektoren.
Abbildung 2.90 Grove Base Shield v2
Jeder Grove-Konnektor auf dem Base Shield führt zwei Signalleitungen sowie VCC und GND. Die Signalleitungen sind auf dem Base Shield beschriftet und gemäß Tabelle 2.14 den GroveKonnektoren zugeordnet. Grove-Konnector Name
Anzahl
Analog
A0/A1/A2/A3
4
Digital
D2/D3/D4/D5/D6/D7/D8 7
UART
Tx, Rx
1
I2C
SDA, SCL
4
Tabelle 2.14 Zuordnung der Grove-Konnektoren zu den Signalleitungen
Da es Arduino-Boards mit Betriebsspannungen von 3,3 V und 5 V gibt, dient ein Schalter auf dem Base Shield zur Auswahl der betreffenden Betriebsspannung.
Arduino Motor Shield Rev3
Das Arduino Motor Shield Rev3 ist das derzeit aktuelle Arduino Motor Shield zur Ansteuerung von zwei DC-Motoren oder einem Schrittmotor (Stepper) über eine H-Brücke mit dem Treiberbaustein L298P. Abschnitt 8.2 ist Motoren gewidmet. Dort sind Anwendungen mit dem Motor Shield beschrieben. Adafruit Motor Shield
Das originale Adafruit Motor Shield gehört zu den beliebtesten Kits von Adafruit. Es können bis zu vier DC-Motoren oder zwei Schrittmotoren über eine H-Brücke mit dem Treiberbaustein L293 (v1) bzw. TB6612 MOSFET (v2) angesteuert werden. Auch hier möchte ich Sie auf Abschnitt 8.2 verweisen. Arduino Ethernet Shield
Mit einem Arduino Ethernet Shield kann ein Arduino über Ethernet eine Verbindung zum Internet herstellen. Zusätzlich bietet das Shield die Möglichkeit, eine SD-Karte zu lesen und zu beschreiben. Abschnitt 10.7.1 befasst sich mit dieser Thematik direkt und zeigt Ihnen den Einsatz eines Ethernet-Shields anhand eines Anwendungsbeispiels. Arduino WiFi Shield
Mit einem Arduino WiFi Shield wird einem Arduino ein drahtloser Internetzugang über WiFi ermöglicht. Da mittlerweile einige Arduino-Boards selbst diese WiFi-Konnektivität zur Verfügung stellen, ist der Einsatz eines solchen WiFi Shields nicht mehr zu empfehlen.
LCD Shield bzw. LCD Keypad Shield
LCD Shields gibt es in zahlreichen Ausführungsformen – mit und ohne zusätzliche Tasten. Abbildung 2.91 zeigt Ihnen ein LCD Keypad Shield von Velleman, wie es aber auch von zahlreichen anderen Anbietern in nahezu identischer Art geliefert wird. Diese Shields reduzieren die Komplexität für die notwendigen Ein-/Ausgaben einer Arduino-Anwendung im Zusammenspiel mit den zugehörigen Librarys beträchtlich und sind deshalb sehr beliebt. Abschnitt 7.5.3 ist speziell dieser Anzeigeart gewidmet und betrachtet Anwendungsbeispiele im Detail.
Abbildung 2.91 LCD Keypad Shield von Velleman
Arduino Shield List
Der Arduino Store und die einschlägigen Distributoren bieten eine große Zahl von Arduino-Shields an. Einige davon habe ich Ihnen vorgestellt.
Beim Start eines neuen Projekts sollten Sie sich deshalb zuerst im Store oder über eine Suchmaschine im Netz nach einem geeigneten Arduino-Shield umsehen. Eine weitere Möglichkeit ist die Arduino Shield List (http://shieldlist.org/), die derzeit (Stand: Winter 2022) 317 Shields von 125 Anbietern umfasst. Wenn Sie auf diesem Wege nichts finden, dann können Sie sich für einen konventionellen Aufbau oder für das Erstellen eines eigenen Arduino-Shields entscheiden.
2.3.2 Arduino-MKR-Shields Die Arduino-MKR-Familie erfordert wegen ihrer abweichenden Abmessungen eine eigenständige Lösung für die HardwareErweiterung. Daher wurden die Arduino-MKR-Shields entwickelt. Ich zeige in diesem Abschnitt beispielhaft einige MKR-Shields zur Lösung unterschiedlicher Aufgaben. MKR ENV Shield
Das MKR ENV Shield erfasst mit verschiedenen Sensoren Messdaten für eine Reihe von Umgebungsdaten. Die Sensoren messen folgende Umgebungsdaten: Luftdruck Temperatur und Luftfeuchtigkeit ultraviolette UV-A-Intensität ultraviolette UV-B-Intensität Lichtintensität (in Lux)
Aus den Daten für UV-A und UV-B wird der UV-Index berechnet. Die Daten können lokal auf einer Micro-SD-Karte abgespeichert werden. Ein entsprechender Slot ist auf der Unterseite des Shields vorhanden. Abbildung 2.92 zeigt eine Draufsicht auf das MKR ENV Shield. Die mittig angeordneten Sensoren sind deutlich zu erkennen.
Abbildung 2.92 Arduino MKR ENV Shield
Auf dem MKR ENV Shield kommen die folgenden modernen Sensoren zum Einsatz: ST LPS22HB – zur Messung des atmosphärischen Drucks ST HTS221 – zur Messung von Temperatur und relativer Luftfeuchtigkeit VISHAY TEMT6000 – zur Messung der Beleuchtungsstärke VISHAY VEML6075 – zur Messung der Intensität von UV-A und UV-B MKR Relay Shield
Das MKR Relay Shield weist zwei Relais auf, die durch ein ArduinoMKR-Board angesteuert werden können. Außerdem steht ein kleiner Prototyping-Bereich auf dem Board für eigene Schaltungserweiterungen zur Verfügung. Vier analoge Eingänge sind auf Klemmen geführt. Abbildung 2.93 zeigt das MKR Relay Shield mit seinen nach außen geführten Klemmen. Der MKR-Formfaktor wird durch das MKR Relay Shield nicht eingehalten.
Abbildung 2.93 Arduino MKR Relay Shield
MKR Connector
Funktionell mit dem Grove Base Shield v2 vergleichbar ist das MKR Connector Shield (siehe Abbildung 2.94).
Abbildung 2.94 Arduino MKR Connector
An den Grove-Konnektoren stehen sieben analoge Eingänge und sechs digitale I/O-Pins sowie je ein UART- und ein I2C-Anschluss zur Verfügung. Werden mehrere I2C-Anschlüsse benötigt, dann können diese durch einen I2C-Hub erweitert werden. MKR2UNO-Adapter
Will man nicht auf die Arduino-Standard-Shields verzichten, obwohl man ein MKR-Board benutzt, dann kann der Arduino MKR2UNOAdapter (siehe Abbildung 2.95) weiterhelfen. Der MKR2UNOAdapter wird im Arduino Store für 10,90 € angeboten.
Abbildung 2.95 Arduino-MKR2UNO-Adapter
Durch den Einsatz eines Arduino MKR kann die Performance des Controllers gesteigert und das bei den meisten MKR-Boards vorhandene Ladegerät für einen LiPo-Akku genutzt werden. Achtung: Unbedingt Bauhöhen beachten Die Buchsenleisten für das Arduino-MKR-Board und das ArduinoShield liegen auf gleicher Höhe. Hier kann es leicht zu Kollisionen beider Boards kommen. Abhilfe schafft eine Zwischenleiste zur Buchsenleiste für das Arduino-Shield.
Abbildung 2.96 zeigt solche Leisten, die Sie unter dem Begriff Arduino Stackable Headers im Internet finden. Bitte beachten Sie, dass der MKR2UNO nur ein Formfaktor-Adapter ist und daher keine Spannungsumsetzung vorliegt. Nur beim Anschluss eines Shields, das IOREF auswertet, wird es keine Probleme geben. Andernfalls kann es zur Zerstörung von Bauteilen kommen.
Abbildung 2.96 Arduino Stackable Headers
Falls Sie mit diesen Einschränkungen nicht leben können, bietet das Board MKR2UNO Plus (siehe Abbildung 2.97) von Gtronics.NET eine Alternative.
Abbildung 2.97 MKR2UNO Plus (Bild: Gtronics.NET)
Das MKR2UNO Plus bietet eine interne, bidirektionale Pegelanpassung (5 V 3,3 V) an jedem digitalen Pin und eine Begrenzungsspannung bei 3,3 V an jedem analogen Eingangspin. Über Lötbrücken kann das Board hardwareseitig weiter konfiguriert werden, sodass auch der DAC-Ausgang nach außen zur Verfügung gestellt werden kann. Das Handbuch zum MKR2UNO Plus gibt detailliert Auskunft über die erforderlichen Konfigurationsschritte (https://www.gtronicsshop.com/en/index.php? controller=attachment&id_attachment=12). Gtronics.NET bietet das MKR2UNO-Plus-Board für 19,90 € an (https://www.gtronicsshop.com/en/protoshield-plus/21-mkr2unoplus-shield-8068020578536.html).
2.4 Expansionsboards Expansionsboards dienen der Erweiterung von MikrocontrollerBoards und dem besseren Zugang zur Peripherie des jeweiligen Mikrocontrollers. Die bereits behandelten Arduino-Shields können auch zu dieser Klasse von Boards gezählt werden.
2.4.1 Arduino Portenta H7 Für den Arduino Portenta H7 habe ich Ihnen in Abschnitt 2.1.4 bereits das Arduino Portenta Breakout Boards vorgestellt. Das Portenta Vision Shield ist eine erste Erweiterung, die Bildverarbeitung und Ethernet-Kommunikation auf dem Arduino Portenta H7 ermöglicht (https://docs.arduino.cc/hardware/portentavision-shield). Bei diesem ersten Portenta Shield wird es nicht bleiben, da bin ich mir sicher.
2.4.2 Seeeduino XIAO Die kompakten Seeeduino XIAO lassen sich sehr einfach auf einem Steckbrett einsetzen. Expansionsboards bieten aber weitaus mehr Komfort. Zwei Boards möchte ich Ihnen vorstellen. Seeeduino XIAO Expansion Board
Das Seeeduino XIAO Expansion Board ist mit reichlich Peripherie ausgestattet. Auf dem Board stehen ein 0,96"-OLED-Display, eine
RTC PCF8563, ein CR1220-Batteriehalter für die RTC, ein SD-KartenHalter, Buzzer, User Button und das komplette Batteriemanagement für den Betrieb an einem LiPo-Akku zur Verfügung. Zusätzliche Erweiterungen können über Grove-Anschlüsse erfolgen. Es stehen zwei I2C-Ports, ein UART-Port und ein A0/D0-Anschluss zur Verfügung. Abbildung 2.98 zeigt Vorder- und Rückseite des Seeeduino XIAO Expansion Boards.
Abbildung 2.98 Seeeduino XIAO Expansion Board
Detailinformationen und Programmbeispiele finden Sie im SeeedStudio-Wiki unter der URL https://wiki.seeedstudio.com/SeeeduinoXIAO-Expansion-Board/. Grove Shield für Seeeduino XIAO
Das Seeeduino XIAO Grove Shield ist ein Erweiterungsboard mit integriertem Batteriemanagement-Chip. Die Spannungsversorgung über einen LiPo-Akku und dessen Aufladung sind einfach möglich. Es stehen acht Grove-Anschlüsse zur Verfügung, die zwei I 2C-Ports, ein UART-Port oder zehn digitale I/Os umfassen. Über ein Bonding Pad können Sie den Speicher durch Auflöten von Flash Memory in einem SOIC8-Gehäuse erweitern.
Abbildung 2.99 zeigt die Draufsicht auf das Seeeduino XIAO Grove Shield.
Abbildung 2.99 Seeeduino XIAO Grove Shield
Detailinformationen und Programmbeispiele finden Sie im SeeedStudio-Wiki unter der URL https://wiki.seeedstudio.com/GroveShield-for-Seeeduino-XIAO-embedded-battery-management-chip/.
2.4.3 Raspberry Pi Pico Mit dem Erscheinen der Raspberry Pi Pico kamen nahezu zeitgleich eine Vielzahl von Erweiterungsboards, Shields etc. auf den Markt. Wenn Sie eine Anwendung mit einem Raspberry Pi Pico planen, dann rate ich Ihnen zu einer gründlichen Recherche vorab. Der Markt ist hier sehr dynamisch und mit hoher Wahrscheinlichkeit finden Sie bereits eine passende Ergänzung. Ich möchte Ihnen Boards für den Raspberry Pi vorstellen, die gerade in der Einarbeitungsphase sehr hilfreich sein können. Raspberry Pi Pico Breadboard Kit
Raspberry Pi Pico Breadboard Kit ermöglicht Erweiterungen auf dem Steckbrett und bietet zusätzlich einen Buzzer, vier Buttons und vier LEDs. Die Pins des Raspberry Pi Pico sind auf Stiftleisten geführt
und können über Dupont-Kabel mit den externen Elementen oder dem Steckbrett verbunden werden. Abbildung 2.100 zeigt das Raspberry Pi Pico Breadboard Kit.
Abbildung 2.100 Raspberry Pi Pico Breadboard Kit
Weiterführende Informationen finden Sie auf GitHub unter der URL https://github.com/sbcshop/Raspberry-Pi-Pico-Breadboard-Kit. Pico Breakout Garden Base
Die Pico Breakout Garden Base bietet einen Steckplatz für einen Raspberry Pi Pico und ermöglicht es Ihnen, bis zu sechs Breakouts aus der umfangreichen Auswahl an Pimoroni-Breakouts daran anzuschließen. Die Pimoroni-Breakouts sind kleine Boards, die über I2C oder SPI mit dem Mikrocontroller kommunizieren. Die ganze Palette verfügbarer Pimoroni-Breakouts sehen Sie unter https://thepihut.com/collections/pimoroni-breakouts. Über die sechs Steckplätze der Pico Breakout Garden Base werden die Pimoroni-Breakouts mit dem Raspberry Pi Pico verbunden. Es stehen zwei Steckplätze für SPI-Breakouts (für das 0,96"-LCD-
Breakout oder das 1,12"-SPI-OLED-Breakout) und vier Steckplätze für I2C-Breakouts zur Verfügung. Abbildung 2.101 zeigt die Pico Breakout Garden Base. Die Pico Breakout Garden Base und die Pimoroni-Breakouts sind eine hervorragende Möglichkeit, ohne komplizierte Verdrahtungen, Lötarbeiten oder Steckbretter Versuchsaufbauten zu erstellen. Für die Ausbildung scheint mir gerade dieser Aspekt von großer Bedeutung.
Abbildung 2.101 Pico Breakout Garden Base
Maker Pi Pico
Das Maker Pi Pico Board der Firma Cytron aus Malaysia, was auch hierzulande angeboten wird, erfüllt nahezu alle Wünsche, die an ein Erweiterungsboard gestellt werden. Es bietet Zugriff auf alle Pins des Raspberry Pi Pico und weist LEDs an den Anschlüssen auf. Des Weiteren sind drei Taster, eine RGB-LED (NeoPixel), ein Buzzer, ein 3,5 mm Stereo Audio Jack, ein Micro-SD-Karten-Slot, sechs GrovePorts und ein ESP-01 Socket auf dem Board vorhanden.
Abbildung 2.102 zeigt eine Übersicht über das Maker-Pi-Pico-Board, einschließlich der Erläuterung der diversen Anschlüsse.
Abbildung 2.102 Maker Pi Pico (Bild: Cytron Technologies)
Da der Raspberry Pi Pico selbst keine WiFi-Kommunikation aufweist, dient ein ESP-01 der Verbindung ins Internet. Ich komme genau auf diesen Aspekt bei den Anwendungen in Abschnitt 10.7.2 noch zurück. Auf der Website des Herstellers https://www.cytron.io/p-maker-pipico finden Sie weiterführende Informationen.
3 Das Experimentierumfeld In den letzten Kapiteln habe ich Ihnen Grundlagen zum Mikrocontroller allgemein und die Arduino-Familie einschließlich der Shields zur Erweiterung vorgestellt. Bevor wir zum Software-Teil kommen, auf den Sie sicher schon warten, will ich Ihnen aber noch unser Experimentierumfeld näherbringen. Um Ihren Arduino herum brauchen Sie noch Zusatzschaltungen aus elektronischen Bauelementen, die nach bestimmten Regeln zusammengeschaltet werden sollten, um die gewünschte Funktion sicherzustellen. Bestimmtes Zubehör unterstützt den elektronischen Aufbau. Bei der Inbetriebnahme helfen Messmittel, und schließlich soll das resultierende Schaltbild dokumentiert und vielleicht sogar eine Leiterplatte daraus gefertigt werden. All diese spannenden Themen erwarten Sie in diesem Kapitel. Danach können Sie gut vorbereitet in den Software-Teil einsteigen.
3.1 Elektronische Bauteile Mit den bislang vorgestellten Hardwarekomponenten kennen Sie schon einige elektronische Bauteile. In diesem Kapitel geht es aber darum, dass Sie die grundlegenden Eigenschaften der Bauteile
kennenlernen, mit denen wir später unseren Arduino erweitern. Außerdem helfen die Kenntnisse dabei, ein vorgegebenes Schaltbild zu verstehen.
3.1.1 Widerstand, Kondensator und Spule Mit Widerständen, Kondensatoren und Spulen wurden Sie bereits im Physikunterricht konfrontiert. Widerstand
Sicher kennen Sie auch noch den Begriff des ohmschen Widerstandes. Er ist ein elektrischer Widerstand R, dessen Widerstandswert im Gleichstromkreis genauso groß ist wie im Wechselstromkreis. Für ihn gilt das ohmsche Gesetz: U = I × R Das ohmsche Gesetz besagt, dass die Stromstärke I in einem Leiter und die Spannung U zwischen den Enden des Leiters direkt proportional sind. Außerdem erzeugt der Stromfluss eine Erwärmung des Widerstands. Es wird Leistung P umgesetzt, die nach der Beziehung
berechnet werden kann. Das Schaltbild für den Widerstand zeigt Abbildung 3.1. Die linke Darstellung 1 entspricht der EU-Norm und bezeichnet einen Widerstand R1 mit einem Wert von 1 kΩ (kOhm). Die rechte Darstellung 2 entspricht der US-Norm und bezeichnet einen Widerstand R2 mit einem Widerstandswert von 2,2 kΩ. Ich zeige hier
beide Normen, da beispielsweise im weitverbreiteten CADProgramm Fritzing, das ich Ihnen in Abschnitt 3.7.1 vorstelle, die USSymbole verwendet werden.
Abbildung 3.1 Schaltbild für den Widerstand
Widerstände sind durch die Kenngrößen Nennwiderstand, Belastbarkeit und Toleranz bestimmt. Berechnungsbeispiel Ein Widerstand soll bei einer Spannung von 5 V den Stromfluss auf 25 mA begrenzen. Nach dem ohmschen Gesetz bekommen wir einen Widerstandswert von 200 Ω. In der Widerstandsreihe E48 finden wir aber nur einen Widerstand von 205 Ω (siehe Abschnitt A.3.2), wodurch der Strom 24,39 mA betragen wird. Die umgesetzte Leistung beträgt 122 mW. Berechnete Kenngrößen: Nennwiderstand 205 Ω
Belastbarkeit 0,125 W (SMD-Bauform min. 0805) Toleranz 2 % (E48)
Ohmsche Widerstände als Bauteil gibt es in verschiedenen Bauformen. Sicher jedem bekannt sind bedrahtete Widerstände, deren Widerstandswert durch farbige Ringe gekennzeichnet wird. Abbildung 3.2 zeigt hierfür ein Beispiel.
Abbildung 3.2 Bedrahtete Widerstände (Quelle: Afrank99 – Eigenes Werk, CC BY-SA 2.5, https://commons.wikimedia.org/w/index.php?curid=456666)
Auf den bisher vorgestellten Boards war diese Bauform nicht vorhanden, obwohl Sie gerade für Versuchsaufbauten diese Widerstände sicher bevorzugen werden, weil sie sich gut handhaben lassen. Weil man Boards mit ihnen besser maschinell bestücken kann, werden auf den Boards heute praktisch ausschließlich Widerstände in SMD-Bauform (Surface Mounted Device) eingesetzt (siehe Abbildung 3.3). Sie sind als Dünnschicht- bzw. Metallschicht-, Metallglasur- und Kohleschichtwiderstände erhältlich.
Abbildung 3.3 SMD-Widerstand (Quelle: Haragayato, CC BY-SA 3.0, https://commons.wikimedia.org/w/index.php?curid=199075)
Technische Daten zur Kennzeichnung und zur Bauform habe ich im Anhang in Abschnitt A.3 zusammengestellt. Neben den hier betrachteten Festwiderständen (Widerstand mit festem Wert) gibt es Widerstände, die von einem Parameter abhängig sind. Zu ihnen zählen: Potenziometer Fotowiderstand temperaturabhängiger Widerstand (Thermistor) spannungsabhängiger Widerstand (Varistor) druck- und dehnungsabhängiger Widerstand Schaltungstechnisch sind diese parameterabhängigen Widerstände als ohmsche Widerstände zu betrachten, nur dass ihr Widerstandswert eine Funktion des betreffenden Parameters darstellt. Kondensator
Auch der Kondensator wird Ihnen aus dem Physikunterricht bekannt sein. Der Kondensator verhält sich im Gleichstromkreis anders als im Wechselstromkreis. Für unseren Anwendungsfall in einer digitalen Schaltung steht der Gleichstromkreis im Vordergrund, den wir hier auch vorrangig betrachten. Der Kondensator kann eine Ladung Q aufnehmen, die zu seiner Kapazität C proportional ist: Der Spannung U am Kondensator sind durch die Spannungsfestigkeit des Dielektrikums Grenzen gesetzt. Der Ladevorgang eines Kondensators C über einen Vorwiderstand R folgt einer Exponentialfunktion:
Dieses Verhalten ist deshalb wichtig, da hiervon zeitabhängige Größen f(t) abgeleitet werden. Es gibt sehr viele verschiedene Kondensatortypen und jeder hat seine spezifischen Eigenschaften und Anwendungen. Man unterscheidet die Kondensatortypen in der Regel anhand des Dielektrikums. Abbildung 3.4 zeigt Keramikkondensatoren unterschiedlicher Bauformen.
Abbildung 3.4 Keramikkondensatoren (Quelle: Elcap [CC BY-SA 3.0 (http://creativecommons.org/licenses/by-sa/3.0/)])
Der Keramikkondensator weist ein keramisches Dielektrikum auf. Die Zusammensetzung der Inhaltsstoffe des Dielektrikums ermöglicht die Herstellung von Kondensatoren mit vorher bestimmbaren elektrischen Eigenschaften. Keramikkondensatoren werden überwiegend mit Kapazitäten von 1 pF bis 100 µF hergestellt. In der Bauform des KeramikvielschichtChipkondensators (Multi Layer Ceramic Capacitor, MLCC) sind sie die am häufigsten eingesetzten diskreten Kondensatoren in der Elektronik. Sie werden als Entstör-, Durchführungs- oder als Leistungskondensatoren verwendet. Wenn Sie Ihre Kenntnisse zum Keramikkondensator vertiefen wollen, dann finden Sie unter https://de.wikipedia.org/wiki/Keramikkondensator eine detaillierte Beschreibung zahlreicher Aspekte des Keramikkondensators. Folienkondensatoren weisen isolierende Kunststofffolien als Dielektrikum auf. Nach den Keramikkondensatoren und
Elektrolytkondensatoren gehören Folienkondensatoren zu den am häufigsten eingesetzten Kondensatorbauarten in der Elektronik. Die Hauptvorteile von metallisierten Kunststofffolienkondensatoren sind sehr niedrige ohmsche Verluste und eine kleine Induktivität. Sie zeichnen sich durch eine hohe Impulsbelastbarkeit aus. Bei Einsatz von Polypropylenfolie kommt außerdem noch eine geringe Temperaturabhängigkeit der Kapazität und des Verlustfaktors hinzu. Sie werden in Oszillatoren, Schwingkreisen, Frequenzfiltern, Abstimmkreisen und temperaturstabilen Zeitgliedern eingesetzt. Darüber hinaus werden sie in ADUmsetzern (Sample-and-Hold-Schaltung für AD-Umsetzer) eingesetzt. Die beiden letzten Einsatzgebiete sind durchaus für unsere Anwendungen interessant. Wenn Sie Ihre Kenntnisse zum Folienkondensator vertiefen wollen, dann finden Sie unter https://de.wikipedia.org/wiki/KunststoffFolienkondensator eine detaillierte Beschreibung zahlreicher Aspekte des Folienkondensators. Abbildung 3.5 zeigt Folienkondensatoren unterschiedlicher Bauform.
Abbildung 3.5 Folienkondensatoren (Quelle: Elcap [CC BY-SA 3.0 (http://creativecommons.org/licenses/by-sa/3.0)])
Ein Elektrolytkondensator ist ein gepolter Kondensator, dessen Anode aus Metall besteht, auf dem durch anodische Oxidation eine gleichmäßige, äußerst dünne, elektrisch isolierende Oxidschicht erzeugt wird, die das Dielektrikum des Kondensators bildet. Ein flüssiger oder fester Elektrolyt, der sich geometrisch der Oberflächenstruktur der Anode anpasst, bildet die Kathode des Elektrolytkondensators. Aluminium-Elektrolytkondensatoren sind preiswerter als Tantalbzw. Niob-Elektrolytkondensatoren und werden überall in der Elektronik eingesetzt. Gegenüber den Keramik- und Folienkondensatoren weisen Elektrolytkondensatoren eine hohe volumenbezogene Kapazität auf. Elektrolytkondensatoren sind gepolte Bauteile, die nur mit Gleichspannung betrieben werden dürfen. Falschpolung, zu hohe Spannung (oberhalb der Nennspannung) oder Rippelstrom-
Überlastung können den Kondensator zerstören. Die Zerstörung kann katastrophale Folgen (Explosion, Brand) nach sich ziehen! Durch die große spezifische Kapazität eignen sich Elektrolytkondensatoren besonders zum Entkoppeln unerwünschter Frequenzen vom zweistelligen Hertz-Bereich bis hin zu einigen Megahertz, zum Glätten gleichgerichteter Spannungen in Netzteilen, Schaltnetzteilen und Gleichspannungswandlern. Sie puffern auch Versorgungsspannungen bei plötzlichen Lastspitzen in digitalen Schaltungen. Auch hier darf der Hinweis auf die ausgezeichnete Darstellung der Thematik in der deutschen Wikipedia nicht fehlen. Wenn Sie also mehr Informationen zum Elektrolytkondensator benötigen, dann finden Sie unter https://de.wikipedia.org/wiki/Elektrolytkondensator wieder eine detaillierte Beschreibung zahlreicher Aspekte des Elektrolytkondensators. Abbildung 3.6 zeigt Elektrolytkondensatoren unterschiedlicher Bauform.
Abbildung 3.6 Elektrolyt- und Tantal-Kondensatoren (Quelle: Elcap [CC0 (https://creativecommons.org/publicdomain/zero/1.0/deed.de)])
Das Schaltbild für den Kondensator zeigt Abbildung 3.7. Die linke Darstellung 1 entspricht der EU-Norm und bezeichnet einen nicht
polarisierten Kondensator C1 mit einem Wert von 10 nF. Die Darstellung rechts daneben 2 entspricht der US-Norm und bezeichnet einen nicht polarisierten Kondensator C2 mit einem Wert von 100 pF. Auf der rechten Seite von Abbildung 3.7 sind die Schaltbilder polarisierter (Elektrolyt-)Kondensatoren zu sehen. Die Darstellung 3 entspricht wieder der EU-Norm und zeigt einen Elektrolytkondensator C3 mit einem Wert von 10 μF, während die Darstellung 4 der US-Norm entspricht und einen Elektrolytkondensator C4 mit einem Wert von 1 μF zeigt.
Abbildung 3.7 Schaltbild für Kondensatoren
Spule
Spulen können Teile eines Gerätes, z. B. eines Relais, eines Elektromagneten oder Elektromotors, eines Transformators oder Lautsprechers sein. Bei diesen Anwendungen wird das erzeugte Magnetfeld unmittelbar ausgenutzt. Spulen sind aber auch passive, induktive Bauelemente mit einer definierten Induktivität, die sich im Gleichstromkreis anders als im Wechselstromkreis verhalten. Eingesetzt werden Spulen unter anderem in Filterschaltungen, zur Störungsunterdrückung oder als Energiespeicher in Schaltnetzteilen. In einer Spule mit n Windungen, deren Länge l größer als ihr Durchmesser ist, erzeugt ein fließender Strom I ein Magnetfeld H nach folgender Beziehung:
Die Strom-Spannungsbeziehung an der Spule lautet:
Hier bezeichnen L die Induktivität der Spule und di/dt die Stromänderung über die Zeit. Mit anderen Worten erzeugt eine Stromänderung an einer Spule eine Spannung. Beim Schalten von Spulen und Relais müssen Sie dieses Verhalten berücksichtigen, was durch sogenannte Freilaufdioden geschieht. Abbildung 3.8 zeigt typische RingkernSpulen.
Abbildung 3.8 Typische Ringkern-Spulen
Bei den in diesem Buch betrachteten Arduino-Anwendungen spielen die Spulen als eigenständiges Bauteil eine untergeordnete Rolle. Ganz anders sieht das bei Relais, Magneten und Elektromotoren aus.
3.1.2 Taster, Schalter und Relais Taster und Schalter sind mechanische Elemente, die den Stromfluss ermöglichen oder unterbrechen. Der Unterschied zwischen einem Taster und einem Schalter liegt in der mechanischen Verriegelung. Ein Taster ist nur bei Betätigung aktiv (offen oder geschlossen) und kehrt nach der Betätigung wieder in seinen Ausgangszustand zurück, während ein Schalter bei Betätigung geschlossen wird und sich erst bei erneuter Betätigung wieder öffnet oder umgekehrt. Abbildung 3.9 zeigt die Schaltbilder für Taster 1, Schalter 2, DIPSchalter 3, Drehschalter 4 und ein Relais mit einem Umschaltkontakt 5. Taster und Schalter werden durch die Kennzeichnung der mechanischen Betätigung an der Schaltzunge unterschieden.
Abbildung 3.9 Taster, Schalter und Relais – Schaltbilder
Abbildung 3.10 zeigt beispielhaft für die Leiterplattenbestückung geeignete Bauformen für Taster, Schalter und Relais. Die Vielfalt ist hier außerordentlich groß. Sicher kennen Sie auch andere Bauformen für diese Gruppe von Bauelementen, die wir in unseren Anwendungen immer wieder vorfinden werden.
Abbildung 3.10 Taster, Schalter und Relais – Beispiele für Bauformen
3.1.3 Dioden Dioden möchte ich insgesamt betrachten, da sie eine wesentliche gemeinsame Eigenschaft aufweisen: Sie lassen den Stromfluss in eine Richtung durch und sperren ihn in der anderen Richtung. In der Halbleitertechnik bezieht sich der Begriff Diode in der Regel auf Siliziumdioden mit einem p-n-Übergang. Das sind auch die Dioden, mit denen wir in unseren Anwendungen zu tun haben werden. Andere Varianten werden z. B. speziell als Schottky-Diode oder Germanium-Diode bezeichnet. Dioden werden wegen ihrer richtungsabhängigen Leitfähigkeit zur Gleichrichtung von Wechselspannung zu Gleichspannung, für logische Verknüpfungen, als Freilaufdioden und für viele weitere Zwecke eingesetzt. Abbildung 3.11 zeigt die Strom-Spannungskennlinie einer Diode des Typs 1N914. Deutlich erkennbar ist das von einem idealen Schalter abweichende Verhalten.
Abbildung 3.11 Dioden-Kennlinie
Im Durchlassbereich muss erst eine Flussspannung von ca. 0,5 V überwunden werden, bevor ein hinreichend großer Strom durch die Diode fließen kann. Im Bereich um 0,65 V ändert sich bei einer SiDiode die Spannung nur noch wenig. In diesem Bereich kann das Verhalten der Diode sehr gut durch die Shockley-Gleichung beschrieben werden:
Hier gilt: Strom durch die Diode in Flussrichtung ID (Sättigungs-)Sperrstrom IS = 10–12 … 10–6 A Emmisionskoeffizient n = 1 … 2 Temperaturspannung UT = kT/q (ca. 25 mV bei Raumtemperatur) Boltzmann-Konstante k = 1381 × 10–21 Ws/K Elementarladung e = 1602 × 10–19 As Im Sperrbereich, das bedeutet umgekehrte Polarität der anliegenden Spannung, fließt ein kleiner Sperrstrom. Erreicht die in Sperrrichtung an der Diode angelegte Spannung die sogenannte Durchbruchspannung, dann ist die Feldstärke im p-n-Übergang so groß, dass durch den Durchbrucheffekt bedingt der Stromfluss stark zunimmt. Dieser Bereich ist für die normale Anwendung tabu. Nur bei Z-Dioden wird dieser Durchbruch speziell zur Erzeugung von Spannung-Referenzen genutzt. Es gibt aber weitere Effekte am p-n-Übergang, die für spezielle Dioden genutzt werden. Bei Fotodioden wird die Lichtempfindlichkeit des p-n-Übergangs ausgenutzt. Der
Sperrstrom ist proportional zum einfallenden Licht, weshalb die Fotodiode sehr gut zur Lichtmessung eingesetzt werden kann. Der prinzipielle Aufbau einer Leuchtdiode (LED) entspricht dem einer p-n-Halbleiterdiode, wodurch LEDs die gleichen Grundeigenschaften besitzen. Dioden aus Silizium oder Germanium leuchten nicht. Ist das Ausgangsmaterial aber ein direkter Halbleiter (meist eine Gallium- oder GalliumarsenidVerbindung), dann wird vom p-n-Übergang bei Stromfluss in Durchlassrichtung Licht abgegeben. LEDs haben als Anzeigeelemente eine herausragende Bedeutung. In Abschnitt 7.1 gehe ich auf deren Besonderheiten ein. Abbildung 3.12 zeigt die Schaltbilder für verschiedene Dioden. D1 1 steht für eine »Allzweck«-Diode 1N4446, die es von verschiedenen Herstellern gibt. D2 2 ist eine Z-Diode, was durch die den Durchbruch kennzeichnende Katode verdeutlicht wird. D3 3 steht für eine Fotodiode. Die Lichtempfindlichkeit wird durch die Pfeile markiert, die einfallende Strahlung symbolisieren. Umgekehrt ist das bei der LED 4. Alle diese Bauteile werden wir in den Anwendungen wiederfinden.
Abbildung 3.12 Dioden – Schaltbilder
Abbildung 3.13 zeigt unterschiedliche Bauformen der in Abbildung 3.12 dargestellten Dioden. Die »Allzweck«-Diode 1N4446 1 und die Z-Diode 1N821 2 haben Standardgehäuse mit axialen Anschlüssen (DO-204AA). Die Fotodiode BP104 3 weist ein
für die SMD-Montage geeignetes DIL-Gehäuse (Dual In Line) auf. Die LED LS T670 4 mit ihrem PLCC-Gehäuse ist ebenfalls für die SMDMontage geeignet. Die traditionelle LED-Bauform sind die 3-mmoder 5-mm-Rundgehäuse 5, die gerade für Experimente gut geeignet sind. Im Rundgehäuse gibt es auch zwei- oder dreifarbige LEDs, die durch mehrere verschiedenfarbige LED-Chips gebildet werden.
Abbildung 3.13 Dioden – Beispiele für Bauformen
Die Vielfalt ist auch hier außerordentlich groß. Sicher kennen Sie andere Bauformen für diese Gruppe von Bauelementen, die wir in unseren Anwendungen immer wieder vorfinden werden
3.1.4 Transistoren und FETs als Schalter Bei Bipolar- und Feldeffekt-Transistoren (FET) mache ich bereits in der Überschrift eine Einschränkung. Im Umfeld des Arduino werden diese Bauteile im Wesentlichen als Schalter betrieben, was die Betrachtung dieser Bauteile deutlich vereinfacht. Wenn von Transistoren gesprochen wird, dann sind in der Regel Bipolartransistoren gemeint, die es als npn-Transistoren bzw. pnpTransistoren gibt. Beide Varianten bestehen aus jeweils zwei p-nÜbergängen. Abbildung 3.14 zeigt schematisch den Aufbau eines npn-Transistors. Die beiden p-n-Übergänge sind vertikal angeordnet.
Abbildung 3.14 Aufbau des npn-Transistors
Beschrieben wird das Verhalten eines Transistors durch ein recht komplexes Kennlinienfeld (siehe Abbildung 3.15). Die im Kennlinienfeld verwendeten Bezeichnungen für Spannungen und Ströme sind gemäß Abbildung 3.16 definiert.
Abbildung 3.15 Transistor-Kennlinienfeld
Abbildung 3.16 Spannungen am npn-Transistor
Das Eingangskennlinienfeld beschreibt das Verhalten des BasisEmitter-Übergangs und zeigt uns eine Dioden-Kennlinie. Diese Kennlinie haben Sie in Abschnitt 3.1.3 bereits für den Durchlassbereich der Diode kennengelernt. Eine am Basis-EmitterÜbergang anliegende Spannung UBE hat einen Basisstrom IB zur Folge. Im eingeschalteten Zustand des Transistors wird die BasisEmitter-Spannung ca. 0,65 V betragen und sich in Abhängigkeit vom Strom nur noch wenig ändern. Durch den fließenden Basisstrom wird die Basis mit Ladungsträgern geflutet, was Auswirkungen auf die Sperrschicht des Collector-BasisÜbergangs hat und diesen Übergang ebenfalls leitend macht. Der dadurch fließende Kollektorstrom ist wesentlich größer als der Basisstrom, was in der nahezu linearen Stromverstärkung des Transistors zum Ausdruck kommt. Die Stromsteuerkennlinie bringt das zum Ausdruck. Stromverstärkungen von BN = 100 und mehr sind üblich. Es gilt die Beziehung:
Das Ausgangskennlinienfeld beschreibt das Verhalten der CollectorEmitter-Strecke. Als Steuergröße wirkt der Basisstrom. Für den aktiven Betrieb als Verstärkerelement ist das Kennlinienfeld insgesamt interessant, im Betrieb als Schalter nur das Gebiet nahe der Abszisse (x-Achse) und nahe der Ordinate (y-Achse). Fließt kein Basisstrom (Sperrzustand des Transistors), dann verbleibt ein äußerst kleiner Collector-Emitter-Reststrom ICE0, der meist im nA-Bereich liegt, und die Collector-Emitter-Spannung UCE liegt sehr nahe an der Betriebsspannung. Fließt hingegen ein ausreichend großer Basisstrom, dann leitet der Transistor und kommt in die Übersteuerung (UCB < 0). Die Collector-EmitterSpannung verharrt bei der Collector-Emitter-
Sättigungsspannung UCES, die in der Regel unterhalb von 200 mV liegt. Diese beiden Arbeitspunkte des Transistors im Betrieb als Schalter habe ich ins Ausgangskennlinienfeld eingezeichnet (siehe Abbildung 3.15). Der Feldeffekttransistor (FET) hat einen einfacheren Aufbau als der Bipolartransistor (siehe Abbildung 3.17).
Abbildung 3.17 Aufbau eines n-Kanal-MOSFET
Die Leitfähigkeit des Kanals zwischen Drain- und Source-Anschluss wird durch die Gate-Source-Spannung gesteuert. Beim FET handelt es sich also um einen gesteuerten Widerstand. Der große Vorteil gegenüber Bipolartransistoren ist die verlustfreie Ansteuerung. Der Eingang des FETs ist hochohmig. Der Widerstand zwischen Drain und Source im eingeschalteten Zustand ist nicht zu vernachlässigen und ist stark bauelementeabhängig. Hier müssen Sie in jedem Fall das Datenblatt konsultieren! Einige Beispiele helfen, das zu verdeutlichen: Typ
Bauteil
RDSon
UDS @ ID = 100 mA
Typ
Bauteil
RDSon
UDS @ ID = 100 mA
5 Ω
500 mV
BSS295
0,3 Ω
30 mV
2SK2961
0,2 Ω
20 mV
IRLD024
0,1 Ω
10 mV
14 Ω
1400 mV
VP0808L
5 Ω
500 mV
VP0300L
2,5 Ω
250 mV
n-Kanal BS170
p-Kanal BS250
IRFD9024 0,28 Ω 28 mV Tabelle 3.1 RDSon verschiedener FETs
Aufbaubedingt sind die Widerstände im eingeschalteten Zustand bei p-Kanal-FETs höher als bei n-Kanal-FETs. Kommen wir zum praktischen Teil und betrachten die Schaltbilder in Abbildung 3.18. Der Pfeil am Emitter des Bipolartransistors zeigt, ob es sich um einen npn-Transistor 1 oder um einen pnpTransistor 2 handelt. Beim FET zeigt die unterbrochene Strecke zwischen Drain und Source, dass der Kanal nicht selbstleitend ist (selbstsperrender bzw. Enhancement-Typ). Den selbstleitenden FET (Verarmungstyp bzw. Depletion Typ) habe ich hier nicht betrachtet. Der Pfeil am Gate kennzeichnet die Dotierung des Kanals (nKanal 3, p-Kanal 4).
Abbildung 3.18 Schaltbilder für Transistor und FET
Auch für FETs wie für Bipolartransistoren gibt es wieder sehr unterschiedliche Bauformen. Abbildung 3.19 zeigt links TO-92Gehäuse. Die Gehäuse rechts sind für die SMD-Bestückung geeignet und werden für leistungsstärkere Typen verwendet.
Abbildung 3.19 Bauformen für Bipolartransistoren und FETs
Wie die verschiedenen Transistoren und FETs als Schalter in Digitalschaltungen eingesetzt werden, zeigen Ihnen die folgenden Abbildungen. Abbildung 3.20 zeigt einen npn-Transistor als Schalter. Diese Schaltung werden Sie sehr oft wiederfinden, z. B. zur Ansteuerung von LEDs, Relais und anderen Bauelementen. Geschaltet wird die Last am Kollektor, der hier durch den Widerstand R3 dargestellt und gegen die Betriebsspannung geschaltet ist. Eine hohe Spannung am Eingang (IN) schaltet den Transistor ein. Der Widerstand R1 dient zur Begrenzung des Eingangsstroms. Bei Einsatz des Widerstands R2 wird die Einschaltschwelle für den Transistor beeinflusst. Ich komme in einem Berechnungsbeispiel noch darauf zurück.
Abbildung 3.20 npn-Transistor als Schalter
Beim Einsatz eines pnp-Transistors kehren sich die Verhältnisse um. Die Last ist hier gegen Masse (GND) geschaltet, und eine niedrige Spannung am Eingang (IN) schaltet den Transistor ein (siehe Abbildung 3.21).
Abbildung 3.21 pnp-Transistor als Schalter
Die Schaltungen für FETs sind denen der Bipolartransistoren sehr ähnlich (siehe Abbildung 3.22 und Abbildung 3.23). Ich bin hier von FETs mit Schaltspannungen am Gate im Bereich von bis zu 5 V ausgegangen, wodurch eine aufwendigere Schaltung am Gate vermieden werden kann. Da bauartbedingt die Kapazität zwischen Gate und Source nicht zu vernachlässigen ist, kann der Widerstand R1 dynamisch entkoppeln bzw. eine Schwingneigung unterdrücken. Statisch hat er wegen des hochohmigen Eingangs keine Bedeutung. Der n-Kanal-FET wird durch eine hohe Spannung am Eingang (IN) eingeschaltet. Beim p-Kanal-FET geschieht das wiederum durch eine niedrige Spannung am Eingang (IN).
Abbildung 3.22 n-Kanal-FET als Schalter
Abbildung 3.23 p-Kanal-FET als Schalter
3.1.5 Operationsverstärker Operationsverstärker sind eine wichtige Klasse analoger Schaltungen und könnten ein eigenes Buch füllen. Ich erwähne sie hier nur deshalb, weil Sie die relevanten Grundlagen kennen sollten, um ihren Einsatz zur Anbindung von Sensoren oder in Verbindung mit AD-Umsetzern (ADU) zu verstehen. Operationsverstärker gibt es in vielen verschiedenen Ausführungen. Allen gemeinsam sind aber die folgenden Eigenschaften (idealer Operationsverstärker): sehr hohe Verstärkung (unendliche Verstärkung) hoher Eingangswiderstand (unendlicher Eingangswiderstand)
vernachlässigbare Eingangsströme (keine Eingangsströme) sehr niedriger Ausgangswiderstand (kein Ausgangswiderstand) Durch die hohe Verstärkung des Operationsverstärkers bedingt, wird die Eingangsspannung – das ist die Differenz der Spannungen an den beiden Eingängen (+) und (–) – sehr klein bzw. geht gegen null. Für den in Abbildung 3.24 gezeigten invertierenden Operationsverstärker bedeutet das, dass die Spannung am Eingang (–) scheinbar auf GND-Potenzial zu liegen kommt (virtueller GND). Der durch den Widerstand R1 fließende Strom wird also mit dem durch den Widerstand R2 fließenden Strom identisch sein.
Abbildung 3.24 Invertierender Operationsverstärker
Ich greife hier dem nächsten Kapitel einmal kurz vor und gebe die Formel für das Übertragungsverhalten des invertierenden Operationsverstärkers an:
Wenn wir die oben angegebenen Bedingungen für einen idealen Operationsverstärker annehmen, bestimmen die Widerstände R1
und R2 das Verhalten der Gesamtschaltung. Die Spannungsversstärkung entspricht dem Verhältnis – (R2/R1), daher der Name invertierender Verstärker (eine positive Eingangsspannung hat eine negative Ausgangsspannung zur Folge). Der Eingangswiderstand der Schaltung ist identisch mit dem Widerstand R1. Die Betriebsspannungen VCC und VSS liegen hier symmetrisch zu GND. Beispielsweise sind oft VCC = 12 V und VSS = –12 V oder auch VCC = 5 V und VSS = –5 V. Durch Vertauschen der Eingänge bekommt man einen nichtinvertierenden Operationsverstärker gemäß Abbildung 3.25.
Abbildung 3.25 Nichtinvertierender Operationsverstärker
Der Eingang der Schaltung führt direkt an den Eingang (+) des Operationsverstärkers. Die Eingangsspannung liegt damit auch über dem Widerstand R1, die Ausgangsspannung hingegen über der
Reihenschaltung von R1 und R2. Für das Übertragungsverhalten gilt dann:
Die minimale Spannungsverstärkung beträgt hier also 1. Größere Spannungsverstärkungen sind über das Verhältnis R2/R1 einstellbar. Eine positive Eingangsspannung hat auch eine positive Ausgangsspannung zur Folge. Der sogenannte Spannungsfolger (R2 = 0, R1 nicht vorhanden => v = 1) dient häufig zur Entkopplung. Der Eingangswiderstand ist durch den Operationsverstärker gegeben sehr hoch und der Ausgangswiderstand sehr niedrig. Wenn Sie sich tiefer in diese Thematik einarbeiten möchten, dann kann ich Ihnen einen Blick in das Elektronikkompendium unter http://www.elektronik-kompendium.de/sites/bau/0209092.htm empfehlen.
3.2 Grundlagen zur Schaltungstechnik An einigen Stellen hatte ich bereits auf Grundlagen zur Schaltungstechnik zurückgegriffen, die ich Ihnen in diesem Abschnitt aber zusammengefasst vorstellen möchte. Keine Angst: Es ist keine graue Theorie, und Sie werden Schaltungsdetails besser verstehen, wenn Ihnen diese Grundlagen bekannt sind.
3.2.1 Ohmsches Gesetz Bei der Betrachtung des Widerstands R in Abschnitt 3.1.1 habe ich bereits das ohmsche Gesetz erwähnt. Es besagt, dass die Stromstärke I in einem Leiter und die Spannung U zwischen den Enden des Leiters direkt proportional sind: U = I × R Dieser Zusammenhang ist fundamental für alle unsere schaltungstechnischen Betrachtungen.
3.2.2 Kirchhoffsche Regeln Bei der Analyse elektrischer Schaltungen werden die kirchhoffschen Regeln eingesetzt. Die kirchhoffschen Regeln beschreiben den Zusammenhang zwischen Strömen und Spannungen in einer elektrischen Schaltung. Sie unterteilen sich in den Knotenpunktsatz und den Maschensatz. Knotenpunktsatz
Der Knotenpunktsatz besagt, dass in einem Knotenpunkt einer elektrischen Schaltung die Summe der hineinfließenden Ströme gleich der Summe der herausfließenden Ströme ist. Mit anderen Worten: Die Summe der Ströme in einem Knotenpunkt einer elektrischen Schaltung ist gleich null.
Abbildung 3.26 zeigt einen Knotenpunkt mit den hineinfließenden Strömen I1 und I4 sowie den hinausfließenden Strömen I2 und I3 (n = 4).
Abbildung 3.26 Knotenpunkt mit hinein- und hinausfließenden Strömen
Mit einem einfachen praktischen Beispiel zeige ich Ihnen die Anwendung des Knotenpunktsatzes. Abbildung 3.27 zeigt Ihnen noch einmal den invertierenden Verstärker aus Abbildung 3.24, diesmal aber etwas umgezeichnet.
Abbildung 3.27 Invertierender Verstärker
Die Eingangsspannung UIN treibt den Strom I1 in den Knoten am Eingang (–) des Operationsverstärkers. Da der Eingangsstrom des Operationsverstärkers mit null angenommen wird, fließt nur der Strom I2 aus dem Knoten heraus. Es gilt also I1 = I2 oder auch I1 – I2 = 0. Jetzt ersetzen wir die Ströme dem ohmschen Gesetz folgend durch die Spannungsabfälle über dem jeweiligen Widerstand:
Das Minuszeichen vor der Ausgangsspannung steht deshalb, weil die Ausgangsspannung UOUT nicht die gleiche Richtung wie der Strom I2 hat. Wenn Sie die letzte Gleichung nun nach UOUT umstellen, dann erhalten Sie die Gleichung aus Abschnitt 3.1.5, die das Übertragungsverhalten des invertierenden Operationsverstärkers beschreibt:
Maschensatz
Der Maschensatz besagt, dass alle Spannungen in einem geschlossenen Stromkreis (Masche) gleich null sind:
Angewendet auf den in Abbildung 3.28 gezeigten Stromkreis, bedeutet das in Richtung der eingetragenen Orientierung für den Strom I:
Abbildung 3.28 Maschensatz
Mit einem Beispiel möchte ich Ihnen wieder die Handhabung des Maschensatzes und anschließend die Kombination beider Regeln demonstrieren. Abbildung 3.29 zeigt eine Ihnen bereits bekannte Schaltung – eine Inverterstufe mit einem npn-Transistor.
Abbildung 3.29 Inverterstufe
Wir betrachten den Eingangskreis in Richtung des eingezeichneten Pfeils und können nach dem Maschensatz folgende Gleichung aufstellen: Der Basisstrom wird durch den Stromverstärkungsfaktor BN und eine mögliche Übersteuerung m im Schalterbetrieb zu:
Der Kollektorstrom IC beträgt im durchgesteuerten Zustand des Transistors:
Die Schwellenspannung UINS für das Umschalten der Inverterstufe kann nun durch das Zusammenführen der drei Gleichungen berechnet werden:
Mit den Werten BN = 100, m = 5 und UCES = 0,1 V und den in Abbildung 3.29 angegebenen Widerstandswerten für R1 und R3 erhält man eine Schwellenspannung UINS von 0,9 V. Die Ausgangsspannung VOL des ATmega328P, die für den Lo-Pegel steht, liegt im Extremfall bei dem Wert der berechneten Schwellenspannung UINS (siehe Tabelle 3.2). Symbol Parameter
Messbedingung Wert
VOL
Output Low Voltage
IOL = 20 mA,
VCC = 5 V
VOH
Output High Voltage IOH = –20 mA,
VCC = 5 V
Tabelle 3.2 ATmega328P – Spannungen am digitalen Ausgang
4,2 V
Das sind keine guten Voraussetzungen für ein sicheres Schaltverhalten der Inverterstufe. Durch Einfügen des Widerstands R2 (siehe Abbildung 3.30) soll die Schwellenspannung in einen sicheren Bereich verschoben werden.
Abbildung 3.30 Erweiterte Inverterstufe
Um die Veränderung der Schwellenspannung UINS zu berechnen, müssen wir den Knoten an der Basis des Transistors und den Eingangskreis betrachten. Die Formeln dazu kennen Sie bereits. Mit dem Knotenpunktsatz erhält man: Nach dem Maschensatz ergibt sich nun die folgende Änderung:
Mit den oben angegebenen Beziehungen für IB und IC und dem Strom I2 = UBE/R2 erhalten Sie nach der Umstellung der Formel
folgende Beziehung:
Daraus können Sie für die Schwellenspannung UINS einen Wert von UINS = 2,4 V berechnen. Die Schwellenspannung für die an einen digitalen Ausgang angeschlossene Inverterstufe liegt nun in der Mitte des Spannungshubs und sollte damit wesentlich unempfindlicher gegenüber Störungen sein.
3.2.3 Reihen- und Parallelschaltung von Widerständen Mit der Kenntnis des ohmschen Gesetzes und der kirchhoffschen Regeln können Sie nun auch die Reihen- und Parallelschaltung von Widerständen berechnen (siehe Abbildung 3.31).
Abbildung 3.31 Reihen- und Parallelschaltung von Widerständen
Werden Widerstände in Reihe geschaltet, werden diese vom gleichen Strom durchflossen. Mit dem Maschensatz gilt die Beziehung U1 = UR1 + UR2 = I × (R1 + R2) und für den Gesamtwiderstand dann R = R1 + R2.
Bei der Parallelschaltung von Widerständen liegt über allen Widerständen die gleiche Spannung an. Mit dem Knotenpunktsatz gilt:
Daraus folgt durch Umstellung:
Bei der Parallelschaltung von Widerständen addieren sich also deren Leitwerte (Gi = 1/Ri). Bei der Parallelschaltung von zwei Widerständen, wie oben angegeben, vereinfacht sich die Formel zu:
Merke: Gesamtwiderstand Der Gesamtwiderstand parallel geschalteter Widerstände ist immer kleiner als deren kleinster Widerstandswert.
So viel zu den theoretischen Grundlagen. Sie werden sie immer wieder heranziehen müssen, wenn es um konkrete Dimensionierungen von Bauteilen geht.
3.3 Breadboards und Zubehör In den vorigen beiden Abschnitten haben Sie Schaltungsteile und die erforderlichen Grundlagen zu ihrer Berechnung kennengelernt. In diesem Abschnitt möchte ich Sie mit einigen empfehlenswerten Hardware-Erweiterungen bekannt machen. Diese Hardware soll den Aufbau Ihrer Versuchsschaltungen oder Prototypen so einfach wie möglich machen. Nichts ist schlimmer, als einen Fehler in einem Drahtverhau zu suchen, dessen Ursachen möglicherweise an ganz anderer Stelle liegen.
3.3.1 Breadboards Zum Aufbau von Versuchsschaltungen sind die sogenannten Breadboards (Steckbretter) sehr beliebt. Ich bleibe hier bei den originalen Begriffen, denn mit diesen können Sie entsprechende Angebote im Netz finden. Die Breadboards sind in verschiedenen Größen bis hin zum Arduino Prototyping Shield zu haben. Abbildung 3.32 zeigt Ihnen Breadboards in verschiedenen Größen sowie deren Abmessungen.
Abbildung 3.32 Breadboards verschiedener Größe
Allen Breadboards gemeinsam sind die Verbindungen der verschiedenen Lochraster. In Abbildung 3.33 habe ich einige verbundene Lochreihen farbig hervorgehoben.
Abbildung 3.33 Verbundene Lochreihen
An der Ober- und Unterkante befinden sich Lochreihen, die der Zuführung der Betriebsspannung (+) und des Massepotenzials (–) dienen. Im mittleren Bereich sind die senkrechten Reihen verbunden, die dann die elektrischen Bauteile aufnehmen.
Die Breadboards weisen aber noch eine weitere wichtige Eigenschaft auf. Mechanisch ist dafür gesorgt, dass die Breadboards durch Zusammenstecken zu einer größeren Prototyping-Fläche kombiniert werden können. Abbildung 3.34 zeigt Ihnen verschiedene Kombinationsmöglichkeiten.
Abbildung 3.34 Kombination von Breadboards
Speziell für den Arduino gibt es noch ein sogenanntes Prototype Shield – eine Kombination aus einem Lochraster-Shield und einem kleinen Breadboard. Abbildung 3.35 zeigt das Prototype Shield v.5, wie es von verschiedenen Lieferanten so oder in ähnlicher Form angeboten wird. Ich habe dieses Shield im Dezember 2022 für ca. 3 € erworben.
Abbildung 3.35 Prototype Shield v.5
Neben den Arduino-Steckerleisten weist das Shield zwei LEDs mit Vorwiderstand, zwei Taster (davon einer ein Reset) und einen Lochrasterbereich sowie einen Bereich zum Auflöten eines Bausteins im SOIC-Gehäuse auf. Möchten Sie das Breadboard in Verbindung mit dem Shield nutzen, dann können Sie es mit dem dort bereits angebrachten doppelseitigen Klebeband (nach Lösen der Schutzfolie) auf das Prototype Shield aufkleben.
3.3.2 Breadboard Holder Ein sehr einfacher Breadboard Holder (Steckbrett-Halter) entsteht bereits durch das Aufkleben des kleinen Breadboards auf das im vorigen Abschnitt vorgestellte Protoptype Shield. Abbildung 3.36 zeigt Ihnen diese Kombination, die ich gern für kleine Versuchsaufbauten nutze, z. B. für den Anschluss eines Sensor-Boards oder einiger LEDs. Die Kontakte des darunter liegenden Arduinos stehen auf dem Prototype Shield 1:1 zur Verfügung und können mit den auf dem Breadboard erstellten Schaltungsteilen einfach zusammengeschaltet werden.
Abbildung 3.36 Prototype Shield v.5 mit aufgesetztem Breadboard
Benötigen Sie etwas mehr Platz auf dem Breadboard, dann können Sie den von SparkFun für 3,95 US$ angebotenen Arduino and Breadboard Holder (https://www. sparkfun.com/products/11235) einsetzen. Abbildung 3.37 zeigt diesen, bestückt mit einem Arduino Uno und einem passenden Breadboard.
Abbildung 3.37 Breadboard Holder (Steckbrett-Halter)
In eine ganz andere Liga steigen Sie auf, wenn Sie das von der italienischen Firma Gtronics angebotene und als Arduino Protoshield bezeichnete Board einsetzen (siehe Abbildung 3.38). Da das Board für rund 50 € angeboten wird, wird nicht jeder es sofort bestellen. Dennoch sind die gebotenen Möglichkeiten vor allem für die Ausbildung sehr hilfreich, weshalb ich auch hier die URL des Gtronics-Shops (https://www.gtronicsshop.com/en/12-protoshieldplus) angebe. Dort finden Sie auch alle weiterführenden Informationen.
Abbildung 3.38 Arduino Protoshield (Quelle: Gtronics.NET)
3.3.3 Breadboard Power Für funktionierende Schaltungsaufbauten auf dem Breadboard sind (bei den größeren Boards) an der Ober- und Unterkante Lochreihen angeordnet, die der Zuführung der Betriebsspannung (+) und des Massepotenzials (–) dienen. Damit diese Lochreihen auch die
gewünschten Spannungen bereitstellen, verwenden Sie am einfachsten sogenannte Breadboard Power Adapter. Diese werden in unterschiedlichen Bauformen von vielen Distributoren zu Preisen von unter 5 € angeboten. Abbildung 3.39 zeigt einen auf ein Breadboard aufgesteckten Adapter. Die Spannungsversorgung kann über Micro-USB 1 oder über einen Rundstecker 2 erfolgen. Es lassen sich 3,3 V oder 5 V Betriebsspannung für die beiden Lochreihen unabhängig voneinander erzeugen.
Abbildung 3.39 Breadboard Power Adapter
3.4 Qwiic, Grove und mikroBUS Connection In diesem Abschnitt stelle ich Ihnen Hardware-Erweiterungen vor, mit denen sich das Prototyping auf Arduino-Basis wirkungsvoll vereinfachen lässt. Neben den in Abschnitt 2.3 vorgestellten Arduino-Shields gibt es die Prototyping-Systeme Qwiic von SparkFun, Grove von Seeed Studio und mikroBUS von Mikroelektronika. In diesem Abschnitt lernen Sie, wie Sie mit diesen Systemen Ihre Prototypen schnell erstellen und neue Funktionen austesten können.
3.4.1 Qwiic Connection SparkFun Qwiic Connection ist ein System aus über den I2C-Bus verbundenen Sensoren, Aktoren, Shields, Boards und passenden Kabeln, die das Prototyping beschleunigen und weniger fehleranfällig machen. Alle Qwiic-kompatiblen Boards verwenden einen vierpoligen JST-Anschluss mit 1 mm Rastermaß. Dadurch wird weniger Platz auf dem jeweiligen Board benötigt. Durch die Polarisierung der Anschlüsse können Sie keine Anschlussfehler begehen (https://www.sparkfun.com/qwiic). Um einen Überblick über das Qwiic-System zu bekommen, können Sie die Qwiic-Seite von SparkFun https://www.sparkfun.com/qwiic#products konsultieren. Ich zeige Ihnen in Abbildung 3.40 ein BME280-Breakout-Board. An der linken
und an der rechten Seite können Sie die Qwiic-Konnektoren (JST) sehen. Breakout Board Als Breakout Boards werden Leiterplatten bezeichnet, die elektronische Bauteile tragen, deren Anschlüsse nach außen geführt sind. Das ist häufig die einzige Möglichkeit im Prototypenbereich, um Bauteile mit kompakten Gehäusen überhaupt zu kontaktieren. Außerdem wäre man selbst technisch kaum in der Lage, diese Bauteile auf einer Leiterplatte zu montieren bzw. zu löten. Das in Abbildung 3.40 gezeigte Breakout Board mit dem BME280-Sensor-IC ist hierfür ein sehr gutes Beispiel.
Abbildung 3.40 BME280 Qwiic Breakout (Quelle: SparkFun)
Durch die Gestaltung der Boards des Qwiic-Systems lassen sich komplexe, örtlich verteilte Schaltungen aufbauen. Abbildung 3.41 zeigt eine solche Zusammenschaltung von Mikrocontroller (RedBoard Qwiic) und verschiedenen Qwiic-Breakout-Boards (GPS Breakout – XA1110, OpenLog, Transparent Graphical OLED Breakout, Environmental Combo Breakout).
Abbildung 3.41 Zusammenschaltung von Qwiic-Boards (Quelle: Sparkfun)
Wie Sie schon lesen konnten, wurde der I2C-Bus von Philips (heute NXP) für die Datenübertragung zwischen unterschiedlichen Bausteinen, wie EEPROMs, RAMs, AD- und DA-Umsetzern, RTCs und vielen mehr, und Mikrocontrollern auf einer Leiterplatte entwickelt. Der I2C-Bus ist nicht für lange Strecken ausgelegt. Das Protokoll erlaubt die Verbindung von bis zu 128 unterschiedlichen Bausteinen (Devices) mithilfe einer Zwei-Draht-Leitung. Eine sichere Übertragung über den I2C-Bus bei größeren Distanzen ist nur mit differenziellen Signalen möglich. Die schnellste und einfachste Möglichkeit, um die Reichweite des I2C-Busses zu erweitern, ist die Verwendung des Differential I2C Breakout Board (siehe Abbildung 3.42).
Abbildung 3.42 SparkFun Differential I2C Breakout – PCA9615 (Qwiic)
Das Board verwendet ein PCA9615-IC von NXP, das die beiden Standard-I2C-Signale SCL und SDA in vier Differenzsignale umwandelt: zwei für SCL und zwei für SDA. Die Differenzsignale werden über ein Ethernet-Kabel übertragen, das über die integrierten RJ-45-Anschlüsse an das Board angeschlossen wird. SparkFun gibt an, dass die differenzielle Signalübertragung Entfernungen von bis zu 300 m ermöglicht.
3.4.2 Grove-System Das Grove-System ist ein modulares Open-Source-PrototypingSystem mit standardisierten Steckverbindern. Das Grove-System besteht aus einem Base Shield und verschiedenen Modulen. Ein Base Shield ermöglicht den einfachen Anschluss aller Mikrocontrollereingänge oder -ausgänge der Grove-Module. Jedes Grove-Modul erfüllt eine einzelne Funktion, z. B. eine einfache Taste oder einen komplexen Sensor. Eine Übersicht über die mehr als 300
Grove-Module finden Sie unter https://www.seeedstudio.com/category/Grove-c-1003.html. Abbildung 3.43 zeigt das Grove Base Shield für den Arduino. Ein Schiebeschalter 1 ermöglicht die Wahl der Betriebsspannung in Abhängigkeit vom eingesetzten Arduino. Auf Grove-Konnektoren sind die Anschlüsse A0 bis A3, D2 bis D8 sowie UART und viermal I2C herausgeführt.
Abbildung 3.43 Grove Base Shield
Ich werde an mehreren Stellen dieses Buches auf den Einsatz von Grove-Modulen zurückkommen. Der Schaltungsaufbau wird dadurch wesentlich vereinfacht, und die Grove-Module selbst sind durch den Hersteller gut dokumentiert.
3.4.3 mikroBUS System mikroBUS versteht sich als Standard für Zusatzkarten, der maximale Erweiterbarkeit mit der geringsten Anzahl von Pins bietet.
Kontaktiert über einen mikroBUS-Sockel, lassen sich sogenannte Clickboards als Schaltungserweiterung nutzen. Sensoren, drahtlose Transceiver, Audioverstärker, LED-Anzeigen und anderes mehr stehen als Clickboard zur Verfügung. Eine Übersicht über die Komponenten des mikroBUS-Systems der Belgrader Firma MikroElektronika (mikroe) finden Sie unter https://www.mikroe.com/mikrobus. Um Clickboards für die Schaltungserweiterung einsetzen zu können, kann ein Arduino mit einem Arduino Uno Click Shield verbunden werden (siehe Abbildung 3.44). Damit stehen für die Erweiterung zwei mikroBUS-Steckplätze zur Verfügung.
Abbildung 3.44 Arduino Uno Click Shield
Librarys und Demoprogramme, die mit MikroElektronikaCompilern entwickelt wurden, sind auf der mikroe-Website zu finden. Die MikroElektronika-Compiler sind allerdings nicht Arduino-kompatibel!
Für den Betrieb am Arduino hat die französische Firma Lextronics eine Reihe von Programmbeispielen für zahlreiche Clickboards erstellt. Unter der URL https://www.mikroe.com/blog/-arduinolibraries-for-click-boards finden Sie die Programmbeispiele sowie Schaltbilder im Fritzing-Format. Das CAD-Programm Fritzing stelle ich Ihnen in Abschnitt 3.7.1 noch im Detail vor. Den Hinweisen von Lextronics folgend, können Sie später auch selbst Programme für weitere Clickboards erstellen.
3.5 Spannungsversorgung Für die Spannungsversorgung der Arduino-Boards gibt es in der Regel mehrere Möglichkeiten. Zum einen kann der eingesetzte Mikrocontroller direkt mit der betreffenden Betriebsspannung versorgt werden, was eine extern geregelte Versorgungsspannung von 3,3 V oder 5 V erfordert. Hat das betreffende Arduino-Board eine Spannungsregelung on-board, dann kann über den Anschluss VIN oder eine separate Buchse der Arduino mit einer höheren Spannung versorgt werden. Die einfachste Variante ist aber, das Arduino-Board über den USB-Anschluss mit Spannung zu versorgen.
3.5.1 USB-Anschluss Mit Ausnahme des Lilypad Arduino haben alle hier vorgestellten Arduinos einen USB-Anschluss, der zum Programm-Upload dient und zur Spannungsversorgung verwendet werden kann. Die auf den Arduinos verbauten Stecker sind verschieden, weshalb Sie sich mit unterschiedlichen USBKabeln ausrüsten sollten. Meist hat man diese aber ohnehin von bereits gekauften Geräten im Haus. Beim Arduino Uno finden Sie beispielsweise eine USB-Buchse vom Typ B, die ein Kabel mit einem Stecker gemäß Abbildung 3.45 verlangt. Diese Kabel werden oft für den Anschluss eines Druckers an einen PC verwendet.
Abbildung 3.45 USB-Stecker vom Typ B
Die kompakteren Arduino-Boards verlangen auch nach kleineren Steckverbindern, und so hat beispielsweise der Arduino Nano eine Mini-USB-Buchse, die ein Kabel mit dem in Abbildung 3.46 gezeigten Mini-USB-Stecker erfordert. Diese Steckverbinder sind häufig bei Digitalkameras zu finden.
Abbildung 3.46 Mini-USB-Stecker
Beim Arduino Micro und vielen anderen Arduinos wird eine Micro-USB-Buchse eingesetzt, die ein Kabel mit dem in Abbildung 3.47 gezeigten Micro-USB-Stecker erfordert. Diese Stecker werden oft bei älteren Smartphones und Tablets eingesetzt.
Abbildung 3.47 Micro-USB-Stecker
Gerade bei aktuellen Arduino-kompatiblen Boards kommt zunehmend eine USB-Buchse vom Typ C zum Einsatz. Diese Buchse erfordert ein Kabel, das mit einem USB-Stecker vom Typ C (siehe Abbildung 3.48) versehen ist.
Abbildung 3.48 USB-Stecker vom Typ C
USB Typ C ist ein 2015 eingeführtes Steckerformat. Diese Stecker sind kleiner und von beiden Seiten verwendbar. Sie müssen also nicht mehr darauf achten, wie herum der Stecker in die Buchse gesteckt werden muss. Laptops, Tablets und Smartphones weisen diesen Stecker auf.
Wenn man ein solches Kabel nicht zur Hand hat, dann kann man auch einen Adapter von Typ C auf Micro-USB verwenden. Abbildung 3.49 zeigt einen solchen Adapter, der von verschiedenen Herstellern angeboten wird.
Abbildung 3.49 Adapter »USB Typ C auf Micro-USB« von Xystec
So viel zu der Hardware, mit der Sie den Anschluss vornehmen können. Zur Spannungsversorgung müssen Sie wissen, dass USB 1.x und 2.0 nur bis zu 500 mA und USB 3.0 bis zu 900 mA Strom bereitstellen. Tabelle 3.3 zeigt die Übertragungsgeschwindigkeit und Stromversorgung der verschiedenen USB-Standards im Vergleich. Standard
USB 1.0
USB 2.0
USB 3.0 USB 3.1
max. Übertragungsgeschwindigkeit 12 Mbit/s 480 Mbit/s 5 Gbit/s
10 Gbit/s
max. Stromversorgung
5 A
500 mA
500 mA
900 mA
Tabelle 3.3 Übertragungsgeschwindigkeit und Stromversorgung via USB-Anschluss
Zur Inbetriebnahme eines Arduinos können Sie also ohne Bedenken die Spannungsversorgung über USB vornehmen. Erst wenn externe Lasten oder drahtlose Kommunikation hinzukommen, kann es zu einer Überlastung des USB-Ports durch zu hohe Stromaufnahme kommen. In gleicher Weise wirken sich zu lange USB-Kabel mit geringem Drahtquerschnitt aus: Am Serienwiderstand des Kabels bewirkt ein großer Strom einen Spannungsabfall, der die Betriebsspannung am USB-Port des Arduinos herabsetzt. Wenn in der Folge dann die Versorgungsspannung (durch einen Spike kurzzeitig) zusammenbricht bzw. vom USB-Port unterbrochen wird, stürzt das laufende Programm des angeschlossenen Arduinos ab oder weist ein sehr merkwürdiges Verhalten auf. Solche Fehler sind nur mit erheblichem messtechnischem Aufwand lokalisierbar. Beziehen Sie den Stromverbrauch einzelner Komponenten deshalb von vornherein in die Betrachtungen mit ein, und legen Sie die Stromversorgung eher großzügig aus. Zwei Beispiele mit Komponenten, die ich später noch verwenden werde, sollen das verdeutlichen: Mikrocontroller ESP8266, ESP32 – Stromaufnahme 50 bis 70 mA, Stromspitzen im WiFi-Mode 400 mA und mehr (sehr lesenswert dazu: https://arduino-hannover.de/2018/07/25/die-tuecken-deresp32-stromversorgung/)
GSM/GPRS Module SIM800L – Stromaufnahme (Data Mode (1 Tx, 4 Rx), GSM850) = 453.57 mA (typ. Mittelwert), Spitzenströme bis 2 A! (https://datasheet-pdf.com/PDF/SIM800L-Datasheet-SIMCom989664)
3.5.2 USB-Hub mit Schnellladeanschluss Können Sie in stromhungrigen Anwendungen auf die Kommunikation über USB verzichten, dann können Sie die Verbindung zum PC durch ein USB-Ladegerät ersetzen. Ein USB-Ladegerät liefert bei richtiger Wahl dann den benötigten Strom. Da die Kommunikation nicht nur für das Debugging wichtig ist, stellt der Vorschlag oben nur eine Möglichkeit für einige wenige Anwendungsfälle dar. Abhilfe kann die Verwendung eines speziellen USB-Hubs schaffen, der, durch ein eigenes Netzteil gespeist, einen sogenannten Schnellladeanschluss aufweist. Der D-Link DUB-H4 ist ein solcher USB-Hub mit vier Downstream-USB-Anschlüssen vom Typ A (Buchse) inklusive eines Schnellladeanschlusses, der bei Anschluss des zugehörigen Netzteils bis zu 2 A liefern und den erforderlichen Strombedarf der meisten Anwendungen decken kann, ohne dass Sie auf die Kommunikation mit dem seriellen Port verzichten müssen (https://eu.dlink.com/de/de/products/dub-h4-4-port-usb-2-hub). Abbildung 3.50 zeigt den USB-Hub mit seinem Schnellladeanschluss.
Abbildung 3.50 D-Link DUB-H4 mit Schnelladeanschluss (markiert)
3.5.3 Steckernetzteil Wollen Sie den Arduino und eine möglicherweise stromhungrige Zusatzschaltung über ein Steckernetzteil mit Spannung versorgen, dann sollten Sie die Spannung des Steckernetzteils nicht zu hoch wählen. Die Spannungsdifferenz zwischen der angelegten Spannung VIN und der Betriebsspannung von 5 V (beim Arduino Uno) wird, multipliziert mit dem aufgenommenen Strom am Längsregler, in Wärme umgesetzt. Außerdem ist der Strom beim Arduino Uno durch den Spannungsregler MC33269D-5.0 auf 800 mA begrenzt. Abbildung 3.51 zeigt in einem Schaltungsausschnitt den Längsregler beim Arduino Uno.
Abbildung 3.51 Längsregler beim Arduino Uno
Das Schaltungsprinzip ist bei allen Arduinos gleich. Die eingesetzten Bauteile sind unterschiedlich. Beim Arduino Uno WiFi Rev2 beträgt der maximale Strom durch den eingesetzten Schaltregler MPM3610 immerhin 1,2 A. Schauen Sie unter diesem Aspekt noch einmal in das Angebot von Reichelt, dann finden Sie beispielsweise ein Steckernetzteil von Meanwell mit 7,5 V DC Ausgangsspannung und einem maximalen Strom von 1,6 A (https://www.reichelt.de/steckernetzteil-12-w-7-5-v-1-6-a-stabilisiert-gs15e11p1j-p161605.html). Ist Ihnen das Konzept der Spannungsversorgung des Arduinos und der erforderlichen Zusatzschaltung klar, dann finden Sie im umfangreichen Angebot der verschiedenen Distributoren mit Sicherheit ein geeignetes Steckernetzteil zu sehr geringen Kosten.
3.5.4 Labornetzgerät Labornetzgeräte sind für die Spannungsversorgung jeglicher Elektronik geeignet. Sie stellen eine oder mehrere einstellbare Spannungen mit meist einstellbarer Strombegrenzung zur Verfügung. Das Spektrum von angebotenen Geräten ist breit gefächert, was Funktionalität und Preise angeht. Ich verweise hier beispielhaft auf zwei einfache Labornetzgeräte von Eventek und PeakTech, die unter anderem über Amazon.de bezogen werden können. Die technischen Daten beider Labornetzgeräte sind in Tabelle 3.4 zusammengestellt.
Eingangsspannung
Eventek KPS305D
PeakTech 6225 A
110/230 V AC, 50/60 Hz
110–240 V, 50/60 Hz
Ausgangsspannung 0–30 V DC
0–30 V DC
Ausgangsstrom
0–5 A
0–5 A
Restwelligkeit
≤ 0,5 % Vp-p
≤ 3 mV RMS
Lastregelung
≤ 0,01 % + 3 mV
≤ 0,01 % + 5 mV
Spannungsregelung k. A.
≤ 0,01 % + 1 mV
Anzeigegenauigkeit
0,01 V
+/–0,1 % + 2 dgt.
Schutz
Hohe Strombegrenzung und intelligenter Temperaturregler
Überlast, Übertemperatur, Kurzschluss bei Konstantstromquelle und Ausgangsüberspannung
Abmessungen (B × H × T)
70 × 130 × 230 mm
78 × 160 × 255 mm
Gewicht
1,3 kg
2,6 kg
Preis (amazon.de)
Eventek KPS305D
PeakTech 6225 A
57,99 €
82,10 €
Tabelle 3.4 Technische Daten zweier Labornetzgeräte
3.5.5 Lithium-Polymer-Akku Was den Batteriebetrieb eines Arduinos betrifft, so beschränke ich mich hier auf den Lithium-PolymerAkku (LiPo-Akku), den Sie zumindest als Spannungsquelle Ihres Mobiltelefons kennen. Der LiPo-Akku ist eine Weiterentwicklung des bekannten Lithium-Ionen-Akkus (LiIon-Akku). Der eigentliche Unterschied besteht im verwendeten Anodenmaterial. Beim Lipo-Akku besteht die Anode aus einer gelartigen Folie, die einen sehr dünnen Schichtenaufbau (weniger als 0,1 mm Dicke) und dadurch eine wesentlich höhere Flexibilität bei der Bauform ermöglicht. Ein LiPo-Akku stellt eine Spannung von 3,5 bis etwa 3,8 V bereit und weist eine sehr hohe Energiedichte auf, was kleine Baugrößen bei guter Leistung ermöglicht. Neben der Energiedichte sind für den in Tabelle 3.5 gezeigten Akkuvergleich auch noch andere Werte von Interesse. So wird angegeben, welche Spannung eine einzelne Akkuzelle abgibt. Dieser Wert ist abhängig von den verwendeten Materialien der Akkus. Die Spannung kann durch Reihenschaltung mehrerer Zellen zu einem Vielfachen der Zellenspannung erhöht werden. Die Lebensdauer wird in Tabelle 3.5 sowohl in Jahren als auch in Lade- und Entladezyklen angegeben. Der Ladewirkungsgrad gibt an, wie hoch der Anteil der Energie ist, der durch Wärmeentwicklung beim Laden und teilweise auch beim Entladen (bei Schnellentladung) verloren geht. Typ
Energiedichte (Nenn-)Zellspannung Ladewirkungs- Lebensdauer Selbstentladung Wh/kg grad und im Monat in % Ladezyklen des Akkus
Bleiakku 30–40
2,0 V
60–70 %
4–8 Jahre
300–600 Zyklen
5–10 %
NiCd Akku
40–50
1,2 V
70 %
15 Jahre
800–1500 Zyklen
10–15 %
NiMH Akku
60–80
1,2 V
70 %
7–10 Jahre
350–500 Zyklen
15–20 %
NiMH
LSD
60–80
1,2 V
70 %
7–10 Jahre
350–500 Zyklen
1–2 %
LiIon Akku
120–180
3,6 V
90 %
10–15 Jahre
500–800 Zyklen
1–2 %
Typ
Energiedichte (Nenn-)Zellspannung Ladewirkungs- Lebensdauer Selbstentladung Wh/kg grad und im Monat in % Ladezyklen des Akkus
LiPo
Akku
130–150
3,7 V
90 %
7–10 Jahre
300–500 Zyklen
1–2 %
Tabelle 3.5 Vergleich verschiedener Akkutypen (Quelle: http://www.akku-abc.de/akku-vergleich.php)
Abschließend finden Sie noch eine Angabe zur Selbstentladung des jeweiligen Akkutyps. Diese Angabe ist für die Lagerung bzw. die Zeit ohne Stromentnahme relevant. Beim Kauf eines für den Einsatz mit dem Arduino geeigneten LiPo-Akkus müssen Sie noch den verwendeten Stecker beachten. Bei den Arduinos und den verschiedenen Zubehör-Boards wird als Stecker JST-PH 2-Pin mit 2 mm Pinabstand verwendet. Im Modellbau sind es meist andere Stecker. Abbildung 3.52 zeigt einen geeigneten LiPo-Akku, der beispielsweise von EXP-Tech (https://www.exptech.de/zubehoer/batterien-akkus/lipo-akkus/) für 6,13 € angeboten wird. Das Angebot bei EXP-Tech umfasst LiPo-Akkus mit 2-mm-JST-Steckern unterschiedlicher Bauform von 100 mAh bis 4400 mAh. LiPo-Akkus reagieren bei einer Überladung oder einem Tiefentladen weitaus empfindlicher als andere Akkutypen und können dadurch sogar unbrauchbar werden. Laden Sie deshalb LiPo-Akkus immer mit einem passenden LiPo-Charger. Bei EXP-Tech finden Sie passende LiPo-Charger, wie den Battery Babysitter von SparkFun (20,39 € bei EXP-Tech).
Abbildung 3.52 LiPo-Akku (3,7 V, 2000 mAh) mit 2-mm-JST-Stecker
Der SparkFun Battery Babysitter wird vom Hersteller als »All-in-One Single-Cell Lithium Polymer (LiPo) Batteriemanager« bezeichnet. Das Board vereint LiPo-Charger (Ladegerät) und LiPo-Monitor. Abbildung 3.53 zeigt die Draufsicht auf das 33 × 33 mm große Board mit Steckern für Micro-USB 1 zur Ladung und einem JST-Stecker 2 für den Anschluss des LiPo-Akkus. An der Unterkante des Boards befinden sich die Anschlüsse für die Monitorfunktion (I2C-Bus) und die bereitgestellte Ausgangsspannung VOUT.
Abbildung 3.53 Sparkfun Battery Babysitter
Die Bausteine BQ24075 (1.5A USB-FRIENDLY Li-Ion BATTERY CHARGER AND POWER-PATH MANAGEMENT IC) und BQ27441-G1A (bq27441-G1 System-Side Impedance Track™ Fuel Gauge) bilden die technische Basis. Mit den angegebenen Begriffen finden Sie leicht die Datenblätter auf der Website des Herstellers Texas Instruments. Das Ladegerät unterstützt einstellbare Laderaten von bis zu 1,5 A sowie USB-konforme 100-mA- und 500-mA-Optionen. Der LiPo-Monitor misst die Spannung des LiPo-Akkus sowie den Lade- bzw. Entladestrom und gibt Werte zur Schätzung des Ladezustands, der verbleibenden Kapazität und des Zustands des LiPo-Akkus (Battery State-of-Health, Alterung) an. Je nach Ladezustand der Batterie bzw. angeschlossenem USB liegt die erzeugte Ausgangsspannung VOUT zwischen 3 und 5,5 V. LiPo-Akku
USB
angeschlossen ohne
VOUT VBAT–100 mV
wird geladen
angeschlossen 3,8–4,3 V
aufgeladen
angeschlossen 4,5–5 V
Tabelle 3.6 SparkFun Babysitter – Ausgangsspannung VOUT
Jede an der Ausgangsspannung VOUT angeschlossene Last sollte den in Tabelle 3.6 angegebenen Betriebsspannungsbereich verarbeiten können. Kann der variable Betriebsspannungsbereich nicht toleriert werden, dann kann ein Aufwärtsregler eine Gleichspannung von 5 V erzeugen. Mit einem MT3608-DC-DC-Step-up-Modul können Sie eine konstante Spannung von 5 V oder mehr zur Spannungsversorgung eines Arduinos erzeugen. Abbildung 3.54 zeigt ein MT3608-Step-up-Modul, das die folgenden technischen Eigenschaften aufweist: Step-up-Konverter zur Erzeugung höherer Ausgangsspannungen stufenlos einstellbar
Wirkungsgrad größer 93 % Eingangsspannung 2–24 V Ausgangsspannung 5–28 V max. Ausgangsstrom kleiner 2 A Restwelligkeit kleiner 100 mV
Abbildung 3.54 MT3608 DC-DC Step up Modul (Quelle: AZ-Delivery)
Grundlagen und Dimensionierungshinweise zu Aufwärtsreglern finden Sie unter https://www.digikey.ch/de/articles/techzone/2018/jan/generating-a-high-dc-output-voltage-from-a-lowinput-supply. Wollen Sie einen eigenen Aufbau vermeiden, dann können Sie auch eine sogenannte Powerbank einsetzen. Sicher kennen Sie diese Geräte zur Unterstützung eines schwachen Akkus beim Mobiltelefon. Mit einer Kapazität von 10.000 mAh können Sie so theoretisch eine Last von 100 mA über eine Laufzeit von 100 Stunden versorgen.
3.5.6 Spannungsversorgung mit Solarzellen Das Problem jeder batteriegestützten Spannungsversorgung ist, dass irgendwann – und zwar meist viel zu früh – der Akku leer ist. Entweder wird der Akku noch rechtzeitig gegen einen vollgeladenen getauscht oder das zu speisende Gerät stellt seinen Dienst ein. Abhilfe kann dadurch geschaffen werden, dass Sie den eingesetzten LiPo-Akku mithilfe einer Solarzelle laden (siehe Abbildung 3.55).
Abbildung 3.55 »Solar Set 2W« mit Laderegler für LiPo-Akku
Ich habe das in Abbildung 3.55 gezeigte Set für 32,50 CHF gekauft und teste mit dem ESP32-LiPoMonitor (siehe Abbildung 3.56) die Versorgung eines IoT-Knotens.
Abbildung 3.56 ESP32-LiPo-Monitor
Technische Daten zum LiPo-Charger sind im Wiki des Herstellers unter https://www.elecrow.com/wiki/index.php?title=Mini_solar_Lipo_Charger_v1.0 zu finden. Scheuen Sie sich vor dem notwendigen Hardware-Aufwand, dann ist eine solarbetriebene Powerbank sicherlich eine interessante Alternative. Es gibt allerdings einige grundsätzliche Probleme, wie ein vergleichender Test solarbetriebener Powerbanks zeigt, den Sie unter https://reisefroh.de/solarpowerbank-test-solarakku-ratgeber-vergleich/ finden. Ich kann das dort enthaltene Fazit aus eigenen Tests nur bestätigen (https://ckblog2016.net/2016/06/15/solar-ladegeraet-zur-spanungsversorgung/): »Die breite Mehrheit der solaren Powerbanks teilt sich ein großes Problem: Die Fläche ihrer Solarzelle ist einfach zu klein, um den Akku in einem sinnvollen Zeitraum wieder aufzuladen […]. Das Modell von X-DRAGON bietet als einzige Solar-Powerbank eine wirkliche Lösung für dieses Problem: eine geniale Kombination aus faltbarem Solarmodul und Powerbank, um mehr Sonnenenergie umwandeln zu können!« Die in Abbildung 3.57 gezeigte Solar-Powerbank X-Dragon hat eine ausklappbare Solarhülle mit vier Solar-Kollektoren, die mit knapp 5 W die Powerbank laden. Amazon bietet diese Solar-Powerbank für ca. 32 € an (https://www.amazon.de/Powerbank-X-DRAGON-Ladeger%C3%A4t-Wasserdichte-LEDLicht/dp/B078GCLK5D/).
Abbildung 3.57 Solar-Powerbank »X-DRAGON 10000 mAh«
3.5.7 Reduzierung des Strombedarfs für Batteriebetrieb Bei der Spannungsversorgung über eine Batterie ist die Batteriekapazität in der Regel beschränkt und der Strombedarf einer angeschlossenen Elektronik muss daran angepasst werden. Die hier
betrachteten LiPo-Akkus mit Kapazitäten bis zu 4400 mAh machen da keine Ausnahme. Sie kennen die Situation vom Smartphone, dem Fitnesstracker oder anderen batteriebetriebenen Geräten zur Genüge. Will man einen drahtlos kommunizierenden IoT-Knoten aufbauen, der beispielsweise die Daten einer autonom betriebenen Wetterstation versendet, dann hat man aber unter Umständen nicht einmal Zugang zu diesen Komponenten, und die Spannungsversorgung muss autonom oder mindestens kalkulierbar sein. Schaut man sich vorhandene Kommunikationstechnologien, wie ZigBee, Bluetooth Low Energy (BLE) und WiFi an, dann zwingen Energiebedarf, Reichweite, Datendurchsatz und Einbindung in eine vorhandene Infrastruktur zu Kompromissen. WiFi bietet bis auf den Energiebedarf immer noch eine gute Basis. Bei den einzusetzenden Mikrocontrollern sieht das heute schon wesentlich besser aus. Nahezu jeder Hersteller von Mikrocontrollern bietet eine Low-Power-Familie an, die eine gute Ausgangslage darstellt. Eine vergleichende Betrachtung mithilfe der EMBCC ULP Benchmarks habe ich unter http://www.elektroniknet.de/halbleiter/mikrocontroller/artikel/120997/ veröffentlicht. Obwohl einige der angeführten Aspekte kaum für eine WiFi-Lösung sprechen, habe ich diese dennoch einem Praxistest unterzogen.[ 6 ] Die kompakte Bauweise und die niedrigen Kosten der verfügbaren Komponenten, die praktisch überall vorhandene Infrastruktur und die einfache Integration haben mich zu diesem Ansatz geführt. Beim Einsatz von WiFi zur drahtlosen Kommunikation muss der hohe Leistungsbedarf auf die absolut erforderliche Zeit reduziert werden. Das bedeutet, dass der IoT-Knoten nach Erfassung und Übermittlung der Sensordaten in einen Schlafzustand versetzt werden muss. Gemäß der Beziehung
wird die mittlere Stromaufnahme umso geringer werden, je größer das Verhältnis von Schlafzeit tSLEEP zu Betriebszeit tOP ist. Der Betriebsstrom IOP wird weitgehend durch den WiFiTransceiver bestimmt, während die Stromaufnahme während des Schlafzustands ISLEEP durch den eingesetzten Mikrocontroller und dessen Schlafmodi definiert ist. In meinem Beitrag hatte ich mit einem ESP8266-Modul gearbeitet, und diese Bilanz sah zunächst wenig optimal aus. In einem Beitrag zum Ultra-Low-Power-Management des ESP32 liegen die ermittelten Werte nicht weit davon entfernt. Weitere Informationen dazu finden Sie unter https://www.elektronikpraxis.vogel.de/ultra-low-power-management-des-esp32-fuer-wifi-iot-modulenutzen-a-738971/. Bei der später noch zu betrachtenden Applikation nehmen Wakeup, Sensorabfrage und Versand der Daten eine Zeit von ca. 12 Sekunden in Anspruch. Die Sleep-Time kann anwendungsspezifisch gewählt werden. Tabelle 3.7 zeigt die Stromaufnahme eines ESP32 in den beiden Betriebsarten. Mode
Stromaufnahme Dauer
Operation 150 mA
12 s
Sleep
Anwendung bestimmt die Länge der Schlafphase
150 μA
Tabelle 3.7 Stromaufnahme in unterschiedlichen Betriebsarten
Betrachtet man nun das Erheben von Umweltdaten (Temperatur, relative Luftfeuchtigkeit etc.), dann reicht möglicherweise ein Abfragezyklus von 30 min (48 Calls/Tag). Will man hingegen die Daten in einem Zyklus von 5 min aktualisieren, dann resultieren daraus bereits 288 Calls/Tag. Für meinen Test habe ich zwei verschiedene Möglichkeiten der Spannungsversorgung herangezogen. Drei Energizer-Max-LR6-(AA-)Zellen mit 2000 mAh dienten als reine Batterieversorgung und ein Solarzellen-gepufferter Lithium-Polymer-Akku mit 1400 mAh als nachladbare Option. Das ergibt unter den gegebenen Bedingungen immerhin Laufzeiten von mehr als einem Monat bei 48 Calls/Tag und von mehreren Tagen bei 288 Calls/Tag (siehe Tabelle 3.8). Die für den LiPo-Akku angegebene Zeit versteht sich dabei ohne Nachladung durch die angeschlossene Solarzelle. Batterietyp
Batteriekapazität Calls/Tag
3 Energizer Max LR6 2000 mAh LiPo
1400 mAh
3 Energizer Max LR6 2000 mAh LiPo
1,15 mA 72 d 50 d
144
1400 mAh
3 Energizer Max LR6 2000 mAh LiPo
48
Laufzeit (in Tagen = d)
3,15 mA 26 d 18 d
288
1400 mAh
6,14 mA 13 d 9 d
Tabelle 3.8 Berechnung der Laufzeit in Abhängigkeit von der Call-Rate
Wenn Sie die hier angegebenen theoretischen Werte erreichen wollen, dann müssen Sie alle verdeckten Stromfresser des IoT-Knotens eliminieren. Am besten ist es, für Low-Power-Anwendungen einen nahezu unbeschalteten ESP32 zu verwenden. Ein solches ESP32-Minimalsystem kann beim Einsatz eines ESP32-WROOM-32 auf einer Trägerplatine gebildet werden. AZ-Delivery bietet die Komponenten für das in Abbildung 3.58 gezeigte ESP32Minimalsystem über Amazon.de für 9,79 € an. Bausatz Die Komponenten werden als Bausatz geliefert. Die Trägerplatine ist also unbestückt. Auf dem ESPWROOM-32 haben die Pinholes einen Abstand von 1,27 mm. Das Löten kann hier zu Herausforderung werden. Ein Feinlötkolben, ruhige Hände sowie gute Augen bzw. eine große Lupe sind unbedingt erforderlich.
Abbildung 3.58 ESP32-Minimalsystem
Einfacher ist es, das auf minimalen Stromverbrauch hin optimierte ThingPulse ESP32 DevBoard aus Abschnitt 2.2.9 einzusetzen. Seine 25 μA Stromaufnahme im Sleep-Mode sind schwer zu unterbieten. Mit etwas externem Schaltungsaufwand kann der Mikrocontroller auch ganz von der Versorgungsspannung getrennt werden. Hierzu gibt es einen Schaltungsentwurf für eine Abschaltautomatik von Rui Santos. Unter der URL https://randomnerdtutorials.com/power-savinglatching-circuit finden Sie alle erforderlichen Daten, wie Arduino-Sketch, Schaltplan und Gerber-Daten für die Leiterplatte. Achtung: Abschaltautomatik Die Abschaltautomatik schaltet den Strom vollständig ab. Es wird also kein Strom verbraucht, wenn auf dem Mikrocontroller keine Aufgabe ausgeführt wird. Im Tiefschlafmodus hingegen tritt immer ein gewisser Stromverbrauch auf. Bei den hier betrachteten Arduino-Boards kommen noch LEDs und andere Peripheriekomponenten hinzu, die die Strombilanz verschlechtern.
3.6 Messtechnik Für die Inbetriebnahme oder die Ermittlung von Kennwerten eines elektronischen Aufbaus mit einem Arduino ist ein Minimum an Messtechnik erforderlich, das ich Ihnen in diesem Abschnitt vorstellen möchte. Auch hier ist das Spektrum des Angebots groß, aber den Anfang kann man mit bescheidenen Mitteln machen.
3.6.1 Multimeter Ein Multimeter – der Name lässt es schon vermuten – ist ein Messgerät, mit dem verschiedene elektrische Kenngrößen erfasst werden können. Multimeter – wozu brauche ich das? Beim Schaltungsaufbau können Sie mit einem Multimeter die Werte von Widerständen oder Kondensatoren (Kapazität) messen, wenn die Angaben auf den betreffenden Bauelementen unklar oder nicht leserlich sind. Die Widerstandsmessung oder den Durchgangsprüfer können Sie verwenden, um eine elektrische Verbindung bezüglich ihrer Leitfähigkeit zu überprüfen. Die Unterbrechung eines Leiterzugs auf der Leiterplatte kann damit leicht gefunden werden. Die Spannungsmessung ist fast die wichtigste Funktion, da Sie damit die Versorgung der einzelnen Schaltungsteile überprüfen oder Spannungen von Sensoren bzw. Schaltungsausgängen messen können.
Über die Strommessung können Sie beispielsweise die Stromaufnahme eines Schaltungsteils testen und so Rückschlüsse auf dessen Funktion ziehen. Die Frequenzmessung zeigt Ihnen beispielsweise, ob ein Oszillator die erwartete Frequenz liefert oder ob das PWM-Signal an LED oder Motor im erwarteten Bereich liegt. Hinzu kommen Zusatzfunktionen mancher Multimeter wie Temperatur und andere, die gegebenenfalls von Interesse sind.
Ich greife aus dem umfangreichen Angebot von Multimetern das PeakTech 3690 und das LOMVUM T28B heraus. Tabelle 3.9 zeigt eine Zusammenstellung der Messgrößen für beide Multimeter. Messgröße
PeakTech 3690
LOMVUM T28B
Gleichspannung
400 mV, 40/400/600 V
600 mV, 6/60/600/1000 V
Wechselspannung 400 mV, 4/40/400/600 V
600 mV, 6/60/600/750 V
Gleichstrom
400/4000 µA, 40/400 mA, 10 A
600 μA, 60/600 mA, 20 A
Wechselstrom
400/4000 µA, 40/400 mA, 10 A
600 μA, 60/600 mA, 20 A
Widerstand
400 Ω, 4/40/400 kΩ, 4/40 MΩ
600 Ω, 6/60/600 kΩ, 6/60 MΩ
Kapazität
50/500 nF, 5/50/100 µF
6/60/600 nF, 6/60/600 μF, 6/100 mF
Messgröße
PeakTech 3690
LOMVUM T28B
Frequenz
5/50/500 Hz, 5/50/500 kHz, 10 MHz
10/100/1000 Hz, 10/100/1000 kHz, 10 MHz
Temperatur
n. a.
–50 bis 400 °C (mit TP-01)
URL
https://amzn.to/3lNmBQL https://amzn.to/3GliOnj
Tabelle 3.9 Messgrößen ausgewählter Multimeter
Die beiden hier beschriebenen Multimeter sollen Ihnen einen Eindruck vom angebotenen Spektrum vermitteln. Das Angebot ist nahezu unübersichtlich, und Sie sollten auch das mitgelieferte Zubehör mit in die Bewertung einbeziehen. Ordentliche Messleitungen und -klemmen sind ein Teil der Messung und sollten eine sichere Kontaktierung ermöglichen.
3.6.2 Funktionsgenerator Mit einem Funktionsgenerator lassen sich elektrische Signale erzeugen, die einem bestimmten Funktionsverlauf oder einer speziellen Kurvenform entsprechen. Einfache Funktionsgeneratoren stellen Sinus-, Rechteck-, Dreieck- und Sägezahnsignale mit einstellbarer Frequenz und Amplitude zur Verfügung (siehe Abbildung 3.59). Sie sind oft in analoger Schaltungstechnik ausgeführt und enthalten einen einstellbaren Dreieck-Oszillator, dessen Ausgangssignal über eine nichtlineare Schaltung in eine Sinusform umgesetzt wird. Das Rechtecksignal wird aus dem Dreieck mittels eines Komparators erzeugt, wobei durch Veränderung der Vergleichsspannung die Impulsbreite des Rechtecks eingestellt werden kann.
Besser ausgestattete Funktionsgeneratoren weisen Einstellmöglichkeiten für Symmetrie, Gleichanteil und Modulationen (Wobbelfunktionen, Frequenzverstimmung) auf. Mitunter ist ein Frequenzmesser zur genauen Einstellung integriert. Solche Funktionsgeneratoren sind in der Regel digital und arbeiten mit direkter digitaler Synthese (DDS). Die Genauigkeit ist wesentlich höher als bei Geräten mit analoger Schaltungstechnik und hängt primär von der internen Auflösung in der DDS ab.
Abbildung 3.59 Spannungsverläufe
Zur digitalen Signalsynthese gibt es heute integrierte Schaltkreise, beispielsweise den Programmable Waveform Generator AD9833 von Analog Devices. Matthias Busse hat einen AD9833 mit einem Arduino gesteuert und so einen Funktionsgenerator aufgebaut. Die detaillierte Beschreibung finden Sie unter http://shelvin.de/ad9833frequenzgenerator-mit-dem-arduino-programmiert-und-vermessen/. Funktionsgenerator – wozu brauche ich den?
Die von einem Funktionsgenerator erzeugten Signale dienen oft als Eingangssignal zum Überprüfen von elektronischen Baugruppen. Beispielsweise kann der Frequenzgang eines Filters mit einem Sinussignal unterschiedlicher Frequenz gemessen oder die Schaltschwelle eines Komparators mithilfe eines Dreiecksignals getestet werden. Rechtecksignale können Sie zum periodischen Triggern eines Counters/Timers einsetzen.
Je nach Anwendungsfall können Sie schon sehr einfache Funktionsgeneratoren sinnvoll einsetzen. Der MSG2 von ELV ist ein durch Batteriebetrieb auch mobil einsetzbarer Laborhelfer, der Sinus-, Rechteck- und Dreiecksignale im Frequenzbereich bis 50 kHz bereitstellt. Einen erweiterten Frequenzbereich bis zu 1 MHz stellt beispielsweise ein TOOGOO-XR2206-Funktionsgenerator zur Verfügung. Beide Funktionsgeneratoren sind als Bausatz erhältlich. Einen professionelleren Ansatz bietet der Funktionsgenerator JDS6600 , der als Zwei-Kanal-Signalgenerator Signale (Sinus, Rechteck, Dreieck, Puls, Halbwelle) von bis zu 60 MHz erzeugt. Zusätzlich ist ein EinKanal-Frequenzzähler integriert. Reichelt bietet diesen Funktionsgenerator für 125,30 € an. Die technischen Daten lassen sich für den Preis durchaus sehen. Sie finden ihn auf der Website von Reichelt gelistet. Wer seinen Arbeitsplatz längerfristig für komplexe Arduino-Projekte ausstatten möchte, tätigt mit dem Funktionsgenerator JDS6600 (oder einem vergleichbaren Gerät) eine dauerhafte Investition.
3.6.3 Oszilloskop Ein Oszilloskop ist neben dem Multimeter eines der wichtigsten Laborinstrumente. Auch hier gibt es ein sehr breites Angebot
unterschiedlich ausgestatteter Geräte. Oszilloskop – wozu brauche ich das? Mit einem Oszilloskop können Sie Spannungsverläufe auf einem Display im Zeitverlauf grafisch darstellen. Dabei kann es sich um einen analogen Spannungsverlauf oder um eine digitale Bitfolge handeln. Manche Geräte erlauben sogar die grafische Darstellung von Bus-Signalen.
Beim Oszilloskop handelt es sich um ein komplexeres Messgerät, weswegen auch die Einstiegspreise nicht unerheblich sind. Bei Amazon habe ich mit dem LCD Speicher-Oszilloskop OWON SDS1022 ein brauchbares Oszilloskop am unteren Ende der nach oben offenen Preisskala gefunden. Amazon bietet dieses Einsteigermodell für 190,44 € an. Die technischen Daten des Oszilloskops entnehmen Sie bitte der Produktbeschreibung auf der Amazon-Website. Ähnliche Angebote gibt es von weiteren Herstellern. Neben dem Oszilloskop in Form eines Einzelgeräts, wie des hier gezeigten SDS1022, gibt es sogenannte USB-Oszilloskope. USB-Oszilloskope bestehen in der Regel aus einer Box, die die Elektronik zur Messwerterfassung beinhaltet und über USB mit einem PC verbunden ist. Vom PC aus werden die Bedienung des Oszilloskops und die Darstellung der Messwerte vorgenommen. Die Bedienoberfläche wird meist einem klassischen Oszilloskop nachempfunden. Das erleichtert die Bedienung. Die Einstiegspreise solcher USB-Oszilloskope liegen unter denen der klassischen Oszilloskope. Im folgenden Abschnitt stelle ich Ihnen ein
solches USB-Oszilloskop vor, das aber durch seine Zusatzfunktionen bereits den Rahmen des eigentlichen Oszilloskops überschreitet.
3.6.4 BitScope Micro Das BitScope Micro ist ein voll ausgestattetes Mixed-Signal-Test- und Messsystem, ein Mixed-Signal-Oszilloskop in einer Sonde. Zur messtechnischen Unterstützung bei der Inbetriebnahme von Arduino-Projekten und bei der Fehlersuche in ihnen ist dieses kompakte Messsystem eine hervorragende Unterstützung zum kleinen Preis. Im Shop des Herstellers unter http://my.bitscope.com/store/ wird BitScope Micro zum Preis von 145 US$ angeboten. Abbildung 3.60 zeigt den Lieferumfang des BitScope Micro.
Abbildung 3.60 BitScope Micro
Das BitScope Micro wird über einen USB-Anschluss mit dem PC verbunden. Auf Ihrem PC müssen Sie zusätzlich die BitScope-Software installieren. BitScope Micro selbst ist eine schmale Leiterplatte, die durch Kunststoff elektrisch isoliert ist und so bedenkenlos auf dem Labor- oder Arbeitsplatz platziert werden kann. Hinzu kommen zahlreiche Messleitungen (Probes), die am Diagnostic Port (siehe Abbildung 3.61) angeschlossen werden.
Das BitScope Micro zeichnet sich durch die folgenden Eigenschaften aus: 20 MHz Bandbreite 40 Msps Logik-Abtastrate 2 analoge Oszilloskop-Kanäle 2 analoge Komparator-Kanäle 6 Logic/Protocol-Analyzer-Kanäle 8 und 12 Bit analoge Signalauflösung eingebauter, analoger Signal- und Clock-Generator Decodierung serieller Daten wie SPI-, I2C-, CAN-Bus-Signale Windows-, Linux- und macOS-kompatibel durch den Anwender programmierbar (C/C++, Python, VM API) geringes Gewicht (14 g) wasserdicht Standard-Oszilloskop-Tastkopf-Adapter verfügbar
Abbildung 3.61 Diagnostic Port
Die BitScope-Software setzt sich aus mehreren Anwendungen (Apps) zusammen – ich zeige Ihnen in den folgenden Abschnitten nur die
wichtigsten. BitScope DSO
BitScope DSO ist die Premium-Test- und Messsoftware für BitScope und bietet eine Reihe integrierter virtueller Testinstrumente wie digitales Oszilloskop, Mixed Signal Scope, Wellenformgenerator, Spektrumanalysator, Logic Analyzer und Datenrekorder. Abbildung 3.62 zeigt die Oberfläche des BitScope DSO. Hier habe ich den Ausgang AWG mit dem Kanal CHA des Oszilloskops kurzgeschlossen, sodass das erzeugte Rechtecksignal von 4 kHz mit dem Oszilloskop sichtbar gemacht werden kann.
Abbildung 3.62 BitScope DSO (AWG mit CHA verbunden)
Zwei-Kanal-Oszilloskop
Ein Klick auf den Button DUAL konfiguriert das BitScope Micro als ein Zwei-Kanal-Oszilloskop.
Abbildung 3.63 Abtastung von SCL und SDA mit dem Zwei-Kanal-Oszilloskop
Mit Kanal A (CHA) überwache ich hier die Leitung SCL (Clock) eines I2CBusses. Kanal B (CHB) ist mit der Leitung SDA (Data) verbunden. Im Display des Oszilloskops können Sie erkennen, dass die Übertragung von 3 Bytes über den I2C-Bus sichtbar ist (siehe Abbildung 3.63). Logic Analyzer
Ein Klick auf den Button LOGIC schaltet das BitScope Micro in den Logic Mode, wodurch der gleiche Signalverlauf stilisiert dargestellt wird. Wie Sie an der Displaydarstellung in Abbildung 3.64 erkennen, ist dieser Modus nicht auf zwei Kanäle beschränkt: Es werden alle digitalen Eingänge am Diagnostic-Port berücksichtigt.
Abbildung 3.64 Abtastung von SCL und SDA mit dem Logic Analyzer
Mixed Domain Scope
Ein Klick auf den Button SCOPE konfiguriert das BitScope Micro wieder als Oszilloskop. Aktivieren Sie nun die Option MIXED DOMAIN SCOPE, dann fungiert das BitScope Micro als leistungsstarker EchtzeitSpektrumanalysator für gemischte Domänen (Zeit und Frequenz). Abbildung 3.65 zeigt ein über Kanal A (CHA) abgetastetes Rechtecksignal (PWM-Signal) mit einer Frequenz von ungefähr 500 Hz. Dieses Signal wird mit einer Frequenz von ca. 1 MHz abgetastet, einer Spektralanalyse (Fourier-Transformation) unterzogen und im oberen Teil des Displays als Spektrum dargestellt.
Abbildung 3.65 Abtastung und Spektralanalyse eines PWM-Signals
BitScope Logic
BitScope Logic ist eine weitere wichtige Applikation für das BitScope Micro und stellt einen komfortablen Logic- und Protokoll-Analyzer zur Verfügung. Ich zeige Ihnen hier zur Demonstration noch einmal das I2C-BusBeispiel. Der Eingang L0 ist mit der Leitung SCL verbunden, der Eingang L1 hingegen mit der Leitung SDA. Abbildung 3.66 zeigt die beiden nun schon bekannten Signalverläufe. In der ersten Spalte ist allerdings der I2C-Bus für die Protokoll-Analyse (sichtbar durch das Zeichen I) ausgewählt. In der vierten Spalte ist für die Leitung SCL die Timing-Darstellung (sichtbar durch T) und für die Leitung SDA die Paket-Darstellung (sichtbar durch P) aktiviert. Das führt dazu, dass die über die Leitung SDA gesendeten Daten decodiert und angezeigt werden. Bei den gesendeten Daten handelt es sich beginnend beim Wert 0x03 um Adressdaten, die jeweils um 1 inkrementiert werden. In den Anwendungen zum I2C-Bus (Abschnitt 10.3) werde ich hierauf noch einmal zurückkommen.
Sicher ahnen Sie schon, dass der Logic Analyzer zahlreiche weitere Optionen bereithält. Um den Rahmen des Abschnitts nicht zu sprengen, verweise ich auf die Dokumentation des Herstellers unter der URL https://www.bitscope.com/software/logic/guide/.
Abbildung 3.66 Analyse des I2C-Bus mit dem Logic Analyzer »Bitscope Logic«
3.6.5 Saleae Logic Analyzer Schon sehr preiswerte Geräte bieten eingebaute Protokollanalysen an, die denen des Bitscope Logic ähneln. Unter Makern verbreitet ist der Acht-Kanal-Saleae-Logic-Analyzer, der als Clone für weniger als 20 € erhältlich ist (siehe Abbildung 3.67).
Abbildung 3.67 »Saleae Logic Analyzer«-Clone
Ich persönlich habe diesen Logic Analyzer noch nicht eingesetzt und verweise deshalb auf seine Vorstellung im Blog von Christian Marmann unter https://hartgeloetet.blogspot.com/2015/10/saleaelogic-analyzer.html.
3.7 CAD-Software In diesem Kapitel werden CAD-Produkte (Computer-Aided Design) betrachtet, die die Dokumentation von elektronischen Schaltungen bis hin zum Entwurf von Leiterplatten unterstützen und für den Maker sinnvoll sind. Ein CAD-Tool zum Entwurf von Multi-LayerLeiterplatten ist Spezialisten vorbehalten und sprengt ohnehin jegliches Budget, von dem wir hier ausgehen können.
3.7.1 Fritzing Fritzing ist eine Open-Source-Hardware-Initiative (http://fritzing.org), die Elektronik als kreatives Material für jedermann zugänglich machen soll. Fritzing wird von der Friends-of-Fritzing e. V., einer gemeinnützigen Stiftung mit Sitz in Berlin, gepflegt. Das Projekt ist aus einem staatlich geförderten Forschungsprojekt am Interaction Design Lab (http://idl.fh-potsdam.de) der FH Potsdam (http://fh-potsdam.de) hervorgegangen. Derzeit ist die Open-Collective-Seite (https://opencollective.com/fritzing) für diejenigen verfügbar, die bereit sind, die Entwicklung des Projekts zu unterstützen. Das Kernteam besteht aus Prof. Reto Wettach, André Knörig, Jonathan Cohen und Stefan Hermann. Viele fantastische Leute (http://fritzing.org/about/people/) haben im Laufe der Jahre zum Gelingen des Projektes beigetragen. Neben der Fritzing-Software werden eine Community-Website und Services im Geiste von Processing und Arduino angeboten. Ziel ist
es, ein kreatives Ökosystem zu fördern, in dem Benutzer ihre Prototypen entwickeln, mit anderen teilen sowie (weitgehend) professionelle Leiterplatten entwerfen und herstellen können. Nachdem das Fritzing-Projekt in den Jahren 2017 und 2018 trotz mehr als 200.000 monatlicher Nutzer stillstand, ist die Weiterentwicklung von Fritzing seit Anfang 2019 in neue Hände gelegt worden. Mittlerweile wurde die Version 0.9.10 fertiggestellt. Sie können Fritzing von der URL https://fritzing.org/download/ herunterladen. Fritzing präsentiert sich in drei verschiedenen Ansichten. Abbildung 3.68 zeigt die sogenannte Steckplatinen-Ansicht. Gerade bei Anfängern ist diese intuitive Ansicht sehr beliebt, denn mit ihr kann recht einfach ein Breadboard-Aufbau dokumentiert werden. Hier ist eine Beschaltung des Arduino Uno Rev3 zu sehen, die aus einem Sensor DHT12 und einem 0,96''-OLED-Display sowie einer RGB-LED und zwei Tastern besteht. Ziel ist es, aus dieser Schaltung mithilfe von Fritzing ein Test-Shield herzustellen.
Abbildung 3.68 Fritzing – Steckplatinen-Ansicht
Nach Eingabe die verwendeten Bauteile und deren Verbindung ist das Gesamtsystem erstellt, und Fritzing generiert daraus automatischen einen Schaltplan. Der Schaltplan mag korrekt sein – will man ihn aber in die gewohnte Form bringen, dann müssen die Bauelemente in dieser Ansicht entsprechend verschoben und die Drahtverbindungen angepasst werden. Elektrisch ändert sich bei korrekter Vorgehensweise natürlich nichts. Diesen kosmetischen Schritt will ich aber nicht gehen. Stattdessen möchte ich mich lieber um den Leiterplattenentwurf kümmern. Da ein Arduino-Shield entstehen soll, wird alles auf einem Board mit Arduino-Uno-Format aufgebaut. Abbildung 3.69 zeigt die Leiterplatte mit den platzierten Bauteilen. Das OLED-Display wird über Pfostenstecker aufgesteckt. Ist die Platzierung der Bauteile vorgenommen, kann das Verbinden der Anschlüsse (Routing) erfolgen. Fritzing hat hierzu einen Auto-Router, den man verwenden kann. Naturgemäß liefert ein solcher Auto-Router keine optimale
Gestaltung, und man kann von Hand nacharbeiten. Die unterschiedlichen Farben der Leiterbahnen zeigen, ob diese auf der Ober- oder Unterseite verlegt wurden. Die Verbindung zwischen einem Leiterzug auf der Ober- und Unterseite übernehmen sogenannte Vias (Durchkontaktierungen). Über das Menü Routing • Entwurfsregelprüfung (DRC) überprüfen Sie die Einhaltung von diversen Entwurfsregeln (z. B. Leiterbahnabständen). Sie bekommen Hinweise zu Entwurfsproblemen, die Sie noch manuell durch Anpassungen beheben können.
Abbildung 3.69 Fritzing – Leiterplattenansicht
Sind Sie mit Ihrem Entwurf fertig, dann klicken Sie auf den Button Herstellen, und die Daten werden an die Fritzing FAB geschickt. Hinter der Fritzing FAB verbirgt sich die Firma Aisler B. V. aus den Niederlanden mit einem deutschen Betrieb in Aachen, der mein Test-Shield in dreifacher Ausführung innerhalb Wochenfrist für weniger als 25 € hergestellt und mir zugeschickt hat (siehe
Abbildung 3.70). Ein kleiner Betrag von 1,68 € wird als Spende an Fritzing abgeführt.
Abbildung 3.70 Auszug aus der Rechnung von »Aisler B.V.«
3.7.2 KiCAD KiCad ist eine Open-Source-Software-Suite für Electronic Design Automation (EDA). Die Programme der Software-Suite dienen der Erstellung von Schaltplänen und zum Layout von Leiterplatten. Durch die Ausgabe von Gerber-Daten kann die erstellte Leiterplatte auch gleich bei einem entsprechenden Fertiger bestellt werden. KiCAD läuft unter Windows, Linux und macOS und ist unter der GNU GPL v3 lizenziert. Die erste Version von KiCAD erschien 1992, und KiCAD wird derzeit von einer Gruppe von freiwilligen Entwicklern und Wissenschaftlern des CERN (Europäisches Kernforschungszentrum in Genf) entwickelt. Wer sonst noch das KiCAD-Projekt unterstützt, können Sie unter https://www.kicad.org/about/kicad/ nachlesen. Die Arduino Company gehört auch dazu. KiCAD liegt heute in der Version 6.0.5 vor und deckt alles ab, was Sie für Arduino-Projekte benötigen. KiCAD kann von der URL https://www.kicad.org/download/ heruntergeladen werden. Auf die Details zur Arbeit mit KiCAD möchte ich hier nicht eingehen. Hierzu gibt es zahlreiche, auch deutschsprachige Tutorials im Netz und ein aktuelles Buch mit dem
Titel »KiCad wie ein Profi: Ein praktischer Leitfaden zum Erlernen des weltweit beliebtesten Open-Source-Tools für PCB-Design«.
3.7.3 EAGLE EAGLE von Autodesk ist ebenfalls eine Software für die Entwurfsautomatisierung elektronischer Systeme (Electronic Design Automation, EDA). Elektroniker können mit dieser Software Stromlaufpläne (Schematics) erfassen, Komponenten auf Leiterplatten platzieren, Leiterbahnen routen und umfassende Bibliotheksinhalte nahtlos miteinander verbinden. EAGLE Free ist eine Design-Software, die Autodesk mit limitiertem Funktionsumfang gratis für Maker zur Verfügung stellt (https://www.autodesk.de/products/eagle/overview). Es ermöglicht zweiseitige Stromlaufpläne, ein- oder zweiseitige Leiterplatten-Layouts für eine Leiterplattenfläche von maximal 80 cm2. Die Entwurfsdaten werden wieder als Gerber-Daten für die Fertigung bereitgestellt. Einige hier im Buch gezeigte Stromlaufpläne wurden mit EAGLE Free erfasst.
3.7.4 EasyEDA Standard EasyEDA ist ein einfacheres und leistungsfähiges Online-Tool für das PCB-(Printed Circuit Board-)Design, mit dem Elektronikingenieure, Pädagogen, Studenten, Hersteller und Maker ihre Projekte entwerfen und teilen können. Hierbei handelt es sich um ein Design-Tool, das den Komponentenkatalog der chinesischen
Firma LCSC und den PCB-Service der ebenfalls chinesischen Firma JLCPCB integriert. LCSC wurde 2011 in Shenzhen, am Rande von Hongkong, gegründet. Es hat sich zu einem der größten Distributoren für elektronische Komponenten in China entwickelt. Im März 2017 übernahm LCSC EasyEDA. JLCPCB (JiaLiChuang (HongKong) Co., Limited) ist das größte Unternehmen für Leiterplatten-Prototypen in China und ein Hightech-Hersteller, der sich auf die rasche Herstellung von Leiterplatten-Prototypen und Kleinserien-Leiterplatten spezialisiert hat. Benutzer können durch die Verwendung von EasyEDA und die Kombination mit LCSC und JLCPCB Zeit und Beschaffungsaufwand reduzieren, wenn sie ihre Ideen in echte Produkte umsetzen (https://easyeda.com/page/about). Auch für EasyEDA gibt es wieder zahlreiche Tutorials und Videos im Netz. Ein deutschsprachiges Tutorial finden Sie beispielsweise unter https://www.heise.de/make/artikel/EasyEDA-Online-Designtool-fuerSchaltplaene-Simulation-und-Leiterplatten-3566216.html. Im Arduino-Praxis-Blog wurde unter dem Titel »Review – Leiterplatten (PCB) von JLCPCB« die gesamte Strecke vom Entwurf bis zur Lieferung der Leiterplatten getestet und beschrieben (http://arduino-praxis.ch/2018/07/26/review-leiterplatten-pcb-vonjlcpcb/). Aus dem Fazit des Beitrags möchte ich wie folgt zitieren: »Der chinesische Leiterplattenhersteller JLCPCB liefert Leiterplatten von hoher Qualität und zu einem sehr günstigen Preis.« Die Lieferzeit beträgt nur wenige Tage, sodass dieser Lieferant auch eine Alternative darstellt.
3.7.5 Welches Tool soll ich verwenden? Ich habe Ihnen in diesem Kapitel vier verschiedene CAD-Tools zum Erstellen von Schaltplänen und zum Entwurf von Leiterplatten vorgestellt. Welches Tool Sie zukünftig verwenden sollten, kann ich nicht eindeutig beantworten. Fritzing zeichnet sich durch die Möglichkeit aus, einen BreadboardAufbau zu dokumentieren, wie er in der Prototypen-Phase häufig zum Einsatz kommt. Dieser Breadboard-Aufbau lässt sich dann in einen Leiterplattenentwurf überführen. Der im Zwischenschritt erzeugte Schaltplan muss in der Regel manuell nachbearbeitet werden, sonst ist er nicht brauchbar. Die anderen drei Tools – KiCAD, Eagle und EasyEDA – starten mit der Eingabe des Schaltbilds. Durch die spätere Platzierung der Komponenten auf der zu erzeugenden Leiterplatte und das anschließende Verbinden der Anschlüsse gemäß Schaltbild (Routing) entsteht die Leiterplatte. In allen Fällen stehen Autorouter zur Verfügung, mit denen das manuelle Routen ersetzt werden kann. Allerdings sind die vom Autorouter erzeugten Ergebnisse nicht immer über jeden Zweifel erhaben. Erfahrenere Layouter verzichten oft von vornherein auf den Autorouter. Allen vorgestellten CAD-Tools gemeinsam ist, dass die Ergebnisse des Layout-Prozesses zur Weiterbearbeitung zur Verfügung gestellt werden. Die so gewonnenen Layoutdaten umfassen alle Daten zur Herstellung der Leiterplatte – einschließlich einer Stückliste der benötigten Bauelemente (BOM, Bill of Materials). Den Leiterplattenlieferanten werden die für die Herstellung der Leiterplatte erforderlichen Daten in Form von Gerber-Daten bereitgestellt.
Ich verwende in diesem Buch zur Dokumentation der BreadboardAufbauten wegen der einfachen Darstellung Fritzing. Für komplexere Schaltpläne oder da, wo es (noch) keine FritzingKomponente gibt, nutze ich Eagle.
4 Arduino-Software Sie haben sich tapfer durch die Grundlagen gearbeitet oder diese quergelesen, weil Sie sich in diesem Umfeld bereits fit fühlen. Nun komme ich zu einem sehr wichtigen Kapitel: der Arduino-Software. Ich stelle Ihnen die Arduino-Entwicklungsumgebung auf dem PC und in der Cloud vor. Welche der Umgebungen Sie schlussendlich verwenden, ist eine Geschmacksfrage. Mit der Arduino-Entwicklungsumgebung erstellen Sie den Quelltext des betreffenden Arduino-Anwendungsprogramms in einem vereinfachten C++.
4.1 Schritte bei der Programmerstellung Die Arduino-Entwicklungsumgebung (Arduino IDE, Integrated Development Environment) ist eine Sammlung von Programmen (auch als Programm-Suite bezeichnet), mit der Sie den Quelltext eines Arduino-Anwendungsprogramms erstellen, diesen in einen vom betreffenden Arduino ausführbaren Code kompilieren und den Code in den Programmspeicher (Flash-Memory) des verwendeten Mikrocontrollers hochladen. Der gesamte Prozess ist in Tabelle 4.1 dargestellt. Die Arduino IDE nimmt Ihnen die erforderlichen Zwischenschritte ab, sodass Sie sich
eigentlich nur mit dem ersten Schritt (Edit) und den letzten beiden (Upload und Run) befassen müssen. Edit • Compile • Link • Run Edit
Erzeugen oder Editieren von Quelltext in einem Texteditor
Preprocess Ersetzen von Makros, Processing der Header Files und Entfernen der Kommentare Compile
Syntaxcheck des Quelltextes und Übersetzung des Quelltextes in Objectcode (Binärcode).
Link
Verbindung des Objectcodes und von Librarys zu ausführbarem Binärcode.
Upload
Übertragung des ausführbaren Programms (Binärcode) auf den Zielprozessor (Target)
Run
Ausführung des Programms auf dem Zielprozessor (Target), um die Funktionalität zu prüfen
Tabelle 4.1 Schritte bei der Entwicklung eines Arduino-Programms
Damit Sie auf Ihrem PC mit der Arduino IDE arbeiten können, müssen Sie diese zuerst herunterladen und auf Ihrem PC installieren.
4.2 Die Arduino-Entwicklungsumgebung Die jeweils aktuelle Version der Arduino IDE laden Sie von der Website https://www.arduino.cc/en/Main/Software herunter. Dort finden Sie zwei unterschiedliche Versionen: Die neue Arduino IDE mit der Versionsnummer 2 und die alte, bewährte Variante mit der Versionsnummer 1.8. Grundsätzlich können Sie gut mit beiden Versionen arbeiten, und ich gehe im Folgenden kurz auf beide Programme ein. Beachten Sie bei der Wahl, dass die neue Version zwar interessante Features mitbringt, viele Programmbeispiele und Libraries aber mit der alten Version getestet wurden. Es ist also davon auszugehen, dass beide Versionen noch einige Zeit nebeneinander exisitieren werden und es dauern wird, bis die alte Version vollständig verschwindet. Meine Empfehlung lautet: Probieren Sie die neue Version ruhig aus und nutzen Sie sie für Ihre Projekte. Falls irgendetwas nicht korrekt funktioniert oder etwas nicht unterstützt wird, können Sie wieder zur alten IDE wechseln. Für dieses Buch habe ich die meisten Beispiele mit der Arduino IDE 1.8.2 getestet, und auch die Abbildungen stammen größtenteils aus der älteren Version. Wenn Sie den Anleitungen folgen möchten, greifen Sie am besten auf das stabile Fundament der Legacy IDE zurück.
4.2.1 Legacy IDE: Arduino 1.8 Die jetzt als Legacy Arduino bezeichnete Arduino IDE lag im September 2022 in Version 1.8.19 für Windows, macOS und Linux
zur Verfügung. Klicken Sie die gewünschte Version Ihres Betriebssystems an. Verwenden Sie für Windows den Installer oder das ZIP-File. Nun erscheint ein Fenster, das Ihnen die Möglichkeit eröffnet, das Arduino-Projekt finanziell zu unterstützen, bevor die Arduino IDE auf den PC heruntergeladen wird. Wählen Sie beispielsweise den Windows Installer, dann erfolgt der Download einer EXE-Datei, die nach einem Doppelklick die Arduino IDE endgültig auf dem PC installiert. Wenn Sie die Arduino IDE nun starten, öffnet sich das Fenster aus Abbildung 4.1.
Abbildung 4.1 Arduino IDE v1.8.19
In der Titelzeile sind der Name des zu editierenden Programms und die Version der Arduino IDE (hier Arduino 1.8.19) angegeben. Der Name des Programms lautet (erst einmal automatisch vorgegeben)
sketch_jan26a. Hierzu müssen Sie wissen, dass die ArduinoQuelltexte als Sketches (dt. Skizze) bezeichnet werden. Mir gefällt die Bezeichnung nicht, denn »Skizze« vermittelt immer einen unfertigen Eindruck. Sie wollen aber sicher keine Programme schreiben, die einen solchen Eindruck erwecken. Obwohl sich Software von vielen anderen Produkten dadurch unterscheidet, dass sie niemals fertig ist, sollten ausgelieferte Versionen keinen unfertigen Eindruck mehr vermitteln. Neue Versionen werden neben Bugfixes (Behebung von Fehlern) neue oder veränderte Funktionen aufweisen. In der Mitte des Fensters ist der Quelltext angeordnet, der hier allerdings noch aus zwei leeren Funktionsaufrufen besteht. Das Zeichen § hinter dem (vorläufigen) Dateinamen besagt, dass der betreffende Quelltext noch nicht abgespeichert ist. Nach dem Abspeichern (Save) verschwindet es. Für ein verkürztes Arbeiten stehen die Symbole aus Abbildung 4.2 unterhalb der Menüleiste zur Verfügung.
Abbildung 4.2 Die Menüleiste
In der Reihenfolge von links nach rechts bedeuten diese Symbole Verify, Upload, New, Open, Save und Serial Monitor. Verify – Kompilieren des Quelltextes, Syntaxcheck Upload – Upload des Binarys nach fehlerfreier Kompilation New – Erstellen eines neuen Quelltextes (Sketchs) Open – Öffnen eines bestehenden Quelltextes
Save – Speichern eines Quelltextes Serial Monitor – Öffnen des seriellen Monitors (Serial Monitor oder Terminal) Für anspruchsvolleres Arbeiten in der Arduino IDE stehen mehrere Menüs zur Verfügung. Abbildung 4.3 zeigt das Menü File, über das Sie Quelltextdateien öffnen und speichern können. Die Option Open Recent ermöglicht das Öffnen einer kürzlich bearbeiteten Datei und vermeidet dadurch aufwendigeres Suchen. Über Sketchbook erfolgt der direkte Zugriff auf die im SketchbookVerzeichnis abgelegten Quelltexte, während über Examples der Zugriff auf Programmbeispiele der verschiedenen Librarys möglich ist.
Abbildung 4.3 Das Menü »File«
Page Setup und Print richten die Ausgabe über einen Drucker ein, die ich praktisch nicht verwende. Preferences hingegen sind eine wichtige Option, da hier die Grundeinstellungen vorgenommen werden, die Sie in Abbildung 4.4 sehen.
Abbildung 4.4 Preferences
Das Sketchbook-Verzeichnis kann an einem beliebigen Ort auf der Festplatte oder im Netzwerk eingerichtet werden. Bei meiner Installation ist das E:\Arduino. Hier werden automatisch alle erzeugten Arduino-Quelltexte als Datei .ino in einem gleichlautenden Verzeichnis abgelegt. Im Verzeichnis können weitere Dateien abgespeichert sein. Die Arduino IDE ist mittlerweile in über 30 verschiedene Sprachen übersetzt worden. Standardmäßig wird die IDE in der von Ihrem Betriebssystem ausgewählten Sprache geladen. Ich habe hier als Editor-Sprache English gewählt, da das beim Austausch von Informationen (oder Screenshots) in der Community hilfreich ist. Wählen Sie die Option Check for updates on startup aus, dann werden Sie auf Updates der Arduino IDE oder verwendeter Librarys hingewiesen. Die Option Save when verifying or upload stellt sicher, dass die aktuelle Programmversion stets auch abgespeichert ist. Sollte Ihnen der Arduino-Editor nicht gefallen, dann können Sie auch mit einem externen Editor Ihrer Wahl arbeiten. Hierzu muss ein Haken bei der Option Use external editor gesetzt werden. Da jetzt
der Arduino-Editor abgeschaltet ist, wird der Hintergrund des Quelltextes abgedunkelt. Bei jedem Verify oder Upload wird der mit dem externen Editor bearbeitete Quelltext eingelesen. Die Quelltextdateien müssen Sie aber im externen Editor selbst öffnen und speichern. Die Arduino IDE dient dann im Wesentlichen als komfortabler Uploader. Ich benutze diese Option praktisch nie. Auf die Angaben im Feld Additional Boards Manager URLs komme ich später noch zurück. Das Verhalten des Arduino-Editors steuern Sie über das Menü Edit (siehe Abbildung 4.5).
Abbildung 4.5 Das Menü »Edit«
Die Kommandos sind weitgehend selbst erläuternd und alle zusätzlich mit Tastenkombinationen zum schnelleren Arbeiten im Editor versehen. Copy for Forum bettet den Quelltext in die passenden Tags [code] und [/code] ein, während Copy as HTML
richtigen HTML-Code ausgibt. Für Dokumentationszwecke sind diese Kommandos sicher interessant, wichtig sind sie nicht. Im Menü Sketch (siehe Abbildung 4.6) finden sich die schon beschriebenen Optionen Verify/Compile und Upload.
Abbildung 4.6 Das Menü »Sketch«
Durch die Option Upload Using Programmer wird der Bootloader auf dem Board überschrieben und der Upload erfolgt über einen externen Programmer, beispielsweise einen AVR-ISP-Programmer. Dieses Vorgehen nutzt den kompletten Programmspeicher, brennt aber keine Fuses[ 7 ]. Wollen Sie die Binärdatei (*.hex) archivieren oder weitergeben, dann können Sie das über die Option Export compiled Binary tun. Über die Option Include Library kann dem Quelltext eine Library hinzugefügt werden. Hierzu wird die betreffende Library am Anfang des Quelltextes über #include eingefügt. Weitere Details zu Librarys folgen in Abschnitt 4.6.4. Der Quelltext eines Arduino-Anwenderprogramms kann aus mehreren Dateien bestehen. Mithilfe der Option Add File… werden weitere Dateien in das betreffende Verzeichnis aufgenommen und als Reiter (Tab) auch angezeigt. Über das kleine Dreieck unter dem seriellen Monitor auf der rechten Seite der Symbolleiste kann die Handhabung weiterer Dateien gleichermaßen erfolgen.
Über das Menü Tools (siehe Abbildung 4.7) können Sie verschiedene Einstellungen für das Management der Librarys und den Upload vornehmen.
Abbildung 4.7 Das Menü »Tools«
Mithilfe der Option Auto Format kann der Quelltext optisch ansprechender dargestellt werden. Um Ihre Quelltexte in einer ZIP-Datei zu archivieren, nutzen Sie die Option Archive Sketch. Mit Fix Encoding & Reload können Sie mögliche Diskrepanzen zwischen der Char-Map-Codierung des Editors und den Char-Maps anderer Betriebssysteme auflösen. Der serielle Monitor (Serial Monitor) ist ein Terminalprogramm, mit dem Sie die Ein-/Ausgaben über den seriellen Port ansehen können. Die Option Serial Monitor öffnet ein Terminalfenster zur Anzeige des Datentransfers über den ausgewählten COM-Port. Der serielle Monitor ist wichtig für das Debugging sowie für serielle
Ein-/Ausgaben des Arduino-Anwenderprogramms und wird bei unseren Anwendungen noch häufig eingesetzt werden. Über die Option Serial Plotter wird ebenfalls eine serielle Verbindung geöffnet, allerdings erfolgt die Anzeige von ausgegebenen numerischen Werten in grafischer Form. Mit der Option Board: wählen Sie das angeschlossene ArduinoBoard aus. Unter den Arduino AVR Boards ist hier der Arduino Duemilanove, ein Vorgänger des Arduino Uno, zu finden, den ich ausgewählt habe. Sollte das gewünschte Board nicht in der Auswahlliste aufgeführt sein, dann kann es über den Boards Manager installiert werden. Die Option Port: dient zur Auswahl der seriellen Schnittstelle (COMPort), über die das Arduino-Board mit dem PC verbunden wurde. Im Windows-Geräte-Manager sind die geöffneten seriellen Ports zu sehen (siehe Abbildung 4.8).
Abbildung 4.8 Serielle Ports im Windows-Geräte-Manager
Das Arduino-Duemilanove-Board ist über COM21 mit dem PC verbunden, was über die Option Port: auch auszuwählen ist. Wenn die serielle USB-Verbindung nicht zum Programmieren über den internen Bootloader eingesetzt werden soll, dann können Sie über die Option Programmer: ein Hardware-Programmiergerät auswählen. Normalerweise wird dies nicht benötigt, aber wenn Sie einen Bootloader auf einen neuen Mikrocontroller brennen, verwenden Sie diese Option. Die Option Burn Bootloader dient zur Programmierung eines neuen Bootloaders. Nach der Programmierung des Bootloaders können Anwendungsprogramme wieder über die serielle USB-Verbindung auf den Arduino hochgeladen werden. Außerdem sind dadurch auch die Fuses korrekt gebrannt worden.
Über das Menü Help finden Sie Antworten zu Fragen, die während der Arbeit mit der Arduino IDE sicher auch bei Ihnen auftreten werden. Die Option Getting Started führt Sie auf die auf Ihrem PC abgespeicherte (englischsprachige) Website mit dem Titel »Getting Started with Arduino on Windows«, die Ihnen den Anschluss des Arduinos an den PC und das Hochladen des ersten ArduinoProgramms erläutert. Genauso erfolgt über die Optionen Environment, Troubleshooting und Reference ein Aufruf von erläuternden Seiten zur jeweiligen Thematik. Wichtig in der praktischen Arbeit dürfte für Sie die Option Reference sein, denn da bekommen Sie Hilfe zu den Sprachbestandteilen der hier eingesetzten Programmiersprache. Über die Option Find in Reference können Sie eine Instruktion im Quelltext in der Hilfe suchen. Positionieren Sie den Cursor auf die betreffende Instruktion im Quelltext, und drücken Sie (Ctrl)+(ª)+ (F). Schon erhalten Sie die zugehörige Information. Die restlichen Optionen sind selbsterklärend und werden hier nicht weiter vertieft. Mit diesen Erläuterungen haben Sie die Installation und die Arbeit mit der Arduino IDE auf dem PC unter Windows kennengelernt. Auch unter macOS oder Linux gibt es keine größeren Abweichungen zu den Erläuterungen hier.
4.2.2 Die neue Arduino IDE 2 Die Arduino Foundation hat im September 2022 eine neue Hauptversion (Major Release) der Arduino IDE veröffentlicht. Ich konnte die Arduino IDE 2.0 bereits auf Basis einer Reihe von Release Candidate-(RC-)Builds testen und verwende seitdem das
neue Major Release. Sie können diese Version von der ArduinoWebsite herunterladen. Die Arduino IDE 2.0 ist schneller und leistungsfähiger. Zusätzlich zu einem moderneren Editor und einer reaktionsschnelleren Oberfläche bietet sie Autovervollständigung, Code-Navigation und sogar einen Live-Debugger. Wie Ihnen die folgenden Screenshots zeigen werden, hat sich nicht nur das Aussehen, sondern auch die Funktionalität verändert. Die Arduino IDE 2.0 wurde komplett neu geschrieben und hat keinen gemeinsamen Code mit der Arduino Legacy IDE 1.x. Sie basiert auf dem Theia IDE Framework (https://theia-ide.org/) und wurde mit Electron (https://www.electronjs.org/) erstellt. Wollen Sie tiefer einsteigen, dann empfehle ich Ihnen die »Theia Adopter Story: The new Arduino IDE 2.0« (https://blogs.eclipse.org/post/johnkellerman/theia-adopter-story-new-arduino-ide-20). Die Backend-Operationen wie das Kompilieren und Hochladen des Codes wurden in eine Arduino-CLI-Instanz ausgelagert, die im Daemon-Modus läuft. Das Arduino CLI (Command Line Interface) ist eine in Golang geschriebene Open-Source-CLI-Anwendung, die von einem Terminal aus verwendet werden kann, um Arduino-Programme zu kompilieren, zu verifizieren und auf Arduino-Boards hochzuladen. Über das CLI ist die Integration in übergeordnete Softwaresysteme einfach möglich. Der Editor ist ein solches System. Wollen Sie sich eingehend mit dem Konzept befassen, dann finden Sie unter https://arduino.github.io/arduino-cli/0.19/integration-options/ weiterführende Informationen. Diese neue Arduino IDE wurde mit dem Ziel entwickelt, die gleiche Schnittstelle und Benutzererfahrung der vorherigen Hauptversion
beizubehalten, um ein reibungsloses Upgrade zu ermöglichen. Für ein Beispiel habe ich in der Arduino IDE 2.0 RC8 einen Arduino Nano Every angeschlossen und konnte die Kombination Board/Port über die obere Menüleiste oder manuell, wie in Abbildung 4.9 gezeigt, auswählen.
Abbildung 4.9 Selektion von Board und Port
Der zu bearbeitende Quelltext zeigt sich im Editor gemäß Abbildung 4.10. Wollen Sie vom Autocomplete-Feature des Editors Gebrauch machen, dann setzen Sie in den Preferences bei Editor Quick Suggestions den Haken und bestätigen Sie mit OK.
Abbildung 4.10 Quelltext im Editor
Die Ausgaben während Kompilation und Upload erscheinen unterhalb des Quelltextes. Im gleichen Bereich erscheinen dann auch die Ausgaben des Seriellen Monitors (oder der Console), wie Abbildung 4.11 zeigt.
Abbildung 4.11 Ausgaben des Seriellen Monitors
Ich habe hier in den Preferences das Erscheinungsbild des Editors (Theme) in Dark (Arduino) verändert, werde aber die weiteren Screenshots wieder in Light (Arduino) erstellen. Welche Darstellungsform Sie bevorzugen, liegt aber ganz bei Ihnen. Besonders interessant ist der linke Menübalken, über den der Zugang zu den Quelltexten der Projekte (Sketchbook), zu den Boards (Boards Manager) und den Bibliotheken (Library Manager) organisiert ist. Abbildung 4.12 zeigt die Dateien im Sketchbook. Das hier betrachtete Programmbeispiel ArduinoNano_Every_HW.ino ist im Sketchbook markiert.
Abbildung 4.12 Quelltexte im Sketchbook
Neu ist der interne Debugger, der für den Arduino Zero und MKR Zero ohne zusätzliche Hardware auskommt. Die beiden Boards verfügen über einen eingebauten Debugger (Atmel-EDBG), der direkt mit der Arduino IDE 2.0 verwendet werden kann. Kompatibel ist der Debugger mit allen SAMD-Boards, allerdings bedarf es zusätzlicher Hardware.
Details zum Debugging in der Arduino IDE 2.0 finden Sie unter https://docs.arduino.cc/tutorials/zero/debugging-with-zero und https://docs.arduino.cc/tutorials/mkr-wifi-1010/mkr-jlink-setup sowie in Abschnitt 4.8.5. Ein Ausprobieren der Arduino IDE 2.0 lohnt sich auf jeden Fall – zumal es kaum einer Einarbeitung bedarf.
4.3 Die Arduino-Create-Plattform Arduino Create ist im Gegensatz zu der in Abschnitt 4.2 beschriebenen PC-basierten Arduino IDE eine cloudbasierte OnlinePlattform. Sie ermöglicht es Makern und professionellen Entwicklern, für zahlreiche Arduino-Boards Code zu schreiben, diesen zu konfigurieren, die erstellten Programme zu testen, Quelltexte zu speichern und darauf zuzugreifen sowie Projekte mit der Arduino-Community zu teilen. Bislang gab es für IoT-Entwicklungen keinen durchgängigen Entwicklungspfad. Meist musste zwischen verschiedenen Tools und von IDEs zu den Cloud-Services hin- und hergewechselt werden. Arduino Create ist ein Ansatz, die Entwicklung in die Cloud zu verlagern und damit die Art und Weise der Projekterstellung zu verändern sowie das Teilen der Ergebnisse zu vereinfachen. Arduino-Hard- und -Software ist Open Source. Mit dieser Art der Projekterstellung und Verbreitung in der Community wird der Open-Source-Aspekt im Sinne von Open Innovation im ArduinoUniversum weiter gefördert. Damit Arduino Create als Plattform gelten kann, müssen zwangsläufig verschiedene Komponenten zur Projekterstellung bereitgehalten werden. In welcher Weise diese bereitgestellt werden, erfahren Sie im folgenden Abschnitt. Nach Aufruf der URL https://create.arduino.cc öffnet sich die Plattform Arduino Create und präsentiert ihre zur Verfügung stehenden Bestandteile. Abbildung 4.13 zeigt hiervon einen Ausschnitt. Die angezeigten Komponenten werden im Folgenden näher betrachtet.
Abbildung 4.13 Bestandteile der »Arduino Create«-Plattform
Arduino-Account erforderlich Zur Arbeit mit der Arduino-Create-Plattform ist ein ArduinoAccount erforderlich, den Sie unter https://id.arduino.cc/ einrichten können.
Sie können unter den in Abbildung 4.14 gezeigten Plänen wählen.
Abbildung 4.14 Arduino IoT Cloud – wählbare Pläne
4.3.1 Arduino Web Editor
Die wichtigste Komponente der gesamten Arduino-CreatePlattform ist der Arduino Web Editor, der als Online-Kompagnon der klassischen Arduino IDE betrachtet werden kann. Automatisches Software-Update Durch die Verwendung des Arduino Web Editors ist gesichert, dass Sie stets mit der aktuellen Arduino-Softwareversion und aktualisierten Librarys arbeiten, ohne dass Sie sich speziell um ein Update kümmern müssen.
Nach der (automatischen) Installation eines Arduino-Web-EditorPlugins (Arduino Create Plugin) kann von einem Webbrowser aus Code geschrieben und in die Cloud hochgeladen werden. Dies ermöglicht, Anwendungsprogramme in der Cloud zu speichern und sie auf jedem Gerät verfügbar sowie gesichert zu haben. Bedingung ist natürlich eine zuverlässige Internetverbindung. Als Webbrowser können Chrome, Firefox, Safari oder Edge verwendet werden. Der Arduino Web Editor wird von Windows, Linux, macOS und Chrome OS unterstützt. Die Oberfläche ist intuitiv bedienbar, sodass die Lernkurve kurz ausfallen wird. In jedem Fall müssen Sie das oben erwähnte Arduino Create Plugin installieren, das folgende Aufgaben übernimmt: Upload von Arduino-Programmen vom Browser über ein USBKabel oder das Netzwerk auf das betreffende Board Ermöglicht die Verwendung anderer Arduino-Cloud-Dienste Nach erfolgreicher Installation des Arduino Create Plugins erscheint das Arduino-Symbol in der Taskleiste der Windows-Oberfläche
(siehe Abbildung 4.15).
Abbildung 4.15 Das »Arduino Create Plugin« wurde installiert.
Sollte das Plugin nicht mehr in der Taskleiste zu sehen sein, dann kann es jederzeit neu aufgerufen werden. Sie müssen es dann allerdings unter der Bezeichnung Arduino Create Agent suchen. Nun können Sie mit dem installierten Arduino Create Plugin vergleichbar zur klassischen Arduino IDE arbeiten (siehe Abbildung 4.16). Der Unterschied ist, dass beim Plugin die Ablage der Programme und die Kompilierung in der Cloud erfolgen.
Abbildung 4.16 Arduino Create Web Editor
4.3.2 Arduino IoT Cloud
Über die Arduino IoT Cloud (siehe Abbildung 4.13) können Sie Geräte mit dem Internet und anderen Geräten verbinden. Mit diesem Tool können Sie schnell, einfach und sicher verbundene Objekte erstellen. Um Verbindung mit der Arduino IoT Cloud aufnehmen zu können, brauchen Sie ein Arduino-Board, das netzwerkfähig ist. Folgende netzwerkfähige Arduino-Boards werden unterstützt: MKR 1000 WiFi MKR WiFi 1010 MKR WAN 1300 MKR WAN 1310 MKR GSM 1400 MKR NB 1500 Nano RP2040 Connect Nano 33 IoT Portenta H7 Portenta H7 Lite Connected Nicla Vision Außerdem sind einige Boards von Drittanbietern kompatibel: ESP8266 ESP32 Arm Pelion IoT Platform LoRaWAN-Geräte
Wenn Sie sich für diese Möglichkeit interessieren, finden Sie eine gute Dokumentation auf der Arduino-Projektseite. Die Vorgehensweise ist zudem gut geführt, allerdings hatte ich nicht immer eine stabile Kommunikation zur Arduino IoT Cloud. Weitere Informationen finden Sie u. a. https://docs.arduino.cc/cloud/iot-cloud/tutorials/technical-reference.
4.3.3 Arduino Project Hub Über den Arduino Project Hub werden Projekte und Tutorials bereitgestellt, die als Vorlagen und Anregungen für eigene Projekte dienen können. Im Eröffnungsfenster der Arduino-Create-Plattform ist der Link zum Project Hub nicht mehr zu finden, dennoch können Sie über den Link https://create.arduino.cc/projecthub auf ihn zugreifen. Der Arduino Project Hub basiert auf der hackster.io Community (https://www. hackster.io), einer weltweit stark wachsenden Entwickler-Community für das Erlernen, Programmieren und Erstellen von Hardware. Hackster.io ist heute ein Bereich des Distributors Avnet. Eine Suchfunktion mit unterschiedlichen Kriterien unterstützt das Auffinden eines gesuchten Themas. Die Projekte präsentieren sich in der Form, die Sie in Abbildung 4.17 sehen.
Abbildung 4.17 Arduino Project Hub
Anhand der Views erkennen Sie, wie oft ein Projekt aufgerufen wurde – was direkt das Interesse der Community an dieser Thematik widerspiegelt. Das Projekt kann kommentiert werden, wodurch auch ein Dialog mit dem Autor möglich wird. Die Respects entsprechen den Likes, die Sie aus den sozialen Medien kennen. Damit die Community weiterwachsen kann, kann jeder sein eigenes Projekt im Arduino Project Hub veröffentlichen. Das Formular ist dafür sehr hilfreich und macht es den Autoren einfach, ihre Projekte zu veröffentlichen. Haben Sie Texte, Fotos und Informationen hochgeladen, können Sie auf einer Checkliste prüfen, ob nichts fehlt.
4.4 Arduino Create vs. Arduino IDE Nachdem ich in Abschnitt 4.3 die Eigenschaften der Arduino-CreatePlattform vorgestellt habe, möchte ich diese nun mit der klassischen Arduino IDE vergleichen. Mit der klassischen Arduino IDE haben Sie eine lokale Installation der Entwicklungsumgebung auf dem eigenen PC und bearbeiten Ihre Projekte auch lokal. Für die Versionskontrolle der ArduinoSoftware und der eingesetzten Librarys sind Sie selbst verantwortlich, Sie werden aber über vorhandene Updates informiert. Bei der Arduino-Create-Plattform handelt es sich um eine in die Arduino Cloud ausgelagerte Entwicklungsumgebung, die eine stabile Internetverbindung erfordert. Ist diese gegeben, dann können Sie die Vorteile der Cloud nutzen. Die Vorteile bestehen im webbasierten Zugriff auf die Ressourcen, wodurch keine lokale Bindung mehr besteht. Am Quelltext können Sie von überall und praktisch von jeder Plattform aus arbeiten. Praktisches Arbeiten ist mit beiden Varianten möglich. Wer Bedenken gegenüber der Cloud-Lösung hat, kann weiterhin mit der klassischen Arduino IDE arbeiten. Mir persönlich hat das Arbeiten mit der Arduino-Create-Plattform Spaß gemacht, zumal die bei umfangreicheren Quelltexten längeren Laufzeiten des Compilers in der Arduino IDE von der ArduinoCreate-Plattform deutlich unterboten wurden. Arduino IDE
Generell gilt für jede der Arduino-Entwicklungsumgebungen Folgendes: Die Arduino IDE nutzt die GNU Toolchain, die die GNU Compiler Collection (GCC) beinhaltet. Alle hier vorgestellten Mikrocontroller werden durch diese Programmierumgebung unterstützt. Sie haben deshalb mit der Arduino IDE ein universelles Werkzeug für die Entwicklung von Anwendungen für sehr unterschiedlich ausgestattete Mikrocontroller zur Verfügung, und Sie haben die Möglichkeit, ohne Wechsel der Programmierumgebung Programme von einem Mikrocontroller auf einen anderen zu portieren.
4.5 Programmieren in C++ Es wäre vermessen, die Grundlagen der Programmierung in C++ in nur einem Kapitel vermitteln zu wollen – diese Darstellung füllt ganze Programmierhandbücher.[ 8 ] Ich möchte Ihnen aber die Dinge zeigen, die für die Programmierung eines Arduinos in der Arduino IDE erforderlich sind. Wenn Fragen offenbleiben sollten, dann empfehle ich Ihnen, in einem Online-Tutorial noch einmal nachzuschauen. Zusammen mit den Programmbeispielen werden Sie so über ausreichend Rüstzeug verfügen, um eigene Projekte in Angriff nehmen zu können. Die Programmbeispiele sind hier aus Platzgründen nicht oder nur auszugsweise abgedruckt. Laden Sie sich diese bei Bedarf aus dem Repository, um sie beim Lesen zur Hand zu haben.
4.5.1 Empfehlenswerte Online-Tutorials Damit Sie die Möglichkeit haben, bei Fragen auch in einem OnlineTutorial nachzulesen, habe ich hier die URLs einiger aus meiner Sicht geeigneter Online-Tutorials zusammengestellt. Bis auf das letzte Tutorial sind alle in deutscher Sprache verfasst. Das letzte Tutorial kann aber mit Grundkenntnissen der englischen Sprache ebenfalls gut verwendet werden. https://www.grundwissen.de/informatik/c/_downloads/grundkurs-c.pdf http://www.c-howto.de/tutorial/ https://de.wikibooks.org/wiki/C%2B%2B-Programmierung
https://www.w3schools.com/cpp/ (leichtes Englisch, empfehlenswert)
4.5.2 Einführung in die Grundlagen von C++ In diesem Abschnitt betrachten wir die Grundlagen von C++, die Sie für die Programmierung eines Arduinos benötigen. Bei Mikrocontrollern mit beschränktem Speicher ist die Vorgehensweise etwas anders als bei einem gut ausgestatteten PC, weshalb kaum alle Finessen der C++-Programmierung eingesetzt werden können. Datentypen, Variablen und Konstanten
Der eingesetzte Mikrocontroller hat im Allgemeinen die Aufgabe, erfasste physikalische Signale in bearbeitbare digitale Werte umzuwandeln, diese zu bewerten und daraus wieder Steuergrößen für einen Prozess zu ermitteln. Das ist das Grundprinzip einer jeden Steuerung, egal ob es sich dabei um die Heizung eines Aquariums oder um den Spurhalteassistenten im Fahrerassistenzsystem eines Autos handelt. Es werden also Daten erfasst, bearbeitet und in anderer Form ausgegeben. Die Daten stehen im Programm als Variablen oder Konstanten zur Verfügung und werden im Speicher gehalten. Für die Daten gibt es unterschiedliche Datentypen: Boolesche Daten beschreiben die zwei Zustände wahr (true) und falsch (false). Zeichen sind Ganzzahlen, die ein Zeichen repräsentieren (z. B. gemäß ASCII- Tabelle). Ganz- oder Integer-Zahlen sind Zahlen ohne Nachkommastellen.
Gleitkommazahlen sind Zahlen mit Nachkommastellen. Bevor Variablen und Konstanten verwendet werden können, müssen diese im Speicher angelegt werden. Diesen Vorgang nennt man Deklaration. Durch die Deklaration ist für eine Variable oder Konstante erst einmal nur Speicherplatz reserviert, ein definitiver Wert ist aber nicht zugeordnet. Das erfolgt im zweiten Schritt – bei der Initialisierung. Für die boolesche Variable flag sieht das folgendermaßen aus: bool flag = true;
Die boolesche Variable flag wird deklariert und mit dem Wert true initialisiert. Der Standarddatentyp für Zeichen ist char und nimmt 1 Byte im Speicher ein. Damit können 128 Zeichen codiert werden, die in der erweiterten ASCII-Tabelle definiert sind. Abbildung 4.18 zeigt diese Tabelle mit Codierungen als Dezimal- und Hexadezimalcodes sowie als Zeichen.
Abbildung 4.18 ASCII-Tabelle
Für Zeichen bzw. Zeichenketten (Strings) erfolgen Deklaration und Initialisierung folgendermaßen: char at = '@';
char s[] = "Ein String";
In der ersten Zeile wird ein Zeichen mit dem Namen at deklariert, und es wird ihm der Wert '@' (= 0x40) zugewiesen. Die zweite Zeile definiert ein Array s[], dem der String "Ein String" zugewiesen wird. Zu Arrays komme ich später. Während die Variable at 1 Byte im Speicher belegt, nimmt das Stringarray s[] 11 Byte in Anspruch. Zehn Zeichen kommen vom String, dem ein Null-Byte (0x00) angehängt wird. Man spricht hier vom null-terminierten String. Das Null-Byte am Ende des Strings vereinfacht es, die Länge eines Strings zu bestimmen. Für Integer-Zahlen, so will ich die Ganzzahlen in der Folge bezeichnen, gibt es eine Vielzahl von Datentypen, die in Tabelle 4.2 gelistet sind. Schreibweise
Typ
signed char
signed char
unsigned char
unsigned char
short
short
short int
Anzahl der Bits nach C++Standard mindestens 8
mindestens 16
Schreibweise
Typ
Anzahl der Bits nach C++Standard
signed short
signed short int
unsigned short
unsigned short
unsigned short int
int
int
mindestens 16
signed
signed int
unsigned
unsigned int
unsigned int
long
long int
signed long
long
mindestens 32
Schreibweise
Typ
Anzahl der Bits nach C++Standard
signed long int
unsigned long
unsigned long
unsigned long int
long long
long long
mindestens 64
long long int
signed long long
signed long long int
unsigned long long
unsigned long long
unsigned long long int
Tabelle 4.2 Datentypen für Integer-Zahlen
Alle Schreibweisen sind identisch mit dem jeweils zugeordneten Typ. Die Schreibweise, die in der Typ-Spalte verwendet wird, ist die in diesem Buch meistens genutzte. In der Praxis finden Sie aber, je nachdem wer den Code geschrieben hat, auch die äquivalenten Schreibweisen der ersten Spalte.
Der C++-Standard schreibt bei der Anzahl von Bits für den jeweiligen Datentyp gemäß Tabelle 4.2 nur Minimalwerte vor. Die tatsächliche Anzahl von Bits ist implementierungsabhängig. Eine Überprüfung kann mit der Funktion sizeof(var) erfolgen. Hier ist ein Auszug aus dem Programm VariableDatatypes.ino: int y = -4567;
…
Serial.print("int "); Serial.print(y); Serial.print(" needs ");
Serial.print(sizeof(y)); Serial.println(" Byte in RAM");
Die Variable y wird als Integer (int) deklariert und mit dem Wert – 4567 initialisiert. Die hier vorweggenommene Funktion Serial.print(value) gibt den Wert value über die serielle Schnittstelle an den Serial Monitor aus und kann mit der C++Konsolenausgabe cout verglichen werden. Erwartet wird hier also die Ausgabe: int –4567 needs 2 Byte in RAM
Abbildung 4.19 zeigt die Ausgabe des Programms VariableDatatypes.ino im Serial Monitor. Der Wertebereich von vorzeichenbehafteten Typen (signed) berechnet sich nach folgender Formel: -(2(n–1)) bis 2(n–1) – 1 Für vorzeichenlose Typen (unsigned) berechnet er sich durch: 0 bis 2n – 1
Abbildung 4.19 Serielle Ausgaben des Programms »VariableDatatypes.ino«
Tabelle 4.3 zeigt den Wertebereich für verschiedene IntegerDatentypen. Den 64 Bit umfassenden Datentyp long long habe ich wegen der Größe des Zahlenbereichs in der Tabelle weggelassen. n
8
Wertebereich Signed
unsigned
–128 bis 127
0 bis 256
16 –32.768 bis 32.767
0 bis 65.535
32 –2.147.483.648 bis 2.147.483.647 0 bis 4.294.967.296 Tabelle 4.3 Wertebereich verschiedener Integer-Datentypen
Alternativ zu den Bezeichnungen char, int, long und long long können Sie auch die Bezeichnungen gemäß Tabelle 4.4 verwenden, die weniger missverständlich sind. Datentyp
Alternative
signed char
int8_t
Datentyp
Alternative
unsigned char
uint8_t
int
int16_t
unsigned int
uint16_t
long
int32_t
unsigned long
uint32_t
long long
int64_t
unsigned long long uint64_t Tabelle 4.4 Alternative Datentypen
Bei char zu beachten darf nicht mit char abgekürzt werden! Das liegt daran, dass char ein Datentyp für Zeichen ist, während signed char und unsigned char üblicherweise Zahlen repräsentieren. signed char
Historisch bedingt ist die Trennung zwischen Zeichen und Zahlen in C++ leider sehr unsauber, was sich vor allem bei den charDatentypen zeigt (https://de.wikibooks.org/wiki/C%2B%2BProgrammierung/_Einf%C3%BChrung_in_C%2B%2B#Ganzzahle n).
Eine Gleitkommavariable kann sich eine bestimmte Anzahl Ziffern merken und dazu die Position des Kommas. Abbildung 4.20 zeigt das Format einer 32-Bit-Gleitkommazahl, wie es im Standard IEEE754 festgeschrieben ist.
Abbildung 4.20 IEEE-754 Single Floating Point Format (Quelle: Codekaizen [CC BY 3.0])
Die Gleitkommazahl N berechnet sich aus der 23-Bit-Fraction (F) und dem 8-Bit-Exponenten (E) sowie dem Vorzeichen (S) wie folgt:
Mit einem IEEE-754 Floating Point Converter, wie Sie ihn beispielsweise unter der URL https://www.hschmidt.net/FloatConverter/IEEE754de.html finden, können Sie sich mit dem Gleitkommaformat vertraut machen. In C++ werden Sie Gleitkommazahlen bzw. -variablen für das Rechnen mit Kommazahlen verwenden. Es gibt drei Datentypen für Gleitkommazahlen, die in Tabelle 4.5 mit ihren charakteristischen Werten aufgelistet sind: Typ
Speicherplatz Wertebereich kleinste positive Zahl
Genauigkeit
float
4 Byte
±3,4 × 1038
1,2 × 10–38
double
8 Byte
± 1,7 × 10308
2,3 × 10–308 12 Stellen
10 Byte
± 1,1 × 104932 3,4 × 10–
long double
Tabelle 4.5 Datentypen für Gleitkommazahlen
4932
6 Stellen
18 Stellen
Die Auswahl eines Gleitkommadatentyps ist normalerweise weniger einfach als die einer Integer-Zahl. Beim Arduino ist allerdings die Genauigkeit abhängig von der Implementierung. In Abbildung 4.19 konnten Sie sehen, dass beim Arduino Uno für alle drei Datentypen 4 Byte reserviert wurden. Das bedeutet: Bei diesem Controller gibt es keinen Unterschied zwischen float, double und long double. Anders ist das beim Arduino Due, denn dort ist double auf 8 Byte erweitert und entspricht damit den Angaben in Tabelle 4.5. Sie müssen also im Zweifelsfall immer die implementierungsabhängigen Details einem Test unterziehen. Das Programm VariableDatatypes.ino unterstützt Sie dabei. In C++ können Sie unterschiedliche Zahlenformate verwenden. Die Dezimalzahl 255 kann hexadezimal als 0xFF, oktal als 0377 und binär als 0b11111111 dargestellt werden. Geltungsbereich von Variablen
Variablen in C++ haben einen Geltungsbereich (Scope). Sie müssen generell zwischen globalen und lokalen Variablen unterscheiden. Eine globale Variable ist eine Variable, die von jeder Funktion in einem Programm gesehen werden kann. Lokale Variablen sind nur innerhalb der Funktion sichtbar, in der sie deklariert worden sind. Der Einsatz lokaler Variablen stellt sicher, dass nur eine Funktion Zugriff auf ihre eigenen Variablen hat. Dadurch kann diese Funktion keine Variablen ändern, die von einer anderen Funktion verwendet werden. Bei globalen Variablen ist das möglich. Qualifier
Das Verhalten von Variablen kann durch sogenannte Qualifier beeinflusst werden. Drei dieser Qualifier sind für die
Programmierung eines Arduinos wichtig: volatile, static und const. volatile ist ein Schlüsselwort, das als Variablenqualifier bezeichnet
wird. Es wird beispielsweise in der Form volatile boolean flag
volatile int value
verwendet, also durch Voranstellen vor den Datentyp einer Variablen. Der Compiler wird durch dieses Schlüsselwort angewiesen, die Variable im RAM und nicht in einem Speicherregister anzulegen. Eine Variable sollte immer dann als volatile (flüchtig) deklariert werden, wenn ihr Wert außerhalb der Kontrolle des Codeabschnitts, in dem sie angezeigt wird, geändert werden kann. Beim (einfachen) Arduino sind das im Wesentlichen Interrupt-Serviceroutinen. Interrupts werden in Abschnitt 4.6.2 beschrieben. Wenn die flüchtige Variable größer als 1 Byte ist (z. B. ein 16-BitInteger oder ein 32-Bit-Integer), kann der 8-Bit-Arduino diese nicht in einem Schritt lesen. Es sind mehrere Speicherzugriffe (auf jeweils 1 Byte) erforderlich. Es kann also passieren, dass beim Lesen des ersten Bytes ein Interrupt das zweite Byte ändert und dadurch ein fehlerhafter 16-Bit-Wert zusammengesetzt wird. Es sind deshalb während des Lesevorgangs aller Bytes die Interrupts zu sperren. Nach dem Lesevorgang sollten sie reaktiviert werden. Mit dem Schlüsselwort static werden lokale Variablen erstellt, die nur für die Funktion sichtbar sind, in der sie deklariert wurden. Lokale Variablen werden beim Aufruf einer Funktion erstellt und beim Verlassen zerstört. Statische Variablen bleiben über den Funktionsaufruf hinaus bestehen und behalten ihre Daten zwischen den Funktionsaufrufen.
Als statisch deklarierte Variablen werden nur beim ersten Aufruf einer Funktion erstellt und initialisiert. Das Schlüsselwort const steht für Konstante und bewirkt, dass der Wert der so deklarierten Variablen nicht verändert werden kann. Konstanten sind also Variablen mit einem einmal zugewiesenen Wert. Gekennzeichnet wird eine Konstante, indem Sie ihr bei der Deklaration const voranstellen. Eine Initialisierung ist zwingend: const int val = 123;
Um RAM zu sparen, wird in einem Embedded System eine Konstante im Flash abgelegt. Zur Definition von Konstanten können Sie const oder #define verwenden. Sie sollten aber wegen der größeren Sicherheit bei der Definition von Konstanten const gegenüber #define bevorzugen. Das Programmbeispiel qualifier.ino zeigt die Verwendung von const und static. Die Anwendung von volatile ist im Programmbeispiel ExternalInterrupts.ino gezeigt. Rechnen mit Variablen
Beim Rechnen mit Variablen und Konstanten sind die Datentypen zu beachten. Für Integer-Zahlen gilt, dass das Ergebnis immer den »größeren« Datentyp annimmt. Unter der URL https://de.wikibooks.org/wiki/C%2B%2BProgrammierung/_Einf%C3%BChrung_in_C%2B%2B/_Rechnen_mit_ unterschiedlichen_Datentypen finden Sie eine detaillierte Darstellung hierzu. Anhand weniger Beispiele wird Ihnen sicher das grundlegende Verhalten klar:
char char char char float float float
+ + + + + + +
int unsigned int long unsigned long float double long double
=> => => => => => =>
int
unsigned int
long
unsigned long
float
double
long double
Nun sind aber beim Rechnen mit Variablen und Konstanten nicht nur die Datentypen, sondern auch die Werte selbst interessant. Beim Rechnen verhält sich C++ genauso, wie wir es in der Schule gelernt haben. Es sind die vier Grundrechenarten Multiplikation (*), Division (/), Addition (+) und Subtraktion (–) bekannt, und es gilt »Punktrechnung geht vor Strichrechnung«. Hierzu will ich Ihnen ein Beispiel zeigen, das Sie auch mit dem Programm Calculation.ino selbst ausprobieren können: ((1+2/3)*4-5) = -1
((1+2./3)*4-5) = 1.67
Wo kommen die unterschiedlichen Resultate her? In der ersten Zeile beginnen wir mit der Operation 2/3, deren Ergebnis 0 lautet. Da es sich um eine Integer-Division handelt, ist das Ergebnis 0 richtig. Zu diesem Wert wird 1 addiert und die Summe mit 4 multipliziert. Von diesem Zwischenresultat wird nun noch der Wert 5 subtrahiert und als Ergebnis folgt –1. In der zweiten Zeile erfolgt wieder die Operation 2./3. Hier ist aber durch den Dezimalpunkt der Zahl 2 ein float-Typ zugeordnet und das Ergebnis der Operation float/int ist float und damit 0.6667. Durch die Addition von 1 wird das Zwischenergebnis der ersten Klammer 1.6667. Durch die Multiplikation mit 4 und der anschließenden Subtraktion von 5 lautet schließlich das Ergebnis 1.6667 (die Ausgabe im Programm ist auf zwei Stellen gerundet, deshalb 1.67).
Zur Vereinfachung der Quelltexteingabe können zusammengesetzte Operationen verwendet werden. Hierzu ein paar Beispiele, die weitgehend selbsterklärend sind (siehe Tabelle 4.6): Rechenoperation Zusammengesetzte Operation val = val + 5
val +=5
val = val - 5
val -=5
val = val * 5
val *=5
val = val / 5
val /=5
val = val + 1
val++
val = val - 1
Val--
Tabelle 4.6 Zusammengesetzte Operationen
Bedingte Verzweigungen
Durch bedingte Verzweigungen kann der Programmfluss in unterschiedliche Pfade gelenkt werden. Im einfachsten Fall sieht eine bedingte Verzweigung bei erfüllter Bedingung (true) folgendermaßen aus: if (bedingung)
{
//Anweisungen, wenn Bedingung erfüllt ist
anweisung1;
anweisung2;
}
Für den Fall, dass auch die nicht erfüllte Bedingung (false) berücksichtigt werden soll, erweitern Sie das Konstrukt mit einem else-Zweig: if (bedingung)
{
//Anweisungen, wenn Bedingung erfüllt ist
anweisung1;
anweisung2;
…
}
else
{
//Anweisungen, wenn Bedingung nicht erfüllt ist
Anweisung3;
Anweisung4;
…
}
Die zu testende Bedingung wird mithilfe der sechs in C++ zur Verfügung stehenden Vergleichsoperatoren formuliert (siehe Tabelle 4.7): Vergleichsoperator Bedeutung ==
ist identisch
=
ist größer gleich
ist größer
!=
ist ungleich
Tabelle 4.7 C++-Vergleichsoperatoren
Die folgenden Codezeilen zeigen den Vergleich der beiden IntegerZahlen a und b und die entsprechende Verzweigung nach der
Bedingung a < b. Im hier gezeigten Beispiel wird also der Wert a = 10 (true-Zweig) ausgegeben werden. Vergleichen Sie noch die Schreibweise der Anweisungen in den zwei Zeilen. Im true-Zweig ist die Anweisung in Klammern {} gesetzt. Es lassen sich also weitere Anweisungen hinzufügen. Ist nur eine Anweisung im Zweig vorhanden, dann kann diese auch direkt hinter das Schlüsselwort if oder else gesetzt werden (wie Sie es im falseZweig sehen). int a = 10, b = 20;
if (a < b)
{
Serial.print(a);
}
else Serial.print(b);
Es lassen sich weitere Alternativen durch Erweiterung mit else if() einbauen. Ich verzichte hier darauf, um keine Verwirrung zu stiften. Bei Bedarf schauen Sie einfach in eines der Online-Tutorials, die Sie in Abschnitt 4.5.1 finden. Mit logischen Operatoren können Sie mehrere Bedingungen zu einem Ausdruck verknüpfen. C++ bietet folgende Möglichkeiten (siehe Tabelle 4.8): Logische Funktion Bedeutung Operation !
NICHT
Resultat ist true, wenn der Operand false ist.
&&
UND
Resultat ist true, wenn beide Operanden true sind.
Logische Funktion Bedeutung Operation ||
ODER
Resultat ist true, wenn mindestens ein Operand true ist (inklusives ODER, inclusive OR).
Tabelle 4.8 Logische Operationen in C++
Mit diesen logischen Operationen lassen sich Bedingungen komfortabel verknüpfen. Hier sind die beiden Variablen wieder mit den gleichen Werten wie vorhin initialisiert worden, also mit 10 und 20. Mit der irgendwo im Quelltext angeführten Bedingung if (a == 10 && b ==20) kann getestet werden, ob die Variablen zum Zeitpunkt des Tests die Initialisierungswerte (wieder oder noch) aufweisen. int a = 10, b = 20;
…
if (a == 10 && b == 20)
{
Serial.println("Beide Werte sind unverändert");
}
In C++-Quelltexten werden Sie auch häufig die folgende Notation vorfinden: int min = a < b ? a : b;
Serial.println(min);
Der Auswahloperator ? vereinfacht die Schreibweise, spiegelt aber gleiches Verhalten wider. Ist das Ergebnis des Tests a 40
40
Mit sogenannten Default-Parametern kann die Parameterübergabe an eine Funktion vereinfacht werden, indem nicht alle Parameter komplett übergeben werden müssen.
Der Funktion summe() werden die vier Argumente a, b, c und d übergeben. int summe(int a, int b, int c = 0, int d = 0)
{
int x = a +b +c +d;
return x;
}
Die Argumente c und d werden schon bei der Deklaration mit dem Wert 0 initialisiert und müssen deshalb beim Aufruf der Funktion nicht mehr explizit angegeben werden. Die drei folgenden Funktionsaufrufe kennzeichnen die Möglichkeiten: x = summe(2, 3, 4, 5); x = summe(2, 3, 4); x = summe(2, 3);
//x = 14
//x = 9, weil d = 0
//x = 5, weil c = 0 und d = 0
Im ersten Fall werden alle vier möglichen Argumente der Funktion explizit angegeben und in der Berechnung berücksichtigt. Die Summe der vier Argumente beträgt erwartungsgemäß 14. Beim zweiten Aufruf wird auf die Angabe des Arguments d verzichtet, weshalb der Default-Wert (hier 0) in die Berechnung eingeht. Die Summe der drei übergebenen Argumente beträgt dann 9. Der dritte Aufruf berücksichtigt nur die ersten beiden Argumente und nimmt für den Rest die Default-Werte (beide 0). Das Ergebnis der Berechnung lautet nun 5. Das Überladen von Funktionen (Function Overloading) ist eine Möglichkeit in C++, dass mehrere Funktionen den gleichen Namen, aber unterschiedliche Parameter aufweisen. Am Beispiel der Summenfunktion sieht das wie folgt aus: int summe(int a, int b, int c, int d)
{
int x = a +b +c +d;
return x;
}
int summe(int a, int b, int c)
{
int x = a +b +c;
return x;
}
int summe(int a, int b)
{
int x = a +b;
return x;
}
Jede der drei Funktionen bildet die Summe aus den übergebenen Parametern. Der Compiler kann durch die unterschiedlichen Parameterlisten die Funktionen richtig zuordnen. Der ersten Funktion werden vier Parameter übergeben, der zweiten drei und der dritten nur noch zwei: x = summe(2, 3, 4, 5); // x = 14
x = summe(2, 3, 4); // x = 9
x = summe(2, 3); // x = 5
Mit dem Programmbeispiel overload.ino haben Sie dieses Prinzip als ausführbares Programm zur Hand. Wenn Sie später in die Interna der Arduino-Quellen schauen, dann werden Sie diese Überladung von Funktionen häufig zu sehen bekommen. Aufzählungen
Eine Aufzählung (Enumeration) ist in C++ ein benutzerdefinierter (user-defined) Datentyp, der eine Anzahl von Werten abbilden kann. Die folgenden Beispiele zeigen die Definition solcher Aufzählungen, die durch das Schlüsselwort enum eingeleitet werden: enum Days{Sun,Mon,tue,Wed,thu,Fri,Sat};
enum Colors{Red=10, Green, Blue};
Die erste Aufzählung Days listet die Wochentage Sonntag (Sun) bis Samstag (Sat) auf, während die zweite Aufzählung Colors die Farben Rot, Grün und Blau in einer Liste zusammenfasst. Jedem Listenelement ist ein Index zugeordnet. Entweder geschieht das explizit, wie bei Red=10, oder implizit, beginnend mit 0. Die folgenden Indizes werden dann jeweils um 1 erhöht. Die im Programm enum.ino enthaltenen Ausgabeanweisungen zeigen dann das im Kommentar genannte Resultat: Serial.println(Mon); Serial.println(Fri); Serial.println(Green);
Colors myFavorite = Red;
Serial.println(myFavorite);
// -> 1
// -> 5
// -> 11
// -> 10
In der vierten Zeile wird die Variable myFavorite vom Typ Colors deklariert und mit dem Wert Red initialisiert. Die folgende Ausgabeoperation gibt deshalb auch den Wert 10 aus. Zeiger
Diesem Abschnitt möchte ich ein (übersetztes) Zitat aus der Arduino Reference (https://www.arduino.cc/reference/en/language/structure/pointeraccess-operators/dereference/) voranstellen: »Zeiger sind eines der komplizierten Themen für Anfänger beim Erlernen von C, und es ist möglich, die überwiegende Zahl der Arduino-Sketches zu schreiben, ohne jemals auf Zeiger zu stoßen. Um bestimmte Datenstrukturen zu manipulieren, kann die Verwendung von Zeigern den Code vereinfachen, und das Wissen, wie man Zeiger manipuliert, ist im eigenen Toolkit nützlich.«
Dieses Zitat soll Sie nicht davon abschrecken, Zeiger zu verwenden. Es soll Sie stattdessen animieren, sich mit dem betreffenden Code zu befassen, bis Sie ihn verstanden haben. Die Fehlersuche kann sich ansonsten recht schwierig gestalten. Schauen Sie sich die Grundlagen zu Zeigern (Pointer) also gut an. Zeiger sind zwar kein einfaches Thema, aber in der Praxis sehr hilfreich. Mit der folgenden Instruktion werden drei IntegerVariablen deklariert und initialisiert: Int i = 0, j = 1, k = 2;
Im Speicher sieht das folgendermaßen aus: Adresse
… addr0 addr1 addr2 …
Variablenname
i
j
k
Wert
0
1
2
Beginnend an Adresse addr0 sind die drei Integer-Variablen i, j und k im Speicher abgelegt und mit den Werten 0, 1 und 2 initialisiert. Durch die Instruktion int *a, *b;
// a und b sind Zeiger auf Integer-Variablen
werden die Zeiger a und b auf Integer-Variablen deklariert. Die Anweisungen a = &i; b = &k;
// die Adresse von i wird dem Zeiger a zugewiesen
// die Adresse von k wird dem Zeiger b zugewiesen
weisen dem Zeiger a die Adresse der Variablen i und dem Zeiger b die Adresse der Variablen k zu. Mit & wird der Adressoperator bezeichnet. Soll nun der Inhalt der Adresse wiedergegeben werden, auf den die Zeiger a und b zeigen, dann erfolgt das mithilfe des Dereferenz-
Operators *. Wenn a ein Zeiger ist, stellt *a den Wert dar, der in der Adresse enthalten ist, auf die a zeigt. Der jeweilige Kommentar in den folgenden beiden Zeilen zeigt das Ergebnis der seriellen Ausgabe: Serial.println(*a); // -> 0
Serial.println(*b); // -> 2
Im Programmbeispiel pointer.ino sind die geschilderten Operationen ausführbar zusammengestellt. Arrays
Arrays sind eine Zusammenstellung von Variablen des gleichen Typs. Deklaration und Initialisierung folgend einem einfachen Muster: int array[10];
int array[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
int array[10] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
In der ersten Zeile wird ein Array aus zehn Integer-Zahlen deklariert, d. h., es wird der Speicherplatz für zehn Integer-Zahlen reserviert. In der zweiten Zeile wird das Array ohne Angabe einer Dimension deklariert und mit den Zahlen zwischen den geschweiften Klammern initialisiert. Dadurch ist auch hier ein Array mit zehn Integer-Zahlen definiert. In der letzten Zeile ist der komplette Eintrag formuliert. Der Zugriff auf die Elemente des Arrays kann über den Index des jeweiligen Elements oder über Zeiger erfolgen: Serial.println(array[5]); // Zugriff über Index -> 6
Serial.println(*(array +5)); // Zugriff über Zeiger -> 6
Im Programmbeispiel array.ino sind die geschilderten Operationen ausführbar zusammengestellt.
Speichergrenzen Der Compiler übernimmt keine Überprüfung, ob der aufgerufene Index innerhalb der definierten Grenzen liegt. Beim Zugriff auf ein Element außerhalb der definierten Grenzen – im obigen Beispiel wäre das durch array[22] gegeben – ist ein undefiniertes Verhalten die Folge. Dadurch kann ein anderer Speicherbereich überschrieben werden oder das Programm abstürzen.
Strukturen und Unions
In einem Array können nur Daten gleichen Typs zusammengefasst werden. Eine Struktur hingegen ist ein Datentyp, der mehrere Variablen gleichen oder unterschiedlichen Typs zu einem neuen Datentyp zusammenfasst. Die Deklaration erfolgt in der Form: struct Struktur1
{
bool a;
int b;
float c;
};
Der Name Struktur1 kann nun wie ein primitiver Datentyp (char, int etc.) verwendet werden, um eine Instanz dieser Struktur zu erstellen. Der Zugriff auf die einzelnen Elemente der Struktur erfolgt über den Operator . (nachdem die Instanz erzeugt wurde): Struktur1 s1;
s1.a = true;
s1.b = 123;
s1.c = 1.23;
Bei C++ ist ein struct auch eine Klasse und kann genauso verwendet werden. Klassen stelle ich Ihnen später vor. Hier zeige ich Ihnen aber schon einmal die Formulierung der Struktur als Klasse:
class Struktur2
{
public:
bool a;
int b;
float c;
};
Bei Arrays und Strukturen sind die darin enthaltenen Elemente öffentlich (public), also von außen zugänglich (lesbar und beschreibbar), während bei einer Klasse diese privat, d. h. nur in der Klasse selbst, zugänglich sind. Um diese Elemente in einer Klasse wiederum öffentlich zugreifbar zu gestalten, müssen diese als public deklariert werden. Im Programmbeispiel struct.ino sind die geschilderten Operationen ausführbar zusammengestellt. Eine Union vereint ebenfalls unterschiedliche Datentypen, allerdings nicht wie bei der Struktur nacheinander im Speicher angeordnet, sondern auf einem gemeinsamen Speicherplatz. Die Deklaration ist vergleichbar zur struct in der Form: union Value
{
int i;
double d;
};
Es wird der Datentyp Value deklariert, der eine Integer- und eine Double-Variable am gleichen Speicherplatz bereitstellen soll. Wie geht das? Der Compiler reserviert einen genügend großen Speicherbereich, damit der größte Datentyp abgelegt werden kann. Der Datentyp double umfasst hier 4 Byte, weshalb für die Union v auch 4 Byte Speicher reserviert werden.
Der Zugriff auf die Union erfolgt nach deren Instanziierung in der bekannten Weise: Value v;
v.d = 987.654;
v.i = 123;
Der Vorteil einer Union ist der reduzierte Speicherbedarf. Ihr Nachteil ist, dass Sie zu jedem Zeitpunkt selbst über den aktuellen Datentyp Bescheid wissen müssen. Datentypen und Union Eine Union kann zu einem Zeitpunkt stets nur einen Datentyp besitzen. Es wird immer nur der zuletzt geschriebene Datentyp korrekt gelesen.
Im Programmbeispiel union.ino sind die geschilderten Operationen ausführbar zusammengestellt. Klassen
Eine Klasse ist ein benutzerdefinierter Datentyp, den Sie in Ihren eigenen Programmen einsetzen, aber auch in den zahlreichen Arduino-Librarys immer wieder finden können. In C++ ist alles zusammen mit Attributen und Methoden den Klassen und Objekten zugeordnet. Attribute und Methoden sind Variablen und Funktionen, die zu einer Klasse gehören, und werden daher oft auch als Klassenmitglieder (class members) bezeichnet. Im Abschnitt zu den Strukturen hatte ich Ihnen einen ersten Hinweis zu Klassen gegeben. Diesen Punkt möchte ich hier noch einmal aufgreifen.
In die Klasse Struktur gehören die von außen zugänglichen (public) Variablen a, b und c: class Struktur
{
public:
bool a;
int b;
float c;
};
Nachdem ein Objekt s der Klasse Struktur erzeugt wurde, können Sie darauf zugreifen. Ist das betreffende Element initialisiert, dann wird es einen gültigen Wert aufweisen. Die Initialisierung kann durch einen sogenannten Konstruktor erfolgen. class Struktur
{
public:
bool a;
int b;
float c;
Struktur(bool x, int y, double z)
{
a = x; b = y; c = z;
}
};
Der Konstruktor weist den gleichen Namen wie die Klasse auf und übergibt die Initialwerte an die Variablen. Im ausführbaren Programmbeispiel class.ino habe ich nicht alle Variablen initialisiert. Ich zeige dort auch den fehlerhaften Zugriff auf eine nicht initialisierte Variable der Klasse. Als letzte Aktion möchte ich in dieser knappen Einführung zu Klassen noch eine Methode einführen, sodass sich die Klassendefinition wie folgt erweitert: class Struktur
{
public:
bool a;
int b;
float c;
Struktur(bool x, double z) // Konstruktor
{
a = x; c = z;
}
void about()
{
Serial.println("This is an object of class Struktur");
}
};
Die Funktion about() gibt einen Text seriell aus und kann nach der Instanziierung aufgerufen werden: Struktur s(true,123, 1.23); s.about();
// Create an object s
Im Programmbeispiel class.ino sind die geschilderten Operationen ausführbar zusammengestellt. Listing 4.1 zeigt den betreffenden Quelltext: class Struktur
{
public:
bool a;
int b;
float c;
Struktur(bool x, double z) // Konstruktor
{
a = x; c = z;
}
void about()
{
Serial.println("This is an object of class Struktur");
}
};
void setup()
{
Serial.begin(115200);
while(!Serial); // wait for serial port to connect (native USB only)
Struktur s(true,1.23); // Create an object s
s.about();
// Access to initialized member by constructor
Serial.print("s.c: "); Serial.println(s.c);
// Access to uninitialized member
Serial.print("s.b: "); Serial.println(s.b);
// Initialising integer member
s.b = 123;
Serial.print("s.b: "); Serial.println(s.b);
}
void loop() {}
Listing 4.1 Quelltext des Beispiels class.ino
Abbildung 4.21 zeigt die Ausgaben des Programmbeispiels, die ich Ihnen im Folgenden erläutere. Durch die Anweisung Struktur s(true,1.23) wird ein Objekt s erzeugt, dem mit true ein boolescher Wert und mit 1.23 eine Gleitkommazahl übergeben werden. Der in der Struktur vorhandene Integer-Wert wird vom Konstruktor nicht initialisiert. Der Aufruf der Methode s.about() erzeugt die erste Zeile der Ausgabe. Danach folgt der Zugriff auf die Variable s.c und damit die Ausgabe der Gleitkommazahl 1.23. Der Zugriff auf die Variable s.b, die zu diesem Zeitpunkt nicht initialisiert ist, liefert den Wert 0. Dieser Wert ist falsch, denn die Variable ist nicht initialisiert. Erst nach deren Initialisierung durch die Anweisung s.b = 123 erfolgt beim nächsten Zugriff auch die Ausgabe eines korrekten Wertes.
Abbildung 4.21 Ausgaben des Programbeispiels »class.ino«
Nicht initialisierte Variablen
In C++ werden lokale Variablen nicht standardmäßig initialisiert. Nicht initialisierte Variablen können einen beliebigen Wert enthalten, und ihre Verwendung führt zu nicht definiertem Verhalten. Initialisieren Sie lokale Variablen, wenn sie deklariert werden, oder weisen Sie ihnen einen Wert zu, bevor sie verwendet werden.
Sie sind jetzt auf einem Kenntnisstand, auf dem ich Ihnen einen Blick in das Programmbeispiel Uno_Flasher.ino empfehle. class.ino zeigt sehr gut die vorangegangenen Schritte in einem praxisrelevanten Beispiel. Präprozessor-Direktiven
Präprozessor-Direktiven erkennen Sie im Quelltext von Programmen an dem Hash-Zeichen (#) zu Beginn der Zeilen. Diese Zeilen sind Anweisungen für den Präprozessor, der den Quelltext vor der Kompilierung überprüft und vorverarbeitet. Präprozessor-Direktiven erstrecken sich über eine Codezeile bis zum Zeilenende durch Newline (\n). Eine Präprozessor-Direktive kann sich nur dann über mehr als eine Zeile erstrecken, wenn dem Newline am Zeilenende ein Backslash (\) vorangestellt wird. Sie werden bei der Arduino-Programmierung mit drei verschiedenen Arten von Präprozessor-Direktiven konfrontiert: Makrodefinitionen, bedingte Kompilation und Einfügen von Quelltext. Makrodefinitionen (#define, #undef)
Findet der Präprozessor ein #define, dann wird jedes Vorkommen des Identifiers im Quelltext durch das Replacement (dt. Ersatz)
ersetzt. Es ist vollkommen gleich, ob das Replacement sinnvoll ist oder nicht, weshalb hier durchaus Vorsicht geboten ist. #define Identifier Replacement
#define SIZE 100
#undefine SIZE
#define getmax(a,b) ((a)>(b)?(a):(b))
In der zweiten Zeile wird dem Identifier SIZE die Zeichenfolge 100 zugeordnet. Mit der dritten Zeile wird diese Zuordnung aufgehoben. In der vierten Zeile wird ein Makro getmax(a, b) erstellt, das den Maximalwert der Zahlen a und b zurückgibt. Bedingte Kompilation (#ifdef, #ifndef, #if, #endif, #else und #elif)
Diese Direktiven steuern eine bedingte Kompilation, d. h., in Abhängigkeit von bestimmten Bedingungen werden Teile des Quelltextes in die Kompilation ein- bzw. aus ihr ausgeschlossen. Häufig anzutreffen sind Konstrukte wie: #ifndef SIZE
#define SIZE 100
#endif
int table[SIZE];
Ist der Identifier SIZE noch nicht definiert, dann wird er es mit der nachfolgenden Zeile, und das Replacement nimmt den Wert 100 an. Überall im Quelltext wird nun SIZE durch 100 ersetzt, wodurch in der letzten Zeile ein Array mit dem Namen table erzeugt wird, das 100 Integer-Zahlen aufnehmen kann. Quelltextersetzung (#include)
Findet der Präprozessor eine #include-Direktive, dann ersetzt er diese durch den kompletten Inhalt der betreffenden Headerdatei:
#include
#include "file"
Im ersten Fall wird eine Headerdatei mit dem Namen header eingebunden, die normalerweise in einem separaten Verzeichnis (neben anderen Headerdateien) abgelegt ist. Im zweiten Fall wird eine Datei eingebunden, die im gleichen Verzeichnis wie der Quelltext des Programms liegt. Auf diese Weise lässt sich beispielsweise eine spezielle Variante einer Datei einbinden.
4.6 Den Arduino programmieren Nachdem Sie in den vorigen Abschnitten die für die Programmierung des Arduinos wichtigsten Elemente der Programmiersprache C++ kennengelernt haben, möchte ich nun auf die Programmierung des Arduinos selbst eingehen.
4.6.1 Programmstruktur Die Arduino-Sprache ist C++. Die Arduino-Kernfunktionen sind eine Reihe von C++-Klassen und -Bibliotheken. Als Compiler dient der GNU-Compiler gcc/g++. Listing 4.2 zeigt die Struktur eines Arduino-Programms, das oft auch als Sketch bezeichnet wird. Die Struktur ist sehr einfach gehalten und umfasst die beiden Funktionen setup() und loop(): void {
// }
void {
// }
setup()
put your setup code here, to run once:
loop()
put your main code here, to run repeatedly:
Listing 4.2 Struktur eines Arduino-Programms
Die Funktion setup() wird nach einem Reset einmal ausgeführt. Dabei ist es unerheblich, wodurch der Reset ausgelöst wurde. Der in der Funktion loop() enthaltene Code hingegen wird in einer Endlosschleife abgearbeitet. Die Funktionen setup() und loop() werden durch den Compiler in die für C++ obligatorische Funktion main() eingefügt. Listing 4.3 zeigt Ihnen die Struktur des erzeugten main(), die neben setup() und loop() noch Initialisierungen, die optionale Einbindung eines USBDevices und das Handling der seriellen Schnittstelle aufweist: int main(void)
{
init();
initVariant();
#if defined(USBCON)
USBDevice.attach();
#endif
setup();
for (;;)
{
loop();
if (serialEventRun) serialEventRun();
}
return 0;
}
Listing 4.3 Die Struktur eines kompilierten Arduino-Sketches
Durch die Definition der Funktionen setup() und loop() im Arduino-Quelltext sind alle Anforderungen des Compilers an eine gültige C++-Programmstruktur erfüllt. Die eigentliche Struktur wird vor Ihnen verborgen aufgebaut.
4.6.2 Arduino-Funktionen In Abschnitt 4.5.2 haben Sie eine knappe Einführung in C++ erhalten. Die ArduinoProgrammierung baut darauf auf, stellt aber über Librarys (Bibliotheken) zahlreiche Vereinfachungen zur Verfügung, die die Ansteuerung der Hardware, die Kommunikation und vieles mehr wesentlich erleichtern. Mithilfe der Arduino Language Reference (http://arduino.cc/en/Reference) möchte ich Ihnen die zusätzlichen Funktionen zur Arduino-Programmierung zeigen. Built-in Functions
Unter Built-in Functions (eingebaute Funktionen) sind Funktionen zu verstehen, die ohne das Laden zusätzlicher Librarys zur Verfügung stehen. Zur besseren Erläuterung der Funktionen stehen teilweise Programmbeispiele zur Verfügung, die Sie begleitend zum Lesen des Textes betrachten sollten. Es ist nicht erforderlich, dass Sie diese unbedingt laufen lassen. Allein die betreffenden Quelltexte sind schon hilfreich. Digitale Ein-/Ausgabe
Für die digitale Ein-/Ausgabe stehen alle Pins zur Verfügung. Das sind beim Arduino Uno die Pins 0 bis 13 sowie A0 bis A5. Sie müssen als Eingang oder Ausgang initialisiert sein und können gelesen und beschrieben werden. Folgende Funktionen stehen hierfür zur Verfügung: pinMode(uint8_t pin, INPUT | OUTPUT | INPUT_PULLUP);
int digitalRead(uint8_t pin);
void digitalWrite(uint8_t pin, HIGH | LOW);
Die Schreibweise HIGH | LOW bedeutet hier, dass die Funktion HIGH oder LOW als Argument erwartet. Um Pin 13 als Ausgang zu definieren und auf Lo (GND) zu setzen, sind also folgende Anweisungen erforderlich: pinMode(13, OUTPUT);
void digitalWrite(13, LOW);
Um Pin 7 als Eingang mit aktiviertem Pull-up-Widerstand zu definieren und diesen Eingang zu lesen, müssen Sie folgende Anweisungen schreiben: pinMode(7, INPUT_PULLUP);
int I7 = digitalRead(7);
Ist der Eingang unbeschaltet, dann wird die Variable I7 den Wert 1 liefern. Wird hingegen Pin 7 mit GND verbunden, dann liefert I7 den Wert 0. Analoge Ein-/Ausgabe
Für die analoge Eingabe stehen beim Arduino Uno die Pins A0 bis A5 zur Verfügung. Die analoge Ausgabe erfolgt bei allen Arduinos, die keinen internen DA-Umsetzer aufweisen, über ein PWM-Signal (PWM = Pulsweitenmodulation). Die PWM-fähigen Pins sind controllerspezifisch. Beim Arduino Uno sind das die Pins 3, 5, 6, 9, 10 und 11. Einige Arduinos weisen einen internen DA-Umsetzer auf und können dann eine analoge Ausgangsspannung liefern. Folgende Funktionen stehen hierfür zur Verfügung: analogReference(DEFAULT | INTERNAL | EXTERNAL);
int analogRead(uint8_t pin);
void analogWrite(uint8_t pin, int value);
Die Analog-Referenz ist wiederum controllerspezifisch. Für die AVR-basierten Arduinos gelten die in Tabelle 4.9 gezeigten Zuordnungen: Parameter
Referenzspannung
Board
DEFAULT
Default-Analog-Referenz 5 V für 5-V-Arduinos oder 3,3 V für 3,3-V-Arduinos
INTERNAL
Built-in-Analog-Referenz 1,1 V
ATmega168,
ATmega328P
Built-in-Analog-Referenz 2,56 V
ATmega32U4, ATmega8
INTERNAL1V1
Built-in-Analog-Referenz 1,1 V
Arduino Mega
INTERNAL2V56
Built-in-Analog-Referenz 2,56 V
Arduino Mega
EXTERNAL
Spannung an Pin AREF (0–5 V)
Tabelle 4.9 Analog-Referenzspannung für AVR-Arduinos
Für die megaAVR- und SAMD-Arduinos finden Sie die Informationen unter https://www.arduino.cc/reference/en/language/functions/analog-io/analogreference/. Beim Arduino Uno wird durch die folgenden Anweisungen eine Referenzspannung von 5 V festgelegt und anschließend die an Pin A0 anliegende Spannung erfasst: analogReference(DEFAULT);
int vA0 = analogRead(A0);
Die Variable vA0 wird danach einen Wert zwischen 0 und 1023 annehmen, da der integrierte AD-Umsetzer im Arduino Uno (ATmega328P) eine Auflösung von 10 Bit aufweist.
Ein PWM-Signal kann nach Glättung durch einen nachgeschalteten Filter (RC-Glied) als analoge Ausgangsspannung dienen. Ein solches PWM-Signal mit einem Tastverhältnis von 50 % an Pin 11 kann durch die folgende Anweisung ausgegeben werden: analogWrite(11, 128); // 0 - 255 possible
Das PWM-Signal bleibt so lange aktiv, bis es durch ein neues PWM-Signal aktualisiert wird oder durch ein digitalWrite() oder digitalRead() am gleichen Pin abgeschaltet wird. Erweiterte Ein-/Ausgabe
Zur Ausgabe von Tönen im hörbaren Bereich erzeugt der Arduino über seine internen Timer ein Rechteck-Signal, das an einem beliebigen Pin abgreifbar ist und durch einen PiezoSummer (Buzzer) hörbar gemacht werden kann. Folgende Funktionen stehen zur Verfügung: void tone(uint8_t pin, unsigned int frequency)
void tone(uint8_t pin, unsigned int frequency, unsigned long duration)
void noTone(uint8_t pin)
Die beiden Funktionen tone() unterscheiden sich nur darin, dass bei der zweiten neben Pin und Frequenz auch noch die Dauer des Tons angegeben wird. Die Dauer des Tons wird aber nur dann wirksam, wenn vor Ablauf der durch duration angegebenen Zeit kein weiterer Aufruf der Funktion tone() erfolgt. void tone(5, 440, 1000); // Dieser Ton ist nicht hörbar
void tone(5, 880, 1000);
Die Funktion noTone() stoppt die Ausgabe des Rechteck-Signals, das mit tone() begonnen wurde. Es kann immer nur ein Ton erzeugt werden. Wenn ein Ton bereits an einem Pin ausgegeben wird, dann hat der Aufruf von tone() für einen anderen Pin keine Wirkung. Wird hingegen der gleiche Pin gewählt, dann wird die Frequenz aktualisiert. Im Programmbeispiel tone.ino ist die Verwendung von tone() mit einem Dreiklang demonstriert. Auch wenn sich die Signalfolge nicht wie das wohltemperierte Klavier anhört, so ist diese Art der Tonausgabe zu Signalisationszwecken doch recht gut geeignet. Will man etwas mehr Komfort bei der Tonausgabe, dann leistet die Tone-Library von Brett Hagman (https://github.com/bhagman/Tone) gute Dienste. Die Funktionen shiftIn() und shiftOut() dienen zur synchronen seriellen Ein-/Ausgabe von Daten von bzw. zu einem Schieberegister oder Peripherie-Baustein, der diese Art von Interface unterstützt. Zur Verfügung stehen die folgenden Funktionen: void shiftOut(uint8_t dataPin, uint8_t clockPin, MSBFIRST | LSBFIRST, uint8_t val)
uint8_t shiftIn(uint8_t dataPin, uint8_t clockPin, MSBFIRST | LSBFIRST)
Die seriellen Daten werden über den Pin dataPin übertragen, das Taktsignal über Pin clockPin. Durch die Option MSBFIRST wird das höchstwertige Bit (Most Significant Bit, MSB) zuerst gesendet. Bei LSBFIRST ist das niederwertigste Bit (Least Significant Bit, LSB) zuerst an der Reihe. Abbildung 4.22 zeigt das Timing der Shift-Funktionen.
Abbildung 4.22 Timing der Shift-Operation
Bei der Funktion shiftOut() steht am seriellen Ausgang zuerst das zu sendende Datenbit DAT bereit. Es kann vom Clock-Signal CLK in ein Schieberegister übernommen werden. Bei der Funktion shiftIn() ist das vergleichbar. Der externe Sender stellt das von ihm zu sendende Datenbit auf seinem Datenausgang bereit, und unmittelbar nach der steigenden Flanke des Clock-Signals CLK liest der Arduino die Datenleitung, worauf das nächste Datenbit vom Sender bereitgestellt werden kann. Verschiedene Sensoren stellen ihr Ausgangssignal als Ausgangsimpuls zur Verfügung, dessen Pulslänge dann die eigentliche Information beinhaltet. Ein in der Robotik weitverbreiteter Sensor zur Abstands- oder Kollisionserfassung ist der Ultraschall-Sensor HCSR04, der Entfernungen zwischen ca. 2 cm und 3 m im Idealfall mit einer Auflösung von 3 mm messen kann. Die Länge des Signals am Echo Pulse Output des HC-SR04 liefert die Abstandsinformation (siehe Abbildung 4.23).
Abbildung 4.23 Timing bei der Entfernungsmessung mit dem HC-SR04
Mit den beiden Funktionen unsigned long pulseIn(uint8_t pin, HIGH | LOW,
unsigned long timeout) unsigned long pulseInLong(uint8_t pin, HIGH | LOW,
unsigned long timeout)
lassen sich solche Pulsbreiten vermessen. Beide Funktionen lesen einen Puls am vorgegebenen Pin. Der Parameter state, auf HIGH oder LOW gesetzt, definiert, ob ein Hi-Pulse
oder ein Lo-Pulse vermessen werden soll. Wurde state auf HIGH gesetzt, dann wartet die Funktion auf eine L/H-Flanke zum Start der Zeitmessung, die dann von einer H/L-Flanke abgeschlossen wird. Die Funktionen geben die Länge des vermessenen Impulses in Mikrosekunden zurück. Wenn innerhalb des Timeouts kein Resultat ermittelt werden konnte, dann geben die Funktionen 0 zurück. pulseInLong() ist eine Alternative zu pulseIn(), die sich besser für Szenarien mit langen
Impulsen und Unterbrechungen eignet.
Das Timing dieser Funktionen wurde empirisch bestimmt. Bei pulseIn() werden sich wahrscheinlich Fehler bei längeren Impulsen zeigen, während diese bei pulsInLong() wahrscheinlich eher bei kürzeren Impulsen auftreten. Beide Funktionen können Impulse von 10 Mikrosekunden bis 3 Minuten Länge vermessen. pulsInLong() kann nur verwendet werden, wenn Interrupts aktiviert sind. Zeitfunktionen
Abgeleitet von den internen Timern können zeitabhängige Funktionen erstellt werden. Vereinfacht wird die Arbeit mit zeitabhängigen Größen durch die folgenden Funktionen: unsigned long millis()
unsigned long micros()
void delay(unsigned long ms)
void delayMicroseconds(unsigned int us)
Die ersten beiden Funktionen geben die Laufzeit des Programms seit Programmstart zurück. Die Funktion millis() gibt die Zeit in Millisekunden zurück. Ein Überlauf des Zahlenbereichs erfolgt nach ca. 50 Tagen. Die Funktion micros() hat ein identisches Verhalten bis auf das Format der Rückgabe. Hier wird die Laufzeit des Programms seit dem Programmstart in Mikrosekunden zurückgegeben. Der Bereichsüberlauf geschieht hier nach ca. 70 Minuten. Bei mit 16 MHz betriebenen Arduinos (Arduino Uno, Arduino Nano und anderen) beträgt die zeitliche Auflösung 4 µs – bei mit 8 MHz betriebenen Arduinos (z. B. LilyPad) beträgt sie entsprechend 8 µs. Die beiden Delay-Funktionen (Delay, dt. Verzögerung) halten das laufende Programm für eine in Millisekunden bzw. Mikrosekunden angegebene Zeit an, um nach Ablauf dieser Zeit das Programm weiterlaufen zu lassen. Während eines Delays werden die meisten Aktivitäten angehalten. Einige Hintergrundaktivitäten laufen aber weiter. Sie sollten bei komplexeren Programmen versuchen, Delays zu vermeiden. In den Programmbeispielen zeige ich Ihnen später eine einfache Möglichkeit, den Einsatz von Delays zu vermeiden. Bei einfachen Demoprogrammen und eingeschränkten Zeiten ist die Verwendung von Delays hingegen problemlos möglich.
Bei Arduino-Programmen, die mit einem Betriebssystem, wie FreeRTOS beim ESP32, betrieben werden, ist in die Delays die Funktion yield() eingebaut, die in einem Multitasking-System eine Task-Umschaltung bewirkt und so das Blockieren des Programms bzw. dessen Absturz verhindert. Zufallszahlen
Zufallszahlen sind in der Informatik zum Test von Algorithmen und zur Simulation sehr wichtig. Als Zufallszahlen werden Zahlen bezeichnet, die nicht als Ergebnis eines festgelegten Zusammenhangs (z. B. einer Funktion), sondern nach zufälligen Gesichtspunkten gebildet wurden. Physikalisch betrachtet, erzeugen beispielsweise Rauschquellen ein mehr oder minder zufälliges Signal, das nach einer AD-Umsetzung als Zufallszahl dienen kann. Im Allgemeinen geht man aber einen anderen Weg. Man benutzt sogenannte PseudoZufallszahlengeneratoren, die zwar nach einer festgelegten Vorschrift, aber dennoch scheinbar zufällig ihre Ergebnisse generieren. Für die Arbeit mit Zufallszahlen stehen die folgenden Funktionen zur Verfügung: long random(long max);
long random(long min, long max);
void randomSeed(unsigned long seed);
Die beiden Funktionen namens random() erzeugen eine Zufallszahl im Bereich von 0 bis max oder im Bereich von min bis max. Da es sich hier um Pseudo-Zufallszahlen handelt, ist die erzeugte Folge von Zufallszahlen nach einem Programmstart immer gleich. Das kann für die Reproduzierbarkeit von Tests von Vorteil sein, in der Regel ist es aber ein Nachteil wegen der nur bedingt vorhandenen Zufälligkeit. Die Funktion randomSeed() initialisiert den Pseudo-Zufallszahlengenerator und startet an einem beliebigen Punkt in seiner Zufallsfolge. Diese Sequenz ist zwar sehr lang und zufällig, aber immer gleich. Wird die Zufallsfolge an einem zufälligen Punkt gestartet, dann wird sich die erzeugte Zufallszahlenfolge auch unterscheiden. Wählt man beispielsweise die Spannung eines offenen Analogeingangs als Initialwert für randomSeed(), dann kommt man einer Zufallsfolge schon recht nahe. Bleibt der Eingang A0 beispielsweise unbeschaltet, dann kann die Funktion randomSeed(analogRead(A0));
die Initialisierung des Pseudo-Zufallszahlengenerators zufällig gestalten. Zur Demonstration der Erzeugung von Zufallszahlen schauen Sie in das Programmbeispiel random.ino. Wenn Sie dieses Programm mehrfach starten, dann sehen Sie eine Ausgabe auf dem seriellen Monitor, vergleichbar mit Abbildung 4.24.
Die Ausgabe eines Programmlaufs habe ich markiert. Bei jedem Programmlauf handelt es sich um eine feste Initialisierung von randomSeed() (hier willkürlich mit 0) sowie um eine zufällige Initialisierung durch die Abfrage eines offenen Analogeingangs (hier willkürlich A0). Im Screenshot können Sie sehen, dass die jeweils erste Ausgabe eines Programmlaufs eine identische Folge an Pseudo-Zufallszahlen ist, während die zweite Ausgabe kein Muster erkennen lässt und somit als (pseudo-)zufällig gelten kann.
Abbildung 4.24 Ausgaben des Programmbeispiels »random.ino«
Mathematische Funktionen
Die mathematischen Funktionen aus Tabelle 4.10 stehen für numerische Aufgaben zur Verfügung. Bei der Angabe des Datentyps any sind beliebige Datentypen möglich. Fehlt eine Typangabe, dann ist der Datentyp implementierungsabhängig bzw. controllerspezifisch. Aufgabe
Funktion
Keine Funktionen als Argumente
Berechnung des Betrags einer Integer-Zahl
int abs(int x)
x
Beschränkung einer Zahl auf einen Bereich
constrain(x, low, high)
x
Mapping (Zuordnung) einer Zahl zu einem Bereich
long map(long x, long in_min, long
Bestimmung des Maximums oder Minimums zweier Zahlen
max(x, y) min(x, y)
in_max, long out_min, long out_max) x
Aufgabe
Funktion
Berechnung der Potenz baseexponent
double pow(float base, float
Berechnung des Quadrats einer Zahl
double sq(any x)
Berechnung der Wurzel einer Zahl
any sqrt(any x)
Berechnung des Cosinus einer Zahl im Bogenmaß
double cos(float rad)
Berechnung des Sinus einer Zahl im Bogenmaß
double sin(float rad)
Berechnung des Tangens einer Zahl im Bogenmaß
double tan(float rad)
Keine Funktionen als Argumente
exponent) x
Tabelle 4.10 Mathematische Funktionen für die Arduino-Programmierung
Hinweis Bei einigen Funktionen sollte implementierungsbedingt auf Funktionen als Argument verzichtet werden, da dies zu falschen Ergebnissen führen kann.
Für die Umrechnung von Grad- und Bogenmaß können die in der Datei Arduino.h definierten Konstanten #define DEG_TO_RAD 0.017453292519943295769236907684886
#define RAD_TO_DEG 57.295779513082320876798154814105
verwendet werden. Die Datei Arduino.h finden Sie unter C:\Users\ \AppData\Local\Arduino15\packages\arduino\hardware\avr\1.8.2\cores\arduino oder auch im Repository. Zur Erläuterung der Verwendung der mathematischen Funktionen dient das Programmbeispiel math.ino, dessen Ausgaben in Abbildung 4.25 gezeigt sind. Die mathematischen Funktionen werden hier mit unterschiedlichen Argumenten aufgerufen. Die Unterschiede bestehen im Datentyp (integer, float etc.) und in den Zahlenwerten selbst. Hinweis
Es ist für Sie von großem Vorteil, wenn Sie jede dieser Ausgaben verstehen. Nur so vermeiden Sie Fehler bei der Anwendung der Funktionen.
Abbildung 4.25 Ausgaben des Programmbeispiels »math.ino«
Eine Erläuterung zur Funktion map() möchte ich Ihnen noch liefern, da diese Funktion gerade für die Anpassung von Zahlenbereichen (Messbereich von Sensoren, AD-Umsetzern und anderen) wichtig ist. Zur Erinnerung sehen Sie hier noch einmal die Definition der Funktion: long map(long x, long in_min, long in_max, long out_min, long out_max)
Die Argumente der Funktion in_min = –10, out_min = 0 sowie in_max = 10, out_max = 1000 sind Punkte auf einer Geraden, die durch folgende Gleichung beschrieben werden kann: y = mx + n = 50 x + 500 Abbildung 4.26 zeigt eine grafische Darstellung dieser Funktion.
Abbildung 4.26 Grafische Darstellung der Funktion »y = 50 x + 500«
Anhand der so definierten Gleichung werden nun die Funktionswerte der Funktion map(x, – 10, 10, 0, 1000) berechnet. Mit der Geradengleichung wird klar, dass der außerhalb des Bereichs liegende Wert –20 (kleiner als in_min) das Ergebnis –500 erzielen muss. Das Gleiche gilt für den ebenfalls außerhalb des Bereichs liegenden Wert 20 (größer als in_max), dem ein Wert von 1500 zugeordnet ist. Bits und Bytes
Zur Manipulation von Daten auf Bit- und Byte-Ebene stehen Ihnen die folgenden Funktionen zur Verfügung: Berechnung des Bitwertes für Werte n 0)
{
byte buffer[80];
if (len > 80) len = 80;
client.read(buffer, len);
if (printWebData) Serial.write(buffer, len); //show in the serial monitor
//(slows some boards)
byteCount = byteCount +len;
}
// if the server's disconnected, stop the client:
if (!client.connected())
{
endMicros = micros();
Serial.println();
Serial.println("disconnecting.");
client.stop();
Serial.print("Received "); Serial.print(byteCount);
Serial.print(" bytes in ");
float seconds = (float)(endMicros - beginMicros) / 1000000.0;
Serial.print(seconds, 4);
float rate = (float)byteCount / seconds / 1000.0;
Serial.print(", rate = "); Serial.print(rate);
Serial.print(" kbytes/second");
Serial.println();
// do nothing forevermore:
while (true) delay(1);
}
}
Listing 10.11 Quelltext UnoETH_WebClient.ino – loop()
Aus der Anzahl der heruntergeladenen Bytes und der gemessenen Zeit wird nun eine gesamte Übertragungsrate von ca. 58 KByte/s errechnet (siehe Abbildung 10.30).
Abbildung 10.30 Ausgabe des Programms »UnoETH_WebClient.ino«
10.7.2 WiFi WiFi-Kommunikation wird durch den Arduino Unio WiFi Rev2, die Arduinos MKR1000 WiFi bzw. MKR WiFi 1010 sowie die ESP8266/32basierten Mikrocontroller ermöglicht. Da unterschiedliche Module für die WiFi-Konnektivität verantwortlich sind, sind die betreffenden Programme auch controllerspezifisch. Arduino Uno WiFi Rev2
Ich arbeite gern mit dem Arduino Uno WiFi Rev2, weil er durch den ATmega4809 leistungsstärker ist als der Arduino Uno. Außerdem können die klassischen Shields eingesetzt werden. Er ist allerdings ein wenig teurer als die Arduinos der MKR-Serie. Mit dem Programm UnoWiFiR2_WebClient.ino zeige ich Ihnen, wie der über WiFi verbundene Arduino Uno WiFi Rev2 von einer Website Daten abfragt. Um einen Eindruck von der DownloadGeschwindigkeit zu bekommen, werden – wie im letzten Abschnitt – die Zahl der heruntergeladenen Bytes und die Zeit gemessen. Zu Beginn des ausschnittsweise erläuterten Programms werden die erforderlichen Librarys eingebunden. Der Arduino Uno WiFi Rev2 nutzt ein WiFi-Modul NINA-W132 von u-blox, das über SPI mit dem ATmega4809p verbunden ist. Deshalb sind die SPI-Library und die Bibliothek WiFiNINA notwendig: #include
#include
#include "arduino_secrets.h"
Die WLAN-Zugangsdaten sind in einen separaten Tab arduino_secrets.h ausgelagert: ///////please enter your sensitive data in the Secret tab/arduino_secrets.h
char ssid[] = SECRET_SSID; // your network SSID (name)
char pass[] = SECRET_PASS; // your network password
int keyIndex = 0; // your network key Index number (needed only for WEP)
int status = WL_IDLE_STATUS;
Bezüglich der Adressierung des Google-Servers gibt es keine Veränderungen: // if you don't want to use DNS (and // use the numeric IP instead of the //IPAddress server(74,125,232,128); char server[] = "www.google.com";
reduce your sketch size)
name for the server:
// numeric IP for Google (no DNS)
// name address for Google (using DNS)
Schließlich kann im Gegensatz zum vorangegangenen Programm eine WiFiClient-Instanz erzeugt werden, auf die sich alle weiteren
Aktionen beziehen: // Initialize the WiFi client library
// with the IP address and port of the server
// that you want to connect to (port 80 is default for HTTP):
WiFiClient client;
In der Funktion setup() wird das WiFi-Modul initialisiert und die Firmware-Version überprüft. Sollten Sie ein älteres Modul haben, kann ein Firmware-Update erforderlich sein: void setup()
{
…
// check for the WiFi module:
if (WiFi.status() == WL_NO_MODULE)
{
Serial.println("Communication with WiFi module failed!");
while (true); // don't continue
}
String fv = WiFi.firmwareVersion();
if (fv < WIFI_FIRMWARE_LATEST_VERSION)
Serial.println("Please upgrade the firmware");
Der Arduino nimmt anschließend Verbindung zum WLAN des Heimnetzwerkes auf. Die Zugangsdaten dazu waren im Tab arduino_secrets.h abgelegt: // attempt to connect to Wifi network:
Serial.print("Attempting to connect to SSID: ");
Serial.println(ssid);
while (status != WL_CONNECTED)
{
// Connect to WPA/WPA2 network.
// Change this line if using open or WEP network:
status = WiFi.begin(ssid, pass);
Serial.print(".");
delay(500);
}
printWifiStatus();
Ist die Verbindung zum WLAN erfolgt, dann kann der Verbindungsaufbau zum Server erfolgen – hier ist das wieder ein Server von Google (www.google.com). Sobald die Verbindung steht,
können der GET-Request https://www.google.com/search?q=arduino abgesetzt und die Zeiterfassung gestartet werden: Serial.println("\nStarting connection to server...");
// if you get a connection, report back via serial:
if (client.connect(server, 80))
{
Serial.println("connected to server");
// Make a HTTP request:
client.println("GET /search?q=arduino HTTP/1.1");
client.println("Host: www.google.com");
client.println("Connection: close");
client.println();
}
beginMicros = micros();
}
Die Funktion loop() unterscheidet sich nicht von der im vorangegangenen Programm. Aus der Anzahl der heruntergeladenen Bytes und der gemessenen Zeit kann nun wieder die Übertragungsrate (über alles) von ca. 50 KByte/s ermittelt werden (siehe Abbildung 10.31).
Abbildung 10.31 Ausgabe des Programms »UnoWiFiR2_WebClient.ino«
Raspberry Pi Pico mit ESP-01
In Abschnitt 2.4.3 hatte ich Ihnen das Expansionsboard Pi Pico Maker vorgestellt, bei dem die Internet-Konnektivität durch einen ESP-01 sichergestellt werden kann. Dem Raspberry Pi Pico
fehlte diese, was anfangs auch sehr stark als Argument gegen seinen Einsatz benutzt wurde. Seit dem Sommer 2022 gibt es mit dem Raspberry Pi Pico W nun auch einen WiFi-tauglichen Raspberry Pi Pico. Dennoch zeige ich Ihnen hier, wie einfach Sie mit einem ESP-01 fehlende WiFi-Konnektivität ergänzen können. Im eingesetzten ESP01 Modul sorgt ein Espressif ESP8266, der kleine Bruder des hier mehrfach verwendeten ESP32, für die erforderliche WiFiKonnektivität. Der ESP-01 wird hier gesteuert über AT-Kommandos als reiner Netzwerk-Controller (Serial-WiFi) eingesetzt. Abbildung 10.32 zeigt das kompakte Board mit den insgesamt acht Pins, die die Kontaktierung mit dem Pi-Pico-Maker-Board übernehmen. Die Antenne auf dem Board ist in der Regel vollkommen ausreichend, sodass keine weiteren Komponenten benötigt werden.
Abbildung 10.32 ESP-01
Den ESP-01 können Sie heute praktisch überall beziehen, wo Sie auch andere Arduino-Komponenten erhalten. Bei Aliexpress müssen Sie dafür gerade noch einen Euro spendieren, d. h., die Netzwerkanbindung mit einem ESP-01 fällt kostenmäßig kaum ins Gewicht. Ich habe zur Überwachung der Luftgüte eine M5Stack TVOC/eCO2 Unit sowie ein 0,96"-OLED zur Anzeige der Messwerte über zwei Grove-I2C-Ports mit dem Expansionsboard Pi Pico Maker verbunden und den ESP-01 im vorgesehenen Steckplatz kontaktiert. Eine NeoPixel-LED dient als Ampelanzeige für die unterschiedlichen eCO₂-Resultate. Den kompletten Aufbau zeigt Abbildung 10.33.
Abbildung 10.33 Messung der Luftgüte mit Raspberry Pi Pico
Auf die Details möchte ich hier nicht eingehen. Sie finden Sie auch in einem Beitrag der Zeitschrift Elektor[ 11 ]. Hier geht es in erster Linie um den durch den ESP-01 sichergestellten Internetzugang.
Aus dem Programmbeispiel RP2040_WiFi.ino möchte ich Ihnen deshalb hier nur die Teile vorstellen, die für den Internetzugang verantwortlich sind (Listing 10.12). Anpassungen müssen Sie in der Datei arduino_secrets.h für den WiFi-Zugriff (SSID, Password) vornehmen sowie den Write Token für die Visualisierung mit ThingSpeak hinterlegen. Sie benötigen dafür eine Registrierung bei ThingSpeak. Die im Programmbeispiel verwendete Library WiFiEsp ermöglicht jedem mit einem ESP8266 Board, wie beispielsweise dem ESP-01, ausgestatteten Arduino eine Verbindung zum Internet. Es kann entweder als Server dienen, der eingehende Verbindungen akzeptiert, oder als Client, der ausgehende Verbindungen herstellt. Die WiFiEsp-Library ist den Arduino WiFi- und EthernetBibliotheken sehr ähnlich, und viele der Funktionsaufrufe sind gleich. Die WiFiEsp-Library weist die folgenden Merkmale auf: APIs, die mit der Standard-Arduino-WLAN-Bibliothek kompatibel sind Verwendung von AT-Befehlen der Standard-ESP-Firmware (keine Notwendigkeit, eine benutzerdefinierte Firmware zu flashen) Unterstützt serielle Hardware- und Software-Ports /*
* File: RP2040_WiFi.ino
*
* Measuring air condition by Sensirion SGP30 and RP2040.
* ESP-01 connected to hardware UART for WiFi connection to Thingspe/arduino-pico
* needs several Adafruit libraries and https://github.com/bportaluri/WiFiEsp/, too.
*
* 2021-05-17 [email protected]
*/
#include
#include
#include
#include
#include
#include
#include
#include "arduino_secrets.h"
…
// Initialize the Ethernet client object
WiFiEspClient client;
void setup()
{
Serial.begin(115200);
…
// Serial1 for ESP-01 connection
Serial1.setRX(17);
Serial1.setTX(16);
Serial1.begin(115200);
WiFi.init(&Serial1);
// check for the presence of the ESP-01
if (WiFi.status() == WL_NO_SHIELD)
{
Serial.println("ESP-01 shield not present");
while (1); // Don't proceed, loop forever
}
// attempt to connect to WiFi network
while ( status != WL_CONNECTED)
{
Serial.print("Attempting to connect to WPA SSID: ");
Serial.println(ssid);
status = WiFi.begin(ssid, pass); }
// you're connected now, so print out the data
Serial.println("You're connected to the network");
printWifiStatus();
Serial.println(F("Initialization finished."));
}
void loop()
{
…
// if there's incoming data send it out the serial port
// this is for debugging purposes only
while (client.available())
{
char c = client.read();
Serial.write(c);
}
if (millis() > now +PERIODE)
{
now = millis();
sendMessage();
}
else delay(5000);
}
Listing 10.12 Quelltext RP2040_WiFi.ino – Auszug
Wenn Sie sich andere Programme anschauen, die einen Internetzugriff implementieren, dann werden Sie kaum Unterschiede zur hier gezeigten Vorgehensweise erkennen. Das macht den Wert der verwendeten WiFiEsp-Library aus. Die Funktionen printWiFiStatus() und sendMessage() habe ich in einen separaten Tab ausgelagert, zeige sie hier aber vollständig (Listing 10.13). void printWifiStatus()
{
// print the SSID of the network you're attached to
Serial.print("SSID: ");
Serial.println(WiFi.SSID());
// print your WiFi shield's IP address
IPAddress ip = WiFi.localIP();
Serial.print("IP Address: ");
Serial.println(ip);
// print the received signal strength
long rssi = WiFi.RSSI();
Serial.print("Signal strength (RSSI):");
Serial.print(rssi);
Serial.println(" dBm");
}
void sendMessage()
{
// close any connection before send a new request
// this will free the socket on the WiFi shield
client.stop();
Serial.println("Starting connection to server...");
// if you get a connection, report back via serial
if (client.connect(server, 80))
{
Serial.println("Connecting...");
// Make a HTTP request
client.println("GET /update?api_key=" +api_key +"&field1=" +String(TVOC) + "&field2=" +String(eCO2) +" HTTP/1.1");
client.println("Host: api.thingspeak.com");
client.println("Connection: close");
client.println();
}
// if there are incoming bytes available
// from the server, read them and print them
while (client.available())
{
char c = client.read();
Serial.write(c);
}
// if the server's disconnected, stop the client
if (!client.connected())
{
Serial.println();
Serial.println("Disconnecting from server...");
client.stop();
}
}
Listing 10.13 Quelltext RP2040_WiFi.ino – printWifiStatus(), sendMessage()
Auch in diesem Programmteil werden Sie zu den Standard-Librarys für den Internetzugang identische Instruktionen erkennen. Gönnen Sie sich einen Blick in die Library selbst, dann erkennen Sie die Vorteile der Kapselung der AT-Kommandos in der Datei https://github.com/bportaluri/WiFiEsp/blob/master/src/utility/EspDr v.cpp. Der Arduino Nano RP2040 Connect ist mit einem NINA-W102-00BModul von u‐blox ausgestattet und kann deshalb ohne zusätzliche Komponenten mit dem Internet Kontakt aufnehmen. Ich habe den Zugriff mit dem in Listing 10.14 gezeigten Programmbeispiel RP2040_Connect_WebClient.ino getestet. /*
* RP2040_Connect_WebClient.ino
*
* This sketch connects to my website (http://ckuehnel.ch)
* using the WiFi module.
* This example is written for a network using WPA encryption. For
* WEP or WPA, change the Wifi.begin() call accordingly.
*
* Circuit: Arduino Nano RP2040 Connect
*
* based on WiFiWebClient.ino by Tom Igoe
*
* 2022-01-28 [email protected]
*/
#include
#include
#include "arduino_secrets.h"
int status = WL_IDLE_STATUS;
char server[] = "www.ckuehnel.ch";
// Initialize the Ethernet client library
// with the IP address and port of the server
// that you want to connect to (port 80 is default for HTTP):
WiFiClient client;
void setup()
{
Serial.begin(9600);
delay(2000); // wait for serial monitor
Serial.println("Arduino Nano RP2040 Connect WebClient");
if (WiFi.status() == WL_NO_MODULE)
{
Serial.println("Communication with WiFi module failed!");
while (true); // don't continue
}
String fv = WiFi.firmwareVersion();
Serial.print("Actual Firmware Version: ");
Serial.println(fv);
Serial.print("Latest Firmware Version: ");
Serial.println(WIFI_FIRMWARE_LATEST_VERSION);
if (fv < WIFI_FIRMWARE_LATEST_VERSION)
Serial.println("Please upgrade the firmware");
while (status != WL_CONNECTED)
{
Serial.print("Attempting to connect to SSID: ");
Serial.println(SSID);
status = WiFi.begin(SSID, PASS);
delay(10000);
}
Serial.println("Connected to wifi");
printWifiStatus();
Serial.println("\nStarting connection to server...");
if (client.connect(server, 80))
{
Serial.println("connected to server");
// Make a HTTP GET request:
client.println("GET /text.txt HTTP/1.1");
client.prw.ckuehnel.ch");
client.println("Connection: close");
client.println();
}
}
void loop()
{
// if there are incoming bytes available
// from the server, read them and print them:
while (client.available())
{
char c = client.read();
Serial.write(c);
}
// if the server's disconnected, stop the client:
if (!client.connected())
{
Serial.println();
Serial.println("disconnecting from server.");
client.stop();
// do nothing forevermore:
while (true);
}
}
void printWifiStatus()
{
Serial.print("SSID: ");
Serial.println(WiFi.SSID());
IPAddress ip = WiFi.localIP();
Serial.print("IP Address: ");
Serial.println(ip);
long rssi = WiFi.RSSI();
Serial.print("signal strength (RSSI):");
Serial.print(rssi);
Serial.println(" dBm");
}
Listing 10.14 Quelltext RP2040_Connect_WebClient.ino
Wichtig im Programmbeispiel hier ist das Einbinden der Library WiFiNINA, die ihrerseits der SPI-Library bedarf, die für die Kommunikation von RP2040 und NINA-Modul über SPI erforderlich ist. Bevor das Programmbeispiel auf den Arduino Nano RP2040 Connect geladen wird, empfiehlt sich ein Update der WiFiNINAFirmware. Hierzu gibt es im Menü Tools den WiFi101/WiFiNINA Firmware/Certificates Updater, der im ersten Schritt auf das Board geladen wird. Dann erfolgt gemäß Abbildung 10.34 ein Update der Firmware und der SSL Root Certificates.
Abbildung 10.34 Update der WiFiNINA Firmware und der SSL Root Certicicates
Nach erfolgtem Update kann das Programmbeispiel RP2040_Connect_WebClient.ino auf das Board geladen und anschließend gestartet werden. Den Serial Output nach Programmstart zeigt Abbildung 10.35.
Abbildung 10.35 Serial Output Programm RP2040_Connect_WebClient.ino
Nach dem Firmware-Update war bei mir die Firmware Version 1.4.5 installiert, obwohl offenbar 1.4.8 bereits als »latest« deklariert wurde. Eine Version 1.4.8 stand aber beim Firmware-Update nicht zur Verfügung. Das Programmbeispiel verbindet sich jedoch mit dem Server, liest erwartungsgemäß die Datei text.txt und zeigt deren Inhalt »Das ist ein Textfile mit Text und Ziffern.« im Serial Monitor.
10.7.3 Die Performance testen Für die beiden vorgestellten Webclients hatte ich die Downloadzeiten für einen Zugriff auf den Google-Server gemessen. Es ist nicht verwunderlich, dass die beiden ermittelten Zeiten nicht sehr unterschiedlich sind. Neben der Netzwerkanbindung, die für Ethernet und WiFi unterschiedlich erwartet wird, gibt es beim
Zugriff auf das Internet weitere Punkte, die die Performance begrenzen. Für die folgenden Untersuchungen bin ich von einer Testumgebung wie in Abbildung 10.36 ausgegangen.
Abbildung 10.36 Arduinos im Heimnetzwerk
Mit Ping habe ich die Verbindung von meinem Entwicklungs-PC zu den beiden Arduinos getestet. Ping sendet im Hintergrund fünf Datenpakete an den zu testenden Netzwerk-Teilnehmer, also an einen der beiden Arduinos, und misst, wie lange das Zurückschicken dieser Pakete dauert. Hieraus wird der Mittelwert gebildet. Je niedriger der Ping-Wert ist, desto besser. Dem Arduino Uno mit Ethernet-Shield war die IPAdresse 192.168.1.199 zugewiesen, dem Arduino Uno WiFi Rev2 die IP-Adresse 192.168.1.195 und dem Arduino Nano RP2040 Connect die IP-Adresse 192.168.1.191. Mit diesen IP-Adressen können Sie dann Ping auf dem PC ausführen: C:\>ping 192.168.1.199 bzw. C:\>ping 192.168.1.195 C:\>ping 192.168.1.191
Um den Durchsatz von Netzwerken zu messen, empfiehlt sich die Verwendung des Open-Source-Tools iPerf. Sie können iPerf von der Website https://iperf.fr/ herunterladen und auf Ihrem PC installieren. Auf den Arduinos muss ein iPerf-Server installiert werden, mit dem der iPerf-Client auf dem PC Daten austauscht. Unter https://www.instructables.com/id/How-to-measure-Arduinonetwork-performance/ finden Sie eine iPerf-Implementierung für ein Ethernet-Shield, das ich an den Arduino Uni WiFi Rev2 angepasst habe. Für den Performancetest mit iPerf stehen nun die Programme UnoETH_iPerfServer.ino und UnoWiFiR2_iPerfServer.ino zur Verfügung. Der iPerf-Client wird auf dem PC mit den Parametern gestartet, die ich an den doch etwas schwachen Mikrocontroller angepasst habe: C:\>iperf -c 192.168.1.199 -t 30 -i 10 -w 10k bzw. C:\>iperf -c 192.168.1.195 -t 30 -i 10 -w 10k
Tabelle 10.7 zeigt Ihnen die Ergebnisse der beiden Tests zusammengefasst. Test/Board
Arduino Uno und Ethernet-Shield
Arduino Uno WiFi Rev2
Ping
='0' && Buf[i+j]='a' && Buf[i+j]='A' && Buf[i+j] Periode)
{
previousMillis = millis();
char text[] = "Count: ";
dtostrf(count++, 8, 0, buffer);
strcat (text, buffer);
Serial.print("Send message...\t");
Serial.println(text);
digitalWrite(LED_BUILTIN, HIGH); delay(500);
radio.write(&text, strlen(text));
digitalWrite(LED_BUILTIN, LOW);
}
}
Listing 10.29 Quelltext Nano_nRF24L01_Tx.ino
Nach dem Laden der verwendeten Librarys kann mit radio eine Instanz der Klasse RF24 erzeugt werden. Die Anschlüsse der Steuerleitungen CE und CSN sind als Argumente zu übergeben. Da die Hardware-SPI verwendet wird, sind zum SPI keine weiteren Angaben erforderlich. Im Array address[6] können die Adressen der sechs Pipes abgelegt werden. Hier wird nur eine Adresse benötigt. Der Funkkanal wird als Konstante channel deklariert und mit 4 initialisiert. Die Konstante Periode bestimmt die Senderate, die hier auf 5 Sekunden eingestellt ist. Da ich hier auf die Verwendung von delay() (außerhalb von setup()) verzichten möchte, braucht es die Variable previousMillis. Es folgen noch die Deklaration der Variable count und eines
Zwischenspeichers buffer[10] für die Umwandlung einer Zahl in einen String. In der Funktion setup() kann nach Initialisierung der seriellen Schnittstelle und der Konfiguration des LED-Ausgangs ( LED_BUILTIN) die Initialisierung des nRF24L01 erfolgen. Nach der DefaultInitialisierung durch radio.begin() erfolgen die Änderungen für den Funkkanal (radio.setChannel(channel)) und die TransmitDatenrate (radio.setDataRate(RF24_250KBPS)). Daran anschließend kann der Empfangsmode durch radio.stopListening() beendet und der Sendekanal durch radio.openWritingPipe(address) geöffnet werden. Damit ist die Initialisierung abgeschlossen und der Transmitter signalisiert seine Betriebsbereitschaft durch die Ausgabe »Ready to transmit messages on channel 4«. In der Funktion loop() wird nun alle fünf Sekunden (definiert durch die Konstante Periode) die Variable count inkrementiert und in einen String »Count:xxxxxxxx« gepackt, der über die serielle Schnittstelle und mit radio.write(&text, strlen(text)) an den nRF24L01 und damit in den Funkkanal geschrieben wird. Abbildung 10.93 zeigt die Ausgaben des Programms Nano_nRF24L01_Tx.ino im Transmitter.
Abbildung 10.93 Ausgabe Programm Nano_nRF24L01_Tx.ino
Der identisch aufgebaute Receiver soll nun in die Lage versetzt werden, das ausgesendete Signal zu empfangen. Das in Listing 10.30 gezeigte Programm Nano_nRF24L01_Rx.ino ist im Initialisierungsteil nahezu identisch zum Transmitter-Programm. /*
* File: Nano_nRF24L01_Rx.ino
* nRF24L01 Peer-to-Peer Test
* based on Arduino Wireless Communication Tutorial
* by Dejan Nedelkovski, www.HowToMechatronics.com
* Used Library: TMRh20/RF24, https://github.com/tmrh20/RF24/
*/
#include
#include
#include
RF24 radio(7, 8); // CE, CSN
const byte address[6] = "00001";
const byte channel = 4;
void setup()
{
Serial.begin(115200);
delay(1000); // wait for Serial Monitor
Serial.print("Initializing Radio...");
radio.begin();
radio.setChannel(channel);
radio.setDataRate(RF24_250KBPS); // low data rate for higher range
radio.openReadingPipe(1, address);
radio.startListening();
Serial.println("done.");
Serial.print("Ready to receive messages on channel ");
Serial.println(radio.getChannel());
}
void loop()
{
if (radio.available())
{
char text[32] = ""; // max payload
radio.read(&text, sizeof(text));
Serial.print(text);
bool goodSignal = radio.testRPD();
Serial.println(goodSignal ? "\t\tStrong signal > 64dBm" : "\t\tWeak signal < 64dBm" );
radio.read(0,0);
}
}
Listing 10.30 Quelltext Nano_nRF24L01_Rx.ino
Benötigt werden hier aber nur die beiden Konstanten address[6] und channel. In der Funktion setup() ist die Initialisierung des nRF24L01 praktisch auch identisch, nur dass hier durch radio.openReadingPipe(1, address) der Empfangskanal geöffnet und durch radio.startListening() in den Empfangsmode geschaltet wird. Damit ist auch hier die Initialisierung abgeschlossen, und der Receiver signalisiert seine Betriebsbereitschaft durch die Ausgabe »Ready to receive messages on channel 4«. In der Funktion loop() wird zuerst getestet, ob Daten empfangen wurden (radio.available()). Sind Daten vorhanden, dann werden diese durch die Anweisung radio.read(&text, sizeof(text)) im Array text[] gespeichert und seriell ausgegeben. Über die Abfrage des Repeat Power Detector Bits RPD kann die Stärke des Empfangssignals klassifiziert werden. Beträgt diese mehr als –64 dBm, dann ist dieses Bit 1, anderenfalls 0. Diese Abfrage passiert durch die Funktion radio.testRPD(), und anschließend erfolgt die betreffende serielle Ausgabe, gefolgt vom Abschluss des Auslesens der empfangenen Daten (radio.read(0,0)). Abbildung 10.94 zeigt die Ausgaben des Programms Nano_nRF24L01_Rx.ino im Receiver. Bewegt man den Transmitter auf den Receiver zu, dann ändert sich die Ausgabe zur Signalstärke im Serial Monitor.
Abbildung 10.94 Ausgabe Programm Nano_nRF24L01_Rx.ino
10.11.8 Datenübertragung zwischen mehreren Sensorknoten Mit dem nRF214L01 lassen sich aber nicht nur Peer-to-PeerVerbindungen, sondern ganze Netzwerke aufbauen.
Abbildung 10.95 nRF214L01-Sensornetzwerk
Abbildung 10.95 zeigt das nun betrachtete Sensornetzwerk. Das Gateway ist hier bereits vorgesehen, hat aber noch keine Verbindung ins Internet. Die Sensoren 01 und 02 sind direkt mit dem Gateway verbunden, währen die Sensoren 013 und 023 über den Repeater 03 mit dem Gateway verbunden werden.
Die Library RF24Network unterstützt nRF24L01-Netzwerke und kann über die weiter oben angegebene URL von GitHub oder über den Library Manager der Arduino IDE geladen werden. Auf der Website howtomechatronics.com finden Sie ein ausgezeichnetes Tutorial, das nRF24L01-Netzerke auf Basis der verwendeten Librarys beschreibt. Die Programmbeispiele zeigen die Verwendung der RF24Network-Library und können als Vorlage für eigene Netzwerk-Implementierungen dienen: https://howtomechatronics.com/tutorials/arduino/how-to-build-anarduino-wireless-network-with-multiple-nrf24l01-modules/ Die Nummerierung der in Abbildung 10.95 gezeigten Netzwerkknoten ist nicht willkürlich, sondern folgt den durch die Library gegebenen Bedingungen. Die durch die Library gebildete Netzwerkschicht nutzt die Fähigkeit des nRF24L01, bis zu sechs andere Netzwerkknoten gleichzeitig zu hören. Das Netzwerk folgt einer Baumstruktur (Tree Topology), in der ein Knoten die Basis darstellt, dem alle anderen Netzwerkknoten untergeordnet sind. Jedem Knoten muss eine 15-Bit-Adresse zugewiesen werden. Diese Adresse beschreibt genau die Position des Knotens innerhalb des Baumes. Die Adresse ist eine Oktalzahl. Jede Ziffer in der Adresse repräsentiert eine Position im Baum weiter von der Basis entfernt. Damit bildet sich die folgende Adressierung, die Sie mit Abbildung 10.95 vergleichen können. Knoten 00 ist der Basisknoten, der hier als Basis oder Gateway bezeichnet wird. Die Knoten 01 bis 03 sind Knoten, die dem Basisknoten untergeordnet, also dessen Kinder (Child) sind.
Knoten 013 und 023 sind die Kinder von Knoten 03. Das könnte nahezu beliebig fortgeführt werden. Die größte Knotenadresse lautet 05555, sodass bis zu 781 Knoten auf einem einzelnen Kanal zulässig sind. Tabelle 10.12 zeigt die Baumstruktur des hier betrachteten Netzwerkes. Beim Versenden einer Nachricht mit RF24Network::write(), wird in den RF24NetworkHeader u. a. die logischen Knotenadressen eingetragen. Die Netzwerkschicht ermittelt den richtigen Pfad, um den Zielknoten (header.to_node) zu finden, und sendet die Nachricht durch das Netzwerk bis zum vorgegebenen Zielknoten. Das funktioniert auch dann, wenn die beiden Knoten weit voneinander entfernt sind, da die Nachricht an den Basisknoten und dann wieder an das endgültige Ziel gesendet wird. In der oben gezeigten Netzwerkstruktur ist beispielsweise das Versenden einer Nachricht von Knoten 013 an Knoten 02 kein Problem. Master Node (00) 1st level children of master (00) 2nd level children of master. Children of 1st level.|
00 01 02
03 013 023
Tabelle 10.12 Baumstruktur des Netzwerkes
Das geschilderte Routing wird im Hintergrund durch die Methode RF24Network::update() erledigt, ohne dass der Anwender involviert ist. Bedingung ist ein regelmäßiger Aufruf der Methode, da sonst Nachrichten im Netzwerk verloren gehen können. Der bereits erwähnte RFNetworkHeader hat die in Tabelle 10.13 gezeigte Struktur:
RF24NetworkHeader uint16_t
uint16_t uint16_t unsigned char
from_node to_node id
type
unsigned char
static uint16_t
reserved
next_id
Tabelle 10.13 RF24NetworkHeader
Die beiden Adressen from_node und to_node bezeichnen die Ausgangs- und die Zieladresse der zu versendenden Nachricht. Der Nachricht wird eine fortlaufend inkrementierte Identifikationsnummer id mitgegeben, die zur Detektion von vermissten Nachrichten herangezogen werden kann. Zusätzlich kann der Nachricht ein Typ zugeordnet werden, wobei type von 1 bis 64 kein Acknowledge durch das Netzwerk erhalten, 65 bis 127 hingegen schon. Die types von 0 bis 127 sind für den Anwender frei (user-defined). Das folgende Byte ist für Systemanwendungen reserviert und die letzte ID ist derzeit ungenutzt. Mit diesem Wissen ist es möglich, ein nRF24L01-Netzwerk aufzubauen. Ich werde die einzelnen Netzwerkknoten hier abschnittsweise beschreiben. Gateway 00
Gateway 00 bezeichnet den Basisknoten des Netzwerkes. Ich werde hier noch keine Gateway-Funktionalität implementieren. Mit dem Wissen, das Sie bereits über Internet-Kommunikation erworben haben, können Sie beispielsweise einen Web- oder MQTT-Client zum Versand der Daten implementieren. Mit einem ESP8266-basierten NodeMCU stehen genügend Ressourcen für beide Aufgaben zur Verfügung. Bei Verwendung der
SPI-Schnittstelle und der beiden Steuerleitungen CE und CSN ergibt sich die in Abbildung 10.96 gezeigte Schaltung für den Basisknoten.
Abbildung 10.96 Basisknoten mit NodeMCU
Für den Aufbau habe ich ein Breadboard verwendet, da mir kein Grove Base Shield for NodeMCU zur Verfügung stand (Abbildung 10.97).
Abbildung 10.97 Aufbau Basisknoten mit NodeMCU und nRF24L01+PA+LNA
Durch die Verwendung der RF24Network-Library gestaltet sich der Quelltext für den Basisknoten sehr übersichtlich (Listing 10.31). Ich habe im folgenden ausschnittsweise gezeigten Listing die neuen Anweisungen fett markiert und beschränke mich bei der Beschreibung deshalb im Wesentlichen auf diese. #include
#include
#include
RF24 radio(D1, D2); // nRF24L01 (CE,CSN)
RF24Network network(radio); // Include the radio in the network
const uint16_t this_node = 00; // Address of this node in Octal format
const uint16_t node01 = 01; // Address of the other nodes in Octal format
const uint16_t node02 = 02;
const uint16_t node03 = 03;
const uint16_t node013 = 013;
const uint16_t node023 = 023;
const uint8_t ch = 4; // Used channel number
void setup()
{
Serial.begin(115200);
delay(1000); // wait for Serial Monitor
Serial.print("\nInitializing Radio...");
SPI.begin();
radio.begin();
radio.setChannel(ch); // set channel
radio.setDataRate(RF24_250KBPS); // low data rate for higher range
network.begin(ch, this_node); //(channel, node address)
pinMode(LED_BUILTIN, OUTPUT);
digitalWrite(LED_BUILTIN, HIGH);
Serial.println("done.");
Serial.print("Ready to receive messages on channel ");
Serial.println(radio.getChannel());
}
void loop()
{
network.update();
//===== Receiving =====//
while ( network.available() ) // Is there any incoming data?
{
RF24NetworkHeader header;
unsigned long incomingData;
// Read the incoming data
network.read(header, &incomingData, sizeof(incomingData));
if (header.from_node == node01)
{ // If data comes from Node 01
Serial.print("Received from Node 01: "); Serial.println(incomingData);
}
{
if (header.from_node == node02)
// If data comes from Node 02
Serial.print("Received from Node 02: "); Seri-al.println(incomingData);
}
…
}
}
Listing 10.31 Quelltext NodeMCU_nRF24L01_Base00.ino – Auszug
Da im Basisknoten mit einem NodeMCU-Mikrocontroller gearbeitet wird, ändern sich die Anschlussbezeichnungen für die Leitungen CE und CSN bei der Instanziierung der Klasse RF24 (RF24 radio(D1, D2)). Durch RF24Network network(radio) wird radio nun ins Netzwerk eingebunden. Mit der Anweisung network.begin(ch, this_node) wird dem Netzwerkknoten seine Adresse mitgeteilt. Wird im Netzwerk mit dem gesetzten Kanal gearbeitet, dann kann das Kanal-Argument auch weggelassen werden. Zu Beginn der Endlosschleife loop() erfolgt der Aufruf zum Update des Netzwerkes network.update() und mit network.available() die Abfrage nach empfangenen Daten. Sind Daten vorhanden, dann werden durch RF24NetworkHeader header und unsigned long incomingData entsprechende Speicherbereiche zur Aufnahme der Daten deklariert und diese dann mit der Funktion network.read(header, &incomingData, sizeof(incomingData)) gelesen und abgespeichert. Im folgenden Abschnitt wird durch die Anweisung if (header.from_node == 01) der Ursprungsknoten der Nachricht ermittelt und die Nachricht (das ist hier der Inhalt der betreffenden Count-Variablen) am Serial Monitor ausgegeben. So wird mit jedem Ausgangsknoten verfahren.
Sensorknoten
Alle Netzwerkknoten, die dem Basisknoten untergeordnet sind, weisen die gleiche Hardware auf. Ich habe diese in Abschnitt 10.11.5 beschrieben und mit Abbildung 10.91 auch bildlich dargestellt. Die Programme der einzelnen Knoten sind nach folgender Nomenklatur bezeichnet: Nano_nRF24L01_.ino Da sie weitgehend identisch sind, gehe ich vor allem auf die Unterschiede ein. Sensorknoten 01 und 02
Sensorknoten 01 und 02 (Node 01 und 02) sind Kinder des Basisknotens. Der Quelltext für Node 01 ist in Listing 10.32 gezeigt. Die Anweisungen, die Sie besonders beachten müssen, habe ich wieder markiert. #include
#include
#include
RF24 radio(10, 9); // nRF24L01 (CE,CSN)
RF24Network network(radio); // Include the radio in the network
const uint16_t this_node = 01; // Address of our node in Octal format
const uint16_t master00 = 00; // Address of the other node in Octal format
const byte channel = 4;
const unsigned long interval = 1000; // How often to send data to the other unit
unsigned long last_sent; // When did we last send?
unsigned long count = 0;
void setup()
{
…
}
void loop()
{
network.update();
//===== Sending =====//
unsigned long now = millis();
if (now - last_sent >= interval) // If it's time to send a data, send it!
{
last_sent = now;
Serial.print("Transmit "); Serial.print(count);
Serial.println(" to Base 00");
RF24NetworkHeader header(master00); // (Address where the data is going)
bool ok = network.write(header, &count, sizeof(count)); // Send the data
if (!ok) Serial.println("Transmission failed");
count++;
}
}
Listing 10.32 Quelltext Nano_nRF24L01_01.ino – Auszug
Im Vereinbarungsteil werden mit this_node = 01 und master00 = 00 die Adressen für Ausgangs- und Zielknoten als Konstanten vereinbart. Das ganze Netzwerk arbeitet auf dem Funkkanal 4, was in der Konstante channel definiert ist. Die Konstante interval = 1000 gibt an, wie oft Daten zum Zielknoten gesendete werden sollen. Die Zeitangabe erfolgt in Millisekunden. Mit Count ist die Zählervariable vereinbart, die den zu übertragenden Messwert eines Sensors simuliert. Im Initialisierungsteil gibt es keine Veränderungen. Diese sind auf die Funktion loop() beschränkt. Wichtig ist hier zu Beginn der Aufruf des Netzwerkupdates. Dann kann nach Ablauf der vereinbarten Intervallzeit die Nachricht aufgebaut und versendet werden. Dem Header wird durch RF24NetworkHeader header(master00) die Zieladresse mitgeteilt, und durch die Anweisung network.write(header, &count, size-of(count)) werden Header und der Inhalt der Counter-Variablen zum Basisknoten gesendet. Ist der Sendevorgang nicht erfolgreich, erfolgt eine Fehlerausschrift. Anschließend wird count inkrementiert. → Sensor 01 sendet also jede Sekunde eine Nachricht an den Basisknoten
Da beim Sensor 02 der Messwert wiederum durch einen Counter simuliert wird, ändern sich im Programm Nano_nRF24L01_02.ino nur die Ausgangsadresse und ggf. das Sendeintervall. Die folgenden Codezeilen haben sich verändert: const uint16_t this_node = 02; // Address of our node in Octal format
const unsigned long interval = 5000; // How often to send data to the other unit
→ Sensor 02 sendet also jede fünfte Sekunde eine Nachricht an den Basisknoten. Repeater 03
Beim Repeater 03 fehlt die Sensoraktivität, weshalb nur die Angabe der Ausgangsadresse angepasst werden müsste. Dennoch sende ich wieder den Inhalt der Countvariablen an den Master, um zumindest für die Inbetriebnahme ein Lebenszeichen im Gateway vorzufinden. const uint16_t this_node = 03; // Address of our node in Octal format
const unsigned long interval = 10000; // How often to send data to the other unit
In der Funktion loop() würde ohne den Sendevorgang ausschließlich die Methode network.update() aufgerufen. → Repeater 03 sendet also jede zehnte Sekunde eine Nachricht an den Basisknoten Sensorknoten 013 und 023
Die Sensorknoten 013 und 023 simulieren wieder einen Messwert durch einen Counter und entsprechen damit Sensorknoten 01 bzw. 02. Geändert habe ich deshalb gegenüber den Sensoren 01 bzw. 02 nur die Ausgangsadressen und das Sendeintervall. Die folgenden Codezeilen haben sich verändert:
Für Sensor 013: const uint16_t this_node = 013; // Address of our node in Octal format
const unsigned long interval = 2000; // How often data is send to the other unit
Für Sensor 023: const uint16_t this_node = 023; // Address of our node in Octal format
const unsigned long interval = 12000; // How often data is send to the other unit
→ Sensor 013 sendet also jede zweite und Sensor 023 jede zwölfte Sekunde eine Nachricht an den Basisknoten. Nachrichten der Sensorknoten im Gateway
Nach dem nun alle Netzwerkknoten mit ihrer entsprechenden Software ausgestattet sind, kann das Netzwerk Schritt für Schritt in Betrieb genommen werden. Ich überspringe hier die einzelnen Schritte und zeige Ihnen das Endergebnis im Serial Monitor (Abbildung 10.98). Als Orientierung für den zeitlichen Ablauf können Sie die von Node 01 im Sekundentakt versendeten Nachrichten verwenden. Die einzelnen Zykluszeiten der Sensorknoten sind in Abbildung 10.98 vermerkt.
Abbildung 10.98 Nachrichten der Sensorknoten im Gateway
Wie Abbildung 10.98 zeigt, werden die Nachrichten der einzelnen Sensorknoten im Gateway empfangen und stehen damit auch für eine Weiterverarbeitung zur Verfügung. Hat das Gateway einen Internetzugang, dann können die Daten extern weiterverarbeitet oder visualisiert werden.
11 Datenformate und Kommunikationsprotokolle Daten sind eigentlich nur dann interessant, wenn sie ausgetauscht und ausgewertet werden können. Je besser diese Vorgänge standardisiert und strukturiert sind, desto einfacher ist die Verarbeitung. In diesem Kapitel stelle ich Ihnen beispielhaft das JSONDatenformat und das MQTT-Kommunikationsprotokoll vor. Beide spielen vor allem beim Zugriff auf bzw. über das Internet eine wichtige Rolle. Ich werde beide in Programmen noch einsetzen, sodass Sie hier erste Grundlagen dazu finden.
11.1 JSON JSON steht für JavaScript Object Notation und ist ein Textformat für den Austausch von Daten zwischen Anwendungen. JSON ist das beliebteste Austauschformat, denn es ist gut lesbar, einfach, schnell und erzeugt nur wenig Overhead. Ein JSON-Objekt ist eine Sammlung von Schlüssel-Wert-Paaren (Key Value Pairs). JSON-Schlüssel sind Strings in doppelten Hochkommas. Links steht der Schlüssel, rechts der Wert. Wie sich JSON zur Formatierung von Sensorausgaben einsetzen lässt, zeigt die folgende JSON-Ausgabe:
{
"sensor1": { "temperature" : 22.2 , "humdity" : 66 , "pressure" : 999 },
"sensor2": { "temperature" : 22.2 , "humdity" : 66 },
"sensor3": { "position" : [8.8172433, 47.1979687]}
}
Mit ArduinoJson steht eine Arduino-Library von Benoît Blanchon zur Verfügung, die die Arbeit mit JSON sehr effektiv unterstützt (https://github.com/bblanchon/ArduinoJson). Das in Listing 11.1 gezeigte Programmbeispiel Uno_JsonOutputv6.ino erzeugt den oben angegebenen JSON-Output für die (hier fiktiven) Sensoren BME280, DHT11 und NEO6M GPS. Die ArduinoJson-Library ist das eigentliche Tool. Im Programm wird die Nutzung der Library gezeigt. Der ArduinoJson Assistant (https://arduinojson.org/v6/assistant/) hilft, die Größe des JSON-Buffers festzulegen, und bietet Unterstützung bei der Anwendung von ArduinoJson. Aktuell liegt ArduinoJson in der Version v6 vor. Achten Sie unbedingt auf die Version, denn es sind noch viele Programme im Umlauf, die die veraltete Version v5 nutzen. Kompatibilität ist dann nicht gegeben! Nach dem Einbinden der ArduinoJson-Library werden hier noch einige Ausgaben zu Programmnamen, zum Kompilierzeitpunkt und zu den eingesetzten Versionen der Arduino IDE und der ArduinoJson-Library gemacht. Die Ausgabe dieser Informationen kann (in jedem Programm) sehr hilfreich sein, ist aber Geschmacksache. In der Funktion setup(), die hier alle Programmaktivitäten beherbergt, wird ein dynamisches JSON-Objekt doc erzeugt. Hilfe bei der Dimensionierung bietet der ArduinoJson Assistant. In diese Struktur können nun die Nested Objects mit ihren KeyValue-Paaren eingebaut werden. Am Ende des Programms erfolgt
die JSON-Ausgabe zum Serial Monitor: #include
// helper macro
#define LINE(name,val) Serial.print(name); Serial.print(" ");
Serial.println(val);
#define SENSOR1 "BME280"
#define SENSOR2 "DHT11"
#define SENSOR3 "NEO6M_GPS"
void setup()
{
// Initialize Serial port
Serial.begin(115200);
while (!Serial) continue;
LINE("File", __FILE__);
String s1 = __DATE__;
String s2 = __TIME__;
// Date of compilation
LINE("Compilation @", s1 +" " +s2);
// Arduino IDE SW version
LINE("ARDUINO IDE", ARDUINO);
Serial.print("Test JSON using ArduinoJson v.");
Serial.println(ARDUINOJSON_VERSION);
//https://arduinojson.org/v6/assistant/ used for configuration
const size_t capacity = JSON_ARRAY_SIZE(2) +JSON_OBJECT_SIZE(1) +
JSON_OBJECT_SIZE(2) +2*JSON_OBJECT_SIZE(3);
DynamicJsonDocument doc(capacity);
Serial.println("Serialization of data...");
JsonObject sensor1 = doc.createNestedObject("sensor1");
sensor1["temperature"] = 22.2;
sensor1["humdity"] = 66;
sensor1["pressure"] = 999;
JsonObject sensor2 = doc.createNestedObject("sensor2");
sensor2["temperature"] = 22.2;
sensor2["humdity"] = 66;
JsonObject sensor3 = doc.createNestedObject("sensor3");
JsonArray sensor3_position = sensor3.createNestedArray("position");
sensor3_position.add(8.8172433);
sensor3_position.add(47.1979687);
Serial.println("\nOutput minified JSON...");
serializeJson(doc, Serial);
Serial.println("\n\nOutput prettified JSON...");
serializeJsonPretty(doc, Serial);
}
void loop() {};
Listing 11.1 Quelltext Uno_JsonOutputv6.ino
Wie die Terminalausgabe des Programms Uno_JsonOutputv6.ino in Abbildung 11.1 zeigt, gibt es einmal den minified JSON Output (minimale Ausgabe) und zum anderen den prettified JSON Output (»schöne« Ausgabe), der sicher etwas einfacher lesbar ist. Entscheiden Sie, welche Variante Sie bevorzugen.
Abbildung 11.1 Terminalausgaben im JSON-Format
11.2 MQTT MQTT (Message Queuing Telemetry Transport) ist ein äußerst simpel aufgebautes Publish/Subscribe-Protokoll für den Nachrichtenaustausch zwischen Geräten geringer Funktionalität. Das robuste MQTT-Protokoll wurde für unzuverlässige Netze mit geringer Bandbreite und hoher Latenzzeit entwickelt.
11.2.1 Grundlagen MQTT minimiert die genutzte Netzwerk-Bandbreite und die Anforderungen an Geräte – gleichzeitig wird für die Datenübermittlung eine hohe Zuverlässigkeit erreicht. Diese Anforderungen bestehen insbesondere bei Sensornetzwerken, bei der Machine-to-Machine-Communication (M2M), in der Telemedizin, der Patientenüberwachung und allgemein beim IoT. Bei dieser Anwendung sind die angeschlossenen Geräte immer verbunden und kommunizieren ständig miteinander. Seit Januar 2016 ist MQTT ISO/IEC-standardisiert als ISO/IEC PRF 20922. Die Struktur, in der das MQTT-Protokoll arbeitet, besteht aus der Datenquelle, die als Publisher bezeichnet wird, der Datensenke, dem Subscriber, und dem zwischengeschalteten Message Broker, der für die Kommunikationssteuerung sorgt. Abbildung 11.2 zeigt das betreffende Modell.
Abbildung 11.2 Publish/Subscribe Message Queueing Model
Wie Abbildung 11.2 zeigt, kommunizieren der Publisher und der Subscriber immer über den Broker. Die Nachrichten, die über diesen Kanal laufen, sind sogenannten Topics zugeordnet. Nachdem sich ein Subscriber erfolgreich am Broker angemeldet hat, teilt er diesem mit, welche Topics er abonnieren möchte, um in Zukunft mit den jeweiligen Nachrichten versorgt zu werden (Subscribe(topic)). Beim Publisher funktioniert das umgekehrt: Beim Versenden einer Nachricht teilt er dem Broker mit, zu welchem Topic diese gehört (Publish(topic, data)). Die Hauptaufgabe des Brokers besteht also darin, Nachrichten anzunehmen und diese entsprechend an die Subscriber weiterzuleiten. Topics sind einfache Zeichenketten, die eine Nachrichten-Hierarchie abbilden und mit einer einfachen URL vergleichbar sind. So kann ein Topic für einen Sensor, der Temperatur und Luftfeuchtigkeit ermittelt, beispielsweise folgendermaßen aufgebaut sein: sensor/ID/temperature sensor/ID/humidity
Der so ausgestattete Sensorknoten kann nach Verbindung mit dem MQTT-Broker diese Topics an den MQTT-Broker senden (publish). Der MQTT-Broker stellt diese Information dann allen IoT-Knoten bereit, die das betreffende Topic abonniert haben. Haben wir nun mehrere gleichartige Sensorknoten in unserem Netz, dann werden an den MQTT-Broker Messages versendet, die
sich nur in den IDs unterscheiden. Mit Wildcards können diese Topics gefiltert werden. Durch Einführung der Wildcards + und # lassen sich die Messages entsprechend filtern. Wenn ein Subscriber den Topic DHT11/+/temperature abonniert, dann wird er die Temperaturwerte von allen vorhandenen DHT11-Sensorknoten erhalten. Sollen alle im Netz vorhandenen Werte von allen vorhandenen DHT11-Sensoren erfasst werden, dann ist der Topic DHT11/+/# zu abonnieren. MQTT wird oft in unsicheren Netzwerken eingesetzt, und es kann geschehen, dass IoT-Knoten nicht mehr mit dem Netzwerk verbunden sind. Die Last-Will-and-Testament-(LWT-)Mitteilung wird in MQTT verwendet, um andere Netzwerkknoten über den Verbindungsverlust zu informieren. Jeder MQTT-Client kann bei der Verbindung mit einem Broker seine LWT-Mitteilung spezifizieren. Der Broker speichert diese Mitteilung und versendet sie erst, wenn der betreffende Client unerwartet nicht mehr erreichbar ist. Wenn Sie diese Grundlagen kennen, werden Sie die folgenden Ausführungen sicher schon verstehen. Falls Sie mehr in die Tiefe gehen wollen, kann ich Ihnen die umfangreichen Ausführungen in den MQTT Essentials (http://www.hivemq.com/blog/mqtt-essentials/) empfehlen. Um sich praktisch mit dem MQTT-Protokoll bekannt zu machen, muss ein MQTT-Broker zur Verfügung stehen. Im nächsten Abschnitt finden Sie verschiedene Möglichkeiten dazu.
11.2.2 MQTT-Broker
Jede MQTT-Kommunikation im IoT läuft über einen MQTT-Broker. Setzen wir auf ein abgeschlossenes Netzwerk, dann kann der MQTTBroker auf einem PC oder Linux-Device im eigenen Netz installiert werden (Self Hosted MQTT Broker). Für den Aufbau eines solchen MQTT-Brokers existieren verschiedene Softwarelösungen. Mosquitto ist einer der verbreitetsten MQTT-Broker. Aktuell ist die Version 2.0.15 verfügbar und kann von http://mosquitto.org/download/ heruntergeladen werden. Der Raspberry Pi ist eine ausgezeichnete Mosquitto-Plattform und kann so den Sensoren einen MQTT-Broker zur Verfügung stellen. Eine Anleitung zur schrittweisen Installation von Mosquitto auf dem Raspberry Pi ist unter http://blog.thingstud.io/recipes/how-tomake-your-raspberry-pi-the-ultimate-iot-hub/ zu finden. Ich werde hier nicht diesen Weg gehen. Eine andere Variante ist, einen MQTT-Broker zu verwenden, der als Cloud-Applikation zur Verfügung steht (Hosted MQTT Brokers). Diese Variante hat den Vorteil, dass man die Grenzen seines abgeschlossenen Netzwerkes verlässt und die Daten über das Internet bereitstellt. Auf der Website mqtt.org gibt es eine Liste öffentlich zugänglicher MQTT-Broker (https://github.com/mqtt/mqtt.github.io/wiki/public_brokers). Um sich an den Datenaustausch über das MQTT-Protokoll heranzutasten, bietet sich die Verwendung eines freien BrokerDienstes als Spielwiese an. Der CloudMQTT-Broker der schwedischen Firma 84codes AB ist eine solche Möglichkeit. CloudMQTT sind Mosquitto-Server in der Cloud. Zum Erstellen einer CloudMQTT-Instanz ist es erforderlich, unter http://www.cloudmqtt.com/ ein Konto einzurichten und sich für
einen Kunden-Plan zu entscheiden. Als Testfeld nutze ich den freien Plan Cute Cat. Die Anmeldung eines Kundenkontos erfolgt über eine E-Mail-Adresse, an die ein Link zur Freischaltung verschickt wird. Nach der Erzeugung einer CloudMQTT-Instanz werden die Informationen zur erzeugten Instanz angezeigt. Alle in Abbildung 11.3 gezeigten Daten werden vom System zugewiesen. Das trifft auch für den Usernamen und das Passwort zu.
Abbildung 11.3 CloudMQTT-»Instance Info«
Bevor über das MQTT-Protokoll Daten ausgetauscht werden können, müssen sogenannte ACL Rules definiert werden. ACL steht für Access Control List. Damit sind serverseitig alle Vorbereitungen getroffen, und der Datenaustausch kann nach Einrichtung des Sensorknotens (MQTTClient, Publisher) im Websocket-UI (User Interface) getestet werden. Abbildung 11.4 zeigt den Zugriff auf den CloudMQTT-Broker über das Websocket-UI. Abonniert wurde der Topic UnoWiFiR2/#, was durch
die empfangenen Messages auch repräsentiert wird.
Abbildung 11.4 Empfangene MQTT-Messages von einem Sensor
11.2.3 MQTT-Client Damit der MQTT-Broker auch die in Abbildung 11.4 gezeigten Nachrichten empfangen kann, stelle ich Ihnen hier einen einfachen MQTT-Client vor. Ich habe einfach einen Arduino Uno WiFi Rev2 und ein YwRobot Easy Module Shield v1 zusammengesteckt, um den DHT11-Sensor nutzen zu können. Hardwareseitig sind damit alle Vorkehrungen für einen Sensorknoten getroffen, der MQTTMessages verschicken kann. Das Programm UnoWiFiR2_DHT11_MQTT.ino fragt den DHT11Sensor ab (oder auch einen beliebigen anderen), verpackt die Resultate in die zu versendende Nachricht und verschickt diese. Mit den ersten Zeilen des Quelltextes sind auch alle Bestandteile für die einzubindenden Librarys benannt. Die ersten beiden Librarys unterstützen den WiFi-Zugriff auf den Router. Die PubSubClientLibrary ist für MQTT verantwortlich. Die DHT-Library unterstützt den Zugriff auf einen Sensor der DHT11-Familie, und in
arduino_secrets.h sind die zu behütenden Geheimnisse, wie Zugangsdaten etc., abgelegt. #include #include #include #include #include
"DHT.h"
"arduino_secrets.h"
Mit den Defines werden wieder Info- und Debug-Ausgaben gesteuert: #define INFO 0
#define DEBUG 1
Mit dem Erzeugen des PubSubClients sind wir dann schon nahe am eigentlichen Kern: /* create an instance of PubSubClient client */
WiFiClient UnoWiFiClient;
PubSubClient client(UnoWiFiClient);
Der Sensor DHT11 liefert zwei Messwerte, denen je ein Topic zugeordnet wird: /* topics */
#define TEMP_TOPIC #define HUMI_TOPIC
"UnoWiFiR2/temp"
"UnoWiFiR2/humi"
Bleibt noch das Konfigurieren und Initialisieren des Sensors vor dem eigentlichen setup(): /* define DHT pins */
#define DHTPIN 4
#define DHTTYPE DHT11
DHT dht(DHTPIN, DHTTYPE);
In der Funktion setup() (Listing 11.2) werden die WiFi- und die MQTT-Verbindung aufgebaut und der Sensor initialisiert. Die Funktionen sind mehr oder weniger vorgegeben und werden in der Anwendung in der Regel so belassen:
void setup()
{
…
connectWiFi();
configureMQTT();
initSensor();
if (DEBUG) Serial.println(F("Running...")); }
//last line in setup()
Listing 11.2 Quelltext UnoWiFiR2_DHT11_MQTT.ino – setup()
In der Funktion loop() (Listing 11.3) spielt sich nach dem Verbindungsaufbau alles Weitere ab. Alle 30 Sekunden wir der DHT11-Sensor nach seinen Messwerten abgefragt. Handelt es sich um die erwarteten numerischen Resultate, dann werden diese in einen String umgewandelt und als MQTT-Message versendet: void loop()
{
/* if client was disconnected then try to reconnect again */
if (!client.connected()) mqttconnect();
/* this function will listen for incomming subscribed topic-process-
invoke receivedCallback */
client.loop();
/* we measure temperature every 10 secs
we count until 10 secs reached to avoid blocking program if using delay()*/
long now = millis();
if (now - lastMsg > 30000)
{
lastMsg = now;
/* read DHT11/DHT22 sensor and convert to string */
temp = dht.readTemperature();
hum = dht.readHumidity();
if (!isnan(temp))
{
dtostrf(temp, 3, 1, msg);
/* publish the message */
client.publish(TEMP_TOPIC, msg);
if (DEBUG) Serial.print(msg);
}
if (!isnan(hum))
{
dtostrf(hum, 3, 0, msg);
/* publish the message */
client.publish(HUMI_TOPIC, msg);
if (DEBUG) Serial.println(msg);
}
}
}
Listing 11.3 Quelltext UnoWiFiR2_DHT11_MQTT.ino – loop()
Die schrittweise Abarbeitung des Programms können Sie leicht anhand der Ausgaben in Abbildung 11.5 nachverfolgen: Die vom MQTT-Broker empfangenen Meldungen können nun von einem weiteren MQTT-Client abonniert (subscribe) werden. Auf meinem Windows-PC verwende ich gern die Software MQTTlens und auf dem Smartphone MQTT Dashboard. Beide Programme können gratis heruntergeladen werden.
Abbildung 11.5 Ausgaben des Programms »UnoWiFiR2_DHT11_MQTT.ino«
Den Mittschnitt von MQTTlens zeigt Abbildung 11.6. Die Subscription lautet hier UnoWiFiR2/#. Das heißt, alle Topics, die mit UnoWiFiR2/ beginnen, sind abonniert und werden angezeigt.
Abbildung 11.6 Mitschnitt von MQTT-Messages mit MQTTlens
Einen MQTT-Client auf Basis eines ESP32 habe ich in meinem Blog beschrieben: HiGrow-Sensor: Daten erfassen und versenden, https://ckblog2016.net/2018/03/19/higrow-sensor-daten-erfassenund-versenden/. Wenn Sie also die Umgebungsbedingungen für Ihre Pflanzen überwachen wollen, dann ist das eine Möglichkeit. Achten Sie aber darauf, dass die Bodenfeuchte kapazitiv gemessen wird: Bei resistiver Messung haben Sie nicht lange Freude, denn der Sensor zerstört sich durch Korrosion langsam selbst.
12 Arduino-Benchmarks Wenn Sie die Leistungsfähigkeit Ihres Projekts messen wollen, brauchen Sie Benchmarks. Benchmarks sind Bewertungsverfahren, mit deren Hilfe Sie die Leistung von IT-Systemen oder -Komponenten ermitteln und diese nach bestimmten Kriterien miteinander vergleichen können. Bekannt sind die Benchmark-Tests für die Hardware-Leistung bei Computersystemen. Benchmarks werden aber ebenfalls verwendet, um die Leistung von Programmiersprachen – mithin Interpretern sowie Compilern und deren Laufzeitsystemen – auf derselben Hardware zu vergleichen. Dann spricht man von einer SoftwareBenchmark. Ein Benchmark im Allgemeinen ist immer ein Programm, das ein (oft aus der Mathematik stammendes, aufwendiges) Problem löst. Beispiele sind das Lösen linearer Gleichungssysteme oder die Berechnung von Primzahlen. Im Rahmen dieses Buches habe ich Ihnen verschiedene ControllerBoards vorgestellt, die alle zur Rubrik »Arduino« gehören. Sicher ist es für Sie von Interesse, die einzelnen Boards bezüglich ihrer Leistungsfähigkeit zu klassifizieren. Eine Benchmark hilft Ihnen, ein entsprechendes Ranking vornehmen zu können. Ich habe hier verschiedene Benchmarks zur Verfügung, die unterschiedliche Aspekte der Hard- und Software betrachten:
Sieve of Eratosthenes IOLoop Dhrystone Whetstone IOBench CoreMark Tabelle 12.1 listet die verwendeten Benchmarks und ihre Beschreibung auf. Weitere Informationen finden Sie unter: BMAR – https://github.com/oomlout/oomlout-BMAR EEMBC – https://www.eembc.org/techlit/articles/coremarkwhitepaper.pdf Benchmark
Beschreibung
Quelle
Sieve of Das »Sieb von Eratosthenes« ist eine Public Eratosthenes Standard-Benchmark, mit der die relative Domain Geschwindigkeit verschiedener Computer oder die Effizienz des Codes bestimmt wird, der von verschiedenen Compilern für denselben Computer generiert wird. Der Algorithmus wurde im antiken Griechenland entwickelt und ist eine von mehreren Methoden, um Primzahlen zu finden. IOLoop
Endlosschleife mit zur Messung der resultierenden Frequenz digitalWrite(LOW|HIGH)
Benchmark
Beschreibung
Quelle
Dhrystone
Dhrystone betrachtet die Fähigkeit eines Mikrocontrollers, mit Integer-Arithmetik umzugehen. Die hier verwendete BMARVersion von Dhrystone wurde geändert, um auch auf dem ATmega328P lauffähig zu sein.
BMAR
Whetstone
Die klassische Gleitkomma-Benchmark, in der BMAR-Version wegen der 8-BitMikrocontroller auf einfache Genauigkeit reduziert, zeigt die Fähigkeit eines bestimmten Mikrocontrollers, mit Gleitkomma-Arithmetik umzugehen.
IOBench
IOBench ist eine benutzerdefinierte Benchmark, die speziell für BMAR geschrieben wurde. Digitale I/O liefert Ergebnisse in kHz, die zeigen, wie viele Signalwechsel durch I/O-Operationen an einem Pin erfolgen können.
Benchmark
Beschreibung
Quelle
CoreMark
CoreMark von EEMBC ist eine Benchmark, die die Leistung von Mikrocontrollern (MCUs) und Zentraleinheiten (CPUs) misst, die in eingebetteten Systemen verwendet werden. CoreMark ersetzt die veraltete Dhrystone-Benchmark und enthält Implementierungen der folgenden Algorithmen: Listenverarbeitung (Suchen und sortieren), Matrixmanipulation (allgemeine Matrixoperationen), Zustandsmaschine (Feststellen, ob ein Eingabestream gültige Zahlen enthält) und CRC (zyklische Redundanzprüfung). CoreMark kann auf Geräten mit 8-BitMikrocontrollern bis hin zu Geräten mit 64-Bit-Mikroprozessoren ausgeführt werden.
EEMBC
Tabelle 12.1 Benchmark-Beschreibung
Auf die Programme selbst möchte ich an dieser Stelle nicht eingehen. Stattdessen verweise ich auf das Repository. Dort sind sie in einem eigenen Verzeichnis abgelegt. Sie können die Programme verwenden und damit Ihre eigenen Tests durchführen. Abbildung 12.1 zeigt die Resultate, die einzelne Mikrocontroller beim Test mit der CoreMark-1.0-Benchmark erzielten.
Abbildung 12.1 Resultate beim Benchmark »CoreMark 1.0«
Der Arduino Uno taucht in dieser Aufstellung nicht auf, denn seine Ressourcen sind für die CoreMark-Benchmark nicht ausreichend. Zieht man die Dhrystone-Benchmark heran, dann liegen Arduino Uno und Arduino Uno WiFi Rev2 erwartungsgemäß nahe beieinander. Aus der Grafik wird deutlich, dass es für unterschiedliche Leistungsanforderungen in jedem Fall Unterstützung durch die Arduino-Familie im weiteren Sinn gibt. Weitere Testresultate finden Sie auch auf meiner Arduino-Website unter https://ckarduino.wordpress.com/benchmarks/.
13 Projektideen für den Arduino Jetzt kennen Sie die Hardware zahlreicher Mitglieder der Arduino-Familie sowie Sensoren und Aktoren und deren Ansteuerung sowie die Kommunikation des Arduino im Netzwerk bis zur Cloud. Mit diesem Wissen können Sie Ihre ersten eigenen Anwendungen entwickeln. Ich möchte Ihnen in diesem Kapitel Anwendungsbeispiele zeigen, die Sie an Ihre Bedingungen anpassen oder als Anregung für eigene Anwendungen verwenden können.
13.1 Tragbare Elektronik (Wearables) Die Integration von Elektronik in Bekleidung ist ein Ansatz, der neue Möglichkeiten multifunktionaler, tragbarer Textilien zur Überwachung von Körperfunktionen, zur Bereitstellung von Kommunikationsmöglichkeiten, Datenübertragung, individueller Steuerungsfunktionen und anderem mehr eröffnet. Modeartikel weisen Tastenfelder für Mobiltelefone und Anschlussmöglichkeiten für iPods oder MP3-Player auf. Mithilfe von Spezialkleidung ist man in der Lage, Vitalfunktionen zu erfassen. Beim trainierenden Sportler kann die Herzfrequenz ebenso erfasst werden wie die Muskelarbeit. Risikopatienten können in Notfällen mit diesem Mittel gezielt Hilfe anfordern. Diese Aufzählung kann nahezu beliebig fortgesetzt werden.
Obwohl Wearable Electronics immer wieder mal in den Mittelpunkt der Aufmerksamkeit rücken und zahlreiche Forschungsaktivitäten laufen, bleibt es um die Textilien selbst noch eher still. In diesem stark heterogen geprägten Umfeld gibt es noch viele technische Herausforderungen zu überwinden, bevor Interactive Wear nicht nur im Fashion- und Entertainment-Bereich, sondern auch im Gesundheits- und Pflegebereich zum Alltag gehören werden. Spielerisch kann man sich aber bereits heute mit Wearable Electronics beschäftigen und dabei recht interessante Lösungen gestalten. Mit dem folgenden Anwendungsbeispiel möchte ich einen solchen Versuch wagen. Eine Sicherheitsblinkschaltung, die beispielsweise auf der Jacke von Kindern angebracht werden kann, soll sich bei Dunkelheit einschalten und so in der Dunkelheit auf den Passanten aufmerksam machen. Neben dem LilyPad-Arduino-Mainboard werden zwei LilyPad Bright White LEDs für die Anzeigefunktion verwendet, die beispielsweise im Bereich von Schulter oder Arm beidseits montiert werden können. Der LilyPad Light Sensor misst das Umgebungslicht und schaltet bei Unterschreiten eines einstellbaren Helligkeitswerts die LEDs in den Blinkmodus. Zur Spannungsversorgung dient das mit einer AAA-Batterie zu bestückende LilyPad Power Supply, das auch den Hauptschalter trägt. Abbildung 13.1 zeigt die zur Blinkschaltung verdrahteten LilyPad-Komponenten.
Abbildung 13.1 LiliyPad-Blinker
An das LilyPad-Arduino-Mainboard ist ein FTDI-Breakout-Board angesteckt. Dieses Breakout Board fungiert als USB-Serial-Bridge und dient zum Programm-Upload bzw. zur Kommunikation über USB mit dem PC. Läuft das Programm so, wie Sie es erwarten, und ist der gewünschte Schwellenwert eingestellt, dann kann die USB-Serial-Bridge abgezogen werden und die LilyPad-Komponenten verrichten ihren Dienst autonom. Das Programm, das die LilyPad-Komponenten zum Leben erweckt, können Sie in der Arduino IDE entwickeln und in Betrieb nehmen. Wie Abbildung 13.2 zeigt, können Sie über den Serial Monitor der Arduino IDE die Ausgaben der seriellen Schnittstelle beobachten. Nach einigen Zeilen Eröffnungstext sehen Sie den gesetzten Schwellenwert und den Wert für das gemessene Umgebungslicht. Liegt der Messwert unter dem Schwellenwert, dann muss das Blinken aktiviert sein. Die Veränderung des Schwellenwerts ist über
die serielle Schnittstelle möglich. Durch Eingabe des Wertes 400 wurde dieser geändert.
Abbildung 13.2 Ausgaben des Programms »LightControlledBlinking.ino«
Das Programm LightControlledBlinking.ino ist sehr einfach und besteht im Wesentlichen aus digitalen Ausgaben. Der serielle eingegebene Schwellenwert wird im internen EEPROM an Adresse 0 gespeichert: const int eeAddress = 0; int threshold;
// EEPROM location for threshold
// threshold defines activation of blinking
In der Funktion setup() wird neben der Initialisierung der digitalen Ausgabe und der seriellen Schnittstelle der im EEPROM abgelegte Schwellenwert zurückgelesen: void setup()
{
…
EEPROM.get(eeAddress, threshold);
…
}
In der Funktion loop() wird bei serieller Eingabe eines Schwellenwertes dieser ins EEPROM gespeichert. Das Umgebungslicht wird über den am Analogeingang A0 angeschlossenen Lichtsensor erfasst und durch
analogRead(sensorPin) gelesen. Liegt der Lichtwert unterhalb des
Schwellenwertes, blinken die angeschlossenen LEDs, anderenfalls wird eine Sekunde bis zur nächsten Abfrage gewartet. void loop()
{
// check if data has been sent from host
if (Serial.available())
{
threshold = (int) Serial.parseInt();
EEPROM.put(eeAddress, threshold);
}
int value = analogRead(sensorPin); // read the value from light sensor
…
if (value < threshold) blinking();
else delay(1000);
}
Listing 13.1 Quelltext LightControlledBlinking.ino – loop()
Neben dieser eher ernsthaften Anwendung finden Sie mit diesen Komponenten sicher auch Möglichkeiten, die eher dem Thema »Spiel und Spaß« zugeordnet werden können.
13.2 Überwachung des Raumklimas Wohlbefinden und Gesundheit werden durch das Raumklima in Ihrer Wohnung oder Ihrem Haus beeinflusst. Für ein gesundes Raumklima sind mehrere Faktoren von Bedeutung, die zusammenspielen müssen: Temperatur, Luftfeuchtigkeit, Luftqualität, Luftzirkulation u. a. m. Bei der Ermittlung einer optimalen Raumtemperatur wird zwischen Wohn- und Schlafräumen unterschieden. Für einen gesunden Schlaf reichen Temperaturen von 16 bis 19 °C aus, während in Wohnräumen die Temperatur zwischen 18 und 24 °C liegen sollte. Das Empfinden angenehmer Temperaturen ist allerdings sehr individuell. Mit einem Thermometer kann die Raumtemperatur leicht überwacht werden. Die Luftfeuchtigkeit ist in gleichem Maße wie die Temperatur für ein gutes Raumklima verantwortlich. Der optimale Wert für die relative Luftfeuchtigkeit liegt zwischen 40 und 60 %. Dieser Wert wird auch durch die Wetterbedingungen beeinflusst und kann mit einem Hygrometer überwacht werden. Der Begriff Luftqualität ist leider wenig scharf umrissen. Schadstoffe wie Feinstaub, Asbest, Formaldehyd, PCB, Radon, Reinigungsmittel, Schimmel, Staub, Tabakrauch und VOC (volatile organic compounds) beeinträchtigen neben CO₂ die Luftqualität in Innenräumen. Leider lassen sich keine allgemeingültigen Aussagen über die optimale Luftqualität in Innenräumen treffen. Jeder Mensch reagiert unterschiedlich auf Schadstoffbelastungen. Das Setzen von Grenzwerten ist deshalb auch sehr schwierig.[ 15 ]
Professionelle Testgeräte wie beispielsweise das air-Q (https://www.air-q.com/produkt) analysieren die Luftqualität durch die Messung von Sauerstoff (O₂), Kohlendioxid (CO₂), Kohlenmonoxid (CO), Stickstoffdioxid (NO₂), Schwefeldioxid (SO₂), Ozon (O₃), VOC (Flüchtige organische Substanzen), Feinstaub (PM1, PM2.5, PM10), Temperatur, relativer und absoluter Luftfeuchtigkeit sowie Luftdruck. Hinzu kommen weitere Messgrößen, wie z. B. der Lärmpegel. Für diese komplexen Messungen werden dann mehr als elf Sensoren eingesetzt. Neben Temperatur und Luftfeuchtigkeit sind die Konzentration von CO₂ und VOC wichtige Kenngrößen, da diese in der aktuellen Situation von COVID-19 stark in den Mittelpunkt der Betrachtungen zur Luftgüte gerückt sind. Der für die Erkrankung an COVID-19 verantwortliche Virus SARSCoV-2 wird vorrangig und mit hoher Ansteckungsrate über luftgetragene Tröpfchen (Aerosole) aus den Atemwegen Infizierter auf weitere Personen übertragen. Im Freien bei Beachtung eines hinreichenden Abstands von Personen ist das Infektionsrisiko eher gering. Anders sieht das in Innenräumen aus, die durch mehrere Personen belegt sind. Wie sich Aerosole in Räumen verteilen und was das für das Infektionsrisiko bedeutet, können Sie im Blog der TU Berlin[ 16 ] nachlesen. Eine Überwachung der CO₂- und/oder VOCKonzentration ist aus diesem Grund aktuell sehr wichtig. Der Anteil des Kohlendioxids in der Atemluft beträgt heute ca. 415 ppm (entspricht 0,04 % der Luft). Die ausgeatmete Luft eines Menschen weist einen CO₂-Gehalt von ca. 40.000 ppm auf. Entsprechend können in ungelüfteten Schlafzimmern, voll besetzten Klassen- oder Meetingräumen schnell Konzentrationen von bis zu 5000 ppm gemessen werden. Diese hohen CO₂-
Konzentrationen sind schädlich für Konzentration, Leistungsfähigkeit und die Gesundheit im Allgemeinen.
Abbildung 13.3 Messanordnung zur Qualifizierung von Sensoren
In einer umfangreichen Untersuchung habe ich Sensoren zur Messung von CO₂- bzw. VOC-Konzentration messtechnisch erfasst und gegenübergestellt (https://ckarduino.wordpress.com/2021/02/04/luftqualitat-mit-ndirund-mox-sensoren-messen/). Abbildung 13.3 zeigt schematisch die Messanordnung und Abbildung 13.4 einige der eingesetzten Sensoren.
Abbildung 13.4 Sensoren in der Messanordnung
Ich möchte hier nicht auf die Einzelheiten der Messungen eingehen. Diese finden Sie im betreffenden Blogbeitrag. Das Fazit der Untersuchungen wird Sie aber sicher interessieren: Ziehen wir die CO₂-Konzentration als Maß für die Luftqualität heran, dann haben wir ein gutes Indiz für die Belastung der Luftqualität durch die Atemluft anwesender Personen und über das Infektionsrisiko von über die entstehenden Aerosole übertragenen Viren. Ziehen wir die Ergebnisse der breitbandig messenden MOXSensoren als Maß für die Luftqualität heran, dann haben wir ein gutes Indiz für die Belastung der Luftqualität durch unterschiedliche Schadstoffe – einschließlich menschlicher Ausdünstungen und Gerüche.
Es kann also durchaus angezeigt sein, CO₂- und MOX-Sensoren zu kombinieren und aus deren Messwerten Kriterien für eine bedarfsgerechte Lüftung abzuleiten. Auf diesem Weg kann die Luftqualität mit Sicherheit optimiert werden.
13.2.1 Sensirion SCD30 Will man mit einfacheren Mitteln die Luftqualität überwachen, dann ist der CO₂-Gehalt der Luft ein wichtiges Indiz für »verbrauchte« Luft. Dieser Wert wird häufig für die Steuerung von Belüftungsanlagen herangezogen. Basis für unsere Raumklima-Anzeige ist der CO₂-, Temperatur- und Feuchtesensor SCD30 von Sensirion (siehe Abbildung 13.5).
Abbildung 13.5 SCD30 von Sensirion (Quelle: Sensirion)
Der SCD30 ermöglicht CO₂-Messungen mit hoher Genauigkeit zu einem attraktiven Preis. Der nach dem Non-Dispersive-Infrared(NDIR-)Verfahren arbeitende CO₂-Sensor wird auf dem gleichen
Sensormodul mit einem Feuchte- und Temperatursensor von Sensirion kombiniert. Seeed Studio hat diesen Sensor zu einem leicht handhabbaren Grove-Modul konfektioniert und mit einem I 2C-Interface ausgestattet (siehe Abbildung 13.6).
Abbildung 13.6 Grove-SCD30-Sensor (Quelle: https://wiki.seeedstudio.com/ GroveCO2_Temperature_Humidity_Sensor-SCD30/)
Mit diesem Sensor, einem LCD-Shield und einem Arduino Uno haben Sie schon die gesamte erforderliche Hardware zur Raumklima-Anzeige zusammen (siehe Abbildung 13.7). Verwenden Sie noch ein Grove Base Shield v2 für die Verbindung zum GroveSCD30, dann können Sie einfach alles zusammenstecken, ohne eine einzige Lötverbindung anbringen zu müssen. Als LCD-Shield habe ich ein LCD-Keypad-Shield verwendet.
Abbildung 13.7 Hardware für eine Raumklima-Anzeige
Die Ansteuerung des SCD30 wird durch Verwendung der SCD30Library von SparkFun sehr vereinfacht. Das Programm Uno_SCD30_Monitor.ino ist durch die Verwendung der SCD30-Library ähnlich einfach wie der Aufbau der Hardware. Ich erläutere hier deshalb nur wenige Ausschnitte aus dem Programm. Zu Beginn werden die erforderlichen Librarys eingebunden. Die Library LiquidCrystal wird für HD44780-kompatible LCDs benötigt, die Wire-Library für das I2C-Interface, und die SCD30-Library hatten wir eben installiert: #include
#include
#include "SparkFun_SCD30_Arduino_Library.h"
Die LCD-Anschlüsse müssen dem Arduino zugeordnet werden. Diese Zuordnung gilt für das hier verwendete LCD-Keypad-Shield: // select the pins used on the LCD panel
LiquidCrystal lcd(8, 9, 4, 5, 6, 7);
Mit der Instanz airSensor sind dann auch schon alle Vorkehrungen abgeschlossen: SCD30 airSensor;
In der Funktion setup() erfolgen die notwendigen Initialisierungen: void setup()
{
Wire.begin();
airSensor.begin(); //This will cause readings to occur every two seconds
…
}
In der Funktion loop() können nun nach dem Muster für den CO₂Wert die weiteren Messwerte abgefragt und angezeigt werden. Es geht also im Wesentlichen um das Löschen alter Inhalte vom LCD, das Positionieren des Cursors und die eigentlichen LCD-Ausgaben. Nach 5 Sekunden wiederholt sich das Prozedere: void loop()
{
clearLine(0);
lcd.setCursor(0,0); // move to the begining of the first line
lcd.print(" CO2 ");
lcd.print(airSensor.getCO2());
lcd.print(" ppm");
…
delay(5000);
}
Auf der zweizeiligen LCD-Anzeige gestaltet sich die Messwertausgabe dann so wie in Abbildung 13.8.
Abbildung 13.8 Anzeige des Raumklimas
Wenn Sie den hier verwendeten Arduino Uno durch einen Arduino Uno WiFi Rev2 ersetzen, dann können Sie sehr einfach die
erhobenen Messwerte auch über das Internet zugänglich machen. Sie können also auch aus der Ferne das Raumklima verfolgen, was z. B. ebenso für die Tiefgarage oder ein Gewächshaus interessant sein dürfte. Nutzen Sie beispielsweise dweet.io (http://dweet.io), was auch als Twitter für das IoT bezeichnet wird, dann kann der Arduino seine Werte da abspeichern, und Sie können mit einem Webbrowser vom PC oder dem Smartphone auf diese Daten zugreifen. dweet.io stellt so eine sehr einfache Alternative zu MQTT-basierten Services dar. Auf die Details zu MQTT bin ich in Abschnitt 11.2 eingegangen. Über eine sehr einfach gehaltene REST-API können IoT-Devices ihre Daten unter Angabe eines Namens an die dweet.io-Plattform übermitteln. Die Daten können mithilfe des Namens abgerufen werden. In der Gratisversion von dweet.io werden die Daten für 24 Stunden gespeichert, in der kostenpflichtigen Version für 30 Tage. Mit dem Programm UnoWiFiR2_SCD30_dweetio.ino zeige ich Ihnen auf Basis des letzten Programms, wie Sie die Messwerte nicht nur über ein LCD anzeigen lassen, sondern zusätzlich über einen HTTPGET-Request an den dweet.io-Server senden können. Auf diesem Server abgelegte Daten können von jedermann eingesehen und abgeholt werden. Ich zeige Ihnen hier nur die mit dem Zugriff auf dweet.io zusammenhängenden Aspekte, denn nur diese sind hier neu. Außerdem habe ich eine Funktion reconnectWiFi() eingebaut, die bei Bedarf eine verlorene WiFi-Verbindung wieder repariert. Der dweet.io-Server wird über die Adresse dweet.io erreicht, weshalb diese als Konstante vereinbart ist:
// Host
const char* host = "dweet.io";
Die Messwerte sind als Gleitkommazahlen definiert, und die Zahl der Reconnect-Versuche steht hinter der Variablen wifi_retry: float CO2, temp, hum;
int wifi_retry = 0;
Wird durch den dweet.io-Server kein Socket zur Verfügung gestellt, dann erfolgen ein globaler Reset des Arduino und ein erneuter Verbindungsaufbau: void(* resetFunc) (void) = 0; // Reset ATmega4809
Die Funktion setup() bietet nichts Neues, und in der Funktion loop() ist auch nur der Zugriff auf den dweet.io-Server neu. Wichtig ist der Aufbau des Strings für den GET-Zugriff, den Sie an den dweet.io-Server senden. Ihm müssen die zu übergebenden Daten mitgegeben werden: GET /dweet/for/RoomClimate?CO2=&temperature=&humidity= HTTP/1.1\r\nHost: \r\nConnection: close\r\n\r\n
Den gesamten Quelltext finden Sie in Listing 13.2. Abbildung 13.9 zeigt die Ausgaben des Programms über den Serial Monitor. void loop()
{
reconnectWiFi(); // if Wifi connection is no more available
…
const int httpPort = 80;
if (!client.connect(host, httpPort))
{
Serial.println("connection failed");
resetFunc(); // if there is no socket from Dweet.io
}
Serial.print("Requesting URL: ");
Serial.println(host);
temp = airSensor.getTemperature();
hum = airSensor.getHumidity();
CO2 = airSensor.getCO2();
…
// This will send the request to the server
client.print(String("GET /dweet/for/RoomClimate?CO2=") + String(CO2) +
"&temperature=" + String(temp) +
"&humidity=" + String(hum) + " HTTP/1.1\r\n" +
"Host: " +host +"\r\n" +
"Connection: close\r\n\r\n");
delay(100);
// Read all the lines of the reply from server and print them to Serial
while(client.available())
{
String line = client.readStringUntil('\r');
Serial.print(line);
}
Serial.println();
Serial.println("closing connection");
delay(15000); //Send a request every 15 seconds
}
Listing 13.2 Quelltext UnoWiFiR2_SCD30_dweetio.ino – Auszug
Abbildung 13.9 Ausgabe des Programms »UnoWiFiR2_SCD30_dweetio.ino«
Um auf die letzten auf dem dweet.io-Server zwischengespeicherten Werte zuzugreifen, nutzen Sie den folgenden Aufruf aus dem Webbrowser heraus: https://dweet.io/get/latest/dweet/for/RoomClimate
Die Antwort ist ein JSON-String mit allen von dweet.io bereitgestellten Daten: {
"this": "succeeded",
"by": "getting",
"the": "dweets",
"with": [
{
"thing": "RoomClimate",
"created": "2022-04-11T12:37:53.044Z",
"content": {
"CO2": 527,
"temperature": 28.15,
"humidity": 26.73
}
}
]
}
Wollen Sie die Messwerte kontinuierlich verfolgen, nutzen Sie den Aufruf https://dweet.io/follow/RoomClimate. Dann öffnet sich das Fenster aus Abbildung 13.10 im Browser.
Abbildung 13.10 dweet-Verlauf
13.2.2 Sensirion SGP30 und Bosch BME280 Möchten Sie Sensorik zur Überwachung der Luftgüte im Wohnbereich anordnen, dann sollten Sie alles in einem ansprechenden Gehäuse verpacken. Mit den AZ-Touch ESP von Zihatec stehen optisch ansprechende Gehäuse für die Wandmontage zur Verfügung, die komplett
vormontiert und getestet geliefert werden und nur noch durch die Sensorik ergänzt werden müssen. Ich habe ein ESP32 DevKit und Breakout Boards der Sensoren SGP30 und BME280 verwendet, die über den I2C-Bus mit dem ESP32 verbunden sind.[ 17 ] Das Breakout Board des Sensirion SGP30 entspricht der untersuchten M5Stack TVOC/eCO2 Gas Sensor Unit (SGP30). Der Bosch BME280 kommt für Temperatur und Luftfeuchte noch hinzu. Da die Standard-Pins der I2C-Schnittstelle beim AZ-Touch ESP durch das Display belegt sind, habe ich SDA auf GPIO25 und SCL auf GPIO32 gelegt. Das Programm finden Sie im Repository unter https://github.com/ckuehnel/Arduino2023/blob/main/ESP32/ESP32_ CO2_Ampel/ESP32_CO2_Ampel.ino. Die Anzeige der zur Beurteilung der Luftqualität wichtigen Werte zeigt Abbildung 13.11. Die Farbe des Hintergrundes signalisiert dabei die entsprechenden Bereiche der Luftqualität. Bei einem roten Hintergrund ist auf jeden Fall zu lüften.
Abbildung 13.11 eCO2-Konzentration im Normalbereich
13.2.3 Bosch BME680 Der Bosch Sensortec BME680 ist einer der neuesten Umgebungssensoren für Luftfeuchtigkeit, barometrischem Druck, Temperatur und Luftgüte, der mit I2C- und SPI-Schnittstelle ausgerüstet ist. Dieser MOX-Sensor gibt die Luftqualität als Widerstandswert zurück, der proportional zur TVOC-Konzentration ist. Mithilfe der proprietären BSEC-Software (Bosch Sensortec Environmental Cluster) ist es möglich, aus den BME680-Messwerten die gewünschten Ausgangsgrößen, wie den Indoor Air Quality Index (iAQ) zu berechnen. Die BSEC-Software unterstützt zahlreiche Plattformen von 8 Bit bis zu 32 Bit. Informationen hierzu sind auf der Bosch-Website zu finden. Für Controller, die von der BSEC-Software nicht unterstützt werden, gibt es eine Library von David Bird, die den iAQ näherungsweise bestimmt. Von Watterott wird das in Abbildung 13.12 gezeigte Breakout Board angeboten, das ich für Tests verwendet habe. Andere Anbieter führen vergleichbare Boards, die funktional praktisch identisch sind.
Abbildung 13.12 BME680 Breakout Board von Watterott
Für den Test habe ich das BME680-Breakout-Board an einem Seeeduino XIAO Expansionsboard (siehe Abschnitt 2.4.2) betrieben. Abbildung 13.13 zeigt die mithilfe des Programms XIAO_BME680.ino vom Sensor ermittelten Messwerte, die alles umfassen, was für die Bewertung der Umgebung in Innenräumen erforderlich ist.
Abbildung 13.13 Messwerte BME680 Sensor
Aus den einzelnen Messwerten des Gassensors kann der Indoor Air Quality Index iAQ berechnet werden. Die aus dem Datenblatt für den BME680-Sensor von Bosch entnommene Tabelle (Bosch BME680 Datasheet, https://www.boschsensortec.com/media/boschsensortec/downloads/datasheets/bstbme680-ds001.pdf) zeigt den Wertebereich dieses Index und die betreffenden Merkmale.
Abbildung 13.14 Indoor Air Quality Index
Der Bosch Sensortec BME688 ist der Nachfolger des BME680 und der erste Gassensor mit künstlicher Intelligenz (KI) und integrierten, sehr präzisen Feuchte- und Temperatursensoren. Der integrierte Gassensor ist in der Lage, flüchtige organische Verbindungen (VOCs), flüchtige Schwefelverbindungen (VSCs) und andere Gase wie Kohlenmonoxid (CO) und Wasserstoff im ppbBereich zu erkennen. Der neue BME688-Sensor ist abwärtskompatibel zum BME680. Zusätzlich zu allen Funktionen des BME680 verfügt der BME688 über eine Gasscannerfunktion. In der Standardkonfiguration wird das Vorhandensein von VSCs als Indikator für z. B. Bakterienwachstum gewertet. Der Gassensor hat eine hohe Empfindlichkeit und reagiert auf die meisten flüchtigen Verbindungen (VOC) sowie viele andere Gase, die die Raumluft
verschmutzen. Als MOX-Sensor ist der BME688 in der Lage, die Summe der VOCs bzw. Schadstoffe in der Umgebungsluft zu messen. Dadurch kann der BME688 z. B. Ausgasen von Farbe, Möbeln und/oder Müll, hohe VOC-Werte durch Kochen, Nahrungsaufnahme, ausgeatmete Luft und/oder Schwitzen erfassen. In Abschnitt 2.1.4 hatte ich Ihnen den Arduino Nicla Sense ME vorgestellt – dieses Board verwendet den Sensor beispielsweise. Eine gute Einführung in die Anwendung des Arduino Nicla Sense ME finden Sie im Arduino Nicla Sense ME Cheat Sheet (https://docs.arduino.cc/tutorials/nicla-sense-me/cheat-sheet). In den Examples zum Nicla Sense ME ist das Auslesen von Accelerometer und Gyroskop sowie Temperatur und Feuchtigkeit gezeigt. Ich möchte hier speziell auf das Erfassen von Umgebungsdaten (Environmental Data) eingehen. Das in Listing 13.3 gezeigte Programm Nicla_EnvironmentalSensor.ino fragt den Temperatur-, Feuchtigkeits-, Druck und Gassensor ab und gibt die erfassten Daten über die Konsole aus. Durch die Verwendung der beiden Librarys Nicla_System.h und Arduino_BHY2.h (getestet jeweils in der Version 2.9.9) werden die Details der Zugriffe auf die Sensoren sehr gut gekapselt, und das Programm selbst besteht nur noch aus den Abfragen der Sensoren selbst. /* * * * * * * * * * *
File: Nicla_EnvironmentalSensor.ino
Base: https://GitHub.com/arduino-
libraries/Arduino_BHY2/tree/main/examples/Standalone
This sketch shows how nicla can be used in standalone mode.
Without the need for an host, nicla can run sketches that
are able to configure the bhi sensors and are able to read all
the bhi sensors data.
This program queries the environmental sensors and controls the on-board
RGB Led according to the value of eCO2.
* 2021-11-10 Claus Kühnel [email protected]
*/
#include "Nicla_System.h"
#include
// from SensorID.h
// SENSOR_ID_TEMP = 128, /* Temperature */
// SENSOR_ID_BARO = 129, /* Barometer */
// SENSOR_ID_HUM = 130, /* Humidity */
// SENSOR_ID_GAS = 131, /* Gas */
// SENSOR_ID_BSEC_LEGACY = 171, /* BSEC 1.x output (legacy, deprecated) */
Sensor temp(SENSOR_ID_TEMP);
Sensor humi(SENSOR_ID_HUM );
Sensor baro(SENSOR_ID_BARO);
Sensor gas(SENSOR_ID_GAS);
// #define SENSOR_DATA_FIXED_LENGTH (30) in SensorTypes.h
SensorBSEC bsec(SENSOR_ID_BSEC_LEGACY);
void setup()
{
Serial.begin(115200);
while(!Serial);
BHY2.begin();
temp.begin();
humi.begin();
baro.begin();
gas.begin();
bsec.begin();
nicla::begin();
nicla::leds.begin();
}
void loop()
{
static auto printTime = millis();
// Update function should be continuously polled
BHY2.update();
if (millis() - printTime >= 5000) // Measuring cycle 5 sec
{
printTime = millis();
nicla::leds.setColor(blue);
delay(100);
Serial.println("\n\nNicla Sense ME as Environmental Sensor\n");
Serial.println(String("Temperature: ") +String(temp.value(),1) +
String(" °C"));
Serial.println(String("Humidity: ") +String(humi.value(),0) +
String(" %rH"));
Serial.println(String("Pressure: ") +String(baro.value(),0) +
String(" hPA"));
Serial.println(String("MOX Resistance: ") +String(gas.value(),0) +
String(" Ohm"));
Serial.println(String("iAQ: ") +String(bsec.iaq_s()));
uint32_t eCO2 = bsec.co2_eq();
Serial.println(String("eCO2: ") +String(eCO2) +String(" ppm"));
Serial.println(String("bVOC: ") +String(bsec.b_voc_eq(),3) +
String(" ppm"));
Serial.println(String("BSEC: ") +bsec.toString());
if (eCO2 < 800) nicla::leds.setColor(green);
if (eCO2 >= 800 && eCO2 < 1200) nicla::leds.setColor(yellow);
if (eCO2 >= 1200) nicla::leds.setColor(red);
}
}
Listing 13.3 Quelltext Nicla_EnvironmentalSensor.ino
Abbildung 13.15 Serielle Ausgaben Nicla_EnvironmentalSensor.ino - iAQ 30
Abbildung 13.16 Serielle Ausgaben Nicla_EnvironmentalSensor.ino - iAQ 307
Die On-Board-RGB-LED habe ich als Zustandsanzeige verwendet. Bei der Einleitung eines Messzyklus blinkt die LED kurz blau auf. Dem folgt dann eine vom ermittelten eCO₂-Wert abgeleitete Zustandsanzeige gemäß Tabelle 13.1 bis zum nächsten Messzyklus.
LED Color Zustand Blau
Beginn Messzyklus
Grün
eCO₂ < 800 ppm
Gelb
800 ppm < eCO₂ 1200 ppm
Tabelle 13.1 Zustandsanzeige CO₂-Ampel
Mit diesem Programmbeispiel halten Sie bereits eine sogenannte CO₂-Ampel in den Händen, die für die Erfassung der Raumluftqualität durchaus brauchbare Werte liefert.
13.2.4 Environmental Sensor AZ-Envy In Abschnitt 5.7 hatte ich Ihnen den Luftqualitätssensor MQ135 vorgestellt. AZ-Delivery bietet mit AZ-Envy ein sehr preiswertes Sensorboard, mit dem durch einen Sensirion SHT30 Temperatur- und Luftfeuchtigkeit und durch einen MQ-2 ein Gasgemisch aus Methan, Butan, LPG und Rauch erfasst werden kann. Der MQ-2-Sensor ist ein Mitglied der umfangreichen MQ-Serie, die unterschiedliche Gasgemische detektieren kann. Eine Übersicht dazu habe ich Ihnen ebenfalls in Abschnitt 5.7 gegeben. Das von Niklas Heinzel entworfene Sensorboard (Abbildung 13.17) weist neben den beiden Sensoren SHT30 und MQ-2 ein ESP8266-12FModul auf, das beide Sensoren ausliest, die Daten aufbereitet und gleichzeitig eine WiFi-Verbindung aufbauen kann.
Abbildung 13.17 AZ-Envy
Der microUSB-Anschluss dient nur der Spannungsversorgung über USB. Die Programmierung muss über einen an die Stiftleiste angeschlossenen FT232RL – USB-TTL-Serial Adapter erfolgen. Im AZDelivery-Blog (https://www.az-delivery.de/blogs/azdelivery-blog-furarduino-und-raspberry-pi/az-envy-das-etwas-andere-microcontroller-board) wird das mit dem zusätzlichen Platzbedarf begründet, was mich jedoch nicht überzeugt. Eine diesbezügliche Anfrage blieb bislang unbeantwortet. Unabhängig hiervon sollten Sie den Beitrag unbedingt lesen, da sehr detailliert die Inbetriebnahme beschrieben wird. Mit einem über Female-Female-Jumper an RX, TX und GND der Stiftleiste angeschlossenen FT232RL – USB-TTL-Serial Adapter habe ich die Inbetriebnahme ohne Probleme vornehmen können. Achtung: RX und TX hier nicht kreuzen! In Abbildung 13.18 sind die erforderlichen Verbindungen für die Entwicklungsphase gezeigt.
Abbildung 13.18 AZ-Envy Beschaltung für die Programmentwicklung
Im Programm ESP8266_AZ-Envy_Data.ino werden Temperatur und Luftfeuchtigkeit mit dem Sensor SHT30 erfasst und angezeigt. Ausgehend von den Kennlinien im Datenblatt des MQ-2 wurde von Sandbox Electronics eine Prozedur für die Bestimmung verschiedener Gase (LPG, CO, Rauch) entwickelt, die Bestandteil der im Programm verwendeten MQ-2-Library ist. Bei Tests an frischer Luft werden die Gasbestandteile bei 0 liegen sein. Bei Messungen in einem belasteten Innenraum können die Werte des MQ-2 Sensors dann auch leicht die im Screenshot in Abbildung 13.19 gezeigten Werte annehmen. AZ-Envy weist ein Problem auf, das in der Anordnung des Sensors SHT30 auf dem Board begründet ist. Der Sensor MQ-2 muss funktionsbedingt beheizt werden, wodurch auch der SHT30 »fremdbeheizt« wird. Auf dem Board sind schon thermische Isolationsmaßnahmen vorgesehen, dennoch ist der Einfluss nicht vollständig eliminiert. Das ist bei ähnlichen Boards nicht anders.
Abbildung 13.19 Serielle Ausgabe ESP8266_AZ-Envy_Data.ino - belasteter Innenraum
Im Diagramm aus Abbildung 13.20 sind die Abweichungen anhand von drei Messpunkten gezeigt. Durch eine lineare Approximation erhält man eine Korrekturmöglichkeit, die auch im Programm verwendet wird. Sicher sollten Sie diese Korrektur durch weitere Messpunkte verbessern, doch das Prinzip wird hier bereits deutlich.
Abbildung 13.20 AZ-Envy Temperatur Kalibrierung
Die Ausgabe der Messwerte über die Konsole ist eine gute Möglichkeit für die Inbetriebnahme einer Messeinrichtung, um die es sich beim AZ-Envy schließlich handelt. Eine andere Möglichkeit ist die Übergabe der Messwerte an einen Webserver, auf den dann über einen Webclient (Webbrowser) zugegriffen werden kann. Mit dem Programmbeispiel ESP8266_Webserver_AZ-Envy.ino bin ich diesen Weg gegangen. Die folgenden Bilder zeigen die Ausgabe über die Konsole (Abbildung 13.21) und die Anzeige der Daten im Webbrowser eines Smartphones (Abbildung 13.22).
Abbildung 13.21 Serielle Ausgabe der Messwerte
Abbildung 13.22 Ausgabe der Messwerte im Webbrowser eines Smartphones
13.3 Open Data aus dem Internet Mit den bisherigen Beispielen habe ich Ihnen gezeigt, wie erhobene Daten auf Servern im Internet abgelegt und so allgemein zugänglich gemacht werden können. In diesem Abschnitt möchte ich auf Daten aus dem Internet zugreifen. Dass einem Controller mit beschränkten Ressourcen da Grenzen gesetzt sind und wie Sie diese teilweise umgehen können, zeige ich Ihnen auch.
13.3.1 OpenWeatherMap In zahlreichen Programmen in diesem Buch hatte ich einen Sensor zur Messung von Temperatur und manchmal auch von Feuchte und Druck eingesetzt. Das war natürlich als Beispiel zu verstehen, aber so lassen sich sehr einfach Daten zur Demonstration und gegebenenfalls auch zur Weiterverarbeitung erzeugen. Will man wirkliche Wetterdaten erfassen, dann ist das nicht mehr ganz so einfach. In meinem Blogbeitrag »Erfassen von Wetterdaten – gar nicht so einfach« unter der URL https://ckblog2016.net/2019/05/02/erfassen-von-wetterdaten-garnicht-so-einfach/ habe ich einige Gedanken zu diesem Thema niedergeschrieben. Ich möchte Ihnen hier das Programm UnoWiFiR2_Weather.ino vorstellen, mit dem Sie von Openweathermap.org bereitgestellte Wetterdaten aus der ganzen Welt abfragen können. Bedingung für den Zugriff auf die Wetterdaten ist, dass Sie sich bei Openweathermap.org registrieren, um den erforderlichen API-Key
zu erhalten. Der Aufruf der aktuellen Wetterdaten erfolgt dann durch einen APICall: api.openweathermap.org/data/2.5/weather? q=Altendorf,CH&appid=87286xxx…xxx8d510
Hinter q= folgt der Ort, für den die Abfrage erfolgen soll. Hier reicht bei eindeutigen Ortsbezeichnungen der Ort allein, sonst kann der Ländercode ergänzt werden. Hinter appid= folgt der von Openweathermap.org zugewiesene API-Key, den ich hier unkenntlich gemacht habe. Der Server beantwortet die Anfrage dann mit einem etwas umfangreichen JSON-String, der alle erforderlichen Informationen enthält (siehe Listing 13.4): {
"coord": {
"lon": 8.83,
"lat": 47.19
},
"weather": [
{
"id": 802,
"main": "Clouds",
"description": "scattered clouds",
"icon": "03d"
}
],
"base": "stations",
"main": {
"temp": 294.05,
"feels_like": 291.02,
"temp_min": 289.82,
"temp_max": 296.48,
"pressure": 1021,
"humidity": 30
},
"wind": {
"speed": 2.1, "deg": 340
},
"clouds": {
"all": 34
},
"dt": 1586619938,
"sys": {
"type": 1,
"id": 6932,
"country": "CH",
"sunrise": 1586580202,
"sunset": 1586628448
},
"timezone": 7200,
"id": 2661776,
"name": "Altendorf",
"cod": 200
}
Listing 13.4 JSON-Antwort von Openweathermap.org
Vom Quelltext des Programms UnoWiFiR2_Weather.ino kann ich Ihnen mit Listing 13.5 wiederum nur die zugriffsrelevanten Dinge erläutern. Sie finden die Datei bei den Materialien zum Buch. Der Quelltext ist kommentiert. Eingebunden werden zu Beginn die Librarys für die WiFiVerbindung und die JSON-Library, mit deren Hilfe der JSON-String auseinandergenommen wird: #include #include #include #include
"arduino_secrets.h"
Den Zugriff über die GET-Abfrage hatte ich bereits erläutert, sodass Sie jetzt sehen können, wie der String schrittweise zusammengesetzt wird. Den API-Key habe ich wieder unkenntlich gemacht. Außerdem ist dieser vorsorglich in der Datei arduino_secrets.h abgelegt. Damit die Daten auch in metrischen Einheiten zurückgegeben werden, wurde mit units=metric ein weiterer Parameter eingeführt: // http://api.openweathermap.org/data/2.5/weather?q=Altendorf,CH&units=metric&
// appid=87286fexxx…xxx8d510
const char* host = "api.openweathermap.org";
const char* url = "/data/2.5/weather";
const char* openweathermapq = "Altendorf, CH"; // chosse your location - here
const char* openweathermapunits = "metric"; // Celsius
String param = String(url) +
"?q=" +openweathermapq +
"&units=" +openweathermapunits +
"&appid=" +appid;
Serial.print("requesting URL: ");
Serial.print(host);
Serial.println(param);
client.print(String("GET ") +param +" HTTP/1.1\r\n" +
"Host: " +host +"\r\n" +
"User-Agent: MKR1000\r\n" +
"Connection: close\r\n\r\n");
Serial.println("request sent\n");
Listing 13.5 QuelltextUnoWiFiR2_Weather.ino – GET Access
Zur Analyse des JSON-Strings wird ein DynamicJsonDocument doc angelegt, in dem die vom Client empfangenen Daten abgelegt werden. Zu JSON finden Sie in Abschnitt 11.1 eine Einführung. Im Debug-Mode können die Daten mithilfe der Funktion serializeJsonPretty(doc, Serial) über die serielle Schnittstelle ausgegeben und im Serial Monitor sichtbar gemacht werden (siehe Listing 13.6). Danach erfolgt elementweise der Zugriff auf die einzelnen Daten im JSON-String. Vergleichen Sie diese mit dem bereits gezeigten JSON-String, und Sie erkennen den Mechanismus. if (client.find("\r\n\r\n")) {
DynamicJsonDocument doc(4096);
DeserializationError err = deserializeJson(doc, client);
if (err)
{
Serial.print(F("deserializeJson() failed: "));
Serial.println(err.c_str());
}
if (DEBUG)
{
serializeJsonPretty(doc, Serial);
Serial.println();
}
// parsed output
const char* name = doc["name"];
Serial.print("City: ");Serial.println(name);
char buffer[64];
const double temp = doc["main"]["temp"];
Serial.print("Temperature: "); Serial.print(temp,2); Serial.println(" °C");
const int humidity = doc["main"]["humidity"];
sprintf(buffer, "Humidity: %d %%r.H.", humidity);
Serial.println(buffer);
const int pressure = doc["main"]["pressure"];
sprintf(buffer, "Pressure: %d hPa", pressure);
Serial.println(buffer);
const double wind = doc["wind"]["speed"];
Serial.print("Wind speed: "); Serial.print(wind,2); Serial.println(" m/s");
const char* weather = doc["weather"][0]["main"];
const char* description = doc["weather"][0]["description"];
sprintf(buffer, "Weather: %s (%s)", weather, description);
Serial.println(buffer);
}
Listing 13.6 QuelltextUnoWiFiR2_Weather.ino – serielle Ausgabe
Da alle Programmaktivitäten in der Funktion setup() gelaufen sind, bleibt die Funktion loop() leer: void loop() {}
Wie Abbildung 13.23 anhand der Ausgaben des Programms UnoWiFiR2_Weather.ino zeigt, übernimmt es den Verbindungsaufbau zum WiFi-Router sowie zu Openweathermap.org, sendet die weiter oben erläuterte Abfrage an den Server und wertet den zurückgesendeten JSON-String aus.
Abbildung 13.23 Ausgabe des Programms »UnoWiFiR2_Weather.ino«
Die hier im Serial Monitor angezeigten Daten können Sie beispielsweise für die Anzeige auf einem LCD aufbereiten. Sie haben damit eine OpenWeatherMap-basierte Wetterstation. Wenn Sie nun die Anfrage über mehrere Orte erweitern, dann haben Sie alle Daten, die für eine Wetteranzeige auf einem grafischen Display erforderlich sind. Mit dem Nextion habe ich Ihnen in Abschnitt 7.7.2 eine Möglichkeit dafür vorgestellt. Abbildung 13.24 zeigt Ihnen einen Vorschlag für eine solche Weiterentwicklung.
Abbildung 13.24 Temperaturanzeige mit hinterlegter Karte
13.3.2 Covid-19-Datenbank In einer Zeit, in der Covid-19 Feinstaub, Diesel und Klima aus dem Mittelpunkt des Interesses verdrängt hat, möchte ich Ihnen zeigen, wie Sie von einem Arduino aus auf diese Daten zugreifen können. Der Umfang dieser Daten übersteigt die Möglichkeiten eines Arduino, sie zu laden und dann mithilfe der JSON-Library zu zerlegen. Aufbauend auf der Auswertung von Corona-Daten der Worldometer-Website (www.worldometers.info/coronavirus/) hat Hartmut Wendt einen Corona-Tracker für den Arduino MKR WiFi 1010 geschrieben:
https://create.arduino.cc/projecthub/hwhardsoft/covid19-realtimemonitor-5f6920 Nach eigenen Angaben wird Worldometer von einem internationalen Team von Entwicklern, Forschern und Freiwilligen betrieben, um einem breiten Publikum auf der ganzen Welt Statistiken zur Verfügung zu stellen. Details zu den Corona-Daten finden Sie unter der URL https://www.worldometers.info/coronavirus/about/. Auf der Basis des Corona-Trackers von Hartmut Wendt habe ich Anpassungen für den Arduino Uno WiFi Rev2 vorgenommen und die Anzeige auf den Serial Monitor beschränkt. Das Ergebnis ist das Programm UnoWiFiR2_CoronaTracker.ino, das ich Ihnen wieder ausschnittsweise erläutern möchte. Zu Beginn werden die Librarys für WiFi und den HTTP-Client eingebunden: #include #include #include #include
"arduino_secrets.h"
Die Instanzen client und http regeln den Zugriff auf den Worldometer-Server: WiFiSSLClient client;
HttpClient http(client,"www.worldometers.info", 443);
Die Funktion setup() dient dem Verbindungsaufbau zum WiFiRouter und bietet nichts Neues. In der Funktion loop() ist eine Liste zur Abfrage der Länderdaten hinterlegt: void loop()
{
check_country("China");
delay(2000);
check_country("US");
delay(2000);
check_country("Italy");
delay(2000);
check_country("Germany");
delay(2000);
check_country("Spain");
delay(2000);
check_country("Austria");
delay(2000);
check_country("Switzerland");
delay(2000);
}
In der Funktion check_Country() erfolgt nun die Abfrage der länderspezifischen Daten. Für Deutschland habe ich die Abfrage vom Webbrowser aus vorgenommen (siehe Abbildung 13.25) und die Daten auch heruntergeladen (siehe Abbildung 13.26).
Abbildung 13.25 Corona-Abfrage für Deutschland
Abbildung 13.26 Download der Daten
Die heruntergeladene HTML-Datei ist immerhin ca. 71 KByte groß – also nichts für unseren Arduino. Deshalb wird in der Funktion check_country() (siehe Listing 13.7) auch die Antwort des Worldometer-Servers zeichenweise gelesen und nach dem String Coronavirus Cases: und der entsprechenden Fallzahl in direkter Nachbarschaft gesucht. Es wird nach folgenden Ausschnitten in der empfangenen HTML-Datei gesucht:
Coronavirus Cases:
36,005,025
Identisch wird nach den Todesfällen (Deaths:) und den Genesenen (Recovered:) gesucht. Listing 13.7 zeigt die vollständige Funktion, die die Daten extrahiert. void check_country(String sCountry)
{
int err =0;
int readcounter = 0;
int read_value_step = 0;
String s1 = "";
String s2 = "";
err = http.get("/coronavirus/country/" +sCountry +"/");
if (err == 0)
{
if (DEBUG) Serial.println("startedRequest ok");
err = http.responseStatusCode();
if (err >= 0)
{
if (DEBUG)
{
Serial.print("Got status code: ");
Serial.println(err);
}
if (DEBUG) Serial.print("\nRequest data for ");
else Serial.println("--------------------------");
Serial.println(sCountry);
// Now we've got to the body, so we can print it out
unsigned long timeoutStart = millis();
char c;
// Whilst we haven't timed out & haven't reached the end of the body
while ( (http.connected() || http.available()) &&
(!http.endOfBodyReached()) &&
((millis() - timeoutStart) < kNetworkTimeout) )
{
if (http.available())
{
c = http.read();
s2 = s2 +c;
if (readcounter < 300) {
readcounter++;
} else {
readcounter = 0;
String tempString = "";
tempString.concat(s1);
tempString.concat(s2);
// check infected first
if (read_value_step == 0) {
int place = tempString.indexOf("Coronavirus Cases:");
if ((place != -1) && (place < 350)) {
read_value_step = 1;
s2 = tempString.substring(place +15);
tempString = s2.substring(s2.indexOf("#aaa") +6);
s1 = tempString.substring(0, (tempString.indexOf("