2024年4月
  1 2 3 4 5 6
7 8 9 10 11 12 13
14 15 16 17 18 19 20
21 22 23 24 25 26 27
28 29 30        
無料ブログはココログ

カテゴリー「電子工作:ESP32」の15件の記事

2024年4月23日 (火)

ESP32 Builtin Basic を期待して衝動買い

何気にAmazonでマイコンボードを検索していたら、以下のお買い得品を見つけました。
ESP32開発ボードに、IO拡張ボードもついて、何と1180円。
Amazonの取り扱い開始が2018/1/8だし、古くて売れず、安売りみたいな感じかな。

Amazon | waves NodeMCU-32 デュアルコア 開発ボード ESP32 WiFi Bluetooth Type-C ワイドバージョン I/O拡張ボード 付き | waves | マザーボード 通販

Photo_20240423194601

レビューを見ていると、古いチップのため、EN端子とGND間に1uFを付けると書き込みが安定するとか、書き込み時はBOOTを押しながらとか記載があります。ESP32を調べ始めた頃にはそんな記事を幾つか見ていたので、古いチップならもしかしてBuiltinBasicが走るかもしれないとの期待が高まりました。2018年度頃のレビューが見当たらないのが少し気になりますけど、まあいいや。
もしダメでも、拡張ボード(後で良く見たら30ピン、少し後悔。本体単体だと1080円だから、おまけだと思う事にします)が手に入るだけでも、まあお買い得だろうと自分を納得させ、衝動買い。

帰宅してから、モジュールの写真をチェック、BuiltinBasicが走っていた古いものと、刻印がほぼ同じ。これは期待できるかも。
アマゾンプライム対象商品なので、明日到着予定。
なんか、ワクワクしてます。


ちなみに、上記のアマゾンの商品紹介のモジュール部分の拡大写真が以下。
Photo_20240423195201

BuiltinBasicの記事の載っているESP32-WROOM-32 (ht-deko.com)の、esp32_rev.jpg (1200×900) (ht-deko.com)と見比べると、ESP-WROOM-32 Rev.1(以下) とそっくりです。文字・記号の配置が若干小さいようですが、文字・記号そのものは全く同じ。
Photo_20240423195501


もし、BuiltinBasicが走ったら、幾つかの方法でGPIOのトグルをさせ、波形を見て速度の比較でもしてみようと思います。
Easter Egg of ESP32 | macsbug (wordpress.com) を参考に、レジスタ書き込みの場合、IOSETの場合と、豊四季TinyBasicの場合で、どの程度違うのかとか。

 

続報あったらまた。

 

2024年4月19日 (金)

ESP32開発ボード用に830穴ブレッドボードをカット

前回、400穴ブレッドボードを半分に切り、ESP32開発ボードを使い易くしましたが、小さいので多くの部品が載る余裕がありません。

今回は、以前買ったブレッドボードセットの830穴ブレッドボードが2枚まだ余っているので、新たにカットしてみました。
製作では、金鋸も紙やすりも使わず、プラスチックカッターを使ったので、細かい切りカスや削りカスもなく、綺麗に仕上がりました。
また、裏面の両面テープはカットする部分だけ切り取るだけにしたので、全体の製作作業効率も上がりました。

今回製作の830穴幅広化ブレッドボード(右)と、前回製作の400穴幅広化ブレッドボード(左)。
Img_0261


以下、詳細手順です。

1、カットに使った830穴ブレッドボード2枚です。
  Img_0251

2、カットする中央溝部分の裏面の両面テープをカッターで切り取ります。
  土台に張り付ける前に、両面テープを剥がすと、ベタベタくっ付くし、すごく伸びて簡単に変形するので、作業効率激減、きっと後悔します。
  Img_0252

3、表の穴をセロハンテープで覆って塞ぎます。右がセロハンテープを貼った様子。左は貼る前。
  Img_0253

4、プラスチックカッターで、表の溝の中をカットしていきます。プラスチックを掘る感じの糸状の切りカスが出ます。
  最初の数回は定規を当てました。
  Img_0254_20240419175201
  Img_0257

5、力加減にもよりますが、5回程度カットするだけで、部分的には切れ目が裏に達し、既に折れ気味。
  向こう側も見えます。裏面の数か所にある厚いプラ材部分は、裏からカッターでカット。
  Img_0255_20240419175201

6、更にカッターで切り込んでいき、最後は指でパキット折ります。

7、切断面の凸部をカッターで切り取り平坦にします。プラスチックが柔らめで、割れる感じもなく、簡単にカッター薄く切り取れます。
  Img_0256
  紙やすりだと割と時間がかかりるし、細かい削りカスが飛び散り片付けが少し大変。
  カッターなら切り口は平坦ですし、手加減だけでスムーズに切り取れ、面状の切りカスは掃除も楽です。

8、カット後切断面を平坦に整え、穴の保護のセロハンテープを剥がした、2枚分のブレッドボードです。
  Img_0258

9、現物合わせのためブレッドボードにはESP32ボードを刺し、適当なプラ板を土台にして貼り付けます。
  Img_0259

10、裏面の両面テープの保護シートを剥がし、土台のプラ板に張り付け、完成です。
  真ん中の溝は、穴に刺したESP32ボードの取り外しの際の、指を入れるスペースにできます。
  Img_0260

 

まとめ
830穴ブレッドボードをカットし、幅広ブレッドボードが出来ました。
今回は作業効率良く、切り口も綺麗に製作できました。
1000ミルのESP32ボードを載せても、7割程度の穴が自由に使えますし、多少部品が多くなっても大丈夫でしょう。
アマゾンなら1枚200円程度で830ブレッドボードが買えますし、カットすれば使い易くなるので、私はこれで十分です。
もし、幅の狭いマイコンボード(例えばArduino NANOは600ミルらしい)を使いたい場合は、土台板から剥がして付け直せば良いので、幅の可変性・穴利用効率・コスパが向上しました。


気になって、J-PlatPatで「ブレッドボード」で四法全てで簡易検索、計54件ヒット。「ブレッド・ボード」だと0件。
しかも、いろいろありますが、拒絶や却下が多いですし、中身見ると可変幅ブレッドボード等見当たりません。
30年位前にも、今と同じブレッドボードを買っていたので、今回の様な活用事例や加工例は、昔からある工夫の一つなのでしょう。

今頃思いつくのは、普通に売っているブレッドボード2枚を使い、電源部分を外して、適当な間隔で並べれば、ほぼ同じものが出来る事。
これなら、裏面の両面テープを切って、電源部分と分離して、並べるだけで面倒な加工は不要。
部品がもっと増えても、余裕のボードに出来ますね。中央の空間が広く開くので、追加で電源部分も置けそう(下図)。
Photo_20240419203301

部品をたくさん使うケースが出てきたら、考えようかな。
買ったアルティメットスターターキットには部品が沢山あるので、今後実験で試してみたい部品を適当に並べておいて、後から配線だけ変え、いろいろ出来る、「いろいろ実験トレーニングボード」でも良いかな。


 

続報あったらまた。

 

2024年4月16日 (火)

Arduino ESP32 ライブラリの不用意なバージョンアップは危ないかも

TinyBasicの拡張をやっている際に、最新APIライブラリの説明と、実際にArduino IDEでコンパイルに使っているバージョンに差がある事が分かったため、少し調べてみました。

Arduino ESP32 の最新APIライブラリの説明を参照すると、ledcAttachや、ledcAttachChannelがあります。
 でも私のArduino IDEの環境では、エラーが出てしまい実際には使えませんでした。
 ledcSetupやledcAttachPinの記載はないものの、こちらの方は問題なく使えたため、コード記述・コンパイルに使いました。

Arduino ESP32 APIの更新情報には、2.Xから3.0への更新の際の差分として、LEDCだけでも以下の記載があります。
 破壊的な更新( breaking changes )として、大々的に変わってしまう様で、詳細なマイグレーションガイドも書かれています。
 Photo_20240415154901
 
正直、こんなに変わってしまって、いいの? って感じです。困ってしまう人が続出しそう。危ない危ない!

・自分のArduino IDEで使っているライブラリは最新のはずだと思っていますが、アップデートの仕組みや仕方が良く分かっていません。
一応、Arduino IDEのボードマネージャーでは、esp32 by Espressif Systemsが2.0.15(プルダウンメニューの最上位)をインストール済み。ボードじゃなくて、ライブラリマネージャーを開いても、それらしき項目を見つけきれません。
 Photo_20240415161601_20240417164601

・気になるのは、今後最新のものに勝手にアップデートがかかってしまうと、コンパイルでエラーが出てしまう点です。
 その場合は3.0ではなく、2.Xに戻せばOKのはずなんだろうとは思います。
 まだライブラリを戻すとかやった事がないので、必要になった時に改めてやり方を調べる予定。
 複数のバージョンを共存させる方法もありそうです。
 └esp32-arduinoの複数バージョンを共存させる | Lang-ship

・もし、不用意にアップデートすると、下の記事の様に余計な手間がかかるみたいで、それはそれで危険そうですしね。
 └[ESP32]Arduino core for the ESP32のバージョンを上げると動作しなくなったことについて | farmsoft
 └Arduino IDE ESP32ボードのバージョンアップに伴うTimerCameraライブラリの変更内容 - MSR合同会社 (msr-r.net)

・どうもライブラリがリリースが公開されるのは、GitHubの様です。
 GitHub - espressif/arduino-esp32: Arduino core for the ESP32 を開くと、画面右下の方に、Releases (53)と言うところがあり、
 そこに Arduino Release v2.0.15 based o... (Latest)とあり、ボードマネージャーで見た、
 esp32 by Espressif Systemsの2.0.15 と一致しています。
 Photo_20240416195601
 上記赤丸部分を拡大したのが以下。
 Photo_20240416193801
 上記の(Latest)をクリックすると、Arduino Release v2.0.15の説明画面に飛び、こちらにも右端には(Latest)とあります。
  Photo_20240416194001

 + 52 releases をクリックしたら、v3.0.0が出てきました。但し(Latest)ではなく、右端は(Pre-release)になっています。
 Photo_20240416194201
 開発環境ESP-IDFのv5.1に合わせた、ライブラリアップデートの様ですが、まだ先行リリースの段階の様です。
 なので、ライブラリが勝手にアップデートされる事はないのでしょうね。


いろいろと調べると、Espressif社の公式な開発環境は、ESP IDFの方であり、Arduino IDEは有志により開発されているらしい事も分かってきました。どうりでコントリビューターのアイコンが沢山並んでいます。

まだ、v3.0.0は(Pre-release)なので、Arduino IDEで自動ではアップデートされないとしても、今後(Latest)になると、自動アップデートされて、エラーに見舞われアタフタしそうな予感がします。

今後、GitHubのArduino ESP32 ライブラリの情報は、今後もウォッチしておく必要がありそうです。特に下記の右下赤丸部分。
Photo_20240416195601


続報あればまた。

 

2024年4月14日 (日)

ESP32開発ボード用にブレッドボードをカット

先日秋月から、ESP32開発ボードを2枚買ったので、Freenoveの2枚と合わせて、合計4枚あります。

FreenoveのはGPIOエクステンションボード(40pinの開発ボード用)が付属しているので、Freenoveの2枚は余裕でブレッドボードの穴が有効に使え楽で良いです。が、
秋月の38ピンの開発ボード2枚は、予備で買っていた400穴の安いブレッドボードが、5穴タイプのため、ESP32開発ボードの片側1列だけしかピンを刺せる穴がなく、有効に使えません。

ネットで調べると、いろいろ付いたエクステンションボードスリムなエクステンションボードブレークアウトボード等もいろいろありますが、どんどん買い足していくのも考え物だなーとの思いもあり、しっくりこない感じでいました。
ブレッドボードも、サンハヤトのSAD-101なら、6穴タイプなので、少しはましですが、電源/GNDが片側だけ、使いにくそうです。

汎用性とコストを考えて、安いブレッドボードの真ん中をカットして広げて、ESP32開発ボードを載せる程度が、自分に合っていそうかなーと考えながら、先例を探してみたらラジオペンチさんの記事があったので、じゃー俺もって感じでやってみました。

最初に、ブレッドボードの穴と裏面の金属片全体をセロハンテープを貼り、ごみが入らない様に準備。
削りカスが沢山出るのを避けたかったので、全部を金鋸で切ってしまわず、最初にゆっくり慎重に金鋸で1mm深さ程度に削り込み、
その後はカッターで何度も強めに切り込みを入れ、指で曲げながら更にカッターで切り込んでいき、最後は手でパキット折りました。
切り口は紙やすりで平坦にし、最初に貼ったセロハンテープをはがしました。
両面テープで適当なプラ板に張り付けて、完成です。

以下、秋月の開発ボードを載せた様子で、左側がESP32-DevKitC-32E、右側がESP32-DevKitC-VEです。Img_0243

土台を白いプラ板にしたためか、間が空いていても、違和感はそんなにないです。
上下に電源/GNDがありますし、穴も4~5列片側にあるので、小さめのブレッドボードですが、少ない部品点数なら今のところOK。
既にTinyBasicの拡張の検証で使ってます。

まあ、部品点数が多くなる場合は、もっと大きい830穴のブレッドボードの真ん中を切れば、良いかな。
金はかけずに、手間と工夫で頑張るってね。

尚、今回はカットの前にブレッドボードの裏面の両面テープを最初に全部剥がしてしまったので、カット後に貼り付け直す際に、だいぶ手こずりました。剥がした後に金属部分に粘着が残るし、それを剥がすのに手でベタベタ触るし、両面テープは伸縮性があって、ベタベタひっつき、剥がす時も貼る時も、長方形の形が簡単に崩れてしまうんです。次にやるなら、ブレッドボードのカット部分から、両側に1mm程度広めでカッターで切って剥がしておいて、他は貼ったままにして、カットするのが、楽で綺麗に加工出来そうな気がしています。


2024-4-19追記 830穴ブレッドボードのカットもしてみました。

 

続報あればまた。

 

2024年4月 6日 (土)

ESP32 WROOM/WROVER GPIO16,17使用可否実機検証

先日拡張したTinyBasicの開発に使った手持ちのボードではGPIO16,17ピンが出ておらず、GPIO操作対象外としてました。
他のボードを調べていたら、普通のESP32-DevKitC-32EやESP32-DevKitC-VEでは、外部ピンとして出ているのが分かりました。
ボードにより、ピンあるならTinyBasicでの操作対象にしておくべきとの思いが浮かんできました。

今回、秋月電子から開発キットのESP32-DevKitC-32EとESP32-DevKitC-VEを購入したので、TinyBasicでGPIO16,17の操作を試し、使えるか検証してみました。

結論を表にまとめてみました。

開発キット 搭載モジュール PSRAM・FLASH GPIO16,17用途 GPIO16,17使用可否
ESP32-DevKitC-VE WROVER 8M PSRAM有
8M FLASH有
PSRAM制御に使用
 CS#、SRAM_CLK
不可
NC
ESP32-DevKitC-32E WROOM PSRAM無し
4M FLASH有
フリー

使用可

TinyBasic GPIO+AnalogIO版へのフィードバックとしては、GPIO16,17を操作対象としておき、
WROVERモジュールを使っている場合は実際には使えない事に注意」程度にしようと思います。

---------------------------------------

2024-4-21追記
ArduinoIDEでのタイニーBASICの書き込みの際に出力画面に出るメッセージには、chip型番、搭載メモリ情報、CPUクロック、MACアドレスなどの情報が書き出されているのに気づきました。今後のタイニーBASICの拡張・プログラム領域拡大・スタック深さ拡大などで、参考になりそうなので、以下にメッセージ例を添付。

ESP32-DevKitC-32E
(ESP32-WROOM-32E)
最大1310720バイトのフラッシュメモリのうち、スケッチが754525バイト(57%)を使っています。
最大327680バイトのRAMのうち、グローバル変数が78836バイト(24%)を使っていて、ローカル変数で248844バイト使うことができます。
esptool.py v4.5.1
Serial port COM6
Connecting....
Chip is ESP32-D0WD-V3 (revision v3.1)
Features: WiFi, BT, Dual Core, 240MHz, VRef calibration in efuse, Coding Scheme None
Crystal is 40MHz
MAC: 省略
ESP32-DevKitC-VE
(ESP32-WROVER-E)
最大1310720バイトのフラッシュメモリのうち、スケッチが772921バイト(58%)を使っています。
最大327680バイトのRAMのうち、グローバル変数が78924バイト(24%)を使っていて、ローカル変数で248756バイト使うことができます。
esptool.py v4.5.1
Serial port COM5
Connecting....
Chip is ESP32-D0WD-V3 (revision v3.1)
Features: WiFi, BT, Dual Core, 240MHz, VRef calibration in efuse, Coding Scheme None
Crystal is 40MHz
MAC: 省略

ESP32-D0WD-V3(チップ内FLASH/PSRAM無し)を搭載し、内蔵SRAMが327,680バイト等分かります。(データシートでは520KB SRAMとの記載ですが)。
尚、ArduinoIDEのツールメニュー、FlashのPartition Schemeでは、"Default 4MB with spiffs(1.2MB APP/2.5MB SPIFFS)"を指定しているので、アプリには1.2MB(1310720バイト)を割り当てている条件下でのメッセージです。

Photo_20240421093701
余談ですが、タイニーBASICを載せても、内蔵RAMのリソースは余裕たっぷりなので、もっとプログラム領域を広げるとか、配列要素数やスタック数を増やすとかできそうです。

#define SIZE_LIST 1023 //List buffer size
#define SIZE_ARRY 32 //Array area size
#define SIZE_GSTK 6 //GOSUB stack size(2/nest)
#define SIZE_LSTK 15 //FOR stack size(5/nest)


----------------------------------------

以下、今回調査の詳細です。

 


 

各ボード毎のGPIO16,17ピンの有無

Photo_20240408193701 実際、手持ちで実機検証に使っているFreenove社ESP32-WROVER-Eの開発ボード(写真右)は、カメラモジュールがボード上のコネクタに繋げられる仕様で、カメラ用途で8MBのPSRAMを搭載し多用するためか、GPIO4と5に間にはGPIO16,17が無くGND 2つに代わっています(左図赤枠部分)。またボードのピンの数は、片側20ピン、両側で40ピンと多いです。

秋月のESP32-DevKitC-32E(写真左)と、ESP32-DevKitC-VE(写真中央)では、GPIO16,17が端子に出ています(左図青枠部分)。ピン数は片側19、両側38。純正DevKitCも秋月同様GPIO16,17が出ています。

この事から、手持ちの方が特殊で、通常の開発ボードでを配慮すると、TinyBasicでは操作対象にしておくべきと考え、今回実機で検証しています。

 

PSRAMとFLASHの有無に着目しての比較すると、

ESP32-DevKitC-32E(ESP32-WROOM-32Eモジュール搭載)は PSRAM搭載無しFLASH(4MB)搭載有り
ESP32-DevKitC-VE (ESP32-WROVER-Eモジュール搭載)は  PSRAM(8MB)搭載有りFLASH(8MB)搭載有り

です。以下、Espressif社のDevKitCのWebより抜粋
Photo_20230628203701_20240406172801

今回以下の2者で実機でGPIOを操作して、波形で比較してみました。
ESP32-DevKitC-32E ⇒ 波形出力OK
ESP32-DevKitC-VE   ⇒ 波形出ずNG、全く反応なし

以下、GPIO16,17テストプログラムとオシロ波形です。黄色CH1がGPIO16、青色CH2がGPIO17です。


GPIO16,17テストプログラム

ボード:ESP32-DevKitC-32E

(モジュール:ESP32-WROOM-32)
PSRAM無し:波形出力OK

ボード:ESP32-DevKitC-VE

(モジュール:ESP32-WROVER-E)
PSRAM搭載:波形出ず、全く反応なし

100 REM ---- GPIO16,17 TEST ----
110 PIN_MODE 16,3; PIN_MODE 17,3
200 REM
210 DIGITAL_WRITE 16,1
220 DIGITAL_WRITE 17,1
230 DELAY_MS 100
300 DIGITAL_WRITE 16,0
310 DIGITAL_WRITE 17,0
320 DELAY_MS 100
400 GOTO 210
Img_0227 Img_0226

上記実機検証結果より、ESP32-DevKitC-VEでは全く反応しません。記事の後半でNCを確認。

2024-4-7追記 WROVERであっても、モジュール選択やPSRAM利用設定を変えればどうなるか調べてみました。
・ボードマネージャーでESP32 dev module を選択すると、ツールにPSRAMの項目が現れ、disableかenableが選択できます。
 ここでdisableを選択し、コンパイルして書き込んでも、状況は改善せず全く反応しません。(下図左)
・ボードマネージャーでESP32 wrover moduleを選択すると、ツールにPSRAMの項目すら出てきません。(下右図)
DevWrover

雑感:

今回、GPIO16,17だけですが、開発ボードでのピンの有無に気づいて、実際に入手。
TinyBasicで試しで操作してみたら、今度は別の問題に引っ掛かり、調べて検証し、やっと状況が判明。
と言う感じでした。まあボード毎の制約事項の理解は深まりました。

なかなか、一歩づつ ステップバイステップ って感じですかね。
やってみないと分からないし、疑問を持って調べないと必要な情報には辿り着かないし、最初から注意・制限事項を熟知しておくなんて出来ないし、まあ世の中こんなもんなのでしょう。

ただ、TinyBasicインタープリタをESP32に書けば、TeraTermからの操作ですし、コマンドラインからの直接操作やプログラムの実行で、簡単便利で気楽にIOが操作出来るのって、とっても良い検証環境にもなるって事が、自分でも実感できました。

------------------------------------

WROVERでGPIO16,17がPSRAMを制御している情報です。

・ESP32フォーラム記事の抜粋
(*1)Unable to use gpio 16 and 17 - ESP32 Forum
GPIO16 and 17 may be used for communication with flash or PSRAM, depending on particular chip or module that you have on your development board.
For example see the datasheet of ESP32-WROVER-E module.

Esp32wrovereflashpsram
WROVERのデータシートで最新情報を確認。
下図が15ページ Fig.7がモジュールのリファレンスデザインの回路図で、GPIO16がPSRAMのCS#へ、GPIO17がPSRAMのSRAM_CLKへしっかり繋がっています。
Photo_20240406212001
2024-4-13追記
WROVERのデータシートの周辺回路図 Fig.9を見ると、IO16,17が並んでいるはずの、IO4とIO5の間がNCになっています。
モジュール内でPSRAMと繋がるので、外からは使えない様に、NCにしているのでしょう。
なるほど、今回テスト的にGPIO16,17を強制的に動かしてみたつもりでも、NCなので波形には何の反応も現れない訳ですね。

Photo_20240415072501

2024-4-13追記
WROVERのモジュールは、GPIO16,17がNCとなっているのが本当か、確かめてみました。
単純に、GPIO16,17をOUTPUTに設定し、共に0を出力、GPIO36,39のADC入力へ接続し、ADC変換結果を読み取るものです。
ブレッドボード上で、配線を伸ばしてノイズを拾いやすくしておきました。
以下、テストプログラムと、ブレッドボード配線の写真、100ms毎10回のADC変換結果です。
結果は、予想通り、ADC結果は暴れているので、本当にNCとなっている様な結果が得られました。

100 REM ------ GPIO16,17 ADC INPUT Test ------
110 PIN_MODE 16,3; PIN_MODE 17,3
120 DIGITAL_WRITE 16,0; DIGITAL_WRITE 17,0
130 PIN_MODE 36,192; PIN_MODE 39,192
140 ANALOG_SET_PIN_ATTENUATION 36,3
150 ANALOG_SET_PIN_ATTENUATION 39,3
200 FOR I=0 TO 10
210 PRINT #5,ANALOG_READ 36,#5,ANALOG_READ 39
220 DELAY_MS 100
230 NEXT I

 

Img_0247

1回目の実行結果
Photo_20240415092601

2回目の実行結果
Photo_20240415092701_20240417121601

-------------------------------

2024-4-10追記
一方、ESP32-WROOM-32Eの内部回路情報 Fig.5を見ると、PSRAMは無いですし、内蔵FLASHへはGPIO16,17は接続していない様です。
Photo_20240410113801

2024-4-13追記
ESP32-WROOM-32Eの周辺回路情報 Fig.7を見ると、IO16に注意書きがありました。
PSRAM内蔵のESP32-D0WDR2-V3等では、IO16を10KΩでPullUp、他の用途では使用不可とあります。

Photo_20240415065201

余り気にするべき所ではないかも知れませんが、以下の図が気になるので、念のため確認として調べました。
R11 0(NC)と言う書き方が、オープンなのかショートなのか自分的には混乱しています。
WROVERの回路なので、GPIO17をSRAM_CLKとして、SCK/CLKをFLASH_CLKとして用い、R11は未実装と言う意味で(NC)としているとは思いますが...
Photo_20240417120401
WROOMには、上記回路は見当たりませんが、FLASHは搭載されているので、FLASHとSRAMのクロックを兼用するための接続の目的が過去にあったのかもと思えてしまいます。
であるならば、WROOMのFLASHアクセスにGPIO17の影響は本当にないのか? が気になってしまう訳です。
WROOMの実機テストでDIGITAL_WRITEではGPIO16,17は普通に波形が出せましたが、それはTinyBasicでユーザープログラムの実行中に確認したものでしかなく、FLASHのアクセスはしてなかったので、ハードウェア的に動かしっ放しにできるはずのPWM出力を、GPIO16,17へ出し続け、[esc]でユーザープログラムの走行を止め、その状態でSAVEやLOADでFLASHのアクセスを行い、問題が発生するかどうか調べました。

WROOMにTinyBasicを載せ、GPIO16,17へPWMを出したまま、SAVE→NEW→LOADを繰り返してみました。書き込んだユーザープログラムが化けるとか、動作がおかしくなるとかの支障はみられませんでした。

関係ないはずと信じてはいたものの、確認するまでは安心できなかったのですが、今回WROOMなら、GPIO16,17は試した限りでは問題なく使えるのが分かってよかったです。


 

続報あればまた。

 

2023年7月12日 (水)

ESP32 Wi-Fi Lチカのスケッチを読解

30年程前にPICをやったっきりで、Arduinoとかも知らかなった自分が、はやりのIoTをやってみたくてESP32を買い、ネット記事を真似してWi-FiでLチカをやってみました。関連情報も探せばたくさん出てきますし、それこそコピペでできてしまう便利な時代ではありますが、仕組みを知らないと面白くないし、応用もきかないので、自分なりに頑張って読解してみました。

目次

 前置き
 基本的な理解から
 処理全体の流れ
 クライアントとサーバーのやり取り
 リクエストの中身
 リクエストの文字列処理の詳細
 HTMLの生成

 読解を終えて
 おまけ:高速化のあがきと顛末

参照した記事を書いた諸先輩達に感謝。この記事が少しでも誰かの役に立てば幸いかな。

 

前置き

ESP32を買ってから1か月半経ちました。
Wi-Fiを使った初IoTのWi-Fi Lチカですが、下の動画の様にスマホのブラウザ画面のボタンを押して、ESP32に繋いだLEDをOn/Offさせる事が出来ます。初めてだからか、これだけでもなんだか感動するものがありましたね。

スマホでESP32に繋いだLEDをOn/Offさせる様子。

でも実は、スマホでLEDを制御しているブログにあったスケッチ(これ)をコピペしただけで、中身の理解が出来ておらず、実はチンプンカンプン、やったら簡単にできたと言う印象だけの状態で、まともな応用もできないでしょう。

ワンショットリモコンのIoT化もそうでしたが独自のIoT工作やスケッチ作成をするにも、エイヤなカットアンドトライになるので、良くありません。
今後のために、ここで一旦Wi-Fi Lチカのスケッチ1行1行をにらめっこし、分からない事をネットで調べ、先人達の知恵も借りて、各行の処理の役割、全体の制御の流れなど自分なりに読解し、理解を深めたいと考えました。
何でもそうですが、分かっていないと面白くないですしね。

ネットにだいぶ助けて貰いましたが、部分部分を個々に解説した記事や言葉で説明した記事は良く見かけるものの、自分の頭の中で多数の記事の断片を繋ぎ合わせ、全体を把握するのに数日掛かりました。
自分は分かり易く全体が見える様にするのが好きなので、Excelでテキストや図・矢印等を付けて分かり易い資料を作成し本記事にpdfで添付してみました。

                    

上記動画では、ボタンを押してから約2秒でLEDが切り替わるので、もっさりと遅いです。
本記事の最後では応答を高速化したくて少しあがき原因が判明。約0.2秒と大幅に改善(下)。果たしてその原因は?

 

基本的な理解から

Wi-Fiを使ったIoT工作の基本的な理解からですが、Lチカの事例ではESP32側がサーバーで、PCやスマホのブラウザ画面がクライアントになります。(中間のWi-Fiルーターとのやり取り等は省略)

クライアントからはリクエストが送られ、サーバーがレスポンスを返すというやり取りの繰り返しです。
Photo_20230712165401_20230806090501


ESP32側のWi-Fiルーター接続時のIPアドレスを、クライアント側ブラウザに入力する事で初めて、クライアントとサーバーが接続し、クライアントからリクエストが送られ、サーバーからレスポンスとしてブラウザ画面用のHTMLを返す事で、クライアントのブラウザ画面が構成されます。

以下、Wi-Fi Lチカでクライアントがサーバーに接続した直後のブラウザ画面です。
サーバー側からのレスポンスとして受信したHTMLでブラウザ画面の各パーツが配置されます。
予めボタンにはLEDをOn/Offするためのリンク先を、HTMLの<a href=リンク先>~ボタン配置~</a>の形式で付けてあります。
1_20230713205601_20230806090501

画面のボタンをクリックすると、ボタンに貼られているLEDのOn/Offのためのリンク先へのリクエストがサーバーに送信され、サーバー側でリクエストの文字列から"GET /26/on"等を見付け、必要なGPIOを操作し、次の操作のためのブラウザ画面の更新用のHTMLデータをクライアントへ送信し、接続を解除します。

その後の動作は、ブラウザのボタンを押すたびに、ボタンのリンク先へのリクエストが送られ、サーバーで必要な処理をしてレスポンスを返すという繰り返しですね。

 

処理全体の流れ

簡単には、ざっとこんな感じですが、中身は細かい処理が並んでいて結構複雑ですね。
リクエストの中身を知らないと、サーバー側での必要な処理の仕方が分かりませんし、どう言う構成でレスポンスを返すかも知っておく必要があります。HTTPプロトコルと言うらしいですけどね。
特にサーバー側でのリクエストの中身の文字列を、どんな方法で判別しているかを理解する事が重要に思います。

とは言え、まずは全体の流れを追い、大まかでも良いので全体を理解するのが良い気がします。
と言う事で、先ずは全体の大まかな流れを書いてみました。

大雑把には、初期化・Wi-Fi接続を終えたら、クライアントからのリクエストを待ちます。
リクエストが来たら、リクエストの受信完了後に、GETコマンドに従った処理と、レスポンス送信(HTMLも更新)をして、再度リクエスト待ちを繰り返すって感じですね。
Photo_20231225161701
注意:シリアルモニタへのメッセージ送信とか、レスポンス送信後のクライアントとのWi-Fi接続の切り離し処理とか、タイムアウト処理とかは先ずは考えないで書いています。

前項で書いたように、リクエストで大事な所は”GET /リンク先"です。
最初にIPアドレスだけでアクセスすると、”GET /"だけがクライアントから送られますが、/以降のリンク先(26/onとか)が無いので、LED点灯の操作は実施されず、ブラウザ画面を構成するためのHTMLをクライアントへ送信するだけです。
それ以降は、ブラウザ画面のボタンを押す事で、"GET /26/on"とかのリクエストが送られ、GPIO26のLEDを点灯させる操作が実施され、その状態にブラウザ画面も更新されます。

この大まかな流れを、細かい処理で実現しますが、細かい処理では良く分からない部分が残ってしまうでしょうから、後で詳細を追えば良いと思います。

と言う事で細かい処理の全体像として、スケッチ1行1行を読解し説明を加えてみた図です。クリックでpdfが開きます。
先人達のWi-Fi Lチカの解説ブログやHTTPプロトコルのネット情報など、書き加えて全体が見える様に書いてみました。
Photo_20230805165601_20230806090601

左側がESP32側がWi-Fiルーターに接続するまでの部分で、ESP32の電源OnでWi-Fiに繋ぐまで1回だけ実行されます。
右側がクライアントと接続し、ブラウザのボタン操作でLEDの点灯/非点灯をする部分で、クライアントとの接続と切り離しを繰り返します。

クライアント側ブラウザ画面のボタンが押されるとサーバーと接続し、ボタンのリンク先を含むGETリクエストがクライアントがサーバーに送信されるので、サーバー側ではリクエスト文字列を1字づつ受信しながら、行末判定と行末処理を全行繰り返し、最後のリクエスト受信終了の判定の後、レスポンス送信・リンク先文字列により必要なGPIO操作・更新用HTML送信を行い、接続を切り離し、次の接続を待つと言う流れです。

自分もそうでしたが初めてだと、しばらく頭をもやもやさせて脳内の情報整理と定着が必要でしょうし、ネット検索でヒント探しを繰り返すとか、必要な気がします。コツは何度も繰り返して考えながら見る事かな。

 

クライアントとサーバーのやり取り

クライアントとサーバーのやり取りの、たぶん通例的な形式であろう部分が、予備知識ほぼゼロの自分にはとっても分かりにくいと感じたので、少し補足です。

クライアントからのリクエストはGETメソッドを使っていて、リクエスト内のリンク先を示すURI文字列は、ブラウザのURL欄にも表示される様です。以下、少し順を追って実際の画面例を見ながら説明してみます。

ブラウザでURLに192.168.1.8を入力し、クライアントと最初に接続した場合のリクエストには、ボタンからのリンク等何もないので、サーバー側の"GET /26/on"等の検索にヒットすることなく、初期値のoutput26State = "off"、output27State = "off" のまま、サーバーからHTML構成のレスポンス送信が行われ、下記の画面が表示されます。
注意:このスケッチ例では、ブラウザ画面のボタンの文字や色は押した後の状態を示す様になっています。

接続直後のクライアントのブラウザ画面。URL欄は"192.168.1.8"だけです。
1_20230713205601_20230806090501

この状態で、GPIO26の ON ボタンを押すと、URL欄は192.168.1.8/26/on になり、GET /26/on リクエストがサーバーに送られ、サーバー側でGET /26/onの検索がヒットし、GPIO26出力がHIGHになり、HTML生成を含むレスポンスにより、GPIO 26 - State on で  OFF  にブラウザ画面が変わります(下図)。
GPIO26の ON ボタンを押した後の画面。URL欄は"192.168.1.8/26/on"に変わっています。
2_20230713205701_20230806090801

更に、GPIO26の OFF ボタンを押すと、URL欄は192.168.1.8/26/off に変わり、GET /26/off リクエストがサーバーに送られ、サーバー側でGET /26/offの検索がヒットし、GPIO26出力がLOWになり、HTML生成を含むレスポンスにより、GPIO 26 - State off で  ON  にブラウザ画面が変わります(下図)。
GPIO26の OFF ボタンを押した後の画面。URL欄は"192.168.1.8/26/off"に変わっています。
3_20230713210101_20230806090901

注意:上記画面はPCでの画面ですが、スマホ(iPhoneのSafari)では画面が小さいためかドメイン表示しかせず、URL欄に/26/on等の文字は一見表示されませんが、URL欄を選択すれば表示されました。

で、ここで肝心なのは、上記URL欄にも表示される、GETリクエストの1行目にあるリンク部分です。
その文字列によって、GPIO操作の判別を行えば良い事になります。
下記は、最初の全体像のpdfの一部拡大です。
Photo_20230805171801_20230806091001

最初だけ取り出したのが、以下の記述です。

// turns the GPIOs on and off
if (header.indexOf("GET /26/on") >= 0) {
    Serial.println("GPIO 26 on");
    output26State = "on";
    digitalWrite(output26, HIGH);
} else if (header.indexOf("GET /26/off") >= 0) {
...

リクエスト文字列は文字列変数headerに入っているので、"GET /26/on"の文字を検索し、ヒットすればGPIO26をonにするため、digitalWrite(output26, HIGH);を実行しています。

これで、リクエスト文字列から、GPIO操作に必要な情報を得る方法が分かりました。
HTML書式に則り、ボタンのリンク先の部分へGPIO操作のキーワードを埋め込んでおき、ボタンが押されたら指定されたGPIO操作を行う感じで、なかなか上手い方法と思います。

尚、上記では文字列変数output26stateに現在の状態として"on"を代入しています。
この変数は更新用HTMLの生成で、現在の状態に応じてボタンの色や文字とGPIOの状態表示を変えるためです。

 

 URL欄GPIOコマンド操作 

この方法では、サーバーとの最初の接続時に、例えば 192.168.1.8/26/on とURL欄に入力すると、接続時点でGPIO26のLEDをOnさせる事も出来ます。
接続とブラウザ画面の立ち上がりを待ってボタンを押す操作をするまでもなく、URL欄だけの情報で操作できる訳で、まさに「GPIOコマンド操作」と言えそうです。
ブラウザ上のボタンが無くても操作できるので、面倒なボタン配置用HTMLのスケッチ記述を後回しにして、GPIO操作のスケッチ記述のデバッグに集中できますし、ブラウザ画面にボタンすらない簡易サーバーで済ませるとか、いろいろと応用できそうです。
ボタンがある方がIoTって感じが強くなりますし、何よりカッコいいですけどね。

PCブラウザのURL欄だけでGPIO操作をしている動画です。ボタンは一切押していません。

やってみたことはありませんが、26/onとか、27/offの文字列は、ESP32側の処理の振り分けのためのキーワードになっているだけなので、26onでも27offでも良いはずです。その場合は、if文での検索文字も合わせる必要があります。
HTMLのリンクの仕組みをそのままESP32側での処理の振り分けに利用した方法と言えます。

 

リクエストの中身

上記やり取りの背景となるりリクエストの中身の理解も必要です。
具体的に、リクエスト文字列を見た方が早いので、スケッチの一部を変えて、リクエスト文字列をシリアルモニタに送るSerial.write(c);を有効と無効とした各々で、シリアルモニタ画面の差を見てみました。

Serial.write(c);の有効・無効でのシリアルモニタ画面。クリックでpdfが開きます。
Photo_20230806091101

これで、リクエストの中身の構成が分かりました。
シリアルモニタでは改行されるだけで文字として見えないので少し分かりにくいですが、各行末には実際には CR LF (\r\n or ¥r¥n or 0x0d 0x0a ASCII文字)が定型的に付加される様です。

リクエストのフォーマット 参考(*1)の説明を抜粋
Photo_20230715121001_20230806091201

上記の様に行末が\r\nとなる複数行と、最後の\r\nだけの空行で、GETリクエストをクライアントが送ってくるので、この特徴を使ってサーバー側の処理をする事になります。
Wi-Fi Lチカのスケッチでは、参考(*2)での説明(下)が分かり易いです。

HTTPでは「\n」と「\r\n」のどちらにも対応することを定めています。
しかし「\r\n\r\n」だと煩雑になるので、読み取った文字が「\r」の場合はcurrentLineに追加しないことで、「\r」の排除を行っています。
currentLineの長さが0になるのは「\n」を読み取った後です。
その後に他の文字を読み取ればcurrentLineの長さは1以上になります。

「\n」を読み取った直後にまた「\n」を読み取った場合、currentLineの長さが0の状態で「\n」を読み取ったということは、HTTPリクエストの区切りの空白行なので、これでリクエストが完了したとみなし、HTTPレスポンスの送信を開始しています。

 

リクエストの文字列処理の詳細

リクエストの文字列は把握できましたが、今度はサーバー側での具体的な処理のアルゴリズムをどうしているのか、具体的に知っておく必要がありそうです。
サーバー側でのリクエストの1文字処理を行う部分は結構長い記述ですので、元のスケッチのまま処理を追っていては、目が上下に行き来してしまうし、頭もこんがらがってしまいます。
途中をはしょって、受信するリクエストも4行と簡略化して、スケッチに従って1文字ずつ単純に処理するCPUの身になり、処理の流れを追ってみました。

以下、リクエストの処理の読解図です。クリックでpdfが開きます。
Photo_20230806091301

上記では矢印が多すぎてかえって分かりにくいかもしれませんが、大事な所は\nを受信した際の処理です。
\n受信で、行末判定とリクエスト受信終了判定が行われます。

\n受信での行末判定は、受信した行の\rの直前までの文字列がcurrentLineに入っているので、\n受信時かつcurrentLine.length()==0が成り立たない事で行の終わりと判断され、currentLine=""でクリアするだけで次の行の文字受信に移行します。

\n受信でのリクエスト受信終了判定は、リクエストの最後は\r\nだけの空行の受信となるので、一つ前の行末処理でcurrentLine=””のまま、\r\nの受信に入る事になり、\n受信時かつcurrentLine.length()==0が成立する事でリクエストの終了と判断し、レスポンス送信・GPIO操作・更新用HTML送信に移行します。

尚、受信した文字はそのまま文字列変数headerにため込んでいきますし、1行毎の可読文字(\r\n以外)は文字列変数currentLineへ取り込みます。文字列変数headerはGPIO操作にも使われますが、文字列変数currentLineは行末判定とリクエスト受信終了判定に使われるだけですね。

以上、ざっとした説明ですが、スケッチ1行1行の処理内容・流れが追えたので、やっと全貌が把握できた気がします。
やれやれでした。

スケッチで最初にインクルードされる WiFi.h に定義されているライブラリの説明が、以下参考(*3)にありました。
元のスケッチ内のコメントと綴りでだいたいの意味は分かりますが、一度きちんと見ておいた方が良いと思われます。

WiFiServer begin() WiFiサーバを開始
available() WiFiクライアントからの接続を取得
WiFiClient connected() ホストとの接続状態を返却
available() ストリームで利用可能なバイト数を取得
read() 受信したデータを1バイト読む
stop() ホストとのTCP接続を切断

ESP32をサーバー側として、クライアントPC・スマホとやり取りするのですが、ESP32側のスケッチ内にあるread()がWiFiClient側にあって、WiFiServer側にないのかとか、良く分からない部分もあるので、知っておくべきタイミングで調べる必要がありそうです。
この辺まで来ると、本当に詳細を知るのが必要な時に調べれば良いと思います。

 

HTMLの生成

上記まででほぼWi-Fi Lチカのスケッチの重要な部分は読解できました。
あと残りはサーバー側のレスポンスで更新用HTMLをクライアントへ送る部分で、HTMLとして一般的な文字列表示、ボタン配置、リンクの埋め込み、CSSでの見え方指定などで、本Wi-Fi Lチカの例もそうですが、比較的簡易なブラウザ画面構成を生成する部分と思います。

スケッチでは、client.println(”HTMLの各行”)を多数並べHTML各行を順にクライアント側に送信する形になります。
以下は、実際のスケッチのclient.println(”HTMLの各行”)の”HTMLの各行”部分だけを取り出し、そのままブラウザで見れる様に少し加工したHTMLファイルを作成し、PCで見たものです。
ブラウザの右クリックで「ページのソース表示」を選択すればHTMLテキストが見れます(Edgeの場合)。
Photo_20230809134601
注意:このブログにHTMLファイルを置いたので、ボタンを押しても/26/on等のLink先が無く、ココログ サーバーは「ページが見つかりません」とエラーを返します。
この時ブラウザのURL欄を見ると、末尾に/26/on等のリンク先が付加されているのが分かります。


下が上記のテキストで、<html><head><body>の順の一般的な構成です。
赤字の部分は実際にはESP32側のスケッチで処理する部分になります。

<!DOCTYPE html>
<html>

   <head>
      <meta name="viewport" content="width=device-width, initial-scale=1">
     <link rel="icon" href="data:,">

     <style>html { font-family: Helvetica; display: inline-block; margin: 0px auto; text-align: center;}
         .button { background-color: #4CAF50; border: none; color: white; padding: 16px 40px;
                       text-decoration: none; font-size: 30px; margin: 2px; cursor: pointer;}
         .button2 {background-color: #555555;}
      </style>
   </head>

   <body>
      <h1>ESP32 Web Server</h1>
      <!-- 以下GPIO26の現在の状態表示は、実際はoutput26State変数を表示させている-->
      <p>GPIO 26 - State output26State変数の中身</p>

      <!-- 以下はif文でoutput26Stateの内容によりどちらか選択して表示させている-->
      <p><a href="/26/on"><button class="button">O N</button></a></p>
      <p><a href="/26/off"><button class="button button2">OFF</button></a></p>

      <!-- 以下GPIO27の現在の状態表示は、実際はoutput27State変数を表示させている-->
      <p>GPIO 27 - State output27State変数の中身</p>

      <!-- 以下はif文でoutput27Stateの内容によりどちらか選択して表示させている-->
      <p><a href="/27/on"><button class="button">O N</button></a></p>
      <p><a href="/27/off"><button class="button button2">OFF</button></a></p>

   </body>

</html>

現在の状態表示の赤字部分は、実際にはESP32側スケッチでは以下の記述で、現在の状態を保持している文字列変数output26Stateの中身の"on"か"off"の文字列を表示させています。
client.println("<p>GPIO 26 - State " + output26State + "</p>");

ボタンの文字と背景色の赤字部分も、実際にはESP32側スケッチでは以下の記述で、リンク先・ボタンのクラス・ボタンの文字を、output26Stateが"off"か否かで、どちらかを選択しています。
// If the output26State is off, it displays the ON button
if (output26State=="off") {
    client.println("<p><a href=\"/26/on\"><button class=\"button\">ON</button></a></p>");
} else {
    client.println("<p><a href=\"/26/off\"><button class=\"button button2\">OFF</button></a></p>");
}

GPIO27の方も同様です。

IoT工作では、ブラウザ画面のボタンの色や表示内容を変えたり、ハードウェアの状態表示や、センサーから得た数値の表示を行う程度で、そんなに複雑なブラウザ画面にはならないと思いますし、HTMLの文法・構成等は一般的な内容です。
今回のWi-Fi Lチカのスケッチ読解の趣旨目的から少し外れるので、ざっとした説明に留めます。
もっと複雑な画面構成が必要な場合は、HTMLエディタ等でひな形を作成し、1行ずつclient.println()内に記述してクライアントへ送るか、文字列変数htmlbodyへ htmlbody += HTMLの各行毎記述; を繰り返し、文字列全体を作り一気に送るとかで、対応できると思われます。

 

読解を終えて

やっとほぼ読解できたと思います。
クライアントサーバー間のリクエストとレスポンスの形式、リクエスト文字列からのサーバー側処理内容の検出方法、HTMLのheaderやbodyの書式、など理解しESP32言語で必要な処理を記述すると言う、IoTならではの知識が必須なのを痛感しました。

今回読解したWi-Fi Lチカのスケッチですが、かなり理解が少し進みました。

ブラウザ画面にボタンを数個並べてクリックする事で、ESP32側でGPIOの操作等をするのが、IoT工作の第一歩でしょうし、そんなの常識、当たり前って言われる気もします。
が私にとってはES32を入手した約1か月前までは何にも知らなかった訳ですので、今回の読解でIoT工作の階段を一段登れたって感じでいます。

でも、まだまだ知らない事だらけでしょうから、今後も分からない事は、ネットの情報検索で先人達の知識や情報を借りながら、更に理解を深めながらIoT工作等をしていきたいと思います。

 

おまけ:高速化のあがきと顛末

実はこのWi-Fi Lチカは、ブラウザのボタンを押してから、体感で2秒程しないとLEDが変わらないもっさり感があります。最初の動画です。
スケッチの読解により、GETリクエストの1行目だけでやりたい事はできるので、残りの文字列全部の1文字づつの処理は時間の無駄に思えます。
最初の1行目の最後の改行を受信し終えたら、GPIO操作やブラウザ画面更新に移行してしまえば、応答が早くなるとは思いますが、リクエストの受信途上でサーバー側の処理を始めてしまうと、それはそれで、リクエスト・レスポンスのやり取りの同期が取れなくなり、見えないライブラリの内部処理とかで不都合が発生する気もします。
特に最初にクライアントと繋がった際は、一旦全部リクエストを受け取らないといけない気もしますが、今回のスケッチがクライアント-サーバーのやり取りの全てであるならば、今回のスケッチではリクエストの最初の1行目でしか意味ある処理はしていません。
ならば、無知な私に考えつくのは、1行目の\r\nを受信したら、レスポンス送信・GPIO操作・更新用HTML送信動作へ直ぐに移行させ、接続を切ってしまうスケッチにしたら、高速化できるのか? 不都合は生じるのか? 見えない内部処理からのエラーに見舞われるのか? など試してみたい気がします。ESP32だと手軽に試せますしね。
今のスケッチでも、接続時間が2秒をこえるとタイムアウトが働き、Whileループを抜け、client.stop(); で強制的に接続を切っているくらいですし、大丈夫な感じもします。

-----------------------------------------------------
2023-7-17 上記やってみましたが、特にエラーとかは発生しないものの、高速な応答にはならず、体感的には余り変わらないかな。
ボタンを押してももっさりLEDが切り替わる状況は変わりませんでした。
ハハハ 我 浅はかなり! まだまだ修行が足りません。

変更してみたスケッチです。
最初に\nを受信したら、currentLine ="" にして、リクエストの最後だと勘違いさせる方法です。

77行目が追加した部分。
Photo_20230717211901_20230806091501

シリアルモニタを見ると、IPアドレス表示後の、リクエストを返す部分には、1行目の GET / HTTP/1.1 や GET /26/on HTTP/1.1 等しか表示されないので、2行目以降のリクエスト文字列は見ていません。やった事は正しそうです。
Serial_20230717212201_20230806091501

比較のための元のスケッチでのシリアルモニタ画面です。2行目以降のリクエスト文字列も表示されています。
Motonoserial_20230806091601

-----------------------------------------------------
2023-7-18追記
参照したwak-techさんの記事にあった動画では、ボタンを押してからLEDが変わるまでの応答が早いです。
【ESP32】Wi-Fi経由でスマホからLチカ - YouTube
スケッチはタイムアウト処理がないくらいですが、コピペして実行しましたが、全く早くなりません。
それどころか、スマホのブラウザ画面では通信データ待ちのクルクルが回る状態になったりします。
しばらくしてから実行すると反応が早くなっていたりと、安定しません。
どうも、自宅のWi-Fi通信環境の問題な気がしてきました。
これとは別に、Freenove社へ質問しているので、回答来たらUpdate予定です。
今となっては、MACアドレスフィルターリングを止めてみろとか、Wi-Fi通信環境を調べるべきとの回答が期待かな。
-----------------------------------------------------
2023-7-20追記
Freenove社への質問は、「最初に\nを受信したら、currentLine ="" にして、リクエストの最後だと勘違いさせる方法」でも早くならないので、簡単で一般的な高速化のアイデアとかを問いかけたものです。
回答としては、「You can refer to chapter 30 of our esp8266 kit.」(esp8266 kitのChapter 30 を参照できるよ)だけで、以下の紹介を受けました。

https://github.com/Freenove/Freenove_Ultimate_Starter_Kit_for_ESP8266/archive/refs/heads/main.zip
 
以前の記事にも書いたのですが、Freenove社の各種キットのドキュメント・スケッチ類はフリーでダウンロード可能で、上記はFNK0073と思います
Photo_20230721090501_20230806091701

DLして出てきたスケッチ sketch_30.1_control_led_through_web.ino を試してみましたが、高速化されませんでした。

この結果は今の認識としては思っていた通りで、スケッチやESP32の処理の問題ではなさそうなので効果はありません。

------------------------------------------------------------------
しかし、このスケッチ、今まで試したWi-Fi Lチカ スケッチ(ブラウザ画面は以下、ボタン2つで、LED 2個をOn/Offのもの)と中身ほぼ同じでした。
1_20230713205601_20230806091701
オリジナルがどれなのか分かりませんが、世界中でほぼ同じスケッチを使ってWi-Fi Lチカのブログ記事やYoutube動画が発信されているんですね。
それだけお手軽で誰でもできるって事でなのでしょう。
------------------------------------------------------------------

別アイデアとして試したのが、MACアドレスフィルターリングの停止です。
停止させると、早い時は0.5秒位でLEDが切り替わり高速化されましたが、不安定で遅いときは2秒くらいかかりました。
やはり自宅のWi-Fi環境が原因の可能性が高そうです。
ははは、今のWi-Fiルーターは約8年前から使っていますが、MACアドレスフィルターリングで10台程度の機器をWi-Fiで繋いでいるので、性能が足りていないのでしょう。
3年程前にNifty光にした際にキャンペーンでもらっていたWi-Fiルーターがあるので、取り替えてみるのが良いかな。

 

  もっさり応答の原因はWi-Fiルーターでした   
2023-7-21追記
今日Wi-Fiルーターを更新しました。高速応答の効果が出ました。
ボタンを押してからLEDが変わるまで体感的には0.2秒程度、応答時間は大幅に短縮されました。
今までの2秒程度のもっさり感はなくなり、指で押して直ぐ反応、ストレスを感じません。
以下、動画です。

動画をWindows10のビデオエディターを使いコマ送りで変化点を追ってみました。
見たのは16秒過ぎ辺りで、ボタンを押した瞬間⇒LEDが点灯した瞬間⇒ブラウザ画面が更新された瞬間の順です。
コマが荒いのですが、ボタンを押してから LED点灯まで0.16秒、画面更新まで0.33秒 なのが分かります。
タイミングによって多少の時間差がありますが、最大でも0.5秒以内に画面更新までされるようになりました。

ボタンを押した瞬間16.50秒 LEDが点灯した瞬間16.66秒 画面が更新された瞬間16.83秒
1_20230726094701 2_20230726094701 3_20230726094701

ちなみに、77行のcurrentLine ="" を有効にしてみましたが、より早くなる感じはなく、ほぼ上記と同じ反応速度でした。
リクエスト全行の処理よりもWi-Fiルーターの応答速度が、もっさり応答の主因で間違いなさそうです。

Wi-Fiルーターの更新でインターネット通信速度も改善しました。
今まで100Mbpsを超える事は無かったのですが、超えるケースが出てきました。
Photo_20230726120301_20230806091901

Wi-Fiルーター起因は全く予想もしていない原因でしたが、更新により内外の速度が早くなり良かったです。
これで、サクサク動くESP32 IoT工作ができそうです。

 

続報あればまた。

 


参考
ESP32を使ってスマホからLチカ(LED点滅)する【webserver】 | Wak-tech
SimpleWiFiServer (fc2.com)
 └client.available()で、読み込み可能なバイト数を取得します。1文字以上読み取りできる場合は、client.read()で1文字読みます。
ESP32入門 通信機能が標準搭載されたマイコン・ボード (4) サンプル・プログラムを用いてWi-Fi経由でLEDのON/OFFを行う(2) - Arduinoクックブック (denshi.club)
・(*1)HTTP リクエストとレスポンスの形式に関する注記 | AppExpert (netscaler.com)
・(*2)ESP-WROOM-32でWebサーバーを作ってHello World!をする - Qiita
HTTPプロトコル (quu.cc)
「HTTPリクエスト」と「HTTPレスポンス」 | ITSakura
・(*3)https://garretlab.web.fc2.com/arduino/esp32/reference/libraries/WiFi/

 

2023年7月 4日 (火)

ESP32-WROVER-E PSRAM有効化

ESP32-WROVER-EでttBasicを使った際に、スケッチのコンパイル時のメッセージには、メモリの使用量が出ていました。

最大1310720バイトのフラッシュメモリのうち、スケッチが749337バイト(57%)を使っています。
最大327680バイトのRAMのうち、グローバル変数が46112バイト(14%)を使っていて、ローカル変数で281568バイト使うことができます。
との事です。
Compile_noerror

ESP32-WROVER-Eは8MBのPSRAMを搭載しているので、余りにも少なすぎます。

調べると、PSRAMをIDEで有効にし、setup()が開始されている事との記事がありました。
ESP32で外部ライブラリ等でのPSRAM割当制御 | Lang-ship
Photo_20230704214701

ttBasicをコンパイルする際に、Arduino IDE - ツール - PSRAM:"Enabled"のEnabledにチェックが入っている記憶がないので、おそらく原因はこれかなー!と言う事で、チェックを入れてコンパイルしてみます。

ESP32-WROVER-E アルティメットスターターキットでは、PSRAMを含めRAMを大量に使うはずのカメラを使ったアプリがあります。
その辺りのドキュメントをよく見ればヒントもある気がします。

今日は仕事で手がつかないので、明日続報かな。


2023-7-5追記
Arduino IDE(最新の2.1.1)ではPSRAM:"Enabled"が出てきません。探してもそれらしい所が見当たりません。
で、スターターキットのカメラアプリの357ページでは、以下の設定をせよとの事が記載されていました。
意味は良く分かりませんが、
Partition Scheme:Huge APP (3MB No OTA/1MB SPIFFS) を選択する必要がある様です。
Cameraserversample

Arduino IDEで同じ設定をやってみました。
Photo_20230705121501

コンパイル後のメッセージが出ました。
最大3145728バイトのフラッシュメモリのうち、スケッチが749337バイト(23%)を使っています。
最大327680バイトのRAMのうち、グローバル変数が46112バイト(14%)を使っていて、ローカル変数で281568バイト使うことができます。
Arduinoidecompile

単純にRAM容量が増えるメッセージは出ず、RAMに関しては変わりありませんが、フラッシュメモリの方の最大値が大きくなっています。
FLASHやPSRAMは、パーテーションやファイルシステム、作業用メモリ領域確保など、いろいろと使い方のバリエーションがありそうで、単純ではない様ですね、ははは!、まだまだ未熟で浅はかなり。。。以下参考。
ESP32-WROVER-Bで4MBもの広大なメモリ空間を手にいれる | kohacraftのblog
Use PSRAM (upesy.com)


続報あればまた。

 

2023年7月 1日 (土)

ESP32-WROVER基本スターターキット他購入と動作チェック

ESP32-WROVER-Eですが、以前買ったアルティメットスターターキットだけで、今まで幾つか回路を組んだりしてきましたが、マイコンボードもブレッドボードも1つしかないので、何かとやりにくさを感じる様になってきました。

ブレッドボードも回路が簡単に組めるのが便利で良いのですが、別の事をやろうとすると部品と配線を外す必要があり、一旦ばらしてしまうと、元の回路の再現には、また組み上げるのが必要になるので、なかなかばらせないおっくうさが付きまといます。

要は、1つしかないのがやりにくさの原因なので、買い足せば不足感は解消し、いろいろ同時並行的にやり易くなるはずです。

と言う事で、どうせならGPIOエクステンションボードも手に入るし、カメラ等のパーツ類もブレッドボードも付いて、コスパ良しで安心なFreenove 基本スターターキットと、評判が比較的高めで大小ブレッドボードが2枚づつ入っているブレッドボードセットを買い足しました。


買った基本スターターキットです。
Photo_20230701202201

合わせて買ったブレッドボードセットです。
2_20230701202201


2023-7-6追記

2つのパッケージを並べた写真です。
Img_9550

箱を開けた写真です。
Img_9551
右のブレッドボードセットは残念ながら全体が収納できるプラケースが入っていませんでした。
アマゾンの製品レビューでは写真も多数掲載されていますが...まあ中?品質ってところでしょう。

箱から取り出して並べた写真です。
Img_9552

基本スターターキットにも一通りのものが入っています。
Img_9553

自宅Wi-Fiへ繋ぐためMACアドレスを調べ、Wi-Fiルーターに登録し、ttBasicを入れて動かしてみました。
Photo_20230706140401
Wi-Fiも繋がり、ttBasicも走り、ESP32の動作が確認出来ました。

これで、ESP32-WROVER-Eの工作環境が2つになりましたし、ブレッドボードもジャンパー線もタップリです。
いろいろとやれそうです。


続報あればまた。

 

2023年6月23日 (金)

ワンショットリモコンのIoT化:成功

全体の目次

先日構想していたワンショットリモコンシステムのIoT化ですが、今日回路の組み上げとスケッチの編集をし、スマホのブラウザ画面からのIoT制御が成功しました。

編集元のスケッチ内のHTML記述の動作が良く分からない部分がありましたが、ネット検索でいろいろと記事をあさり、斜め読みしながらカットアンドトライで何とかできました。
いやー!情報が結構ネットに転がっているので、つまずいても比較的簡単に解決にたどり着くことが出来、良き時代になったものだと感じます。

クライアントに表示されるHTMLの見え方編集に関し、Visual Studio Code・LiveServer・Prettier-Code Formatterのインストールで少しでも楽になるかと思いましたが、それはそれで面倒だったので、今回は手修正のカットアンドトライで何とかなりました。


全体構成は以下です。
Photo_20230623225001
ダイオード接続切替回路はトグル動作なので赤と緑のLEDを付けました。
このLEDは、リモコンスイッチの赤緑LEDと役割は同じです。
もしクライアントのブラウザ画面とリモコントランスのOnとOffの関係が逆になっている場合は、リモコンシステムへ接続する線を入れ替えれば一致させられます。

ESP32に繋いだ外部回路部分の拡大です。
2_20230623225001
右下の5Vリレー回路がワンショット回路でGPIO26に100ms期間HIGHを出力し、既設ワンショットリモコンシステムへダイオードを接続する事で、ワンショットリモコンリレーを切り替えます。
切り替わってしまえばリモコンリレー内のダイオードの向きも変わり、電流は流れなくなるのが分かっている事と、確実な切替動作のため、接続時間を長めの100ms(50Hzだと5サイクル)にしました。
右上の5Vリレー回路がダイオードの接続向きの切り替え回路で、GPIO26からのHIGH出力が終わってから、逆向きへ切り替えておくため、GPIO27の出力がHIGHだったらLOWへ、LOWだったらHIGHへと切り替える、トグル動作をさせます。
状態が分かる様に赤と緑のLEDを排他的に点灯させます。緑LED側はESP32のGPIOは3.3V系なので、3.3Vを電源にしました。


スケッチは、前回のLチカのものを加工して作成しました。
ボタンは1つだけにし、押すたびにGPIO26で100msだけHighを出し、その後GPIO27をトグルさせダイオードの向きを切り替えます。
ボタンの色は、リモコンリレーとリモコンスイッチの現在の状態に合わせ、ON状態なら赤色で to OFF 表示、OFF状態なら緑色で to ON 表示にしました。

元のスケッチからの主な変更点が下の赤字部分です。
output27Stateの if else でのトグル動作の記述は、たぶん冗長かなーと思いつつそのままです。

-- 省略 --
    // turns the GPIOs on and off
    if (header.indexOf("GET /26/on") >= 0) {
      Serial.println("GPIO 26 on");
      output26State = "on";
      digitalWrite(output26, HIGH);
      delay(100);
      digitalWrite(output26, LOW);
      if(output27State=="off"){
        digitalWrite(output27,HIGH);
        output27State="on";
      } else {
        digitalWrite(output27,LOW);
        output27State="off";
      }
    } else if (header.indexOf("GET /26/off") >= 0) {
      Serial.println("GPIO 26 off");
      output26State = "off";
      digitalWrite(output26, HIGH);
      delay(100);
      digitalWrite(output26, LOW);
      if(output27State=="off"){
        digitalWrite(output27,HIGH);
        output27State="on";
      } else {
        digitalWrite(output27,LOW);
        output27State="off";
      }
  }
-- 省略 --

  // Feel free to change the background-color and font-size attributes to fit your preferences
  client.println("<style>html { font-family: Helvetica; display: inline-block; margin: 0px auto; text-align: center;}");
  client.println(".button { background-color: #009933; border: none; color: white; padding: 16px 40px;");
  client.println("text-decoration: none; font-size: 30px; margin: 2px; cursor: pointer;}");
  client.println(".button2 {background-color: #f61f20;}</style></head>");

  // Web Page Heading
  client.println("<body><h1>One-Shot-Remocon Server by ESP32</h1>");

  // Display current state, and ON/OFF buttons for GPIO 26
  client.println("<p>Current State " + output26State + "</p>");
  // If the output26State is off, it displays the ON button
  if (output26State=="off") {
    client.println("<p><a href=\"/26/on\"><button class=\"button\">to ON</button></a></p>");
  } else {
    client.println("<p><a href=\"/26/off\"><button class=\"button button2\">to OFF</button></a></p>");
  }

--  // Display current state, and ON/OFF buttons for GPIO 27
     以降のボタン処理関係は削除  --
 


-- 省略 --


IoT化のESP32と外部回路です。上に延びた赤黒線がワンショットリモコンシステムに繋がります。
Img_9526

外部回路の拡大です。部品と配線が密集しているので分かりにくいです。四角い箱が5Vリレーです。
Img_9529

ワンショットリモコンシステムに繋いだ状態です。ESP32側はモバイルバッテリーで動かしました。
Img_9530

ESP32に繋いだ回路の組み上げ部分で、GPIO27でダイオード接続向きをトグルさせる回路の赤LEDが点灯している状態。
Img_9546

同上で緑LEDが点灯している状態。
Img_9545

スマホでWi-Fi経由で制御している動画です。
ワンショットリモコンスイッチを押すと同期がずれますが、スマホ側ブラウザのボタンを2回押すと同期するのが分かります。

スマホとPCからも制御してみた動画です。分かり易い様にワンショットリモコンリレーの主回路にランプを繋ぎました。

2023-6-25追記
リモコンスイッチの結線を外して、今回のIoT化回路だけでリモコンリレーの制御ができるか確認しました。
実験の様子です。リモコンスイッチからの赤い線(上下のボードの間)を外したので、リモコンスイッチ側の赤緑LEDは点灯していません。
Img_9532

動画です。

---------------------------------------------------------------------
ついでに、自作ワンショットリモコンリレーをIoT制御してみました。
実験の様子です。
Img_9534

動画です。

どちらも期待通りに動作させることが出来ました。

 


ワンショットリモコンシステムのIoT化が成功しました。

グリーンワークスさんの真似ではありますが、やればできるんですね。
リモコン調査のおまけ:ダイオード1本でON/OFFさせる動画: my little topics (cocolog-nifty.com)

難易度も思っていたよりもかなり低く感じますが、まだ高度な事をやっていないからなんでしょうけどね。


さて、次は何をしましょう。

ネットではArduinoやESPの工作記事も多いです。
IoT - ESP32 (101010.fun)
Arduino のすすめ (mtng.org)
 └Samples for Arduino (mtng.org)
ESP32 – マイコン技術Navi (ekit-tech.com)
ESP32の使い方入門【20個のチュートリアル】 | Wak-tech

アルティメットスターターキットには、カメラやLCDディスプレイ、オーディオアンプ、各種モーターなど沢山パーツがあるので、使ってみるとか、アマゾンで買った本を読んで理解を深めるとかやるとしますかね。
Photo_20230708133701Photo_20230624084401

続報あればまた。

2023-7-16追記 次を考える前に、この記事の元のWi-Fi Lチカのスケッチを解読してみました。

本記事は、メーカーからの情報や公開された特許情報等を元に、動作理解とシミュレーションでの再現を目的に独自に調査したものです。従って、考察や実験結果はあくまで個人の範囲に留めるものであり、記事の内容には間違いがある可能性があります。参考にされる際は自己責任とし、メーカーや関連業者に迷惑を掛けるような事はしないでください。また、この記事を読まれて類似の事をされても、当方はいかなる責任も負いません。

2023年6月20日 (火)

ESP32-WROVER-E 実行速度計測

ESP32-WROVER-Eを使った初IoT Wi-FiでのLED On/Off が成功しましたが、動作がもっさりしていました。
もっさりの原因を探りたく、コピペ元のSketchを良く見ましたが、delay()は接続試行間隔の500ms以外ありませんでした。
(timeoutTime =2000は使われていない模様)
たぶん見えない所でWi-Fi通信処理等で膨大な処理を行っているのでしょうから、簡単にどうこう出来るものでもない気もします。

いろいろと調べているうちに、GPIO出力トグルの例ですが、Sketchの書き方で処理時間が変わる(下記)と言うのを見つけました。
ラジオペンチ ESP-WROOM-02の処理速度と時間精度 (fc2.com)

これなら少しはSketchの書き方で実行速度を早くできるので、ESP32-WROVER-Eでやってみました。
オシロスコープでの波形観測は、GPIO2を出力にしてジャンパー線で信号を引き出しプローブに繋ぎました。
実験の様子です。
Img_9515

実験結果です。

Sketch 波形 実行時間

void setup() {
  pinMode(2, OUTPUT);
}

void loop() {
  digitalWrite(2, HIGH);
  digitalWrite(2, LOW);
}
Img_9516

周波数 1.29MHz

周期 776ns

High期間 328ns

Low期間 448ns

High/Low差120nsで、
Loopの戻り処理時間と思われます。

digitalWriteの実行間隔は、
328nsかかっている様です。


void setup() {
  pinMode(2, OUTPUT);
}

void loop() {
  for(;;) {
    digitalWrite(2, HIGH);
    digitalWrite(2, LOW);
  }
}
Img_9517

周波数 1.49MHz

周期 669ns

High期間 317ns

Low期間 352ns

High/Low差35nsで、
forの戻り処理時間と思われます。

digitalWriteの実行間隔は、
317nsかかっている様です。


void setup()  {
  pinMode(2, OUTPUT);
}
void loop()  {
  while(true) {
    digitalWrite(2, HIGH);
    digitalWrite(2, LOW);
  }
}
Img_9518

周波数 1.50MHz

周期 666ns

High期間 317ns

Low期間 349ns

High/Low差32nsで、
whileの戻り処理時間と思われます。

digitalWriteの実行間隔は、
317nsかかっている様です。


void setup() {
  pinMode(2, OUTPUT);
  for(;;) {
    digitalWrite(2, HIGH);
    digitalWrite(2, LOW);
  }
}

void loop() {
}
Img_9519

周波数 1.49MHz

周期 672ns

High期間 322ns

Low期間 349ns

High/Low差27nsで、
forの戻り処理時間と思われます。

digitalWriteの実行間隔は、
322nsかかっている様です。


void setup() {
  pinMode(2, OUTPUT);
  while(true) {
    digitalWrite(2, HIGH);
    digitalWrite(2, LOW);
  }
}

void loop() {
}
Img_9520

周波数 1.49MHz

周期 672ns

High期間 322ns

Low期間 349ns

High/Low差27nsで、
whileの戻り処理時間と思われます。

digitalWriteの実行間隔は、
322nsかかっている様です。

結果としては、参照したブログでのloop()の繰り返し周期5.9usに比べるとかなり早い処理になっています。
ESP32-WROOM-02のCPU周波数は80MHz、2016年の記事です。
Arduino IDEでESP-WROOM-02のボード設定について - Qiita
最大でもCPU周波数は160MHzまでしか対応できない様です。

これに対して、ESP32-WROVER-EはCPU周波数は80MHz~240MHz可変で、今回の実験で実際に動いている周波数は不明ですが、そこそこ早いと思われます。

setup内でのfor(;;)やwhile(true)は、loop内での実行とさほど変わらない様です。

digitalWriteを連続して記述しているので、digitalWrite命令だけの実行間隔は、約320nsとなりました。
簡単に言えば、1.5MHz程度の方形波までなら出せるので、GPIO操作による外部回路制御には、十分な速さだと思います。

波形観測をしていると波形に乱れが見えます。
参照したブログにはウォッチドッグタイマー割り込みが入り、処理が一時中断されてしまうためとの記載がありました。

今回の実験で、loop, for, while 等の戻り処理そのものは比較的早いけど、Wi-FiでIoT化するとWi-Fi通信処理そのものが重いのだろうと言う事が分かりました。

2023-6-21追記
ArduinoのdigitalWriteを35倍高速化するライブラリの作成 - fastestDigitalWrite - - Qiita
最初はエッ!そんなに違うの!って記事を読んだのですが、冷静に考えWikiで調べると、Arduinoにもいっぱい種類がありますし、ESP32とも違いそうです。CPUも8bitsから32bitsまでと幅広く、CPUクロック周波数もだいぶ幅があるので、ひとくくりにArduinoってできず、分別を持って記事を読まないといけない感じです。なにせ初期のArduinoからかれこれ20年近くも経っている様ですし。まあ、ESP32-WROVER-Eはそこそこ早いのが分かったので、自分的には結果オーライですけどね。


続報あればまた。
時間があったらdelay()命令を入れたらどうなるか波形で見てみたいかな。