akino が 2025年07月08日07時49分10秒 に編集
「Wi-Fi編」へのリンク設定
本文の変更
# はじめに 2024年SPRESENSE活用コンテストでの「[HDRカメラでメーターからAI自動検針](https://elchika.com/article/16635721-4b63-43e5-a090-cbfb16d96b3e/)」では、[Wi-Fiアドオンボード](https://idy-design.com/product/is110b.html)のモニター提供の選に漏れたため、急遽手持ちの「[W5500-Ether (クレイン電子)](https://crane-elec.co.jp/products/vol-20/) 」を使い有線LANを使用しました。しかし、屋外での使用を前提とした構想のためWi-Fi化は必須でした。 購入も考えましたが、画像データを送信するだけですし安上がりなので、ESP-WROOM-02(以下、ESP8266と記す)を使いATコマンドの勉強を兼ねて自作してみました。 # 実現させる機能 - SpresenseからESP8266のATコマンドを使いWi-Fiによるデータの送受を行う - ESP8266の電源(+3.3V)は、EXT_VDD(4V)からLDOを介して供給する - 待機時には、deepsleepまたはLDOの出力オフにより省電力化する - 装着状態のまま、Spresenseを介してESP8266への書込みを可能にする # 使用部品 | 製品名 | 品番 | メーカー | |:---|:---|:---| |ESP-WROOM-02ピッチ変換キット|[AE-ESP-WROOM-02-1100MIL](https://akizukidenshi.com/catalog/g/g113646/)|秋月電子| |低飽和型レギュレーター 3.3V500mA|[NJM2884U1-33](https://akizukidenshi.com/catalog/g/g110673/)|JRC (秋月電子)| |抵抗内蔵型トランジスタ|[RN1402](https://www.digikey.jp/ja/products/detail/toshiba-semiconductor-and-storage/RN1402-LF/5640257) / [RN2402](https://www.digikey.jp/ja/products/detail/toshiba-semiconductor-and-storage/RN2402-LF/7809537)|東芝(DigiKey)| |スイッチングダイオード|[1SS355](https://www.digikey.jp/ja/products/base-product/rohm-semiconductor/846/1SS355/29863)|Rohm(DigiKey)| | ピンヘッダ | | | | ユニバーサル基板 | | | # 回路構成 全体の回路図です。  ++現状、SpresenseのD20はLDO(NJM2884U1-33)のCONTROL入力に接続し、ESP8266への電源供給をオンオフしています。 未接続のQ1はUART download modeでの起動用です。詳細は後述の「Spresense経由でESP8266の書込み」のところに書きます。 RST-IO16間のダイオードを入れたのは、deepsleep機能の他に外部からもRSTを制御するためです。RST-IO16間を直結の場合、通常動作中のESP8266のIO16はH出力状態であり、外部からRSTをLレベルには引ききれません。これを回避しています。++ ## レベル変換回路 SpresenseのメインボードのIOは1.8V、ESP8266のIOは3.3Vですので、このレベル変換を行います。BSS138 などのMOSFETを使用した事例が多いですが、手持ちに適当なものがなかったので、SpresenseのTXはトランジスタを2段で、ESP8266のTXDは抵抗分割で変換しました。通信速度が115200bps程度であれば問題なさそうです。 **SpresenseのTX → ESP8266のRXD** 下図が回路とその動作波形です。PNP+NPNの(10k,10kの抵抗入り)トランジスタで変換しています。遅延を心配しましたが、R6, R7を1k程度とすれば問題なさそうです。 1段目をNPNではなくPNPとしたのは、TXがHi-ZまたはH時(待機時や非通信時、実際はこの状態が多い)には、1、2段目ともオフにし無駄な電流を流さないようにするためです。  **ESP8266のTXD → SpresenseのRX** 下図が回路とその動作波形です。R9,R10を10k,10kの抵抗分割で1.8Vに合わせました。R8(1k)でTXDをプルアップした理由は下記します。  ++ここで一点、はまりました。 TXDに単純に分割抵抗をぶら下げると、なぜかシリアル通信ができません。ESP8266の起動時にTXDが’L’(分割抵抗により)にされていると、何か違うモードに入ってしまうようです。このときオシロでTXDを確認するとHi-Zになっているようでした。TXDを分割(抵抗)に影響の少ない1k程度でプルアップすることで回避できました。 確かに仕様書には「UART0_TXD, transmit end in UART download, floating or pull up;」と書かれていますが、その詳細な説明はないようです。++ ## ESP8266への電源供給 Spresenseメインボードの3.3V(JP1-10)は、CXD5247からの供給で「[最大出力100mA程度](https://developer.sony.com/spresense/development-guides/hw_docs_ja#_spresense%E3%83%9C%E3%83%BC%E3%83%89%E3%81%AB%E5%A4%96%E9%83%A8%E6%8E%A5%E7%B6%9A%E6%A9%9F%E5%99%A8%E3%82%92%E6%8E%A5%E7%B6%9A%E3%81%99%E3%82%8B%E5%A0%B4%E5%90%88%E3%81%AE%E9%9B%BB%E6%BA%90%E4%BE%9B%E7%B5%A6%E3%81%AB%E9%96%A2%E3%81%97%E3%81%A6)」とあります。ここからESP8266に電源供給するとWi-Fi通信時に電力不足(ピーク値は300mA 程度)となるようでダメでした。そこで EXT_VDD(JP2-3、4.0V)からLDOを介して電源供給しました。 使用したLDOの [NJM2884U1-33](https://akizukidenshi.com/catalog/g/g110673/) はESP8266を電池駆動(3本)するときによく使用していました。実績では入力電圧が3.0VくらいまでWi-Fi通信が可能です。 今回改めてその仕様書を見て、CONTROL端子で出力をオンオフできることに気づきました。これをSpresenseから制御し待機時に出力オフとすれば、deepsleepとするより低消費電力化できます。 「[HDRカメラでメーターからAI自動検針](https://elchika.com/article/16635721-4b63-43e5-a090-cbfb16d96b3e/)」では、1回/日に起動し数10秒程度で動作完となるので、圧倒的に待機時間の方が長くなります。従って、待機時のわずかな省電力化であっても、電池交換なしの連続稼働時間の延長に効果大と考えました。 ++余談ですが、ここで少し気になることがありました。 SONYさんのサイト内の「[Equipping Spresense with WiFi connectivity](https://developer.sony.com/ja/spresense/tutorials-sample-projects/spresense-tutorials/how-to-equip-spresense-with-wifi-connectivity)」では下図のようにメインボードの3.3V(JP1-10)からESP8266の電源供給をしています。モジュールはESP-01ですが、ピーク電流は同様かと思いますので不思議です。 また、TX, RXが直結となっています。H/Lレベルの閾値の差は何とかなるかもしれませんが、SpresenseのIOの最大絶対定格電圧は 「[コネクタ ピンリスト (xlsx)](https://github.com/sonydevworld/spresense-hw-design-files/raw/master/Pin/Spresense_pin_function_ja.xlsx)」に「+2.5V」とあるので問題ではないかと思いました。SpresenseのIOは「トレラント」ではないと思います。すぐに壊れるようなことはないとは思いますが「最大絶対定格」というのは、いかなるときでも、たとえ瞬時であっても超えてはいけないと教えられてきました。 さらに Youtubeの「[Spresense | 5. LCDにグラフィックを表示する【ソニー公式】](https://youtu.be/3a2VrQBmCiU?list=PLzgPwCLYLGPOau4b4_2NPjKUVa1l1OhK3)」の最後のほうでも「スペック割れではあるがメインボードに直結も可能」と話されていました。閾値のこととして話されていますが、最大絶対定格について疑問を感じました。 ++ # ATモード用ファームウェアの書込み 使用したESP8266は2017年頃の購入品でフラッシュは4MB品のようでした。Arduinoで使用していたので「ATコマンド」が使えるようにファームウェアの書き戻しを行いました。 githubから、書込みツールは「[flash_download_tools_v3.6.6 ](https://github.com/Makerfabs/esp_tool/blob/master/flash_download_tools_v3.6.6.zip)」、ファームウェアは「 [ESP8266_NONOS_SDK-2.2.1](https://github.com/espressif/ESP8266_NONOS_SDK/tree/v2.2.1)」をダウンロードし、下図の設定で書込みました。  ++ここでもハマりました。上記では、あっさりと書いてますが随分と手こずりました。 最初、ツールを最新の「flash_download_tool_3.9.8_3 」で行いました。しかし書込みはできているようですが、ATモードでの起動メッセージや、ATコマンドへの応答が少し変でした。 ネット情報では旧版での事例が多かったので、ツール、ファームウェアともいくつかを試しながら「4MB品の設定情報があり正常に動作するなるべく新しいもの」を探して、上記にたどり着きました。++ # アドオンボード化 レベル変換回路他の仕様が固まったので、アドオンボード化を行いました。 「[ESP-WROOM-02ピッチ変換キット](https://akizukidenshi.com/catalog/g/g113646/)」をピンヘッダーでユニバーサル基板に直付けし、このユニバーサル基板に周辺回路とメインボードへの装着用ピンヘッダーを実装しました。下図が完成したボードの写真です。(老眼に鞭打って実装・配線しました!) メイン基板のアンテナ上部には何も置くなと「[Spresenseの注記](https://developer.sony.com/spresense/development-guides/hw_docs_ja#_spresense_%E3%83%A1%E3%82%A4%E3%83%B3%E3%83%9C%E3%83%BC%E3%83%89%E4%B8%8A%E3%81%AEgnss%E7%94%A8%E3%81%AE%E3%82%AA%E3%83%B3%E3%83%9C%E3%83%BC%E3%83%89%E3%83%81%E3%83%83%E3%83%97%E3%82%A2%E3%83%B3%E3%83%86%E3%83%8A%E3%82%92%E4%BD%BF%E7%94%A8%E3%81%99%E3%82%8B%E5%A0%B4%E5%90%88%E3%81%AE%E6%B3%A8%E6%84%8F%E7%82%B9)」にありましたので、このような位置関係としESP8266のアンテナ部はカメラ用コネクタ側に向くようにしました。 メインボードへの挿抜の負荷を少しでも減らすため接続は最低限の5ピン×2としました。Serial2を使う場合、RTS,CTS(D28,D27)端子をGPIOとして使えないのはもったいないですね。  # 動作確認 ## ESP8266のATモードの初期設定 実際の使用では、ESP8266はWi-Fiの初期設定済みで起動することを前提としました。 この初期設定を行うためののソースコードが下記です。setup()後半部の ’sendATCommand()' で適宜設定を行います。「AT+CWAUTOCONN=1」により、ESP8266は起動すると設定に従い自動的にWi-Fiアクセスポイントに接続に行きます。 ATコマンドについては、Espressif の [AT Instruction Set](https://www.espressif.com/sites/default/files/documentation/4a-esp8266_at_instruction_set_en.pdf)、[AT Command Examples](https://www.espressif.com/sites/default/files/documentation/4b-esp8266_at_command_examples_en.pdf) 、[AT Command Set](https://espressif-docs.readthedocs-hosted.com/projects/esp-at/en/release-v2.2.0.0_esp32c3/AT_Command_Set/index.html) などを参考にしました。 ```arduino: #include <Arduino.h> #define RSTN 21 //ESP8266のresetピン(RST)へNPN-TrNPN-Trを介して接続 #define CONT 20 //NJM2885U1-33(LDO)の出力制御、'H'でオン(B/Bボード時はD19で検討) String cmd ="AT+CWJAP_DEF=\"SSID\",\"PASSWORD\""; //接続するWi-FiアクセスポイントのSSID,PASSWORD void sendATCommand(String command, unsigned long timeout) { String response = ""; Serial2.println(command); // ATコマンドを送信 unsigned long start = millis(); while (millis() - start < timeout) { while (Serial2.available()) { char c = Serial2.read(); response += c; } } Serial.println(response); //レスポンスを表示 } void setup() { pinMode(RSTN, OUTPUT); pinMode(CONT, OUTPUT); digitalWrite(RSTN, LOW); digitalWrite(CONT, HIGH); //LDOの出力オン Serial.begin(BAUDRATE); while(!Serial); Serial.println("\nwifi_esp8266_config v1.0 start"); Serial.println("HW_Reset ESP8266, and wait..."); digitalWrite(RSTN, HIGH); delay(1); //ESP8266をreset digitalWrite(RSTN, LOW); delay(4000); //ESP8266起動待ち Serial2.begin(115200); //ESP8266に接続 sendATCommand("AT+GMR", 1000); //バージョン確認 sendATCommand("AT+CWMODE_DEF=1", 1000); //stationモード sendATCommand("AT+CWDHCP_DEF=1,1", 1000); //stationモード、DHCP有効 sendATCommand("AT+CWLAP", 10000); //接続可能なAPをリスト sendATCommand(cmd, 10000); //Wi-Fi アクセスポイントに接続 sendATCommand("AT+CIPSTA_CUR?", 1000); //割当られたIPアドレスの確認 sendATCommand("AT+CIFSR", 1000); //IPアドレス、MACアドレス確認 sendATCommand("AT+CWAUTOCONN=1", 1000); //Auto-Connects to the AP の設定 delay(1000); Serial.println("now, start AT mode"); } void loop() { //Spresense-ESP8266間で相互に送受信 if (Serial.available()) Serial2.write(Serial.read()); if (Serial2.available()) Serial.write(Serial2.read()); } ``` ## Spresense経由でESP8266の書込み 頻繁にこのアドオンボードのESP8266を書き換える可能性は低いのですが、そのためにボードを挿抜するのは避けたいので、アドオン状態のままESP8266に書込むことを検討しました。 RSTとIO0を、SpresenseのIOでトランジスタを介して操作すればESP8266を UART Download mode として起動することは容易ですが、この後の書込みのプロトコルをSpresenseに実装するのは(自分には)難しそうに思えました。 しかし、考えてみるとSpresenseがESP8266へのゲートウェイ的に動作していれば、つまり相互に通信を垂れ流すように送受信できていれば書込めるのではないかと思い試しました。結果、実にあっさりと書込みができました。(当たり前じゃないか、と言われそうですが) 起動後はシリアル通信の待ち状態になっているので、Arduino IDE のESP8266に対するCOMポートの指定をSpresenseのCOMポートとし書込みます。Reset Method は nodemcu, ck のどちらでも書込めました。 また、ATモードのファームウェアの書込みツールでも問題なく書込みができました。 なお、先の回路図では、D20をLDOのCONTROL端子に接続していますが、書込み機能を使う場合は、D20をトランジスタ(Q1)を介してIO0に接続します。 ソースコードを下記します。 変数のload が ’1か2' で UART Download mode、'0' で Flash Boot modeで起動します。 ```arduino: #include <Arduino.h> #define BAUDRATE (115200) #define RSTN 21 //ESP8266のresetピン(RST)へNPNを介して接続 #define IO0 20 //ESP8266のIO0ピンへNPNを介して接続、書込みモードで起動用 const uint8_t load = 2; //ESP8266を UART Download mode で起動、1=nodemcuライク, 2=手動ライク、0=通常モード void setup() { pinMode(RSTN, OUTPUT); pinMode(IO0, OUTPUT); digitalWrite(RSTN, LOW); digitalWrite(IO0, LOW); Serial.begin(BAUDRATE); while(!Serial); if (load == 1) { // ESP8266書込みモード(nodemcuの実測タイミングに合わせた) digitalWrite(RSTN, HIGH); //ESP8266をreset delay(10); digitalWrite(RSTN, LOW); delayMicroseconds(200); digitalWrite(IO0, HIGH); delay(60); digitalWrite(IO0, LOW); } else if (load == 2) { // ESP8266書込みモード(一般的な手動によるシーケンス) digitalWrite(IO0, HIGH); delay(100); digitalWrite(RSTN, HIGH); delay(100); digitalWrite(RSTN, LOW); delay(100); digitalWrite(IO0, LOW); } else { // 通常動作モード digitalWrite(RSTN, HIGH); delay(10); digitalWrite(RSTN, LOW); } //delay(4000); Serial2.begin(BAUDRATE); if (load) { Serial.println("UART Download mode set " + String(load)); } else { Serial.println("Flash Boot mode"); } void loop() { if (Serial.available()) Serial2.write(Serial.read()); if (Serial2.available()) Serial.write(Serial2.read()); } ``` ++ソースコードにある「nodemcuの実測タイミングに合わせた」のところですが、RTS, DTRを使うnodemcuのタイミングをオシロで調べると、このようになっていました。IO0がLとなる前にRSTがHに戻っています。「IO0をLにしてresetする」に反しますが、resetが外れて実際にIO0をチェックするタイミングがこの辺だということなのでしょう。++ ## ATモードでのWi-Fi通信の実例
コンテスト応募の「 HDRカメラでメーターからAI自動検針」のGoogle Driveへの画像送信のところをこのWi-Fiアドオンボードで行うように変更したものをを新たにその「 Wi-Fi編」として投稿しました。
コンテスト応募の「 HDRカメラでメーターからAI自動検針」のGoogle Driveへの画像送信のところをこのWi-Fiアドオンボードで行うように変更したものをを新たにその「 [Wi-Fi編](https://elchika.com/article/e88e9945-2f1d-4792-8d5e-bf67df6034ff/)」として投稿しました。
# あとがき ちょっと手こずったところもありましたが、何とか完成できました。ATコマンドの勉強もできました。 ほぼ完成したところで、トラ技7月号「ソニーの超小型コンピュータ Spresense」の発売を知り、早速購入しました。「Wi-FiモジュールESP8266」の記事もあります。ソース・コードの掲載もあるので読み込んでみたいと思っています。