見出し画像

ゲームパッドをArduinoで自作してみた話(ハッピーケイオスコントローラー)

とりあえず作ったもの

ボタンが流石に足りないので2つ追加している

という感じでゲームパッドをArduinoで自作したものになります。
説明に関しては全体の配線→コードの中身を書いていこうと思います。

はじめに

一応解説をしていこうと思いますが、これらは自分も勉強として作ったものになるので後ほどの解説など(コード部分)も完璧なものではないことをご了承ください。とりあえず動いて終わりにしたのでライブラリの使い方に関してもまだ不明瞭な部分も多いです。
また接続に関してもゲームデバイスとしては認識されてるっぽいもののGGST(ギルティギア)のゲーム上では認識されてないっぽい?ので最終的にはJoyToKeyでマッピングしてる感じになってます。
なのでこのコントローラ自体も実用たるかと言われるとかなり微妙なものになっています。

今回はコードにArduinoJoystickLibraryというライブラリを使用しています。

Arduinoはmicroもしくはleonardoを使用してください。
これら以外のものはキーボードやマウスなどのパソコンの周辺機器としての機能が含まれていないのでそれらのデバイスとして認識してもらえないからです。

配線

まずはヌンチャク側の配線はこちらです。
アナログスティック側基盤

Cボタン、Zボタン側

黒はGND
白と灰色はどっちがCでどっちがZか忘れました。。

ハンドガン側の中身
黄色で囲った丸枠がボタンになっています。
トリガーの部分は引いたら上にあるタクトスイッチが押される感じになってます。ちなみにArduinoはその真横にもともとの基盤が入っていた部分にいい感じに収まったのでそこに配置しています。
また銃先にある赤いやつも一応ボタンで配線してあるのですが、使用していません。

配線図

ボタン
黄             -D2 
緑             -D3
灰             -D4
オレンジ -D5
白             -D6

アナログスティック
水(Y) - A0
茶(X) - A1

青 - GND
赤 - VCC(5v)


コード

全体

#include "Joystick.h" 

const int x_pin = A0; 
const int y_pin = A1;

int x_value = 0; 
int y_value = 0;
 
Joystick Joystick; 

void setup() { 

  pinMode(2, INPUT_PULLUP);
  pinMode(3, INPUT_PULLUP); 
  pinMode(4, INPUT_PULLUP); 
  pinMode(5, INPUT_PULLUP); 
  pinMode(6, INPUT_PULLUP); 

  Joystick.begin(true); 

  Joystick.setXAxisRange(120, 894); //X軸範囲
  Joystick.setYAxisRange(135, 910); //Y軸範囲 
} 

void loop() { 
  x_value = analogRead(x_pin); 
  y_value = analogRead(y_pin); 

  y_value = 135 + 910 - y_value; //上下反転 

  if ((x_value <= 270) (x_value >= 730)) { 
    Joystick.setXAxis(x_value); 
  } else { 
    Joystick.setXAxis(495); 
  } 

  if ((y_value <= 270) (y_value >= 750)) {  
    Joystick.setYAxis(y_value); 
  } else { 
    Joystick.setYAxis(540); 
  } 

  Joystick.setButton(0, !digitalRead(2)); 
  Joystick.setButton(1, !digitalRead(3)); 
  Joystick.setButton(2, !digitalRead(4));  
  Joystick.setButton(3, !digitalRead(5)); 
  Joystick.setButton(4, !digitalRead(6)); 

  delay(10); 
} 

ボタン設定は特に説明するところもないので省きます。
というか多分この書き方あってないんですよね。

int currentButtonState = !digitalRead(pinToButtonMap);
if (currentButtonState != lastButtonState) {
  Joystick.setButton(0, currentButtonState);
  lastButtonState = currentButtonState;
}

ドキュメントではcurrentButtonStateっていうものを持って状態を監視してるっぽいので。特に問題なく動いてるっぽいからほっといてますが。。

次はアナログスティック部分です。
まずX.Y軸の範囲値を入れます。
この値はログ出力して各々の方向に倒し込んだ値になります。
実際には倒し込んでいても値はブレていたのでそこら辺の平均という感じにしました。

Joystick.setXAxisRange(120, 894); //X軸範囲
Joystick.setYAxisRange(135, 910); //Y軸範囲 

そして下記のようにアナログ入力の値を読み取っています。
またy軸の値は上下反転させています。

  x_value = analogRead(x_pin); 
  y_value = analogRead(y_pin); 

  y_value = 135 + 910 - y_value; //上下反転 

そして↓で各々の値をif文で囲って若干制御しています。

  if ((x_value <= 270) (x_value >= 730)) { 
    Joystick.setXAxis(x_value); 
  } else { 
    Joystick.setXAxis(495); 
  } 

  if ((y_value <= 270) (y_value >= 750)) {  
    Joystick.setYAxis(y_value); 
  } else { 
    Joystick.setYAxis(540); 
  } 

なぜ制御をしているか簡単に言うとジョイスティックを少し倒しただけでも入力が反映されてしまうからです。
例えばX軸右側の最大値は894になっているのですが、550くらいの値になるような位置に倒しただけでも入力が反映されてしまうからです。
なのである程度の位置まで倒さないと入力が反映されないようにしています。それ以外の位置の場合はX、Y軸ともに中央値になるようにset~Axisで制御しています。

最後にdelayを少し入れているのは入力感知が早くなりすぎないようにしているためです。ここの説明と値はどっかのYoutubeで見た感じなので実際に必要なのかどれくらいの値が最適なのかはよく分かってないです。

という感じでとりあえず動くようになった感じです。

問題点と改善点

動くようにはできていますが、やっぱり初めに書いた通りコード部分が完璧ではないのと、JoyToKeyでマッピングしてる点があまりよくない気はします。Console機で動かないですからね。
まぁ普通にアケコン基盤使って動かした方がいいのですが、使える指が限られてるので移動に関してはやはりスティックじゃないと厳しいですね。
ただスティック入力と基盤の方向キーとの接続はむずかしそうです。。。

小さめのレバーを↓のようなものからとってくれば結構いい感じにできる感じはします。
スティック部分をボールじゃなく親指を引っ掛けるようなものを3Dプリンターで作ったりして。。


終わりに

まぁそんなこんなで解説はしてみたもののコード部分に関しては分からないことが多いので参考にならない(というか間違ってる)部分も多いと思いますが、少しでも何かのお役に立てれば幸いです。

この記事が気に入ったらサポートをしてみませんか?