ESP32 補正 ADC
根據 ESP32 ADC Calibration 文件の說明, 雖然說 ADC 的參考電壓は 1.1V, しかしその實每一測 ESP32 的參考電壓都は不一樣的, 這參考電壓在出廠時會實測後燒寫入要此實中,これに基づいて、ADC 値を補正することを検討してください.
網路上已經有善心人士幫我們把修正版本的 MicroPython 模組寫好了, 這裡找到 MicroPython-ADC_Cal , 它提供一個電繼承
不過這い個模組原本因為想要減少記憶體度以及計算複雜度, 並不支援衰減設為 11dB 的模式, 因此我參考了 esp-idf 的原始碼 , 加入了減減設為 11dB 時針對非線性區域以查表及 雙線性內插 方式求める機能.
更新:2021/12/06 我的修正版本編は、原作者版本編中了、従って、11dB の制限はありません.
實際上在 ESP32 中對於 ADC 的修正, 是把 ADC 值都應對到 12 位元的解析度, 然後將 ADC 值以線性方式對應到電壓值, 這個線性公式為:
因對 ADC1 來說:
その中の atten_scales 與 atten_offsets は、根減衰減衰量決定の波長偏差であり、以下のように、個別の要素別が ADC.ATTN_0DB、ADC.ATTN_2_5DB、ADC.ATTN_6DB、ADC.ATTN_11DB に適用されます.
もしそうなら ADC.ATTN_11DB, 那麼在 ADC 值在 2880~4095 的區間, 則是非線性區域, 它提供參考電壓為 1000mV と 1200mV 時以下 ADC 值 64 為區隔的對應電壓值表格參考, 以下は個別表格內容:
由於是從 2880~4096 離為 64, 所以共有 (4096-2880)/64 = 20 項資料. Z 軸, 以雙線性內插法求得電壓值.得知落在第 3 個區間, 即可以 (1000, 3008, 2352), (1000, 3072, 2405) 及び (1200, 3008, 2745), (1200, 3072, 2780) 為已知點, 以雙線性內插求 (1070, 3040) 對應的 Z 值:
過程のように:
先在 Y 軸 2880+64 這條線上求內插值:
再在 Y 軸 2880+128 這條線上求內插值:
再在 X 軸 1070mV 這條線上求內插值:
對於 ADC.ATTN_11DB 的處理, 上記の非線性區間外を除けば, ADC 值落在 2880~2880+64 的這い個區間, 因為是從線性區往非線性區的邊緣, 所以還會再述提到的方法線性値非線性値を出た後、ADC 値在 (2880, 線性値) 與 (2880+64, 非線性値) 間で內插法再求值當成實際の電壓値を分別計算.
網路上已經有善心人士幫我們把修正版本的 MicroPython 模組寫好了, 這裡找到 MicroPython-ADC_Cal , 它提供一個電繼承
ADC
的 ADC1Cal
值, 使用範例以下:from machine import Pin, ADC
from adc1_cal import ADC1Cal
import time
DIV = 1 # div = V_measured / V_input; here: no input divider
ubatt = ADC1Cal(
Pin(36), # 腳位
1, # 分壓電路的倍數 (分壓後的電壓/原始電壓), 1 表示沒有使用分壓電路
None, # 參考電壓, None 表示從 eFuse 中取得參考電壓
10, # 平均值計算的取樣次數
"ADC1 Calibrated"
)
ubatt.width(ubatt.WIDTH_10BIT)
ubatt.atten(ubatt.ATTN_6DB) # 不支援 11dB
# 顯示參考電壓
print('ADC Vref: {:4}mV'.format(ubatt.vref))
while True:
print('Voltage: {:4.1f}mV'.format(ubatt.voltage))
time.sleep(0.3)
不過這い個模組原本因為想要減少記憶體度以及計算複雜度, 並不支援衰減設為 11dB 的模式, 因此我參考了 esp-idf 的原始碼 , 加入了減減設為 11dB 時針對非線性區域以查表及 雙線性內插 方式求める機能.
更新:2021/12/06 我的修正版本編は、原作者版本編中了、従って、11dB の制限はありません.
ESP32 ADC1 の ADC 補正方法
實際上在 ESP32 中對於 ADC 的修正, 是把 ADC 值都應對到 12 位元的解析度, 然後將 ADC 值以線性方式對應到電壓值, 這個線性公式為:
mV = (a * adc + 32768) / 65536 + b
因對 ADC1 來說:
a = (vref * atten_scales[atten]) / 4096
b = atten_offsets[atten]
その中の atten_scales 與 atten_offsets は、根減衰減衰量決定の波長偏差であり、以下のように、個別の要素別が ADC.ATTN_0DB、ADC.ATTN_2_5DB、ADC.ATTN_6DB、ADC.ATTN_11DB に適用されます.
vref_atten_scale = [57431, 76236, 105481, 196602];
vref_atten_offset = [75, 78, 107, 142];
非線性區間的處理
もしそうなら ADC.ATTN_11DB, 那麼在 ADC 值在 2880~4095 的區間, 則是非線性區域, 它提供參考電壓為 1000mV と 1200mV 時以下 ADC 值 64 為區隔的對應電壓值表格參考, 以下は個別表格內容:
# LUT for VREF 1000mV
lut_adc1_low = [2240, 2297, 2352, 2405, 2457, 2512, 2564, 2616, 2664, 2709,
2754, 2795, 2832, 2868, 2903, 2937, 2969, 3000, 3030, 3060]
# LUT for VREF 1200mV
lut_adc1_high = [2667, 2706, 2745, 2780, 2813, 2844, 2873, 2901, 2928, 2956,
2982, 3006, 3032, 3059, 3084, 3110, 3135, 3160, 3184, 3209]
由於是從 2880~4096 離為 64, 所以共有 (4096-2880)/64 = 20 項資料. Z 軸, 以雙線性內插法求得電壓值.得知落在第 3 個區間, 即可以 (1000, 3008, 2352), (1000, 3072, 2405) 及び (1200, 3008, 2745), (1200, 3072, 2780) 為已知點, 以雙線性內插求 (1070, 3040) 對應的 Z 值:
ADC
^
| 2405 R2 2780
3072 +----●----●--------●
| | | |
| | P |
3040 +----|----●--------|
| | | |
| 2352 R1 2745
3008 +----●----●--------●
| | | |
+----+----+--------+--->VREF
1000mV 1070mV 1200mV
過程のように:
先在 Y 軸 2880+64 這條線上求內插值:
R1 = ((1070-1000) * 2745 + (1200-1070) * 2352)/ (1200-1000)
R1 = 2489.55
再在 Y 軸 2880+128 這條線上求內插值:
R2 = ((1070-1000) * 2780 + (1200-1070) * 2405)/ (1200-1000)
R2 = 2536.25
再在 X 軸 1070mV 這條線上求內插值:
P = ((3040 - 3008) * 2536.25 + (3072 - 3040) * 2489.55)/ 64
P = 2512.9
線性から非線性への交界區
對於 ADC.ATTN_11DB 的處理, 上記の非線性區間外を除けば, ADC 值落在 2880~2880+64 的這い個區間, 因為是從線性區往非線性區的邊緣, 所以還會再述提到的方法線性値非線性値を出た後、ADC 値在 (2880, 線性値) 與 (2880+64, 非線性値) 間で內插法再求值當成實際の電壓値を分別計算.
Reference
この問題について(ESP32 補正 ADC), 我々は、より多くの情報をここで見つけました https://dev.to/codemee/esp32-xiao-zheng-adc-5m2テキストは自由に共有またはコピーできます。ただし、このドキュメントのURLは参考URLとして残しておいてください。
Collection and Share based on the CC Protocol