「M5Atomで作る歩行ロボット」という本の犬型ロボットの製作記です。

サーボをバッテリーを使ってマイコンM5Atomで動かすテストをしました。

バッテリーにソケットを接続

6Vバッテリー(Gecoty Ni-MHバッテリー Amazonで購入) には、充電用のUSBケーブルもついて来ましたが(写真右上)、使用するときにバッテリーにつなげられるソケットがありません。引き出しを探したところ、写真左上のような同じUSBケーブルが出てきたので、このソケット部分を利用することにしました。

下のように加工しました(切っただけ)。これで、バッテリーの使用時と充電時で取り外しができます。

電源 DCDCコンバータの調整

6Vのバッテリーは12個のサーボを動かすために、電圧が変動するとのことで直接M5Atomを動かすのではなく、いったんDCDCコンバーター LXDCSS で安定した4Vの電源を作って、供給することになります。

DCDCコンバーター LXDCSS の基板の上に取り付けた青いパーツのねじ部分を回すことで、出力の電圧を調節することができます。

テスターで出力電圧をモニターしながらねじ部分を回すことで、6Vの供給電圧に対して、4Vを出力するように調整しました。

サーボとの接続

回路をサーボモーターに接続しました。サーボモーターは12個もあるので配線がすごいです。あとはバッテリーの赤いケーブルを投げると電源が投下されます。

サーボの動作確認のためのマイコンのプログラム

12個ものサーボをマイコン(M5Atom Matrix)で直接動かすことができないために、サーボドライバー(PCA9685)を使います。

マイコンからサーボドライバーには、I2Cで通信します。

サーボドライバー用のライブラリーにはいろいろあるようなのですが、本で紹介している秋月電子通商のものがなぜか使えなかったので(zipファイルを追加時にエラーが出る、ファイルが違っている?)、Adafruit-PWM-Servo-Driver-Library というものを使いました。

これは、Arduion IDEのライブラリマネージャーに登録されているので、簡単にインストールできました。

これを使って、1番目の端子につなげたサーボを10度の幅で動かすことができました。

#include "M5Atom.h"
#include <Wire.h>          // I2C setting
#include <Adafruit_PWMServoDriver.h>

Adafruit_PWMServoDriver pwm = Adafruit_PWMServoDriver();

#define SERVOMIN 104    //Min pulse width (12bit 500μs) 
#define SERVOMAX 512    //Max pulse width (12bit 2500μs) 
#define DIGMIN -9000    // -90deg x 100
#define DIGMAX 9000     //  90deg x 100

void setup()
{
  Wire.begin(19, 22); //SDA-19, SCL-22
  pwm.begin();        //initial setting (for 0x40) (PCA9685)
  pwm.setPWMFreq(50); //PWM 50Hz (for 0x40) (PCA9685)

  M5.begin(true, true, true);
  delay(50);
  M5.dis.drawpix(0, 0x00ff00); // LED green

  Serial.begin(19200);
}

int count = 0;
int dir = 1;

void loop()
{
  // count を0から10まで増加させ、0まで減少させるを繰り返す
  count += dir;
  if (count >= 10) {
    dir = -1;
    M5.dis.drawpix(0, 0x0000ff); // LED blue
  } else if (count <= 0) {
    dir = 1;
    M5.dis.drawpix(0, 0x000000); // LED black
  }

  servo_set(0, count * 1.0);
  delay(100);
}

void servo_set(int i, float angle)
{
  int srv_ang = map(100 * angle, DIGMIN, DIGMAX, SERVOMIN, SERVOMAX);
  pwm.setPWM(i, 0, srv_ang);
}
Code language: C++ (cpp)

これを拡張して、12個のサーボを同時に動かすことも次のプログラムでできました。

#include "M5Atom.h"
#include <Wire.h>          // I2C setting
#include <Adafruit_PWMServoDriver.h>

Adafruit_PWMServoDriver pwm = Adafruit_PWMServoDriver();

#define SERVOMIN 104            //Min pulse width (12bit 500μs) 
#define SERVOMAX 512            //Max pulse width (12bit 2500μs) 
#define DIGMIN -9000    // -90deg x 100
#define DIGMAX 9000     //  90deg x 100

int SrvAng[12] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
float TARGET_JOINT_POSITIONS[12] = {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0};
float TRIM[12] = {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0};

void setup()
{
  Wire.begin(19, 22); //SDA-19, SCL-22
  pwm.begin();                   //initial setting (for 0x40) (PCA9685)
  pwm.setPWMFreq(50);            //PWM 50Hz (for 0x40) (PCA9685)

  M5.begin(true, true, true);
  delay(50);
  M5.dis.drawpix(0, 0xff0000); // LED

  Serial.begin(19200);
}


int count = 0;
int dir = 1;

void loop()
{
  // count を0から10まで増加させ、0まで減少させるを繰り返す
  count += dir;
  if (count >= 10) {
    dir = -1;
    M5.dis.drawpix(0, 0x0000ff);
  } else if (count <= 0) {
    dir = 1;
    M5.dis.drawpix(0, 0x000000);
  }
  // JOINT の単位が度だとする 
  for (int i = 0; i <= 11; i++){
    TARGET_JOINT_POSITIONS[i] = count * 1.0;
  }
  servo_set();
  delay(50);
}


void servo_set()
{
  for (int i; i <= 11; i++) {
    int srv_ang = 100 * (TARGET_JOINT_POSITIONS[i] + TRIM[i]);
    SrvAng[i] = map(srv_ang, DIGMIN, DIGMAX, SERVOMIN, SERVOMAX);
    pwm.setPWM(i, 0, SrvAng[i]);
  }
}
Code language: C++ (cpp)

こんな感じに動きました。

https://youtu.be/g4zyxEbf4sY