takminの書きっぱなし備忘録 @はてなブログ

主にコンピュータビジョンなど技術について、たまに自分自身のことや思いついたことなど

PySerial経由でArduinoが動かずに苦戦した件

最近Arduinoを触り始めていきなり躓いたのでメモ。

以下のような、シリアル通信で数値を受け取ってその角度だけサーボモータを動かすArduinoのデモプログラムを書きました。 環境はWindows11、Python3.12です。

#include <Servo.h>

Servo myservo;  // create servo object to control a servo

int pos = 0;    // variable to store the servo position

void setup() {
  Serial.begin(9600);
  myservo.attach(9);  // attaches the servo on pin 9 to the servo object
  myservo.write(pos);
}

void move_servo(int angle){
  if(angle < 0){
    for(int i = 0; i > angle && pos > 0; i -= 1){
      pos -= 1;
      myservo.write(pos);              // tell servo to go to position in variable 'pos'
      delay(15);                       // waits 15ms for the servo to reach the position
    }
  }
  else{
    for(int i=0; i < angle && pos < 180; i +=1){
      pos += 1;
      myservo.write(pos);              // tell servo to go to position in variable 'pos'
      delay(15);                       // waits 15ms for the servo to reach the position
    }
  }
}

void loop() {
  if(Serial.available()){
    int angle = Serial.parseInt();
    if(angle != 0){
      move_servo(angle);
    }
  }
}

Arduino IDEのからSerial Monitorから動かしたい角度を入力すると、その角度だけサーボが動くことは確認しました。

今度は、PySeriralを用いてPython経由で90度サーボを動かすプログラムを書きました。

import serial
import time

ser = serial.Serial('COM3', 9600)
ser.write("90".encode())  # 角度(文字列)をArduinoに送信
time.sleep(1)  # 1秒待つ
ser.close()

尚、このプログラムを動かす前にArduino IDEを閉じないとエラーが出ます。

ただし、このプログラムを走らせても、サーボは動かず、エラーも吐き出されません。

どうもArduino側の受信準備に時間がかかるようです。

そこで、

ser = serial.Serial('COM3', 9600)
time.sleep(2)  # 2秒待つ
ser.write("90".encode())  # 角度(文字列)をArduinoに送信
time.sleep(1)  # 1秒待つ
ser.close()

とシリアル通信前に2秒ほど待ち時間を設定したところうまくいきました。