Android mit Arduinoâ„¢ Due. Manuel di Cerbo
verwendet werden. Der Source-Code muss dabei nicht verändert werden.
Nachdem wir nun unseren ersten Sketch, das Blink-Beispiel aus Abschnitt 2.2, auf den Arduino Due geladen haben, wollen wir dessen Source-Code studieren.
Bei den ersten Zeilen handelt es sich um Kommentarzeilen. Wie in C/C++ üblich, sind mehrzeilige Kommentare durch die Zeichen /* (zu Beginn) bzw. */ (am Ende) und einzeilige Kommentare durch // gekennzeichnet. Im Kommentar der ersten Zeilen wird die Funktion des Programms kurz erläutert.
Die erste für das Programm entscheidende Zeile
int led = 13;
wird verwendet, um den Mikrocontroller-Pin mit der On-board-LED zu definieren. Die LED ist in unserem Fall verbunden mit dem Arduino-Pin Nummer 13. Diese Information entnehmen wir zum Beispiel der Produktwebseite (http://arduino.cc/en/Main/ArduinoBoardDue). Dort finden wir unter Input und Output die folgende Beschreibung:
»L« LED: 13
There is a built-in LED connected to digital pin 13. When the pin is HIGH, the LED is on, when the pin is LOW, it's off. It is also possible to dim the LED because the digital pin 13 is also a PWM output.
Hinweis
Bitte beachten Sie: Als Arduino-Pin Nummer 13 wird derjenige Mikrocontroller-Pin bezeichnet, welcher oben auf dem Board mit der Nummer 13 angeschrieben ist. Es handelt sich nicht etwa um den 13ten Pin des SAM3X-Mikrocontrollers. Die Zuordnung zwischen Arduino und SAM3X-Pins findet man ebenfalls auf der Produktwebseite (http://arduino.cc/en/Hacking/PinMappingSAM3X). Aus der Tabelle entnehmen wir, dass der Arduino-Due-Pin 13 dem SAM3X-Pin PB27 entspricht. Im Datenblatt des SAM3X steht außerdem, dass sich der Pin PB27 am physikalischen Mikrocontroller-Pin mit Nummer 68 befindet. Mit dieser Begebenheit müssen wir uns nicht weiter beschäftigen. Es sollte bloß im Hinterkopf behalten werden, dass es Unterschiede bei der Nummerierung von Arduino-Pins und physikalischen Mikrocontroller-Pins gibt. Insbesondere wenn bereits bestehender C-Code mit Arduino-Source-Code vermischt wird (oder umgekehrt), kann dies eine Stolperfalle darstellen.
Als Nächstes betrachten wir die Funktionen setup() und loop(). Wie die Namen schon vermuten lassen, werden alle Anweisungen innerhalb von loop() in einer Endlos-Schleife ausgeführt. Der Inhalt von setup() hingegen wird nur ein einziges Mal ausgeführt, und zwar ganz zu Beginn des Programmablaufs, noch bevor loop() das erste Mal ausgeführt wird. Bei den Funktionen setup() und loop() handelt es sich um eine Besonderheit von Arduino. Falls Sie schon Erfahrungen mit C-Programmierung haben, fragen Sie sich bestimmt, wo die main()-Funktion geblieben ist. Da Arduino unter der Haube auch nur C/C++ verwendet, gibt es intern natürlich auch eine main()-Funktion. Darin werden dann unsere Methoden setup() und loop() an den entsprechenden Stellen aufgerufen, gemäß folgendem Muster:
int main(void){
…
setup();
// loop forever
for(;;){
loop();
}
return 0; // never reached
}
Die genaue Implementierung der main()-Funktion für den Arduino Due finden Sie übrigens im Arduino-Ordner unter ./hardware/arduino/sam/cores/arduino/main.cpphttp://arduino.cc/en/Reference/HomePage.
Falls Sie noch keine Erfahrungen mit C/C++ haben, merken Sie sich einfach, dass die Funktion setup() nur ein einziges Mal zu Programmbeginn ausgeführt wird. Die Funktion loop() hingegen wird endlos und periodisch aufgerufen. Die Funktionen setup() und loop() sind auch in der offiziellen Language Reference (http://arduino.cc/en/Reference/HomePage) beschrieben.
Innerhalb von setup() sollten also im Idealfall alle Initialisierungen stattfinden, wie zum Beispiel Pin-Konfigurationen. Die Pins eines Mikrocontrollers können grundsätzlich als Eingänge oder Ausgänge konfiguriert werden. Intern speichert ein Mikrocontroller diese Konfiguration in speziellen Registern ab. Das Ändern einer Pin-Konfiguration erfordert also das Schreiben von Registern, und dies wiederum verbraucht kostbare Rechenzeit. Um ehrlich zu sein, in den meisten Fällen würde man kaum eine Performance-Einbuße feststellen können. Dennoch lohnt es sich, dieses Pattern korrekt anzuwenden.
Im Blink-Sketch wird der LED-Pin (Arduino-Pin Nummer 13) als Ausgang konfiguriert. Dies geschieht mit der Funktion pinMode().
void setup() {
// initialize the digital pin as an output.
pinMode(led, OUTPUT);
}
Bei pinMode() handelt es sich ebenfalls um eine spezifische Arduino-Funktion. Der erste Parameter bestimmt die Arduino-Pin-Nummer (vorher wurde led gleich 13 gesetzt). Der zweite Parameter legt fest, ob es sich um einen Eingang oder einen Ausgang handelt. Anstatt OUTPUT könnte zum Beispiel auch INPUT verwendet werden. Wie bereits erwähnt, ist die Arduino-Programmiersprache eine »Cross-Plattform«-Programmiersprache. Die Funktion pinMode() kann für unterschiedliche Arduino-Boards bzw. Mikrocontroller verwendet werden. Je nach Mikrocontroller braucht es dann natürlich eine andere Implementation der pinMode()-Funktion. Bei Interesse findet man die Implementation für den SAM3X des Arduino Due im Arduino-Ordner unter ./hardware/arduino/sam/cores/arduino/wiring_digital.c
Nun betrachten wir die Anweisungen innerhalb der loop()-Funktion.
Die Funktionen sind grundsätzlich selbsterklärend. Mit digitalWrite() wird ein Ausgang gesetzt (HIGH) oder gelöscht (LOW). Mit delay(1000) wird 1000 Millisekunden, also 1 Sekunde, gewartet.
2.5 Serielle Verbindung: Host-Computer und Arduino
In einem ersten Schritt stellen wir eine serielle Verbindung zwischen unserem Host-Computer und dem Arduino Due her. Unser Host-Computer dient dabei als USB-Host, der Arduino ist das USB-Device. Später können wir dann anstatt unseres Computers ein USB-Host-fähiges Android-Gerät verwenden.
Die serielle Verbindung wird aufgrund ihrer Einfachheit sehr häufig zur Kommunikation mit Mikrocontrollern verwendet. Dazu muss der Mikrocontroller mindestens zwei dedizierte Pins RX und TX zur Verfügung stellen. Der RX-Pin (»Receive«) dient dem Mikrocontroller zum Empfangen von Daten; der TX-Pin (»Transmit«) zum Versenden von Daten. Diese Struktur wird je nach Ausführung auch UART (Universal Asynchronous Receiver Transmitter) oder USART (Universal Synchronous Asynchronous Receiver Transmitter) genannt. Der Mikrocontroller des Arduino Due verfügt sogar über vier serielle Schnittstellen. Sie sind auf der Oberseite jeweils mit TX0/RX0, TX1/RX1, TX2/RX2 und TX3/RX3 beschriftet. Die Anschlüsse CANRX/CANTX ermöglichen übrigens eine Kommunikation über den sogenannten CAN(Controller Area Network)-Bus. Die Anschlüsse SDA und SCL werden ihrerseits für das Two-wire Interface (TWI) beziehungsweise I²C verwendet.
Eine serielle Schnittstelle, oft auch COM-Port genannt, gehörte früher praktisch zur Grundausstattung eines jeden Computers. Der meist verwendete RS-232-Standard benutzt neben den zwei RX- und TX-Pins noch sieben weitere Leitungen. Darunter zum Beispiel RTS (Request to Send) und DSR (Data Set Ready). Diese 9-poligen Stecker sind heutzutage größtenteils verschwunden, stattdessen können aber auch USB-zu-seriell-Adapter mit den entsprechenden Treibern verwendet werden. Für eine serielle Verbindung zwischen unserem Host-Computer und dem Arduino brauchen wir allerdings keinen physikalischen Adapter, sondern lediglich ein USB-Kabel. Der USB-Programming-Port des Arduino Due ist direkt mit einem kleinen Mikrocontroller, dem ATMega16U2, verbunden. Dieser ist seinerseits wieder mit den RX0/TX0-Pins des Haupt-Mikrocontrollers SAM3X verbunden. Auf dem ATMega16U2 läuft also eine USB-zu-seriell-Firmware. Diese wandelt das USB-Protokoll auf der Computer-Seite in serielle Kommunikation auf der Mikrocontroller-Seite um, und umgekehrt.
Bild