Top/Devel/電子工作/Arduino/ゲームコントローラー

ゲームコントローラーはてなブックマーク

finish01.jpg

片手でゲームをしたい!


…でも市販のゲームコントローラーはほぼ両手用。



ということで、今回はWiiのヌンチャクコントローラーArduino Leonardoに接続して、USB接続のゲームコントローラー*1を作ってみます。

Windows PCからは何の変哲もない普通のゲームコントローラーに見えるので、ゲームとの相性問題が出ることもないはず。


ヌンチャクを使ったゲームコントローラー(≒ジョイスティック)なので、JoyChuckという名前にしました。

必要なもの

ハードウェア

項目説明
Arduino Leonardo比較的小型で安価で簡単に使えるマイコンボード。

なお、Arduino UnoでもUSB接続のHID(human interface device)を作ることはできますが、その場合ATMEGA8U2マイコンのファームウェアを書き換える必要があります。
難しそうなので、今回は素直にLeonardoを使用することにしました。
ヌンチャクコントローラー通常はWiiリモコンに接続して使うヌンチャクコントローラー。
WiiChuckArduinoにヌンチャクコントローラーを接続しやすくする基板。
なくても頑張れば接続できるでしょう。
ピンヘッダ(4P)何でも良いです。今回は 秋月電子通商で購入しました

ソフトウェア

項目説明
chuck_funcs.hヌンチャクコントローラーの情報をArduinoで取得するための関数が定義されたヘッダファイル。
todbotさんのgithubからダウンロードしてください。
(「Raw」を右クリックして名前をつけて保存。)
USBAPI.hUSB機器用ヘッダファイル。
Imaginary Industriesからダウンロードしてください。
または、fileUSBAPI.hのパッチをお手持ちの環境のUSBAPI.hに当ててください。
HID.cppHID用プログラム。
Imaginary Industriesからダウンロードしてください。
または、fileHID.cppのパッチをお手持ちの環境のHID.cppに当ててください。
leoJoy.inoテスト用ランダム入力スケッチ。
Imaginary Industriesからダウンロードしてください。
JoyChuck.inoヌンチャクコントローラをゲームパッドにするスケッチ。
下記からダウンロードしてください。

手順

ソフトウェアの準備(Arduino Leonardoをゲームコントローラーとして認識させる)

  1. arduinoの開発環境をインストールしたディレクトリの配下のhardware\arduino\cores\arduinoを開く。
    (私の場合は、「C:\Program Files (x86)\Arduino\hardware\arduino\cores\arduino」でした)
  2. 上記で示したUSBAPI.hとHID.cppをコピーする。
  3. USBケーブルを挿す。
  4. leoJoy.inoを開き、Arduino Leonardoに書き込む。

ソフトウェアの動作確認

device_manager.jpg
  1. [コントロールパネル]>[デバイス マネージャー]>[ヒューマン インターフェース デバイス]を開く。
  2. 「HID 準拠ゲーム コントローラー」が表示されていることを確認する。
    device_and_printer.jpg
  3. [コントロールパネル]>[デバイスとプリンター]を開く。
  4. 「デバイス」欄に「Arduino Leonardo」が表示されていることを確認する。
  5. 右クリックし、「ゲームコントローラーの設定」をクリックする。
  6. 「プロパティ」ボタンをクリックする。
    game_controller_property.jpg
  7. 右のようなウィンドウが表示され、「軸」「ボタン」「ハットスイッチ」がランダムに入力されていることを確認する。
    (leoJoy.inoはランダムな入力を発生させるスケッチです)

ハードウェアの準備

joychuck.jpg
  1. WiiChuckにピンヘッダを半田付けする。(labs.thingm.comと書いてある側からピンヘッダの短い方を差込み、逆側から半田付けする。)
  2. ArduinoのGNDピンに-、3.3Vピンに+、D2ピン*2にd、D3ピン*3にcを接続する。
  3. WiiChuckにヌンチャクコントローラを挿す。(ヌンチャクの金属端子の凹みがある方が上になるように挿す。)

ソフトウェアの準備(ヌンチャクコントローラーをゲームコントローラーとして使えるようにする)

  1. JoyChuck.inoとchuck_funcs.hをJoyChuckというフォルダに格納する。
  2. nunchuck_funcs.hの25行目〜34行目は次のようにコメントアウトする。*4
    // Uses port C (analog in) pins as power & ground for Nunchuck
    static void nunchuck_setpowerpins()
    {
    /*
    #define pwrpin PORTC3
    #define gndpin PORTC2
        DDRC |= _BV(pwrpin) | _BV(gndpin);
        PORTC &=~ _BV(gndpin);
        PORTC |=  _BV(pwrpin);
        delay(100);  // wait for things to stabilize        
    */
    }
  3. JoyChuck.inoを開き、Arduino Leonardoに書き込む。

最終動作確認

  1. [コントロールパネル]>[デバイスとプリンター]を開く。
  2. 「デバイス」欄に「Arduino Leonardo」が表示されていることを確認する。
  3. 右クリックし、「ゲームコントローラーの設定」をクリックする。
  4. 「プロパティ」ボタンをクリックする。
  5. ヌンチャクコントローラーのジョイスティックの操作が、軸欄に反映されることを確認する。
  6. ヌンチャクコントローラーのCボタンの操作が、ボタン欄の1に反映されることを確認する。
  7. ヌンチャクコントローラーのZボタンの操作が、ボタン欄の2に反映されることを確認する。


以上で終了です。お疲れ様でした :)


joychuck02.jpg

Arduinoの基板がむき出しだとトラブルの元なので、 ALTOIDSミントサイズ缶に穴を空けて線を通し、穴部分の切り口で線が切れないようにスポンジ(激落ちくんなどでも可)で保護するとスマートです。

スケッチ

fileJoyChuck.ino
/*
 * JoyChuck
 *
 * 2013 http://cubic9.com
 *
 * original sketch is leoJoy
 *   by 2012 Connor,
 *      http://www.imaginaryindustries.com/blog/?p=80
 * nunchuck_funcs.h
 *   by 2008 Tod E. Kurt,
 *      http://todbot.com/blog/2008/02/18/wiichuck-wii-nunchuck-adapter-available/
 *
 */

#include <Wire.h>
#include "nunchuck_funcs.h"

#define DEBUG 0
#define INTERVAL 50

#define STICK_LEFT_DEFAULT 127
#define STICK_RIGHT_DEFAULT 127
#define POV_DEFAULT -1
#define BUTTON_DEFAULT 0

#define PAD_JOYX_MIN 0
#define PAD_JOYX_MAX 255
#define PAD_JOYY_MIN 0
#define PAD_JOYY_MAX 255

#define CHUCK_JOYX_MIN 24
#define CHUCK_JOYX_MAX 230
#define CHUCK_JOYY_MIN 33
#define CHUCK_JOYY_MAX 226

#define SERIAL_BPS 19200

JoyState_t joySt;
int loop_cnt = 0;
byte accx, accy, accz, zbut, cbut, joyx, joyy;

void setup()
{
    #if DEBUG
        Serial.begin(SERIAL_BPS);
    #endif

    nunchuck_init();

    #if DEBUG
        Serial.print("JoyChuck ready\n");
    #endif

    joySt.xAxis = STICK_LEFT_DEFAULT;
    joySt.yAxis = STICK_LEFT_DEFAULT;
    joySt.zAxis = STICK_RIGHT_DEFAULT;
    joySt.xRotAxis = 0;
    joySt.yRotAxis = 0;
    joySt.zRotAxis = 0;
    joySt.throttle = 0;
    joySt.rudder = STICK_RIGHT_DEFAULT;
    joySt.hatSw1 = POV_DEFAULT;
    joySt.hatSw2 = POV_DEFAULT;
    joySt.buttons = BUTTON_DEFAULT;

}


void loop()
{
    if( loop_cnt > INTERVAL ) {
        loop_cnt = 0;

        nunchuck_get_data();

        #if DEBUG
            accx = nunchuck_accelx();
            accy = nunchuck_accely();
            accz = nunchuck_accelz();
        #endif
        zbut = nunchuck_zbutton();
        cbut = nunchuck_cbutton();
        joyx = nunchuck_joyx();
        joyy = nunchuck_joyy();

        #if DEBUG
            Serial.print(" accx:"); Serial.print((byte)accx, DEC);
            Serial.print(" accy:"); Serial.print((byte)accy, DEC);
            Serial.print(" accz:"); Serial.print((byte)accz, DEC);
            Serial.print(" zbut:"); Serial.print((byte)zbut, DEC);
            Serial.print(" cbut:"); Serial.print((byte)cbut, DEC);
            Serial.print(" joyx:"); Serial.print((byte)joyx, DEC);
            Serial.print(" joyy:"); Serial.print((byte)joyy, DEC);
            Serial.println();
        #endif

        joySt.xAxis = constrain(
            map(joyx, CHUCK_JOYX_MIN, CHUCK_JOYX_MAX,
                PAD_JOYX_MIN, PAD_JOYX_MAX),
            PAD_JOYX_MIN, PAD_JOYX_MAX);
        joySt.yAxis = constrain(
            map(joyy, CHUCK_JOYY_MIN, CHUCK_JOYY_MAX,
                PAD_JOYY_MAX, PAD_JOYY_MIN),
            PAD_JOYY_MIN, PAD_JOYY_MAX);
        joySt.buttons = cbut + zbut * 2;

        Joystick.setState(&joySt);
    }
    loop_cnt++;
    delay(1);
}

設定について

  • DEBUG定数を1にすると、シリアルモニタにヌンチャクのセンサの現在の値が表示されます。

JoyState_tのメンバ変数とゲームコントローラーの関係

JoyState_tのメンバ説明
xAxis, yAxis左スティックに対応。0-255の範囲で指定。
zAxis, rudder右スティックに対応。0-255の範囲で指定。
buttonsボタンのオンオフをビットで指定。
1番目のボタンは1/0でオンオフを表現、2番目のボタンは2/0でオンオフを表現、3番目のボタンは4/0でオンオフを表現…という感じ。
各ボタンの同時押し込みは加算で表現する。
hatSw1POVキーに対応。上方向を0として、時計回りに0〜7で指定。

デバイスとプリンターに表示される名称を変更したい

USBCore.cppのSTRING_IPRODUCTとSTRING_IMANIFACTUREを修正してください。

【発展】ボタンを増やす

ctrlpad03.jpg

ヌンチャクコントローラーのボタン数は2個。これではちょっと少ない。

そこで発展系としてボタンを増やしてみます。

Arduinoではマイコン内にプルアップ抵抗を持っていて、設定で使用できるため、スイッチのみ用意すればボタンを簡単に増やすことが出来ます。(参考

右の写真は十字キーを増設してヌンチャクコントローラーと合体させたものです。

必要なもの

あるとよいもの

項目説明
DS LiteやPSPの保守パーツ十字キーやボタンの外装とラバードームを利用します。
秋葉原なら三月兎などで買えます。
Y字ドライバヌンチャクコントローラーには特殊なネジが使われています。
頑張ればマイナスドライバでもネジを破壊しつつ開けられますが、安全に開けるにはこれが必要です。
秋葉原なら三月兎などで買えます。

手順

  1. ユニバーサル基板にタクトスイッチを挿す。
  2. タクトスイッチの =□= となっている4本の足のうち、=の1本ずつをGNDとデジタル端子に接続する。(下記ではデジタル10番ピンを使用)
    複数のスイッチを設けたいときはGNDは共有しても大丈夫です。
  3. スケッチのinclude文の下辺りに下記を追加する。
    #define PIN_SWITCH1 10
    
    byte switch1;
  4. スケッチのsetup()の中に下記を追加する。
    pinMode(PIN_SWITCH1, INPUT_PULLUP);
  5. スケッチのloop()の中に下記を追加する。(下記はタクトスイッチが押されると、POVキー上が入力されるようになる)
    switch1 = digitalRead(PIN_SWITCH1);
    Serial.print(" SWITCH1:"); Serial.print(switch1);
    if (switch1 == LOW) {
        joySt.hatSw1 = 0;
    }
  6. DEBUG定数を1にしてArduinoに書き込むと、シリアルモニタに"SWITCH1:1"と表示され続け、スイッチを押すと"SWITCH1:0"に表示が変わるはずです。
    ctrlpad02.jpg
  7. あとはお好みでラバードームと外装を両面テープで貼ってください。
    ctrlpad03.jpg
  8. また、ヌンチャクコントローラと合体させたい場合は、Y字ドライバでコントローラを開けた後、外装を適当に切断し、埋め込んでください。

関連

../楽器

参考

Amazon

*1 ゲームパッド、ジョイパッド、ジョイスティックなど色々な名前で呼ばれますが、ここでは、Windowsの流儀に沿って、ゲームコントローラーと呼びます。
*2 SDAピンでも可。
*3 SCLピンでも可。
*4 Uno用の関数のため。
差分 一覧