ESP32的ADC可用于测量模拟信号,如温度、湿度和光强度等。ESP32可以将模拟的的电压信号转换为数字信号,然后进行进一步的处理,如输出到显示屏或发送到服务器。往往第一次使用的时候会发现测量的值跟预期的结果不一样。
举个例子
读取39管脚的电压并打印:
from machine import Pin
from machine import ADC
import time
def main():
pin = Pin(39, Pin.IN) #将39管脚作为输入
adc = ADC(pin) #指定为ADC
val = adc.read() #读取值
print(val)
if __name__ == "__main__":
main()
如果39管脚的电压>=950mv,将会打印出4095
。
如果用read_u16()方法读取,将会得到65535
。
出现这样的结果与ESP32的电压测量电路有关。
基准电压和ADC原理
ESP32内部ADC的基准电压通常为 1.1V,不同封装可能会略有不同。ADC在接近基准电压时线性较差(特别是在较高衰减时),其最低测量电压约为 100mV,低于或等于100mV的电压读数为0,也就是说不能用ESP32直接测量低于100mv的电压。
ESP32的ADC模块包括电压参考电路、采样保持电路、比较器、采样电路和SAR(Successive Approximation Register,连续逼近寄存器)。电压参考电路为ADC提供参考电压,采样保持电路可使输入信号在采样周期内保持不变。比较器根据参考电压和输入信号的大小关系输出比较结果。采样电路将放大器输出的信号放大,并将放大器输出的反向电压反馈到比较器以实现反馈控制。SAR将比较器的输出与任意精度DAC中的数字比较器相比较,以实现逐步逼近转换。因此在逐步逼近测量电压的时候,测量精度会降低。为了扩大测量的范围,需要对测量信号进行一定程度的衰减。
输入信号衰减量
由于ADC的基准电压为1.1V所以,ESP32的ADC在无衰减的情况下,能测量的电压范围为100mV至950mV,要读取高于基准电压的电压,就需要使用atten参数指定输入衰减。其有效值(近似线性测量范围)为:
ADC.ATTN_0DB
:无衰减(100mV - 950mV)
ADC.ATTN_2_5DB
:2.5dB 衰减(100mV - 1250mV)
ADC.ATTN_6DB
:6dB 衰减(150mV - 1750mV)
ADC.ATTN_11DB
:11dB 衰减(150mV - 2450mV)
还是刚才的例子
读取39管脚的电压并打印:
from machine import Pin
from machine import ADC
import time
def main():
pin = Pin(39, Pin.IN)
adc = ADC(pin)
adc.atten(ADC.ATTN_11DB) #指定输入信号衰减量
val = adc.read()
print(val)
if __name__ == "__main__":
main()
指定了衰减量后,此时39管脚可测量的电压将会是150mv~2450mv。
注意事项
- 避免将超过0-3.3V电压范围的信号输入到ESP32 ADC,否则可能会损坏该芯片模块。文档中说是3.6V,安全起见还是不要超过3.3V,其实超过2.45V也没意义了,读出来的值都是最大值了。
- 在没有衰减的情况下,1V的输入电压读数就已经是最大值了,也就是adc.read()会读取出来4095,read_u16()会读出来65535,如果测量电压超过950mv,记得衰减一下。
- 在线性范围内,使用 read_u16()并使用常数缩放结果将获得更准确、更一致的结果,也就是要求精度更高的时候可以考虑使用read_u16()。
- ESP32的ADC输入管脚有32~39(ADC Block1)0,2,4,1215,2527(ADC Block2),因为ADC Block2还会用于WiFi,所以,如果WiFi激活的时候使用Block2的引脚会抛出异常。这也就意味着,当使用WiFi模块的时候,只有32~39可以用于ADC。