記事一覧

ArduinoでサーボGWS Micro2BBMGを動かす時の注意

ArduinoでサーボGWS Micro2BBMGを動かす時の注意



RoboTakaoです。ようこそ「極力ローコスト ロボット製作 ブログ」にお越しくださいました。

前回まででRaspberry Pi Zero Wと2個のArduino Nanoをi2cで接続して最大24個のサーボを動かすようにしました。

前回の記事はこちらを参照してください。

たくさんサーボつなげていてサーボがブルブル震える現象が気になりました。これは特にゼロ度の指令をすると発生します。
オシロで波形見たり、いろいろ試行錯誤して原因究明していたのですが、基本的な使い方でまずいところがあったので書いておきます。

SERV04.png


Arduinoの標準ライブラリーでサーボのライブラリーがありますが、今回はこれを使用していました。よくよく調べてみると、デフォルトではサーボのパルス幅は544msから2400msとなっていますが、今回使用のGWSのサーボの使用範囲は800msから2200msだということがわかりました。

Arduino日本語リファランス

GWSサーボのスペック

Pulse width Horn position
0.7-0.8ms Safety zone for CW
0.8ms +90 degrees
1.15ms +45 degrees(H position)
1.5ms 0 degree(center position)
1.85ms -45 degrees(V position)
2.2ms -90 degrees
2.2-2.4ms Safety zone for CCW


つまり、指令ゼロ度だとサーボには544msの幅のパルスを入力していることとなり、安全範囲の0.7msも超えてだいぶ短い幅になっているため異常な動きをしていたようです。

動画を見てください。シリアルモニタで角度を入力するとその角度になるスケッチでテストしてみると、0度、90度、180度で回転させると、どうもそれ以上回転しているようです。また0度だとカタカタ異音がします。



さてそれではどうしましょう。
Arduino日本語リファレンスを見るとパルス幅の最小と最大を指定できることがわかります。

servo.attach(pin)
servo.attach(pin, min, max)

servo: Servo型の変数
pin: サーボを割り当てるピンの番号
min (オプション): サーボの角度が0度のときのパルス幅(マイクロ秒)。デフォルトは544
max (オプション): サーボの角度が180度のときのパルス幅(マイクロ秒)。デフォルトは2400

つまりGWSのサーボの場合はminに800、maxに2200を入れることになります。

次の動画はパルス幅を800msから2200msの範囲になるようにスケッチを改良したものです。
中心の90度でサーボホーンを合わせると、どうも0度と180度まで届きません。



次の動画はパルス幅を安全範囲の700msから2300msの範囲に変更したものです。概ね0〜180度で回転してくれているようです。
ただし一つだけ回りきっていないものがあります。(右から三番目)
結構バラツキがあります。



さらに次の動画では安全範囲を超えて600msから2400msの範囲にしてみました。右から三番目のものも0〜180度で回転しました。その替わり他のサーボは動きすぎです。
つまり正確に角度指定する場合は一つ一つ現物のバラツキを見てパルス幅の範囲を設定しないといけないということになります。
ちなみに600msから2400msの範囲でもカタカタ異音はしないので大丈夫そうです。



結論
ArduinoでGWS Micro2BBMGを使用する場合はパルス幅を700msから2300msにする。ただしバラツキも結構あるので一つ一つ角度を検査して、適切な値に設定する。

安全範囲を超えての使用は自己責任でお願いします。

スケッチ

参考としてArduinoのスケッチを示します。

その1 パルス幅はデフォルト 544〜2400ms


#include

Servo myservo2;
Servo myservo3;
Servo myservo4;
Servo myservo5;
Servo myservo6;
Servo myservo7;
Servo myservo8;
Servo myservo9;
Servo myservo10;
Servo myservo11;
Servo myservo12;
Servo myservo13;

int ang = 90; //サーボの角度[deg]

char c_data[5]=" ";

void setup()
{
myservo2.attach(2);
myservo3.attach(3);
myservo4.attach(4);
myservo5.attach(5);
myservo6.attach(6);
myservo7.attach(7);
myservo8.attach(8);
myservo9.attach(9);
myservo10.attach(10);
myservo11.attach(11);
myservo12.attach(12);
myservo13.attach(13);

Serial.begin(9600);

}

void loop()
{
myservo2.write(ang);
myservo3.write(ang);
myservo4.write(ang);
myservo5.write(ang);
myservo6.write(ang);
myservo7.write(ang);
myservo8.write(ang);
myservo9.write(ang);
myservo10.write(ang);
myservo11.write(ang);
myservo12.write(ang);
myservo13.write(ang);
delay(500);

Serial.println(ang);

if(Serial.available()>0){
rs_gets_4c(c_data); //4文字受信
ang = atoi(c_data); //文字列を整数に変換
}
}

void rs_gets_4c(char gtc[5]) //4文字受信する関数
{
char gc;
int i;

sprintf(gtc," ");
for( i = 0 ; i < 5 ; i++ )
{
gc = Serial.read();
if (gc == ',')
break;
else
gtc[i] = gc;
}
}


その2 パルス幅を700〜2300msに指定


#include

Servo myservo2;
Servo myservo3;
Servo myservo4;
Servo myservo5;
Servo myservo6;
Servo myservo7;
Servo myservo8;
Servo myservo9;
Servo myservo10;
Servo myservo11;
Servo myservo12;
Servo myservo13;

int Width_Min = 700; //最小パルス幅(ms)
int Width_Max = 2300; //最大パルス幅(ms)
int ang = 90; //サーボの角度[deg]

char c_data[5]=" ";

void setup()
{
myservo2.attach(2,Width_Min,Width_Max);
myservo3.attach(3,Width_Min,Width_Max);
myservo4.attach(4,Width_Min,Width_Max);
myservo5.attach(5,Width_Min,Width_Max);
myservo6.attach(6,Width_Min,Width_Max);
myservo7.attach(7,Width_Min,Width_Max);
myservo8.attach(8,Width_Min,Width_Max);
myservo9.attach(9,Width_Min,Width_Max);
myservo10.attach(10,Width_Min,Width_Max);
myservo11.attach(11,Width_Min,Width_Max);
myservo12.attach(12,Width_Min,Width_Max);
myservo13.attach(13,Width_Min,Width_Max);

Serial.begin(9600);

}

void loop()
{
myservo2.write(ang);
myservo3.write(ang);
myservo4.write(ang);
myservo5.write(ang);
myservo6.write(ang);
myservo7.write(ang);
myservo8.write(ang);
myservo9.write(ang);
myservo10.write(ang);
myservo11.write(ang);
myservo12.write(ang);
myservo13.write(ang);
delay(500);

Serial.print(Width_Min);
Serial.print(" ");
Serial.print(Width_Max);
Serial.print(" ");
Serial.println(ang);

if(Serial.available()>0){
rs_gets_4c(c_data); //4文字受信
ang = atoi(c_data); //文字列を整数に変換
}
}

void rs_gets_4c(char gtc[5]) //4文字受信する関数
{
char gc;
int i;

sprintf(gtc," ");
for( i = 0 ; i < 5 ; i++ )
{
gc = Serial.read();
if (gc == ',')
break;
else
gtc[i] = gc;
}
}





それでは今回はこの辺で失礼します!ありがとうございました。

スポンサードリンク

コメント

コメントの投稿

非公開コメント

プロフィール

RoboTakao

Author:RoboTakao
みなさんご訪問ありがとうございます。ロボット作りたいけどお小遣いそんなにないし、簡単でローコストでロボットを作るための私のプロジェクトを紹介します。

ウェブサイトもありますのでそちらもよろしくお願いします。
http://robotakao.jp/

スポンサーリンク