做温控方案的人迟早要面对一个尴尬问题测点明明就在眼前却不能把传感器直接放进去或者放得进去了走线一长读回来的全是乱跳的数据。最近我在做一套嵌入式温度监测模块要在 HVAC 的风柜电控箱里同时测板温和远端管路温度试过好几颗传感器最终落到 PJ85718DM 加 STM32F756ZG 这套组合上。PJ85718DM 负责本地与远程两路温度采集STM32F756ZG 则负责读取、校准、显示和远程上报整体跑下来很稳。这篇东西不是讲教科书写法而是把我从选型到画板、写驱动、调误差、联调上报的完整过程整理出来。无论你在做暖通控制器、机房温控板、嵌入式设备健康监测还是在为“本地温度 远端管道/柜内温度”这种双测点需求发愁都可以参考这套思路。我会尽量把原理、接口设计、关键代码、踩坑点都讲透尤其是远程测温那一路别看它只是多接了一根线实际调试时坑多得很。1. 为什么是“本地 远程”双路温度监测以及我选型时对比了什么1.1 需求拆解HVAC 控制柜里到底需要测哪些温度做 HVAC 相关设备时温度测点看起来简单实际一拆就发现至少分两类。一类是“板子自己的温度”也就是嵌入式设备电控板上处理器、电源模块、驱动电路的温升目的是防止局部过热、控制风扇启停、延长器件寿命另一类是“现场设备的温度”比如风管里的回风温度、表冷器进出水管温度、压缩机排气管温度目的是参与制冷/制热控制逻辑实现温度调节和故障保护。这两种测点的物理位置往往隔得很远。板温传感器贴在 PCB 上只有几毫米到几厘米的走线距离而管道温度传感器可能要装在距离主控板几十厘米甚至几米外的位置。过去我碰到这类需求本能反应是“那就上两个传感器”板子上放一个远端管道上放一个用两根延长线引回来。但延长线一长模拟量电压信号会衰减、会被电机干扰污染热敏电阻更是容易因为线阻引入额外误差。用数字传感器能解决一部分问题但两颗数字传感器同样要占用两个接口、两份校验代码还可能出现两路读数的系统偏差不一致的问题。PJ85718DM 这类双通道数字温度传感器的价值就在这里一颗芯片同时带本地测温通道和远程测温通道。板温直接用片内传感器测远端温度则通过外接一颗二极管或三极管的 PN 结来测不需要在远端放一块完整电路板只需要把二极管引过去。这个方案在布线和成本上都比“两颗传感器 延长线”干净尤其适合 HVAC 电控箱这种强电磁干扰环境。1.2 三套方案的取舍为什么最终选了 PJ85718DM我不是一开始就选它而是把常见的三套方案都过了一遍。第一套是“板载热敏电阻 NTC 延长线”。成本最低但 NTC 的阻值—温度关系是非线性的要拉表做拟合更麻烦的是线阻补偿和 EMI 抗扰都需要额外电路。实测下来延长线超过三十厘米后读数波动就开始让人不放心必须做滤波而滤波又会让温度响应变迟钝。第二套是“两颗数字传感器走 I2C 总线”。稳定性和抗干扰都不错测温精度通常能做到正负 0.5℃ 以内但一颗传感器占一个地址如果 I2C 总线上还有其他器件地址冲突就要想办法通过地址引脚错开。两块传感器分布在两块电路上连线至少四根电源、地、SDA、SCL接线端子、线材成本翻倍。我还遇到过一个问题两块传感器因为出厂校准批次不同同一温度下读数能差到 1.2℃左右做系统校准时非常头疼。第三套是“双通道远程测温传感器”。一颗芯片放在主控板上本地通道测板温远程通道通过两芯线引出到测量点远端只需要接一个二极管或者三极管的发射结。它的线性度、精度和一致性比热敏电阻好接线也比数字延长线少。PJ85718DM 走的就是这个路线I2C 接口读回两个温度值软件上高度统一校准偏置也只需维护一份。三套对比下来我选第三套。这里多说一句如果你只需要测一个点、距离又特别短那用单通道数字传感器完全够没必要为双通道多花钱。选 PJ85718DM 的前提是“一路本地、一路远程”这个结构确实符合你的系统布局。方案精度抗干扰接线成本软件复杂度NTC 热敏电阻 延长线中等较弱最少最低需拟合表、滤波两颗数字传感器高强较多中高双驱动、双地址管理PJ85718DM 双通道高强少中单驱动、单设备2. PJ85718DM 怎么做到一路本地、一路远端从 PN 结测温原理说起2.1 本地通道片内传感器不需要外接元件PJ85718DM 的本地测温通道本质上就是芯片内部集成了一个测温 PN 结或者类似的热敏结构出厂前在恒定温度下做过校准并把校准参数存进了芯片内部。使用时不外接任何元件直接通过 I2C 读寄存器就能拿到片内温度。这个“片内温度”测的其实是芯片自己封装内部的温度和 PCB 表面温度、环境温度之间会有细微差异但把它当作“板温”来监测是合适的。芯片功耗越大自热效应就越明显。我实测数据是芯片正常连续转换时自热带来的读数偏高大约在 0.25℃到 1.0℃之间具体取决于芯片功率和 PCB 散热面积。所以如果你拿它精确测量“环境温度”最好在软件里做一点偏置修正如果是用来做板卡过温保护那自热效应反而帮了你——它反映了芯片真实的工作温度保护更及时。2.2 远端通道一根线的远端靠的是二极管温度特性远程测温的原理比本地通道稍微绕一点但也不难理解。半导体 PN 结的正向导通电压会随温度变化温度每升高 1℃正向压降大约下降 2mV 左右。这种特性很稳定而且可以通过“不同电流下的电压差”来消除 PN 结自身绝对值的离散性得到更接近线性的温度读数。PJ85718DM 的远程通道就是干这件事的芯片向外部输出一个偏置电流经过远端接的二极管或三极管 PN 结后芯片测量这个结在两种不同电流激励下的电压差再用内部算法把它换算成温度。所以“远程测温”并不是芯片把温度传感器延伸出去了而是把 PN 结这个温度敏感元件延伸出去了。你只需要在远端放一个二极管比如常见的小信号三极管把基极和集电极短接用发射结当作测温结然后两根线引回主控板即可。这里有几个容易踩的坑我列一下远端必须接有 PN 结特性的器件不能接普通电阻。接电阻测出来的温度毫无意义。引线串联电阻会直接影响读数精度所以我后来在硬件上选择了短走线并把双绞线作为远程头引线。远端 PN 结如果靠近大电流负载比如散热风扇旁边测出来的温度会明显偏低或偏高需要在实际安装位置做标定。2.3 采样时序与寄存器读法不要把远程通道当模拟量处理第一次用这种芯片最需要扭转思维的是远程温度不是模拟量不用自己接 ADC 采样PJ85718DM 内部已经完成了电流激励、电压测量、数字化转换的全过程。你只需要配置转换模式、启动转换、查询状态位、读寄存器。我通常在初始化时把这些事安排好配置为连续转换模式让芯片持续刷新温度数据设置转换分辨率如果要快速响应就选较低分辨率如果要稳定读值就选高分辨率开启远程通道的开路检测远端二极管断线时能直接报错而不是给一个离谱的温度数。读寄存器时候本地和远程温度通常是两个独立的 16 位寄存器高低字节按手册约定的格式组合再乘上转换系数。具体寄存器地址和系数每个型号会有差异所以一定要以 PJ85718DM 数据手册为准我下面的代码里用的是常见格式但你别拿来直接用要对照手册核一遍。3. STM32F756ZG 在板级设计里的作用接口、供电与抗干扰布局3.1 处理器选型为什么是 STM32F756ZG 而不是更便宜的单片机既然只是读个温度有人会问随便一颗小单片机不行吗行但要看整体需求。我项目里除了读温度还要同时跑人机交互界面、风扇 PWM 控制、网络上报、参数存储和故障诊断日志。这些任务叠在一起普通的 Cortex-M0/M3 内核芯片资源会很紧张写代码时处处要省 Flash、省内存后期扩展没有余地。STM32F756ZG 属于高性能系列Cortex-M7 内核主频可以跑到两百多兆赫兹带 FPU 和 DSP 指令。这意味着什么温度数据的滤波、PID 控温算法、传感器校准曲线的浮点运算都能比较轻松地完成不会挤占主循环时间。它还内置了以太网 MAC配合外部 PHY 芯片就能直接做远程数据上报省掉一个外挂网络芯片的麻烦。I2C、SPI、UART、ADC、PWM 定时器的数量也足够充裕PJ85718DM 只是挂在一个 I2C 接口上的小负载其他外设还都能各司其职。这颗芯片确实有点“杀鸡用牛刀”的意思。如果你只做单纯温度采集选个小尺寸、低功耗的片子会更合适。我选它的核心原因是温度和 HVAC 控制通常不是单一功能而是一整套系统处理器要为后续控制逻辑、通信协议栈、存储扩展留足余量。3.2 传感器接口电路上拉电阻、滤波与去耦PJ85718DM 通过 I2C 与 STM32F756ZG 通信硬件上看起来很简单接 SCL、SDA、VDD、GND。但“简单”只体现在原理图具体连线有一些细节决定成败。I2C 是开漏结构需要外部上拉电阻。我选 4.7kΩ 作为 I2C 总线的上拉电阻为什么不是 1kΩ 或 10kΩ因为 I2C 总线速度越高上拉电阻越小以保证信号边沿足够陡但电阻太小会让低电平灌电流变大影响噪声容限。4.7kΩ 是 100kHz 到 400kHz 速率的常见选择。如果总线上挂的设备多、走线长还可以改成 2.2kΩ但要注意 PCB 走线阻抗和寄生电容的影响。供电去耦方面我在 PJ85718DM 的电源引脚旁边放了 0.1μF 陶瓷电容和 1μF 电容并联位置尽量靠近芯片电源脚。这个细节不能省因为温度传感器的内部 ADC 对电源纹波敏感如果供电不稳你会发现温度读数的低字节一直在跳误以为环境温度在波动。STM32F756ZG 的 VDDA 也同样处理模拟域和数字域用磁珠隔开能明显减少开关电源纹波对 ADC 的干扰。远程测温头的走线也要注意。我最初用普通单股线长度约 80cm风扇一启动读数就乱跳后来换成双绞线并把屏蔽层单端接地问题基本消失。远程测温头信号本质是毫伏级小信号很容易被变频器、继电器电弧干扰所以走线一定远离 PWM 风扇驱动线和功率线。3.3 预留外设风扇 PWM、报警中断、存储与显示既然跑 HVAC 控制不能只读温度还得让温度参与控制。我在硬件设计上专门留了一路 PWM 定时器输出给散热风扇频率定在 20kHz 左右避开人耳可听范围减少噪音。风扇的反馈测速引脚接一个定时器输入可以实时监测风扇是否堵转、停转。PJ85718DM 还可以把温度报警阈值配好超过上限时它的中断引脚直接拉低接到 STM32 的外部中断不依赖主循环轮询即使主循环被其他任务卡住过温保护也能第一时间触发。显示方面我预留了一个 SPI 接口的小尺寸屏平时显示本地温度和远程温度。存储则用一颗 SPI NOR Flash 保存系统配置和历史温度记录掉电不丢失。电源部分用 DC-DC 把板上电压降到 3.3V同时加了 LDO 给模拟部分确保温度采集不受 PWM 风扇负载波动影响。4. 固件落地I2C 初始化、寄存器读写、温度换算与滤波重试4.1 I2C 总线初始化与设备探测代码层面先初始化 I2C。在 HAL 库里可以用现成结构体只要正确配置时钟、模式和地址。我这里不粘贴完整工程只给关键流程。按 STM32F756ZG 的 I2C 外设初始化设为主模式、标准模式或快速模式都可以。我因为总线上还有 EEPROM 等器件统一跑 400kHz 快速模式PJ85718DM 手册如果支持这个速率就没问题。初始化后第一件事是探测设备在不在。PJ85718DM 的 I2C 地址取决于地址引脚接法常见是 0x4C 这种 7 位地址形式具体要以手册为准。我会写一个简单的探测函数向目标地址发送一个零长度读请求成功返回则说明设备在线。如果返回 NACK就检查接线、供电和地址配置别急着往下走否则后面读回来的全是错误值。#define PJ85718DM_I2C_ADDR 0x4C // 以实际手册为准 #define REG_CONFIG 0x00 #define REG_LOCAL_TEMP 0x01 #define REG_REMOTE_TEMP 0x02 #define REG_STATUS 0x03 int pj85718_probe(I2C_HandleTypeDef *hi2c) { HAL_StatusTypeDef ret; ret HAL_I2C_IsDeviceReady(hi2c, PJ85718DM_I2C_ADDR 1, 5, 100); return (ret HAL_OK) ? 0 : -1; }这段代码里把 7 位地址左移一位变成 8 位地址是因为 HAL 库期望的是完整地址字节。如果探测失败你先用示波器看 SCL、SDA 上有没有时钟和数据波形如果没有波形大概率是引脚复用配置错了或者芯片没上电。4.2 配置寄存器与单次/连续转换设备在线之后写配置寄存器。配置内容包括转换模式、分辨率和远程通道检测。由于不同批次芯片的寄存器位定义可能有区别我不会在这里写死某个魔数而是用“读回—改位—写回”的方式先读一字节配置保留其他位只修改需要的位再写回去。这样即使寄存器默认值不同也能保证不破坏其他设置。我一般设为连续转换模式因为 HVAC 场景要频繁刷新温度连续模式比单次模式省去每次启动转换的软件开销。如果你做电池供电的低功耗设备则应该用单次模式需要读数时启动一次转换等待转换完成读回结果然后让芯片进入低功耗状态。我在这两者之间直接做成了编译选项方便以后复用。远程通道开路检测一定要开。如果远端二极管断线或者没接好PJ85718DM 会给一个异常温度值开了检测以后状态寄存器会标记错误固件就能明确提示“传感器异常”而不是让上位机拿一个假的 60℃ 去执行错误控制。这个细节在 HVAC 现场非常关键因为接线端子松动是常见故障。4.3 温度原始值换算成摄氏度PJ85718DM 的本地和远程温度寄存器都是 16 位有符号数实际温度值由高低字节拼接后乘上分辨率系数。我这里用一个通用例子假设数据格式是高字节为整数部分低字节的高几位为小数部分那么温度和原始值的换算大致如下。float pj85718_read_temp(I2C_HandleTypeDef *hi2c, uint8_t reg) { uint8_t buf[2]; uint8_t reg_addr reg; HAL_I2C_Master_Transmit(hi2c, PJ85718DM_I2C_ADDR 1, reg_addr, 1, 100); HAL_I2C_Master_Receive(hi2c, PJ85718DM_I2C_ADDR 1, buf, 2, 100); int16_t raw (int16_t)((buf[0] 8) | buf[1]); return raw / 256.0f; // 具体转换公式以手册为准 }这个除法因子 256 不是所有芯片都一样有的芯片分辨率是 12 位有的带扩展符号位换算规则不同。你拿到芯片后第一件事就是把不同温度下的原始值和标准温度计读数对应起来验证换算公式。温度换算做错后面所有控制逻辑和远程展示全是白搭这是基础中的基础。4.4 数据质量问题滤波、剔除毛刺与 I2C 错误恢复读温度本身很简单难的是让读回来的温度“可信”。我实际遇到过三种问题第一种是偶发毛刺读回来的温度瞬间跳高十几度下一拍又恢复正常。这种多半是 I2C 信号被干扰、数据线被风扇电源线串扰或者芯片电源波纹导致转换错误。软件上做中值滤波很有效连续读 5 次排序后取中间值毛刺会被剔除。第二种是正常波动但变化很快对于 HVAC 这种惯性很大的系统温度不需要特别快响应。我会再做一层滑动平均把最近几次有效温度值做一个加权平均降低短时波动。注意滑动平均窗口不要太大否则温度真的发生故障飙升时响应会变得迟钝。我一般取 4 到 8 个样本窗口内如果出现超过 10℃ 的跳变不管它是不是真实值先单独标记并触发重读。#define TEMP_HISTORY_SIZE 5 float temp_history[TEMP_HISTORY_SIZE]; uint8_t temp_index 0; float temp_filter(float new_temp) { temp_history[temp_index] new_temp; temp_index (temp_index 1) % TEMP_HISTORY_SIZE; float sorted[TEMP_HISTORY_SIZE]; for (uint8_t i 0; i TEMP_HISTORY_SIZE; i) { sorted[i] temp_history[i]; } // 简单冒泡排序样本数只有5开销很小 for (uint8_t i 0; i TEMP_HISTORY_SIZE - 1; i) { for (uint8_t j 0; j TEMP_HISTORY_SIZE - 1 - i; j) { if (sorted[j] sorted[j 1]) { float tmp sorted[j]; sorted[j] sorted[j 1]; sorted[j 1] tmp; } } } return sorted[TEMP_HISTORY_SIZE / 2]; }第三种是 I2C 通信偶尔卡死或者应答失败。我在每次读取后检查返回值一旦失败就重启 I2C 外设。STM32 的 I2C 有总线忙状态硬件卡住后直接清空状态寄存器再重新初始化比无限等待有效得多。重试三次仍失败就报告温度传感器故障并进入安全控制模式风扇按最大占空比运行或维持上一个安全值。5. 把温度送到“外面”本地显示、串口日志与远程上报5.1 本地可视化串口终端与显示模块温度数据读回来之后第一步是本地可视化。我调试时最常用的是串口日志每分钟输出一行简单的文本包括时间、本地温度、远程温度、状态标志。格式类似这样[10:05:31] local28.42C remote35.16C fan_pwm45% statusOK [10:05:36] local28.40C remote35.20C fan_pwm45% statusOK为什么我会把日志做成这种整齐的文本格式因为后续无论是用串口助手查看还是写个小脚本从日志文件里抓取曲线都很方便。如果日志里列一堆十六进制帧人眼没法直接判读工作效率会低很多。如果设备带显示本地温度走 SPI 或者 I2C 屏没问题。这里有个经验屏幕刷新和 I2C 读取温度不要挤在同一个时间片里做尤其当显示屏是通过同一个 I2C 总线挂载的时候。一旦屏的数据传输占用总线时间过长温度读取会被拉长到不可控甚至产生超时。所以我一般把显示屏刷新频率降到每秒一次温度读取保持高频两个任务分别用不同的间隙执行。5.2 远程上报从板卡到服务端的链路设计远程上报才是这次标题里的重点之一。STM32F756ZG 自带以太网 MAC外部加一颗 PHY 芯片之后通过网线和局域网内的服务端通信即可实现远程监控。我这里的做法是每个电控箱里的主控板作为一个测温节点把本地温度和远程温度周期性地发送给一台数据采集服务。关于传输协议我在实际项目里用过两种。最简单的是 HTTP POST把温度数据拼成 JSON 文本通过 HTTP 请求发给局域网内的服务端。优点是服务端随便写个小接口就能接数据网页端可以直接展示。缺点是 HTTP 头开销大对于多个节点同时上报有点浪费而且没有 QoS 机制丢包了也不重传。另一种是更轻量的发布订阅模式比如私有 MQTT 服务。每个测温板作为一个发布端定时把温度数据发布到对应主题服务端订阅主题统一入库和展示。它的优点是消息小、断线重连恢复机制成熟多节点扩展比较方便。我最终用的是私有 MQTT因为后期要接入多个 HVAC 节点甚至可能在几十块板子上同步采集。上报频率我设置为 10 秒一次。温度变化本身是慢变量10 秒刷新已经能很平滑地画出曲线同时给网络和服务端留足余量。如果你有实时监控告警需求把异常变化作为事件单独上报比单纯提高上报频率更有效。5.3 一个最小的温度帧协议与解析端示例网络传输层面我不建议直接裸发浮点数文本虽然调试方便但结构不清晰。可以先定义一个紧凑的温度上报结构体填充后用二进制序列化发出服务端再解析。下面是一个简化示例实际字段可以根据项目需要扩充。typedef struct { uint8_t device_id; uint8_t status; float local_temp; float remote_temp; uint16_t sequence; } temp_report_t;设备 ID 用来区分不同节点status 表示传感器状态sequence 是发送序号用于乱序检测和丢包统计。发送时把这个结构体填充好通过网络回调发送。这个帧格式足够清晰服务端收到后解包直接入库。如果你不想自己编解析器把报文格式定义好用现成序列化工具也可以但要注意大小端一致性。STM32 默认小端服务端常见架构也是小端基本不用额外转换跨平台时还是显式按字节组装更保险。远程上报链路正常后我习惯做两个健康指标一个是“最近一次上报时间”超过 60 秒没有上报就算节点离线另一个是“温度连续异常次数”连续 N 次超过告警阈值才触发告警避免单点毛刺导致误报。这两个机制都是从实际运行中总结出来的看着不起眼却能省掉很多麻烦。6. 实测中的误差与踩坑记录以及几种校准补偿手段6.1 远程通道读值“卡死”或漂移走线与被测对象的锅我最初把远程测温头接好上电后读数是有的但总觉得哪里不对劲把测温头用手捂热读数居然要十几秒才缓慢变化而且会飘到比真实体温高好几度。排查了很久才发现问题有两个。第一个问题是远端引线用了较长的普通排线线电阻太大而且排线里的其他信号线带来了电容耦合使得 PN 结电压测量被干扰。换用双绞线后浮动明显变小。双绞线本身有抑制磁场耦合的作用对于低频毫伏级信号这个改善立竿见影。第二个问题是测温头表面和被测物体之间的热接触不好。我把测温头用普通电工胶带缠在管道上但管道表面有油污和氧化层热阻很大测温头真正感受到的是周围空气温度而不是管道温度。正确做法是清理表面涂导热硅脂再用导热胶带固定并保温覆盖。这一步是纯物理问题软件怎么滤波都补偿不了只能从安装工艺上解决。还有一次读值彻底“卡死”在某一个值怎么捂都没反应。查下来是远端三极管的引脚接反了PN 结方向不对芯片量到的是一个反向漏电流信号温度自然不对。远程通道的极性一定要按手册接这个最容易忽视。6.2 本地通道读数比室温偏高自热和外壳热累积本地通道的读数稳定但偏高高多少不一定。我比较过芯片装在通风良好的位置自热约 0.5℃装进密闭电控箱后箱内热空气积聚读到的板温会比实际环境温度高 5℃甚至更多。这不是芯片坏了而是它测的就是这个小环境的温度。如果你要的是系统控制用的板温偏高反而合理因为板温高会影响板上其他器件可靠性风扇启动要以它为参考。但如果你想把本地温度当作环境温度上报就必须做偏置校准。我在代码里留了一个local_offset变量默认 0现场标定时用标准温度计比对然后写入 Flash 校准值。这种可配置的校准项比写死一个固定偏移量实用得多。6.3 软件校准偏置修正、两点校准与滤波参数调优校准时我遵循一个顺序先保证硬件安装正确、热接触良好再做软件修正绝不反过来。软件偏置修正就是给远程温度加一个固定偏移量比如float calibrated_remote remote_temperature_raw remote_offset;这个单点偏移适合工程快速修正前提是不同温度点下的偏差基本一致。大多数半导体测温器件的线性度不错在 0℃到 70℃ 范围内用单点偏移通常够用。如果精度要求更高就要做两点校准比如用 20℃ 和 60℃ 两个恒温点分别测出偏差做线性插值float temp_calibrate(float raw_temp, float offset_t1, float offset_t2, float t1, float t2) { // raw_temp 在 t1-t2 之间时按比例插值偏置量 float ratio (raw_temp - t1) / (t2 - t1); return raw_temp offset_t1 (offset_t2 - offset_t1) * ratio; }这个公式能解决“低温准、高温偏”或反过来的一致性问题。不过两点校准时两个校准点之间的温度范围要覆盖你的实际工作区间否则外推误差会很大。现场如果条件不允许做恒温标定那就用单点校准加全量程固定偏差对 HVAC 应用通常已经足够。滤波器参数也要按实际场景调。远程温度、本地温度的响应速度不一样。本地板温波动快滤波窗口小一点远程管道温度惯性大滤波窗口可以大一点。我观察到一个反直觉的现象滤波窗口调得太大时如果管道温度因故障真的飙升系统会因为平均掉突变而延迟报警。所以我在告警判断时不用滤波后的值而是直接看原始值只有展示和控制才用滤波后的值。这样既能抑制毛刺又能保证告警及时。7. HVAC 场景的进阶用法迟滞控制、风扇曲线与故障保护7.1 两路温度如何参与控制逻辑温度读出来不是只看是要参与控制的。HVAC 设备里最常见的控制器是风扇、继电器、比例阀、电加热。我在这套系统里用两种温度分别做不同的事本地板温控制散热风扇防止控制板过热远程管道温控制制冷/制热逻辑决定压缩机或电加热的动作。关键点是不能让温度在设定值附近频繁振荡。比如远程温度 25℃ 就开压缩机制冷24.9℃ 就关那压缩机会频繁启停寿命会短得吓人。正确做法是加迟滞控制比如设定目标 25℃回差 2℃那么超过 26℃ 才启动制冷降到 24℃ 以下才停止。迟滞窗口留多大取决于系统惯量和允许的温度波动范围我一般先按正负 1℃ 到 2℃ 起步现场再调。typedef struct { float setpoint; float hysteresis; uint8_t output_on; } hvac_control_t; uint8_t hvac_update(hvac_control_t *ctl, float current_temp) { if (!ctl-output_on current_temp ctl-setpoint ctl-hysteresis) { ctl-output_on 1; } else if (ctl-output_on current_temp ctl-setpoint - ctl-hysteresis) { ctl-output_on 0; } return ctl-output_on; }本地板温也用迟滞逻辑控制风扇但这种场景的迟滞不需要太大否则板温会冲到很高才启动风扇。我设的是 45℃ 启动、40℃ 停止对大多数嵌入式主控板来说比较合适。7.2 风扇 PWM 曲线与电加热保护风扇只用开关逻辑也可以但 HVAC 设备里更推荐用 PWM 调速。温度低时低转速温度升高时按比例提高转速既能控温又能降噪。风扇转速曲线不用做成复杂 PID先做最简单的线性映射就行低于 40℃ 转 30%40℃ 到 65℃ 之间线性从 30% 加到 100%高于 65℃ 直接满转。uint32_t fan_pwm_by_temp(float temp) { if (temp 40.0f) return 30; if (temp 65.0f) return 100; return (uint32_t)(30.0f (temp - 40.0f) / 25.0f * 70.0f); }这里有个细节PWM 占空比变化要平滑不要让电机转速突变。每次调节占空比时限制最大变化量比如每次只允许变化 2%然后再过几百毫秒更新下一次。否则风扇会发出急促的变调噪音现场体验会很差。远程温度如果用于电加热控制保护优先级要高于舒适度逻辑。比如电加热启动条件是远程温度低于 10℃但同时要限制上限超过 45℃ 必须无条件切断加热并点亮故障灯。这个上限保护不能只在应用层做最好用 PJ85718DM 的报警寄存器配一个硬件级阈值超过后芯片中断引脚直接拉到 MCUMCU 再切断加热继电器双保险更安全。7.3 断电记忆与看门狗长时间运行的稳定性HVAC 设备经常连续运行数月稳定性比功能多更重要。两个必须做的机制断电保存和看门狗。我每次修改校准偏置、设定温度或者控制参数后都会写进 SPI Flash。上电时读取并校验如果校验失败就恢复默认值避免设备因为 Flash 数据损坏而起不了机。写 Flash 时要注意次数限制不要每次控制变化都写只在“人工参数变更”或“整点历史记录”时写否则 Flash 寿命会被轻易耗尽。看门狗我用独立看门狗喂狗放在主循环里。温度采集、网络上报、控制逻辑分别用不同的任务如果某个环节卡死看门狗超时后会自动复位系统。复位后系统重新初始化读回 Flash 配置继续运行。这里有个隐藏问题如果复位太频繁可能说明系统存在严重的软件缺陷不能只是默默重启就完事。我会在 Flash 里维护一个复位计数器连续多次异常复位后标记故障状态并把日志通过上报通道发出去。这套组合跑了一段时间我的总体体会是真正的难点从来不是芯片怎么读而是远端测温头的安装、校准和抗干扰这些功夫花在硬件布局和现场标定上比在软件里反复调参有效得多。如果你也准备用类似的双通道传感器方案我建议留足时间做温度和稳定性的长时间测试别只看刚上电时的读数。
阅读完成 · 觉得有帮助?