ESP32 の ADC の精度について,少し詳しく調べてみたので紹介します.
はじめに
以前作成した PM2.5 センサーでは,ESP32 の ADC を使っていますが,計測値のばらつきが大きいのが気になっていました.
ばらつきの要因として ADC の精度の問題があるのではないかと思い,今回計測してみました.
測定環境
計測は,ESP32 を DAC と DMM (KEYSIGHT 34461A) に接続して行いました.
16bit DAC LTC2606 の出力を 0.05V 刻みで変化させながら,ESP32 の ADC と DMM で電圧を測定する形です.
ESP32 ADC は adc1_to_voltage()
関数とadc1_get_raw()
関数を使用し,次の設定で行っています.
- 事前にキャリブレーションを実施
adc1_to_voltage()
を使う場合については,下記を使ってADC のリファレンス電圧を DMM で計測し,esp_adc_cal_get_characteristics()
を呼ぶ際に渡しています.
esp-idf/examples/peripherals/adc at master · espressif/esp-idfEspressif IoT Development Framework. Official development framework for Espressif SoCs. - espressif/esp-idf- 11dB アッテネータを使用
- 0~3.3V までを変換したかったので,次のコードで 11dB のアッテネータを有効化しました.
1adc1_config_channel_atten(TEST_ADC_CH, ADC_ATTEN_11db); - 変換精度は 12bit
-
次のコードで 12bit 変換としました.
1adc1_config_width(ADC_WIDTH_BIT_12);
コード全体は github にあります.
結果
横軸に DMM の読み値,縦軸に ESP32 の変換結果をプロットすると次のようになります.
adc1_to_voltage()
関数を使った場合を CALIB,adc1_get_raw()
関数を使った場合を RAW としています.誤差については,256サンプルを平均した結果もプロットしてあります.縦軸は左側が絶対値,右側が誤差になります.
分かったこと
adc1_to_voltage()
関数の場合については次のような感じです.
- 誤差はおおよそ 30mV 程度
- LUT の効果もあって,チップ全体のスペックと価格から想定していたものよりは悪くないです.
0.1V オーダーの電圧を得る目的では全然問題ありません. - 0V や最大電圧付近では誤差大
- 電圧が低い場合,0.2V までは AD の出力結果は 0.11V 固定でした.また,3.2V 以上では 3.11V となってます.
この付近の電圧を正確に計りたい場合,注意が必要そうです. - 誤差の方向は一定
- 上記の誤差が大きい範囲以外では,ESP32 の出力は常に DMM よりも低い側でした.真値を挟んで上下にばらつくことはありませんでした.誤差の特性として対処しやすそうです.
特性さえ理解しておけば十分使えそうです.
コメント
[…] A/D コンバータを内蔵していない Raspberry Pi や精度に課題がある ESP32 で A/D 変換を行いたいときに頼りになるのが I2C 接続タイプの A/D コンバータ. […]