mbot_streckenfahren
                Unterschiede
Hier werden die Unterschiede zwischen zwei Versionen angezeigt.
| Beide Seiten der vorigen RevisionVorhergehende ÜberarbeitungNächste Überarbeitung | Vorhergehende Überarbeitung | ||
| mbot_streckenfahren [2025/03/02 14:31] – [Quellcode (engl. Sourcecode)] torsten.roehl | mbot_streckenfahren [2025/03/02 14:38] (aktuell) – [Erklärungen zum Quellcode] torsten.roehl | ||
|---|---|---|---|
| Zeile 745: | Zeile 745: | ||
| } | } | ||
| </ | </ | ||
| + | ==== Erklärungen zum Quellcode ==== | ||
| + | === ⚙️ Setup (setup()) === | ||
| + | Initialisiert die IR-Fernbedienung und setzt den LED-Pin. | ||
| + | * '' | ||
| + | * '' | ||
| + | |||
| + | === 🔄 Loop (loop()) === | ||
| + | - **Liest IR-Signale ('' | ||
| + | - **Bestimmt den aktuellen Zustand ('' | ||
| + | - **Führt die passende Aktion aus (`actionXXX()`)** | ||
| + | |||
| + | === 🚦 Zustandsbezogene Aktionen (actionXXX()) ==== | ||
| + | * **'' | ||
| + | * **'' | ||
| + | * **'' | ||
| + | * **'' | ||
| + | |||
| + | === ⌨️ Eingabeverarbeitung (handleInput(), | ||
| + | - Ermöglicht die Eingabe einer numerischen Distanz per IR-Fernbedienung. | ||
| + | - '' | ||
| + | - '' | ||
| + | |||
| + | === ⚙️ Die ADJUST AREA === | ||
| + | Hier können **drei zentrale Parameter** angepasst werden: | ||
| + | * **'' | ||
| + | * **'' | ||
| + | * **'' | ||
| + | * Falls das Fahrzeug rückwärts fährt, auf '' | ||
| + | |||
| + | Die Werte beeinflussen das Fahrverhalten direkt und sollten je nach Umgebung angepasst werden. | ||
| - | #include " | ||
| - | |||
| - | // 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 | ||
| - | static unsigned long lastTime = 0; | ||
| - | const unsigned long COOL_DOWN = 1000; // in Millisekunden, | ||
| - | |||
| - | // Allgemein | ||
| - | unsigned long calibrationTravelTime; | ||
| - | unsigned long currentTravelTime = 100; | ||
| - | |||
| - | // ADJUST AREA START | ||
| - | int calibrationDistance = 40; // in cm | ||
| - | int speed = 200; // Motor speed | ||
| - | int dir = 1; // change to -1 if forward drive backwards! | ||
| - | // ADJUST AREA END | ||
| - | |||
| - | // actionCalibration... | ||
| - | unsigned long ac_movingStartTimeForward | ||
| - | unsigned long ac_movingTimeForward | ||
| - | unsigned long ac_movingStartTimeBackward = 0; | ||
| - | unsigned long ac_movingTimeBackward | ||
| - | bool ac_isMoving | ||
| - | bool ac_isForwardMoving | ||
| - | bool ac_isBackwardMoving = false; | ||
| - | bool ac_calibrationDone | ||
| - | |||
| - | // motor movement | ||
| - | bool mm_firstRunMotor = true; | ||
| - | bool mm_motorActive | ||
| - | unsigned long mm_motorStartTime = 0; | ||
| - | |||
| - | //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 | ||
| - | |||
| - | int | ||
| - | String | ||
| - | int | ||
| - | |||
| - | void setup() { | ||
| - | led.setpin(13); | ||
| - | // | ||
| - | 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 | ||
| - | --------------------------- | ||
| - | */ | ||
| - | void setLED(int r, int g, int b) { | ||
| - | led.setColorAt(0, | ||
| - | led.setColorAt(1, | ||
| - | led.show(); | ||
| - | } | ||
| - | |||
| - | int read() { | ||
| - | if (ir.decode()) { | ||
| - | uint32_t code = getIRCode(); | ||
| - | |||
| - | // Vermeidung wiederholter Eingaben | ||
| - | 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, | ||
| - | return 0; // STATE_OFF | ||
| - | break; | ||
| - | case IR_BUTTON_B: | ||
| - | buzzer.tone(1200, | ||
| - | return 1; // STATE_BACKWARD | ||
| - | break; | ||
| - | case IR_BUTTON_C: | ||
| - | buzzer.tone(1200, | ||
| - | return 2; // STATE_CALIBRATION | ||
| - | break; | ||
| - | case IR_BUTTON_D: | ||
| - | initInput(); | ||
| - | return 3; // STATE_DISTANCE | ||
| - | break; | ||
| - | case IR_BUTTON_F: | ||
| - | buzzer.tone(1200, | ||
| - | return 4; // STATE_FORWARD | ||
| - | break; | ||
| - | |||
| - | // Ziffern 0–9 | ||
| - | case IR_BUTTON_0: | ||
| - | case IR_BUTTON_1: | ||
| - | case IR_BUTTON_2: | ||
| - | case IR_BUTTON_3: | ||
| - | case IR_BUTTON_4: | ||
| - | case IR_BUTTON_5: | ||
| - | case IR_BUTTON_6: | ||
| - | case IR_BUTTON_7: | ||
| - | case IR_BUTTON_8: | ||
| - | case IR_BUTTON_9: | ||
| - | |||
| - | // Taste ' | ||
| - | case IR_BUTTON_SETTING: | ||
| - | finalizeInput(); | ||
| - | return -1; // Kein direkter Zustandswechsel | ||
| - | break; | ||
| - | } | ||
| - | } | ||
| - | return -1; // keine bekannte/ | ||
| - | } | ||
| - | |||
| - | 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, | ||
| - | exState | ||
| - | inputNumber = 0; | ||
| - | inputBuffer = ""; | ||
| - | setLED(0, 0, 255); // LED BLUE | ||
| - | } | ||
| - | |||
| - | void handleInput(int number) { | ||
| - | |||
| - | if (exState != EX_WAIT_FOR_INPUT) return; | ||
| - | |||
| - | // Maximal 3 Stellen erlauben | ||
| - | if (inputNumber >= 3) { | ||
| - | buzzer.tone(300, | ||
| - | delay(200); | ||
| - | buzzer.tone(300, | ||
| - | return; | ||
| - | } | ||
| - | |||
| - | // Zahl anhängen | ||
| - | inputBuffer += String(number); | ||
| - | inputNumber++; | ||
| - | buzzer.tone(1200, | ||
| - | } | ||
| - | |||
| - | void finalizeInput() { | ||
| - | if (exState == EX_WAIT_FOR_INPUT) { | ||
| - | exState = EX_IDLE; | ||
| - | buzzer.tone(1200, | ||
| - | setLED(0, 0, 0); // LED OFF | ||
| - | } | ||
| - | } | ||
| - | |||
| - | /* | ||
| - | --------------------------- | ||
| - | Funktionen ...actionXXX | ||
| - | --------------------------- | ||
| - | */ | ||
| - | void actionCalibration() { | ||
| - | |||
| - | if (ac_calibrationDone) | ||
| - | return; | ||
| - | |||
| - | setLED(255, 0, 0); // RED ON | ||
| - | int sensorState = lineFinder.readSensors(); | ||
| - | |||
| - | // step - start moving forward | ||
| - | if (!ac_isMoving) { | ||
| - | motor1.stop(); | ||
| - | motor2.stop(); | ||
| - | motor1.run(-dir * speed); | ||
| - | motor2.run( dir * 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( dir * speed); | ||
| - | motor2.run(-dir * speed); | ||
| - | ac_movingStartTimeBackward = millis(); | ||
| - | do { | ||
| - | sensorState = lineFinder.readSensors(); | ||
| - | } while ( sensorState != S1_OUT_S2_OUT); | ||
| - | ac_isBackwardMoving = false; | ||
| - | ac_isForwardMoving | ||
| - | } | ||
| - | |||
| - | // 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; | ||
| - | buzzer.tone(1200, | ||
| - | lastState = STATE_OFF; | ||
| - | } | ||
| - | } | ||
| - | |||
| - | void motorMovement(int go_forward ) { | ||
| - | unsigned long currentMillis = millis(); | ||
| - | |||
| - | // Wenn der Motor aktuell läuft, prüfen wir, ob die Zeit abgelaufen ist | ||
| - | if (mm_motorActive) { | ||
| - | if (currentMillis - mm_motorStartTime >= currentTravelTime) { | ||
| - | motor1.stop(); | ||
| - | motor2.stop(); | ||
| - | mm_motorActive = false; | ||
| - | state = STATE_OFF; | ||
| - | lastState | ||
| - | } | ||
| - | return; | ||
| - | } | ||
| - | |||
| - | if (!mm_firstRunMotor) | ||
| - | return; | ||
| - | |||
| - | setLED(0, 255, 0); // LED GREEN | ||
| - | motor1.run(-go_forward * speed); | ||
| - | motor2.run( go_forward * speed); | ||
| - | |||
| - | mm_motorStartTime = currentMillis; | ||
| - | mm_motorActive | ||
| - | mm_firstRunMotor | ||
| - | } | ||
| - | |||
| - | void actionForward() { | ||
| - | motorMovement(dir); | ||
| - | } | ||
| - | void actionBackward() { | ||
| - | motorMovement(-dir); | ||
| - | } | ||
| - | |||
| - | void actionDistance() { | ||
| - | // | ||
| - | // noch in der Eingabe? | ||
| - | if (exState == EX_WAIT_FOR_INPUT) | ||
| - | return; | ||
| - | |||
| - | // step: ...calculate distance | ||
| - | inputDistance = max(0, min(200, inputBuffer.toInt())); | ||
| - | |||
| - | // step: calculate the travel time (for non blocking-method) | ||
| - | double v = (1.0 * calibrationDistance) / (1.0 * calibrationTravelTime); | ||
| - | currentTravelTime = inputDistance / v; | ||
| - | // Serial.print(" | ||
| - | // Serial.println(inputDistance); | ||
| - | } | ||
| - | |||
| - | void actionOff() { | ||
| - | setLED(0, 0, 0); // LED OFF | ||
| - | // reset | ||
| - | motor1.stop(); | ||
| - | motor2.stop(); | ||
| - | |||
| - | // reset state calibration | ||
| - | ac_isMoving | ||
| - | ac_isForwardMoving | ||
| - | ac_isBackwardMoving = false; | ||
| - | ac_calibrationDone | ||
| - | |||
| - | // reset movement | ||
| - | mm_firstRunMotor | ||
| - | mm_motorActive | ||
| - | mm_motorStartTime | ||
| - | |||
| - | // reset state distance | ||
| - | exState | ||
| - | } | ||
mbot_streckenfahren.1740925870.txt.gz · Zuletzt geändert:  von torsten.roehl
                
                