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+

Kepler Kit

Alternativ können Sie die Teile auch einzeln über die untenstehenden Links erwerben.

SN

KOMPONENTE

ANZAHL

LINK

1

Raspberry Pi Pico W

1

BUY

2

Micro-USB-Kabel

1

3

Steckbrett

1

BUY

4

Jumperkabel

Mehrere

BUY

5

Transistor

1(S8050)

BUY

6

Widerstand

1(1KΩ)

BUY

7

Passiver Summer

1

BUY

8

Li-Po-Lademodul

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.

../_images/6.mqtt_sub_bb.png

3. Code ausführen

  1. Laden Sie die Datei play_music.py aus dem Pfad kepler-kit-main/iot auf das Raspberry Pi Pico W hoch.

    ../_images/mqtt-A-1.png
  2. Öffnen Sie die Datei 6_mqtt_subscribe_music.py im Pfad kepler-kit-main/iot und klicken Sie auf die Schaltfläche Aktuelles Skript ausführen oder drücken Sie F5, um es auszuführen.

    ../_images/6_cloud_player.png

    Bemerkung

    Bevor Sie den Code ausführen, stellen Sie sicher, dass Sie die Skripte do_connect.py und secrets.py auf Ihrem Pico W haben. Wenn nicht, beziehen Sie sich bitte auf 1. Zugang zum Netzwerk, um sie zu erstellen.

  3. Ö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.

    Bemerkung

    In play_music.py sind nokia, starwars, nevergonnagiveyouup, gameofthrone, songofstorms, zeldatheme, harrypotter enthalten.

    ../_images/mqtt-5.png
  4. 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