サーボモータを複数同時に同期させる | arduinoロボットプログラミング

2023年12月3日

arduinoのC言語プログラミングによって、複数のサーボモータをそれぞれ異なった角度に指定した時間かけて同時に動かす方法を、クムクムロボット入門モデル(R3J)の両手と顔のモータを使って作ってみます。

サーボモータの接続ピンと制御の基本

まずは、クムクムロボットのどのピンにどのモータが接続されているかを確認しておきます。

クムクムメイン基板のサーボモータ番号

次にクムクムロボットの場合、モータへの電源供給を行うためのポート(11)制御が必要なのでこれを忘れないようにします。

プログラム

#include <Servo.h>

Servo servo1; // 4番ピンに接続されたサーボモータ
Servo servo2; // 7番ピンに接続されたサーボモータ
Servo servo3; // 10番ピンに接続されたサーボモータ

int angle1 = 0; // サーボ1の初期角度(0度)
int angle2 = 0; // サーボ2の初期角度(0度)
int angle3 = 0; // サーボ3の初期角度(0度)
int targetAngle1 = 90; // サーボ1の目標角度(90度)
int targetAngle2 = 180; // サーボ2の目標角度(180度)
int targetAngle3 = 150; // サーボ3の目標角度(150度)
unsigned long startTime; // タイマー開始時刻

void setup() {
  pinMode(11,OUTPUT) ;  //電源供給ピン
  digitalWrite(11,HIGH); //電源供給ON
  servo1.attach(4); // 4番ピンに接続されたサーボをサーボ1として初期化
  servo2.attach(7); // 7番ピンに接続されたサーボをサーボ2として初期化
  servo3.attach(10); // 10番ピンに接続されたサーボをサーボ3として初期化
  servo1.write(angle1); // サーボ1を初期位置に設定
  servo2.write(angle2); // サーボ2を初期位置に設定
  servo3.write(angle3); // サーボ3を初期位置に設定
  startTime = millis(); // タイマー開始時刻を設定
 
}

void loop() {
  unsigned long currentTime = millis(); // 現在の時刻を取得
  if (currentTime - startTime < 5000) { // 5秒間実行
  // サーボ1を0度から90度に動かす
  angle1 = map(currentTime - startTime, 0, 5000, 0, targetAngle1);
  servo1.write(angle1);

  // サーボ2を0度から180度に動かす
  angle2 = map(currentTime - startTime, 0, 5000, 0, targetAngle2);
  servo2.write(angle2);

  // サーボ3を0度から150度に動かす
  angle3 = map(currentTime - startTime, 0, 5000, 0, targetAngle3);
  servo3.write(angle3);
  }
}

説明

#include <Servo.h>

この行は、Servo ライブラリをインクルードしています。Servo ライブラリは、サーボモータを制御するために使用されます。このライブラリを使用することで、サーボモータを簡単に制御できます。

Servo servo1; // サーボ1の制御用オブジェクト
Servo servo2; // サーボ2の制御用オブジェクト
Servo servo3; // サーボ3の制御用オブジェクト

これらの行は、各サーボモータに対するServoオブジェクトを作成します。各オブジェクトは、特定のサーボモータを制御するために使用されます。

int angle1 = 0; // サーボ1の現在の角度(初期値:0度)
int angle2 = 0; // サーボ2の現在の角度(初期値:0度)
int angle3 = 0; // サーボ3の現在の角度(初期値:0度)
int targetAngle1 = 90; // サーボ1の目標角度(90度)
int targetAngle2 = 180; // サーボ2の目標角度(180度)
int targetAngle3 = 150; // サーボ3の目標角度(150度)

これらの変数は、各サーボの現在の角度と目標の角度を管理します。たとえば、angle1はサーボ1の現在の角度を表し、targetAngle1はサーボ1の目標角度を表します。初期状態ではすべてのサーボが0度に設定されています。

unsigned long startTime; // タイマー開始時刻

startTime変数は、タイマーの開始時刻を記録します。この時刻を基準にして、サーボの角度変化を制御します。

void setup() {
  pinMode(11,HIGH);
  digitalWrite(11,HIGH);
  servo1.attach(4); // サーボ1を4番ピンに接続
  servo2.attach(7); // サーボ2を7番ピンに接続
  servo3.attach(10); // サーボ3を10番ピンに接続

  servo1.write(angle1); // サーボ1を初期位置に設定
  servo2.write(angle2); // サーボ2を初期位置に設定
  servo3.write(angle3); // サーボ3を初期位置に設定

  startTime = millis(); // タイマー開始時刻を記録
}

setup()関数は、Arduinoが起動したときに1度だけ実行されます。この関数内で、サーボモータの初期設定を行います。

  • servo1.attach(4)servo2.attach(7)servo3.attach(10):各サーボモータを対応するピンに接続します。例えば、servo1は4番ピン(4)に接続されています。
  • servo1.write(angle1)servo2.write(angle2)servo3.write(angle3):各サーボモータを初期位置に設定します。初期位置は0度です。
  • startTime = millis():タイマーの開始時刻を現在の時間(ミリ秒単位)で記録します。
void loop() {
  unsigned long currentTime = millis(); // 現在の時刻を取得

  if (currentTime - startTime < 5000) { // 5秒間実行
  // サーボ1を0度から90度に動かす
  angle1 = map(currentTime - startTime, 0, 5000, 0, targetAngle1);
  servo1.write(angle1);

  // サーボ2を0度から180度に動かす
  angle2 = map(currentTime - startTime, 0, 5000, 0, targetAngle2);
  servo2.write(angle2);

  // サーボ3を0度から150度に動かす
  angle3 = map(currentTime - startTime, 0, 5000, 0, targetAngle3);
  servo3.write(angle3);
  }
}

loop()関数は、Arduinoがプログラムを繰り返し実行する部分です。この関数内で、サーボモータの角度変化を制御します。

  • unsigned long currentTime = millis():現在の時間(ミリ秒単位)を取得し、currentTime変数に格納します。
  • if (currentTime - startTime < 5000):5秒間(5000ミリ秒)の間、以下のコードを実行します。
  • angle1 = map(currentTime - startTime, 0, 5000, 0, targetAngle1)map()関数を使用して、angle1変数を時間に応じて変化させます。これにより、サーボ1が0度から90度に徐々に動きます。
  • 同様に、angle2angle3も時間に応じて目標角度に変化させ、servo2servo3を制御します。

このプログラムをArduinoにアップロードし、実行すると、3つのサーボモータが同時に動き、それぞれ指定された目標角度に徐々に移動します。サーボモータの制御は、angle1angle2、およびangle3変数を時間に応じて変化させることで実現されます。

もう少し詳細な説明を続けます。

タイマーを使用した同時制御

このプログラムでは、loop()関数内のif文によって、時間の経過に応じてサーボモータの角度が変化します。具体的には、millis()関数を使用して現在の時間を取得し、startTime(タイマー開始時刻)からの経過時間に応じてサーボモータの角度を計算します。このようにすることで、3つのサーボモータが同じ時間に動作し、同時に目標角度に到達します。

map() 関数の使用

map()関数は、ある範囲の値を別の範囲の値に変換するのに役立ちます。このプログラムでは、map()関数を使用して時間に応じてサーボモータの角度を変化させています。例えば、次のコードはサーボ1の角度を変化させます:

angle1 = map(currentTime - startTime, 0, 5000, 0, targetAngle1);

この行では、currentTime - startTime(経過時間)を0から5000の範囲から、0からtargetAngle1(目標角度)の範囲に変換しています。これにより、0から目標角度までの範囲でangle1が変化し、サーボ1が指定した目標角度に達します。

タイマー割り込みについて

このプログラムでは、タイマー割り込みを明示的に使用しているわけではありませんが、millis()関数を使用することで、時間経過を制御しています。millis()関数は、Arduino内部でタイマー割り込みを使用して時間を追跡します。

サーボライブラリの利用

Servo ライブラリは、サーボモータを簡単に制御するために使用されています。このライブラリを使用することで、サーボの角度を指定するだけで、サーボの位置を制御できます。

これらの要点を理解することで、Arduinoを使用してサーボモータを制御する基本的な方法についての理解が深まるはずです。プログラム内で使用されている各部分の役割を把握し、必要に応じてカスタマイズできるようになります。