Dies ist eine alte Version des Dokuments!
Inhaltsverzeichnis
mBot Streckenfahren
Der mBot kann, gesteuert über die Infrarot-Fernbedienung, eine zuvor eingegebene Strecke vorwärts oder rückwärts fahren.
Grundgerüst
Dieses Abschnitt stellt ein Grundgerüst vor, um den mBot mit einer IR-Fernbedienung zu steuern. Es stellt eine funktionierende Steuerlogik bereit, in der verschiedene Zustände und Befehle verarbeitet werden, um komplexe Abläufe zu ermöglichen.
Die Kernstruktur ist vollständig funktionsfähig und kann flexibel erweitert werden.
Die spezifischen Action-Funktionen (z. B. für Bewegung oder Sensoren) müssen jedoch noch individuell implementiert werden.
👉 Im nächsten Abschnitt werden die Methoden implementiert, um das vollständige Programm zu erhalten.
🎮 Bedienung des Programms
Die Steuerung erfolgt über fünf Tasten (E, C, D, F, B) sowie eine Zahleneingabe mit Bestätigung über die Setting-Taste
Taste | Funktion | Info |
---|---|---|
E (Escape) | 🛑 Stopp – Beendet aktuelle Aktion | |
C (Calibration) | ⚙️ Kalibrierung starten | |
D (Distance) | 📏 Distanz eingeben (1–3 Stellen) | Erweiterter Eingabemodus! |
F (Forward) | ▶️ Vorwärts fahren (eingestellte Distanz) | |
B (Backward) | ◀️ Rückwärts fahren (eingestellte Distanz) |
Starten Sie das Programm und beobachten Sie den seriellen Monitor, um das Zusammenspiel der Steuerlogik mit der Fernbedienung und den Action-Funktionen zu studieren.
Dieses Grundgerüst simuliert die Logik nur.
- 🛠️ C drücken → Kalibrierung startet
- 📏 D drücken → Distanz-Eingabe aktiv
- 🔢 1 5 0 eingeben → 150 Einheiten setzen
- ✅ Setting drücken → Eingabe bestätigen
- 🚀 F drücken → mBot fährt 150 Einheiten (cm) vorwärts
➡ Falls nötig: E drücken um jederzeit eine Aktion abzubrechen!
Die Distanz kann 1- bis 3-stellig eingegeben werden.
Quellcode (engl. Sourcecode)
Listing 1:MinimalesProgramm.ino
#include "MeMCore.h" // Hardware MeIR ir; MeBuzzer buzzer; MeLineFollower lineFinder(PORT_2); MeRGBLed led(0, 2); // must be fixed! MeDCMotor motor1(M1); MeDCMotor motor2(M2); // IR-Entprellen static uint8_t lastCode = 0xFF; static unsigned long lastTime = 0; const unsigned long COOL_DOWN = 1000; // in Millisekunden, also 1 Sekunde //FSM enum State { STATE_OFF, STATE_BACKWARD, STATE_CALIBRATION, STATE_DISTANCE, STATE_FORWARD }; State state = STATE_OFF; State lastState = STATE_OFF; enum ExState { EX_IDLE, EX_WAIT_FOR_INPUT }; ExState exState = EX_IDLE; int inputNumber = 0; // Anzahl der eingegebenen Stellen String inputBuffer = ""; // Sammeln der Ziffern als Text int inputDistance = 0; // Konvertierte Eingabe void setup() { led.setpin(13); Serial.begin(9600); ir.begin(); } void loop() { // step: command (IR-Taste einlesen) int cmd = read(); // step: state bestimmen state = decode(cmd); // step: zustandsabhängige Aktion switch (state) { case STATE_CALIBRATION: actionCalibration(); break; case STATE_FORWARD: actionForward(); break; case STATE_BACKWARD: actionBackward(); break; case STATE_DISTANCE: actionDistance(); break; case STATE_OFF: actionOff(); break; } } /* --------------------------- Funktionen --------------------------- */ int read() { if (ir.decode()) { uint32_t code = getIRCode(); // vermeiden wiederholender eingabe unsigned long now = millis(); if (code == lastCode && (now - lastTime < COOL_DOWN)) return -1; lastCode = code; lastTime = now; // switch (code) { case IR_BUTTON_E: buzzer.tone(1200, 200); return 0; // STATE_OFF break; case IR_BUTTON_B: buzzer.tone(1200, 200); return 1; // STATE_BACKWARD break; case IR_BUTTON_C: buzzer.tone(1200, 200); return 2; // STATE_CALIBRATION break; case IR_BUTTON_D: initInput(); return 3; // STATE_DISTANCE break; case IR_BUTTON_F: buzzer.tone(1200, 200); return 4; // STATE_FORWARD break; // Ziffern 0–9 case IR_BUTTON_0: handleInput(0); break; case IR_BUTTON_1: handleInput(1); break; case IR_BUTTON_2: handleInput(2); break; case IR_BUTTON_3: handleInput(3); break; case IR_BUTTON_4: handleInput(4); break; case IR_BUTTON_5: handleInput(5); break; case IR_BUTTON_6: handleInput(6); break; case IR_BUTTON_7: handleInput(7); break; case IR_BUTTON_8: handleInput(8); break; case IR_BUTTON_9: handleInput(9); break; // Taste 'Setting' = Eingabe abschließen case IR_BUTTON_SETTING: finalizeInput(); return -1; // Kein direkter Zustandswechsel break; } } return -1; // keine bekannte/verwertbare Taste } uint32_t getIRCode() { uint32_t value = ir.value; value = (value >> 16) & 0xff; return value; } State decode(int cmd) { switch (cmd) { case 0: lastState = STATE_OFF; return STATE_OFF; case 1: lastState = STATE_BACKWARD; return STATE_BACKWARD; case 2: lastState = STATE_CALIBRATION; return STATE_CALIBRATION; case 3: lastState = STATE_DISTANCE; return STATE_DISTANCE; case 4: lastState = STATE_FORWARD; return STATE_FORWARD; } return lastState; } /* --------------------------- Eingabemodus für EX-Befehle --------------------------- */ void initInput() { buzzer.tone(1000, 200); exState = EX_WAIT_FOR_INPUT; inputNumber = 0; inputBuffer = ""; } void handleInput(int number) { if (exState != EX_WAIT_FOR_INPUT) return; // Maximal 3 Stellen erlauben if (inputNumber >= 3) { buzzer.tone(300, 300); delay(200); buzzer.tone(300, 300); return; } // Zahl anhängen inputBuffer += String(number); inputNumber++; buzzer.tone(1200, 80); } void finalizeInput() { if (exState == EX_WAIT_FOR_INPUT) { exState = EX_IDLE; buzzer.tone(1200, 200); } } /* --------------------------- Funktionen ...actionXXX --------------------------- */ void actionCalibration() { Serial.println("...actionCalibration"); } void actionForward() { Serial.println("...actionForward"); } void actionBackward() { Serial.println("...actionBackward"); } void actionDistance() { Serial.println("...actionDistance"); // noch in der Eingabe? if (exState == EX_WAIT_FOR_INPUT) { return; } // step: ...calculate distance inputDistance = inputBuffer.toInt(); if (inputDistance > 200) { inputDistance = 200; } Serial.print("Eingegebene Distance: "); Serial.println(inputDistance); } void actionOff() { Serial.println("...actionOff"); }
Programm Steckenfahren
ABSCHNITT ENTSTEHT GERADE! - CODE NICHT GETESTET!
Quellcode (engl. Sourcecode)
Listing 1:MinimalesProgramm.ino
#include "MeMCore.h" // Hardware MeIR ir; MeBuzzer buzzer; MeLineFollower lineFinder(PORT_2); MeRGBLed led(0, 2); // must be fixed! MeDCMotor motor1(M1); MeDCMotor motor2(M2); // Allgemein unsigned long calibrationTravelTime = 0; int calibrationLength = 100; // cm int travelDistance = 0; unsigned long currentTravelTime; int speed = 180; // Motor speed // actionCalibration... unsigned long ac_movingStartTimeForward = 0; unsigned long ac_movingTimeForward = 0; unsigned long ac_movingStartTimeBackward = 0; unsigned long ac_movingTimeBackward = 0; bool ac_isMoving = false; bool ac_isForwardMoving = false; bool ac_isBackwardMoving = false; bool ac_calibrationDone = false; // actionForward unsigned long af_StartTime = 0; bool af_done = false; unsigned long previousMillis = 0; bool firstRun = true; enum State { STATE_OFF, STATE_CALIBRATION, STATE_FORWARD, STATE_BACKWARD }; State state = STATE_OFF; State lastState = STATE_OFF; void setup() { led.setpin(13); ir.begin(); } void loop() { // step: command int cmd = read(); // step: state state = decode(cmd); // step: action switch (state) { case STATE_CALIBRATION: actionCalibration(); break; case STATE_FORWARD: // actionForward(); break; case STATE_BACKWARD: // actionBackward(); break; case STATE_OFF: // actionOff(); break; } } /* Funktionen */ int read() { if (ir.decode()) { uint32_t code = getIRCode(); switch (code) { case IR_BUTTON_E: buzzer.tone(1200, 600); return 0; break; case IR_BUTTON_C: buzzer.tone(1200, 600); return 1; break; case IR_BUTTON_B: { buzzer.tone(1200, 600); // TODO read value return 2; break; } case IR_BUTTON_F: { buzzer.tone(1200, 600); // TODO read value return 3; break; } } } return -1; // unknow cmd } uint32_t getIRCode() { uint32_t value = ir.value; value = value >> 16 & 0xff; return value; } State decode(int cmd) { switch (cmd) { case 0: lastState = STATE_OFF; return STATE_OFF; case 1: lastState = STATE_CALIBRATION ; return STATE_CALIBRATION; case 2: lastState = STATE_FORWARD; return STATE_FORWARD; case 3: lastState = STATE_BACKWARD; return STATE_BACKWARD; } return lastState; } void calculateTravelTime() { double v = (1.0 * calibrationLength) / (1.0 * calibrationTravelTime); currentTravelTime = v * travelDistance; } void actionCalibration() { if (ac_calibrationDone) return; led.setColorAt(1, 255, 0, 0); led.setColorAt(0, 255, 0, 0); led.show(); int sensorState = lineFinder.readSensors(); // step - start moving forward if (!ac_isMoving) { motor1.stop(); motor2.stop(); motor1.run(-speed); motor2.run(speed); ac_movingStartTimeForward = millis(); ac_isMoving = true; ac_isBackwardMoving = true; do { sensorState = lineFinder.readSensors(); } while ( sensorState != S1_OUT_S2_OUT); } // step - end moving forward ... start moving backward if (ac_isBackwardMoving && sensorState == S1_IN_S2_IN) { motor1.stop(); motor2.stop(); ac_movingTimeForward = millis() - ac_movingStartTimeForward; motor1.run(speed); motor2.run(-speed); ac_movingStartTimeBackward = millis(); do { sensorState = lineFinder.readSensors(); } while ( sensorState != S1_OUT_S2_OUT); ac_isBackwardMoving = false; ac_isForwardMoving = true; } // step - end turing right if (ac_isForwardMoving && sensorState == S1_IN_S2_IN) { motor1.stop(); motor2.stop(); ac_movingTimeBackward = millis() - ac_movingStartTimeBackward; calibrationTravelTime = (ac_movingTimeForward + ac_movingTimeBackward) / 2.0; ac_calibrationDone = true; led.setColorAt(1, 0, 0, 0); led.setColorAt(0, 0, 0, 0); led.show(); buzzer.tone(1200, 600); } } void actionForward() { } void actionBackward() { } void actionDistance(){ } void actionOff() { led.setColorAt(1, 0, 0, 0); led.setColorAt(0, 0, 0, 0); led.show(); // reset motor1.stop(); motor2.stop(); // reset state calibration ac_isMoving = false; ac_isForwardMoving = false; ac_isBackwardMoving = false; ac_calibrationDone = false; // reset state forward // reset state backward }