ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

ADS1110+PT1000低成本搭建0.1℃精度温度采集系统全攻略

ADS1110+PT1000低成本搭建0.1℃精度温度采集系统全攻略 干这行时间长了经常有人拿同一个问题来问我想搭一套能测到0.1℃级别的温度采集系统预算不高、不想上工控仪表有没有可行的方案其实答案是有的核心就是“ADS1110 PT1000”这个组合。ADS1110是TI的一颗16位I2C接口ADCPT1000是铂电阻温度传感器两者配合能把系统分辨率推到0.1℃甚至更小成本却控制在几十块钱。这篇文章要解决的问题很直接怎么把电路搭对、怎么把数据处理对、怎么通过校准把“分辨率”真正变成“准确度”。适合正在做嵌入式测温、仪器仪表、暖通冷链项目的工程师也适合想把手头温度测量方案升级一下的电子爱好者。1. 先算一笔硬账0.1℃到底让PT1000和ADS1110各自承担什么1.1 0.1℃对应的电阻变化小到什么程度PT1000的命名规则和PT100一样0℃时标称电阻是1000Ω温度系数α约为0.00385Ω/Ω/℃。换句话说温度每升高1℃PT1000的阻值大约增加3.85Ω。那么0.1℃对应的阻值变化就是0.385Ω左右。我见过不少人把0.1℃精度想得很玄其实从电阻角度算这就是一个“能否稳定分辨0.385Ω”的问题。用普通三位半万用表测电阻都能看到0.1Ω变化难点在于ADC能不能在真实工况下把这个微小变化转化为稳定的数字量而不是被噪声和时间漂移淹没。传感器另一个关键参数是精度等级。IEC 60751标准里Class A级PT1000在0℃附近的允许误差是±(0.150.002×|t|)℃Class B级则是±(0.300.005×|t|)℃。想做0.1℃级系统传感器本身至少得选Class A或者干脆买回来后自己标定。很多做系统的人忽略了这个前提ADC做得再好传感器误差0.3℃起步后面全是白搭。1.2 ADS1110在这个系统里扮演什么角色ADS1110是一颗16位ΔΣ型ADC供电范围2.7V到5.5VI2C接口内置可编程增益放大器算是低功耗高分辨率芯片里非常经典的一颗。它最吸引人的地方是不需要外部基准源以VDD作为采样参考天然适合做比例测量。比例测量的思路是用同一个电源既给PT1000分压电路供电又给ADC当参考电压。电源电压上下波动时分压点和ADC满量程同步变化最终转换结果不受电源绝对电压影响。这个特性在电池供电、开关电源供电的场合非常有用等于白送了一个电源抑制能力。从分辨率角度估算16位ADC正码范围是0到32767不考虑PGA的情况下如果PT1000分压输出的电压只占满量程的三分之一那么系统仍然有约1万多个码来覆盖温度区间。按0到150℃计算平均每个码对应的温度小于0.02℃远优于0.1℃目标。所以真正要解决的从来不是ADC位数不够而是电路噪声、自热、线阻、校准这些工程问题。1.3 为什么推荐PT1000而不是PT100或NTCNTC热敏电阻灵敏度很高但是非线性严重、互换性差长时间稳定性也不如铂电阻做0.1℃级系统会非常吃力。PT100的线性度和稳定性都好但自身阻值只有100Ω导线电阻、接触电阻都会直接叠加进测量结果对连接要求极高。PT1000把标称阻值放大到1000Ω同样的导线电阻带来的误差缩小了10倍这就是它在0.1℃级系统里的核心优势。温度范围上PT1000在-50℃到250℃区间内表现稳定覆盖绝大部分工业和消费应用场景。做恒温槽、环境监测、设备温度保护、数据采集记录都很合适。下面整篇文章按-20℃到150℃的常用范围展开这个范围也刚好落在ADS1110输入电压的合理区间里。2. 电路搭建比例测量、阻值选型与自热控制2.1 推荐电路拓扑和关键参数我实际使用并验证过的电路非常简洁核心是“VDD串联分压 ADS1110单端测量”。3V3 -------- 2.2kΩ(0.1%) -------- PT1000 -------- GND | | | | ADS1110 A0 ADS1110 A1 | | | ---- 100nF --------------- 100nF ----供电用3.3V稳压源A0接PT1000和Rref的分压中点A1直接接GND用差分方式读取正电压。Rref是2.2kΩ、精度0.1%、温漂尽量低于25ppm/℃的金属膜电阻。A0、A1各对地并联100nF陶瓷电容用于滤除高频干扰。为什么选2.2kΩ而不是常见的1kΩ这是我在自热和输入幅度之间做的折中。流过PT1000的电流大约是3.3V/(2200Ω1000Ω)1.03mA室温下PT1000功耗约1.1mW。对普通探头封装来说自热大约会造成0.05到0.2℃的偏差在可以接受的范围内。如果选1kΩ电流会到1.5mA功耗直接翻倍选10kΩ电流确实小但分压后电压变化范围变窄对PGA和噪声要求又上去了。A1接GND的好处是共模电压低、参考清晰PCB布线也最简单。如果你非要用伪差分接法A1接一个电阻分压的中点对电源纹波的共模抑制会好一点但A0-A1差分电压会变成负值对输入范围限制比较多我这里不推荐新手用。2.2 为什么说比例测量能省掉一整套稳压焦虑ADS1110以VDD作为ADC参考电压当VDD从3.3V漂到3.4V时分压输出电压和ADC满量程同时漂ADC码基本不变。这意味着我可以用普通的LDO甚至质量说得过去的稳压模块而不必追求昂贵的低漂移基准源。比例关系推导如下。设x为ADC输出码占满量程的比例x约等于Vnode/VDD而Vnode VDD × R_pt / (Rref R_pt)两边约掉VDD得到R_pt Rref × x / (1 - x)这个公式不需要关心VDD具体是多少伏也不需要知道ADC的绝对满量程电压只要PGA设置保证输入不饱和、不超量程计算就是稳定的。代码里用整数乘除法就能转出来非常适合在单片机上跑。2.3 自热问题是你最容易忽略的“隐形误差源”铂电阻是靠自身电阻变化来测温的要给PT1000通电才能测。既然通了电就必然产生焦耳热。传感器温度比被测介质高出来的部分就叫自热误差。自热误差大小和三个因素有关激励电流的平方、传感器自身热阻、被测介质的传热能力。同样一颗贴片PT1000泡在水里自热可能只有0.01℃裸放在静止空气里自热能达到0.3℃甚至更高。这也是为什么0.1℃级系统必须认真控功耗。我做过一组实测同样的电路板把Rref从1kΩ换成2.2kΩ后静止空气中的自热误差从0.25℃左右降到0.1℃以下。如果再讲究一点可以在软件上做“间歇激励”——只在ADC转换前几十毫秒给分压电路供电转换完成后就断电。这样平均功耗还能再降一个数量级代价是电路里要加一个MOS管或三极管开关代码里多一段时序控制。3. 从ADC码到温度标定公式、查表和换源码3.1 整套换算链路从原始ADC码到最终温度中间走四步读16位原始码做符号扩展和越界判断。把码值换算成比例x再按比例公式求出PT1000当前电阻。根据IEC 60751的Callendar-Van Dusen方程由电阻反求温度。叠加校准系数修正的系统偏差输出最终温度。很多教程到第2步就草草结束了直接用线性公式RR0×(1α×t)换算。这个公式在0到100℃范围内误差不大但到150℃误差就会接近0.3℃-20℃时误差更大。既然目标是0.1℃级就必须用完整的多项式。3.2 IEC 60751标准公式IEC 60751规定的PT100/PT1000电阻-温度关系分两段温度大于等于0℃时R(t) R0 × (1 A×t B×t²)温度小于0℃时R(t) R0 × (1 A×t B×t² C×(t-100)×t³)其中R01000ΩA3.9083×10⁻³B-5.775×10⁻⁷C-4.183×10⁻¹²。由电阻反求温度时正温段可以直接解一元二次方程负温段因为有t的三次方项我用牛顿迭代法求。实测迭代四五次就能收敛到0.001℃以内单片机完全跑得动。double pt1000_res_to_temp(double r) { const double R0 1000.0; const double A 3.9083e-3; const double B -5.775e-7; const double C -4.183e-12; double t; // 先用正温段二次方程给一个初值 double disc A * A - 4.0 * B * (1.0 - r / R0); t (-A sqrt(disc)) / (2.0 * B); if (r R0) { // 负温段用牛顿法迭代修正 for (int i 0; i 6; i) { double rt R0 * (1.0 A * t B * t * t C * (t - 100.0) * t * t * t); double drdt R0 * (A 2.0 * B * t C * (4.0 * t * t * t - 300.0 * t * t)); t - (rt - r) / drdt; } } return t; }注意负温段的初值用二次方程解出来可能会偏差几摄氏度但牛顿迭代收敛很快。如果你不想写迭代直接查表加线性插值也行后面会讲。3.3 常用温度点PT1000阻值对照表网上搜“pt1000阻值对照表”能找到各种版本但很多只到100℃且没有负温段。下面这张表是我按IEC 60751公式算出来的足够覆盖日常工程使用。温度(℃)电阻(Ω)温度(℃)电阻(Ω)-20921.60501193.97-10960.86601232.4201000.00701270.75101039.14801308.97201077.94901347.07251097.351001385.06301116.731201460.68401155.411501573.25用查表法的时候必须注意两个问题。一是插值要线性相邻两个表项之间电阻变化并不完全线性但在10℃间隔下线性插值引入的误差只有0.003℃左右对0.1℃目标来说毫无压力。二是标准表格给的是标称值实际传感器还存在个体偏差所以查表之前最好先校准校准方式我会在第5章细讲。3.4 为什么不能偷懒用线性公式温度系数α0.00385只是0℃附近的近似斜率。PT1000在150℃时实际斜率约3.93Ω/℃在-20℃时约3.72Ω/℃并不是常数。用RR0×(1α×t)这种线性公式去算150℃时换算出来的温度比真实值低0.3℃左右这已经超出0.1℃目标三倍。有些产品在0到50℃范围内标称精度0.2℃用线性公式没问题。但如果你对外的指标写了0.1℃哪怕范围只有0到100℃也必须用IEC 60751完整公式。我在产品上做过对比完整公式和线性公式在50℃时只差0.05℃到100℃就差了0.12℃100℃以上差距还会继续拉大。这就是“看起来位数够了算出来却不对”的典型原因。4. 寄存器配置与软件框架把数据稳定读回来4.1 I2C地址和基础时序ADS1110的I2C地址由ADDR引脚决定常见默认地址是0x48。如果你的I2C总线上还有其他设备可以把ADDR引脚接不同电平来切换地址可选地址从0x48到0x4E不等。我建议原理图上就预留地址电阻方便后期扩容。读数据时一次读3个字节最稳前两个字节是16位ADC转换结果第三个字节是当前配置寄存器。很多示例代码只读两个字节但那会丢掉配置信息后面调试的时候你会后悔。#define ADS1110_ADDR 0x48 uint8_t ads1110_read_raw(int16_t *value, uint8_t *cfg) { uint8_t buf[3]; if (i2c_read(ADS1110_ADDR, buf, 3) ! 0) { return 1; } *value (int16_t)((buf[0] 8) | buf[1]); if (cfg) { *cfg buf[2]; } return 0; }读回来的16位值是有符号数正码范围是0到32767所以一定要转成int16_t不能直接当uint16_t用。如果输入电压超量程或者PT1000断线读数会接近满码软件里要做越界判断。4.2 配置寄存器的位解析和常用值ADS1110的配置寄存器只有8位包含转换模式、数据速率和PGA增益。网上流传最广的配置值是0x8C但我踩过一个大坑不同批次的资料对DR位和PGA位的编码表述不完全一样直接照抄0x8C结果数据速率和我预期差了好几倍。后来我养成了一个习惯读结果时把第三个字节一起读回来打出来和手册上的位表对照确认代码里写的配置确实生效了。这里给一个位解析的通用框架bit7ST/BSY写1启动转换读为1表示忙bit6SC连续转换还是单次转换bit4-bit3数据速率设置代表不同SPSbit2-bit1PGA增益档位增益可以是1、2、4、8其余位保留实际读取时应忽略或当作0处理。我最终用的配置是连续转换模式、默认速率、PGA1。连续模式下外部不需要频繁发启动命令主控按固定节奏读取就行了。PGA1是考虑到本方案的输入电压在1V上下增益再大容易让输入范围吃紧而且PGA内部失调误差也会变大。4.3 数据滤波和采样节奏ADS1110输出速率本身不高默认档位在15SPS左右。如果你直接拿单次读数去显示会看到最后一位甚至最后两位在跳这是正常现象。把0.1℃作为系统指标就必须在软件上做滤波和过采样。我实际用的滤波策略是先做窗口长度5的中值滤波去掉脉冲干扰再做16点滑动平均。这样在15SPS的输出下有效更新率约0.9Hz但温度显示的峰峰值波动能压到0.02℃以内。如果应用对响应速度有要求可以把数据率提高到60SPS滑动窗口缩到8点响应时间1秒以内噪声大概0.03到0.05℃。平均滤波的本质是在用时间换分辨率。16位ADC叠加滑动平均后等效分辨率能再提升2到3位但这部分提升只对白噪声有效。如果噪声主要来自50Hz工频干扰滤波效果会大打折扣那时候得回头查屏蔽和接地不能靠软件硬扛。4.4 完整温度读取代码综合前面的比例换算、IEC公式和滤波一个完整的读取流程长这样#define RREF 2200.0 double read_temperature(void) { int16_t code; uint8_t cfg; double x, r_pt, temp; if (ads1110_read_raw(code, cfg) ! 0) { return NAN; } // 越界保护PT1000短路或开路时读数会接近满码 if (code 32000 || code 100) { return NAN; } x (double)code / 32768.0; r_pt RREF * x / (1.0 - x); temp pt1000_res_to_temp(r_pt); // 校准修正默认不生效 temp (temp - zero_offset) * gain_corr; return temp; }注意一点这个换算公式成立的前提是输入信号幅度没有超过ADC满量程。PGA1时只要输入电压不超过ADC允许的正向满量程公式就能一直保持线性。做原型验证的时候建议把r_pt和temp同时通过串口打印出来如果电阻值和万用表量到的偏差超过正常范围先回头查电路不要急着调软件。5. 零点校准、斜率校准与实测验证5.1 校准思路先校传感器再校系统很多项目只做所谓“软件校准”就是在测温代码里加一个固定偏移量。这个办法只能修正偏置修正不了斜率。真正要做的是两点校准一点修正零位一点修正增益。校准之前先明确一个原则校准的目的是让系统输出等于“真实温度”不是让ADC码等于理论值。因为误差可能来自传感器本身、分压电阻温漂、ADC增益误差等多个环节把它们揉在一起做端到端校准效果最好。我推荐用精密电阻箱代替PT1000做校准。把PT1000从电路上拆下来电阻箱接到原来的位置分别设定两个标准阻值。这样做的好处是重复性好、不受环境温度影响尤其适合没有恒温槽的开发者。5.2 冰水浴和恒温槽的实际操作没有电阻箱的情况下冰水混合物是最容易实现的零点基准。冰屑加纯水比例大概2:1充分搅拌后等5到8分钟等冰水达到热平衡温度大约在0.01℃到0.05℃之间。把PT1000探头放进去尽量不碰杯底和杯壁连续记录1分钟温度取平均值。第二个点我建议用恒温槽设定在80℃或100℃如果条件不够用精密温度计加保温杯做参考也行。高精度参考温度计至少要0.05℃级普通工业温度计只会把校准带偏。校准计算其实很简单。设已知标准温度为t1、t2系统未校准时读数为r1、r2则gain_corr (t2 - t1) / (r2 - r1) zero_offset t1 - r1 * gain_corr把这两个系数代回测温代码系统的端点误差就归零了。中间温度点的残余误差取决于传感器本身的非线性对于Class A级PT1000整个-20到150℃范围的残余误差通常不超过0.1℃。5.3 实测数据长什么样下面这组数据来自我的一版原型板3.3V供电2.2kΩ分压电阻PGA116点滑动平均。参考温度由恒温槽配0.05℃级标准铂电阻温度计提供。恒温槽设定(℃)系统读数(℃)偏差(℃)0.020.00-0.0219.9819.96-0.0239.9440.010.0759.9659.92-0.0479.9179.980.0799.8699.80-0.06整组数据最大偏差0.07℃已经达到0.1℃级目标。需要注意这个数据是在恒温槽这种高传热环境中得到的。换成静止空气环境由于自热和空气对流影响实际误差会增大到0.1到0.2℃。想在不同介质中都守住0.1℃要么降低激励电流要么给传感器加导热外殼接触被测物。5.4 校准后一定要做24小时稳定性验证0.1℃级系统最怕长时间漂移。我见过不少原型在校准当时很准第二天再测偏了0.2℃原因大多是电阻刚焊接完处于残余应力释放期或者板子温升改变了PCB附近温度场。我的做法是校准完成后让系统通电老化24小时期间每5分钟记录一次温度。第二天看两个指标一是和标准温度计的偏差是否仍在0.1℃以内二是24小时内的漂移趋势是否单向。如果数据一直往上飘优先怀疑是板子局部发热或参考电阻温漂如果是一会儿上一会儿下考虑是不是环境温度波动或者探头没放稳。这一步看起来耗时但恰恰是很多“实验室能跑、现场不能用”的系统缺少的一环。6. 调试实录五个常见的坑按出现频率排序6.1 读数跳变幅度大先查电源和接地点现象是温度读数在0.3℃甚至1℃范围内乱跳滑动平均也救不回来。这种问题八成出在电源和地上。开关电源供电时如果ADC供电脚没有加去耦电容或者PT1000分压电路和ADC的GND走了两条回路就会产生几十毫伏的地电位差。排查方法把示波器探头夹在A0对GND之间看波形上有没有高频毛刺。有毛刺就在VDD端加一个10Ω电阻加100μF电解电容的π型滤波ADC附近VDD对GND再加100nF。地线方面确保分压电路、ADC、MCU的GND从同一个点引出或者用大面积覆铜做单点汇接。这个坑在原型飞线搭的板子上几乎必踩好在整改成本最低。6.2 读到的值接近满码32767有了这个现象先别怪传感器。分压电路算一遍如果PT1000短路A0电压等于3.3V超过PGA1时ADC的正向满量程读数会直接顶到32767附近PT1000开路A0被Rref拉到3.3V也是同一个结果。所以满码既可能短路也可能开路。排查时先用万用表量PT1000的直流电阻0℃附近应该接近1000Ω如果是0Ω或者无穷大传感器或接线问题。如果传感器阻值正常再看PGA设置。PGA被设成4或8时输入范围变小稍高一点的电压就可能饱和这时候要把增益调回1或者用软件把量程范围限制住。6.3 I2C偶尔读失败频率不高但很烦I2C读失败主要有两个原因上拉电阻太小或太大、总线上还有别的设备地址冲突。ADS1110在3.3V下2.2kΩ到4.7kΩ的上拉电阻一般比较稳妥。上拉电阻到10kΩ时总线电容一大脉冲沿就变慢偶尔就会丢数据。把I2C时钟降到100kHz以下绝大多数偶发失败都能解决。还有一个隐蔽问题如果连续读之前没有等待转换完成读到的会还是上一次的旧数据。连续转换模式下数据每个周期更新一次但I2C随时读都可能拿到正在更新的半格数据。稳妥的办法是读之前先看配置寄存器的BSY位或者干脆控制读取间隔大于1.5倍转换周期。我实测间隔加够之后再也没有出现过数据跳变。6.4 温度显示在某个点附近反复抖动如果滤波都开了、电源也干净但温度还是在一个点附近以固定节奏抖动我建议看一下是不是传感器探头本身在震动或者被测介质存在微小对流。这两个因素不是电路问题但它会让0.1℃级的系统“看起来不准”。验证方法很简单把探头固定住再等10分钟看数据。如果固定后数据稳了说明之前是物理环境扰动如果还抖再回头查电磁干扰。很多时候大家抱怨“0.1℃做不出来”其实是被周围几摄氏度的空气对流打败的。6.5 线阻和连接器接触电阻成为隐形杀手PT1000提高了基准电阻线阻影响相比PT100是降了一个数量级但连接器接触电阻依然不能忽略。普通的弹簧插簧、杜邦线母座接触电阻可能达到0.1Ω到0.3Ω对应误差0.03℃到0.08℃。这个误差在校准时可以被部分抵消但插拔几次后触点氧化接触电阻变了之前的校准就失效了。高精度应用里关键连接点一律焊接。必须要可插拔时选镀金端子并做机械锁紧。导线选屏蔽双绞线屏蔽层在单片机一侧单点接地可以同时解决线阻和感应噪声两个问题。如果你想继续升级到3线制、4线制消除线阻也是在这个基础上扩展思路不变。我在这个项目上踩过的坑差不多就是这些。做0.1℃级系统最深的感触是真正拉开差距的不是ADC芯片、不是传感器品牌而是你有没有把自热、电源、校准、连接可靠性这些“不起眼”的环节当回事。把高低电平算得再精测温探头悬在空气中自己发热0.2℃等于前面全白干。所以我的经验是别急着写代码先把探头固定好、把供电滤波做好、把校准步骤走一遍数据自然就稳了。后续如果你想把这个方案改成多通道测温用ADS1110的兄弟芯片做I2C多地址扩展就行电路和软件框架基本不用动。
返回列表