概要
ESP-WROOM-32で、起動直後におけるGPIO出力レベルがポートごとに異なることを確認し、対処方法について考察した。
背景と目的
先日、ArduinoでESP-WROOM-32をいじっていたところ、GPIOの起動直後における出力レベルがGPIOポートごとに異なるようにみえる現象に遭遇した。具体的には、以下に示すように、ポートの入出力方向の設定後→出力レベルを設定すると、実際に出力されるまでの間HIGHが出力されるポートと、LOWが出力されるポートがあるように見えた。ポートごとの違いが本当にあるのか、チェックしてみる。
void setup () {
pinMode(GPIO_NUM, OUTPUT);
digitalWrite(GPIO_NUM, HIGH);
}
詳細
1. 環境
2.方法
今回は、現象の確認が主な実施事項なので、あまり細かいところに立ち入らず、以下のように、2つのGPIOポートに対して入出力設定と出力レベル設定を行ったときに、出力レベルがどう遷移するか、オシロスコープによって波形を観測する。時間関係が分かりやすいように、2つのポート間に100msecの時間差をつけて観測しやすくしておく。ここで、
- IO5: 常に、もう一方に対して100msec後にHIGHを出力する
- 他のIO: IO5に先行する
- IO34,35,36,39は入力専用なので除く
- 負荷は何もつけない
void setup () { pinMode(他, OUTPUT); pinMode(5, OUTPUT); digitalWrite(他, HIGH); delay(100); digitalWrite(5, HIGH); }
3. 結果
以下の通り、起動後0.5秒間の出力レベルが、GPIOポートによって異なるということが、明らかになった。 青はIO5の出力、赤はもう一方のGPIOの出力である。横軸0秒の時点でリセットボタンを押し、約0.2秒後にリセットボタンを離し、ESP32が再起動させている。その時点から約0.5秒後、IO5がいったんLOWに落ち、0.1秒後にHIGHになることから、LOWに落ちた時点でpinModeが実行されている。
IO5,4,15: HIGHが出力される
IO0: HIGHが出力される(リセット中)
それ以外: LOWが出力される
なお、リセット前の出力レベルに依存しないか確かめるため、LOWを出力した状態でリセットし、起動後LOWを出力する場合についても調べた(赤=IO15)が、以下のように依存しないことが分かった。
4.考察
Arduino-esp32特有の現象なのか、ESP-IDFでも同じなのかといったところは確認できていないが、ひとまず、ポート設定前の挙動を気にせず、ハードウェアを組むと思わぬ動きをするということが予想できる。実際、私はIO5を出力に設定したプログラムで、起動後勝手にHIGH出力がされて意図しない動きになってしまって困った。 対処方法としては、より望ましいレベルが出力されるポートを選択するべきということだ。具体的には、起動直後LOWであってほしい場合には、IO5,15,4は避けるといった感じに。また、ポートに接続される負荷によって出力電圧が変わる。以下は、10kΩの負荷がGNDとの間にぶら下がっている場合だが、0.7V程度までしか上がらない。細かいことはわからないが出力インピーダンスが大きい状態になっているようだ。負荷を利用してLOWになるようにする手もあるだろう。
まとめと今後の課題
ESP-WROOM-32で、起動直後におけるGPIO出力レベルがポートごとに異なることを確認できた。ハード/ソフトを組む際に参考にしたい。