Arduinoに用意されているサーボモータ制御クラスServoを利用しモータの角度設定設定ではなくパルス設定でサーボモータを動作させるプログラムを作って、クムクムロボット(R3J)を動かしてみる。

サーボモータについて

サーボモータ(Servo Motor)は、位置や角度を制御可能なモーターの一種です。一般的に、サーボモータは小型で精密な制御が可能で、ロボット、ラジコンカー、カメラのジンバル、ドローン、3Dプリンターなど、さまざまなアプリケーションで使用されています。サーボモータは、通常、以下の3つの主要な要素から構成されています。

  1. モーター: サーボモータの駆動力を提供する部分で電流を流すことで回転します。
  2. ポテンショメータ(位置センサー): モーターの回転位置を検出するためのセンサーで、これにより、サーボモータは指定した位置に正確に動かすことができます。
  3. 制御回路: アナログまたはデジタル信号を受け取り、モーターを正確な位置に動かすための制御を行います。Arduinoなどのマイコンボードを使用して制御できます。

サーボモーターの構造

乱数(ランダムな数値)を使って動きを楽しんでみる

今日のプログラミングでは、Arduinoの乱数を使ってモータの動きをランダムにしてみます。

乱数(Random Number)は、完全に予測不可能でランダムな値をコンピュータの仕組みによって発生させます。この乱数をプログラム内で使用することにより、さまざまなアプリケーションでランダムな要素を導入できます。
Arduinoでは、random()関数を使用して乱数を生成できます。

例えば、random(500, 2501)というコードによって、クムクムロボットが使うサーボモータのパルス範囲500から2500の範囲内で、ランダムな整数を生成します。しして、その発生させた乱数によるパルスでサーボモータにランダムなパルス幅を設定し動作させます。

クムクムサーボモータの角度とパルス

writeMicroseconds()関数について

writeMicroseconds()関数は、サーボモータの位置を指定するためのArduinoのServoライブラリの関数です。この関数を使用すると、サーボモータに対してマイクロ秒単位でパルス幅を設定できます。
一般的なサーボモータは、パルス幅によって角度が制御され、通常、パルス幅が小さいとサーボは一定の角度に、パルス幅が大きいと別の角度に移動します。例えば、writeMicroseconds(1500)とすると、サーボは中間の位置に移動します。
クムクムロボットでは180度回転をするサーボモータを使用しているので、1500は中間の90度の位置を示します。

サンプルプログラム

4番ピンから10番ピンに接続された複数のサーボモータの中から、0度から180度の間を自由に動かしても安全なモータである、腕2本・顔の合計3つのサーボモーターを制御してランダムな動きをさせます。

#include <Servo.h>

// サーボの数
const int numServos = 3; // サーボの数を設定(4番ピンから10番ピンまでの7つ)

// サーボのピン番号
int servoPins[numServos] = {4,7,10}; // サーボのピン番号を配列で指定

// サーボオブジェクトの配列
Servo servos[numServos];

void setup() {
  // サーボの初期化
  for (int i = 0; i < numServos; i++) {
      servos[i].attach(servoPins[i]);
  }
  // ランダムなシード値を設定
  randomSeed(analogRead(0));
  // シリアル通信の初期化
  Serial1.begin(9600);
}

void loop() {
  // 各サーボにランダムなパルス幅を設定
  for (int i = 0; i < numServos; i++) {
    int pulseWidth = random(500, 2501); // ランダムなパルス幅(500から2500の範囲)
    servos[i].writeMicroseconds(pulseWidth); // サーボにパルス幅を設定
  }
  // ランダムな時間待機
  int delayTime = random(100, 1001); // ランダムな待機時間(100から1000ミリ秒の範囲)
  delay(delayTime);
  // シリアルモニターにパルス幅を表示
  for (int i = 0; i < numServos; i++) {
    int pulseWidth = servos[i].readMicroseconds();
    Serial.print("Servo ");
    Serial.print(i);
    Serial.print(": ");
    Serial.print(pulseWidth);
    Serial.print(" us\t");
  }
  Serial1.println();
  // 短い待機時間を挿入(サーボの動きを見やすくするため)
  delay(500);
}

プログラムの説明

//サーボモータの初期化
const int numServos = 3; // サーボの数を設定(4番ピンから10番ピンまでの7つ)
int servoPins[numServos] = {4, 7, 10}; // サーボのピン番号を配列で指定
Servo servos[numServos];

まず、numServosという変数でサーボの数を指定し、servoPinsという配列で各サーボの接続ピン番号を指定します。
そして、この後で、Servoクラスのオブジェクトを配列として宣言し、各サーボに対応するピンにアタッチします。

//シリアル通信と乱数の初期化
randomSeed(analogRead(0)); // ランダムなシード値を設定
Serial.begin(9600); // シリアル通信の初期化

randomSeed()関数を使用して、ランダムな数値を生成する際のシード値を設定します。これにより、毎回異なるランダムな値が生成されます。また、シリアル通信を9600ボーに初期化しています。シリアル通信を使用することで、サーボモータの動作や乱数の生成結果をシリアルモニターで確認できるようにしました。

void loop() {
  // 各サーボにランダムなパルス幅を設定
  for (int i = 0; i < numServos; i++) {
    int pulseWidth = random(500, 2501); // ランダムなパルス幅(500から2500の範囲)
    servos[i].writeMicroseconds(pulseWidth); // サーボにパルス幅を設定
  }

  // ランダムな時間待機
  int delayTime = random(100, 1001); // ランダムな待機時間(100から1000ミリ秒の範囲)
  delay(delayTime);

  // シリアルモニターにパルス幅を表示
  for (int i = 0; i < numServos; i++) {
    int pulseWidth = servos[i].readMicroseconds();
    Serial.print("Servo ");
    Serial.print(i);
    Serial.print(": ");
    Serial.print(pulseWidth);
    Serial.print(" us\t");
  }
  Serial.println();
  // 短い待機時間を挿入(サーボの動きを見やすくするため)
  delay(500);
}
  1. for ループを使用して、各サーボにランダムなパルス幅を設定しています。乱数関数 random(500, 2501) を使用して、各サーボに500から2500マイクロ秒の範囲でランダムなパルス幅を生成し、servos[i].writeMicroseconds(pulseWidth) でサーボに設定します。これにより、各サーボが異なる位置に移動します。
  2. 次に、random(100, 1001) を使用してランダムな待機時間を生成し、delay() 関数を使ってその時間だけプログラムの実行を一時停止します。この部分により、サーボモータがランダムな位置に移動してから次の動作までの待機時間が設定されます。
  3. シリアルモニターに各サーボの現在のパルス幅を表示します。for ループを使用して、各サーボのパルス幅を servos[i].readMicroseconds() を使って読み取り、シリアルモニターに出力します。これにより、サーボの現在の位置情報をモニターで確認できます。
  4. 最後に、短い待機時間を挿入しています。これにより、サーボの動きが見やすくなります。

 

この loop() 関数内の処理が繰り返し実行され、複数のサーボモータがランダムな動きを続けることになります。

のプログラムをクムクム入門モデル(R3J)にアップロードし、シリアルモニターを開いて実行すると、3個のサーボモータが同時にランダムな動きだします。
各サーボのパルス幅が表示され、その位置情報にもとづいて手や腕が動くことが確認できます。

このサンプルプログラムを実行することで、サーボモータの制御、乱数の生成、そしてArduinoの基本的なプログラム構造について記述しました。サーボモータを使用したプロジェクトやロボットの制御に役立ってくれることを期待しています。