ESP-WROOM-02のWEBサーバーでLEDをチカチカさせてみる

以前は、WROOM-02のフラッシュメモリにもともと書かれているATコマンドを使って簡易的なWEBサーバーを作ってサーボを動かしてみたが、今回はESP8266 Communityが用意してくれているWEBサーバーライブラリ(ESP8266WebServer)を利用して、WROOM-02のフラッシュメモリに簡易的なwebサーバーの実装を書き込みLEDをチカチカさせる。ハードウェアとしては、これまでと同様に、秋月電子のAE-ESP-WROOM-02を中心にブレッドボードに組んだものを使っている。

FT231XとWROOM-02

httpリクエストに応じてLEDをチカチカする

先日載せたLEDをチカチカするスケッチを拡張し、httpリクエストに応じてLEDを操作するような具合にしてみた。

#include <ESP8266WiFi.h>
#include <ESP8266WebServer.h>
#include <Ticker.h>

#define RED_LED 12 
#define GRN_LED 14

Ticker ticker;

const char* ssid = "ESP8266AP2";
const char* password = "password";

ESP8266WebServer server(80);

enum  led_style {led_off = 0, led_on = 1, slow_blink = 2, fast_blink = 3 } ;
static enum led_style red_led = led_off;
long tick_counter = 0;

void ticker_func() {
  static byte led_state = 0;
  tick_counter++;
  if (red_led == led_off)
    led_state = 0;
  else if  (red_led == led_on)
    led_state = 1;
  else if ((red_led == slow_blink && (tick_counter % 100 == 0)) || 
      (red_led == fast_blink && (tick_counter % 40 == 0)))
    led_state ^= 1;    
  digitalWrite(RED_LED, led_state);
}

static const char* cpResponse400 = "<HTML><BODY>Bad request</BODY></HTML>\r\n";
static const char* cpResponse200 = "<HTML><BODY style='font-size:48px;'>ESP_HTTPD_LED1<br/><br/>"
 "<br/><a href=/cmd?LED=on>on</a><br/><a href=/cmd?LED=off>off</a><br/>"
 "<a href=/cmd?LED=blink1>blink1</a><br/><a href=/cmd?LED=blink2>blink2</a><br/>"
 "</BODY></HTML>\r\n";

void send_bad_request() {
  server.send(400, "text/html", cpResponse400);
  Serial.println("Bad request");
}

// /cmd?LED=on/off/blink1/blink2
void handleCommand() {
  if (!server.hasArg("LED")) {
      send_bad_request();
      return;
  }
  String cmd = server.arg("LED");
  Serial.println("handleCommand() LED=" + cmd);
  if (cmd == "on")  
    red_led = led_on;
  else if (cmd == "off")
    red_led = led_off;
  else if (cmd == "blink1")
    red_led = slow_blink;
  else if (cmd == "blink2")
    red_led = fast_blink;
  server.send(200, "text/html", cpResponse200);
}

void setup() {
  Serial.begin(115200);
  
  pinMode(RED_LED, OUTPUT);
  pinMode(GRN_LED, OUTPUT);
  digitalWrite(RED_LED, 0);
  digitalWrite(GRN_LED, 0);
  ticker.attach_ms(10, ticker_func);

  WiFi.softAP(ssid, password);
  IPAddress ip = WiFi.softAPIP();
  Serial.println("");
  Serial.println(ssid + String(" starts..")); 
  Serial.print("this AP : "); 
  Serial.println(ip);

  server.on("/cmd", handleCommand);
  server.begin();
  Serial.println("HTTP server started");
}
void loop() { 
  server.handleClient();
  delay(1);
}

※ 最初の掲載時から、cpResponse200の内容を変更しリクエストが正しかったときには、ブラウザにLED操作用のリンク一覧を応答するように変更した。いちいちアドレスバーにオプションを入力するのが面倒になったので。

ライブラリの組み込み

#include <ESP8266WiFi.h>
#include <ESP8266WebServer.h>

この2つの #include によりwifi機能とwifi機能を利用したwebサーバーの実装が組み込まれる。ライブラリを使う側が書くべきことは、ライブラリを使って独自に構築したい部分だけでよくて、このスケッチの場合には、

  • esp8266のwifiをアクセスポイントモードに指定すること
  • 特定のURIが指定された場合の所定の処理を記述すること

の2つだけである。今回のスケッチでは、
http://192.168.4.1/cmd?LED=led_optionsというリクエストをうけたときにLEDを点灯/消灯/点滅し、const char * cpResponse200 に書かれているhtml文をリクエスト元のブラウザに応答する。
led_options の内容については上記ソースの handleCommand()を参照のこと。なお、GPIO14に接続した緑色LEDは操作していない。

Tickerライブラリと、実際にLED用のI/O操作を実行するticker_func()についての説明は省略。

ESP8266WebServer server(80);

この記述により、ライブラリが提供するESP8266WebServerクラスのインスタンス( server )を作成し、引数(80)によってサーバーが待ち受けるポート番号(tcp/80 = httpd)を指定している。スケッチ内では、server に対する操作や参照を行えばよい。

void setup()

2つのLED用のI/Oピンの設定を行った後、ticker.attach_ms(10, ticker_func); により、Tickerライブラリを使った10msecごとのインターバル呼び出しを定義する。
次に、 WiFi.softAP(ssid, password); によってESP8266のwifiモジュールをソフトAP(アクセスポイント)モードに設定する。wifiに関するコードはこれだけ。ssidは”ESP8266AP2″、パスワードは”password”とした。

URIとハンドラの関連付けとサーバーの開始

server.on(“/cmd”, handleCommand);

この行により、クライアントから “/cmd”というURIがリクエストされるごとに、ライブラリの内部からスケッチ側に用意するリクエストハンドラ(この場合は、 void handleCommand(); )が呼び出される。
あとは、スケッチとして書きたい処理(つまり、特定のリクエストに対する操作や応答)を、リクエストハンドラ内に記述すればよくなる。

server.begin();

によって、wifi softAPによるステーションからの接続の受け入れと、wifiを経由したtcp/ip接続の受け入れ処理が開始する。

void loop()

server.handleClient(); を繰り返し呼び出している。このメソッドの内部では、softAPへのwifi接続要求の受け入れ、tcp/80接続の受け入れ、httpリクエスト内容の解析、パラメータの分解と格納、そして先にでてきた、server.on()メソッドで登録済のリクエストハンドラの呼び出しといった処理が行われる。

モニタ出力

シリアルモニタには、以下のようにsoftAPの開始、サーバー自局アドレス、クライアントから受信したリクエスト内容が表示される。

esp_httpd_monitor

動作の様子

動作時の動画を撮ってみた。意図したよりボケてしまいましたが。

既にwifi接続済で、スマホのブラウザから http://192.168.4.1/cmd?LED= とかリクエストして cpReponse200に書かれている応答が表示されている状態から、ブラウザに表示されているリンクをクリックするごとに、手前のブレッドボードに載せた赤いLEDが点灯/点滅/消灯する様子を示している。

きょうのまとめ

意外なほど簡単に実装できた。
ながながとやっているwifiで動かすサーボ雲台の話も、残りはブレッドボード上に3.3Vから5Vにレベル変換するデバイスを載せて、2つのサーボを動かすためのコードを書くだけになってしまった。別のアプローチでは既に動いているものなので、(やれば)すぐにできるのだろう、とは思うのですが。

ブレッドボードではなくて、もっと小さな基板上にハンダ付けして箱に入れるとか、外で使うことを考えて12Vの外部電源(例えば海釣り用電動リールのバッテリとか)も使えるようにするとか、考えてみると、いろいろ無きにしも非ず。