Nota

Ciao, benvenuto nella Community di appassionati di SunFounder Raspberry Pi, Arduino e ESP32 su Facebook! Approfondisci le tue conoscenze su Raspberry Pi, Arduino e ESP32 insieme ad altri appassionati.

Perché unirti?

  • Supporto esperto: Risolvi i problemi post-vendita e le sfide tecniche con l’aiuto della nostra community e del nostro team.

  • Impara e condividi: Scambia consigli e tutorial per migliorare le tue competenze.

  • Anteprime esclusive: Ottieni accesso anticipato agli annunci di nuovi prodotti e alle anteprime.

  • Sconti speciali: Approfitta di sconti esclusivi sui nostri prodotti più recenti.

  • Promozioni festive e giveaway: Partecipa a promozioni festive e concorsi a premi.

👉 Pronto a esplorare e creare con noi? Clicca su [Qui] e unisciti oggi stesso!

6. Lettore cloud con @MQTT

Si consiglia di eseguire prima il progetto 5. Sistema di chiamata in cloud con @MQTT per completare l’installazione di alcuni moduli e la configurazione della piattaforma HiveMQ.

In questo progetto, Pico W agirà come sottoscrittore e riceverà il nome della canzone sotto l’argomento specificato. Se il nome della canzone è già presente nel codice, Pico W farà suonare il brano al buzzer.

1. Componenti necessari

In questo progetto, abbiamo bisogno dei seguenti componenti.

È sicuramente conveniente acquistare un kit completo, ecco il link:

Nome

ELEMENTI IN QUESTO KIT

LINK

Kit Kepler

450+

Kepler Ultimate Kit

Puoi anche acquistarli separatamente dai link qui sotto.

SN

COMPONENTE

QUANTITÀ

LINK

1

Introduzione al Pico W

1

ACQUISTA

2

Cavo Micro USB

1

3

Breadboard

1

ACQUISTA

4

Cavi Jumper

Diverse

ACQUISTA

5

Transistor

1(S8050)

ACQUISTA

6

Resistenza

1(1KΩ)

ACQUISTA

7

Buzzer passivo Cicalino

1

ACQUISTA

8

Modulo Caricatore Li-po

1

9

Batteria 18650

1

10

Supporto batteria

1

2. Costruisci il circuito

Nel kit sono inclusi due buzzers, utilizziamo un buzzer passivo (quello con PCB esposto sul retro). Il buzzer necessita di un transistor per funzionare, qui usiamo S8050.

Avvertimento

Assicurati che il modulo caricabatterie Li-po sia collegato come mostrato nello schema. Altrimenti, un cortocircuito potrebbe danneggiare la batteria e il circuito.

../../_images/6.mqtt_sub_bb.png

3. Esegui il codice

  1. Carica il file play_music.py nel percorso kepler-kit-main/iot nel Raspberry Pi Pico W.

    ../../_images/mqtt-A-1.png
  2. Apri il file 6_mqtt_subscribe_music.py nel percorso kepler-kit-main/iot e clicca sul pulsante Esegui script corrente o premi F5 per eseguirlo.

    ../../_images/6_cloud_player.png

    Nota

    Prima di eseguire il codice, assicurati di avere gli script do_connect.py e secrets.py nel tuo Pico W, in caso contrario fai riferimento a 1. Accesso alla Rete per crearli.

  3. Apri HiveMQ Web Client nel tuo browser, inserisci il Topic come SunFounder MQTT Music, inserisci il nome della canzone come Messaggio. Dopo aver cliccato sul pulsante Publish, il buzzer collegato al Pico W riprodurrà la canzone corrispondente.

    Nota

    Incluse in play_music.py sono le canzoni nokia, starwars, nevergonnagiveyouup, gameofthrone, songofstorms, zeldatheme, harrypotter.

    ../../_images/mqtt-5.png
  4. Se desideri che questo script si avvii automaticamente, puoi salvarlo nel Raspberry Pi Pico W come main.py.

Come funziona?

Per facilitare la comprensione, abbiamo separato il codice MQTT dal resto. Di conseguenza, ottieni il seguente codice, che implementa le funzionalità di base delle sottoscrizioni MQTT in tre punti.

import time
from umqtt.simple import MQTTClient

from do_connect import *
do_connect()

mqtt_server = 'broker.hivemq.com'
client_id = 'Jimmy'

# sottoscrivi il messaggio
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)

Quando ci si connette al broker MQTT, chiamiamo la funzione client.set_callback(callback), che serve come callback per i messaggi di sottoscrizione ricevuti.

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()

Successivamente viene eseguita la funzione callback, che stampa il messaggio ricevuto dall’argomento sottoscritto. MQTT è un protocollo basato su byte binari e non su stringhe di testo, quindi questi messaggi devono essere decodificati utilizzando message.decode('utf-8').

def callback(topic, message):
    print("New message on topic {}".format(topic.decode('utf-8')))
    message = message.decode('utf-8')
    print(message)

Use a While True loop to get messages under this topic at regular intervals.

while True:
    client.subscribe(topic)
    time.sleep(1)

Successivamente, verrà riprodotta la musica. Questa funzione è inserita nello script play_music.py, che consiste in tre parti principali.

  • Tone: Simula un tono specifico basato sulla Piano key frequencies fondamentale, utilizzato per riprodurlo.

    NOTE_B0 =  31
    NOTE_C1 =  33
    ...
    NOTE_DS8 = 4978
    REST =      0
    
  • Score: Modifica la musica in un formato che il programma possa utilizzare. Questi spartiti provengono dalla condivisione gratuita di Robson Couto, puoi anche aggiungere la tua musica preferita nel seguente formato.

# 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: Questa parte è sostanzialmente la stessa di 3.2 Tono Personalizzato, ma leggermente ottimizzata per adattarsi allo spartito sopra.

import time
import machine

# cambia questo per rendere la canzone più lenta o più veloce
tempo = 220

# questo calcola la durata di una nota intera 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):

    # iterare sulle note della melodia.
    # Ricorda, l'array è il doppio del numero di note (note + durate)
    for thisNote in range(0,len(melody),2):
        # calcola la durata di ciascuna nota
        divider = melody[thisNote+1]
        if divider > 0:
            noteDuration = wholenote/divider
        elif divider < 0:
            noteDuration = wholenote/-(divider)
            noteDuration *= 1.5

        # suoniamo la nota solo per il 90% della durata, lasciando il 10% come pausa
        tone(pin,melody[thisNote],int(noteDuration*0.9))

        # Attendi la durata specificata prima di suonare la nota successiva.
        time.sleep_ms(int(noteDuration))

        # ferma la generazione d'onda prima della nota successiva.
        noTone(pin)

Torna alla funzione principale e lascia che MQTT attivi la riproduzione della musica. Nella funzione callback, determina se il messaggio inviato è il nome di una canzone inclusa. Se lo è, assegna il nome della canzone alla variabile melody e imposta play_flag su 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

Nel ciclo principale, se play_flag è True, suona melody.

while True:
    client.subscribe(topic)
    time.sleep(1)
    if play_flag is True:
        play(buzzer,melody)
        play_flag = False