TTGO T-watchという製品がある.
これはスマートウォッチ「っぽい」もの。中にはESP32マイコンモジュールが入っているので、自分でプログラムを書くことにより様々な機能を追加できる。持ち主のプログラミング能力次第でいくらでも”スマート”になる。

いくつか種類があるようだけど、T-watch2020というやつは、本当のスマートウォッチのようなコンパクトなサイズにまとまっている。タッチパネル液晶画面、振動モーター、加速度センサ、バッテリー、スピーカーなどがついていてこの値段とサイズなら、単品で集めて自分で組むよりお得だと思う。

裏面はただのカバー。Apple watchのように、脈拍を測るセンサはついていない。

プログラムの書き込みや充電は側面にUSBケーブルを繋いで行う。USBはmicro-Bタイプである。隣についているボタンは、まるで腕時計のりゅうずのような形状なので、押す以外に回して入力というのもできるのかな?と思ったができなかった。ただの押しボタンなので回らない。
さて、このウォッチや、本製品に限らずESP32マイコンにプログラムを書き込む際には、マイコンを書き込みモードに入れる必要がある。例えば、下記のような開発ボードにまとめられた製品では、最初から書き込みモードに入るためのボタンが付いていたりする。

左下、USBコネクタの隣にあるのがBOOTボタン。このBOOTというボタンを書き込み時に押しっぱなしにしておくと良い。
また、ものによっては、このBOOTボタンがなくても自動的にボタンが押されたのと同じ状態になるように回路に工夫をされたものもあり、その場合はボタン操作など必要なく、パソコンの書き込みボタンをポチッとクリックするだけでマイコンは自動で書き込みモードに入ってくれる。
T-watch2020にもBOOTボタンは付いていない。ということは、本来ならば何もしなくても自動的に書込み可能なはずだ。

ただ、いくつか購入してみたら、中には書き込みモードに入ることができず、上記のような「A fatal error occurred: Failed to connect to ESP32: Timed out waiting for packet header」というエラーが出る個体があった。上記の画像はVSCodeを使って書き込もうとしたときの画像だが、Arduino IDEを使ったとしてもエラーの内容としては同じものがコンソールに出てくるはず。
このエラーはすごく単純に言うと「マイコンにプログラムを書き込もうと思ってトライしてたけどずっと反応ないからもう諦めました」というもので、要するにマイコンが書き込みモードに入れていないため、いつまで経っても書き込みを受け付けてくれないのが原因で出るエラーである。
というわけで本記事では、回路の手直しをすることなく書き込みモードに入るための方法を記す。力技なのであんまりスマートではないけど、そこはまあ動けばいいやの精神で。
方法1 コンデンサを追加する
開発ボードに関する対策としては、ENピンとGNDの間にコンデンサを並列に追加するといった回路の手直しで解決できたりする。使っている開発ボードに、わざわざ手でBOOTボタンを押さなくてもシリアル通信によるリセットがかかったときに自動でIO0ピンがローになるような遅延回路が組まれているのなら、その遅延回路の働きをコンデンサで少し助けてやることで、自動書き込みができるようになる。

0.1μFを入れたら自動で書き込みモードに入れたという報告もネット上で見かけるが、0.1μFでは足りなかったという声も聞く。僕も0.1μFを入れてみても何も変化がなかった。1μFを入れてみたところ、ボタンを押さなくても自動で書き込みモードに入ることができた。
製品ごとに差があったり、同じ製品でも個体差があるのかもしれないが、今回の1μFというのはかなり大きな(対策としては十分すぎる)値であり、0.47μFとか0.22μFでも大丈夫だったという報告もあるようだ。
0.47~1μFのあたりで適当に手持ちの余ったコンデンサを入れてやればいいと思う。
対策2 IO0ピンを物理的にGNDに繋げる
T-watchのようなコンパクトにまとまった製品の狭いスペースに、さらにコンデンサを追加というのはかなり厳しい。そのため対策1はおすすめできない。
マイコンが書き込みモードに入れないのは結局IO0ピンがローになっていないことが原因だとすると、むりやりこいつをローにしてやれば良い。

まずこんな感じで、ピンヘッダと、針のように細い金属の何かを線でつないではんだ付けする。針のような、というか、僕は本当にまち針を使った。

T-watch2020裏面の蓋を外す。ボタンやUSBポートがある方の下側の角にちょっと隙間が空いているので、ここから爪で持ち上げれば簡単に外れる。写真ではマイナスドライバーを突っ込んでいるが、こんな工具を使って無理やりこじ開ける必要はないくらい蓋の固定は甘い。
蓋を開けるとすぐにバッテリーが見えるので、これを取り外すと下のように回路が見える。

先程作った針とピンヘッダを繋いだやつで、矢印で示した2箇所を繋ぐ。バッテリーのマイナス接点(GND)にピンヘッダで触れ、マイコンのIO0ピンに針先で触れる。
プログラム書き込みを実施中、PC画面のコンソールに「connecting….._____」と表示され始めたら、このようにGNDとIO0ピンを強制的に繋ぐことによって、マイコンを書き込みモードに入れることができる。

ICのサイズが小さすぎてIO0ピンどこだよ、って感じなのでマイクロスコープでの画像を載せる。右から2番めのピン。慎重に針先でこのピンに触れてGNDとショートさせてやる。
書き込みのたびにこれをやれば良いんだけど正直めんどいので、まず最初にこの方法でOTA(Over The Air)のプログラムをさっさと書いてやって、以降はWi-Fi経由で書き込みできる状態にしたほうが楽。
方法3 書き込み速度を変える
プログラムの書き込み速度を遅くするだけで、運が良ければ書き込みモードに入れたりする。

Arduino IDEの場合はここを変える。この記事を読んでいる人ならT-watchの開発環境は既にできていると思うので、このメニューはちゃんと存在しているはず。Upload speedを少し遅くしてやるとうまく行ったりする。115200とかに設定してトライしてみよう。
VScode + Platform IOを使っているなら、platformio.iniにupload_speed という項目を追加し、upload_speed = (設定したい速度)のように書く。下のスクショでは230400にしているが、ここを115200とかの小さい値にして速度を遅くする。確か何も記述していなかったらデフォルトの速度は1152000なんだったかな?

対策2の解説
T-watch2020に使われているESP32マイコンはこれ。

刻印を読むと、「ESP32-DOWDQ6」であることがわかる。このマイコンのデータシートを見ると……

※Espressif社データシートより
書き込みモード、すなわちプログラムをダウンロードするDownload Bootに入るためには、IO0ピン、IO2ピンを両方ゼロ、すなわち電圧ローにする必要がある。ここで、表の左の方を見るとIO2についてはデフォルトでプルダウン、つまり何もしなくても自然と電圧ローになっているので、あとはIO0ピンをGNDにつなげて強制的にローにしてやればよいということになる。
通常起動(SPI Boot)のときは逆にIO0は1、すなわち電圧HIGHでなければならないので、IO0をGNDに落としたいからと言ってはんだづけで繋げるようなことはしてはいけない。
IO2とは逆にIO0はデフォルトでプルアップ、つまり何もしなくても電圧ハイなので、通常起動しようと思ったときにわざわざIO0と3.3Vを繋げるような作業は必要ない。

IO0ピンはここ。右から2番目。
まとめ
・ESP32マイコンを書き込みモードにするためには、IO0, IO2の両方のレベルをローにする必要がある。
・回路上の工夫により、ボタンでIO0をローにしなくてもよいように組んでいる製品もあるが、回路はそうなっているのにちゃんと動作していないのであれば、コンデンサを追加して手助けしてやるとうまくいくことがある。
・どうしても書き込みモードに入れないし回路の修正も厳しいなら、IO0ピンとGNDをどうにかして繋いでやればいい。
・IO0ピンのレベルが原因ではないのに書き込みモードに入れない不具合については、この記事の方法では解決できない。(今のところそんな不具合が出る製品に出会ったことはない)