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:
Dieses Programm ermöglicht eine 90-Grad-Drehung des mBot.  
Die Drehung erfolgt zeitgesteuert, wobei die Dauer (turn_time) für eine präzise Kalibrierung angepasst werden kann.  
turn_time aus.  turn_time verringern.  turn_time erhöhen.  Listing 1:MinimalesProgramm.ino
#include <MeMCore.h>
MeDCMotor motor1(M1);
MeDCMotor motor2(M2);
void setup() {
    Serial.begin(9600);
}
void loop() {
    turn90Degrees(400); // Hier die Drehzeit anpassen
    delay(5000); // Wartezeit zwischen Drehungen
}
void turn90Degrees(int turn_time) {
    int speed = 100;  // Geschwindigkeit
    motor1.run(speed);  
    motor2.run(speed);  
    delay(turn_time);
    motor1.run(0);
    motor2.run(0);
}
| 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. | 
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.
Listing 1:MinimalesProgramm.ino
#include "MeMCore.h"
// 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  = 500; // Analoger Schwellenwert!
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  = 0;
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;
//actionTest...
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, INPUT);
  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;
  }
}
/*
     Funktionen
*/
bool turn90Degree(bool left) {
  // step: ...start turning
  if (!t90d_isTurning) {
    motor1.stop();
    motor2.stop();
    t90d_isTurning     = true;
    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, 255, 0, 0);
  led.setColorAt(0, 255, 0, 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, 0, 0, 0);
    led.setColorAt(0, 0, 0, 0);
    led.show();
    buzzer.tone(1200, 600);
  }
}
void actionTest() {
  if (!at_doneLeft) { // Links-Drehung
    at_doneLeft = turn90Degree(true);
    led.setColorAt(1, 0, 255, 0);
    led.setColorAt(0, 0, 255, 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, 0, 0, 0);
    led.setColorAt(0, 0, 0, 0);
    led.show();
    buzzer.tone(1200, 600);
    at_testComplete = true;
    return;
  }
}
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_isTurning = false;
  ac_isLeftTurning = false;
  ac_isRightTurning = false;
  ac_calibrationDone = false;
  // reset state test
  at_doneLeft = false;
  at_doneRight = false;
  at_testComplete = false;
}
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 rot
⚡ Schritt 2: ▶ Erneutes Drücken des Tasters → LEDs werden grün
⚡ Schritt 3: ▶ Nach dem Testlauf kehrt der mBot durch Drückens des Tasters in den Ruhezustand zurück.
| 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. |