3、ADC数据采集基础:ADC分辨率与采样率、单端与差分输入、参考电压选择、常见ADC芯片(ADS1115、MCP3421)配置

好,咱们进入第三讲。ADC,模数转换器,说白了就是把模拟世界的连续信号,翻译成单片机能懂的0和1。这个翻译过程,质量高低,直接决定了你采集到的电导率数据是「准」还是「废」。

我刚开始做传感器项目时,踩过一个坑:买了个高精度的传感器,结果配了个低分辨率的ADC,数据跳得像心电图。后来才明白,ADC才是整个采集链路的「咽喉」。今天咱们就把这个咽喉部位彻底打通。

3.1 ADC分辨率与采样率:两个核心指标

先聊分辨率。分辨率决定了ADC能分辨多小的电压变化。比如一个12位的ADC,参考电压是5V,那它能分辨的最小电压就是5V / 2^12 ≈ 1.22mV。16位的呢?5V / 2^16 ≈ 76μV。你想想看,电导率传感器的输出信号往往很微弱,分辨率不够,数据直接「糊」掉了。

我个人习惯:做水质监测这种高精度场景,至少16位起步。12位?嗯,测个电位器还行,测电导率就有点勉强了。

再说采样率。采样率就是ADC每秒能转换多少次。这里有个铁律——奈奎斯特定理:采样率至少要是信号最高频率的两倍。但实际项目中,我一般会留3-5倍的余量。

核心公式:

分辨率(LSB)= Vref / 2^N

其中N是ADC位数,Vref是参考电压

我的经验:电导率传感器输出变化很慢,属于低频信号。采样率不用太高,100-200SPS(每秒采样次数)就足够了。但分辨率一定要高,16位是底线,24位更安心。

3.2 单端与差分输入:选对模式很重要

这个问题,我在项目里被问过无数次。单端输入,就是信号一端接ADC输入,另一端接地。差分输入呢?两个输入端分别接信号的正和负,ADC测量的是两者之间的差值。

什么时候用单端?信号源离ADC很近,地线干净,没有共模干扰。比如板子上的电位器分压。

什么时候用差分?信号线比较长,或者现场有电机、变频器等干扰源。电导率传感器的探头信号,我强烈建议用差分输入。为什么?因为差分能抑制共模噪声。我曾经在一个工厂现场调试,单端输入时数据跳得飞起,换成差分后,稳如老狗。

避坑指南:我曾经犯过一个低级错误——差分输入的两个引脚接反了。结果读出来的数据全是负值,还以为是传感器坏了。记住:差分输入有极性,正负不能搞反。

3.3 参考电压选择:精度从这里开始

参考电压,就是ADC用来做比较的「尺子」。这把尺子不准,后面所有数据都是错的。

参考电压有两种常见来源:

  • 内部参考:芯片自带的,方便但精度一般,温漂大
  • 外部参考:用专门的基准电压芯片,比如REF3033、ADR421,精度高、温漂小

我个人的建议:做产品级项目,别省那几块钱。用外部参考电压芯片。ADS1115内部有2.048V参考,精度还行,但如果你追求极致稳定,外挂一个REF3033,效果立竿见影。

关键点:参考电压必须小于或等于ADC的供电电压。比如ADS1115供电5V,参考电压可以选2.048V、4.096V等。参考电压越低,分辨率越高,但测量范围也越小。这是个取舍。

3.4 常见ADC芯片配置:ADS1115与MCP3421

这两款芯片,是我在电导率项目里用得最多的。一个16位,一个18位,各有千秋。

3.4.1 ADS1115:16位、I2C接口、4通道

ADS1115,TI家的经典款。16位分辨率,I2C接口,最多4个单端通道或2个差分通道。价格便宜,资料多,新手友好。

配置代码示例(MicroPython):

import machine
import time

# I2C初始化
i2c = machine.I2C(0, scl=machine.Pin(22), sda=machine.Pin(21), freq=400000)

# ADS1115地址:0x48(ADDR接GND)
ADS1115_ADDR = 0x48

# 配置寄存器:0x01
# 配置值:0xC283
# 位15: 开始转换(1)
# 位14-12: 输入选择(100 = AIN0对GND单端)
# 位11-9: 增益(001 = ±4.096V)
# 位8: 连续转换模式(0)
# 位7-5: 数据速率(100 = 1600SPS)
config = 0xC283

# 写入配置
i2c.writeto_mem(ADS1115_ADDR, 0x01, bytes([(config >> 8) & 0xFF, config & 0xFF]))
time.sleep(0.1)

# 读取转换结果
data = i2c.readfrom_mem(ADS1115_ADDR, 0x00, 2)
raw = (data[0] << 8) | data[1]

# 转换为电压(参考电压4.096V,16位)
voltage = raw * 4.096 / 32768.0
print("电压值:{:.3f} V".format(voltage))

注意:ADS1115的增益设置决定了测量范围。增益=1时范围±4.096V,增益=16时范围±0.256V。电导率传感器输出一般在0-2V,我习惯用增益=2(±2.048V),分辨率刚好。

3.4.2 MCP3421:18位、I2C接口、单通道

MCP3421,Microchip家的。18位分辨率,比ADS1115高两倍。但只有单通道,而且价格贵一点。适合对精度要求极高的场景。

配置代码示例(MicroPython):

import machine
import time

i2c = machine.I2C(0, scl=machine.Pin(22), sda=machine.Pin(21), freq=400000)

# MCP3421地址:0x68(默认)
MCP3421_ADDR = 0x68

# 配置寄存器:0x10
# 位7: 连续转换(1)
# 位6-5: 通道(00 = 通道1)
# 位4-3: 采样率(00 = 240SPS,18位)
# 位2-1: 增益(00 = 1x)
config = 0x10

# 写入配置
i2c.writeto(MCP3421_ADDR, bytes([config]))
time.sleep(0.1)

# 读取3字节数据(18位)
data = i2c.readfrom(MCP3421_ADDR, 3)
raw = (data[0] << 10) | (data[1] << 2) | (data[2] >> 6)

# 处理符号位(18位有符号数)
if raw & 0x20000:
    raw -= 0x40000

# 转换为电压(参考电压2.048V,18位)
voltage = raw * 2.048 / 131072.0
print("电压值:{:.6f} V".format(voltage))

避坑指南:MCP3421的18位数据是补码格式,最高位是符号位。我曾经直接按无符号数处理,结果负电压读成了几十万的大数。记得做符号扩展。

3.5 实战对比:ADS1115 vs MCP3421

参数 ADS1115 MCP3421
分辨率 16位 18位
通道数 4(单端)/ 2(差分) 1
接口 I2C I2C
最大采样率 860SPS 240SPS(18位)
参考电压 内部/外部可选 内部2.048V
价格 约5元 约15元
适用场景 多通道、中等精度 单通道、高精度

我个人怎么选?如果项目需要同时测多个传感器,比如温度、电导率、pH,我会用ADS1115,4个通道刚好够用。如果只测一个电导率传感器,而且对精度有执念,那就上MCP3421,18位的数据,看着就舒服。

总结一下:

  • 分辨率决定精度,采样率决定速度。电导率场景,分辨率优先。
  • 差分输入抗干扰,单端输入省通道。有干扰就选差分。
  • 参考电压是ADC的「尺子」,别省那几块钱。
  • ADS1115适合多通道中等精度,MCP3421适合单通道高精度。

嗯,这一讲的内容就到这里。下一讲咱们会把这些ADC芯片真正接到电导率传感器上,看看实际数据长什么样。到时候我会分享一个我踩过的坑——关于信号调理的,保证让你少走弯路。