まず,ロータリーエンコーダーをDIP化基板にハンダ付けして,それからこれを使って音量調整できるようにしました(フェーズ5I完了)。
フェーズ5I 詳細マニュアル
ロータリーエンコーダーで音量調整する
0. 今回の目標
今回追加する機能はこれです。
ロータリーエンコーダーを右に回す
↓
音量アップ
ロータリーエンコーダーを左に回す
↓
音量ダウン
今回は、エンコーダーの押し込みによるミュートは扱いません。
たなさんの手元のロータリーエンコーダーは3端子タイプなので、
A
C / GND / COM
B
の3本だけを使います。
1. 今回使うGPIO
フェーズ5Gでは、次の構成で進んでいる前提にします。
再生/一時停止ボタン:GPIO17
戻るボタン:GPIO27
次へボタン:GPIO22
棚選びボタン:GPIO23
再生モードボタン:GPIO5
棚LED:GPIO24
モードLED:GPIO6
mpv IPCソケット:
/tmp/tanaradio-mpv.sock
今回は、ロータリーエンコーダー用に次の2本を追加します。
エンコーダーA:GPIO20
エンコーダーB:GPIO21
エンコーダーC / COM:GND
物理ピンで言うと、Raspberry Piの40ピンヘッダーでは次の並びが使いやすいです。
GPIO20:物理ピン38
GND :物理ピン39
GPIO21:物理ピン40
ここが気持ちよく並んでいます。電子工作の神様が一瞬だけ優しい顔をしています。
gpiozeroの公式ドキュメントでも、ロータリーエンコーダーはA/BをGPIOへ、CつまりcommonをGNDへ接続する形で説明されています。
2. 配線する前にRaspberry Piを終了する
まず、現在動いている tanaradio_5g.py があれば Ctrl + C で止めます。
そのあと、Raspberry Piを終了します。
sudo shutdown -h now
緑LEDの点滅が落ち着き、完全に止まったら電源ケーブルを抜きます。
GPIO配線は、必ず電源を抜いてから行います。
特に今回はGPIOが増えるので、ここは慎重でよいです。急がない。ラジオは逃げません。
3. ロータリーエンコーダーを配線する
ロータリーエンコーダーの3端子を、次のようにつなぎます。
ロータリーエンコーダー A → GPIO20
ロータリーエンコーダー C → GND
ロータリーエンコーダー B → GPIO21
DIP化基板に A、C、B のような表記があれば、それに従います。
もし表記が分かりにくい場合は、中央の端子が C / COM / GND であることが多いです。ただし、ここは部品によって違う可能性もあります。基板に印字があるなら印字を優先してください。
重要なのはこれです。
ロータリーエンコーダーには 5V をつながない
3.3V も今回はつながない
C / COM は GND につなぐ
A と B を GPIO20 / GPIO21 につなぐ
4. 起動して作業フォルダへ移動する
配線が終わったら、Raspberry Piの電源を入れます。
起動したらターミナルを開きます。
cd ~/tanaradio5
確認します。
pwd
次のように表示されればOKです。
/home/tana/tanaradio5
5. 必要パッケージを確認する
念のため、gpiozero関係を入れておきます。
sudo apt update
sudo apt install -y python3-gpiozero python3-lgpio
すでに入っていれば、そのままで大丈夫です。
6. ロータリーエンコーダー単体テスト
まず、音量制御とは関係なく、エンコーダーを回したらPythonが反応するかだけ確認します。
nano test_encoder_5i.py
次を貼り付けます。
#!/usr/bin/env python3
from gpiozero import RotaryEncoder
from signal import pause
ENC_A_GPIO = 20
ENC_B_GPIO = 21
encoder = RotaryEncoder(
ENC_A_GPIO,
ENC_B_GPIO,
max_steps=0,
bounce_time=0.002
)
def rotated_clockwise():
print("右回し")
def rotated_counter_clockwise():
print("左回し")
encoder.when_rotated_clockwise = rotated_clockwise
encoder.when_rotated_counter_clockwise = rotated_counter_clockwise
print("ロータリーエンコーダーのテストを開始します。")
print("つまみを左右に回してください。")
print("終了するには Ctrl+C を押してください。")
pause()
保存します。
Ctrl + O
Enter
Ctrl + X
実行できるようにします。
chmod +x test_encoder_5i.py
実行します。
./test_encoder_5i.py
つまみを右に回して、
右回し
左に回して、
左回し
と出れば成功です。
終了は、
Ctrl + C
です。
8. 5Gを動かしたまま音量制御テストをする
次に、tanaradio_5g.py はそのまま使い、別のテストプログラムからmpvへ音量命令を送ります。
mpvはIPCソケットで外部制御できます。mpvの公式マニュアルでも、外部プログラムから制御する場合は --input-ipc-server を使う方法が説明されています。 また、mpvの音量操作は add volume 5 / add volume -5 のようなコマンドで行えます。
まず、1つ目のターミナルで5Gを起動します。
cd ~/tanaradio5
./tanaradio_5g.py
音が出る状態にしておきます。
次に、別のターミナルを開いて、同じフォルダへ移動します。
cd ~/tanaradio5
音量テスト用ファイルを作ります。
nano test_volume_5i.py
次を貼り付けます。
#!/usr/bin/env python3
import json
import os
import socket
import time
from gpiozero import RotaryEncoder
from signal import pause
MPV_SOCKET = "/tmp/tanaradio-mpv.sock"
ENC_A_GPIO = 20
ENC_B_GPIO = 21
VOLUME_STEP = 5
MIN_VOLUME_INTERVAL = 0.04
last_volume_time = 0.0
encoder = RotaryEncoder(
ENC_A_GPIO,
ENC_B_GPIO,
max_steps=0,
bounce_time=0.002
)
def send_mpv_command(*command):
if not os.path.exists(MPV_SOCKET):
print("mpvのソケットが見つかりません。")
print("先に別ターミナルで ./tanaradio_5g.py を起動してください。")
return
try:
data = json.dumps({"command": list(command)}) + "\n"
with socket.socket(socket.AF_UNIX, socket.SOCK_STREAM) as client:
client.connect(MPV_SOCKET)
client.sendall(data.encode("utf-8"))
try:
response = client.recv(4096)
if response:
print(response.decode("utf-8").strip())
except Exception:
pass
except Exception as e:
print(f"mpvコマンド送信エラー: {e}")
def change_volume(delta):
global last_volume_time
now = time.monotonic()
if now - last_volume_time < MIN_VOLUME_INTERVAL:
return
last_volume_time = now
if delta > 0:
print("音量アップ")
else:
print("音量ダウン")
send_mpv_command("add", "volume", delta)
def volume_up():
change_volume(VOLUME_STEP)
def volume_down():
change_volume(-VOLUME_STEP)
encoder.when_rotated_clockwise = volume_up
encoder.when_rotated_counter_clockwise = volume_down
print("ロータリーエンコーダー音量テストを開始します。")
print("別ターミナルで tanaradio_5g.py が動いている必要があります。")
print("つまみを右に回すと音量アップ、左に回すと音量ダウンです。")
print("終了するには Ctrl+C を押してください。")
pause()
保存します。
Ctrl + O
Enter
Ctrl + X
実行できるようにします。
chmod +x test_volume_5i.py
実行します。
./test_volume_5i.py
5Gで音声を流したまま、つまみを回します。
右回し → 音量アップ
左回し → 音量ダウン
になれば、フェーズ5Iの核心部分は成功です。
9. 5Gコードを5Iとしてコピーする
ここから本体に統合します。
まず、5Gコードをコピーします。
cp tanaradio_5g.py tanaradio_5i.py
バックアップも作っておきます。
cp tanaradio_5g.py tanaradio_5g_backup.py
編集します。
nano tanaradio_5i.py
10. RotaryEncoder をimportに追加する
コードの上の方に、たぶん次のような行があります。
from gpiozero import Button, LED
これを次のようにします。
from gpiozero import Button, LED, RotaryEncoder
すでに RotaryEncoder が入っていたら、そのままでOKです。
11. GPIO設定を追加する
GPIO番号を定義している部分に、次を追加します。
ENC_A_GPIO = 20
ENC_B_GPIO = 21
VOLUME_STEP = 5
MIN_VOLUME_INTERVAL = 0.04
last_volume_time = 0.0
VOLUME_STEP = 5 は、1クリックごとに音量を5ずつ変える設定です。
大きすぎると感じたら、あとで次のように小さくできます。
VOLUME_STEP = 3
または、
VOLUME_STEP = 2
12. 音量変更関数を追加する
ボタンの処理関数が並んでいるあたりに、次を追加します。
def change_volume(delta):
global last_volume_time
now = time.monotonic()
if now - last_volume_time < MIN_VOLUME_INTERVAL:
return
last_volume_time = now
if delta > 0:
print(f"音量アップ +{delta}")
else:
print(f"音量ダウン {delta}")
send_mpv_command("add", "volume", delta)
def volume_up():
change_volume(VOLUME_STEP)
def volume_down():
change_volume(-VOLUME_STEP)
ここで使っている send_mpv_command() は、5Gですでに使っているmpv制御関数です。
もし5Gコード内で関数名が違っていて、たとえば、
send_command(...)
や、
mpv_command(...)
のような名前になっている場合は、この部分だけ5G側の関数名に合わせてください。
つまり、この行です。
send_mpv_command("add", "volume", delta)
ここを、5Gで使っている名前に合わせます。
13. エンコーダーを作成してイベントを登録する
ボタンを作っている場所を探します。
たとえば次のような場所です。
play_button = Button(...)
prev_button = Button(...)
next_button = Button(...)
shelf_button = Button(...)
mode_button = Button(...)
その近くに、次を追加します。
encoder = RotaryEncoder(
ENC_A_GPIO,
ENC_B_GPIO,
max_steps=0,
bounce_time=0.002
)
encoder.when_rotated_clockwise = volume_up
encoder.when_rotated_counter_clockwise = volume_down
もし5Gコードに setup_buttons() のような関数がある場合は、その関数の中に追加してください。
その場合、最後の return に encoder も含めておくと安全です。
例:
def setup_buttons():
play_button = Button(PLAY_GPIO, pull_up=True, bounce_time=0.05)
prev_button = Button(PREV_GPIO, pull_up=True, bounce_time=0.05)
next_button = Button(NEXT_GPIO, pull_up=True, bounce_time=0.05)
shelf_button = Button(SHELF_GPIO, pull_up=True, bounce_time=0.08)
mode_button = Button(MODE_GPIO, pull_up=True, bounce_time=0.08)
encoder = RotaryEncoder(
ENC_A_GPIO,
ENC_B_GPIO,
max_steps=0,
bounce_time=0.002
)
play_button.when_pressed = toggle_pause
prev_button.when_pressed = previous_episode
next_button.when_pressed = next_episode
shelf_button.when_pressed = change_shelf
mode_button.when_pressed = change_mode
encoder.when_rotated_clockwise = volume_up
encoder.when_rotated_counter_clockwise = volume_down
return [
play_button,
prev_button,
next_button,
shelf_button,
mode_button,
encoder,
]
すでにLEDも同じ関数内で作っている場合は、LEDもreturnに残してください。
大事なのは、encoder を作ったあと、プログラム終了まで消えないようにすることです。
Pythonでは、作った部品オブジェクトを変数として保持しておく必要があります。
14. time がimportされているか確認する
今回の change_volume() では time.monotonic() を使います。
コードの上の方に、
import time
があるか確認してください。
なければ追加します。
import time
15. 保存して実行する
保存します。
Ctrl + O
Enter
Ctrl + X
実行できるようにします。
chmod +x tanaradio_5i.py
5Gが動いている場合はいったん止めます。
Ctrl + C
5Iを実行します。
./tanaradio_5i.py
確認することは次の通りです。
再生/一時停止ボタンが効く
戻るボタンが効く
次へボタンが効く
棚選びボタンが効く
再生モードボタンが効く
棚LEDが点滅する
モードLEDが点滅する
ロータリーエンコーダー右回しで音量アップ
ロータリーエンコーダー左回しで音量ダウン
これができれば、フェーズ5I成功です。
フェーズ5Iの成功条件
次の3つができれば成功です。
1. test_encoder_5i.py で右回し/左回しが表示される
2. test_volume_5i.py で5G再生中の音量を変えられる
3. tanaradio_5i.py 単体で、5ボタン・2LED・音量つまみが全部動く
これで、TanaRadio Piはかなり「ラジオ」になります。
ボタンで番組の棚と時間順を選び、つまみで音量を調整する。ここまで来ると、もう単なるRaspberry Pi工作ではなく、手元の音声装置です。良いところまで来ています。
サマリー
TanaRadio Pi製作シリーズのフェーズ5Iでは、ロータリーエンコーダーを使った音量調節機能の実装に挑戦しました。まず、DIP化基板へのハンダ付け作業を行い、Raspberry PiのGPIOピンに配線。その後、Pythonスクリプトでエンコーダーの単体動作と、既存の5Gプログラムと連携した音量制御テストを実施し、成功を確認しました。最終的に、5Gコードに音量調節機能を統合した5Iプログラムを作成し、初期エラーを解決して、全てのボタンとLED、そしてロータリーエンコーダーによる音量調節が正常に機能することを確認しました。
コメント
このエピソードのトピック
すべてのトピック →それぞれのトピックから、ほかの番組の会話も探せます。
似ているエピソード
タイトル・AI要約・文字起こしの話題をもとにおすすめしています。
-
387 日記 | 押しボタンを5つに増やす
TanaRadio
共通する話題: TanaRadio Pi · TanaRadio · Raspberry Pi
TanaRadio Pi製作シリーズでは、押しボタンのタクトスイッチを2つ追加し、合計5つにする作業が行われました。まず基板にスイッチ...
-
389 日記 | 基板化を完了
TanaRadio
共通する話題: TanaRadio Pi · TanaRadio · Raspberry Pi
今回はTanaRadio Pi製作シリーズの最終部品であるロータリーエンコーダーの取り付けに挑戦しました。リード線やスズメッキ線を用...
-
361 日記 | TanaRadio Piの部品を追加注文
TanaRadio
共通する話題: TanaRadio Pi · TanaRadio · Raspberry Pi
Raspberry Piを使ったインターネットラジオ受信機「TanaRadio Pi」の製作プロジェクトは、フェーズ1を完了し、現在はフェーズ3の...
-
379 日記 | Raspberry Piをケースに入れる
TanaRadio
共通する話題: TanaRadio Pi · TanaRadio · Raspberry Pi
本エピソードでは、TanaRadio Pi製作シリーズのフェーズ5Jを進める前に、Raspberry Piをケースに収納する作業が行われました。こ...
-
376 日記 | 棚選択ボタンとLEDランプを追加
TanaRadio
共通する話題: TanaRadio Pi · TanaRadio · Raspberry Pi
TanaRadio Pi製作シリーズのフェーズ5Fでは、棚選びボタンとLED1の追加が行われました。まず、Raspberry Piの電源を切り、GPIO23...
-
RODECaster Pro2を使って低音をラジオっぽく調整してみた
ポッドキャスト機材庫
YouTube · Twitter · Amazon · RODECaster Pro 2
-
#52 ICD-LX31A
CafeP #a4w_Radio (旧a4wラヂオ)
東京通信工業の ICD-LX31A を入手したのでこれで録音テスト。
-
#59 同時録音聴き比べ
CafeP #a4w_Radio (旧a4wラヂオ)
Discord 経由の Audacity での録音とその出力を ICD-LX31A で録音したものの聴き比べ。
-
リコーダー166 from Radiotalk
しんじの番組
Radiotalk
-
TLM103をRODECaster Pro2につないだ時のDSP設定
ポッドキャスト機材庫
RODECaster Pro 2