ARTICLE DETAIL

资讯详情

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

PT100测温系统实战:从惠斯通电桥到单片机校准算法

PT100测温系统实战:从惠斯通电桥到单片机校准算法 1. PT100的决定性优势为什么我在测温项目里弃用NTC换铂电阻1.1 从一次失败的NTC方案说起做温度采集板时头一回把PT100的信号链从惠斯通电桥一路做到单片机代码踩的坑比想象中多。去年产线上一块三路测温板读数飘得厉害最后发现不是PT100的问题而是电桥参考电阻温漂惹的祸。这篇文章就把我当时如何选桥臂电阻、配仪表放大器、写单片机采样与校准代码的完整过程写出来希望对打算用PT100做测温项目的朋友有帮助。先说为什么换掉NTC。NTC热敏电阻价格便宜、灵敏度高1Ω的阻值随温度变化能到几十欧听起来很香。但它的致命伤有两个一是阻值-温度曲线是强指数关系想覆盖宽量程必须做多点标定二是批次离散性大同一个型号焊上去20℃时阻值都可能差出好几个百分点。而且NTC的长期稳定性也一般用久了阻值会漂。做工业级温度采集时这三个特性叠加基本可以劝退了。PT100正好相反它的核心价值在于标准性强、重复性好、长期稳定。铂电阻由IEC 60751标准约束0℃时基准阻值100Ω温度每升高1℃阻值大约增加0.385Ω。阻值变化很微弱这既是它的劣势也是它能保证精度的原因——纯金属铂的物理特性决定了它的漂移小、一致性好不用像NTC那样逐颗标定。1.2 三种测温传感器的选型对比如果手头正在纠结用哪种温度传感器我用实际项目经验给你列个对照表帮助快速判断。类型灵敏度线性度互换性典型精度主要麻烦NTC热敏电阻很高差差±0.5~1℃批次离散大不适合宽量程热电偶电压信号弱非线性一般±1~2℃需要冷端补偿参考端处理麻烦PT1000.385Ω/℃较好好B级±0.3℃A级±0.15℃微弱信号需要放大与调理电路热电偶能干到上千摄氏度这是PT100比不了的但在-50℃到300℃这个常见区间PT100的稳定性和线性优势很明显。关键是热电偶还要做冷端补偿那个补偿点本身就会引入误差处理不好温度不准。PT100不需要任何补偿电路测出来就是真实的电阻变化后续靠查表或者多项式就能还原出温度。1.3 精度等级选择A级和B级怎么取舍再补充一个选型细节。PT100探头会标A级、B级、1/3B级等精度等级不是越贵越好得看系统整体误差分配。以0℃附近的B级为例允许偏差是±0.3℃A级是±0.15℃1/3B级做到±0.1℃以内。我的习惯是控制精度目标在±0.5℃以上的场合B级完全够用目标在±0.2℃左右才上A级。真正决定最后精度的往往不是探头本身而是后面的电桥参考电阻、运放失调、ADC参考电压和校准质量。我见过不少项目买了A级探头结果参考电阻用普通贴片电阻温度一升高读数跟着飘白白浪费钱。2. 惠斯通电桥的参数计算从0℃零点到满量程增益2.1 为什么偏偏要用电桥PT100的阻值变化只有0.385Ω/℃如果直接用电阻串联分压把PT100和一个固定电阻串在一起取中点电压电源电压一波动读数就会跟着动。电桥的价值在于差分输出——把两个支路的电压相减共模干扰被抵消掉电源波动对两个支路的影响基本一致所以差电压对电源变化不敏感。另一个原因是PT100信号本身太微弱。0℃到100℃只有38.5Ω的变化如果不做差分处理直接单端测信号里混进的噪声很难过滤。电桥把电阻变化变成毫伏级差分电压再送到仪表放大器放大信号质量会干净很多。2.2 桥臂电阻取值与输出范围的计算搭建最常用的四臂电桥两个固定电阻R1和R2相等取1kΩ或更大目的是限制流过PT100的电流。上支路中点电压是稳定的分压值下支路中点电压随PT100阻值变化。我实际用的配置是R1R21kΩ参考电阻R3120ΩPT100接在R3对面那个桥臂。输出差分电压公式为Vout VCC × (R2 / (R1 R2) - Rpt / (R3 Rpt))当R1R2且VCC3.3V时第一个分式正好是0.5。代入不同温度下的阻值可以得到下面这张表温度PT100阻值VoutR3120ΩVoutR3100Ω0℃100.00Ω150mV0mV50℃119.40Ω-9mV-129mV100℃138.50Ω-118mV-266mV这里有个关键选择R3取120Ω时0℃输出为正避免运放输出靠近0V时的非线性区R3取100Ω时0℃正好平衡但输出会变成负电压处理起来麻烦。我倾向用R3120Ω然后用一个偏置电压把整段信号抬到ADC能采的正电压范围或者直接用带双极性输入的ADC。2.3 增益怎么算以0~100℃量程为例假设测温范围0℃到100℃用R3120Ω0℃时输出150mV100℃时输出-118mV峰峰跨度约为268mV。如果ADC参考电压是3.3V想让信号尽量吃满ADC量程增益至少是3.3V/0.268V≈12倍。实际取10倍左右留出余量防止放大后信号削顶。用AD620这类仪表放大器时增益公式是G49.4kΩ/Rg1。要得到10倍增益Rg49.4kΩ/(10-1)≈5.49kΩ取标称5.6kΩ实际增益约9.8倍。这是我在面包板上实测出来的经验值选放大倍数时不要贴得太满否则探头老化、温度过冲时信号容易超出ADC范围。2.4 电桥设计的四个隐蔽深坑这里把我的踩坑记录集中列一下这四个问题几乎每个新手都会遇到。参考电阻R3选了普通贴片电阻。普通电阻温漂几百ppm/℃环境温度变化10℃就能让读数偏出0.5℃以上。必须用低温漂精密电阻我推荐0.1%精度、25ppm/℃起步想做好就上5ppm的金属箔电阻。电桥激励和ADC参考不是同一个源。PT100测量的美妙之处在于可以做成比率测量电桥电源和ADC参考都用同一个3.3V电源波动会同时影响电桥输出和ADC参考最终计算结果基本不受电源影响。如果电桥用3.3V、ADC参考用另外的基准那么两个源的噪声就都会进入结果。流过PT100的电流太大。电流越大PT100自身发热越明显这就是自热效应。我用R1R21kΩ、3.3V供电时PT100支路电流约2.7mA悬空测试时温度读数会虚高0.3℃左右。后来把R1、R2换成2.2kΩ电流降到1.3mA左右才压住了。稳妥的做法是把电流控制在0.5~1mA以内。长导线电阻直接叠加进测量结果。如果PT100离主板有几十米导线电阻可能有好几欧姆这对0.385Ω/℃的PT100来说是非常大的误差。短距离可以用两线制超过1米建议用三线制更远就用四线制恒流源方案。3. 硬件落地的几个关键判断参考电阻、自热、走线与接地3.1 元件清单与实测配置下面这份清单是我实际使用过的组合可以直接抄作业。PT100探头A级或B级明确测温范围和引线长度精密参考电阻R3120Ω0.1%精度25ppm/℃低温漂R1、R22.2kΩ0.1%精度普通金属膜即可仪表放大器AD620或INA128增益电阻5.6kΩ单片机STC15F2K60S2后续量产换过STC8系列ADC方案A用STC内置10位ADC方案B用ADS1220电源3.3V低纹波LDO电桥、仪表放大器、ADC参考共用去耦电容每个运放电源脚放0.1μF陶瓷电容靠近芯片引脚面包板可以先验证逻辑但我不建议在面包板上做高精度测试。PT100信号是毫伏级面包板簧片接触电阻和长跳线天线效应都会让数据乱跳。我通常是面包板跑通代码框架然后立刻画一块小板子四层板或双层板都行注意地平面完整。3.2 供电、接地的具体做法供电顺序是外部电源进板先经过LDO降到3.3V再用电感或者磁珠分成模拟3.3V和数字3.3V。电桥和ADC的参考电压都从模拟3.3V取。模拟地和数字地在PCB上单点连接连接点放在ADC芯片下方。这样数字开关噪声就没有机会在电桥输出回路里形成环路电流。电桥到运放之间的走线要短尽量走内层或者包地。如果要用飞线连接外部PT100探头导线采用双绞线信号地与屏蔽层单端接地。我在现场排过好几次故障最后发现都是因为信号线和24V继电器输出线平行走了半米噪声全耦合进来了。3.3 自热效应和三线制接线自热效应不太起眼但最容易让实测温度偏高。PT100探头本体是有热阻的如果内部电流产生的功率没法及时散掉探头测到的温度就比环境高。公式很简单PI²×R。0.5mA时在100Ω上耗散0.025mW温升可以忽略2mA时耗散0.4mW探头温升可能到0.1~0.5℃。所以设计目标就是把电流压到1mA以下同时避免把电流给得越低越好因为信号太弱也会被噪声淹没需要平衡。三线制接法的原理本质上是用一根线把导线电阻抵消掉一根线向PT100供电流另外两根线分别接在PT100两端分别测量电压和参考电阻。由于电流线和电压线分开电流在导线上的压降不会进入差分测量路径。实际接线时三根线要等长、同等材质否则导线电阻差还是会带来误差。4. 单片机里的转换算法从ADC原始码到温度值的三种做法4.1 ADC采样与数字滤波先别急着换算很多代码把每次ADC读到的原始值直接丢进温度公式出来的数据能跳得你怀疑人生。原因很简单运放放大了信号的同时也放大了噪声ADC单次采样的结果包含了大量随机噪声。我的做法是先做软件滤波。常用滑动平均或者中值平均。比如连续采32次去掉最大值和最小值再对剩下30个点求平均。这样能让10位ADC的有效分辨率稳定很多。实测下来原始数据跳动±5个LSB滤波后能压到±1个LSB以内。代码可以这样写#define FILTER_N 32 unsigned int adc_filter(unsigned char channel) { unsigned char i; unsigned int max 0, min 4095; unsigned long sum 0; for (i 0; i FILTER_N; i) { unsigned int val adc_read(channel); if (val max) max val; if (val min) min val; sum val; } return (unsigned int)((sum - max - min) / (FILTER_N - 2)); }注意STC15内置ADC是10位读回结果是0~1023。如果用16位ADC方案把数据类型改成unsigned short甚至unsigned long别在类型转换上栽跟头。4.2 两点校准消除运放失调和电阻容差电桥的参考电阻有0.1%误差仪表放大器有输入失调电压ADC也有零偏。这些误差叠加起来会让同一个温度点测出来的代码跟理论值差出不少。两点校准就是为了把这些固定偏差一次性消掉。具体做法是准备两个标准温度点。我常用0℃冰水混合物和100℃沸水。等探头稳定后记录两个ADC平均码值分别记为code0和code100。之后每次采样得到的code通过线性映射转成温度float code_to_temp(unsigned int code) { return (float)(code - code0) * 100.0f / (float)(code100 - code0); }这里的100.0f对应校准温差的100℃。如果你的标准点不是0和100改成实际温度差就行。这种线性映射在0~100℃内最大误差大约0.3~0.4℃因为PT100本身的非线性被忽略了。想要更高精度就得用下面的查表或多项式。4.3 查表加线性插值8位单片机的最优解PT100的电阻-温度关系用10℃间隔存一张表然后线性插值这个做法在8位单片机上非常友好不用浮点运算也能保持较高精度。我用的表是从0℃到100℃每10℃一个点对应PT100标准电阻值。数组如下#define TABLE_N 11 const float rtd_table[TABLE_N] { 100.00, 103.90, 107.79, 111.67, 115.54, 119.40, 123.24, 127.07, 130.89, 134.70, 138.50 };根据测得的电阻值R在表里找到相邻区间线性插值得到温度float rtd_to_temp_table(float R) { unsigned char i; float t_lo, t_hi, r_lo, r_hi; if (R rtd_table[0]) return 0.0f; if (R rtd_table[TABLE_N - 1]) return 10.0f * (TABLE_N - 1); for (i 0; i TABLE_N - 1; i) { if (R rtd_table[i] R rtd_table[i1]) { r_lo rtd_table[i]; r_hi rtd_table[i1]; t_lo 10.0f * i; t_hi 10.0f * (i1); return t_lo (R - r_lo) * (t_hi - t_lo) / (r_hi - r_lo); } } return -1.0f; }每10℃一段的线性插值误差远小于PT100本身的B级偏差足够大多数场景用。想要覆盖负温区间把表头扩展成-50℃、-40℃这些负值点即可逻辑不用改。4.4 用Callendar-Van Dusen公式做全量程换算查表法精度已经不差但如果不想维护一张大表又需要全量程连续输出CVD公式是更好的选择。0℃以上时R(T) R0 × (1 A×T B×T²)其中R0100ΩA3.9083×10⁻³B-5.775×10⁻⁷。这个二次方程可以直接解单片机里写个求根函数#include math.h float rtd_res_to_temp_cvd(float R) { float a 100.0f * (-5.775e-7f); float b 100.0f * 3.9083e-3f; float c 100.0f - R; return (-b - sqrtf(b*b - 4.0f*a*c)) / (2.0f*a); }这个函数在0~300℃区间误差可以做到0.01℃量级。要注意0℃以下时CVD公式要加入一个额外的C项公式形态会变负温区间我更推荐直接用查表法。另外在STC15这类不带硬件浮点的单片机上运行平方根运算单次计算大约几百微秒对温度采样这种低速场景完全够用。5. 附上两套可跑代码STC内置ADC方案与ADS1220高精度方案5.1 方案ASTC15内置10位ADC低成本快速验证如果只是做原型验证STC15的10位ADC加运放方案是最快路径。STC15系列的ADC用ADC_CONTR寄存器控制读取高位结果存ADC_RES低位结果存ADC_RESL拼成10位。#include STC15F2K60S2.h #define ADC_POWER 0x80 #define ADC_START 0x08 #define ADC_FLAG 0x10 void adc_init(void) { P1ASF 0x07; // 将P1.0~P1.2设置为模拟输入 ADC_CONTR ADC_POWER | 0x60; // 开启ADC电源选择时钟分频 delay_ms(1); } unsigned int adc_read(unsigned char channel) { ADC_CONTR ADC_POWER | ADC_START | (channel 0x07); while (!(ADC_CONTR ADC_FLAG)); ADC_CONTR ~ADC_FLAG; return (unsigned int)(ADC_RES 2) | ADC_RESL; }主循环里做的事情就是滤波、校准、查表最后通过串口或者数码管输出。整个工程结构很清爽void main(void) { unsigned int code_val; float rtd_res; float temp; adc_init(); uart_init(); while (1) { code_val adc_filter(0); // 多路选择P1.0对应通道0 rtd_res code_to_res(code_val); // 根据校准和增益换算电阻 temp rtd_to_temp_table(rtd_res); // 查表插值 printf(Temp: %.1f C\\n, temp); delay_ms(500); } }这里code_to_res函数需要你把电桥输出电压、运放增益、ADC参考电压和校准点一起换算成电阻值。最简单的办法是用两个已知电阻做两点校准反推系数k和b然后rtd_res k * code_val b。5.2 方案BADS1220实现0.1℃级别精度如果项目要求0.1℃稳定度我会直接上ADS1220。这是一颗24位Δ-Σ ADC内置PGA和两个可编程恒流源专门为RTD测量设计。使用比例测量接法电流源流过PT100和一个精密参考电阻RREFRREF上的电压同时作为ADC参考电压。这样一来电源漂移、电流源漂移都被自动抵消了。典型配置是IDAC电流设为500μARREF取1.5kΩPGA增益16倍差分输入接AIN0和AIN1。SPI读取转换结果的框架如下unsigned long ads1220_read(void) { unsigned long raw 0; ADS1220_CS 0; while (ADS1220_DRDY); // 等待转换就绪 raw (unsigned long)spi_read_byte(); raw (raw 8) | spi_read_byte(); raw (raw 8) | spi_read_byte(); ADS1220_CS 1; return raw; }把转换码换算成PT100电阻float ads1220_to_rtd(unsigned long raw) { float rref 1500.0f; // 参考电阻1.5kΩ float gain 16.0f; // PGA增益 return (float)raw * rref / (8388608.0f * gain); }ADS1220的寄存器配置必须对着数据手册来重点是把恒流源选择到正确的引脚参考电压选择为外部参考。不同板子的配置差异主要在IDAC电流和PGA增益建议按实际探头引线长度和量程调整。5.3 代码层面的几个工程陷阱第一STC内置ADC的参考电压其实就是VCC。如果你的3.3V LDO精度一般那么绝对温度就会有偏差。办法是保留校准流程或者把ADC参考切换到内部高精度带隙基准具体看型号是否支持。第二很多STC系列单片机C语言代码跑着跑着就复位有人怀疑是不是没有堆栈。这里说明一下51单片机的C语言是有堆栈的只是栈空间默认在IDATA区顶部空间极小通常只有几十字节。如果函数嵌套太深或者定义了较大的局部数组栈很容易溢出然后程序乱飞。我在代码里只用了两层函数调用局部变量也尽量用全局数组复用规避这个问题。第三校准参数一定要存到EEPROM或者Flash的专门区域不能每次上电重新校准。我把code0、code100这些参数放在最后校准后存起来主程序上电时先读参数再跑。参数异常时应输出错误码别让系统拿一组错误系数算温度。6. 实测排查记录读数漂移、偏低偏高和校准经验6.1 案例一环境温度一变读数跟着变我调试一块板子时发现早上校准好是25℃到中午环境温度升到30℃之后读数变成了27℃。排查了很久问题出在参考电阻R3上。我最初用的是普通0805贴片电阻温漂大约300ppm/℃。12Ω误差算下来5℃环境变化轻松带来上欧姆的阻值变化再叠加PT100的0.385Ω/℃误差自然放大。排查的方法是用万用表同时监测电桥输出和参考电阻发现环境温度变化时参考电阻两端电压明显漂移。换成25ppm低温漂电阻后读数稳定多了。6.2 案例二探头悬空与插入水中读数不一致探头悬空时显示26℃插入20℃的恒温水槽中却显示20.4℃悬空状态虚高明显。这是自热效应加上散热条件不同造成的空气中散热差PT100自身发热无法散去温度自然偏高。解决方式是降低激励电流后来我把流过PT100的电流从2.7mA降到0.9mA悬空和浸水之间的差距从0.6℃缩小到0.15℃。凡是遇到探头读数偏高且在不同介质中偏差不同的情况优先怀疑自热。6.3 校准实操心得冰水浴与电阻箱的选择做两点校准时0℃的冰水混合物是最廉价的基准。注意要用碎冰加少量水充分搅拌后等温度稳定再把探头密封好放进去等读数不再变化了再记录。沸水校准则要留意当地大气压对沸点的影响海拔不同沸点有差异。想更省心我建议买一台0.01%精度的电阻箱直接模拟出标准电阻值不需要准备热水冷水校准时把PT100换成电阻箱拨到对应阻值就行。校准顺序也要固定先校零点再校满度再回到零点复核。如果两个零点读数不一致说明斜率系数有问题或者电路有严重非线性不能直接取平均值糊弄过去。6.4 最终实测效果整套电路和代码调通之后我做了一个72小时连续运行测试恒温箱设定在85℃每30秒记录一次串口输出的温度值。经过滑动滤波和两点校准后最大偏差在±0.15℃以内折算成阻值误差约0.06Ω。虽然还达不到三线制加高精度ADC的0.02℃水平但对大多数温控和采集项目来说已经完全够用。后来我又在多路测温项目中复用了这套代码把电桥、运放、ADC参数封装成了独立模块。每次换量程只需要重新算一遍桥臂电阻和增益其他逻辑几乎不用动。这也算是我从一堆折腾里沉淀下来的最大心得——测温系统想要稳定靠的不是某一个高端器件而是把电桥激励、参考电阻、零点校准这串链条上的每一环都想明白。
返回列表