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

ArduinoのセンサモジュールをPythonに反映させてみた

ArduinoのセンサモジュールをPythonに反映させてみた

授業でpythonでゲームを作ることになったので、コントローラをArduinoで自作しようと考えたのですが、細かい記事が見当たらなかったので投稿してみました。

参考記事

https://omoroya.com/arduino-lesson13/
https://shizenkarasuzon.hatenablog.com/entry/2018/09/29/180625#5byte%E5%9E%8B%E3%81%AE%E3%83%87%E3%83%BC%E3%82%BF%E3%82%92%E5%8F%97%E4%BF%A1

環境

・Arduino UNO
・Arduino IDE 1.8.13
・2軸ジョイスティックモジュール
https://akizukidenshi.com/catalog/g/gM-08763/
・python 3
・pyserial 3.5

Arduino側

const int X_PIN = A0;  // X軸方向の入力をアナログピンA0に
const int Y_PIN = A1;  // Y軸方向の入力をアナログピンA1に
const int SW_PIN = 2;  // センタースイッチの入力をデジタルピンD2に

byte X_POS ;   // X軸方向の読み取り値の変数をbyte型に
byte Y_POS ;   // Y軸方向の読み取り値の変数をbyte型に
byte SW_POS ;  // センタースイッチの読み取り値の変数をbyte型に

 void setup(){

   pinMode(X_PIN, INPUT);          // A0ピンを入力に(省略可)
   pinMode(Y_PIN, INPUT);          // A1ピンを入力に(省略可)
   pinMode(SW_PIN, INPUT_PULLUP);  // D2ピンをプルアップして入力に

   Serial.begin(115200); // シリアル通信の開始
   //Serial.begin(9600); 

}


 void loop(){

   X_POS = analogRead(X_PIN)/5;     // X軸方向のアナログ値を読み取る
   Y_POS = analogRead(Y_PIN)/5;     // Y軸方向のアナログ値を読み取る
   SW_POS = 1-digitalRead(SW_PIN);  // センタースイッチの状態を読み取る

   Serial.write('H');               //ヘッダー
   Serial.write(X_POS);
   Serial.write(Y_POS);
   Serial.write(SW_POS);


   delay(100);

 }

Arduinoとジョイスティックの接続についてはたくさん記事があるので省略します。
工夫した点は2つ。
1つ目はSerial.writeでシリアル通信にセンサー値を載せるときにbyte型にします。多くのサイトではArduino IDEのシリアルレポート機能を使うためにint型にしていますが、シリアル通信はbyte型でのやりとりが楽です。Serial.printにしてstring型で送ることも可能。
2つ目はヘッダーを付加することです。pythonでシリアル通信のデータを受け取る際、1つ目のデータはX座標、2つ目はY座標3つ目はスイッチと受け取りますが、通信ラグを考えると1つ目のデータはY座標、2つ目はスイッチ、3つ目はX座標と入れ替わった順番で送られてくる可能性があるため、ヘッダーを付加しました。

Python側

Pyserialを使います。

pip install pyserial

ゲーム内のコードがこちら。

import serial
class Game:
    def __init__(self):
        self.ser = serial.Serial('COM3', 115200, timeout = 0.1)
        self.serialheader='H'.encode('utf-8')

    def __del__(self):
        self.ser.close()

    def keyboard(self):
        while True:
            if self.ser.read() == self.serialheader:#ヘッダーを受け取った時、シリアル通信のデータを受け取る
                switchflag = False
                    joyx = int.from_bytes(self.ser.read() , 'big')#x座標を読み取ろ
                    joyy = int.from_bytes(self.ser.read() , 'big')#y座標を読み取り
                    switch=self.ser.read()                        #スイッチを読み取り
                    if  switch == b'\x01':             
                        switchflag=True
                    else:
                        switchflag=False

pyserialの基本的な使い方をしています。serial.Serialの引数ですが、pyserialのバージョンによってポートの書き方が異なるそうです。自分の場合は'COM+番号'(デバイスマネージャーに表示されるやつ)でした。

ヘッダーを受け取ったとき、シリアル通信を受信した順にX座標、Y座標、スイッチとデータを受け取ります。
また、繰り返し処理が重くならないように、スイッチのバイナリとヘッダーに関しては、あらかじめbyte型にencodeしたもので論理文を作成し、decodeの手間を極力省きました。

以上拙いものではございますが、Arduinoでジョイスティックの操作をpythonのゲームに反映させることができたので共有しておきます。

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