2018年2月10日土曜日

ArduinoでSG90をゆっくり滑らかに動かしたい(失敗)



サーボSG90を20度/秒ぐらいで滑らかに動かしたいと思ったのですが、どうも難しいです。割り箸をホットボンドで接着するといういかにも共振したりハンチング起こしそうな条件ではありますが。

試行錯誤としては、
  • Arduino標準のServoライブラリのexample
  • 同じく、値を変えるごとにdetachしてdelayし再度attach
  • ESP32のLEDCを使って15bit PWM
  • ESP32 / Arduino unoでdelayMicrosecondsを使って正確なパルスを出す
などを試みたのですが、いずれも動画のようなブルブルっぷりでした。強いて言えばLEDCを使ったものが一番良かったですが、やっぱり震えます。今回使ったのはSG90のパチ品です。本物あるいはもっと高価なサーボを使えば滑らかに動いてくれるのでしょうか?

うーむ。

一応LEDC版のソースです。delayは「次のPWMパルスが出そうなところでledcWrite命令を出すとパルス列がコケるのではないか?」ということで一つだけ出るようなタイミングにしてみたりPWM周期を変えてみたりしましたが特に大きな変動は見られません。
#define servoPin 12
#define servoCh 0
#define servoBits 15
#define servoMax 32767
void degreeToLED(float inDegree) {
float msec = inDegree / 90.0 * 0.5 + 1.5;
int duty = msec / 20.0 * (float)servoMax;
Serial.println(duty);
ledcWrite(servoCh, duty);
}
float pos = 0;
void setup() {
Serial.begin(115200);
ledcSetup(servoCh, 50, servoBits);
ledcAttachPin(servoPin, servoCh);
}
void loop() {
for (pos = -90; pos <= 90; pos += 0.1) { // goes from 0 degrees to 180 degrees
// in steps of 1 degree
degreeToLED(pos); // tell servo to go to position in variable 'pos'
delay(15);
}
for (pos = 90; pos >= -90; pos -= 0.1) { // goes from 180 degrees to 0 degrees
degreeToLED(pos); // tell servo to go to position in variable 'pos'
delay(15);
}
}
view raw SG90_Slow1.ino hosted with ❤ by GitHub

こっちはdelayMicroseconds版。
#define servoPin 12
void setup() {
Serial.begin(115200);
pinMode(servoPin, OUTPUT);
}
void loop() {
for (float pos = -90; pos <= 90; pos += 0.1) {
float msec = pos / 90.0 * 0.5 + 1.5;
long limitUSec = msec * 1000;
digitalWrite(servoPin, HIGH);
delayMicroseconds(limitUSec);
digitalWrite(servoPin, LOW);
delayMicroseconds(10000-limitUSec);
delay(10);
}
delay(1000);
}
view raw SG90_Slow2.ino hosted with ❤ by GitHub

0 件のコメント:

コメントを投稿

注: コメントを投稿できるのは、このブログのメンバーだけです。