サーボモーターSG90
回転を角度にできるやつ。使ってみたいので使い方調べる。
お買い物
秋月で売ってる。スタンダードなやつみたい。
ちっちゃい!
プレート?ガイド?なんていうのか分かんないけど付いてた。
接続
直で繋いだ。大丈夫かな。
茶=GND、赤=電源[+]、橙=制御信号 [JRタイプ]
スケッチ
0-90-180度の繰り返し
#include <Servo.h>
int pwmpin = 9;
Servo myservo;
void setup() {
myservo.attach(pwmpin);
}
void loop() {
myservo.write(0);
delay(1000);
myservo.write(90);
delay(1000);
myservo.write(180);
delay(1000);
}
Servo.hをincludeするだけで使える。
0.1秒毎に0-180度に動かす
#include <Servo.h>
int pwmpin = 9;
Servo myservo;
void setup() {
myservo.attach(pwmpin);
}
void loop() {
for (int i = 0 ; i < 180 ; i++) {
myservo.write(i);
delay(100);
}
}
こんなとか。
0.5秒ごとにランダム
#include <Servo.h>
int pwmpin = 9;
int deg = 0;
Servo myservo;
void setup() {
myservo.attach(pwmpin);
randomSeed(analogRead(0));
}
void loop() {
deg = random(0, 180);
myservo.write(deg);
delay(500);
}
こんなんも。
気になることがあって、ピニオンギアとプレートの歯を合わせると、0度ないし180度の時に筐体と直交しないから見た目的に若干角度がついているように見える。なんかヤダな。まぁ安いしちっちゃいからそこは我慢か。
なぜanalogWrite()だとちゃんと動かないのか
最初、analogWriteの説明にPWMって書いてあったので
int pwmpin = 9;
int deg = 0;
Servo myservo;
void setup() {
pinMode(pwmpin, OUTPUT);
}
void loop() {
analogWrite(pwmpin, 0);
delay(1000);
analogWrite(pwmpin, 127);
delay(1000);
analogWrite(pwmpin, 255);
delay(1000);
}
ていうコードを書いた。analogWriteは0-255の範囲で値を書き込めるっていうから、0-127-255で0-90-180度になると考えたわけだ。でもこの考えは間違ってた。サーボ全然動かんし。
サーボモーターは電圧の変化で角度を変えているわけではない
秋月にあるSG90の資料を見てみると
電圧は4.8V(5V)で、20msの周期での、0.5-2.4msのデューティサイクルによって角度が決まる。PWMを電圧を低く見せるためではなくて(結果的に低くなっているように見えるけど)、パルス幅を使ってるだけってことみたい。PWM=電圧を変化させること、みたいな雑な理解だったから駄目なんだな。
analogWriteの周期とSG90の周期は違う
analogWriteの周波数は、こちらを見ると約490Hz(≒2.04msに1回)で、SG90は上記から50Hz(=20msに1回)なので、都合10倍ぐらい違う。analogWriteの方が短い。ていうかanalogWriteでこの制御信号を作ろうとしてはいけない。なのでdigitalWriteとdelayMicrosecondsを組み合わせて制御信号を作らないといけないみたい。
踏まえたスケッチ
int pwmpin = 9;
void setup() {
pinMode(pwmpin, OUTPUT);
}
void loop() {
pulse(0, 1000);
pulse(90, 1000);
pulse(180, 1000);
}
void pulse(int deg, int ms) {
int d = 0;
int startms = millis();
int endms = startms + ms;
d = map(deg, 0, 180, 500, 2400);
do {
digitalWrite(pwmpin, HIGH);
delayMicroseconds(d);
digitalWrite(pwmpin, LOW);
delayMicroseconds(20000 - d);
} while (endms < millis());
delay(ms);
}
一応動く。
ただ1分ぐらいすると勝手に止まっちゃう。たぶんこれはintのせいなのかな?
コメント
ATTiny202でサーボを動かそうと思っていました。Servoライブラリを使ってしまうとコンパイル後のサイズが2メガを超えてしまい、困っていました。本サイトを拝見して2メガを超えないものが作れました。
とても助かりました。ありがとうございます。