現(xiàn)HVAC本地遠(yuǎn)程監(jiān)測)
去年在做一個暖通空調(diào)的嵌入式控制單元時碰到了那個經(jīng)典的老問題既要看主板附近的設(shè)備腔內(nèi)溫度又要看風(fēng)道遠(yuǎn)端、冷卻水管或室外機(jī)附近的溫度。如果用多個傳感器分別采集校準(zhǔn)基準(zhǔn)不一致、線纜數(shù)量跟著翻倍、故障點(diǎn)也多了一大堆如果只用一個傳感器測“平均溫度”又根本滿足不了溫差控制的邏輯需求。后來我把方案收斂到 PJ85718DM 這顆雙通道數(shù)字溫度傳感器配上 PIC32MX695F512L 做主控一次解決了本地溫度與遠(yuǎn)程溫度的同步監(jiān)測問題順帶把遠(yuǎn)程上報通道也打通了。這篇文章就是那次落地過程的完整復(fù)盤。內(nèi)容涉及硬件接線、PIC32 下的 I2C 讀取、溫度標(biāo)定、HVAC 現(xiàn)場的干擾處理以及最后通過以太網(wǎng)做遠(yuǎn)程數(shù)據(jù)上報的思路。如果你想在嵌入式設(shè)備里同時監(jiān)測本機(jī)環(huán)境和遠(yuǎn)端探頭溫度或者正在選 MCU 方案、調(diào)溫度采樣精度這篇應(yīng)該能給你省不少彎路。1. “本地遠(yuǎn)程”溫度監(jiān)測到底在測什么1.1 兩種溫度的來源標(biāo)題里“本地與遠(yuǎn)程溫度”這幾個字在不同項目里的含義差別很大。我這次做的是 HVAC 設(shè)備上的溫度監(jiān)測本地溫度指的是控制板所在電氣腔內(nèi)溫度也就是 PJ85718DM 芯片內(nèi)部測溫點(diǎn)感知到的環(huán)境溫度遠(yuǎn)程溫度指的則是通過外部感溫探頭引到風(fēng)道、回風(fēng)口、冷水管或室外的溫度。PJ85718DM 這顆芯片內(nèi)部自帶一個本地溫度傳感單元同時還有一個外部測溫通道可以接一顆二極管結(jié)構(gòu)的探頭到設(shè)備遠(yuǎn)端。也就是說一顆芯片同時輸出兩個獨(dú)立的溫度值不用再為遠(yuǎn)程測點(diǎn)單獨(dú)拉一路傳感器電源和信號線。這個特性在 HVAC 控制器里非常實(shí)用因為設(shè)備的電氣腔和風(fēng)道往往隔著幾米線束遠(yuǎn)程探頭只靠兩根細(xì)線就能把溫度數(shù)據(jù)傳回來。1.2 HVAC 為什么需要“看兩個點(diǎn)”空調(diào)箱或者熱泵機(jī)組運(yùn)行的時候要判斷是否需要制熱、制冷、除濕或旁通靠的是各個測點(diǎn)的溫差和變化趨勢。比如判斷蒸發(fā)器是否結(jié)霜要對比管道表面溫度和空氣溫度判斷過濾器是否堵塞要對比送風(fēng)溫度和回風(fēng)溫度。如果只測設(shè)備內(nèi)部溫度風(fēng)機(jī)停轉(zhuǎn)、風(fēng)道堵塞這類工況根本看不出來。這就是為什么“測兩個點(diǎn)”遠(yuǎn)比“多測幾遍一個點(diǎn)”重要。PIC32MX695F512L 作為主控通過 I2C 總線反復(fù)讀取 PJ85718DM 的兩個溫度寄存器再把本地溫度和遠(yuǎn)程溫度一起放進(jìn)控制邏輯。硬件上無需增加額外的傳感器節(jié)點(diǎn)軟件上也只需處理一顆芯片的寄存器維護(hù)成本低很多。1.3 為什么用 PIC32MX695F512L 這顆芯片選主控的時候其實(shí)列過幾個候選8 位機(jī)、Cortex-M0、還有 PIC32MX695F512L。最終定這顆 32 位 MCU 主要是三個原因。第一它有兩組獨(dú)立的 I2C 外設(shè)一顆 PJ85718DM 掛在 I2C1 上另一路 I2C 還可以兼顧 EEPROM 或顯示屏互不干擾第二片內(nèi) Flash 有 512KBRAM 也不小跑 TCP/IP 協(xié)議棧和溫度采集任務(wù)不會捉襟見肘第三它在工業(yè)溫度范圍內(nèi)工作穩(wěn)定HVAC 設(shè)備夏天 60°C 的電氣腔里用起來不會像消費(fèi)級芯片那樣參數(shù)飄得離譜。低功耗和高性能未必能兼得但 PJ85718DM 本身功耗很低整體系統(tǒng)功耗主要取決于 MCU。用 PIC32 做控制可以保證后期擴(kuò)展邏輯和協(xié)議棧時有足夠余量。2. PJ85718DM 的通道結(jié)構(gòu)、接線方式與硬件設(shè)計注意事項2.1 本地通道和遠(yuǎn)程通道共同工作PJ85718DM 的本地測溫單元在芯片內(nèi)部靠近芯片表面反映的是 PCB 附近空氣溫度和板卡自身發(fā)熱的綜合結(jié)果。遠(yuǎn)程測溫通道則通過引腳引出連接一個外部探頭。探頭通常是一只二極管結(jié)構(gòu)的溫敏器件溫度變化時正向?qū)▔航蹈兓酒瑑?nèi)部通過電流激勵和 ADC 采集把這個壓降轉(zhuǎn)換還原成溫度。我第一次用這種遠(yuǎn)端二極管探頭時還不太放心總怕線長會有衰減。實(shí)際測試下來普通兩線制探頭線長做到 2 米以內(nèi)完全沒問題只要線材屏蔽和供電處理好數(shù)據(jù)穩(wěn)定得反而比某些熱敏電阻方案更好。遠(yuǎn)程通道的測溫范圍比本地通道大不少適合放到 HVAC 風(fēng)道里測低溫回風(fēng)或高溫盤管。2.2 硬件接線的三個關(guān)鍵細(xì)節(jié)硬件接線這里有一張參考連接表是我在樣機(jī)上驗證過的接法信號PJ85718DM引腳PIC32MX695F512L引腳說明VCCVDD3.3V建議 100nF10μF 去耦GNDGNDGND單點(diǎn)接地SCLSCLI2C1 SCL4.7kΩ 上拉到3.3VSDASDAI2C1 SDA4.7kΩ 上拉到3.3VREMOTED--用雙絞線接遠(yuǎn)端探頭正極REMOTE-D---用雙絞線接遠(yuǎn)端探頭負(fù)極SCL 和 SDA 的上拉電阻一定要接在 MCU 電源側(cè)不能接在傳感器電源側(cè)。否則 MCU 已經(jīng)上電、傳感器還沒供電時I2C 線上會出現(xiàn)從 MCU 到傳感器 VDD 的漏電流路徑把傳感器半喚醒。這也是很多板子“時而能讀、時而讀不到”的隱藏原因。遠(yuǎn)端探頭的兩根線最好采用雙絞線形式并且遠(yuǎn)離變頻器功率線。我在這套樣機(jī)上試過普通平行線線長 1.5 米時讀數(shù)偶爾會跳 0.5°C換成雙絞線并加上一個 2.2nF 的差分濾波電容后跳變徹底消失。2.3 電氣腔與探頭的隔離處理HVAC 現(xiàn)場最麻煩的不是傳感器的精度而是地電位差。風(fēng)道里的探頭往往和壓縮機(jī)、風(fēng)機(jī)共地而控制板的信號地又和功率地連在一起。如果控制板地和探頭遠(yuǎn)端地之間存在壓差遠(yuǎn)程通道讀數(shù)就會莫名其妙偏移。這次設(shè)計中我在探頭負(fù)極與控制板地之間不加直接連接讓 PJ85718DM 依靠雙線差分方式測量壓差從源頭避免地環(huán)路。如果板子空間允許還可以在 VDD 和 GND 之間加一個共模電感進(jìn)一步抑制共模干擾對 ADC 的影響。3. PIC32MX695F512L 的軟件配置與讀取流程3.1 采樣周期和主循環(huán)的設(shè)計溫度采集看著簡單但 HVAC 控制里不能一味追求“越頻繁越好”。本地溫度和風(fēng)道溫度都存在熱慣性1 秒采一次已經(jīng)能滿足 90% 的控制需求。如果每 10ms 就去讀一次 I2C反而會把總線占用滿影響其他傳感器和對顯示屏的刷新。我最終把溫度采樣放在一個 1Hz 的軟件定時中斷標(biāo)志位里。主循環(huán)檢測到標(biāo)志位置位后才發(fā)起 I2C 讀取。讀取完成后通過隊列發(fā)給控制任務(wù)。這樣溫度數(shù)據(jù)和 PID 周期天然對齊調(diào)試時也容易復(fù)盤。3.2 I2C 寄存器讀寫時序與代碼示例PJ85718DM 的讀取流程通常分兩步先寫配置寄存器選擇要讀的通道再從對應(yīng)的數(shù)據(jù)寄存器讀取 16 位溫度原始值。以下代碼是實(shí)際項目中精簡出來的關(guān)鍵函數(shù)基本反映了 PIC32MX695F512L 操作 I2C 的套路。#define PJ85718DM_ADDR 0x4C #define REG_LOCAL_TEMP_HI 0x01 #define REG_REMOTE_TEMP_HI 0x02 #define REG_CONFIG 0x09 uint8_t i2c_read_reg(uint8_t addr, uint8_t reg) { uint8_t val 0; // start i2c_start(); // 7-bit地址寫位 i2c_send_byte((addr 1) | 0); i2c_send_byte(reg); i2c_restart(); // 7-bit地址讀位 i2c_send_byte((addr 1) | 1); val i2c_read_byte(0); // 帶NACK i2c_stop(); return val; } uint16_t read_temperature(uint8_t reg_hi) { uint16_t raw; raw ((uint16_t)i2c_read_reg(PJ85718DM_ADDR, reg_hi) 8); raw | i2c_read_reg(PJ85718DM_ADDR, reg_hi 1); return raw; }這里需要提醒一下PIC32 的 I2C 外設(shè)在作為主機(jī)發(fā)送完最后一個字節(jié)后必須手動產(chǎn)生 Stop 條件。很多人讀回全是 0xFF 就是在 restart 和 stop 順序上出了問題。另外某些版本的外設(shè)庫中I2C_ReadByte會自動返回 ACK 狀態(tài)最后一個字節(jié)要改成 NACK 應(yīng)答否則傳感器會認(rèn)為主機(jī)還要繼續(xù)讀下一幀數(shù)據(jù)就錯位了。3.3 溫度原始值到工程值的換算PJ85718DM 溫度寄存器里的數(shù)值通常是 16 位帶符號數(shù)分辨率可以做到 0.0625°C 或更細(xì)。拿到 raw 值后本地和遠(yuǎn)程通道的換算公式略有不同但基礎(chǔ)邏輯都是先判斷符號位再乘分辨率。float reg_to_celsius(uint16_t raw, float resolution) { int16_t signed_raw; // 先轉(zhuǎn)換為有符號類型再由編譯器做擴(kuò)展 signed_raw (int16_t)raw; return signed_raw * resolution; }需要注意本地通道的偏移和遠(yuǎn)程通道的偏移并不一樣。PJ85718DM 的數(shù)據(jù)手冊一般會分別給出兩個通道的 offset 校準(zhǔn)值。如果硬件在遠(yuǎn)程通道接了不同規(guī)格的二極管探頭還需要根據(jù)二極管型號的 ideality factor理想系數(shù)做一次比例修正。HVAC 系統(tǒng)里常見的探頭是 2N3904 或同類小信號管它們的系數(shù)不完全相同直接用默認(rèn)值會引入 1°C 到 2°C 的偏差。4. HVAC 現(xiàn)場的標(biāo)定、誤差來源與抗干擾經(jīng)驗4.1 零點(diǎn)與滿度標(biāo)定剛把板子裝回樣機(jī)時遠(yuǎn)程溫度和標(biāo)準(zhǔn)水銀溫度計差了大約 1.3°C本地通道只差了 0.2°C。排查了一圈發(fā)現(xiàn)是遠(yuǎn)程通道的二極管探頭壓降偏大導(dǎo)致的不是芯片問題。解決辦法是標(biāo)定。我取 0°C 冰水混合物和 60°C 恒溫槽兩個點(diǎn)記錄遠(yuǎn)程通道的原始讀數(shù)然后用線性插值修正。修正系數(shù)直接寫進(jìn)設(shè)備的校準(zhǔn)區(qū)每次開機(jī)讀 EEPROM 加載。這樣下來兩個通道在 0°C 到 70°C 范圍內(nèi)都能穩(wěn)定在 ±0.3°C 以內(nèi)。標(biāo)定的具體步驟很簡單把探頭放到已知溫度環(huán)境中等待 10 分鐘讓熱平衡建立然后讀取 PJ85718DM 的原始值。注意不要剛放入就采樣傳感器自身的熱時間常數(shù)加上探頭外殼的導(dǎo)熱延遲至少要等讀數(shù)穩(wěn)定兩次變化小于 0.05°C 才算有效。這一步如果省了后面所有控制邏輯都會跟著飄。4.2 探頭熱阻和風(fēng)道風(fēng)速對讀數(shù)的影響HVAC 風(fēng)道溫度測量有一個繞不開的問題風(fēng)道里的空氣流速很高時探頭表面不會真正達(dá)到空氣溫度。實(shí)測 2m/s 風(fēng)速下裸露二極管探頭與靜止空氣環(huán)境的讀數(shù)差異能到 0.8°C。這是因為探頭自身的對流換熱系數(shù)有限而熱輻射和熱傳導(dǎo)又把周圍管道壁溫帶進(jìn)去了。應(yīng)對策略是在探頭外面加一個薄壁金屬護(hù)套并讓護(hù)套與空氣流有足夠接觸面積。護(hù)套會稍微增大熱慣性但換來的是更穩(wěn)定的讀數(shù)??刂瞥绦蚶镌賹h(yuǎn)程溫度做一階低通濾波時間常數(shù)設(shè)為 5 秒到 10 秒既不會讓控制反應(yīng)遲鈍也能過濾掉風(fēng)機(jī)啟停時造成的波動。4.3 電源地和信號地的處理我在這套系統(tǒng)里吃過一次大虧主控板、風(fēng)機(jī)驅(qū)動和 PJ85718DM 共用同一個開關(guān)電源風(fēng)機(jī)啟動瞬間遠(yuǎn)程溫度讀數(shù)會突然從 25°C 跳到 35°C過兩秒又回落。用示波器看傳感器 VDD 上疊加了接近 200mV 的尖峰遠(yuǎn)超數(shù)據(jù)手冊允許范圍。后來做了三件事才解決。一是 PJ85718DM 的供電通過一顆小功率 LDO 單獨(dú)供給不再直接接系統(tǒng) 3.3V二是把去耦電容從 100nF 加到 4.7μF并在 D/D- 之間加了一顆 10nF 電容三是把傳感器和主控之間的 I2C 線改為 10cm 以內(nèi)的短走線遠(yuǎn)離功率電感的輻射路徑。處理后風(fēng)機(jī)啟停期間的讀數(shù)抖動降到了 0.1°C 以內(nèi)。5. 遠(yuǎn)程上報通道PIC32MX695F512L 的以太網(wǎng)與 Modbus TCP 簡化實(shí)現(xiàn)5.1 遠(yuǎn)程溫度不只是“探頭遠(yuǎn)程”還要“數(shù)據(jù)遠(yuǎn)程”標(biāo)題里還有一個“遠(yuǎn)程”是容易被忽略的數(shù)據(jù)遠(yuǎn)程上傳。PIC32MX695F512L 自帶以太網(wǎng)控制器這是它比普通單片機(jī)更適合 HVAC 場景的原因之一?,F(xiàn)場設(shè)備把本地溫度和遠(yuǎn)程溫度計算出來后通過以太網(wǎng)打包交給上位機(jī)或云網(wǎng)關(guān)運(yùn)維人員不用跑到設(shè)備跟前就能看到實(shí)時數(shù)據(jù)。以太網(wǎng)在 HVAC 控制器里最常見的方式是跑 Modbus TCP。相比自定義 UDP 協(xié)議Modbus TCP 的優(yōu)勢是通用調(diào)試工具多、上位機(jī)組態(tài)軟件直接支持。PIC32 的資源可以支撐一個輕量級的 TCP 服務(wù)器每次收到主站的查詢請求后把溫度寄存器映射到保持寄存器地址即可。5.2 數(shù)據(jù)幀組裝與狀態(tài)機(jī)Modbus TCP 的報文結(jié)構(gòu)并不復(fù)雜。我實(shí)現(xiàn)時只保留了讀保持寄存器這個功能碼足夠覆蓋溫度上報場景。核心是把 PJ85718DM 獲取的溫度值換算成 0.01°C 單位的有符號數(shù)再放到響應(yīng)緩沖區(qū)里。uint16_t temp_fixed (uint16_t)(celsius * 100 0.5f); // 構(gòu)造響應(yīng)幀 resp_frame[0] transaction_id_hi; resp_frame[1] transaction_id_lo; resp_frame[2] 0x00; resp_frame[3] 0x00; resp_frame[4] 0x00; resp_frame[5] 0x06; // 后續(xù)字節(jié)數(shù) resp_frame[6] slave_id; resp_frame[7] 0x03; // 功能碼 resp_frame[8] 0x02; // 2個保持寄存器 resp_frame[9] (uint8_t)(temp_fixed 8); resp_frame[10] (uint8_t)(temp_fixed 0xFF); // 第二個寄存器類似...狀態(tài)機(jī)分成監(jiān)聽、接收、解析、響應(yīng)四個狀態(tài)。PIC32 的 TCP 處理如果放在主循環(huán)里一定要控制單次處理時間否則長時間 PING 沒人管連接會假死。我把每個 TCP Socket 都設(shè)了 60 秒超時回收機(jī)制防止異常斷連占住連接池。5.3 斷線重連與掉電保持HVAC 現(xiàn)場的網(wǎng)絡(luò)沒想象中那么可靠。交換機(jī)重啟、網(wǎng)線被老鼠咬斷、維護(hù)人員誤拔網(wǎng)線這些都可能讓連接斷掉。我做了兩個保險一是 TCP 服務(wù)器端把被動連接改成主動重連加被動監(jiān)聽并存二是在檢測到連接斷開后把最近 30 分鐘的溫度歷史存進(jìn)片內(nèi) Flash 的一小塊區(qū)域恢復(fù)連接后再補(bǔ)傳。掉電保持這塊要特別小心 Flash 擦寫次數(shù)。溫度數(shù)據(jù)每秒一組幾分鐘就能把扇區(qū)寫穿。所以實(shí)際實(shí)現(xiàn)是每 5 分鐘寫入一次并且用雙緩沖區(qū)交替寫寫壞一個還能從另一個恢復(fù)。對于 HVAC 設(shè)備的運(yùn)維5 分鐘粒度足夠判斷設(shè)備是否異常。6. 實(shí)際調(diào)試中遇到的三個典型問題與排查鏈路6.1 遠(yuǎn)程溫度在 100°C 附近亂跳最后查出來是接線端子樣機(jī)裝好后遠(yuǎn)程通道讀數(shù)偶爾會直接跳到 100°C 以上持續(xù)一兩秒又恢復(fù)正常。一開始懷疑是傳感器損壞換了一顆新的還是同樣現(xiàn)象。后來用示波器測 D 和 D- 兩腳的電壓發(fā)現(xiàn)探頭的連接端子稍微一晃動差分電壓就出現(xiàn)瞬間中斷。PJ85718DM 對遠(yuǎn)程通道的故障檢測開關(guān)被觸發(fā)把故障值當(dāng)作測溫結(jié)果輸出。排查鏈路是先排除軟件配置錯誤再用示波器觀察引腳波形最后把接線端子壓接處重新冷壓并固定線纜問題消失。教訓(xùn)是遠(yuǎn)程探頭線纜盡量使用焊接或?qū)S脡航宇^不要讓裸露銅線在端子排里懸空。6.2 I2C 總線讀回全是 0xFFSCL 被某個設(shè)備拉低另一塊實(shí)驗板在上電后PIC32 讀 PJ85718DM 的寄存器全部返回 0xFF。這通常是 I2C 總線 ACK 異常。我用邏輯分析儀看總線SCL 和 SDA 的波形在地址階段還有活動但器件沒有返回 ACK。逐個排查時發(fā)現(xiàn)總線上的另一個外設(shè)EEPROM地址和 PJ85718DM 存在沖突。把 PJ85718DM 的地址線跳線從高電平改到低電平后總線恢復(fù)正常。如果你遇到的不是地址沖突還有可能是 SDA 上拉電阻太小導(dǎo)致低電平無法被拉低通信時讀到的全為 1。I2C 總線上的每個器件都要有唯一地址這條規(guī)則在原型階段最容易忽略。6.3 變頻器干擾導(dǎo)致周期性跳變樣機(jī)最終測試時系統(tǒng)旁邊多了一臺變頻器。只要變頻器啟動PJ85718DM 的本地溫度讀數(shù)每隔 200ms 左右就有一次 0.3°C 的跳變。用示波器抓 VDD 波形能看到明顯的周期性紋波頻率正好是變頻器載波頻率。解決方式除了前面提到的獨(dú)立 LDO 和去耦電容軟件上也做了一個中值濾波每次取連續(xù) 5 個采樣值去掉最大值和最小值取中間 3 個的平均作為最終溫度。這個辦法對周期性干擾很有效而且不犧牲溫度控制的響應(yīng)速度。中值濾波窗口不能太大否則會濾掉真實(shí)溫度變化5 點(diǎn)窗口在 HVAC 場景里已經(jīng)夠用。如果未來再擴(kuò)展這套系統(tǒng)我會把 PJ85718DM 的遠(yuǎn)程通道接到冷卻水進(jìn)出口兩端通過溫差判斷換熱器效率。本地溫度則繼續(xù)作為機(jī)柜過溫保護(hù)輸入。兩個通道的數(shù)據(jù)各自獨(dú)立主控里的控制邏輯卻能同時使用它們這才是“監(jiān)測本地與遠(yuǎn)程溫度”最舒服的落地方式。到那時候也會先把變送器輸出端加上一級 RC 濾波讓現(xiàn)場調(diào)試不用再靠運(yùn)氣解決問題。