SG90(Servo Motor) for ESP32

ESP32でのSG90の使い方の説明です。SG90のマニュアルは秋月さんのHPに有りました=>SG90。これによると基本性能は

制御方法は

  • 赤と茶色の線に電源を供給し、オレンジの線に信号を送る。
  • 信号は幅20ms(50Hz)でHighの時間で角度が決まる
    • 0.5ms: -90度
    • 1.45ms: 0度
    • 2.4ms: 90度

3.3Vから駆動する様ですがパルスHigh電圧が4.8から5Vなら供給電圧は5Vとなるのでしょうか。角度をPWMのパルス幅に換算するのは面倒と思っていたらESP32用のライブラリーが有りました。DwonloadしてArduinoのライブラリーに登録すれば使用出来ます。主な関数は以下の通り。

  • int attach(pin ): モーター制御に使用するGPIOピンの定義。
    • すべてのGPIOピンが使用出来ると有りますが2,4,12-19,21-23,25-27,32-33の使用を推奨。
    • 戻り値
      • 正常終了: 指定したピン番号
      • 異常終了: 0
  • int attach(pin, min, max ): 最大と最小のパルス幅と共にモーター制御に使用するGPIOピンの定義。
    • パルスの幅を指定出来る以外はattach(pin )と一緒
    • プログラムを見るとデフォルトの最小パルス幅は500us。最大は2500us。SG90に合わせている様です。
    • SG90以外のパルス幅の違うモーターを使用する時にこの関数を使うのでしょうか。
  • void write (): 回転角度指定(引数として0から180度を指定)
  • void writeMicroseconds(): 回転角度指定(引数としてパルス幅を指定)
  • int read():1つ前に指定した角度を0から180度の角度で返す。
  • int readMicroseconds():1つ前に指定した角度をパルス幅で返す。
  • bool attached(): ピン指定されていれば真。
  • void detach(): 制御用に使用しているピンを開放する。

動作確認

動作確認の為下記の回路を作製。

  • 5V電源をSG90とESP32に供給。
  • 信号用にGPIO33を使用。

使用したプログラムは、

sg90.ino

#include "Arduino.h"
#include <ESP32Servo.h>

// Pin definition for Servo Motor
#define sg90_pin             33

void setup()
{
  Servo sg90;
  int a;
  
    Serial.begin(115200);

    sg90.attach(sg90_pin);
    Serial.print("Attached PIN: ");
    if(sg90.attached()) Serial.println("GPIO33");
    else Serial.println("None");
    
    for(a = 90; a > -1; a -= 10){
      sg90.write(a);
      Serial.println(String(a) +  " / " + String(sg90.read()));
      delay(1000);
    }
    for(a = 90; a < 181; a += 10){
      sg90.write(a);
      Serial.println(String(a) +  " / " + String(sg90.readMicroseconds()));
      delay(1000);
    }

      sg90.detach();
      Serial.println("Detach GPIO32");
}

void loop()
{
  delay(500);
}
  • 12行: Servoクラスのインスタンス sg90を宣言
  • 14行: GPIO33を信号に設定
  • 16行: 設定されたか確認
  • 20行: 回転角を角度で指定。
  • 21行: 指定した角度と実際に指定された角度を表示
  • 26行: 指定した角度と実際に指定された角度(us)の表示
  • 30行: 使用ピンの開放

実行結果(シリアルモニタ)

serial monitor

ets Jun  8 2016 00:22:57

rst:0x1 (POWERON_RESET),boot:0x13 (SPI_FAST_FLASH_BOOT)
configsip: 0, SPIWP:0xee
clk_drv:0x00,q_drv:0x00,d_drv:0x00,cs0_drv:0x00,hd_drv:0x00,wp_drv:0x00
mode:DIO, clock div:1
load:0x3fff0030,len:1344
load:0x40078000,len:13964
load:0x40080400,len:3600
entry 0x400805f0
Attached PIN: GPIO33
90 / 89
80 / 79
70 / 68
60 / 58
50 / 49
40 / 38
30 / 28
20 / 19
10 / 9
0 / -1
90 / 1464
100 / 1562
110 / 1660
120 / 1777
130 / 1875
140 / 1972
150 / 2089
160 / 2187
170 / 2285
180 / 2382
Detach GPIO32

  • 11行: GPIO33が使用されている事を確認
  • 12から21行:回転角90度から0度に向けて10度毎に回転。
    • 最初がプログラムで指定した角度。/の後は実際の回転角(read()関数の戻り値)
    • 指定値とRead()の値は若干違う。(Read()の値の方が小さい)
  • 22から31行:回転角を角度で指定。実際の角度をusで表示(readMicroseconds()の戻り値)
    • 90度が1500us。180度が2500us。という訳では無いようです。
  • 30行: GPIOのピンを開放して終了。

気付いた事

  • 指定した値と関数で確認した値(Read()等の戻り値)に若干のずれがある。
  • これは角度で指定した場合もパルス幅で指定した場合も同じ。
  • 回転速度の調整は出来ない。
    • 回転速度が若干速い。もう少し遅くしたい。
  • コマンドはESP32からモーターに送られるがモーター側に状態をESP32から確認出来ない。
    • 今回のプログラムで、モーター側の電源を切ってもシリアルモニタに同じ結果を表示する。
  • 今回使用した回路でGPIOの出力はHigh:3.3Vのはずだが問題無く動作した。
  • 総合的に非常に良いライブラリーと思います。