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