ESP-WROOM-32による強度計測にトライ

最終修正日:2020/6/18

ESP32のオリジナル開発モジュールを購入してみたいと思い立ったちました。Espressif 社オリジナルの入手を試みたのですが、なかなか入手しやすいものがないです。AliExpressから入手は可能なようですが、コロナ禍の中、中国からの輸入は躊躇します。
技適を取得しているかどうかは重要だと思っています。ESP-WROOM-32は技適を取得しておりマークも付いているので変な心配が一つ減ります。
スイッチサイエンスはESP-WROOM-32を独自モジュールに載せて販売しています。秋月はEspressif 社オリジナルを安価に扱っていました。それも38pinDIPタイプで自分が欲するモノでした。ところがアンテナ部がモジュールから飛び出しています。これ折れやすいという情報もあり避けたいと思っていました。DIP化キットは期待通りなのですが、この場合自分で半田付けしないといけません。

結局Amazonに出店していた WayinTop社の ESP-WROOM-32 モジュールを購入しました。ピンアサイン等の情報公開はしているので使えるだろうという考えです。

既に確認している現象をリストアップして置きます。

サンプルスケッチにジャンプ



初期ファームのまま使ってみる


ESP-WROOM-32開発ボードをArduino IDEで開発する方法
によると、

  1. Settingタブ内のAdditional Boards Manager URLsに次のURLを入力して、Arduino IDEにESP32ボードを追加します。
    https://arduino.esp8266.com/stable/package_esp8266com_index.json
    2020.5.28現在のArduinoIDE最新バージョンは1.8.12です。
    START
  2. ツール>ボード>ボードマネージャーを選択してesp32環境をインストールします。
    2020.6.8の時点での最新版は1.0.4でした。
  3. ArduinoIDEを再起動するとツール>ボードリストに追加したESP32 Module群がリストアップされているはずです。
    ESP32 DEV Module を選択します。自分は以下のように設定しました。
    @ ボード: ESP32 DEV Module
    A Upload Speed 921600
    B CPU Frequency 240MHz
    C Flash Size 2M(FS1M)
    D Flash Mode QIO(fast)
    E Flash Frequency 80MHz
    F Reset Method dtr(aka nodemcu)
    G シリアルポート 実機に合わせて
  4. GetChipIDというサンプルスケッチを書き込んでみました。
    /*
     * 20200608 T.Wanibe 
     * Amazon で扱っていた WayinTop ESP32開発ボード の使い方を勉強するために購入しました。
     * 多分純正の ESP-WROOM32 の条件で使えると思っています。
     * 最大1310720バイトのフラッシュメモリのうち、スケッチが214853バイト(16%)を使っています。
     * 最大327680バイトのRAMのうち、グローバル変数が15396バイト(4%)を使っていて、ローカル変数で312284バイト使うことができます。
     */
    uint64_t chipid;  
    //----------------
    void setup() {
    	Serial.begin(115200);
    }
    //----------------
    void loop() {
    	chipid=ESP.getEfuseMac();                                       //The chip ID is essentially its MAC address(length: 6 bytes).
    	Serial.printf("ESP32 Chip ID = %04X",(uint16_t)(chipid>>32));   //print High 2 bytes
    	Serial.printf("%08X\n",(uint32_t)chipid);                       //print Low 4bytes.
    	delay(3000);
    }

    これまでのように書き込むと『A fatal error occurred: Failed to connect to ESP32: Timed out waiting for packet header』というエラーが発生します。ESPのプログラム書込に際しては『BOOT』ボタンを押した状態で書込開始して、書込完了したらボタンを放せば良いです。ArduinoIDEには以下のようなメッセージが出て書き込めました。
    esptool.py v2.6
    Serial port COM35
    Connecting....
    Chip is ESP32D0WDQ6 (revision 1)
    Features: WiFi, BT, Dual Core, 240MHz, VRef calibration in efuse, Coding Scheme None
    MAC: 24:0a:c4:5e:ed:7c
    Uploading stub...
    Running stub...
    Stub running...
    Changing baud rate to 921600
    Changed.
    Configuring flash size...
    Auto-detected Flash size: 4MB
    Compressed 8192 bytes to 47...
    Writing at 0x0000e000... (100 %)
    Wrote 8192 bytes (47 compressed) at 0x0000e000 in 0.0 seconds (effective 2340.6 kbit/s)...
    Hash of data verified.
    Compressed 17392 bytes to 11186...
    Writing at 0x00001000... (100 %)
    Wrote 17392 bytes (11186 compressed) at 0x00001000 in 0.2 seconds (effective 909.4 kbit/s)...
    Hash of data verified.
    Compressed 214976 bytes to 109251...
    Writing at 0x00010000... (14 %)
    Writing at 0x00014000... (28 %)
    Writing at 0x00018000... (42 %)
    Writing at 0x0001c000... (57 %)
    Writing at 0x00020000... (71 %)
    Writing at 0x00024000... (85 %)
    Writing at 0x00028000... (100 %)
    Wrote 214976 bytes (109251 compressed) at 0x00010000 in 1.8 seconds (effective 946.0 kbit/s)...
    Hash of data verified.
    Compressed 3072 bytes to 128...
    Writing at 0x00008000... (100 %)
    Wrote 3072 bytes (128 compressed) at 0x00008000 in 0.0 seconds (effective 877.7 kbit/s)...
    Hash of data verified.
    Leaving...
    Hard resetting via RTS pin...
  5. 『RST』ボタンを押すとコンソールに以下のようなメッセージが返りました。
    16:04:04.226 -> ets Jun  8 2016 00:22:57
    16:04:04.226 -> 
    16:04:04.226 -> rst:0x1 (POWERON_RESET),boot:0x13 (SPI_FAST_FLASH_BOOT)
    16:04:04.226 -> configsip: 0, SPIWP:0xee
    16:04:04.226 -> clk_drv:0x00,q_drv:0x00,d_drv:0x00,cs0_drv:0x00,hd_drv:0x00,wp_drv:0x00
    16:04:04.226 -> mode:DIO, clock div:1
    16:04:04.226 -> load:0x3fff0018,len:4
    16:04:04.226 -> load:0x3fff001c,len:1216
    16:04:04.226 -> ho 0 tail 12 room 4
    16:04:04.260 -> load:0x40078000,len:9720
    16:04:04.260 -> ho 0 tail 12 room 4
    16:04:04.260 -> load:0x40080400,len:6352
    16:04:04.260 -> entry 0x400806b8
    16:04:04.396 -> ESP32 Chip ID = 7CED5EC40A24

    Chip ID が 7CED5EC40A24 と云う事が判りましたがSSIDとの関連は不明です。なんとなく近い文字列なんですが。。
    もう少し調査すれば何か判るかもしれません。


サンプルスケッチの実行例を挙げてゆきます。
ArduinoIDEには可成りのサンプルスケッチが登録されているのですが、いまいち目的とするスケッチが判らないと自分は感じています。そんな折、先人が紹介記事を書いていました。参考にさせて戴いております。
Arduino(ESP-WROOM-32)サンプルグログラム解説:https://garretlab.web.fc2.com/arduino/esp32/examples/

  1. Chipの情報及びMACアドレスを調査するサンプルスケッチ
  2. NTP時刻同期
  3. WebServerの実行
  4. Chipのリビジョンを確認する方法
  5. EEPROMClassの使用
  6. WiFiScan
  7. WiFi-Control-Car(DHCP)
  8. WiFi-Control-Car(AP)
  9. ESPでAJAXを試す


Chipの情報及びMACアドレスを調査するサンプルスケッチ】

/*
 * 20200609 T.Wanibe 
 * ESP32 Chip ID等更に情報取得する方法を探していたところ見つかったスケッチを実行してみます。
 * 最大1310720バイトのフラッシュメモリのうち、スケッチが216977バイト(16%)を使っています。
 * 最大327680バイトのRAMのうち、グローバル変数が15388バイト(4%)を使っていて、ローカル変数で312292バイト使うことができます。
 */
//-----------------------
void setup(void) {
        Serial.begin(115200);
        Serial.println(F("-----------------------------"));
 
        uint64_t chipid;
        chipid=ESP.getEfuseMac();                                               //The chip ID is essentially its MAC address(length: 6 bytes).
        Serial.printf("ESP32 Chip ID = %04X\r\n",(uint16_t)(chipid>>32));       //print High 2 bytes
 
        Serial.printf("Chip Revision %d\r\n", ESP.getChipRevision());
        esp_chip_info_t chip_info;
        esp_chip_info(&chip_info);
        Serial.printf("Number of Core: %d\r\n",               chip_info.cores);
        Serial.printf("CPU Frequency: %d MHz\r\n",            ESP.getCpuFreqMHz());  
        Serial.printf("Flash Chip Size = %d byte\r\n",        ESP.getFlashChipSize());
        Serial.printf("Flash Frequency = %d Hz\r\n",          ESP.getFlashChipSpeed());
        Serial.printf("ESP-IDF version = %s\r\n",             esp_get_idf_version());
        Serial.printf("Free Heap Size = %d\r\n",              esp_get_free_heap_size());
        Serial.printf("System Free Heap Size = %d\r\n",       system_get_free_heap_size());
        Serial.printf("Minimum Free Heap Size = %d\r\n",      esp_get_minimum_free_heap_size());
        Serial.println();
 
        uint8_t mac0[6];
        esp_efuse_mac_get_default(mac0);
        Serial.printf("Default Mac Address = %02X:%02X:%02X:%02X:%02X:%02X\r\n", mac0[0], mac0[1], mac0[2], mac0[3], mac0[4], mac0[5]);
 
        uint8_t mac1[6];
        esp_efuse_read_mac(mac1);
        Serial.printf("EFuse Mac Address = %02X:%02X:%02X:%02X:%02X:%02X\r\n", mac1[0], mac1[1], mac1[2], mac1[3], mac1[4], mac1[5]);
 
        uint8_t mac2[6];
        system_efuse_read_mac(mac2);
        Serial.printf("System Mac Address = %02X:%02X:%02X:%02X:%02X:%02X\r\n", mac2[0], mac2[1], mac2[2], mac2[3], mac2[4], mac2[5]);
 
        uint8_t mac3[6];
        esp_read_mac(mac3, ESP_MAC_WIFI_STA);
        Serial.printf("[Wi-Fi Station] Mac Address = %02X:%02X:%02X:%02X:%02X:%02X\r\n", mac3[0], mac3[1], mac3[2], mac3[3], mac3[4], mac3[5]);
 
        uint8_t mac4[7];
        esp_read_mac(mac4, ESP_MAC_WIFI_SOFTAP);
        Serial.printf("[Wi-Fi SoftAP] Mac Address = %02X:%02X:%02X:%02X:%02X:%02X\r\n", mac4[0], mac4[1], mac4[2], mac4[3], mac4[4], mac4[5]);
 
        uint8_t mac5[6];
        esp_read_mac(mac5, ESP_MAC_BT);
        Serial.printf("[Bluetooth] Mac Address = %02X:%02X:%02X:%02X:%02X:%02X\r\n", mac5[0], mac5[1], mac5[2], mac5[3], mac5[4], mac5[5]);
 
        uint8_t mac6[6];
        esp_read_mac(mac6, ESP_MAC_ETH);
        Serial.printf("[Ethernet] Mac Address = %02X:%02X:%02X:%02X:%02X:%02X\r\n", mac6[0], mac6[1], mac6[2], mac6[3], mac6[4], mac6[5]);
}
//-----------------------
void loop() {
}

[実行結果]

15:38:51.829 -> ets Jun  8 2016 00:22:57
15:38:51.829 -> 
15:38:51.829 -> rst:0x1 (POWERON_RESET),boot:0x13 (SPI_FAST_FLASH_BOOT)
15:38:51.829 -> configsip: 0, SPIWP:0xee
15:38:51.863 -> clk_drv:0x00,q_drv:0x00,d_drv:0x00,cs0_drv:0x00,hd_drv:0x00,wp_drv:0x00
15:38:51.863 -> mode:DIO, clock div:1
15:38:51.863 -> load:0x3fff0018,len:4
15:38:51.863 -> load:0x3fff001c,len:1216
15:38:51.863 -> ho 0 tail 12 room 4
15:38:51.863 -> load:0x40078000,len:9720
15:38:51.863 -> ho 0 tail 12 room 4
15:38:51.863 -> load:0x40080400,len:6352
15:38:51.863 -> entry 0x400806b8
15:38:51.999 -> -----------------------------
15:38:51.999 -> ESP32 Chip ID = 7CED
15:38:51.999 -> Chip Revision 1
15:38:51.999 -> Number of Core: 2
15:38:51.999 -> CPU Frequency: 240 MHz
15:38:51.999 -> Flash Chip Size = 4194304 byte
15:38:52.033 -> Flash Frequency = 80000000 Hz
15:38:52.033 -> ESP-IDF version = v3.2.3-14-gd3e562907
15:38:52.033 -> Free Heap Size = 289780
15:38:52.033 -> System Free Heap Size = 289780
15:38:52.033 -> Minimum Free Heap Size = 283732
15:38:52.033 -> 
15:38:52.033 -> Default Mac Address = 24:0A:C4:5E:ED:7C
15:38:52.033 -> EFuse Mac Address = 24:0A:C4:5E:ED:7C
15:38:52.033 -> System Mac Address = 24:0A:C4:5E:ED:7C
15:38:52.033 -> [Wi-Fi Station] Mac Address = 24:0A:C4:5E:ED:7C
15:38:52.033 -> [Wi-Fi SoftAP] Mac Address = 24:0A:C4:5E:ED:7D
15:38:52.067 -> [Bluetooth] Mac Address = 24:0A:C4:5E:ED:7E
15:38:52.067 -> [Ethernet] Mac Address = 24:0A:C4:5E:ED:7F

SSIDの値は[Wi-Fi SoftAP] Mac Addressの下3バイトを使っていた事が明解になりました。
また、Chip IDはDefault Mac Addressのエンディアンが逆の6バイト値と云う事も判りました。そして、
Wi-Fi SoftAP = Default Mac Address +1
Bluetooth = Default Mac Address +2
Ethernet = Default Mac Address +3

MACアドレスを検索したところ、24:0A:C4 cn - 中華人民共和国 Espressif Inc. が確認出来ました。
ということはESP-WROOM-32にはユニークなMACアドレスが付加されてリリースされているということはESP-WROOM-32には可能性が出てきました。CHIPIDから生成されていると推測できるためユニークだと信じたいところですが、IDが16bitなので衝突する番号を発行してしまっているのでは無いかと云う疑問が湧きます

MACアドレスに関するコラム

興味深い議事の多い『Geekなページ』の 2020/06/16 のブログ記事に興味深いモノがありました。

2020-06-16 MACアドレスの再利用は、みんなが思っているよりもはるかに一般的

Derbycon 2102の発表の MACアドレスが示すベンダーごとに、重複したMACアドレスが検出された数が示されています。これを見るとHUWAI社が吐出しており30万件あります。
RFC 7707 にて MACアドレスの重複が確認されたら動的に調整する手順が示されていることからこのような事は事前に検討されていたのでしょう。

MACアドレスはユニークに割り振る必要がある は 迷信なのでしょうか?多分HUWAI社が出荷するネットワーク機器は同一MACアドレス商品がたくさんあったのでしょう。
この記事から8年経っていますが、現在の状況はどうなのか判りませんが、Arduinoでコーディングしたネットワーク機器はbitイメージ書込時にユニークなMACアドレスを設定しないでしょうから更に面白い結果が得られるのでは無いかと思います。当然Privateなゾーンで使われていれば攻められないのでしょうが、Publicなゾーンに無意識に出て行く人が,,少なからずいるでしょう。


NTP時刻同期】

ESP-WROOM-32 リセット後、WIFI経由でLANに入り、LAN内のNTPDにアクセスして時刻取得して時刻表示するというサンプルスケッチです。
表示にはI2CのOLCDを採用しました。

追加が必要なライブラリ:
<Adafruit_GFX.h>  https://github.com/adafruit/Adafruit-GFX-Library
<Adafruit_SSD1306.h>https://github.com/adafruit/Adafruit_SSD1306

/*
 * 20200610 T.Wanibe
 * 起動時にNTPサーバにアクセスして時刻取得したら以後1秒毎に時刻プリントするスケッチを実行します
 * オリジナルのコードはコンソールに時刻表示をしていたが、これをI2CのOLCDに表示するように変更した。
 * 最大1310720バイトのフラッシュメモリのうち、スケッチが647730バイト(49%)を使っています。
 * 最大327680バイトのRAMのうち、グローバル変数が39680バイト(12%)を使っていて、ローカル変数で288000バイト使うことができます。
 */
#include <WiFi.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#include "time.h"
#include "time.h"
#define SCREEN_WIDTH    128                     // OLED display width, in pixels
#define SCREEN_HEIGHT   64                      // OLED display height, in pixels
#define OLED_RESET      -1                      // Reset pin # (or -1 if sharing Arduino reset pin)
#define NUMFLAKES       10                      // アニメーション例の雪片の数
#define LOGO_HEIGHT     16
#define LOGO_WIDTH      16
#define PLCDAres        0x3C                    //0x3Cか0x3D
const char* ssid                = "Kingsland";
const char* password            = "";
const char* ntpServer           = "192.168.0.206";
const long  gmtOffset_sec       = 32400;                        //GMT+9
const int   daylightOffset_sec  = 0;                            //夏時間はありません
//I2C(SDA、SCLピン)に接続されたSSD1306ディスプレイの宣言
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);
//--------------------------
void printLocalTime(){
        struct tm timeinfo;
        if(!getLocalTime(&timeinfo)){
                Serial.println(F("Failed to obtain time"));
                return;
        }
        Serial.println(&timeinfo, "%A, %B %d %Y %H:%M:%S");
        display.clearDisplay();
        display.setTextSize(1);                                 // Draw 2X-scale text
        display.setTextColor(SSD1306_WHITE);
        display.setCursor(0, 5);                                //左上原点(0,5)開始点
        display.println(&timeinfo,"%A, %B %d %Y");
        display.setTextSize(2);
        display.setCursor(10, 20);
        display.println(&timeinfo,"%H:%M:%S");
        display.display(); 
}
//--------------------------
void setup()
{
        Serial.begin(115200);
        //SSD1306_SWITCHCAPVCC =内部で3.3Vから表示電圧を生成
        if(!display.begin(SSD1306_SWITCHCAPVCC, PLCDAres)) {        // 128x64のスレーブアドレスオリジナル値は0x3Dでしたが手元の元は0x3Cでした。
                Serial.println(F("SSD1306 allocation failed"));
                for(;;); // Don't proceed, loop forever
        }
        // バッファをクリアします
        display.clearDisplay();
        display.display();
        //connect to WiFi
        Serial.printf("Connecting to %s ", ssid);
        WiFi.begin(ssid, password);
        while (WiFi.status() != WL_CONNECTED) {
                delay(500);
                Serial.print(F("."));
        }
        Serial.println(F(" CONNECTED"));
        //init and get the time
        configTime(gmtOffset_sec, daylightOffset_sec, ntpServer);
        printLocalTime();
        //disconnect WiFi as it's no longer needed
        WiFi.disconnect(true);
        WiFi.mode(WIFI_OFF);
}
//--------------------------
void loop()
{
        delay(1000);
        printLocalTime();
}

[実行結果]

16:24:30.628 -> ets Jun  8 2016 00:22:57
16:24:30.628 -> 
16:24:30.628 -> rst:0xc (SW_CPU_RESET),boot:0x13 (SPI_FAST_FLASH_BOOT)
16:24:30.628 -> configsip: 0, SPIWP:0xee
16:24:30.628 -> clk_drv:0x00,q_drv:0x00,d_drv:0x00,cs0_drv:0x00,hd_drv:0x00,wp_drv:0x00
16:24:30.628 -> mode:DIO, clock div:1
16:24:30.628 -> load:0x3fff0018,len:4
16:24:30.628 -> load:0x3fff001c,len:1216
16:24:30.628 -> ho 0 tail 12 room 4
16:24:30.628 -> load:0x40078000,len:9720
16:24:30.628 -> ho 0 tail 12 room 4
16:24:30.628 -> load:0x40080400,len:6352
16:24:30.662 -> entry 0x400806b8
16:24:30.899 -> Connecting to Kingsland . CONNECTED
16:24:31.477 -> Friday, June 12 2020 16:24:30
16:24:31.477 -> Guru Meditation Error: Core  1 panic'ed (Connecting to Kingsland . CONNECTED
16:26:51.391 -> Friday, June 12 2020 16:26:50

・・・・・


WebServerの実行】

ESP-WROOM-32 リセット後、WIFI経由でLANに入り、WebServerが公開されます。
IPアドレスが固定する方法が判りませんが、一応ブラウザでアクセス出来ました。

/*
 * 2020/06/10 T.Wanibe
 * ESP-WROOM32のサンプルスケッチを改造しました。
 * オリジナルは、
 * Copyright (c) 2015, Majenko Technologies All rights reserved.
 * ソースおよびバイナリ形式での再配布および使用は、変更の有無にかかわらず、次の条件を満たす場合に許可されます。
 * ソースコードの再配布では、上記の著作権表示、この条件のリスト、および次の免責事項を保持する必要があります。
 * バイナリ形式で再配布する場合は、上記の著作権表示、この条件のリスト、および次の免責事項を、配布物とともに
 * 提供されるドキュメントやその他の資料に複製する必要があります。
 * Majenko Technologiesの名前もその貢献者の名前も、書面による事前の明確な許可なしに、このソフトウェア
 * から派生した製品を推奨または宣伝するために使用することはできません。
 * 
 * 
 * このソフトウェアは、著作権者および寄稿者によって「現状のまま」提供され、商品性および特定の目的に対する適合性の
 * 黙示の保証を含むがこれに限定されない、明示または黙示の保証は否認されます。 いかなる場合においても、
 * 著作権者または寄稿者は、直接的、間接的、偶発的、特別、例示的、または結果的損害に対して責任を負わないものとします。
 * (これに限定されないが、代替商品またはサービスの調達、使用、データ、利益の喪失、または業務の中断)責任の理論、
 * 責任、過失、または責任の不一致にかかわらず、 それ以外の場合)そのような損害の可能性について知らされていたとしても、
 * 本ソフトウェアの使用からいかなる方法においても生じること。
 * 
 * 最大1310720バイトのフラッシュメモリのうち、スケッチが749050バイト(57%)を使っています。
 * 最大327680バイトのRAMのうち、グローバル変数が41264バイト(12%)を使っていて、ローカル変数で286416バイト使うことができます。
 */
#include <WiFi.h>
#include <WiFiClient.h>
#include <WebServer.h>
#include <ESPmDNS.h>
#define HTTPPort 80
const char *ssid        = "Kingsland";          //有効なSSIDにLOGONしてLANに入る
const char *password    = "";
const int led           = 13;                   //BuiltInLEDというのがESPには無いようなのでcheck用のLEDを接続する。
                                                //GPIO13を使うのが一般的とのこと
                                                //ON/OFFとかTRUE/FALSEという表記はマクロ定義されていない模様
WebServer server(HTTPPort);
//--------------------
void handleRoot() {
        digitalWrite(led,1);
        char temp[400];
        int sec = millis() / 1000;
        int min = sec / 60;
        int hr = min / 60;
        snprintf(temp, 400,
"<html>
 <head>
    <meta http-equiv='refresh' content='5'/>
    <title>ESP32 Demo</title>
    <style>
      body { background-color: #cccccc; font-family: Arial, Helvetica, Sans-Serif; Color: #000088; }
    </style>
  </head>
  <body>
    <h1>Hello from ESP32!</h1>
    <p>Uptime: 00:01:38</p>
    <img src="/test.svg" />
  </body>
</html>",
        hr, min % 60, sec % 60);
        server.send(200, "text/html", temp);
        digitalWrite(led, 0);
}
//--------------------
void handleNotFound() {
        digitalWrite(led, 1);
        String message = "File Not Found\n\n";
        message += "URI: ";
        message += server.uri();
        message += "\nMethod: ";
        message += (server.method() == HTTP_GET) ? "GET" : "POST";
        message += "\nArguments: ";
        message += server.args();
        message += "\n";
        for (uint8_t i = 0; i < server.args(); i++) {
                message += " " + server.argName(i) + ": " + server.arg(i) + "\n";
        }
        server.send(404, "text/plain", message);
        digitalWrite(led, 0);
}
//--------------------
void drawGraph() {
        String out = "";
        char temp[100];
        out += "<svg xmlns=\"https://www.w3.org/2000/svg\" version=\"1.1\" width=\"400\" height=\"150\">\n";
        out += "<rect width=\"400\" height=\"150\" fill=\"rgb(250, 230, 210)\" stroke-width=\"1\" stroke=\"rgb(0, 0, 0)\" />\n";
        out += "<g stroke=\"black\">\n";
        int y = rand() % 130;
        for (int x = 10; x < 390; x += 10) {
                int y2 = rand() % 130;
                sprintf(temp, "<line x1=\"%d\" y1=\"%d\" x2=\"%d\" y2=\"%d\" stroke-width=\"1\" />\n", x, 140 - y, x + 10, 140 - y2);
                out += temp;
                y = y2;
        }
        out += "</g>\n</svg>\n";
        server.send(200, "image/svg+xml", out);
}
//--------------------
void setup(void) {
        pinMode(led, OUTPUT);
        digitalWrite(led, 0);
        Serial.begin(115200);
        WiFi.mode(WIFI_STA);
        WiFi.begin(ssid, password);
        Serial.println(F(""));
        // Wait for connection
        while (WiFi.status() != WL_CONNECTED) {
                delay(1000);
                Serial.print(F("."));
        }
        Serial.println(F(""));
        Serial.print(F("Connected to "));
        Serial.println(ssid);
        Serial.print(F("IP address: "));
        Serial.println(WiFi.localIP());
        if (MDNS.begin("esp32")) {
                Serial.println(F("MDNS responder started"));
        }
        server.on("/", handleRoot);
        server.on("/test.svg", drawGraph);
        server.on("/inline", []() {
                server.send(200, "text/plain", "this works as well");
        });
        server.onNotFound(handleNotFound);
        server.begin();
        Serial.println(F("HTTP server started"));
}
//--------------------
void loop(void) {
        server.handleClient();
}

[実行結果]

17:35:47.566 -> ets Jun  8 2016 00:22:57
17:35:51.365 -> 
17:35:51.365 -> rst:0x1 (POWERON_RESET),boot:0x13 (SPI_FAST_FLASH_BOOT)
17:35:51.365 -> configsip: 0, SPIWP:0xee
17:35:51.365 -> clk_drv:0x00,q_drv:0x00,d_drv:0x00,cs0_drv:0x00,hd_drv:0x00,wp_drv:0x00
17:35:51.365 -> mode:DIO, clock div:1
17:35:51.365 -> load:0x3fff0018,len:4
17:35:51.365 -> load:0x3fff001c,len:1216
17:35:51.365 -> ho 0 tail 12 room 4
17:35:51.365 -> load:0x40078000,len:9720
17:35:51.365 -> ho 0 tail 12 room 4
17:35:51.365 -> load:0x40080400,len:6352
17:35:51.365 -> entry 0x400806b8
17:35:51.738 -> 
17:35:52.246 -> ................................................
17:38:36.516 -> .
17:38:36.516 -> Connected to Kingsland
17:38:36.516 -> IP address: 192.168.0.99
17:38:36.516 -> MDNS responder started
17:38:36.516 -> HTTP server started

コンソール画面にIP address: 192.168.0.99と云う表示が出てこれを確認出来ないと使えないのであれば問題有りですね。ブラウザでアクセスしてみると以下の結果になりました。


5秒毎のREFLESH グラフ自体は乱数です。
このサンプルスケッチは使えそうで使いにくいですね。


Chipのリビジョンを確認する方法】

/*
 * 20200612 T.Wanibe
 * ESP-WROOM-32のRev0にはバグがあるそうです。そのバグとは、espressifがエラータを出しています。
 * https://www.espressif.com/sites/default/files/documentation/eco_and_workarounds_for_bugs_in_esp32_en.pdf
 * なかなか解釈の難しいバグです。ただ、Rev1でもバグは残っているような雰囲気です。
 * chipのリビジョンを確認する方法が掲載されていたので実行してみました。
 * 最大1310720バイトのフラッシュメモリのうち、スケッチが214449バイト(16%)を使っています。
 * 最大327680バイトのRAMのうち、グローバル変数が15380バイト(4%)を使っていて、ローカル変数で312300バイト使うことができます。
 */
//------------------
void setup() {
        Serial.begin(115200);
        while (!Serial);                                                //シリアル接続されていないとここで無限LOOP
        Serial.printf("Revision: %d\r\n" , ESP.getChipRevision());
}
//------------------
void loop() {
}

[実行結果]

09:56:20.575 -> ets Jun  8 2016 00:22:57
09:56:20.575 -> 
09:56:20.575 -> rst:0x1 (POWERON_RESET),boot:0x13 (SPI_FAST_FLASH_BOOT)
09:56:20.575 -> configsip: 0, SPIWP:0xee
09:56:20.575 -> clk_drv:0x00,q_drv:0x00,d_drv:0x00,cs0_drv:0x00,hd_drv:0x00,wp_drv:0x00
09:56:20.575 -> mode:DIO, clock div:1
09:56:20.575 -> load:0x3fff0018,len:4
09:56:20.575 -> load:0x3fff001c,len:1216
09:56:20.575 -> ho 0 tail 12 room 4
09:56:20.575 -> load:0x40078000,len:9720
09:56:20.575 -> ho 0 tail 12 room 4
09:56:20.575 -> load:0x40080400,len:6352
09:56:20.609 -> entry 0x400806b8
09:56:20.711 -> Revision: 1

外観でも判るというお話がありました。シールドケースに『CE1313』の刻印があるのはRev0で古いバージョンである可能性が高いようです。一方『CE』のみはRev1のようです。自分の所有するESP-WROOM32はRev1でした。外観も『CE』のみでした。


EEPROMClassの使用】

ESP-WROOM32のモジュール構成を見ても実EEPROMは載っていないように思います。多分STM32F1と同様Flash領域の一部を仮想的にEEPROMとして使用していると想像します※間違いがあれば後日訂正します。

EEPROMが使えるなら、接続するSSIDやPASSWORDをブラウザから登録出来るようなサンプルsketchを検討しました。

[実行結果]


WiFiScan】

WiFiネットワークをスキャンし、見つかったSSID名、強度、暗号化の種別を表示します。

/*
 * 20200612 T.Wanibe
 *  このスケッチは、WiFiネットワークをスキャンする方法を示しています。
 *  APIはWiFiシールドライブラリとほとんど同じですが、
 *  最も明白な違いは、含める必要がある別のファイルです。
 *  最大1310720バイトのフラッシュメモリのうち、スケッチが623662バイト(47%)を使っています。
 *  最大327680バイトのRAMのうち、グローバル変数が38744バイト(11%)を使っていて、ローカル変数で288936バイト使うことができます。
 */
#include "WiFi.h"
//----------------------------
void setup()
{
        Serial.begin(115200);
        // WiFiをステーションモードに設定し、以前に接続されていた場合はAPから切断します
        WiFi.mode(WIFI_STA);
        WiFi.disconnect();
        delay(100);
        Serial.println(F("Setup done"));
}
//----------------------------
void loop()
{
        Serial.println(F("scan start"));
        // WiFi.scanNetworksは見つかったネットワークの数を返します
        int n = WiFi.scanNetworks();
        Serial.println(F("scan done"));
        if (n == 0) {
                Serial.println(F("no networks found"));
        } else {
                Serial.print(n);
                Serial.println(F(" networks found"));
                for (int i = 0; i < n; ++i) {
                        // 見つかった各ネットワークのSSIDとRSSIを出力する
                        Serial.print(i + 1);
                        Serial.print(F(": "));
                        Serial.print(WiFi.SSID(i));
                        Serial.print(F(" ("));
                        Serial.print(WiFi.RSSI(i));
                        Serial.print(F(")"));
                        Serial.println((WiFi.encryptionType(i) == WIFI_AUTH_OPEN)?" ":"*");
                        delay(10);
                }
        }
        Serial.println(F(""));
        //もう一度スキャンする前に少し待ってください
        delay(5000);
}

[実行結果]

17:46:32.152 -> ets Jun  8 2016 00:22:57
17:46:32.152 -> 
17:46:32.152 -> rst:0x1 (POWERON_RESET),boot:0x13 (SPI_FAST_FLASH_BOOT)
17:46:32.152 -> configsip: 0, SPIWP:0xee
17:46:32.152 -> clk_drv:0x00,q_drv:0x00,d_drv:0x00,cs0_drv:0x00,hd_drv:0x00,wp_drv:0x00
17:46:32.185 -> mode:DIO, clock div:1
17:46:32.185 -> load:0x3fff0018,len:4
17:46:32.185 -> load:0x3fff001c,len:1216
17:46:32.185 -> ho 0 tail 12 room 4
17:46:32.185 -> load:0x40078000,len:9720
17:46:32.185 -> ho 0 tail 12 room 4
17:46:32.185 -> load:0x40080400,len:6352
17:46:32.185 -> entry 0x400806b8
17:46:32.593 -> Setup done
17:46:32.593 -> scan start
17:46:34.901 -> scan done
17:46:34.901 -> 8 networks found
17:46:34.901 -> 1: Kingland_Guest (-54)*
17:46:34.901 -> 2: Kingsland (-55)*
17:46:34.935 -> 3: SPWH_H33_61CE92 (-91)*
17:46:34.935 -> 4: Buffalo-G-2FC8 (-91)*
17:46:34.935 -> 5: elecom2g-bf4469 (-92)*
17:46:34.969 -> 6: 001D73B49DAC (-92)*
17:46:34.969 -> 7: Buffalo-G-3A80 (-95)*
17:46:34.969 -> 8: 001D73B49DAC-1 (-96)*

このスケッチをレタッチしてOLCD(SSD1306)に表示するようにしました。モバイルバッテリから電源供給するようにすれば、簡易的な WiFi強度チェッカーに仕立てることが出来ます。


WiFi-Control-Car】

無線ロボットカー制御のテストスケッチです

/*
 * 20200617 T.Wanibe
 * このスケッチは、WiFi-Control-Car という名で紹介されていたものです。
 * 東芝のMOSFETを駆動して2基のモータを前後させ車を動かすというものです。ESPはWebServerを起動しており、ブラウザから制御出来ます。
 * 最大1310720バイトのフラッシュメモリのうち、スケッチが641410バイト(48%)を使っています。
 * 最大327680バイトのRAMのうち、グローバル変数が38776バイト(11%)を使っていて、ローカル変数で288904バイト使うことができます。
 */
#include <WiFi.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#define SCREEN_WIDTH    128                     // OLED display width, in pixels
#define SCREEN_HEIGHT   64                      // OLED display height, in pixels
#define OLED_RESET      -1                      // Reset pin # (or -1 if sharing Arduino reset pin)
#define NUMFLAKES       10                      // アニメーション例の雪片の数
#define LOGO_HEIGHT     16
#define LOGO_WIDTH      16
#define PLCDAres        0x3C                    //0x3Cか0x3D
#define HTTPport        80
#define P1              4
#define P2              0
#define P3              2
#define P4              15
const char* ssid        = "Kingsland";                                     //アクセスポイントのSSID
const char* password    = "minawanibe";                                    //アクセスポイントのパスワード
const char titleStr[]   = "ESP32 WiFi_Car Controller";
WiFiServer server(HTTPport);
//I2C(SDA、SCLピン)に接続されたSSD1306ディスプレイの宣言
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);
//--------------------------HTML出力
void PrintResponse200( WiFiClient client)
{
        client.println(F("HTTP/1.1 200 OK"));
        client.println(F("Content-Type: text/html"));
        client.println();
}
//--------------------------
void PrintResponse404( WiFiClient client )
{
        client.println(F("HTTP/1.1 404 Not Found"));
        client.println(F("Content-Type: text/html"));
        client.println();
}
//--------------------------HTMLのコードを作成する場合は、HTMLエディタで構築した後、行毎にclient.println(F(""))に割り当てます。
void PrintNormalPage(WiFiClient client)
{
        client.println(F("<!DOCTYPE HTML PUBLIC '-//W3C//DTD HTML 4.01 Transitional//EN'>"));
        client.println(F("<html lang='ja'>"));
        client.println(F("\t<head>"));
        client.println(F("\t\t<META name='GENERATOR' content='IBM WebSphere Studio Homepage Builder Version 10.0.0.0 for Windows'>"));
        client.println(F("\t\t<META http-equiv='Content-Type' content='text/html; charset=UTF-8'>"));
        client.println(F("\t\t<META http-equiv='Content-Style-Type' content='text/css'>"));
        client.println(F("\t\t<style>"));
        client.println(F("\t\t\t<!--"));
        client.println(F("\t\t\tinput {margin:8px;width:80px;}"));
        client.println(F("\t\t\tdiv {font-size:16pt;color:red;text-align:center;width:400px;border:groove 40px orange;}-->"));
        client.println(F("\t\t</style>"));
        client.print(F("\t\t<title>"));
        client.print(titleStr);
        client.println(F("</title>"));
        client.println(F("\t</head>"));
        client.println(F("\t<body>"));
        client.println(F("\t\t<div>"));
        client.println(F("\t\t\t<p>Controller</p>"));
        client.println(F("\t\t\t<form method='get'>"));
        client.println(F("\t\t\t<input type='submit' name='le' value='左' />"));
        client.println(F("\t\t\t<input type='submit' name='fo' value='前' />"));
        client.println(F("\t\t\t<input type='submit' name='ri' value='右' /><br>"));
        client.println(F("\t\t\t<input type='submit' name='st' value='停' /><br>"));
        client.println(F("\t\t\t<input type='submit' name='bl' value='左後' />"));
        client.println(F("\t\t\t<input type='submit' name='ba' value='後' />"));
        client.println(F("\t\t\t<input type='submit' name='br' value='右後' /><br><br>"));
        client.println(F("\t\t\t</form>"));
        client.println(F("\t\t</div>"));
        client.println(F("\t</body>"));
        client.println(F("</html>"));
}
//-------------------------
void stop(){
        digitalWrite(P1, LOW);
        digitalWrite(P2, LOW);
        digitalWrite(P3, LOW);
        digitalWrite(P4, LOW);
}
//-------------------------
void clearTXT(Adafruit_SSD1306 display){
        display.setTextColor(SSD1306_BLACK);
        display.setCursor(0, 8);display.print(F("                                "));
        display.setTextColor(SSD1306_WHITE);
}
//-------------------------
void setup()
{
        Serial.begin(115200);
        pinMode(P1, OUTPUT);
        pinMode(P2, OUTPUT);
        pinMode(P3, OUTPUT);
        pinMode(P4, OUTPUT);
        //SSD1306_SWITCHCAPVCC =内部で3.3Vから表示電圧を生成
        if(!display.begin(SSD1306_SWITCHCAPVCC, PLCDAres)) {        // 128x64のスレーブアドレスオリジナル値は0x3Dでしたが手元の元は0x3Cでした。
                Serial.println(F("SSD1306 allocation failed"));
                for(;;); // Don't proceed, loop forever
        }
        // バッファをクリアします
        display.clearDisplay();
        delay(10);
        Serial.print(F("\nConnecting to "));Serial.println(ssid);
        WiFi.begin(ssid, password);
        while (WiFi.status() != WL_CONNECTED) {
                delay(500);
                Serial.print(F("."));
        }
        Serial.println(F("\nWiFi connected."));
        Serial.print(F("IP address: "));Serial.println(WiFi.localIP());
        display.setTextSize(1);display.setTextColor(SSD1306_WHITE);display.setCursor(0, 0);
        display.print(F("IP:"));display.println(WiFi.localIP());display.display();
        server.begin();
}
//-------------------------
void loop(){
        WiFiClient client = server.available();
        if (client) {
                Serial.println(F("New Client."));
                String currentLine = "";
                while (client.connected()) {
                        if (client.available()) {
                                char c = client.read();
                                Serial.write(c);
                                if (c == '\n') {
                                        if (currentLine.length() == 0) {
                                                PrintResponse200(client);
                                                PrintNormalPage(client);
                                                client.println();
                                                break;
                                        } else {
                                                currentLine = "";
                                        }
                                } else if (c != '\r') {
                                        currentLine += c;
                                }
                                if (currentLine.endsWith("GET /?fo")) {
                                        stop();
                                        digitalWrite(P2, HIGH);
                                        digitalWrite(P1, HIGH);
                                        display.clearDisplay();
                                        display.setCursor(0, 8);display.print(F("Detect:FO"));display.display();
                                }
                                if (currentLine.endsWith("GET /?le")) {
                                        stop();
                                        digitalWrite(P2, HIGH);
                                        display.clearDisplay();
                                        display.setCursor(0, 8);display.print(F("Detect:LE"));display.display();
                                }
                                if (currentLine.endsWith("GET /?ri")) {
                                        stop();
                                        digitalWrite(P1, HIGH);
                                        display.clearDisplay();
                                        display.setCursor(0, 8);display.print(F("Detect:RI"));display.display();
                                }
                                if (currentLine.endsWith("GET /?ba")) {
                                        stop();
                                        digitalWrite(P3, HIGH);
                                        digitalWrite(P4, HIGH);
                                        display.clearDisplay();
                                        display.setCursor(0, 8);display.print(F("Detect:BA"));display.display();
                                }
                                if (currentLine.endsWith("GET /?bl")) {
                                        stop();
                                        digitalWrite(P3, HIGH);
                                        display.clearDisplay();
                                        display.setCursor(0, 8);display.print(F("Detect:BL"));display.display();
                                }
                                if (currentLine.endsWith("GET /?br")) {
                                        stop();
                                        digitalWrite(P4, HIGH);
                                        display.clearDisplay();
                                        display.setCursor(0, 8);display.print(F("Detect:BR"));display.display();
                                }
                                if (currentLine.endsWith("GET /?st")) {
                                        stop();
                                        display.clearDisplay();
                                        display.setCursor(0, 8);display.print(F("Detect:ST"));display.display();
                                }
                        }
                }
                client.stop();
                Serial.println(F("Client Disconnected."));
        }
}

[実行結果]

ボタンの反応は悪くないです。
IPアドレスの確認が必要でコンソールでの確認が必要です。それを避けるためにOLCDにIPアドレスを表示するようにしました。また、接続するSSIDをソースに固定しなくても良い方法を検討しておきたいです。


WiFi-Control-Car(AP)】

ESPはアクセスポイントになるわけで、iPhoneから直接ESPに接続し、ブラウザを介して機器制御出来るはずです。それを実現出来るか確認すべくテストスケッチを書きました。

/*
 * 20200618 T.Wanibe
 * このスケッチは、WiFi-Control-Car という名で紹介されていたものです。
 * 東芝のMOSFETを駆動して2基のモータを前後させ車を動かすというものです。ESPはWebServerを起動しており、ブラウザから制御出来ます。
 * ESPをSoftAPとして立ち上げて直接iPhoneから制御出来ることを確認する。
 * OLCDにSSIDと及びIPアドレスを表示します。
 * 最大1310720バイトのフラッシュメモリのうち、スケッチが662090バイト(50%)を使っています。
 * 最大327680バイトのRAMのうち、グローバル変数が39688バイト(12%)を使っていて、ローカル変数で287992バイト使うことができます。
 */
#include <WiFi.h>
#include <WiFiClient.h>
#include <WiFiAP.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#define SCREEN_WIDTH    128                     // OLED display width, in pixels
#define SCREEN_HEIGHT   64                      // OLED display height, in pixels
#define OLED_RESET      -1                      // Reset pin # (or -1 if sharing Arduino reset pin)
#define NUMFLAKES       10                      // アニメーション例の雪片の数
#define LOGO_HEIGHT     16
#define LOGO_WIDTH      16
#define PLCDAres        0x3C                    //0x3Cか0x3D
#define HTTPport        80
#define P1              4
#define P2              0
#define P3              2
#define P4              15
const char*     ssid            = "ESP";                                        //アクセスポイントのSSID
const char*     password        = "password";                                   //アクセスポイントのパスワード
const char      titleStr[]      = "ESP32 WiFi_Car Controller";
WiFiServer      server(HTTPport);
IPAddress       ip(192,168,0,190);                                              // Select ip and mask
IPAddress       mask(255, 255, 255, 0);
//I2C(SDA、SCLピン)に接続されたSSD1306ディスプレイの宣言
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);
//--------------------------HTML出力
void PrintResponse200( WiFiClient client)
{
        client.println(F("HTTP/1.1 200 OK"));
        client.println(F("Content-Type: text/html"));
        client.println();
}
//--------------------------
void PrintResponse404( WiFiClient client )
{
        client.println(F("HTTP/1.1 404 Not Found"));
        client.println(F("Content-Type: text/html"));
        client.println();
}
//--------------------------HTMLのコードを作成する場合は、HTMLエディタで構築した後、行毎にclient.println(F(""))に割り当てます。
void PrintNormalPage(WiFiClient client)
{
        client.println(F("<!DOCTYPE HTML PUBLIC '-//W3C//DTD HTML 4.01 Transitional//EN'>"));
        client.println(F("<html lang='ja'>"));
        client.println(F("\t<head>"));
        client.println(F("\t\t<META name='GENERATOR' content='IBM WebSphere Studio Homepage Builder Version 10.0.0.0 for Windows'>"));
        client.println(F("\t\t<META http-equiv='Content-Type' content='text/html; charset=UTF-8'>"));
        client.println(F("\t\t<META http-equiv='Content-Style-Type' content='text/css'>"));
        client.println(F("\t\t<style>"));
        client.println(F("\t\t\t<!--"));
        client.println(F("\t\t\tinput {margin:8px;width:80px;}"));
        client.println(F("\t\t\tdiv {font-size:16pt;color:red;text-align:center;width:400px;border:groove 40px orange;}-->"));
        client.println(F("\t\t</style>"));
        client.print(F("\t\t<title>"));
        client.print(titleStr);
        client.println(F("</title>"));
        client.println(F("\t</head>"));
        client.println(F("\t<body>"));
        client.println(F("\t\t<div>"));
        client.println(F("\t\t\t<p>Controller</p>"));
        client.println(F("\t\t\t<form method='get'>"));
        client.println(F("\t\t\t<input type='submit' name='le' value='左' />"));
        client.println(F("\t\t\t<input type='submit' name='fo' value='前' />"));
        client.println(F("\t\t\t<input type='submit' name='ri' value='右' /><br>"));
        client.println(F("\t\t\t<input type='submit' name='st' value='停' /><br>"));
        client.println(F("\t\t\t<input type='submit' name='bl' value='左後' />"));
        client.println(F("\t\t\t<input type='submit' name='ba' value='後' />"));
        client.println(F("\t\t\t<input type='submit' name='br' value='右後' /><br><br>"));
        client.println(F("\t\t\t</form>"));
        client.println(F("\t\t</div>"));
        client.println(F("\t</body>"));
        client.println(F("</html>"));
}
//-------------------------
void stop(){
        digitalWrite(P1, LOW);
        digitalWrite(P2, LOW);
        digitalWrite(P3, LOW);
        digitalWrite(P4, LOW);
}
//-------------------------
void clearTXT(Adafruit_SSD1306 display){
        display.setTextColor(SSD1306_BLACK);
        display.setCursor(0, 8);display.print(F("                                "));
        display.setTextColor(SSD1306_WHITE);
}
//-------------------------
void setup()
{
        Serial.begin(115200);
        pinMode(P1, OUTPUT);
        pinMode(P2, OUTPUT);
        pinMode(P3, OUTPUT);
        pinMode(P4, OUTPUT);
        //SSD1306_SWITCHCAPVCC =内部で3.3Vから表示電圧を生成
        if(!display.begin(SSD1306_SWITCHCAPVCC, PLCDAres)) {        // 128x64のスレーブアドレスオリジナル値は0x3Dでしたが手元の元は0x3Cでした。
                Serial.println(F("SSD1306 allocation failed"));
                for(;;); // Don't proceed, loop forever
        }
        // バッファをクリアします
        display.clearDisplay();
        delay(10);
        //APを開く場合は、パスワードパラメータを削除できます。
        WiFi.softAP(ssid, password);
        WiFi.softAPConfig(ip,ip,mask);
        IPAddress myIP = WiFi.softAPIP();
        Serial.print(F("AP IP address: "));Serial.println(myIP);
        display.setTextSize(1);display.setTextColor(SSD1306_WHITE);display.setCursor(0, 0);
        display.print(F("SSID:"));display.println(ssid);
        display.print(F("PASS:"));display.println(password);
        display.print(F("IP:"));display.println(myIP);display.display();
        server.begin();
}
//-------------------------
void loop(){
        WiFiClient client = server.available();
        if (client) {
                Serial.println(F("New Client."));
                String currentLine = "";
                while (client.connected()) {
                        if (client.available()) {
                                char c = client.read();
                                Serial.write(c);
                                if (c == '\n') {
                                        if (currentLine.length() == 0) {
                                                PrintResponse200(client);
                                                PrintNormalPage(client);
                                                client.println();
                                                break;
                                        } else {
                                                currentLine = "";
                                        }
                                } else if (c != '\r') {
                                        currentLine += c;
                                }
                                if (currentLine.endsWith("GET /?fo")) {
                                        stop();
                                        digitalWrite(P2, HIGH);
                                        digitalWrite(P1, HIGH);
                                        display.clearDisplay();
                                        display.setCursor(0, 8);display.print(F("Detect:FO"));display.display();
                                }
                                if (currentLine.endsWith("GET /?le")) {
                                        stop();
                                        digitalWrite(P2, HIGH);
                                        display.clearDisplay();
                                        display.setCursor(0, 8);display.print(F("Detect:LE"));display.display();
                                }
                                if (currentLine.endsWith("GET /?ri")) {
                                        stop();
                                        digitalWrite(P1, HIGH);
                                        display.clearDisplay();
                                        display.setCursor(0, 8);display.print(F("Detect:RI"));display.display();
                                }
                                if (currentLine.endsWith("GET /?ba")) {
                                        stop();
                                        digitalWrite(P3, HIGH);
                                        digitalWrite(P4, HIGH);
                                        display.clearDisplay();
                                        display.setCursor(0, 8);display.print(F("Detect:BA"));display.display();
                                }
                                if (currentLine.endsWith("GET /?bl")) {
                                        stop();
                                        digitalWrite(P3, HIGH);
                                        display.clearDisplay();
                                        display.setCursor(0, 8);display.print(F("Detect:BL"));display.display();
                                }
                                if (currentLine.endsWith("GET /?br")) {
                                        stop();
                                        digitalWrite(P4, HIGH);
                                        display.clearDisplay();
                                        display.setCursor(0, 8);display.print(F("Detect:BR"));display.display();
                                }
                                if (currentLine.endsWith("GET /?st")) {
                                        stop();
                                        display.clearDisplay();
                                        display.setCursor(0, 8);display.print(F("Detect:ST"));display.display();
                                }
                        }
                }
                client.stop();
                Serial.println(F("Client Disconnected."));
        }
}

[実行結果]

17:59:08.645 -> ets Jun  8 2016 00:22:57
17:59:08.645 -> 
17:59:08.645 -> rst:0x1 (POWERON_RESET),boot:0x13 (SPI_FAST_FLASH_BOOT)
17:59:08.679 -> configsip: 0, SPIWP:0xee
17:59:08.679 -> clk_drv:0x00,q_drv:0x00,d_drv:0x00,cs0_drv:0x00,hd_drv:0x00,wp_drv:0x00
17:59:08.679 -> mode:DIO, clock div:1
17:59:08.679 -> load:0x3fff0018,len:4
17:59:08.679 -> load:0x3fff001c,len:1216
17:59:08.679 -> ho 0 tail 12 room 4
17:59:08.679 -> load:0x40078000,len:9720
17:59:08.679 -> ho 0 tail 12 room 4
17:59:08.679 -> load:0x40080400,len:6352
17:59:08.679 -> entry 0x400806b8
17:59:09.017 -> AP IP address: 192.168.0.190


iPhoneからESPで構築したAPに接続し、表示されているIPアドレスにブラウザでアクセスするとESPのIPが制御出来ます。

WindowsPCからであれば、PCに無線LANドングルを接続し、ESPに直接アクセスして接続。
TelnetツールのPuTTYを起動してコマンドラインから制御が可能です。


ESPでAJAXを試す】

ESP32でAJAXでのWeb表示のサンプルスケッチを探しました。先人はいろいろ用意してくれています。参考にして書いてみました。
HTMLのコードは“index.h”の名前でinoと同じフォルダに書き込みます。

/*
 * 20200622 T.Wanibe
 * このコードはESP32をAJAXベースのWeb表示のテストスケッチです。
 * オリジナルのスケッチは以下の通りESP8266用のものです。
 * https://circuits4you.com/2018/02/04/esp8266-ajax-update-part-of-web-page-without-refreshing/
 * ESP8266 NodeMCU AJAX Demo
 * Updates and Gets data from webpage without page refresh
 * AI入力はAI0(3pin)を使用しています。
 * DIOはGPIO13(15pin)を使用しています。
 * IPアドレス等はOLCDに表示する。
 * 最大1310720バイトのフラッシュメモリのうち、スケッチが739042バイト(56%)を使っています。
 * 最大327680バイトのRAMのうち、グローバル変数が40256バイト(12%)を使っていて、ローカル変数で287424バイト使うことができます。
 */
#include <WiFi.h>
#include <WiFiClient.h>
#include <WebServer.h>
#include <Wire.h>                               // I2C interface
#include <Adafruit_SSD1306.h>                   // SSD1306 display
#include <Adafruit_GFX.h>                       // SSD1306 display
#include "index.h"                              //JavaScriptを使用したHTML Webページのコンテンツ
 
#define LED             13                      //ボード上のLEDは使えないのでGPIO13にLEDを接続
#define AIport          A0
#define SCREEN_WIDTH    128                     // OLED display width, in pixels
#define SCREEN_HEIGHT   64                      // OLED display height, in pixels
#define OLED_RESET      -1                      // Reset pin # (or -1 if sharing Arduino reset pin)
#define NUMFLAKES       10                      // アニメーション例の雪片の数
#define LOGO_HEIGHT     16
#define LOGO_WIDTH      16
#define PLCDAres        0x3C                    //0x3Cか0x3D
#define HTTPport        80
#define P1              4
#define P2              0
#define P3              2
#define P4              15
//SSIDとパスワードを入力してください
const char* ssid        = "Kingsland";
const char* password    = "";
WebServer       WS(HTTPport);
//I2C(SDA、SCLピン)に接続されたSSD1306ディスプレイの宣言
Adafruit_SSD1306 OLCD(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);
//-----------このルーチンは、ブラウザでIPを開いたときに実行されます。
void handleRoot() {
        String s = MAIN_page;                           //Read HTML contents
        WS.send(200, "text/html", s);                   //Send web page
}
//-----------
void handleADC() {
        int a = analogRead(AIport);
        String adcValue = String(a); 
        WS.send(200, "text/plane", adcValue);           //Send ADC value only to client ajax request
}
//-----------
void handleLED() {
        String ledState = "OFF";
        String t_state = WS.arg("LEDstate");            //Refer  xhttp.open("GET", "setLED?LEDstate="+led, true);
        Serial.println(t_state);
        if(t_state == "1"){
                digitalWrite(LED,HIGH);                 //LED ON
                ledState = "ON";                        //Feedback parameter
        }else{
                digitalWrite(LED,LOW);                  //LED OFF
                ledState = "OFF";                       //Feedback parameter  
        }
        WS.send(200, "text/plane", ledState);           //Send web page
}
//-----------SETUP
void setup(void){
        Serial.begin(115200);
  
        WiFi.begin(ssid, password);                     //Connect to your WiFi router
        Serial.println("");
 
        pinMode(LED,OUTPUT);                            //Onboard LED port Direction output
        pinMode(P1,OUTPUT);     digitalWrite(P1,LOW);
        pinMode(P2,OUTPUT);     digitalWrite(P2,LOW);
        pinMode(P3,OUTPUT);     digitalWrite(P3,LOW);
        pinMode(P4,OUTPUT);     digitalWrite(P4,LOW);
        //SSD1306_SWITCHCAPVCC =内部で3.3Vから表示電圧を生成
        if(!OLCD.begin(SSD1306_SWITCHCAPVCC, PLCDAres)) {        // 128x64のスレーブアドレスオリジナル値は0x3Dでしたが手元の元は0x3Cでした。
                Serial.println(F("SSD1306 allocation failed"));
                for(;;); // Don't proceed, loop forever
        }
        // バッファをクリアします
        OLCD.clearDisplay(); 
        // Wait for connection
        while (WiFi.status() != WL_CONNECTED) {
                delay(500);
                Serial.print(F("."));
        }
        IPAddress myIP = WiFi.localIP();
        //If connection successful show IP address in serial monitor
        Serial.print(F("\nConnected to "));     Serial.println(ssid);
        Serial.print(F("IP address: "));        Serial.println(myIP); //IP address assigned to your ESP
        OLCD.setTextSize(1);OLCD.setTextColor(SSD1306_WHITE);OLCD.setCursor(0, 0);
        OLCD.print(F("IP:"));OLCD.println(myIP);OLCD.display();
        WS.on("/", handleRoot);                         //Which routine to handle at root location. This is display page
        WS.on("/setLED", handleLED);
        WS.on("/readADC", handleADC);
 
        WS.begin();                                     //Start server
        Serial.println(F("HTTP server started"));
}
//-----------MAINLOOP
void loop(void){
        WS.handleClient();                      //Handle client requests
}

const char MAIN_page[] PROGMEM = R"=====(
<!DOCTYPE html>
<html>
<body>

<div id="demo">
<h1>The ESP32 Update web page By AJAX</h1>
<button type="button" onclick="sendData(1)">LED ON</button>
<button type="button" onclick="sendData(0)">LED OFF</button><BR>
</div>
<div>
ADC Value is : <span id="ADCValue">0</span><br>
LED State is : <span id="LEDState">NA</span>
</div>
<script>
function sendData(led) {
var xhttp = new XMLHttpRequest();
xhttp.onreadystatechange = function() {
if (this.readyState == 4 && this.status == 200) {
document.getElementById("LEDState").innerHTML = this.responseText;
}
};
xhttp.open("GET", "setLED?LEDstate="+led, true);
xhttp.send();
}
setInterval(function() {
// Call a function repetatively with 2 Second interval
getData();
}, 1000); //2000mSeconds update rate
function getData() {
var xhttp = new XMLHttpRequest();
xhttp.onreadystatechange = function() {
if (this.readyState == 4 && this.status == 200) {
document.getElementById("ADCValue").innerHTML = this.responseText;
}
};
xhttp.open("GET", "readADC", true);
xhttp.send();
}
</script>
<br><br><a href="https://toolsbox.biz">TOOLSBOX.BIZ</a>
</body>
</html>
)=====";

[実行結果]

17:18:38.836 -> ets Jun  8 2016 00:22:57
17:18:38.836 -> 
17:18:38.836 -> rst:0x1 (POWERON_RESET),boot:0x13 (SPI_FAST_FLASH_BOOT)
17:18:38.836 -> configsip: 0, SPIWP:0xee
17:18:38.836 -> clk_drv:0x00,q_drv:0x00,d_drv:0x00,cs0_drv:0x00,hd_drv:0x00,wp_drv:0x00
17:18:38.836 -> mode:DIO, clock div:1
17:18:38.870 -> load:0x3fff0018,len:4
17:18:38.870 -> load:0x3fff001c,len:1216
17:18:38.870 -> ho 0 tail 12 room 4
17:18:38.870 -> load:0x40078000,len:9720
17:18:38.870 -> ho 0 tail 12 room 4
17:18:38.870 -> load:0x40080400,len:6352
17:18:38.870 -> entry 0x400806b8
17:18:39.209 -> 
17:18:39.717 -> .
17:18:39.717 -> Connected to Kingsland
17:18:39.717 -> IP address: 192.168.0.99
17:18:39.751 -> HTTP server started
17:18:59.276 -> 1

ブラウザからhttps://192.168.0.99/にアクセスします。index.hに書かれているHTMLコードがレンダリングされています。

ボリュームを動かすとADC値が変わり、LEDON/OFFボタンでLEDも消点灯します。

ESP32のWebCodeの記述方法の一例を垣間見ました。


戯言(nonsense)に戻る


免責事項

本ソフトウエアは、あなたに対して何も保証しません。本ソフトウエアの関係者(他の利用者も含む)は、あなたに対して一切責任を負いません。
あなたが、本ソフトウエアを利用(コンパイル後の再利用など全てを含む)する場合は、自己責任で行う必要があります。

本ソフトウエアの著作権はToolsBoxに帰属します。
本ソフトウエアをご利用の結果生じた損害について、ToolsBoxは一切責任を負いません。
ToolsBoxはコンテンツとして提供する全ての文章、画像等について、内容の合法性・正確性・安全性等、において最善の注意をし、作成していますが、保証するものではありません。
ToolsBoxはリンクをしている外部サイトについては、何ら保証しません。
ToolsBoxは事前の予告無く、本ソフトウエアの開発・提供を中止する可能性があります。

商標・登録商標

Microsoft、Windows、WindowsNTは米国Microsoft Corporationの米国およびその他の国における登録商標です。
Windows Vista、Windows XPは、米国Microsoft Corporation.の商品名称です。
LabVIEW、National Instruments、NI、ni.comはNational Instrumentsの登録商標です。
I2Cは、NXP Semiconductors社の登録商標です。
その他の企業名ならびに製品名は、それぞれの会社の商標もしくは登録商標です。
すべての商標および登録商標は、それぞれの所有者に帰属します。