サーボモータの制御

サーボモーター はPWM制御を用いて、任意の角度まで回転させることができるモーターで、ロボットアームなど精密な動作が必要な時に使われます。ロボットアームは複数のサーボモーターを組み合わせることにより、自由度が増え、複雑な動きをすることが可能となります。

ロボットの動きが複雑になるほど、必要なサーボモーターの数が5個、10個と増えてきますが、1つのサーボモーターに対し1つのPWMピンで制御するのは限界があります。

PCA9685のすすめ

そこで、i2c通信とPCA9685という複数のPWM制御ができるコントローラを用いて、2つのピンを用いるだけで数十個のサーボモータ を制御する方法を解説します。

購入はこちらから

https://rb-station.com/products/pca9685-16%E3%83%81%E3%83%A3%E3%83%B3%E3%83%8D%E3%83%AB-%E3%82%B5%E3%83%BC%E3%83%9C%E3%83%A2%E3%83%BC%E3%82%BF%E3%82%B3%E3%83%B3%E3%83%88%E3%83%AD%E3%83%BC%E3%83%A9

 

i2c通信とはSCLとSDAの2つのピンだけで複数のモジュールと通信ができるインターフェースで、モジュールを増やしていく際にピンの数を増やさないで済ませられるメリットがあります。

Raspberry Piでのi2c通信有効化については、下記記事をご参考ください。

https://rb-station.com/blogs/article/raspberry-pi-i2c-activation

 

PCA9685の各部位の説明

上図の下側に0から15の番号がついており、これらがPWM制御用の端子となっていて、サーボモータを繋いでいく形となります。

各接続部の用途は下記になります。

  • SCL/SDA: i2c通信用のピンです。Raspberry Pi側のSCL/SDAに繋ぎましょう。
  • VCC/GND: Raspberry Piの電源とGNDに繋ぎましょう。
  • PWM/V+/GND: 16対あるPWM制御のピンです。ピンの隣に0〜15の数値が記載されており、これがチャンネルの番号になります。サーボモーターの駆動電圧が5Vの場合は、このV+/GNDに繋ぎ、それ以上の電圧の場合は、別途駆動電源を用意すると良いかと思います。

PCA9685とサーボモータ ーの接続

上記はサーボモーターを2つ繋いだ時の回路の例になります。駆動電圧は5Vを例としているので、PWMピンの隣にあるV+/GNDをサーボモーターの駆動電圧として用いています。

PCA9685の制御コード

Adafruit社が下記レポジトリにて公開しているpythonのライブラリを使いましょう。

https://github.com/adafruit/Adafruit_Python_PCA9685

README.mdに従い、インストール

sudo apt-get install git build-essential python-dev
cd ~
git clone https://github.com/adafruit/Adafruit_Python_PCA9685.git
cd Adafruit_Python_PCA9685
sudo python setup.py install

 

i2c通信時のアドレスは下記コマンドで確認できます。調べた際は0x40になりましたので、0x40をコード上で指定していきます。

sudo i2cdetect -y 1

 

servo_motor.py

import Adafruit_PCA9685

class ServoMotor:

    def __init__(self, Channel, ZeroOffset):
        self.mChannel = Channel
        self.m_ZeroOffset = ZeroOffset

        #initialize PCA9685
        self.mPwm = Adafruit_PCA9685.PCA9685(address=0x40) 
        self.mPwm.set_pwm_freq(60) # 60Hz

    def setAngle(self, angle):
        pulse = int((650-150)*angle/180+150+self.m_ZeroOffset)
        self.mPwm.set_pwm(self.mChannel, 0, pulse)

    def cleanup(self):
        self.setAngle(10)

main.py

from servo_motor import ServoMotor

servoMotors = []

servoMotors.append(ServoMotor(Channel=0, ZeroOffset=0))
servoMotors.append(ServoMotor(Channel=1, ZeroOffset=0))

servoMotors[0].setAngle(60)
servoMotors[1].setAngle(100)

こちらは、サーボモーターを2つ接続し、それぞれの角度を60 度と100度に回転させるというコードになっています。

I2cサーボモータ