Arduino IDEでESP8266(ESP-WROOM-02)をプログラムするときESPr-DeveloperやNodeMCUの開発ボードを使用すると書込みボタンをクリックするとESP8266はプログラムモード自動遷移して手間なくプログラムを書き込むことができます。これは「ESP-WROOM-02へのプログラム書込み」で調べたようにSerialポートの制御線号DTRとRTSを用いて遷移させています。
FTDIのUSB-Serialケーブルやその互換のUSB-Serialモジュールを用いる場合は制御信号はDTRしか出力されておらず手動操作でのプログラムモードへの遷移が必要でした。そこで,DTR信号のみでESP8266をプログラムモードに自動遷移させることができないか考えて回路を製作しました。
2017.02.09
- 回路と制御シーケンスを見直して回路と制御プログラム改編をしました。
DTR信号1本だけでESPr-DeveloperやNodeMCUと同等の自動遷移制御を行います。
初期版ではシリアルモニタ等で通信ポートをオープンしたときESP8266にリセットがかかるアクションがありましたが不要なリセットがかからないように制御プログラムを改編しました。 - プログラムモードのインジケータLEDの点灯方式を変更しました。
1.方針
- USB-SerialのDTR信号を見てプログラム書込みだったらRSTとIO0信号を制御してESP8266をプログラムモードに遷移させる。
- Arduino IDEでシリアルモニタ/シリアルプロッタや別の通信ソフトでポートをオープンしたときにDTR信号の変化によるプログラムモードのへの遷移を抑止する。(抑止しないと通信ができない)
- プッシュボタンスイッチを設けて
長押しだったらプログラムモードに遷移させる。
短押しだったらリセットをする。
この機能はDTRやRTS制御信号が引き出されていないUSB-Serialモジュール(秋月のコレなど)を使っているとき簡単操作でプログラムモードにしたい要求から考えました。(実はこの機能のついでにDTRでの自動遷移を付け加えたのです) - ATtiny13を用いて1〜3を実装する。
2.事前調査
- ARduino IDEの「書込みボタン」をクリックした時のRTS,DTR信号の変化の様子を観測した。
黄色信号がRTS,水色信号がDTR。
- ARduino IDEの「書込みボタン」をクリックしてからのDTR信号の変化は70mSec以内に終了する。
- 70mSec以上DTRがLOWになっている場合はArduino IDEでシリアルモニタ/シリアルプロッタが動いていると判断できる。
3.信号生成
- DTRのHIGH→LOW変化に同期してプログラムモードに遷移させる制御信号を作ればよい。
下図はATtiny13で生成した信号。黄色信号IO0,水色信号RST - DTRがLOWになってから70mSec以上経過した後,DTRの状態を見る(実際は安全時間をとって125mSec後)
HIGHの場合はプログラムモードに遷移させる。
LOWの場合はシリアルモニタ等なので何もしない。 - スイッチの長押し(500mSec以上)でプログラムモードに遷移させる。
- スイッチの短押し(500mSec未満)ではリセットかけ通常モードにする。
4.回路
- IO0に接続されているLED(PRG)はプログラムモードのインジケータです。
- IO0をLOWにしてリセットをかけるとプログラムモードに遷移しIO0からHIGHが出力されるので
- このHIGH信号でLED(PRG)を点灯させています。
- 使用するLEDはVF2.1V(20mA)程度のものを使用します。
VFの小さいLEDを使用するとIO0が常時LOWとなりESP-WROOM-02が動作しません。 - ダイオードD1はATtiny13-PB3からLED(PRG)へ電流が流れるのを阻止しするために挿入しています。
- スイッチ長押しによるプログラムモードへの遷移を確かめるためにLEDインジケータは必須です。
5.動作検証の様子
6.プログラム
とりあえず素のプログラムを掲載します。そのうちコメントを付けます。
ARduino IDE + ATtiny13開発環境でビルドします。
//ESP8266 ISP Reset controller by kimio kosaka //ATtiny13 ピンの割付 (0 == PB0) #define DTR 0 #define SW 2 #define ISP 3 #define RESET 4 void setup() { //デジタルピンのセットアップ pinMode(DTR, INPUT_PULLUP); pinMode(SW, INPUT_PULLUP); pinMode(ISP, OUTPUT); pinMode(RESET, OUTPUT); //実行モードにする digitalWrite(RESET, HIGH); digitalWrite(ISP, HIGH); digitalWrite(RESET, LOW); delay(10); digitalWrite(RESET, HIGH); } //プログラムモードに遷移させる void do_isp() { digitalWrite(ISP, LOW); delay(2); digitalWrite(RESET, LOW); delay(2); digitalWrite(RESET, HIGH); delay(50); digitalWrite(ISP, HIGH); } //SW押下をチェックする void chk_sw() { if (digitalRead(SW) == LOW) { //SW押下(LOW)をチェック int n = 0; digitalWrite(RESET, LOW); digitalWrite(ISP, HIGH); while (n < 50) { //SW==LOWでdelay(10)を50回ループ(500mS) delay(10); if (digitalRead(SW) == HIGH) n = 51; //ループ中にSW==HIGHになったらループ脱出 n++; } if (digitalRead(SW) == LOW) { //500mSループ脱出してもなおSW==LOWならば do_isp(); //プログラムモードに遷移させる while (digitalRead(SW) == LOW);//SWが押下されている間は何もしないでループ delay(10); } else { digitalWrite(RESET, HIGH); //SW==HIGHときはリセットだけ } } } //DTR信号をチェック void chk_dtr() { if (digitalRead(DTR) == LOW) { //DTR==LOWならば delay(25); //25mS待つ if (digitalRead(DTR) == LOW) { //さらにDTR==LOWならば delay(100); //100mS待ち if (digitalRead(DTR) == HIGH) { //DTR==HIGHのときは do_isp(); //プログラムモードに遷移させる。 } else { //そうでない(DTR==LOW)のときは while (digitalRead(DTR) == LOW) chk_sw(); //なにもしないで,DTR==LOWの間SW押下をチェック delay(10); } } } } void loop() { digitalWrite(RESET, HIGH);//念のためループ毎にリセット信号ををHIGHに保つ chk_sw(); //SW押下チェック chk_dtr(); //DTR信号チェック }
プログラムには何の工夫もありません。DTR,SWの変化をみてシーケンス制御しているだけです。ビルドに用いたATtiny13(bitDuino13)の定義はタイマー割込み非対応なのでdelay関数を多用して適切なタイミングを図っています。
5.その他
- この回路でISPとRESETのタイミングを改編すればLPC1114等のARMマイコンのプログラムモード自動遷移も可能です。
6.参考
コンデンサとダイオードの簡単な回路でプログラムモードへの自動遷移が可能ですよと次のページを教えていただきました。
DTR信号をIO0に加えると同時にDTR信号を微分回路を通して得たワンパルスをRSTに加える仕掛けです。
微分パルスを利用した回路はプログラム書き込み以外でシリアル通信ポートをオープンするときDTRをLOWに落とすとプログラムモードに遷移し手動リセットをかけるまでプログラムモードのままという弱点があるのでDTR信号を切り離す物理的スイッチを設けて置いたほうが良いですね。
来歴
update 2017.02.09 プログラム変更:ISP(IO0)信号の挙動変更
update 2017.02.09 回路変更:プログラムモード表示LEDの接続箇所
update 2017.02.08 記述バグ修正, 参考リンクの追加
upload 2017.02.08 kimio kosaka