前回に続き、いよいよプログラミングに入っていきます。
【プログラミング】
早速、ソースプログラムすべてを載せます。
27行目のSSIDと28行目のセキュリティキーは、接続するネットワークのものを入れましょう。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 |
; title="Web LED Switch"]#include <ESP8266WiFi.h> #include <WiFiClient.h> #include <ESP8266WebServer.h> #include <ESP8266mDNS.h> extern "C"{ #include "user_interface.h" } #define LEDPIN 0 const char INDEX_HTML[] = "<!DOCTYPE HTML>" "<html lang=¥"ja¥">" "<head>" "<meta charset=¥"UTF-8¥">" "<title>ESP8266 LED web turn ON-OFF</title>" "<style></style>" "</head>" "<body>" "<form>" "<button type=¥"submit¥" name=¥"led¥" value=¥"lighton¥">LED On</button>" "<button type=¥"submit¥" name=¥"led¥" value=¥"lightoff¥">LED Off</button>" "</form>" "</body>" "</html>"; const char* ssid = "Your SSID"; const char* password = "Your Security Key"; ESP8266WebServer server(80); /* * root process for receiving server request successfully */ void handleRoot(){ if(server.hasArg("led")){ handleSubmit(); }else{ server.send(200, "text/html", INDEX_HTML); } } void handleSubmit(){ if(!server.hasArg("led")){ return returnFail("BAD ARGS"); } char temp[400]; int sec = millis() / 1000; int min = sec / 60; int hr = min / 60; snprintf(temp, 400, INDEX_HTML, hr, min % 60, sec % 60); if(server.arg("led") == "lighton"){ digitalWrite(LEDPIN, HIGH); server.send(200, "text/html", temp); }else if(server.arg("led") == "lightoff"){ digitalWrite(LEDPIN, LOW); server.send(200, "text/html", temp); }else{ returnFail("Bad LED value"); } } /* * Irregular response for server request */ void handleNotFound(){ String message = "File Not Found¥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 += " " + server.argName(i) + ": " + server.arg(i) + "¥n"; } server.send(404, "text/plain", message); } void handleLEDon(){ digitalWrite(LEDPIN, HIGH); returnOK(); } void handleLEDoff(){ digitalWrite(LEDPIN, LOW); returnOK(); } void returnOK(){ server.sendHeader("Connection", "close"); server.sendHeader("Access-Control-Allow-Origin", "*"); server.send(200, "text/plain", "OK¥r¥n"); } void returnFail(String msg){ server.sendHeader("Connection", "close"); server.sendHeader("Access-Control-Allow-Origin", "*"); server.send(500, "text/plain", msg + "¥r¥n"); } void setup() { pinMode(LEDPIN, OUTPUT); digitalWrite(LEDPIN, LOW); 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("esp8266")){ Serial.println("MDNS responder started"); } //Server start up server.on("/", handleRoot); //on access server.on("/lighton", handleLEDon); server.on("/lightoff", handleLEDoff); server.on("/inline", [](){ server.send(200, "text/plain", "this works as well"); }); server.onNotFound(handleNotFound); //not found event server.begin(); Serial.println("HTTP server started"); Serial.print("Access to http://esp8266WebForm.local or http://"); Serial.println(WiFi.localIP()); } void loop() { //int adc = system_adc_read(); //TOUT(pin 16) server.handleClient(); } |
これを、前回で環境構築したESP-WROOM-02に書き込むことで、WebブラウザからESP-WROOM-02にアクセスし、表示された2種類のボタン(On/Off)からLEDを点灯、あるいは消灯させることができます。
それでは、ソースを上から順に追っていきましょう。
まずは必要なライブラリをインクルードしていきます。
1 2 3 4 |
#include <ESP8266WiFi.h> #include <WiFiClient.h> //クライアント処理 #include <ESP8266WebServer.h> //サーバー処理 #include <ESP8266mDNS.h> //DNS設定(独自のドメイン名でアクセスできるようにする) |
続いて、INDEX_HTMLという文字列(char配列)が出てきますが、こちらはESP_WROOM_02に格納されたHTMLファイルで、いわばアクセスするサイトの中身ということになります。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
const char INDEX_HTML[] = "<!DOCTYPE HTML>" "<html lang=¥"ja¥">" "<head>" "<meta charset=¥"UTF-8¥">" "<title>ESP8266 LED web turn ON-OFF</title>" "<style></style>" "</head>" "<body>" "<form>" "<button type=¥"submit¥" name=¥"led¥" value=¥"lighton¥">LED On</button>" "<button type=¥"submit¥" name=¥"led¥" value=¥"lightoff¥">LED Off</button>" "</form>" "</body>" "</html>"; |
直下の部分は、接続するWi-FiネットワークのSSIDとパスワード、そしてサーバーのインスタンスを生成します。
今回はSSIDとパスワードは決め打ち、サーバーはポート80番で接続するようにしています。
1 2 3 |
const char* ssid = "Your SSID"; const char* password = "Your Security Key"; ESP8266WebServer server(80); |
この後は、クライアントからのアクセスに対するコールバックメソッドを定義しています。
まず、handleRootは最初にアクセスを受けた際のイベント処理を定義し、アドレスにledというパラメータがあればhandleSubmitを呼び出し、それ以外は格納されているHTMLファイルをそのまま開くという処理になっています。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 |
/* * root process for receiving server request successfully */ void handleRoot(){ if(server.hasArg("led")){ handleSubmit(); }else{ server.send(200, "text/html", INDEX_HTML); } } void handleSubmit(){ if(!server.hasArg("led")){ return returnFail("BAD ARGS"); } char temp[400]; int sec = millis() / 1000; int min = sec / 60; int hr = min / 60; snprintf(temp, 400, INDEX_HTML, hr, min % 60, sec % 60); if(server.arg("led") == "lighton"){ digitalWrite(LEDPIN, HIGH); server.send(200, "text/html", temp); }else if(server.arg("led") == "lightoff"){ digitalWrite(LEDPIN, LOW); server.send(200, "text/html", temp); }else{ returnFail("Bad LED value"); } } |
続いて、handleNotFoundはサーバー側、つまりESP-WROOM-02にエラーが発生した場合の処理を定義します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
/* * Irregular response for server request */ void handleNotFound(){ String message = "File Not Found¥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 += " " + server.argName(i) + ": " + server.arg(i) + "¥n"; } server.send(404, "text/plain", message); } |
こちらは、ブラウザのボタンを押した際のイベントを定義します。
(文字通り)handleLEDonが点灯、handleLEDoffが消灯の処理となります。
1 2 3 4 5 6 7 8 |
void handleLEDon(){ digitalWrite(LEDPIN, HIGH); returnOK(); } void handleLEDoff(){ digitalWrite(LEDPIN, LOW); returnOK(); } |
そして、クライアントへ送るステータスメッセージの内容を定義します。
イベント処理ではないのですが、前述のイベントメソッドの一部で呼び出されます。returnOKがアクセス成功、returnFailがアクセス失敗をクライアントに通知するメソッドです。
1 2 3 4 5 6 7 8 9 10 |
void returnOK(){ server.sendHeader("Connection", "close"); server.sendHeader("Access-Control-Allow-Origin", "*"); server.send(200, "text/plain", "OK¥r¥n"); } void returnFail(String msg){ server.sendHeader("Connection", "close"); server.sendHeader("Access-Control-Allow-Origin", "*"); server.send(500, "text/plain", msg + "¥r¥n"); } |
一連の準備が完了したところで、いよいよメイン処理に移ります。
まず、setupメソッドで出力ピン設定、シリアル通信とWi-Fi、そしてサーバーを起動します。
ピン設定は、IO0を出力ピンにするため、0(LEDPIN)をデジタル出力と設定します。
続いて、Wi-Fiおよびシリアル通信ですが、まずWiFi.biginメソッドで接続先のSSIDとパスワードを入れてネットワークへの接続を確立します。Wi-Fiへの接続は、WiFi.status()がWL_CONNECTEDになるまで待機しています。
ESP-WROOM-02とのシリアル通信は必須ではないのですが、デバッグ処理に便利なため設定しています。ただ、ESP-WROOM-02の初期設定がボーレート115200bpsとなっているため、プログラム側でも同じ速度に設定します。
最後のサーバー設定は、大まかに(1)コールバック設定、(2)サーバー立ち上げに分かれます。
まず、コールバック設定については、前述のコールバックメソッドを各イベントに合わせて設定します。server.onはクライアントのアクセス時、server.onNotFoundはサーバー内部のエラー発生時の処理を与えます。
必要なコールバック処理を追加したら、server.beginでサーバーとして起動します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 |
void setup() { //pin configuration (IO 0 as output) pinMode(LEDPIN, OUTPUT); digitalWrite(LEDPIN, LOW); //Serial setting Serial.begin(115200); //Wi-Fi initialization (input SSID and password to enter) 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()); //start DNS if(MDNS.begin("esp8266")){ Serial.println("MDNS responder started"); } //Server start up server.on("/", handleRoot); //on access server.on("/lighton", handleLEDon); server.on("/lightoff", handleLEDoff); server.on("/inline", [](){ server.send(200, "text/plain", "this works as well"); }); server.onNotFound(handleNotFound); //not found event server.begin(); Serial.println("HTTP server started"); Serial.print("Access to http://esp8266WebForm.local or http://"); Serial.println(WiFi.localIP()); } |
最後のメインループは、常にクライアントからのアクセスを待機するのみです。
1 2 3 |
void loop() { server.handleClient(); } |
なお、今回使用したモジュール(部品については初回参照)の注意点として、出力に使えるピン番号が0, 2のみのため、プログラムのピン設定も0、あるいは2のどちらかを設定してください。
ちなみに、アナログ出力(PWM)は可能ですが、入力ピンとしてはどちらも一切使えないため、実質このモジュールは出力ピンが2つだけとなっています。
【テスト】
プログラムを書き込んだら、さっそくテストしてみましょう。
手順は以下の通り。
(1)Webブラウザを開く
(2)IPアドレス(あるいはhttp://esp8266WebForm.local)を入力してアクセス
(3)サイトに出てきたボタン(LED On / LED Off)を押す
(4)回路のLEDが点灯/消灯すれば成功
これですべての実装が終わりました。いかがだったでしょうか。
まだまだいろいろと必要な知識も残っていますが、これがIoT電子工作の入門になれば幸いです。
では(・ω・)ノ))
コメント