ESP-WROOM-02を始めました(4) WiFi経由でLEDを制御
ESP-WROOM-02のGPIOまわりの雰囲気が分かったので、
本来の目的のIoTをボチボチとやり始めました。
まずは、Arduino IDEのサンプルソースのSDWebserverを修正して
簡単なLED制御プログラムを作って見ました。
スマートフォンにてESP-WROOM-02にて稼働するWebサーバーに接続して
LEDを制御しています。
動作の様子
動作としては単純なのですが、ESP-WROOM-02が具体的に何をやっていると言うと
1)WiFiアクセスポイント 機能の提供
2)接続したスマートフォンにIPアドレスの配布(DHCP)
3)Webサーバー
4)WebコンテンツをSDカードから配信
5)URL名前解決(DNSサーバー)
6)LEDの制御
てな感じです。
ESP-WROOM-02がWiFiアクセスポイントになっているので、既存ネットワークが無くても
スマートフォンから接続することが出来ます。
動画見ると分かりますが、表示レスポンス等、Webサーバーとしてはさすがに遅いです。
ですので、ボタン操作によるLED制御は、非同期通信を使ってページ更新が発生しない
ようにしました。
結線
05ピン LEDのアノードへ接続
13ピン microSDカードモジュールのMOISに接続
12ピン microSDカードモジュールのMISOに接続
14ピン microSDカードモジュールのCLKに接続
15ピン microSDカードモジュールのCSに接続
microSDカードの接続・使い方はスイッチサイエンスさんの記事
ESP-WROOM-02を使ったWi-Fi機能付き温度ロガーを作る(1)
が参考になると思います。
スケッチ
ダウンロード SDWebServerEx.zip (64.5K)
#include <ESP8266WiFi.h> #include <WiFiClient.h> #include <DNSServer.h> #include <ESP8266WebServer.h> #include <ESP8266mDNS.h> #include <SPI.h> #include <SD.h> #define DBG_OUTPUT_PORT Serial #define LED_PIN 5 const char* ssid = "esp8266"; const char* password = "xxxxxxx"; const char* host = "sd.local"; const byte DNS_PORT = 53; IPAddress apIP(192, 168, 0, 1); DNSServer dnsServer; ESP8266WebServer server(80); static bool hasSD = false; void returnOK() { server.send(200, "text/plain", ""); } void returnFail(String msg) { server.send(500, "text/plain", msg + "\r\n"); } bool loadFromSdCard(String path){ String dataType = "text/plain"; if(path.endsWith("/")) path += "index.htm"; if(path.endsWith(".src")) path = path.substring(0, path.lastIndexOf(".")); else if(path.endsWith(".htm")) dataType = "text/html"; else if(path.endsWith(".css")) dataType = "text/css"; else if(path.endsWith(".js")) dataType = "application/javascript"; else if(path.endsWith(".png")) dataType = "image/png"; else if(path.endsWith(".gif")) dataType = "image/gif"; else if(path.endsWith(".jpg")) dataType = "image/jpeg"; else if(path.endsWith(".ico")) dataType = "image/x-icon"; else if(path.endsWith(".xml")) dataType = "text/xml"; else if(path.endsWith(".pdf")) dataType = "application/pdf"; else if(path.endsWith(".zip")) dataType = "application/zip"; File dataFile = SD.open(path.c_str()); if(dataFile.isDirectory()){ path += "/index.htm"; dataType = "text/html"; dataFile = SD.open(path.c_str()); } if (!dataFile) return false; if (server.hasArg("download")) dataType = "application/octet-stream"; if (server.streamFile(dataFile, dataType) != dataFile.size()) { DBG_OUTPUT_PORT.println("Sent less data than expected!"); } dataFile.close(); return true; } void handleNotFound(){ if(hasSD && loadFromSdCard(server.uri())) return; String message = "SDCARD Not Detected\n\n"; message += "URI: "; message += server.uri(); message += "\nMethod: "; message += (server.method() == HTTP_GET)?"GET":"POST"; message += "\nArguments: "; message += server.args(); message += "\n"; for (uint8_t i=0; i<server.args(); i++){ message += " NAME:"+server.argName(i) + "\n VALUE:" + server.arg(i) + "\n"; } server.send(404, "text/plain", message); DBG_OUTPUT_PORT.print(message); } // LEDの制御 void handleLED() { if (!server.hasArg("LED")) { String msg = "Command Error\n"; returnFail(msg); return; } String cmd = server.arg("LED"); if (cmd == "on") { digitalWrite(LED_PIN, HIGH); DBG_OUTPUT_PORT.println("LED ON"); } if (cmd == "off") { digitalWrite(LED_PIN, LOW); DBG_OUTPUT_PORT.println("LED OFF"); } returnOK(); } void setup(void){ pinMode(LED_PIN, OUTPUT); digitalWrite(LED_PIN, LOW); DBG_OUTPUT_PORT.begin(115200); DBG_OUTPUT_PORT.setDebugOutput(true); DBG_OUTPUT_PORT.print("\n"); WiFi.mode(WIFI_AP); WiFi.softAPConfig(apIP, apIP, IPAddress(255, 255, 255, 0)); WiFi.softAP(ssid, password); dnsServer.setTTL(300); dnsServer.setErrorReplyCode(DNSReplyCode::ServerFailure); dnsServer.start(DNS_PORT, host, apIP); server.onNotFound(handleNotFound); server.on("/do",HTTP_GET, handleLED); server.begin(); DBG_OUTPUT_PORT.println("HTTP server started"); if (SD.begin(SS)){ DBG_OUTPUT_PORT.println("SD Card initialized."); hasSD = true; } } void loop(void){ dnsServer.processNextRequest(); server.handleClient(); }
Webページ
とりあえず、トップ画面のみ掲載します。ファイルはSDカードに入れています。
SDカードライブラリの制約でファイル名は8.3文字となります。
スマートフォンに表示されているページや画像はSDカードに入れています。
ページは2ページ構成です。
簡単な説明
スマートフォンからは、まずssidがesp8266のアクセスポイントに接続します。
このあたりは、ESP-WROOM-02 で
WiFi.mode(WIFI_AP); WiFi.softAPConfig(apIP, apIP, IPAddress(255, 255, 255, 0)); WiFi.softAP(ssid, password);
次にスマートフォンからブラウザにて、URL http://led.local にアクセスして
LED制御画面を(index.htm)を表示します。
ESP-WROOM-02 でこのアクセスによるコンテンツ画面配信のための、
名前解決は DNSServer dnsServer にて生成したDNSサーバーがやってくれています。
コンテンツの配信は下記のコードでやっています。まずはハンドラの設定は
server.onNotFound(handleNotFound); server.on("/do",HTTP_GET, handleLED);です。 LEDを制御するためのURL(GET)は、スマートフォンから
http://led.local/do?LED=on でLED点灯
http://led.local/do?LED=off でLED消灯
のアクセスでやっています。
このled.local/do のURLでアクセスされた場合にLEDの制御を行うため
server.on("/do",HTTP_GET, handleLED);と記述して、処理を行う関数 habdleLED() を指定しています。またdo?LED=on 形式で
スマートフォンから変数LEDの値を渡す方式(GET)を指定するためにHTTP_GET を
指定しています。
led.local/do 以外のURLでアクセスされた場合は、
server.onNotFound(handleNotFound);
handleNotFound()では、loadFromSdCard(String path) を呼び出して
URLで指定したファイルがあればそのファイルをSDカードから
読みだして、配信を行っています("/" の場合は"/index.htm"ファイルを配信)。
今回はサンプルを参照してサクッと作成しましたが、
Webサーバーを操るにあたり、HTTPのプロトコルをちょっと突っ込んで学ばないと
いけないようです。
ただし、ライブラリが充実しており、ちょっとしたプログラムも意外と簡単に作れることが分かりました。
« windows 10でwhoamiコマンドの動きがなんか違う? | トップページ | 4連8x8ドットLEDマトリックスを試してみる »
「ESP32・ESP8226」カテゴリの記事
- M5Stackで日本語表示(2)(2020.02.04)
- M5StackでMML単音演奏(2020.01.26)
- M5Stackのビープ音、Tone音の爆音対策(2020.01.22)
- M5stackで日本語表示(2020.01.18)
- M5Stack始めました(2019.12.05)
« windows 10でwhoamiコマンドの動きがなんか違う? | トップページ | 4連8x8ドットLEDマトリックスを試してみる »
コメント