程上報(bào)實(shí)戰(zhàn))
去年接了一個(gè)機(jī)房精密空調(diào)控制器的改造活現(xiàn)場(chǎng)要盯回風(fēng)溫度、送風(fēng)溫度、室外溫度三個(gè)點(diǎn)本地?cái)?shù)碼管要能看遠(yuǎn)程監(jiān)控大屏也要能刷出來。供應(yīng)商最初報(bào)的方案是 PLC 加模擬量采集模塊一路測(cè)溫的成本高得離譜還要配變送器和線性標(biāo)定。我把方案改成了 MCU 加數(shù)字溫度傳感器一個(gè)測(cè)溫點(diǎn)的物料成本不到一包煙錢數(shù)據(jù)直接走以太網(wǎng)上拋到匯聚端。這里面最核心的兩顆料就是標(biāo)題里的 PJ85718DM 和 TM4C129XNCZAD前者負(fù)責(zé)把現(xiàn)場(chǎng)溫度變成可讀的數(shù)字量后者負(fù)責(zé)本地處理、顯示和遠(yuǎn)程上報(bào)。如果你也在做嵌入式溫度采集、HVAC 控制器或者只是想把溫度數(shù)據(jù)搬上網(wǎng)這篇全是實(shí)際調(diào)試驗(yàn)證過的配置與經(jīng)驗(yàn)可以直接照抄再按項(xiàng)目改。1. 兩個(gè)器件的分工邏輯為什么溫度采集要“本地遠(yuǎn)程”雙通道1.1 本地控制與遠(yuǎn)程運(yùn)維本質(zhì)上在消費(fèi)兩種溫度嵌入式和 HVAC 里的“溫度”其實(shí)有兩個(gè)消費(fèi)者。本地控制器要拿溫度做閉環(huán)壓縮機(jī)啟停、風(fēng)機(jī)三速切換、電加熱 PID 調(diào)節(jié)這些動(dòng)作要求毫秒到秒級(jí)響應(yīng)數(shù)據(jù)必須留在本機(jī)不能依賴網(wǎng)絡(luò)。遠(yuǎn)程運(yùn)維則完全不同值班人員看的是趨勢(shì)曲線、歷史溫升、設(shè)備告警時(shí)間尺度通常是十秒到分鐘級(jí)數(shù)據(jù)必須匯聚到中控或者云端。這兩個(gè)需求的時(shí)間尺度差異很大所以設(shè)計(jì)時(shí)不要把本地采集和遠(yuǎn)程上報(bào)揉成一團(tuán)。正確做法是三級(jí)解耦底層傳感器只管把溫度變成數(shù)字主控負(fù)責(zé)本地控制與顯示網(wǎng)絡(luò)模塊只做周期性的數(shù)據(jù)上拋。即使網(wǎng)絡(luò)斷線本地控制也不能?!@是 HVAC 項(xiàng)目的底線。1.2 三種測(cè)溫方案對(duì)比數(shù)字傳感器為什么是首選做溫度監(jiān)測(cè)行業(yè)內(nèi)基本三條路方案單點(diǎn)物料成本精度開發(fā)工作量典型問題PLC 模擬量變送器很高高取決于變送器接線多標(biāo)定繁瑣小項(xiàng)目性價(jià)比低通道數(shù)不靈活MCU NTC/PT100低中依賴調(diào)理電路偏置、運(yùn)放、ADC、查表全都要自己搞模擬鏈路受電源噪聲影響長(zhǎng)期漂移MCU 數(shù)字溫度傳感器低出廠已校準(zhǔn)讀幾個(gè)寄存器幾乎零外設(shè)需要 I2C/單總線驅(qū)動(dòng)選型別踩坑這里不賣關(guān)子我選的 PJ85718DM 就屬于第三類。它測(cè)溫范圍覆蓋供暖通風(fēng)空調(diào)的完整場(chǎng)景典型精度 ±0.5°C 以內(nèi)12 位分辨率輸出3.3V 供電能直接對(duì)拷 TM4C129XNCZAD 的 I/O 電平I2C 接口只占兩個(gè)引腳。選它的另一個(gè)理由是封裝小、價(jià)格低壞了換新也不用重新標(biāo)定。主控這顆 TM4C129XNCZADCortex-M4F 核跑到 120MHz最大亮點(diǎn)是內(nèi)置以太網(wǎng) MAC 和 PHY。以前單片機(jī)想聯(lián)網(wǎng)外掛 ENC28J60 或 W5100 是常態(tài)SPI 轉(zhuǎn)以太網(wǎng)麻煩不說還偶爾掉線。這顆芯片把 PHY 集成進(jìn)封裝PCB 上只要一顆網(wǎng)絡(luò)變壓器加 RJ45 座就能入網(wǎng)物料少、故障點(diǎn)少。再配合多路 I2C、UART、定時(shí)器和 GPIO讀傳感器、控繼電器、刷顯示、跑協(xié)議棧全部一只片子搞定。2. PJ85718DM 采集鏈路從引腳連接到 12 位溫度換算2.1 四個(gè)引腳背后的硬件細(xì)節(jié)PJ85718DM 這類數(shù)字溫度傳感器硬件連接看著簡(jiǎn)單實(shí)際有幾個(gè)細(xì)節(jié)決定穩(wěn)定性。供電和地是顯而易見的SDA、SCL 兩條線要接上拉電阻到 3.3V阻值常規(guī)取 4.7kΩ。這個(gè)上拉不能省也不能為了省電取太大否則總線上升沿變慢通信距離和速率都會(huì)受影響。傳感器供電腳建議放 100nF 去耦電容如果現(xiàn)場(chǎng)環(huán)境惡劣、壓縮機(jī)頻繁啟停再并聯(lián)一個(gè) 10μF 電容效果更好。我第一版畫 PCB 省了 10μF實(shí)測(cè)在大型 HVAC 設(shè)備邊上溫度曲線偶爾出現(xiàn)孤立尖峰補(bǔ)上之后明顯改善。傳感器有個(gè)地址選擇腳通過硬接高電平或低電平可以切換 I2C 地址。一條 I2C 總線上掛四片同型號(hào)傳感器四個(gè)地址剛好錯(cuò)開多路測(cè)溫就這么擴(kuò)展。我要提醒的是傳感器盡量遠(yuǎn)離功率電阻、繼電器、變壓器這類發(fā)熱元件數(shù)字輸出不代表它不被 PCB 熱傳導(dǎo)影響這個(gè)問題后面專門講。2.2 寄存器讀寫與 I2C 時(shí)序拿到一顆新傳感器先翻數(shù)據(jù)手冊(cè)的寄存器表。PJ85718DM 的寄存器布局按常見范式來0x00 是溫度數(shù)據(jù)寄存器0x01 是配置寄存器。配置寄存器里可以設(shè)置分辨率、關(guān)斷模式、比較/中斷模式我一般保持默認(rèn) 12 位分辨率關(guān)閉中斷輸出只當(dāng)普通溫度計(jì)用。讀取溫度的標(biāo)準(zhǔn) I2C 時(shí)序是這樣起始條件寫器件地址加寫位寫寄存器指針 0x00重復(fù)起始寫器件地址加讀位連續(xù)讀回兩個(gè)字節(jié)最后非應(yīng)答結(jié)束。這里容易犯一個(gè)錯(cuò)讀完溫度寄存器后有人習(xí)慣用 stop start 代替重復(fù)起始。如果從機(jī)對(duì)事務(wù)邊界要求嚴(yán)格兩段事務(wù)之間數(shù)據(jù)可能錯(cuò)位讀回來的高字節(jié)和低字節(jié)對(duì)不上。下面是一段基于通用 I2C 抽象層的讀取代碼實(shí)際工程里只要把底層三個(gè)函數(shù)替換成驅(qū)動(dòng)庫的 API 就能跑void pj85718dm_write_pointer(uint8_t reg) { i2c_start(); i2c_write_byte(0x90); // 0x48 1 | W i2c_write_byte(reg); i2c_stop(); } uint16_t pj85718dm_read_temp_raw(void) { uint8_t buf[2]; i2c_start(); i2c_write_byte(0x90); // 寫寄存器指針 i2c_write_byte(0x00); i2c_restart(); // 重復(fù)起始不是 stop 再 start i2c_write_byte(0x91); // 0x48 1 | R buf[0] i2c_read_byte(I2C_ACK); buf[1] i2c_read_byte(I2C_NACK); i2c_stop(); return ((uint16_t)buf[0] 8) | buf[1]; }調(diào)試期我習(xí)慣把原始寄存器值先打到串口確認(rèn)硬件鏈路沒問題再談溫度換算。很多初學(xué)者上來就寫浮點(diǎn)打印結(jié)果數(shù)據(jù)不對(duì)分不清是傳感器壞了還是換算錯(cuò)了最后折騰半天發(fā)現(xiàn)只是地址寫錯(cuò)。2.3 溫度換算與負(fù)溫度處理溫度數(shù)據(jù)寄存器讀回來是兩個(gè)字節(jié)需要弄清楚數(shù)據(jù)格式。PJ85718DM 的 12 位溫度值在寄存器里左對(duì)齊存放也就是高字節(jié)的 8 位完整有效低字節(jié)的高 4 位有效低字節(jié)低 4 位讀出恒為 0。換算公式很簡(jiǎn)單float pj85718dm_convert(uint16_t raw) { // 12 位左對(duì)齊先左移 4 位再算術(shù)右移 4 位完成符號(hào)擴(kuò)展 int16_t val (int16_t)(raw 4) 4; // 分辨率 0.0625°C/LSB return val * 0.0625f; }這里必須用帶符號(hào)擴(kuò)展的寫法否則負(fù)溫會(huì)算錯(cuò)。比如 -1°C 在 12 位補(bǔ)碼里是 0xFFF左對(duì)齊后讀回的 16 位原始值是 0xFFF0如果用無符號(hào)整數(shù)直接乘會(huì)算出一百多度。原始值16位讀回符號(hào)擴(kuò)展后的12位數(shù)實(shí)際溫度0x0AA017010.625°C0x01A0261.625°C0xFFF0-16-1.000°C0x0370553.4375°C需要注意不同廠家的傳感器數(shù)據(jù)格式未必一樣有的右對(duì)齊有的高 8 位才是有效字節(jié)還有的是 13 位帶擴(kuò)展符號(hào)位。拿到新器件不要想當(dāng)然先查數(shù)據(jù)手冊(cè)里的 Temperature Data Format 小節(jié)再看我給的這個(gè)模板。3. TM4C129XNCZAD 的工程化配置時(shí)鐘、I2C 與任務(wù)節(jié)奏3.1 外設(shè)時(shí)鐘與引腳復(fù)用第一步最容易翻車這類 Cortex-M4F 系列 MCU外設(shè)默認(rèn)都是關(guān)時(shí)鐘的想用哪個(gè)模塊先開哪個(gè)模塊的時(shí)鐘再配引腳復(fù)用。我拿 TM4C129XNCZAD 的驅(qū)動(dòng)庫寫法做模板核心步驟就三步void i2c0_init(void) { // 1. 打開 GPIOB 與 I2C0 外設(shè)時(shí)鐘 // 2. 配置 PB2/PB3 復(fù)用為 I2C0 的 SCL/SDA // 3. 配置 I2C0 為主機(jī)模式總線速率 100kHz }引腳分配是整個(gè)環(huán)節(jié)最容易翻車的地方。同一顆芯片的 I2C 功能往往有多個(gè)可選引腳組比如 I2C0 既可以在 PB2/PB3也可能映射到 PD0/PD1具體看板子的原理圖決定。GPIO 復(fù)用寄存器配置錯(cuò)現(xiàn)象很統(tǒng)一總線忙標(biāo)志拉不起來讀傳感器永遠(yuǎn)返回 0xFF。我這次板子上同時(shí)用兩路 I2CI2C0 專門接四片 PJ85718DMI2C1 接 EEPROM 和段碼顯示驅(qū)動(dòng)。兩路獨(dú)立互不干擾。如果只有一個(gè)應(yīng)用場(chǎng)景把傳感器掛在專用總線上比和其它設(shè)備混掛更好排查問題。3.2 I2C 讀取節(jié)奏與 CPU 負(fù)載分配溫度這種緩變信號(hào)采樣周期不需要很激進(jìn)。我們實(shí)際取 200ms 讀一次原始值濾波后更新顯示和判斷告警這個(gè)節(jié)奏在 HVAC 場(chǎng)景綽綽有余——房間溫度一分鐘能變半度就算劇烈波動(dòng)了。I2C 的讀取方式裸機(jī)裸奔時(shí)輪詢最簡(jiǎn)單但有個(gè)隱藏坑如果主循環(huán)同時(shí)要跑 TCP/IP 協(xié)議棧長(zhǎng)時(shí)間輪詢 I2C 會(huì)卡住協(xié)議棧的報(bào)文收發(fā)網(wǎng)絡(luò)丟包率飆升。我后來改成可配置的節(jié)拍驅(qū)動(dòng)系統(tǒng)滴答 1ms主循環(huán)里檢查定時(shí)器標(biāo)志時(shí)間到了才發(fā)起一次 I2C 讀取讀取期間不占太長(zhǎng)時(shí)間。以后任務(wù)變多想上 RTOS這套節(jié)拍邏輯遷過去也順。實(shí)際任務(wù)分配供參考200ms 讀四路溫度500ms 刷新本地顯示3s 向服務(wù)器上報(bào)一次30s 發(fā)一次心跳。全部用標(biāo)志位加主循環(huán)輪詢根本不需要上 RTOS。很多項(xiàng)目一上來就 RTOS任務(wù)多了調(diào)試?yán)щy其實(shí)嵌入式該省就省。3.3 先串口穩(wěn)定再考慮顯示和聯(lián)網(wǎng)調(diào)試期的順序比很多人想的更重要。我的固定習(xí)慣是第一步只把 I2C 讀到的原始值和換算后的溫度從 UART 打出來讓它跑半天以上確認(rèn)傳感器鏈路穩(wěn)定、沒有隨機(jī)跳變。第二步加本地顯示。第三步才掛以太網(wǎng)上報(bào)。先串口后網(wǎng)絡(luò)能讓你在任何一個(gè)環(huán)節(jié)出問題時(shí)立刻定位到是傳感器、I2C、還是網(wǎng)絡(luò)的問題。否則幾塊代碼混在一起又是中斷又是定時(shí)器查起來懷疑人生。顯示方面嵌入式環(huán)境不建議直接做浮點(diǎn)格式化輸出太費(fèi) CPU。溫度值乘 10 轉(zhuǎn)成整數(shù)比如 23.45°C 存成 235顯示時(shí)整數(shù)丟小數(shù)位一位小數(shù)靠除 10 取余實(shí)現(xiàn)打印速度比浮點(diǎn)快一個(gè)量級(jí)。int16_t temp_x10 (int16_t)(temp * 10.0f); // 打印時(shí)temp_x10 / 10 為整數(shù)部分temp_x10 % 10 為小數(shù)部分4. 遠(yuǎn)程上報(bào)實(shí)戰(zhàn)以太網(wǎng)協(xié)議棧、TCP 鏈路與報(bào)文設(shè)計(jì)4.1 集成 PHY 的板級(jí)優(yōu)勢(shì)不是省一顆芯片那么簡(jiǎn)單以前用單片機(jī)聯(lián)網(wǎng)最痛苦的是外掛網(wǎng)絡(luò)芯片。SPI 轉(zhuǎn)以太網(wǎng)模塊先不說成本驅(qū)動(dòng)調(diào)試就能耗掉大半個(gè)月MAC 地址燒錄、收發(fā) FIFO、中斷模式稍不留意就丟包。TM4C129XNCZAD 把 PHY 直接集成進(jìn)來板級(jí)電路只要用一個(gè)帶變壓器的 RJ45 座加四五個(gè)去耦電阻電容硬件 BOM 少一大堆。布線時(shí)注意差分線對(duì)TX± 和 RX± 要等長(zhǎng)、阻抗匹配網(wǎng)絡(luò)變壓器中心抽頭的接法直接抄官方參考設(shè)計(jì)別自己發(fā)揮。這個(gè)位置做不了太多創(chuàng)新老老實(shí)實(shí)復(fù)制粘貼最穩(wěn)。方案額外器件驅(qū)動(dòng)工作量實(shí)測(cè)穩(wěn)定性外掛 SPI 以太網(wǎng)芯片模塊 晶振 變壓器高需移植廠商驅(qū)動(dòng)和協(xié)議棧接口中等偶發(fā)掉線需復(fù)位集成 MACPHY 的 MCU僅網(wǎng)絡(luò)變壓器/RJ45低直接綁定協(xié)議棧驅(qū)動(dòng)高長(zhǎng)期運(yùn)行不掉線4.2 輕量級(jí) TCP/IP 協(xié)議棧接入裸機(jī)環(huán)境下跑網(wǎng)絡(luò)業(yè)內(nèi)標(biāo)準(zhǔn)方案就是輕量級(jí) TCP/IP 協(xié)議棧。初始化流程三步走先初始化協(xié)議棧內(nèi)存池再注冊(cè)網(wǎng)卡驅(qū)動(dòng)配置 IP 地址、網(wǎng)關(guān)和掩碼最后創(chuàng)建 TCP 連接。協(xié)議棧內(nèi)存池大小要按需調(diào)。默認(rèn)配置可能只支撐幾個(gè) TCP 連接如果你既要 DHCP 又要 TCP 客戶端和服務(wù)器那內(nèi)存池需求會(huì)明顯上升。RAM 資源夠就多分點(diǎn)避免運(yùn)行到一半內(nèi)存不足導(dǎo)致連接靜默斷開。這類問題最難查因?yàn)楸砻婵粗皇菙?shù)據(jù)不更新實(shí)際是協(xié)議棧內(nèi)存耗盡。設(shè)備到底做 TCP 客戶端還是 TCP 服務(wù)器我的建議是設(shè)備做客戶端主動(dòng)連服務(wù)器?,F(xiàn)場(chǎng)設(shè)備通常在一個(gè)局域網(wǎng)里主動(dòng)連接固定 IP 的中控最省事也不需要給每臺(tái)設(shè)備做端口映射。這個(gè)項(xiàng)目里三塊控制板全部作為客戶端連接一臺(tái)中控主機(jī)。4.3 報(bào)文結(jié)構(gòu)、心跳與斷線重連上報(bào)報(bào)文我用 JSON 行協(xié)議一行一個(gè)數(shù)據(jù)對(duì)象換行符分隔。好處是抓包時(shí)肉眼能讀服務(wù)器端解析也簡(jiǎn)單不需要自定義二進(jìn)制格式再寫編碼解碼。{id:ac-01,temp:[23.4,25.1,12.6],ts:1700000000}上報(bào)策略周期 3 秒一次同時(shí)做變化檢測(cè)——溫度變化超過 0.5°C 立即補(bǔ)發(fā)一包。溫度穩(wěn)定時(shí)降低頻率減少服務(wù)器壓力。心跳報(bào)文 30 秒一次只帶設(shè)備 ID 和時(shí)間戳用來判斷設(shè)備在線狀態(tài)。斷線重連一定要做指數(shù)退避。第一次失敗等 500ms第二次 1s第三次 2s依次翻倍最大封頂 30s。曾經(jīng)見過設(shè)備斷網(wǎng)后每 100ms 瘋狂重連把中控服務(wù)器的并發(fā)連接數(shù)打滿整個(gè)系統(tǒng)崩潰。加上退避后斷網(wǎng)期間設(shè)備只是安靜地等待本地采集和控制完全不受影響。5. HVAC 實(shí)測(cè)記錄溫度毛刺、長(zhǎng)線干擾與異常數(shù)據(jù)治理5.1 一次溫度毛刺的完整排查鏈路服務(wù)器曲線偶發(fā)出現(xiàn)孤立尖峰23.4°C 突然跳到 28.1°C 又馬上跳回來一天出現(xiàn)三四次。最初我懷疑 I2C 時(shí)序有問題邏輯分析儀掛在總線上抓了半天ACK 正常、字節(jié)正確排除了通信鏈路。接著懷疑換算邏輯把原始寄存器值打出來發(fā)現(xiàn)尖峰出現(xiàn)的一刻讀回值從 0x0AA0 突然變成 0x0D00 附近確認(rèn)是傳感器輸出本身異常不是換算問題。這時(shí)候才想起來測(cè)電源示波器探頭點(diǎn)在傳感器 VDD 和 GND 上壓縮機(jī)啟動(dòng)瞬間3.3V 上有約 300mV 的跌落加振鈴。傳感器內(nèi)部 ADC 對(duì)電源瞬變敏感讀值瞬間偏大。修復(fù)分兩步硬件上給傳感器供電加 22Ω 串聯(lián)電阻加 100μF 電容做 RC 濾波軟件上加 8 次滑動(dòng)平均。毛刺從此消失。這件事的教訓(xùn)是數(shù)字傳感器不等于免疫電源噪聲ADC 還是模擬電路供電必須干凈。5.2 兩米線束引發(fā)的 I2C 超時(shí)傳感器裝在風(fēng)管里離主控板 PCB 兩米線束一接上去就時(shí)不時(shí)讀到滿量程 0xFFFF 或者 0x0000頻率不高但很惡心。測(cè)了波形發(fā)現(xiàn) SCL 上升沿嚴(yán)重變緩原因是線束電容太大I2C 從機(jī)對(duì)信號(hào)電平的翻轉(zhuǎn)時(shí)間超了規(guī)格。處理辦法四件套總線速率從 400kHz 降到 100kHz上拉電阻從 4.7kΩ 改成 2.2kΩSDA、SCL 各串 33Ω 電阻線束改用雙絞線一組走 SCL 和 GND另一組走 SDA 和 VDD。改完再跑連續(xù)一周零讀錯(cuò)。注意改小上拉電阻會(huì)增大靜態(tài)電流電池供電的設(shè)備要權(quán)衡。HVAC 這類有市電供電的場(chǎng)景完全不用糾結(jié)帶上拉電阻功耗再大也大不過一顆指示燈。5.3 校準(zhǔn)、異常值與告警滯回?cái)?shù)字傳感器出廠精度很好但 PCB 布局會(huì)毀掉它。傳感器貼得離 MCU 近MCU 發(fā)熱通過 PCB 銅皮直接熱傳導(dǎo)過去。實(shí)測(cè)同一顆傳感器貼片靠近 MCU 時(shí)讀值比實(shí)際環(huán)境高 1~2°C這是熱傳導(dǎo)導(dǎo)致的系統(tǒng)性偏差。解決辦法優(yōu)先級(jí)依次是重新布局讓傳感器遠(yuǎn)離發(fā)熱源PCB 上加開槽或隔熱墊實(shí)在動(dòng)不了就在固件里做單點(diǎn)補(bǔ)償。我這次把室外溫度傳感器用排線接到板外偏差直接歸零。異常數(shù)據(jù)處理策略也很關(guān)鍵。單個(gè)無效值直接丟棄連續(xù) 5 次讀取失敗才判定傳感器故障并上報(bào)。不要讀取一次失敗就立刻告警HVAC 設(shè)備半夜誤告警會(huì)讓值班工程師一晚上睡不好。告警閾值要加滯回比如上限 50°C 觸發(fā)動(dòng)作降到 48°C 才恢復(fù)避免溫度在邊界來回抖動(dòng)導(dǎo)致報(bào)警反復(fù)觸發(fā)。這個(gè)邏輯看起來簡(jiǎn)單但確實(shí)是最容易漏掉的細(xì)節(jié)。6. 擴(kuò)展玩法多節(jié)點(diǎn)、上云與本地保護(hù)邏輯6.1 板內(nèi)多點(diǎn)與跨房間組網(wǎng)一條 I2C 總線上通過地址選擇腳最多掛 8 個(gè)同型號(hào)傳感器板內(nèi)多點(diǎn)測(cè)溫足夠了。如果超過 8 路可以用 I2C 多路選擇器或者直接換有硬件輪詢功能的測(cè)溫芯片。跨房間的場(chǎng)景就組網(wǎng)每個(gè)控制板一個(gè)固定 ID通過局域網(wǎng)匯聚到中控服務(wù)器。三塊板分別放在回風(fēng)口、送風(fēng)管和室外服務(wù)器端按 ID 區(qū)分?jǐn)?shù)據(jù)畫三條曲線在同一張圖里對(duì)比送風(fēng)溫度、回風(fēng)溫度、室外溫度的溫差一目了然。這套結(jié)構(gòu)擴(kuò)展性很好以后加一層樓就再加一塊板服務(wù)器端只需要新增 ID 配置。6.2 MQTT 上云與樓宇協(xié)議對(duì)接數(shù)據(jù)要上云TCP 直連平臺(tái)不如換成 MQTT 協(xié)議。它自帶發(fā)布訂閱模型和斷線重連機(jī)制掉線自動(dòng)重連的體驗(yàn)比裸 TCP 好太多。MCU 端跑輕量級(jí) MQTT 客戶端topic 按設(shè)備劃分payload 沿用 JSON 格式服務(wù)器端不用改任何解析邏輯。樓宇自控方向HVAC 設(shè)備經(jīng)常要對(duì)接 BMS 系統(tǒng)。Modbus TCP 是必須考慮的協(xié)議TM4C129XNCZAD 的資源跑 Modbus TCP 從站綽綽有余寄存器表把溫度值、告警狀態(tài)、設(shè)備開關(guān)量全部映射出來就行。海外高端樓宇可能要求 BACnet協(xié)議太重建議加網(wǎng)關(guān)設(shè)備而不是硬塞進(jìn) MCU術(shù)業(yè)有專攻。6.3 不依賴服務(wù)器的本地保護(hù)邏輯溫度監(jiān)測(cè)的最終價(jià)值是落到保護(hù)動(dòng)作上超溫時(shí)繼電器切斷壓縮機(jī)低溫時(shí)啟動(dòng)加熱器同時(shí)點(diǎn)亮聲光報(bào)警燈。關(guān)鍵一條這些邏輯必須完全本地執(zhí)行服務(wù)器掉線也要能保護(hù)設(shè)備??刂七壿嫿ㄗh采用上下限加滯回加故障安全。故障安全的意思是傳感器失效時(shí)控制器按保守策略運(yùn)行比如強(qiáng)制停止壓縮機(jī)并報(bào)警而不是用上次的正常值繼續(xù)帶載。HVAC 設(shè)備最怕的不是停機(jī)是傳感器壞了還按錯(cuò)誤溫度使勁運(yùn)行燒了壓縮機(jī)才叫大事故。滯回判斷的寫法很固定參考這段偽代碼#define RELAY_ON_TEMP 50.0f // 超 50°C 動(dòng)作 #define RELAY_OFF_TEMP 48.0f // 低于 48°C 恢復(fù) static uint8_t relay_state 0; void overtemp_protect(float temp) { if (relay_state 0 temp RELAY_ON_TEMP) { relay_state 1; relay_set(relay_state); } else if (relay_state 1 temp RELAY_OFF_TEMP) { relay_state 0; relay_set(relay_state); } }這里沒有判斷邊界的抖動(dòng)因?yàn)?2°C 的滯回區(qū)間就是天然的防抖。經(jīng)驗(yàn)值HVAC 保護(hù)的滯回至少給 1.5~2°C太小還是會(huì)誤觸發(fā)。最后按老規(guī)矩分享一下我的開發(fā)順序建議先把溫度數(shù)據(jù)從串口打出來穩(wěn)定跑三天再掛 LCD 顯示最后再碰以太網(wǎng)。絕大多數(shù)項(xiàng)目延誤都是跳過了前兩步直接在開發(fā)板上堆網(wǎng)絡(luò)代碼。另外一個(gè) USB 邏輯分析儀在 I2C 排錯(cuò)上比萬用表和示波器都好用幾十塊錢的能直接看到地址、ACK 和每字節(jié)數(shù)據(jù)比瞎猜快太多了。