memorandums

日々の生活で問題解決したこと、知ってよかったことなどを自分が思い出すために記録しています。

SG90をdigitalWriteで動かしてみた

サーボモータの入門機?としてSG90は有名ですね.

たまに不良品がありますが,400円くらいなので気軽に買えちゃいます.

デジタル・マイクロサーボ SG90 (1個) www.amazon.co.jp 440円 (2020年10月31日 11:07時点 詳しくはこちら) Amazon.co.jpで購入する

で,ArduinoでSG90を使うときには,Servoライブラリを利用するのが定番?ですので,私もそれしか経験がありませんでした.

以下のサイトをみるとdigitalWriteでPWM信号を作って制御している例がありました.有用な情報ありがとうございました.

その9 Arduinoでサーボモータをキュイキュイ動かす! marupeke296.com

これは理解するのにいいな,と思いましてやってみた次第です.

ちょっと真似してやってみました.

SG90のスペックシートには以下のチャートがあります.20msを1サイクルとして,その中で0.5msから2.4msだけオンして,残り20ms-0.5ms等をオフにする,を繰り返してSG90に送れば動いてくれることになります.

スクリーンショット 2020-10-31 11.10.40

単純に考えて,以下のコードを書きました.まぁ,動きました.ちなみに,delayMicrosecondsで20msをWAITするのに10000μsごとにわけているのは,delayMicrosecondsが16383μsまでしかカウントできないところから来ているようです.詳しくはドキュメント参照してください

void setup() {

   pinMode(11, OUTPUT);

}



void loop() {

   digitalWrite(11, HIGH);

   delayMicroseconds(500);

   digitalWrite(11, LOW);

   delayMicroseconds(10000);

   delayMicroseconds(10000 - 500);

}

で,これは動作したんですね.

続いて,0度,90度,180度と1秒ずつホールドして動かしてみたんです.単純に上記のloop処理をコピーして作りました.単純ですね.

でも,これ動かないんです.いや,正確にはちょっとずつだけしか動かないんですね.

void setup() {

   pinMode(11, OUTPUT);

}



void loop() {

   digitalWrite(11, HIGH);

   delayMicroseconds(500);

   digitalWrite(11, LOW);

   delayMicroseconds(10000);

   delayMicroseconds(10000 - 500);



   delay(1000);



   digitalWrite(11, HIGH);

   delayMicroseconds(1350);

   digitalWrite(11, LOW);

   delayMicroseconds(10000);

   delayMicroseconds(10000 - 1350);



   delay(1000);



   digitalWrite(11, HIGH);

   delayMicroseconds(2400);

   digitalWrite(11, LOW);

   delayMicroseconds(10000);

   delayMicroseconds(10000 - 2400);



   delay(1000);

}

ちょっと考えてわからなかったんです.

11番ピンがPWMポートだからダメなのかなぁ...と,いつも使っていたServoライブラリで書き換えたらちゃんと動きました.

その動作をみていたときにやっと気づきました.

上記のコードでは1サイクルしかPWM信号(回転位置の指令)が出力されないわけです.

サーボモータの原理まではわかりませんが,恐らく,PWM信号と回転位置の差を0にするようにフィードバック制御しているのかと.

となると,サーボが指定した角度まで移動するまでPWM信号を与え続けなければならないと想像できます.

ということで,PWM信号を生成している部分をfor文で100回くらい繰り返したらちゃんと動作するようになったんですねぇ〜.

考えてみれば当然ですが,Servoライブラリに頼ってブラックボックス的に扱っているとその意識は持てませんでした.なかなかいい勉強になりました.

とりあえず,変更後のコードを載せておきます.

//#include <Servo.h>

//Servo myservo;



void setup() {

 pinMode(11, OUTPUT);

//  myservo.attach(11);

}



void my_pwm(int v) {

 for (int i=0;i<40;i++) {

   digitalWrite(11, HIGH);

   delayMicroseconds(v);

   digitalWrite(11, LOW);

   delayMicroseconds(10000);

   delayMicroseconds(10000 - v);

 }

}

void loop() {



//  myservo.write(0);

 my_pwm(500);

 delay(1000);



//  myservo.write(90);

 my_pwm(1350);

 delay(1000);





//  myservo.write(180);

 my_pwm(2400);

 delay(1000);

}

では,PWM信号を送るには何サイクル送ればいいんだろうか?と疑問がわきました.

サーボのスペックシートにある回転速度が参考になりそうですね.

スクリーンショット 2020-10-31 11.25.59

サーボの最大移動量は180度です.

回転速度は0.12s / 60度です.

つまり,0度から180度まで回転するのに,360msかかるってことになります.

PWMの1サイクルは20msですから,単純計算では360ms / 20ms = 18回送ればよさげです.

で,20回にしてみたんですが,安定しない...この辺はコンピュータというかソフトウェアの世界とは違いますねぇ〜.

1+1が必ずしも2になるとは限らない世界です.

カタログ値と実際は異なることはよくあります.

ということで色々試すと倍の40にすると安定して動作するようでした.

もしかすると,この現象の背景も専門知識があれば読み解くことができるのかもしれません.興味のある方は調べて教えて下さい.

僕はここまでで十分なので,おしまいにします😁

でわ,また.ハッピーハロウィン🎃