ESP32のADコンバータを調整:ESP-IDFのドライバAPIでキャリブレーションしてみる
前回、初めてADコンバータというものを使ってみました。
とはいってもESP32に内蔵されているものですが、、、
しかし困った事に、かなり実測値とかけ離れたデータが取れてしまいます。
Webで情報収集してみると、入力は3.3Vまでだが実際は3.9Vスケールだとか3.6Vスケールだとか色々出てくるわけですが、、、
確かに前回の数値を3.9Vスケールで計算すると、実測値に近づくは近づくのですが、、
なんだかそういうのは違う気がする。
一応、3.6V、3.9Vのスケールで計算してみました。
3.3V(外部) | 3.3V(ESP32) | 5V(外部) | 5V(ESP32) | |
---|---|---|---|---|
analogRead | 1392 | 1439 | 2205 | 2303 |
計算電圧 | 2.80V | 2.90V | 4.45V | 4.65V |
実測電圧 | 3.22V | 3.27 | 4.77V | 4.91V |
実測差 | 0.42V | 0.38V | 0.32V | 0.26V |
3.6Vスケール | 3.05V | 3.16V | 4.84V | 5.06V |
3.9Vスケール | 3.31V | 3.42V | 5.25V | 5.48V |
釈然としませんね、、、
そんな時はリファレンスを読めとじっちゃんが言ってた
リファレンスによると、チップによってADCが参照する電圧レンジに差があるから、内部基準電圧で補正するAPIを使えとか書いてあるンゴ
ついでにulp(省電力モード)でも使える様にする方法も少し書いてありますたが、今回はひとまずパス。
で、肝心のAPIですが、、
↑これはESP-IDFのAPIですが、Arduino用も恐らくあるだろうと探してみるとありますた。
多分これ。↓
GitHub espressif – arduino-esp32/tools/sdk/include/esp_adc_cal/esp_adc_cal.h
必要そうなメソッドはとりあえず移植されているっぽいので、よく判らないけど使ってみます。
ESP-IDFのexampleを見るに、ADC用の構造体を作って補正APIを紐づける感じなのかな。
これによると、、ADCドライバAPIを使うのに構造体に必要なのは以下の4点っぽいですん
ADCチャンネル番号
APIがサポートするGPIOの範囲は以下の通り
チャンネル番号で指定しなくてはいけないらしく、どのGPIOがどのチャンネルか調べる必要がありそう。
なんかGPIOとADCチャンネルの対応表みたいなのが何処かのヘッダファイルにきっとある
アッテネータの値
アッテネータってなんだ・・・?という感じですが、、
ざっくりと信号を波形はそのまま減衰させる装置が内臓されているらしいですぬ
4段階で使えるそうで、0db、2.5db、6db、11dbだそうな。
どんな感じかよく判らないけど、、
調べてる最中に見かけたものの中に、ADCは0~1.1Vまでの電圧を読み取るからアッテネーターで減衰して使うみたいなのがあった気がする。
と思ったら、公式ドキュメントにありました。
When VDD_A is 3.3V:
ESPRESSIF – ESP-IDF Programming Guide
・0dB attenuaton (ADC_ATTEN_DB_0) gives full-scale voltage 1.1V
・2.5dB attenuation (ADC_ATTEN_DB_2_5) gives full-scale voltage 1.5V
・6dB attenuation (ADC_ATTEN_DB_6) gives full-scale voltage 2.2V
・11dB attenuation (ADC_ATTEN_DB_11) gives full-scale voltage 3.9V (see note below)
https://docs.espressif.com/projects/esp-idf/en/stable/api-reference/peripherals/adc.html#_CPPv425adc1_config_channel_atten14adc1_channel_t11adc_atten_t
減衰を11dBにするとスケールは0~3.9Vで計算されるよ、と。
さらにこんな記述が。
At 11dB attenuation the maximum voltage is limited by VDD_A, not the full scale voltage.
ESPRESSIF – ESP-IDF Programming Guide
・0dB attenuaton (ADC_ATTEN_DB_0) between 100 and 950mV
・2.5dB attenuation (ADC_ATTEN_DB_2_5) between 100 and 1250mV
・6dB attenuation (ADC_ATTEN_DB_6) between 150 to 1750mV
・11dB attenuation (ADC_ATTEN_DB_11) between 150 to 2450mV
For maximum accuracy, use the ADC calibration APIs and measure voltages within these recommended ranges.
https://docs.espressif.com/projects/esp-idf/en/stable/api-reference/peripherals/adc.html#_CPPv425adc1_config_channel_atten14adc1_channel_t11adc_atten_t
ちょっと何言ってるかわかんないですね
つまり11dBの減衰では3.9Vのスケールで計算されるけど、VDD_Aの値に制限される、と。
ちょっと何言ってるかわかんないですね
VDD_Aというのは電源電圧の事らしい。
減衰を11dBにすると、最大3.9Vのスケールでデータを取得できるが、電源電圧が大体3.35V位迄のため、VDD_Aを使って計算しろと、、?
あってます、、、?
そんな、、、
電圧計を作ってるのに、電源電圧で計算しろとか
ちょっと何言ってるか判らないですね・・・
進まないのでひとまず置いておきます。
解像度
9,10,11,12ビットが使えるらしい。
それぞれ入力電圧までのスケールをどのくらいの解像度で取得するか、という設定の様です。
ビット数の値によって、512,1024,2048,4096階調出ると。
電圧計用途のため速度も必要ありませんので、勿論12ビットしか選びませんが、、、
校正値(Vref)
これが多分キモです。
製造チップによって基準が違っているらしく、なんかAPIでこれを調べられるメソッドがある模様。
尚、値が既に入っているものはAPIを使えばわざわざ指定しなくても勝手に使ってくれるらしい。
コマンドラインツールで確認するのがお手軽っぽいのでちょっと打ってみました。
このチップでは1142mVで校正が行われていたという事らしいです。
このタイプのほか、2点校正(150mVと850mV)を行っているチップもあるらしいですが、ひとまず私のは一点校正だったという事で。
さて、、わりと調べるのがありますな、、、
もう疲れたよバドラッジュ
尚、ADCチャンネル番号と、アッテネータの値の定数は以下のヘッダにありました。
GPIOとADCチャンネルの対応を調べるのが面倒ですが、GPIOでチャンネルが判るマクロがある様です。
ざっくりとまとめると、こんな感じかしらん
・ESP-IDFでADコンバータのAPIを利用すれば校正値を利用できる
・校正値は製造チップで3パターンあり、eFuseに書かれている(2地点計測/1地点計測/校正情報なし)
・APIを利用すれば自動的に校正値が有効になる(無い場合はデフォルト値が使われる)
かなり面倒そうな感触ではありますが、ここまで来たらやるしかないンゴねぇ
さてじゃそろそろ使ってみる事にします。
ESP-IDFのAPIでADCを構成する
キャリブレーションを通してADCを利用する際には、ADC1を使うかADC2を使うかで若干の違いがある様でした。
基本的にADC2はwifiを使うとおかしくなる様ですので、ADC1のGPIOピンを利用する方が良いと思います。
全体の工程はこんな感じ
- ADCで使うピン(GPIO)を決定
- 設定値を決定(解像度、減衰値)し、ADCに渡す
- 校正用の構造体インスタンスを作成し、キャリブレーションAPIに設定値とともに構造体を渡す
- getメソッド実行
スケッチにするとそれほど量は多くないです。
下の方のモニタ用キャリブレーション値変更の箇所がやたら長いだけです、、
ADC2も一応使ってはみてますが、、、
キャリブレーションの変更は面倒なのでADC1の分しか書いてませんが、、
シリアルモニタで文字を送ると値を変更できる様にしています。
1-4:アッテネータの減衰変更
A,S:係数 +100, -100
D,F:オフセット +5, -5
W:解像度 9bit~12bit 押す度にトグル
Z:初期化時の値にリセット
P:構造体の値表示
初期化せずに構造体の値を直接いじってしまっています。
ホントはだめなんでしょうけれど、、
とりあえずこんな感じでADC1のGPIO32ピン とADC2のGPIO27ピン、GNDを繋ぎます。

3.3Vと5Vも取り出せる様にボードに挿しておいてますが、ESP32側には刺しません。(あとで)
回路図は前回のものにADC2のピンGPIO27を足しただけです。

それでは動かしてみます。

おお?
なんかソレっぽい値になってるじゃないですか。
少し実測値よりも多く出ている様に思いますが、前回に比べればかなり誤差の範囲かもしか。
さてではキャリブレーションの値を確認しますと、、

なんかADC1とADC2では値が違うんですね
オフセットはADC1の方が大きいですが、係数はADC2の方が大きく設定されている様です。
この数値をいじれば、ある程度はこちらでキャリブレーションできるかもしれませぬね。
さてじゃ数値を取って実測値との差を確認しましょうか
テスターを、、、
・・・・ジジッ!!
もくもく・・もくもく・・・
いい香りがしてきたンゴねぇorz

なんか真ん中のチップが少し艶やかな様な

やっちまってますんorz
接触が悪く電圧も安定しなかった電源君ですが、3.3V と 5V を両方出せて便利でしたのに、、、
この三端子レギュレータだけ交換したら直らないかしらん
仕方がないので電源はESP32から取る事に。
リファレンスが減ってしまい参考にならないかもしれませんが
3.3V(実測 3.27V) | ADC1 | ADC2 |
---|---|---|
Raw | 1467-1471 | 1526-1530 |
RawVoltage | 1370-1372 mV | 1418-1421 mV |
Voltage | 3.425-3.430 V | 3.545-3.555 V |
5V(実測 4.91V) | ADC1 | ADC2 |
---|---|---|
Raw | 2275-2278 | 2337-2342 |
RawVoltage | 2045-2048 mV | 2097-2101 mV |
Voltage | 5.113-5.120 V | 5.242-5.245 V |
実測との差が0.2V前後となり、一番上の3.6Vスケール、3.9Vスケールの丁度間くらいの数値に。
ADC2は係数が大きいだけあって少し高い数値が出ますね。
元の3.3Vスケールで計算するよりはAPIの係数をいじった方が実測に近い値が出るのではないかと思います。
思うだけですが、、、
目標であったリポバッテリーの2セルを測定するにはもっと広い電圧を測れる様に作り変えないといけませんが、色々調べてみて釈然としない部分がだいぶスッキリしてきました。
ひとまずは少し高い電圧で出るものとして取り扱えばいいのかな。
ESP32の内臓ADCの基本的な使い方が判ったので、きっと後々役に立つに違いない
たぶん、、、いつか、、
次回がありましたら、もう少し高い電圧まで測定できる様にして、実測値との差を確認していこうかなと思います。
ディスカッション
コメント一覧
まだ、コメントがありません