カイワレスタイル

ゲーム、アニメ、プログラム、興味のあることをツラツラと。

Raspberry Pi 2にPS3のコントローラーをBluetoothで接続する

先日書いた通り、Raspberry Pi 2にPS3のコントローラーをBluetoothで接続してみた。
結論から書くと、準備に余計な時間が取られてしまい、接続できたところで力尽きた。


用意したもの

  • Raspberry pi 2
  • PS3のコントローラー
  • USB Bluetoothドングル
    今回はBUFFALOのBSBT4D09を使用

準備その1

Bluetoothを使えるようにするための準備をする。

sudo apt-get update
sudo apt-get upgrade
sudo apt-get install bluetooth bluez-utils bluez-compat bluez-hcidump

Bluetoothドングルのセットアップについては省略する。

ペアリング用のツールを落としてきてビルドする。

mkdir sixpair
cd sixpair/
wget "http://www.pabr.org/sixlinux/sixpair.c" -O sixpair.c
gcc -o sixpair sixpair.c -lusb

ビルドが成功したらPS3のコントローラーをUSBでRaspberry piと接続する。
接続したらPS3のコントローラーのPSボタンを押して、先ほどビルドしたsixpairを実行する。

sudo ./sixpair 
Current Bluetooth master: xx:xx:xx:xx:xx:xx
Setting master bd_addr to xx:xx:xx:xx:xx:xx

ペアリングに成功するとPS3のコントローラーのmacアドレスが表示される。


準備その2

QtSixAというツールソースコードをダウンロードして、その中のsixadという部分だけビルドする。

wget "https://sourceforge.net/projects/qtsixa/files/QtSixA%201.5.1/QtSixA-1.5.1-src.tar.gz/download" -O QtSixA-src.tar.gz
cd QtSixA-1.5.1/sixad
make
sudo make install

sixadだけビルドするのを間違えて QtSixA-1.5.1/ で全体makeしてしまったため、
pyuic4が見つからないやらjack.hが見つからないやら色々エラーが出て余計な時間が取られてしまった…。

ビルドが通ったら、早速接続したいところだが、一旦再起動しないとダメだった。


いよいよBluetooth接続

再起動後、sixadコマンドで接続開始。

sudo sixad -start &
sixad-bin[2702]: started
sixad-bin[2702]: sixad started, press the PS button now
sixad-bin[2702]: unable to connect to sdp session
sixad-bin[2702]: Connected Sony Computer Entertainment Wireless Controller (xx:xx:xx:xx:xx:xx)

接続に成功すると上記の表示が出る。
下記のコマンドでデータの入力を確認できる。

cat /dev/input/js0

適当にボタンを押したりスティックを倒したりすると何やらデータが流れてくる。
このままだとわけがわからないので、入力確認用のプログラムを作成。

#include <iostream>
#include <iomanip>
#include <vector>
#include <cstdio>
#include <fcntl.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <linux/joystick.h>

#define JOY_DEV "/dev/input/js0"

using namespace std;

int main() {
    int joy_fd(-1), num_of_axis(0), num_of_buttons(0);
    char name_of_joystick[80];
    vector<char> joy_button;
    vector<int> joy_axis;

    if((joy_fd = open(JOY_DEV, O_RDONLY)) < 0) {
        printf("Failed to open %s", JOY_DEV);
        cerr << "Failed to open " << JOY_DEV << endl;
        return -1;
    }

    ioctl(joy_fd, JSIOCGAXES, &num_of_axis);
    ioctl(joy_fd, JSIOCGBUTTONS, &num_of_buttons);
    ioctl(joy_fd, JSIOCGNAME(80), &name_of_joystick);

    joy_button.resize(num_of_buttons, 0);
    joy_axis.resize(num_of_axis, 0);

    printf("Joystick: %s axis: %d buttons: %d\n", name_of_joystick, num_of_axis, num_of_buttons);

    fcntl(joy_fd, F_SETFL, O_NONBLOCK); // using non-blocking mode

    while(true) {
        js_event js;

        read(joy_fd, &js, sizeof(js_event));

        switch(js.type & ~JS_EVENT_INIT) {
            case JS_EVENT_AXIS:
                joy_axis[(int)js.number] = js.value;
                break;
            case JS_EVENT_BUTTON:
                joy_button[(int)js.number] = js.value;
                break;
        }
        
        printf( "LX: %6d  LY: %6d  ", joy_axis[0], joy_axis[1] );
        
        if( num_of_axis > 2 )
            printf("RX: %6d  ", joy_axis[2] );
        
        if( num_of_axis > 3 )
            printf("RY: %6d  ", joy_axis[3] );
                                    
        for(int x=0 ; x<num_of_buttons ; ++x )
            printf("B%d: %d  ", x, joy_button[x] );
        
        printf("\n");
        fflush(stdout);

        usleep(100);
    }

    close(joy_fd);
    return 0;
}

ビルドして実行。

g++ joystickTest.cpp 
./a.out

実行すると下記のようなログが流れ続ける。

f:id:kaiware007:20150708021628p:plain

LXとLYが左スティック、RXとRYが右スティックの値。
B**が各ボタンのオンオフ。
スティックを倒したり、ボタンを押すと値が変わるのがわかった。

CTRL+Cで停止。


切断

PS3のコントローラーと切断するときは

sudo sixad -stop

とするのだが、そうしてもBluetooth接続は切れないらしく、
/dev/input/js0
にはデータが流れ続けてしまう。
しかたがないので、

sudo hcitool dc [PS3のコントローラーのmacアドレス]

で切断したが、これだともう一度

sudo sixad -start 

を呼んでも再接続できなくなってしまった。
不便だ…。
なにかいい方法はないものか…。

とりあえずPS3のコントローラーとBluetooth接続できたので、次こそはモーターの制御をしたいところ。