2
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

パソコンにUSB接続したゲームパッド(方向キー、複数ボタン)と、Arduino nanoの通信

2
Posted at

複数のボタンや方向キーの情報を同時に送るには、「データをカンマ(,)で区切った1つの文字列」にして送信し、Arduino側でそれを分解して読み取る方法(CSV形式)が確実で簡単です。

例えば、方向キーのX軸、Y軸、ボタン0〜3の状態を 1,0,1,0,0,0\n のようなテキストデータとして送受信します。

以下に、方向キー(D-pad)とボタン0〜3(A, B, X, Yなど)をPCから送信し、Arduinoで受信して各変数に格納するプログラムを作成しました。

Arduino側のプログラム(C++)
送られてきたカンマ区切りの文字列を読み取り、sscanf という関数を使って6つの変数(X軸、Y軸、ボタン4つ)に切り分けます。

.c++
// PCからカンマ区切りのデータを受信し、各ボタン・キーの状態を読み取るプログラム

void setup() {
  Serial.begin(9600);
  // 文字列の読み取り待ち時間(タイムアウト)を短くして動作の遅れを防ぐ
  Serial.setTimeout(20); 
}

void loop() {
  // PCからデータが届いているか確認
  if (Serial.available() > 0) {
    // 改行コード ('\n') が来るまで文字列として読み取る
    String msg = Serial.readStringUntil('\n');

    // 読み取ったデータを入れる変数
    int dpad_x = 0;
    int dpad_y = 0;
    int btn0 = 0;
    int btn1 = 0;
    int btn2 = 0;
    int btn3 = 0;

    // sscanfを使って、カンマ区切りの文字列から6つの整数(%d)を抽出する
    // うまく6つのデータが取り出せた場合のみ処理を実行
    if (sscanf(msg.c_str(), "%d,%d,%d,%d,%d,%d", &dpad_x, &dpad_y, &btn0, &btn1, &btn2, &btn3) == 6) {
      
      // ==========================================
      // ここにモーターやLEDを動かす処理を書きます
      // ==========================================
      
      // 【テスト用】受信したデータをPCに送り返す(Python側で表示させるため)
      Serial.print("受信成功 -> ");
      Serial.print("方向X:"); Serial.print(dpad_x);
      Serial.print(" 方向Y:"); Serial.print(dpad_y);
      Serial.print(" B0:"); Serial.print(btn0);
      Serial.print(" B1:"); Serial.print(btn1);
      Serial.print(" B2:"); Serial.print(btn2);
      Serial.print(" B3:"); Serial.println(btn3);
    }
  }
}

PC側のプログラム(Python)
Pygameでは、一般的な十字の方向キーは「ハットスイッチ(Hat)」として認識され、(X軸, Y軸) のタプル形式(-1, 0, 1 のいずれか)で取得できます。これをボタンの情報と合体させて送信します。

.py
import pygame
import serial
import time

# --- 環境に合わせて書き換える設定 ---
COM_PORT = 'COM3' # Mac/Linuxの場合は '/dev/tty.usbserial-XXXX' など
BAUD_RATE = 9600

# シリアル通信の初期化
try:
    ser = serial.Serial(COM_PORT, BAUD_RATE, timeout=0.1)
    time.sleep(2) # Arduinoの再起動待ち
    print("Arduinoと接続しました!")
except serial.SerialException:
    print(f"エラー: {COM_PORT} が開けません。")
    exit()

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

if pygame.joystick.get_count() == 0:
    print("ゲームパッドが接続されていません。")
    ser.close()
    exit()

joystick = pygame.joystick.Joystick(0)
joystick.init()
print(f"{joystick.get_name()}」を使用します。")
print("方向キーとボタン0〜3を操作してください。ターミナルにArduinoからの返信が表示されます。")
print("終了するには Ctrl+C を押してください。")

try:
    while True:
        pygame.event.pump() # ゲームパッドの状態を更新

        # 方向キー(ハットスイッチ)の状態を取得
        # hat_data は (X, Y) の形式。左が-1、右が1、上が1、下が-1(※コントローラーによる)
        if joystick.get_numhats() > 0:
            hat_data = joystick.get_hat(0)
            dpad_x = hat_data[0]
            dpad_y = hat_data[1]
        else:
            dpad_x, dpad_y = 0, 0 # ハットスイッチが無い場合

        # ボタン0〜3の状態を取得 (押していれば 1, 離していれば 0)
        btn0 = joystick.get_button(0)
        btn1 = joystick.get_button(1)
        btn2 = joystick.get_button(2)
        btn3 = joystick.get_button(3)

        # データをカンマ区切りの文字列にする(最後に改行 \n を入れる)
        # 例: "1,0,1,0,0,0\n"
        send_str = f"{dpad_x},{dpad_y},{btn0},{btn1},{btn2},{btn3}\n"
        
        # Arduinoへ送信(バイト列に変換して送る)
        ser.write(send_str.encode('utf-8'))

        # 【デバッグ用】Arduinoから送り返されてきた文字があれば画面に表示する
        while ser.in_waiting > 0:
            response = ser.readline().decode('utf-8', errors='replace').strip()
            print(response)

        # データの送りすぎを防ぐため、少し待機 (0.05秒 = 秒間20回送信)
        time.sleep(0.05) 

except KeyboardInterrupt:
    print("\nプログラムを終了します。")
finally:
    ser.close()
    pygame.quit()

動作確認のポイント
Pythonのプログラムを動かしている間は、Arduino IDEの「シリアルモニタ」は開けません(通信ポートの取り合いになるため)。

そのため、この構成ではArduino側で Serial.print した内容を、Python側が読み取ってターミナル(黒い画面)に表示する仕組みにしてあります。方向キーやボタンを押して、ターミナルに 受信成功 -> 方向X:1 方向Y:0 B0:1... のように表示されれば、Arduinoまでデータが完璧に届いています。

2
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?