Raspberry Pi Pico W(受信側)のプログラム。
Picoでは、PWM(パルス幅変調)を使って擬似的に音を鳴らすのが一般的です。
import network, socket
from machine import Pin, PWM
import time
# Wi-Fi接続情報
ssid = 'あなたのSSID'
password = 'あなたのパスワード'
# Wi-Fi接続の初期化
sta_if = network.WLAN(network.STA_IF)
sta_if.active(True)
# IPアドレスの固定設定
# 1つ目の192.168.XX.XXの部分には、Pico Wで使用するIPアドレス
# 2つ目の192.168.XX.XXの部分には、Wi-FiルーターのIPアドレス
sta_if.ifconfig(('192.168.XX.XX', '255.255.255.0', '192.168.XX.XX', '8.8.8.8'))
# Wi-Fiに接続
sta_if.connect(ssid, password)
# Wi-Fi接続が確立するまで待機
while not sta_if.isconnected():
time.sleep(0.1)
# ソケットの準備
# ここではポート8080をリッスン(受信待機)するように設定
addr = socket.getaddrinfo(sta_if.ifconfig()[0], 8080)[0][-1]
s = socket.socket()
s.bind(addr)
s.listen(1)
# ブザーをPWM制御で鳴らす準備
buzzer = PWM(Pin(16)) # GPIO16に接続したブザー
# 音階周波数の定義
REST= 0
G3,Ab3,A3,Bb3,B3 = 196,208,220,233,247
C4, Db4, D4, Eb4, E4, F4, Gb4, G4, Ab4, A4, Bb4, B4 = 262, 277, 294, 311, 330, 349, 370, 392, 415, 440, 466, 494
C5, Db5, D5, Eb5, E5, F5, Gb5, G5, Ab5, A5, Bb5, B5 = 523, 554, 587, 622, 659, 698, 740, 784, 831, 880, 932, 988
C6, Db6, D6, Eb6, E6, F6, Gb6, G6, Ab6, A6, Bb6, B6 =1047,1109,1175,1245,1319,1397,1480,1568,1661,1760,1865,1976
# 音を鳴らす関数
def tone(frequency, duration):
if frequency == REST:
# 休符の場合は音を鳴らさずに待機
time.sleep(duration)
return
buzzer.freq(frequency) # 周波数を設定
buzzer.duty_u16(30000) # デューティ比を設定(音を鳴らす)
time.sleep(duration) # 指定時間鳴らす
buzzer.duty_u16(0) # 音を止める
time.sleep(0.002) # 少し間を空ける
# 勇者のテーマを再生する関数
def yusya():
BPM = 208 # 曲のテンポ
BEAT = 60 / BPM # 1拍の長さ(秒)
# メロディ(音階と長さの組み合わせ)
melody = [
# イントロ部分
[C5, BEAT/2], [D5, BEAT/2], [E5, BEAT/2], [C5, BEAT/2],
[C5, BEAT/2], [D5, BEAT/2], [E5, BEAT/2], [C5, BEAT/2],
# メインメロディ
[G4, BEAT], [C5, BEAT], [E5, BEAT], [G5, BEAT],
[A5, BEAT], [G5, BEAT], [E5, BEAT], [C5, BEAT],
[A4, BEAT], [C5, BEAT], [E5, BEAT], [G5, BEAT],
[F5, BEAT], [E5, BEAT], [C5, BEAT], [A4, BEAT],
# サビ
[F4, BEAT], [A4, BEAT], [C5, BEAT], [F5, BEAT],
[E5, BEAT], [D5, BEAT], [C5, BEAT], [A4, BEAT],
[G4, BEAT], [B4, BEAT], [D5, BEAT], [G5, BEAT],
[F5, BEAT], [E5, BEAT], [C5, BEAT], [G4, BEAT],
# エンディング
[C5, BEAT*2], [D5, BEAT*2], [E5, BEAT*2],
[C5, BEAT*2], [G4, BEAT*2], [C5, BEAT*2], [REST, BEAT]
]
# メロディを順番に再生
for m in melody:
tone(m[0], m[1])
# 接続待機
print('Waiting for CALL...')
while True:
# クライアントからの接続を受け付ける
cl, addr = s.accept()
print('Connected from', addr)
# 受信データを取得
data = cl.recv(1024)
print('Received:', data)
# "CALL"というデータが届いたらメロディ再生
if data == b'CALL':
yusya()
# クライアントとの接続を閉じる
cl.close()
PC(送信側)のプログラムです。
# main.py
import socket
import time
# 接続先のIPアドレスとポート番号
target_ip = '192.168.XX.XX' # 受信側(Pico Wなど)のIPアドレスに書き換えてください
target_port = 8080 # 受信側プログラムで待ち受けているポート番号
print("Enterキーを押すと'CALL'を送信します。終了はCtrl+Cで。")
try:
while True:
# ユーザーの入力待ち(Enterキーで送信)
key = input("Enterを押して送信> ")
if key == "":
try:
# ソケット通信の準備
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# 受信側へ接続
s.connect((target_ip, target_port))
# 文字列 "CALL" を送信
s.send(b'CALL')
# ソケットを閉じる
s.close()
print("送信完了!")
except Exception as e:
# 送信に失敗した場合のエラーメッセージ
print("送信失敗:", e)
# ちょっとだけ待機(CPU負荷を減らす)
time.sleep(0.1)
except KeyboardInterrupt:
# Ctrl+Cでプログラムを終了するときのメッセージ
print("\n終了します。")
参考にしたサイト

【IoT工作】Raspberry Pi Pico Wでワイヤレス呼び鈴を作ろう!
Pico Wとブレッドボードでワイヤレス呼び鈴を自作!配線写真・MicroPythonコードを丸ごと掲載し、初心者でも30分で完成する手順を解説しています。
PC(送信側)のプログラムです。送信側に音楽のデータを持たせました
Raspberry Pi Pico W(受信側)のプログラム。
import network, socket
import ujson as json
from machine import Pin, PWM
import time
# Wi-Fi接続情報
ssid = 'あなたのSSID'
password = 'あなたのパスワード'
# Wi-Fi初期化
sta_if = network.WLAN(network.STA_IF)
sta_if.active(True)
sta_if.ifconfig(('192.168.XX.XX', '255.255.255.0', '192.168.XX.XX', '8.8.8.8'))
sta_if.connect(ssid, password)
while not sta_if.isconnected():
time.sleep(0.1)
print('✅ Wi-Fi接続完了:', sta_if.ifconfig())
# 音階→周波数の辞書
NOTE_FREQ = {
"REST":0,
"G3":196, "Ab3":208, "A3":220, "Bb3":233, "B3":247,
"C4":262, "Db4":277, "D4":294, "Eb4":311, "E4":330, "F4":349, "Gb4":370, "G4":392, "Ab4":415, "A4":440, "Bb4":466, "B4":494,
"C5":523, "Db5":554, "D5":587, "Eb5":622, "E5":659, "F5":698, "Gb5":740, "G5":784, "Ab5":831, "A5":880, "Bb5":932, "B5":988,
"C6":1047,"Db6":1109,"D6":1175,"Eb6":1245,"E6":1319,"F6":1397,"Gb6":1480,"G6":1568,"Ab6":1661,"A6":1760,"Bb6":1865,"B6":1976
}
# PWMブザー設定
buzzer = PWM(Pin(16))
def play_note(note, duration):
freq = NOTE_FREQ.get(note, 0)
if freq == 0:
time.sleep(duration)
else:
buzzer.freq(freq)
buzzer.duty_u16(3000)
time.sleep(duration)
buzzer.duty_u16(0)
time.sleep(0.02)
# サーバー待機
addr = socket.getaddrinfo(sta_if.ifconfig()[0], 8080)[0][-1]
s = socket.socket()
s.bind(addr)
s.listen(1)
print('🎵 メロディサーバー待機中...')
while True:
cl, addr = s.accept()
print('🎶 接続:', addr)
# 受信データ(長い曲でも受信できるようにループで集める!)
data = b''
while True:
chunk = cl.recv(1024)
if not chunk:
break
data += chunk
print('🎼 受信完了! データサイズ:', len(data))
# JSONパースして再生
try:
melody = json.loads(data)
for note, duration in melody:
play_note(note, duration)
except Exception as e:
print('⚠️ エラー:', e)
cl.close()
PC(送信側)のプログラムです。送信側に音楽のデータを持たせました
import socket
import json
# BPMからBEATを計算
BPM = 208
BEAT = 60 / BPM
melody = [
["C6", BEAT/2],["Bb5", BEAT/2],["C6", BEAT/2],["Bb5", BEAT/2],["C6", BEAT/2],["Bb5", BEAT/2],["C6", BEAT/2],["D6", BEAT/2],["REST", BEAT/2],["G5", BEAT*3/4],["REST", BEAT/4],
["C5", BEAT/2],["D5", BEAT/2],["G5", BEAT/2],["Bb5", BEAT/2],["A5", BEAT/2],["REST", BEAT/2],["F5", BEAT*3/4],["REST", BEAT/4],
["Bb4", BEAT/2],["C5", BEAT/2],["Bb4", BEAT/2],["C5", BEAT/2],["D5", BEAT],
["C5", BEAT/2],["D5", BEAT/2],["C5", BEAT/2],["D5", BEAT/2],["G5", BEAT/2],["F5", BEAT/2],["C5", BEAT],["Bb4", BEAT/2],["Bb4", BEAT],
["G4", BEAT],["A4", BEAT],["Bb4", BEAT],["C5", BEAT],["D5", BEAT],["Eb5", BEAT],["Gb5", BEAT],["G5", BEAT],["A5", BEAT],["Bb5", BEAT],["C6", BEAT],["F5", BEAT],["Eb6", BEAT],["Eb6", BEAT*2],["D6", BEAT],
["C6", BEAT/2],["Bb5", BEAT/2],["C6", BEAT/2],["D6", BEAT/2],["REST", BEAT/2],["G5", BEAT*3/4],["REST", BEAT/4],
["C5", BEAT/2],["D5", BEAT/2],["G5", BEAT/2],["Bb5", BEAT/2],["A5", BEAT/2],["REST", BEAT/2],["F5", BEAT*3/4],["REST", BEAT/4],
["Bb4", BEAT/2],["C5", BEAT/2],["Bb4", BEAT/2],["C5", BEAT/2],["D5", BEAT],
["C5", BEAT/2],["D5", BEAT/2],["G5", BEAT/2],["F5", BEAT/2],["Bb4", BEAT/2],["Bb4", BEAT/2],["C5", BEAT],["Bb4", BEAT/2],["Bb4", BEAT],
["G4", BEAT],["A4", BEAT],["Bb4", BEAT],["C5", BEAT],["D5", BEAT],["Eb5", BEAT],["F5", BEAT],["G5", BEAT],["A5", BEAT],["Bb5", BEAT],["A5", BEAT*2],
["D5", BEAT],["D5", BEAT/2],["D5", BEAT/2],["D6", BEAT/2],["A5", BEAT],["A5", BEAT],["G5", BEAT/2],["G5", BEAT],["REST", BEAT]
]
# JSON文字列にしてバイト列に変換
data = json.dumps(melody).encode()
# 送信先のIPとポート
target_ip = '192.168.XX.XX' # Pico Wの固定IPアドレス
target_port = 8080
try:
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((target_ip, target_port))
s.sendall(data) # sendallを使うのがベスト!
s.close()
print("🎶 メロディ送信完了!")
except Exception as e:
print("送信失敗:", e)
コメント