内容
以前実装した方法ではソフトウェアPWMを使用しているため、雑音の入った音色が出力されます。調査したところ、ハードウェアPWMを使用することで改善できました。ラズパイの設定変更とライブラリのインストール、ソースコードの修正をします。
ハードウェアPWMを設定する手順
ラズパイの設定変更と再起動
ラズパイの設定ファイルを追記し再起動することで、ハードウェアPWMを有効にします。
sudo vim /boot/firmware/config.txt
/boot/firmware/config.txt
dtoverlay=pwm-2chan
この設定を追加することにより、GPIO18、19にそれぞれPWMのチャンネル0、1が割り当てられます。
- PWM Channel0: GPIO18
- PWM Channel1: GPIO19
※上記の代わりに以下の設定とすることで、ハードウェアPWMを使用するPINをGPIO12、13へ変更できます。
- PWM Channel0: GPIO12
- PWM Channel1: GPIO13
/boot/firmware/config.txt
dtoverlay=pwm-2chan,pin=12,func=4,pin2=13,func2=4
ラズパイを再起動することで、設定が有効になります。
sudo reboot
ライブラリのインストール
ハードウェアPWMをPythonから操作するライブラリを導入します。今回も--break-system-packages
としてインストールしてしまいます。
pip install rpi-hardware-pwm --break-system-packages
ソースコードの修正
@@ -6 +6 @@
-import RPi.GPIO as GPIO
+from rpi_hardware_pwm import HardwarePWM
@@ -25,3 +24,0 @@
-# GPIO XX の XXの数値でPIN番号を指定する
-GPIO.setmode(GPIO.BCM)
-
@@ -29,2 +25,0 @@
-GPIO.setup(13, GPIO.OUT, initial=GPIO.LOW)
-p = GPIO.PWM(13, 1)
@@ -40 +34,0 @@
- p.start(50)
@@ -42 +36,3 @@
- p.ChangeFrequency(freq)
+ # Rpi 1,2,3,4 は chip=0, Rpi 5は chip=2
+ pwm = HardwarePWM(pwm_channel=1, hz=freq, chip=0)
+ pwm.start(50)
@@ -45 +41 @@
- p.stop()
+ pwm.stop()
ソースコード全体は以下のようになります。
import math
import sys
import time
import mido
from rpi_hardware_pwm import HardwarePWM
def midi_number_to_note_number(midi_number: int):
"""MIDIのnote numberを鍵盤番号へ変換します"""
# 鍵盤番号: 1:ラ0(A0) = MIDIのnote number: 21
return midi_number - 20
def onkai(n):
"""鍵盤番号nに応じた周波数[Hz]を返します"""
# 鍵盤番号は、ラ0(A0)を1とした連番
# n=1(ラ0(A0)) -> 27.500Hz
# n=2(ラ#0(A#0)) -> 29.135...Hz
# n=3(シ0(B0)) -> 30.867...Hz
# ...
return 27.500 * math.pow(math.pow(2, 1 / 12), n)
# GPIO 13 = PWM 1 の33番PINに圧電スピーカーの+端子を接続する
# 圧電スピーカーの-端子はGroundならどこでもよい
# 今回は34番PINに接続する
for msg in mido.MidiFile(sys.argv[1]):
time.sleep(msg.time)
if msg.type == "note_on":
# 圧電スピーカー
freq = onkai(midi_number_to_note_number(msg.note))
# Rpi 1,2,3,4 は chip=0, Rpi 5は chip=2
pwm = HardwarePWM(pwm_channel=1, hz=freq, chip=0)
pwm.start(50)
print(f"note_on {freq} {msg}")
if msg.type == "note_off":
pwm.stop()
print(f"note_off {msg}")
以下のコマンドで実行します。
python3 midi.py sample.mid
動作環境
- Raspberry Pi 4 Model B Rev 1.5
- Raspberry Pi OS Lite (64-bit)(Debian GNU/Linux 12.2.0 (bookworm))
- Python 3.11.2
- mido 1.3.3
- rpi-hardware-pwm 0.2.2