Die Experimente dieses Kapitels konzentrieren sich auf einzelne Aspekte des ftDuino. Sie veranschaulichen einen Effekt oder ein Konzept und verwenden dafür nur minimale externe Komponenten. Die Experimente stellen an sich keine vollständigen Modelle dar, können aber oft als Basis dafür dienen.
Beispiele für komplexe Modelle finden sich im Kapitel 7.
Schwierigkeitsgrad: ★☆☆☆☆
Dieses sehr einfache Modell besteht nur aus einem Taster und einer Lampe und bildet die Funktion einer typischen Treppenhausbeleuchtung nach. Um Energie zu sparen wird hier nicht einfach ein Kippschalter genommen, um das Licht zu schalten. Stattdessen wird ein Taster verwendet und jeder Druck auf den Taster schaltet das Licht nur für z.B. zehn Sekunden ein. Wird während dieser Zeit der Taster erneut gedrückt, so verlängert sich die verbleibende Zeit wieder auf volle zehn Sekunden. Nach Ablauf der zehn Sekunden verlischt das Licht und das Spiel beginnt von vorn.
Der folgende Sketch findet sich bei installierter ftDuino-Unterstützung im Menü der Arduino-IDE unter Datei ► Beispiele ► FtduinoSimple ► LampTimer.
1 /*
2 LampTimer - Lampen-Zeitschaltuhr
3
4 (c) 2017 by Till Harbaum <till@harbaum.org>
5
6 Schaltet eine Lampe an Ausgang O1 für 10 Sekunden ein,
7 sobald ein Taster an Eingang I1 gedrückt wird.
8 */
9
10 #include <FtduinoSimple.h>
11
12 uint32_t startzeit = 0;
13
14 // Die Setup-Funktion wird einmal ausgeführt, wenn Reset gedrückt oder
15 // das Board gestartet wird.
16 void setup() { }
17
18 // Die Loop-Funktion wird endlos immer und immer wieder ausgeführt
19 void loop() {
20 // Teste, ob der Taster an I1 gedrückt ist
21 if(ftduino.input_get(Ftduino::I1)) {
22 // merke Startzeit
23 startzeit = millis();
24
25 // schalte Lampe ein (Ausgang HI)
26 ftduino.output_set(Ftduino::O1, Ftduino::HI);
27 }
28
29 // gültige Startzeit und seitdem mehr als 10 Sekunden
30 // (10.000 Millisekunden) verstrichen?
31 if((startzeit != 0) &&
32 (millis() > startzeit + 10000)) {
33 // vergiss Startzeit
34 startzeit = 0;
35 // schalte Lampe aus (Ausgang OFF)
36 ftduino.output_set(Ftduino::O1, Ftduino::OFF);
37 }
38 }
39
Die für die Lampen-Zeitschaltung nötigen Funktionen des ftDuino sind sehr einfach und die Anwendung lässt sich mit der einfachen FtduinoSimple-Bibliothek (siehe Abschnitt 9.1) abdecken.
Der Arduino-Sketch enthält eine leere setup()-Funktion, da keine Initialisierung nötig ist. Sämtliche Funktionalität steckt in der loop()-Funktion.
Die Taste an I1 wird über input_get() permanent abgefragt. Ist sie gedrückt, so wird die aktuelle Zeit seit Gerätestart in Millisekunden mit der Funktion millis() abgefragt und in der Variablen startzeit gespeichert und die Lampe wird eingeschaltet. War die Lampe bereits an, dann bewirkt dieses zusätzliche Einschalten nichts, aber der bereits gesetzte Zeitwert in startzeit wird durch den aktuellen ersetzt.
Unabhängig davon wird permanent getestet, ob startzeit einen gültigen Wert enthält und ob die aktuelle Systemzeit bereits mehr als zehn Sekunden (10.000 Millisekunden) nach dem dort gespeicherten Wert liegt. Ist das der Fall, dann sind seit dem letzten Tastendruck mehr als zehn Sekunden vergangen und die Lampe wird ausgeschaltet sowie der Wert in startzeit auf Null gesetzt, um ihn als ungültig zu markieren.
Sorge dafür, dass die Lampe nach jedem Tastendruck 20 Sekunden lang an bleibt.
In Zeile 32 muss der Wert 10000 durch den Wert 20000 ersetzt werden, damit die Lampe 20000 Millisekunden, also 20 Sekunden eingeschaltet bleibt.
31 if((startzeit != 0) &&
32 (millis() > startzeit + 20000)) {
Sorge dafür, dass ein weiterer Druck auf den Taster, während die Lampe bereits leuchtet, die verbleibende Zeit nicht wieder auf 10 Sekunden verlängert.
Vor der Zuweisung in Zeile 23 muss eine zusätzliche Abfrage eingefügt werden, die nur dann einen neue Wert setzt, wenn bisher keiner gesetzt war. Beide Zeilen zusammen sehen dann so aus:
23 if(startzeit == 0)
24 startzeit = millis();
Schließt Du statt der Lampe eine Leuchtdiode an (der rote Anschluss der Leuchtdiode muss an Ausgang O1), dann wirst Du etwas merkwürdiges bemerken, wenn das Licht eigentlich aus sein sollte: Die Leuchtdiode leuchtet trotzdem ganz schwach, obwohl der Ausgang doch OFF ist. Wie kommt das?
Durch eine Lampe oder Leuchtdiode fließt ein Strom, wenn zwischen den beiden Anschlüssen ein Spannungsunterschied besteht. Den einen Anschluss haben wir fest mit Masse beziehungsweise 0 Volt verbunden, der andere ist offen und wird von den Bauteilen im ftDuino nicht mit Spannung versorgt. Anders als bei einem mechanischem Schalter ist diese Trennung bei dem im ftDuino als sogenannter Ausgangstreiber verwendeten Halbleiterbaustein aber nicht perfekt. Ein ganz kleiner sogenannter Leckstrom fließt trotzdem zur 9V-Versorgungsspannung. Dieser kleine Strom reicht nicht, die Lampe zum Leuchten zu bringen. Aber er reicht, die wesentlich effizientere Leuchtdiode ganz leicht aufleuchten zu lassen.
Lässt sich daran etwas ändern? Ja! Statt den Ausgang komplett unbeschaltet zu lassen können wir dem Ausgangstreiber im ftDuino sagen, dass er den Ausgang fest auf Masse (0 Volt) schalten soll. Beide Anschlüsse der Leuchtdiode liegen dann fest auf Masse und die Einflüsse irgendwelcher Leckströme treten nicht mehr in Erscheinung. Dazu muss in der Zeile 36 die Konstante OFF durch LO ersetzt werden. LO steht für low, englisch niedrig und meint in diesem Fall 0 Volt. Die Leuchtdiode erlischt nun komplett nach Ablauf der Zeit.
36 ftduino.output_set(Ftduino::O1, Ftduino::LO);
Direkt nach dem Einschalten des ftDuino leuchtet die Leuchtdiode aber
nach wie vor. Vielleicht findest Du selbst heraus, wie sich das ändern
lässt. Tipp: Die bisher unbenutzte setup()-Funktion könnte
helfen.
Mehr dazu gibt es im Abschnitt 6.8.
Schwierigkeitsgrad: ★☆☆☆☆
Ein Not-Aus-Schalter kann Leben retten und scheint eine einfache Sache zu sein: Man drückt einen Taster und die betreffende Maschine schaltet sich sofort ab. Im Modell stellt ein XS-Motor mit Ventilator an Ausgang M1 die Maschine dar. Ein Taster an Eingang I1 bildet den Not-Aus-Taster.
1 /*
2 EmergencyStop - Not-Aus
3
4 (c) 2017 by Till Harbaum <till@harbaum.org>
5
6 Schaltet einen Ventilator aus, sobald der Not-Aus-Taster
7 betätigt wird.
8 */
9
10 #include <FtduinoSimple.h>
11
12 // Die Setup-Funktion wird einmal bei Start des Systems ausgeführt
13 void setup() {
14 // Ventilator bei Start des Systems einschalten
15 ftduino.motor_set(Ftduino::M1, Ftduino::LEFT);
16
17 // Ausgang der internen roten LED aktivieren
18 pinMode(LED_BUILTIN, OUTPUT);
19 // und LED ausschalten
20 digitalWrite(LED_BUILTIN, LOW);
21 }
22
23 // Die Loop-Funktion wird endlos immer und immer wieder ausgeführt
24 void loop() {
25 // Teste, ob der Taster an I1 gedrückt ist
26 if(ftduino.input_get(Ftduino::I1)) {
27 // Motor bremsen
28 ftduino.motor_set(Ftduino::M1, Ftduino::BRAKE);
29 // interne rote LED einschalten
30 digitalWrite(LED_BUILTIN, HIGH);
31 }
32 }
33
Der Sketch ist sehr kurz und einfach. In der setup()-Funktion wird in Zeile 15 bei Sketchstart der Motor gestartet. Zusätzlich wird in den Zeilen 18 bis 20 die rote interne Leuchtdiode des ftDuino für die spätere Verwendung aktiviert, aber zunächst ausgeschaltet gelassen.
In der loop()-Funktion wird in Zeile 26 permanent abgefragt, ob der Not-Aus-Taster geschlossen wurde. Ist das der Fall, dann wird der Motor in Zeile 28 sofort gestoppt und in Zeile 30 die rote Leuchtdiode eingeschaltet. Der Motor wird bewusst per BRAKE gestoppt statt OFF. Auf diese Weise wird der Motor kurzgeschlossen und aktiv gebremst, während er andernfalls langsam auslaufen würde, was im Notfall eine Gefahr darstellen würde.
Not-Taster sind zwar an vielen Maschinen vorhanden. Glücklicherweise werden sie aber nur sehr selten wirklich benötigt. Das hat den Nachteil, dass kaum jemand bemerken wird, wenn mit dem Not-Aus-Taster etwas nicht stimmt. Anfälliger als der Taster selbst sind oft die Kabel und es kann im Arbeitsalltag leicht passieren, dass ein Kabel beschädigt wird. Oft sieht man das dem Kabel nicht an, wenn z.B. die Ummantlung unbeschädigt aussieht, durch zu starke Belastung aber dennoch die Kupferleiter im Inneren unterbrochen sind. Der Resultat ist ein sogenannter Kabelbruch.
Du musst kein Kabel durchreissen. Es reicht, wenn Du einen der Stecker am Kabel, das den Taster mit dem ftDuino verbindet, heraus ziehst. Der Not-Aus-Taster funktioniert dann nicht mehr und die Maschine lässt sich nicht stoppen. Eine gefährliche Situation.
Die Lösung für das Problem ist überraschend einfach. Wir haben unseren Not-Aus-Taster als Schließer angeschlossen. Das bedeutet, dass der Kontakt geschlossen wird, wenn der Taster betätigt wird. Man kann den fischertechnik-Taster aber auch als Öffner verwenden. Der Kontakt ist dann im Ruhezustand geschlossen und wird bei Druck auf den Taster geöffnet.
Mit dem aktuellen Sketch geht die Maschine bei einem Kabelbruch sofort in den Notzustand, da der Taster ja sofort als geschlossen erkannt wird. Also muss auch im Sketch die Logik herum gedreht werden. Das passiert durch folgende Änderung in Zeile 26:
26 if(!ftduino.input_get(Ftduino::I1)) {
Man muss genau hinschauen, um den Unterschied zu sehen. Hinter der
öffnenden Klammer steht nun aus Ausrufezeichen, das in der
Programmiersprache C für die logische Negation eines Ausdrucks
steht. Die Bedingung wird nun also ausgeführt, wenn der Taster
nicht geschlossen ist. Nach dieser Änderung sollte sich die
Maschine wieder genau wie ursprünglich verhalten. Mit einer kleinen
Änderung: Zieht man nun einen der Stecker am Not-Aus-Taster heraus, so
stoppt die Maschine sofort. Bei einem Kabelbruch würde das ebenfalls
passieren.
So eine Schaltung nennt man auf englisch ``Fail-Safe'': Wenn etwas kaputt geht, dann wechselt die Schaltung in einen sicheren Zustand. Der fischertechnik-3D-Drucker verwendet diese Schaltung zum Beispiel für die Endlagentaster. Ist hier ein Kabel abgerissen, dann fährt der Drucker seine Motoren nicht gewaltsam gegen die Endanschläge der Achsen. Stattdessen verweigert der Drucker die Arbeit komplett, sobald die Verbindung zu einem Endlagentaster unterbrochen ist.
Ein Kabel kann nicht nur unterbrochen werden. Es kann auch passieren, dass ein Kabel z.B. so stark gequetscht wird, dass die inneren Leiter Kontakt miteinander bekommen. Das passiert wesentlich seltener, stellt aber ebenfalls eine realistische Gefahr dar.
Vor diesem Fall würde unsere verbesserte Notschaltung nicht schützen und der Not-Aus-Taster würde in dem Fall wieder nicht funktionieren. Wir brauchen also eine Variante, bei der weder der geschlossene noch der offene Zustand der Verbindung als ``gut'' erkannt wird.
Die Lösung ist in diesem Fall etwas aufwändiger. Es müssen nun mindestens drei Zustände unterschieden werden: ``normal'', ``unterbrochen'' und ``kurzgeschlossen''. Reine Schalteingänge können aber nur die beiden Zustände ``geschlossen'' und ``offen'' unterscheiden.
Die Lösung ist, die analogen Fähigkeiten der Eingänge zu nutzen. Dazu kann man z.B. direkt am Taster einen 100Ω-Widerstand in die Leitung integrieren.
Im Normalfall ist der Taster geschlossen und der am Eingang I1 zu messende Widerstand beträgt 100Ω. Ist die Leitung unterbrochen, dann ist der Widerstand unendlich hoch. Und ist die Leitung kurzgeschlossen, dann ist der Widerstand nahe 0Ω. Die Maschine darf also nur dann laufen, wenn der Widerstand nahe an 100Ω ist. Etwas Toleranz ist nötig, da der genau Wert des verwendeten Widerstands Fertigungstoleranzen unterworfen ist und auch der geschlossene Taster sowie sein Anschlusskabel über einen eigenen sehr geringen Widerstand verfügen, der den gemessenen Gesamtwiderstand beeinflusst.
Warum muss der Widerstand nahe am Taster angebracht werden? Was passiert, wenn er nahe am ftDuino eingesetzt wird und dann ein Kurzschluss im Kabel zwischen Widerstand und Taster auftritt?
Schwierigkeitsgrad: ★★☆☆☆
Wenn man eine Lampe mit variierender Helligkeit leuchten lassen möchte oder einen Motor mit regelbarer Geschwindigkeit laufen lassen will, dann benötigt man eine Möglichkeit, die Energieaufnahme der Lampe oder des Motors zu beeinflussen. Am einfachsten klappt das mit einer einstellbaren Spannungsquelle. Bei höherer Spannung steigt auch die Energieaufnahme der Lampe und sie leuchtet heller und der Motor dreht sich schneller, bei niedrigerer Spannung wird die Lampe dunkler und der Motor dreht sich langsamer. Für die Analogausgänge des ftDuino bedeutet das, dass sie eine zwischen 0 und 9 Volt kontinuierlich (analog) einstellbare Spannung ausgeben können sollen, um Lampen und Motoren von völliger Dunkelheit beziehungsweise Stillstand bis zu maximaler Helligkeit beziehungsweise Drehzahl betreiben zu können.
Der Erzeugung variabler Spannungen ist technisch relativ aufwändig. Es gibt allerdings einen einfachen Weg, ein vergleichbares Ergebnis zu erzielen. Statt die Spannung zu senken schaltet man die Spannung periodisch nur für sehr kurze Momente ein. Schaltet man die Spannung z.B. nur 50% der Zeit ein und 50% der Zeit aus, so wird über die Gesamtzeit gesehen nur die Hälfte der Energie übertragen. Ob man das Ergebnis als Blinken der Lampe oder als Stottern des Motors wahrnimmt oder ob die Lampe einfach mit halber Helligkeit leuchtet und der Motor mit halber Drehzahl dreht ist von der Geschwindigkeit abhängig, mit der man die Spannung ein- und ausschaltet.
1 /*
2 Pwm - Pulsweitenmodulation
3
4 (c) 2017 by Till Harbaum <till@harbaum.org>
5 */
6
7 #include <FtduinoSimple.h>
8
9 uint16_t schaltzeit = 8192; // 8192 entspricht je 1/2 Sekunde an und aus
10
11 // Die Setup-Funktion wird einmal ausgeführt, wenn Reset gedrückt oder
12 // das Board gestartet wird.
13 void setup() { }
14
15 // warte die angegebene Zeit. Der "zeit"-Wert 8192 soll dabei einer halben Sekunde
16 // entsprechen. Es muss also "zeit" mal 500000/8192 Mikrosekunden gewartet werden
17 void warte(uint16_t zeit) {
18 while(zeit--)
19 _delay_us(500000/8192);
20 }
21
22 // Die Loop-Funktion wird endlos immer und immer wieder ausgeführt
23 void loop() {
24 static uint8_t an_aus = false; // der aktuelle Ausgang-an/aus-Zustand
25 static uint8_t i1=false, i2=false; // letzter Zustand der Tasten an I1 und I2
26
27 // ist die Taste an I1 gedrückt?
28 if(ftduino.input_get(Ftduino::I1)) {
29 // und war die Taste vorher nicht gedrückt und ist die
30 // aktuelle Schaltzeit kleiner 8192?
31 if(!i1 && (schaltzeit < 8192)) {
32 // dann verdopple die Schaltzeit
33 schaltzeit *= 2;
34 // warte eine Millisekunde, falls die Taste nachprellt
35 _delay_ms(1);
36 }
37 // merke, dass die Taste an I1 zur Zeit gedrückt ist
38 i1 = true;
39 } else
40 // merke, dass die Taste an I1 zur Zeit nicht gedrückt ist
41 i1 = false;
42
43 // ist die Taste an I2 gedrückt?
44 if(ftduino.input_get(Ftduino::I2)) {
45 // und war die Taste vorher nicht gedrückt und ist die
46 // aktuelle Schaltzeit größer 1?
47 if(!i2 && (schaltzeit > 1)) {
48 // dann halbiere die Schaltzeit
49 schaltzeit /= 2;
50 // warte eine Millisekunde, falls die Taste nachprellt
51 _delay_ms(1);
52 }
53 // merke, dass die Taste an I2 zur Zeit gedrückt ist
54 i2 = true;
55 } else
56 // merke, dass die Taste an I2 zur Zeit nicht gedrückt ist
57 i2 = false;
58
59 // schalte den Ausgand O2 je nach Zustand der an_aus-Variable an oder aus
60 if(an_aus)
61 // wenn der aktuelle an_aus-Zustand wahr ist, dann schalte den Ausgang ein
62 ftduino.output_set(Ftduino::O1, Ftduino::HI);
63 else
64 // wenn der aktuelle an_aus-Zustand unwahr ist, dann schalte den Ausgang aus
65 ftduino.output_set(Ftduino::O1, Ftduino::OFF);
66
67 // warte die aktuelle Schaltzeit
68 warte(schaltzeit);
69
70 // wechsel den an_aus-Zustand
71 an_aus = !an_aus;
72 }
73
74
Der Sketch schaltet den Ausgang O1 in der loop()-Funktion in den Zeilen 60 bis 71 kontinuierlich ein und aus. Je nach Wert der Variable an_aus wird der Ausgang in Zeile 62 auf 9 Volt (HI) geschaltet oder in Zeile 65 ausgeschaltet (von der Spannungsversorgung getrennt). In Zeile 71 wird in jedem Durchlauf der loop()-Funktion der Zustand der Variable an_aus gewechselt, so dass der Ausgang im in jedem Durchlauf im Wechsel ein- und ausgeschaltet wird.
Nach jeden An/Aus-Wechsel wird in Zeile 68 etwas gewartet. Wie lange gewartet wird steht in der Variablen schaltzeit Sie gibt die Wartezeit in 1/8192 halben Sekunden an. Dazu wird in der Funktion wait() in Zeile 19 so oft 500000/8192 Mikrosekunden gewartet wie in der Variablen schaltzeit angegeben. Warum halbe Sekunden? Weil zweimal pro Zyklus gewartet wird, einmal wenn der Ausgang eingeschaltet ist und einmal wenn er ausgeschaltet ist. Wird jeweils eine halbe Sekunde gewartet, so dauert der gesamte Zyklus eine Sekunde und der Ausgang wird einmal pro Sekunde für eine halbe Sekunde eingeschaltet. Der Ausgang wechselt also mit einer Frequenz von 1/Sek. oder einem Hertz.
Durch einen Druck auf den Taster an I1 (Zeile 28) kann der Werte der Variablen schaltzeit verdoppelt (Zeile 33) und mit einem Druck auf den Taster an I2 (Zeile 44) halbiert (Zeile 49) werden. Dabei wird der Wert von Schaltzeit auf den Bereich von 1 (Zeile 47) und 8192 (Zeile 31) begrenzt. Nun wird auch klar, warum dieser merkwürdig ``krumme'' Wert 8192 gewählt wurde: Da 8192 eine Zweierpotenz (213) ist lässt der Wert sich ohne Rundungsfehler bis auf 1 hinunterteilen und wieder hochmultiplizieren.
Da die Tasten nur beim Wechsel zwischen an und aus abgefragt werden muss man den Taster bei niedrigen Frequenzen einen Moment gedrückt halten, bis sich die Blinkfrequenz verändert.
Wenn der Sketch startet leuchtet die Lampe einmal pro Sekunde für eine halbe Sekunde auf. Ein (langer) Druck auf den Taster an I2 halbiert die Wartezeit und die Lampe blinkt zweimal pro Sekunde. Nach einem zweiten Druck auf den Taster blinkt sie viermal. Nach dem sechsten Druck blinkt sie 32 mal pro Sekunde, was nur noch als leichtes Flackern wahrnehmbar ist und nach dem siebten Druck gar 64 mal. Frequenzen oberhalb circa 50 Hertz kann das menschliche Auge nicht mehr auflösen und die Lampe scheint mit halber Helligkeit zu leuchten. Die Frequenz weiter zu erhöhen hat dann keinen erkennbaren Effekt mehr.
Es ist in diesem Aufbau nicht nur das menschliche Auge, das träge ist. Die Lampe ist ebenfalls träge. Es dauert eine Zeit, bis sich ihr Glühfaden aufheizt und die Lampe leuchtet und es dauert auch eine Zeit, bis sich der Glühfaden wieder so weit abkühlt, dass die Lampe nicht mehr leuchtet.
Wesentlich schneller als Glühlampen sind Leuchtdioden. In ihnen muss sich nichts aufheizen oder abkühlen, sondern das Licht entsteht direkt durch optoelektrische Effekte im Halbleitermaterial der Leuchtdiode. Schließt man statt der Lampe eine Leuchtdiode an (rot markierter Anschluss an Ausgang O1), dann sieht das Verhalten zunächst ähnlich aus und wieder scheint ab einer Frequenz von 64 Hertz die Leuchtdiode gleichmäßig mit halber Helligkeit zu leuchten. Viele Menschen nehmen 64 Hz allerdings noch als leichtes Flimmern wahr und erst ab 100Hz redet man von einer wirklich flimmerfreien Darstellung.
Man kann das Flimmern der Leuchtdiode aber auch bei diesen Frequenzen noch beobachten, wenn sich die Leuchtdiode bewegt. Nutzt man ein etwas längeres Kabel, so dass die Leuchtdiode sich frei bewegen lässt und bewegt sie dann in einer etwas abgedunkelten Umgebung schnell hin- und her, so wird der Eindruck einer Reihe von unterbrochenen Leuchtstreifen entstehen.
Je höher die PWM-Frequenz ist, desto kürzer sind die sichtbaren Leuchtstreifen.
Dieses Experiment kann man auch mit der Lampe wiederholen. Durch die Trägheit der Lampe sieht man nur einen durchgehenden Leuchtstreifen. Allerdings sollte man nicht allzu wild vorgehen, da der empfindliche Glühfaden einer leuchtenden Lampe bei Erschütterung leicht kaputt geht. Leuchtdioden sind auch in dieser Beziehung robust und lassen sich selbst von starken Erschütterungen nicht beeindrucken.
Ein Motor ist ebenfalls träge und nicht in der Lage, beliebig schnellen An-/Aus-Signalen zu folgen. Schon bei recht niedrigen PWM-Frequenzen dreht sich der Motor kontinuierlich mit halber Drehzahl. Das dabei vornehmlich zu vernehmende Geräusch ist das Laufgeräusch des Motors.
Wenn man den Motor aber mechanisch blockiert, indem man ihn z.B. mit der Hand festhält, dann wird das Laufgeräusch unterdrückt und ein anderer Effekt wird hörbar: Die Spulen im Motor wirken wie ein Lautsprecher und man kann die PWM-Frequenz bei blockiertem Motor als Ton hören. Eine Veränderung der PWM-Frequenz hat dabei einen deutlich hörbaren Unterschied der Tonhöhe zur Folge.
Je höher die PWM-Frequenz, desto höher der am blockierten Motor hörbare Ton.
Im Fall der Lampe scheint eine höhere PWM-Frequenz ein reiner Vorteil zu sein, da das Flimmern mit höherer Frequenz abnimmt. Am Motor kann aber ein negativer Effekt beobachtet werden.
Läuft der Motor frei, so hängt die gehörte Tonhöhe des Motor-Laufgeräuschs mit seiner Drehgeschwindigkeit zusammen, während das PWM-Geräusch der vorigen Aufgabe in den Hintergrund tritt. Je schneller der Motor dreht, desto höher die Frequenz des Laufgeräuschs und umgekehrt.
Erhöht man nun die PWM-Frequenz, dann sinkt die Frequenz der Töne, die der Motor abgibt leicht. Er wird offensichtlich mit steigender PWM-Frequenz langsamer. Dieser Effekt ist damit zu erklären, dass der Motor eine sogenannte induktive Last darstellt. Er besteht im Wesentlichen aus Spulen, sogenannten Induktoren. Der Widerstand einer induktiven Last ist abhängig von der Frequenz einer angelegten Wechselspannung. Und nichts anderes ist das durch die PWM erzeugte An-/Aus-Signal. Je höher die Frequenz, desto höher der Widerstand der Spule und es fließt weniger Strom durch die Spule.
Es ist technisch möglich, die Ausgangsspannung zu glätten und diesen Effekt zu mildern. Diese Auslegung so einer Glättung ist allerdings von der verwendeten PWM-Frequenz und der Stromaufnahme des Motors abhängig. Außerdem beeinflusst sie das generelle Schaltverhalten des Ausgangs. Der Einsatz einer entsprechenden Glättung im ftDuino kommt daher nicht in Frage, da die universelle Verwendbarkeit der Ausgänge dadurch eingeschränkt würde.
Ziel bei der Auswahl der PWM-Frequenz ist also eine Frequenz, die hoch genug ist, um Lampenflackern oder Motorstottern zu verhindern, die aber dennoch möglichst gering ist, um induktive Widerstände in den Wicklungen der Motoren zu minimieren. Eine PWM-Frequenz von 100-200Hz erfüllt diese Bedingungen.
Die Motordrehzahl lässt sich durch das Verhältnis der An- und Ausphasen während der Pulsweitenmodulation beeinflussen. In den bisherigen Versuchen waren die An- und Ausphase jeweils gleich lang. Verändert man das Verhältnis der beiden Phasen, dann lässt sich die Helligkeit einer Lampe oder die Drehzahl eines Motors steuern. Die PWM-Frequenz kann dabei konstant bleiben.
Je länger die eingeschaltete Phase gegenüber der ausgeschalteten, desto heller leuchtet die Lampe und desto schneller dreht der Motor. Der genaue Zusammenhang zwischen Lampenhelligkeit und PWM-Verhältnis ist mangels entsprechender Messmöglichkeit nicht einfach festzustellen. Die sogenannten Encoder-Motoren haben aber eine eingebaute Möglichkeit zur Geschwindigkeitsmessung. Im Fall der TXT-Encodermotoren erzeugen diese Encoder 63 Signalimpulse pro Umdrehung der Achse. Man kann also durch Auswertung der Encodersignale an den Zählereingängen des ftDuino die Drehzahl des Motors feststellen.
Das Beispiel Datei ► Beispiele ► Ftduino ► PwmSpeed regelt das An-/Ausverhältnis der PWM langsam von 0 auf 100% hoch und misst dabei kontinuierlich für jeweils eine Sekunde die am Eingang C1 anliegenden Impulse. Diese werden in Umdrehungen pro Minute umgerechnet und ausgegeben. Dabei kommt die vollständige Bibliothek Ftduino zum Einsatz, die die eigentliche Erzeugung der PWM-Signale bereits mitbringt. Die Erzeugung des PWM-Signals passiert vollständig im Hintergrund, so dass der Sketch selbst lediglich den Motor startet und dann eine Sekunde wartet.
Speist man die so gewonnenen Daten in den sogenannten ``seriellen Plotter'', der sich im Menü der Arduino-IDE unter Werkzeuge ► Serieller Plotter befindet, so kann man die Messergebnisse anschaulich visualisieren.
Auf der horizontalen Achse ist das PWM-Verhältnis aufgetragen, beginnend mit ``dauerhaft aus'' ganz links bis ``dauerhaft an'' ganz rechts. Auf der vertikalen Achse ist die gemessene Drehzahl in Umdrehungen pro Minute dargestellt. Man sieht, dass der Zusammenhang im Leerlauf nicht linear ist. Bereits bei nur circa 25% der Zeit eingeschaltetem Signal wird 90% der maximalen Motordrehzahl erreicht.
Man kann z.B. indem man den Motor eine konstante Last anheben lässt nachprüfen, wie sich diese Kurve und Last verändert.
Schwierigkeitsgrad: ★★★★☆
Gängige Elektromotoren, wie sie üblicherweise in Spielzeug eingesetzt werden sind sogenannte Asynchronmotoren. Diese in der Regel mit Gleichspannung versorgten Motoren zeichnen sich dadurch aus, dass sie beim Anlegen einer Spannung sofort anfangen, sich zu drehen. Die Drehzahl richtet sich dabei nur indirekt nach äußeren Einflüssen und der Motor dreht letztlich so schnell es ihm möglich ist. Für viele Anwendungen ist diese Art Motor sehr gut geeignet. Modellautos lassen sich ohne weitere Steuerung motorisieren und fahren auf mit diesen Motoren so schnell wie gerade möglich. Auch fischertechnik setzt diese Motoren in den meisten Fällen ein und der ftDuino erlaubt es, sie direkt an jeweils einen Motorausgang M1 bis M4 anzuschließen.
Aber es gibt Anwendungen, in denen diese Motorfamilie sehr große Schwächen zeigt. So ist es sehr schwierig, mit einfachen Asynchronmotoren eine exakte Drehzahl zu erreichen beziehungsweise eine exakte Position anzufahren. Die Encoder-Motoren von fischertechnik versuchen dies durch zusätzliche Hardware zu ermöglichen. Aber auch diesem Vorgehen sind Grenzen gesetzt, speziell bei den fischertechnik-Encoder-Motoren, die nicht in der Lage sind, die Drehrichtung zu erfassen.
Für Aufgaben, bei denen es auf exaktes reproduzierbares Verhalten des Motors ankommt, gibt synchron arbeitende Motoren wie die sogenannten Schrittmotoren. Gängige Anwendungen dafür sind heutzutage Scanner und 3D-Drucker, aber auch die früher verwendeten Diskettenlaufwerke und frühe Festplatten verwendeten Schrittmotoren. Erkennbar ist die Nutzung von Schrittmotoren auch am charakteristischen Betriebsgeräusch, das findige Tüftler sogar nutzen, um mit solchen Motoren Musik zu erzeugen1 .
Gängige Schrittmotoren bestehen aus einem drehbar gelagerten Anker aus Permanentmagneten, der von Elektromagneten umgeben ist. Der Permanentmagnet richtet sich entsprechend den ihm umgebenden Magnetfeldern aus. Im Spannungslosen Zustand lässt sich die Achse des Motors vergleichsweise leicht drehen. Der dabei spürbare Widerstand resultiert daraus, dass der Permanentmagnet von den Eisenkernen der Elektromagnete auch im spannungslosen Zustand angezogen wird.
Der in der Abbildung dargestellte vereinfachte Schrittmotor verfügt über einen Permanentmagneten und zwei Elektromagnete. Reale Schrittmotoren haben in der Regel mehr als zwei Spulen und der Anker bildet auch mehr als nur zwei magnetische Pole ab. Auf das Funktionsprinzip hat diese Vereinfachung keine Auswirkungen.
Übliche sogenannte bipolare Schrittmotoren verfügen über vier Anschlüsse, jeweils zwei für jeden der beiden Elektromagneten. Durch Anlegen einer Spannung werden die Elektromagnete magnetisiert. In der Folge richtet sich der Anker entsprechend aus. Die Polarität der angelegten Spannung bestimmt die Richtung des Magnetfelds der Elektromagneten.
Sind immer beide Spulen unter Spannung, so gibt es vier verschiedene Ausrichtungen der beiden Elektromagnetfelder und der Anker nimmt jeweils vier unterschiedliche Positionen ein. Wird eine entsprechende sich wiederholende Signalfolge an die Elektromagneten angelegt, so folgt der Anker den Signalen und dreht sich. Er folgt dabei exakt den sich wechselnden Magnetfeldern und dreht sich synchron zum angelegt Signalmuster. Geschwindigkeit und Position des Motors sind auf diese Weise exakt vorhersagbar. Sind immer alle Spulen unter Spannung und durchläuft der Zyklus daher genau vier Zustände, so spricht man von einer Vollschrittsteuerung.
Ein Sketch, der kontinuierlich das entsprechende Signalmuster erzeugt sieht folgendermaßen aus:
while(1) {
ftduino.motor_set(Ftduino::M1, Ftduino::LEFT);
delay(5);
ftduino.motor_set(Ftduino::M2, Ftduino::LEFT);
delay(5);
ftduino.motor_set(Ftduino::M1, Ftduino::RIGHT);
delay(5);
ftduino.motor_set(Ftduino::M2, Ftduino::RIGHT);
delay(5);
}
Ein vollständiges Beispiel findet sich in der Arduino-IDE unter
Datei ► Beispiele ► FtduinoSimple ► StepperMotor.
Während sich der dargestellte vereinfachte Schrittmotor pro Signaländerung um 90° dreht und daher nach vier Schritten eine volle Umdrehung absolviert hat haben reale Schrittmotoren eine höhere Auflösung. Gängig ist ein Schrittwinkel von 1,8°. Erst nach 200 Schritten hat sich so ein Motor einmal komplett gedreht. Da im abgebildeten Listing nach jedem Schritt 5ms gewartet wird werden genau 200 Schritte pro Sekunde erzeugt. Ein gängiger 1,8°-Motor würde sich genau einmal pro Sekunden drehen.
Für die Experimente am ftDuino muss ein Motor gewählt werden, der mit den 9V-Ausgängen des ftDuino kompatibel ist. Der hier verwendete 17HS13 ist für eine Betriebsspannung von 12V ausgelegt, arbeitet aber auch mit den fischertechnik-üblichen 9 Volt zuverlässig. Die Motoren des fischertechnik-Plotters 305712 von 1985 waren für 6 Volt ausgelegt. Sollen diese Motoren am ftDuino betrieben werden, so ist dieser mit 6 statt den üblichen 9 Volt zu versorgen.
Die Abbildungen der Abläufe beinhalten in der unteren Hälfte jeweils die Signalverläufe an den vier Anschlüssen des Motors. Die Signalverläufe sind farblich entsprechend der sich ergebenden Megnetfeldrichtung hinterlegt. Man sieht, wie die beiden Anschlüsse eines Magneten immer genau gegenteilig angesteuert werden und sich das Magnetfeld beim Wechsel der Signale ändert. Die abgebildete Farbe entspricht jeweils der Polarität der dem Anker zugewandten Seite des Elektromagneten.
Eine höhere Winkel-Auflösung erreicht man, wenn man den Schrittmotor im sogenannten Halbschrittbetrieb ansteuert. Der Signalzyklus besteht in dem Fall nicht mehr aus vier sondern aus acht Schritten. In jedem zweiten Schritt wird einer der beiden Elektromagneten abgeschaltet, so dass sich der Anker nur nach dem verbliebenen Magneten ausrichtet. Die sich dadurch ergebenden vier Zwischenzustände sind von den resultierenden Winkel genau zwischen den vier Zuständen der Vollschrittsteuerung angeordnet. Der Motor kann also die doppelt so viele Winkel ansteuern und entsprechend genauer positioniert werden.
In der Abbildung ist sichtbar, dass sich die beiden Signale zur Ansteuerung eines Elektromagneten nicht mehr gleichzeitig ändern, sondern dass es einen Versatz gibt, währenddessen beide Signale auf gleichem Pegel liegen. Der Magnet steht zu dieser Zeit nicht unter Spannung und hat kein Magnetfeld. Die Signalverläufe sind zu dieser Zeit daher nicht farbig hinterlegt.
Der Nachteil der Halbschrittsteuerung liegt darin, dass in den Zeiten, in denen nur ein Elektromagnet aktiv ist die Kraft des Motors reduziert ist.
Der im vorhergehenden Abschnitt verwendete Sketch zur Schrittmotoransteuerung hat vor allem einen großen Vorteil: Er ist anschaulich. Das Problem ist aber, dass die Ansteuerung Motors permanente Signalwechsel benötigt und daher die Motorfunktionen im Sketch permanent aktiv sein müssen, damit der Motor sich dreht. Der Sketch verbringt praktisch die ganze Zeit damit in den diversen delay()-Funktionsaufrufen, auf den nächsten Signalwechsel zu warten. Der größte Nachteil: Während der Sketch einen Motor bedient kann er kaum etwas anderes tun. Einen zweiten Motor gleichzeitig mit gegebenenfalls sogar unterschiedlicher Drehzahl laufen zu lassen ist mit diesem einfachen Sketch kaum zu realisieren.
Das gleiche Problem stellte sich während der Entwicklung des ftDuino bereits mit den übrigen Komponenten des ftDuino auch die Auswertung der Analogeingänge, die PWM-Drehzahlregelung der Motorausgänge und die Auswertung der Zähler beanspruchen permanent eine aktive Mitarbeit des Mikrocontrollers. Trotzdem muss der Anwender dafür in seinem Sketch keine Funktion vorsehen. All diese Dinge passieren weitgehend unbemerkt im Hintergrund. Solch eine Hintergrundfunktion wäre auch für den Betrieb des Schrittmotors wünschenswert.
Mikrocontroller wie der ATmega32u4 des ftDuino bestehen aus einem Mikroprozessor (der eigentlichen Recheneinheit) und diversen zusätzlichen Hardwarekomponenten wie z.B. USB-Schnittstellenfunktionen. Unter anderem verfügt der ATmega32u4 über einige sogenannte Timer. Einen Timer kann man sich wie eine unabhängig vom eigentlichen Prozessor arbeitende Uhr vorstellen. Man kann per Software festlegen, wie schnell die Uhr laufen soll und ob zu bestimmten Zeitpunkten gegebenenfalls bestimmte Dinge passieren sollen, aber das eigentliche Fortschreiten der Uhrzeit geschieht automatisch und ohne weiteres Zutun eines auf dem Prozessor ausgeführten Sketches. Eines der Dinge, die von so einem Timer regelmäßig ausgelöst werden können ist eine sogenannte Unterbrechungsanforderung (englisch Interrupt). Sie veranlasst den Prozessor, zu unterbrechen, was auch immer er gerade tut und sich für kurze Zeit einer anderen Aufgabe zu widmen.
Diese Art von Unterbrechung ist ideal, um z.B. einen Schrittmotor zu steuern. Soll der Schrittmotor z.B. 200 Schritte pro Sekunde bewegt werden, so kann ein Timer so programmiert werden, dass der Prozessor alle 5 Millisekunden unterbrochen wird. In dieser Unterbrechung muss der Prozessor dann das Magnetfeld des Motors einen Schritt weiter drehen und sich dann wieder seiner normalen Aufgabe widmen.
Das folgende Code-Segment programmiert den Timer 1 des ATmega32u4 so, dass die sogenannte Interrupt-Service-Routine exakt alle 5 Millisekunden ausgeführt wird. Der Motor ließe sich so durch passenden Programmcode innerhalb dieser Routine völlig unabhängig vom Hauptprogramm des Sketches betreiben.
1 #include <FtduinoSimple.h>
2
3 // die sogenannte Interrupt-Service-Routine (ISR) wird
4 // nicht vom Sketch selbst zur Ausführung gebracht, sondern
5 // die Hardware des ATmega32u$ löst die Ausführung auf Basis
6 // eines Timer-Ereignisses aus
7 ISR(TIMER1_COMPA_vect) {
8 // Diese Funktion wird alle 5ms ausgeführt.
9 // Das Weiterdrehen des Schrittmotor-Magnetfeldes
10 // könnte z.B. hier geschehen.
11 // ...
12 }
13
14 void setup() {
15 // Konfiguration des Timer 1 des ATmega32u4, die genaue
16 // Beschreibung der Register findet sich in Kapitel 14
17 // des Datenblatt:
18 // http://ww1.microchip.com/downloads/en/DeviceDoc/Atmel-7766-8-bit-AVR-ATmega16U4-32U4_Datasheet.pdf
19
20 // Timer 1 soll im sogenannten CTC-Modus schalten mit OCR1A
21 // als obere Grenze. Der Timer läuft mit 1/256 CPU-Takt. Dieser
22 // wiederum beträgt 16 MHz, der Timer läuft also mit 62,5 kHz.
23 // Um den Motor 200 Schritte pro Sekunde zu drehen muss der
24 // Motor immer dann einen Schritt machen, wenn der Timer 312
25 // (62500/200) seiner Zählschritte durchlaufen hat.
26 TCCR1A = 0;
27 TCCR1B = (1<<WGM12) | (1<<CS12); // Starte Timer 1 mit 1/256 F_CPU = 62.5kHz
28 TCCR1C = 0;
29
30 // Ereignis auslösen wenn 62400/200 Zählerschritte erreicht sind
31 TCNT1 = 0;
32 OCR1A = 62500/200;
33
34 // Ereigniserzeugung bei Erreichen der Zielschritte auslösen
35 TIMSK1 = (1<<OCIE1A);
36 }
37
38 void loop() {
39 // die Hauptroutine kann beliebig genutzt werden und
40 // der Timer 1-Interrupt wird unabhängig regelmäßig
41 // ausgeführt
42 }
Das vollständige Beispiel findet sich unter
Datei ► Beispiele ► FtduinoSimple ► StepperMotorSrv. Es entspricht weitgehend der
vorgeschlagenen Nutzung von Timer 1. Ein zweiter Motor ließe sich
z.B. ebenfalls im Hintergrund und unabhängig vom bereits vorhandenen
Motor und auch unabhängig vom Hauptprogramm des Sketches durch Timer 3
steuern. Mit zwei Schrittmotoren ist so recht elegant z.B. ein
sogenannter Plotter zu realisieren wie in Abschnitt 7.5
gezeigt.
Schwierigkeitsgrad: ★★★☆☆
Neben den normalen Gleichspannungsmotoren und den Schrittmotoren aus Abschnitt 6.4 gibt es eine dritte vor allem im Modellbau verbreitete Art von Motoren, die sogenannten Servos. fischertechnik vertreibt einen Servo unter der Artikelnummer 1322923 .
Technisch bestehen Servos aus einfachen Gleichstrommotoren und einer einfachen Elektronik. Eine Messmechanik meldet dieser Elektronik ständig den aktuellen Stellwert (Winkel) des Servos. Die Elektronik vergleicht diesen mit einem externen Sollwert und regelt den Motor bei Bedarf nach. Das Servo folgt also mit seinem Drehwinkel einem externen Sollwert.
Servos haben daher ein drei-adriges Anschlusskabel. Zwei Adern werden zur Spannungsversorgung (rot = 6 Volt, braun = Masse) verwendet, die dritte Ader (orange) überträgt den Sollwert. Es lassen sich handelsübliche Servos verwenden, aber auch der fischertechnik-Servo 1322924 aus dem 5405855 -PLUS Bluetooth Control Set. Auch der fischertechnik RC-Servo 302756 von 1983 müsste auf diese Weise verwendbar sein. Das wurde jedoch bisher nicht überprüft.
Da Servos für eine Betriebsspannung von 6 Volt ausgelegt sind und oft auch bei 5 Volt noch funktionieren ist eine Versorgung aus den internen 5 Volt des ftDuino über den I²C-Anschluss möglich wie in Abbildung 6.15 dargestellt. Bei dieser Versorgung ist Vorsicht geboten, da die Stromaufnahme des Servos 100mA nicht überschreiten darf, um die interne Stromversorgung des ftDuino nicht zu überlasten. Die meisten Servos überschreiten diesen Wert deutlich und sollten daher nicht direkt aus dem ftDuino versorgt werden.
Wesentlich robuster und kaum aufwändiger ist die Versorgung über einen externen Spannungsregler z.B. vom Typ 7806, der unter dieser Bezeichnung leicht im Online-Handel zu finden ist. Dieser sogenannte Längsregler kann direkt an einen der 9-Volt-Ausgänge des ftDuino angeschlossen werden und stellt an seinem Ausgang eine auf 6 Volt reduzierte Spannung bereit.
Benötigte Teile:
1x | Spannungsregler 7806 |
1x | Servo-Verlängerungskabel JR-Stecker |
2x | roter ft-Stecker |
1x | grüner ft-Stecker |
1x | rote ft-Buchse |
Der 7806 kann mit fischertechnik-üblichen Steckern versehen und dann
direkt in den ftDuino eingesteckt werden. Der
Steuersignal-Anschluss muss mit dem SDA-Anschluss des I²C-Steckers
verbunden werden. Die zusätzliche Nutzung des SCL-Anschlusses
ermöglicht den Anschluss eines zweiten Servos. Trennt man das rote
Kabel direkt am Stecker des Servos auf und versieht es mit einem
fischertechnik-Stecker wie in Abbildung 6.15
dargestellt, so lässt sich der Stecker des Servos mit den zwei
verbliebenen Adern direkt auf den I²C-Anschluss stecken. Will man
das Anschlusskabel des Servos nicht zerschneiden, dann kann man auch
ein handelsübliche JR-Servo-Verlängerungskabel zerschneiden wie in
Abbildung 6.16 dargestellt. Der aufgetrennte mittlere
rote Anschluss wird dann mit dem fischertechnik-Stecker an den
ebenfalls mit fischertechnik-Hülsen versehenen 7806 gesteckt.
Das Steuersignal eines Servos entspricht nicht dem I²C-Standard. Stattdessen verwenden Servos ein einfaches Pulsweitensignal, das alle 20 Millisekunden wiederholt wird. Der Puls selbst ist zwischen einer und zwei Millisekunden lang und bestimmt den Winkel, den das Servo einnehmen soll. Eine Millisekunde steht dabei für den minimalen Wert und zwei Millisekunden für den maximalen. Soll der Servomotor in Mittelstellung fahren, so ist dementsprechend ein Puls von 1,5 Millisekunden Länge nötig.
Das Servo verfügt über keine weitere Intelligenz und es werden die
vorgegebenen Steuersignale nicht überprüft. Pulslängen kleiner einer
Millisekunde oder größer zwei Millisekunden versucht das Servo
ebenfalls in entsprechende Winkel umzusetzen. Dabei ist zu beachten,
dass der Bewegung des Servos mechanische Grenzen gesetzt sind und das
Servo Schaden nehmen kann, wenn es Positionen außerhalb seines
normalen Arbeitsbereichs anzufahren versucht. Es ist daher nicht
ratsam, den Bereich von ein bis zwei Millisekunden zu verlassen.
Um das nötige Puls-Signal auf den eigentlich für I²C-Signale vorgesehenen Pins zu erzeugen muss auf Software zurückgegriffen werden. Ein Programmfragment, das den Servo in die Mittelposition bewegt könnte z.B. folgendermaßen aussehen:
1 void setup() {
2 // Port D.1 (SDA-Anschluss) auf Ausgang schalten
3 bitSet(DDRD, 1);
4 }
5
6 void loop() {
7 // Port D.1 auf High-Pegel (5V) legen
8 bitSet(PORTD, 1);
9
10 // 1500us (1.5ms) warten
11 _delay_us(1500);
12
13 // Port D.1 auf Low-Pegel (GND) legen
14 bitClear(PORTD, 1);
15
16 // 18500us (18.5ms) warten
17 _delay_us(20000-1500);
18 }
Hier wird der SDA-Anschluss am I²C zunächst in der
setup()-Funktion zu einem unabhängig verwendbaren Ausgang
konfiguriert. In der Folge kann in der loop()-Funktion der
Ausgang auf Hi (5 Volt) oder Masse (GND) geschaltet werden, indem das
entsprechende Bit im Register PORTD gesetzt oder gelöscht
wird. Nach dem Einschalten des Ausgangs wird 1500 Mikrosekunden (1,5
Millisekunden) gewartet, nach dem Ausschalten 18,5 Millisekunden, so
dass die Zykluszeit von insgesamt 20 Millisekunden erreicht wird.
Wie schon beim Schrittmotor ergibt sich das Problem, dass der Prozessor des ftDuino bei dieser einfachen Art der Programmierung permanent mit der Signalerzeugung ausgelastet wird und nebenbei keine anderen Aufgaben erledigen kann.
Die Lösung besteht wie beim Schrittmotor darin, die Signalerzeugung im Hintergrund durch einen Hardwaretimer zu veranlassen. Das Beispiel Datei ► Beispiele ► FtduinoSimple ► ServoDemo bringt eine einfache Klasse zur Servoansteuerung mit. Das eigentliche Hauptprogramm sieht dann folgendermaßen aus:
1 //
2 // Servo.ino
3 //
4
5 #include "Servo.h"
6
7 void setup() {
8 servo.begin();
9 }
10
11 void loop() {
12 static uint8_t value = Servo::VALUE_MAX/2;
13
14 if(value < Servo::VALUE_MAX) value++;
15 else value = 0;
16 servo.set(value);
17
18 delay(10);
19 }
Die Ansteuerung des Servos beschränkt sich auf den Aufruf der
servo.begin()-Funktion, die die nötigen Timer im Hintergrund
einrichtet. Der Winkel des Servos kann dann mit der
servo.set()-Funktion von 0 (minimaler Winkel) bis
Servo::VALUE_MAX (maximaler Winkel) eingestellt werden. Die
Mittelposition wird z.B. durch servo.set(Servo::VALUE_MAX/2)
angefahren.
Schwierigkeitsgrad: ★★☆☆☆
Wer sich schon einmal mit einem Arduino beschäftigt hat weiss, dass
man dort relativ frei bestimmen kann, welche Anschlüsse man als Ein-
oder Ausgänge verwenden möchte, da sämtliche Pins am Mikrocontroller
in der Richtung umgeschaltet werden können. Beim ftDuino konnte
diese Fähigkeit nicht erhalten werden, da an den Eingängen zusätzliche
Schutzschaltungen gegen Überspannung und Kurzschlüsse eingesetzt
werden und die Signale Ausgänge verstärkt werden, um
fischertechnik-Lampen und -Motoren betreiben zu können.
Jeder der acht Eingänge I1 bis I8 des ftDuino führt auf einen eigenen Analogeingang des ATmega32u4-Mikrocontrollers und kann von diesem unabhängig ausgewertet werden. Dazu kann der Mikrocontroller die Spannung des entsprechenden Eingangs messen.
Bevor das Eingangssignal den Mikrocontroller erreicht wird es über einen Spannungsteiler aus zwei 47-Kiloohm-Widerständen geführt. Diese Widerstände erfüllen zwei Aufgaben. Erstens halbieren sie die Spannung eines angelegten Signals bevor es den Mikrocontroller erreicht. Da der Mikrocontroller ftDuino-intern mit 5 Volt betrieben wird und auch nur Signale im Bereich von 0 bis 5 Volt verarbeiten kann. Die Spannungshalbierung erweitert den messbaren Eingangsspannungsbereich auf 0 bis 10 Volt, wodurch sich die fischertechnik-üblichen Spannungen bis maximal 9 Volt verarbeiten lassen. Zum zweiten schützen diese Widerstände im Zusammenspiel mit den Mikrocontroller-internen Schutzdioden den Mikrocontroller vor Spannungen, die außerhalb des für ihn verträglichen 0 bis 5 Volt-Spannungsbereichs liegen. Spannungen bis zu 47 Volt an einem Eingang beschädigen den Mikrocontroller daher nicht.
Die 1kΩ- und 2,2kΩ-Widerstände sowie der Schalter haben keine Bedeutung, solange der Schalter offen ist. Acht dieser Schalter, je einer für jeden Eingang, befinden sich im ftDuino im Baustein mit der Bezeichnung CD4051 (IC1) wie im Schaltplan in Anhang A ersichtlich. Der Mikrocontroller kann genau einen der acht Schalter zu jeder Zeit schließen und auf diese Weise einen Widerstand von insgesamt 3,2kΩ (1kΩ plus 2,2kΩ) vom jeweiligen Eingang gegen 5 Volt aktivieren.
Der Schalter wird geschlossen und die Widerstände werden aktiviert, wenn eine Widerstandsmessung erfolgen soll. Der 3,2kΩ-Widerstand bildet dann mit einem zwischen Eingang und Masse angeschlossenen externen Widerstand einen Spannungsteiler. Aus der gemessenen Spannung kann dann der unbekannte externe Widerstand bestimmt werden.
Die Widerstandsmessung wird von der Ftduino-Bibliothek im Hintergrund ausgeführt. Dabei findet auch eine automatische Umschaltung der Widerstandsmessung auf all jene Eingänge statt, die im Sketch zur Zeit zur Widerstandsmessung genutzt werden. Der Programmierer muss sich also um keine Details kümmern und kann jederzeit Widerstandswerte mit Hilfe der Funktion ftduino.input_get() (siehe 9.2.2) abfragen.
Die Tatsache, dass im Falle einer Widerstandsmessung ein Widerstand
gegen 5 Volt geschaltet wird bedeutet, dass über den zu messenden
extern angeschlossenen Widerstand ein Stromkreis geschlossen wird.
Der Strom durch diesen Stromkreis ist relativ gering. Wenn der Eingang
direkt mit Masse verbunden ist beträgt der Gesamtwiderstand
3,2kΩ und es fließt ein Strom von
I=5V/3,2kΩ=1,5625mA.
Dieser Strom reicht zwar nicht, um eine Lampe oder gar einen Motor zu betreiben. Aber eine Leuchtdiode kann man damit schwach zum Leuchten bringen. Schließt man eine Leuchtdiode direkt zwischen einem Eingang und Masse an und schaltet den Eingang auf Widerstandsmessung, so wird die LED ganz leicht leuchten.
Der tatsächliche Strom wird noch deutlich unter den vorausgesagten 1,5mA liegen, da zum einen direkt an der Leuchtdiode die sogenannte Vorwärtsspannung von circa 0,7V abfällt und über den Widerständen daher nur eine Spannung von etwas über vier Volt anliegt.
Zum anderen fragt die Ftduino-Bibliothek im Hintergrund alle acht Eingänge ab und aktiviert jeden Eingang dabei nur 1/8 der Zeit. Es fließt im Mittel daher auch nur 1/8 des Stroms.
Die FtduinoSimple-Bibliothek schaltet ebenfalls die Widerstände ein und zwar für den jeweils zuletzt aktivierten Eingang. Dieser Widerstand ist dann dauerhaft aktiviert, bis ein anderer Eingang angefragt wird. Das folgenden Code-Fragment lässt eine LED an Eingang I1 im Sekundentakt blinken.
1 #include <FtduinoSimple.h>
2
3 void loop() {
4 // lies Wert von Eingang I1, aktiviert Widerstand auf I1
5 ftduino.input_get(Ftduino::I1);
6 delay(1000);
7 // lies Wert von Eingang I2, deaktiviert Widerstand auf I1
8 // (und aktiviert ihn auf I2)
9 ftduino.input_get(Ftduino::I2);
10 delay(1000);
11 }
Schwierigkeitsgrad: ★☆☆☆☆
Fischertechnik vertreibt unter der Artikelnummer 364377 einen sogenannten NTC. Dieses unscheinbare Bauteil liegt einigen Robotics-Baukästen bei.
Ein NTC ist ein elektrischer Widerstand, der seinen Wert abhängig von der Umgebungstemperatur ändert. Er eignet sich daher zur Temperaturmessung. NTC steht dabei für ``Negativer-Temperatur-Coeffizient'', was bedeutet, dass der ohmsche Widerstand mit steigender Temperatur sinkt. NTCs werden im Deutschen auch als Heißleiter bezeichnet, da ihre Leitfähigkeit mit der Temperatur steigt.
Der Nennwiderstand RN eines NTCs wird in der Regel bei einer
Temperatur von 25 °C (298,15 K) angegeben. Der für den
fischertechnik-Sensor angegebene Wert ist 1,5kΩ. Der ohmsche
Widerstand beträgt bei 25 °C also 1,5kΩ.
Der folgende Sketch findet sich bei installierter ftDuino-Unterstützung im Menü der Arduino-IDE unter Datei ► Beispiele ► Ftduino ► Temperature.
1 //
2 // Temperaure.ino
3 //
4 // Abfrage eines fischertechnik Temperatur-Widerstands an Eingang I1
5 //
6 // (c) 2018 by Till Harbaum <till@harbaum.org>
7 //
8
9 #include <Ftduino.h>
10 #include <math.h> // Für Fliesspunkt-Arithmetik
11
12 #define K2C 273.15 // Offset Kelvin nach Grad Celsius
13 #define B 3900.0 // sog. B-Wert des Sensors
14 #define R_N 1500.0 // Widerstand bei 25 Grad Celsius Referenztemperatur
15 #define T_N (K2C + 25.0) // Referenztemperatur in Kelvin
16
17 float r2deg(uint16_t r) {
18 if(r == 0) return NAN; // ein Widerstand von 0 Ohm ergibt keine sinnvolle Temperatur
19
20 // Widerstand in Kelvin umrechnen
21 float t = T_N * B / (B + T_N * log(r / R_N));
22
23 // Kelvin in Grad Celsius umrechnen
24 return t - K2C;
25
26 // alternativ: Kelvin in Grad Fahrenheit umrechnen
27 // return t * 9 / 5 - 459.67;
28 }
29
30 void setup() {
31 // LED initialisieren
32 pinMode(LED_BUILTIN, OUTPUT);
33 digitalWrite(LED_BUILTIN, LOW);
34
35 Serial.begin(115200);
36 while(!Serial);
37
38 ftduino.init();
39
40 // Die Temperaturmessung erfolgt mit einem
41 ftduino.input_set_mode(Ftduino::I1, Ftduino::RESISTANCE);
42 }
43
44 void loop() {
45 uint16_t r = ftduino.input_get(Ftduino::I1);
46
47 Serial.print("I1: ");
48 Serial.print(r2deg(r));
49 Serial.println(" Grad Celsius");
50
51 delay(1000);
52 }
Der Temperatur-Sketch verwendet an einigen Stellen sogenannte Fließkommazahlen, um Temperaturen zu speichern. So wird die in der Computertechnik verwendete interne Darstellung von nicht-ganzzahligen Werten (Dezimalbrüchen) genannt. Der Sketch bindet dafür in Zeile 10 die Datei math.h ein, um dem Sketch Zugriff auf Fließkommafunktionen zu geben. Zur Speicherung der Fließkommazahlen wird der Datentyp float z.B. in Zeile 21 verwendet.
Da der zur Temperaturmessung verwendete Sensor ein Widerstand ist wird in der setup()-Funktion in Zeile 41 der Eingang I1 des ftDuino auf Widerstandsmessung eingestellt.
Der eigentlich Widerstandswert wird in Zeile 45 von Eingang I1 ausgelesen und in der ganzzahligen Variablen r abgelegt. Während der Ausgabe des Wertes in Zeile 48 wird die Funktion r2deg() aufgerufen. Diese Funktion befindet sich in den Zeilen 17 bis 28. Sie nimmt einen ganzzahligen Widerstandswert in Ohm entgegen und liefert eine Temperatur in Grad Celsius als Fließkommawert zurück.
Zunächst erfolgt in Zeile 21 die Umrechnung des Widerstands in Kelvin. Dazu wird neben dem Widerstand RN bei 25 °C auch der sogenannte B-Wert des Sensors benötigt. Dieser Wert beschreibt das Verhalten des Sensors außerhalb des 25 °C-Punkts und wie stark dabei der Widerstand auf Temperaturänderungen reagiert. Dieser Wert liegt bei dem von fischertechnik vertriebenen Sensor bei 3900.
Für NTCs gilt näherungsweise8 :
1/T = 1/TN + 1/B logn(RT/RN) ↔ T = TN * B/B + TN * logn(RT/RN)
mit
Nach der Umrechnung liegt die Temperatur in Kelvin vor. Zur Umrechnung in Grad Celsius muss Zeile 24 lediglich eine Konstante abgezogen werden. Eine Umrechnung in Grad Fahrenheit wäre etwas komplexer und ist beispielhaft in Zeile 27 dargestellt.
Die Genauigkeit der Temperaturmessung ist direkt von der Genauigkeit der Widerstandsmessung abhängig und diese ist wie in Abschnitt 1.2.5 erklärt von der Spannungsversorgung abhängig. Zur Temperaturmessung sollte der ftDuino daher aus einer 9v-Quelle mit Spannung versorgt werden. Eine Versorgung nur über die USB-Schnittstelle ist nicht ausreichend.
Schwierigkeitsgrad: ★★☆☆☆
Einen Ausgang kann man ein- oder ausschalten, das ist die gängige
Sichtweise. Dass es aber noch einen weiteren Zustand gibt ist auf
den ersten Blick vielleicht nicht offensichtlich.
Die Ausgänge des ftDuino lassen sich in drei Zustände schalten: Ftduino::HI, Ftduino::LO und Ftduino::OFF.
Am offensichtlichsten ist der Zustand Ftduino::HI. In diesem Zustand wird der entsprechende Ausgang ftDuino-intern mit der 9-Volt-Versorgungsspannung verbunden. Ist an diesem Ausgang eine Lampe oder ein Motor so angeschlossen, dass der zweite Anschluss an Masse liegt, so fließt ein Strom von der 9V-Quelle über den Ausgang durch Lampe oder Motor zur Masse. Der Motor dreht sich und die Lampe leuchtet. Im abgebildeten Beispiel leuchtet die rote Lampe.
Im Zustand Ftduino::LO ist der entsprechende Ausgang mit Masse verbunden. Eine wieder mit dem zweiten Anschluss an Masse angeschlossene Lampe wird nun nicht mehr leuchten, da beide Anschlüsse der Lampe auf Masse liegen und die Spannung zwischen beiden Anschlüssen daher 0 Volt beträgt. Schließt man den zweiten Anschluss der Lampe aber an 9 Volt an, so leuchtet sie nun. Der Strom fließt von der Spannungsversorgung des ftDuino über den 9-V-Anschluss, durch die Lampe und schließlich über den auf Masse liegenden Ausgang. Im abgebildeten Beispiel leuchtet nun die blaue Lampe.
Der dritte Zustand ist schließlich der Zustand Ftduino::OFF. In diesem Fall ist der Ausgang komplett offen. Er ist weder mit Masse noch mit 9 Volt verbunden und es fließt kein Strom über ihn. Als Resultat leuchten beiden Lampen mit halber Helligkeit, da der Strom nun vom Ausgang völlig unbeeinflusst durch beide Lampen fließt. Dieser Zustand wird oft auch mit dem englischen Begriff ``tristate'' bezeichnet und entsprechende Ausgänge an Halbleitern als ``tristate-fähig''. Im Deutschen beschreibt der Begriff ``hochohmig'' diesen dritten Zustand recht gut.
Der folgende Sketch wechselt im Sekundentakt zwischen den drei Zuständen. Man kann diesen Effekt zum Beispiel ausnutzen, um zwei Motoren oder Lampen an einem Ausgang unabhängig zu steuern, um Ausgänge zu sparen. Allerdings lassen sich bei dieser Verschaltung niemals beide Lampen gleichzeitig ausschalten
1 /*
2 OnOffTristate - der dritte Zustand
3 */
4
5 #include <FtduinoSimple.h>
6
7 void setup() { }
8
9 // Die Loop-Funktion wird endlos immer und immer wieder ausgeführt
10 void loop() {
11 // Ausgang O1 auf 9V schalten
12 ftduino.output_set(Ftduino::O1, Ftduino::HI);
13 delay(1000);
14 // Ausgang O1 auf Masse schalten
15 ftduino.output_set(Ftduino::O1, Ftduino::LO);
16 delay(1000);
17 // Ausgang O1 unbeschaltet lassen
18 ftduino.output_set(Ftduino::O1, Ftduino::OFF);
19 delay(1000);
20 }
21
Ganz korrekt ist die Aussage, dass im hochohmigen beziehungsweise Tristate-Zustand kein Strom fließt nicht. Über die Leistungsendstufen und deren interne Schutzschaltungen fließt oft trotzdem ein geringer Strom. In einigen Fällen wird dies sogar bewusst getan, um z.B. mit Hilfe dieses geringen Stromflusses das Vorhandensein eines angeschlossenen Verbrauchers feststellen zu können. Diese sogenannten Leckströme wurden in Abschnitt 6.1.1 bereits beobachtet.
Ersetzt man die zwei Lampen im aktuellen Modell durch zwei Leuchtdioden, so wird man feststellen, dass die vom Ausgang nach Masse angeschlossene LED immer dann leicht glimmt, wenn der entsprechende Ausgang hochohmig geschaltet ist. Nur wenn der Ausgang auf Masse geschaltet ist leuchtet die LED nicht. Man kann also direkt an der LED die drei Zustände unterscheiden.
Schwierigkeitsgrad: ★★☆☆☆
Das Abschalten eines Motors scheint rein elektrisch trivial zu sein. Sobald der Motor von der Spannungsversorgung getrennt wird bleibt er stehen. Im Wesentlichen stimmt das auch so.
Physikalisch bedeutet die Trennung von der Spannungsversorgung lediglich, dass dem Motor keine weitere Energie zugeführt wird. Dass das letztlich dazu führt, dass der Motor anhält liegt daran, dass die in der Rotation des Motors gespeicherte Energie langsam durch Reibung z.B. in den Lagern der Motorwelle verloren geht. Wie lange es dauert, bis der Motor auf diese Weise zum Stillstand kommt hängt wesentlich vom Aufbau des Motors und der Qualität seiner Lager ab.
Zusätzlich wirken viele Gleichstrom-Elektromotoren, wie sie auch
fischertechnik einsetzt, als Generator. Werden sie gedreht, so wird in
ihren internen Elektromagneten eine Spannung induziert.
Dieser Effekt lässt sich mit einer Leuchtdiode leicht nachvollziehen. Schließt man die Leuchtdiode direkt an den Motor an und dreht dann manuell die Motorachse, so leuchtet die Leuchtdiode auf, wenn man den Motor in die richtige Richtung dreht und damit eine Spannung mit der für die Leuchtdiode passenden Polarität erzeugt. Man kann für diesen Versuch auch eine Glühlampe oder gar einen zweiten Motor nehmen. Deren gegenüber einer Leuchtdiode höhere Energieaufnahme erfordert aber gegebenenfalls ein etwas kräftigeres Drehen.
Je mehr Last ein Generator versorgen soll und je mehr Energie im
entnommen werden soll, desto größer ist die mechanische Kraft, die
nötig ist, um den Generator zu drehen. Höhere Last bedeutet in diesem
Fall ein geringerer elektrischer Widerstand. Die Leuchtdiode mit ihrer
vergleichsweise geringen Last besitzt einen hohen elektrischen
Widerstand, die Glühlampe und noch mehr der Motor besitzen einen
geringen elektrischen Widerstand und belasten beziehungsweise bremsen den
Generator damit stärker. Die größte denkbare Last ist in diesem Fall
der Kurzschluss. Er hat einen minimalen elektrischen Widerstand und
sorgt für maximalen Stromfluss und damit maximale elektrische Last am
Generator. Auch die Bremswirkung ist dabei maximal.
Dieser Effekt lässt sich nutzen, um einen Elektromotor zu bremsen. Wende beide Anschlüsse eines Motors miteinander verbunden, so fließt ein Strom, der eine Bremswirkung entwickelt. Das wurde bereits beim Not-Aus-Modell aus Abschnitt 6.2 genutzt, um den Motor im Notfall schnell zu stoppen. Ist dagegen z.B. einer der Anschlüsse des Motors offen, so ist kein geschlossener Stromkreis vorhanden und es fließt kein Strom und es tritt keine Bremswirkung auf. Wie groß ist dieser Effekt aber?
Der fischertechnik-Encoder-Motor enthält eine Möglichkeit zur
Drehzahlmessung wie schon im PWM-Experiment in Abschnitt 6.3
genutzt. Das Bremsverhalten dieses Motors lässt sich daher
experimentell gut verfolgen.
Das Beispiel Datei ► Beispiele ► Ftduino ► MotorBrake lässt den Motor an Ausgang M1 alle fünf Sekunden für drei Umdrehungen laufen und misst dann für eine weitere Sekunde, wie viele weitere Impulse der Encoder an Eingang C1 liefert, nachdem er die drei Umdrehungen vollendet hat und abgeschaltet wurde.
Die Funktion motor_counter_set_brake() (siehe Abschnitt
9.2.9) wird dabei im Wechsel so
aufgerufen, dass der Motor frei ausläuft beziehungsweise dass er aktiv gebremst
wird.
Wie in Abbildung 6.25 zu sehen macht die aktive Bremse einen deutlichen Unterschied. Während der Encoder-Motor ungebremst noch für weitere 90 Impulse weiter dreht, also fast 1,5 volle Umdrehungen, kommt er bei aktiver Bremse bereits nach fünf weiteren Impulse zum Stillstand. Das entspricht lediglich knapp 1/13 Umdrehung.
Schwierigkeitsgrad: ★★☆☆☆
Der ftDuino ist nicht vom klassischen Arduino Uno abgeleitet, sondern vom Arduino Leonardo. Der wesentliche technische Unterschied zwischen beiden Arduinos liegt in der Tatsache, dass der Arduino Uno einen separaten Chip für die USB-Kommunikation mit dem PC verwendet, während diese Aufgabe beim Arduino Leonardo allein dem ATmega32u4-Mikrocontroller zufällt.
In den meisten Fällen macht das keinen Unterschied und die meisten Sketches laufen auf beiden Arduinos gleichermaßen. Es gibt allerdings sehr große Unterschiede in den Möglichkeiten, die sich mit beiden Arduinos bei der USB-Anbindung bieten. Während der USB-Chip im Uno auf das Anlegen eines COM:-Ports beschränkt ist zeigt sich der Leonardo und damit auch der ftDuino sehr viel flexibler und der ftDuino kann sich unter anderem gegenüber einem PC als USB-Tastatur ausgeben.
Da die Ausgänge des ftDuino bei diesem Modell nicht verwendet
werden reicht die Stromversorgung über USB und es ist keine weitere
Versorgung über Batterie oder Netzteil nötig.
1 /*
2 KeyboardMessage - USB-Tastatur
3
4 Der ftDuino gibt sich als USB-Tastatur aus und "tippt" eine Nachricht, sobald
5 ein Taster an Eingang I1 für mindestens 10 Millisekunden gedrückt wird.
6
7 Basierend auf dem Sketch:
8 http://www.arduino.cc/en/Tutorial/KeyboardMessage
9
10 Dieser Beispielcode ist Public-Domain.
11 */
12
13 #include <FtduinoSimple.h>
14 #include <Keyboard.h>
15
16 unsigned long lastButtonEvent = 0;
17 uint16_t previousButtonState = Ftduino::OFF; // for checking the state of a pushButton
18
19 void setup() {
20 // initialize control over the keyboard:
21 Keyboard.begin();
22 }
23
24 void loop() {
25 // Taste an Eingang I1 auslesen
26 uint16_t buttonState = ftduino.input_get(Ftduino::I1);
27
28 // Hat sich der Zustand der Taste geändert?
29 if(buttonState != previousButtonState) {
30 // ja, Zeit des Wechsels merken
31 lastButtonEvent = millis();
32 // und den neuen Zustand merken, damit wir weitere
33 // Änderungen erkennen können
34 previousButtonState = buttonState;
35 }
36
37 // Gibt es ein unbearbeitetes Eregnis und hat sich der Zustand der Taste seitdem
38 // für mehr als 10 Millisekunden nicht geändert?
39 if(lastButtonEvent && ((millis() - lastButtonEvent) > 10)) {
40 // Zeit dieses Ereignisses vergessen
41 lastButtonEvent = 0;
42
43 // Taste wurde gedrückt
44 if(buttonState) {
45 // Nachricht "tippen"
46 Keyboard.println("Hallo vom ftDuino!");
47 }
48 }
49 }
50
Die Arduino-IDE bringt bereits Bibliotheken mit, um USB-Geräte wie Mäuse und Tastaturen umzusetzen. Der eigentliche Sketch bleibt so sehr einfach und die komplizierten USB-Detail bleiben in den Bibliotheken verborgen. Entsprechend kurz ist auch dieser Sketch.
In der setup()-Funktion muss lediglich die Methode Keyboard.begin() aufgerufen werden, um beim Start des ftDuino alle USB-seitigen Vorkehrungen zu treffen, so dass der ftDuino vom PC als USB-Tastatur erkannt wird. Allerdings verfügt diese Tastatur zunächst über keine Tasten, so dass man kaum merkt, dass der PC nun über eine zusätzliche Tastatur zu verfügen meint.
Um die Tastatur mit Leben zu füllen muss in der loop()-Funktion bei Bedarf ein entsprechendes Tastensignal erzeugt und an den PC gesendet werden. In den Zeilen 25 bis 35 des Sketches wird ein Taster an Eingang I1 abgefragt und sichergestellt, dass nur Tastendrücke über 10ms Länge als solche erkannt werden (mehr Details zu diesem sogenannten Entprellen findet sich in Abschnitt 6.12).
Immer wenn die Taste an I1 gedrückt wurde, werden die Sketchzeilen 45 und folgende ausgeführt. Hier wird die Funktion Keyboard.println() aus der Arduino-Keyboard-Bibliothek aufgerufen und ein Text an den PC gesendet. Für den PC sieht es so aus, als würde der Text vom Anwender auf der Tastatur getippt 9 .
Die Möglichkeit, Nachrichten direkt als Tastatureingaben zu senden kann sehr praktisch sein, erlaubt sie doch ohne weitere Programmierung auf dem PC, die automatische Eingabe z.B. vom Messwerten in eine Tabelle oder ähnlich. Natürlich lässt sich diese Fähigkeit aber auch für allerlei Schabernack nutzen, indem der ftDuino zeitgesteuert oder auf andere Ereignisse reagierend den überraschten Anwender mit unerwarteten Texteingaben irritiert. Bei solchen Späßen sollte man immer eine ordentliche Portion Vorsicht walten lassen, da der falsche Tastendruck zur falschen Zeit leicht einen Datenverlust zur Folge haben kann.
Schwierigkeitsgrad: ★★★☆☆
Aus der PC-Sicht ist der Unterschied zwischen einer USB-Tastatur und
einen USB-Joystick oder -Gamepad minimal. Beide nutzen das sogenannte
USB-HID-Protokoll (HID = Human Interface Device, also ein
Schnittstellengerät für Menschen). Arduino-seitig gibt es aber den
fundamentalen Unterschied, dass die Arduino-Umgebung zwar
vorgefertigte Bibliotheksfunktionen für Tastaturen mitbringt, für
Gamepads und Joysticks aber nicht. Um trotzdem ein USB-Gamepad zu
implementieren ist daher im Sketch sehr viel mehr Aufwand zu
treiben.
Das entsprechende Beispiel findet sich unter Datei ► Beispiele ► FtduinoSimple ► USB ► GamePad. Dieser Sketch besteht aus drei Dateien. Während GamePad.ino den eigentlichen Sketch enthält implementieren HidGamePad.cpp und HidGamePad.h denjenigen Teil der Gamepad-Unterstützung, die die Arduino-IDE nicht bietet. Interessant ist vor allem die _hidReportDescriptor-Struktur in der Datei HidGamePad.cpp.
9 static const uint8_t _hidReportDescriptor[] PROGMEM = {
10 0x05, 0x01, // USAGE_PAGE (Generic Desktop)
11 0x09, 0x05, // USAGE (Gamepad)
12 0x85, REPORT_ID, // REPORT_ID(3)
13 0xa1, 0x01, // COLLECTION (Application)
14 0x09, 0x01, // USAGE (Pointer)
15 0xa1, 0x00, // COLLECTION (Physical)
16 0x09, 0x30, // USAGE (X)
17 0x09, 0x31, // USAGE (Y)
18 0x15, 0x00, // LOGICAL_MINIMUM(0)
19 0x26, 0xff, 0x00, // LOGICAL_MAXIMUM(255)
20 0x35, 0x00, // PHYSICAL_MINIMUM(0)
21 0x46, 0xff, 0x00, // PHYSICAL_MAXIMUM(255)
22 0x75, 0x08, // REPORT_SIZE(8)
23 0x95, 0x02, // REPORT_COUNT(2)
24 0x81, 0x02, // INPUT (Data,Var,Abs)
25 0xc0, // END_COLLECTION
26 0x05, 0x09, // USAGE_PAGE (Button)
27 0x19, 0x01, // USAGE_MINIMUM (Button 1)
28 0x29, 0x02, // USAGE_MAXIMUM (Button 2)
29 0x15, 0x00, // LOGICAL_MINIMUM(0)
30 0x25, 0x01, // LOGICAL_MAXIMUM(1)
31 0x95, 0x02, // REPORT_COUNT(2)
32 0x75, 0x01, // REPORT_SIZE(1)
33 0x81, 0x02, // INPUT (Data,Var,Abs)
34 0x95, 0x06, // REPORT_COUNT(6)
35 0x81, 0x03, // INPUT (Const,Var,Abs)
36 0xc0 // END_COLLECTION
37 };
Diese vergleichsweise kryptische Struktur beschreibt die Fähigkeiten
eines USB-HID-Geräts10 .
Sie beschreibt, um welche Art Gerät es sich handelt und im Falle
eines Joysticks über was für Achsen und Tasten er verfügt.
In diesem Fall meldet das Gerät, dass es über zwei Achsen X und Y verfügt, die jede einen Wertebereich von 0 bis 255 abdecken. Weiterhin gibt es zwei Buttons, die jeweils nur den Zustand an und aus kennen. Für einen einfachen Joystick reicht diese Beschreibung. Es ist aber leicht möglich, die Beschreibung zu erweitern und zusätzliche Achsen und Tasten vorzusehen. Mit den insgesamt acht analogen und den vier digitalen Eingängen verfügt der ftDuino über ausreichend Verbindungsmöglichkeiten für komplexe Eingabegeräte.
Übliche HID-Geräte sind Tastaturen, Mäuse und Joysticks beziehungsweise Gamepads. Aber die Spezifikation der sogenannten HID-Usage-Tabellen11 sieht wesentlich originellere Eingabegeräte für diverse Sport-, VR-, Simulations- und Medizingeräte und vieles mehr vor. Und natürlich ist mit den Ausgängen des ftDuino auch die Implementierung von Rückmeldungen über Lampen oder Motoren in Form von z.B. Force-Feedback möglich.
Schwierigkeitsgrad: ★★★☆☆
In einigen der vorherigen Sketches wurde unerwartet viel Aufwand betrieben, um Taster abzufragen. Im Pwm-Sketch aus Abschnitt 6.3.1 wurde in den Zeilen 35 und 51 eine Verzögerung von einer Millisekunde eingebaut und im KeyboardMessage-Sketch in Abschnitt 6.10 wurde in den Zeilen 31 und 39-41 ebenfalls die Zeit erfasst und in die Auswertung des Tastendrucks eingefügt. Die Frage, warum das nötig ist soll etwas näher betrachtet werden.
Der Grund für diese Verwendung von Zeiten bei der Auswertung von einzelnen Tastendrücken ist das sogenannte ``Prellen''. Mechanische Taster bestehen aus zwei Metallkontakten, die entweder getrennt sind oder sich berühren. In Ruhe sind die Kontakte getrennt und wenn der Taster betätigt wird, dann sorgt eine Mechanik dafür, dass die beiden Metallkontakte in Berührung kommen und der Kontakt geschlossen wird.
Folgender Sketch fragt kontinuierlich einen Taster an Eingang I1
ab und gibt auf dem COM:-Port eine Meldung aus, wenn sich
der Zustand ändert. Zusätzlich zählt er mit, wie oft sich der Zustand
insgesamt bereits geändert hat.
1 /*
2 Debounce
3
4 Demonstriert Tastenprellen
5 */
6
7 #include <FtduinoSimple.h>
8
9 // die setup-Funktion wird einmal beim Start aufgerufen
10 void setup() {
11 Serial.begin(9600);
12
13 while(!Serial); // warte auf USB-Verbindung
14
15 Serial.println("ftDuino Tastenprell-Beispiel");
16 }
17
18 uint8_t letzter_zustand = false;
19 uint8_t wechselzaehler = 0;
20
21 // die loop-Funktion wird immer wieder aufgerufen
22 void loop() {
23 uint8_t zustand = ftduino.input_get(Ftduino::I1); // Taster auslesen
24
25 if(zustand != letzter_zustand) { // Hat der Zustand sich geändert?
26 wechselzaehler = wechselzaehler + 1; // Ja, Zähler rum eins erhöhen
27
28 Serial.print("I1 "); // und eine Meldung ausgeben
29 Serial.print(wechselzaehler);
30 Serial.println(" mal geändert");
31 letzter_zustand = zustand; // neuen Zustand als letzten merken
32 }
33 }
34
In den Zeilen 10 bis 16 wird wie schon beim ComPort-Beispiel aus Abschnitt 3.3 die Ausgabe an den PC vorbereitet und für den seriellen Monitor eine Nachricht ausgegeben.
In Zeile 23 wird kontinuierlich der Eingang I1 abgefragt. Hat sich sein Zustand gegenüber dem in der Variablen letzter_zustand gespeicherten geändert, so wird dies in Zeile 25 festgestellt. In der Folge wird die Variable wechselzaehler erhöht und der neue Wert in den Zeilen 28 bis 30 ausgegeben.
Etwas merkwürdiges passiert, wenn man den Sketch auf den ftDuino lädt und ausprobiert: Sobald die Taste gedrückt wird erscheinen gleich mehrere Meldungen über Zustandsänderungen des Eingangs und auch der Zähler zählt wesentlich weiter als erwartet. Was passiert hier?
Das Problem ist, dass im Moment des Schaltens der Kontakt nicht sofort perfekt schließt. Stattdessen berühren sich die Metallflächen kurz, federn dann für ein paar Mikrosekunden zurück und öffnen sich wieder für einen sehr kurzen Moment. Erst nach mehreren Federvorgängen kommen die Kontakte zur Ruhe und sind dauerhaft geschlossen.
Die einfachste Lösung des Problems liegt darin, ein klein wenig zu warten, bevor man nach einem Schaltereignis ein weiteres akzeptiert. Das erreicht man zum Beispiel, indem man nach Zeile 31 zusätzlich etwas wartet, wie es auch im Pwm-Sketch aus Abschnitt 6.3.1 getan wurde.
31 letzter_zustand = zustand; // neuen Zustand als letzten merken
32 delay(10); // warte zehn Millisekunden
33 }
Nach dieser Änderung zählt der Sketch tatsächlich nur noch einzelne
Tastendrücke. Diese einfache Lösung hat aber einen Nachteil: Die
Ausführung des gesamten Sketches wird bei jeden Tastendruck für zehn
Millisekunden pausiert. Hat der Sketch noch andere Aufgaben zu
erledigen, dann wird die Verarbeitung dieser Aufgaben ebenfalls für
diese zehn Millisekunden unterbrochen. Je nach verwendetem Taster
lässt sich die Zeit auf unter eine Millisekunde verkürzen. Aber bei zu
kurzer Wartezeit werden wieder falsche Ereignisse erkannt.
Eleganter ist es daher, bei jedem Ereignis mit der Funktion millis() einen Zeitstempel aus dem Systemzeitzähler zu nehmen und erst dann ein Ereignis als gültig zu erkennen, wenn das letzte Ereignis länger als 10 Millisekunden zurück liegt. Der KeyboardMessage-Sketch aus Abschnitt 6.10 löst das Problem auf genau diese Weise.
Wie lange der Taster prellt und wie er sich genau verhält konnte wir bisher nur vermuten. Lässt sich der ftDuino nutzen, um etwas genauer auf das Schaltverhalten des Tasters zu schauen?
Um Signalverläufe zu veranschaulichen verfügt die Arduino-IDE über ein sehr einfaches aber interessantes Werkzeug: Den sogenannten ``seriellen Plotter'' er findet sich im Menü unter Werkzeuge ► Serieller Plotter und öffnet wie der serielle Monitor ein eigenes Fenstern. Aber statt einen per COM:-Port empfangenen Text direkt anzuzeigen interpretiert der serielle Plotter die eingehenden Daten Zeile für Zeile als Werte, die grafisch in einer Kurve dargestellt (geplottet) werden.
Das folgende Beispiel ist unter Datei ► Beispiele ► FtduinoSimple ► BounceVisu zu finden.
1 /*
2 BounceVisu
3
4 visualisiert Tastenprellen
5 */
6
7 #include <FtduinoSimple.h>
8
9 #define EVENT_TIME 480 // 480us
10 uint8_t event[EVENT_TIME];
11
12 // die setup-Funktion wird einmal beim Start aufgerufen
13 void setup() {
14 Serial.begin(9600);
15 while(!Serial); // warte auf USB-Verbindung
16 }
17
18 // die loop-Funktion wird immer wieder aufgerufen
19 void loop() {
20
21 // Warte bis Taster gedrückt
22 if(ftduino.input_get(Ftduino::I1)) {
23
24 // hole 480 Mikrosekunden lang im MiKrosekundentakt je einen Eingangswert
25 for(uint16_t i=0;i<EVENT_TIME;i++) {
26 event[i] = ftduino.input_get(Ftduino::I1);
27 _delay_us(1);
28 }
29
30 // gib zunächst 20 Nullen aus
31 for(uint16_t i=0;i<20;i++)
32 Serial.println(0);
33
34 // gib die eingelesenen 480 Werte aus
35 for(uint16_t i=0;i<EVENT_TIME;i++)
36 Serial.println(event[i]);
37
38 // Warte eine Sekunde
39 delay(1000);
40 }
41 }
42
Der Sketch wartet in Zeile 22 darauf, dass die Taste an Eingang
I1 gedrückt wird. Daraufhin zeichnet er für eine kurze Weile den
Zustand des Eingang I1 auf. In Zeile 9 ist festgelegt, dass 480
Werte aufgezeichnet werden. Zwischen zwei Aufzeichnungen wird in Zeile
27 jeweils eine Mikrosekunde gewartet, so dass insgesamt über 480
Mikrosekunden aufgezeichnet wird. Ist die Aufzeichnung vollständig,
dann werden zunächst 20 Zeilen Nullen ausgegeben und danach die vorher
aufgezeichneten 480 Werte, so dass insgesamt 500 Werte ausgegeben
werden. Die ersten 20 Werte repräsentieren den Zustand vor der
Aufzeichnung, als der Taster noch nicht gedrückt wurde.
Die insgesamt 500 Werte stellt der serielle Plotter als Kurve dar. Der Wert ist null, wenn der Kontakt als offen erkannt wird und eins, sobald der Kontakt geschlossen ist. Man sieht in der Grafik, wie der Taster zunächst circa 40 Mikrosekunden lang mehrfach öffnet und schließt, dann liegt das Signal über 100 Mikrosekunden stabil an, bevor der Kontakt noch ein paar mal öffnet, um schließlich nach insgesamt 200 Mikrosekunden stabil geschlossen zu bleiben. Die in Lösung 1 eingesetzte Pause kann also auf gute 200 Mikrosekunden reduziert werden, ohne dass das Prellen Auswirkungen hätte.
Es ist nötig, die Werte vor der Ausgabe komplett zu erfassen und zu speichern, da die Übermittlung der Zeichen an den PC vergleichsweise viel Zeit in Anspruch nimmt. Würden die Werte sofort an den PC übermittelt, dann wäre die Auflösung von einer Mikrosekunde nicht zu erreichen, da die Datenübermittlung selbst schon länger dauert. Tatsächlich dauert auch das Auslesen des Eingangs I1 etwas Zeit und das Zeitverhalten unser Messung ist nicht sehr genau. Es genügt aber, um die prinzipiellen Abläufe darzustellen.
Schwierigkeitsgrad: ★★★★★
Wie in Abschnitt 1.2.6 beschrieben verfügt der ftDuino über einen I²C-Anschluss. In der Arduino-Welt ist der I²C-Bus äußerst beliebt, denn er erlaubt den einfach Anschluss einer Vielzahl von preisgünstigen Erweiterungsbausteinen.
Der ftDuino wird mit einer Schutzkappe auf dem I²C-Anschluss ausgeliefert wie in Abschnitt 1.2.6 abgebildet. Diese Kappe muss vor Benutzung des I²C-Anschlusses entfernt werden.
Mit wenig Aufwand lassen sich die meisten Sensoren mit einem passenden
Anschlusskabel für den ftDuino versehen. In Abbildung
6.30 ist beispielhaft die Verkabelung einer typischen im
Online-Handel günstig erhältlichen MPU6050-Sensor-Platine
dargestellt. Der Sensor ist damit direkt an den ftDuino
anschließbar.
Um den jeweiligen Sensor in eigenen Projekten zu verwenden sind in der
Regel zusätzliche Code-Routinen oder Bibliotheken nötig. Die große
Verbreitung der Arduino-Plattform führt dazu, dass man zu praktisch
jedem gängigen Sensor mit wenig Suche passende Beispiele und
Code-Bibliotheken
findet12 .
Für einen schnellen Test, ob die elektrische Verbindung zum Sensor
korrekt ist reicht aber in der Regel ein einfacher Test der
I²C-Kommunikation aus. Unter
Datei ► Beispiele ► FtduinoSimple ► I2C ► I2cScanner
findet sich ein einfaches I²C-Testprogramm, das am I²C-Bus nach
angeschlossenen Sensoren sucht und deren Adresse ausgibt. Die jeweilige
Adresse eines Sensors wird in der Regel vom Sensorhersteller fest
vergeben. Im Falle des MPU-6050 ist dies die Adresse 0x68.
Diese Adresse wird bei korrektem Anschluss des Sensors angezeigt.
Für den MPU6050 liefert die ftDuino-Umgebung ein eigenes Beispiel
mit. Der Beispiel-Sketch unter Datei ► Beispiele ► FtduinoSimple ► I2C ► MPU6050Test liest
die Beschelunigungswerte aus dem MPU-6050 aus und gibt sie
auf dem seriellen Monitor aus.
Eine weitere naheliegenden Anwendung des I²C-Anschlusses ist der Anschluss eines kleinen Displays, mit dem z.B. direkt am ftDuino Messwerte ausgegeben werden können.
Für wenig Geld gibt es im Online-Handel OLED-Displays mit 0,96 Zoll
Bilddiagonale. Mit einer Größe von etwas unter 3*3cm2 eignen sich diese
Displays auch sehr gut für den Einbau in ein entsprechendes
fischertechnik-kompatibles Gehäuse
13 .
Beim Anlöten des Kabels muss man sich unbedingt am Aufdruck auf der Display-Platine und nicht an den Skizzen hier orientieren, da es in der Anschlussbelegung Unterschiede zwischen den ansonsten baugleichen Displays gibt.
Dieses Display verwendet als Display-Controller-Baustein den SSD130614 von Solomon Systech. Diese Display-Sorte ist im Arduino-Umfeld sehr beliebt und passende Bibliotheken gibt es im Internet15 16 .
Wichtig: Wie viele andere I²C-Sensoren auch ist das OLED-Display nicht ftDuino-spezifisch, sondern wird auch in anderen Arduino-Projekten eingesetzt. Daher ist dessen Unterstützung kein Teil der ftDuino-Installation, sondern es müssen die o.g. Adafruit-Bibliotheken unbedingt separat installiert werden. Andernfalls wird die Übersetzung des Sketches mit einer Meldung der Art ``fatal error: Adafruit_GFX.h: No such file or directory'' oder ähnlich abgebrochen.
Zum Displaytest bringt die Adafruit_SSD1306-Bibliothek unter Datei ► Beispiele ► Adafruit SSD1306 ► ssd1306_128x64_i2c ein Beispiel.
Hinweis: In früheren Versionen dieses Handbuchs wurde an dieser Stelle eine manuelle Änderung der Bibliothek beschrieben, die für das 128x64-Display nötig war. In der aktuellen Version der Adafruit-SSD1306-Bibliothek ist diese Anpassung nicht mehr nötig. Die Beispiele wurden ebenfalls entsprechend angepasst.
Dabei muss im Sketch selbst die I²C-Adresse von 0x3D nach 0x3C angepasst werden:
60 // by default, we'll generate the high voltage from the 3.3v line internally! (neat!)
61 display.begin(SSD1306_SWITCHCAPVCC, 0x3C); // initialize with the I2C addr 0x3D (for the 128x64)
62 // init done
Die ftDuino-Installation selbst bringt ebenfalls ein Beispiel mit,
das dieses Display verwendet. Das Shootduino-Spiel findet sich unter
Datei ► Beispiele ► FtduinoSimple ► Shootduino. Das Spiel erwartet drei Taster an
den Eingängen I1, I2 und I3 zur Steuerung des
Raumschiffs und gegebenenfalls eine Lampe an O1.
Fischertechnik liefert einen Ultraschallsensor zur Distanzmessung, der wie in Abschnitt 1.2.6 gezeigt auch am ftDuino betrieben werden kann. Dieser Ultraschallsensor sendet einen Ultraschallimpuls aus und misst die Laufzeit, bis die Schallwelle ein Hindernis erreicht und zum Sensor zurück reflektiert. Aus der Laufzeit und der bekannten Schallgeschwindigkeit lässt sich so die Distanz bestimmen.
In der Arduino-Welt gibt es eine interessante Alternative in Form
des VL53L0X-Laser-Distanzsensors. Das Funktionsprinzip gleicht
dem des Ultraschallsensors, allerdings kommt kein Schall, sondern
Laserlicht zu Einsatz. Der VL53L0X lässt sich recht leicht über
I²C mit dem ftDuino verbinden.
Ein passendes Gehäuse zum selbst-drucken findet sich im ftDuino-Repository17 .
Wie für fast alle üblichen I²C-Sensoren findet man auch beim VL53L0X bereits fertige Arduino-Bibliotheken und -Sketches im Internet18 .
Der ftDuino kann nicht nur andere Geräte über den I²C-Bus ansprechen, er kann sich selbst auch als passives Gerät am Bus ausgeben, um von einem anderen Gerät angesprochen zu werden.
Am einfachsten lässt sich diese Möglichkeit nutzen, wenn zwei ftDuinos
direkt über I²C gekoppelt werden.
Es wird dazu eine 1:1-Verbindung zwischen den beiden I²C-Anschlüssen der beteiligten Controller hergestellt. Ein Controller muss in diesem Aufbau als Master konfiguriert werden, einer als Slave. Entsprechende Beispiel-Sketches finden sich unter Datei ► Beispiele ► FtduinoSimple ► I2C ► I2cMaster und Datei ► Beispiele ► FtduinoSimple ► I2C ► I2cSlave.
Der Master fragt kontinuierlich einen an Eingang I1 angeschlossenen Taster ab und sendet den Zustand des Tasters über I²C an den zweiten, als Slave konfigurierten ftDuino. Dieser schaltet dann eine Lampe an Ausgang O1 entsprechend ein oder aus.
Die Spannungsversorgung des Masters kann dabei über die I²C-Verbindung erfolgen. Lediglich der Slave muss direkt mit 9 Volt versorgt sein, um die Lampe am Ausgang steuern zu können. Die Versorgung über I²C entspricht der Versorgung über USB mit den bekannten Einschränkungen wie in Abschnitt 1.2.5 beschrieben.
Neben dem einfachen Beispiel Datei ► Beispiele ► FtduinoSimple ► I2C ► I2cSlave, das auf der funktionsreduzierten FtduinoSimple-Bibliothek aufbaut befindet sich unter Datei ► Beispiele ► Ftduino ► I2C ► I2cSlave ein auf der vollwertigen Bibliothek aufbauendes Beispiel, das die meisten Ein- und Ausgabefähigkeiten des ftDuino über I²C verfügbar macht.
Dieser erweiterte Sketch eignet sich als Basis für komplexe
Modelle. Das hier abgebildete Beispiel verwendet drei ftDuinos zur
Erweiterung des Master-ftDuino um weitere 24 Aus- und 36 Eingänge.
Der erste ftDuino im Bild ganz links bildet den Master, gefolgt von den drei Slaves. Auf dem ersten Slave läuft das unveränderte Beispiel aus Datei ► Beispiele ► Ftduino ► I2C ► I2cSlave. Für die weiteren Slaves muss die I²C-Adresse im Sketch jeweils angepasst werden. Das geschieht, indem in Zeile 16 im I2cSlave-Sketch die Adresse 43 ersetzt wird durch 44 bzw 45 für die beiden weiteren Slaves.
13 void setup() {
14 pinMode(LED_BUILTIN, OUTPUT); // LED initialisieren
15
16 Wire.begin(43); // tritt I2C-Bus an Adresse #43 als "Slave" bei
17 Wire.onReceive(receiveEvent); // Auf Schreib-Ereignisse registrieren
18 Wire.onRequest(requestEvent); // Auf Lese-Ereignisse registrieren
19
20 ftduino.init();
21
22 // alle Ausgänge sind hochohmig
23 memset(output_mode, 0, sizeof(output_mode));
24 }
Der Master enthält in diesem Fall die gesamte eigentliche
Programmlogik und die Slaves nehmen fundamentale Steuerbefehle über
I²C entgegen. Der Master-Sketch findet sich unter
Datei ► Beispiele ► Ftduino ► I2C ► I2cMaster. In Zeile 12 sind dort die Adressen
43, 44 und 45 der drei Slaves bereits eingestellt. Sollen mehr oder
weniger Slaves verwendet werden, so ist die Zeile 12 entsprechend
anzupassen.
9 // Liste der anzusteuernden I2c-Clients, beginnend mit 0 (der Master selbst)
10 // und -1 als Endemarkierung. In diesem Fall sind drei Clients unter den Adressen
11 // 43, 44 und 45 angeschlossen
12 static const int8_t clients[] = { 0, 43, 44, 45, -1 };
Die Stromversorgung aller vier ftDuinos kann aus einem
fischertechnik-Netzteil erfolgen, das an den Master angeschlossen
wird. Die Slaves werden dann vom 9-Volt-Ausgang des Masters über
zweipolige fischertechnik-Kabel versorgt.
Das Beispiel Datei ► Beispiele ► Ftduino ► I2C ► I2cMaster eignet sich als Vorlage für komplexe Modelle. Je nach Modell kann es aber praktischer sein, auch die Slaves zu verändern und zu erweitern. Geräte bei Modellen mit weitgehend eigenständigen Untereinheiten (z.B. Taktstraße) kann es einfacher sein, die einzelnen Stationen jeweils von einem ftDuino weitgehend autonom steuern zu lassen und die I²C-Kommunikation auf das nötigste zu reduzieren, um z.B. die Ankunft eines neuen Bauteils in der Station anzukündigen.
Die folgenden Tabelle listete die I²C-Register, wie sie vom I2cSlave.ino für den ftDuino implementiert werden. Werte mit vorangestelltem 0x sind in Hexadezimalschreibweise dargestellt.
Register | Beschreibung |
0x00 | Ausgangs-Modus O1/M1 |
0x0x - Betrieb als Einzelausgang | |
0x00 - Einzelausgang offen/hochohmig (tristate) | |
0x01 - Einzelausgang gegen +9V geschaltet (High) | |
0x02 - Einzelausgang gegen Masse geschaltet (Low) | |
0x1x - Ausgang mit O2 zum Motorausgang M1 gekoppelt | |
0x10 - Motorausgang ungebremst aus (off) | |
0x11 - Motorausgang gebremst aus (brake) | |
0x12 - Motorausgang links drehend an | |
0x13 - Motorausgang rechts drehend an | |
0x01 | Ausgangswert (PWM) O1/M1 von 0 (aus) bis 255 (100% an) |
Der Zustand des Hardwareausgangs wird beim Schreiben | |
dieses Registers aktualisiert | |
0x02 | Ausgangs-Modus O2 |
Der Inhalt dieses Registers wird ignoriert, wenn Ausgangs-Modus O1/M1 | |
(Register 0x00) den Wert 0x1x enthält | |
0x00 - Einzelausgang offen/hochohmig (tristate) | |
0x01 - Einzelausgang gegen +9V geschaltet (High) | |
0x02 - Einzelausgang gegen Masse geschaltet (Low) | |
0x03 | Ausgangswert (PWM) O2 von 0 (aus) bis 255 (100% an) |
Der Inhalt dieses Registers wird ignoriert, wenn Ausgangs-Modus O1/M1 | |
(Register 0x00) den Wert 0x1x enthält | |
Der Zustand des Hardwareausgangs wird beim Schreiben | |
dieses Registers aktualisiert | |
0x04 | Ausgangs-Modus O3/M2, siehe Ausgang-Modus O1 (Register 0x00) |
0x05 | Ausgangswert O3/M2, siehe Ausgangswert O1 (Register 0x01) |
0x06 | Ausgangs-Modus O4, siehe Ausgang-Modus O2 (Register 0x02) |
0x07 | Ausgangswert O4, siehe Ausgangswert O2 (Register 0x03) |
0x08 | Ausgangs-Modus O5/M3, siehe Ausgang-Modus O1 (Register 0x00) |
0x09 | Ausgangswert O5/M3, siehe Ausgangswert O1 (Register 0x01) |
0x0a | Ausgangs-Modus O6, siehe Ausgang-Modus O2 (Register 0x02) |
0x0b | Ausgangswert O6, siehe Ausgangswert O2 (Register 0x03) |
0x0c | Ausgangs-Modus O7/M4, siehe Ausgang-Modus O1 (Register 0x00) |
0x0d | Ausgangswert O7/M4, siehe Ausgangswert O1 (Register 0x01) |
0x0e | Ausgangs-Modus O8, siehe Ausgang-Modus O2 (Register 0x02) |
0x0f | Ausgangswert O8, siehe Ausgangswert O2 (Register 0x03) |
Register | Beschreibung |
0x10 | schreiben: Eingangs-Modus I1 |
0x00 - Spannung | |
0x01 - Widerstand | |
0x02 - Schalter | |
lesen: Eingangswert I1, Low-Byte (LSB) | |
0x11 | lesen: Eingangswert I1, High-Byte (MSB) |
0x12 | Eingangs-Modus/Eingangswert I2, siehe Eingangs-Modus I1 (Register 0x10) |
0x13 | Eingangswert I2, siehe Eingangswert I1 (Register 0x11) |
0x14 | Eingangs-Modus/Eingangswert I3, siehe Eingangs-Modus I1 (Register 0x10) |
0x15 | Eingangswert I3, siehe Eingangswert I1 (Register 0x11) |
0x16 | Eingangs-Modus/Eingangswert I4, siehe Eingangs-Modus I1 (Register 0x10) |
0x17 | Eingangswert I4, siehe Eingangswert I1 (Register 0x11) |
0x18 | Eingangs-Modus/Eingangswert I5, siehe Eingangs-Modus I1 (Register 0x10) |
0x19 | Eingangswert I5, siehe Eingangswert I1 (Register 0x11) |
0x1a | Eingangs-Modus/Eingangswert I6, siehe Eingangs-Modus I1 (Register 0x10) |
0x1b | Eingangswert I6, siehe Eingangswert I1 (Register 0x11) |
0x1c | Eingangs-Modus/Eingangswert I7, siehe Eingangs-Modus I1 (Register 0x10) |
0x1d | Eingangswert I7, siehe Eingangswert I1 (Register 0x11) |
0x1e | Eingangs-Modus/Eingangswert I8, siehe Eingangs-Modus I1 (Register 0x10) |
0x1f | Eingangswert I8, siehe Eingangswert I1 (Register 0x11) |
Register | Beschreibung |
0x20 | schreiben: Zähler-Modus C1 |
0x00 - aus | |
0x01 - steigende Flanke | |
0x02 - fallende Flanke | |
0x03 - beide Flanken | |
0x04 - Ultraschallsensor aktivieren | |
lesen: Eingangszustand C1 | |
0x21 | schreiben: Zähler C1 |
0x00 - Zähler unverändert lassen | |
sonst - Zähler löschen | |
lesen: Zählerstand C1/Ultraschall-Distanz, Low-Byte (LSB) | |
0x22 | Zählerstand C1/Ultraschall-Distanz, High-Byte (MSB) |
0x24 | schreiben: Zähler-Modus C2 |
0x00 - aus | |
0x01 - steigende Flanke | |
0x02 - fallende Flanke | |
0x03 - beide Flanken | |
lesen: Eingangszustand C2 | |
0x25 | schreiben: Zähler C2 |
0x00 - Zähler unverändert lassen | |
sonst - Zähler löschen | |
lesen: Zählerstand C2, Low-Byte (LSB) | |
0x26 | Zählerstand C2, High-Byte (MSB) |
0x28 | Zähler-Modus C3, siehe Zähler-Modus C2 (Register 0x24) |
0x29 | Zählerstand C3, Low-Byte (LSB), siehe Zählerstand C2 (Register 0x25) |
0x2a | Zählerstand C3, High-Byte (MSB), siehe Zählerstand C2 (Register 0x26) |
0x2c | Zähler-Modus C4, siehe Zähler-Modus C2 (Register 0x24) |
0x2d | Zählerstand C4, Low-Byte (LSB), siehe Zählerstand C2 (Register 0x25) |
0x2e | Zählerstand C4, High-Byte (MSB), siehe Zählerstand C2 (Register 0x26) |
Natürlich lässt sich der ftDuino als I²C-Slave nicht nur an
anderen ftDuinos betreiben, sondern auch an PCs und anderen
Geräten, wenn sie mit einer entsprechenden I²C-Schnittstelle
ausgerüstet sind. Im Fall eines PCs lässt sich die nötige
I²C-Schnittstelle auch mit Hilfe eines einfachen Adapters
über USB nachrüsten. Ein solcher Adapter ist der
i2c_tiny_usb19 .
Auf einem Linux PC20 kann das Programm i2c_detect verwendet werden. Mit dem Parameter -l kann man sich zunächst eine Liste aller im PC installierten I²C-Busse ausgeben lassen.
$ i2cdetect -l i2c-3 unknown i915 gmbus dpc N/A i2c-1 unknown i915 gmbus vga N/A i2c-8 i2c em2860 #0 I2C adapter i2c-6 unknown DPDDC-B N/A i2c-4 unknown i915 gmbus dpb N/A i2c-2 unknown i915 gmbus panel N/A i2c-0 unknown i915 gmbus ssc N/A i2c-9 i2c i2c-tiny-usb at bus 001 device 023 I2C adapter i2c-7 unknown DPDDC-C N/A i2c-5 unknown i915 gmbus dpd N/ADer Digispark/i2c_tiny_usb erscheint in diesem Fall als i2c-9. Unter dieser Bus-Nummer lässt sich der I²C-Bus des i2c_tiny_usb nach Geräten absuchen.
$ i2cdetect -y 9 0 1 2 3 4 5 6 7 8 9 a b c d e f 00: -- -- -- -- -- -- -- -- -- -- -- -- -- 10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 20: -- -- -- -- -- -- -- -- -- -- 2a -- -- -- -- -- 30: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 40: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 50: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 60: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 70: -- -- -- -- -- -- -- --In diesem Fall wurde unter Adresse $2a (dezimal 42) der auf der FtduinoSimple-Bibliothek basierende einfache I2cSlave des ftDuino erkannt.
Im Repository21 findet sich ein Python-Beispiel, mit dem vom PC aus auf den ftDuino zugegriffen werden kann. Für die umfangreichere auf der Ftduino-Bibliothek basierende Variante gibt es ebenfalls ein Python-Beispiel im Repository22 .
Wie im Abschnitt 6.13 erwähnt ist mit 3,3 Volt betriebene I²C-Anschluss des fischertechnik-TXT-Controllers nicht elektrisch kompatibel zum mit 5 Volt betriebenen I²C-Anschluss des ftDuino.
Mit Hilfe eines passenden Pegel-Wandlers kann man aber leicht die
nötige Signalanpassung vornehmen. Die Elektronik dazu ist preisgünstig
im Online-Handel erhältlich. Man sollte darauf achten, dass die
Elektronik die Spannungsversorgung der 3,3-Volt-Seite selbst aus der
Versorgung der 5-Volt-Seite erzeugt, da der TXT selbst keine 3,3 Volt
zur Verfügung stellt.
Die Funktion eines Levelshifters erfüllt auch der sogenannte
I²C-Expander23 .
Dieses Gerät wurde zum Einsatz am ftDuino entworfen, kann aber
auch am TXT oder TX betrieben werden.
Der I²C-Expander stellt einen TXT-kompatiblen 10-poligen I²C-Anschluss bereit und vier 6-polige TX- beziehungsweise ftDuino-kompatible. Die vier ftDuino-kompatiblen Anschlüsse sind 1-zu-1 verbunden und können zum Anschluss mehrerer I²C-Geräte an den ftDuino verwendet werden. Zusätzlich ist eine Levelshifter enthalten, der einen Anschluss an den TXT beziehungsweise an dessen Sensoren erlaubt. Die Spannungsversorgung des Levelshifters erfolgt vom ftDuino.
Eine passende App für die Community-Firmware des fischertechnik-TXT-Controllers findet sich im cfw-apps-Repository24 .
Da I²C-Geräte am TXT auch unter RoboPro und der Originalfirmware angesteuert werden können lässt sich der ftDuino auf diese Weise auch unter RoboPro als Erweiterung des TXT nutzen.
Das Kabel zum Anschluss des ftDuino an den TXT und der
I²C-Expander sind nicht auf eines feste Richtung festgelegt. Sie
können daher auch dazu verwendet werden, für den TXT entworfene
Sensoren an den ftDuino anzuschließen.
Getestet wurde dies z.B. mit dem ``Kombisensor 15840225 3-in-1
Orientierungssensor''26
basierend auf dem Bosch BMX055, für den es auch fertige
Arduino-Sketches
gibt27 .
Der Anschluss der 9-Volt-Versorgungsspannung erfolgt dabei exakt wie
beim TXT an einem der 9-Volt-Ausgänge des ftDuino.
Der Umweltsensor aus dem ``ROBOTICS TXT Smart Home''-Baukasten 54462428 basiert auf dem BME68029 von Bosch Sensortec. Er beinhaltet Sensoren für Temperatur, Luftdruck, Luftfeuchtigkeit und Luftqualität.
Auch für diesen Sensor gibt es im Arduino-Umfeld diverse Bibliotheken, die
über den Bibliotheks-Manager der Arduino-IDE leicht zu installieren sind, wie
in Abbildung 6.45 zu sehen. Für erste Experimente empfielt sich
die Bibliothek von Adafruit.
Die I²C-Adresse des BME680 ist durch entsprechende Verdrahtung verstellbar. Fischertechnik stellt die Adresse auf 0x76 ein während die Adafruit-Bibliothek den Sensor standardmäßig unter der Adresse 0x77 erwartet. In den Beispielen unter Datei ► Beispiele ► Adafruit BME680 Library muss daher jeweils die von fischertechnik verwendete Adresse explizit angegeben werden. Der Aufruf der Funktion bme.begin() ist in den Beispielen wie folgt zu ändern:
if (!bme.begin(0x76)) {
Serial.println("Could not find a valid BME680 sensor, check wiring!");
while (1);
}
Der Sensor lässt sich mit dem Levelshifter als auch mit dem I²C-Expander
betreiben sowie mit dem ft-Extender (siehe Abschnitt 8.5).
Die Luftqualität wertet der BME680 durch Erhitzen und Widerstandsmessung aus. Die Adafruit-Bibliothek liefert hier lediglich den wenig aussagekräftigen Widerstandswert. Bosch selbst liefert eine Closed-Source-Bibliothek, um den Wert in den ACQ-Qualitätswert umzurechnen, den auch fischertechnik selbst in seinen Baukästen nutzt. Diese Bibliothek ist auch für den Arduino erhältlich, allerdings ist die Bibliothek zu groß für den Flash-Speicher des ftDuino.
Eine alternative Berechnung eines abstrakten ``Air-Quality''-Wertes airq sieht wie folgt aus.
gas_baseline = 200000.0;
hum_baseline = 40.0;
hum_weighting = 0.25;
gas_offset = gas_baseline - gas_resistance;
hum_offset = humidity - hum_baseline;
hum_score = (100 - hum_baseline - hum_offset) /
(100 - hum_baseline) * (hum_weighting * 100);
gas_score = (gas_resistance / gas_baseline) * (100 - (hum_weighting * 100));
airq = hum_score + gas_score;
Speziell für den ftDuino wurde der Mini-I²C-Servo-Adapter
entworfen. Er vereint trotz seiner geringen Größe eine
Spannungsversorgung und eine Servosteuerung in einem Gehäuse.
Zur Erstinbetriebnahme sollte nur die I²C-Verbindung zwischen ftDuino und Mini-I²C-Adapter hergestellt werden. Generell ist es ratsam, den ftDuino von der Spannungs- und USB-Versorgung zu trennen, während die I²C-Verbindungen hergestellt und getrennt werden. Sobald die Verbindung hergestellt ist kann der ftDuino eingeschaltet werden. Die Leuchtdiode im Mini-I²C-Adapter sollte für ca. eine Sekunde aufleuchten und dann verlöschen.
Auf dem ftDuino sollte für den ersten Test der Datei ► Beispiele ► FtduinoSimple ► I2C ► I2cScanner-Sketch installiert werden. Weder 9 Volt noch der Servoanschluss werden für erste Tests benötigt. Der I2cScanner-Sketch sollte nun unter Adresse 0x11 den Adapter finden:
I2C Scanner Scanning... I2C device found at address 0x11 ! doneJedesmal wenn der Adapter vom ftDuino angesprochen wird sollte die Leuchtdiode im Adapter kurz aufleuchten. Sollte dieser Test nicht klappen sollte das I²C-Kabel überprüft werden (sind beiden Stecker korrekt orientiert?). Funktionieren andere Gerät am I²C-Anschluss des ftDuino?
War dieser Test erfolgreich, dann können Servo und 9-Volt-Versorgung
angeschlossen werden wie in Abbildung 6.48 zu
sehen. Auch hier sollte der ftDuino während der Umverkabelung von
der Strom- und USB-Versorgung getrennt werden.
Der Mini-I²C-Servo-Adapter wird zwischen den I²C-Ausgang des ftDuino und den Anschluss des Servos gesteckt. Zusätzlich wird eine 9-Volt-Verbindung zur Spannungsversorgung des Servos benötigt. Der Mini-I²C-Adapter reduziert die fischertechnik-üblichen 9 Volt auf Servo-verträgliche 5 Volt.
Achtung! Die I²C-Anschlüsse des ftDuino, des Mini-I²C-Servo-Adapters und des Servos sind nicht gegen Überspannung geschützt und dürfen nicht mit 9V in Kontakt kommen. Es wird empfohlen, den ftDuino zur Verkabelung spannungslos zu machen.
Sind alle Verbdidungen hergesellt kann z.B. der Sketch unter Datei ► Beispiele ► FtduinoSimple ► I2C ► MiniServoAdapter verwendet werden. Er steuert kontiniertlich beide Servoausgänge gegenläufg an.
Die Programmierung des Mini-I²C-Servo-Adapters ist recht einfach, ein simples Beispiel findet sich unter Datei ► Beispiele ► FtduinoSimple ► I2C ► MiniServoAdapter. Das Setzen eines Ausgangs auf einen Wert benötigt lefiglich folgenden Code:
Wire.beginTransmission(ADDRESS);
Wire.write(0x00); // 0 = servo 1, 1 = servo 2
Wire.write(94); // Mitte, 63 (ganz links) bis 125 (ganz rechts)
Wire.endTransmission();
Die Standard-Adresse des Mini-I²C-Servo-Adapters ist hex 0x11 beziehungsweise dezimal 17. Diese Adresse kann permanent geändert werden (s.u.). Sollte man die Adresse vergessen haben, dann hilft der Datei ► Beispiele ► FtduinoSimple ► I2C ► I2cScanner-Sketch, die Adresse des Adapters zu bestimmen.
Register | Beschreibung |
0x00/0x01 | Setzen der Pulsweite der Servoausgänge 1 oder 2 in Schritten von 16µs. In der Standardeinstellung werden nur Werte im für Servos geeigneten Bereich von 63 (1ms) bis 125 (2ms) akzeptiert. Werte außerhalb dieses Bereiches werden gekappt. Die Grenzen können verändert werden (s.u.). |
0x02/0x03 | Setzen der unteren Grenze der Pulsweise von Servo 1 beziehungsweise Servo 2 in 16µs-Schritten. Standardwert ist 63. Werte größer als diese Grenze, die in die Register 0x00 und 0x01 geschrieben werden werden auf diese untere Grenze beschränkt. |
0x04/0x05 | Setzen der oberen Grenze der Pulsweise von Servo 1 beziehungsweise Servo 2 in 16µs-Schritten. Standardwert ist 125. Werte kleiner als diese Grenze, die in die Register 0x00 und 0x01 geschrieben werden werden auf diese obere Grenze beschränkt. |
0x06/0x07 | Das Schreiben dieses Registers setzt einen Offset für Servo 1 oder 2. Der Standardwert ist 0. Der Offset wird zu der durch Register 0x00 oder 0x01 gesetzen Pulsweise addiert nachdem die Grenzen überprüft wurden. Auf diese Weise lässt sich z.B. die Mittelstellung an die individuallen Eigenschaften eines Servos anpassen. |
0x08 | Setzen der I²C-Adresese. Die neue Adresse muss im Bereich von 0x03 bis 0x77 liegen mit Ausnahme von 0x3c (diese Adresse wird vom internen OLED-Display entsprechender ftDuinos verwendet). |
0x09 | Das Schreiben von 0xa5 in Register 0x09 überträgt speichert die über Register 0x02 bis 0x08 gemachten Einstellungen permanent im EEPROM. Ab diesem Zeitpunkt bleiben die Einstellungen auch über einen Neustart und Stromlosigkeit erhalten. |
0x00 lesen | Das Lesen von Register 0x00 liefert die Firmwareversion in BCD-Kodierung zurück. Also beispielsweise 0x10 für Version 1.0 |
0x01+ lesen | Alle anderen Register liefern beim Lesen 0x5a |
Wie im vorigen Abschnitt beschrieben lässt sich die I²C-Adresse des Mini-I²C-Servo-Adapters ändern. Unter Datei ► Beispiele ► FtduinoSimple ► I2C ► MiniServoAddress findet sich dazu ein fertiger Sketch.
Wird dieser Sketch auf den ftDuino geladen, so kann die Adresse interaktiv geändert werden.
Dies ist übrlicherweise nicht nötig. Erst wenn mehr als ein Mini-I²C-Servo-Adapters gleichzeitig
betrieben werden soll, dann ist es nötig, jedem Adapter eine individuelle Adresse zu geben. Dazu
wird der zu verstellende Adapter zunächst alleine an den ftDuino angeschlossen und die Adresse
wie in Abbildung 6.49 zu sehen verändert.
Schwierigkeitsgrad: ★★★★★
Die Nutzung von WS2812B-Leuchtdioden am ftDuino erfordert etwas Lötarbeit sowie die Installation von Hilfs-Bibliotheken. Dieses Projekt wird daher nur einem fortgeschrittenen Nutzer empfohlen.
Der I²C-Anschluss des ftDuino ist zwar primär zum Anschluss von I²C-Geräten gedacht. Da die dort angeschlossenen Signale SDA und SCL aber auf frei benutzbaren Anschlüsse des ATmega32u4-Mikrocontrollers liegen können sie auch für andere Signalarten zweckentfremdet werden. Ein solches Signal ist der serielle synchrone Datenstrom, wie ihn die WS2812B-Leuchtdioden verwenden. Diese Leuchtdioden gibt es für kleines Geld als Meterware bei diversen Online-Anbietern.
Um die interne Stromversorgung des ftDuino nicht zu überlasten
sollten maximal zwei WS2812B-Leuchtdioden an der 5-Volt-Versorgung des
I²C-Anschlusses des ftDuino betrieben werden. Sollen mehr
Leuchtdioden verwendet werden, so ist eine separate externe
5-Volt-Versorgung vorzusehen.
Jeder WS2812B-Leuchtdiodenstreifen verfügt über drei Eingangssignale: Masse, +5V und DI. Versorgungssignale Masse und +5V werden direkt mit ihren Gegenstücken am I²C-Anschluss verbunden. Das Signal DI steht für ``Data In'' und ist der Datensignaleingang der Leuchtdioden. Der ebenfalls am anderen Ende des Leuchtdiodenstreifens vorhandene Datenausgang (DO) darf nicht verwendet werden. Er leitet das über DI empfangene Signal gegebenenfalls an zusätzliche Leuchtdioden weiter. Das DI-Signal kann wahlweise mit dem SCL oder SDA-Pin des I²C-Anschluss verbunden werden. Der entsprechende Signalname muss später im Sketch eingetragen werden.
Die Leuchtdioden sollten mit Vorsicht angeschlossen werden. Kurzschlüsse oder falsche Verbindungen können die Leuchtdioden und den ftDuino beschädigen.
Das Beispiel zu Ansteuern der WS2812B-Leuchtdioden sowie die nötige Code-Bibliothek können beispielsweise der WS2812BFX-Bibliothek30 entnommen werden. Andere Bibliotheken zur Ansteuerung der WS2812B-Leuchtdioden dürften gleichermaßen zu nutzen sein.
Die Installation der Bibliothek erfordert etwas Erfahrung mit der Arduino-IDE. Wurde die Bibliothek korrekt installiert, dann finden sich diverse Beispiele unter Datei ► Beispiele ► WS2812FX. Das Beispiel auto_mode_cycle ist gut geeignet, die Funktion der Leuchtdioden zu überprüfen.
Am Beginn des Sketches sind lediglich zwei kleine Änderungen vorzunehmen, um die Zahl und den verwendeten Anschluss der Leuchtdioden anzupassen.
1 #include <WS2812FX.h>
2
3 #define LED_COUNT 2
4 #define LED_PIN SCL
5
6 #define TIMER_MS 5000
Schwierigkeitsgrad: ★★☆☆☆
Der ftDuino verfügt über keinen eingebauten Lautsprecher und kann
daher ohne Hilfe keine Töne ausgeben. Es ist aber problemlos möglich,
einen Lautsprecher an einen der Ausgänge des ftDuino
anzuschließen. Dazu eignet sich natürlich besonders gut die
fischertechnik Lautsprecherkassette 36936.
Wichtig ist, dass ein Vorwiderstand von mindestens 100Ω zwischen den Lautsprecher und den ftDuino geschaltet wird. Werden die 9 Volt des ftDuino direkt auf den Lautsprecher gelegt, dann kann der Lautsprecher sehr leicht Schaden nehmen und erzeugte Töne wären extrem laut. Der Vorwiderstand begrenzt den maximal fließenden Strom und schützt Lautsprecher und Gehör.
Schaltet man nun den Ausgang O2 mit 50% PWM-Verhältnis ein, so kann man das PWM-Signal direkt hören.
ftduino.output_set(Ftduino::O2, Ftduino::HI, Ftduino::MAX/2);
Durch das 50% PWM-Signal wird der Ausgang permanent zwischen
HI und OFF umgeschaltet (siehe auch Abschnitt
6.3). Nur wenn der Ausgang HI ist fließt ein Strom
vom Ausgang über den Lautsprecher zum Masse-Anschluss. Da die
PWM-Frequenz der Ftduino-Bibliothek circa 200 Hertz beträgt
hört man dann einen Ton in dieser Frequenz.
Die PWM-Erzeugung wird wie im Abschnitt 6.3 beschrieben nicht über dafür vorgesehene PWM-Ausgänge des ATmega32u4-Mikrocontrollers erzeugt sondern durch Signale, die der Mikrocontroller kontinuierlich über seinen SPI-Bus an die Ausgangstreiber sendet. Dieses Vorgehen ist sehr flexibel und erlaubt es, alle acht Ausgänge mit unabhängigen Signalen zu steuern, es erfordert aber ein konstantes Mitarbeiten des Mikrocontrollers und nimmt einen gewissen Prozentsatz seiner Rechenzeit permanent in Anspruch. Je höher die PWM-Frequenz, desto häufiger muss der Mikrocontroller die Signale ändern und desto höher ist der Bedarf an Rechenzeit, die nicht im eigentlichen Sketch zur Verfügung steht. Bei 200 Hertz ist dieser Effekt zu vernachlässigen. Für eine Tonerzeugung sind aber Frequenzen im Kilohertzbereich nötig. Sollen nicht nur digitale an/aus-Rechtecksignale sondern z.B. auch analoge Sinussignale erzeugt werden, dann sind sogar PWM-Signale im Megahertz-Bereich nötig. Das kann der ATmega32u4 über den SPI-Bus nicht leisten.
Die MC33879-Ausgangstreiber haben jeweils zwei Eingänge31 , die am SPI-Bus vorbei direkt angesteuert werden können. Im ftDuino liegen die meisten dieser Eingänge auf Masse, aber der für den Ausgang O2 zuständige Eingang EN6 des Ausgangstreibers U3 ist mit dem Pin PB7 des ATmega32u4 verbunden. Damit lässt sich einer der Ausgangstransistoren des Ausgangstreibers über diesen Pin am ATmega32u4 direkt schalten. In der Arduino-Welt hat dieser Pin die Nummer 11 und lässt sich mit den üblichen Arduino-Funktionen schalten.
// Highside-Treiber von Ausgang O2 für eine Sekunde aktivieren
pinMode(11, OUTPUT);
digitalWrite(11, HIGH);
delay(1000);
digitalWrite(11, LOW);
Um den Effekt am Ausgang zu sehen muss die
FtduinoSimple-Bibliothek in den Sketch eingebunden sein, da
die nach wie vor nötige Initialisierung der Ausgangstreiber durch die
Bibliothek erfolgt.
Schwierigkeitsgrad: ★☆☆☆☆
Alternativ können auf diesen Pin auch die Arduino-Befehle zur Ton-Erzeugung angewendet werden. Der Beispielsketch unter Datei ► Beispiele ► FtduinoSimple ► Music nutzt dies.
// Kammerton A für eine Sekunde spielen
tone(11, 440, 1000);
Schwierigkeitsgrad: ★★★★★
Der verwendete Pin PB7 ist Teil des ATmega32u4-internen Timer 1. Das bedeutet, dass spezielle Hardware des ATmega32u4 zur Signalerzeugung herangezogen werden kann. Damit können Signale hoher Frequenz ganz ohne Einsatz von Rechenleistung erzeugt werden.
Der Beispiel-Sketch Datei ► Beispiele ► FtduinoSimple nutzt das, um die exakt gleiche Melodie wie der vorige Sketch zu erzeugen. Der Code ist deutlich kryptischer und sieht komplizierter aus. Während die Arduino-tone()-Funktion aber im Hintergrund in einem sogenannten Timer-Interrupt Rechenleistung benötigt, um den Ton zu erzeugen werden die Töne in diesem Beispiel allein aus der sogenannten Timer-Hardware des ATmega32u4-Prozessors erzeugt. Lediglich zum Ändern der Tonhöhe oder zum Stoppen der Tonausgabe ist der eigentliche Rechenteil des Prozessors verantwortlich.
In einem einfachem Musik-Beispiel wie diesem ist der Hintergrundbedarf an Rechenleistung zu vernachlässigen. Sollen aber sehr hohe Frequenzen, z.B. im Ultraschallbereich oder höher erzeugt werden, so steigt der Bedarf an Rechenleistung im Hintergrund, da mit höheren Frequenzen häufiger das Signal geändert werden muss. Die Verwendung der Timer-Hardware hat dieses Problem nicht. Die zur Tonerzeugung nötigen Signalwechsel, also das permanente Ein- und Ausschalten des Ausgangs in der gewünschten Ton-Frequenz wird automatisch erledigt und benötigt daher auch bei hohen Frequenzen keinerlei Rechenzeit des Mikrocontrollers.
Einen Lautsprecher anzuschließen ist nur eine Art, Töne zu erzeugen. Baukastensysteme wie fischertechnik laden natürlich ein, auf elektromechanische Weise Töne auszugeben z.B. mit Hilfe der Klangrohre aus der Dynamic-Baukastenserie.
Mit seiner flexiblen USB-Schnittstelle bietet der ftDuino eine
elegante Methode, solche Fähigkeiten nutzbar zu machen. Die sogenannte
MIDI-Schnittstelle32 wurde
entwickelt, um Computer und elektronische Musikinstrumente zu
verbinden. Neben der elektrisch sehr speziellen MIDI-Verbindung gibt
es eine Variante von MIDI über USB. Die Arduino-Umgebung bietet dafür
die MIDIUSB-Bibliothek an, die über die Bibliotheksverwaltung
der IDE direkt installiert werden kann.
Der ftDuino-Beispielsketch unter Datei ► Beispiele ► FtduinoSimple ► MidiInstrument nutzt diese Bibliothek, um den ftDuino als MIDI-Gerät für den PC nutzbar zu machen. Treiber für entsprechende Geräte bringen die gängigen Betriebssysteme bereits mit und Windows, Linux und MacOS erkennen einen zum MIDI-Gerät konfigurierten ftDuino ohne weitere Treiberinstallation als USB-Audio-Gerät.
Der ftDuino ist ein sogenanntes USB-Verbundgerät. Das bedeutet, dass er mehrere USB-Funktionen gleichzeitig umsetzen kann. Im MIDI-Fall bedeutet das, dass er gegenüber dem PC als MIDI-Gerät erscheint und gleichzeitig weiterhin über die USB-COM:-Schnittstelle verfügt, was speziell während der Sketchentwicklung sehr praktisch sein kann.
Ein mit dem MidiInstrument-Sketch versehener ftDuino wird z.B. von einem Linux-PC mit den gängigen MIDI-Werkzeugen erkannt:
$ aplaymidi -l Port Client name Port name 14:0 Midi Through Midi Through Port-0 24:0 ftDuino ftDuino MIDI 1 $ aplaymidi -p 24:0 demosong.mid ...Der ftDuino wird eine Stimme des Songs auf einem an O2 angeschlossenen Lautsprecher abspielen und gleichzeitig auf dem COM:-Port Informationen über die empfangenen Befehle ausgeben und damit als Basis für eine elektromechanisches Instrument dienen.
Nur wenige MIDI-Dateien lassen sich mit diesem einfachen Setup befriedigend abspielen, weil dieses einfache Beispiel nur monophon ist und nur einen Ton zur Zeit abspielen kann. Mehrstimmige Lieder können nicht abgespielt werden. Diese Beschränkung lässt sich in einem mehrstimmigen mechanischen Musikmodell natürlich aufheben und ergibt sich allein aus der sehr simplen hier verwendeten Art der Tonerzeugung.
Eine monophone Beispieldatei song.mid findet sich im Verzeichnis des Sketches.
Schwierigkeitsgrad: ★★☆☆☆
Mit den meisten modernen Android-Smartphones und -Tabletts lässt sich
der ftDuino über ein passendes Kabel direkt verbinden. Dafür ist
ein sogenanntes USB-On-the-Go(USB-OTG)-Kabel notwendig. Für den
ftDuino eignet sich das Lindy 31717 gut. Es verfügt an beiden Enden
über die passenden Stecker und ist mit 50cm kurz genug, um in einem
Modell untergebracht zu werden.
Mit USB-OTG übernimmt das Smartphone die Rolle des PCs. Es beim Anschluss eines entsprechenden Kabels eine Spannung am USB-Anschluss bereit und übernimmt die Steuerung des USB-Bus als aktiver sogenannter USB-Host. Werden die Ausgänge des ftDuino nicht benötigt, so kann auf diese Weise sogar auf eines eigenen Stromversorgung des ftDuino verzichtet werden. Der ftDuino wird dann vom Handy mit Strom versorgt.
Die gesamte Kommunikation zwischen Smartphone und ftDuino läuft über die serielle USB-Verbindung (COM-Port) und wird ftDuino-seitig nicht anders behandelt als die übliche Kommunikation mit dem PC. In einigen Fällen mag es sinnvoll sein, wenn dem ftDuino bekannt ist, ob die USB-Verbindung zum Smartphone besteht oder nicht, wenn z.B. ohne Smartphone eine automatische Funktion ausgeführt werden soll während mit angeschlossenem Smartphone eine manuelle Bedienung erwünscht ist. Das ist im Sketch über die Abfrage der USB-Stromversorgung möglich.
// Abfrage der USB-Stromversorgung vorbereiten (z.B. in der setup()-Funktion)
USBCON |= (1<<OTGPADE);
// Abfrage der USB-Stromversorgung
if(USBSTA & (1<<VBUS)) {
// USB ist verbunden
// ...
} else {
// USB ist nicht verbunden
// ...
}
Ein kompletter einfacher Demo-Sketch findet sich unter
Datei ► Beispiele ► FtduinoSimple ► USB ► AndroidDemo. Er sendet über USB einmal pro
Sekunde eine Nachricht (``COUNTER: XX'') und erwartet die Nachricht
``ON'' oder ``OFF'' und schaltet den Ausgang O1 entsprechend.
Im ftDuino-Repository findet sich die dazu passende Android-App33 . Sie lässt sich im AndroidStudio übersetzen und als Basis für eigene Entwicklungen nutzen. Die Android-App basiert auf der UsbSerial-Bibliothek34 und kann nach minimalen Anpassungen neben dem ftDuino auch die meisten Arduinos anbinden.
Die Benutzung ist sehr viel einfacher als die sonst verwendeten Bluetooth- oder WLAN-Verbindungen, da sie keine weitere Konfiguration erfordert. Sobald Smartphone und ftDuino verbunden werden startet die entsprechende App und die Verbindung ist vollständig.
Schwierigkeitsgrad: ★★☆☆☆
Die übliche Weise, auf USB-Geräte wie den ftDuino zuzugreifen folgt einem festen Schema: Auf dem PC werden passenden Treiber installiert, die dem PC mitteilen, wie die Kommunikation mit dem dem Gerät abzulaufen hat. Eine PC-Anwendung wie die Arduino-IDE nutzt diesen Treiber, um auf das Gerät zuzugreifen.
WebUSB35 ist der Versuch, die Benutzung von USB-Geräten massiv zu vereinfachen, indem auf Treiber- und Softwareinstallation komplett komplett verzichtet wird. Stattdessen bringt eine spezielle Webseite alles mit, um direkt mit einem entsprechend angepassten USB-Gerät zu kommunizieren. Dabei kann das USB-Gerät dem PC mitteilen, unter welcher URL die steuernde Webseite zu finden ist. Für den Anwender ergibt sich so eine echte Plug-'n-Play-Lösung. Nach dem Anstecken eines bisher unbekannten WebUSB-Gerätes öffnet der Browser direkt die passende Webseite und das Gerät kann sofort ohne Treiber- oder Softwareinstallation verwendet werden.
WebUSB ist kein offizieller Web-Standard und wird daher lediglich von Googles Chromebrowser36 unterstützt. Chrome muss für dieses Experiment nicht auf dem PC installiert sein, es reicht, die sogenannte Portable-Version37 z.B. von einem USB-Stick zu starten. Aus Sicherheitsgründen hat Google in aktuellen Versionen die Möglichkeit zum automatischen Start der vom Gerät gemeldeten URL unterbunden. Die URL https://harbaum.github.io/ftduino/webusb/console muss daher manuell im Browser angegeben werden.
Der Chrome-Browser ist der von Google mitgelieferte Browser auf
Anrdoid-Smartphones und -Tabletts. Diese Version eignet sich ebenfalls
für WebUSB-Experimente. Zum Anschluss des ftDuino an das Smartphone
wird ein USB-Host-Kabel (z.B. Lindy 31717, siehe Abschnitt
6.17) benötigt.
Auf Linux-PCs erfüllt den gleichen Zweck der Chromium-Browser. Er
lässt sich normalerweise über den Paketmanager nachinstallieren. Im
Gegensatz zur Windows-Version funktioniert hier auch das automatische
Weiterleiten an die vom USB-Gerät bereitgestellte URL wie in Abbildung
6.55 zu sehen.
Auf Linux-PCs hat der Webbrowser normalerweise keine ausreichenden Rechte, um USB-Geräte direkt ansprechen zu dürfen. Die Installation der udev-Regeln wie in Abschnitt 2.1.4 beschrieben ermöglicht den Zugriff.
Einige WebUSB-Beispiel-Sketches werden als Beispiel in der ftDuino-Installation der Arduino-IDE unter Datei ► Beispiele ► WebUSB mitgeliefert.
Die URL eines WebUSB-Projektes wird im Sketch direkt angegeben und kann in eigenen Sketches entsprechend angepasst werden.
WebUSB WebUSBSerial(1 /* https:// */, "harbaum.github.io/ftduino/webusb/console");
Neben dem passenden Sketch verlangt die WebUSB-Spezifikation weitere
Anpassungen an der USB-Konfiguration des Geräts. Die nötigen
Änderungen nimmt die Arduino-IDE vor, wenn man in der Board-Auswahl
den Board-Typ ftDuino (WebUSB) wie in Abbildung
6.56 dargestellt auswählt. Diese Einstellung sollte
nur für WebUSB verwendet werden, da die Anpassungen nur in
Zusammenhang mit der WebUSB-Bibliothek vollständig sind und Windows
das Gerät andernfalls nicht erkennt.
Der Datei ► Beispiele ► WebUSB ► Console-Sketch bietet eine einfache Kommandoschnittstelle über USB, mit der die eingebaute Leuchtdiode ein- und ausgeschaltet werden kann.
Ist der Sketch auf dem ftDuino installiert, der ftDuino an den
PC angeschlossen und der Chrome- oder Chromium-Browser geöffnet, so
reicht ein Klick auf Connect, um die Verbindung zum Gerät aus
dem Browser herzustellen. Die Leuchtdiode kann dann über direkt in der
Console eigegebene Befehle gesteuert oder durch Klick auf die Buttons
geschaltet werden.
Das in Abschnitt 8.3 beschriebene
Brickly-Projekt38
hat seinen Ausgangspunkt bei der Community-Firmware für den
TXT-Controller. Brickly basiert auf Blockly39 , einer grafischen
Programmierumgebung zur Nutzung per Webbrowser. Im Falle des TXTs
können so per Smartphone, PC oder Tablett mit Hilfe des Webbrowsers
Programmer erstellt und auf dem TXT laufen gelassen werden.
Brickly-lite wurde für den ftDuino völlig neu konzipiert. Auf die Ausführung von Blockly-generiertem Code auf dem ftDuino wurde dabei verzichtet. Stattdessen werden die Brickly-lite-Programme am Browser erstellt und auch im Browser ausgeführt. Lediglich zur Bedienung der fischertechnik-Sensoren und -Aktoren greift der Browser per USB auf einen angeschlossenen ftDuino zurück. Auf dem ftDuino muss dabei der Sketch Datei ► Beispiele ► WebUSB ► IoServer laufen. Da dieser Sketch mit einem internen OLED-Display (siehe Abschnitt 1.2.7) umgehen kann wird die ``Adafruit GFX Library''40 zum Übersetzen des Sketches benötigt.
Die Brickly-lite-Webseiten finden sich unter https://harbaum.github.io/ftduino/webusb/brickly-lite/. Zur Benutzung muss der ftDuino mit installiertem Datei ► Beispiele ► WebUSB ► IoServer-Sketch direkt an PC, Smartphone oder Tablett angeschlossen sein. Der Chrome-Browser verbindet sich dann mit dem ftDuino und sobald Ein- oder Ausgaben am Modell erfolgen sollen sendet der Browser enstprechende Befehle an den ftDuino.
Den Anspruch eines echten ``Plug-n-Play''-Erlebnisses kann die Festlegung auf den Chrome-Browser und der fehlende Auto-Start der vom Gerät gesendeten URL unter Windows leider nicht erfüllen. Mit einer vorbereitenen Portable-Installation des passenden Browsers auf einem USB-Stick kann man dennoch auch für Anfänger leicht und ohne Installation zu nutzende Szenarien schaffen, die sich z.B. auf PC-Pools in Schulen einsetzen lassen. Das Beispiel unter Datei ► Beispiele ► WebUSB ► Console kann dafür als Ausgangspunkt für Browser-bedienbare einfache Modelle dienen.
Ein ähnliches grafisches Programmiersystem ist ``Scratch for Arduino'' und ``Scatch 3.0''. Mehr Informationen finden sich in Abschnitt 8.6 und 6.18.5.
Scratch 3.0 basiert wie Brickly auf dem Blockly-Projekt von Google.
Dementsprechend nutzen beide eine sehr ähnliche Art, wer WebUSB
aus dem Browser auf dem ftDuino zuzugreifen.
Während Brickly eine komplette ftDuino-spezifische Entwicklung ist ist Scratch 3.0 ein eigenständiges Projekt. Die unter https://harbaum.github.io/ftduino/webusb/scratch3/ befindliche Variante von Scratch 3.0 beinhaltet zusätzlich eine sogenannte Extension zur Ansteuerung des ftDuino.
Die ftDuino-Extension greift direkt auf den ftDuino zu und benötigt daher im Gegensatz zu z.B. den Lego-Extensions keine weitere Software auf dem PC. Damit kann die Extension auf allen Plattformen genutzt werden, die prinzipiell WebUSB unterstützen. Das sind neben den üblichen Windows-, Apple- und Linux-PCs auch die meisten Smartphones und Android-Tabletts.
Mehr Informationen zu Scratch 3.0 und dem Einsatz des ftDuino finden sich in Abschnitt 5.1.4.
Schwierigkeitsgrad: ★★★☆☆
Bluetooth ist eine drahtlose Übertragungstechnik für Kurzstrecken.
Die meisten PCs, Tabletts und Smartphones beherrschen Bluetooth und
können sich so drahtlos mit Endgeräten verbinden. Viele Spielzeuge
unterstützen Bluetooth ebenfalls und auch die meisten Controller
von Lego oder fischertechnik beherrschen diese Technologie.
Bluetooth existiert in vielen Varianten mit unterschiedlichen Datenraten, Reichweiten, Energiebedarf und ähnlich. Die meisten Unterschiede sind für die Anwendung am ftDuino irrelevant. Es gibt allerdings eine fundamentale Unterscheidung zwischen dem sogenannten klassischen Bluetooth und Bluetooth-Low-Energy, die für die Nutzung am ftDuino bedeutsam ist.
Als klassisches Bluetooth wird üblicherweise die ursprünglich Variante bezeichnet. Sie wurde vor allem zum spontanen Datenaustausch zwischen PC und mobilen Endgeräten entworfen und findet zum Beispiel dann Verwendung, wenn über Bluetooth Dateien, Bilder, Kontakte oder ähnlich ausgetauscht werden. Auch Bluetooth-Tastaturen und -Mäuse sowie Bluetooth-Kopfhörer und -Lautsprecher verwenden klassisches Bluetooth. Das klassische Bluetooth implementiert dafür sogenannte Profile. Eines dieser Profile ist z.B. das Object-Exchange-Profil (OBEX), das für den Austausch Dateien verwendet wird.
Ein weiteres Profil des klassischen Bluetooth ist das sogenannte Serial-Port-Profil (SPP). Dieses Profil stellt eine Punkt-zu-Punkt Datenverbindung her. SPP sollte vor allem kabelgebundene serielle RS232-Verbindungen ersetzen und kam zum Beispiel häufig mit separaten GPS-Empfängern und ähnlichen Geräten zum Einsatz. Heutzutage spielt das SPP eine geringe Rolle, wird aber von den meisten Betriebssystemen, die klassisches Bluetooth einsetzen, nach wie vor unterstützt. Dazu zählen die aktuelle PC-Betriebssysteme wie Windows, MacOS und Linux ebenso wie einige Mobilbetriebssysteme.
Da die PC-Betriebssysteme schon immer mit seriellen RS232-Verbindungen umgehen konnten gibt es entsprechend viel Software, die diese Verbindungen nutzen kann. Diese Unterstützung überträgt sich auf SPP, USB und andere moderne Technologien, die auf serielle Verbindungen abgebildet werden können. Für den Benutzer sieht daher eine SPP-Bluetooth-Verbindung aus wie jede andere serielle Verbindung und wird z.B. unter Windows durch einen sogenannten COM-Port dargestellt. Jede Windows-Software, die einen COM-Port nutzen kann, kann auch eine SPP-Bluetooth-Verbindung nutzen. Dazu zählt unter anderem die Arduino-IDE selbst, die einen COM-Port zur Verbindung mit dem Arduino oder ftDuino nutzt und somit auch eine SPP-Bluetooth-Verbindung nutzen kann.
Bei den Mobilbetriebssystemen ist die Nutzung von seriellen Verbindungen weniger verbreitet. Eine Verwendung des SPP unter Android möglich, wird aber von IOS inzwischen nicht mehr unterstützt.
Auch Geräte wie der TXT-Controller oder der Raspberry-Pi unterstützen klassisches Bluetooth und SPP.
Im Gegensatz zum klassischen Bluetooth ist Bluetooth-Low-Energy (BLE) eine recht junge Technologie. Sie wurde erst sehr spät zur Bluetooth-Familie hinzugefügt und basiert auf gänzlich neuen Übertragungsverfahren und Protokollen. Die Kommunikation mit BLE-Geräten erfordert relativ moderne Hardware und gänzlich andere Software. BLE wurde vor allem auf geringen Energieverbrauch ausgerichtet. Dies wird durch geringe Datenraten und geringe zu übertragene Datenmengen erreicht. Zusätzlich verzichtet BLE auf einen komplexen und langwierigen Verbindungsauf- und abbau. Stattdessen werden bei BLE kleine Datenpakete versendet.
Im PC-Bereich wird BLE eher selten verwendet und die Unterstützung auch in den neuesten Windows-Betriebsystemversionen ist häufig problematisch41 . Aber vor allem bei der Verbindung mit mobilen Endgeräten mit Geräten wie Smart-Watches, Pulssensoren und ähnlich hat sich BLE etabliert. Die Unterstützung von BLE in den Mobilbetriebssystemen Android und IOS ist ausgereift und zuverlässig.
Geräte wie der TXT-Controller oder der Raspberry-Pi unterstützen neben klassischem Bluetooth auch BLE.
Die vorherigen Beschreibungen lassen es schon erahnen: Während klassisches Bluetooth vor allem bei PCs eingesetzt wird ist BLE eher im Mobilumfeld die Technologie der Wahl.
Das bedeutet nicht, dass es umgekehrt generell gar nicht funktioniert. Eine Nutzung von BLE ist unter Windows unter bestimmten Bedingungen möglich und Android bietet weitgehende SPP-Unterstützung für klassisches Bluetooth. Im Zweifelsfall stellt aber klassisches Bluetooth im PC-Umfeld die einfachere Lösung dar und BLE bietet sich im Zusammenspiel mit Mobilgeräten an.
Einfache Arduinos verfügen ab Werk genauso wenig über Bluetooth-Unterstützung wie der ftDuino. Für die Bluetooth-Nutzung ist daher Zusatzhardware nötig. Sehr preisgünstig und verbreitet sind kleine Module der Serien HC-05, HC-06 und HM-10 wie in Abbildung 6.60 dargestellt.
Während die Module HC-05 und HC-06 klassisches Bluetooth unterstützen nutzt das HM-10-Modul Bluetooth-Low-Energy. Die Unterschiede zwischen HC-05 und HC-06 sind kleiner. Während das HC-05 etwas leistungsfähiger ist und z.B. selbst Verbindungen zu anderen Geräten aufbauen kann (unter anderem seinesgleichen) ist das HC-06 darauf beschränkt, von anderen Geräten angesprochen zu werden. Für die allermeisten Einsatzzwecke ist das völlig ausreichend, denn in der Regel wird man von einem PC oder Mobilgerät die Verbindung zum ftDuino herstellen wollen.
HC-05 und HC-06 eigenen sich vor allem zur Verbindung mit Windows-PCs. Das HM-10-Modul auf der anderen Seite kann als einziges der drei Module mit IOS-basierten Mobilgeräten eingesetzt werden.
Windows | Linux | MacOS | Android | IOS | |
HC-05 | ok | ok | ok | ok | nicht nutzbar |
HC-06 | ok | ok | ok | ok | nicht nutzbar |
HM-10 | problematisch | ok | ok | ok | ok |
Elektrisch und mechanisch unterscheiden sich die drei Module nur wenig, so dass die Anbindung an den ftDuino für alle drei gleich abläuft und das Modul jederzeit austauschbar ist.
Die Verbindung zum Arduino/ftDuino erfolgt bei allen drei
Modulen über vier Signale:
VCC | Versorgungsspannung von 5 Volt |
GND | Masse |
TXD | serieller UART-Datenausgang des Moduls |
RXD | serieller UART-Dateneingang zum Modul |
Über eine passende UART-Schnittstelle verfügen zwar die Mikrocontroller des Arduino wie auch des ftDuino. Diese Schnittstelle ist beim klassischen Arduino-UNO bereits für die USB-Kommunikation zum PC genutzt. Beim ftDuino werden diese Signale für die Zählereingänge C1 und C2 verwendet. In beiden Fällen steht die UART-Schnittstelle nicht direkt zum Anschluss eines Bluetooth-Moduls zur Verfügung.
Zusätzlich ist zu beachten, dass die Module zwar mit 5 Volt versorgt werden, aber ihre UART-Signale nur 3,3 Volt nutzen. Das macht für die TXD-Verbindung vom Modul zum Arduino/ftDuino keinen Unterschied, da diese mit den niedrigeren Spannungspegeln des Moduls umgehen können. Die Verbindung vom Arduino/ftDuino zum RXD-Eingang des Moduls sollte aber so gestaltet werden, dass nicht die vollen 5 Volt vom TX-Ausgang des Arduino/ftDuino auf das Modul treffen. Diverse Anleitungen im Internet ignorieren diese Regel, was darauf hindeutet, dass die Module in dieser Beziehung robuster sind als der Aufdruck auf ihrer Unterseite vermuten lässt. Dennoch schadet es sicher nicht, innerhalb der 3,3-Volt-Grenzen zu bleiben.
Im den fehlenden Zugriff auf den Hardware-UART des Mikrocontrollers in Arduino und ftDuino zu umgehen behilft man sich in der Arduino-Welt in der Regel mit der Nutzung der SoftwareSerial-Bibliothek42 . Mit ihrer Hilfe können auch andere Pins des Mikrocontrollers in begrenztem Maße UART-Aufgaben übernehmen. Am ftDuino sind lediglich zwei Anschlüsse des Mikrocontrollers direkt von außen zugänglich. Dies sind die SCL- und SDA-Signale am I²C-Anschluss des ftDuino. Diese beiden Signale sind leider nicht per SoftwareSerial nutzbar. Damit kann SoftwareSerial am ftDuino nicht wie bei Arduinos üblich zur Kommunikation mit den Bluetooth-Modulen genutzt werden.
Eine elegante Möglichkeit ist der Einsatz eines Bausteins, der zwischen dem I²C-Anschluss des ftDuino und dem UART-Protokoll, wie es für die Bluetooth-Module benötigt wird, übersetzen kann.
Ein solcher Baustein ist der SC16IS75043
von NXP. Er ist unter anderem unter der Bezeichnung CJMCU 750 auf
einfachen Adapterplatinen im Online-Handel erhältlich und lässt sich
sowohl direkt mit dem I²C-Anschluss des ftDuino als auch mit den
UART-Signalen der Bluetooth-Module verbinden. Ein weiterer Vorteil
dieses Chips ist, dass er mit 3,3-Volt-Signalen arbeitet und so keine
Gefahr für das Bluetooth-Modul darstellt. Auf der anderen Seite ist er
selbst tolerant gegen 5 Volt auf der I²C-Seite zum ftDuino.
Abbildung 6.62 stellt die nötigen Verbindungen dar, die zwischen I²C-Anschluss des ftDuino und I²C-Anschluss des CJMCU 750 sowie UART-Anschluss des CJMCU 750 und dem Bluetooth-Modul hergestellt werden müssen.
Die Anschlüsse A0-CS und A1-SI des CJMCU 750 werden in diesem Beispiel auf Masse gelegt. Der SC16IS750 reagiert daher auf Adresse 0x4e am I²C-Bus. Dies wird in den folgenden Beispielsketches berücksichtigt. Sollen mehrere SC16IS750 am ftDuino angeschlossen werden, so kann durch entsprechende Beschaltung von A0-CS und A1-SI eine andere Adresse vergeben werden.
Ein einfacher Beispielsketch findet sich unter Datei ► Beispiele ► Ftduino ► Bluetooth ► CJMCU_750 ► Bridge. Er überbrückt in beiden Richtungen zwischen dem USB-Anschluss des ftDuino zum PC und dem UART-Anschluss des SC16IS750 zum Bluetooth-Modul. Jedes Zeichen, das vom PC (zum Beispiel mit Hilfe des seriellen Monitors, siehe Abschnitt 3.3.1) an den ftDuino gesendet wird, wird vom ftDuino an das Bluetooth-Modul weitergeleitet und umgekehrt. Man kann so direkt mit dem Bluetooth-Modul kommunizieren und Daten aus dem seriellen Monitor über Bluetooth senden. Per Bluetooth empfangene Daten werden wiederum direkt im seriellen Monitor angezeigt.
Wie bereits erwähnt wird der UART des Mikrocontrollers des ftDuino
intern bereits verwendet. Da auch der fischertechnik-Ultraschallsensor
(siehe Abschnitt 1.2.6) einen UART verwendet wurde das
UART-Empfangssignal des ftDuino auf dem Zählereingang C1 zugänglich
gemacht. Die Schutzschaltungen im ftDuino haben einen geringen
Einfluss auf die eingehenden Signale, so dass sich der TXD-Anschluss
eines Bluetooth-Moduls direkt mit dem Zählereingang C1 des ftDuino
verbinden lässt und so doch in den Genuss des UART im Mikrocontroller
kommt.
Die für das Modul nötige 5-Volt-Versorgungsspannung kann wie in Abbildung 6.63 zu sehen vom I²C-Anschluss abgegriffen werden. Dazu finden am einfachsten sogenannte Buchse-auf-Buchse-Jumperwire Verwendung wie in der Abbildung zu sehen. Diese Kabel lassen sich sowohl direkt auf die Pins des ftDuino-I²C-Anschlusses stecken aus auch auf die Pins am Bluetooth-Modul.
Achtung: Ein auf diese einfache Art angeschlossenes Bluetooth-Modul kann keine Daten vom ftDuino empfangen, sondern nur an ihn senden. Für die Bluetooth-Verbindung zum Beispiel zu einem PC bedeutet das, dass Daten zwar vom PC an den ftDuino geschickt werden können, aber nicht vom ftDuino zum PC. Für viele einfache Fernsteueranwendungen ist das aber ausreichend und zum Beispiel ArduinoBlue (siehe Abschnitt 6.19.3 ist vollständig nutzbar.
Der Datenempfang von einem PC kann zum Beispiel mit dem Sketch Datei ► Beispiele ► Ftduino ► Bluetooth ► CounterPort ► Bridge im seriellen Monitor beobachtet werden.
Die Nutzung des UARTs in dieser Form gerät in Konflikt mit der Ftduino-Bibliothek, da dort wie gesagt der UART ebenfalls Verwendung für den Ultraschallsensor findet. Der Beispielsketch Datei ► Beispiele ► Ftduino ► Bluetooth ► CounterPort ► ArduinoBlue beinhaltet daher eine modifizierte Version der Ftduino-Bibliothek, die keine Unterstützung für den Ultraschallsensor enthält. Diese Version kann ohne Konflikt mit dem Bluetooth-Anschluss über C1 genutzt werden.
Die UART-Sendeleitung des Mikrocontrollers, die zum Senden von Daten vom ftDuino zum Bluetooth-Modul nötig ist, wird intern für den Zähleranschluss C2 verwendet. Dieser Anschluss ist in der normalen Konfiguration des ftDuino ein Eingang und mit entsprechenden Schutzschaltungen versehen.
Nutzt man diesen Anschluss als Ausgang, so sorgen diese Schutzschaltungen dafür, dass ein ausgehendes Digitalsignal eine Spannung von 2,5 Volt als Low-Pegel (0) und eine Spannung von 5 Volt als High-Pegel (1) aufweist. Der RXD-Eingang am Bluetooth-Modul erwartet aber eine Spannung kleiner 0,8 Volt für ein Low-Signal und eine Spannung zwischen 2 und 3,3 Volt für ein High-Signal.
Eine der einfachsten Möglichkeiten, die Spannung entsprechend
abzusenken bietet eine einfache Siliziumleuchtdiode. Wie in Abbildung
6.64 dargestellt kann ihr Spannungsabfall genutzt
werden, um den Signalpegel um ca. zwei Volt zu senken. Die
resultierenden 0,5 Volt und 3 Volt werden vom Bluetooth-Modul sicher
erkannt und liegen innerhalb des für das Bluetooth-Modul verträglichen
Bereiches unter 3,3 Volt. Beim Anschluss der Leuchtdiode ist die
Polarität zu beachten. Der längere Anschlussdraht der Leuchtdiode
(Anode) gehört an den C2-Anschluss des ftDuino. Sind
Leuchtdiode und Widerstand korrekt angeschlossen, dann sollte die
Leuchtdiode ganz schwach leuchten. Der 100k-Widerstand stellt sicher,
dass die Spannung beim Wechsel von 3 auf 0,5 Volt schnell genug sinkt.
Mit dieser Schaltung ist ein bidirektionaler Betrieb möglich und die
Kommunikation ist sowohl vom ftDuino zum PC als auch in
Gegenrichtung vom PC zum ftDuino möglich.
Der Sketch Datei ► Beispiele ► Ftduino ► Bluetooth ► CounterPort ► Bridge erlaubt so unter anderem die Konfiguration des Bluetooth-Moduls per sogenannter AT-Kommandos. Abbildung 6.65 zeigt unter Nutzung des Bridge-Sketches die Reaktion des HM-10 auf die Kommandos AT+NAME, AT+VERSION und AT+HELP. HC-05 und HC-06 reagieren gegebenenfalls etwas anders auf Kommandos beziehungsweise müssen erst per Tastendruck in den Kommandomodus gebracht werden. Diese Kommandos sind für den einfachen Betrieb zunächst bedeutungslos. Sie beweisen hier nur beispielhaft die erfolgreiche Kommunikation in beide Richtungen.
Das verbleibende Manko ist die Nutzung des I²C-Anschlusses zur
Stromversorgung des Bluetooth-Moduls. Zum einen wird dadurch der
Anschluss mechanisch blockiert und kann nicht mehr zum Anschluss
von I²C-Sensoren genutzt werden. Zum anderen wird die interne
Spannungsversorgung des ftDuino unnötig belastet.
Abbildung 6.66 zeigt daher, wie ein einfacher
7805-Spannungsregler eine Versorgung aus den 9 Volt des ftDuino
ermöglicht. Einziger Nachteil dieser Lösung ist, dass der ftDuino
nun tatsächlich mit 9 Volt versorgt werden muss. Für die Nutzung des
I²C-Anschlusses war eine Versorgung des ftDuino über USB
ausreichend.
Abbildung 6.67 zeigt im Detail, welche Einzelteile nötig sind und wie sie mit dem ftDuino zu verbinden sind. Die nötigen Einzelteile sind zum Beispiel bei Reichelt44 erhältlich. Die verlinkte Liste enthält auch das HC-05-Bluetooth-Modul, das bei Bedarf durch ein HM-10 (leider nicht bei Reichelt erhältlich) ersetzt werden kann.
Es bestehen mehrere Möglichkeiten, den ftDuino mit einem Bluetooth-Modul zu erweitern. Die wesentlichen Vor- und Nachteile dieser Lösungen sind:
Erste Versuche sind am einfachsten mit dem alleinigen Anschluss über C1 möglich. Reine Fernsteueranwendungen sind damit bereits möglich. Die zusätzliche Nutzung von C2 eröffnet sämtliche Möglichkeiten der Bluetooth-Kommunikation. Die Verwendung eines I²C-UART oder der 9-Volt-Versorgung sind optional und kann je nach Erfahrung und Bedarf erfolgen.
Soll Bluetooth zusammen mit dem fischertechnik-Ultraschallsensor am ftDuino eingesetzt werden, so scheidet die Nutzung von C1 aus und es muss ein I²C-UART verwendet werden.
Bluetooth am ftDuino erfordert die Benutzung einer passenden Gegenstelle in Form passender Software am PC oder Smartphone.
Für die Nutzung an einem Windows-PC eignet sich wie beschrieben das HC-05 am besten. Sobald es mit Spannung versorgt ist und seine rote Leuchtdiode hektisch (circa 5 mal je Sekunde) blinkt ist es bereit, eine Verbindung vom PC anzunehmen.
Am PC nutzt man das Bluetooth-Icon in der Symbolleiste unten rechts und bindet das HC-05 als neues Gerät ein. Dabei wird während der Kopplung eine Sicherheits-Pin abgefragt. Diese lautet für alle hier vorgestellten Module ab Werk 1234.
Nach erfolgreicher Kopplung erscheint das HC-05 unter Windows im Fenster ``Geräte und Drucker'' wie in Abbildung 6.68 dargestellt. Die eigentliche Kommunikation erfolgt danach über einen COM-Port, den man wie dargestellt in Erfahrung bringen kann. In diesem Fall ist das HC-05-Modul als COM6 eingebunden und kann zum Beispiel aus der Arduino-IDE mit Hilfe des seriellen Monitors angesprochen werden.
Hinweis: Der Bluetooth-COM-Port dient ausschließlich dem Datenaustausch
über Bluetooth. Es ist zum Beispiel nicht möglich, einen neuen Sketch auf
den ftDuino über Bluetooth aufzuspielen.
Neben der Arduino-IDE eignen sich andere sogenannte Terminalprogramme wie zum Beispiel Tera-Term45 zur Kommunikation über den COM-Port. Da die Arduino-IDE nur ein serielles Monitorfenster zur Zeit öffnen kann ist die Benutzung eines zweiten Terminalprogramms gegebenenfalls nötig, wenn man Testdaten zwischen ftDuino-USB-COM-Port und Bluetooth-COM-Port austauschen will.
Beispiel-Sketches zur Nutzung unter Windows sind Datei ► Beispiele ► Ftduino ► Bluetooth ► CounterPort ► Bridge und Datei ► Beispiele ► Ftduino ► Bluetooth ► CJMCU_750 ► Bridge.
Die App-Stores der großen Mobilbetriebssysteme bieten eine Vielzahl von Apps zum Zugriff auf das HM-10-Modul und im Falle von Android auch zum Zugriff auf das HC-05 oder HC-06.
Für das HM-10 sticht die kostenlose und werbefreie App ArduinoBlue46 aus der Masse.
Wie in Abbildung 6.69 dargestellt ist die Oberfläche
von ArduinoBlue übersichtlich gehalten und erlaubt sowohl eine
Joystick-Steuerung des Modells, als auch eine Steuerung durch
einstellbare Schaltflächen und Slider.
ArduinoBlue ist für Android und IOS verfügbar.
Beispiel-Sketches zur Nutzung mit ArduinoBlue sind Datei ► Beispiele ► Ftduino ► Bluetooth ► CounterPort ► ArduinoBlue und Datei ► Beispiele ► Ftduino ► Bluetooth ► CJMCU_750 ► ArduinoBlue. Ersterer enthält wieder die angepasste Version der ftduino-Bibliothek und zeigt beispielhaft, wie ein Motor am M1-Anschluss des ftDuino über den Joystick in ArduinoBlue gesteuert werden kann.