日記とか、工作記録とか

自分に書けることを何でも書いてゆきます。作った物、買ったもの、コンピュータ系の話題が多くなるかもしれません。

Raspberry pi + gamepad (XBOXコンントローラー)

xboxのコントローラを持っているのですが、これをRaspberry piにUSB接続して、ゲームパッドとして認識させるところを試してみます。もともとPCでゲームを遊ぶ時に使っているものなのですが、これで何か遊べないかなぁということで……

実を言うと全然難しくなくて、ただつなぐだけで認識しました。lsusbコマンドで認識しているかどうか確認することができます。5行目に表示されていますね。

pi@raspberrypi:~$ lsusb
Bus 001 Device 002: ID 0424:9514 Standard Microsystems Corp. 
Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
Bus 001 Device 003: ID 0424:ec00 Standard Microsystems Corp. 
Bus 001 Device 004: ID 056e:4008 Elecom Co., Ltd 
Bus 001 Device 005: ID 045e:02d1 Microsoft Corp. 
pi@raspberrypi:~$

むやみに長くてすみませんがデバイスの詳細。詳細にアクセスするにはsudoコマンドを使ってスーパーユーザー権限を使う必要があります。

pi@raspberrypi:~/gamepad$ sudo lsusb -v -s 005

Bus 001 Device 005: ID 045e:02d1 Microsoft Corp. 
Device Descriptor:
  bLength                18
  bDescriptorType         1
  bcdUSB               2.00
  bDeviceClass          255 Vendor Specific Class
  bDeviceSubClass        71 
  bDeviceProtocol       208 
  bMaxPacketSize0        64
  idVendor           0x045e Microsoft Corp.
  idProduct          0x02d1 
  bcdDevice            1.01
  iManufacturer           1 Microsoft
  iProduct                2 Controller
  iSerial                 3 7EED83246AAF
  bNumConfigurations      1
  Configuration Descriptor:
    bLength                 9
    bDescriptorType         2
    wTotalLength           96
    bNumInterfaces          3
    bConfigurationValue     1
    iConfiguration          0 
    bmAttributes         0xa0
      (Bus Powered)
      Remote Wakeup
    MaxPower              500mA
    Interface Descriptor:
      bLength                 9
      bDescriptorType         4
      bInterfaceNumber        0
      bAlternateSetting       0
      bNumEndpoints           2
      bInterfaceClass       255 Vendor Specific Class
      bInterfaceSubClass     71 
      bInterfaceProtocol    208 
      iInterface              0 
      Endpoint Descriptor:
        bLength                 7
        bDescriptorType         5
        bEndpointAddress     0x01  EP 1 OUT
        bmAttributes            3
          Transfer Type            Interrupt
          Synch Type               None
          Usage Type               Data
        wMaxPacketSize     0x0040  1x 64 bytes
        bInterval               4
      Endpoint Descriptor:
        bLength                 7
        bDescriptorType         5
        bEndpointAddress     0x81  EP 1 IN
        bmAttributes            3
          Transfer Type            Interrupt
          Synch Type               None
          Usage Type               Data
        wMaxPacketSize     0x0040  1x 64 bytes
        bInterval               4
    Interface Descriptor:
      bLength                 9
      bDescriptorType         4
      bInterfaceNumber        1
      bAlternateSetting       0
      bNumEndpoints           0
      bInterfaceClass       255 Vendor Specific Class
      bInterfaceSubClass     71 
      bInterfaceProtocol    208 
      iInterface              0 
    Interface Descriptor:
      bLength                 9
      bDescriptorType         4
      bInterfaceNumber        1
      bAlternateSetting       1
      bNumEndpoints           2
      bInterfaceClass       255 Vendor Specific Class
      bInterfaceSubClass     71 
      bInterfaceProtocol    208 
      iInterface              0 
      Endpoint Descriptor:
        bLength                 7
        bDescriptorType         5
        bEndpointAddress     0x02  EP 2 OUT
        bmAttributes            1
          Transfer Type            Isochronous
          Synch Type               None
          Usage Type               Data
        wMaxPacketSize     0x00e4  1x 228 bytes
        bInterval               1
      Endpoint Descriptor:
        bLength                 7
        bDescriptorType         5
        bEndpointAddress     0x82  EP 2 IN
        bmAttributes            1
          Transfer Type            Isochronous
          Synch Type               None
          Usage Type               Data
        wMaxPacketSize     0x00e4  1x 228 bytes
        bInterval               1
    Interface Descriptor:
      bLength                 9
      bDescriptorType         4
      bInterfaceNumber        2
      bAlternateSetting       0
      bNumEndpoints           0
      bInterfaceClass       255 Vendor Specific Class
      bInterfaceSubClass     71 
      bInterfaceProtocol    208 
      iInterface              0 
    Interface Descriptor:
      bLength                 9
      bDescriptorType         4
      bInterfaceNumber        2
      bAlternateSetting       1
      bNumEndpoints           2
      bInterfaceClass       255 Vendor Specific Class
      bInterfaceSubClass     71 
      bInterfaceProtocol    208 
      iInterface              0 
      Endpoint Descriptor:
        bLength                 7
        bDescriptorType         5
        bEndpointAddress     0x03  EP 3 OUT
        bmAttributes            2
          Transfer Type            Bulk
          Synch Type               None
          Usage Type               Data
        wMaxPacketSize     0x0040  1x 64 bytes
        bInterval               0
      Endpoint Descriptor:
        bLength                 7
        bDescriptorType         5
        bEndpointAddress     0x83  EP 3 IN
        bmAttributes            2
          Transfer Type            Bulk
          Synch Type               None
          Usage Type               Data
        wMaxPacketSize     0x0040  1x 64 bytes
        bInterval               0
Device Status:     0x0002
  (Bus Powered)
  Remote Wakeup Enabled
pi@raspberrypi:~/gamepad$ 

いつものようにPythonからこれを利用できるようにしたいのですが、こちらもすでにモジュールがインストールされていました。pygameというモジュールです。
pygame
しかし、このサイト、近年稀に見る見づらいレイアウトです。横スクロールしないとマニュアルドキュメントが見られません。辛抱強く読む必要がありますね。

いろいろ試行錯誤して、とりあえずゲームパッドの名称や軸の数、ボタンの数を検出するところまで作りました。

pi@raspberrypi:~/gamepad$ cat gamepad_init.py 
#!/usr/bin/python
# -*- coding: utf-8 -*-
import sys
import pygame
from pygame import locals

# 初期化
pygame.init()
pygame.joystick.init()

# ゲームパッドを列挙する(複数つなぐ場合があるので)
joysticks = [pygame.joystick.Joystick(x) for x in range(pygame.joystick.get_count())]

# ゲームパッドを認識しているか?
if pygame.joystick.get_count() == 0:
	print "ゲームパッドがありません。"
	sys.exit("終了")
else:
	print "ゲームパッドが" + str(len(joysticks)) + "個見つかりました。"

# ゲームパッドを初期化
print "ゲームパッドを初期化します..."
joysticks[0].init()
print "名称:%s" % (joysticks[0].get_name())

# ゲームパッドに軸はいくつあるの? => 6軸
n_axis = joysticks[0].get_numaxes()
print "軸の数(axis):" + str(n_axis)

# ゲームパッドにボタンはいくつあるの? => 11個
n_button = joysticks[0].get_numbuttons()
print "ボタンの数(buttons):" + str(n_button)

pi@raspberrypi:~/gamepad$ 

実行してみるとこんな出力になります。

pi@raspberrypi:~/gamepad$ python gamepad_init.py 
ゲームパッドが1個見つかりました。
ゲームパッドを初期化します...
名称:Microsoft X-Box One pad
軸の数(axis):6
ボタンの数(buttons):11
pi@raspberrypi:~/gamepad$ 

軸が6個?というのに少し驚いたのですが、xbox oneのコントローラは、左手の親指のスティックで2軸、右手の親指のスティックで2軸、左右の中指あたりで押すボタン(LT, RT)が無段階ボタンなのでこれで2軸ということのようです。今後もう少し細かくコントロールできるようにしていきたいと思います。

Raspberry Pi3 Model B (Element14)

Raspberry Pi3 Model B (Element14)