●サーボを動かす

サーボを動かしてみましょう。サーボの出力軸(白いギザギザのところ)は通常0°~180°の範囲で回転しますが、その位置はサーボの容器に対して絶対的に決まっています。そのため出力軸の回転位置を気にせずに適当にロボットを組み立ててしまうと、出力に取り付けられた部品が思い通りに動いてくれません。まずはサーボの出力軸を90°の位置に停止させるプログラムをつくります。

下の写真を参考に配線してください。サーボは電池から電源を供給する回路になっていますので、今回は電池をつなぎます。サーボは12個使いで対応するコネクタが12箇所ありますが、すべてのコネクタから90°の信号を出力します。サーボのコネクタは逆向きに挿しても動きませんが壊れることはありません。中央のピンがプラス電源となっているためです。一方、電池のワイヤーは逆につけるとマイコンが壊れますので絶対に間違えないでください。コネクター側基板上に"G"と記載されている側がグランド(黒線)です。
電源スイッチはOFF側にしておきます。
*サーボを取り扱う際の注意
サーボは非常に精密なギアで構成されています。出力軸を回そうとして(「バックドライブ」と言います。)引っ掛かりがある場合に無理に回そうとするとギアを破損します。

paperbots_mm_servo_bat

ハードウェアの準備ができましたらプログラムを作っていきます。通常Arduinoでサーボを動かす場合専用の関数を使って簡単に駆動できるのですが、今回サーボが12個と多いので「PCA9685」というICを利用してATMEGA328マイコンからI2Cで制御するようにします。
Arduino IDEを起動して「ボード」と「シリアルポート」の設定をしてください。
下記のプログラムを書き込みます。

#include <Wire.h>

int16_t tempAngles[12] = {90,90,90,90,90,90,90,90,90,90,90,90};
const uint8_t oePin = 15;  //PCA9685の出力許可(Low active)

void init_pca9685() {
  Wire.beginTransmission(0x40);
  Wire.write(0x0);
  Wire.write(0x80);   //reset device
  Wire.endTransmission();
  
  Wire.beginTransmission(0x40);
  Wire.write(0x0);
  Wire.write(0x10);   //sleep mode
  Wire.endTransmission();
  
  Wire.beginTransmission(0x40);
  Wire.write(0xFE);
  Wire.write(0x65); //set prescaler to 60Hz
  Wire.endTransmission();
  
  Wire.beginTransmission(0x40);
  Wire.write(0x0);
  Wire.write(0x80);   //back to prev mode
  Wire.endTransmission();
  
  Wire.beginTransmission(0x40);
  Wire.write(0x0);
  Wire.write(0xa0);   //enable auto-increment
  Wire.endTransmission();
}

void set_angle() {
  int angle;
  for(int i=0;i<12;i++){
    angle = 400 + (tempAngles[i] - 90)*2.8;
    Wire.beginTransmission(0x40);
    Wire.write(6+i*4);
    Wire.write(0x0);       //led_on lower byte
    Wire.write(0x0>>8);    //led_on upper byte
    Wire.write(angle);     //led_off lower byte
    Wire.write(angle>>8);  //led_off upper byte
    Wire.endTransmission();
  }
}

void setup() {
  // put your setup code here, to run once:
  Wire.begin(21,22);
  Wire.setClock(100000);

  init_pca9685();
  set_angle();
  
  pinMode(oePin, OUTPUT);
  digitalWrite(oePin,LOW);
}

void loop() {
  // put your main code here, to run repeatedly:

}

チェックボタンでコンパイルが成功したら、矢印ボタンでメイン基板に書き込みます。「ボードへの書き込みが完了しました。」と出たら基板の電源スイッチをONにします。サーボが動いて90°の位置(センター位置)で停止します。(新品のサーボを用いた場合はもともと90°の位置になっていて動かない場合があります。)

●プログラムの説明

プログラムの内容的にはPCA9685とのI2C通信に関する部分がほとんどです。PCA9685のデータシート回路図を参照しながら確認してください。初学者の方はsetup()の部分だけを見ておけばOKです。

#include <Wire.h>

ArduinoでI2C通信を使う時にはプログラムの最初にこの行を書きます。Arduino IDEにあらかじめ用意されている"Wire.h"というファイルに実際にI2Cをコントロールするプログラムが書かれていて、我々は簡単にI2Cを使えるようになっています。

void setup() {
  // put your setup code here, to run once:
  Wire.begin();
  Wire.setClock(100000);

I2C通信を使えるようにします。100kHzの周波数で使用します。

  init_pca9685();
  set_angle();

サーボ駆動用のIC PCA9685をイニシャライズし、角度を設定します。角度はグローバル変数としてtempAngles[12]で保持しています。

  pinMode(oePin, OUTPUT);
  digitalWrite(oePin,LOW);

15ピンをLOWにしてPCA9685を有効化します。(データシート P6)

今回はサーボを一度動かして終わりなのでloop()は何もしません。

void set_angle() {
  int angle;
  for(int i=0;i<12;i++){
    angle = 400 + (tempAngles[i] - 90)*2.8;
    Wire.beginTransmission(0x40);
    Wire.write(6+i*4);
    Wire.write(0x0);       //led_on lower byte
    Wire.write(0x0>>8);    //led_on upper byte
    Wire.write(angle);     //led_off lower byte
    Wire.write(angle>>8);  //led_off upper byte
    Wire.endTransmission();
  }
}

PCA9685データシートのP10~P17を参照してください。
I2C通信はWire.beginTransmission(0x40)~Wire.endTransmission()で一区切りです。0x40はこのデバイス(PCA9685)のアドレスです。まずWire.write(6)でP10の表の6行目を指定します。forループの中のWire.write()はP10の表の6-9行目に対して実行され、サーボ#0(LED0と表記)のパルス立ち上がりタイミングと立ち下がりタイミングを指定します。
なお表の上の行から順番に実行されるのは、init_pca9685()の中でenable auto-incrementを指定していることによります。
サーボに与えるパルスは通常15-20msec周期でONパルス幅1.5msecで90°(センター位置)となります。init_pca9685()の中でPWM周波数を60Hzに設定していて1周期のカウント数が4095となっていますので、パルス幅が1.5msecとなるカウント数は369となります。プログラム中のangle=の式は、サーボの可動範囲のセンターが90°となるように実測して決めた変換式です。
forループでこれを12回まわしてすべてのサーボの角度を設定していきます。

●往復運動させる
loop()の中身を書き換えてサーボを往復運動させてみます。#0サーボ(P2コネクタ)のみ動かします。プログラムの意味はわかると思います。

void loop() {
  // put your main code here, to run repeatedly:
  tempAngles[0] = 80;
  set_angle();
  delay(1000);
  tempAngles[0] = 100;
  set_angle();
  delay(1000);
}

#0サーボがセンター位置を中心に往復運動することを確認してください。そのままでは見えませんのでサーボホーンを取り付けてください。

●デバッグの方法
サーボとは直接関係ありませんが、プログラムが思い通りに動かない時などに原因を調べるひとつの方法です。
上のプログラムに少し追加します。

void setup() {
  // put your setup code here, to run once:
  Wire.begin();
  Wire.setClock(100000);

  init_pca9685();
  set_angle();
  
  pinMode(oePin, OUTPUT);
  digitalWrite(oePin,LOW);
  Serial.begin(9600);  //追加
}

void loop() {
  // put your main code here, to run repeatedly:
  tempAngles[0] = 80;
  set_angle();
  Serial.print("angle=80\n");  //追加
  delay(1000);
  tempAngles[0] = 100;
  set_angle();
  Serial.print("angle=100\n");  //追加
  delay(1000);
}

このプログラムをメイン基板に転送して実行し、Arduino IDEの「ツール」->「シリアルモニタ」からシリアルモニタを起動します。Serial.print()に書いた内容が1000msごとに出てくると思います。(出てこない場合は画面下で9600bpsを選択)このように実行中のプログラムの状況を調べることができます。

最後にloop()の中をすべてコメントアウト(/* ... */)して12個すべてのサーボを90°の位置に戻してサーボホーンを外しておいてください。

今回の成果は"mm03"などとして保存しておきましょう。

<= PAPERBOTS マイクロマシーン チュートリアル(2)
チュートリアルベース
PAPERBOTS マイクロマシーン チュートリアル(4) =>