操作ボタンを増やしたら使い易くなる?
短押し/長押しを含めると、機能的には以前の2種類から6種類に増える事になるので、これらを活用できれば、かなり使い勝手を上げる事が出来そうです。
ボタン操作でやりたい事はこんな感じ
①音量アップ
②音量ダウン
③次のトラック
④前のトラック
⑤プレイ/ポーズ(トグル切り替え)
⑥シャットダウン
今回の「Pi函(pi-bako)」に搭載しているアンプHATには基板上に音量調整ノブやスイッチがありませんのでスピーカー本体側の「音量調整」ボタンは必須です。
あとは、トラック(曲あるいは局)のアップダウン、プレイ/ポーズもあれば便利ですね。
これを3つのボタンで実現させる方法を考えます。
ボタン別で考えると下図のようになります。
ボタン別で考えると下図のようになります。
まずはボタンの配線から
ボタン1をGPIO23、ボタン2をGPIO24、ボタン3をGPIO27に割り当てます。
ボタン1に内蔵されたLEDも一緒に制御したいのでGPIO17を割り当てておきます。
以下の説明について。
当方、プログラミングについてはほとんど素人です。
ネットにある関連記事を参考に、適当にプログラムのコードを弄ってます。
結果オーライで運よく上手くいっているだけの可能性が大きいです。
ですので、もし参考にされる場合は、あくまで自己責任でお願いします。
---------------------------------------------------------------------------------------------------------------
手順は今までの記事にもありますので、割愛しますが、いつものようにTera Termを起動して、図のような画面が出てくればOKです。この画面でPCからVolumio2にアクセスします。
次はプログラムの変更ですが…
---------------------------------------------------------------------------------------------------------------以下の説明について。
当方、プログラミングについてはほとんど素人です。
ネットにある関連記事を参考に、適当にプログラムのコードを弄ってます。
結果オーライで運よく上手くいっているだけの可能性が大きいです。
ですので、もし参考にされる場合は、あくまで自己責任でお願いします。
---------------------------------------------------------------------------------------------------------------
ラズパイとPCをsshで接続する
Volumio2の中の特定のファイルの記述(コード)を一部変更する必要がありますので、まずは変更ファイルにsshを使ってアクセス可能にします。手順は今までの記事にもありますので、割愛しますが、いつものようにTera Termを起動して、図のような画面が出てくればOKです。この画面でPCからVolumio2にアクセスします。
先にシステム環境を整える
Volumio2のシステムには「RPi.GPIO」がインストールされていないようです。
なので、先にインストールします。
「RPi.GPIO」はGPIOをプログラムでコントロールする場合に必要なライブラリーです。
ssh画面で「sudo apt-get update」と入力して、Enterキーを押します。
これはアプリケーション情報の更新なのですが、かなり時間がかかりますが終了まで待ちましょう。
一番下の行が下図のような文字列になればOKです。
次に「sudo apt-get install python-rpi.gpio」と入力して、Enterキーを押します。
これで「RPi.GPIO」がインストールされます。
こちらも多少時間がかかりますが、同様に終了まで待ちましょう。
以前に「RPi.GPIO」をインストール済みであれば、この操作は割愛出来ます。
プログラムファイルを作成する
プログラムファイルは、ボタンの動作を記述したファイルです。
新規で「button_led.py」というファイルが/home/volumioの中に作成されます。
(最初のみ「[sudo] password for volumio:」とパスワードを聞いてきますので、「volumio」と入力して、Enterします。)
上図のメモ帳のような画面になりますので、ここに以下の文字列をコピーしてペーストします。
------------------------------------------------------------------------------------
------------------------------------------------------------------------------------
#!/usr/bin/python
# coding:utf-8
import time
import RPi.GPIO as GPIO
import subprocess
import os
GPIO.setmode(GPIO.BCM)
GPIO.setup(23,GPIO.IN,pull_up_down=GPIO.PUD_UP)
GPIO.setup(24,GPIO.IN,pull_up_down=GPIO.PUD_UP)
GPIO.setup(27,GPIO.IN,pull_up_down=GPIO.PUD_UP)
GPIO.setup(17,GPIO.OUT)
GPIO.output(17, 1)
while True:
sw_counter = 0
if GPIO.input(23) == 0:
while True:
sw_status = GPIO.input(23)
if sw_status == 0:
sw_counter = sw_counter + 1
if sw_counter >= 20:
os.system("sudo shutdown -h now")
time.sleep(1)
break
else:
subprocess.call('volumio toggle', shell=True)
break
time.sleep(0.1)
elif GPIO.input(24) == 0:
while True:
sw_status = GPIO.input(24)
if sw_status == 0:
sw_counter = sw_counter + 1
if sw_counter >= 20:
subprocess.call('volumio next', shell=True)
time.sleep(1)
break
else:
subprocess.call('volumio volume plus', shell=True)
break
time.sleep(0.1)
elif GPIO.input(27) == 0:
while True:
sw_status = GPIO.input(27)
if sw_status == 0:
sw_counter = sw_counter + 1
if sw_counter >= 20:
subprocess.call('volumio previous', shell=True)
time.sleep(1)
break
else:
subprocess.call('volumio volume minus', shell=True)
break
time.sleep(0.1)
------------------------------------------------------------------------------------そのまま保存します。
キーボードの「Ctrl」キーを押しながら「x」キーを押すと、保存するか聞いてきますので、「y」キーを押します。
ファイル名をbutton_led.py(元のまま)にするか聞いてきますので、「Enter」キーを押して保存完了です。
キーボードの「Ctrl」キーを押しながら「x」キーを押すと、保存するか聞いてきますので、「y」キーを押します。
ファイル名をbutton_led.py(元のまま)にするか聞いてきますので、「Enter」キーを押して保存完了です。
ちなみに、それぞれのGPIO番号の下の例えば「subprocess.call('volumio next', shell=True)」の「next」のところを変更すると違う動作のボタンに変更できます。
変更できる機能の種類はVolumioの公式ページで確認できます。
サービスファイルを作成する
サービスファイルは、ラズパイが起動する時に先ほど作成したプログラムファイルを自動的に読み込むようにするためのファイルです。
同様にメモ帳画面に以下の文字列をコピーしてペーストします。
------------------------------------------------------------------------------------
[Unit]
Description=do something
[Service]
ExecStart=/usr/bin/python /home/volumio/button_led.py
[Install]
WantedBy=multi-user.target
------------------------------------------------------------------------------------
これも同様に保存します。
ssh画面でまず「sudo chmod 755 /home/volumio/button_led.py」と入力して、Enterキーを押します。
次に同様に「sudo chmod 755 /lib/systemd/system/button_led.service」と入力して、Enterキーを押します。
この操作は2つの新規作成のファイルにラズパイの中で使用する際の権限を付与するものです。
さらにサービスファイル「button_led.service」は、ラズパイの起動時に紐づけされたプログラムファイルを「読み込む」か「読み込まない」かを指定できますので、「読み込む」設定に指定します。
それぞれのファイルを使えるようにする
ファイルは作成しただけでは動かない場合が多いです。(特に新規で作成した場合)ssh画面でまず「sudo chmod 755 /home/volumio/button_led.py」と入力して、Enterキーを押します。
次に同様に「sudo chmod 755 /lib/systemd/system/button_led.service」と入力して、Enterキーを押します。
この操作は2つの新規作成のファイルにラズパイの中で使用する際の権限を付与するものです。
さらにサービスファイル「button_led.service」は、ラズパイの起動時に紐づけされたプログラムファイルを「読み込む」か「読み込まない」かを指定できますので、「読み込む」設定に指定します。
ssh画面で「sudo systemctl enable button_led.service」と入力して、Enterキーを押します。
(もし、「読み込まない」設定にしたい場合は、「sudo systemctl disable button_led.service」です。)
以上でプログラムの変更は完了です。
実際の動作は?
Volumio2を再起動して動作を確認します。①完全に起動した事(LED消灯→点灯)を確認した後、ボタン1を押すとプレイリストの再生が始まります。
さらに押すと、再生が止まってポーズ状態になります。
②ボタン2を押すと音量が大きくなり、ボタン3を押すと音量が小さくなります。
③ボタン2を長押し(2~3秒)するとプレイリストのトラックが次に進み、ボタン3を長押し(2~3秒)すると現在のトラックが先頭から再生し直されます。
(どうやらVolumio2の「前のトラック」機能は「トラックの先頭に戻る」機能のようです。)
④ボタン1を長押し(2~3秒)すると、シャットダウンが始まります。(LED点灯→消灯)
とりあえずは上手く動作しているようです。
おまけ(プログラムファイルの動作について)
※以下の説明は素人の勝手な書き散らしなので、あえて読む必要ないかもしれません…
今回のプログラムファイルですが、複数ボタンを一度に制御するようなプログラムの記述が、ネット上で探しましたがあまりなく、かなり怪しいですが試行錯誤して自分で作ってみました。
以前まではネット上の記事にあるプログラムの記述をコピーして、必要最低限の変更でそのまま使っていましたので、実際システム上でどのように動作しているとか、個々の記述の意味とかはあまり深く考えていませんでした。
今回、自分でも調べてみて、自分なりの解釈ですが、なんとなく理解できたので、書き残したいと思います。
改めて、今回のプログラムファイルはこんな感じです。
------------------------------------------------------------------------------------
17行目「while True:」より前の記述は、初期設定や「RPi.GPIO」の設定なので、置いておいて。
#!/usr/bin/python
# coding:utf-8
import time
import RPi.GPIO as GPIO
import subprocess
import os
GPIO.setmode(GPIO.BCM)
GPIO.setup(23,GPIO.IN,pull_up_down=GPIO.PUD_UP)
GPIO.setup(24,GPIO.IN,pull_up_down=GPIO.PUD_UP)
GPIO.setup(27,GPIO.IN,pull_up_down=GPIO.PUD_UP)
GPIO.setup(17,GPIO.OUT)
GPIO.output(17, 1)
while True:
sw_counter = 0
if GPIO.input(23) == 0:
while True:
sw_status = GPIO.input(23)
if sw_status == 0:
sw_counter = sw_counter + 1
if sw_counter >= 20:
os.system("sudo shutdown -h now")
time.sleep(1)
break
else:
subprocess.call('volumio toggle', shell=True)
break
time.sleep(0.1)
elif GPIO.input(24) == 0:
while True:
sw_status = GPIO.input(24)
if sw_status == 0:
sw_counter = sw_counter + 1
if sw_counter >= 20:
subprocess.call('volumio next', shell=True)
time.sleep(1)
break
else:
subprocess.call('volumio volume plus', shell=True)
break
time.sleep(0.1)
elif GPIO.input(27) == 0:
while True:
sw_status = GPIO.input(27)
if sw_status == 0:
sw_counter = sw_counter + 1
if sw_counter >= 20:
subprocess.call('volumio previous', shell=True)
time.sleep(1)
break
else:
subprocess.call('volumio volume minus', shell=True)
break
time.sleep(0.1)
------------------------------------------------------------------------------------17行目「while True:」より前の記述は、初期設定や「RPi.GPIO」の設定なので、置いておいて。
ちなみに、LEDの点灯の処理は、以下の2行でやってます。
-----------------------------
GPIO.setup(17,GPIO.OUT)
GPIO.output(17, 1)
-----------------------------
まずは17行目「while True:」の意味ですが、これはこれ以降の動作をずっと繰り返すという意味です。
この場合繰り返すのはその「while True:」の一段下の位置にある記述のみです。
(記述が段々になっているのは、それを分かりやすくするためだったんですね。)
なので、17行目「while True:」では以下の命令を繰り返します。(一段下のみ表記)
------------------------------------------------------------------------------------
while True:
①sw_counter = 0
③elif GPIO.input(24) == 0:
④elif GPIO.input(27) == 0:
------------------------------------------------------------------------------------
この部分の動きは、以下の繰り返しです。
①「sw_counter」という名前の変数に「0」の値を書き込む。
②GPIO23の値が「0」かどうか確認する。「0」でないならスルーして下に進む。
③GPIO24の値が「0」かどうか確認する。「0」でないならスルーして下に進む。
④GPIO27の値が「0」かどうか確認する。「0」でないならスルーして①に戻る。
簡単に言うと、3つのボタンのどれかが押されるのを待っている状態です。
ここでいう「GPIO.input(23)」つまりGPIO23の値が「0」というのは、ボタン1(GPIO23)が押されていない状態が「1」で、押されている状態が「0」になるという理解でOKです。
ここでもし、ボタン1(GPIO23)が押された場合に変化が起きます。
②GPIO23の値が「0」かどうか確認する→「0」だった場合です。
ここで流れは「 if GPIO.input(23) == 0:」が「正しい」となり、その一段下の位置にある記述に進みます。
つまり22行目の「while True:」です。今度は以下の命令を繰り返します。
------------------------------------------------------------------------------------
while True:
①sw_status = GPIO.input(23)
②if sw_status == 0:
③else:
④time.sleep(0.1)
------------------------------------------------------------------------------------
この部分の動きは、以下の繰り返しです。
①「sw_status」という名前の変数に「GPIO.input(23)」の値を書き込む。
②「sw_status」の値が「0」かどうか確認する。「0」でないならスルーして下に進む。
もし「0」だったら、その一段下の位置にある記述に進む。
③②の確認内容が違っていた場合、つまり「sw_status」の値「1」だった場合、その一段下の位置にある記述に進む。
④動作を0.1秒休んで、①に戻る。
ここで実際の動きを想定してみると、先ほどボタン1(GPIO23)が押されたため、この流れに入ってきたので、「GPIO.input(23)」の値は「0」、つまり「sw_status」も「0」ですので②が「正しい」となり、その一段下の位置にある記述に進みます。
------------------------------------------------------------------------------------
①sw_counter = sw_counter + 1
②if sw_counter >= 20:
------------------------------------------------------------------------------------
この部分の動きは、以下です。だだし繰り返さないで、そのまま22行目の「while True:」の
繰り返しに戻ります。
①「sw_counter」という名前の変数に1を加えます。「0」→「1」になる。
「sw_counter」というのは17行目「while True:」の所で「0」にしたものです。
②「sw_counter」の値が「20」以上かどうか確認する。「20」以上でないならスルーして
進み、この流れから出てしまう。
さて、この後以下の流れに戻るのですが、ここでボタン1(GPIO23)の状態によって分岐が起こります。
------------------------------------------------------------------------------------
sw_status = GPIO.input(23)
①if sw_status == 0:
②else:
time.sleep(0.1)
------------------------------------------------------------------------------------
①ボタン1(GPIO23)が押されたまま、つまり「sw_status」の値が今度も「0」の場合はもう一度、以下の流れに入ります。
------------------------------------------------------------------------------------
①sw_counter = sw_counter + 1
②if sw_counter >= 20:
------------------------------------------------------------------------------------
すると、また「sw_counter」に1が加えられて、「1」→「2」になります。
つまり、ボタン1(GPIO23)を押している限り「sw_counter」の値は増えてい行きます。
この値が増える時間は「time.sleep(0.1)」の記述により、0.1秒で1づつですので、2秒後に「sw_counter」が「20」以上になります。すると②が「正しい」となり、その一段下の位置にある記述に進みます。
------------------------------------------------------------------------------------
os.system("sudo shutdown -h now")
time.sleep(1)
break
------------------------------------------------------------------------------------
ここでやっと実際のVolumio2への命令が出てきます。
ここの動作は「シャットダウン」を実行して、1秒休んで、この流れから出る、です。
(1秒休むのは、誤動作防止のためです。)
どこに戻るかというと、17行目「while True:」の以下の繰り返しで、次のボタンが押されるまでこの動作を繰り返します。
------------------------------------------------------------------------------------
while True:
sw_counter = 0
elif GPIO.input(24) == 0:
elif GPIO.input(27) == 0:
------------------------------------------------------------------------------------
(実際はボタン1(GPIO23)の場合は「シャットダウン」してしまうので戻りません…。
ボタン2(GPIO24)やボタン3(GPIO27)の場合は、戻って、次のボタンが押せます。)
以上が、ボタンの長押しの場合の流れです。
では、ボタンの短押しの流れはどうかと言うと、下の流れの中で、2秒に達しない、つまり「sw_counter」が「20」未満の間に、ボタン1(GPIO23)を離して、押されていない状態になった場合です。
------------------------------------------------------------------------------------
sw_status = GPIO.input(23)
①if sw_status == 0:
②else:
time.sleep(0.1)
------------------------------------------------------------------------------------
当然、GPIO.input(23)、つまり「sw_status」が「0」でなくなりますので、①をスルー、②else:が「正しい」になりますので、その一段下の位置にある記述に進み、実際のVolumio2への命令を実行します。
------------------------------------------------------------------------------------
subprocess.call('volumio toggle', shell=True)
break
------------------------------------------------------------------------------------
ここの動作は「toggle(プレイ/ポーズ)」を実行して、この流れから出る、です。
戻り先は17行目「while True:」の繰り返しで、やはり次のボタンが押されるまで以下の動作を繰り返します。
------------------------------------------------------------------------------------
while True:
sw_counter = 0
elif GPIO.input(24) == 0:
elif GPIO.input(27) == 0:
------------------------------------------------------------------------------------
以上がボタン1(GPIO23)の短押し/長押しの場合の動作の流れです。
ボタン2(GPIO24)、ボタン3(GPIO27)の場合も基本的にボタン1(GPIO23)と同様の
流れになります。
コメント
コメントを投稿