計)
過去一年多我在三個產(chǎn)品上做過同一件事用一顆低功耗 MCU 加一顆帶遠程通道的溫度傳感器把本地溫度和遠端溫度一起讀準再按周期送出去。三塊板子分別是某項目的 HVAC 控制面板、一個電機驅(qū)動器和一張電池管理檢測子卡測溫對象雖然完全不同但骨架完全一樣——PJ85718DM 負責把本地溫度與遠端探頭的溫度變成數(shù)字量STM32L021K4 負責在大部分時間里休眠只按周期醒來取數(shù)、校準、上報。如果你正在做嵌入式溫度監(jiān)測或者想給 HVAC 的控制器加一路遠程測溫這篇應(yīng)該能幫你省掉不少彎路。下面我把這套設(shè)計從需求、電路、固件到聯(lián)調(diào)細節(jié)完整捋一遍包括我在實際調(diào)試中踩過的幾個坑能避一個是一個。1. 這套組合要解決什么本地與遠程測溫的兩個典型場景1.1 嵌入式里的遠程溫度和 HVAC 里的遠程溫度不是一回事在寫代碼之前先把概念捋清楚。嵌入式系統(tǒng)里說的本地溫度通常指傳感器所在 PCB 附近的環(huán)境溫度或者機箱內(nèi)部溫度遠程溫度則指放在遠處測溫對象里的測溫二極管比如電源管理芯片、功率器件模塊內(nèi)部的襯底二極管。這類二極管并沒有封裝成傳感器只是芯片里引出來的一對引腳需要專門的測溫 IC 去激勵和讀取。HVAC 行業(yè)對兩個詞的理解略不同。本地溫度一般指控制器所在柜體內(nèi)的空氣溫度遠程溫度指安裝在風管、送風口、回風口或管道表面的探頭讀數(shù)探頭和控制器之間可能隔著 1 到 10 米線纜。HVAC 的遠程強調(diào)的是距離和現(xiàn)場安裝條件而不單純指半導(dǎo)體二極管。這兩種場景放在一起看共性非常清楚都需要兩路測溫一路在板子上一路在別處都需要較低的系統(tǒng)功耗因為 HVAC 控制器和嵌入式設(shè)備經(jīng)常長期通電待機都需要盡可能免標定、讀數(shù)穩(wěn)定、抗現(xiàn)場干擾。PJ85718DM 正好把本地和遠程兩個通道做在一顆芯片里MCU 只需要通過 I2C 讀寄存器不需要自己搭二極管激勵電路。這就是整套設(shè)計的出發(fā)點。1.2 為什么不用兩路 NTC 或 MCU 內(nèi)置 ADC 直接采NTC 便宜HVAC 里非常常見但每個探頭都有 B 值和精度離散性批量生產(chǎn)時要逐個標定或者接受比較寬的誤差。MCU 內(nèi)置 ADC 直采還要處理參考電壓、自熱、走線串擾如果板子上還有 PWM、繼電器、變頻電機模擬采樣的抗干擾成本并不低。遠程二極管測溫的核心優(yōu)勢在于測的是兩個電流下的 ΔVBE 壓差二極管絕對壓差的離散偏移被抵消所以探頭一致性好。數(shù)字接口 I2C 比長距離模擬線好處理雖然 I2C 本身不適合拉 10 米但把模擬前端從探頭搬到傳感器芯片里之后探頭到芯片只要兩根短線或雙絞線芯片到 MCU 又是標準數(shù)字總線校準和故障定位都方便得多。如果你是做純 HVAC、遠端探頭距離 5 米以上、產(chǎn)品標定流程已經(jīng)很成熟NTC 方案依然好用但如果你想要免標定、兩路同時采、還要兼顧嵌入式里那種二極管測溫需求這套方案的優(yōu)勢就體現(xiàn)出來了。這不是誰替代誰的問題是看你的探頭形態(tài)和生產(chǎn)流程更匹配哪條路。1.3 為什么是 PJ85718DM STM32L021K4而不是別的排列組合PJ85718DM 從型號定位來看屬于本地加遠程兩通道的數(shù)字溫度傳感器I2C 接口地址可配置帶關(guān)斷或單次轉(zhuǎn)換模式。一顆芯片干完兩個通道的活BOM 簡單軟件上也不用面對兩片傳感器的地址和時序協(xié)調(diào)問題。STM32L021K4 這邊LQFP32 封裝適合中小批量板子16 KB Flash 跑一個溫度采集狀態(tài)機足夠供電從 1.65V 到 3.6V對電池和 3.3V 系統(tǒng)都友好stop 模式電流不到 1 μA配合低功耗定時器可以做到秒級喚醒采集。Cortex-M0 核心雖然沒有硬件浮點但溫度換算只是乘一個 0.0625 的常數(shù)軟浮點完全感覺不到負擔。如果換用普通 Cortex-M0 加獨立遠程測溫 IC要多管一片 I2C 總線和一路使能信號如果換用帶豐富模擬前端的高端 MCU成本又上去了。選這套組合本質(zhì)上是把模擬前端和低壓低功耗 MCU兩個問題分別交給最合適的器件各管一段出了問題排查面也窄。2. 從傳感器到 MCU 的電路細節(jié)供電、地址、上拉與現(xiàn)場保護2.1 PJ85718DM 的供電、地址與報警腳設(shè)計先交代最基礎(chǔ)的連接。PJ85718DM 的 VDD 我習慣直接接 3.3V電源引腳旁邊放一個 100 nF 陶瓷電容緊貼引腳稍遠一點再并一個 1 μF如果傳感器和 MCU 用同一個電源域上電時序問題基本不存在。GND 引腳底下記得鋪地別讓 I2C 走線穿過繼電器或者加熱器區(qū)域。地址引腳 ADDR 接 GND 或 VDD 可以換來不同的 7 位 I2C 地址。按這類器件的常見映射默認地址可能是 0x48ADDR 接 VDD 后變成 0x49具體以手冊為準。板子上如果只有這一顆傳感器地址不用搞復(fù)雜固定接死就行但如果一個系統(tǒng)里掛多顆ADDR 的幾種接法就要在原理圖階段規(guī)劃清楚別等 PCB 回來了才發(fā)現(xiàn)地址撞了。ALERT 腳是開漏輸出我一般接一個 10 kΩ 上拉到 3.3 V再連到 MCU 的一個普通 GPIO。如果你的系統(tǒng)不打算用中斷方式處理溫度越限這顆腳也可以完全不接軟件輪詢寄存器就夠了。真正要注意的是 ALERT 腳的配置模式這個后面在踩坑部分會詳細講。2.2 本地通道與遠程通道的接法本地通道不需要任何外部元件傳感器內(nèi)部自帶測溫結(jié)。板上布局時注意離發(fā)熱元件遠一點如果把它貼在電源旁邊讀出來的就不是環(huán)境溫度而是局部受熱溫度。很多現(xiàn)場問題其實從這里就埋下了。遠程通道按用途分兩種接法。嵌入式場景里遠程測溫對象通常是目標芯片內(nèi)部的襯底二極管直接把傳感器的 D/D- 兩個引腳連到目標芯片的測溫引腳即可走線盡量短兩個引腳之間不要跨過 PWM 輸出或高頻信號線。HVAC 場景里遠程通道需要把一個 PN 結(jié)封裝成獨立探頭推薦用二極管接法的 PNP 小信號三極管發(fā)射極接 D基極和集電極短接后接 D-。這個接法符合多數(shù)遠程測溫 IC 的電流方向約定雙絞線引到控制器線長控制在手冊標稱范圍內(nèi)。極性一定不能接反接反了讀數(shù)會直接變成亂碼或者明顯錯誤裝機前先用萬用表確認一遍。2.3 I2C 上拉電阻的計算與電平匹配I2C 是開漏總線必須有上拉電阻。上拉阻值取決于總線電容和時鐘頻率公式是R_pullup ≤ t_rise / (0.8473 × C_bus)同時還要保證從機在拉低時能滿足低電平輸出要求。實際計算起來不用太精確按經(jīng)驗值選就好總線電容100 kHz 推薦400 kHz 推薦100 pF4.7 kΩ ~ 10 kΩ2.2 kΩ ~ 4.7 kΩ200 pF3.3 kΩ ~ 4.7 kΩ1.5 kΩ ~ 2.2 kΩ板子上的走線很短總線電容通常在 100 pF 以下所以我量產(chǎn)設(shè)計里 100 kHz 用 4.7 kΩ100 kHz 是首選。HVAC 現(xiàn)場電磁環(huán)境差低速總線本身抗干擾能力就更好沒有必要為了快那一點去跑 400 kHz。電平匹配方面PJ85718DM 和 STM32L021K4 都用 3.3 V 供電時不存在問題但如果傳感器是 5 V 供電的版本就要考慮開漏上拉到 3.3 V 還是 5 V以及 MCU 引腳是否容忍 5 V。用同一個電壓域是最省事的我這邊全按 3.3 V 設(shè)計。2.4 HVAC 現(xiàn)場保護電路探頭線進柜子之前做的事HVAC 現(xiàn)場最怕兩件事雷擊感應(yīng)和變頻器傳導(dǎo)干擾。探頭線進入控制柜之后我會在傳感器之前加一級保護D/D- 之間并一顆雙向 TVS對地也加 TVS再串一個 1 kΩ 左右的限流電阻靠近傳感器引腳放。電源線上加磁珠I2C 走線盡量短而直。線纜屏蔽層的接地也有講究。屏蔽雙絞線的屏蔽層應(yīng)該在控制器側(cè)單端接地不要兩端都接否則會形成地環(huán)路反而把干擾引進系統(tǒng)。我見過不少現(xiàn)場案例讀數(shù)周期性跳動最后查出來就是屏蔽層兩端都接了地。另外提醒一句I2C 總線不適合像 RS485 那樣長距離掛一堆節(jié)點。如果 HVAC 系統(tǒng)里有多路遠程探頭更合理的做法是每路探頭配一顆帶遠程通道的傳感器芯片然后通過 RS485 或 Modbus 匯總到主控不要在一條 I2C 上硬拉 10 米。3. STM32L021K4 固件I2C 讀取、校準與低功耗調(diào)度3.1 初始化引腳復(fù)用、時鐘和 I2C 參數(shù)固件這邊我按 HAL 庫來寫因為 STM32L021K4 的資源有限用 HAL 反而省心。先初始化 GPIOSCL 用 PB6SDA 用 PB7復(fù)用為開漏輸出內(nèi)部上拉關(guān)掉因為外部已經(jīng)有 4.7 kΩ 上拉。然后初始化 I2C1__HAL_RCC_GPIOB_CLK_ENABLE(); __HAL_RCC_I2C1_CLK_ENABLE(); GPIO_InitTypeDef GPIO_InitStruct {0}; GPIO_InitStruct.Pin GPIO_PIN_6 | GPIO_PIN_7; GPIO_InitStruct.Mode GPIO_MODE_AF_OD; GPIO_InitStruct.Pull GPIO_NOPULL; GPIO_InitStruct.Speed GPIO_SPEED_FREQ_LOW; HAL_GPIO_Init(GPIOB, GPIO_InitStruct); hi2c1.Instance I2C1; hi2c1.Init.ClockSpeed 100000; hi2c1.Init.DutyCycle I2C_DUTYCYCLE_2; hi2c1.Init.OwnAddress1 0; hi2c1.Init.AddressingMode I2C_ADDRESSINGMODE_7BIT; hi2c1.Init.DualAddressMode I2C_DUALADDRESS_DISABLE; HAL_I2C_Init(hi2c1);這里有兩個容易忽略的點。第一速度等級不要選太高低速 GPIO 配合 100 kHz 時鐘足夠還能減少邊沿噪聲第二I2C 時鐘頻率我建議直接定 100 kHz現(xiàn)場穩(wěn)定遠比速度重要調(diào)試的時候再臨時切 400 kHz 測性能也不遲。3.2 讀溫度寄存器的時序與代碼這類溫度傳感器的標準讀法是一樣的先寫寄存器指針再讀數(shù)據(jù)。以讀本地溫度為例先把指針指向溫度寄存器然后連讀兩個字節(jié)uint8_t reg 0x00; uint8_t rx[2] {0}; HAL_I2C_Master_Transmit(hi2c1, PJ85718DM_ADDR, reg, 1, 50); HAL_I2C_Master_Receive(hi2c1, PJ85718DM_ADDR, rx, 2, 50); int16_t raw (int16_t)((uint16_t)(rx[0] 8) | rx[1]); float temperature (float)raw * 0.0625f;其中 0.0625 是這類器件常見的溫度分辨率因為內(nèi)部 ADC 是 12 位最高位是符號位每位代表 0.0625°C。注意這里的符號處理必須先轉(zhuǎn)成 signed 16 位再做乘法否則后面全是負數(shù)處理問題。寄存器具體是 12 位左對齊還是右對齊不同器件不同以手冊為準如果手頭的寄存器格式和示例不同把移位邏輯調(diào)整一下就行整體流程不變。遠程通道的讀法完全一樣只是寄存器指針不同。代碼層面建議把寫指針 讀兩字節(jié) 換算溫度封裝成一個函數(shù)本地和遠程各調(diào)一次別在主循環(huán)里裸寫 I2C 事務(wù)。3.3 遠程通道的校準與偏移處理遠程測溫的原理是利用二極管在不同電流下的正向壓降差ΔVBE (kT/q)·ln(N)其中 N 是兩個激勵電流的比值。這個公式的好處是把二極管的絕對壓降消掉了所以探頭一致性很好但二極管理想因子和線阻仍然會帶來偏差所以遠程通道多少要做一點校準。我的校準方法是兩點線性插值。先在 25°C 恒溫環(huán)境讀遠程通道記錄偏差 delta1再在 60°C 恒溫環(huán)境讀一次記錄偏差 delta2。固件里保存這兩個點實際讀數(shù)出來后做線性補償float calibrate_remote(float raw_temp) { // T125, T260, offset1/offset2 由實測得到 float slope (offset2 - offset1) / (T2 - T1); return raw_temp (raw_temp - T1) * slope offset1; }本地通道通常做一個固定偏移就夠了因為它的偏差主要是封裝和貼片應(yīng)力引起的線性度本身不錯。遠程通道如果現(xiàn)場線長是固定的兩點校準之后偏差可以壓到 ±1°C 以內(nèi)對 HVAC 控制來說足夠了。3.4 低功耗調(diào)度1 秒周期上報平均電流怎么算系統(tǒng)大部分時間應(yīng)該待在 stop 模式用 LPTIM 或 RTC 產(chǎn)生 1 秒喚醒。喚醒后做三件事讀兩個通道、校準換算、寫 UART 或 RS485 上報然后回到 stop。PJ85718DM 如果有關(guān)斷或單次轉(zhuǎn)換模式讀完立即切過去它能省下的電流可能比 MCU stop 電流還大。平均電流可以這樣估算假設(shè)每次喚醒后運行 5 ms運行態(tài)整鏈路電流約 1.2 mA休眠 995 msMCU stop 加傳感器關(guān)斷合計約 1.2 μA。那么一秒鐘的電荷消耗大約是 1200 μA × 0.005 s 1.2 μA × 0.995 s ≈ 7.2 μA·s平均電流就是 7 μA 左右。這個量級對電池供電的嵌入式監(jiān)測設(shè)備很友好。如果你想把平均電流再壓下去把上報周期從 1 秒拉到 5 秒或 10 秒平均電流能降到 2 μA 以下但 HVAC 控制回路一般需要 1 秒以內(nèi)的采樣率所以我在 HVAC 項目里堅持用 1 秒在電池監(jiān)測項目里才用更長周期。4. 聯(lián)調(diào)時踩過的幾個坑死鎖恢復(fù)、線阻誤差與數(shù)據(jù)處理4.1 總線死鎖傳感器把 SDA 拉低不放手第一次遇到這個現(xiàn)象時我以為上拉電阻焊壞了拆了又焊焊了又拆折騰了快一天。現(xiàn)象是這樣的程序跑一段時間后I2C 總線的 SDA 一直為低MCU 復(fù)位也沒用必須整板斷電才能恢復(fù)。這類溫度傳感器帶 SMBus 風格的總線協(xié)議如果主機在錯誤時序下多發(fā)了時鐘或者從機以為主機還在讀數(shù)據(jù)它就可能一直把 SDA 拉低形成死鎖?;謴?fù)方法其實很簡單用 GPIO 模擬 SCL 連續(xù)翻轉(zhuǎn) 9 個時鐘讓從機釋放 SDA然后再發(fā)一個 STOP。代碼上就是在 I2C 引腳切換成普通 GPIO 后手動拉高拉低 SCL。更重要的還是預(yù)防。每個 I2C 事務(wù)都加超時判斷不要無限等 HAL 回調(diào)讀數(shù)據(jù)時先寫寄存器指針再讀確保持久事務(wù)之間的 STOP/RESTART 行為符合手冊要求。另外如果 ALERT 引腳被誤配成了比較器模式且閾值不合理它也可能一直把某個引腳拉低讓你誤以為是總線問題。4.2 遠程線纜線阻與濾波電容造成的讀數(shù)偏差現(xiàn)場反饋遠程探頭讀數(shù)比實際高 1 到 2°C實驗室里怎么都復(fù)現(xiàn)不了后來發(fā)現(xiàn)是 3 米雙絞線的線阻在作怪。遠程二極管測溫會把線阻上的壓降也計入 ΔVBE線越長、線越細正偏差越大。解決辦法有兩個方向一是現(xiàn)場條件允許就換粗一點的屏蔽雙絞線并確認 D/D- 的壓降在手冊允許范圍內(nèi)二是用傳感器自帶的線阻補償或者 offset 寄存器把這個系統(tǒng)性偏差消掉。但要提醒一句補償值是對固定線長有效的如果現(xiàn)場線長不固定最好在安裝說明里規(guī)定最長線纜規(guī)格讓每個項目的補償條件一致。另一個坑是濾波電容。為了抗干擾我在 D/D- 之間并了 100 nF結(jié)果讀數(shù)開始漂。原因是激勵電流切換后電容充放電會干擾 ADC 的采樣時機。這類遠程通道的抗干擾應(yīng)該靠芯片內(nèi)部濾波和雙絞線本身外部并電容要非??酥莆易詈蟀讶葜到档?1 nF 以內(nèi)才穩(wěn)定。4.3 符號位與分辨率負數(shù)溫度別讀成 4046°C有次凌晨收到現(xiàn)場消息說溫度顯示 4046°C我第一反應(yīng)是探頭短路了。排查到最后原因很簡單某次讀到原始值 0xFCE0按 uint16 計算是 64736乘 0.0625 就是 4046°C而正確的處理是先轉(zhuǎn)成 int160xFCE0 對應(yīng)的有符號值是 -800再乘 0.0625 才是 -50°C。這個問題在 0°C 以下的制冷場景很容易踩。不同器件的寄存器格式差別很大有的是 12 位左對齊有的是右對齊有的帶符號擴展位。我建議把字節(jié)轉(zhuǎn)溫度的代碼集中在一個函數(shù)里把所有位數(shù)、符號、縮放邏輯都寫清楚業(yè)務(wù)層只認 float 溫度值不要在多個地方各自移位。如果你用 Modbus 上報還要注意協(xié)議層的符號約定。常見做法是溫度乘以 10 后以 int16 上報那么 -5.0°C 就是 -50接收端再除以 10。這一步看起來簡單但發(fā)送端和接收端只要有一邊忘了縮放現(xiàn)場調(diào)試就會多耗半天。4.4 報警腳、中斷風暴與地址沖突ALERT 腳如果不打算用硬件中斷最安全的做法是在初始化時把芯片配置成中斷模式并讓主機輪詢狀態(tài)寄存器來清標志或者干脆關(guān)閉報警功能只靠軟件閾值。如果誤用比較器模式閾值設(shè)置不合理ALERT 會一直拉低和總線死鎖癥狀一模一樣很容易誤導(dǎo)排查方向。多傳感器場景下地址沖突是原理圖階段就該解決的問題。上電初始化時先掃描一遍 I2C 地址確認每個地址都能讀到預(yù)期器件 ID再進入正常運行讀不到就報故障而不是用默認溫度繼續(xù)跑。HVAC 里如果溫度信號丟失還按正常溫度控制風機和閥門就會按錯誤邏輯動作后果比報警本身嚴重得多。5. 實測數(shù)據(jù)與落地部署從實驗室到 HVAC 現(xiàn)場5.1 實驗室驗證恒溫箱與鉑電阻參考固件寫得差不多之后我做了三輪驗證。方法不復(fù)雜把整個測試板放進恒溫箱遠程探頭通過 2 米 24AWG 雙絞線引出箱外再放回箱內(nèi)模擬現(xiàn)場走線穩(wěn)定 30 分鐘后同時讀本地通道、遠程通道和鉑電阻參考值。數(shù)據(jù)大概是這樣恒溫箱設(shè)定鉑電阻參考本地通道遠程通道25.0°C25.03°C25.01°C25.05°C45.0°C44.96°C45.02°C44.91°C70.0°C69.94°C69.98°C70.11°C本地通道最大偏差 0.07°C遠程通道經(jīng)過兩點校準后最大偏差約 0.15°C這個精度對 HVAC 和嵌入式保護用途都足夠。需要說明的是這只是我自己測試板的個別數(shù)據(jù)不能代表芯片全溫區(qū)指標量產(chǎn)項目還是要按批量抽檢方式做統(tǒng)計。5.2 HVAC 場景控制柜加管道探頭現(xiàn)場環(huán)境比實驗室殘酷得多。某項目的控制柜裝在機房角落風管探頭在 3 米外中間還過了兩個彎。柜內(nèi)本地溫度實測 38°C風管里的遠程溫度只有 24.5°C。如果把控制邏輯只看本地溫度系統(tǒng)會一直以為環(huán)境過熱而加大制冷實際風管側(cè)早就達標了加入遠程通道作為控制變量后閥門的動作才合理。安裝層面的心得是探頭不能貼在風管保溫層外面那測的是環(huán)境溫度不是管道溫度D/D- 極性裝機前必須確認屏蔽層接柜內(nèi)大地不接傳感器地探頭線不要和 220V 動力線走同一個線槽。這些都是現(xiàn)場沒人會替你保證的細節(jié)寫進安裝手冊最靠譜。5.3 嵌入式場景電機驅(qū)動器與電池管理監(jiān)測另一個項目是電機驅(qū)動器功率模塊內(nèi)部有測溫二極管用同一顆 PJ85718DM 的遠程通道去讀。實測遠程結(jié)溫 87.5°C 時本地通道看到的 PCB 空氣溫度只有 52°C。這個溫差很正常但也說明了一個問題如果你的保護邏輯用的是板載溫度實際功率結(jié)溫可能已經(jīng)超限了。這類場景里D/D- 走線盡量短在 PCB 上走差分形式遠離 PWM 輸出和功率走線。我做過一次調(diào)整把遠程通道的兩根線從功率管旁邊拉開 2 mm讀數(shù)穩(wěn)定度立刻改善。電池管理子卡上也類似遠程通道貼在電芯表面用來做充放電溫度保護讀取周期可以放到 5 秒平均電流非常低。5.4 數(shù)據(jù)送出去串口、Modbus 與本地記錄溫度讀出來總要送出去才有意義。HVAC 項目里我把 STM32L021K4 的 USART 接了一顆 RS485 收發(fā)器跑 Modbus RTU 上報本地溫度和遠程溫度分別映射到兩個保持寄存器單位是 0.1°C。代碼里只有一行關(guān)鍵轉(zhuǎn)換uint16_t reg_local (uint16_t)(int16_t)(local_temp * 10.0f); uint16_t reg_remote (uint16_t)(int16_t)(remote_temp * 10.0f);嵌入式場景更簡單直接 UART 輸出文本幀或者二進制幀給主控。如果主控資源緊張可以在 STM32L021K4 的 Flash 里做一個環(huán)形緩沖保存最近 100 條記錄報警前后各留 20 條方便事后分析。這套固件狀態(tài)機很小16 KB Flash 完全裝得下我最后還塞了一個簡單的自檢邏輯上電時確認寄存器能讀寫才進入主循環(huán)。最后聊一個我自己的習慣每次拿到新批次 PJ85718DM我會先做一次 25°C 和 60°C 的兩通道復(fù)測把偏差寫進固件里的偏移表而不是依賴生產(chǎn)環(huán)節(jié)做滿板標定。這樣批量焊接后的分布很穩(wěn)定現(xiàn)場出問題的概率小很多。這套架構(gòu)真正省心的地方在于傳感器把模擬前端處理掉了MCU 只做數(shù)字搬運和時機調(diào)度剩下的就是對閾值和濾波邏輯的持續(xù)打磨了。祝一次過。