Arduinoで複数のサーボを動かす(PCA9685)

はじめに

以前にも同様のことをしました。
touch-sp.hatenablog.com
今回はサーボドライバを購入したので使用してみました。
購入したのはこちらです。
PCA9685搭載16チャネル PWM/サーボ ドライバー (I2C接続)www.switch-science.com

動作環境

Windows10 Pro
Python 3.8.8
Arduino IDE 1.8.15
Arduino Uno R3

Pythonパッケージ

インストールするのは「pyserial」のみです。pipでインストール可能です。

pyserial==3.5

モーションの作成

次のようなテキストファイルを用意します。
ファイル名は「motion.txt」、区切りはタブ。
1行ごとにサーボの角度が記載されています。(この場合サーボは2つ)

servo1	servo2
90	90
20	160
160	20
60	120
160	110
20	100
90	90

Pythonコード

import serial, time

with open('motion.txt') as f:
    lines = [s.strip() for s in f.readlines()[1:]]

print("Open Port")
ser =serial.Serial("COM6", 9600)
time.sleep(1.5)

for i in range(len(lines)):
    
    x = lines[i].split()
    x = [int(i) for i in x]
    x = [179 if i > 179 else i for i in x]
    x = [0 if i < 0 else i for i in x]

    #servoは200からカウントすることとする
    #servoの角度は0~179
    #サーボ番号と角度がバッティングすることはない
    servo_1_id = (200).to_bytes(1, 'big')
    servo_2_id = (201).to_bytes(1, 'big')

    servo_1_angle = (x[0]).to_bytes(1, 'big')
    servo_2_angle = (x[1]).to_bytes(1, 'big')

    ser.write(servo_1_id)
    ser.write(servo_1_angle)
    
    ser.write(servo_2_id)
    ser.write(servo_2_angle)

    time.sleep(2)

print("Close Port")
ser.close()

Arduinoスケッチ

#include <Wire.h>
#include <Adafruit_PWMServoDriver.h>

#define SERVOMIN 180 // this is the 'minimum' pulse length count (out of 4096)
#define SERVOMAX 420 // this is the 'maximum' pulse length count (out of 4096)

#define servo_count 2

Adafruit_PWMServoDriver pwm1 = Adafruit_PWMServoDriver(0x40);

void setup() {
  Serial.begin(9600);
  pwm1.begin();
  pwm1.setPWMFreq(50);  // This is the maximum PWM frequency;
}

void loop() {
  if(Serial.available()> (2*servo_count-1)){
    int servo_no;
    int servo_angle;
    for(int i=0; i<servo_count; i++){
      servo_no = Serial.read();
      if(servo_no > 199){
        servo_angle = Serial.read();
        if(servo_no==200){
          servo_write(0, servo_angle);
        }
        if(servo_no==201){
          servo_write(1, servo_angle);
        }
      }
    }
    delay(200);
  }
}

void servo_write(int ch, int ang){
  ang = map(ang, 0, 180, SERVOMIN, SERVOMAX);
  pwm1.setPWM(ch, 0, ang);
}

スケッチ内に出てくる「SERVOMIN」「SERVOMAX」はサーボによって異なるようです。一般的には150, 600が多いようですが今回使用したサーボは180, 420がちょうどよい値でした。
使用したサーボはVstone社製の「VS-S092J」というものです。現在は製造中止になっています。

最後に

touch-sp.hatenablog.com
以前Arduinoでラジコンを作ったら思いのほか良い動きをしたので少し電子工作に自信がつきました。電子工作を初めて約1年です。
いずれは2足歩行ロボットの作成にチャレンジしたいと思っています。