首页 / 资讯中心 / 文章详情

基于PJ85718DM与TM4C129ENCZAD的本地与远程温度采集上报方案

基于PJ85718DM与TM4C129ENCZAD的本地与远程温度采集上报方案 ★ FEATURED ARTICLE
搞嵌入式或者暖通控制的朋友多少会遇到一个很典型的需求现场设备既要采集主控板附近的温度又要盯着几十米外风管、机房或者室外机的温度。最近我在一个项目里用了 PJ85718DM 数字温度传感器和 TM4C129ENCZAD 主控把“本地温度”和“远程温度”一起采集、一起上报整个过程比想象中顺畅也踩了几个坑。这篇文章就把从硬件到代码的完整思路整理出来给同样做嵌入式或 HVAC 监控的同行一个参考尤其适合那些正准备把温度监测从“单点采集”升级到“多点远程”的朋友。1. 场景拆解为什么要把温度分成“本地”和“远程”1.1 本地温度与远程温度在工程上分别代表什么在嵌入式设备里“本地温度”通常指主控板附近的环境温度比如机箱内的空气温度、控制面板周围的环境温度。它的特点是传感器离 MCU 很近走线短信号稳定采集起来最省心。而“远程温度”就复杂多了可能是风管内部的空气温度、室外机组的温度、离主控几十米甚至几百米的测温点。远程温度在暖通空调HVAC里尤其常见比如送风温度、回风温度、混合风温度都需要装在风道上而控制板往往放在配电箱里两者根本不在一个位置。如果只用一根长线把传感器拉到远处就不得不考虑信号衰减、抗干扰和电源压降这些是本地测温基本碰不到的麻烦。实际工程中还要注意本地温度测不准也会影响控制逻辑。很多控制板放在密闭电箱里箱内温度可能比外界高好几度如果把电箱内的温度当作环境温度去参与空调联动结果会偏得离谱。所以设计时你要先明确每一个温度点的物理含义它是用来做保护、用来做显示还是用来参与控制用途不同对精度、时效和安装位置的要求都不一样。1.2 从数据流看“远程测温”的两种实现路径远程测温可以从两个方向理解。第一种是“传感器外置”传感器本体就在远端通过总线把温度值传回主控这时“远程”是相对传感器的位置而言的。第二种是“数据上报远程”主控把采集到的本地和远程温度汇总再通过网络或串口送到监控中心。因为 TM4C129ENCZAD 自带以太网接口把温度数据打包发到上位机这就是远程监测。实际项目中两种常常同时出现远端传感器把温度送回主控主控再把所有温度点远程上报给机房监控平台。理解了这一层后面的选型和代码才顺理成章。从数据流的角度看本地温度是“第一跳”远程温度是“第二跳”。第一跳要解决传感器怎么读数第二跳要解决数据怎么打包、怎么传输、怎么在另一端解析。很多初学者一上来就纠结用 TCP 还是 UDP其实那是最后一步的事。先把传感器读准再把协议的帧格式定好后面的问题都会简单许多。2. 硬件选型PJ85718DM 与 TM4C129ENCZAD 怎么配合2.1 PJ85718DM 温度传感器的关键特性与接线PJ85718DM 是一颗单总线接口的数字温度传感器。这类芯片最大的魅力在于只占一根信号线就能把一个甚至多个温度节点挂在同一条总线上非常适合风管、墙壁、机柜这些分散测温的场景。和模拟传感器比如 NTC 热敏电阻不同PJ85718DM 内部集成了温度采集和数字转换主控只要按照时序访问它就能直接读到温度数值不需要做非线性校正也不需要额外的 ADC 采集通道。单总线的另一个好处是节省 IOMCU 侧只需要一个 GPIO 就能挂一堆传感器后续要扩展测温点时不用改硬件。但单总线也意味着时序要求严格差个几微秒就可能读回 0xFF 或者 85。接线时要注意三点电源、地、信号线。上拉电阻一般取 4.7kΩ如果线缆较长可以适当减小到 2.2kΩ。考虑到很多 HVAC 现场会有变频器、接触器、继电器这些强干扰源我强烈建议传感器供电不要直接从开关电源的输出端取电而是经过一级 LC 滤波或者至少加一个磁珠再进传感器否则温度读数会在设备启动瞬间出现明显跳变。2.2 TM4C129ENCZAD 主控为什么适合这个场景TM4C129ENCZAD 是一颗带以太网控制器的 ARM Cortex-M4 主控工作主频可以到 120MHz片上资源非常齐全。它不只用来读温度更重要的是能直接把数据发出去正好补上单总线温度传感器缺少网络上报能力这块短板。很多项目要求主控既有本地数据处理能力又要能通过局域网甚至互联网上报数据TM4C129ENCZAD 内置 MAC 和 PHY只需要加一个网络变压器和 RJ45 座就能组网省掉了外挂以太网芯片的麻烦。同时它有多个 UART 和 I2C 接口未来要接触摸屏、接 RS485 网关、接第二路传感器总线都有富余。选型时我还会重点看 IO 的驱动能力和定时器的丰富程度因为单总线时序虽然简单但用 GPIO 模拟时需要非常精准的延时好在 Cortex-M4 主频足够高配合定时器就能把时序做得很稳。以前用低主频单片机模拟单总线一根指令的延时差异就能导致读取失败换到 TM4C129ENCZAD 之后只要用定时器做延时基准基本一次通过。如果你未来还想在这个平台上跑轻量级网络协议它也是比较从容的选择。2.3 供电、滤波和信号线处理硬件上最容易翻车的其实是供电和滤波。PJ85718DM 这类传感器通常支持 3.3V 供电但如果现场的电源纹波太大温度读数就会不稳定看起来像“漂移”。我一般会在传感器电源引脚附近加一个 100nF 的陶瓷电容再并联一个 10μF 电解电容用来吸收低频波动和高频噪声。信号线上如果走线超过 10 米建议在输入端加一个 RC 滤波比如 100Ω 电阻串联到 DQ再接 100pF 电容到地这能减少电机、继电器动作带来的干扰。远程传感器如果是通过接插件连接最好用带屏蔽层的双绞线屏蔽层单端接地避免形成接地环路。电缆长度超过 15 米时还要实测一下信号上升沿线缆上的分布电容会把沿变缓影响读时序。如果发现读取不稳定可以把上拉电阻降到 2.2kΩ同时降低总线访问频率。这些细节看起来不起眼但在现场调试时能少走很多弯路。3. 本地温度读取从初始化到拿到有效温度值的完整流程3.1 单总线时序基础单总线通信的特点是一根线既做数据输入又做数据输出所有操作都由主机发起。主机先发送一个复位脉冲把总线拉低至少 480μs然后释放总线。传感器检测到下降沿后会给出一个存在脉冲表示它在线上。之后主机才能依次发送功能命令比如跳过 ROM、启动温度转换、读暂存器。PJ85718DM 如果和常见单总线传感器一样那么它的每个数据位都由主机产生一个写时隙或读时隙。写“0”时拉低总线并保持 60μs 左右写“1”时拉低一小段时间后立刻释放让上拉电阻把总线拉高。读时隙同样是主机拉低总线然后在 1μs 到 15μs 之间检查引脚电平如果传感器输出“1”总线是高电平否则是低电平。这些时序的本质就是通过脉冲宽度和采样位置来传递数据。初学者容易犯的错是把延时写死成几个大循环结果在优化等级不同的编译器上跑出完全不同的行为。所以我的建议很明确所有微秒级延时必须基于定时器或者 SysTick不要用嵌套循环去凑时间否则换个编译选项就可能读不出数据。3.2 读取流程与代码实现标准的读取流程分几步先复位检查传感器是否存在发送跳过 ROM 命令再发送启动温度转换命令等待转换完成然后再次复位跳过 ROM发送读暂存器命令最后连续读出多个字节取出温度值。如果用 TM4C129ENCZAD 的库函数GPIO 初始化和电平切换可以写得很简洁。下面给一个参考实现实际使用要根据你的芯片型号和时钟频率调整延时参数。#include stdint.h #include stdbool.h #define DQ_GPIO GPIO_PORTA_BASE #define DQ_PIN GPIO_PIN_3 static void Delay_us(uint32_t us) { // 使用 SysTick 或定时器实现精确微秒延时 } static void SetDQInput(void) { GPIOPinTypeGPIOInput(DQ_GPIO, DQ_PIN); GPIOPadConfigSet(DQ_GPIO, DQ_PIN, GPIO_STRENGTH_2MA, GPIO_PIN_TYPE_OD); } static void SetDQOutput(void) { GPIOPinTypeGPIOOutput(DQ_GPIO, DQ_PIN); GPIOPadConfigSet(DQ_GPIO, DQ_PIN, GPIO_STRENGTH_2MA, GPIO_PIN_TYPE_OD); } static void SetDQLow(void) { SetDQOutput(); GPIOPinWrite(DQ_GPIO, DQ_PIN, 0); } static void SetDQHigh(void) { SetDQInput(); } static uint8_t TempSensor_Reset(void) { uint8_t present 0; SetDQLow(); Delay_us(500); SetDQHigh(); Delay_us(70); if (GPIOPinRead(DQ_GPIO, DQ_PIN) 0) { present 1; } Delay_us(410); return present; } static void TempSensor_WriteBit(uint8_t bit) { if (bit) { SetDQLow(); Delay_us(2); SetDQHigh(); Delay_us(58); } else { SetDQLow(); Delay_us(58); SetDQHigh(); Delay_us(2); } } static uint8_t TempSensor_ReadBit(void) { uint8_t val 0; SetDQLow(); Delay_us(1); SetDQHigh(); Delay_us(1); if (GPIOPinRead(DQ_GPIO, DQ_PIN)) { val 1; } Delay_us(50); return val; } static void TempSensor_WriteByte(uint8_t data) { for (uint8_t i 0; i 8; i) { TempSensor_WriteBit(data 0x01); data 1; } } static uint8_t TempSensor_ReadByte(void) { uint8_t data 0; for (uint8_t i 0; i 8; i) { data 1; if (TempSensor_ReadBit()) { data | 0x80; } } return data; }有了底层操作函数之后读温度的主流程就简单了float TempSensor_ReadCelsius(void) { uint8_t data[2]; int16_t raw; if (!TempSensor_Reset()) { return -999.0f; } TempSensor_WriteByte(0xCC); // 跳过 ROM TempSensor_WriteByte(0x44); // 启动温度转换 Delay_ms(750); // 等待转换完成具体时间以手册为准 if (!TempSensor_Reset()) { return -999.0f; } TempSensor_WriteByte(0xCC); // 跳过 ROM TempSensor_WriteByte(0xBE); // 读暂存器 data[0] TempSensor_ReadByte(); data[1] TempSensor_ReadByte(); raw (int16_t)((data[1] 8) | data[0]); return (float)raw * 0.0625f; }这里把读取失败时的返回值设为 -999方便在日志里一眼看出异常。你可以根据实际需求改成 NAN 或者加上错误标志。Delay_ms(750) 的温度转换等待时间来自常见单总线传感器的典型参数不同型号可能有差异量产后记得用更精确的定时方式来替代固定延时。3.3 温度换算与精度处理PJ85718DM 这类数字温度传感器在 12 位分辨率模式下每个 LSB 对应 0.0625℃所以直接乘 0.0625 就能得到摄氏度。但要注意负温度的情况传感器内部用补码表示负数比如 -0.5℃ 对应的原始值并不是一个单纯的十六进制数直接按无符号读取再乘会出现错误。代码里把两个字节拼成 int16_t 再做转换就是处理符号位的关键。在 HVAC 场景里温度数据往往不需要 0.0625℃ 这么高的理论分辨率。相反控制逻辑更关心温度的稳定性和变化趋势。我的经验是软件上做三件事第一连续读取 3 到 5 次去掉最大值和最小值取中间几个值的平均第二设定一个跳变阈值比如相邻两次读数变化超过 2℃就认为可能是干扰用上一次的读数替代第三把换算结果保留一位小数就够了显示上不必把 23.4375℃ 原样打印出来。这些处理看起来很简单却能让整个监控界面的数据干净很多。4. 远程温度上报把数据送到监控端4.1 串口转发方式在没有网络的环境里串口依然是远程温度传输最可靠的方案。把 TM4C129ENCZAD 的温度读数通过 UART 发给串口服务器、DTU 或者直接接上位机报文格式可以自己定。比如LOC:25.3 REM:18.2上位机按行解析读到 LOC 和 REM 两个字段就能拆出温度。这种文本格式虽然占用带宽多一点但调试方便用串口助手一眼就能看出数据对不对。如果数据点很多建议改成紧凑格式比如25.3,18.2,21.0,20.4不用字段名按位置对应。要注意的是浮点数转字符串时别用系统自带的 printf 全家桶在嵌入式环境里既占 Flash 又占 CPU。我一般自己写一个简单的格式化函数或者用 snprintf 但只用在调试版本里。串口通信的波特率建议固定为 9600 或者 115200。HVAC 现场环境比较嘈杂的时候尽量降低波特率能减少误码。如果距离超过十几米就要考虑 RS232 转 RS485而不是直接把 TTL 电平拉出去否则电平损耗和环境干扰会让通信非常不稳定。4.2 以太网 UDP/TCP 上报方式TM4C129ENCZAD 的优势就在于以太网这是很多其他温度采集主控做不到的。利用它的网口可以把本地和远程温度封装成报文定时推送到监控中心。如果采用 UDP代码逻辑最简单丢包也不至于影响整体控制因为温度数据本身是周期性的。但若要保证对端必须收到或者温度数据要入库存储那就用 TCP 会更可靠。以太网报文可以这样设计一条消息包含设备编号、温度点个数、每个温度点的通道号和测量值。例如DEV:01 CNT:2 CH0:25.3 CH1:18.2如果有固定的 Modbus 网关还可以在应用层把温度映射成保持寄存器。这样上层 SCADA 系统不需要额外开发直接通过 Modbus 协议读寄存器就能拿到所有温度值。实际开发中我建议先跑通 UDP 广播让局域网内的调试工具都收得到数据再决定是否改成 TCP 主动上报。因为先用 UDP 能快速确认传感器和主控逻辑是否正确网络层的问题留到后面再排查。4.3 远程传感器节点的扩展如果“远程温度”指的是传感器本身在远端那就要考虑怎么把传感器挂到主控上。最直接的方式是多挂几个 PJ85718DM 在同一条单总线上通过每个传感器唯一的 ROM 序列号来区分。但单总线长距离能力有限超过 15 米要加驱动电路超过 50 米基本不推荐。更稳的方案是做成 RS485 节点每个远端位置放一个小的采集板板上有一颗单片机和一路单总线传感器单片机把温度换算好之后通过 RS485 总线以 Modbus RTU 从站的方式响应主控的读取请求。这种方式看着多了一道中间环节但在大型 HVAC 系统里反而好维护。每个 RS485 节点可以挂 32 个甚至更多通讯距离可以到 1000 米以上而且现场接线可以走两芯屏蔽线比多路单总线简单得多。表格里是两种方式的对比方案单总线直连RS485 节点单根总线最多节点通常 10 个左右32 个以上典型通信距离10-15 米1000 米以上抗干扰能力一般强成本低中调试难度低中从成本考虑点数少、距离短用单总线直连点数多、距离远、现场电磁环境差果断选 RS485 节点。两种方案都可以和 TM4C129ENCZAD 的多个串口同时配合主控一侧的代码结构可以保持统一都是“总线读数-数据打包-网口上报”三段式。5. HVAC 应用中的安装与校准细节5.1 风管温度测量的位置选择HVAC 项目里最常栽跟头的不是传感器本身而是安装位置。送风温度传感器如果直接贴在风管外壁测到的是管壁温度不是空气温度要插进风道内部并且让探头位于气流主流区避开靠近管壁的低速涡流区域。回风温度传感器同样如此安装位置选不好控制逻辑得到的反馈就是错的整个空调系统都会跟着误动作。混风段的温度测量要更小心冷盘管和热盘管附近的辐射热会干扰温度探头。我见过有项目把回风温度传感器装在离冷盘管不到半米的地方实际读数比真实回风温度低了三四摄氏度导致空调一直误判制冷效果偏弱。原则上传感器要离盘管至少几倍管径的距离如果空间不允许就要用隔热套把探头和辐射源隔开。安装座和探头之间加一点导热硅脂能减小热阻但不能把探头完全包死否则热量散不出去测出来的温度会被探头自热抬高。5.2 热延迟和校准所有温度传感器都有热时间常数通常是几十秒到几分钟。如果你希望温度数据能快速反映送风温度变化就要选热容量小的安装方式比如把传感器直接固定在薄金属卡扣上而不是包在一个厚重的铜套里。HVAC 控制本身不需要毫秒级响应但热延迟太大会让系统出现振荡温度一会儿冲高一会儿冲低。校准方法其实很简单用一支经过校准的参考温度计和被测传感器放在同一个位置的同一气流环境中等读数稳定后记录偏差。如果偏差是固定的零点几度就在软件里加一个偏移量。要注意不要试图去调节硬件电路来“校零”数字传感器的偏差大多来自芯片内部基准硬件调整空间有限。更系统的做法是两点校准在低温点和高温点分别记录实际偏差然后用线性插值修正中间段的读数。这样应对大部分 HVAC 应用已经绰绰有余。5.3 多传感器的地址分配与轮询当一条单总线上并联多个 PJ85718DM 时每个器件都有自己的 ROM 序列号。首次使用时要用读 ROM 命令把每个传感器编号读出来并逐一记录之后在软件里用匹配 ROM 指令访问指定编号的传感器。这个步骤不能省否则多个传感器同时响应总线上的数据会互相冲突读出来的温度值七零八落。轮询周期要大于传感器转换时间。比如转换时间是 750ms那 1 秒轮询 4 个传感器就不合适因为第二个传感器开始采集时第一个可能还没完全结束。更合理的做法是划分时间片先向所有传感器广播启动转换等待 750ms 后依次读取每个传感器的暂存器这样一次转换周期能拿到全部读数。如果你的应用要求更高的刷新率可以考虑把传感器拆到多条总线上或者选用转换速度更快的芯片。这个思路也适用于 RS485 节点方式主控轮询各个从站时从站必须在寄存器里保存好最近一次转换结果而不是让主控现场等它转换完。6. 常见问题与排查技巧实录6.1 典型读数异常对照表调试过程中我整理了一张对照表遇到问题可以直接对照排查现象可能原因处理办法总是读到 85℃传感器刚上电或转换未完成检查读取流程是否等待转换完成读回 0xFF / 0x00时序错误、总线损坏检查上拉电阻和接线用示波器看波形温度值随机跳变电源纹波、线缆过长、周围干扰加强滤波降低上拉电阻屏蔽线单端接地多个传感器读数互相串ROM 匹配失败、多个传感器同时响应确认每个传感器的 ROM 编号使用匹配指令网口能 Ping 通但收不到数据UDP 端口绑定错误、对端地址错误检查端口号和目标 IP先在本机回环测试这张表看起来简单但每一条背后都是实际踩过的坑。比如“总是读到 85℃”这个现象最容易出现在刚上电的一瞬间因为很多单总线传感器内部上电复位后暂存器里会有一个固定的默认值这个值对应的温度恰好是 85℃。如果代码里复位后立刻去读而不等待第一次转换完成就会把这个默认值当成真实温度。6.2 排查经验和注意事项排查顺序很重要。我的习惯是先用示波器量 DQ 引脚上的波形确认复位脉冲、存在脉冲、写读时隙是否符合手册要求。没有示波器的时候就简化问题只接一个传感器用很慢的频率读一次打印出原始字节。如果原始字节稳定再怀疑上层协议和网络的问题如果原始字节就不稳定先查硬件连接和供电。还有一个容易被忽略的坑是传感器自热。在密闭的小机箱里传感器本身消耗的功率会让周围温度微微上升导致测出来的温度比环境空气温度高一点。降低采样频率、减少总线上的寄生供电电流都可以减轻这个问题。如果测温点本身空间狭小且封闭建议把传感器探头引到机箱外部用防水接头固定这样测得的数据更有参考意义。远程传感器线缆的屏蔽层必须单端接地最好是接在主控板那一侧的“地”上不要两端都接。两端都接会形成接地环路在雷雨天气或者大功率设备启停时反而会把干扰引入系统。这些经验看着琐碎但现场调试时能帮你省下大半天时间。我个人在实际项目里的体会是先把本地温度读数做到稳定再去折腾远程上报。很多人一上来就急着写网络协议栈的代码结果传感器数据读出来就是乱的网络调通了也没有意义。另一个建议是日志打印一定要带上原始字节这样出了问题能回溯到底层。这个习惯帮我快速定位过不少问题比如某次温度读数偏移了 2℃最后发现是传感器线缆被空调冷凝水滴湿绝缘下降导致的。项目后期的稳定性往往就藏在这些看起来不起眼的细节里。
阅读完成 · 觉得有帮助?
咨询建站