ESP32の「自動書き込み機能には、2つのトランジスタをクロス接続した特別な回路が必要」と思っていませんか?
結論から言うと、ファームウェアの自動書き込みを行うだけなら、特別な回路は必要ありません。 DTR / RTS信号を直接 ESP32 に接続するだけで動作します。
しかし、なぜ市販の開発ボードには必ずあの回路が載っているのでしょうか?
本記事では、以下のステップで「自動書き込みの仕組み」と「あの回路の役割」を解き明かしていきます。
- 実証: DTR / RTSの直結だけで自動書き込みができることを確認
- 深掘り: なぜ直結だけで「ダウンロードモード」に遷移できるのか?
- 納得: それでも「あの特別な回路」が実装されている理由
「自動書き込みしたい」「自作回路を簡略化したい」という方の参考になれば幸いです。
はじめに
-
ESP起動ログ(ESP32-WROOM-32E)
SPIブート(通常ブート)ets Jul 29 2019 12:21:46 rst:0x1 (POWERON_RESET),boot:0x13 (SPI_FAST_FLASH_BOOT) configsip: 0, SPIWP:0xee clk_drv:0x00,q_drv:0x00,d_drv:0x00,cs0_drv:0x00,hd_drv:0x00,wp_drv:0x00 mode:DIO, clock div:2 load:0x3fff0030,len:4200 load:0x40078000,len:15236 load:0x40080400,len:3332 entry 0x400805a8ダウンロードブートets Jul 29 2019 12:21:46 rst:0x1 (POWERON_RESET),boot:0x3 (DOWNLOAD_BOOT(UART0/UART1/SDIO_REI_REO_V2)) waiting for download
ESP32 は UART でファームウェアを書き込むブートモードがあります。ダウンロードブートです。このモードに入るためには、ESP32 の IO0ピン をLOにしたまま ENピンを LO→HIにします。
ENピンをLO→HIにするタイミングで、
IO0ピンがLOであればダウンロードブート、HIであればSPIブートとなる。
IO0ピンはマイコン内部でプルアップされているため、何も配線しなければ HI 。
ところで、
自動で書き込む機能と言えば、トランジスタ(MOSFET) 2個をクロス接続した 次の回路図が有名です。実際、この回路図は、ESP32-DevKitC v4 で使われているものです。
ところが、自動書き込みするだけならば、この回路は 必要無い ということです。
1. 自動書き込みはesptoolが制御
ESP32にファームウェアを書き込むときに使うコマンドであるesptoolの公式ページに、次の説明があります。
意訳すると、
USBシリアル変換チップの DTR および RTS信号を ESP32 の IO0 および ENピンに接続しておくと、esptool は、DTR および RTS信号を制御することで、ESP32 を自動的にリセットし、ファームウェアダウンロードモードで起動します。
先に説明したような 特別な回路が必要との記述はありません。
そこで、CH340C を使ったUSBシリアル変換モジュールを使って試してみます。
CH340C 以外でも、DTR / RTS信号が取り出せるシリアル変換ICであれば、何でもよいです。
2. DTR / RTSのみで自動書き込みはできるのか?
DTR / RTSのみ(特別な回路不要)で、自動書き込みできるのか を検証します。
・ 使用機材
-
ESP32 ESP32-WROOM-32E
-
USBシリアル
USB-TTL変換モジュール [U2TL340CR]

このモジュールのピンソケットには、DTRはありますが、RTSがありません。そこで、CH340Cの RTS(14番)ピンに直接ワイヤをハンダ付けして取り出します。
次の通り配線します。USBシリアル ESP32 RTS EN (CHIP_PU) DTR GPIO0 (IO0) TXD RXD RXD TXD VCC 3v3 GND GND
・ 結果
DTR / RTSのみ(特別な回路不要)で、自動書き込みができることを 確認できました。では、冒頭で紹介した あの回路 は、何のためにあるのでしょうか??
3. あの回路は何のために必要か
DTR および RTS信号が ESP32 の IO0 および ENピンに接続されていることを前提に、esptoolコマンドは、DTR および RTS信号を制御することで、ESP32 をダウンロードモードで起動します。
これは、UARTプロトコルで規定した RTS / CTS、DTR / DSR によるハードウェアフロー制御とは直接関係ありません。あくまで、自動書き込みは esptoolコマンドの機能であって、他のシリアルモニタ系のコマンドでは このような制御はありません。
逆に、UARTプロトコルによるハードウェア制御に基づいて 各信号が制御されるため、DTR / RTS が ESP32 の IO0 / EN に接続されていると、悪影響を受けます。DTR および RTS信号がLOのため、ESP32がリセットされたまま起動しないという 現象です。
これを回避するために、あの回路 の出番となります。右下に真理値表がありましたが、
DTR / RTS が LO / LO、HI / HI の場合に、この回路は、EN / IO0 を HI / HI に維持することで、影響を打ち消しているのです。
一般のUSBシリアルモジュールには、このような特別な回路は実装されていませんので、DTR / RTS を IO0 / EN に接続していると、自動書き込みは出来ますが、通常のシリアルモニタとして使用するときに不都合が起きてしまいます。
一方、ESP32ダウンローダーと言われるUSBシリアルモジュールや USBシリアル搭載のDEVボードには、この回路が実装されているため、自動書き込みが出来て、かつ、シリアルモニタとしても使用できる。
ということです。
esptoolの公式ページの次の説明(An additional circuitry)が、この回路の存在を示しています。
DTR / RTS を 非アクティブにできる シリアルモニタプログラムにて この問題を回避する方法を、@laddgeさんがこちらの記事で紹介されています。
また、74thさんの記事では、シリアルモニタで見ようとするとRTS(=EN)ピンとDTR(=IO0)ピンがLOWのままになってESP32が起動しないという問題が示されていたが、自分が使っているPlatformIOのpio device monitorというコマンドでは、RTS, DTRそれぞれを明示的にinactiveにすることができるため、その問題を回避できた。
確かに、screenコマンドでは ESP32がリセットされ動作しませんでした。
screen <シリアルポート> 115200
一方、pio device monitorのベースとなっている pyserial(miniterm)にオプション--dtr=0 --rts=0を指定すれば、問題なく動作します。
python -m serial.tools.miniterm --dtr=0 --rts=0 <シリアルポート> 115200
もちろん、pio device monitorにオプション--rts 0 --dtr 0を指定しても、問題なく動作します。
pio device monitor --port <シリアルポート> --baud 115200 --rts 0 --dtr 0
ただし、minitermもpio device monitorも、コマンド起動時にESP32をリセットしてしまう点に注意が必要です。もし、リセットされては困るタイミングで使用する場合は、やはり、RTS/DTRを外す必要があります。
なお、引用した @laddgeさんの記事で紹介されている CH340X は、
CH340シリーズの中で、DTRとRTS信号が取れる最小ICで便利ですが、自分が調べた限りでは、このICは あの回路相当までは内蔵されていないようです。この点、もしかすると少し認識違いがあるのかもしれません。
4. なぜ、DTR / RTS信号のみでダウンロードブートにできるのか?
DTR / RTS は負論理(Active LOW signals) です。
- active : 0v (GND) LO
- inactive : 3v3 (VCC) HI
2項で試したときに、CH340C の信号をロジックアナライザで可視化しました。
esptoolコマンドが シリアルポートをオープンした直後の 0s では、RTS / DTR ともに HI (inactive) です。esptoolコマンドは、
まず ① RTS を LO (active) にして およそ100ms維持します。
次に ② RTS を HI (inactive) にすると共に、DTR を LO (active) にして およそ60ms維持します。その後 ③ DTR を HI (inactive) にします。
この信号をみると、EN LO, IO0 HI → EN HI, IO0 LO にするだけで、これで どうしてダウンロードモードに入るのか不思議ですね。
ここで重要なのが、ENピンとGNDの間の コンデンサ(キャパシタ)の存在です。
- ① RTS を LO にすると、このコンデンサは放電します
- ② RTS を HI にすると、このコンデンサの充電時間だけ、ENピンは わずかに遅延して HI になります。ENピンが HI になったタイミングでは、DTR(=IO0)は LO です
このコンデンサにより、『 EN をLO→HIになるタイミングに、IO0 がLOである状態が発生し』 ダウンロードブートで起動することになります。
RC遅延回路として、ESP32のデータシートで推奨されているため、大抵のDEVモジュールは、(10KΩプルアップ抵抗と)0.1μFのコンデンサが実装されています。
今回使用した ピッチ変換基板も同様です。
もし、このコンデンサがない場合、自動書き込みできるのか ギリギリな気がします。
(100%失敗するのかどうなのかは、未検証のため不明)
DTR / RTS を接続せず、手動でダウンロードモードにして ファームウェアを書き込んだ場合は、"Hard resetting via RTS pin..." が出力されていても、実際にはESP32はリセットされていません。よって、手動でリセットする必要があります。
疑問点
esptoolの公式ページの次の説明に 疑問が残ります。
(すべてのEspressif製ボードは搭載している、)この回路 を実装した場合、リセット回路を確実に動作させるには、ENピンとGNDの間に、追加のキャパシタ(1μF〜10μF)が必要。
しかし、「ESP32-DevKitC v4」の回路図 から、追加のキャパシタの存在を確認できませんでした。
ENピンを追っても、RC遅延回路のC9(0.1μF)と、RESET(SW2)スイッチと並列に入っているC14(0.1μF)しか見当たりません。
DevKitC v4等の実機では0.1µF程度しか載っていないが、使用するPCやUSBケーブル、シリアルチップの相性によってはタイミングがシビアになり、自動書き込みに失敗する場合がある。そのため、公式ガイドやトラブルシューティングでは、より確実な動作のために1µF以上の追加が推奨されているようです。
▶︎なぜ「コンデンサ不足」で失敗するのか
自動書き込みは、esptoolが DTR/RTS信号を操作して「ENをLO→HIにする瞬間に IO0 がLOである」という状態を作り出すことで機能します。しかし、以下の要因でこのタイミングが狂うことがあります。
- 信号の立ち上がりが速すぎる:コンデンサの容量が小さいと、EN信号の電圧が瞬時に立ち上がってしまいます。PC側の信号制御のわずかな遅れにより、ENが
HIになった瞬間にまだIO0がLOになりきっていないと、通常モードで起動してしまう - PCや変換チップの個体差:USBシリアル変換チップや、PCのOS、ドライバによって、DTR/RTS信号が切り替わるタイミングに数ミリ秒単位のバラツキが生じる
- ノイズの影響:書き込み開始時の突入電流などで電源電圧がわずかに変動し、リセット動作が不安定になることがある
おわりに
これまで、漠然と理解していましたが、検証も含めて 一通りの説明は できたかと思います。自分も誤解していた部分がクリアになりました。
もし、誤りや説明不足等があれば コメントで指摘していただけると幸いです。
2026.3.1 追記
DTR/RTS信号が取り出せる、おすすめのUSBシリアル変換モジュールをご紹介します。
- おすすめポイント;
- DTR/RTS信号が用意されている
- 小型で USB Type-C である
- 安価(執筆時点で税込500円)
ピンヘッダーをハンダ付けする前に、VIOを3.3Vに変更する必要があります(下記赤印)。(デフォルトは5Vになっているので、ESP32やRP2040が壊れます。)
|
|
以上












