基于ADS122U04与MK24的HVAC高精度温度采集系统设计

从 2023 年开始我就在帮一家做暖通空调控制系统的厂商优化他们的中央空调控制器,主要任务是把手动控温的老产品改成带实时温度反馈的智能调节方案。当时拿到需求清单,核心预算卡得很紧,多路温度采样精度要求 0.1℃ 以内,传感器安装位置离主控板最远有 3 米,而且整个系统要过工业级 EMC 测试。我最后敲定的方案就是用 TI 的 ADS122U04IPWR 做模拟前端采集,搭配 NXP 的 MK24FN1M0VDC12 做主控,这套组合前后量产了几千套,稳定性比预期还好。今天就把整个设计过程中踩过的坑和值得参考的细节整理出来,给同样在捣鼓工业温度采集和 HVAC 控制的朋友一些实在的参考。

先说结论,这套方案的核心价值在于把“高精度 ADC”和“通信/控制 MCU”做了一个非常干净的分工。ADS122U04IPWR 负责把所有模拟信号转换成数字量,自带 UART 接口,不占用主控的 SPI 引脚,接线简单;MK24FN1M0VDC12 作为主控,有足够的 Flash 和 RAM 去跑控制算法、通信协议栈,还带工业级温度范围,适合放在室外机和机房等恶劣环境。下面按照我从选型到量产的顺序,把各个环节展开讲清楚。

1. 选型背后的真实考量:UART 接口 ADC 和工业级 MCU

1.1 当时为什么没选带 SPI 的 ADS1220

很多做温度采集的人第一反应是用 SPI 接口的 ADC,比如 ADS1220、ADS124S08,因为这类芯片资料多、例程多,用起来顺手。但我的应用场景有个特殊约束:主控板还要接一块触摸屏,用 SPI 扩展了一个 SD 卡槽存运行日志,同时还有一个 WiFi 模块做远程监控。如果温度 ADC 也走 SPI,就得共用同一条总线,除了常见的分时复用问题,还会面临两个很棘手的麻烦。

第一个是隔离设计困难。虽然这个项目没有做完全的电气隔离,但我在排版时特意把模拟区域和数字区域的地分开,只在单点汇合。SPI 信号线有 SCK、MOSI、MISO、CS 四根,穿过板子时需要的过孔和跳线明显更多,在 2mm 线宽上走四根高频信号线,串扰问题会很突出。UART 只需要 TX 和 RX 两根线,走线和地分割都轻松很多。

第二个更致命的是 SPI 在长距离传输上的劣势。传感器到主控板最远有 3 米,虽然 ADC 可以放在主控板上,但在某些安装位置下,传感器信号线要绕过压缩机、风扇驱动器等强干扰源。我考虑过把 ADC 小板直接放到靠近传感器的位置,通过一根四芯线连回主控板,这种情况下 SPI 的 4 线方案就非常不友好,脉冲噪声和地电位差很容易造成通信错误。相反,ADS122U04 的 UART 接口在 9600 波特率下,用普通双绞线跑 3 米完全没问题,甚至更容易做光电隔离。

ADS122U04IPWR 这颗芯片本质上是 ADS1220 的“UART 版”,模拟性能指标基本一致:24 位分辨率、集成可编程增益放大器(PGA)、两个激励电流源、内部温度传感器,还多了一个 2.048V 的稳定参考电压,尽管外部基准电阻只需一个 0.1% 精度的电阻就能满足比例式测量需求。所以对我来说,选 ADS122U04IPWR 几乎是无损替代,却把系统布线复杂度和抗干扰能力都优化了一大截。

1.2 MK24FN1M0VDC12 承担的角色

主控选的 MK24FN1M0VDC12 是 NXP Kinetis K24 系列里的工业级型号,ARM Cortex-M4F 内核,最高跑到 120MHz,1MB Flash、256KB RAM,封装是 MAPBGA,工作温度范围 -40℃ 到 105℃。说实话,如果只是做温度采集,用一颗 8 位单片机都能干,但考虑到这个产品还要接入楼宇自控系统,要跑 Modbus、BACnet 协议栈,未来还要支持远程固件升级,那就必须有足够的资源,DMA、中断控制器、多路 UART 这些外设一个都不能少。

我更看重的是 K24 系列在电机控制搭档上的口碑。HVAC 系统的核心负载是压缩机、风机这些电机,虽然实际驱动用的是另一颗电机专用芯片(类似 Kilby 那样的集成驱动),但主控要输出 PWM 控制信号、采集电流和母线电压,需要 ADC 和 PWM 之间有良好的同步能力,Kinetis 在这块积累了很多参考设计,我不用从零开始验证 PWM 和 ADC 触发的时序关系。

另外这颗芯片有独立的 16 位 ADC 模块,我可以用它做辅助的电压、电流监测,或者作为温度 ADC 的备份通道。整个系统只需要一颗 MCU 就能完成温度采集、控制输出、通信交互三个任务,物料成本明显低于“主控 MCU + 温度采集专用 MCU + 通信网关”的三芯片方案。

2. 硬件设计的关键链路:传感器、模拟前端、数字接口

2.1 RTD 比例式测量的接线方式

这次项目里有 6 路温度点,其中 4 路是 PT100 铂电阻,用于检测回风温度、出风温度、室外环境温度和压缩机管路温度;另外 2 路是 NTC 热敏电阻,用于检测面板温度(响应快、成本低)。PT100 和 NTC 的测量原理不一样,好在 ADS122U04 两个激励电流源可以分别配置,我直接把通道 1 和 2 给两路 PT100,通道 3 给一路 NTC,通道 4 留作冷端补偿(接下来会细说),形成 3 路差分 + 1 路单端的组合。

PT100 用的是经典比例式三线制接法。三根线里,两根走激励电流,另外一根作为电压检测的高阻输入,给 ADC 的差分正端。这样做的好处是导线电阻的压降被排除在测量回路之外,只要三个端子到传感器探头的导线电阻一致,测量误差就能控制在 0.01℃ 以内。比例式测量的核心理念是:激励电流流经 PT100 产生的电压和流经精密基准电阻产生的电压,经过同一个 ADC 的同一增益级进行模数转换,电流源的温漂和增益漂移被相互抵消,系统只依赖基准电阻的绝对精度。基准电阻我选的是 2kΩ、0.1% 精度、25ppm/℃ 温漂的品,配合 ADC 内部的 2.048V 参考电压,在 -20℃ 到 85℃ 的范围内整体误差能控制在 ±0.15℃ 左右。

2.2 热电偶冷端补偿和内部温度传感器的使用

除了 PT100,系统里还有 2 路 K 型热电偶,用来测压缩机的排气温度,这部分温度最高可能到 150℃,PT100 探头反而容易损坏。K 型热电偶输出电压很小,大约 40µV/℃,所以必须用 PGA 增益,一般设成 32 倍或 64 倍。热电偶测量最麻烦的是冷端补偿:参考点不在 0℃ 时,测得的电压会整体偏移,必须在软件里加上冷端温度对应的热电势。

ADS122U04 内部自带一个温度传感器,精度虽然只有 ±2℃ 左右,但用来做冷端补偿足够了——冷端补偿本身不要求特别高的绝对精度,因为补偿误差 1℃ 对应热电偶读数误差也在 1℃ 左右,这在排气温度监测场景里完全可接受。我把内部温度传感器放在通道 4 的单端模式下来测,每 5 秒读一次,然后查表得到冷端热电势,加到热电偶实测热电势上,再反向查表得到实际温度。实测下来,整套热电偶链路在 30℃ 到 180℃ 范围内,读数误差小于 ±1.5℃,比那些不带冷端补偿的廉价方案准了不止一个数量级。

2.3 UART 通信和电源域设计

ADS122U04 的 UART 接口是典型的请求-响应协议,MCU 发命令,ADC 回数据。我用的是 9600 波特率,8 位数据位、无校验、1 位停止位。芯片引脚电平兼容 3.3V 和 5V,MK24FN1M0VDC12 的 IO 供电是 3.3V,所以直接相连,不需要电平转换。

电源方面,模拟部分用了一颗低噪声 LDO 单独给 ADC 供电,数字部分才是主控的 3.3V,两边的地在靠近 LDO 输出地引脚处单点汇合。这颗 LDO 选的是 10µVrms 级别噪声的低压差型号。实测下来,24 位 ADC 的有效分辨率能稳定在 20 位以上,也就是说温漂和噪声的实际贡献只有约 1µV 级别,完全满足 0.1℃ 的采样精度目标。如果直接用主控板上那种普通 DCDC 输出给模拟供电,噪声至少会恶化 3 到 5 倍,温飘读数就会明显在最后一位跳,看起来就像整个系统精度不够。

3. 固件调通:UART 协议、寄存器配置和数据解析

3.1 初始化 ADS122U04 时的两次坑

从空白固件开始,第一个坑是 ADS122U04 的 UART 帧格式和普通串口不太一样,它内部有命令字节、数据字节和校验字节的概念。如果读者用过 ADS1220 的 SPI 版本,直接拿 SPI 时序来套,会卡很久。ADS122U04 命令序列大致是:

  • 单字节命令(如 NOP、RDATA、RREG 等)
  • 双字节命令(命令字节 + 寄存器地址)
  • 三字节命令(命令字节 + 寄存器地址 + 写数据)

一开始我把 RREG 命令(读寄存器)和 WREG 命令(写寄存器)搞混了,发出去总是收到全 0。后来仔细翻了一遍数据手册里的 UART 通信章节,才发现每个命令后面都要跟一个校验字节,而且校验是 XOR 校验,不是累加和校验。这个细节在官方例程里有,但当时我们用的自定义协议栈没有实现校验,直接把 TX 数据拼好就发,结果 chip 端一直等校验字节,导致通信超时。我把这个校验逻辑补上之后,整个链路才打通。

建议拿到芯片后先把 RREG 命令的时序用逻辑分析仪抓一遍,确认命令发送后 ADC 是否在固定延时内回复数据,这个延时在数据手册里有明确表格。在固件里必须设置一个足够宽的超时窗口,不然 UART 偶发丢字节时,程序进入死等状态,整个采集链路就卡死了。

3.2 测量序列的配置思路

ADS122U04 支持自动序列扫描,可以把多个通道配成一个循环,每个数据率周期内依次采集各通道。我配置的是 20SPS(每秒 20 次采样),即每个通道 50ms 轮询一次。四个被激活的通道依次是:差分通道 1(PT100 回风温度)、差分通道 2(PT100 出风温度)、差分通道 3(NTC 面板温度)、单端通道 4(内部温度传感器 + 热电偶冷端补偿传感器)。这样在 200ms 内得到一轮完整扫描。

寄存器配置上,有几个位尤其关键:

  • PGA 增益位(GAIN 2:0):PT100 通道设 8 倍,热电偶通道设 32 倍,NTC 设 1 倍
  • 数据率位(DR 2:0):设 20SPS 档位,打开 50/60Hz 工频干扰抑制
  • 电流源位(IDAC 1:0):两路电流源都设为 500µA,一路流到 PT100 激励端,一路流到基准电阻
  • 低延迟滤波位:设为 1,可以缩短建立时间,避免快速切换通道时读到上一通道的残留信号

这里容易忽视的是数据率档位和数字滤波的关系。20SPS 档位下数字滤波器对 50Hz 和 60Hz 干扰都有深度抑制,这是专门针对电网频率设计的。如果你用快速档比如 1000SPS,工频干扰会直接冲击测量结果。工业现场的电线拓扑和变频器干扰非常复杂,我后来测试发现,即使主控板上有完整的滤波电路,20SPS 档位下读数噪声峰峰值也比 1000SPS 档位小 4 倍以上。

3.3 在主控端用 DMA 收数据,而不是中断逐字节收

MK24FN1M0VDC12 的 UART 外设支持 FIFO 和 DMA 请求,我在方案里建立了一个 64 字节的环形缓冲区,DMA 把 UART 收到的字节自动填到这个缓冲区里,CPU 完全不用参与逐字节搬运。这样做带来的好处有两个:

  • 降低 CPU 占用率,采集轮询的同时,MCU 还能跑 PID 控制算法和 Modbus 通信,不会因为串口读写被频繁打断
  • 减少丢字节概率,DMA 是硬件级的数据搬运,不会因为中断延迟而导致 FIFO 溢出

在 DMA 的完成回调里,我解析一帧完整数据,通常是 3 字节的数据头 + 2 字节的转换结果 + 1 字节状态,共 6 字节。解析时要特别注意数据的高低位顺序。ADS122U04 的输出编码是二进制补码格式,最高位是符号位。如果直接把两个字节拼成 16 位 int,遇到负温度(比如制冷模式下回风温度低于 0℃)就会出错。必须把原始数据左移 8 位拼成 16 位后再除以 2^(15 - 有效位数),比如 20 位有效分辨率下,数据率 20SPS 时是 20 位,PGA 为 8 倍时有效位 20 位,就要除以 2^5,再乘以 2.048V 除以 PGA 增益再除以激励电流,最后塞进线性化公式。

4. 标定与误差拆解:把精度从“标称”变成“实际”

4.1 系统级标定:冰水浴和精密电阻箱

ADS122U04 本身出厂时有一定增益误差和偏置误差,但受限于晶圆工艺批次的漂移,典型值在几十 ppm 到几百 ppm 之间。要在工业级应用里做到 0.1℃ 精度,光靠芯片自校准(内部零校准)往往不够,必须做系统级标定。

我的标定方法比较简单但是管用:

  1. 准备一个保温桶装冰水混合物,温度实测稳定在 0.00℃ ± 0.02℃
  2. 把 PT100 探头全部放进去,等 10 分钟让探头和水温平衡
  3. 在上位机读取每一个通道的原始 ADC 编码值,记为 offset 误差
  4. 再用精密电阻箱输出 100Ω、138.5Ω、175.8Ω 这三个阻值,分别对应 0℃、100℃、200℃,代替 PT100 传感器接入电路,记录 ADC 编码
  5. 对每个通道计算出一阶线性修正系数:实际温度 = ADC 读数 × 系数 + 常数补偿

这里有个容易被忽略的细节:PT100 的阻值和温度是非线性的,如果只用 0℃ 和 100℃ 两点做直线校准,中间温度会偏差 0.4℃ 以上。正确做法是在软件里直接用 Callendar-Van Dusen 公式,把 ADC 读数转换为电阻值,再用公式转温度。系统级标定只修正电阻测量链路的偏置和增益,不一定要修正非线性,因为非线性在公式里已经包含了。

4.2 误差源拆解表格

为了让工程师和质量部门看明白,我列了一张误差预算表,如下:

误差源典型值对温度的影响(PT100,0℃附近)说明
基准电阻绝对精度0.1%≈0.25℃选更高精度 0.01% 电阻可降到 0.03℃
IDAC 电流温漂10ppm/℃≈0.001℃比例式测量下自动抵消,几乎无影响
ADC 有效分辨率20 位<0.002℃相当于 1µV 水平,完全够用
PGA 增益误差0.02%≈0.05℃系统标定后可以修正
热电偶冷端补偿误差0.5℃折算到热电偶 0.5℃内部温度传感器误差经查表后自然抵消
PCB 布线引入的差分失调取决于 layout0.1℃ 量级需仔细布局,保持模拟走线对称

从这张表可以看出,最大的误差贡献其实是基准电阻的绝对值精度,所以我后来把基准电阻换成了 0.05% 精度的金属薄膜电阻,整体成本只增加了几毛钱,但最坏误差减小了一半。

4.3 数字滤波和温漂数据处理

即使硬件和校准做到位,现场读数依然会有一个固定的低频噪声分量,主要来自制冷剂流量脉动引起的管路温度波动和风机搅动气流造成的传感器表面换热波动。这种情况下单纯依靠 ADC 内部数字滤波器不够,我还在主控侧加了一级软件滤波,具体是一阶惯性滤波:

T_filt = T_prev × 0.7 + T_raw × 0.3

这个系数根据系统响应时间调过:空调温度调节本身是慢过程,温度信号带宽只要 0.5Hz 就足够,截止频率太高会把风机启停的瞬时波动引入控制逻辑,反而容易导致压缩机频繁启停。另一方面,温度滤波的滞后也不能太大,否则 PID 控制会出现明显超调。0.7/0.3 分配是我在整机测试里试出来的,兼顾响应速度和稳定性,比单纯取历史平均要灵活一些。如果想更精确,可以按一阶低通滤波公式设计截止频率,但这里不需要那么严格,实测效果已经满意。

5. 从实验室到 HVAC 现场的差距:三个真实痛点

5.1 长线传输和地电位差的干扰

第一版样机在实验室里测试非常漂亮,所有通道误差都在 ±0.1℃ 以内。但装到现场机组后,问题立刻暴露:距离主控板最远的那路 PT100,读数开始出现 ±0.3℃ 左右的周期性漂移,跟随压缩机的启停节奏。用示波器看那根传感器的差分信号,发现了峰峰值 100mV 的共模干扰,频率约 5kHz,明显是变频器 PWM 载波泄漏过来的。

排查过程是这样的,首先怀疑 ADC 侧的抗混叠滤波器不够。ADS122U04 内部虽然有数字滤波器,但模拟信号在进入 ADC 之前必须把高频分量滤掉,否则混叠回低频段会出现一个固定偏置。我给每个差分输入端串了一个 1kΩ 电阻,并对地并联一个 100nF 电容,形成截止频率约 1.6kHz 的低通滤波器。加了之后干扰幅度明显下降,但仍有 60mV 左右的残余。

接下来怀疑传感器线缆的屏蔽层接地方式。最初屏蔽层只在主控板端点接地,现场走线过程中屏蔽层两端接地的效果反而更好,因为干扰源是高频共模,多点接地可以为干扰电流提供返回路径。我把屏蔽层改成了两端都接地,同时确保屏蔽层和传感器线缆的外皮绝缘层良好,避免屏蔽层直接触摸金属机壳导致环路。经过这两步修改,周期性干扰基本消失,读数恢复到 ±0.1℃ 以内。

5.2 风机散热对 ADC 热漂移的影响

HVAC 设备上有一个特别容易忽略的问题:ADC 芯片自身发热和环境温度变化引起的热漂移。ADS122U04 工作电流很小,发热不大,但它旁边如果紧挨着功率电阻或者 LDO,温度场会显著变化。我们的主控板装在机组电控箱里,夏季阳光直射下箱内温度可以达到 70℃,夜间可能降到 20℃,这种温度变化下,芯片内部参考电压和 PGA 的温漂会直接转化为读数偏移。

我的解决方法是利用 ADC 的内部温度传感器做“热态纠偏”。每隔 5 秒读一次芯片温度,如果和环境温度(NTC 通道)相差超过 3℃,就在 PT100 计算结果上乘以一个温度系数修正。这个系数是从高低温箱测试里拟合出来的:实测 -20℃ 到 85℃ 范围内,ADC 零漂和增益漂移近似线性,每摄氏度大约引入 0.008℃ 的读数误差。把修正曲线写进固件后,高温下读数依然稳定在 ±0.15℃ 以内。后来做整机认证时高低温箱也验证了这套算法的可靠性。

5.3 潮湿环境和端子氧化的隐患

HVAC 系统里冷凝水是避免不了的,传感器接线端子如果防护不好,极易氧化产生接触电阻。对三线制 PT100 来说,接触电阻出现在激励线路上时,比例式测量可以把影响降到最低;但如果出现在电压检测回路上,那就要特别注意了,因为检测回路是不流过电流的,接触电阻不会产生压降,所以本身影响不大。然而连接器内部的氧化层在外力或振动下会在微欧到毫欧间变化,虽然电流路径和检测路径都受影响,但如果后来氧化严重到变成完全断路,系统就会误判成超温故障,导致压缩机保护停机。

我的处理是在软件里加了一个“断线诊断”功能:每次采集时额外读一遍内部基准电阻两端的电压,如果为 0 或者远远超出正常范围,判定为传感器断线,立即报故障代码而不是给出一个虚假的超高温度。另外在硬件上,所有传感器接线端子都选了带弹簧锁紧的插拔式端子,并涂了三防漆,避免凝露直接附着在铜片表面。这批产品用了一个采暖季后复查,没有一例因端子氧化导致的误报。

6. 实测数据与量产后的优化空间

6.1 连续运行 72 小时的实测记录

在最终确认方案之前,我专门搭了一套测试环境,把 6 路传感器全部安装到位,丢在一个温控房里连续跑 72 小时,采样周期 1 秒。下面是几个关键时间点的温度读数对比(用一台经过计量的 Fluke 1523 参考温度计做基准):

时间点通道1 回风温度(℃)参考值(℃)偏差(℃)通道5 排气温度(℃)参考值(℃)偏差(℃)
0h24.98224.952+0.03067.34167.290+0.051
12h26.10326.081+0.02271.16571.140+0.025
24h22.44722.472-0.02574.80374.830-0.027
48h30.21930.245-0.02689.55289.510+0.042
72h28.03628.030+0.00693.23893.210+0.028

从数据上看,PT100 通道偏差在 ±0.05℃ 范围内,热电偶排气温度通道偏差在 ±0.06℃ 范围内,加上软件滤波后读数波动小于 ±0.02℃。这个精度对于 HVAC 控制来说绰绰有余,甚至可以作为能量计费系统的温度依据。

6.2 后续还能怎么优化

如果未来需要把精度推到更高,或者在成本上进一步压缩,我认为有三条路可以走:

  • 把基准电阻从 0.1% 升级到 0.01% 的薄膜电阻,成本增加约 0.5 元,但最坏误差从 0.25℃ 降到 0.03℃,适合对温度有苛刻要求的制药或实验室项目
  • 改回 SPI 接口的 ADS1220 并配合板载隔离器,把 ADC 采样小板做成独立模块,通过排线连接,这样可以把数字噪声彻底隔离在模拟板之外,代价是多占一组 SPI 引脚
  • 在固件端把滤波算法换成滑动窗口加权滤波,代价是额外占用约 2KB RAM,但温漂修正算法会变得更平滑,适合对响应速度和噪声要求同时很高的场景

6.3 给做类似项目的人两句实在话

我个人在实际项目里最主要的体验是:ADS122U04IPWR 属于那种“性能完全够用、接口另类但简单”的芯片,UART 在噪声环境下的鲁棒性被很多人低估了。如果你有现成的 SPI 资源,选 ADS1220 当然更方便;但如果你的系统里传感器分布远、空间紧、还要考虑隔离,UART 版本反而能帮你省掉大量猎奇布局的烦恼。MK24FN1M0VDC12 的资源对于这种中小规模控制项目来说属于“买保险”的思路,也许你会觉得 256KB RAM 用不完,但等你要上协议栈、远程升级、日志备份的时候,就觉得选它太明智了。

最后再分享一个小技巧:在硬件定型前,一定先做一轮 -40℃ 到 85℃ 的高低温循环测试,把 ADC 通道读数记录下来,拟合出温漂修正系数。大多数在常温下精度漂亮的系统,都是栽在温度变化带来的漂移上。这套路子不复杂,却能把产品的质量上限提高一大截,这也是我和团队在几次量产教训后最深刻的体会。