hello_mbot_kalibrierung
Unterschiede
Hier werden die Unterschiede zwischen zwei Versionen angezeigt.
Beide Seiten der vorigen RevisionVorhergehende ÜberarbeitungNächste Überarbeitung | Vorhergehende Überarbeitung | ||
hello_mbot_kalibrierung [2025/02/18 13:18] – [erste (einfache) Variante] torsten.roehl | hello_mbot_kalibrierung [2025/02/19 19:55] (aktuell) – [Bedienung] torsten.roehl | ||
---|---|---|---|
Zeile 1: | Zeile 1: | ||
====== Hello mBot Kalibrierung ====== | ====== Hello mBot Kalibrierung ====== | ||
- | FIXME Abschnitt entsteht gerade! | + | |
Zeile 11: | Zeile 11: | ||
{{ : | {{ : | ||
- | ====== erste (einfache) Variante | + | ====== |
<WRAP center round tip 90%> | <WRAP center round tip 90%> | ||
Dieses Programm ermöglicht eine **90-Grad-Drehung** des mBot. | Dieses Programm ermöglicht eine **90-Grad-Drehung** des mBot. | ||
Zeile 26: | Zeile 26: | ||
* Falls sich der mBot zu weit dreht → '' | * Falls sich der mBot zu weit dreht → '' | ||
* Falls sich der mBot zu wenig dreht → '' | * Falls sich der mBot zu wenig dreht → '' | ||
- | * Der optimale Wert wird durch Tests ermittelt. | + | * <color #ff7f27>Der optimale Wert muss durch Tests experimentell |
+ | ==== Quellcode (engl. Sourcecode) ==== | ||
<Code c linenums:1 | Listing 1: | <Code c linenums:1 | Listing 1: | ||
#include < | #include < | ||
Zeile 56: | Zeile 56: | ||
</ | </ | ||
- | ^ ✅ Vorteil ^ ❌ Nachteil ^ | + | === Vorteile & Nachteile === |
- | | Einfach zu implementieren und gut für Programmieranfänger geeignet. | ❌ Manuelle Kalibrierung ist aufwendig. | | + | ^Vorteil ^Nachteil^ |
+ | | ✅ Einfach zu implementieren und gut für Programmieranfänger geeignet. | ❌ Manuelle Kalibrierung ist aufwendig. | | ||
| | ❌ Bei schwächer werdender Batterie muss die Drehzeit erneut angepasst werden. | | | | ❌ Bei schwächer werdender Batterie muss die Drehzeit erneut angepasst werden. | | ||
| | ❌ Die Methode blockiert das Programm und lässt sich nicht elegant in komplexere Programme integrieren. | | | | ❌ Die Methode blockiert das Programm und lässt sich nicht elegant in komplexere Programme integrieren. | | ||
- | ====== zweite (komplexere) Variante ====== | + | ====== |
+ | |||
+ | <WRAP center round tip 90%> | ||
+ | ** mBot 90-Grad-Drehung mit automatischer Kalibrierung** | ||
+ | |||
+ | |||
+ | Dieses Programm ermöglicht eine **automatische 90-Grad-Kalibrierung** des mBot. | ||
+ | Die Steuerung erfolgt über eine **finite state machine (FSM)**, die eine tastengesteuerte Kontrolle erlaubt. | ||
+ | Nach der Kalibrierung kann der Roboter getestet werden. | ||
+ | |||
+ | ** | ||
+ | Dieses Programm verwendet eine einfache Tastensteuerung – einmal zur Kalibrierung und danach zum Testen der Kalibrierung. Es dient lediglich als Beispiel, um das Prinzip zu veranschaulichen.** | ||
+ | </ | ||
+ | |||
+ | |||
+ | ^Idee^ | ||
+ | |{{ : | ||
+ | |< | ||
+ | Der **mBot** befindet sich auf einem **schwarzen L** (90-Grad-Winkel) als Referenz. | ||
+ | |||
+ | Der Roboter dreht sich gegen den Uhrzeigersinn, | ||
+ | Beim Zurückdrehen wird die Zeit erneut erfasst. | ||
+ | Aus beiden Werten wird der Mittelwert gebildet, wodurch sich der **mBot** selbstständig auf 90-Grad-Kurven kalibriert. | ||
+ | |||
+ | Auf diese Weise kann er sich immer wieder automatisch anpassen, falls sich z. B. der Akkuladestand ändert und die Motorleistung variiert. | ||
+ | Durch mehrfaches Kalibrieren ließe sich ein noch präziserer Mittelwert berechnen. | ||
+ | |||
+ | </ | ||
+ | |||
+ | |||
+ | |||
+ | |||
+ | ==== Quellcode (engl. Sourcecode) ==== | ||
+ | |||
<Code c linenums:1 | Listing 1: | <Code c linenums:1 | Listing 1: | ||
+ | #include " | ||
+ | // Hardware | ||
+ | MeBuzzer buzzer; | ||
+ | MeLineFollower lineFinder(PORT_2); | ||
+ | MeRGBLed led(0, 2); // must be fixed! | ||
+ | MeDCMotor motor1(M1); | ||
+ | MeDCMotor motor2(M2); | ||
+ | int PIN_BUTTON = 7; // must be fixed! | ||
+ | int threshold | ||
+ | int buttonCount; | ||
+ | // Allgemein | ||
+ | int speed = 100; // Motor speed | ||
+ | unsigned long time90degree; | ||
+ | |||
+ | // turn90Degree... | ||
+ | bool t90d_isTurning = false; | ||
+ | unsigned long t90d_turnStartTime = 0; | ||
+ | // actionCalibration... | ||
+ | unsigned long ac_turnStartTimeLeft | ||
+ | unsigned long ac_turnTimeLeft = 0; | ||
+ | unsigned long ac_turnStartTimeRight = 0; | ||
+ | unsigned long ac_turnTimeRight = 0; | ||
+ | bool ac_isTurning = false; | ||
+ | bool ac_isLeftTurning = false; | ||
+ | bool ac_isRightTurning = false; | ||
+ | bool ac_calibrationDone = false; | ||
+ | // | ||
+ | bool at_doneLeft = false; | ||
+ | bool at_doneRight = false; | ||
+ | bool at_testComplete = false; | ||
+ | |||
+ | enum State { | ||
+ | STATE_OFF, | ||
+ | STATE_CALIBRATION, | ||
+ | STATE_TEST | ||
+ | }; | ||
+ | State state = STATE_OFF; | ||
+ | |||
+ | void setup() { | ||
+ | led.setpin(13); | ||
+ | pinMode(PIN_BUTTON, | ||
+ | buttonCount = 0; | ||
+ | } | ||
+ | |||
+ | void loop() { | ||
+ | // step: command | ||
+ | int cmd = read(); | ||
+ | // step: state | ||
+ | state = decode(cmd); | ||
+ | // step: action | ||
+ | switch (state) { | ||
+ | case STATE_CALIBRATION: | ||
+ | actionCalibration(); | ||
+ | break; | ||
+ | case STATE_TEST: | ||
+ | actionTest(); | ||
+ | break; | ||
+ | case STATE_OFF: | ||
+ | actionOff(); | ||
+ | break; | ||
+ | } | ||
+ | } | ||
+ | |||
+ | |||
+ | /* | ||
+ | | ||
+ | */ | ||
+ | |||
+ | bool turn90Degree(bool left) { | ||
+ | // step: ...start turning | ||
+ | if (!t90d_isTurning) { | ||
+ | motor1.stop(); | ||
+ | motor2.stop(); | ||
+ | t90d_isTurning | ||
+ | int dir = left ? 1 : -1; | ||
+ | |||
+ | motor1.run(dir * speed); | ||
+ | motor2.run(dir * speed); | ||
+ | t90d_turnStartTime = millis(); | ||
+ | return false; | ||
+ | } | ||
+ | // step: ...in progress | ||
+ | if (millis() - t90d_turnStartTime < time90degree) | ||
+ | return false; | ||
+ | |||
+ | // step: ... finished | ||
+ | motor1.stop(); | ||
+ | motor2.stop(); | ||
+ | t90d_isTurning = false; | ||
+ | |||
+ | return true; | ||
+ | } | ||
+ | |||
+ | bool isButtonPressed() { | ||
+ | static bool buttonPressed = false; | ||
+ | int value = analogRead(PIN_BUTTON); | ||
+ | |||
+ | if (value < threshold) { | ||
+ | if (!buttonPressed) { | ||
+ | buttonPressed = true; | ||
+ | return true; | ||
+ | } | ||
+ | } else { | ||
+ | buttonPressed = false; // Button wurde losgelassen | ||
+ | } | ||
+ | return false; | ||
+ | |||
+ | } | ||
+ | |||
+ | int read() { | ||
+ | if ( isButtonPressed() ) | ||
+ | buttonCount += 1; | ||
+ | |||
+ | if (buttonCount > 2) | ||
+ | buttonCount = 0; | ||
+ | |||
+ | return buttonCount; | ||
+ | } | ||
+ | |||
+ | |||
+ | State decode(int cmd) { | ||
+ | switch (cmd) { | ||
+ | case 1: return STATE_CALIBRATION; | ||
+ | case 2: return STATE_TEST; | ||
+ | } | ||
+ | return STATE_OFF; | ||
+ | } | ||
+ | |||
+ | void actionCalibration() { | ||
+ | |||
+ | if (ac_calibrationDone) | ||
+ | return; | ||
+ | |||
+ | led.setColorAt(1, | ||
+ | led.setColorAt(0, | ||
+ | led.show(); | ||
+ | int sensorState = lineFinder.readSensors(); | ||
+ | |||
+ | // step - start turning left | ||
+ | if (!ac_isTurning) { | ||
+ | motor1.stop(); | ||
+ | motor2.stop(); | ||
+ | motor1.run(speed); | ||
+ | motor2.run(speed); | ||
+ | ac_turnStartTimeLeft = millis(); | ||
+ | ac_isTurning = true; | ||
+ | ac_isRightTurning = true; | ||
+ | do { | ||
+ | sensorState = lineFinder.readSensors(); | ||
+ | } while ( sensorState != S1_OUT_S2_OUT); | ||
+ | } | ||
+ | |||
+ | // step - end turning left ... start turning right | ||
+ | if (ac_isRightTurning && sensorState == S1_IN_S2_IN) { | ||
+ | motor1.stop(); | ||
+ | motor2.stop(); | ||
+ | ac_turnTimeLeft = millis() - ac_turnStartTimeLeft; | ||
+ | |||
+ | motor1.run(-speed); | ||
+ | motor2.run(-speed); | ||
+ | ac_turnStartTimeRight = millis(); | ||
+ | do { | ||
+ | sensorState = lineFinder.readSensors(); | ||
+ | } while ( sensorState != S1_OUT_S2_OUT); | ||
+ | ac_isRightTurning = false; | ||
+ | ac_isLeftTurning = true; | ||
+ | } | ||
+ | |||
+ | // step - end turing right | ||
+ | if (ac_isLeftTurning && sensorState == S1_IN_S2_IN) { | ||
+ | motor1.stop(); | ||
+ | motor2.stop(); | ||
+ | ac_turnTimeRight = millis() - ac_turnStartTimeRight; | ||
+ | time90degree = (ac_turnTimeLeft + ac_turnTimeRight) / 2.0; | ||
+ | ac_calibrationDone = true; | ||
+ | led.setColorAt(1, | ||
+ | led.setColorAt(0, | ||
+ | led.show(); | ||
+ | buzzer.tone(1200, | ||
+ | } | ||
+ | |||
+ | } | ||
+ | void actionTest() { | ||
+ | |||
+ | if (!at_doneLeft) { // Links-Drehung | ||
+ | at_doneLeft = turn90Degree(true); | ||
+ | led.setColorAt(1, | ||
+ | led.setColorAt(0, | ||
+ | led.show(); | ||
+ | return; | ||
+ | } | ||
+ | |||
+ | if (!at_doneRight) { // Rechts-Drehung | ||
+ | at_doneRight = turn90Degree(false); | ||
+ | return; | ||
+ | } | ||
+ | |||
+ | if (!at_testComplete) { // fertig | ||
+ | motor1.stop(); | ||
+ | motor2.stop(); | ||
+ | led.setColorAt(1, | ||
+ | led.setColorAt(0, | ||
+ | led.show(); | ||
+ | buzzer.tone(1200, | ||
+ | at_testComplete = true; | ||
+ | return; | ||
+ | } | ||
+ | } | ||
+ | |||
+ | void actionOff() { | ||
+ | led.setColorAt(1, | ||
+ | led.setColorAt(0, | ||
+ | led.show(); | ||
+ | |||
+ | // reset | ||
+ | motor1.stop(); | ||
+ | motor2.stop(); | ||
+ | |||
+ | // reset state calibration | ||
+ | ac_isTurning = false; | ||
+ | ac_isLeftTurning = false; | ||
+ | ac_isRightTurning = false; | ||
+ | ac_calibrationDone = false; | ||
+ | |||
+ | // reset state test | ||
+ | at_doneLeft = false; | ||
+ | at_doneRight = false; | ||
+ | at_testComplete = false; | ||
+ | } | ||
</ | </ | ||
+ | ==== Bedienung ==== | ||
+ | <WRAP center round box 90%> | ||
+ | **Nach dem Start** befindet sich der mBot im Ruhezustand. Nachdem er auf der **L-Position** platziert wurde, kann es losgehen. | ||
+ | |||
+ | ⚡ **Schritt 1: | ||
+ | ▶ **Drücken des Tasters** → **LEDs werden <color # | ||
+ | * Die **Kalibrierung** startet. | ||
+ | * Nach Abschluss der Kalibrierung **erlöschen die LEDs**. | ||
+ | |||
+ | ⚡ **Schritt 2: | ||
+ | ▶ **Erneutes Drücken des Tasters** → **LEDs werden <color # | ||
+ | * Der **Testlauf** beginnt. | ||
+ | * Nach Abschluss des Testlaufs **erlöschen die LEDs**. | ||
+ | |||
+ | ⚡ **Schritt 3: | ||
+ | ▶ **Nach dem Testlauf** kehrt der mBot durch Drückens des Tasters in den **Ruhezustand** zurück. | ||
+ | * Der Vorgang kann **von vorne** gestartet werden. | ||
+ | |||
+ | </ | ||
+ | |||
+ | === Vorteile & Nachteile === | ||
+ | ^Vorteil ^ Nachteil ^ | ||
+ | |✅ Automatische Kalibrierung ohne manuelles Anpassen der Drehzeit. | ❌ Erfordert eine FSM-Implementierung. | | ||
+ | |✅ Präzisere Drehung durch wiederholte Anpassung. | ❌ Höherer Programmieraufwand.| | ||
+ | |✅ Nach der Kalibrierung direkt einsatzbereit. | | | ||
+ | |✅ Die Methode blockiert das Programm __nicht__ und lässt sich damit elegant in komplexere Programme integrieren. | | |
hello_mbot_kalibrierung.1739884727.txt.gz · Zuletzt geändert: 2025/02/18 13:18 von torsten.roehl