サイトアイコン KOKENSHAの技術ブログ

ESP32でウェブからサーボを制御する!

前の記事

ESP32をアクセスポイントにした上、ウェブサーバーを立てる!

とても人気になっていまして、調子に乗って、これの記事を書きました!

というより、私がずっとこれをやりたかったのです。

目次

はじめ

ESP32をアクセスポイントにすることもできますし、もちろんESP32がWIFIのネットワークに参加することもできます。

[amazonjs asin=”B0718T232Z” locale=”JP” title=”HiLetgo ESP32 ESP-32S NodeMCU開発ボード2.4GHz WiFi + Bluetoothデュアルモード”]

ウェブ経由すれば、つまり、ネット越しに制御ができるということですね。

VPNを経由すれば「外」から家の中のものを制御することも当然できます。

この記事で書いた内容をベースにして、いろんな「ちょっとした」応用ができるようになりますね。

配線

サーボの接続はとても簡単です。

[amazonjs asin=”B00VUJYNWG” locale=”JP” title=”デジタル・マイクロサーボ SG90 (5個)”]

12番は信号線

後電源は3VをESP32から接続するだけです。

プログラム

#include <WiFiClient.h>
#include <ESP32WebServer.h>
#include <WiFi.h>
#include <ESPmDNS.h>

/* あなたのWIFIに接続するSSIDとパスワードに書き替えください。 */
const char* ssid = "XXXXXXXX";
const char* password = "XXXXXXXX";

ESP32WebServer server(80);

const int servoPin = 12;
int oldAngle = 0; 
int PWM_WIDTH = 20000;

/* 
HPのデータを格納するデータ配列
*/
char res[2500]=
"<!DOCTYPE html>\
<html>\
<head>\
<meta charset='utf-8'>\
<link href='https://stackpath.bootstrapcdn.com/bootstrap/4.1.0/css/bootstrap.min.css' rel='stylesheet' integrity='sha384-9gVQ4dYFwwWSjIDZnLEWnxCjeSWFphJiwGPXr1jddIhOegiu1FwO5qRGvFXOdJZ4' crossorigin='anonymous'>\
<script src='https://stackpath.bootstrapcdn.com/bootstrap/4.1.0/js/bootstrap.min.js' integrity='sha384-uefMccjFJAIv6A+rW+L4AHf99KvxDjWSu1z9VI8SKNVmz4sk7buKt/6v9KI65qnm' crossorigin='anonymous'></script>\
<script src='https://code.jquery.com/jquery-3.3.1.min.js' integrity='sha256-FgpCb/KJQlLNfOu91ta32o/NMZxltwRo8QtmkMRdAu8=' crossorigin='anonymous'></script>\
<script src='https://code.jquery.com/ui/1.12.1/jquery-ui.min.js' integrity='sha256-VazP97ZCwtekAsvgPBSUwPFKdrwD3unUfSGVYrahUqU=' crossorigin='anonymous'></script>\
<script>\
$(function() {\
$('#sliVal').html('角度: 0 度');\
$('#slider').slider({\
    orientation:'horisontal',value:0,min: 0,max: 180,step: 1\
});\
$('#slider').slider().bind({\
slidestop: function(e,ui){\
    $('#res').removeClass('p-3 mb-2 bg-success text-white').addClass('p-3 mb-2 bg-danger text-white');\
    $('#sliVal').html('角度: '+ui.value+' 度');\
    $.get('/ang?val=' + ui.value, function(d, s){\
        $('#res').removeClass('p-3 mb-2 bg-danger text-white').addClass('p-3 mb-2 bg-success text-white');\
        $('#res').html(s);\
    }); \
}\
});\
});\
</script>\
</head>\
  <body>\
    <div class='container'>\
      <br>\
      <div class='row'>\
        <div class='col-lg-12 shadow-lg p-3 mb-5 bg-white rounded d-block'>\
          <h1>株式会社虹賢舎</h1>\
          <hr>\
          <p>ESP32 Web経由サーボ制御</p>\
        </div>\
      </div>\
      <div class='row'>\
        <div class='col-lg-12 shadow-lg p-3 mb-5 bg-white rounded d-block'>\
            <div class='col-lg-12' id='slider'></div></br>\
            <div class='col-lg-12' id='sliVal'></div></br>\
            <div class='col-lg-12' id='res'></div></br>\
        </div>\
      </div>\
    </div>\
  </body>\
</html>";


///////////////////
void handleRoot() {
  server.send(200, "text/html", res);
}
/* 角度から pulse に変換する */
int servoPulse(int angleDegrees)
{
  int pulseWidth = map(angleDegrees, 0,180,600,2400);
  return pulseWidth;
}
/* 
角度を確認して、pulseを動作させる
*/
void servoGo(int oldAngle, int newAngle)
{
  int pulseWidth;
  if(oldAngle == newAngle){
    return;
  }else if(oldAngle < newAngle){
    /* 時計回り処理 */
    for (int i=oldAngle; i<=newAngle; i++){
      /* convert angle to pulse width us*/
      pulseWidth = servoPulse(i);
      /* HIGH pulse */  
      digitalWrite(servoPin, HIGH);
      /* use delayMicroseconds to delay for pulseWidth */
      delayMicroseconds(pulseWidth); 
      /* LOW pulse */                          
      digitalWrite(servoPin, LOW);
      /* 
      DELAY
    */ 
      delayMicroseconds(PWM_WIDTH - pulseWidth);   
    }
  }else if(oldAngle > newAngle){
    /* 逆時計回り処理 */
    for (int i=oldAngle; i>=newAngle; i--){
      pulseWidth = servoPulse(i);
      digitalWrite(servoPin, HIGH);
      delayMicroseconds(pulseWidth);                           
      digitalWrite(servoPin, LOW);
      delayMicroseconds(PWM_WIDTH - pulseWidth);
    }
  }
}
/* サーボを動かす */
void handleServo() {
  //Serial.println(server.argName(0));
  int newAngle = server.arg(0).toInt();
  servoGo(oldAngle, newAngle);
  oldAngle = newAngle;
  server.send(200, "text/html", "ok");
}

void handleNotFound(){
  String message = "File Not Found\n\n";
  server.send(404, "text/plain", message);
}

void setup(void){
  
  Serial.begin(115200);
  WiFi.begin(ssid, password);
  Serial.println("");
  // Wait for connection
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  Serial.println("");
  Serial.print("Connected to ");
  Serial.println(ssid);
  Serial.print("IP address: ");
  Serial.println(WiFi.localIP());

  if (MDNS.begin("esp32")) {
    Serial.println("MDNS responder started");
  }
  
  server.on("/", handleRoot);
  server.on("/ang", handleServo);

  server.onNotFound(handleNotFound);

  server.begin();
  pinMode(servoPin, OUTPUT);
  Serial.println("HTTP server started");
}

void loop(void){
  server.handleClient();
}

上記のプログラムをArduinoのIDEで

編集、確認、ESP32に書き込めば、OKです!

ちなみに私が使っているのは下記のもので

書き込みできないエラーが出た場合は、bootボタンを押したまま、書き込むとうまくいきます。

四隅に穴が開いてるのが V1 (DOIT 社製)のものだそうです。

ESP32をArduinoのIDEで使えるための設定は、下記の記事をご参照ください。

MacでArduinoIDEとESP32でLチカ

動作確認

たまに、編集後、書き込みをしても、すぐWIFIに接続しないあるいは、接続するのが遅い現象がありますが

その時、一回電源を抜いて(再起動?)すれば治ります。

WIFIに接続して、IPアドレスを特定します。

IPアドレスの特定方法が色々ありますが、私は、下記の記事に書いたようによく使っています。

LANかWANに接続しているhostのIPアドレス

expressifというメーカーさんのhostを見つけたら、おそらくそれはあなたのEPS32です!笑

そうしましたら、ブラウザーで

http://your_ip_address を開いてみてください!

これが表示できましたら、成功です!(株式会社虹賢舎の文字はあたなの会社や名前に置き換えてください。笑)

スライダーを動かしてみると、サーボが連動して動いているはずです!

まとめと展望

どうでしょう!感動の瞬間でしょう!笑。

私は感動して、泣きました!(ウソ)笑

でも、本当に楽しいですね。

ちなみに、余談ですが今回は、bootstrapの4を使っていますので、結構綺麗ですね。

CSSもjavascriptも実は外部のサーバーに置くこともできるんではないかとこれを作りながら、思いました。

そうすると、毎回、ESP32に書き込まなくても良いかなと思いました。その辺の実験はまた他の記事で書こうと思います。

今、サーボを動かすロジックがとてもシンプルなものですが

サーボも増やして少し複雑なものに設計すれば、ロボットアームやなどより複雑な操作もできるはずです!

後、フロントエンドにもvue.jsやangular.js react.jsとかも使ってみたいですね!

皆さんも何か面白いIdeaやプロジェクトの成果物があれば、ぜひお教えください!

Twiiterでもお気軽にフォロー、絡みよろしくお願いします!

 


では、また次回! Happy Coding!

モバイルバージョンを終了