Edited at

Raspberry Pi 3B にPS3コントローラを認識させる

More than 1 year has passed since last update.


概要

本記事では、PlayStation3 (SIXAXIS) コントローラ(以下PS3コントローラ)を

Raspberry Piに無線(Bluetooth)で接続し、

LED の ON/OFF をPS3コントローラから制御するまで書いています。


実装


LEDチカチカ装置

Raspberry Pi Robotics #1: GPIO Control

の動画を参考に作成しました。英語ですが音声OFFにしてても雰囲気でなんとなくわかりました。

キャプチャ.PNG

以下 プログラム開始直後からLED が3回チカチカするプログラムです。


/path/to/LED.py

import RPi.GPIO as GPIO

import time

GPIO.setmode( GPIO.BOARD)
GPIO.setup( 7, GPIO.OUT)

for x in range(0,3):
GPIO.output(7,True)
time.sleep(1)
GPIO.output(7,False)
time.sleep(1)
GPIO.cleanup()



PS3コントローラ登録

とりあえずOSを最新版に更新しました。

$ sudo apt update && sudo apt upgrade

$ sudo apt-get install libusb-dev


sixpair

落としてきたファイル(sixpair.c)からsixpair 実行ファイルを作ります。

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

$ gcc -o sixpair sixpair.c -lusb
$ ls -la
合計 24
drwxr-xr-x 2 pi pi 4096 9月 4 17:36 .
drwxr-xr-x 5 pi pi 4096 9月 4 15:32 ..
-rwxr-xr-x 1 pi pi 10076 9月 4 17:36 sixpair
-rw-r--r-- 1 pi pi 3367 9月 4 17:31 sixpair.c


qtsixa

次にqtsixa を作るのですが、いくつかライブラリが不足していたので

インストールします。

--- pyuic4 ---

$ sudo apt install python-qt4 pyqt4-dev-tools qt4-designer
--- jack.h ---
$ sudo apt install libjack-jackd2-dev
--- bluetooth.h ---
$ sudo apt install libbluetooth-dev

ライブラリの準備が終わったので、コンパイル、インストール します。

$ git clone https://github.com/falkTX/qtsixa.git

$ cd qtsixa
$ make
$ sudo make install
make install -C qtsixa
make[1]: Entering directory '/path/to/qtsixa/qtsixa'
#Make directories
...
#Install files
...
Installation is Complete!
make[1]: Leaving directory '/path/to/qtsixa/sixad'
$ echo $?
0

準備完了です。sixad を起動した後、PSボタンを押して接続します。

(※細かい手順を忘れました。うまくいかなかった人は以下サイトを参考にしてください。

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

 $ sudo sixad -start &

[1] 8098
$ [....] Starting bluetooth (via systemctl): bluetooth.service[ ok .
sixad-bin[8191]: started
sixad-bin[8191]: sixad started, press the PS button now
sixad-sixaxis[8198]: started
sixad-sixaxis[8198]: Connected 'PLAYSTATION(R)3 Controller (00:19:C1:1B:70:3C)' [Battery 05]

無事繋がりました\(^o^)/

Raspberry Pi起動時にいつでもsixadが起動しているようにサービスの設定を行います。

$ sudo systemctld enable sixad


PS3コントローラでLチカ

ラズパイでラジコン(3):Pythonでdualshock3の入力を読み取る

入力を読み取るコードを参考に以下のようなプログラムを作ってみました。


仕様概要


  • PS3コントローラの〇を押したら、LEDが点灯

  • PS3コントローラの〇から指が離れたら、LEDを消灯

  • PS3コントローラの×を押したら、アプリ終了


プログラム


LED_FLASH.py

$ cat 20180904_PS3.py

import RPi.GPIO as GPIO
import time
import struct

device_path = "/dev/input/js0"
EVENT_FORMAT = "LhBB";
EVENT_SIZE = struct.calcsize(EVENT_FORMAT)

GPIO.setmode( GPIO.BOARD)
GPIO.setup( 7, GPIO.OUT)
try:
with open(device_path, "rb") as device:
event = device.read(EVENT_SIZE)
while event:
(ds3_time, ds3_val, ds3_type, ds3_num) = struct.unpack(EVENT_FORMAT, event)
if ds3_type == 1:
if ds3_num == 13:
sw = False if ds3_val == 0 else True
GPIO.output(7,sw)
# print('LED POWER ')

if ds3_num == 14:
break

# print( "{0}, {1}, {2}, {3}".format( ds3_time, ds3_val, ds3_type, ds3_num ) )
event = device.read(EVENT_SIZE)
finally:
GPIO.cleanup()



最終系


仕様概要


  • 起動時に今回のプログラムを起動し、PS3コントローラの接続を待つ

  • 〇△□×ボタンのどれかを押したら、LEDを点灯

  • ボタンから離したら、LEDを消灯

  • PSボタン長押しでコントローラの電源が切れると同時にRaspberryPiもシャットダウン


プログラム


/etc/rc.local

#!/bin/sh -e

#
# rc.local
#
# This script is executed at the end of each multiuser runlevel.
# Make sure that the script will "exit 0" on success or any other
# value on error.
#
# In order to enable or disable this script just change the execution
# bits.
#
# By default this script does nothing.

# Print the IP address
_IP=$(hostname -I) || true
if [ "$_IP" ]; then
printf "My IP address is %s\n" "$_IP"
fi

python3 /path/to/PS3LED.py
exit 0


↑↑↑元のソースからpython3 /path/to/PS3LED.py を追加しております。


/path/to/PS3LED.py

import RPi.GPIO as GPIO

import time
import struct
import os

device_path = "/dev/input/js0"
EVENT_FORMAT = "LhBB";
EVENT_SIZE = struct.calcsize(EVENT_FORMAT)

GPIO.setmode( GPIO.BOARD)
GPIO.setup( 7, GPIO.OUT)

#コントローラ接続待ち
con = False
while True:
try:
with open(device_path, "rb") as device:
event = device.read(EVENT_SIZE)
print("コントローラに繋がったょ")
break
except IOError:
con = False

# コントローラに繋がった
sw_stat = 0
sw_counter = 0
try:
with open(device_path, "rb") as device:
event = device.read(EVENT_SIZE)
while event:
(ds3_time, ds3_val, ds3_type, ds3_num) = struct.unpack(EVENT_FORMAT, event)
if ds3_type == 1:
if ds3_num == 12: # △ボタン
sw = False if ds3_val == 0 else True
GPIO.output(7,sw)

elif ds3_num == 13: # 〇ボタン
sw = False if ds3_val == 0 else True
GPIO.output(7,sw)

elif ds3_num == 14: # ×ボタン
sw = False if ds3_val == 0 else True
GPIO.output(7,sw)

elif ds3_num == 15: # □ボタン
sw = False if ds3_val == 0 else True
GPIO.output(7,sw)

# print( "{0}, {1}, {2}, {3}".format( ds3_time, ds3_val, ds3_type, ds3_num ) )
event = device.read(EVENT_SIZE)

except IOError:
# PSボタン長押しでコントローラの電源が切れた時を想定(乱暴)
print("コントローラの電源切れたよ")
os.system("sudo shutdown -h now")

finally:
GPIO.cleanup()



ブレッドボード図はFritzingを用いて作成しております。