资讯详情

资讯详情

PIC18LF45K80与单总线传感器实现本地远程多点测温

做暖通控制器这几年我发现自己被客户问得最多的不是温度准不准而是为什么控制器上读的温和风管远端测点对不上。这个项目里我索性把问题拆成两半处理控制器板级温度交给 PIC18LF45K80 的内部温度指示器机组各处和房间里的温度统一用单总线数字传感器 PJ85718DM 分点挂测。主控选这颗 MCU主要是看中它在低电压工作状态下还带 12 位 ADC 和 ECAN 模块既能读本地温度又能通过单总线把远程温度收回来再通过 CAN 把数据交给上层。这套方案没什么高深技术但对嵌入式和 HVAC 领域的开发者很有参考价值尤其是想用最少硬件成本实现本地远程多点测温的朋友可以照着这套思路直接搭。1. 为什么要用这两颗料从远近都要测温这个需求说起1.1 一片K80能同时干三件事采集、控制、通信PIC18LF45K80 这颗片子拿到手的第一感觉是什么都有点但都不算夸张1.8V 到 3.6V 的低压工作范围32KB Flash、3.6KB RAM、还有 1KB 数据 EEPROM12 位 ADC 够做模拟量采集ECAN 模块直接支持 CAN 2.0B。对我来说最关键的其实是 CAN 和 EEPROM 这两样。HVAC 现场和实验室完全不一样。一套空调机组分布在机房、风管、楼层末端控制器和控制器之间动辄几十米上百米。用 RS485 当然也能组网但相比之下 CAN 的差分信号抗干扰能力、多主机仲裁机制、报文优先级设计更适合这种分散场景。K80 系列自带 ECAN 模块意味着我不需要额外挂一颗 CAN 控制器只需要在外面配一颗收发器芯片成本和 PCB 面积都省下来了。EEPROM 的价值在系统调试时体现得最明显。单总线温度传感器每个都有唯一的 64 位 ROM 码这个码要在现场安装后逐一扫描出来。如果每次上电都重新扫描冷启动时间会拖得很长而且现场传感器突然掉一个整个扫描过程可能卡死。把 ROM 码固化到 EEPROM 里上电直接点名读取系统行为完全可控。这些需求和嵌入式系统常见的采集-控制-通信三段式结构刚好对上了一片 K80 全包。1.2 PJ85718DM的定位是数字温度传感器而不是热敏电阻以前做测温很多人第一反应是 NTC 热敏电阻加 ADC。这方案便宜但问题在调试阶段全暴露出来每个电阻的 B 值有离散性长线缆带来的压降和干扰直接影响 ADC 采样结果而且不同厂家的 NTC 查表曲线还不一样软件里得维护一堆参数。PJ85718DM 这类单总线数字传感器把麻烦挪到了芯片内部。它自己完成温度到数字量的转换通过一根 DQ 数据线把结果发给控制器原理上等于一根线传数据、芯片内部做测量。这类器件几乎都兼容市面上最常见的 18B20 类命令生态指令集、时序、寄存器布局都差不多复位、存在脉冲、写入命令、读取暂存器、CRC 校验。从软件角度来说这意味着网上大量成熟代码可以直接移植调试工具也现成。实际工程中我更看重的是它的多点接入能力。每个传感器烧录了唯一的 ROM 编号所有传感器可以并联挂在同一根数据线上控制器用 ROM 匹配命令点名读取互不干扰。对于一个空气处理机组需要测回风、送风、盘管进出水、室外温度的场景一根两芯线就能串完这省下来的线材、穿管和人工成本在工地上是非常可观的。1.3 本地温度和远程温度在我这里的定义这个标题里的本地和远程我在项目里是这么界定的本地温度指控制器电路板所在环境的温度包括 MCU 自身结温和机柜内空气温度它反映的是设备自身健康状况远程温度指被控对象和空间里的温度比如风管、房间、水管的温度它反映的是系统运行状态。这两类数据用途完全不同远程温度参与温控闭环本地温度则参与设备保护和散热控制。测温类别传感器来源用途采样频率本地温度MCU内部温度指示器或板载PJ85718DM机柜过热保护、散热风扇联动、传感器数据交叉校验每秒1~2次远程温度单总线PJ85718DM多点挂测温控调节、报警、能效计算每2~5秒循环一次这步定义非常关键因为后续所有硬件布局、固件逻辑都是围绕这个分工展开的。如果一开始不把哪路温度归保护、哪路归控制说清楚写代码时很快就会乱。2. 系统怎么分工本地结温、远程测点与CAN节点网2.1 内部温度指示器不花钱的板级保护传感器PIC18 K80 系列有内部温度指示器原理是输出一个随芯片结温线性变化的电压接到内部 ADC 通道上。配置流程不算复杂使能温度指示器模块选择 ADC 参考电压然后把对应的内部通道采样转换。得到 ADC 码之后按照数据手册给出的电压-温度斜率换算成摄氏度。这里要提醒一下内部温度指示器的绝对精度并不高芯片不同批次、不同工作电压都会让偏移量有差异。我在项目里从来不拿它当精密温度计用而是做三件事检测机柜是否过热比如结温超过 85℃ 就强制提高散热风扇转速和板载的 PJ85718DM 做交叉比对如果两者偏差超过 20℃说明传感器导热路径有问题触发维护报警作为 MCU 工作环境的长期记录判断设备是否长期在高温降额状态下运行。如果不想依赖内部温度指示器的精度也可以直接在 PCB 上焊一颗 PJ85718DM 当板级本地传感器把传感器贴在容易发热的功率器件附近。我实际做混合方案内部温度指示器负责快速结温保护板载传感器负责环境温度记录两者互补。2.2 一根双绞线上的单总线多点布局远程温度部分我把每台机组的所有测点接头并联到同一根数据线上。单总线协议的结构是主机通过时序窗口逐位读写传感器在收到转换命令后自行完成测量结果放在暂存器里等主机来取。每个传感器的 ROM 码保证了总线上的每一个器件都可以被独立寻址。现场一套小型空气处理机组我通常挂 4 到 8 个测点回风温度、送风温度、盘管进水温度、盘管回水温度再加上室外环境温度。这些测点的共同点是位置分散、线缆走线路径各不相同但都通过一条总线汇总到控制器。安装调试时先逐个单独连接传感器把每个传感器的 ROM 码读出来并记录正式运行时控制器对已知 ROM 码逐一匹配读取不加搜索总线逻辑可靠性和速度都有了保障。单总线还有一个容易被忽略的工程点总线分支不应太复杂。实测下来多个传感器在一条主干上串糖葫芦式连接比每个传感器分叉一根线到总线要稳定。分支太长会造成信号反射波形上就是边沿变缓、振铃严重后面读回来就是乱码。后面专门有一节讲这个坑。2.3 用ECAN模块把各节点的温度汇到中央远程温度在单机上读出来只是第一步HVAC 场景里还要把不同机组的温度数据汇到中央。我在每台机组的控制器上配了 CAN 收发器ECAN 模块经过初始化之后就按固定周期上报数据。报文规划很直白每个节点有一个基础标识符报文数据段的前两个字节是节点编号和测点编号后面是温度原始值。比如中央控制器收到某个报文先解析节点号再解析测点号就知道这路温度来自哪台机组的哪个位置。总线速率我一般配置为 500kbps在楼内几百米的布线范围内足够使用。一开始做这个方案时有人问我为什么不用 RS485 把所有温度传感器直接拉到中央控制器原因很简单温度传感器的单总线协议不适合跨越长距离而且把每个房间的模拟或数字量测点全拉回机房线缆数量和施工难度都不现实。让分布在现场的控制器就近采集温度、再用 CAN 往中央汇总才是符合实际施工架构的做法。3. 硬件决定与现场布线上拉电阻、供电方式和线缆防护3.1 上拉电阻的取值不是玄学是边沿时间问题单总线空闲时靠一个上拉电阻把数据线拉到高电平传感器和主机通过拉低数据线来发送信号。这个上拉电阻的取值直接决定了数据线的上升沿时间。阻值越大上升沿越慢阻值越小传感器拉低时需要承载的灌电流越大。最常用的起步值是 4.7kΩ。如果你只是在一个实验板上测一堆传感器线缆很短4.7kΩ 完全够用。当现场线缆变长、传感器数量增多总线寄生电容也跟着涨再用 4.7kΩ 就会发现上升沿明显变缓严重时传感器传回来的 1 也会被误读成 0。此时可以把上拉电阻降到 2.2kΩ 甚至 1kΩ。但不要无脑降低于 1kΩ 会让传感器在拉低总线时承受过大的灌电流影响输出低电平的可靠性。我的做法是PCB 上预留一个 0402 电阻位先按 4.7kΩ 装现场实测波形后再根据线长和节点数调整。调试时判断标准很简单用示波器看 DQ 引脚的上升沿如果从低到高的跃变时间超过 1µs就该把阻值降一档。3.2 为什么不建议用寄生供电挂远程测点单总线传感器支持两种供电方式外部供电和寄生供电。寄生供电模式下传感器在总线为高电平时偷电给内部电容充电转换期间靠电容储能维持工作这样远端传感器只需要数据线和地线两根线省一根电源线。但 HVAC 现场恰恰是最不适合寄生供电的地方。电动阀动作、接触器吸合、变频器启停这些都会在供电线上制造剧烈的电压跌落和尖峰干扰。寄生供电模式下传感器对供电电压跌落非常敏感一旦在温度转换过程中电容储能不足芯片直接复位数据要么不响应要么返回一个莫名其妙的温度值。所以我这里明确推荐三线制VDD、DQ、GND。传感器电源由控制器统一供给D 线单独走信号。三线制多跑一根线但换来的是温度转换过程的确定性在工地上这比省一根线值太多。屏蔽层要单端接地避免形成地环路。3.3 线缆、屏蔽与保护器件的安装经验温度传感器的信号线虽然不像模拟量那样对微弱干扰敏感但长距离传输时依然要走正经的布线规范。我的经验是传感器线用双绞屏蔽线和强电电缆分开穿管至少保持 30cm 间距屏蔽层在控制器端单点接地接入控制器的 DQ 线上加一个 100Ω 左右的串联电阻做阻尼再加 TVS 管防止静电和浪涌。还有一个细节容易被忽略不要随意把传感器线缆当作反正只有一根线所以无所谓来布置。实测中我遇到过因为线缆与风机动力线平行走了十几米导致每次风机高速档启动时温度读数跳变的情况。把线缆移开、加屏蔽、调上拉电阻三个措施一起上之后问题彻底消失。硬件层面的余量要给足后面固件才能省心。防护措施具体做法解决的问题双绞屏蔽线信号线双绞屏蔽层单端接地共模干扰、电场耦合DQ串联阻尼电阻100Ω串入减小边沿振铃TVS管数据线对地TVS静电、浪涌损坏传感器强弱电分离信号线与动力线间距30cm以上变频器、接触器干扰4. 固件核心在PIC上把单总线时序和温度换算写扎实4.1 时序参数先背下来再动手写代码单总线协议严格的点都在时序上。PIC18LF45K80 内部振荡器经过 PLL 可以跑到 64MHz指令周期是 62.5ns这意味着每条指令的执行时间都在几十纳秒量级完全有能力卡出单总线的微秒级时序但对延时实现的精确性要求很高。先从复位时序说起。主机要把数据线拉低至少 480µs然后释放并等待传感器的存在脉冲。存在脉冲是传感器在主机释放总线后 15µs 到 60µs 之间主动拉低 60µs 到 240µs。如果主机这边延时不准要么错过存在脉冲要么把不存在误判为存在。读写时隙的规则更细致写 1 的时隙是主机拉低 1µs 到 15µs 之后释放整个时隙持续 60µs 以上写 0 的时隙是主机把低电平保持 60µs 以上读时隙是主机拉低 1µs 到 15µs 后释放然后在时隙开始后的约 15µs 采样数据线。采样点太早传感器还没把线拉低读到的是 1采样点太晚可能进入下一个时隙。我在 XC8 环境下的实现方式是用宏定义_XTAL_FREQ 64000000UL然后直接用__delay_us()做微秒级延时。写时序和读时序的每个函数都临时关闭全局中断防止 CAN 中断或定时器中断插进来把时序拉长。单总线设备对时序漂移的容忍度只有几微秒关中断是最简单的保命手段。4.2 单点采集与多点点名读取的完整流程单点采集流程是理解协议的基础逻辑上就五步复位总线检测存在脉冲发送跳过 ROM 命令0xCC发送温度转换命令0x44等待转换完成再次复位发送跳过 ROM 命令发送读取暂存器命令0xBE连续读出 9 个字节。读出的前两个字节分别是温度值的低字节和高字节第 3、4 字节是报警上下限第 5 字节是配置寄存器最后一个是 CRC 校验字节。12 位分辨率下把两个字节拼成一个有符号 16 位整数除以 16 就是实际温度。比如读到 0x0550拼起来是 1360除以 16 就是 85.0℃。多点场景把跳过 ROM换成匹配 ROM先复位再发 0x55 匹配命令接着把目标传感器的 8 字节 ROM 码逐个发出然后才发转换或读取命令。这样总线虽然挂了多个传感器但每次只和指定 ID 对话。核心代码片段大概是这个风格// 以12位分辨率发起温度转换并等待完成 uint8_t ds_start_conversion(uint8_t *rom) { if (!ow_reset()) return 0; // 总线无响应 if (rom) { ow_write_byte(0x55); // MATCH ROM for (uint8_t i 0; i 8; i) ow_write_byte(rom[i]); } else { ow_write_byte(0xCC); // SKIP ROM } ow_write_byte(0x44); // CONVERT T __delay_ms(750); // 12位最大转换时间 return 1; } // 读取一次温度带回CRC校验 int16_t ds_read_temperature(uint8_t *rom) { if (!ow_reset()) return 0x8000; if (rom) { ow_write_byte(0x55); for (uint8_t i 0; i 8; i) ow_write_byte(rom[i]); } else { ow_write_byte(0xCC); } ow_write_byte(0xBE); // READ SCRATCHPAD uint8_t data[9]; for (uint8_t i 0; i 9; i) data[i] ow_read_byte(); if (ow_crc8(data, 8) ! data[8]) // 校验失败返回异常 return 0x8000; return (int16_t)((data[1] 8) | data[0]); }ow_crc8是单总线标准的 8 位 CRC 算法多项式就是 0x8C反射形式。CRC 校验这一行绝对不能省现场环境下总线偶尔受干扰是很正常的如果读回来的 9 个字节里出现了错误CRC 能拦住绝大多数情况。4.3 EEPROM里存什么ROM码、校准偏移与阈值PIC18LF45K80 有 1KB 数据 EEPROM我把它当成这个项目的现场数据库。规划出一个固定区域地址段划分成节点参数区、传感器列表区、校准数据和阈值区。调试时进行一次总线扫描把发现的所有传感器 ROM 码按顺序写入同时为每个测点预留一个带符号的校准偏移字节。校准这件事在 HVAC 里很实际不同传感器芯片之间存在系统偏差有的偏正 0.2℃有的偏负 0.3℃。现场校准时把传感器和标准温度表放在同一环境记录差值写入 EEPROM。运行时读温度时自动加上这个偏移几路测点的读数就能保持一致性。这个一致性在客户那里往往比绝对精度更重要。EEPROM 的写入要小心擦写寿命有限写入一个字节还要约 4ms 的等待。我的原则是只在调试模式下写 EEPROM正常运行固件一律只读。上电时把这块区域整体拷贝到 RAM之后所有读写都操作 RAM 镜像。我用的 EEPROM 地址规划大致如下表地址范围内容0x0000~0x0001本机节点地址0x0002~0x0003测点数量0x0010~0x002F传感器ROM码数组每测点8字节0x0030~0x0037各测点校准偏移0x0040~0x0041高温报警阈值0x0042~0x0043低温报警阈值这套设计让设备在现场换人维护也能快速上手调试助手只要进入校模式自动扫描、自动建档、自动写入普通电工也能完成传感器更换后的系统重新识别。5. 实测中的故障排查85℃假读、掉线与毛刺的完整处理过程5.1 85℃假读一半是时序问题一半是干扰问题第一次在机柜里跑整套系统时我遇到一个很典型的现象某些测点偶尔返回 85.0℃而且看起来很规律总是在压缩机继电器吸合的瞬间出现。查下来原因有两个层面。第一85.0℃ 这个值对应原始数据 0x0550恰恰是传感器上电复位后暂存器里的默认温度。传感器如果在上一次转换还没完成时被干扰复位主机再读取暂存器读到的就会是这个默认值。所以 85.0℃ 是传感器我又重新上电了的标志而不是真实温度。第二为什么偏偏这时复位示波器抓 DQ 波形发现继电器吸合瞬间总线高电平上叠加了一个明显的跌落尖峰。传感器的工作电压被瞬间拉低内部逻辑就复位了。虽然我用了三线制供电但电源线是从 24V 交流控制箱里引出来的整流滤波余量不足负载突变时电压跌得太狠。排查的过程很长但思路值得分享先复现问题再在关键节点量波形最后用排除法确认干扰源。最后我做了三件事给传感器供电加一个小容量储能电容、把信号线改成屏蔽双绞、上拉电阻从 4.7k 降到 2.2k。三管齐下之后85℃ 假读基本消失。固件层面也要兜底。我的读温度函数里做了三道检查CRC 必须通过温度必须在 -55℃ 到 125℃ 的合理范围内连续三帧读数要一致才接受。三道检查同时做完误读率降到了可以忽略的程度。5.2 分辨率与转换时间的取舍PJ85718DM 这类器件支持 9 到 12 位可编程分辨率。分辨率越高转换时间越长9 位时约 94ms10 位约 188ms11 位约 375ms12 位约 750ms。HVAC 温控系统对响应速度要求其实不高温度本身的变化就是分钟级的所以 12 位 750ms 的等待时间并不奢侈。但如果你有 8 个测点每个测点都等 750ms 再读下一个一轮巡检下来要 6 秒多。这个轮询周期对显示和报警还算可以对控制闭环就显得迟钝了。我的处理方案是全部传感器配置为 12 位分辨率但巡检时采用流水线方式——先给所有传感器依次发转换命令等到最后一颗转换完成后再依次读取所有传感器的暂存器。这样总时间从 N 颗传感器乘以 750ms 变成固定的 750ms 加读取时间8 点一轮巡检控制在 1 秒内。配置分辨率要通过写暂存器命令把配置寄存器写入对应的分辨率位然后把暂存器复制到传感器的 EEPROM 中保存。这个细节容易漏只是改了暂存器值断电后又会恢复默认。配套的复制命令一定要发否则现场掉电重启后所有传感器又退回 12 位默认值等你重新配置。5.3 滤波策略先去掉毛刺再谈平滑温度信号本身是慢变量但单总线上偶尔的干扰会产生一个明显跳变比如从 23.5℃ 突然跳到 28.1℃。这种毛刺如果用滑动平均去处理会被平均掉一部分但如果连续两三次都采到同一个异常值滑动平均也可能被拉偏。我的策略是分两步。第一步做中值滤波每轮巡检对同一测点连采 3 帧取中间值作为有效值。这一步的目的就是干掉单点毛刺。第二步对有效值做一阶低通滤波比如filtered filtered * 0.8 new_value * 0.2用来压制随机噪声。两层滤波之后显示和控制用的温度曲线都非常干净。实测中有个反直觉的经验滤波不要做得太狠。有一次我把低通系数调成 0.95温度响应变得非常迟钝回风温度从 25℃ 降到 22℃ 的过程在界面上拖了一分多钟才走完操作员以为传感器坏了。后来我把系数分成两套控制用稍微灵敏感应一点的参数显示和趋势用重滤波参数各取所需。int16_t temp_filter(int16_t raw) { static int16_t history[3]; history[2] history[1]; history[1] history[0]; history[0] raw; int16_t median history[1]; // 三值取中 if (history[0] history[1]) { if (history[1] history[2]) median history[1]; else if (history[0] history[2]) median history[2]; else median history[0]; } else { if (history[0] history[2]) median history[0]; else if (history[1] history[2]) median history[2]; else median history[1]; } return median; }6. 从单机到HVAC组网温度数据怎么真正变成控制动作6.1 一套空气处理机组的测温点位设计举一个很常见的落地场景一台空气处理机组要给一个楼层送风需要监控回风、送风、盘管进出水和室外温度。五个测点各挂一颗 PJ85718DM都并联在控制器的一条单总线上。控制器放在机组电控箱内传感器分别装在风管、水管和室外防雨盒里。测点传感器位置数据用途回风温度回风管离机组约2米处代表房间平均温度做主控反馈送风温度送风管直管段计算送风温差防止过热/过冷送风盘管进水温度冷/热水供水管判断冷冻水/热水供应状态盘管回水温度冷/热水回水管配合进水温度计算换热温差室外温度屋面/外墙避阳处新风补偿、预冷预热判断这五个测点各管一件事缺哪一个都会让控制逻辑少一只眼睛。特别是盘管进出水温度差是判断换热器是否结垢、水流量是否正常的重要依据。只测回风和送风、不测水管温度系统能运行但出了问题往往只能用猜的。6.2 温度参与控制阈值、滞环和联动温度数据的最终价值在于控制动作。我在固件里没有用复杂的 PID 算法而是先用阈值加滞环把安全逻辑做扎实控制回路再往上层迭代。送风温度保护是第一步送风温度低于 10℃ 时关闭风机前电加热和加湿器防止冷风直接吹入房间高于 45℃ 时报警并限制风机转速。这里必须用滞环比如回温到 12℃ 才重新允许加热否则风机和阀门会在临界点反复通断几个小时就能把接触器磨坏。盘管回水温度还有一个独立功能是防冻保护。冬季机组停机时如果回水温度跌到 5℃ 以下即使机组处于停机状态也要强制打开水泵和电动阀防止盘管冻裂。这个逻辑必须在控制器上独立运行不依赖中央管理系统因为通讯故障时中央帮不上忙。本地结温也参与了联动夏天机柜内温度超过 60℃ 时控制器主动把散热风扇开到最高档同时降低 CAN 报文的发送频率减少自身发热这就是前面说的内部温度指示器真正的应用场景。各项控制参数我都以表驱动的方式放在 EEPROM 区域现场改阈值不需要重新编译固件。6.3 数据后续还能怎么用趋势与预警温度数据如果只是用来做实时调节其实浪费了一大半价值。我在这个项目里把各路温度和温差的历史值保存到外部存储后台定时拉取形成趋势曲线。两周之后再看曲线规律非常明显送风回风温差随着时间缓慢变大基本可以断定过滤网在积尘盘管进出水温差变小要么是水流量下降要么是换热效率变差。这类趋势判断不需要高级算法把每天同时段的数据对比就能给出预警。比如过滤网报警的判据是相同室外工况下送风温差比过滤器初始状态下降超过 30%。这个逻辑放在中央控制器里运行一个月后已经成功提前预警了两台机组的风机超温风险。再往远了说所有测点的温度数据通过 CAN 上报后统一格式接入楼宇管理后台就能做能耗分析、设备轮值优化和故障诊断。温度监测的价值不在于测出来而在于数据怎么参与判断。把判断逻辑设计好这套基于 PJ85718DM 和 PIC18LF45K80 的系统才算是真正用满了。我在实际项目里最大的体会是测温度本身不难难的是设计哪些读数可以信、哪些读数要丢弃的规则。CRC、范围检查、连续帧确认、中值滤波这几层兜底一个都不能省。最后分享一个小技巧给控制器留一个调试串口上电后逐帧打印每个测点的原始暂存器数据和 CRC 校验结果现场排查问题时能省掉大量猜疑时间——你永远不知道下一次出现奇怪温度的是哪根线上的哪个传感器。
觉得有用,分享给同行:

为您的企业打造数字门面

稳重轻奢商务风格,端正雅致视觉,长效耐看不易过时。

立即咨询 →