Skip to Content
RobotikMulti-Modus Roboter - Zustandsmaschine

Lernziele

  • Zustandsmaschine implementieren: Sie können verschiedene Betriebsmodi in einem Programm implementieren und zwischen ihnen wechseln.
  • Konzepte kombinieren: Sie können Radio-Steuerung, Helligkeitssensoren und Event-Loop zu einem komplexen Programm verbinden.
  • Code-Organisation: Sie strukturieren ein grösseres Projekt mit Funktionen und klaren Zuständen.
  • Fehlersuche: Sie können ein komplexes System schrittweise testen und Fehler systematisch eingrenzen.

Das Projekt: Ein Multi-Modus Roboter

Bisher haben Sie verschiedene Einzelfunktionen für den Maqueen programmiert: Fernsteuerung, Linienfolger, Distanzsensoren. Nun kombinieren wir diese zu einem intelligenten Roboter, der zwischen verschiedenen Modi wechseln kann.

Unser Roboter soll drei verschiedene Betriebsmodi haben:

  1. Modus “Fernsteuern”: Beide Motoren werden per Funk ferngesteuert - freie Bewegung in alle Richtungen
  2. Modus “Tracker”: Der Roboter folgt automatisch einem schwarzen Fleck am Boden (links herum)
  3. Modus “Off”: Alle Motoren werden abgestellt und das Programm wird sauber beendet

Das Besondere: Sie benötigen zwei Microbits - einen im Roboter und einen als Fernsteuerung!

Planung: Die Zustandsmaschine

Erinnern Sie sich an die Zustandsmaschine aus der Buttons-Lektion? Genau dieses Konzept brauchen wir hier!

# Verschiedene Modi als Konstanten (Strings sind einfacher!) MODE_OFF = "MODE:OFF" MODE_FERNSTEUERUNG = "MODE:FERNSTEUERUNG" MODE_TRACKER = "MODE:TRACKER" # Aktueller Modus (starten im Fernsteuerungsmodus) mode = MODE_FERNSTEUERUNG

Unser Event-Loop muss dann je nach Modus unterschiedlich reagieren. Elegant ist es, den Modus direkt in der Loop-Bedingung zu nutzen:

while mode != MODE_OFF: if mode == MODE_FERNSTEUERUNG: # Auf Funksignale reagieren, Motoren steuern elif mode == MODE_TRACKER: # Helligkeitssensoren auslesen, automatisch fahren # Wenn die Loop beendet wird, stoppen wir alle Motoren maqueen.motor_stop_all()

Challenge 1: Das Grundgerüst

Erstellen Sie zuerst die Grundstruktur für den Roboter (nicht die Fernsteuerung!):

Aufgaben:

  1. Importieren Sie die nötigen Module (microbit, maqueen, radio)
  2. Definieren Sie die drei Modus-Konstanten
  3. Setzen Sie die Radio-Gruppe (z.B. radio.config(group=42))
  4. Erstellen Sie einen Event-Loop mit while mode != MODE_OFF
  5. Bauen Sie die if/elif-Struktur für die Modi (nur Fernsteuerung und Tracker, OFF ist ja die Loop-Bedingung!)
  6. Zeigen Sie auf dem Display an, in welchem Modus Sie sich befinden (z.B. “F” für Fernsteuerung, “T” für Tracker)
  7. Nach der Loop stoppen Sie alle Motoren und zeigen “0” auf dem Display

Tipps:

  • Starten Sie testweise im MODE_FERNSTEUERUNG - die Loop sollte laufen und “F” anzeigen
  • Ändern Sie testweise zu mode = MODE_OFF - die Loop sollte gar nicht starten
  • Vergessen Sie nicht radio.on() am Anfang!

Mögliche Lösung Challenge 1

from microbit import * import maqueen import radio # Modi definieren MODE_OFF = "MODE:OFF" MODE_FERNSTEUERUNG = "MODE:FERNSTEUERUNG" MODE_TRACKER = "MODE:TRACKER" # Radio konfigurieren radio.config(group=42) radio.on() # Startzustand mode = MODE_FERNSTEUERUNG while mode != MODE_OFF: if mode == MODE_FERNSTEUERUNG: display.show("F") # Hier kommt die Fernsteuerung hin elif mode == MODE_TRACKER: display.show("T") # Hier kommt der Tracker hin # Programm wird beendet maqueen.motor_stop_all() display.show("0")

Challenge 2: Die Fernsteuerung programmieren

Jetzt programmieren Sie die Fernsteuerung auf dem zweiten Microbit. Auch sie braucht Modi!

Die Modi der Fernsteuerung:

  • Modus “Fernsteuerung”: Tasten steuern die Bewegung des Roboters
  • Modus “Tracker”: Der Roboter fährt automatisch, keine Tasten nötig
  • Moduswechsel: Schütteln wechselt zwischen den Modi
  • Ausschalten: Fernsteuerung umdrehen (face down) schaltet beide aus

Aufgaben:

  1. Erstellen Sie Modi für die Fernsteuerung (gleiche Konstanten wie beim Roboter)
  2. Schütteln (accelerometer.was_gesture('shake')) wechselt zwischen MODE_FERNSTEUERUNG und MODE_TRACKER:
    • Ändert den Modus der Fernsteuerung selbst
    • Sendet den neuen Modus an den Roboter, um ihn zu synchronisieren (z.B. radio.send(MODE_FERNSTEUERUNG))
  3. Umdrehen (accelerometer.was_gesture('face down')) sendet MODE_OFF und beendet beide Loops
  4. Zeigen Sie den aktuellen Modus auf dem Display an (F oder T)

Im Fernsteuerungsmodus:

  • button_a.is_pressed() and button_b.is_pressed(): Sende “MOVE:FF” (vorwärts)
  • button_a.is_pressed(): Sende “MOVE:LT” (left turn - nach links drehen)
  • button_b.is_pressed(): Sende “MOVE:RT” (right turn - nach rechts drehen)
  • Keine Taste gedrückt: Sende “MOVE:00” (stopp)

Im Tracker-Modus:

  • Keine Tasten-Steuerung nötig - der Roboter fährt automatisch!

Tipps:

  • Beim Moduswechsel: Erst den eigenen Modus ändern, dann den Befehl senden
  • Nutzen Sie is_pressed() für kontinuierliche Bewegung (Taste gedrückt halten)
  • Da die Modi jetzt Strings sind, können Sie sie direkt mit radio.send(mode) senden!
  • Testen Sie zuerst nur den Moduswechsel mit Schütteln

Mögliche Lösung Challenge 2

from microbit import * import radio # Modi definieren (gleich wie beim Roboter!) MODE_OFF = "MODE:OFF" MODE_FERNSTEUERUNG = "MODE:FERNSTEUERUNG" MODE_TRACKER = "MODE:TRACKER" # Radio konfigurieren radio.config(group=42) radio.on() # Startzustand mode = MODE_FERNSTEUERUNG while mode != MODE_OFF: # Moduswechsel mit Schütteln if accelerometer.was_gesture('shake'): # Zwischen den Modi wechseln if mode == MODE_FERNSTEUERUNG: mode = MODE_TRACKER else: mode = MODE_FERNSTEUERUNG # Roboter synchronisieren - einfach den Modus senden! radio.send(mode) sleep(500) # Kurz warten, damit nicht mehrfach gewechselt wird # Ausschalten durch Umdrehen if accelerometer.was_gesture('face down'): mode = MODE_OFF radio.send(mode) # Fernsteuerungsmodus: Tasten steuern Bewegung if mode == MODE_FERNSTEUERUNG: # Display aktualisieren display.show("F") # Befehle senden if button_a.is_pressed() and button_b.is_pressed(): radio.send("MOVE:FF") elif button_a.is_pressed(): radio.send("MOVE:LT") elif button_b.is_pressed(): radio.send("MOVE:RT") else: radio.send("MOVE:00") # Tracker-Modus: Roboter fährt automatisch elif mode == MODE_TRACKER: # Display aktualisieren display.show("T") # Keine Tasten-Steuerung nötig! sleep(100) # Fernsteuerung beendet display.show("0")

Challenge 3: Fernsteuerung im Roboter empfangen

Jetzt muss der Roboter die Funknachrichten empfangen und verarbeiten.

Aufgaben:

  1. Empfangen Sie Funknachrichten mit radio.receive()
  2. Prüfen Sie, ob eine Nachricht empfangen wurde (nicht None)
  3. Vergleichen Sie die Nachricht direkt mit den möglichen Befehlen:
    • MODE_OFF, MODE_FERNSTEUERUNG, MODE_TRACKER → Modus wechseln
    • “MOVE:FF”, “MOVE:LT”, “MOVE:RT”, “MOVE:00” → Motoren steuern (nur im Fernsteuerungsmodus)

Tipps:

  • “MOVE:FF” bedeutet beide Motoren Full vorwärts (beide Tasten gedrückt)
  • “MOVE:LT” (left turn) bedeutet auf der Stelle nach links drehen (linker Motor rückwärts, rechter vorwärts)
  • “MOVE:RT” (right turn) bedeutet auf der Stelle nach rechts drehen (linker Motor vorwärts, rechter rückwärts)
  • “MOVE:00” bedeutet Stopp (keine Taste gedrückt)
  • Nutzen Sie if nachricht == MODE_FERNSTEUERUNG: statt kompliziertem String-Splitting!

Mögliche Lösung Challenge 3

from microbit import * import maqueen import radio # Modi definieren MODE_OFF = "MODE:OFF" MODE_FERNSTEUERUNG = "MODE:FERNSTEUERUNG" MODE_TRACKER = "MODE:TRACKER" # Geschwindigkeiten FULL = 100 SLOW = 50 # Radio konfigurieren radio.config(group=42) radio.on() # Startzustand mode = MODE_FERNSTEUERUNG while mode != MODE_OFF: # Funknachrichten empfangen nachricht = radio.receive() # Moduswechsel - einfacher Vergleich mit den Konstanten! if nachricht == MODE_OFF: mode = MODE_OFF elif nachricht == MODE_FERNSTEUERUNG: mode = MODE_FERNSTEUERUNG elif nachricht == MODE_TRACKER: mode = MODE_TRACKER # Je nach Modus handeln if mode == MODE_FERNSTEUERUNG: display.show("F") # Bewegungsbefehle verarbeiten if nachricht == "MOVE:FF": # Beide Motoren vorwärts maqueen.set_motor(0, FULL) maqueen.set_motor(1, FULL) elif nachricht == "MOVE:LT": # Links drehen: linker Motor rückwärts, rechter vorwärts maqueen.set_motor(0, -FULL) maqueen.set_motor(1, FULL) elif nachricht == "MOVE:RT": # Rechts drehen: linker Motor vorwärts, rechter rückwärts maqueen.set_motor(0, FULL) maqueen.set_motor(1, -FULL) elif nachricht == "MOVE:00": # Stopp maqueen.motor_stop_all() elif mode == MODE_TRACKER: display.show("T") # Hier kommt der Tracker hin # Programm wird beendet maqueen.motor_stop_all() display.show("0")

Challenge 4: Tracker-Modus implementieren

Jetzt implementieren Sie den automatischen Tracker-Modus. Der Roboter soll einem schwarzen Fleck am Boden folgen - er fährt am Rand des Flecks entlang (links herum).

Aufgaben:

  1. Lesen Sie die Helligkeitssensoren aus: maqueen.read_patrol(0) und maqueen.read_patrol(1)
  2. Implementieren Sie die Tracker-Logik für einen schwarzen Fleck:
    • left == 0 and right == 1 (linker Sensor auf schwarz): Perfekt! Geradeaus fahren
    • left == 1 and right == 1 (beide auf hell): Zu weit rechts! Nach links drehen
    • left == 0 and right == 0 (beide auf schwarz): Zu weit links! Nach rechts drehen
    • Im Fall left == 1 and right == 0 drehen wir uns weiter

Tipps:

  • Der Roboter folgt dem Fleck “links herum” - der linke Sensor ist auf dem Fleck
  • SLOW können Sie auf 0 setzen für schärfere Kurven (Drehen auf der Stelle)
  • Bei “nach links drehen” ist der linke Motor langsam (SLOW), der rechte schnell (FULL)
  • Bei “nach rechts drehen” ist der linke Motor schnell (FULL), der rechte langsam (SLOW)

Mögliche Lösung Challenge 4

Roboter-Code erweitern:

# Im Tracker-Modus diesen Code einfügen: elif mode == MODE_TRACKER: display.show("T") # Helligkeitssensoren auslesen left = maqueen.read_patrol(0) right = maqueen.read_patrol(1) # Tracker-Logik (0 = dunkel/schwarz, 1 = hell/weiss) # Der Roboter fährt links herum um den schwarzen Fleck if left == 0 and right == 1: # Perfekt! Linker Sensor auf schwarz → Geradeaus maqueen.set_motor(0, FULL) maqueen.set_motor(1, FULL) elif left == 0 and right == 0: # Beide auf schwarz → zu weit links! Nach rechts drehen maqueen.set_motor(0, FULL) maqueen.set_motor(1, SLOW) else: # Beide auf hell → zu weit rechts! Nach links drehen # Sie könnten auch schreiben: elif left == 1 and right == 1 , # aber so dreht der Roboter auch, wenn er verkehrt auf der Kante steht maqueen.set_motor(0, SLOW) maqueen.set_motor(1, FULL)

Challenge 5: Alles zusammenfügen und testen

Jetzt haben Sie alle Teile! Zeit für den Systemtest.

Test-Checkliste:

  1. ✅ Roboter und Fernsteuerung starten beide im Fernsteuerungsmodus (F angezeigt)
  2. ✅ Beide Tasten zusammen: Roboter fährt vorwärts (FF)
  3. ✅ Taste A alleine: Roboter dreht nach links (LT)
  4. ✅ Taste B alleine: Roboter dreht nach rechts (RT)
  5. ✅ Keine Taste: Roboter stoppt (00)
  6. ✅ Fernsteuerung schütteln: Beide wechseln synchron zum Tracker-Modus (T angezeigt)
  7. ✅ Im Tracker-Modus folgt der Roboter automatisch dem schwarzen Fleck (links herum)
  8. ✅ Nochmal schütteln: Beide wechseln zurück zum Fernsteuerungsmodus
  9. ✅ Fernsteuerung umdrehen (face down): Beide beenden ihre Loops, Display zeigt “0”, alle Motoren stoppen

Fehlersuche:

  • Funktioniert die Fernsteuerung nicht? → Prüfen Sie die Radio-Gruppe auf beiden Geräten
  • Modi werden nicht synchronisiert? → Prüfen Sie, ob radio.send(mode) korrekt verwendet wird
  • Roboter dreht in falsche Richtung? → Prüfen Sie die Motor-Nummern (0 = links, 1 = rechts) und Vorzeichen
  • Schütteln wechselt mehrfach? → Das sleep(500) nach dem Moduswechsel verhindert Doppel-Wechsel
  • Roboter reagiert nicht auf Tracker? → Testen Sie die Helligkeitssensoren einzeln (display.show(left) und display.show(right))
  • Roboter fährt vom Fleck weg? → Prüfen Sie die Logik: left == 0 bedeutet “linker Sensor auf schwarz”
  • Umdrehen schaltet nicht aus? → Prüfen Sie die Schreibweise: 'face down' (mit Leerzeichen!)

Bonus-Challenge: Verbesserungen

Ihr Roboter funktioniert? Perfekt! Jetzt können Sie ihn noch verbessern:

  1. Rückwärtsfahren hinzufügen: Wenn man im Fernsteuerungsmodus beide Tasten gedrückt hält UND den Microbit nach unten neigt, fährt der Roboter rückwärts
  2. Geschwindigkeitsregelung: Im Tracker-Modus können Sie mit Taste A/B die Geschwindigkeit zwischen verschiedenen Stufen wechseln
  3. LED-Feedback auf Roboter: Nutzen Sie die LEDs des Maqueen (maqueen.set_led()) um den aktuellen Modus anzuzeigen
  4. Automatischer Moduswechsel: Wenn im Tracker-Modus lange keine Linie gefunden wird (beide Sensoren = 1), wechseln Sie automatisch zur Fernsteuerung
  5. Sanfteres Drehen: Statt auf der Stelle zu drehen (LT/RT), könnten Sie mit verschiedenen Geschwindigkeiten sanftere Kurven fahren
  6. Code aufräumen: Lagern Sie die Tracker-Logik in eine eigene Funktion folge_linie() aus (siehe Linienfinder-Lektion)
  7. Notfall-Stop: Fügen Sie einen Notfall-Stop hinzu - wenn man die Fernsteuerung stark schüttelt (3x hintereinander), stoppen sofort alle Motoren
  8. Zweite Fahrtrichtung: Als Herausforderung können Sie einen zweiten Tracker-Modus hinzufügen, der rechts herum um den Fleck fährt

Vollständiges Beispiel: Roboter-Code

from microbit import * import maqueen import radio # Modi definieren MODE_OFF = "MODE:OFF" MODE_FERNSTEUERUNG = "MODE:FERNSTEUERUNG" MODE_TRACKER = "MODE:TRACKER" # Geschwindigkeiten FULL = 100 SLOW = 0 # 0 für scharfe Kurven, oder 50 für sanftere Kurven # Radio konfigurieren radio.config(group=42) radio.on() # Startzustand mode = MODE_FERNSTEUERUNG while mode != MODE_OFF: # Funknachrichten empfangen nachricht = radio.receive() # Moduswechsel if nachricht == MODE_OFF: mode = MODE_OFF elif nachricht == MODE_FERNSTEUERUNG: mode = MODE_FERNSTEUERUNG elif nachricht == MODE_TRACKER: mode = MODE_TRACKER # Je nach Modus handeln if mode == MODE_FERNSTEUERUNG: display.show("F") # Bewegungsbefehle verarbeiten if nachricht == "MOVE:FF": maqueen.set_motor(0, FULL) maqueen.set_motor(1, FULL) elif nachricht == "MOVE:LT": maqueen.set_motor(0, -FULL) maqueen.set_motor(1, FULL) elif nachricht == "MOVE:RT": maqueen.set_motor(0, FULL) maqueen.set_motor(1, -FULL) elif nachricht == "MOVE:00": maqueen.motor_stop_all() elif mode == MODE_TRACKER: display.show("T") # Helligkeitssensoren auslesen left = maqueen.read_patrol(0) right = maqueen.read_patrol(1) # Tracker-Logik (0 = dunkel/schwarz, 1 = hell/weiss) # Der Roboter fährt links herum um den schwarzen Fleck if left == 0 and right == 1: # Perfekt! Linker Sensor auf schwarz → Geradeaus maqueen.set_motor(0, FULL) maqueen.set_motor(1, FULL) elif left == 0 and right == 0: # Beide auf schwarz → zu weit links! Nach rechts drehen maqueen.set_motor(0, FULL) maqueen.set_motor(1, SLOW) else: # Beide auf hell → zu weit rechts! Nach links drehen # Sie könnten auch schreiben: elif left == 1 and right == 1 , # aber so dreht der Roboter auch, wenn er verkehrt auf der Kante steht maqueen.set_motor(0, SLOW) maqueen.set_motor(1, FULL) # Programm wird beendet maqueen.motor_stop_all() display.show("0")

Vollständiges Beispiel: Fernsteuerungs-Code

from microbit import * import radio # Modi definieren MODE_OFF = "MODE:OFF" MODE_FERNSTEUERUNG = "MODE:FERNSTEUERUNG" MODE_TRACKER = "MODE:TRACKER" # Radio konfigurieren radio.config(group=42) radio.on() # Startzustand mode = MODE_FERNSTEUERUNG while mode != MODE_OFF: # Moduswechsel mit Schütteln if accelerometer.was_gesture('shake'): if mode == MODE_FERNSTEUERUNG: mode = MODE_TRACKER else: mode = MODE_FERNSTEUERUNG # Einfach den Modus senden! radio.send(mode) sleep(500) # Ausschalten durch Umdrehen if accelerometer.was_gesture('face down'): mode = MODE_OFF radio.send(mode) # Display aktualisieren if mode == MODE_FERNSTEUERUNG: display.show("F") elif mode == MODE_TRACKER: display.show("T") # Fernsteuerungsmodus: Tasten steuern Bewegung if mode == MODE_FERNSTEUERUNG: if button_a.is_pressed() and button_b.is_pressed(): radio.send("MOVE:FF") elif button_a.is_pressed(): radio.send("MOVE:LT") elif button_b.is_pressed(): radio.send("MOVE:RT") else: radio.send("MOVE:00") # Tracker-Modus: Roboter fährt automatisch # (keine Tasten-Steuerung nötig) sleep(100) # Fernsteuerung beendet display.show("0")

Reflexion

Sie haben jetzt ein komplexes System gebaut, das verschiedene Konzepte elegant kombiniert:

  • Event-Loop als Herzstück des Programms
  • Zustandsmaschine zur Verwaltung verschiedener Modi
  • Radio-Kommunikation zwischen zwei Geräten
  • Sensoren zur Umgebungswahrnehmung
  • Motorsteuerung für präzise Bewegungen

Das ist genau so, wie echte Roboter und autonome Systeme funktionieren! Sie haben die Grundlagen der Robotik und der eingebetteten Systeme kennengelernt.

Last updated on