Das Multi Function Shield mit einem Drehgeber erweitern

Das Multi Function Shield, das ich ja bereits vorgestellt habe, bietet mit der Möglichkeit zur einfachen Anzeige von Daten auf seinem 4-fach-7-Segment-Display und den freien Anschlusspins eine gute Grundlage, Sensoren ausprobieren.

Diesmal wollen wir das MFS und einem Drehgeber-Modul KY-040 erweitern.

Drehgeber-Modul KY-040


Der Drehgeber sieht auf den ersten Blick aus wie ein Potentiometer, doch wenn man ihn dreht, fühlt man so eine Art Riffelung ähnlich wie bei einem Computer-Mouse-Rad. Dadurch kann man einzelne Schritte fühlen und z. B. einen Wert genau einstellen.

Denn ein Drehgeber gibt nicht einen Widerstand wie ein Potentiometer zurück, sondern leitet über zwei digitale Leitungen die Drehimpulse weiter, die wir mit dem Arduino auswerten wollen.

Der Drehgeber verfügt über folgende Anschlüsse:


Damit passt er wunderbar in den 7-Pin-Header des Multi Function Shield, welches ja diese Belegung hat: Ich habe an mein Drehgeber-Modul ein 5-poligen 90°-Header angelötet, so dass ich einfach an- und abstecken kann (unten bündig). Außerdem habe ich ihm einen orangen Drehknopf verpasst, den ich noch in meinem Fundus hatte. Damit lässt er sich leichter drehen und genauer einstellen.



Fehlt nur noch die Verdrahtung der Schalterleitung. Pin 5 des MFS-Headers ist ja nicht beschaltet. Also wollte ich einen freien Digital-Pin verwenden, musste aber feststellen, dass es keinen mehr gibt - die Macher des MFS haben nichts verschenkt. Darum habe ich mich entschlossen, den Drehgeber-Taster mit dem S1-Taster gleichzusetzen und ein entsprechendes Kabel gelötet. Wird jetzt der Drehgeber-Knopf gedrückt, ist es so als ob Schalter 1 betätigt wurde. Wobei ich Schalter 1 den Vorzug geben würde, weil der nicht so windig in der Luft hängt. Legt man allerdings etwas in passender Höhe unter das Modul, dann lässt sich auch der eingebaute Taster ganz gut einhändig bedienen.

Funktionsweise eines Drehgebers

Warum die beiden Datenleitungen Clock und Data heißen, erschließt sich mir nicht ganz. Man sollte sie eher links und rechts nennen.

Grundsätzlich haben beide Leitungen den selben Wert, sind also beide auf HIGH oder LOW.

Wird der Encode, so wird der Drehgeber auch genannt, um einen Schritt gedreht, dann springen beide auf den gegenteiligen Wert, also von HIGH auf LOW und von LOW auf HIGH. Durch die Anzahl der HIGH/LOW-Wechsel kann man also die Schritte zählen.

Doch durch den besonderen Aufbau des Encoders kann man auch die Richtung des Drehens heraus finden. Denn es gibt sozusagen Zwischenschritte. Bei einer Drehung nach rechts (also im Uhrzeigersinn) kippt zuerst der linke Wert um und dann der rechte - Eselsbrücke: die Veränderung wandert von links nach rechts, die Richtung, in die der Regler gedreht wird. Bei einer Linksdrehung verhält es sich umgekehrt: hier kippt zuerst der rechte Wert (Wanderung von rechts nach links).

Ich habe dazu ein kleines Video aufgenommen, da ein Bild (und erst recht ein Video) mehr zu sagen vermag als tausend Worte:



Wer das selbst nachvollziehen möchte, hier ist der Source-Code für das gezeigte Programm:

//////////////////////////////////////////////////////// // (C) 2018 by Oliver Kuhlemann // // Bei Verwendung freue ich mich über Namensnennung, // // Quellenangabe und Verlinkung // // Quelle: http://cool-web.de/arduino/ // //////////////////////////////////////////////////////// #include %lt;TimerOne.h> // für Timings und Interrupts #include %lt;MultiFuncShield.h> // API für das Multi Function Shield #define PinDrehClock 0 // durch MFS-Header vorgegeben #define PinDrehData 1 // durch MFS-Header vorgegeben void setup() { Timer1.initialize(); MFS.initialize(&Timer1); // initialize multi-function shield library pinMode (PinDrehClock, INPUT); pinMode (PinDrehData, INPUT); } void loop() { byte clock; byte data; char st[5]; while (1) { clock = digitalRead(PinDrehClock); data = digitalRead(PinDrehData); st[0]=clock+48; st[1]=32; st[2]=data+48; st[3]=32; st[4]='\0'; MFS.write(st); delay(10); } } Da der Header, an dem der Drehregler angeschlossen ist, genau die gleichen Pins verwendet wie die serielle Kommunikation zwischen Arduino und PC, nämlich D0 und D1 (bzw. RX und TX) ergibt sich ein kleines Problem: Befehle wie Serial.print... werden nicht richtig funktionieren und auch das Hochladen von neuen Scripts tut sich schwer.

Darum beachten, dass beim Hochladen der Drehgeber so eingestellt ist, dass die grüne RX-LED aus ist. Dann funktioniert das Hochladen. Ist sie hingegen an, schlägt das Hochladen fehl.

Programm zur Werteeinstellung

Hauptanwendungsgebiet eines solchen Drehgebers ist natürlich das Einstellen von Zahlen oder das Navigieren durch Menüs (der Taster dann entsprechend zur Auswahl), wobei es wichtig ist, dass Zahlen bzw. Menüpunkte genau ausgewählt werden können und nichts übersprungen wird.

Das nachfolgende Beispielprogramm leistet das, indem es eine einstellbare Zahl anzeigt: Auch hierzu habe ich ein kleines Video aufgenommen, dass die Bedienung des Programmes zeigt:



Und hier der passende Code dazu: //////////////////////////////////////////////////////// // (C) 2018 by Oliver Kuhlemann // // Bei Verwendung freue ich mich über Namensnennung, // // Quellenangabe und Verlinkung // // Quelle: http://cool-web.de/arduino/ // //////////////////////////////////////////////////////// #include <TimerOne.h> // für Timings und Interrupts #include <MultiFuncShield.h> // API für das Multi Function Shield #define PinDrehClock 0 // durch MFS-Header vorgegeben #define PinDrehData 1 // durch MFS-Header vorgegeben void setup() { Timer1.initialize(); MFS.initialize(&Timer1); // initialize multi-function shield library pinMode (PinDrehClock, INPUT); pinMode (PinDrehData, INPUT); } void loop() { byte links = digitalRead(PinDrehClock); byte rechts = digitalRead(PinDrehData); byte linksBefore = links; byte rechtsBefore = rechts; int drehung = 0; int position = 0; int pause = 1; while (1) { // Buttons auswerten ///////////////////////////////////// byte btn = MFS.getButton(); if (btn == BUTTON_1_PRESSED) { MFS.beep(1); position = 0; } else if (btn == BUTTON_2_PRESSED) { MFS.beep(1); position -= 100; } else if (btn == BUTTON_3_PRESSED) { MFS.beep(1); position += 100; } // Drehgeber auswerten ////////////////////////////////// links = digitalRead(PinDrehClock); rechts = digitalRead(PinDrehData); MFS.writeLeds(LED_1, links); MFS.writeLeds(LED_2, rechts); if (links != linksBefore) { // rechtsdrehung // warten, bis anderer Pin nachgezogen while (digitalRead(PinDrehData) != digitalRead(PinDrehClock)) delay (pause); if (digitalRead(PinDrehClock) != links) { // nach Halbschritt wieder zurück gedreht drehung=0; } else { drehung = 1; } links = digitalRead(PinDrehClock); rechts = digitalRead(PinDrehData); linksBefore=links; rechtsBefore=links; } else if (rechts != rechtsBefore){ // linksdrehung // warten, bis anderer Pin nachgezogen while (digitalRead(PinDrehData) != digitalRead(PinDrehClock)) delay (pause); drehung=0; if (digitalRead(PinDrehData) != rechts) { // nach Halbschritt wieder zurück gedreht drehung=0; } else { drehung = -1; } links = digitalRead(PinDrehClock); rechts = digitalRead(PinDrehData); linksBefore=rechts; rechtsBefore=rechts; } else { drehung = 0; } position += drehung; if (position < -999) { position = -999; MFS.beep (10); } else if (position > 9999) { position = 9999; MFS.beep (10); } MFS.write(position); delay(pause); } }

Untersetzer im 3D-Druck


Ich habe einen Untersetzer für das Drehgeber-Modul designt, in das man die Platine passgenau hineindrücken kann und das exakt die richtige Höhe hat, damit der Drehgeber plan aufliegt, wenn der Arduino Uno mit diesem Bumper ausgerüstet wurde. Die .stl-Datei dazu kann hier heruntergeladen werden.

Damit lässt sich auch der Knopf gut niederdrücken, ohne dass man gegenhalten müsste.

Natürlich wird ein 3D-Drucker benötigt oder man kennt jemanden, der einen hat. Dem dann einfach die .stl-Datei schicken, der weiß dann schon, was damit zu tun ist.