測(cè)方案)
做嵌入式溫度監(jiān)測(cè)我最近一直在用 PJ85718DM 這顆傳感器加上 STM32F042C6 這顆 M0 主控做本地和遠(yuǎn)程溫度采集。剛開(kāi)始以為這就是“上拉電阻讀寄存器”的小活真正深入進(jìn)去才發(fā)現(xiàn)本地溫度、遠(yuǎn)程二極管測(cè)溫、HVAC 環(huán)境里的干擾和安裝方式每一環(huán)都有講究。這篇文章就把這套組合從選型、硬件、固件到現(xiàn)場(chǎng)調(diào)試的完整過(guò)程寫(xiě)出來(lái)適合正在做溫控、低壓變頻器、HVAC控制器或者電池管理系統(tǒng)里溫度保護(hù)的朋友參考。PJ85718DM 是一顆帶 I2C 接口的數(shù)字溫度傳感器和普通單點(diǎn)溫度芯片最大的區(qū)別是它同時(shí)支持本地溫度采樣和遠(yuǎn)程二極管溫度采樣。STM32F042C6 則是 Cortex-M0 內(nèi)核的 MCU主頻 48MHz內(nèi)置 CAN、USB、多路 USART 和硬件 I2C做傳感器數(shù)據(jù)讀取、PID 調(diào)節(jié)、Modbus 上報(bào)都足夠用。這個(gè)組合解決的核心問(wèn)題只有一個(gè)設(shè)備既要知道“自己身邊有多熱”也要知道“遠(yuǎn)處一個(gè)溫度敏感點(diǎn)有多熱”而且兩邊數(shù)據(jù)要在同一套采集鏈路里完成成本還不能高。1. 方案拆解為什么是“本地溫度傳感器 遠(yuǎn)程測(cè)溫通道”的組合1.1 PJ85718DM 到底解決了什么問(wèn)題很多場(chǎng)景需要一個(gè)傳感器同時(shí)照顧兩個(gè)測(cè)溫點(diǎn)。舉幾個(gè)我實(shí)際接觸過(guò)的例子嵌入式控制器里要監(jiān)控 PCB 環(huán)境溫度同時(shí)還要監(jiān)控功率器件或者主芯片的結(jié)溫。變頻器或者電機(jī)驅(qū)動(dòng)器里IGBT 模塊附近需要溫度保護(hù)但控制板上的 MCU 也想拿到散熱器溫度。HVAC 空調(diào)內(nèi)機(jī)控制板需要知道板載溫度來(lái)做防凝露判斷而蒸發(fā)器管路、回風(fēng)風(fēng)道的溫度又得靠一個(gè)伸出去的探頭采集。如果只用普通 NTC每個(gè)測(cè)溫點(diǎn)都要一路信號(hào)調(diào)理、一個(gè) ADC 通道、一套校準(zhǔn)系數(shù)硬件復(fù)雜校準(zhǔn)更是麻煩。PJ85718DM 這種帶遠(yuǎn)程通道的芯片本地通道直接讀芯片內(nèi)部結(jié)溫遠(yuǎn)程通道則通過(guò)一對(duì) D、D- 引腳接一顆二極管連接的三極管就能把遠(yuǎn)處的溫度信號(hào)拉回到同一顆芯片上處理輸出統(tǒng)一走 I2C 總線上報(bào)。遠(yuǎn)程測(cè)溫的核心原理并不難理解。二極管的 PN 結(jié)正向壓降 Vbe 會(huì)隨溫度變化大約每升高 1°C 降低 2mV 左右。但直接用 Vbe 絕對(duì)值算溫度會(huì)受到器件批次、串聯(lián)電阻、焊接工藝帶來(lái)的誤差影響。PJ85718DM 這類(lèi)芯片更常用的做法是“不同激勵(lì)電流下的 ΔVbe 測(cè)量”分別用兩種電流去驅(qū)動(dòng)外部二極管測(cè)量?jī)蓚€(gè) Vbe 的差值。因?yàn)?Vbe 絕對(duì)值里的固定項(xiàng)會(huì)被差分運(yùn)算抵消剩下的 ΔVbe 就和絕對(duì)溫度近似成正比再經(jīng)過(guò)片上 ADC 轉(zhuǎn)換就能得到數(shù)字溫度。這也是遠(yuǎn)程通道在較長(zhǎng)距離走線時(shí)仍然能維持精度的原因。本地通道則簡(jiǎn)單很多芯片內(nèi)部有一個(gè)寄生的測(cè)溫二極管和同一個(gè) ADC 采樣鏈路。因?yàn)楸镜貍鞲衅骱?ADC 在同一顆芯片里距離短、溫度梯度小所以本地精度通常能做到比遠(yuǎn)程更好。手冊(cè)里給的典型規(guī)格大約是本地 ±0.5°C遠(yuǎn)程 ±1°C 上下這在 HVAC 和一般嵌入式熱保護(hù)里已經(jīng)夠用。如果你只需要“大概準(zhǔn)”而不是“實(shí)驗(yàn)室級(jí)別準(zhǔn)”這套方案比外面掛三四個(gè) NTC 省事得多。1.2 為什么選 STM32F042C6 當(dāng)主控STM32F042C6 不算新器件但在這個(gè)項(xiàng)目里非常合適。它的技術(shù)參數(shù)并不華麗而是勝在接口全、功耗低、價(jià)格穩(wěn)定。Cortex-M0 內(nèi)核48MHz 主頻。跑 I2C 采樣、濾波算法、PID 或者簡(jiǎn)單的 Modbus 協(xié)議棧完全夠用不需要上高成本 M4。內(nèi)置 CAN 2.0B 和 USB FS。嵌入式場(chǎng)景里如果要和車(chē)輛總線、運(yùn)動(dòng)控制器通訊CAN 是現(xiàn)成的如果要做本地調(diào)試USB 虛擬串口插上就能看數(shù)據(jù)流。I2C 接口是硬件外設(shè)不需要軟件模擬時(shí)序。配合 DMA 和中斷讀溫度寄存器只需要幾個(gè)周期CPU 時(shí)間可以留給控制邏輯。工作電壓只有 3.3V邏輯電平、功耗模型都很好規(guī)劃。整個(gè)測(cè)溫節(jié)點(diǎn)如果控制得夠精細(xì)運(yùn)行電流可以做到很低。OFQFN 或者 LQFP 封裝體積小適合塞進(jìn) HVAC 控制板這種空間不寬裕的場(chǎng)合。有人會(huì)問(wèn)既然只是讀溫度為什么不用一顆 8 腳的小單片機(jī)因?yàn)檫@類(lèi)項(xiàng)目通常不是“只測(cè)溫”這一個(gè)功能。STM32F042C6 還要負(fù)責(zé)繼電器控制、風(fēng)扇調(diào)速、狀態(tài)指示、與上位機(jī)通訊甚至跑本地保護(hù)邏輯。留出一路 I2C 接溫度傳感器只是它的本職工作之一。1.3 這套組合在什么項(xiàng)目里最劃算我做這套的時(shí)候總結(jié)過(guò)一個(gè)判斷標(biāo)準(zhǔn)如果你只需要測(cè)一個(gè)點(diǎn)的溫度用一顆單通道數(shù)字傳感器或者 NTC 加運(yùn)放就解決了完全沒(méi)必要上雙通道遠(yuǎn)程方案但如果系統(tǒng)里“板內(nèi)溫度”和“遠(yuǎn)端溫度”都必須要而且兩者距離可能超過(guò) 20cm、甚至分屬不同 PCB 或者不同結(jié)構(gòu)件那 PJ85718DM 這種方案就開(kāi)始變得合適。典型的嵌入式場(chǎng)景包括充電器 / 電源適配器本地測(cè)內(nèi)部環(huán)境溫度遠(yuǎn)程測(cè)充電接口或者電池包表面溫度超過(guò)閾值直接降功率。無(wú)刷電機(jī)驅(qū)動(dòng)板本地測(cè) PCB 溫度遠(yuǎn)程通過(guò)一顆貼在三相橋散熱片上的二極管三極管測(cè)散熱器溫度。智能照明電源LED 金屬基板上的溫度點(diǎn)通過(guò)遠(yuǎn)程探頭采集實(shí)現(xiàn)過(guò)溫降額延長(zhǎng) LED 壽命。HVAC 場(chǎng)景則更直接空調(diào)外機(jī)控制器本地測(cè)電控盒溫度遠(yuǎn)程探頭固定到壓縮機(jī)排氣管或者冷凝器管壁配合制冷邏輯做防過(guò)載。新風(fēng)系統(tǒng)控制板測(cè)電路溫度遠(yuǎn)程探頭伸進(jìn)風(fēng)道測(cè)進(jìn)風(fēng)溫度用來(lái)判斷是否結(jié)露。恒溫恒濕設(shè)備本地是控制板溫度遠(yuǎn)程測(cè)量水箱或者出風(fēng)口溫度。這些場(chǎng)景的共同點(diǎn)是遠(yuǎn)端溫度點(diǎn)本身不方便放一整塊帶 MCU 和通信芯片的電路板只放一顆小二極管非常靈活。把二極管用導(dǎo)熱膠貼在目標(biāo)物體表面引線長(zhǎng)度控制在幾十厘米內(nèi)溫度信號(hào)就能回到主控板上的 PJ85718DM再由同一顆芯片轉(zhuǎn)成 I2C 數(shù)據(jù)給 STM32F042C6。這種一主一從的架構(gòu)比在每個(gè)測(cè)溫點(diǎn)單獨(dú)放傳感器、再通過(guò)長(zhǎng)線通訊回傳可靠性和成本都更優(yōu)。2. 硬件設(shè)計(jì)PJ85718DM 與 STM32F042C6 的完整連接鏈路2.1 傳感器最小電路別只拉兩線上拉電阻PJ85718DM 的引腳不多一般可以歸納為電源 VDD、地 GND、I2C 時(shí)鐘 SCL、數(shù)據(jù) SDA、遠(yuǎn)程測(cè)溫正負(fù)端 D、D-還有地址選擇 ADD0/ADD1、報(bào)警輸出 OS/ALERT。不同批次可能引腳定義順序有變化但功能類(lèi)別是穩(wěn)定的。在設(shè)計(jì)最小電路時(shí)下面這幾個(gè)要點(diǎn)是我自己的習(xí)慣VDD 對(duì) GND 必須放 0.1μF 陶瓷電容并且靠近引腳放。如果系統(tǒng)電源紋波較大再并聯(lián)一個(gè) 1μF 到 10μF 的電容實(shí)測(cè)對(duì)溫度讀數(shù)穩(wěn)定性很有幫助。SDA、SCL 都需要上拉電阻。電阻值要按總線上掛的設(shè)備數(shù)量、走線長(zhǎng)度和通信速率來(lái)定??偩€上只有這顆傳感器工作頻率在 400kHz 以?xún)?nèi)上拉 4.7kΩ 通常沒(méi)問(wèn)題如果線長(zhǎng)超過(guò) 10cm 或者總線電容偏大就換 2.2kΩ。ADD0/ADD1 決定 I2C 地址。做多路采集時(shí)可以用同一個(gè)寄存器地址通過(guò)不同地址段的芯片接在同一條 I2C 總線上每路能區(qū)分開(kāi)。OS/ALERT 是漏極開(kāi)路輸出也要接上拉電阻并且可以接到 STM32F042C6 的外部中斷引腳。這樣溫度超過(guò)閾值時(shí)MCU 不需要輪詢(xún)直接被中斷喚醒處理。我通常把傳感器放在控制板邊緣靠近遠(yuǎn)程探頭接線端子那一側(cè)避免 D、D- 的長(zhǎng)走線穿過(guò)板子中間的電源區(qū)域。一個(gè)需要注意的坑是遠(yuǎn)程測(cè)溫腳 D、D- 的極性。大多數(shù)傳感器要求把二極管三極管的集電極和基極短接后接 D發(fā)射極接 D-接反了讀數(shù)會(huì)明顯不對(duì)。有的芯片手冊(cè)里說(shuō)“支持反接檢測(cè)”但為了省調(diào)試時(shí)間我建議直接按標(biāo)準(zhǔn)接法設(shè)計(jì)不要賭。下面是一張參考連接示意表信號(hào)PJ85718DM 引腳連接目標(biāo)關(guān)鍵參數(shù)供電VDD3.3V0.1μF 去耦電容地GNDGND單點(diǎn)接地時(shí)鐘SCLSTM32F042C6 PB6上拉 4.7kΩ 到 3.3V數(shù)據(jù)SDASTM32F042C6 PB7上拉 4.7kΩ 到 3.3V地址ADD0/ADD1高/低電平組合決定 I2C 地址報(bào)警OS/ALERTSTM32F042C6 PA0 EXTI漏極開(kāi)路需上拉遠(yuǎn)程D二極管三極管 BC 短接端走線盡量短遠(yuǎn)程-D-二極管三極管發(fā)射極走線盡量短STM32F042C6 這邊VDD 就近加 0.1μF 和 4.7μF 電容NRST 默認(rèn)上拉BOOT0 下拉到地。如果系統(tǒng)里要跑 USB 或者 CAN還要注意晶振和終端電阻這些和普通 STM32 設(shè)計(jì)沒(méi)有區(qū)別不展開(kāi)細(xì)說(shuō)。2.2 遠(yuǎn)程測(cè)溫為什么非得用“三極管接成二極管”很多人第一次看到遠(yuǎn)程溫度探頭會(huì)下意識(shí)覺(jué)得“直接拿一個(gè)普通整流二極管不就行了嗎”。我試過(guò)能工作但精度差不少。PJ85718DM 這類(lèi)芯片測(cè)量遠(yuǎn)程溫度依賴(lài)的是二極管的 Vbe 溫度特性而我們實(shí)際希望測(cè)量的是一個(gè)理想二極管模型的結(jié)溫。普通整流二極管比如 1N4007正向特性不一致生產(chǎn)批次差異大而且封裝管殼熱阻高感應(yīng)到的往往是引腳周?chē)諝鉁囟榷皇悄繕?biāo)物體溫度。更合適的做法是用小信號(hào)三極管比如常見(jiàn)的 MMBT3906把基極和集電極短接讓集電結(jié)變成零偏置只讓發(fā)射結(jié)發(fā)揮二極管作用。這樣發(fā)射結(jié)面積小、熱阻低能更準(zhǔn)確地感應(yīng)粘貼位置的溫度。三極管的工藝一致性比普通二極管好批次離散性小。不同型號(hào)三極管的 ideality factor 值非理想因子相對(duì)接近芯片內(nèi)置的校正算法能更好匹配。更進(jìn)一步的場(chǎng)景是直接測(cè)量 MCU、CPU、GPU 芯片內(nèi)部的結(jié)溫。很多處理器會(huì)把片上測(cè)溫二極管引到外部引腳使用前要查清楚是 PNP 對(duì)管還是 NPN 對(duì)管結(jié)構(gòu)、電流激勵(lì)大小、是否需要設(shè)置 ideality factor 寄存器。PJ85718DM 如果提供 n-factor 校正配置就要按目標(biāo)芯片手冊(cè)里的參數(shù)寫(xiě)進(jìn)去。如果忽略這一步遠(yuǎn)程讀數(shù)可能會(huì)有 1°C 到 2°C 的誤差在某些應(yīng)用里這就足以觸發(fā)保護(hù)動(dòng)作了。2.3 HVAC 環(huán)境下的 PCB 布局和抗干擾經(jīng)驗(yàn)HVAC 設(shè)備里的電磁環(huán)境說(shuō)不上惡劣但比實(shí)驗(yàn)室惡劣得多。我踩過(guò)的坑里印象最深的是風(fēng)機(jī)繼電器吸合的瞬間溫度讀數(shù)跳一下然后恢復(fù)正常。用示波器看 D 引腳發(fā)現(xiàn)上面疊加了不小的高頻毛刺。溫度傳感器內(nèi)部 ADC 采樣雖然會(huì)做濾波但遠(yuǎn)程模擬輸入端口是高阻抗處理不好就容易吸收噪聲。我的處理經(jīng)驗(yàn)有這么幾條D、D- 差分走線盡量貼近中間不要穿插其他信號(hào)線避免形成大的環(huán)路面積。在傳感器 D、D- 引腳附近加一個(gè)幾十 pF 到幾百 pF 的對(duì)地電容。注意不能加太大電容過(guò)大會(huì)影響電流建立時(shí)間導(dǎo)致轉(zhuǎn)換結(jié)果偏低。通常 100pF 起步實(shí)測(cè)可用性最高。如果遠(yuǎn)程探頭線必須過(guò)長(zhǎng)超過(guò) 30cm就在探頭端做一個(gè) RC 低通濾波而不是在主板上硬扛。傳感器和 MCU 的地、電源地之間做單點(diǎn)連接避免繼電器驅(qū)動(dòng)的地電流串進(jìn)傳感器地。報(bào)警輸出漏極開(kāi)路引腳上拉電阻不要選太大否則邊沿過(guò)慢在電磁噪聲里容易被誤觸發(fā)中斷我一般用 4.7kΩ。另外不管板內(nèi)空間多緊張我都建議給遠(yuǎn)程溫度探頭留一個(gè)獨(dú)立的連接器不要直接把裸線焊在主板上。現(xiàn)場(chǎng)接線時(shí)HVAC 設(shè)備往往需要拆裝多次可插拔連接器能減少線纜折斷的概率后續(xù)維護(hù)更換探頭也方便。接線端子盡量選帶鎖定結(jié)構(gòu)的防止震動(dòng)松脫。3. 固件設(shè)計(jì)把溫度讀數(shù)變成可控可用的數(shù)據(jù)3.1 I2C 底層讀取與寄存器讀寫(xiě)STM32F042C6 使用硬件 I2C我在項(xiàng)目里優(yōu)先用 HAL 庫(kù)因?yàn)樗鼘?duì)超時(shí)、錯(cuò)誤標(biāo)志的處理比較完整。調(diào)用方式并不復(fù)雜以讀取本地溫度寄存器為例uint8_t data[2]; HAL_StatusTypeDef status; status HAL_I2C_Mem_Read( hi2c1, (uint16_t)(PJ85718_ADDR 1), PJ85718_REG_LOCAL_TEMP, I2C_MEMADD_SIZE_8BIT, data, 2, 100 ); if (status ! HAL_OK) { // 記錄一次總線錯(cuò)誤連續(xù)失敗則嘗試恢復(fù) I2C 總線 }PJ85718_ADDR 要根據(jù) ADD0、ADD1 的跳線來(lái)定義不能寫(xiě)死成 0x90。寄存器地址按照手冊(cè)填寫(xiě)讀取順序要一次性讀完 2 字節(jié)不要拆成兩次字節(jié)讀取否則在兩次讀取之間數(shù)據(jù)更新高低字節(jié)會(huì)錯(cuò)位溫度值可能出現(xiàn)異常跳變。為了屏蔽總線上其他干擾我給每次讀取加了超時(shí)。HAL 里面最后一個(gè)參數(shù)就是超時(shí)時(shí)間毫秒在溫控邏輯中我習(xí)慣設(shè)為 20ms。超過(guò) 20ms 還沒(méi)讀回來(lái)就判定總線掛死走 5.2 小節(jié)的恢復(fù)流程。3.2 溫度轉(zhuǎn)換計(jì)算從寄存器原始值到“讓人看得懂”的攝氏度PJ85718DM 的溫度數(shù)據(jù)寄存器一般是 16 位高 12 位是有效溫度低 4 位作為擴(kuò)展精度或者為 0。典型分辨率是 0.0625°C也就是把最高有效位當(dāng)作符號(hào)位。轉(zhuǎn)換時(shí)先將兩個(gè)字節(jié)拼成 int16_t再右移 4 位得到真正的 12 位有符號(hào)數(shù)最后乘 0.0625。int16_t raw (int16_t)((data[0] 8) | data[1]); raw 4; // 保留 12 位有符號(hào)溫度 float temp_c (float)raw * 0.0625f;舉個(gè)例子如果 data[0]0x0Ddata[1]0xA0拼起來(lái)是 0x0DA0右移 4 位得到 0x0DA 即 218218 × 0.0625 13.625°C。如果寄存器值是負(fù)溫度右移后符號(hào)擴(kuò)展依然成立這個(gè)公式不用額外處理。遠(yuǎn)程溫度寄存器采用同樣的轉(zhuǎn)換方式。在把原始值轉(zhuǎn)成 float 之前我還建議保留一份原始寄存器值用于后期排查。現(xiàn)場(chǎng)設(shè)備一旦出現(xiàn)溫度異常先用 I2C 調(diào)試器讀寄存器確認(rèn)是“傳感器本身讀數(shù)就不對(duì)”還是“固件轉(zhuǎn)換或上層處理引入了錯(cuò)誤”。這一步在 HVAC 設(shè)備遠(yuǎn)程維修時(shí)特別管用能省下大量來(lái)回跑現(xiàn)場(chǎng)的功夫。3.3 閾值報(bào)警讓 MCU 靠中斷而不是阻塞輪詢(xún)?nèi)绻?100ms 讀一次溫度輪詢(xún)也不會(huì)占用很多 CPU但優(yōu)勢(shì)在于報(bào)警能力。PJ85718DM 一般有本地和遠(yuǎn)程高低溫限值寄存器還會(huì)有一個(gè) OS/ALERT 輸出腳。把高低溫限值寫(xiě)進(jìn)去之后芯片自身會(huì)持續(xù)監(jiān)控兩個(gè)通道溫度一旦超限就把 OS/ALERT 引腳拉低。我在項(xiàng)目里是這樣安排的初始化階段寫(xiě)入本地通道高溫限值、遠(yuǎn)程通道高溫限值和恢復(fù)回差。OS/ALERT 配置成“比較器模式”溫度低于限值時(shí)自動(dòng)恢復(fù)不鎖存。STM32F042C6 的 PA0 配置為外部中斷下降沿觸發(fā)。中斷服務(wù)函數(shù)里只置一個(gè)標(biāo)志位具體的風(fēng)扇調(diào)速、降功率、報(bào)警動(dòng)作放在主循環(huán)處理避免在中斷里做耗時(shí)的 I2C 操作。有一點(diǎn)值得注意報(bào)警限值寄存器用的是和溫度寄存器一樣的分辨率寫(xiě)入時(shí)要把目標(biāo)溫度值除以 0.0625 再換算成整型。比如遠(yuǎn)程最高溫度要設(shè)成 85°C寄存器值就是 85 / 0.0625 1360也就是 0x0550。如果用浮點(diǎn)算完以后不處理對(duì)齊問(wèn)題可能寫(xiě)入一個(gè)略高于目標(biāo)值的數(shù)導(dǎo)致保護(hù)動(dòng)作偏差。3.4 低功耗輪詢(xún)策略這個(gè)方案里傳感器本體功耗很低真正的功耗大頭是 MCU。STM32F042C6 常用的運(yùn)行模式電流有個(gè)幾十毫安但對(duì)電池供電的設(shè)備來(lái)說(shuō)還不夠。我的低功耗策略是“傳感器 asleepMCU stop定時(shí)醒來(lái)一下”。具體時(shí)序是將 PJ85718DM 寫(xiě) shutdown 配置進(jìn)入低功耗待機(jī)。STM32F042C6 進(jìn)入 STOP 模式使用 RTC 或低功耗定時(shí)器設(shè)置喚醒周期。喚醒后給傳感器發(fā)起一次 one-shot 轉(zhuǎn)換等待轉(zhuǎn)換完成讀取溫度寄存器。判斷溫度是否超限然后迅速重新進(jìn)入 STOP。這樣的設(shè)計(jì)能把平均電流壓到微安級(jí)別適合溫度采集節(jié)點(diǎn)。HVAC 控制板通常不要求這么省電但嵌入式電池設(shè)備比如無(wú)線傳感器、冷鏈標(biāo)簽就非常有幫助。需要注意的是one-shot 轉(zhuǎn)換不是馬上完成的啟動(dòng)后必須讓傳感器內(nèi)部 ADC 完成采樣再讀寄存器。有的芯片會(huì)提供數(shù)據(jù)更新標(biāo)志沒(méi)有標(biāo)志的話就按手冊(cè)里的轉(zhuǎn)換時(shí)間延時(shí)。延時(shí)太短讀到的還是上一次數(shù)據(jù)太長(zhǎng)又浪費(fèi)電流所以這個(gè)時(shí)間要按手冊(cè)算準(zhǔn)。不同分辨率模式對(duì)應(yīng)不同的轉(zhuǎn)換時(shí)間一般從幾十毫秒到一兩百毫秒不等。4. 數(shù)據(jù)從量測(cè)到應(yīng)用嵌入式保護(hù)邏輯與 HVAC 監(jiān)控平臺(tái)4.1 嵌入式場(chǎng)景里的環(huán)形緩沖、濾波與 ODT 保護(hù)嵌入式中控板需要的不僅僅是“當(dāng)前溫度值”而是“趨勢(shì)”和“變化率”。我常用的做法是在內(nèi)存里維護(hù)一個(gè)環(huán)形緩沖保存最近 16 到 32 次溫度采樣然后計(jì)算移動(dòng)平均。#define TEMP_BUF_LEN 16 static float temp_buf[TEMP_BUF_LEN]; static uint8_t idx 0; static float temp_sum 0.0f; float update_moving_average(float new_value) { temp_sum - temp_buf[idx]; temp_buf[idx] new_value; temp_sum new_value; idx (idx 1) % TEMP_BUF_LEN; return temp_sum / TEMP_BUF_LEN; }這個(gè)寫(xiě)法占用資源極小但能明顯抑制偶發(fā)毛刺。配合變化率檢測(cè)還能做 ODT過(guò)溫降額或者熱保護(hù)當(dāng)遠(yuǎn)程溫度每秒鐘上升超過(guò)某個(gè)斜率比如 5°C/s就提前降低 PWM 占空比而不是等溫度沖到閾值才動(dòng)。在電機(jī)驅(qū)動(dòng)和電源適配器里提前一點(diǎn)降額往往比事后切斷更實(shí)用因?yàn)樨?fù)載可以繼續(xù)工作只是性能稍微下降。HVAC 里的風(fēng)機(jī)調(diào)速邏輯也類(lèi)似。遠(yuǎn)程冷凝器溫度高時(shí)提高風(fēng)機(jī)轉(zhuǎn)速溫度降下來(lái)后再逐步降速中間加滯回區(qū)間避免風(fēng)機(jī)頻繁變速。PJ85718DM 雙通道的優(yōu)勢(shì)在這里體現(xiàn)得很充分本地溫度負(fù)責(zé)控制板自身熱保護(hù)遠(yuǎn)程溫度負(fù)責(zé)制冷循環(huán)熱負(fù)荷判斷兩路各自有獨(dú)立的報(bào)警限值互不干擾。4.2 HVAC 場(chǎng)景通過(guò) Modbus 把溫度上報(bào)到監(jiān)控平臺(tái)設(shè)備端的溫度數(shù)據(jù)要送到人機(jī)界面或者樓宇控制系統(tǒng)在 HVAC 行業(yè)最通用的還是 RS485 加 Modbus RTU。STM32F042C6 的 USART 加上一個(gè)收發(fā)器配合中斷發(fā)送和接收就能實(shí)現(xiàn)簡(jiǎn)潔的從機(jī)棧。我習(xí)慣把溫度值按 0.1°C 為單位存到保持寄存器里這樣整數(shù)運(yùn)算足夠精度也比 0.0625°C 低不了多少還能避開(kāi)浮點(diǎn)和 Modbus 協(xié)議編碼的麻煩。一張典型的寄存器映射表如下Modbus 地址內(nèi)容說(shuō)明40001本地溫度單位 0.1°C有符號(hào)整型40002遠(yuǎn)程溫度單位 0.1°C有符號(hào)整型40003報(bào)警狀態(tài)字bit0本地高溫bit1本地低溫bit2遠(yuǎn)程高溫bit3遠(yuǎn)程低溫40004設(shè)備狀態(tài)bit0傳感器通信正常bit1正在除霜等協(xié)議棧不需要做全套復(fù)雜邏輯只需要支持 03 讀保持寄存器、06 寫(xiě)單個(gè)寄存器、16 寫(xiě)多個(gè)寄存器就能滿足大多數(shù)現(xiàn)場(chǎng)需求。寫(xiě)入功能多用于遠(yuǎn)程設(shè)置溫度閾值這里要留意整數(shù)單位換算比如上位機(jī)寫(xiě)入 850 表示 85.0°C固件里要除以 10 再存到浮點(diǎn)變量寫(xiě)回傳感器時(shí)再乘回 16 倍換算成寄存器的 0.0625°C 單位。單位不統(tǒng)一是現(xiàn)場(chǎng)參數(shù)錯(cuò)亂的高頻原因我建議在代碼里把所有溫度值統(tǒng)一成“0.1°C 有符號(hào)整型”到了傳感器驅(qū)動(dòng)層再單獨(dú)換算。嵌入式設(shè)備內(nèi)部通訊如果走 CAN則更簡(jiǎn)單每 100ms 發(fā)送一幀 CAN 標(biāo)準(zhǔn)幀ID 前 8 位是設(shè)備類(lèi)型后面數(shù)據(jù)字節(jié)放本地溫度、遠(yuǎn)程溫度、報(bào)警標(biāo)志。總線節(jié)點(diǎn)少的話不需要復(fù)雜的網(wǎng)絡(luò)管理只要約定好數(shù)據(jù)格式即可。4.3 多點(diǎn)校準(zhǔn)與一致性傳感器出廠雖然做過(guò)校準(zhǔn)但遠(yuǎn)程通道的探頭安裝位置、導(dǎo)熱介質(zhì)、線路電阻都會(huì)影響最終讀數(shù)。在 HVAC 和嵌入式現(xiàn)場(chǎng)我強(qiáng)烈建議做一次“系統(tǒng)級(jí)校準(zhǔn)”而不僅僅是芯片級(jí)校準(zhǔn)。校準(zhǔn)流程我一般這樣做把遠(yuǎn)程探頭的感溫端和一只標(biāo)準(zhǔn)溫度探頭綁在一起放在同一個(gè)恒溫環(huán)境里。分別在 0°C、25°C、50°C或者項(xiàng)目關(guān)心的下限、中間、上限三點(diǎn)讀取 PJ85718DM 遠(yuǎn)程溫度值。用最小二乘法擬合出實(shí)際溫度 測(cè)量溫度 × k b 的系數(shù)把 k 和 b 存在 STM32F042C6 的 Flash 里。固件每次上報(bào)前調(diào)用這段校正公式而不是直接上報(bào)原始轉(zhuǎn)換值。如果應(yīng)用場(chǎng)景溫度范圍不大也可以只做單點(diǎn)偏移校正。但要注意只調(diào)整偏移不調(diào)整增益在距離中心溫度較遠(yuǎn)的位置可能依然有偏差。比如 HVAC 設(shè)備冬季遠(yuǎn)程溫度在零下夏季在 60°C跨度大就必須兩到三點(diǎn)校正。導(dǎo)熱介質(zhì)也是容易忽略的誤差來(lái)源。遠(yuǎn)程探頭感溫部分要用導(dǎo)熱硅脂和被測(cè)物體充分接觸不能留空氣間隙??諝獾膶?dǎo)熱系數(shù)很低會(huì)造成明顯滯后和偏低讀數(shù)。現(xiàn)場(chǎng)如果是測(cè)水管外壁還要先清除表面的銹漬和水垢否則測(cè)量的是“銹層溫度”而非“管壁溫度”。5. 實(shí)測(cè)中的坑與排查辦法5.1 溫度讀數(shù)跳變幾十度過(guò)一會(huì)兒又恢復(fù)這個(gè)現(xiàn)象我在第一次做遠(yuǎn)程測(cè)溫時(shí)碰到過(guò)。表面看是數(shù)字亂跳用示波器看發(fā)現(xiàn)遠(yuǎn)程通道波形上疊加了尖峰。排查順序如下確認(rèn)遠(yuǎn)程三極管基極和集電極確實(shí)短接。如果只是用一個(gè)普通二極管接法不對(duì)就可能出現(xiàn)異常。檢查 D、D- 走線是否和繼電器驅(qū)動(dòng)線、電源線平行。如果平行長(zhǎng)度長(zhǎng)嘗試換層、加寬間距。在 D、D- 對(duì)地加 100pF 到 220pF 電容看跳變是否減小。如果數(shù)據(jù)還是亂跳把遠(yuǎn)程探頭線斷開(kāi)用短跳線直接在板載焊盤(pán)上接入測(cè)溫管排除長(zhǎng)線問(wèn)題。這個(gè)問(wèn)題的本質(zhì)是遠(yuǎn)程模擬信號(hào)太容易被干擾。和普通數(shù)字 I2C 不一樣遠(yuǎn)程二極管測(cè)量是一個(gè)微弱的模擬量你沒(méi)法靠“重發(fā)一次數(shù)據(jù)”來(lái)補(bǔ)救必須在硬件端就把噪聲抑制住。5.2 I2C 總線掛死傳感器不回 ACK現(xiàn)象是主控讀取超時(shí)SCL 正常SDA 一直是低電平。這種情況多數(shù)是系統(tǒng)剛上電、總線上有其他設(shè)備搶占了通信或者 SDA 在通信過(guò)程中被干擾拉低。我用的恢復(fù)方法是“總線時(shí)鐘脈沖恢復(fù)法”void recover_i2c_bus(void) { GPIO_InitTypeDef gpio {0}; gpio.Mode GPIO_MODE_OUTPUT_OD; gpio.Pull GPIO_PULLUP; gpio.Speed GPIO_SPEED_FREQ_LOW; HAL_GPIO_Init(SDA_GPIO_Port, gpio); for (int i 0; i 10; i) { HAL_GPIO_WritePin(SCL_Pin, GPIO_PIN_RESET); delay_us(5); HAL_GPIO_WritePin(SCL_Pin, GPIO_PIN_SET); delay_us(5); } HAL_GPIO_WritePin(SDA_Pin, GPIO_PIN_SET); MX_I2C1_Init(); // 重新初始化硬件外設(shè) }這個(gè)辦法利用 SCL 時(shí)鐘沿讓掛死的從機(jī)釋放 SDA成功率比較高。但如果傳感器徹底死機(jī)脈沖不起作用就需要掉電重啟傳感器。所以我在硬件設(shè)計(jì)上給 PJ85718DM 的電源加了一個(gè)由 GPIO 控制的負(fù)載開(kāi)關(guān)。真到需要復(fù)位傳感器的時(shí)候只需要把 GPIO 拉低再拉高不用整個(gè)系統(tǒng)斷電。這一點(diǎn)在 HVAC 現(xiàn)場(chǎng)特別重要因?yàn)樵O(shè)備一旦運(yùn)行斷電重啟需要停機(jī)會(huì)造成很大的麻煩。能單獨(dú)復(fù)位傳感器比復(fù)位整個(gè)控制器好太多。5.3 低溫環(huán)境下讀數(shù)偏高的“假高溫”有次在冷庫(kù)設(shè)備里傳感器裝在控制柜內(nèi)控制柜在冷庫(kù)內(nèi)部遠(yuǎn)程探頭貼在蒸發(fā)器盤(pán)管上。調(diào)試時(shí)發(fā)現(xiàn)遠(yuǎn)程溫度始終比現(xiàn)場(chǎng)溫度高 3°C 左右而且很穩(wěn)定。后來(lái)發(fā)現(xiàn)是冷庫(kù)環(huán)境里空氣相對(duì)濕度很大遠(yuǎn)程探頭感溫部分和導(dǎo)熱硅脂暴露在潮濕空氣中表面結(jié)了一層冰水混合物等效熱阻變大導(dǎo)致傳感器感知的不是盤(pán)管壁溫而是冰層外面的溫度。解決辦法并不神秘把探頭感溫部分用高強(qiáng)度導(dǎo)熱膠密封起來(lái)再壓緊在管壁上接線端子涂抹防凝露硅膠控制柜內(nèi)加一點(diǎn)小功率加熱防止 PCB 直接結(jié)露。之后讀數(shù)就和參考溫度一致了。HVAC 設(shè)備做溫度監(jiān)測(cè)安裝工藝常常比電路設(shè)計(jì)影響更大。5.4 遠(yuǎn)程二極管選型導(dǎo)致的精度偏移我這里補(bǔ)充一個(gè)容易踩的坑PJ85718DM 的手冊(cè)通常會(huì)建議用 2N3904/2N3906 這類(lèi)小信號(hào)三極管做遠(yuǎn)程測(cè)溫探頭但現(xiàn)場(chǎng)如果采購(gòu)替代料很可能買(mǎi)到貼片封裝、die 材料或者工藝參數(shù)差異較大的管子。替代料的 ideality factor 和手冊(cè)校正參數(shù)不匹配采集到的溫度會(huì)穩(wěn)定偏移有的甚至?xí)?2°C 以上。處理方式有兩種嚴(yán)格按推薦型號(hào)采購(gòu)不隨意替代。遠(yuǎn)程溫度探頭是整個(gè)系統(tǒng)里的極小成本項(xiàng)沒(méi)必要在這里省幾毛錢(qián)。如果必須替代就在固件里開(kāi)放一個(gè)遠(yuǎn)程通道增益校正參數(shù)通過(guò)遠(yuǎn)程補(bǔ)償寄存器把誤差拉回來(lái)。前提是芯片支持 ideality factor 或 offset 補(bǔ)償PJ85718DM 這類(lèi)芯片一般會(huì)有對(duì)應(yīng)寄存器。我把常見(jiàn)現(xiàn)象和排查方法整理成了表格方便現(xiàn)場(chǎng)用現(xiàn)象可能原因處理辦法遠(yuǎn)程溫度讀數(shù)明顯偏高/偏低且穩(wěn)定遠(yuǎn)程三極管型號(hào)不匹配、導(dǎo)熱不良按推薦型號(hào)更換重新涂導(dǎo)熱膠本地溫度正常遠(yuǎn)程溫度跳變D/D- 受干擾加濾波電容調(diào)整布線溫度讀數(shù)為 0 或全 1傳感器未初始化、I2C 地址錯(cuò)檢查地址引腳讀回寄存器驗(yàn)證I2C 通信超時(shí)總線掛死用 SCL 脈沖恢復(fù)必要時(shí)重啟傳感器現(xiàn)場(chǎng)溫度正常上報(bào)溫度滯后探頭熱阻大、安裝位置不當(dāng)改善接觸減小熱阻最后再分享一個(gè)小技巧這套方案真正穩(wěn)定運(yùn)行之后我反而舍不得刪掉調(diào)試階段留下的一組“原始值日志”。就是每次把 PJ85718DM 的本地溫度高字節(jié)、遠(yuǎn)程溫度高字節(jié)、報(bào)警狀態(tài)原樣打進(jìn)日志和經(jīng)過(guò)程序轉(zhuǎn)換后的溫度值放在一起。線上設(shè)備一旦出現(xiàn)保護(hù)動(dòng)作先看原始寄存器就知道是傳感器數(shù)據(jù)本身出錯(cuò)還是后端的濾波、轉(zhuǎn)換、閾值比較環(huán)節(jié)出了問(wèn)題。另一個(gè)小經(jīng)驗(yàn)是給遠(yuǎn)程探頭預(yù)留一個(gè)“開(kāi)路自檢”流程。當(dāng)遠(yuǎn)程 D、D- 懸空時(shí)芯片一般能返回一個(gè)明顯異常的溫度值比如 -64°C 或者 127°C。固件里判斷到這種情況直接把對(duì)應(yīng)通道標(biāo)記為故障而不是把異常溫度送進(jìn)控制邏輯。否則 HVAC 設(shè)備在運(yùn)行中探頭線斷掉控制邏輯可能會(huì)誤以為溫度過(guò)低持續(xù)加熱釀成事故。溫度監(jiān)測(cè)系統(tǒng)最重要的不是把數(shù)據(jù)算得多么精確而是在傳感器異常時(shí)能“知道自己是異常的”。這一點(diǎn)做嵌入式的人越早明白越好。