WebSocketライブラリ、ベータのベータバージョンを作ってみました

WebSocket

ESP-WROOM-02 ( ESP8266 )とスマートフォンのブラウザで双方向リアルタイムストリーミング通信をするための Arduino スケッチライブラリを独自に作ってみました。

ライブラリをバージョンアップしました。
現在 BETA 1.3 です。
こちらのページで紹介してます。再接続しやすくなり、更に使いやすくなりました。
2016/2/20

ライブラリを公開するにあたって、いろいろなハードルが立ちはだかり、なかなかアップできませんでしたが、ようやくこぎ着けました。
何しろ、ライブラリの作成方法から一から勉強してたり、さらにGitHubの使い方が分らず、その勉強もあり、いろいろ大変でした。

ツイッターでつぶやいていたら、Adyさんからいろいろアドバイスをいただきました。
ESP8266 には SPIFFSファイルシステムなるものがあるという情報も教えてもらいました。
EEPROMに近いもので、別途フラッシュにソースを書き込めるらしいんです。
これはスゴイですね。
早速、ライブラリに使わせていただきました。
Adyさん、ありがとうございます!!

では、これからライブラリを使うに当たって、事前のArduino IDEの設定方法やインストールの説明をさせていただきます。
ライブラリはまだベータのベータバージョンで、動作安定性に課題がありますのでご容赦ください。

Android のGoogle Chromeでは問題なく動作するのですが、なぜかiPad のSafariでは通信が途切れたりします。
この辺はまだまだ改善していきたいです。

スポンサーリンク

1.Arduino IDE にESP8266ボードをインストールする

Arduino IDE は 1.8.5で動作確認しております。
Arduino core for ESP8266 のインストール方法は以下の記事を参照してください。

Arduino core for ESP8266 インストール方法

2.SPIFFSファイルシステムアップローダーをインストール

SPIFFSファイルシステムとは、ESP-WROOM-02(ESP8266)のフラッシュメモリをIDEで別途割り当てて、HTMLファイルなどを保存しておき、スケッチプログラムから自由に読み書きができるようにしたものです。要するに1MバイトのSDカードやEEPROMがあるようなものです。
ユーザーがスケッチプログラムをわざわざ書き換えなくても、HTMLだけ書き換えられるという利点があります。とても便利ですね。

SPIFFSファイルシステムアップローダープラグインというものがあります。
それを Arduino IDE にインストールする必要があります。
その方法は以下の記事を参照してください。

Arduino IDE に ESP8266 SPIFFS ファイルシステムアップローダーをインストールする方法

3.独自ライブラリ、EasyWebsocket をインストールする

では、私が独自に作ったWebSocketライブラリをGitHubからダウンロードします。

ライブラリをバージョンアップしました。
現在 BETA 1.3 です。
こちらのページで紹介してます。再接続しやすくなり、更に使いやすくなりました。
2016/2/20

こちらのページ をクリックして下図のようなところのZIPファイルをダウンロードして解凍しておいてください。


いままで、使わせていただいたGitHubに自分のものが掲載されていると、何か感慨深いものがありますね。
なかなかこの使い方やアップロードの方法が難しく、初心者には取っ付きにくいです。
ですが、一度できてしまうと意外とスラスラとアップロードできるようになりました。
Adyさんの言う通りでしたね。
ちなみに、このライブラリはまだベータのベータバージョンですのでご承知おきください。

次に、解凍したフォルダの中のEasyWebSocketというフォルダをArduinoIDEのプログラムフォルダへコピーします。
(EasyWebSocket-masterではなく、その中のEasyWebSocketというフォルダですのでご注意)

64bitウィンドウズPCならば、

C:\Program Files (x86)\Arduino\libraries

というパスになると思います。32bit PCならば(x86)は無しです。
そこにフォルダごとコピーします。

そうしたら、Arduino IDEを再起動します。
すると、下図のようにEasyWebSocketライブラリとサンプルコードが表示されると思います。
これが表示されればインストール成功です。

4.ESP-WROOM-02を接続しておく

ESP-WROOM-02 とUSBシリアルの接続をしておきます。
今回もスイッチサイエンスさんの開発ボードを使用しました。
前回、前々回でも紹介しましたが、これはセッティングが簡単なお勧めボードです。
Amazon さんやスイッチサイエンスさんウェブショップで購入できますが、売れているようで在庫切れの場合がありますのでご注意ください。

ESP-WROOM-02開発ボード
スイッチサイエンス(Switch Science)

ESPr Developer(ピンソケット実装済)
スイッチサイエンス(Switch Science)

もし、手に入らない場合は開発ボードではなく、ESP-WROOM-02単体ボードで接続したこちらのページも参考にしてみてください。

次にサンプルスケッチを動かす場合の例として、下図のように接続しておきます。

どうですか?
このスイッチサイエンスさんの開発ボードは簡単でイイですね!

注意していただきたいのは、GPIO端子には最大12mAまでしか電流を流せないことです。
3.3Vの電圧をかけても12mA未満の電流しか流れないLEDを使ってください。
又は、電流制限抵抗をLEDに直列に接続してください。
12mAを超える電流がGPIO端子に一瞬でも流れると、ESPr Developr ( ESP-WROOM-02, ESP8266 )が即壊れる場合があります。

この接続ができたら、PCとUSBを接続しておきます。
そうしたら、次の設定にいきます。

5.ESP8266ボードの設定

Arduino IDE を再起動し、ツールメニューのGeneric ESP8266 Module を選択します。

次に、ESP8266ボードを下図のように設定し、ポートをご自分の環境のCOMポートを選択します。

CPU Frequency は160MHzが正解です。修正しました(2015/12/3)

Flash Size:  4M (1M SPIFFS) というのが、フラッシュ4Mバイト中の1MがHTMLタグなどのソースコードをメモリしておける領域となります。
スゴイですよね、1Mバイトって・・・。
Arduino Mega でEEPROMが 4kB ですからね。
もの凄いポテンシャルです。

Reset Method:  nodemcu の意味は、GPIO#0やリセットスイッチを切り替えなくても書き込めるというモードです。物理的にリセットスイッチを押してGPIO#0をHIGH、LOWと切り替えて読み込みモード、書き込みモードに切り替えたい場合は ck  にします。
私の場合はそんなの面倒なので、nodemcu にしました。
スイッチサイエンスさんの開発ボードではGPIO#0は押しっぱなしにしなければいけませんので、そんな手間無くしました。
でも、それを切り替えないで書き込みができるのは何か不思議ですね。

6.スケッチの例を使う

EasyWebSocketライブラリにスケッチの例が1つだけありますので、それを呼び出します。

すると下図のようなスケッチが表示されます。

GitHubのサンプルスケッチを修正しました。res_htmlという不要な引数を削除しました(2015/12/2)

【ソースコード】 (※無保証 ※PCの場合、ダブルクリックすればコード全体を選択できます)

#include <EasyWebSocket.h>
#include <ESP8266WiFi.h>
#include <Hash.h>

const char* ssid = "xxxx";
const char* password = "xxxx";
const char* LocalIPaddress = "xxx.xxx.xxx.xxx";

long CountTestTime;

byte cnt = 0;

EasyWebSocket ews;

String html_str;
String ret_str;
String view_scale = "1.1";

byte s_rate = 10;
int port = 80;
int PingSendTime = 3000;

#define ledPin1 12
#define ledPin2 13
#define ledPin3 14

void setup() 
{

  html_str = ews.EWS_Body_style("WHITE", "BLACK");
  html_str += "<h2 style='color:#5555FF'><center>ESP-WROOM-02(ESP8266)<br>\r\n";
  html_str += "EasyWebSocket</center></h2>\r\n";
  html_str += "from WROOM DATA = \r\n";
  html_str += "<font size=4>\r\n";
  html_str += ews.EWS_Receive_Text("text","25px","RED");
  html_str += "<br><br>";
  html_str += "BLUE \r\n";
  html_str += ews.EWS_OnOff_Button("BLUE",60,25,15,"#FFFFFF","#0000FF");
  html_str += ews.EWS_Slider_BoxText("vbox1",30,20,15,"BLACK");
  html_str += ews.EWS_Touch_Slider("BLUE", "vbox1");
  html_str += "<br><br>\r\n";
  html_str += "GREEN \r\n";
  html_str += ews.EWS_OnOff_Button("GREEN",60,25,15,"#000000","#00FF00");
  html_str += ews.EWS_Slider_BoxText("vbox2",30,20,15,"#000000");
  html_str += ews.EWS_Touch_Slider("GREEN", "vbox2");
  html_str += "<br><br>\r\n";
  html_str += "RED\r\n";
  html_str += ews.EWS_OnOff_Button("RED",60,25,15,"#FFFFFF","#FF0000");
  html_str += ews.EWS_Slider_BoxText("vbox3",30,20,15,"BLACK");
  html_str += ews.EWS_Touch_Slider("RED", "vbox3");
  html_str += "<br><br>\r\n";
  html_str += "B-G-R\r\n";
  html_str += ews.EWS_Slider_BoxText("vbox4",40,20,15,"BLACK");
  html_str += ews.EWS_Touch_Slider("BGR", "vbox4") ;
  html_str += "<br><br>\r\n";
  html_str += "<div id='msg' style='font-size:25px; color:#FF0000;'></div><br>\r\n";
  html_str += ews.EWS_Close_Button("WS CLOSE",150,40,17);
  html_str += "<br>\r\n";

  
  ews.AP_Connect(ssid, password);

  ews.EWS_HandShake(LocalIPaddress, view_scale, s_rate, html_str);
  
  CountTestTime = millis();
}

void loop() {
  String str;
  if(ret_str != "_close"){
    if(millis()-CountTestTime > 500){
      if(cnt > 3){
        cnt = 0;
      }
      switch(cnt){
        case 0:
          str = "Hello! World";
          break;
        case 1:
          str = "WebSocket";
          break;
        case 2:
          str = "How are you";
          break;
        case 3:
          str = "Fine!!";
          break;
      }
      
      ews.EWS_String_DATA_SEND(str, "text");
      CountTestTime = millis();
      cnt++;
    }

    ret_str = ews.EWS_Char_Receive(PingSendTime);
    
    if(ret_str != "\0"){
      String led_id = ret_str.substring(ret_str.indexOf("|")+1, ret_str.indexOf(";"));
      Serial.print("ret_str = ");
      Serial.println(ret_str);
      Serial.print("led_id=");
      Serial.println(led_id);
      
      byte ws_data = (ret_str[0]-0x30)*100 + (ret_str[1]-0x30)*10 + (ret_str[2]-0x30);
      LED_PWM(led_id, ws_data);
    }
  }else if(ret_str == "_close"){
    delay(100);
//    char res_html[html_str.length()+1];これは不要です
//    html_str.toCharArray(res_html, html_str.length());これも不要です
    ews.EWS_HandShake(LocalIPaddress, view_scale, s_rate, html_str);
    CountTestTime = millis();
    ret_str = String('\0');
  }
}

void LED_PWM(String str_id, byte data_b)
{
  if(str_id == "BLUE"){
    analogWrite(ledPin1, data_b*2.5);
  }
  if(str_id == "GREEN"){
    analogWrite(ledPin2, data_b*2.5);
  }
  if(str_id == "RED"){
      analogWrite(ledPin3, data_b*2.5);
  }
  if(str_id == "BGR"){
    if(data_b < 34){
      analogWrite(ledPin1, data_b*8);
      analogWrite(ledPin2, 0);
      analogWrite(ledPin3, 0);
    }else if(data_b > 33 && data_b < 67){
      analogWrite(ledPin2, (data_b-33)*8);
      analogWrite(ledPin1, 0);
      analogWrite(ledPin3, 0);
    }else if(data_b > 66){
      analogWrite(ledPin3, (data_b-66)*7.78);
      analogWrite(ledPin1, 0);
      analogWrite(ledPin2, 0);
    }
  }
}

ライブラリのおかげでかなりシンプルになりました。
5~7行目でご自分の環境のSSIDやパスワード、ローカルIPアドレスに書き換えてください。

30~58行目はスマホブラウザに吐き出すHTMLタグです。それをライブラリ化して簡単にボタンやスライダーを設置できるようにしました。
IDを用いてスイッチとGPIOを関連付けてます。
このライブラリの使い方は 次回の記事 で解説してます。

このスケッチを名前を付けて保存しておいてください。
これを保存しておかないと、次のSPIFFSファイルシステムが使えませんのでご注意。

7.SPIFFSファイルシステムアップローダーを使って、HTMLテキストをメモリに書き込む

ちょっとややこしいんですが、いつもよりひと手間増えます。
ESP-WROOM-02のフラッシュROMにライブラリのHTMLテキストデータを書き込みます。

まず、先ほど保存したスケッチのフォルダをご覧ください。
下図のようにdataフォルダがあるので、ここにSPIFFSで書き込むHTMLデータが入ってます。

このデータをArduino IDE プラグインのアップローダーを使って書き込みます。
ツールメニューの下図のところをクリックすると書き込み開始します。
※シリアルモニターは閉じておいてください。シリアルモニターが起動しているとアップロードできません!!

書込み中はこんな感じで、白色の点々が出ます。

これが終了しても何もメッセージが出ません。
ただ単に点々の進行が止まるだけです。
そうしたら、書き込み完了です。
1M書き込むのでかなり時間がかかります。慣れてきたら1M以下でもいいかもしれません。
特にそのテキストファイルを書き換える必要が無ければ次のコンパイルでは事前書込み不要です。

8.スケッチをコンパイルする

次にいよいよコンパイル書き込みです。
今回はGPIO#0をLOWにしたりする必要はありません。
書込みボタンをクリックすると下図のように赤い点々で進行していきます。この点々が出ればプログラムは問題ないということです。

完了したらシリアルモニターを起動してください。
するといつものようにこんな画面になります。

こうなったら、スマートフォンのURL欄にIPアドレスを入力してください。
すると、数秒後に以下の動画のようになります。

SPIFFSファイルシステムで、フラッシュからHTMLデータをSPIで読みだしているので、コネクション確立が少々遅いですね。
これは3年くらい前のAndroidスマートフォンで、Google Chromeです。
スケッチのs_rateを50くらいにしておくと通信が途切れることはありません。
最新式のスマートフォンでCPUやメモリが十分ならばまず途切れません。
ただ、iPad のSafariはなぜか途中で通信が途切れることが多いです。
これがなぜかは未だに分かりません。

ネットワークの通信環境によっても途切れる場合がありますので、その場合はs_rateを50~100にしてみてください。
そうすると、スマホからの送信の間引きが出てくるので、追従性は悪くなります。
まだまだベータのベータ版なので、今後バージョンアップしていきたいです。

今回はここまでです。
この記事を書き上げるのにエライ疲れてしまいました・・・。
次回はこのライブラリの使用方法について説明していきたいと思います。
なお、ご意見や改善点等がありましたら、コメントやお問い合わせフォームでご連絡いただけると幸いです。

最後に、いろいろとアドバイスしていただいたAdyさんに感謝いたします。
Adyさんは私より遙かに高度なものをGitHubにアップされてます。
みなさん、試してみてください。
https://github.com/AdySan/ESPSocket

最新記事ではWebSocket通信をライブラリ化して、格段に使いやすくなりました。
こちらのページをご覧ください。
2016/2/22

Amazon.co.jp 当ブログのおすすめ

スイッチサイエンス ESPr Developer 32 Type-C SSCI-063647
スイッチサイエンス
¥2,420(2024/12/13 03:39時点)
ZEROPLUS ロジックアナライザ LAP-C(16032)
ZEROPLUS
¥28,006(2024/12/13 08:53時点)
Excelでわかるディープラーニング超入門
技術評論社
¥1,970(2024/12/13 00:47時点)

コメント

タイトルとURLをコピーしました