6. @MQTTを使ったクラウドプレイヤー

このプロジェクトを始める前に、 5. @MQTTを使用したクラウド呼び出しシステム プロジェクトを先に完了させて、いくつかのモジュールのインストールとHiveMQプラットフォームの設定を完了することをお勧めします。

このプロジェクトでは、Pico Wは購読者として動作し、トピックの下で曲名を受信します。 曲名がコード内に既に存在する場合、Pico Wはブザーでその曲を演奏します。

1. 必要なコンポーネント

このプロジェクトでは、以下のコンポーネントが必要です。

こちらのリンクで一式を購入すると便利です:

名前

このキットに含まれるアイテム

リンク

ケプラーキット

450+

Kepler Kit

以下のリンクから個別に購入することもできます。

SN

コンポーネント

数量

リンク

1

Raspberry Pi Pico W

1

BUY

2

マイクロUSBケーブル

1

3

ブレッドボード

1

BUY

4

ジャンパーワイヤー

数本

BUY

5

トランジスタ

1(S8050)

BUY

6

抵抗器

1(1KΩ)

BUY

7

受動型 ブザー

1

BUY

8

Li-po充電モジュール

1

9

18650バッテリー

1

10

バッテリーホルダー

1

2. 回路を作成する

キットには2つのブザーが含まれていますが、ここでは受動ブザー(裏側に露出したPCBがあるもの)を使用します。このブザーはトランジスタが必要です。ここではS8050を使用します。

警告

ダイアグラムに示されているように、Li-poチャージャーモジュールを接続してください。そうしないと、ショートしてバッテリーや回路が損傷する可能性があります。

../_images/6.mqtt_sub_bb.png

3. コードを実行する

  1. kepler-kit-main/iot のパスで play_music.py ファイルをRaspberry Pi Pico Wにアップロードします。

    ../_images/mqtt-A-1.png
  2. kepler-kit-main/iot のパスで 6_mqtt_subscribe_music.py ファイルを開き、 現在のスクリプトを実行 ボタンをクリックするか、F5を押して実行します。

    ../_images/6_cloud_player.png

    注釈

    コードを実行する前に、Pico Wに do_connect.py および secrets.py スクリプトが存在することを確認してください。ない場合は、 1. ネットワークへのアクセス を参照して作成してください。

  3. ブラウザで HiveMQ Web Client を開き、「トピック」欄に SunFounder MQTT Musicメッセージ 欄に曲名を入力します。 Publish ボタンをクリックすると、Pico Wに接続されたブザーが対応する曲を演奏します。

    注釈

    play_music.pyには nokia , starwars , nevergonnagiveyouup , gameofthrone , songofstorms , zeldatheme , harrypotter が含まれています。

    ../_images/mqtt-5.png
  4. このスクリプトを起動可能にしたい場合、Raspberry Pi Pico Wに main.py として保存できます。

どうやって動作するのか?

理解しやすくするために、MQTTのコードは他の部分から分離されています。 その結果、MQTTの購読に関する最も基本的な機能を3か所で実装する以下のコードが得られます。

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)

MQTTブローカーに接続する際、 client.set_callback(callback) 関数を呼び出して、受信した購読メッセージのコールバックとして機能させます。

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

次に、フェッチされたトピックからのメッセージを出力するコールバック関数です。 MQTTはバイナリベースのプロトコルであり、制御要素もバイナリバイトです。したがって、これらのメッセージは 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)

While True ループを使用して、このトピックに定期的にメッセージを取得します。

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

次に、音楽が演奏されます。この関数は play_music.py スクリプトに配置され、主に3つの部分で構成されています。

  • Tone : 基礎となる Piano key frequencies に基づいて特定の音をシミュレートします。

    NOTE_B0 =  31
    NOTE_C1 =  33
    ...
    NOTE_DS8 = 4978
    REST =      0
    
  • Score : プログラムが使用できる形式に楽曲を編集します。これらの楽譜は Robson Coutoの無料共有 からです。

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 : この部分は基本的に 3.2 カスタムトーン と同じですが、上記の楽譜に適合するようにわずかに最適化されています。

import time
import machine

tempo = 220

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):
    for thisNote in range(0,len(melody),2):
        divider = melody[thisNote+1]
        if divider > 0:
            noteDuration = wholenote/divider
        elif divider < 0:
            noteDuration = wholenote/-(divider)
            noteDuration *= 1.5

        tone(pin,melody[thisNote],int(noteDuration*0.9))

        time.sleep_ms(int(noteDuration))

        noTone(pin)

メイン関数に戻って、MQTTが音楽の再生をトリガーするようにします。 コールバック関数で、送信されたメッセージが含まれている曲の名前であるかどうかを判断します。 そうであれば、曲名を変数 melody に割り当て、 play_flagTrue に設定します。

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

メインループでは、 play_flagTrue であれば、 melody を演奏します。

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