6. Cloud-Player mit @MQTT¶
Es wird empfohlen, zunächst das Projekt 5. Cloud-Rufsystem mit @MQTT abzuschließen, um einige Module zu installieren und die Konfiguration der HiveMQ-Plattform vorzunehmen.
In diesem Projekt wird das Pico W als Abonnent fungieren und den Songtitel unter dem entsprechenden Topic empfangen. Falls der Songtitel bereits im Code hinterlegt ist, wird Pico W den Summer den Song spielen lassen.
1. Benötigte Komponenten
Für dieses Projekt benötigen wir die folgenden Komponenten.
Ein vollständiges Kit zu kaufen ist definitiv praktisch, hier ist der Link:
Bezeichnung |
ARTIKEL IM KIT |
LINK |
---|---|---|
Kepler-Kit |
450+ |
Alternativ können Sie die Teile auch einzeln über die untenstehenden Links erwerben.
SN |
KOMPONENTE |
ANZAHL |
LINK |
---|---|---|---|
1 |
1 |
||
2 |
Micro-USB-Kabel |
1 |
|
3 |
1 |
||
4 |
Mehrere |
||
5 |
1(S8050) |
||
6 |
1(1KΩ) |
||
7 |
Passiver Summer |
1 |
|
8 |
1 |
||
9 |
18650-Batterie |
1 |
|
10 |
Batteriehalter |
1 |
2. Schaltkreis aufbauen
Im Kit sind zwei Summer enthalten, wir verwenden einen passiven Summer (einen mit freiliegender Leiterplatte auf der Rückseite). Für den Betrieb des Summers ist ein Transistor erforderlich, hier verwenden wir S8050.
Warnung
Stellen Sie sicher, dass Ihr Li-Po-Ladegerät wie im Diagramm gezeigt angeschlossen ist. Andernfalls könnte ein Kurzschluss sowohl Ihre Batterie als auch die Schaltung beschädigen.
3. Code ausführen
Laden Sie die Datei
play_music.py
aus dem Pfadkepler-kit-main/iot
auf das Raspberry Pi Pico W hoch.Öffnen Sie die Datei
6_mqtt_subscribe_music.py
im Pfadkepler-kit-main/iot
und klicken Sie auf die Schaltfläche Aktuelles Skript ausführen oder drücken Sie F5, um es auszuführen.Bemerkung
Bevor Sie den Code ausführen, stellen Sie sicher, dass Sie die Skripte
do_connect.py
undsecrets.py
auf Ihrem Pico W haben. Wenn nicht, beziehen Sie sich bitte auf 1. Zugang zum Netzwerk, um sie zu erstellen.Öffnen Sie HiveMQ Web Client in Ihrem Browser, geben Sie das Topic als
SunFounder MQTT Music
ein und den Songtitel als Nachricht. Nach dem Klicken auf die Veröffentlichen-Schaltfläche wird der am Pico W angeschlossene Summer den entsprechenden Song abspielen.Wenn Sie möchten, dass dieses Skript beim Hochfahren ausgeführt wird, können Sie es auf dem Raspberry Pi Pico W als
main.py
speichern.
Wie funktioniert es?
Um es einfacher zu gestalten, haben wir den MQTT-Code vom Rest des Codes separiert. Daraus resultiert der folgende Code, der die grundlegendste Funktionalität der MQTT-Abonnements an drei Stellen implementiert.
import time
from umqtt.simple import MQTTClient
from do_connect import *
do_connect()
mqtt_server = 'broker.hivemq.com'
client_id = 'Jimmy'
# to subscribe the message
topic = b'SunFounder MQTT Music'
def callback(topic, message):
print("New message on topic {}".format(topic.decode('utf-8')))
message = message.decode('utf-8')
print(message)
try:
client = MQTTClient(client_id, mqtt_server, keepalive=60)
client.set_callback(callback)
client.connect()
print('Connected to %s MQTT Broker'%(mqtt_server))
except OSError as e:
print('Failed to connect to MQTT Broker. Reconnecting...')
time.sleep(5)
machine.reset()
while True:
client.subscribe(topic)
time.sleep(1)
Beim Verbindungsaufbau mit dem MQTT-Broker rufen wir die Funktion client.set_callback(callback)
auf, die als Rückruffunktion für die empfangenen Abonnement-Nachrichten dient.
try:
client = MQTTClient(client_id, mqtt_server, keepalive=60)
client.set_callback(callback)
client.connect()
print('Connected to %s MQTT Broker'%(mqtt_server))
except OSError as e:
print('Failed to connect to MQTT Broker. Reconnecting...')
time.sleep(5)
machine.reset()
Als nächstes kommt die Rückruffunktion, die die Nachricht aus dem abonnierten Thema ausgibt.
MQTT ist ein binärbasiertes Protokoll, bei dem die Steuerelemente binäre Bytes und keine Textzeichenfolgen sind. Daher müssen diese Nachrichten mit message.decode('utf-8')
dekodiert werden.
def callback(topic, message):
print("New message on topic {}".format(topic.decode('utf-8')))
message = message.decode('utf-8')
print(message)
Verwenden Sie eine While True
-Schleife, um regelmäßig Nachrichten unter diesem Thema zu erhalten.
while True:
client.subscribe(topic)
time.sleep(1)
Als nächstes wird Musik abgespielt. Diese Funktion befindet sich im Skript play_music.py
, das aus drei Hauptteilen besteht.
Tone
: Simuliert einen spezifischen Ton basierend auf der Grundfrequenz Piano key frequencies, der zum Abspielen verwendet wird.NOTE_B0 = 31 NOTE_C1 = 33 ... NOTE_DS8 = 4978 REST = 0
Score
: Bearbeiten Sie die Musik in ein für das Programm nutzbares Format. Diese Partituren stammen von Robson Coutos kostenloser Weitergabe, Sie können auch Ihre Lieblingsmusik im folgenden Format hinzufügen.# notes of the moledy followed by the duration. # a 4 means a quarter note, 8 an eighteenth , 16 sixteenth, so on # !!negative numbers are used to represent dotted notes, # so -4 means a dotted quarter note, that is, a quarter plus an eighteenth!! song = { "nokia":[NOTE_E5, 8, NOTE_D5, 8, NOTE_FS4, 4, NOTE_GS4, 4, NOTE_CS5, 8, NOTE_B4, 8, NOTE_D4, 4, NOTE_E4, 4, NOTE_B4, 8, NOTE_A4, 8, NOTE_CS4, 4, NOTE_E4, 4, NOTE_A4, 2], "starwars":[,,,], "nevergonnagiveyouup":[,,,], "gameofthrone":[,,,], "songofstorms":[,,,], "zeldatheme":[,,,], "harrypotter":[,,,], }
Play
: Dieser Teil ist im Grunde genommen das gleiche wie 3.2 Eigener Ton, aber leicht optimiert, um zur obigen Partitur zu passen.import time import machine # change this to make the song slower or faster tempo = 220 # this calculates the duration of a whole note in ms wholenote = (60000 * 4) / tempo def tone(pin,frequency,duration): if frequency is 0: pass else: pin.freq(frequency) pin.duty_u16(30000) time.sleep_ms(duration) pin.duty_u16(0) def noTone(pin): tone(pin,0,100) def play(pin,melody): # iterate over the notes of the melody. # Remember, the array is twice the number of notes (notes + durations) for thisNote in range(0,len(melody),2): # calculates the duration of each note divider = melody[thisNote+1] if divider > 0: noteDuration = wholenote/divider elif divider < 0: noteDuration = wholenote/-(divider) noteDuration *= 1.5 # we only play the note for 90% of the duration, leaving 10% as a pause tone(pin,melody[thisNote],int(noteDuration*0.9)) # Wait for the specief duration before playing the next note. time.sleep_ms(int(noteDuration)) # stop the waveform generation before the next note. noTone(pin)
Zurück zur Hauptfunktion und lassen Sie MQTT die Musikwiedergabe auslösen.
In der Rückruffunktion überprüfen Sie, ob die gesendete Nachricht der Name eines enthaltenen Liedes ist.
Falls ja, weisen Sie den Liednamen der Variable melody
zu und setzen play_flag
auf True
.
def callback(topic, message):
print("New message on topic {}".format(topic.decode('utf-8')))
message = message.decode('utf-8')
print(message)
if message in song.keys():
global melody,play_flag
melody = song[message]
play_flag = True
In der Hauptschleife wird, wenn play_flag
auf True
gesetzt ist, melody
abgespielt.
while True:
client.subscribe(topic)
time.sleep(1)
if play_flag is True:
play(buzzer,melody)
play_flag = False