ESP32のGPIO入力について

概要

ESP32の入力に関してかんたんにまとめてみました。digitalRead()とanalogRead()、touchRead()が対象です。厳密にはGPIO入力ではありませんが、hallRead()とtemperatureRead()も紹介します。

上記、出力についてと共通している部分は説明を簡略化してあります。

動作電圧について

ESP32は3.0Vから3.6Vまでの電圧で動作させることができます。本解説では3.3Vで動かした場合の数値で説明を行います。

ピンの接続について

入力を行う場合には、ピンの接続について確認を行う必要があります。基本的には何も接続されていない場合の入力値については信用できません。

これは、内部のセンサーに静電気のような電荷が残っていることがあり、未接続の場合には残っている電荷の値を読み取っていることになります。

とくにESP32の場合にはピンに複数の機能を割り当てられるマトリックス機能があり、ピンの裏側でセレクターで、センサーとピンを動的に切り替えながら読み取っているので、未接続のピンの場合には一つ前に読み取ったピンの電荷が残っている場合があります。

入力の種類について

ESP32では以下の5種類の入力があります。

デジタル入力 digitalRead()

一番標準的なGPIOの入力です。データシートによると3.3Vで動かした場合には、LOWはLow-level input voltageがVDD-0.3から0.25×VDDとあり、-0.3Vから0.825Vまでの入力をLOWと判定します。

HIGHはHigh-level input voltageが0.75×VDDからVDD+0.3とあり、2.475Vから3.6VまでがHIGHと判定されます。

VDDは最大3.6Vまでなので、High-level input voltageはVDD+0.3の3.9Vまでがデータシート上の入力最大値となります。そのため、5Vの信号をESP32に接続した場合にはデータシート上は、規定外の電圧となります。

一般的に3.3V駆動のマイコンに5V信号を入力すると、かんたんに壊れる場合が多いので注意してください。ESP32はデータシート上は保証していませんが、5V信号を入力しても、すぐに壊れることはないのですが、データシート上では保証していないことを理解して利用してください。

繰り返しますが、ESP32と同じ感覚で、他の3.3Vマイコンに5V信号を渡すとかんたんに壊れるので注意してください。STM32などはピンごとに5V入力をしてもよいかが規定されていますので、5Vトレラントかどうかを確認してから5Vを入力するか、レベルコンバーターなどを利用して3.3Vに変換してから接続してください。

ESP32でも5V入力は基本的には避けたほうが好ましいです。

また、実際の判定は3.3Vの半分である1.65Vより低い電圧か、高い電圧かでLOWとHIGHを判定していますが、データシート上は上下25%の範囲のみ保証しているので、中途半端な電圧を入力すると、ノイズの影響を受けやすいのでやめましょう。

5VのマイコンにESP32の3.3V信号を入力した場合には、5Vの50%である2.5V以上なのでHIGHで入力可能ですが、5Vの75%は3.75Vのため、多くのマイコンでは保証外の信号電圧になると思います。

アナログ入力 analogRead()

アナログ入力は、ADCとも呼ばれ、電圧を測定します。ESP32は標準だと0から4095までの値が取得できます。

注意したいのが、VDDを基準電圧としますので3.3Vで動かしている場合と、3.0Vで動かしている場合で取得した値の電圧が異なります。

電圧 = VDD / 4096 * 取得値

上記のような計算を行うことで電圧が求められます。一般的には3.3Vの場合決め打ちでも問題ありませんが、省電力のため3.0Vなどに電圧を下げた場合には注意しましょう。

また、ESP32内蔵のADCはそれほど精度が高くありません。内部的に補正がある程度されているみたいですが、低い電圧のときと高い電圧のときで測定精度に差がでています。精度が必要な用途であれば、I2C接続の電圧計などのほうが適しています。

ただし、通常用途であれば内蔵ADCで問題がでることは少ないと思います。

内部的はADC1とADC2の2つADCモジュールが内蔵されており、無線利用時には内部でADC2を利用してしまうため、ADC1しか使えなくなってしまいます。

無線を利用したいときにADC2に接続されているピンからアナログ入力を行う場合には注意して利用してください。基本的には無線を利用する前にアナログ入力を行い、その後に無線を利用してから、ディープスリープかリセットを行って再起動します。

無線を利用する前のレジスタの値を保存しておいて、無線停止後に元に戻すことでADC2が再度使えるようになりますが、多くの場合には再起動をして、クリーンな環境に戻すか、ADC1のピンを利用したほうが好ましいと思います。

また、ADCの内部的にはVDDを1V程度に減衰して測定しています。0Vから1Vまでなどのようにより低い電圧を高精度で測定する場合には、減衰器の設定を変えることで精度が上がりますが、多くの場合外部のADCを利用したほうが好ましいです。

複数回測定して、平均値を取得するなどの設定もありますが、通常用途の場合にはデフォルトの状態で利用して、移動平均などの適切なフィルタを利用したほうが精度があがりやすいはずです。

タッチ入力 touchRead()

タッチ入力は、静電容量を利用したタッチセンサーです。ピンに一瞬電荷をチャージして、直後にピンの電荷を確認することでタッチの確認をしています。これは人が触れた場合などに、ピンの電荷が人に移動することで、タッチを判定しています。

入力値は電荷の値なので、絶対値ではなくアナログ値での取得になります。タッチセンサーを引き回す方法により、取得値がかわってくるので、実際に実験をして触っていない場合の値と、触った場合の値を確認してから実装する必要があります。

とくにジャンパワイヤで実験していたものを、基板作成してタッチエリアを作成した場合など条件が異なると、取得値も異なります。さらに、実際にためすとGPIO32とGPIO33のタッチセンサーが逆に認識されているようですので、テストしてから基板などの作成をしてください。

タッチセンサーとADCは別の回路のため、無線を利用している場合でもADC2に接続されているピンを利用することができます。

ホールセンサー hallRead()

ESP32に内蔵されている磁力センサーです。ESP32に磁石を近づけると値が小さくなるセンサーです。

対象物に磁石をつけて、接近センサーなどとして利用することが可能です。ただしM5StickCなどの、内部に磁石を内蔵しているマイコンの場合には反応が悪くなります。

内部温度センサー temperatureRead()

ESP32の内部温度のセンサーです。気温ではなく、内部の温度のため高負荷でESP32を利用した場合には上昇していきます。

長時間安定動作をさせたい場合などは、定期的に内部温度を測定し、熱暴走を起こしていないのかを確認する用途には利用できます。

気温を測定することは難しいですので、その場合にはI2C接続などの温度計を利用してください。

ピンモード

Arduinoではすべてのピンを利用前に初期化する必要があります。初期化し忘れても動くことがおおいですが、ピンによって起動時に設定されているモードが違うので、すべてのピンを初期化してから使うようにしたほうが安全です。

特に、アナログ入力は初期化しないと、analogRead()を呼び出しても、デジタル入力相当の0(LOW)か4095(HIGH)のどちらかしか取得できないピンがありますので、忘れずに初期化してください。

INPUT

pinMode(PIN, INPUT);

一番標準的なデジタル入力です。ピンに接続されている電圧に応じてLOWかHIGHが返却されます。

未接続のピンの場合、もどり値が不定ですのでLOWかHIGHがランダムに戻ってくる形になります。未接続なのでLOWが戻ってくるわけではないので注意してください。

INPUT_PULLUP

pinMode(PIN, INPUT_PULLUP);

VDD(3.3V)に抵抗経由でプルアップされているデジタル入力です。何も接続していない場合には常に3.3VですのでHIGHが入力されます。ピンの先にスイッチなどを接続して、スイッチオンでGNDに接続する形にすると電圧が0VになるのでLOWが戻ってきます。

未接続の場合でも常にHIGHが戻ってきます。スイッチなどを接続した場合にONでLOW、OFFでHIGHと信号が逆転したように見えますが、ノイズに強い方式になります。

I2Cなどの通信も内部で自動的にINPUT_PULLUPに設定されており、信号をLOWに落とすことで、通信を行っています。

入力用のモードですが、プルアップは出力を内部で利用しているので、入力専用ピンでは利用できないので注意してください。

INPUT_PULLDOWN

pinMode(PIN, INPUT_PULLDOWN);

GND(0V)に抵抗経由でプルダウンされているデジタル入力です。何も接続していない場合には常に0VですのでLOWが入力されます。ピンの先にスイッチなどを接続して、スイッチオンでVCCに接続する形にすると電圧が3.3VになるのでHIGHが戻ってきます。

未接続の場合でも常にLOWが戻ってきます。スイッチなどを接続した場合でもONでHIGH、OFFでLOWとわかりやすい状態で、ノイズにも強い方式になります。

INPUT_PULLUPとINPUT_PULLDOWNは、未接続状態でも抵抗経由でどこかに接続されているため、信号が安定しています。両方とも基本的な効果は同じなのですが、歴史的経緯によりINPUT_PULLUPがよく利用されています。

値を直接指定して、PULLUPとPULLDOWNを同時に指定すると、1.65Vでプルアップ?された状態になるらしいですが、良い子は真似をしないでください。

入力用のモードですが、プルダウンは出力を内部で利用しているので、入力専用ピンでは利用できないので注意してください。

ANALOG

pinMode(PIN, ANALOG);

アナログ入力を行う端子です。ADCに接続されているピンでのみ利用可能です。

ピンによっては初期化しないでanalogRead()を呼び出すと0(LOW)か4095(HIGH)しか返却しないので注意してください。

ピン一覧

GPIO種類ADCINPUTPULLUPPULLDOWNANALOG
GPIO0I/OADC2
GPIO1I/O×
GPIO2I/OADC2
GPIO3I/O×
GPIO4I/OADC2
GPIO5I/O×
GPIO6I/O×
GPIO7I/O×
GPIO8I/O×
GPIO9I/O×
GPIO10I/O×
GPIO11I/O×
GPIO12I/OADC2
GPIO13I/OADC2
GPIO14I/OADC2
GPIO15I/OADC2
GPIO16I/O×
GPIO17I/O×
GPIO18I/O×
GPIO19I/O×
GPIO21I/O×
GPIO22I/O×
GPIO23I/O×
GPIO24I/OADC2
GPIO25I/OADC2
GPIO26I/OADC2
GPIO27I/OADC2
GPIO32I/OADC1
GPIO33I/OADC1
GPIO34IADC1××
GPIO35IADC1××
GPIO36IADC1××
GPIO37IADC1××
GPIO38IADC1××
GPIO39IADC1××

INPUTはすべてのピンで利用できます。ただし利用しているボードにより、用途が決まっているピンがありますので、自由に利用できるピンから選んでください。

また、多くの場合にはGPIO0は3.3Vに外部からプルアップされています。そのためアナログ入力をしても3.3VかGNDかの入力しかできません。

INPUT_PULLUPとINPUT_PULLDOWNは内部で出力の機能を利用しているので、入力専用の端子であるGPIO34以降では利用できませんので注意してください。

また、ANALOGは利用できるピンがかなり限定されていますので注意してください。特に無線を利用する場合にはADC2に接続しているピンが利用できなくなります。

まとめ

アナログ入力は内部パラメーターがかなり多いですが、あまり利用はしません。興味がある人は調べてみるとより深く知れると思います。

プルアップとプルダウンはちょっとわかりにくいため、検索して他のサイトで回路図付きの解説を確認したほうがよいと思います。(余裕があれば回路図今度書きます、、、)

コメント

  1. 匿名 より:

    編集お疲れ様です、参考になります。GPIO 27が抜けているそうです。