5.2.4 Musik-Player
5.2.4.1 Übersicht

Hier bauen wir einen Musik-Player, der über den eingebauten Summer auf dem micro:bit-Board Töne erzeugt (spielt keine Vokalmusik ab). Er verfügt über eine Bibliothek von 20 kurzen Titeln und unterstützt sowohl die sequentielle als auch die zufällige Wiedergabe.
Im sequentiellen Modus wechseln die Tasten C (vorheriger Titel) oder E (nächster Titel) die Titel gemäß einer voreingestellten Reihenfolge, bis das Ende der Liste erreicht ist; im Zufallsmodus wählt jeder Tastendruck einen Titel zufällig aus den 20 Klängen aus, wobei die Farblichter blinken, und wenn ein Lied beendet ist, stoppt es sofort.
In der Zwischenzeit zeigt die micro:bit-LED-Matrix den aktuellen Wiedergabemodus in Echtzeit an.

5.2.4.2 Benötigte Teile
|
|
|
|---|---|---|
micro:bit V2 Board (selbst mitgebracht) ×1 |
micro:bit Smart Gamepad (montiert) ×1 |
AAA Batterie (selbst mitgebracht) ×4 |
5.2.4.3 Codeablauf

5.2.4.4 Testcode
Vollständiger Code:
# import related libraries
from microbit import *
import music, neopixel, random
# --- Configuration & Data ---
vol = 50
mode = 0 # 0: Manual, 1: Random
idx = 0
last_idx = -1
hue = 0
strip = neopixel.NeoPixel(pin8, 4)
melodies = ["DADADADUM", "ENTERTAINER", "PRELUDE", "ODE", "NYAN", "RINGTONE", "FUNK", "BLUES",
"BIRTHDAY", "WEDDING", "FUNERAL", "PUNCHLINE", "BADDY", "CHASE", "BA_DING",
"WAWAWAWAA", "JUMP_UP", "JUMP_DOWN", "POWER_UP", "POWER_DOWN"]
# Pin Initialization (P13-P16)
btns = [pin13, pin14, pin15, pin16]
for p in btns: p.set_pull(p.PULL_UP)
set_volume(vol)
def get_rgb(h):
""" Simplified HSL to RGB logic """
h %= 360
pos = h // 60
f = (h % 60) / 60.0
v = 76 # 255 * 0.3 (Brightness coefficient)
up, down = int(v * f), int(v * (1 - f))
res = [(v, up, 0), (down, v, 0), (0, v, up), (0, down, v), (up, 0, v), (v, 0, down)]
return res[pos]
# State tracking (for debouncing)
last_states = [1] * 4
last_press_t = 0
while True:
curr_t = running_time()
# 1. Volume Control (Buttons A/B)
if button_a.was_pressed(): vol = min(250, vol + 10); set_volume(vol)
if button_b.was_pressed(): vol = max(20, vol - 10); set_volume(vol)
# 2. Joystick/Button Input Detection (with debouncing)
for i, p in enumerate(btns):
if v == 0 and last_states[i] == 1 and (curr_t - last_press_t > 50):
last_press_t = curr_t
if i == 3: mode = 0; sleep(500) # P16: Manual Mode
elif i == 1: mode = 1; sleep(500) # P14: Random Mode
elif i == 2: # P15: Next track / Random track
idx = random.randint(0, 19) if mode else (idx + 1) % 20
elif i == 0: # P13: Previous track / Random track
idx = random.randint(0, 19) if mode else (idx - 1) % 20
last_states[i] = v
# 3. Music Playback Logic
if idx != last_idx:
music.stop()
try:
music.play(getattr(music, melodies[idx]), wait=False)
last_idx = idx
except: pass
# 4. Lighting & Display Updates
hue = (hue + 1) % 360
strip.fill(get_rgb(hue))
strip.show()
# Show Mode Icon: "X" for Random, Arrow for Manual
display.show(Image("00000:99099:00900:99099:00000") if mode else Image.ARROW_E)
sleep(10)

Kurze Erklärung:
① Bibliotheken importieren, Konstanten konfigurieren und initialisieren.
Es importiert zuerst die microbit-Bibliothek, um auf die Kernfunktionen des Micro:bit zuzugreifen, music zum Abspielen eingebauter Musik, neopixel zur Steuerung des NeoPixel-LED-Streifens und random zur Generierung von Zufallszahlen.
Anschließend werden eine Reihe globaler Variablen und Konstanten definiert: vol setzt die anfängliche Lautstärke auf 50; mode steuert den Musikwiedergabemodus (0 für manuelle Auswahl, 1 für zufällige Wiedergabe); idx speichert den aktuellen Musikindex; verfolgt den vorherigen Wiedergabeindex, um doppelte Wiedergaben zu vermeiden; hue steuert die Farbe des NeoPixel-Streifens; strip initialisiert einen NeoPixel-Streifen, der mit pin8 von vier LEDs verbunden ist; und melodies listet alle MicroPython music-Titel auf.
Als Nächstes definiert die btns-Liste die vier externen Tasten-Pins von pin13 bis pin16 und weist ihnen in einer Schleife interne Pull-up-Widerstände (p.PULL_UP) zu – was zu High-Level-Pins führt, wenn die Tasten losgelassen werden, und Low-Level-Pins, wenn sie gedrückt werden.
set_volume (vol) setzt die Lautstärke auf ihren Standardwert.
# import related libraries
from microbit import *
import music, neopixel, random
# --- Configuration & Data ---
vol = 50
mode = 0 # 0: Manual, 1: Random
idx = 0
last_idx = -1
hue = 0
strip = neopixel.NeoPixel(pin8, 4)
melodies = ["DADADADUM", "ENTERTAINER", "PRELUDE", "ODE", "NYAN", "RINGTONE", "FUNK", "BLUES",
"BIRTHDAY", "WEDDING", "FUNERAL", "PUNCHLINE", "BADDY", "CHASE", "BA_DING",
"WAWAWAWAA", "JUMP_UP", "JUMP_DOWN", "POWER_UP", "POWER_DOWN"]
# Pin Initialization (P13-P16)
btns = [pin13, pin14, pin15, pin16]
for p in btns: p.set_pull(p.PULL_UP)
set_volume(vol)
② Farbkonvertierungsfunktion und Stabilisierungsvariable.
get_rgb(h) ist eine vereinfachte HSL-zu-RGB-Farbkonvertierungsfunktion (Farbton, Sättigung, Helligkeit). Sie akzeptiert einen Farbtonwert h (0–359) und konvertiert ihn in ein RGB-Triplett. Die Helligkeit v ist auf 76 festgelegt (ungefähr 255 × 0,3, entsprechend dem BRIGHTNESS-Koeffizienten). Diese Funktion erleichtert die Erzeugung von Regenbogenfarben basierend auf dem Farbtonwert.
Die last_states-Liste speichert die vorherigen Zustände der vier Tasten, die anfänglich alle auf 1 (High-Level für nicht gedrückt) gesetzt sind. last_press_t zeichnet die Zeit des letzten Tastendrucks auf. Zusammen implementieren diese Variablen eine Software-Entprellung, um mehrere Erkennungen eines einzelnen Tastendrucks zu verhindern.
def get_rgb(h):
""" Simplified HSL to RGB logic """
h %= 360
pos = h // 60
f = (h % 60) / 60.0
v = 76 # 255 * 0.3 (Brightness coefficient)
up, down = int(v * f), int(v * (1 - f))
res = [(v, up, 0), (down, v, 0), (0, v, up), (0, down, v), (up, 0, v), (v, 0, down)]
return res[pos]
# State tracking (for debouncing)
last_states = [1] * 4
last_press_t = 0
③ Hauptschleife: Lautstärkeregelung.
Es gibt eine Endlosschleife (while True), die die aktuelle Laufzeit curr_t abruft. Dann verarbeitet sie die Tasten A und B auf dem Micro:bit-Board:
Wenn
button_agedrückt wird (button_a.was_pressed()), erhöht sich die Lautstärkevolum 10, überschreitet aber nicht 250.set_volume(vol)wird anschließend aufgerufen, um die Systemlautstärke zu aktualisieren.Wenn
button_bgedrückt wird (button_b.was_pressed()), verringert sichvolum 10, bleibt aber nicht unter 20.set_volume(vol)wird anschließend aufgerufen, um die Systemlautstärke zu aktualisieren.
was_pressed() gibt nur einmal True zurück, wenn die Taste von einem nicht gedrückten in einen gedrückten Zustand übergeht, was eine inhärente Entprellung bietet.
while True:
curr_t = running_time()
# 1. Volume Control (Buttons A/B)
if button_a.was_pressed(): vol = min(250, vol + 10); set_volume(vol)
if button_b.was_pressed(): vol = max(20, vol - 10); set_volume(vol)
④ Hauptschleife: Tasten-Eingabeerkennung und Moduswechsel.
Es durchläuft die vier externen Tasten (pin13 bis pin16) in der btns-Liste und erkennt deren gedrückte Zustände. Die Taste wird nur dann reagiert, wenn sie von High (nicht gedrückt) auf Low (gedrückt) wechselt und seit dem letzten gültigen Tastendruck mehr als 50 Millisekunden vergangen sind.
Wenn
pin16gedrückt wird (i == 3), wirdmode= 0 (manueller Modus) und pausiert für 500 ms.Wenn
pin14gedrückt wird (i == 1), wirdmode= 1 (Zufallsmodus) und pausiert für 500 ms.Wenn
pin15gedrückt wird (i == 2), wird der Musikindexidxentsprechend dem aktuellen Muster aktualisiert: Im Zufallsmodus wird eine Musik zufällig ausgewählt; im manuellen Modus wird die nächste Musik abgespielt.Wenn
pin13gedrückt wird (i == 0), wird der Musikindexidxentsprechend dem aktuellen Muster aktualisiert: Im Zufallsmodus wird eine Musik zufällig ausgewählt; im manuellen Modus wird die vorherige Musik abgespielt.
Am Ende jeder Schleife aktualisiert last_states[i] = v den aktuellen Status der Taste zur Vorbereitung auf die nächste Stabilisierungsprüfung.
# 2. Joystick/Button Input Detection (with debouncing)
for i, p in enumerate(btns):
v = p.read_digital()
if v == 0 and last_states[i] == 1 and (curr_t - last_press_t > 50):
last_press_t = curr_t
if i == 3: mode = 0; sleep(500) # P16: Manual Mode
elif i == 1: mode = 1; sleep(500) # P14: Random Mode
elif i == 2: # P15: Next track / Random track
idx = random.randint(0, 19) if mode else (idx + 1) % 20
elif i == 0: # P13: Previous track / Random track
idx = random.randint(0, 19) if mode else (idx - 1) % 20
last_states[i] = v
⑤ Hauptschleife: Musikwiedergabelogik.
Es steuert die Wiedergabe der Musik, indem es überprüft, ob der aktuelle Musikindex idx sich vom letzten last_idx unterscheidet. Wenn ja, muss die Musik gewechselt werden:
music.stop()stoppt die aktuell spielende Musik.music.play(getattr(music, melodies[idx]), wait=False)versucht, eine neue Musik abzuspielen.getattr(music, melodies[idx])ruft dynamisch die Musikdaten des entsprechenden Namens inmusicab, undwait=Falsestellt sicher, dass die Musikwiedergabe die Hauptschleife nicht blockiert.Wenn die Wiedergabe erfolgreich ist, aktualisieren Sie
last_idx = idx.try...exceptfängt potenzielle Fehler ab; zum Beispiel könnten ungültige Musiktitel in dermelodies-Liste vorhanden sein.
# 3. Music Playback Logic
if idx != last_idx:
music.stop()
try:
music.play(getattr(music, melodies[idx]), wait=False)
last_idx = idx
except: pass
⑥ Hauptschleife: Licht- und Display-Updates.
Hier ist ein Update der Farbe des NeoPixel-Streifens und der Anzeige der Micro:bit-LED-Matrix:
hue = (hue + 1) % 360erhöhthuekontinuierlich, um es zwischen 0 und 359 zu zyklisieren, für ein Regenbogen-Verlaufslicht.strip.fill(get_rgb(hue))verwendetget_rgb, um eine Farbe basierend auf dem aktuellenhuezu erzeugen und den gesamten NeoPixel-Streifen mit dieser Farbe zu füllen.strip.show()sendet die aktualisierte Farbe zur Anzeige an den NeoPixel-Streifen.display.show(...)zeigt die Anzeige je nach aktuellemmodean.mode= 1 (zufällig): zeigt ein benutzerdefiniertes „X“;mode= 0 (manuell), zeigt einen Pfeil nach rechts (Image.ARROW_E).
Dann führt sleep(10) eine kurze Verzögerung für eine geeignete Ausführungsgeschwindigkeit, eine geringere CPU-Last und einen flüssigeren Effekt ein.
# 4. Lighting & Display Updates
hue = (hue + 1) % 360
strip.fill(get_rgb(hue))
strip.show()
# Show Mode Icon: "X" for Random, Arrow for Manual
display.show(Image("00000:99099:00900:99099:00000") if mode else Image.ARROW_E)
sleep(10)
5.2.4.5 Testergebnis

Nach dem Brennen des Codes stecken Sie das micro:bit-Board in den Steckplatz des Gamepads (Batterien eingelegt) und schalten Sie den Schalter auf „ON“.
Nach dem Einschalten befindet es sich standardmäßig im sequentiellen Modus und spielt das Lied unter N.O. „0“ ab. Wenn es beendet ist, können Sie C für das letzte Lied oder E für das nächste drücken.
Drücken Sie F, um in den Zufallsmodus zu wechseln. Und Sie können D drücken, um zum sequentiellen Modus zurückzukehren. Im F-Modus wird ein zufälliger Titel aus diesen 20 abgespielt, wenn Sie C/E drücken. Nach Beendigung stoppt es.
Die RGB-Lichter atmen immer vom Einschalten an. In der Zwischenzeit zeigt die micro:bit-LED-Matrix im sequentiellen Modus „
“ und im Zufallsmodus „
“ an.
Für die Lautstärke drücken Sie A zum Erhöhen und B zum Verringern.

Tipp: Wenn das Board nicht reagiert, drücken Sie bitte die Reset-Taste auf der Rückseite des micro:bit-Boards.



