ftDuino Bedienungsanleitung (PDF)
1. Controller- 2. Installation- 3. Erste Schritte- 4. Programmierung- 5. Schule- 6. Experimente- 7. Modelle- 8. Community- 9. Bibliotheken- 10. Aufbau- Anhang

6 Experimente

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.

6.1 Lampen-Zeitschaltung

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.


Abbildung 6.1: Lampen-Zeitschaltung

6.1.1 Sketch LampTimer

Der folgende Sketch findet sich bei installierter ftDuino-Unterstützung im Menü der Arduino-IDE unter DateiBeispieleFtduinoSimpleLampTimer.

      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  

Sketchbeschreibung

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.

Aufgabe 1: 20 Sekunden

Sorge dafür, dass die Lampe nach jedem Tastendruck 20 Sekunden lang an bleibt.

Lösung 1:

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)) {

Aufgabe 2: Keine Verlängerung

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.

Lösung 2:

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();

Expertenaufgabe:

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?

Erklärung

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 bzw. 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.

6.2 Not-Aus

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.


Abbildung 6.2: Not-Aus

6.2.1 Sketch EmergencyStop

      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  

Sketchbeschreibung

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.

Aufgabe 1: Kabelbruch

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.

Lösung 1:

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.


Abbildung 6.3: Kabelbruch-sicherer Not-Aus-Öffner

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.

Expertenaufgabe:

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.

Lösung:

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.


Abbildung 6.4: Gegen Kabelbruch und Kurzschluss sicherer Not-Aus

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?

6.3 Pulsweitenmodulation

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 bzw. Stillstand bis zu maximaler Helligkeit bzw. 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.


Abbildung 6.5: Pulsweitenmodulation

6.3.1 Sketch Pwm

      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  

Sketchbeschreibung

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 usw. 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.

Aufgabe 1: Die träge Lampe

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.


Abbildung 6.6: Muster bei schneller Bewegung der flackernden Leuchtdiode

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.

Aufgabe 2: Töne aus dem Motor

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.

Aufgabe 3: Nachteil hoher PWM-Frequenzen

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.

Motordrehzahl in Abhängigkeit des PWM-Verhältnisses

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.


Abbildung 6.7: Ausgewählte PWM-Verhältnisse von 0 bis 100%

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.


Abbildung 6.8: Anschluss des TXT-Encoder-Motors zur PWM-abhängigen Drehzahlmessung

Das Beispiel DateiBeispieleFtduinoPwmSpeed 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 WerkzeugeSerieller Plotter befindet, so kann man die Messergebnisse anschaulich visualisieren.


Abbildung 6.9: Leerlaufdrehzahl des TXT-Encoder-Motors in Abhängigkeit des PWM-Verhältnisses

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.

6.4 Schrittmotoransteuerung

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 bzw. 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.


Abbildung 6.10: 17HS13-Schrittmotor am ftDuino

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 .


Abbildung 6.11: Anschluss des Schrittmotors an den ftDuino

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.


Abbildung 6.12: Vereinfachtes Schema eines Schrittmotors

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.

6.4.1 Vollschrittsteuerung

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.


Abbildung 6.13: Vollschrittsteuerung eines Schrittmotors

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 DateiBeispieleFtduinoSimpleStepperMotor.

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.

6.4.2 Halbschrittsteuerung

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.


Abbildung 6.14: Halbschrittsteuerung eines Schrittmotors

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.

Timer-Interrupt betriebener Schrittmotor

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 DateiBeispieleFtduinoSimpleStepperMotorSrv. 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.

6.5 Servomotoransteuerung

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.

(a) Versorgung durch den ftDuino
(b) Versorgung mit 7806-Regler

Abbildung 6.15: Anschluss des Servos an den ftDuino

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.

6.5.1 Externe 6-Volt-Versorgung

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.

(a) Servo an Regler und Adapterkabel
(b) Spannungsregler und Adapterkabel

Abbildung 6.16: Servo-Motor am ftDuino

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.


Abbildung 6.17: Servo-Winkel in Abhängigkeit vom Stellsignal

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 DateiBeispieleFtduinoSimpleServoDemo 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.

6.6 Die Eingänge des ftDuino

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.


Abbildung 6.18: Interne Beschaltung der Eingänge I1 bis I8 des ftDuino

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.

6.6.1 Spannungsmessung

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.

6.6.2 Widerstandsmessung

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.

6.6.3 Ein Eingang als Ausgang

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.


Abbildung 6.19: Anschluss einer LED an Eingang I1 des ftDuino

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  }

6.7 Temperaturmessung

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Ω.


Abbildung 6.20: Anschluss des Temperatursensors an Eingang I1

6.7.1 Sketch Temperature

Der folgende Sketch findet sich bei installierter ftDuino-Unterstützung im Menü der Arduino-IDE unter DateiBeispieleFtduinoTemperature.

      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  }

Sketchbeschreibung

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.

6.8 Ausgänge an, aus oder nichts davon?

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.


Abbildung 6.21: Zwei Lampen an Ausgang O1

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

6.8.1 Sketch OnOffTristate

      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  

6.8.2 Leckströme

Ganz korrekt ist die Aussage, dass im hochohmigen bzw. 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.

6.9 Aktive Motorbremse

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.


Abbildung 6.22: Der TXT-Encoder-Motor als Generator

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 bzw. 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.


Abbildung 6.23: Elektrisch gebremster und ungebremster Elektromotor

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.


Abbildung 6.24: Anschluss des TXT-Encoder-Motors an die Anschlüsse M1 und C1

Das Beispiel DateiBeispieleFtduinoMotorBrake 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 bzw. dass er aktiv gebremst wird.


Abbildung 6.25: Ausgabe bei Verwendung des TXT-Encoder-Motors

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.

6.10 USB-Tastatur

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.


Abbildung 6.26: Tastatur-Nachricht

6.10.1 Sketch USB/KeyboardMessage

      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  

Sketchbeschreibung

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.

6.11 USB-GamePad

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.


Abbildung 6.27: GamePad mit vier Richtungstasten und zwei Feuerknöpfen

6.11.1 Sketch USB/GamePad

Das entsprechende Beispiel findet sich unter DateiBeispieleFtduinoSimpleUSBGamePad. 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 bzw. 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.

6.12 Entprellen

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.


Abbildung 6.28: Entprellen

6.12.1 Sketch Debounce

      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  

Sketchbeschreibung

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.

Aufgabe 1: Es zählt zu viel

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.

Lösung 1:

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.

Aufgabe 2: Was passiert denn nun genau?

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?

Lösung 2:

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 WerkzeugeSerieller 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 DateiBeispieleFtduinoSimpleBounceVisu 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.


Abbildung 6.29: Verlauf des Prellens im seriellen Plotter

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.

6.13 Nutzung des I²C-Bus

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.

(a) Verdrahtungsschema
(b) fertiger Sensor

Abbildung 6.30: MPU6050-Sensor mit Anschlusskabel für den ftDuino

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 .


Abbildung 6.31: Diverse I²C-Sensoren mit passendem Anschlusskabel an den ftDuino

6.13.1 Sketch I2C/I2cScanner

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 DateiBeispieleFtduinoSimpleI2CI2cScanner 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.


Abbildung 6.32: Ausgabe von I2cScanner bei angeschlossenem MPU-6050

6.13.2 MPU-6050-Sensor

Für den MPU6050 liefert die ftDuino-Umgebung ein eigenes Beispiel mit. Der Beispiel-Sketch unter DateiBeispieleFtduinoSimpleI2CMPU6050Test liest die Beschelunigungswerte aus dem MPU-6050 aus und gibt sie auf dem seriellen Monitor aus.


Abbildung 6.33: Ausgabe von MPU6050Test

6.13.3 OLED-Display

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 .

(a) Vorderseite
(b) Rückseite
(c) im Gehäuse

Abbildung 6.34: OLED-Display mit Anschlusskabel für den ftDuino

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 DateiBeispieleAdafruit SSD1306ssd1306_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 DateiBeispieleFtduinoSimpleShootduino. Das Spiel erwartet drei Taster an den Eingängen I1, I2 und I3 zur Steuerung des Raumschiffs und gegebenenfalls eine Lampe an O1.

6.13.4 VL53L0X LIDAR-Distanzsensor

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.


Abbildung 6.35: Anschlussschema des VL53L0X an den ftDuino

Ein passendes Gehäuse zum selbst-drucken findet sich im ftDuino-Repository17 .


Abbildung 6.36: VL53L0X in 3D-gedrucktem Gehäuse

Wie für fast alle üblichen I²C-Sensoren findet man auch beim VL53L0X bereits fertige Arduino-Bibliotheken und -Sketches im Internet18 .

6.13.5 ftDuino als I²C-Client und Kopplung zweier ftDuinos

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.


Abbildung 6.37: Kopplung zweier ftDuinos über I²C

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 DateiBeispieleFtduinoSimpleI2CI2cMaster und DateiBeispieleFtduinoSimpleI2CI2cSlave.

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.

Erweiterter I2cSlave

Neben dem einfachen Beispiel DateiBeispieleFtduinoSimpleI2CI2cSlave, das auf der funktionsreduzierten FtduinoSimple-Bibliothek aufbaut befindet sich unter DateiBeispieleFtduinoI2CI2cSlave 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.


Abbildung 6.38: Kopplung von vier ftDuinos über I²C

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 DateiBeispieleFtduinoI2CI2cSlave. 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 DateiBeispieleFtduinoI2CI2cMaster. 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.


Abbildung 6.39: Vier ftDuinos über I²C gekoppelt

Das Beispiel DateiBeispieleFtduinoI2CI2cMaster 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.

Registerbelegungen für Ausgänge O1 bis O8 bzw. M1 bis M4

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)

Registerbelegungen für Eingänge I1 bis I8

Es können maximal die beiden Bytes eines Eingangs in einem gemeinsamen I2C-Transfer gelesen werden. Jeder Eingang muss einzeln gelesen werden.

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)

Registerbelegungen für Zählereingänge C1 bis C4

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)

ftDuino als I²C-Slave am PC

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 .

(a) Verdrahtungsschema
(b) fertiger Adapter

Abbildung 6.40: Digispark/i2c_tiny_usb zum Anschluss an den I²C des ftDuino

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/A
Der 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 .

ftDuino als I²C-Slave am TXT

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.

Einfacher Levelshifter

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.

(a) Kabelschema
(b) Anschluss an den TXT

Abbildung 6.41: Levelshifter zur Verbindung von TXT und ftDuino

6.13.6 ftDuino-I²C-Expander

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.

(a) fertiges Gerät
(b) Einzelteile

Abbildung 6.42: I²C-Expander für den ftDuino

Der I²C-Expander stellt einen TXT-kompatiblen 10-poligen I²C-Anschluss bereit und vier 6-polige TX- bzw. 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 bzw. 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.

6.13.7 fischertechnik-Orientierungssensor

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.


Abbildung 6.43: Anschluss eines fischertechnik-Sensors via I²C-Expander

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.

(a) am Levelshifter
(b) am I²C-Expander

Abbildung 6.44: Orientierungssensor von fischertechnik am ftDuino

6.13.8 fischertechnik-Umweltsensor

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.


Abbildung 6.45: Arduino-Bibliotheken für den BME680

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 DateiBeispieleAdafruit 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).

(a) Anschluss per Levelshifter
(b) Ausgabe von DateiBeispieleAdafruit BME680 Librarybme680test

Abbildung 6.46: fischertechnik-Umweltsensor am ftDuino

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;

6.13.9 Mini-I²C-Servo-Adapter

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.


Abbildung 6.47: Der Mini-I²C-Adapter am ftDuino

Anschluss und Inbetriebnahme

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 DateiBeispieleFtduinoSimpleI2CI2cScanner-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  !
     done
Jedesmal 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.

(a) Einzelner I²C-Anschluss
(b) Doppelter I²C-Anschluss

Abbildung 6.48: Anschluss des Mini-I²C-Adapters an den ftDuino

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 DateiBeispieleFtduinoSimpleI2CMiniServoAdapter verwendet werden. Er steuert kontiniertlich beide Servoausgänge gegenläufg an.

Programmierung

Die Programmierung des Mini-I²C-Servo-Adapters ist recht einfach, ein simples Beispiel findet sich unter DateiBeispieleFtduinoSimpleI2CMiniServoAdapter. 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();

Registerbelegung

Die Standard-Adresse des Mini-I²C-Servo-Adapters ist hex 0x11 bzw. dezimal 17. Diese Adresse kann permanent geändert werden (s.u.). Sollte man die Adresse vergessen haben, dann hilft der DateiBeispieleFtduinoSimpleI2CI2cScanner-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 bzw. 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 bzw. 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

Änderung der I²C-Geräteadresse

Wie im vorigen Abschnitt beschrieben lässt sich die I²C-Adresse des Mini-I²C-Servo-Adapters ändern. Unter DateiBeispieleFtduinoSimpleI2CMiniServoAddress 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.


Abbildung 6.49: Änderung der I²C-Adresse des Mini-I²C-Adapter

6.14 WS2812B-Vollfarb-Leuchtdioden

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.


Abbildung 6.50: Anschluss von zwei WS2812B-Vollfarb-Leuchtdioden

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.

6.14.1 Sketch WS2812FX

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 DateiBeispieleWS2812FX. 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

6.15 Musik aus dem ftDuino

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.


Abbildung 6.51: Anschluss der Lautsprecherkassette an den ftDuino

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.

6.15.1 Sketch Music

Schwierigkeitsgrad: ☆☆☆☆

Alternativ können auf diesen Pin auch die Arduino-Befehle zur Ton-Erzeugung angewendet werden. Der Beispielsketch unter DateiBeispieleFtduinoSimpleMusic nutzt dies.

     // Kammerton A für eine Sekunde spielen
     tone(11, 440, 1000);

6.15.2 Sketch MusicPwm

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 DateiBeispieleFtduinoSimple 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.

6.16 Der ftDuino als MIDI-Instrument

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.


Abbildung 6.52: Installation der MIDIUSB-Bibliothek in der Arduino-IDE

6.16.1 Sketch MidiInstrument

Der ftDuino-Beispielsketch unter DateiBeispieleFtduinoSimpleMidiInstrument 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.

6.17 Der ftDuino am Android-Smartphone

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.

(a) Screenshot
(b) Smartphone am ftDuino

Abbildung 6.53: Android-Demo zur Nutzung des ftDuino am Smartphone

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 DateiBeispieleFtduinoSimpleUSBAndroidDemo. 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.

6.18 WebUSB: ftDuino via Webbrowser steuern

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.

6.18.1 Chrome-Browser

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.


Abbildung 6.54: Der Chrome-Browser ist auf den meisten Android-Geräten vorinstalliert

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.


Abbildung 6.55: Meldung beim Eistecken des ftDuino bei laufendem Chromium-Browser

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.

6.18.2 WebUSB-Sketches

Einige WebUSB-Beispiel-Sketches werden als Beispiel in der ftDuino-Installation der Arduino-IDE unter DateiBeispieleWebUSB 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.


Abbildung 6.56: Auswahl der WebUSB-Konfiguration

6.18.3 Console

Der DateiBeispieleWebUSB 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.

(a) Chromium-Browser unter Linux
(b) Chrome-Browser unter Android

Abbildung 6.57: WebUSB-Console des ftDuino

6.18.4 Brickly-lite

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.

(a) im Chrome-Browser am PC
(b) am Android-Tablett mit Lindy-31717-Kabel

Abbildung 6.58: Brickly-lite für den ftDuino

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 DateiBeispieleWebUSBIoServer 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 DateiBeispieleWebUSBIoServer-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 DateiBeispieleWebUSBConsole 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.

6.18.5 Scratch 3.0

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.


Abbildung 6.59: Scratch 3.0 im Chrome-Browser mit ftDuino-Extension

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 segenannte 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.


1) Im Internet leicht zu finden unter dem Stichwort ``Floppymusik''
2) fischertechnik-Datenbank: https://ft-datenbank.de/tickets?fulltext=30571
3) fischertechnik-Datenbank: https://ft-datenbank.de/tickets?fulltext=132292
4) fischertechnik-Datenbank: https://ft-datenbank.de/tickets?fulltext=132292
5) fischertechnik-Datenbank: https://ft-datenbank.de/tickets?fulltext=540585
6) fischertechnik-Datenbank: https://ft-datenbank.de/tickets?fulltext=30275
7) fischertechnik-Datenbank: https://ft-datenbank.de/tickets?fulltext=36437
8) https://de.wikipedia.org/wiki/Hei%C3%9Fleiter
9) Weitere Informationen und tiefergehenden Erklärungen zu den Arduino-Bibliotheken zur Maus- und Tastaturnachbildung finden sich unter https://www.arduino.cc/en/Reference/MouseKeyboard
10) Mehr Info unter http://www.usb.org/developers/hidpage/
11) http://www.usb.org/developers/hidpage/Hut1_12v2.pdf
12) Eine große Sammlung von Sensorbibliotheken findet sich unter https://github.com/ControlEverythingCommunity.
13) https://www.thingiverse.com/thing:2542260
14) Datenblatt des SSD1306: https://cdn-shop.adafruit.com/datasheets/SSD1306.pdf
15) Adafruit-SSD1306-Bibliothek: https://github.com/adafruit/Adafruit_SSD1306
16) Adafruit-GFX-Bibliothek: https://github.com/adafruit/Adafruit-GFX-Library
17) VL53L0X-Gehäuse: https://github.com/harbaum/ftduino/tree/master/addons/vl53l0x
18) Adafruit-Bibliothek für den VL53L0X: https://github.com/adafruit/Adafruit_VL53L0X
19) Weitere Infos zum i2c_tiny_usb finden sich unter https://github.com/harbaum/I2C-Tiny-USB
20) Auch der Raspberry-Pi oder der fischertechnik TXT sind Linux-PCs
21) https://harbaum.github.io/ftduino/ftduino/libraries/FtduinoSimple/examples/I2C/I2cSlave/master.py
22) https://harbaum.github.io/ftduino/ftduino/libraries/Ftduino/examples/I2C/I2cSlave/master.py
23) Der ftDuino-I²C-Expander: https://github.com/harbaum/ftduino/tree/master/addons/i2c-expander
24) https://github.com/harbaum/cfw-apps/tree/master/packages/ftDuinoI2C
25) fischertechnik-Datenbank: https://ft-datenbank.de/tickets?fulltext=158402
26) https://content.ugfischer.com/cbfiles/fischer/Zulassungen/ft/158402-Kombisensor-Kurzanleitung-BMX055-2017-06-09.pdf
27) https://github.com/ControlEverythingCommunity/BMX055
28) fischertechnik-Datenbank: https://ft-datenbank.de/tickets?fulltext=544624
29) Bosch BME680: https://www.bosch-sensortec.com/bst/products/all_products/bme680
30) https://github.com/kitesurfer1404/WS2812FX
31) EN5 und EN6, siehe http://cache.freescale.com/files/analog/doc/data_sheet/MC33879.pdf
32) MIDI, Musical Instrument Digital Interface, https://en.wikipedia.org/wiki/MIDI
33) ftDuino-Android-App: https://github.com/harbaum/ftduino/tree/master/android
34) UsbSerial für Android: https://github.com/felHR85/UsbSerial
35) WebUSB: https://developers.google.com/web/updates/2016/03/access-usb-devices-on-the-web
36) Google-Chrome-Browser: https://www.google.com/intl/de_ALL/chrome/
37) Chrome-Portable: https://portableapps.com/apps/internet/google_chrome_portable
38) Brickly für den TXT: https://cfw.ftcommunity.de/ftcommunity-TXT/de/programming/brickly/
39) Blockly: https://developers.google.com/blockly/
40) Adafruit GFX Library: https://github.com/adafruit/Adafruit-GFX-Library

ftDuino manual - experimente(c) 2017-2019 Till Harbaum