1. 工业与HVAC温度测量方案的整体设计思路
工业现场和HVAC系统里的温度测量,跟实验室里拿个万用表测室温完全是两码事。前者面对的是长线缆、强电磁干扰、宽温区、多通道轮询、还要保证长期漂移可控。我做过好几个暖通机房和工业烘箱的项目,踩过的坑基本都集中在信号链前端和ADC配置上。这次要聊的这套方案,核心是ADS122U04IPWR这颗24位ΔΣ ADC搭配STM32F303VE做主控,针对RTD(铂电阻)温度测量做一套能落地的工业级采集。
先说这颗ADS122U04IPWR的定位。它是TI的24位、4通道、带PGA的低功耗ΔΣ ADC,内部集成2%精度的基准源、振荡器、温度传感器,还有一路激励电流源(IDAC),UART兼容的SPI接口。为什么选它而不是随便找个ADS1115或者MAX31865?因为ADS1115只有16位,分辨率在0.1℃级别就顶天了,而工业RTD测量经常要求0.01℃甚至更高;MAX31865虽然专为PT100/PT1000设计,但通道数少、灵活性差,遇到需要同时测多路RTD加热电偶的场合就捉襟见肘。ADS122U04的4路差分输入配合内部多路复用器,可以轮询多路RTD,还能用IDAC做比例式测量,把激励电流源的漂移从测量结果里消掉,这是它最值钱的地方。
STM32F303VE这边,它是Cortex-M4内核带FPU,72MHz主频,关键是它有两组独立的ADC、多个定时器、丰富的SPI和UART。选它不是因为算力多强,而是它的模拟外设和定时器资源刚好能配合ADS122U04做同步采样和激励切换。比如用TIM触发ADC采样、用SPI DMA搬运数据,CPU基本不用管,留给算法做滤波和线性化。另外F303VE的封装是LQFP100,引脚够多,工业板子上要挂隔离、继电器、RS485都不缺IO。
整套方案的信号链是这样的:RTD传感器接成三线制或四线制,ADS122U04的IDAC输出激励电流流过RTD,产生的电压经过PGA放大后由ΔΣ调制器转换成数字码,STM32通过SPI读回来,再用Callendar-Van Dusen公式换算成温度。中间还要处理基准电压的选择、PGA增益的配置、滤波器 settling time、工频抑制这些细节。下面我按模块拆开讲,把每个环节的取舍和参数计算都摊开。
注意:ADS122U04IPWR是TSSOP-16封装,手工焊接难度中等,建议用热风枪加助焊膏,或者直接买转接板。我第一次焊的时候引脚连锡,导致SPI通信时好时坏,排查了半天才发现是焊接问题。
2. 核心细节解析与实操要点
2.1 RTD接线方式的选择与激励电流计算
RTD测量里,接线方式直接决定精度上限。两线制最简单,但导线电阻会直接叠加到测量结果里,每米铜线大概0.02Ω,100米就是2Ω,对PT100来说相当于5℃误差,工业现场根本不能用。三线制能补偿导线电阻,前提是两根电流线电阻相等,实际布线时尽量用同规格同长度的线,补偿效果能到90%以上。四线制最准,电流线和电压线分开,导线电阻完全不影响,但多一根线,成本高一点。我的经验是:HVAC风管温度这种精度要求0.5℃的场合,三线制足够;工业反应釜或者计量级应用,老老实实上四线制。
激励电流的选择有个权衡。ADS122U04的IDAC可以配置成10μA到1.5mA,步进10μA。电流越大,RTD上的电压越大,信噪比越好,但自热效应也越严重。PT100的自热系数大概0.2℃/mW,如果流过1mA,PT100上功耗是0.1mW,自热误差0.02℃,可以接受。但如果用PT1000,同样1mA功耗是1mW,自热误差0.2℃,就有点大了。所以我的习惯是:PT100用500μA到1mA,PT1000用100μA到250μA。具体算一下:PT100在0℃时100Ω,1mA激励产生100mV,ADS122U04的PGA设成8倍,就是800mV,接近但不超过基准电压2.048V,留了余量。如果温度到850℃,PT100阻值约390Ω,1mA产生390mV,PGA 8倍就是3.12V,超了。所以高温场合要么降PGA增益,要么降激励电流。我一般用PGA=4,激励500μA,这样850℃时390Ω×500μA=195mV,×4=780mV,安全。
2.2 基准电压与比例式测量
ADS122U04内部有个2.048V基准,初始精度0.1%,温漂5ppm/℃。如果直接用它做绝对测量,基准的温漂会直接变成测量误差。5ppm/℃×50℃温变=250ppm,对PT100来说0.025Ω,约0.065℃。看起来不大,但加上IDAC的温漂、PGA的增益误差,累积起来就不好看了。所以工业上更推荐比例式测量:用一个精密电阻(比如2.49kΩ 0.1% 10ppm/℃)串联在IDAC回路里,ADC测量这个电阻上的电压作为基准,同时测量RTD上的电压。这样IDAC的漂移、基准的漂移在比值里抵消掉,只剩下电阻本身的精度和温漂。代价是需要一路差分输入专门测参考电阻,ADS122U04的4通道刚好够用:两路测RTD,一路测参考电阻,一路备用。
具体接法:IDAC从AIN0流出,经过RTD到AIN1,再经过参考电阻到地。ADC测量AIN0-AIN1的差分电压(RTD)和AIN2-AIN3的差分电压(参考电阻)。STM32读回两个码值,温度计算时用比值。这里要注意,参考电阻的走线要开尔文连接,否则引脚和焊点的电阻会引入误差。我一般用0805或1206封装的金属膜电阻,放在ADC旁边,走线尽量短。
2.3 PGA增益与共模电压范围
ADS122U04的PGA是差分输入,增益1到128。增益越大,小信号分辨越好,但共模电压范围会收窄。数据手册里有个公式:共模电压必须在AVSS+0.2V到AVDD-0.2V之间,而且跟增益有关。比如增益128时,共模范围只有(AVDD-AVSS)/2±0.1V左右。RTD三线制接法时,共模电压大概在激励电流×RTD阻值的一半,比如500μA×100Ω/2=25mV,加上参考电阻上的压降,可能到几百mV。如果AVDD=3.3V,AVSS=0V,共模范围是0.2V到3.1V,几百mV没问题。但如果用双极性供电,比如AVDD=2.5V,AVSS=-2.5V,共模范围就宽了。我一般用单极性3.3V供电,共模电压控制在1.65V附近最稳,所以会在RTD下端加一个偏置电阻,把共模抬到中间。这个偏置电阻跟参考电阻并联,会影响比值,计算时要考虑进去,或者用缓冲器隔离。
2.4 滤波器配置与工频抑制
ΔΣ ADC的滤波器配置直接影响噪声和响应速度。ADS122U04有Sinc1、Sinc2、Sinc3、Sinc4和FIR几种滤波模式。Sinc3是默认的,对50Hz和60Hz都有不错的抑制,但settling time是3个转换周期。如果数据率设20SPS,settling time就是150ms,多通道轮询时每路要等150ms,4路就是600ms,对于温度这种慢变量可以接受。但如果要快速响应,比如HVAC里测送风温度做PID控制,20SPS可能不够,可以设到100SPS,但工频抑制就差了。我的做法是:温度测量用20SPS加Sinc3,同时开启内部50/60Hz同步抑制;如果现场干扰特别大,用FIR滤波器,它的阻带衰减更好,但settling time更长。实测下来,20SPS Sinc3在变频器旁边也能稳住0.01℃的波动。
提示:ADS122U04的转换数据率跟滤波器模式是绑定的,改数据率会自动改滤波器系数。配置寄存器时先写数据率,再写滤波器模式,顺序反了可能不生效。
3. 实操过程与核心环节实现
3.1 硬件连接与PCB布局要点
先列一下关键连接。ADS122U04IPWR的引脚:AVDD接3.3V,AVSS接地,DVDD接3.3V,DGND接地。SPI接口:CS接STM32的SPI1_NSS(PA4),SCLK接PA5,MISO接PA6,MOSI接PA7。DRDY接PA0做中断,用来通知STM32数据就绪。IDAC输出接AIN0,RTD接在AIN0和AIN1之间,参考电阻接在AIN1和地之间,同时AIN2接参考电阻上端,AIN3接地。这样AIN0-AIN1测RTD,AIN2-AIN3测参考电阻。注意AIN1同时是RTD下端和参考电阻上端,走线要短且粗。
PCB布局有几个坑。第一,模拟地和数字地要分开,在ADC下方单点连接。第二,IDAC走线要远离SPI时钟线,否则时钟串扰会调制激励电流。第三,参考电阻和RTD的走线要对称,差分对尽量等长。第四,AVDD的退耦电容用1μF加100nF,放在引脚旁边。第五,如果现场有长线缆,在ADC输入端加RC滤波,比如1kΩ加100nF,截止频率1.6kHz,能滤掉高频干扰,但电阻会跟IDAC回路串联,影响激励电流精度,所以电阻要用0.1%的,或者放在电压测量路径上而不是电流路径上。
3.2 STM32F303VE的SPI与DMA配置
STM32这边,SPI1配置成主机模式,时钟极性CPOL=0,相位CPHA=1,因为ADS122U04在SCLK下降沿采样数据。时钟频率不要超过4MHz,我一般用2MHz,兼顾速度和信号完整性。用DMA搬运接收数据,减少CPU中断开销。DRDY引脚配置成外部中断,下降沿触发,在中断里启动SPI DMA传输。代码框架大概这样:
// SPI1初始化 void SPI1_Init(void) { RCC->APB2ENR |= RCC_APB2ENR_SPI1EN; SPI1->CR1 = SPI_CR1_MSTR | SPI_CR1_SSM | SPI_CR1_SSI | SPI_CR1_BR_1; // 2MHz SPI1->CR1 |= SPI_CR1_SPE; } // DRDY中断处理 void EXTI0_IRQHandler(void) { if (EXTI->PR & EXTI_PR_PR0) { EXTI->PR = EXTI_PR_PR0; // 启动DMA读取4字节 DMA1_Channel2->CNDTR = 4; DMA1_Channel2->CCR |= DMA_CCR_EN; } }读回来的4字节是24位数据加状态位,需要拼装成有符号整数。ADS122U04的输出是二进制补码,最高位是符号位。拼装时注意字节顺序,SPI是MSB first,所以第一个字节是高位。
3.3 寄存器配置与初始化流程
ADS122U04有4个配置寄存器,上电后要先发RESET命令(0x06),然后写配置。我的初始化流程:
- 发RESET,延时1ms。
- 写寄存器0:MUX选择AIN0-AIN1,增益4,PGA使能,连续转换模式。
- 写寄存器1:数据率20SPS,滤波器Sinc3,IDAC电流500μA,IDAC1路由到AIN0。
- 写寄存器2:基准选择外部参考(REF0),温度传感器关闭,DRDY使能。
- 写寄存器3:IDAC2关闭,烧断检测关闭。
- 发START命令(0x08),开始转换。
配置完读一下寄存器确认写入成功。我遇到过SPI时序不对导致寄存器写不进去,读回来全是0xFF,后来发现是CS拉低到第一个SCLK之间的时间不够,ADS122U04要求至少50ns,STM32的SPI自动片选可能太快,改成手动控制CS,加个NOP延时就好了。
3.4 温度换算与线性化
RTD的阻值跟温度不是线性的,PT100在0到850℃用Callendar-Van Dusen公式:
- 0到850℃:R(t) = R0 × (1 + A×t + B×t²)
- -200到0℃:R(t) = R0 × (1 + A×t + B×t² + C×(t-100)×t³)
其中A=3.9083e-3,B=-5.775e-7,C=-4.183e-12。反过来从阻值算温度,0以上可以用二次方程求根:
t = (-A + sqrt(A² - 4B(1 - R/R0))) / (2B)
0以下要用迭代或者查表。我在STM32上用浮点算,F303VE有FPU,一次计算大概几微秒,4路轮询完全够。算出来的温度再做滑动平均滤波,窗口大小8,能压掉随机噪声,又不至于响应太慢。
比例式测量的换算:先算RTD阻值 R_rtd = R_ref × (Code_rtd / Code_ref),其中Code_rtd和Code_ref是ADC读回的码值。因为两个测量用的是同一个IDAC和同一个基准,比值消掉了激励电流和基准的漂移。R_ref用2.49kΩ,Code_ref在500μA下是1.245V,PGA=4时是4.98V,超了!所以参考电阻上的电压不能直接进PGA,要么用PGA=1测参考,要么把参考电阻改小。我后来改成R_ref=1kΩ,500μA下0.5V,PGA=4时2V,刚好在2.048V基准以内。但1kΩ的参考电阻功耗0.25mW,温漂可以忽略。重新算:PT100在0℃时100Ω,500μA下50mV,PGA=4时200mV;参考电阻1kΩ,500μA下500mV,PGA=4时2V。两个都在量程内,比值计算时PGA增益也消掉了,完美。
注意:ADS122U04的PGA增益对两路测量必须一致,否则比值里会残留增益误差。配置时确保MUX切换后PGA设置不变。
4. 常见问题与排查技巧实录
4.1 读数跳动大、噪声高的排查
这是最常见的问题。我遇到过一次,读数在0.5℃范围内跳,查了半天发现是IDAC走线跟SPI时钟线平行走了10cm,时钟串扰耦合到激励电流上。解决办法:IDAC走线包地,或者跟SPI线垂直交叉。还有一次是参考电阻用了普通厚膜电阻,温漂100ppm/℃,手一摸读数就变。换成10ppm/℃的金属膜电阻后稳定了。另外,如果AVDD退耦不好,ΔΣ调制器的噪声会变大,示波器看AVDD上有几十mV的纹波,加个10μF钽电容就好了。
排查步骤我整理成表:
| 现象 | 可能原因 | 排查方法 | 解决措施 |
|---|---|---|---|
| 读数随机跳动 | 时钟串扰 | 示波器看IDAC波形 | 走线包地或远离时钟 |
| 读数随温度漂移 | 参考电阻温漂大 | 用手加热电阻看读数 | 换低温度系数电阻 |
| 读数有规律波动 | 工频干扰 | 看波动频率是否50Hz | 开启工频抑制或加屏蔽 |
| 读数偏置固定 | 导线电阻未补偿 | 短接RTD看零点 | 改用三线制或四线制 |
| 读数满量程 | PGA超范围 | 算共模和差模电压 | 降增益或降激励电流 |
4.2 SPI通信失败的几种情况
SPI通信失败通常表现为读回全0或全1。先检查硬件:CS、SCLK、MOSI、MISO有没有虚焊,ADS122U04的DVDD有没有电。然后看时序:CS拉低到第一个SCLK至少50ns,SCLK空闲电平要跟CPOL匹配。我习惯用逻辑分析仪抓一次完整读写,对比数据手册的时序图。还有一次是STM32的SPI配置成CPHA=0,而ADS122U04要求CPHA=1,数据在第二个边沿采样,改过来就好了。另外,ADS122U04的SPI是模式1(CPOL=0,CPHA=1),不是标准的模式0,这点容易搞错。
4.3 多通道轮询时的串扰问题
ADS122U04内部是多路复用器,切换通道后需要等settling time。如果切换后立刻读数据,会读到上一个通道的残留。我的做法是:切换MUX后,丢弃前3个转换结果,从第4个开始读。因为Sinc3滤波器的settling time是3个周期,第4个才是新通道的稳定值。如果数据率20SPS,每个通道要等200ms,4路轮询一轮800ms。对于温度测量可以接受,但如果要更快,可以用两个ADS122U04并行,或者用STM32的ADC直接测NTC做快速通道,RTD做慢速精确通道。
4.4 自热误差的评估与抑制
自热误差是RTD测量里容易被忽略的。PT100在1mA下自热0.02℃,在5mA下自热0.5℃,差别很大。评估方法:让RTD在静止空气中,分别用不同激励电流测同一温度,看读数变化。如果变化跟电流平方成正比,就是自热。抑制方法:降低激励电流,或者用脉冲激励,只在测量时通电。ADS122U04的IDAC可以配置成脉冲模式,但配置麻烦,我一般直接降电流到100μA,配合PGA=16,信噪比也够。实测100μA下PT100自热0.002℃,基本可以忽略。
4.5 长期稳定性与校准
工业设备要求年漂移小于0.1℃。ADS122U04的增益误差初始0.02%,温漂1ppm/℃,加上参考电阻的10ppm/℃,年漂移主要来自电阻的老化。我一般用Vishay的PTF系列或者VPG的箔电阻,年老化25ppm,换算成温度0.0065℃,可以接受。校准方面,出厂前用冰水混合物(0℃)和沸水(100℃,注意气压修正)两点校准,把增益和偏置写进STM32的Flash。现场如果条件允许,每年用干体炉校准一次。我试过用PT1000做参考,因为PT1000的灵敏度更高,但自热也大,后来还是用PT100加精密电阻。
提示:校准时的冰水混合物要用去离子水,冰块要碎,搅拌到均匀,插入深度至少10cm,等5分钟稳定。沸水校准要查当地气压,每升高300米沸点降1℃,1000米海拔沸点约96.8℃。
5. 方案扩展与个人经验体会
这套方案不止能测RTD,改一下MUX配置就能测热电偶、NTC、甚至应变片。热电偶需要冷端补偿,ADS122U04内部有温度传感器,精度0.5℃,做冷端补偿够用。NTC的阻值高,激励电流要降到10μA,PGA增益可以到128。应变片用比例式测量,参考电阻跟应变片同材质,温漂抵消。STM32F303VE的FPU还能跑简单的PID,直接输出4-20mA或者PWM控制加热器,做成一个完整的温度控制器。
我在实际项目里最深的体会是:模拟前端的布局比选型更重要。同样的芯片,布局好能到0.01℃稳定,布局差0.5℃都跳。IDAC走线、参考电阻位置、地平面分割,这三个地方花的时间比写代码多得多。另外,不要迷信高分辨率,24位ADC的有效位在20SPS下大概21位,噪声-free位19位,算下来0.001℃分辨率,但实际精度受传感器和校准限制,能到0.05℃就不错了。所以选型时留够余量,别为了省几块钱用16位ADC,后期调试的时间成本远高于芯片差价。
最后分享一个小技巧:ADS122U04的DRDY引脚在连续转换模式下会周期性拉低,可以用STM32的定时器输入捕获测它的频率,反推实际数据率。如果频率不对,说明寄存器配置有问题,比读寄存器还直观。我调试时经常用这招快速判断ADC有没有正常工作。