ESP32 -DevKitC ( ESP-WROOM-32 )でスマホとWi-Fi リアルタイム双方向同時通信

記事公開日:2017年3月29日
最終修正日:2017年4月20日

スポンサーリンク

EasyWebSocket Beta 1.51 にアップデートしたことにより、スケッチを変更しました。
(2017/4/19)

また、「複数の SD.h が見つかりました」と警告が出る場合は、インストールした Arduino IDE フォルダの中の libraries フォルダ内の SDフォルダを削除するか、別のフォルダに移動してください。
Arduino 標準の SDライブラリと競合してしまうようです。

こんばんは。

ESP-WROOM-32 電子工作は今まで単体でLDOモジュールを作って動作させていましたが、ESP32 -DevKitC ( ESP-WROOM-32 開発ボード )が秋月電子通商さんで発売されたので、私も早速試してみました。

私の場合は以前、WebSocket を使って、ESP-WROOM-02 ( ESP8266 ) とスマホでWi-Fi リアルタイム双方向通信をしていましたが、多量の文字列を扱うために SRAM の少なさがネックになっていて、フリーズ等に悩まされていました。
ESP32 を使うにあたって、ESP8266 よりも性能がどれくらい優っていて、エラーがどれだけ解消されるかが私にとって重要でした。

そこで、今回は ESP8266 用の自作ライブラリを ESP32 用に移植して、WebSocket 通信を試してみました。
移植するにあたって、Hashライブラリが ESP32 には無かったので、ライセンスが100% Public Domain の sha1.c ソースを使わせていただきました。
Steve Reid さん作です。
Steve Reidさん、ありがとうございます。
m(_ _)m

動作状況は、結論からいうと、Arduino IDE 開発の場合、CPU が80MHz までのため、処理が速くなったという印象はありません。
ただ、ユーザーSRAM領域が5倍大きくなったおかげで、WebSocket 通信がフリーズしても裏でプログラムが動作していて、ESP32 自力でタイムアウトしてWebSocket切断してくれます。
これはESP8266 ではできなかったので、自作ライブラリがSRAMメモリをメチャクチャ食っていたようですね。

そして、ESP-WROOM-32 ( ESP32 ) の ESP8266 より優れている点は、12bit ADコンバーターが3.3V対応になったことで、外付けADコンバーターを使わなくても、CdS ( 硫化カドミウム )セルを使った光センサー値を取得できるようになりました。
今回はそれを使って、スマホからWi-FiでLEDを調光コントロールして、光センサーの値をリアルタイムでスマホに表示させることに挑戦してみました。

リアルタイム双方向通信を売りにしている WebSocket でも、ゲームコントローラーのように怒涛のデータ送受信するとフリーズしますので、データ送信時間間隔をスマホ側で調整できるようにしました。

まずは以下の動画をご覧ください。

いかがでしょうか。

データ転送レートが低いと通信トラフィックが一杯になって、フリーズしていますね。
ブラウザ側と ESP32 側両方の転送レートを変えることによって、フリーズが殆ど無くなりました。
ただ、光センサーの追従は若干遅くなります。
でも、ここまで追従してくれれば十分ですよね。
これを使えば、遠くの場所でコントロールしていても、LEDが点灯したかどうかをスマホ側で確認できます。

ただ、sigmaDelta関数を使っているせいか、全点灯ボタンを押したときに一つだけ点灯しないということがありました。
これの原因は今は全く分かりません。
それ以外は特に問題無く動作してくれるのではないかなと思っています。

因みに、これはWi-Fi のローカルエリアネットワーク内でしか動作確認していません。
WAN を通して、全く別の場所で動作させることはいつか試してみたいと思います。

では、この使い方を説明しようと思いますが、独学の自作ライブラリですので、動作保証は一切しません。
これを使った、いかなるトラブルも当方では責任を負いませんので、予めご了承ください。

ただ、何かありましたらコメント欄等でご連絡いただけると、出来る限りお答えしたいと思っております。

準備するもの

ESP32-DevKitC ( ESP-WROOM-32 開発ボード )
ESPRESSIF社製

ESP32_EWS_CdS_01

これは秋月電子通商さんで販売しております。
ESP32 チップ をモジュール化して、日本で安心して使えるように技適認証取得した ESP-WROOM-32 を使った開発ボードです。

これは LDO ( 低ドロップアウトレギュレーター )が弱いところがありますが、通常使用では今のところ特に問題無く使えています。
また、USBシリアルでスケッチアップロードする場合、スイッチサイエンスさんの ESPr Developer のように自動リセット遷移せず、書き込み失敗することがよくあります。
その辺の回路がまだ甘いように思われます。

SparkFun マイクロSDカードスロット・ピッチ変換基板

Amazon.co.jp

とても単純な micro SD カードスロット基板です。

micro SDHC カード

後で述べますが、miso端子にプルアップ抵抗を入れれば、UHSスピードクラス対応のmicro SDHCカードでも読み込み可能でした。
以下の3種類は動作確認済みです。

Amazon.co.jp

CdSセル 1MΩ GL5528

ESP32_EWS_CdS_02

とりあえず、手元にあった1MΩのものを使いました。

固定抵抗100kΩ 1/2W  1個

ESP32_EWS_CdS_03

1MΩのCdSセルとの分圧抵抗用です。

固定抵抗10kΩ 1/4W 1個

ESP32_EWS_CdS_04

micro SDカード miso端子のプルアップ用です。
これ、重要です。

砲弾型LED 青、赤、緑

ESP32_EWS_CdS_05

5V用くらいのごく普通のLEDで良いです。
ただ、高輝度のものは、電流量が多いので要注意です。
ESP32 のGPIO の最大電流は12mA なので、それ以下で光るものです。

定電流ダイオード E-103 3個

ESP32_EWS_CdS_06

LEDの電流制限用です。
一般にLEDは固定抵抗を使う方が多いのですが、私の場合はちょっと高価でもCRD(定電流ダイオード)をよく使います。
電流が10mA以上流れないので、抵抗値を選ぶ手間が省けて、安全にLEDを点灯できて便利です。
Amazon.co.jp

ブレッドボード SAD-101 (サンハヤト) 2個

このブレッドボードは ESP32-DevKitC を載せても、片側1列、もう片側2列空くのでとても重宝しています。
しかも、2つのブレッドボードを連結できるので、お勧めです。

今回は余裕を持たせて、2つ連結します。

日東 自己融着粘着テープ

電気工事でよく使うブチルゴムテープです。
LEDとCdSセルをくっつける時に使います。
ビニールテープみたいに粘着剤でくっつけるのではなく、粘土みたいに融着できるので便利です。

ジャンパーワイヤー

φ0.65mm の単線ワイヤーならば、ブレッドボードに直挿しできて便利です。

その他、USBケーブル、パソコン等

 

LEDとCdSセルをくっつける

LEDが光ったかどうかを読み取るために、CdS ( 硫化カドミウム )セルという光センサーをLEDにくっつけます。

まず、下図の様に自己融着テープ ( ブチルゴムテープ )をハサミでカットします。
CdSセルの大きさに合わせて、これくらいのものを2つカットします。

ESP32_EWS_CdS_10

1枚を下図の様にリード線の片側にくっつけて、指で押しつぶします。
粘土みたいに潰せばくっつけられます。

ESP32_EWS_CdS_11

そして、下図の様にLEDを巻き込んでくっつけます。
今回は同じ10mAの電流でも一番明るい青色LEDにくっつけました。

ESP32_EWS_CdS_12

もう一枚の自己融着テープを下図の様に巻いていきます。

ESP32_EWS_CdS_13

そして、こんな風に粘土のように潰してくっつけます。

ESP32_EWS_CdS_14

接続する

では、以下の図のように接続してみてください。

ESP32_EWS_CdS_15

最新記事では、micro SDHC カードを使う場合の注意点についてアップしてますので、以下の記事も参照してください。
ESP32 ( ESP-WROOM-32 ) で micro SDHC メモリカードを使う場合の注意点

ここで、重要なのは、micro SD カードホルダの DO端子( miso ) は必ず3.3Vプルアップしておくことです。
これは、最近知ったのですが、このプルアップをやらないと、UHSスピードクラスのmicroSDHCカードを読み込むことができませんでした。
miso ( Master In Slave Out )端子はプルアップしなければならないことは今まで知りませんでした。
気を付けましょう。
この件については、DEKOさんの以下の記事でも書いてありました。

http://ht-deko.com/arduino/esp-wroom-32.html#13

DEKOさんのこのブログは ESP-WROOM-32 ( ESP32 )に関してテンコ盛りでとてもスバラシイです。
是非ご覧になってください。

また、LED は PWM制御で明るさを変えるので、その場合、LED から流れ込む電流によってGND電位が安定しなく、かなり揺れてしまうようです。
よって、micro SDカードスロットのGND とLEDのGND は必ず分けてください
共通にしてしまうと、micro SDカードの読み込み不良になる場合があります。

CdSセルは光の強さによって抵抗値が変わるので、100kΩの抵抗で3.3Vを分圧して、その電圧値を ESP32 のADコンバーター端子で読み取ります。
SVP端子(GPIO #36)がADC端子なので、それを使います。GPIO #36 です。

写真ではこんな感じになります。

ESP32_EWS_CdS_16

CdSセルとLEDをズームした写真はこんな感じです。

ESP32_EWS_CdS_17

Arduino core for the ESP32 のインストール

Arduino IDE でESP32 を開発するために、Arduino core for the ESP32 をインストールします。
この方法は以下のページを参照してください。

Arduino core for the ESP32 のインストール方法

自作ライブラリのインストール

では、私が自作した ESP32 用 Arduino IDE ライブラリをインストールします。
これは、ESP8266用に作ったSD_EasyWebSocketライブラリbeta ver 1.47 をESP32用に移植したものです。
ブラウザと ESP32 ( ESP-WROOM-32 )を WebSocket でリアルタイム双方向通信するものです。
micro SDHC カードからブラウザへHTMLファイルを出力します。
GitHubの以下のページにアップしています。

https://github.com/mgo-tec/ESP32_SD_EasyWebSocket

Arduino IDE へのライブラリインストール方法は以下の記事を参照してください。
ただ、ESP32 の場合、Arduino15フォルダは使わないので、その中のライブラリは削除しなくて結構です。

GitHubにある ZIP形式ライブラリ のインストール方法

ESP8266用ライブラリではArduino core for ESP8266標準のHash.hライブラリをインクルードしていましたが、ESP32 には存在していないので、先に述べたように Steve Reid さん作の sha1.h ライブラリを使用させていただきました。
これがあれば、ブラウザとWebSocket通信のハンドシェイクができます。
改めて、Steve Reid さん、ありがとうございました。

ESP32_SD_EasyWebSocket のライセンスは、Arduino core for ESP8266 内の一部のコードを改変したりしているので、LGPL 2.1 を引き継ぐ形になります。

あと、新しい関数を追加したり、不要な関数を削除したりしています。
移植しているときに感じたのは、マクロを使うと移植が難しいということを改めて感じました。
今後の為にもできるだけそういうものは使わないようにすべきと学習した次第です。

micro SDHCカードにデータファイルをコピーする

大手メーカー製のmicro SDHC カードならば、大体はFAT32でフォーマットされていると思います。
もし、されていなければ、下の記事を参照してください。

micro SD 、micro SDHC カードの初期化(フォーマット)方法

では、次に、データファイルをSDカード内にコピーしていきます。
Windows10 の場合、以下のパスにdataフォルダがあります。

C:\Users\ユーザー名\Documents\Arduino\libraries\ESP32_SD_EasyWebSocket\examples\Auto_Local_IP_sample\data

そこにある以下の3つのテキストファイルをコピーします。

dummy.txt
LIPhead1.txt
LIPhead2.txt

dummyファイルは空のファイルです。
LIPheadファイルはブラウザに送信するHTMLやJavaScript を分割したファイルです。
ESP32 側でテキストとマージ(合体)させて送信するものです。

次に、micro SDHC カードにはルートにEWSフォルダを作成しておきます。

ESP32_EWS_CdS_20

そのフォルダの中に上記の3つのファイルをペーストします。

ESP32_EWS_CdS_21

これでmicro SDHCカードの準備は完了です。
そうしたら、micro SDHCカードを安全に取り出し、SparkFunのカードスロットに挿入します。

スケッチの入力

では、実際にスケッチを入力していきます。

EasyWebSocket ライブラリが Beta 1.51 にバージョンアップしたことにより、スケッチを変更しました。
SRAM消費を節約することができました。
(2017/4/19)
#include <ESP32_SD_EasyWebSocket.h> //beta ver 1.51 
 
const char* ssid = "xxxx"; //ご自分のルーターのSSIDに書き換えてください
const char* password = "xxxx"; //ご自分のルーターのパスワードに書き換えてください
 
const char* HTM_head_file1 = "/EWS/LIPhead1.txt"; //HTMLヘッダファイル1
const char* HTM_head_file2 = "/EWS/LIPhead2.txt"; //HTMLヘッダファイル2
const char* HTML_body_file = "/EWS/dummy.txt"; //HTML body要素ファイル(ここではダミーファイルとしておく)
const char* dummy_file = "/EWS/dummy.txt"; //HTMLファイル連結のためのダミーファイル
 
const uint8_t cs_SD = 5; //SDcard CS(ChipSelect)

SD_EasyWebSocket ews;
 
IPAddress LIP; //ローカルIPアドレス自動取得用
 
String ret_str; //ブラウザから送られてくる文字列格納用
 
int PingSendTime = 10000; //ESP32からブラウザへPing送信する間隔(ms)
 
long ESP32_send_LastTime;
int ESP32_send_Rate = 20;
 
int min_adc = 650; //ブラウザに表示するグラフのADC最小値。環境によって変えてください。
int max_adc = 3800; //ブラウザに表示するグラフのADC最大値。環境によってかえてください。
float adc_deg; //ESP32 の ADC値の範囲
 
#define ledPin1 12 //GPIO #12
#define ledPin2 13 //GPIO #13
#define ledPin3 14 //GPIO #14
#define CdS_cel 36 //GPIO #36
 
void setup() 
{
  pinMode(ledPin1, OUTPUT);
  pinMode(ledPin2, OUTPUT);
  pinMode(ledPin3, OUTPUT);
  pinMode(CdS_cel, INPUT); //cdsセルを接続するポート GPIO #36
     
  ews.AP_Connect(ssid, password);
  delay(1000);
   
  LIP = WiFi.localIP(); //ESP32のローカルIPアドレスを自動取得
 
  Serial.println(); Serial.println("Initializing SD card...");
 
  if (!SD.begin(cs_SD, SPI, 40000000, "/sd")) {
    Serial.println("Card failed, or not present");
    return;
  }
 
  Serial.println("card initialized. OK!");
 
  sigmaDeltaSetup(0, 312500);
  sigmaDeltaSetup(1, 312500);
  sigmaDeltaSetup(2, 312500);
  sigmaDeltaAttachPin(ledPin1,0);
  sigmaDeltaAttachPin(ledPin2,1);
  sigmaDeltaAttachPin(ledPin3,2);
  sigmaDeltaWrite(0, 0); // LED OFF
  sigmaDeltaWrite(1, 0); // LED OFF
  sigmaDeltaWrite(2, 0); // LED OFF
 
  adc_deg = (max_adc - min_adc)/20; //ブラウザに表示するグラフを20分割
   
  ESP32_send_LastTime = millis();
}
 
void loop() {
  websocket_handshake();
   
  if(ret_str != "_close"){
    if(millis()-ESP32_send_LastTime > ESP32_send_Rate){
      websocket_send();
      ESP32_send_LastTime = millis();
    }
 
    ret_str = ews.EWS_ESP32CharReceive(PingSendTime);
    if(ret_str != "\0"){
      Serial.println(ret_str);
      if(ret_str != "Ping"){
        int ws_data = (ret_str[0]-0x30)*100 + (ret_str[1]-0x30)*10 + (ret_str[2]-0x30);
        switch(ret_str[4]){
          case '!':
            ESP32_send_Rate = ws_data;
            break;
          case 'B':
            LED_PWM(1, 0, floor(ws_data/2));
            break;
          case 'G':
            LED_PWM(1, 1, floor(ws_data/2));
            break;
          case 'R':
            LED_PWM(1, 2, floor(ws_data/2));
            break;
          case '_':
            LED_PWM(2, 0, floor(ws_data/2));
            break;
          case 'A':
            LED_PWM(3, 0, ws_data);
            break;
          case 'O':
            LED_PWM(4, 0, ws_data);
            break;
        }
      }
    }
  }else if(ret_str == "_close"){
    ESP32_send_LastTime = millis();
    ret_str = "";
  }
    yield(); //これ重要かも
}
//**************************************************************
void LED_PWM(byte Led_gr, byte channel, int data_i)
{
  Serial.println(data_i);
  switch(Led_gr){
    case 1: //1つのLEDを調光制御
      sigmaDeltaWrite(channel, floor(data_i*2.5));
      break;
    case 2: //3つのLEDを順番に点灯、消灯
      if(data_i < 34){
        sigmaDeltaWrite(0, data_i*7);
        sigmaDeltaWrite(1, 0);
        sigmaDeltaWrite(2, 0);
      }else if(data_i > 33 && data_i < 67){
        sigmaDeltaWrite(1, (data_i-33)*7);
        sigmaDeltaWrite(0, 0);
        sigmaDeltaWrite(2, 0);
      }else if(data_i > 66){
        sigmaDeltaWrite(2, (data_i-66)*7);
        sigmaDeltaWrite(0, 0);
        sigmaDeltaWrite(1, 0);
      }
      break;
    case 3: //3つのLED全点灯
      sigmaDeltaWrite(0, 255);
      sigmaDeltaWrite(1, 255);
      sigmaDeltaWrite(2, 255);
      break;
    case 4: //3つのLED全消灯
      sigmaDeltaWrite(0, 0);
      sigmaDeltaWrite(1, 0);
      sigmaDeltaWrite(2, 0);
      break;
  }
}
//*********************************************
void websocket_send(){
  int adc = analogRead(CdS_cel); //cdsセルセンサー値を読み取る。GPIO #36
  int adc_g = floor(((float)(adc - min_adc)) / adc_deg);
  String graph_str = "";
   
  if(adc_g <= 0 ){
    adc_g = 0;
    graph_str = "OFF";
  }else{
    for(int i=0; i<adc_g; i++){
      graph_str += "■";
    }
  }
   
  ews.EWS_ESP32_Str_SEND(graph_str, "wroomTXT"); //ブラウザに文字列を送信
}
//************************* Websocket handshake **************************************
void websocket_handshake(){  
  if(ews.Get_Http_Req_Status()){
    String html_str1="", html_str2="", html_str3="", html_str4="", html_str5="", html_str6="", html_str7="";

    //※String変数一つにEWS_Canvas_Slider_T関数は2つまでしか入らない
    html_str1 += "<body style='background:#000; color:#fff;'>\r\n";
    html_str1 += "<font size=3>\r\n";
    html_str1 += "ESP-WROOM-32(ESP32)\r\n";
    html_str1 += "<br>\r\n";
    html_str1 += "SD_EasyWebSocket Beta1.51 Sample\r\n";
    html_str1 += "</font><br>\r\n";
    html_str1 += ews.EWS_BrowserSendRate();
    html_str1 += "<br>\r\n";
    html_str1 += ews.EWS_ESP32_SendRate("!esp32t-Rate");
    html_str1 += "<br>\r\n";
    html_str1 += ews.EWS_BrowserReceiveTextTag2("wroomTXT", "from ESP32 DATA", "#555", 20,"#00FF00");
    html_str1 += "<br>\r\n";
    html_str1 += ews.EWS_Status_Text2("WebSocket Status","#555", 20,"#FF00FF");
    html_str1 += "<br><br>\r\n";
    html_str1 += "LED \r\n";
    html_str1 += ews.EWS_On_Momentary_Button("ALL", "ALL-ON", 80,25,15,"#000000","#AAAAAA");
    html_str1 += ews.EWS_On_Momentary_Button("OUT", "ALL-OFF", 80,25,15,"#FFFFFF","#555555");
    html_str1 += "<br>\r\n";
     
    html_str2 += "<br>LED BLUE... Dim\r\n";
    html_str2 += ews.EWS_Canvas_Slider_T("BLUE",200,40,"#777777","#0000ff"); //CanvasスライダーはString文字列に2つまでしか入らない
    html_str2 += "<br>LED GREEN Dim\r\n";
    html_str2 += ews.EWS_Canvas_Slider_T("GREEN",200,40,"#777777","#00ff00"); //CanvasスライダーはString文字列に2つまでしか入らない
     
    html_str3 += "<br>LED RED..... Dim\r\n";
    html_str3 += ews.EWS_Canvas_Slider_T("RED",200,40,"#777777","#ff0000"); //CanvasスライダーはString文字列に2つまでしか入らない
    html_str3 += "<br>LED RGB..... Dim\r\n";
    html_str3 += ews.EWS_Canvas_Slider_T("_RGB",200,40,"#777777","#ffff00");
    
    html_str4 += "<br><br>\r\n";
    html_str4 += ews.EWS_WebSocket_Reconnection_Button2("WS-Reconnect", "grey", 200, 40, "black" , 17);
    html_str4 += "<br><br>\r\n";  
    html_str4 += ews.EWS_Close_Button2("WS CLOSE", "#bbb", 150, 40, "red", 17);
    html_str4 += ews.EWS_Window_ReLoad_Button2("ReLoad", "#bbb", 150, 40, "blue", 17);
    html_str4 += "</body></html>";

    //WebSocket ハンドシェイク関数
    ews.EWS_HandShake_main(3, cs_SD, HTM_head_file1, HTM_head_file2, HTML_body_file, dummy_file, LIP, html_str1, html_str2, html_str3, html_str4, html_str5, html_str6, html_str7);
  }
}

【解説】

●1行目:
自作ライブラリのインクルードです。

●3-4行目:
ここで、xxxxのところをご自分のルーターのSSID とパスワードに書き換えてください。

●6-9行目:
先ほどコピーした micro SDHC カード内のファイルを定義します。
dummy.txtファイルにご自分でHTMLタグを入力しても良いかもしれません。

●11行目:micro SDカードスロットの CSピン ( Chip-Select )を定義します。

●13行目:
自作ライブラリSD_EasyWebSocket のクラス名を定義します。
ews というところを好きな名前にすることができます。

●15行目:
ESP-WROOM-32 ( ESP32 )のWi-Fi ローカルIPアドレスのハンドル名を定義します。

●17行目:
ブラウザからWebSocket通信で送られてくるテキスト形式文字列を格納するためのものです。

●19行目:
ESP-WROOM-32 ( ESP32 )からPingコマンドを送信する間隔を決めます。
ここでは10秒としています。
Ping をブラウザに送信して、Pongが返って来なければ、ESP32側で強制切断します。

●22行目:
ここでは、ESP32 からデータを送信する間隔時間を格納する変数を初期化しています。
最初は20msとしておきます。

●24-26行目:
ESP32 のADコンバーターは12bit なので、電圧値を0-4095 までの値で返します。
LEDが消灯していても、CdSセルは周囲の明るさによって最低電圧値が変わるので、ご自分の環境によってこの値を変えてください。

●28-30行目:
LED を接続するGPIO ピンを定義します。

●35-38行目;
LEDに接続するピンはOUTPUTモードにし、CdSセルに接続するADCピンはINPUTモードにします。

●40行:
ESP-WROOM-32 ( ESP32 )とルーターをコネクションする関数です。

●43行:
ここで、ルーターが割り当てたESP-WROOM-32 ( ESP32 )のローカルIPアドレスを自動取得します。

●47行:
ここで、SDカードライブラリを初期化します。
そこをGPIOピン番号に変えることによって、CSピンを変えることができるようです。
ここは、SD.begin() としても良いのですが、デフォルトの4MHzとなってしまいます。
ここでは40MHz としてみました。

●54-62行:
LED を PWM制御して調光するためのピン設定です。
Arduino UNO では analogWrite などでPWM制御できますが、ESP32 ではsigmaDelta という関数を使うことになります。
54-56行でそれぞれのピンの周波数を決めて、57-59行でGPIOピン番号とsigmaDelta関数のチャンネル番号を定義して、60-62でLEDに出力します。
ここではLEDを消灯してます。
GPIOピン番号とsigmaDelta関数のチャンネル番号とが別々というところがミソですね。

●64行:
CdSセル光センサー値の範囲を20分割します。
後でブラウザにグラフを表示するために使います。

●70行:
メインループ内にこの自作関数を置くことによって、ブラウザとWebSocket ハンドシェイク(コネクション確立)が済んだかどうかを常に監視しています。
167-211行にあります。

●72-111行目:
121行目でブラウザから送信されてくる文字列を格納し、それ以降で文字列から文字を抽出して、条件分岐して処理しています。
ブラウザ側で、Blue のLED が70%点灯というスライダー値を送信したら、
070|BLUE
という文字列をESP32で受信します。
“BLUE” という文字列は68行目でブラウザのボタンのHTMLタグで使われるID文字列です。
そのボタンが押されたら、ID文字列とスライダーの値をESP32側へ送信してくれます。
この文字列を分解して、それぞれLED を制御しています。
Canvas Slider は0-200の値で返ってくるので、Max100%にするために2で割っています。
85行目でブラウザのセレクトボックスからESP32 の送信間隔時間を取得します。
それを73-76行目で判断して、ブラウザに明るさグラフを表示するデータを送信する間隔を決めています。
この時間が小さすぎると、ESP32から怒涛のようにブラウザにデータを送信するので、WebSocketがフリーズする場合があります。
ただ、フリーズしても、Ping送信でPongが返って来なければ強制切断します。

●115-148行:
ここは、LEDをPWM制御で点灯させるための条件分岐です。

●150-165行:
SVPピン( GPIO #36 )で読み取った電圧値を20分割して、その分の文字、”■” を連ねてString文字列としてブラウザに送信します。
164行目の自作ライブラリ関数で実際に送信しています。
“wroomTXT” というID文字列と182行目のブラウザ側のHTMLタグのID文字列と一致させています。

●167-211行:
EasyWebSocket ライブラリの Beta 1.51 から、HTML文字列をローカル関数内で定義することができるようになりました。
それによって、このローカル関数を抜けるとメモリを解放してくれて、SRAM消費の削減になります。
168行目の Get_Http_Req_Status関数は EasyWebSocket ライブラリ Beta 1.51 から追加した関数です。
ブラウザから GET リクエストがあると、ture を返します。
そうしたら、HTML文字列を代入します。
ブラウザに送信するHTMLタグのうち、先ほどコピーしたmicro SDHC カード内のファイルにはヘッダ要素が入っており、ここでは、body要素をString変数に格納して、後でマージしてブラウザに送信します。
ここでSRAMメモリを使わずとも、micro SDHC カードに全て格納しても良いです。
だだ、この場合は自作のHTML文字列吐き出し関数があるので、HTMLを一から組むよりかは楽かと思います。
関数の使い方は過去の当ブログの EasyWebSocket 記事を確認してみて下さい。

因みに、Canvas_Slider関数は文字列が多いため、String変数一つに2つまでしか入れることが出来ません。よって、html_str変数を複数に分けて格納しています。

今回新たに追加した関数が180行目の

EWS_ESP32_SendRate(“ID name”)

です。
これは、ESP32側からブラウザに送信する時間間隔を、スマホ側(ブラウザ側)でSelect Boxでリアルタイムに決めることができます。

スマホによっては、送信間隔を0ms としてしまうとフリーズしてしまので、これを使ってスマホ側で調整できるようにします。

#FF00FF みたいな文字列は色を24bitカラーで指定しています。HTML標準の表記です。

●209行:
EasyWebSocket beta 1.51 から追加になった関数です。
従来のHandShake 関数を分割したものです。
要するに、ここでブラウザとのWebSocket通信ハンドシェイク(コネクション確立)を行います。
最初の数字は3としてください。
この数値は、HTML文字列の送信数やファイル送信数を決めるモード番号です。
詳細は以下のページを参照してください。

EasyWebSocket ライブラリ Beta 1.51 をアップしました

コンパイル実行

まず、コンパイル実行する前に、ご自分のルーターの設定を見直し、ESP-WROOM-32 ( ESP32 )がセキュリティーで弾かれない様にしておいてください。

では、いよいよ、ESP32 -DevKitC で Arduino IDE スケッチをコンパイルしてみましょう。
ESP32-DevKitC の場合は基本的にリセットボタン等を押さなくても書き込みできます。
ただし、リセット自動遷移回路の不具合で、書き込みできない場合が多々あります。
その場合はArduino IDE のメニューの「ツール」でUpload Speed を 115200 にすると書き込める場合があります。
私の場合は921600では度々失敗するので、115200にしたら安定して書き込めました。
ENピンとGNDの間に0.1μFコンデンサを入れると良いという情報がありましたが、私の場合はうまくいきませんでした。
今はOTAでも書き込めるようになったので、安価な製品だからということで、あまり追求せずに諦めています。

コンパイル書き込み成功したら、シリアルモニターを115200bps で起動してください。
文字が表示されていなかったら、ENピンボタン(リセットボタン)を押してください。
リセットボタンは下図の場所です。

ESP32_EWS_CdS_22

シリアルモニターにはこのように表示されます。

ESP32_EWS_CdS_23

ここで表示されたESP-WROOM-32 ( ESP32 )のローカルIPアドレスをスマホのブラウザのURL入力欄に入力してください。
あとは上記の動画のように操作します。

※「複数の SD.h が見つかりました」と警告が出る場合は、インストールした Arduino IDE フォルダの中の libraries フォルダ内の SDフォルダを削除するか、別のフォルダに移動してください。
Arduino 標準の SDライブラリと競合してしまうようです。

動作確認が取れているスマホは以下の通りです。

Android 7.0  Google Chrome
iOS 10.2.1  Safari

Microsoft Edge は動作しないので注意してください。
ブラウザは Google Chrome をお勧めします。

タッチパネルのないパソコンでマウスではCanvasSlider は動作しませんのでご注意ください。

ESP8266の時はAndroidがフリーズが少なく絶好調だったのですが、ESP32 の場合は iOS の方が絶好調でした。
1~2世代前のiPad を使いました。
ハード側の通信能力にも左右されるっぽいですね。

Android Google Chrome操作画面は下図の様になります。

ESP32_EWS_CdS_24

ESP32 の転送Rate初期値は、スケッチ上で20ms にしていますが、フリーズするならばもっと大きい値にしてください。
その代わり、光センサーグラフの反応が遅くなります。
フリーズしたら、10秒後にPingをブラウザに送信するので、Pongが返って来なければ強制切断されます。
そうしたら、WS-Recconect ボタンを押すと再接続されます。

まとめ

いかがでしたでしょうか。
以上、ESP32 -DevKitC ( ESP-WROOM-32 開発ボード )とスマホでWebSocketリアルタイム双方向同時通信でした。
もし、不具合等あればコメント等でご連絡いただけると助かります。

私はまだこのWebSocket でセキュア通信をやったことがありません。
これからの時代はそういう通信が必須になりますので、いつかライブラリを作ろうとは思っています。
また、WANで WebSocket をやったことがないので、これも課題ですね。

Arduino core for the ESP32 はまだまだ発展途上で、CPUが80MHz以上がありません。
今後のクロックアップに期待したいです。
それと、SPIFFSライブラリもありません。
それができれば、何も文句ないのですがね・・・。

ただ、SRAMがESP8266より5倍大きいので、CPUまでフリーズしてしまうことは無くなりました。
それに、3.3V 12bit ADコンバーターが付いているのもとても有難いです。
これからは、ESP-WROOM-32 ( ESP32 )主体で開発していこうと思っています。

ではまた・・・。

スポンサーリンク

広告 と mgo-tec電子工作 関連コンテンツ
Amazon.co.jp広告









投稿者:

mgo-tec

Arduino, ESP8266, ESP-WROOM-02 等を使って、主にスマホと連携した電子工作やプログラミング記事を書いてます。ライブラリも作ったりしてます。趣味、独学でやってますので、動作保証はしません。 電子回路やプログラミングの専門家ではありません。 畑違いの仕事をしてます。 でも、少しだけ電気の知識が必要な仕事なので、電気工事士や工事担任者等の資格は持ってます。

コメントを残す

メールアドレスが公開されることはありません。

*