ESP8266とブラウザ上で動作するWebアプリとを、WebSocketで接続し、ブラウザ上に表示されているスライダーにより、ESP8266に接続したRGBフルカラーLEDの色を変更します。ESP8266は、「TRIAL-ESP8266-LEAFキットでWi-Fi接続」TRIAL-ESP8266-LEAFキットを使用します。また、「Raspberry PiにNode.jsのインストールしてWebSocketを実装」では、Raspberry PiでNode.jsによりWebSocketを実装しました。

ESP8266の結線

TRIAL-ESP8266-LEAFキットのSV4の信号ピンに、次のように結線します。電源はアルカリ電池3本(4.5V)を接続します。

TRIAL-ESP8266-LEAFキットのSV4の信号ピンの結線
SV4の信号ピン 接続先
3.3V 電池+
D12 LED(G)
D13 LED(B)
D15 LED(R)
GND 電池-とLED(カソード)

RGBフルカラーLEDの信号割り当てを次に示します。

RGBフルカラーLEDの信号割り当て

WebSocketライブラリのインストール

WebSocketライブラリは、「arduinoWebSockets」を使用します。GitHub からダウンロードしたZIP形式のArduinoライブラリを、次の手順でインストールします。

  1. Arduino IDE を開いて、メニューバーの「スケッチ」⇒「ZIP形式のライブラリをインストール」をクリックします。
  2. ダイアログが表示されるので、ダウンロードしたZIP形式のArduinoライブラリを選択します。
  3. メニューバーの「ファイル」⇒「スケッチ例」から次のようにWebSocketライブラリを使用したスケッチ例が登録されていることを確認します。
  4. WebSocketライブラリスケッチ例

ESP8266側プログラム作成

サーバとして作成するESP8266側プログラム「WebSocketServerAllFunctionsDemo.ino」を次に示します。このプログラムは「WebSocketServerAllFunctionsDemo.ino」を参考に作成しています。

  • 93行目でIPアドレスを「192.168.10.20」に固定します。
  • 109行目で、イベントのコールバック「webSocketEvent」をメソッド「onEvent」により登録します。35行目のコールバック「webSocketEvent」で接続、切断、受信時のイベントを受け取ります。
  • 148行目で、10秒ごとに「sendTXT」メソッドを使ってクライアントに「ping TomoSoft」を送信します。クライアントのソケットIDは、47行目で接続時にパラメータで渡される値「num」を変数「socketid」に保存します。

WebSocketServerAllFunctionsDemo.ino

/*
   WebSocketServerAllFunctionsDemo.ino

    Created on: 10.05.2018

*/

#include <Arduino.h>

#include <ESP8266WiFi.h>
#include <ESP8266WiFiMulti.h>
#include <WebSocketsServer.h>
#include <ESP8266WebServer.h>
#include <ESP8266mDNS.h>
#include <Hash.h>

#define LED_RED     15
#define LED_GREEN   12
#define LED_BLUE    13

#define USE_SERIAL Serial

IPAddress ip(192, 168, 10, 20); //ip
IPAddress gateway(192, 168, 10, 1);
IPAddress subnet(255, 255, 255, 0);
IPAddress DNS(192, 168, 10, 1);

ESP8266WiFiMulti WiFiMulti;

ESP8266WebServer server(80);
WebSocketsServer webSocket = WebSocketsServer(81);

int socketid;

void webSocketEvent(uint8_t num, WStype_t type, uint8_t * payload, size_t length) {

  switch (type) {
    case WStype_DISCONNECTED:
      USE_SERIAL.printf("[%u] Disconnected!\n", num);
      break;
    case WStype_CONNECTED: {
        IPAddress ip = webSocket.remoteIP(num);
        USE_SERIAL.printf("[%u] Connected from %d.%d.%d.%d url: %s\n", num, ip[0], ip[1], ip[2], ip[3], payload);

        // send message to client
        webSocket.sendTXT(num, "Connected TomoSoft");
        socketid = num;
      }
      break;
    case WStype_TEXT:
      USE_SERIAL.printf("[%u] get Text: %s\n", num, payload);

      if (payload[0] == '#') {
        // we get RGB data

        // decode rgb data
        uint32_t rgb = (uint32_t) strtol((const char *) &payload[1], NULL, 16);

        analogWrite(LED_RED, ((rgb >> 16) & 0xFF));
        analogWrite(LED_GREEN, ((rgb >> 8) & 0xFF));
        analogWrite(LED_BLUE, ((rgb >> 0) & 0xFF));
      }
      break;
  }
}

void setup() {
  //USE_SERIAL.begin(921600);
  USE_SERIAL.begin(115200);

  //USE_SERIAL.setDebugOutput(true);

  USE_SERIAL.println();
  USE_SERIAL.println();
  USE_SERIAL.println();

  for (uint8_t t = 4; t > 0; t--) {
    USE_SERIAL.printf("[SETUP] BOOT01 WAIT %d...\n", t);
    USE_SERIAL.flush();
    delay(1000);
  }

  pinMode(LED_RED, OUTPUT);
  pinMode(LED_GREEN, OUTPUT);
  pinMode(LED_BLUE, OUTPUT);

  digitalWrite(LED_RED, 1);
  digitalWrite(LED_GREEN, 1);
  digitalWrite(LED_BLUE, 1);

  WiFi.config(ip, gateway, subnet, DNS); //static_ip
  delay(100);

  WiFiMulti.addAP("SSID, "PASS");

  while (WiFiMulti.run() != WL_CONNECTED) {
    delay(100);
  }

  USE_SERIAL.printf("Module IP: ");
  //USE_SERIAL.printf(WiFi.localIP()[0]);
  ip = WiFi.localIP();
  USE_SERIAL.println(ip);

  // start webSocket server
  webSocket.begin();
  webSocket.onEvent(webSocketEvent);

  if (MDNS.begin("esp8266")) {
    USE_SERIAL.println("MDNS responder started");
  }

  // handle index
  server.on("/", []() {
    // send index.html
    //server.send(200, "text/html", "<html><head><script>var connection = new WebSocket('ws://'+location.hostname+':81/', ['arduino']);connection.onopen = function () {  connection.send('Connect ' + new Date()); }; connection.onerror = function (error) {    console.log('WebSocket Error ', error);};connection.onmessage = function (e) {  console.log('Server: ', e.data);};function sendRGB() {  var r = parseInt(document.getElementById('r').value).toString(16);  var g = parseInt(document.getElementById('g').value).toString(16);  var b = parseInt(document.getElementById('b').value).toString(16);  if(r.length < 2) { r = '0' + r; }   if(g.length < 2) { g = '0' + g; }   if(b.length < 2) { b = '0' + b; }   var rgb = '#'+r+g+b;    console.log('RGB: ' + rgb); connection.send(rgb); }</script></head><body>LED Control:<br/><br/>R: <input id=\"r\" type=\"range\" min=\"0\" max=\"255\" step=\"1\" oninput=\"sendRGB();\" /><br/>G: <input id=\"g\" type=\"range\" min=\"0\" max=\"255\" step=\"1\" oninput=\"sendRGB();\" /><br/>B: <input id=\"b\" type=\"range\" min=\"0\" max=\"255\" step=\"1\" oninput=\"sendRGB();\" /><br/></body></html>");
  });

  server.begin();

  // Add service to MDNS
  MDNS.addService("http", "tcp", 80);
  MDNS.addService("ws", "tcp", 81);

  digitalWrite(LED_RED, 0);
  digitalWrite(LED_GREEN, 0);
  digitalWrite(LED_BLUE, 0);

}

unsigned long last_10sec = 0;
unsigned int counter = 0;

void loop() {
  unsigned long t = millis();
  webSocket.loop();
  server.handleClient();

  if ((t - last_10sec) > 10 * 1000) {
    counter++;
    bool ping = (counter % 2);
    int i = webSocket.connectedClients(ping);
    USE_SERIAL.printf("%d Connected websocket clients ping: %d\n", i, ping);
    last_10sec = millis();

    webSocket.sendTXT(socketid, "ping TomoSoft");
  }
}

Webアプリの作成

クライアントとして作成するWebアプリ「index.html」を次に示します。WebSocket オブジェクトのメソッド等の説明については「WebSocket」を参照してください。

  • 6行目で、接続時にサーバ側にメソッド「send」を使って現在時刻を送信します。
  • 11行目で、クライアントから送信したデータをメソッド「onmessage」で受信します。
  • 29行目で、スライダを移動させたときにサーバ側にメソッド「send」を使ってRGB色コードを送信します。

index.html

<html>
  <head>
    <script>
      var connection = new WebSocket('ws://' + '192.168.10.20' + ':81/', ['arduino']);
      connection.onopen = function () {
        connection.send('Connect ' + new Date());
      };
      connection.onerror = function (error) {
        console.log('WebSocket Error ', error);
      };
      connection.onmessage = function (e) {
        console.log('Server: ', e.data);
      };
      function sendRGB() {
        var r = parseInt(document.getElementById('r').value).toString(16);
        var g = parseInt(document.getElementById('g').value).toString(16);
        var b = parseInt(document.getElementById('b').value).toString(16);
        if (r.length < 2) {
          r = '0' + r;
        }
        if (g.length < 2) {
          g = '0' + g;
        }
        if (b.length < 2) {
          b = '0' + b;
        }
        var rgb = '#' + r + g + b;
        console.log('RGB: ' + rgb);
        connection.send(rgb); }
    </script>
  </head>
  <body>
  LED Control:<br/><br/>
    R: <input id="r" type="range" min="0" max="255" step="1" oninput="sendRGB();" /><br/>
    G: <input id="g" type="range" min="0" max="255" step="1" oninput="sendRGB();" /><br/>
    B: <input id="b" type="range" min="0" max="255" step="1" oninput="sendRGB();" /><br/>
  </body>
</html>

WebSocketでの接続

ESP8266に作成したプログラムを書き込み実行します。作成したWebアプリをサーバにアップロードしてアクセスするとブラウザに次のように表示されます。ブラウザでJavaScriptからのメッセージを表示できるようにし、表示されているRスライダーを上げます。

JavaScriptから次のメッセージが表示されます。

 Connected TomoSoft
(index):12 Server:  ping TomoSoft
(index):28 RGB: #808087
(index):28 RGB: #808089
(index):28 RGB: #80808c
(index):28 RGB: #80808e
(index):28 RGB: #808090
(index):28 RGB: #808093
(index):28 RGB: #808095
(index):28 RGB: #808097
(index):28 RGB: #808099
(index):28 RGB: #80809c
(index):28 RGB: #80809e
(index):28 RGB: #8080a0
32(index):12 Server:  ping TomoSoft

ESP8266に接続されたRGBフルカラーLEDが青く点灯します。