Mira&Luna's nursery lab

旅乙女と発明娘の子供部屋

サーボモータのスピードを制御します。ライブラリは使いません(∂_∂🎀/

f:id:miraluna:20200223191041j:plain:w150 Mira

<目次>
速度制御に便利なライブラリ
ペンギンのパルス幅をキャリブレート(校正)
  ・ サーボモータの仕組み
  ・ セットアップ
  ・ キャリブレート(ちょうどいいパルス幅を見つける)
Sketch(code)
回転の速度調整
短い動画


f:id:miraluna:20190609183245j:plain

これはサーボモータの「SG90」。私はよく「ペンギン」って呼んでる。ペンギンっぽいでしょ? ......。でしょ?

今回はこのサーボモータの回転の速度をライブラリを使わずに制御したいと思います。
前回までの記事ではサーボのプログラム制御と、可変抵抗による操作を書きました。
miraluna.hatenablog.com
miraluna.hatenablog.com


(∂. <🎀/ 「速度制御に便利なライブラリ
ライブラリを使って速度制御をするなら「VarSpeedServo.h」というライブラリが便利。簡単で扱いやすいわ。作成者はフィリップ・ファン・アレン(pvanallen)さん。
 リンク→ ライブラリのダウンロードはこちらから Thank you Mr.pvanallen.


今回紹介する方法ではライブラリは使いません。Arduinoの「Servo.h」ライブラリはとても便利でよくできているんだけど、他のライブラリを一緒に使ったときに"競合"が起きることがあるの。ここでいう"競合"というのは、別のライブラリ同士が同じタイマーや同じピンなどを指定して(予約して)しまっているために、コンパイルでエラーが出たりうまく動作しなかったりすること。
競合を解消するためにはライブラリに手を加えるか、プログラムに手を加えて処理するか、ライブラリを使わないかなどが考えられるんだけど、ライブラリやプログラムを修正するのは私のような素人には難しすぎる。そこで今回はライブラリを使わない方法を紹介したいと思います。

(∂. <🎀/「ペンギンのパルス幅をキャリブレート(校正)
1. サーボモータの仕組み
ミニ四駆なんかのDCモータは一方向にぐるぐる回転するものだけど、サーボモータは「指定した位置まで回転する」モータのこと。360°回転するものもあれば、私がもっているSG90のように180°しか可動域がないものもある。「70°」と指定すれば70°の位置まで、「150°」と指定すれば150°の位置まで回転してそこで止まるの。
ではどうやって「指定」した位置を伝えるのかというと、パルス(電気信号の波)で情報を伝えます。

◆ペンギン「SG90」のデータシートより
f:id:miraluna:20200718153604p:plain
これはサーボモータ「SG90」のデータシートの一部。
上のオレンジ・赤・茶色というのは配線を表しています。
その下な鍵のような形の図。これが電気信号の波「パルス」です。
左端から右端まで(PWM Period)が波の1周期。1周期は20ms(ミリ秒)。だから20ミリ秒ごとに電気信号の波が送られるわけね。
左にDuty Cycleと書かれた山がありますね。これがサーボモータに角度指定を送る情報です。この幅のことを「パルス幅」というの。パルス幅は電流をON(HIGH)にしてからOFF(LOW)にするまでの時間の長さのこと。パルス幅が小さければ指定する角度は0°に近づき、パルス幅が大きければ180°に近づきます。ただしこのパルス幅とサーボモータの関係は、パーツの個体差が大きいので、校正(キャリブレート)する必要があるの。

データシートでのパルス幅の値は0.5ミリ秒~2.4ミリ秒。つまりパルス幅が0.5ミリ秒ならサーボモータは0°の位置まで回転し、2.4ミリ秒なら180°の位置まで回転する。1.45ミリ秒なら真ん中の90°の位置まで回転する。ということ。これを基本に、自分のペンギンのパルス幅と角度位置を校正していきます。

2. セットアップ
ここから実際にペンギンをArduinoにつないで、動作させながらパルス幅を決めていきます。
◆SG90の配線 f:id:miraluna:20190609183244j:plain:w300
SG90には3本の配線があります。図の右から、茶色をArduinoのGNDピンへ、赤色をArduinoの5vピンへ、黄色をArduinoのD3ピンへつなぎます。黄色のピンはプログラムで好きなピンを指定できます。PWM出力のピンを指定しましょう。

◆セットアッププログラム(キャリブレート用プログラム)

int penguin=3;
/*サーボモータに「penguin」という名前を付けて、信号線を3ピンにつなぎます。*/


void setup() {
pinMode(penguin,OUTPUT);//penguinは出力ピンですよ。という意味。
}

void loop(){
penDash( );//penDashプログラムを繰り返します。( )に数値を入れる。
}

void penDash(int x){//penDashプログラム
digitalWrite(penguin,HIGH);//3pinをON。
delayMicroseconds(x);//ミリ秒ではなく、マイクロ秒。待ち。
digitalWrite(penguin,LOW);//3pinをOFF。
delay(20);//20ミリ秒の待ち。
}

Arduinoサーボモータをつないだまま、赤字コメントが書かれた行の()に数値を入れて、0°と180°の位置(パルス幅の値)を決めます。
パルス幅の基本的な範囲は0.5ミリ秒~2.4ミリ秒でした。整数で処理できるように、青字コメントのある行のdelayをマイクロ秒で指定します。
("delay"はミリ秒。"delayMicroseconds"はマイクロ秒。1ミリ秒=1000マイクロ秒よ。)
単位がマイクロ秒なので、0°は500マイクロ秒(0.5ミリ秒)近辺、180°は2400マイクロ秒(2.4ミリ秒)近辺ね。それではちょうどよい位置(パルス幅)を探っていきましょう。

◆ペンギンことサーボモータ「SG90」のくちばしの可動域は180°。
f:id:miraluna:20190612184059j:plain:w300

3. キャリブレート(ちょうどいいパルス幅を見つける)
ちょっと手間なんだけど、赤字コメント行の()に500前後の値を入れて、可動域の端っこを探るの。400なら行き過ぎだし、600なら10°くらいの位置かもね。地道にプログラムの書き込みをしてちょうど良さそうな値を見つけましょう。私のペンギンは450くらいがちょうどいいみたい。0°のパルス幅が見つかったら、同じようにして180°のパルス幅も見つけましょう。

自分のサーボモータの最適なパルス幅が見つかったら、プログラムを少し変えます。
サーボモータを回転させる角度を指定するときに、今のプログラムのままだとパルス幅を入力して指定しなきゃいけないわよね。でも角度を入力して指定したい。そのために変換用の計算式を間に入れます。
基本の値の計算式なら、500~2400の間の値を180で割れば変換値が出ます。
式 2400-500=1900
1900÷180=10.555...... になるから、
(〇×10.5)+500 というのが変換式になる。
〇に角度を入れると500~2400(2390)の値になるわね。
自分のサーボモータの端っこの値で計算して、この変換式を作りましょう。

◆変換式を入れたpenDashプログラム

void penDash(int x){//xの値は0~180。
int kyori = (x*10.25)+450;//角度からパルス幅への変換式
digitalWrite(penguin,HIGH);
delayMicroseconds(kyori);
digitalWrite(penguin,LOW);
delay(20);//速度
}

これでpenDashプログラムの()に角度を入力すれば、その位置までサーボを回転させることができます。

(∂. <🎀/「Sketch(code)
それでは実際に動かすためのプログラムを書いてみましょう。
くちばしが指定の位置まで回転するのを待たなくていいように、1°ずつ位置を変えていくプログラムにします(Arduinoの公式「Arduino Forum」で話題になっていたものを参考にさせてもらっています。「参考リンク」・「こちらのYoutubeも」)。

int penguin=3;

void setup() {
pinMode(penguin,OUTPUT);
}

void loop() {
for(int i=0;i<=180;i++){//0°から180°へ回転。
penDash(i);
}
for(int j=180;j>0;j--){//180°から0°へ回転。
penDash(j);
}
}
void penDash(int x){//xの値は0~180。
int kyori = (x*10.25)+450;//角度からパルス幅への変換式
digitalWrite(penguin,HIGH);
delayMicroseconds(kyori);
digitalWrite(penguin,LOW);
delay(5);//速度 5~30くらいが良好。
}

180°まで回転してから0°まで回転する、という動きを繰り返すプログラム。
変換式をいじると微調整ができます。

初めてサーボモータを使ったときは、くちばしが回転し終わるまでの「待ち」を"delay"でプログラムしていたけど、今回はその必要がない。こういった調整が不要になるようなコードやpenDashプログラムのように数値変換をするためのコードが、Servo.hライブラリには書かれているのでしょうね。もちろんもっともっと複雑なものでしょうけど。

(∂. <🎀/「回転の速度調整
さて、肝心の速度調整です。
penDashプログラムの最後の行を見てください。"delay"、つまり「待ち」がありますね。これは参考にしたスケッチに書かれていたもので、初め私はパルス周期の20ミリ秒を待つものだと思っていたの。でもそれだったら20ミリ秒からパルス幅(ここでは"kyori")を引いた分だけ待たなきゃいけない。(20)ではなくて、(20-kyori(パルス幅))になるはず。もしかして、ここはいじってもいいのかな? って思って変えてみたら、回転の速度が変わったの。
パルス周期の値を変えていいものなのか、パルス周期とは関係のない待ちだったのか、私にはよく分からないけど、この数値を変えることで待ち時間が短くなって速度が変わることが分かったの。
0~2くらいは短すぎて、くちばしが端まで辿り着かなかった。5以上がいいみたい。角度1°ずつに対する待ちだから、小さな値でも大きな違いがありそうね。
こうして回転の速度は最後のdelayの値で調整することができます。小さくすると回転が速くなり、大きくすると回転が遅くなる。簡単に変えられるわね。

(∂. <🎀/「短い動画
実際に上のプログラムを動かしている動画です。

Servo motor without library


調査・紹介はミラでした。f:id:miraluna:20200610180017j:plain:w100 Mira

miraluna.hatenablog.com
miraluna.hatenablog.com