2019/03/22

100均Bluetoothボタンをラズパイに活用

どうも、ビッグウェーブに乗り遅れたクラゲです。
100円ショップのダイソーで売っていた「Bluetoothリモートシャッター」を活用して、ラズパイの音量アップと音量ダウンを無線操作できるようにします。

動画で流れている音楽はラズパイに接続されている白いスピーカーから流れている音です。
「Bluetoothリモートシャッター」のハックは1年以上前に流行ったネタではありますが、クラゲなりの改善と工夫を盛り込みました。

商品の確認

スマホに専用アプリをインストールしてBluetooth接続すれば、ワイヤレスでカメラ撮影が出来るというものです。iOS用のボタンとandroid用のボタンの2つを実装することで、1種類でどちらのスマホにも対応しているようです。
300円ですのでご注意ください。お試し用のコイン電池が入っているのですぐに使用できます。

もし、スマホで試した後にラズパイに繋ぐ場合など、別の機器にペアリングする場合は、先にペアリングした機器からデバイスの削除を行う必要があります。

ラズパイとペアリング&接続

event番号確認

接続を行う前に、現状のInputDevice event番号を確認しておきます。これは後のプログラミング時に必要になる情報です。以下のコマンドを打ちます

ls /dev/input

クラゲの場合は以下のように表示が出ました。マウスやキーボードなど、その他接続されている機器によって表示結果が異なります。event番号を確認してください。クラゲの例では0,1,2です。この情報は後で使います。

by-id by-path event0 event1 event2 mice mouse0

Bluetooth接続

マウスを使ってGUIでBluetoothの接続を行うことができますが、この方法だとダメでした。ですのでコマンド打ち込みによる接続を行います。

リモートシャッターをなるべくラズパイの近くに持ってきた状態で電源をONにして下さい

以下のコマンドを打ち込みます

bluetoothctl

以下のような表示が出て対話モードが始まります

[bluetooth]#

次のコマンドをそのまま打ちこんでスキャンを開始します

scan on

スキャンに成功すると以下のような表示が出ます。
YY:YY:YY:YY:YY:YY と XX:XX:XX:XX:XX:XX はMACアドレスでデバイス毎に異なります

Discovery started
[CHG] Controller YY:YY:YY:YY:YY:YY Discovering: yes
[NEW] Device XX:XX:XX:XX:XX:XX AB Shutter3
[bluetooth]#

AB Shutter3のMACアドレスを指定してペアリングを行います

pair XX:XX:XX:XX:XX:XX

Pairing successfulなど色々表示出て以下のような表示になります

[AB Shutter3 ]#

AB Shutter3のMACアドレスを指定して接続を行います

connect XX:XX:XX:XX:XX:XX

成功すると以下の表示が出ます

Connection successful

最後に再接続できるようにします。これを行うとシャッターボタンの電源をOFF/ONしても自動的に繋がるようになります

trust XX:XX:XX:XX:XX:XX

成功すると以下の表示が出ます

[CHG] Device YY:YY:YY:YY:YY:YY Trusted: yes
Changing YY:YY:YY:YY:YY:YY trust succeeded

ちなみにその他のコマンドとして、"devices", "info", "show" コマンドなどを使うとBT情報を見ることも可能です。最後にexitコマンドで終了します

exit

これで設定はOK

ボリューム制御が出来ているか確認

スピーカーアイコンをクリックしてボリューム表示させた状態で、シャッターボタンのボタンを押します。ボリュームが変化していることを確認しましょう

このままだと、どちらのボタンを押してもボリュームアップにしかならないので、プログラミングでandroidボタンが押されたときはボリュームダウンするようなスクリプトを書きます。
また、押したことが分かるように効果音も出すようにしたいと思います。

うまくいかない場合

ペアリング&接続は出来ているけど、ボリューム制御ができない場合があります。クラゲも何度かその状態を経験しています。その場合は、切断や削除などを行い、何度かペアリング&接続を試してみて下さい

切断

disconnect  XX:XX:XX:XX:XX:XX

削除

remove  XX:XX:XX:XX:XX:XX

それでもダメな場合は、Bluetoothのオフ/オンを試してみましょう

Bluetoothオフ

power off

Bluetoothオン

power on

GUIでも出来ます

クラゲの接続事例

ペアリング&接続後、シャッターボタンの電源OFF

GUIでTurn off Bluetooth

GUIでTrun On Bluetooth

シャッターボタンの電源ON

ボタン連打でボリュームアップ出来るようになった

ちなみに、一度ボリュームアップが出来れば、その後はラズパイのリブート/シャットダウン、シャッターボタンの電源オフを行っても問題なく接続出来ています。

無線ボリュームUP/DOWN対応プログラム

必要なモジュールインストール

キーイベントを取得するのに必要な "evdev" というモジュールをインストールします

sudo pip3 install evdev

MP3ファイルを再生させるのに必要な "mpg321" というモジュールをインストールします

sudo apt-get install mpg321

event番号再確認

再び、InputDevice event番号を確認します

ls /dev/input

今回新たに増えたevent番号がシャッターボタンの番号です。クラゲの場合はevent3が増えました。次のソースコードに使います

by-id by-path event0 event1 event2 event3 mice mouse0

ソースコード

evdev.InputDeviceの引数は各自のevent番号に修正してください
効果音ファイル(decision3.mp3)は各自の好みで用意してください

import evdev
import subprocess
import time
 
while True:
    try:
        # ls /dev/input でevent番号要確認 
        device = evdev.InputDevice('/dev/input/event3')
        print(device)
 
        for event in device.read_loop():
            if event.type == evdev.ecodes.EV_KEY:
                if event.value == 1# 0:KEYUP, 1:KEYDOWN 
                    print(event.code)
 
                    if event.code == evdev.ecodes.KEY_VOLUMEUP:
                        subprocess.Popen(['mpg321', 'decision3.mp3'])
 
                    if event.code == evdev.ecodes.KEY_ENTER:
                        subprocess.Popen(['amixer', 'sset', 'PCM', '10%-', '-M'])
    except:
        print('Retry...')
        time.sleep(1)

プログラム実行後、シャッターボタンを押すと、効果音再生と共にボリュームアップ/ダウンを行うことができます。うまく行かない場合は、何度か連打してみて下さい。そのうち効くようになります。
ボタンが効いた後は、連打せず、ゆっくりと押すようにしましょう!


ボリュームアップは普通に動いていると思いますが、ボリュームダウンの動きをよく見ると、一瞬上がってからすぐ下がるのが分かります。

ソースコードの解説

evdevモジュール

簡単に言うとキーイベントを取得し、キーが何であるかを判定しています。
詳細は後日、別のページを設けて説明予定です。

subprocessモジュール

簡単に言うと、Pythonプログラム上からLinuxコマンドを実行しています
詳細は後日、別のページを設けて説明予定です。

try~exceptの理由

例えば、シャッターボタンがスリープ中もしくは電源オフ中、ラズパイ起動直後にプログラム実行した場合などはシャッターボタンのevent番号を取得できません。try~exceptで未取得時は1秒スリープしてまたトライを繰り返します。このようにすることで確実に接続できるようにしています。

amixer

このプログラムに関係なく、シャッターボタンのどちらを押してもボリュームが上がります。
今回実現したい機能はiOSボタンではボリュームアップ、androidボタンではボリュームダウンです。
つまり、このプログラムでのボリューム制御はiOSボタン押下時はそのまま、androidボタン押下時はボリュームアップした値×2倍でボリュームダウンさせると良いことが分かります。
ボリュームアップ値は +5% です。つまり -10% でボリュームダウンさせれば良いことが分かります。
Linuxコマンドで書くと以下のようになります。ポイントはオプションで -M を付加してマップされた値を指定することです。

amixer sset PCM 10%- -M

subprocessで実行させる場合の記述は先程のソースコードの通りになります。

if elif ではなく if if にしている理由

iOSボタンを押すとキーコードとして "KEY_VOLUMEUP" が得られます。androidボタンを押すとキーコードとして "KEY_VOLUMEUP" と "KEY_ENTER" の両方が得られます。
今回は「どちらのボタンが押されても効果音を鳴らしたい」「androidボタンが押されたときだけボリュームを下げたい」という仕様なのでこのような分岐処理にしています

その他

中身の解析を行っている方がいました
https://japanese.engadget.com/2017/10/26/bluetooth/

解析状況を要約して表にすると以下の通りです。分解した中の基板にICが実装されています。

IC端子番号 信号入力時の送信キーコード 接続先
8pin KEY_ENTER, KEY_VOLUMEUP androidボタン
9pin KEY_VOLUMEUP iOSボタン
10pin KEY_VOLUMEDOWN 未接続

つまり、androidボタンが繋がっている "8pin" を "10pin" に繋ぎ変えることで以下のようにシンプルなキーコード割り当てになります

IC端子番号 信号入力時の送信キーコード 接続先
8pin KEY_ENTER, KEY_VOLUMEUP androidボタン
9pin KEY_VOLUMEUP iOSボタン
10pin KEY_VOLUMEDOWN androidボタン

ただし改造や動作については、難易度の高いハンダ付けや電波法の規制などもありますので、それらをクリアできる人のみお試しください

トラブルシューティング

クラゲも色々トラブったので、まとめておきます。ご参考まで。

参考にさせていただいたサイト

engadget日本版:ウェブ情報実験室
Qiita:Bluetoothシャットダウンボタンを作る

以上、「100均のBTリモコンをラズパイに活用」でした!