多彩编程 多彩编程MZPH · CODE BLOG
ARTICLE DETAIL

文章详情

深耕前端与后端开发技术的一线实战笔记与踩坑复盘。

基于PJ85718DM与PIC32MX470的嵌入式温度监测系统设计与实现

基于PJ85718DM与PIC32MX470的嵌入式温度监测系统设计与实现 1. 项目缘起与整体设计思路嵌入式温度监测这件事说起来简单做起来全是细节。我最早接触这类需求是在一个HVAC控制板的项目里当时的要求很朴素本地要能看到机房回风温度远程中控室也要能读到同一路数据精度要求±0.5°C以内采样周期1秒。听起来像是随便找个带I2C的温度芯片就能搞定的事但真正落地的时候才发现传感器选型、主控资源分配、本地显示刷新、远程通信协议、多路温度数据的对齐每一个环节都能卡住进度。这个项目用的是PJ85718DM作为温度采集前端PIC32MX470F512H作为主控MCU。先说说为什么是这两个器件。PJ85718DM是一颗支持本地和远程双通道的温度监测芯片本地通道测的是芯片自身所在位置的温度远程通道则通过外接一个二极管接法的三极管通常是MMBT3904这类来测量远端温度。这个“远程”能力在HVAC场景里非常关键因为控制板往往装在电控箱里而真正需要监测的是风管里、回风口或者水箱里的温度两者可能隔着几米甚至十几米的线缆。如果只用本地温度芯片测到的永远是电控箱内的温度跟实际被控对象差得远。PIC32MX470F512H这颗MCU在Microchip的PIC32MX系列里属于中端偏上的型号512KB Flash、128KB RAM带多个I2C、SPI、UART外设主频可以跑到120MHz。选它不是因为算力有多强而是因为外设够用、生态成熟、供货稳定。在这个项目里它要同时处理几件事通过I2C读取PJ85718DM的温度数据、驱动本地LCD或OLED显示、通过UART或RS-485把数据上传给上位机、还要留出足够的余量做温度补偿和告警逻辑。如果选一颗资源太紧的MCU后面加个滤波算法或者多挂一路传感器就会捉襟见肘。整体设计思路可以概括为“前端采集、中端处理、后端呈现”三层。前端就是PJ85718DM加上远端三极管负责把物理温度转换成数字量中端是PIC32MX470F512H负责轮询采集、数据校验、温度换算、告警判断和协议打包后端则是本地显示和远程通信两条路本地用OLED做实时刷新远程用Modbus RTU或者自定义的ASCII协议上传。这个分层的好处是每一层职责清晰调试的时候可以单独抓某一层的数据不会一锅粥。提示远程温度通道对三极管的选型和走线非常敏感。我试过用长导线接远端三极管结果读数比实际高了3°C多后来换成屏蔽双绞线并加了RC滤波才稳定下来。这个坑后面会详细说。2. 核心器件解析与硬件设计要点2.1 PJ85718DM的本地与远程通道工作机制PJ85718DM这颗芯片的核心价值在于它把本地测温和远程测温集成在一颗芯片里通过I2C接口输出。本地通道的原理是基于硅带隙电压芯片内部有一个对温度敏感的PN结温度变化时正向压降会变化芯片内部ADC把这个变化量化成数字量。远程通道则是把外部的三极管接成一个二极管形式用恒流源驱动测量其正向压降再根据理想因子和串联电阻做补偿计算。这里有一个关键参数需要理解远程通道的测温范围通常是-64°C到191°C本地通道是-40°C到125°C。HVAC场景里风管温度一般在-20°C到80°C之间两个通道都覆盖得住。但精度指标要分开看本地通道在25°C到100°C范围内典型精度是±0.5°C远程通道在25°C到100°C范围内是±1°C超出这个范围精度会下降。如果项目要求全量程±0.5°C那远程通道就需要做单点或者多点校准。芯片的I2C地址可以通过ADDR引脚配置通常接地或者接VDD得到两个不同地址这样同一路I2C总线上可以挂两颗PJ85718DM实现四路温度监测。这个特性在多回风口的HVAC系统里很有用不用额外加I2C多路复用器。2.2 PIC32MX470F512H的外设资源分配PIC32MX470F512H在这个项目里需要精打细算地分配外设。I2C1用来接PJ85718DM速率设在400kHz因为温度数据的更新率不需要太高400kHz足够在1ms内读完所有寄存器。UART1用来做调试输出UART2或者UART3配合RS-485收发器做远程通信。如果本地显示用的是SPI接口的OLED那SPI1也要占用。剩下的定时器用来做1秒的采集周期和看门狗。这里有一个容易忽略的点PIC32MX470F512H的I2C外设支持中断和DMA但在温度采集这种低频场景里用轮询方式反而更简单可靠。我试过用中断方式读I2C结果在RS-485通信繁忙的时候偶尔会丢中断后来改成主循环里定时轮询稳定性明显提升。当然如果MCU还要跑其他高优先级任务那就得用中断加状态机的方式避免阻塞。电源设计上PIC32MX470F512H和PJ85718DM都可以跑3.3V但PJ85718DM的远程通道对电源噪声比较敏感。我在PCB上给PJ85718DM单独放了一颗LDO输入用10uF钽电容加0.1uF陶瓷电容去耦远程通道的恒流源引脚旁边再并一颗1uF。实测下来电源纹波从30mV降到5mV以内远程读数的跳动从±0.8°C降到±0.2°C。2.3 远端三极管的选型与走线策略远端测温的三极管不是随便拿一颗就行。PJ85718DM的远程通道要求三极管接成二极管形式即基极和集电极短接发射极接芯片的D和D-引脚。选型时要注意几个参数理想因子要接近1.0串联电阻要小封装热阻要低。常用的MMBT3904理想因子在1.01左右串联电阻约0.5Ω算是比较合适的选择。如果追求更高精度可以用专门为远程测温设计的晶体管比如某些型号的串联电阻只有0.1Ω。走线方面D和D-必须走差分对尽量等长远离高频信号和电源线。如果距离超过30cm建议用屏蔽双绞线屏蔽层单端接地。我在一个项目里因为把D和D-分开走了不同路径结果读数偏差达到5°C后来改成并行走线并包地偏差回到0.3°C以内。另外远端三极管的基极-发射极之间可以并一颗100pF电容滤掉高频干扰但容值不能太大否则会影响测温响应速度。注意远端三极管的焊接温度不能太高回流焊峰值温度建议不超过260°C手工焊接时烙铁温度控制在300°C以内接触时间不超过3秒。过热会改变三极管的理想因子导致测温偏差。3. 固件实现与温度数据处理3.1 I2C通信协议与寄存器配置PJ85718DM的寄存器映射比较直观本地温度结果在高字节和低字节两个寄存器里远程温度也是类似。上电后需要先配置配置寄存器设置采样速率、滤波强度、远程通道使能等。采样速率有几种可选从1次/秒到8次/秒HVAC场景用1次/秒就够了滤波强度可以设成中等这样读数更稳。I2C读写时序上PIC32MX470F512H的I2C外设需要正确配置时钟分频。假设外设时钟是40MHz目标I2C速率400kHz分频值计算为40MHz/(400kHz×2)-149实际速率约392kHz在容差范围内。读写时要注意PJ85718DM的寄存器地址是8位的但温度数据是16位的高字节在前低字节在后低字节的高4位是标志位实际温度值需要右移4位再乘以0.0625°C。这里有一个细节远程通道的读数在未接三极管或者三极管开路时会返回一个特定的错误码通常是0x8000或者0x0000具体要看数据手册。固件里必须判断这个错误码否则会把错误码当成温度值显示出来比如0x8000右移4位是2048乘以0.0625就是128°C看起来像是高温告警实际上是传感器没接好。3.2 温度换算与校准算法温度换算的公式是温度 (原始值 4) × 0.0625。这个0.0625就是1/16因为PJ85718DM的分辨率是0.0625°C。本地通道和远程通道的换算方式一样但远程通道可能需要额外的补偿。如果发现远程读数和参考温度计有固定偏差可以在固件里加一个偏移量。如果偏差随温度变化那就需要做两点校准比如在0°C和100°C各测一次算出斜率和截距。我在实际项目里遇到过远程通道在低温段偏差大的情况后来发现是三极管的理想因子随温度变化导致的。解决办法是在固件里加一个分段线性补偿-20°C到20°C用一个补偿系数20°C到80°C用另一个。这个补偿系数不是拍脑袋定的而是用恒温槽标定出来的。如果没有恒温槽可以用冰水混合物和沸水做粗略标定精度要求不高的话够用了。3.3 本地显示与远程通信的协同本地显示用的是一个128×64的OLEDSPI接口刷新率设在5Hz左右。显示内容有本地温度、远程温度、告警状态和通信状态。刷新率不能太高否则会占用太多MCU时间影响I2C采集和RS-485通信。我试过把刷新率提到20Hz结果RS-485的响应延迟从10ms涨到50ms上位机偶尔会报超时。远程通信用的是Modbus RTU波特率96008位数据位无校验1位停止位。温度数据放在保持寄存器里本地温度占一个寄存器远程温度占一个寄存器单位是0.1°C。上位机轮询周期是500msMCU在收到请求后要在50ms内响应。为了满足这个时序固件里把Modbus处理放在主循环的高优先级位置I2C采集放在低优先级位置用状态机切换避免阻塞。提示RS-485收发器的DE引脚控制要小心发送完成后要及时切回接收否则会占用总线。我见过因为DE引脚切换延迟导致总线冲突的案例后来在固件里加了10us的延时才解决。4. 常见问题与排查技巧实录4.1 温度读数跳动大或偏差大这是最常见的问题原因通常有三个电源噪声、远端三极管走线干扰、I2C通信错误。排查时先用示波器看PJ85718DM的电源引脚纹波如果超过10mV就要加强去耦。然后看D和D-的波形如果有明显的高频毛刺就要加RC滤波或者换屏蔽线。最后用逻辑分析仪抓I2C波形看是否有ACK丢失或者数据错位。我整理了一个排查顺序表按这个顺序走基本能定位到问题现象可能原因排查方法解决措施本地温度正常远程跳动大远端走线干扰示波器看D/D-波形加屏蔽线、RC滤波本地和远程都跳动电源噪声示波器看VDD纹波加LDO、增加去耦电容读数偶尔跳变到极端值I2C通信错误逻辑分析仪抓I2C降低I2C速率、加校验远程读数整体偏高三极管选型不当对比数据手册理想因子换低串联电阻三极管远程读数整体偏低三极管焊接过热检查焊接温度曲线更换三极管、调整焊接参数4.2 I2C通信失败或间歇性失败I2C通信失败的原因比较多常见的有上拉电阻阻值不合适、总线电容过大、从设备地址冲突。PJ85718DM的I2C上拉电阻一般用4.7kΩ如果总线走线长或者挂了多个设备可以降到2.2kΩ。总线电容要控制在400pF以内超了就要加I2C缓冲器。还有一个容易被忽略的点PIC32MX470F512H的I2C外设在某些情况下会产生总线死锁比如从设备在传输过程中复位。解决办法是在固件里加一个超时机制如果I2C传输超过10ms还没完成就手动复位I2C外设重新初始化。这个机制我加了好几次才调稳一开始超时设得太短正常传输也被打断后来改成10ms就合适了。4.3 远程通信丢包或响应超时RS-485通信丢包通常和总线终端电阻、波特率误差、收发切换时序有关。终端电阻用120Ω接在总线两端。波特率误差要控制在2%以内PIC32MX470F512H的UART波特率发生器可以精确到1%以内问题不大。收发切换时序上DE引脚在发送最后一个字节的停止位之后才能拉低早了会截断数据晚了会占用总线。我在一个项目里遇到过上位机轮询周期500ms但MCU偶尔要800ms才响应的情况。后来发现是OLED刷新和I2C采集撞在一起了MCU在刷OLED的时候没及时处理Modbus请求。解决办法是把Modbus处理放在定时器中断里优先级高于OLED刷新这样响应时间稳定在20ms以内。4.4 上电后读数异常或芯片不响应上电异常通常和复位时序、电源上升时间有关。PJ85718DM的电源上升时间建议在1ms到10ms之间太快或者太慢都可能导致内部复位不完整。如果MCU上电后读不到PJ85718DM可以先检查电源上升时间再检查I2C上拉电阻是否接好。另外PIC32MX470F512H的复位引脚需要接一个10kΩ上拉和0.1uF电容确保复位可靠。还有一个坑PJ85718DM的配置寄存器在上电后是默认值但默认值可能不使能远程通道。固件里必须在初始化阶段显式配置一遍不能依赖默认值。我见过因为没配置远程通道使能位结果远程读数一直是0的案例查了半天才发现是配置漏了。5. 实操过程与关键环节记录5.1 硬件搭建与上电检查硬件搭建的顺序是先焊电源部分上电测电压再焊MCU和晶振测复位和时钟然后焊PJ85718DM和远端三极管测I2C波形最后焊RS-485收发器和OLED。每一步都要测不要一次全焊完再调试否则出了问题很难定位。电源部分输入是12V经过一颗降压芯片降到3.3V。PJ85718DM单独用一颗LDO从3.3V降到3.3V主要是为了隔离噪声。实测LDO输入输出压差只有0.1V效率不高但噪声确实小。远端三极管用2米长的屏蔽双绞线接到一个恒温槽里屏蔽层在MCU端单点接地。上电后先用万用表测各路电压3.3V要在3.25V到3.35V之间LDO输出要在3.28V到3.32V之间。然后用示波器看晶振波形8MHz晶振的峰峰值应该在1V以上频率偏差在50ppm以内。最后用逻辑分析仪抓I2C波形看MCU是否能正确读写PJ85718DM的寄存器。5.2 固件烧录与初步调试固件用MPLAB X IDE开发编译器是XC32。烧录用PICkit4接口是ICSP。烧录后先跑一个简单的I2C扫描程序确认PJ85718DM的地址能被识别。然后读配置寄存器的默认值确认芯片工作正常。接着配置采样速率和滤波强度读本地温度用手摸芯片表面看读数是否上升。远程通道调试时先把远端三极管放在室温下读远程温度应该和室温接近。然后把三极管放到冰水混合物里读远程温度应该在0°C附近。如果偏差超过1°C就要检查三极管选型和走线。我调试的时候发现远程读数比冰水混合物实际温度高了1.5°C后来换了一颗串联电阻更小的三极管偏差降到0.3°C。5.3 本地显示与远程通信联调OLED显示调试时先显示固定字符确认SPI通信正常。然后显示本地温度刷新率设在5Hz观察是否有闪烁。如果有闪烁可能是SPI速率太高或者刷新逻辑有问题。我一开始用10MHz的SPI速率OLED偶尔会花屏后来降到4MHz就稳定了。RS-485通信调试时先用USB转RS-485模块接到PC上用串口助手发Modbus请求看MCU是否响应。响应数据要跟OLED显示的温度一致。如果不一致可能是寄存器映射错了或者数据格式不对。我遇到过温度数据在OLED上显示25.3°C但Modbus读出来是253上位机显示25.3°C这是对的因为Modbus里放的是0.1°C单位的整数。但如果上位机按整数显示就会显示253°C这个要在上位机配置里改。5.4 长时间运行与稳定性测试联调完成后让系统连续运行72小时每隔1小时记录一次本地温度、远程温度和Modbus响应时间。观察是否有漂移、丢包或者死机。我跑下来发现远程温度在第一天有0.2°C的漂移之后稳定了应该是三极管的自热效应达到平衡。Modbus响应时间稳定在15ms到25ms之间没有超时。如果长时间运行出现死机首先要看门狗是否开启。PIC32MX470F512H的看门狗可以设成1秒超时主循环里定期喂狗。如果看门狗没开死机后只能手动复位。我建议在量产固件里一定要开看门狗并且在喂狗前检查关键状态比如I2C是否正常、RS-485是否正常不正常就不喂狗让系统复位。提示长时间测试时环境温度最好有变化比如白天和晚上差几度这样可以观察温度补偿算法是否在全温区都有效。如果条件允许用恒温箱做-20°C到80°C的循环测试更能暴露问题。6. 经验总结与扩展思路这个项目做下来最大的体会是温度监测看起来简单但精度和稳定性全靠细节堆出来的。PJ85718DM和PIC32MX470F512H的组合在HVAC场景里够用但前提是硬件设计要扎实固件要健壮。远端三极管的选型和走线是精度瓶颈电源噪声是稳定性瓶颈I2C和RS-485的时序是可靠性瓶颈。每一个瓶颈都要单独验证不能靠猜。如果后续要扩展有几个方向可以考虑。一是增加多路PJ85718DM通过I2C多路复用器或者不同地址挂载实现多点温度监测。二是把RS-485换成以太网或者无线模块适应更远的传输距离。三是在固件里加温度趋势记录用MCU的Flash存最近24小时的数据方便事后分析。四是加一个蜂鸣器或者继电器输出实现超温告警的本地联动。我个人在实际操作中的体会是调试温度监测系统时手边一定要有参考温度计和恒温槽没有这两个东西调精度就是盲人摸象。另外I2C和RS-485的波形一定要用逻辑分析仪抓光看代码是看不出时序问题的。最后固件里一定要加错误处理和超时机制不能假设通信永远正常实际现场什么干扰都有。
返回列表