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

前の記事

RaspberryPiで!SONYのPaSoRi(RC-S380)で(NFC)Felica情報を読み取る!

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

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

目次

はじめ

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アドレスの特定方法が色々ありますが、私は、下記の記事に書いたようによく使っています。

RaspberryPiで!SONYのPaSoRi(RC-S380)で(NFC)Felica情報を読み取る!

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

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

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

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

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

まとめと展望

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

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

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

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

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

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

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

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

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

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

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

 


では、また次回! Happy Coding!

6 comments

  1. こんにちは。
    htmlでのサーボ制御、ものすごく面白いです!電子回路にUIが付くのは斬新ですよね

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

    ちょっと前に出たobnizというボードがこれをやっていたので、使ってみるのも楽しいかも?と思ってコメントさせて頂きました

  2. ESP32を触り始め、カワシマさまの記事がものすごく参考になっております(感謝)
    この作例を動かしてみようと思ったのですが、うまく動作しないので質問させてください
    まずサーボの信号線(オレンジ)は12番につなぐとして
    電源(赤)3V3   
    アース(茶色)GND 
    で良いですよね・・・このように繋いだらボードが熱くなったので急いで外したところです
    それとボードにコードを送ろうとすると・・・
    exit status 1
    ESP32WebServer.h: No such file or directory
    となります・・・
    何か手順が不足しているんだと思うので・・ご教授いただけますと助かります

  3. いつも貴重な情報をありがとうございます。
    今手元にESP8266しかないもので、ESP32向けのライブラリをESP8266に書き換えてやってみました。
    コンパイルにも成功してWebページもちゃんとアクセスできるようになったのですが、なぜかスライダーが出てきません。
    HPのデータを格納するデータ配列 char res[2500]の部分はコピペしているだけですが、コピペでは何か抜け落ちてしまうところがあるのでしょうか? 何か留意すべき点がありましたら、お教え下さい。

  4. 一昨日質問したはやです。JavaScriptのエラーが出てうまく動かないので、いろいろ調べました。
    そうしましたら、まず、bootstrapを読込ませる位置が良くなかったようで、
    src=”https://stackpath.bootstrapcdn.com/bootstrap/4.1.0/js/bootstrap.min.js”
    をjQueryの読み込みの後に持ってきましたら、エラーは出なくなりました。

    さらに、肝心のスライダーが表示されない件ですが、

    の部分がなぜかwidth:0pxとして表示されていることが分かりました。
    ここに無理やり
    style=”width:80%;height:20px”
    などと書き込んでみましたら、つまみは表示されないもののスライダーの輪郭だけは表示されるようになりました。適当にクリックすると角度が入力され、サーボが回りました。でも、bootstrapを使っていながらこんなダイレクトな指定はみっともないですよね。

    きっとbootstrapのスライダーの形やサイズを明示的に指定してやると良いのだということは分かりましたが、指定の仕方はあちこち調べましたが分かりませんでした。
    スライダーの形やつまみの形式を変更する書式がきっとあると思いますが、見つかりません。川島さんの方でこの方法が分かりましたら、ドキュメントの所在など教えていただければ、と思います。
    画面はこんな感じです。前回はスライドバーが全くありませんでしたが、今度は枠だけ見えます(笑)
    https://photos.app.goo.gl/ktQWzeVkKN2P81gu8

Leave a comment

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

Exit mobile version

By continuing to use the site, you agree to the use of cookies. more information

The cookie settings on this website are set to "allow cookies" to give you the best browsing experience possible. If you continue to use this website without changing your cookie settings or you click "Accept" below then you are consenting to this.

Close