ラズパイでラジコン(2):PS3コントローラとBluetooth接続

あたらしい投稿が以下にある
Raspberry Piとdualshock3接続(再び)

PS4に移行して、余ったdualshock3コントローラを、ラズパイに認識させる方法の備忘録。

ちなみに使用したbluetoothレシーバーは以下。

バッファロー
価格
¥ 2,581 (update 2017/7/27)
発売日
2012-09-05
ASIN
B0096FIF0C

Bluetooth関連ツールのインストール

まずは、Raspbianにbluetooth関連のドライバとツールをインストールする。

参考URL

> sudo apt install bluez bluez-hcidump libbluetooth-dev libusb-dev joystick libjack-jackd2-dev bluez-utils bluez-compat

ほかのブログを見ると、bluez-utilsbluez-compatもインストールすることになっているが、どうもRaspbian Jessieではbluezに含まれるコマンドに統合?されているようなので、apt installでは失敗する為、除外した。

bluetoothサービスを自動起動するように設定する

> sudo systemctl enable bluetooth.service
Synchronizing state for bluetooth.service with sysvinit using update-rc.d...
Executing /usr/sbin/update-rc.d bluetooth defaults
Executing /usr/sbin/update-rc.d bluetooth enable

一旦再起動する

> sudo reboot

ラズパイが起動した後、bluetoothレシーバーをUSB接続して、認識しているかを確認する。起動後に挿入するのが重要で、挿入した状態で起動しても、デーモンの起動順によっては認識しないので注意する。この場合、後でデーモンの起動順序を変更して、起動時に自動認識できるように調整する必要がある。

lsusbコマンドを実行すると、"Bluetooth Dongle"と記載されたデバイスが存在すればOK。

> lsusb
Bus 001 Device 006: ID 0a12:0001 Cambridge Silicon Radio, Ltd Bluetooth Dongle (HCI mode)
Bus 001 Device 004: ID 0a5c:bd1e Broadcom Corp. 
Bus 001 Device 003: ID 0424:ec00 Standard Microsystems Corp. SMSC9512/9514 Fast Ethernet Adapter
Bus 001 Device 002: ID 0424:9514 Standard Microsystems Corp. 
Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub

PS3コントローラー専用のドライバをインストール

githubで公開されているツールをダウンロードして、ラズパイでビルドする。

まずはペアリングするsixpairをダウンロード&コンパイルする。

> wget "https://help.ubuntu.com/community/Sixaxis?action=AttachFile&do=get&target=sixpair.c" -O sixpair.c
> gcc -o sixpair sixpair.c -lusb

USBケーブルでラズパイとdualshock3を有線接続した後、PSボタンを押してペアリングを開始する。

> lsusb
Bus 001 Device 006: ID 0a12:0001 Cambridge Silicon Radio, Ltd Bluetooth Dongle (HCI mode)
Bus 001 Device 004: ID 0a5c:bd1e Broadcom Corp. 
Bus 001 Device 007: ID 054c:0268 Sony Corp. Batoh Device / PlayStation 3 Controller
Bus 001 Device 003: ID 0424:ec00 Standard Microsystems Corp. SMSC9512/9514 Fast Ethernet Adapter
Bus 001 Device 002: ID 0424:9514 Standard Microsystems Corp. 
Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub

PlayStation 3 ControllerとUSBで認識されていることがわかる。
さきほどビルドしたツールを実行する。

> sudo ./sixpair
Current Bluetooth master: 00:1b:dc:xx:be:xx
Setting master bd_addr to 00:1b:dc:xx:be:xx 

つぎにdualshock3とやりとりするドライバとなるデーモンのソースをgithubからダウンロード&ビルドする。

> git clone https://github.com/falkTX/qtsixa.git
> cd qtsixa
> make
mkdir -p bins
g++ -O2 -Wall -Wl,-Bsymbolic-functions sixad-bin.cpp bluetooth.cpp shared.cpp textfile.cpp -o bins/sixad-bin `pkg-config --cflags --libs bluez` -lpthread -fpermissive
g++ -O2 -Wall -Wl,-Bsymbolic-functions sixad-sixaxis.cpp sixaxis.cpp shared.cpp uinput.cpp textfile.cpp -o bins/sixad-sixaxis -lpthread -lrt
g++ -O2 -Wall -Wl,-Bsymbolic-functions sixad-remote.cpp remote.cpp shared.cpp uinput.cpp textfile.cpp -o bins/sixad-remote -lrt
g++ -O2 -Wall -Wl,-Bsymbolic-functions sixad-raw.cpp sixaxis.cpp shared.cpp uinput.cpp textfile.cpp -o bins/sixad-raw
g++ -O2 -Wall -Wl,-Bsymbolic-functions sixad-3in1.cpp sixaxis.cpp shared.cpp uinput.cpp textfile.cpp -o bins/sixad-3in1

> sudo make install
install -d /etc/default/
install -d /etc/init.d/
install -d /etc/logrotate.d/
install -d /usr/bin/
install -d /usr/sbin/
install -d /var/lib/sixad/
install -d /var/lib/sixad/profiles/
install -m 644 sixad.default /etc/default/sixad
install -m 755 sixad.init /etc/init.d/sixad
install -m 644 sixad.log /etc/logrotate.d/sixad
install -m 755 sixad /usr/bin/
install -m 755 bins/sixad-bin /usr/sbin/
install -m 755 bins/sixad-sixaxis /usr/sbin/
install -m 755 bins/sixad-remote /usr/sbin/
install -m 755 bins/sixad-3in1 /usr/sbin/
install -m 755 bins/sixad-raw /usr/sbin/

ドライバの実行

sixadを起動してblutoothデバイスを監視させた後、dualshock3コントローラーのPSボタンを押下すると、しばらくして**Connected Sony ...**と出力されれば、成功である。

> sudo sixad -start &
[1] 4154
[ ok spi2:~/qtsixa/sixad $ [....] Starting bluetooth (via systemctl): bluetooth.service.
sixad-bin[4245]: started
sixad-bin[4245]: sixad started, press the PS button now
sixad-bin[3119]: Connected Sony Computer Entertainment Wireless Controller (00:21:4F:13:D3:08)

はまりどころ

もともとPS3に接続していた情報が残っていたのか、最後のsixadとの接続がうまくいかなかった。ずっと4つのLEDが高速点滅したまま反応がなかった。

ふと、リセットボタンがあることを思い出して、細い棒でリセットしたのちにPSボタンを押すと、あっさり接続に成功。

接続が完了すると、1つだけLEDが点灯する。これはPS3本体とペアリングしたときと動作は同じようだ。

接続完了後、デバイスファイルをトレースして、適当にコントローラーのボタンを押して、なにやら反応があればとりあえずOKである。

> sudo cat /dev/input/js0

H)H)H)H)H)H)H)H)HH)	H)
H)
  H)
H)H)H)H)H)H)?H)?H)?H)?H)?H)?H)?H)?H)H)?	H)?
H)?
   H)?
H)?H)?H)?H)?H)?H)?H)?H)?H)?H)?H)?H)?H)?R))
                                          \)\))
                                               ?)
                                                 ?))
                                                    d+

再起動後のdualshock3自動接続

上記の直後にラズパイをリブートすると、PS3のLEDランプが消えて切断される。その後、PSボタンを押してもペアリングできなかった。いろいろ調査したところ、以下のサイトで行っていた手順で自動接続できるようになった。

PlayStation 3 controller help sheet

ここのサイトを見ると、sixadを一切利用しておらず、ひょっとするとjessieぐらいから不要なのかもしれない。。。bluetoothctlで以下を実行する。

> bluetoothctl
[NEW] Device 38:C0:96:xx:xx:xx PlaySation 3 Controller
[bluetooth]# trust 38:C0:96:xx:xx:xx
[bluetooth]# exit

trustコマンドを使って、dualshock3コントローラーのMACアドレスを設定すると、reboot後にPSボタンを押すとペアリングされる。

sixadデーモンが起動中だと、bluetoothctlコマンドが入力を受け付けないので、sixadも結局のところ内部でbluetoothctlを実行しているのであれば、sixpairだけ用意すれば、sixadは不要かもしれない。試行錯誤でいろいろなコマンドを叩いていたので、最短の設定手順がわからなくなってしまったが、上記あたりの設定を行えば、再起動後もペアリングできることは確認できた。

次回は、pythonでこのデバイスファイルを解析して、どんなボタンが入力されたかを判別することにする。