ESP8266のサーボモータ制御ライブラリ servo の細かい挙動を知る
ESP8266でSG90を制御する際の、細かな挙動などについて。
ライブラリ
servoライブラリを利用する
https://github.com/esp8266/Arduino/tree/master/libraries/Servo
PWM波形は、core_esp8266_waveform で生成している
コンストラクタ/デストラクタ
コンストラクタは変数の初期化をしているだけ。detach()状態。
デストラクタはdetach()を行っているだけ。
双方、動的なリソース管理はしていない。
attach()
attachは、3種類ある。
uint8_t attach(int pin);
uint8_t attach(int pin, uint16_t min, uint16_t max);
uint8_t attach(int pin, uint16_t min, uint16_t max, int value);
min,max,valueの単位はµs、指定しない場合デフォルトが使われる。
#define DEFAULT_MIN_PULSE_WIDTH 1000 // uncalibrated default, the shortest duty cycle sent to a servo
#define DEFAULT_MAX_PULSE_WIDTH 2000 // uncalibrated default, the longest duty cycle sent to a servo
#define DEFAULT_NEUTRAL_PULSE_WIDTH 1500 // default duty cycle when servo is attached
デフォルトは1.0msから2.0msのパルス幅が0~180度にマップされる。
SG90は0.5msから2.4msのパルス幅なので、
sg90.attach(PIN, 500,2400);
とする。
attach()時に使われる角度の初期値は、コンストラクタ、およびdetach()時にDEFAULT_NEUTRAL_PULSE_WIDTH(プログラム上1500で固定) が設定される。
SG90の場合、この値は95度くらいの値になってしまうので注意。
また、処理スピードから推察して、attach()直後にwrite()すれば大丈夫だろうと思うかもしれないが、SG90では波形更新が20ms(SG90データシート参照)ごとなので、サーボが僅かに反応する可能性がある。
初期のサーボ位置を一瞬のスキもなしに設定したい場合、attachの第3引数に初期パルス幅が指定できるので
sg90.attach(PIN, 500,2400, map(初期角度, 0, 180, 500,2400));
とすれば良い。
これを含め、attach直後の挙動などを把握するには、ソースを一読した方が良い。
write()
基本、角度指定だが、200以上の値はµsと判断され、writeMicroseconds()に渡される。
「181度がクリップされてるから」などと油断してると、突然変な挙動になるので注意
基本、自分で0-180に正規化するのが安全。
| write(int value) | valueの取り扱い |
|---|---|
| 0未満 | 0度 |
| 0~180 | value度 |
| 181~200 | 180度 |
| 200~ | value µs / 例えば1500だと中間位置(90度) |
謎仕様だが、こういうのは、昔のソースとのコンパチのためなのだろう。
SG90では、上から見て、0は時計回りの最大角度、180は半時計回りの最大角度になる。
detach()
attachされていたピンを常時LOWに設定後、20ms待っている。
また、内部角度をDEFAULT_NEUTRAL_PULSE_WIDTHにリセットしている。
DEFAULT_NEUTRAL_PULSE_WIDTHは、SG90の場合は前述の通り95度くらいになるので注意。
SG90挙動
PWMパルス幅が500µsの時=反時計回り方向に最大角度(0度)、2400µsの時=時計回り方向に最大角度(180度)になる。1周期は20ms(50Hz)。
PWM信号が来なくなった後、一定期間(2秒程度?)は最後の角度を保持しようとするが、それを超えると角度は維持されたままモーターにトルクのかかっていない状態になる。
SG90の制御は AA51880 が使われているらしい。