Im Artikel „Tee, Earl Grey, heiß“ habe ich erstmals davon gesprochen, einen Kalibrierungsmodus zu programmieren, um die Tassenhöhe beim Teeodohr zu ändern. Dies habe ich auch erfolgreich getan. Es war eigentlich relativ simpel, außer das Verlöten von zwei Kabeln auf der Platine, weil keine Leiterbahnen für die zwei Tasten zu Verfügung standen.
Benötigte Bauteile und Werkzeuge
- Zwei Wiederstände, 10 kΩ
- Zwei Taster, SCI R13-24A1-05 RD (oder ähnlich)
- Kabel, Isolierband, Akkuschrauber oder Bohrmaschine, Schraubenzieher
- Einen Bohrer, Stärke 5,5 oder 5
Hardware-Umbau:
Zuerst muss die Batterie entfernt werden und der Roboter muss von der Grundplatte abgeschraubt werden, sodass er beim bohren nicht beschädigt wird. Außerdem hat man nicht genug Platz für den Akkuschrauber. Jetzt muss man sich überlegen, wo die beiden Taster sich befinden sollen. Ich habe sie jeweils links und rechts neben dem Teeodohr platziert. Nachdem die Löcher gebohrt wurden, kann es passieren, dass der Taster nicht hineinpasst. Um dieses Problem zu lösen bohrt man nochmal und achtet darauf, dass man gleichmäßig innerhalb des Lochs den Akkuschrauber dreht.
Das befestigen der Taster sollte eigentlich klar sein, kommen wir nun zum Verlöten. Ich habe die 5V Versorgungsspannung der beiden anderen Taster einfach erweitert. Es ist einfacher, wenn zuerst das Signalkabel an die Taster gelötet wird, das Kabel im Bauch des Hasen unterbrochen wird, der Widerstand verlötet (Isolierung nicht vergessen), ein weiters Kabel an den eben erwähnten Widerstand gelötet wird und dann das Kabel erst an den Pin A4 bzw. A5 gelötet wird. Später müssen im Quelltext ggf. noch die verschiedenen Pins angepasst werden, oder man lötet die Signalkabel um. Somit ist der Hardware-Teil abgeschlossen.
Die Funktionsweise:
Der Code ist ziemlich einfach und effektiv. Zuerst müssen die benötigten Variablen definiert werden:
int Untergrenze = 85; //KH: Grenze zum Schutz des Servos int Obergrenze = 0; //KH: Grenze zum Schutz des Servos
Diese beiden Variablen verhindern, dass der Nutzer den Servo so kalibriert, dass der Servo Schaden nehmen könnte, weil manche Servomotoren sich nur bis zu einem bestimmten Punkt bewegen lassen. Wenn die Software dann aber sagt, dass sich der Servo auf eine Position bewegen soll, die er gar nicht erreichen kann, wird das den Servo langfristig beschädigen. Ein weiterer Vorteil ist, dass der Nutzer weniger Kalibrierungsfehler dabei machen kann. Zu beachten ist dabei, dass die Werte von Servo zu Servo unterschiedlich sind.
//KH: Variablen, die für den Kalibrierungsmodus benötigt werden int changeValue = 5; //KH: Wert, der im Kalibrierungsmodus geändert wird bool configMode = false; //KH: Bool zum aktivieren/deaktivieren des Konfigurationsmodus const unsigned long BAUD_RATE = 9600; //KH: BAUD-Rate zur Seriellen Kommuniation bool secondConfigMode = false; //KH: Weitere Bool zum deaktivieren/aktivieren der Funktion bool MaxOrMinWinkel; //KH: Variable zum erkennen, ob die Variable MaxWinkel oder MinWinkel gaändert werden soll
Hier geht es nun um die verschiedenen Variablen, die dazu da sind, den Kalibrierungsmodus zu steuern. Aber auch in der setup() Funktion müssen Änderungen gemacht werden:
void setup() { Serial.begin(BAUD_RATE); //KH: Starten des Seriellen Monitors pinMode(speakerOut, OUTPUT); // Lautsprecher Ausgang pinMode(LED1, OUTPUT); // LED 1 pinMode(LED2, OUTPUT); // LED 2 pinMode(LED3, OUTPUT); // LED 3 pinMode(A1, INPUT); // ON and minutes select switch pinMode(A2, INPUT); // Start / Stop select switch pinMode(A4, INPUT); //KH: Taster 3 pinMode(A5, INPUT); //KH: Taster 4 analogWrite(LED1, 255); // 3 Minuten LED einschalten analogWrite(LED2, 0); // alle anderen aus analogWrite(LED3, 0); // alle anderen aus Arm.attach(11); // attaches the servo Arm to pin D11 servo object Arm.write(max_Winkel); // tell servo 1 to go to position 10° ON_OFF_Sound(); // Play Sound. Ready to make Tea }
Ich habe in der setup() Funktion die Serielle Kommunikation eingerichtet. Dies erleichtert das Debuggen und erweitern des Teehasen.
void loop() { if (analogRead(A1) > 900 && analogRead(A2) < 900 ) SelectNextTime(); // Mit Taster 1 Zeit einstellen if (analogRead(A2) > 900 && analogRead(A1) < 900) TeaTime() ; // Mit Taster 2 Tea Time Starten if (analogRead(A4)> 900) MainCalibrationMode(); //KH: Aktivieren des Kalibrierungsmodus; Drücken von Taster 1 und 2 }
Im Originalcode wird ja nach dem Programmstart die Funktion setup() einmal ausgeführt. Danach wird die Funktion loop() unendlich lang ausgeführt. Das heißt aber, dass wenn der Taster A4 gedrückt ist, die Software in die Funktion MainCalibrationMode() geht, diese Einmal ausführt und dann wieder die loop() Funktion ausführt. In dieser kurzen Zeitspanne ist es für den Nutzer aber unmögllich, die jewelige Armeinstellung zu kalibrieren. Aus diesem Grund benötige ich die Variablen configmode und secondconfigmode. Gehen wir den Programmablauf nocheinmal durch. Das Programm startet, die setup() Funktion wird einmal ausgeführt, die loop() Funktion wird unendlich mal ausgeführt. Jetzt drückt der Nutzer auf die Taste A4. Daraufhin wird die Funktion MainCalibrationmode() ausgeführt. In der wird zuerst die Variable configMode auf den Wert true gesetzt und eine Schleife wird unendlich lang ausgeführt, solange die Variable configMode den Wert true hat.
//KH: Funktionen zu den Kalibrierungsmodi //KH:Hauptkalibrierungsmodus void MainCalibrationMode(){ configMode = true; Serial.println("Hauptkalibrierungsmodus aktiviert"); do { delay(20); }while (analogRead(A4)>500); AllLedOff(); while (configMode == true){ //LED2 ist angeschaltet analogWrite(LED2, 255); //IF-Anweisungen //KH: MaxWinkel verändern if (analogRead(A1) > 900 ){ do { delay(20); }while (analogRead(A1)>500); AllLedOff(); analogWrite(LED3, 255); MaxOrMinWinkel = true; Serial.println("MaxWinkel"); Calibration(max_Winkel); } //KH: MinWinkel verändern if (analogRead(A2) > 900 ){ AllLedOff(); analogWrite(LED1, 255); Serial.println("MinWinkel"); MaxOrMinWinkel = false; Calibration(min_Winkel); } //KH: Zurück zur Hauptschleife if (analogRead(A4) > 900 ){ do { delay(20); }while (analogRead(A4)>500); configMode = false; AllLedOff(); analogWrite(LED1, 255); loop(); } } }
Hier läuft nun genau das ab, was ich oben Beschreiben habe. Dazu kommen noch die verschiedenen if-Funktionen, die dazu da sind, um in den „normalen“ Modus zurückzukehren und die zwei Parameter der Tassenhöhe zu ändern. Das läuft im Programm so ab: Zuerst muss man die jeweilige Taste für den jeweiligen Parameter drücken. Dann werden alle LED’s ausgeschaltet, um Fehler bei der Darstellung zu vermeiden (mithilfe der Funktion AllLedOff()). Bis hierhin ist der Code in jeder if-Funktion gleich, egal ob Max- oder MinWinkel geändert werden soll. Danach wird die LED angeschaltet, die für den jeweiligen Parameter steht und in der Seriellen Kommunikation wird „MinWinkel“ oder „MaxWinkel“ ausgegeben. Die Variable MaxOrMinWinkel wird auf true gesetzt, wenn der Wert der Variable MaxWinkel geändert wird, wenn die Variable MinWinkel geändert wird, wird der Wert auf false gesetzt. Zuletzt wird der Funktion Calibration der jeweilige Wert der Variable übergeben.
//Kalibrierungsfunktion void Calibration(int Position){ Serial.println(Position); Arm.write(Position); //KH: Servo auf die Position bewegen secondConfigMode = true; Serial.println("Kalibrierung"); do { delay(20); }while (analogRead(A2)>500); while (secondConfigMode == true){ //KH: Schleife beenden, wenn A1 gedrückt if (analogRead(A1) > 900 ){ do { delay(20); }while (analogRead(A1)>500); secondConfigMode = false; //KH: Wenn MaxOrMinWinkel == true; maxWinkel verändern if (MaxOrMinWinkel == true){ max_Winkel = Position; } //KH: Wenn MaxOrMinWinkel == false; minWinkel verändern if (MaxOrMinWinkel == false){ min_Winkel = Position; } Serial.println(Position); AllLedOff(); } //KH: Wert von max_Winkel oder min_Winkel erhöhen if (analogRead(A4) > 900 ){ do { delay(20); }while (analogRead(A4)>500); //KH: if-Funktion zum Schutz des Servos if (Position + changeValue >= Obergrenze){ Serial.println(Position); Position = Position + changeValue; //KH: Wert erhöhen Arm.write(Position); //KH: Servo Bewegen } } //KH: Wert von max_Winkel oder min_Winkel verringern if (analogRead(A5) > 900){ do { delay(20); }while (analogRead(A5)>500); if (Position - changeValue <= Untergrenze){ Position = Position - changeValue; Arm.write(Position); Serial.println(Position); } } } }
Hier wird nun die Funktion Calibration() definiert. Sie erwartet eine Variable vom Typ int, welche in der Funktion unter dem Namen Position weiterverarbeitet wird.Nun wird in der ersten Zeile der Wert der Variable über den Seriellen Monitor ausgegeben, Danach wird der Arm auf die Position der Variable bewegt und der zweite Kalibrierungsmodus wird aktiviert. Wenn der Nutzer jetzt auf die Taste zum erhöhen oder senken des Arms drückt, bewegt sich der Arm dabei mit, solange die Parameter innerhalb des zuvor definierten Bereichs liegen. Dies wird solange ausgeführt, bis man auf die Taste A1 drückt. Sobald man auf die Taste A1 drückt, bekommt die jeweilige Variable den Wert von Position zugewiesen.
void AllLedOff(){ analogWrite(LED1, 0); analogWrite(LED2, 0); analogWrite(LED3, 0); }
Zuletzt muss nur noch die Funktion AllLedOff() definiert werden. Diese schaltet alle LED’s aus.
Schreibe einen Kommentar