つれづれなる備忘録

日々の発見をあるがままに綴る

TinkercadによるArduinoシミュレーション16 ~ サーボモーターの制御

1. サーボモータ

 前回のDCモーターの制御に引き続き、サーボモーターの制御について紹介したい。サーボモーターとはサーボ機構を用いて、位置や速度を制御する用途に用いるモーターで、ロボットやホビー用とではラジコン等に使われている。電力駆動の方式としてはDCとACがあるが、Tinkercad上ではDCサーボモーターがモデルとして使用できる。

2. サーボモーターとの接続

 Tinkercad上のサーボモーターは2種類あるが、今回は黒い筐体のマイクロサーボを選択する。筐体上にSM-S2309Sと書かれており、サーボモーターの使い方 [Arduino]ではArduinoのStarter Kit付属しているサーボモーターのようである。前回一般的なDCモーターとArduinoを直接接続することは勧めなかったが、Starter Kitの含まれている物品で、かつ消費電流も小さいようなのでArduinoの5V端子に接続している。(Tinkercadのようなシミュレーターは破損の恐れはないので、シミュレーションだけであれば気にする必要はないが)

 サーボモーターの電力端子と接地端子をそれぞれArduinoの5VとGNDに接続する。信号線はArduinoの出力ピン2に接続して、信号が見えるようにオシロスコープも接続する。(下図参照)

サーボモーター接続
サーボモーター接続

3. スケッチ

 単純にサーボモーターを駆動させるスケッチを以下に示す。最初に#include<servo.h>としてサーボ制御用のライブラリをロードし、Servo servo;とすることでオブジェクトを宣言する。次にサーボモーターの信号線に接続する出力ピンをservo.attach(2);とすることで設定する。サーボモーターを指定の角度に動かすためには、例えばservo.write(0);とすれば角度0度に回転する。指定できる角度の範囲は0-180度までとなる。

#include <Servo.h>
Servo servo;
void setup()
{
servo.attach(2); //サーボ信号に接続するピンを指定
}

void loop()
{
servo.write(0); //サーボモーターの角度を0degに指定
delay(500);
servo.write(45);
delay(500);
servo.write(160);
delay(500);
}

上のスケッチを実行すると、0.5秒おきに0度、45度、160度の位置にモーターが回転する。サーボモーターに入力される信号の波形は以下のような矩形パルス波形で、パルス幅が長くなるほど回転する角度が大きくなる。なおパルス幅はデフォルトで0度のとき544usで180度のときは2400usになっている。パルス幅はservo.attach(pin,min,max);のmin,,maxの値を指定すれば変更できる。(Arduino 日本語リファレンス)

サーボ入力信号
サーボ入力信号

4. サーボモーターの入力制御

 応用としてユーザからの入力に応答してサーボモーターを動作させる方法を紹介する。接続に関しては上と同じで、スケッチを以下のようにする。

#include <Servo.h>
Servo servo;
int in_rot=0;
int t;
void setup()
{
Serial.begin(9600);
servo.attach(2);
servo.write(in_rot);
}

void loop()
{
if (Serial.available() > 0)
  {
    delay(20);
    byte data_size = Serial.available();
    byte buf[data_size]; //受信データサイズに応じて配列を定義
    
    if(data_size==1){
      buf[0]=Serial.read() - '0'; // ASCIIコードから数値に変換
      t=(int)buf[0];
      disp_deg(t);
      servo.write(t);
    }
    else if(data_size==2){
      buf[0]=Serial.read() - '0';
      buf[1]=Serial.read() - '0';
      t=(int)buf[0]*10+(int)buf[1]; //bufから数値に変換
      disp_deg(t);
      servo.write(t);
    }
     else if(data_size==3){
      buf[0]=Serial.read() - '0';
      buf[1]=Serial.read() - '0';
      buf[2]=Serial.read() - '0';
      t=(int)buf[0]*100+(int)buf[1]*10+(int)buf[2];
      disp_deg(t);
      servo.write(t);
    }
    else{
    }
  }

}
void disp_deg(int t){
     Serial.print("Input: ");
     Serial.print(t);
     Serial.println(" deg");
}

基本的にはシリアルモニタの入力窓に数値を入力したデータを受け取り、servo.write();サーボモータを動かせばよい。ただし、入力した数値は文字と認識されASCIIコードとして処理されてしまう。 (ASCII文字コード - IT用語辞典 e-Words)そこで受信したデータから'0'を引くことで'1'以降を数値に変換する。具体的にはSerial.read()-'0';とすればよい。また桁数が2以上だと、複数バイトのデータとして扱われる。例えば10っを入力すると'1' '0'と認識される。そこでdata_size=Serial.available()により何バイト受信したか調べ、バイト数に応じた配列buf[data_size]を定義する。さらに入力を1バイトづつ読み込みbuf[]に代入、桁が上がるごとに10をかけることで2桁以上の数値に直す。今回は数値が3桁までなので、スケッチ上はそのまま記述することにした。(for文を用いれば任意桁数で、もっとすっきりする)また入力エラー(例えば4桁入れる、小数点が入る)処理も行っていない。詳細はシリアルモニタから数値を送る – jumbleatを参照。

5. まとめ

今回はサーボモータの制御方法を紹介した。また応用としてシリアルモニタ下の入力窓の入力を数値に変換し、サーボモーターを動かす方法も紹介した。