**Dies ist eine alte Version des Dokuments!**
Microbit programmieren
1. Übersicht
Der micro:bit ist ein Microcontroller (eine Art Mini-Computer), der speziell für den Schulbetrieb entwickelt wurde und mit Python programmiert werden kann.
Er verfügt über eine Vielzahl an Komponenten, die man mit seinem Code ansteuern kann. Mit Display und Lautsprecher kann der Microbit Bild und Ton ausgeben. Zur Eingabe von Daten sind auf dem Microbit zwei Tasten, das Touch-Logo und mehrere Sensoren eingebaut. Auf dieser Seite lernst du die wichtigsten Funktionen kennen, um Display, Lautsprecher, Tasten und Sensoren anzusteuern.
Eine kurze Übersicht zu den wichtigsten Funktionen in englischer Sprache findest du im Microbit-Python-Guide
In der Microbit-Micropython-Dokumentation findest du alle Informationen zur Programmierung des Micro-Bit.
2. Getting started
Für die Programmierung des Microbits gibt es zwei Möglichkeiten:
- Online-Editor:
- Verwende Chrome Browser
- Vergleich zum Mu-Editor (unten):
- Pro: unkompliziert, keine Installation nötig, schnelles Laden auf micro:bit
- Contra: Speichern/Laden ist deutlich umständlicher
- Tipp zum Speichern::
- Kopiere deinen Code jeweils in ein Word Dokument.
- Verwende z.B. folgende Vorlage: Template Aufgaben
- Bonus bei diesem Vorgehen: schöne Übersicht von allen deinen Codes!
- Offline-Editor:
- Mu Editor (https://codewith.mu/en/download)
- Lade hier die Installationsdatei herunter.
- Installiere den Editor gemäss den Anweisungen.
- Verbinde den Microbit über das USB-Kabel mit deinem Computer.
- Für macOS-User: Stelle sicher, dass die Applikationen „Mu-Editor“, „sh“, „Terminal“ vollen Schreibzugriff haben (unter Systemeinstellungen –> Sicherheit…).
- Starte den Editor.
- Klicke auf den Mode-Button oben links und wähle den Modus „BBC micro:bit“.
- Schreibe untenstehende Code-Zeilen.
- Klicke auf die „Flash“-Taste und warte, bis dein Code auf den Microbit geladen ist: Wenn dein Microbit nun „Hello, World!“ anzeigt, kannst du mit dem Programmieren beginnen.
from microbit import * display.scroll("Hello, World!")
3. Display
Text anzeigen
Wir schauen uns kurz die beiden Code-Zeilen des Hello-World-Beispiels an:
from microbit import * display.scroll("Hello, World!")
- Die Zeile
from microbit import *
bedeutet, dass alle Microbit-Funktionen und -Objekte importiert werden sollen. Diese Zeile brauchen wir für jedes Microbit-Programm. - Die zweite Zeile sagt dem Display, dass es die Zeichenkette „Hello, World!“ als Laufschrift anzeigen soll – oder etwas genauer formuliert: Vom
display
-Objekt wird die Funktionscroll()
aufgerufen und dieser Funktion wird die Zeichenkette „Hello, World!“ übergeben.
Über das display-Objekt kannst du auf weitere Display-Funktionen zugreifen. Wenn du im Mu-Editor display
und dann einen Punkt eintippst, erhältst du eine Liste mit allen Display-Funktionen. Die wichtigsten sind clear()
zum Löschen des Displays und show()
zur Anzeige von einem oder mehreren Bildern.
Bilder anzeigen
Folgender Code zeigt ein Herz auf dem Display:
from microbit import * display.show(Image.HEART)
Über das Image
-Objekt kannst du auf eine Reihe von vordefinierten Bildern zugreifen.
Animationen mit Bilder-Listen
In Python kannst du auf einfache Weise Listen erstellen, das hast du hier gelernt. Im folgenden Code wird eine Liste von Bildern erstellt und angezeigt.
from microbit import * my_images = [Image.HAPPY, Image.SMILE, Image.SAD, Image.CONFUSED] display.show(my_images)
Die Funktion show()
merkt, dass sie es hier mit einer Liste zu tun hat und zeigt nun jedes Bild der Liste nacheinander.
Du kannst der Funktion weitere Parameter übergeben:
display.show(my_images, delay = 500, loop = True)
- Mit dem Parameter
delay
gibst du an, wie lange (in Millisekunden) jedes Bild angezeigt werden soll. - Wenn du den Parameter
loop
auf „True“ setzt, wird die Animation endlos wiederholt.
4. Tasten
Tasten & Touch-Logo
Der Microbit kann über die Tasten A und B sowie per Touch-Logo bedient werden. Mit den Funktionen is_pressed()
bzw. is_touched()
kannst du fragen, ob die jeweilige Taste gedrückt ist. Das folgende Programm zeigt je nach betätigtem Bedienelement ein anderes Bild auf dem Display:
from microbit import * while True: if button_a.is_pressed(): display.show(Image.HAPPY) if button_b.get_presses(): display.show(Image.SAD) if pin_logo.is_touched(): display.show(Image.HEART)
Mit while True:
wird eine Endlos-Schleife eröffnet: Der Code darunter wird endlos wiederholt:
- Zuerst wird gefragt, ob Taste A gedrückt wurde: Falls ja, soll das Display das Bild HAPPY anzeigen.
- Dann wird gefragt, ob Taste B gedrückt wurde: Falls ja, soll das Display das Bild SAD anzeigen.
- Dann wird gefragt, ob das Logo berührt wurde: Falls ja, soll das Display das Bild HEART anzeigen.
- Dann springt das Programm wieder zum ersten Punkt – und so weiter und so fort.
Beachte, dass es für Tasten drei Befehle gibt: is_pressed()
, get_presses()
und was_pressed()
.
is_pressed()
gibtTrue
zurück, wenn die Taste im Moment der Abfrage gedrückt ist, aber sagt nichts darüber aus, ob sie in der Vergangenheit gedrückt worden ist.was_pressed()
gibtTrue
zurück, falls die Taste seit dem letzten Aufruf der Funktion gedrückt worden ist, als auch, wenn die Taste bereits wieder losgelassen wurde.get_presses()
funktioniert ähnlich wiewas_pressed
, aber gibt die Anzahl Klicks seit dem letzten Funktionsaufruf zurück. Der Funktionsaufruf setzt den Zähler wieder auf Null zurück.
Diese If-Abfragen erfolgen so schnell, dass die Endlos-Schleife jede Sekunde mehrere tausend Mal durchlaufen wird. Du kannst also jederzeit eine Taste drücken und das Bild wird sofort angepasst – probiere es aus!
Pins
Zusätzlich befinden sich unten am micro:bit Pins, die man verwenden kann. Probiere folgenden Code aus:
# Imports go at the top from microbit import * while True: if pin0.is_touched(): display.show(Image.HAPPY) else: display.show(Image.SAD)
Sobald du nun den Stromkreis zwischen Ground (GND) und Pin 0 schliesst (beide gleichzeitig berühren oder mit Kabel verbinden), sollte nun ein Happy-Smile angezeigt werden.
Für mehr Infos siehe hier: https://microbit-micropython.readthedocs.io/en/latest/pin.html
5. Beschleunigungssensor
Auf der Rückseite des Microbits befindet sich unten links ein Beschleunigungssensor. Der Beschleunigungssensor misst die Beschleunigung, die der Microbit in x-, y- und in z-Richtung erfährt. Du kannst dir eine Drohne vorstellen: Wenn sie immer vorwärts und rückwärts fliegt, beschleunigt sie in x-, wenn sie seitwärts hin und her fliegt in y- und wenn sie hoch oder runter fliegt in z-Richtung.
Beschleunigung messen
Folgender Code liest alle 100 ms die Werte aus dem Beschleunigungssensor und sendet sie über USB:
from microbit import * while True: sleep(100) print(str(accelerometer.get_values()))
Innerhalb der Endlos-Schleife while True
werden zwei Befehele ständig wiederholt:
sleep(100)
lässt das Programm während 100 Millisekunden in der Funktion sleep() verharren,- in der zweiten Zeile sind gleich drei Funktionen ineinander verschachtelt:
- Die Funktion
get_values()
gibt die drei Werte vom Beschleunigungssensor für die $x-,y-$ und $z-$Achse zurück, - die Funktion
str()
wandelt diese Zahlenwerte in eine Zeichenkette (engl. String) und - die Funktion
print()
sendet diese Zeichenkette über USB, sodass sie am verbundenen Computer angezeigt werden kann.
Probiere es aus: Lade obigen Code auf den Microbit und starte im MU editor den Plotter (Button „Plotter“ oben Mitte). Es werden drei Kurven angezeigt. Wenn du den Microbit wild schüttelst – achte auf das Kabel und darauf, dass du nicht deinen Laptop mitreisst – dann bewegen sich alle drei Kurven.
Versuche jetzt, den Microbit so zu bewegen, dass jeweils nur eine der drei Kurven ausschlägt.
Zur Info:
- Die Funktion
get_values()
gibt Werte in der Einheit mg zurück, $1000$ mg entsprechen 1 g: $1 g = 9.81 \text{m}/\text{s}^2$. - Standardmässig beträgt der Messbereich des Beschleunigungssensors +/- 2 $g$.
- Mit
get_values()
erhältst du die Beschleunigungen $a_x,a_y,a_z$ für die drei einzelnen Koordinaten. Die Gesamtbeschleunigung (Betrag der Beschleunigung) ist dann gegeben durch den Satz von Pythagoras in 3D: $$a = \sqrt{a_x^2 + a_y^2 + a_z^2}$$ Achtung: Dieser Wert ist immer positiv. Du verlierst damit also sämtliche Informationen über die Richtung der Beschleunigung.
Gesten erkennen
Mit dem Beschleunigungssensor können auch bestimmte Gesten (engl. gestures) erkannt werden – zum Beispiel, ob der Microbit geschüttelt wurde („shake“
), ob er nach oben („face up“
) oder nach unten („face down“
) gedreht ist usw. Folgender Code zeigt ein Happy Face, wenn der Microbit nach oben gedreht ist, sonst ein Sad Face:
from microbit import * while True: if accelerometer.is_gesture("face up"): display.show(Image.HAPPY) else: display.show(Image.SAD)
Die Funktion is_gesture()
gibt True
zurück, wenn der Beschleunigungssensor die in den Klammern angegebene Geste erkannt hat. Sonst gibt sie False
zurück.
Hier findest du eine Übersicht über Funktionen des Beschleunigungssensors.
6. Sounds
Auf der Rückseite des Microbits befindet sich in der Mitte der „Lautsprecher“ (engl. speaker). Dieser klingt nicht wirklich laut, aber dank folgender Software-Module kannst du viel damit machen:
- Das Modul
music
stellt dir eine Reihe von vordefinierten Melodien zur Verfügung. Du kannst auch selber Melodien erstellen. - Mit dem Modul
speech
kann dein Microbit einen Text sprechen oder gar singen. Allerdings lässt die Qualität noch zu wünschen übrig. Für bessere Audio-Qualität schliesst du den einen Kanal eines alten Kopfhörers an den Pins 0 und GND an.
Einzelne Töne abspielen
Folgender Code spielt einen Ton, wenn die Taste A gedrückt wird:
from microbit import * import music while True: if button_a.is_pressed(): music.pitch(440, 100)
- Die Zeile
import music
importiert das Modulmusic
. Dieses enthält die Funktionenpitch()
,play()
und weitere Funktionen. - Der Funktion
pitch()
wird die Frequenz des Tons in Hertz und die Dauer des Tons in Millisekunden übergeben. - Wenn du kurz testen willst, welche Frequenz wie klingt, klicke hier.
Melodien erstellen und abspielen
Das Modul music
enthält schon ein paar vordefinierte Melodien. Folgender Code spielt eine solche Melodie ab:
from microbit import* import music music.play(music.PRELUDE)
Melodien selber erstellen
Du kannst auch selbst Melodien erstellen, wie in folgendem Code:
from microbit import* import music my_melody = ['g3:4', 'g3:4', 'b3:4', 'g3:4','c4:4', 'f4:4', 'c4:4', 'g3:8'] music.set_tempo(bpm = 180) # 120 Schläge pro Minute wäre Standard music.set_tempo(ticks = 8) # 8 Schläge pro Takt ist Standard music.play(my_melody)
- Die Liste
my_melody
enthält jede zu spielende Note und deren Dauer; es gilt die NotationNOTE[Oktave][:Dauer]
, also zum Beispiel'c4:8
' für die Note C in der vierten Oktave, die acht Schläge lang gespielt wird.Hier eine Übersicht über die Noten und Oktaven. - Mit der Funktion
set_tempo()
kann das Tempo (beats per minute) oder die Taktart verändert werden. - Die Funktion
play()
spielt die Melodie ab.
Probiere das Programm aus und verändere die Melodie, du kannst auch Noten hinzufügen oder weglassen.
Melodien anders abspielen
Dir ist vielleicht aufgefallen, dass manche Melodien nicht so klingen, wie sie sollten. Hier zum Beispiel die Melodie für das Lied Frère Jacques (Bruder Jakob):
# Frère Jacques: melody_jacques = ['c4:4', 'd4:4', 'e4:4', 'c4:4','c4:4', 'd4:4', 'e4:4', 'c4:4', 'e4:4', 'f4:4', 'g4:8', 'e4:4', 'f4:4', 'g4:8', 'g4:2', 'a4:2', 'g4:2', 'f4:2', 'e4:4', 'c4:4', 'g4:2', 'a4:2', 'g4:2', 'f4:2', 'e4:4', 'c4:4', 'c4:4', 'g3:4', 'c4:8', 'c4:4', 'g3:4', 'c4:8']
Wenn die Funktion play()
Melodien abspielt, werden die einzelnen Töne unmittelbar aufeinanderfolgend, also ohne Zwischenpause wiedergegeben. Falls zwei gleiche Töne aufeinanderfolgen (wie in Frère Jacques beispielsweise der 4. und 5. Ton), klingt das wie ein einziger, langer Ton. Hierzu gibt es mindestens zwei Lösungen:
- Mit der Note
r
(für engl. rest) können Pausen in die Melodie eingebaut werden:'r:2'
macht eine Pause von zwei Schlägen. Dann sollten aber auch die anderen Ton-Dauern angepasst werden. - Da die Melodie als Liste vorliegt, kannst du sie Ton für Ton abspielen und jeweils dazwischen eine ganz kurze Pause einbauen. Zum Beispiel so:
note = 0 while True: music.play(melody_jacques[note]) sleep(30) if(note < len(melody_jacques)-1): note += 1 else: note = 0
- In obigem Code wird zuerst eine Variable
note
für die Auswahl der Note auf 0 gesetzt. - In der Endlos-Schleife (
while True:
) wird nun in jedem Durchgang eine Note aus der Listemelody_jacques
gespielt. - Dann wird 30 ms lang gewartet.
- Schliesslich wird die Variable
note
erhöht oder – falls Sie bereits der Zahl des letzten Elements der Listemelody_jacques
entspricht – auf 0 gesetzt.
Mikrophon
Mit microphone.sound_level()
kann die Umgebungslautstärke abgefragt werden. Der Rückgabewert ist zwischen 0 (Stille) und 255 (sehr laut).
7. Radio
Grundlagen
Auf der Rückseite des Microbits siehst du oben links eine goldene Leitung, die rechtwinklig hin- und her verläuft (mäanderförmig).
Das ist die Antenne, mit der dein Microbit elektromagnetische Wellen (Funkwellen, engl.: radio waves) senden und empfangen und damit über BLE kommunizieren kann. BLE steht für Bluetooth Low Energy, eine Weiterentwicklung der Bluetooth-Funktechnologie, die dein Smartphone nutzt, um sich beispielsweise mit kabellosen Kopfhörern zu verbinden. BLE braucht weniger Energie als Bluetooth, weil es weniger Daten sendet. BLE ist daher nicht geeignet, Musik zu senden – das wären zu viele Daten. Für kleine Textnachrichten aber eignet sich BLE sehr gut.
Hier ein einfaches Programm, das einen Text senden, empfangen und anzeigen kann:
from microbit import * import radio while True: message_in = radio.receive() if message_in: display.scroll(message_in) if button_a.is_pressed(): radio.send("Ciao!")
- Zuerst muss das Radio-Modul mit dem Befehl
import radio
geladen werden. - In der Endlosschleife wird zuerst die Funktion
radio.receive()
aufgerufen. Diese Funktion schaut, ob eine Nachricht angekommen ist. Falls ja, gibt sie die empfangene Nachricht zurück, falls nein, gibt sieNone
(gleichbedeutend mit0
oderFalse
) zurück. Der zurückgegebene Wert wird in der Variablemessage_in
gespeichert. - Jetzt wird mit der
If
-Abfrage geprüft, ob eine Nachricht angekommen ist (wennmessage_in
=None
ist, dann ist die Bedingung nicht erfüllt). - Falls ja, wird diese Nachricht mit der Funktion
scroll()
angezeigt. - Wenn die Taste A gedrückt wird, wird die Nachricht „Ciao!“ gesendet.
- Achtung: Wenn mehrere Gruppen im gleichen Raum arbeiten lohnt es sich, nur auf einer bestimmten Frequenz resp. in einer bestimmten Gruppe Nachrichten zu senden und empfangen. Für eine private Kommunikation gibt es zwei Möglichkeiten:
- Ihr könnt auf einer anderen Frequenz senden: mit dem Befehl
radio.config(channel = x)
wählt ihr einen Kanal zwischen 0 und 83 (für x setzt ihr die Kanal-Nummer ein). Standardmässig ist der Kanal = 7 (und die Frequenz damit 2407 MHz). - Ihr könnt Nachrichten herausfiltern, indem ihr mit dem Befehl
radio.config(group = x)
eine eigene Gruppe-Nr. zwischen 0 und 255 wählt (standardmässig ist die Gruppe 0). So werden eure Nachrichten mit einer spezifischen Adresse versehen und eure Microbits schauen nur nach Nachrichten mit dieser Adresse.
Versenden von Bildern
Mit radio.send()
und radio.receive()
können nur Strings versendet und empfangen werden. Aus diesem Grund kann man also Bilder nicht direkt versenden. Zum Beispiel resultiert radio.send(Image.HAPPY)
in einem Fehler. Es gibt aber einen Workaround:
- Konvertiere das Bild in einen String:
s = repr(Image.HAPPY)
- Entferne alles, so dass String noch die Form
s = '00000:00000:00900:00000:00000'
hat. - Versende diesen String.
- Wandle den empfangenen String mit
Image()
wieder in ein Bild um und zeige es an.
Signalstärke & Distanzmessungen
Bisher haben wir mit message_in = radio.receive()
Nachrichten empfangen. Es gibt aber noch eine zweite Möglichkeit: Mit radio.receive_full()
empfängt man nicht nur die eigentliche Textnachricht, sondern auch die Signalstärke. Diese ist auch ein Indiz für die Distanz zwischen zwei micro:bits.
Das folgende Code-Beispiel zeigt, wie man die Textnachricht und die Signalstärke aus der erhaltenen Nachricht herauslesen kann:
message_full = radio.receive_full() if message_full: text = message_full[0] signal_strength = message_full[1]
Die Signalstärke (hier signal_strength
) ist einfach eine Zahl, die grösser wird, je stärker das Signal ist. Tipp: Printe die Signalstärke in die Konsole (print(signal_strength)
und Show serial klicken, um Konsole anzuzeigen) und verfolge, wie sich der Wert verändert, wenn die Distanz verändert wird.
Erstes Programm
Probiert das Programm zu zweit aus:
- Ladet obiges Programm auf eure Microbits und schaut, ob ihr euch via Microbit gegenseitig „Ciao!“ sagen könnt.
- Achtung: Wenn andere im gleichen Raum ebenfalls das Programm ausprobieren, empfangen sie ebenfalls eure Nachrichten (und ihr ihre). Um dies zu verhindern, habt ihr mindestens zwei Möglichkeiten:
- Ihr könnt auf einer anderen Frequenz senden: mit dem Befehl
radio.config(channel = x)
wählt ihr einen Kanal zwischen 0 und 83 (für x setzt ihr die Kanal-Nummer ein). Standardmässig ist der Kanal = 7 (und die Frequenz damit 2407 MHz). - Ihr könnt Nachrichten herausfiltern, indem ihr mit dem Befehl
radio.config(group = x)
eine eigene Gruppe-Nr. zwischen 0 und 255 wählt (standardmässig ist die Gruppe 0). So werden eure Nachrichten mit einer spezifischen Adresse versehen und eure Microbits schauen nur nach Nachrichten mit dieser Adresse. Wähle nur eine der beiden Möglichkeiten aus.
8. Maqueen
In diesem Kapitel lernst du die wichtigsten Funktionen kennen, um mit dem Microbit das Fahrwerk Maqueen zu steuern. Du kannst den Microbit einfach in den dafür vorgesehenen Steckplatz stecken. Sobald du den Schalter hinten am Fahrwerk auf On stellst, wird der Microbit mit Strom versorgt.
8.1 Ultraschall-Sensor
Wenn du den Ultraschall-Sensor auf das Maqueen-Fahrwerk steckst, sieht es so aus, als hätte der kleine Roboter nun zwei Augen:
Technisch gesehen sind die beiden Zylinder aber keine Augen: Der linke Zylinder ist eher ein Mund und der rechte ein Ohr. Mit dem linken werden Schallwellen ausgesendet (engl.: transmitted, deshalb steht da ein T); es wird quasi gerufen. Mit dem rechten Zylinder wird dann gehört; es werden also Schallwellen empfangen (engl.: received, deshalb steht da ein R).
Du kennst das vom Echo-Effekt: Du rufst ganz laut „Haaallooo!“ gegen eine Felswand und nach kurzer Zeit hörst du das Echo deines Rufs. Je weiter die Felswand entfernt ist, desto länger dauert es, bis du das Echo hörst, denn der Schall braucht seine Zeit, um von deinem Mund zur Felswand und zurück zu deinem Ohr zu gelangen.
Das heisst: Du könntest die Zeit zwischen Ruf und Echo stoppen und so auf die Distanz zwischen dir und der Felswand schliessen. Genau so funktioniert der Ultraschallsensor:
Auf der linken Seite des obigen Bildes siehst du, wie der Microbit mit dem Ultraschall-Sensor verbunden ist: Pin 1 ist mit dem Signal „Trigger“ verbunden, Pin 2 mit dem Signal „Echo“.
Auf der rechten Seite siehst du, wie es funktioniert: Wenn wir einen kurzen Impuls (10 µs = zehn Mikrosekunden) auf das Trigger-Signal geben, dann sendet der Ultraschall-Sensor Schallwellen in hoher, nicht hörbarer Frequenz (40 kHz) aus: Er „ruft“. Wenn der Ultraschall-Sensor nun das Echo seines Rufes „hört“, sendet er über das Echo-Signal einen Impuls zurück. Dieser Echo-Impuls ist so lange, wie es gedauert hat von „rufen“ bis „hören“.
Um nun eine Distanz zu messen, müssen wir nur ein kurzes Signal auf Pin 1 (Trigger) geben und dann an Pin 2 messen, wie lange das Echo-Signal dauert. Diese Zeit können wir in eine Distanz umrechnen: Der Schall legt ca. 340 Meter pro Sekunde zurück, das sind 0.034 cm pro Mikrosekunde. Angenommen, der Echo-Impuls ist 700 µs lang: Dann beträgt die Distanz 700 * 0.034 / 2 = 11.9 cm. Wir rechnen durch 2, weil der Schall die Distanz zweimal zurücklegt. Folgender Code misst die Distanz und zeigt sie auf dem Display an:
from microbit import * import utime import machine while True: # Distanz messen pin1.write_digital(1) # Pin 1 (Trigger) HIGH für... utime.sleep_us(10) # ...10 µs... pin1.write_digital(0) # ...und wieder LOW. echo_pulse = machine.time_pulse_us(pin2, 1) # Messe, wie lange der Echo-Impuls an Pin 2 dauert. distance = echo_pulse * 0.017 # Rechne Zeit in Distanz um. # Ausgabe display.scroll(distance) # Ausgabe auf LED-Matrix print(distance) # Ausgabe in Konsole sleep(500)
Für die Funktion sleep_us
wird das Modul utime
benötigt; für die Funktion time_pulse_in
wird das Modul machine
benötigt. Verstehst du jede Zeile des Codes? Dann probiere den Code aus und überprüfe, ob die angezeigten Distanzen stimmen.
8.2 Motor
Die beiden Räder des Maqueen-Fahrwerks werden von je einem Motor angetrieben. Die beiden Motoren werden über einen Motor Controller (MC) gesteuert:
Über zwei Leitungen (Pins zwischen „3V“ und „GND“) ist der Microbit mit dem Motor-Controller (MC) verbunden: Diese beiden Leitungen dienen der Kommunikation über die sogenannte I2C-Schnittstelle (I2C). Das ist eine serielle Schnittstelle, ähnlich wie USB. Auf diesem Weg sendet der Microbit dem Motor-Controller (MC) Befehle. Damit das funktioniert, muss der Microbit erst nach dem Motor-Controller suchen. Folgender Code ist dazu nötig:
I2C_ADDR = 16 # Adresse des Motor-Controllers while I2C_ADDR not in i2c.scan(): display.show(Image.SAD) display.show(Image.HAPPY)
Obiger Code ruft die Funktion i2c.scan()
so lange auf, bis der Motor-Controller an seiner Adresse gefunden wurde. Während der Suche wird ein Sad Face angezeigt; nach (erfolgreicher) Suche wird ein Happy Face angezeigt.
Jetzt können über I2C einzelne Nachrichten an die Adresse des Motor-Controllers gesendet werden. In diesen Nachrichten können wir dem MC mitteilen:
- welcher Motor drehen soll,
- in welche Richtung dieser drehen soll und
- wie schnell er drehen soll.
Folgende Funktion sendet abgängig von den Parametern die richtigen Nachrichten:
def motor_run(motors=0, direction=0x00, speed=0): # direction: 0 = forward, 1 = backward # speed range: 0...255 i2c_buf = bytearray([motors, direction, speed]) if motors == 0: # left motor i2c_buf[0] = 0x00 i2c.write(I2C_ADDR, i2c_buf) if motors == 1: # right motor i2c_buf[0] = 0x02 i2c.write(I2C_ADDR, i2c_buf) if motors == 2: # both motors i2c_buf[0] = 0x00 i2c.write(I2C_ADDR, i2c_buf) i2c_buf[0] = 0x02 i2c.write(I2C_ADDR, i2c_buf)
Du musst nicht jede Zeile dieser Funktion verstehen. Wichtig ist, dass du sie richtig verwendest: Hier eine kurze Übersicht:
- Mit dem Parameter
motors
wählst du die Motoren:- 0 für den linken Motor
- 1 für den rechten Motor
- 2 für beide Motoren
- Mit dem Parameter
direction
wählst du die Richtung:- 0 für vorwärts,
- 1 für rückwärts.
- Mit dem Parameter
speed
wählst du die Geschwindigkeit:- von 0 (stillstehend) bis 255 (schnell).
Wenn du zum Beispiel willst, dass der linke Motor mit der Geschwindigkeit 200 rückwärts dreht, dann rufst du die Funktion wie folgt auf:
motor_run(0, 1, 200)
8.3 Maqueen Interface
Für die einfachere Steuerung des Maqueen inklusive seiner Sensoren und Aktoren gibt es eine Schnittstelle auf Github.
Installation
Zur Installation des Codes lädst du maqueen.hex herunter und auf den Microbit drauf (an einfachsten: Datei auf die Seite ziehen).
- Alternative: Lade maqueen.py und füge die Datei deinem Projekt hinzu.
Distanzmesser
Der Ultraschallsensor gibt die ungefähre Distanz bis zum nächsten Objekt wieder. Lies hier mehr dazu. Wenn du die distance()
Funktion einbaust, kannst du vermeiden, dass der Roboter in Gegenstände fährt…
from maqueen import * from microbit import * robot = Maqueen() front_sensor = robot.front_sensor dist = 10 while True: newdist = int(front_sensor.distance() / 10) if newdist != dist: dist = newdist # Show distance in decimeters display.show(dist) sleep(100)
Motorsteuerung
Es gibt zwei Arten, wie die Motoren des Maqueen gesteuert werden können. Am einfachsten ist der Driver
- die Funktionen drive
, left
, right
setzen den Roboter in Bewegung und blockieren die Ausführung, bis die Bewegung zu Ende ist. Achtung: die Angaben zu Distanz (in cm) und Winkel (in Grad) werden je nach Batterieladestand nicht immer genau eingehalten!
from microbit import * from maqueen import * robot = Maqueen() # High-level Driver interface: # Fahre 20cm geradeaus, dann ein paar Kurven. # Der Roboter stoppt automatisch nach jeder Funktion. driver = robot.driver driver.drive(20) driver.left(90) driver.right(180) driver.left(90)
Die Driver-Steuerung ist ähnlich wie die Turtle-Bewegungen aus Programmieren 1, aber eignet sich weniger gut, um auf Ereignisse zu reagieren. Zum Beispiel möchten wir stoppen, wenn der Ultraschall-Sensor ein Hindernis detektiert.
Mit der Chassis
-Schnittstelle kannst du den Roboter bis auf Weiteres in Bewegung setzen und erst auf ein bestimmtes Ereignis hin wieder stoppen:
from microbit import * from maqueen import * robot = Maqueen() # Die Chassis-Funktionen setzen den Roboter in Bewegung # und kommen dann sofort zurück. Vergiss nicht, den Roboter # wieder zu stoppen! Dazu könntest du den Ultraschall- # Sensor benützen: chassis = robot.chassis chassis.forward(speed=100) # Vorwärts fahren mit Geschwindigkeit 100 chassis.stop() # Stoppen chassis.left() # Links drehen
Front LEDs
Schalte die zwei roten LEDs auf der Vorderseite ein und aus mit der front_lights.set_lights
Funktion:
from microbit import * from maqueen import * robot = Maqueen() # Licht an robot.front_lights.set_lights(1,1) # Licht aus robot.front_lights.set_lights(0,0)
Bottom LEDS
Du kannst die Farb-LEDs auf der Unterseite des Maqueens wie folgt kontrollieren. Die LEDs können im RGB-Farbraum (rot-grün-blau) programmiert werden. Jede Farbe kann Werte von 0 (aus) bis 255 annehmen.
from maqueen import * robot = Maqueen() leds = robot.bottom_leds # Setze das erste LED auf rot: leds[0] = (255,0,0) # Setze das zweite LED auf weiss (= alle Farben auf voll): leds[1] = (255,255,255) # Die LEDs werden erst geändert, wenn show() aufgerufen wird: leds.show() # Alle 4 LEDS in magenta: leds.fill((255,0,255)) leds.show() # Licht aus! leds.clear()
Boden-Farbe erkennen
Die read()
Funktion gibt die Helligkeit des Bodens wieder. Beide Werte sind entweder 0 (= Boden ist schwarz oder kein Boden sichtbar) oder 1 (= Boden ist weiss / hell). Auf der Oberseite zeigen zwei kleine blaue LEDs den Zustand der Sensoren an. Kannst du den Roboter einer Linie folgen lassen, wenn du diesen Code einbaust?
from microbit import * from maqueen import * robot = Maqueen() floor_sensor = robot.floor_sensor left, right = floor_sensor.read() # left/right nehmen Wert 0 oder 1 an