Help us understand the problem. What is going on with this article?

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を用いて作成しております。

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away