Wi-Fi リモート LEDスイッチ を スマホ ブラウザ で作ってみました。

ESP8266 ( ESP-WROOM-02 )

今回は Wi-Fi リモート LEDスイッチ を スマホ ブラウザ で作ってみました。
ESP-WROOM-02 ( ESP8266 ) と Arduino UNO で UART ( シリアル )通信を使い、スマートフォンブラウザの Google Chrome や iOS Safari にLEDボタンスイッチを設置し、Arduino のdigital端子に接続したLEDの点灯制御をしてみました。なんと、すべてATコマンドでやってのけました。

※ATコマンドを使った通信は、今はもはや動かない可能性があります。
以下のプログラムは無保証とさせて頂きますのでご了承ください。
ESPr Developer などの ESP-WROOM-02開発ボードを使った方が遙かに簡単でおススメです。
ESPr Developer ( ESP-WROOM-02 開発ボード )の使い方をザッと紹介

 

これはAndroidスマホで、Google Chromeですが、
iOSのSafariではこうなります。


スポンサーリンク


iOSの方がボタンが丸くなってカッコいいですね。
もっとボタンを装飾したかったのですが、Arduino UNOではメモリの関係上なのかどうかわからないのですが、長いHTMLは送れませんでした。 結局ほとんどノーマルボタンです。
これ以上のボタンは厳しいですね。
これのポイントは、前回の記事で述べたように、Arduino UNO のソフトウェアシリアルが115200bpsの速度では処理しきれず、文字化けしてしまうということです。
また、ロジックレベル変換モジュールはハードウェアシリアルとソフトウェアシリアルの微妙に異なる速度が影響してか、まともに動作してくれないので、WROOMの出力はAruduinoに直で入れました。
そして、ハードウェアリセットをArduinoのデジタルピンで制御していたのですが、これも誤作動してリセットしてしまうことがあったので、やめました。
文字化けが解消したので、ハードウェアリセットではなく、ソフトウェアリセットで十分だったのです。
そうしたら、けっこうサクサク良好に受信できるようになり、誤作動もほとんどなくなりました。
動画はこんな感じです。

なかなかサクサク動いてくれますよね。

ESP-WROOM-02はamazonさんのマイクロテクニカさん代理店のブレークボードを使用してます。
2mmピンヘッダもハンダ付けしてジャンパーピンをセットしてます。
(※2015年当初とはタイプが異なっています)


これを購入すると取扱説明書がダウンロードできますので、その通りに接続します。

その他の配線はこんな感じです。

※この図にはありませんが、リセットボタンは、必ずプルアップ抵抗をハンダ付けして、ボタンが押されたときに 3.3V と GND がショートしないようにしてください。
この回路図は古いままで、良く分からず作成した当時のものです。

 

ロジックレベル変換は1chしか使わないので、スペースがもったいないです。
これを抵抗で減圧してやってみたのですが、うまくいかなかったので、とりあえずこのモジュールは残しておきます。
青色LEDは電流少なくてもかなり明るかったので、10kΩの抵抗にして、赤と緑は1kΩでちょうどよい明るさでした。
またまた、見切り発車的にプログラムソースコードを一応載せておきますが、まだベータのベータ版ですので、誤り等ありましたらコメントかご連絡ください。 素人的なコードですみません・・・

※88行目を Accept-Encoding から Accept-Language に変更しました
(Arduino IDE 1.6.13で動作確認済み) (2016/12/29更新)

ATコマンドを使った通信は、今はもはや動かない可能性があります。
以下のプログラムは無保証とさせて頂きますのでご了承ください。
ESPr Developer などの ESP-WROOM-02開発ボードを使った方が遙かに簡単でおススメです。
ESPr Developer ( ESP-WROOM-02 開発ボード )の使い方をザッと紹介

 

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

#include <SoftwareSerial.h>

SoftwareSerial ESP8266_Serial(2,3); // RX, TX(2番は使わない)

long LastTime = 0;

boolean WROOM_boot = false;//WROOMが起動したかどうかの判定
boolean WiFi_setup = false;//WIFIセットアップが済んだかどうかの判定

void setup()
{
  Serial.begin(115200);
  while (!Serial) {
    ; // wait for serial port to connect. Needed for Leonardo only
  }
  ESP8266_Serial.begin(115200);
  Serial.println("Wait.");
  delay(5000);
  //LEDのピンモード設定 
  pinMode(8,OUTPUT);
  digitalWrite(8,LOW);
  pinMode(9,OUTPUT);
  digitalWrite(9,LOW);
  pinMode(10,OUTPUT);
  digitalWrite(10,LOW);
  
  ESP8266_Serial.print("AT+RST");//ソフトウェアリセット
  ESP8266_Serial.print("\r\n");
}

void loop()
{
  String str;
  char c;

  if(Serial.available()){//WROOM購入時はreadyのみ返って来る。
    if(WROOM_boot == false){//シリアルが有効であれば、WROOMが起動していると判定
      Serial.println("ESP-WROOM-02 Serial Boot OK!");
      WROOM_boot = true;
    }
    Serial.print(".");
    switch (WiFi_setup){
      case false:
        if(Serial.find("ready")){
          //セットアップ済みならばWIFI CONNECTが返ってきてWIFI GOT ITという文字が返るまで約4秒
          delay(4000);
          Serial.println();
          Serial.println("-----WIFI setup IN");
          //ステーションモード有効コマンド
          ESP8266_Serial.print("AT+CWMODE=1");
          ESP8266_Serial.print("\r\n");
          Data_Read_Display("OK");  //WROOMからのOKレスポンスを受けたら次へ進む
          //アクセスポイントのSSID、パスワード設定コマンド
          ESP8266_Serial.print("AT+CWJAP=\"xxxx\",\"xxxx\"");//ご自分のルーターのSSIDとパスワード  
          ESP8266_Serial.print("\r\n");
          Data_Read_Display("WIFI GOT IP");  //WROOMからWIFI GOT IPというレスポンスを受けたら次へ進む
          //APから割り当てられたIPアドレスとWROOMのMACアドレス確認
          delay(1000);
          ESP8266_Serial.print("AT+CIFSR");
          ESP8266_Serial.print("\r\n");
          Data_Read_Display("OK");//WROOMからのOKレスポンスを受けたら次へ進む
          //マルチプルコネクション有効コマンド
          ESP8266_Serial.print("AT+CIPMUX=1");
          ESP8266_Serial.print("\r\n");
          Data_Read_Display("OK");  //WROOMからのOKレスポンスを受けたら次へ進む
           //サーバーモード有効、ポート番号設定
          ESP8266_Serial.print("AT+CIPSERVER=1,1001");
          ESP8266_Serial.print("\r\n");
          Data_Read_Display("OK");
          Serial.println("Arduino WROOM Server OK!");//この表示が出たらWROOMのサーバー設定終了
          WiFi_setup = true;
        }
        break;
      case true:
        byte ipd_no = 0;
        str = "";
        while(1){
          if(Serial.available()){
            c = Serial.read();
            if(c<0x80 && c>=0){// 不要な文字や読み取り不能な文字をカット
              str += c;
            }
          }
          if(c=='\n'){
            if(str.indexOf("+IPD")>=0){
              ipd_no = str[str.indexOf("+IPD")+5]-0x30;//これが重要。このID番号を取得しておかねばならない
              if(str.indexOf("GET / HTTP")>=0){
                HTTP_Request_Display("Accept-Language",ipd_no);
                delay(1500);//------各自のネットワーク環境に合わせて変えてください
                HTTP_response("WROOM LED SWITCH",ipd_no);
                str = "";
                break;
              }
             
              if(str.indexOf("?")>=0){  //HTTP GETリクエストで?という文字を検知したらLED表示
                char sw = str.charAt(str.indexOf("?")+1);
                switch(sw){
                  case '0':
                    Serial.println("Blue ON");
                    digitalWrite(8,HIGH);
                    digitalWrite(9,LOW);
                    digitalWrite(10,LOW);
                    HTTP_response("Blue LED ON", ipd_no);
                    break;
                  case '1':
                    Serial.println("RED ON");
                    digitalWrite(8,LOW);
                    digitalWrite(9,HIGH);
                    digitalWrite(10,LOW);
                    HTTP_response("RED LED ON", ipd_no);
                    break;
                  case '2':
                    Serial.println("GREEN ON");
                    digitalWrite(8,LOW);
                    digitalWrite(9,LOW);
                    digitalWrite(10,HIGH);
                    HTTP_response("GREEN LED ON", ipd_no);
                    break;
                }
                str = "";
              }else{     //Google ChromeではGET送信の後すぐにfaviconを投げかけてくるところの対処
                HTTP_Request_Display("\r\n",ipd_no);
                delay(1000);
                ESP8266_Serial.print("AT+CIPCLOSE=");
                ESP8266_Serial.print(ipd_no); //------Client IDをかならず付ける
                ESP8266_Serial.print("\r\n");
                Data_Read_Display("OK");
                Serial.println("Connection Close");
                str = "";
                break;
              }
            }
            str = "";
          }
        }
        break;
    }
  }
  
  if((WiFi_setup == false) && (millis()-LastTime > 40000)){//40秒たってもセットアップできない場合、リセット
    Serial.println("Software Reset Again");
    ESP8266_Serial.print("AT+RST");
    ESP8266_Serial.print("\r\n");
    WROOM_boot = false;
    LastTime = millis();
  }
}

//コマンドモニター用関数***********************************
void Data_Read_Display(String response)
{
  char c;
  String str;
  while(1){
    if(Serial.available()){
      c = Serial.read();
      if(c<0x80 && c>=0){// 不要な文字や読み取り不能な文字をカット
        str += c;
      }
    }
    if(c=='\n'){
      if(str.indexOf(response)==0){
        Serial.println(str);
        str = "";
        break;
      }else if(str.indexOf("ERROR")>=0){
        break;
      }
      Serial.print(str);
      str = "";
    }
  }
}
//HTTPリクエストを表示する関数**********************************
void HTTP_Request_Display(String response,byte ipd_no)
{
  char c;
  String str;
  while(1){
    if(Serial.available()){
      c = Serial.read();
      if(c<0x80 && c>=0){// 不要な文字や読み取り不能な文字をカット
        str += c;
      }
    }
    if(c=='\n'){
      if(str.indexOf(response)>=0){
        Serial.println(str);
        str = "";
        break;
      }else if(str.indexOf("GET")>=0){//ブラウザがフリーズした時にGET送信すれば離脱できるようにした
        ESP8266_Serial.print("AT+CIPCLOSE=");
        ESP8266_Serial.print(ipd_no); //-----Client IDをかならず付ける
        ESP8266_Serial.print("\r\n");
        Serial.println("Connection Close");
        str = "";
        Data_Read_Display("\r\n");
        break;
      }
      Serial.print(str);
      str = "";
    }
  }
}

//HTTPレスポンスをブラウザに送信する関数******************************************
void HTTP_response(String message, byte ipd_no)
{
  String http_res;
  String html_str;
  //Stringが長すぎると受け付けないので、2回に分けて送信
  http_res = "HTTP/1.1 200 OK\r\n";
  http_res += "Content-Type: text/html\r\n";
  http_res += "Connection: close\r\n";
  http_res += "\r\n";
  http_res += "<!DOCTYPE html>\r\n";
  http_res += "<html>\r\n";
  http_res += "<head>\r\n";
  http_res += "<meta name=\"viewport\" content=\"initial-scale=1.5\">\r\n";
  http_res += "</head>\r\n";
  
  html_str = "<body>\r\n";
  //ご自分のWROOMローカルアドレスとポート番号を指定  
  html_str += "<form action=\"http://192.168.0.21:1001/\" method=\"get\">\r\n";
  html_str += message;
  html_str += "<br>\r\n";
  html_str += "<input type=\"submit\" name=0 value=\"BLUE\" style=\"color:#00f;\">";
  html_str += "  <input type=\"submit\" name=1 value=\"RED\" style=\"color:#f00;\">";
  html_str += "  <input type=\"submit\" name=2 value=\"GREEN\" style=\"color:#0f0;\">";
  html_str += "</form>\r\n";
  html_str += "</body>\r\n";
  html_str += "</html>\r\n";
  html_str += "\0";
   
  ESP8266_Serial.print("AT+CIPSEND="); //文字送信コマンド。
  ESP8266_Serial.print(ipd_no); //--------Client IDをかならず付ける
  ESP8266_Serial.print(',');
  ESP8266_Serial.print(http_res.length()+html_str.length()); //HTMLのバイト数も送る
  ESP8266_Serial.print("\r\n");
  Serial.readStringUntil('>');  //この記号がWROOMから返ってきたら送信スタンバイOKとなる。
  ESP8266_Serial.print(http_res); //HTML1回目送信
  ESP8266_Serial.print("\r\n");
  ESP8266_Serial.print(html_str);  //HTML2回目送信
  ESP8266_Serial.print("\r\n");
  HTTP_Request_Display("SEND OK",ipd_no);  //SEND OKという文字が返ってきたら次へ進む
  http_res = "";
  html_str = "";
  ESP8266_Serial.print("AT+CIPCLOSE=");//ここでクローズしないと、ブラウザがフリーズする
  ESP8266_Serial.print(ipd_no); //--------Client IDをかならず付ける
  ESP8266_Serial.print("\r\n");
  Serial.println("Connection Close");
  HTTP_Request_Display("\r\n",ipd_no);
}

以前のHello Worldを表示させたプログラムより、遙かにマシになりました。
以前のプログラムはいつかこの方法に近い形で直したいと思います。
因みに、このプログラムで起きたトラブルは当方では責任を負いかねますので、それをご承知おきください。
54行目のSSIDとパスワードはご自分のルーターで設定したものに書き換えてください。
また、224行目もご自分のルーターで設定したローカルIPアドレスに書き換えてください。

このスケッチの詳しい説明は省きますが、大きなポイントはWROOMから発信される
+IPD,0,…
というメッセージで、この番号がスマホなどの端末にWROOMが番号を割り当てているのです。
この番号を使って、ブラウザから送られてきたGETリクエストをクローズしなければ、ブラウザがフリーズします。
プログラムのザックリした流れは以下の通り。

  1. 電源投入後セットアップでシリアルとLED制御ピン設定をし、その後WROOMのソフトウェアリセット
  2. WROOMのシリアル信号をArduinoのハードウェアシリアル0番ピンで有効と判断したらWIFIセットアップ開始。
  3. 再起動直後のWROOMからの76.8kbps信号は無視し、次のいずれかのメッセージで一旦送信が止まります。
    WIFI GOT IT
    (事前にWROOMのWi-Fiセットアップが済んでいる場合)
    WIFI DISCONNECT
    (Wi-Fiセットアップが済んでないか、初めて実行する場合)
    この2種類のパターンがあって、2種類の文字列判別プログラムを組むとメモリーを食いそうだったので、”WIFI”という文字でセットアップ開始を判断させました。
  4. ATコマンドでWi-Fiセットアップ
    AT+CIPSERVER=1,1001 コマンドで、”OK”という文字が返ってきたらセットアップ終了。
    ここで ”ERROR”と出た場合はAruduino を再起動してください。
    エラーになったらOKになるまで再起動を繰り返すプログラムは組んでいません。
    エラー処理はメモリー不足で極力カットしました。
  5. ブラウザからGETリクエストがあったら、HTTPレスポンスを返し、HTMLを送信。
    ここで、必ずCLOSEコマンドをブラウザに送信する。
  6. ブラウザでLEDスイッチが表示されたら、スイッチを押し、ブラウザからGETリクエスト送信。
  7. 受信したリクエスト文字列中の”?”の文字を検出して、次の1文字でLEDの点灯種類を識別して、LED点灯。
    その後、ブラウザにCLOSEコマンドを送信。
  8. HTTPリクエストを表示する関数で、ブラウザがフリーズ状態になっても、ボタンを押してブラウザからGETリクエストを受ければ、CLOSEコマンドを返信して離脱できるようにしました。

以上です。
他にもまだあるのですが、またいつか解説したいと思います。質問等ありましたらご連絡ください。
ここでコンパイルするときに重要な注意があります。
コンパイルするときにはゼロ番ピンを外してください
そして、プログラムをRUNするときはゼロ番ピンにWROOMからの送信信号を挿してください。

コンパイル中は0番ピン、1番ピンを使用してコンパイルしていますので、特に受信用の0番ピンに何か接続してあると、コンパイルできませんのでご注意!!
また、ネットワーク速度の環境によって、受信しきれないなどの問題が発生する場合があります。
当方では2.4GHz 100Mbps で、他のシステムにそんなに繋げてませんので、サクサク動きました。
それに合わせてDelayの秒数を変えてください。
Arduinoのシリアルモニター結果はこんな感じです。

文字化けもすっかりなくなり、バッチリです。
文字列の取りこぼしも殆どなくなりました。
コンパイルし終えたら、USBシリアル変換を使って、Tera Termなどのシリアル用のフリーソフトなどを使って、WROOMからの送信メッセージを同時に見ることをお勧めします。
かなり、ちゃんとしたメッセージが出ていることが確認できると思います。
Arduino WROOM Server OK!
という表示が出たら、ブラウザのURL入力欄で
http://192.168.0.21:1001
というふうに、AT+CIFSRコマンドで得たローカルIPアドレス(または、ルーターのDHCPで割り当てられたアドレス)を入力して、プログラムで指定したポート番号を入力します。
このコマンドに関しては、以前の記事をご覧ください。
そしたら、シリアルモニターがこんな感じで表示されます。

StringクラスやSerial.printを沢山使うと、メモリーがかなり減りますので、できるだけ省略した結果、こうなりました。
WROOMからのメッセージはUSBシリアルで確認してください。
この方法はネットの先駆者が沢山おりますので・・・。
では、ちょっと長くなりましたので、今回はここまでにします。
あくまで、ベータのベータ版でいつものごとく見切り発車的な記事で申し訳ございません。
誤りや意見等ありましたら、コメント等ご連絡ください。
では、また・・・

最近は ESP-WROOM-02 ( ESP8266 )をさらに使い易くした ESPr Developer を使っています。
USB-シリアル変換、余裕のある容量の電源レギュレーター、ロジックレベル変換をパッケージにした ESP-WROOM-02 開発ボードです。
Wi-Fi通信が安定して実現できるので、超お勧めです。
こちらの記事も合わせてご覧ください。
https://www.mgo-tec.com/blog-entry-ss-wroom-howto01.html

その他、以下の記事では Wi-Fi 双方向通信したり、画像を転送したりもできてしまいました。
https://www.mgo-tec.com/blog-entry-jr-train-message-board-01.html
こちらの記事では、スマホのLEDスイッチが簡単に実現できています。
https://www.mgo-tec.com/blog-entry-easywebsocket-beta13.html
https://www.mgo-tec.com/blog-entry-wroom-esp8266-bme280-ssd1351-sd.html
https://www.mgo-tec.com/blog-entry-neopixel-paper-illumination01.html

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

M5Stack Basic
スイッチサイエンス
¥5,203(2021/09/09 23:54時点)
ESPr Developer 32
スイッチサイエンス(Switch Science)
¥2,200(2021/09/09 23:54時点)
ZEROPLUS ロジックアナライザ LAP-C(16032)
ZEROPLUS
¥15,728(2021/09/09 23:54時点)
Excelでわかるディープラーニング超入門
技術評論社
¥2,068(2021/09/09 23:54時点)

コメント

  1. ayush mandloi より:

    In my serial monitor ,it is showing
    wait
    software rest again

    pls help me

    • mgo-tec mgo-tec より:

      Thank you for visiting my blog.
      It will reset automatically reset?
      Or, froze in the standby state, do you have to reset yourself?
      Current supplied to the ESP-WROOM-02 has more leeway 500mA?

  2. より:

    iphone 6plus:
    Arduino WROOM Server OK!
    .Host: 192.168.2.26:1001
    Accept-Encoding: gzip, deflate
    Connection Close

    iphone5:
    Arduino WROOM Server OK!
    .Host: 192.168.2.26:1001
    Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
    Accept-Language: ja-jp
    Connection: keep-alive
    Accept-Encoding: gzip, deflate
    Connection Close

    WINDOWS8 :
    Arduino WROOM Server OK!
    .Host: 192.168.2.26:1001
    Connection: keep-alive
    Upgrade-Insecure-Requests: 1
    User-Agent: Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2883.87 Safari/537.36
    Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
    Accept-Encoding: gzip, deflate, sdch
    Connection Close

    MAC:
    Arduino WROOM Server OK!
    .Host: 192.168.2.26:1001
    Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
    Accept-Language: ja-jp
    Connection: keep-alive
    Accept-Encoding: gzip, deflate
    Connection Close

    WINDOWSから接続しようとしたらセキュルティの問題があるようで、
    IPHONEまたMAC接続しようとしたらやはり同じAccept-Encoding: gzip, deflateにとどまる
    原因はまだ調べているが、とりあえず、コメントさせてください。
    もし、同じ現象があれば、または原因がわかれば、教えていただけると、幸いです。

    • mgo-tec mgo-tec より:

      雲さん

      当ブログをご覧いただき、ありがとうございます。
      久しくATコマンドを使っておらず、検証するのに時間がかかってしまいスミマセン m(_ _)m

      まず、224行目をご自分のESP-WROOM-02 のIPアドレスに書き換えてあるかどうか確認してください。
      次に、88行目を以下のように書き換えてみてください。

      HTTP_Request_Display(“Accept-Language”,ipd_no);

      Google Chrome の場合は、2016/12/29現在では最後の行がAccept-Encoding ではなく、Accept-Languageでした。
      ここはブラウザによって異なる場合がありますので、初回は\r\n などとして、ブラウザから送られてくるメッセージを全て確認しておいた方が良いと思います。
      そこで、シリアルモニターがフリーズ(固まる)すると思いますので、そこが最後の行です。
      その文字列を受信する設定にすれば良いと思います。
      以前は、Accept-Languageでうまく動作しなかったことがありましたが、今は、私の環境ではそれで動作しました。
      ということで、ソースコードも修正しておきました。

      当方の環境は以下の通りです。

      【コンパイル側PC】
      Windows10
      Arduino IDE 1.6.13

      【スマホ側】
      Android 4.2.2 ~ 6.0.1
      Google Chrome

      また、ルーターの環境のセキュリティはESP-WROOM-02が通信できるように解除するなり、設定を見直してください。
      それと、セキュリティソフトの設定も見直して置くと良いと思います。
      ESP-WROOM-02 のHTTPレスポンスではセキュリティソフトを通過できない設定になっている場合があります。

      これでも動作しない場合はまたコメントください。

  3. より:

    mgo-tecさん

    すみません、さっきほど、送ったコメントのスケッチ部分ですが、
    はどうやら、HTML部分がブラウザに飲み込まれたようで、お手数ですが、
    そのコメントを削除してください。
    原因はこちらに貼ります。
    只今自分で色々テスト、修正などして、やっと原因が分かりました。
    問題はramサイズです。スペックの問題ですね
    コンパイルするとき、下記のように表示されますね
    :最大2048バイトのRAMのうち、グローバル変数が1298バイト(65%)を使っていて、ローカル変数で702バイト使うことができます。

    ここの書いてある使用可能のサイズ802byteは必ずブラウザに送信するサイズと受信サイズより大きく残してはいけないので、mgo-tecさんのスケッチのHTML部分のサイズはだいたい470byteで受信サイズはだいたい300byteだっと470+300>702なので受信が全て受信しきれなくて、
    直接CONNECTION CLOSEになってしまった

    こちらは極力HTML部分を削減し、その他のスケッチコメントも極力削除して、HTMLを314byteまで削減し、全体は下記のようにしました。
    最大2048バイトのRAMのうち、グローバル変数が1246バイト(60%)を使っていて、ローカル変数で802バイト使うことができます。
    これでやっと動くようにできました。(IPHONE5.6またWINDOWS8 IE CHROME確認済み)

    • mgo-tec mgo-tec より:

      雲さん

      この前に送られたコメントは指示通りに削除させていただきました。
      とりあえず、動いて良かったですね。

      そうですか・・・RAMですか・・・。
      私の場合はArduino UNO を使って、グローバル変数が1204byte(58%)でした。
      でも、グローバル変数が65%ならば動くと思うのですが・・・。

      私はマイコンやプログラムの専門家ではなく、趣味と独学で得た知識だけですが、その理由はこんな感じです。
      メインloop内で受信したstr文字列は改行’\n’を検知して、文字列検索が終わったらその文字列は捨てられるはずです。
      ですから、受信時はstr文字列バッファに多くても150文字、つまり150byte しか格納しないと思います。
      しかも、メインloopは繰り返す度にstr文字列を初期化しています。
      また、他の関数、HTTP_response なども、その関数内で宣言した変数はグローバル変数ではないので、その関数を抜けるとSRAMを解放するはずです。
      よって、受信時はSRAM容量を超えないと考えられます。
      これが間違えていたら、ご連絡ください。
      でも、文字列を削除したら動いたということは、もしかしたら雲さんの言う通りかもしれません。

      また、文字列を削除しなくても、Fマクロを使うとメモリを削減できます。
      SerialやSoftwareSerial コマンドの文字列を F() で囲うだけです。
      例えば、こんな感じです。

      Serial.println(F(“—–WIFI setup IN”));
      ESP8266_Serial.print(F(“AT+CWMODE=1”));

      これは、String文字列変数には使えません。あくまで、ダブルクォーテーションマークで囲われている文字列のみに使えるものです。
      これを全てのserial出力に書き換えると、私の場合は
      グローバル変数:1204 byte (58%) → 896 byte (43%)
      まで減りました。

      また、全然検討違いかもしれませんが、私が久々にATコマンド通信をした時に、ESP-WROOM-02に供給される電圧が2.9V付近でした。
      その場合は正常に動作せず、リセットを繰り返したりしました。
      結局、ブレッドボードの接触不良で、グリグリとジャンパーワイヤーを動かしたら3.1V付近に復活して、安定動作するようになりました。
      ESP-WROOM-02 はWi-Fi通信中はかなり電力を消費しますので、瞬時電圧降下が起こってしまうと動作不良起こすので気を付けたいデバイスだということを改めて感じました。

      今、私の場合はUSBシリアル変換やロジックレベル変換、電源レギュレーターをパッケージにしたスイッチサイエンス製の ESPr Developer(ESP-WROOM-02開発ボード)を使用しています。
      これは、Arduino UNO を使わずとも、そのまま直にスケッチを書き込めて、確実に安定動作します。
      しかも、SRAM は81kB (内ユーザーメモリ40kB)もあります。
      Arduino UNO の約20倍のグローバル変数を使うことができるんです。
      これを使えば、ATコマンド不要で、簡単にWiFi通信ができますよ。
      参考記事:ESPr Developer ( ESP-WROOM-02 開発ボード )の使い方をザッと紹介

      では、長くなりましたが、また何かありましたらコメントいただけると幸いです。

  4. より:

    mgo-tecさん

    ご回答ありがとうございます。
    何回テストしたところ、はやりRAMは700~800以上残らないと、受信するとき
    固まってしまいます。
    ご紹介していただいたF()の機能を利用すれば、1200BYTE以上ram残れるので、バッチリ動きます。
    フラッシュメモリはRAM全然大きいのでやはりF()の機能使ったほうがいいですね。
    どうもありがとうございました。
    色々サイト見ましたが、やはりmgo-tecさんの記事は一番くわしいし、フォローまでしていただいた、本当に有難うございました。
    大変勉強になりました。
    ESPr Developer は便利そうで、今度切り替えてESPr Developer を購入してみます。
    こちらはプログラマーで電子について、初めて、同じ興味で、独学してます。
    また、よろしくお願いいたします。<3

    • mgo-tec mgo-tec より:

      なるほど・・・。
      実は、このプログラムを作った当時はメモリがギリギリで、グローバル変数を減らすことに苦労していました。
      String文字列系の関数は予想以上にRAMを消費するということなんでしょうね。
      今回の件は、私も勉強させていただきました。
      私なりの検証が終わったら、トラブルシューティング記事に挙げようと思ってます。
      こちらこそ、ありがとうございました。m(_ _)m

    • mgo-tec mgo-tec より:

      雲さん

      今さらですが、当方でポインタや配列について勉強し直している最中で、いろいろ分かって来ました。
      Arduino UNO の 2KB のメモリの場合、コンパイラでグローバル変数領域が15%しか使っていなくても、ローカル変数内で配列宣言をRAMの80%くらいの領域を確保してしまったら、誤動作することが分かりました。
      これは気を付けなければいけないですね。

      ということで、ここで作った私のプログラムもメモリがギリギリなので、エラーが出やすいことが分かりました。
      プログラマの雲さんのおっしゃる通りでした。
      やはり、RAMの容量を常に意識しながらプログラミングしなければいけないですね。
      とても勉強になりました。

      • より:

        お久しぶりです。雲です(1年たったか 笑)
        最近、チームを組んでLotを始めようとていて、例のWIFI機能を利用して、
        家電のリモコン操作の開発をしています、形ができたら商品化でもしようと思っています。
        そのため、また一年前勉強したことを復習しようと思ったら、いつの間にまたコメントしていただいてありがとうございます。
        御サイトは本当に素晴らしく、いろいろ勉強になりました。

        もし東京あたりに住んでいっらっしゃいましたら、ぜひ1度お会いできたら、うれしいです。

  5. より:

    補足ですが、私は次世代の商品の開発を目指していて、今は色々な人と会って、いつかこの世界を変えるという馬鹿な夢をもっている仲間を集めています。もしmgo-tecさんも自分が作ったものを商品化する思いがあれば、ぜひお力をお貸ししてください。

    • mgo-tec mgo-tec より:

      雲さん

      ご無沙汰しております。
      また、当ブログにお越しいただき、こちらこそ感謝いたします。
      この記事は、私がまだまだ勉強不足な時期でして、そんなところに再度ご覧いただくとは、たいへん恐縮です。

      商品化ですか!
      スゴイですね!
      世知辛い世の中で、そういう強い意志で夢に向かって実行されることをとても羨ましく思います。
      とても有難いお話で、神棚に飾っておきたいくらいのコメントです。

      私も一人メーカーの道を夢見た時期がありました。
      しかし、いろいろな家庭の諸事情と親の介護などもあり、とても新しい挑戦ができる状態ではありません。
      空いた時間にひたすら電子工作とブログ記事を書くだけで精一杯な状態です。

      そういうわけで、折角のとても有難いお誘いで、たいへん心苦しいのですが、お断りさせて頂くしかありません。
      大変申し訳ございません。
      m(_ _)m

  6. より:

    ご返信、ありがとうございます。
    こちらも仕事しながら、空いている時間を利用して商品を開発しております。他の仲間もそうですが、ちゃんと製品になるまでは副業として進めています。
    ご家庭の諸事情もあり、一緒にできないことは大変残念ですが、もしほんの一瞬でも一緒に同じ夢を目指したいでも思ったらぜひご連絡ください。

    • mgo-tec mgo-tec より:

      ご期待に応えられず、本当に申し訳ありません。
      m(_ _)m
      わくわくするような開発ができることをお祈りしております。

  7. あかい より:

    WIFIセットアップとは何ですか?
    ソフトウェアリセットが繰り返されるのですが…

    素人ですみません….

    • mgo-tec mgo-tec より:

      あかいさん

      記事をご覧いただき、ありがとうございます。

      もう3年以上前で、プログラミングを始めて間もない時期のもので、改めて見てお恥ずかしい限りです。

      WiFiセットアップ完了とは、WiFi_setup == true になった場合です。
      ソフトウェアリセットが繰り返される原因は、電源の容量が足りないことが多いです。

      ただ、これは3年以上前に書いたもので、ATコマンドも動くかどうか分かりません。
      Espressif Systems社の AT コマンドもバージョンアップを繰り返しており、今あるかどうかも分かりません。
      基本的にプログラム自身も無保証とさせていただいております。
      もし、ESP-WROOM-02 を使ってスマホと通信したいのならば、ESPr Developer などの開発ボードを使って、Arduino プログラムを直に書き込んだ方が遙かに簡単です。
      電源もしっかりしています。
      以下の記事をご参照ください。
      https://www.mgo-tec.com/blog-entry-ss-wroom-howto01.html
      ATコマンドしか知らなかった時には、このことを知らずにとても面倒なことをやっておりました。
      Arduino 実機が不要で、ESP-WROOM-02 自体を Arduino化できるので、とてもお勧めです。
      ところで、どうしても Arduino UNO を使用されたいのでしょうか?

      • あかい より:

        このsoftware rest againの現象の解決方法を教えてください!!
        ————
        ありがとうございます。電源容量が足りないということは、このコードを動かすのはやっぱり無理そうなんですかね。
        実はArduino UNOとESP8266でwifiを用いたものを作ろう(授業です笑)として、まずは基本的なスマホからのLチカを実装しようと思ったのですか、なかなかうまくいかず….

        いろんなサイトを見てコードを動かしてみるのですが、なかなかうまくいかないものですね(笑)

        • mgo-tec mgo-tec より:

          あかいさん

          なるほど、そういうことですか。
          この記事を書いた当時はこれしか知らなかったのですが、今思えば、ATコマンドで通信はESP8266を使う場合、最も難しい課題だと思います。
          今はもっと簡単に ESP8266 だけでLチカできるんですけどね。

          ところで、使っている部品はここの記事で記載されているものと全く同じパーツを使っていますでしょうか?

          • あかい より:

            返信ありがとうございます。基本的には一緒だと思います。

            arduinoとesp8266とブレッドボードを3つ縦に重ねてピンを差し込んでいる状態のものを使ってます。
            arduinoとpcをUSBでつないでます。

            他の記事ではesp8266WebServer.hなどを使ったものが多いんですけど、やはりそちらの方が簡単なんですかね?

          • mgo-tec mgo-tec より:

            あかいさん

            なるほど。
            esp8266WebServer.h というライブラリは、ATコマンドも使わず、Arduino UNO を使いません。
            ESP8266 単体に Arduino スケッチを描き込むものです。
            もし、Arduino UNO を使わなくても良いのであれば、そちらの方が断然簡単です。
            Arduino UNO を使わない、以下のリンクの構成で、Arduino プログラムを直接 ESP8266 に書き込めます。
            https://www.mgo-tec.com/blog-entry-50.html
            ただし、これでも電源や回路があまりよろしくないので、私は ESPr Developer を使っています。

  8. あかい より:

    なるほど、ありがとうございます。arduino unoは使わないんですね。

    ただ私はarduinoを、介さないと繋げられない状態なので、arduino unoは必須ですね笑

    頑張ってみます。

    • mgo-tec mgo-tec より:

      なるほど。
      Arduino UNO 必須ですか。

      昔、リセットを繰り返したときは、WiFi が起動すると、大電流が流れて、電圧降下を起こし、ESP-WROOM-02 が再起動することが何度もありました。
      過去の記事やその後の記事を読んでもらえると分かると思います。
      もう一つは、ここの記事のスケッチで、既にSRAMメモリが一杯いっぱいです。
      メモリーオーバーで再起動することもあります。
      最新の Arduino UNO や ESP-WROOM-02 ではもしかしたら動かない可能性もあります。
      私の手元には古いものしかないので、再現実験は出来ない状態です。
      お役に立てず申し訳ございません。
      今後何か分かりましたら、お知らせします。
      m(_ _)m

      • あかい より:

        何度もすみません。
        上記のプログラムで他のプログラムと合わせてプログラムを書いてみて、動かしてみたんですけど、htmlの送信まではうまくいくんですけど、ページがブラウザ上に表示されません。
        chrome,Safariと試しましたが、アクセスが拒否されます。なにかわかりますでしょうか?

        • mgo-tec mgo-tec より:

          あかいさん

          こちらこそすみません。
          私の方では、ESP-WROOM-02 の FLASH が動かなくなっていて、FLASH Download tool を使いましたが、最新版では動作しない状態で、再現できませんでした。
          ですから、あまりアドバイスできませんが、HTMl の送信が成功しているのであれば、ローカルIPアドレスがご自分のESP-WROOM-02のアドレスと合っているか確認してみてください。
          このページのソースコードで言うと、54行目と224行目です。
          シリアルモニターに表示されたIPアドレスと合っていれば良いです。
          あとは、Google Chrome や Safari は、この記事を書いた当初よりもかなりバージョンアップしていて、コネクション方法を変えないと正しく認識してくれないかも知れません。
          スマホから送られてきたメッセージを全て残らず受信し切り、それが終わってからESP8266からレスポンスを返すところがポイントです。
          これは少々HTMLやHTTPリクエスト、レスポンスの知識が必要になります。

          私は、今取組中の課題があり、ここに掛かり切りになれずにいます。
          新しい ESP-WROOM-02 を買って試すことも考えていますが、ちょっと手が回りません。
          いつか再現しようと思いますが、しばらく時間がかかると思います。
          多分、あかいさんはUNOを使わざるを得ないと思いますので、こんなことを言ってもあまり意味ないかもしれませんが、私は ESP-WROOM-02 に直接 Arduino コードを書き込むことを強くお勧めします。
          この程度しかアドバイスできず、お役に立てず、申し訳ございません。
          m(_ _)m

          • mgo-tec mgo-tec より:

            あかいさん

            ようやく、当方で再現を試すことができました。
            といっても、私が昔から手持ちで持っていた ESP-WROOM-02 を使ってみたところ、特に問題無くできました。

            まず、お聞きしたいのは、
            Arduino WROOM Server OK!
            というメッセージがシリアルモニターに表示されるところまで行きましたでしょうか?
            これが表示されたかそこまですら表示されないかで、対応が異なります。
            私は、Arduino WROOM Server OK! まで表示されたのですが、IPアドレスの後に「:1001」をブラウザのURL入力欄に入力するのを忘れていて、ちょっとハマりました。

            ということで、お返事お待ちしております。

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