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 12:28] – 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! | + | |
//Dieser Abschnitt zeigt, wie der mBot kalibriert werden kann. Grundsätzlich können alle Motoren oder Sensoren kalibriert werden. Ich stelle zwei Varianten vor, wie der mBot kalibriert werden kann (er besitzt keine Encoder), um 90-Grad-Drehungen durchzuführen.// | //Dieser Abschnitt zeigt, wie der mBot kalibriert werden kann. Grundsätzlich können alle Motoren oder Sensoren kalibriert werden. Ich stelle zwei Varianten vor, wie der mBot kalibriert werden kann (er besitzt keine Encoder), um 90-Grad-Drehungen durchzuführen.// | ||
- | Voraussetzungen: | + | **Voraussetzungen: |
- | * Der Abschnitt | + | * Der Abschnitt |
- | * Der Abschnitt | + | * Der Abschnitt |
{{ : | {{ : | ||
+ | |||
+ | ====== 90°-Drehung: | ||
+ | <WRAP center round tip 90%> | ||
+ | Dieses Programm ermöglicht eine **90-Grad-Drehung** des mBot. | ||
+ | Die Drehung erfolgt zeitgesteuert, | ||
+ | |||
+ | </ | ||
+ | |||
+ | === Funktionsweise === | ||
+ | * Der **mBot** führt eine Drehbewegung für die Dauer von '' | ||
+ | * Nach Ablauf der Zeit stoppt die Bewegung um dann alle 5 Sekunden wiederholt zu werden. | ||
+ | * Die Drehzeit bestimmt, wie weit sich der mBot dreht. | ||
+ | |||
+ | === Kalibrierung === | ||
+ | * Falls sich der mBot zu weit dreht → '' | ||
+ | * Falls sich der mBot zu wenig dreht → '' | ||
+ | * <color # | ||
+ | |||
+ | ==== Quellcode (engl. Sourcecode) ==== | ||
+ | <Code c linenums:1 | Listing 1: | ||
+ | #include < | ||
+ | |||
+ | MeDCMotor motor1(M1); | ||
+ | MeDCMotor motor2(M2); | ||
+ | |||
+ | void setup() { | ||
+ | Serial.begin(9600); | ||
+ | } | ||
+ | |||
+ | void loop() { | ||
+ | turn90Degrees(400); | ||
+ | delay(5000); | ||
+ | } | ||
+ | |||
+ | void turn90Degrees(int turn_time) { | ||
+ | int speed = 100; // Geschwindigkeit | ||
+ | |||
+ | motor1.run(speed); | ||
+ | motor2.run(speed); | ||
+ | delay(turn_time); | ||
+ | |||
+ | motor1.run(0); | ||
+ | motor2.run(0); | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | === Vorteile & Nachteile === | ||
+ | ^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. | | ||
+ | | | ❌ Die Methode blockiert das Programm und lässt sich nicht elegant in komplexere Programme integrieren. | | ||
+ | |||
+ | |||
+ | ====== 90°-Drehung: | ||
+ | |||
+ | <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: | ||
+ | #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.1739881707.txt.gz · Zuletzt geändert: 2025/02/18 12:28 von torsten.roehl