實(shí)時(shí)監(jiān)測(cè)與預(yù)警系統(tǒng)實(shí)戰(zhàn)解析)
做可穿戴設(shè)備尤其是一套能監(jiān)測(cè)心率、血氧、體溫這些生理參數(shù)的嵌入式系統(tǒng)時(shí)我最大的感受是難點(diǎn)從來(lái)不是傳感器能不能讀出數(shù)據(jù)而是數(shù)據(jù)在真實(shí)場(chǎng)景下依然可靠。手指靜止時(shí)MAX30102讀出的心率很漂亮一旦佩戴者走動(dòng)、出汗、環(huán)境光變化波形立刻亂七八糟。這個(gè)項(xiàng)目“基于STM32的可穿戴式多生理參數(shù)實(shí)時(shí)監(jiān)測(cè)與預(yù)警系統(tǒng)”本質(zhì)就是圍繞“如何讓生理參數(shù)在可穿戴場(chǎng)景下測(cè)得準(zhǔn)、傳得穩(wěn)、報(bào)得對(duì)”展開(kāi)的完整實(shí)戰(zhàn)。這篇文章我會(huì)按實(shí)際開(kāi)發(fā)順序來(lái)梳理從方案選型到硬件設(shè)計(jì)再到軟件算法和預(yù)警邏輯最后把調(diào)試中踩過(guò)的坑一并整理。如果你想做類似的畢業(yè)設(shè)計(jì)、醫(yī)療電子項(xiàng)目或者個(gè)人健康監(jiān)測(cè)設(shè)備這篇文章可以直接當(dāng)參考框架用。1. 項(xiàng)目核心思路與方案選型做這種系統(tǒng)第一步不是畫(huà)板子而是先想清楚三個(gè)問(wèn)題測(cè)什么參數(shù)、用什么形態(tài)測(cè)、預(yù)警怎么落地。這三個(gè)問(wèn)題決定了后續(xù)所有的硬件選型和軟件架構(gòu)。1.1 系統(tǒng)要解決的核心問(wèn)題先說(shuō)監(jiān)測(cè)參數(shù)的選取。市面上商業(yè)手環(huán)、醫(yī)療級(jí)貼片能測(cè)的東西很多比如心電、腦電、肌電、血壓、血糖但這些方案要么傳感器昂貴要么信號(hào)調(diào)理難度高要么電極佩戴復(fù)雜。作為一整套可落地、可復(fù)現(xiàn)的可穿戴項(xiàng)目我最后選了四項(xiàng)心率、血氧飽和度、體溫、運(yùn)動(dòng)狀態(tài)。這四項(xiàng)的選擇是有理由的心率是基礎(chǔ)生命體征光電容積脈搏波PPG方案成熟傳感器集成度高血氧飽和度在呼吸系統(tǒng)監(jiān)測(cè)、高原場(chǎng)景、睡眠監(jiān)測(cè)中價(jià)值很大和心率可以用同一路PPG信號(hào)算出體溫是判斷發(fā)熱、炎癥等狀態(tài)的直接指標(biāo)模擬前端簡(jiǎn)單一個(gè)NTC熱敏電阻或紅外傳感器就能解決運(yùn)動(dòng)狀態(tài)本身不是生理參數(shù)但它非常重要——后面預(yù)警算法里需要它來(lái)區(qū)分“安靜時(shí)的心率升高”和“運(yùn)動(dòng)時(shí)的心率升高”區(qū)分不了就容易誤報(bào)實(shí)時(shí)監(jiān)測(cè)和預(yù)警是一體兩面的關(guān)系。監(jiān)測(cè)層負(fù)責(zé)把原始信號(hào)變成可用參數(shù)預(yù)警層則根據(jù)參數(shù)和當(dāng)前運(yùn)動(dòng)狀態(tài)做決策。系統(tǒng)架構(gòu)上我采用“終端采集 本地邊緣預(yù)警 無(wú)線回傳”的三層設(shè)計(jì)保證沒(méi)網(wǎng)、沒(méi)手機(jī)的極端場(chǎng)景下終端也能獨(dú)立報(bào)警。1.2 主控選型為什么是STM32家族主控是整個(gè)系統(tǒng)的中樞。這個(gè)項(xiàng)目里我對(duì)比了幾類方案最終鎖定STM32。最大的原因有三個(gè)模擬采集能力、低功耗模式、開(kāi)發(fā)生態(tài)。STM32家族里具體的芯片選擇我給個(gè)對(duì)比表供參考芯片型號(hào)內(nèi)核主頻關(guān)鍵優(yōu)勢(shì)適用場(chǎng)景STM32F103C8T6Cortex-M372MHz便宜、資料多、教程多學(xué)習(xí)驗(yàn)證、非低功耗場(chǎng)景STM32L431RCCortex-M480MHz超低功耗系列、FlexPower控制可穿戴、電池供電STM32WB55Cortex-M4 M064MHz集成BLE 5.0射頻需內(nèi)置藍(lán)牙的場(chǎng)合STM32G431Cortex-M4170MHz內(nèi)含運(yùn)放、比較器、DAC模擬信號(hào)前端較復(fù)雜的場(chǎng)合我做原型時(shí)最開(kāi)始用的是F103C8T6因?yàn)槭诸^庫(kù)存多調(diào)試方便Keil工程幾分鐘就能建好。但做到功耗優(yōu)化階段就發(fā)現(xiàn)F103的低功耗模式比較基礎(chǔ)STOP模式喚醒邏輯和喚醒源配置不如L4靈活待機(jī)電流也偏大。后來(lái)我把核心板換成了STM32L431用STM32CubeMX重新生成工程代碼基本平移但低功耗表現(xiàn)明顯改善。如果你只是做課程設(shè)計(jì)或驗(yàn)證算法F103完全夠用如果目標(biāo)是做接近產(chǎn)品的可穿戴設(shè)備建議直接上L4系列。至于WB55它把BLE射頻集成進(jìn)了芯片里能省掉一顆外部藍(lán)牙模塊但也意味著射頻天線設(shè)計(jì)、協(xié)議棧調(diào)試的成本更高適合有經(jīng)驗(yàn)的團(tuán)隊(duì)。我的做法是外接BLE透?jìng)髂K主控和通信解耦開(kāi)發(fā)快迭代方便。1.3 傳感器方案的取舍與選型生理參數(shù)測(cè)量方案的選型是這個(gè)項(xiàng)目技術(shù)含量最高的一道關(guān)。心率與血氧MAX30102這個(gè)模塊幾乎是穿戴式項(xiàng)目的標(biāo)配。它內(nèi)部集成了紅光LED660nm、紅外LED880nm實(shí)際典型的為880nm或者940nm不同批次略有差異、光電二極管、ADC、環(huán)境光抑制電路和數(shù)字濾波通過(guò)I2C接口直接輸出數(shù)字化信號(hào)。選它的核心理由是集成度高模擬前端最難處理的部分已經(jīng)封裝好了我們不需要自己搭跨阻放大器和濾波電路大大降低了硬件設(shè)計(jì)門(mén)檻。體溫NTC熱敏電阻體溫測(cè)量有幾種路線NTC接觸式、紅外非接觸式、數(shù)字溫度傳感器如DS18B20??纱┐髟O(shè)備接觸式場(chǎng)景多我選了100k NTC熱敏電阻。理由很簡(jiǎn)單響應(yīng)速度快、體積小、成本極低、電路就一個(gè)分壓電阻。測(cè)量電路就是一個(gè)ADC通道加一個(gè)分壓網(wǎng)絡(luò)標(biāo)定后精度能做到±0.1℃左右。運(yùn)動(dòng)狀態(tài)MPU6050六軸傳感器MPU6050集成了三軸加速度計(jì)和三軸陀螺儀通過(guò)I2C輸出原始數(shù)據(jù)。在可穿戴項(xiàng)目中它用來(lái)判斷佩戴者當(dāng)前處于靜止、正?;顒?dòng)還是劇烈運(yùn)動(dòng)狀態(tài)也能做跌倒檢測(cè)。選擇它的原因就是資料全、庫(kù)多、穩(wěn)定。更新的方案有BMI160、LSM6DS3等性能更好但MPU6050作為成熟器件做原型效率和可靠性都不錯(cuò)。2. 硬件系統(tǒng)搭建與關(guān)鍵電路設(shè)計(jì)方案定型之后下一步是畫(huà)原理圖和PCB。可穿戴設(shè)備的硬件設(shè)計(jì)跟桌面設(shè)備完全不同體積、功耗、信號(hào)完整性三條線要同時(shí)考慮。這里我把幾個(gè)關(guān)鍵模塊的設(shè)計(jì)要點(diǎn)拆開(kāi)講。2.1 整體硬件框架整個(gè)系統(tǒng)的硬件可以劃分為五個(gè)功能塊主控模塊STM32L431負(fù)責(zé)初始化外設(shè)、采集數(shù)據(jù)、運(yùn)行算法、控制外設(shè)生理信號(hào)采集模塊MAX30102采集PPG信號(hào)NTC分壓網(wǎng)絡(luò)采集體溫運(yùn)動(dòng)感知模塊MPU6050采集三軸加速度與角速度無(wú)線通信模塊BLE透?jìng)髂K如HC-08通過(guò)串口與主控交互人機(jī)交互與供電模塊0.96寸OLED無(wú)源蜂鳴器、振動(dòng)馬達(dá)、按鍵、鋰電池與充放電電路模塊間通信很簡(jiǎn)潔MAX30102和MPU6050掛在同一條I2C總線上各用不同地址BLE透?jìng)髂K用USART1OLED用軟件SPI或硬件SPINTC接到ADC的一個(gè)通道。整體沒(méi)有特別復(fù)雜的高速總線所以布線壓力不大真正的重點(diǎn)在電源完整性和模擬信號(hào)質(zhì)量。2.2 生理信號(hào)采集電路設(shè)計(jì)要點(diǎn)MAX30102的電路設(shè)計(jì)要特別注意兩點(diǎn)I2C上拉電平和電源濾波。MAX30102的工作電壓是1.8V而STM32的I/O是3.3V電平。手冊(cè)上寫(xiě)I2C引腳可以容忍3.3V但穩(wěn)妥起見(jiàn)我用了PCA9306做電平轉(zhuǎn)換I2C上拉電阻選4.7k接到1.8V側(cè)。這樣做的好處是時(shí)序可靠長(zhǎng)時(shí)間運(yùn)行不會(huì)出現(xiàn)偶發(fā)抖動(dòng)。電源濾波方面MAX30102內(nèi)部LED驅(qū)動(dòng)電流峰值很大瞬時(shí)電流變化快電源紋波會(huì)直接耦合到PPG信號(hào)里。我的做法是在模塊電源引腳附近并聯(lián)一個(gè)10uF陶瓷電容和一個(gè)100nF高頻電容并且讓LED電源VLED和模擬電源VDD分開(kāi)走線避免共享通路。NTC測(cè)溫電路就更簡(jiǎn)單了典型分壓式結(jié)構(gòu)100k NTC接VCC下拉電阻100k到GND中間節(jié)點(diǎn)進(jìn)ADC。這個(gè)結(jié)構(gòu)的優(yōu)點(diǎn)是靜態(tài)電流小約16.5uA幾乎不影響整機(jī)功耗。測(cè)量時(shí)注意用ADC的內(nèi)部參考電壓而非VCC否則電池電壓下降會(huì)直接導(dǎo)致測(cè)溫漂移。STM32L431的ADC有內(nèi)部參考電壓VREFINT通過(guò)校準(zhǔn)可以反推出實(shí)際VCC這樣即使VCC波動(dòng)溫度計(jì)算結(jié)果也穩(wěn)定。2.3 電源與低功耗設(shè)計(jì)可穿戴設(shè)備對(duì)功耗極其敏感直接決定了它的可用性。電源方案我用的是標(biāo)準(zhǔn)配置3.7V鋰電池 TP4056充電管理 TPS63000或XC6206穩(wěn)壓。如果設(shè)備空間足夠TPS63000升降壓的效率更高但成本和體積也更大原型階段用XC6206-3.3V LDO就夠靜態(tài)功耗低外圍就兩個(gè)電容。整機(jī)功耗的實(shí)測(cè)數(shù)據(jù)可以作為參考工作狀態(tài)電流典型值說(shuō)明STM32運(yùn)行態(tài) 外設(shè)全開(kāi)約25mA全部傳感器連續(xù)工作、OLED常亮正常監(jiān)測(cè)態(tài)OLED關(guān)約8mA傳感器按占空比工作、僅BLE暫無(wú)數(shù)據(jù)時(shí)保持連接BLE廣播/傳輸瞬間峰值約30mA透?jìng)髂K發(fā)射瞬間待機(jī)模式約45uASTM32進(jìn)入STOP2模式、外設(shè)斷電按照400mAh電池計(jì)算正常監(jiān)測(cè)態(tài)下理論續(xù)航約50小時(shí)實(shí)際加上損耗大概能跑到一天半到兩天。如果你需要更長(zhǎng)續(xù)航重點(diǎn)是讓MAX30102工作在采樣占空比模式——比如心率血氧每秒采5秒數(shù)據(jù)然后關(guān)斷這樣能省下大部分電流。低功耗模式切換上STM32L431的STOP2模式保留4KB SRAM足夠保存狀態(tài)參數(shù)和最近的一段波形數(shù)據(jù)。我是用一個(gè)定時(shí)器定時(shí)喚醒采集采集完立刻配置為待機(jī)形成“采-算-傳-睡”的工作節(jié)拍。調(diào)試時(shí)注意把所有GPIO先設(shè)置成合理狀態(tài)輸入上拉或模擬輸入再進(jìn)低功耗避免懸空引腳漏電。3. 軟件架構(gòu)與數(shù)據(jù)鏈路實(shí)現(xiàn)硬件是骨架軟件才是讓這套系統(tǒng)真正工作起來(lái)的血肉。這一章講程序架構(gòu)、信號(hào)處理和通信協(xié)議設(shè)計(jì)。3.1 程序框架時(shí)間片輪詢?yōu)橹飨到y(tǒng)功能量不算大但實(shí)時(shí)性要求卻有層次。傳感器數(shù)據(jù)采集需要毫秒級(jí)調(diào)度心率算法需要連續(xù)數(shù)據(jù)流顯示刷新可以慢一些。這種場(chǎng)景下我選擇了裸機(jī)時(shí)間片輪詢沒(méi)有引入RTOS。原因有兩個(gè)一是功能規(guī)模可控狀態(tài)機(jī)加定時(shí)器完全能梳理清楚二是裸機(jī)下功耗控制更直接——RTOS的空閑任務(wù)鉤子雖然也能進(jìn)低功耗但上下文切換和信號(hào)量喚醒的功耗開(kāi)銷(xiāo)在微安級(jí)別場(chǎng)景下不可忽略。我的任務(wù)規(guī)劃大致如下任務(wù)調(diào)度周期優(yōu)先級(jí)說(shuō)明系統(tǒng)節(jié)拍更新1ms最高定時(shí)器中斷維護(hù)時(shí)間標(biāo)志MPU6050數(shù)據(jù)讀取5ms高加速度頻繁更新為體動(dòng)判斷提供基礎(chǔ)MAX30102采樣10ms高心率血氧的采樣率100Hz算法處理100ms中滑動(dòng)濾波、峰值檢測(cè)、血氧計(jì)算OLED刷新200ms低只在屏幕開(kāi)啟時(shí)刷新BLE數(shù)據(jù)上報(bào)500ms低定期上報(bào)狀態(tài)和參數(shù)主循環(huán)就是一個(gè)輪詢調(diào)度的結(jié)構(gòu)任務(wù)函數(shù)里判斷對(duì)應(yīng)的時(shí)間標(biāo)志是否置位。這樣做的好處是時(shí)序清晰、不會(huì)互相阻塞I2C總線訪問(wèn)也通過(guò)互斥標(biāo)志保證同一時(shí)刻只有一個(gè)任務(wù)占用。3.2 核心算法從原始信號(hào)到可用生理參數(shù)這是整個(gè)系統(tǒng)技術(shù)含量最高的部分。讀傳感器原始數(shù)據(jù)很簡(jiǎn)單但要把數(shù)據(jù)變成可信的“心率值”和“血氧值”中間經(jīng)過(guò)的幾步信號(hào)處理必須到位。心率計(jì)算PPG信號(hào)的特點(diǎn)是包含脈搏波交流分量、呼吸引起的基線漂移、運(yùn)動(dòng)偽跡和高頻噪聲。計(jì)算心率的核心鏈路是“帶通濾波 → 峰值檢測(cè) → 周期計(jì)算”。帶通濾波我用的是二階IIR濾波器高頻截止5Hz低頻截止0.5Hz。之所以不用FIR是因?yàn)镮IR階數(shù)低、計(jì)算量小在以M4內(nèi)核跑100Hz采樣率時(shí)非常輕松。下面是核心流程的示意// 簡(jiǎn)化的濾波-峰值檢測(cè)偽代碼 void hr_process_sample(int32_t raw_ppg) { // 1. 低通濾波去掉高頻噪聲截止約5Hz ppg_lp lowpass_5hz(raw_ppg); // 2. 高通濾波去基線漂移截止約0.5Hz ppg_bp highpass_05hz(ppg_lp); // 3. 動(dòng)態(tài)閾值峰值檢測(cè) // 維護(hù)一個(gè)滑動(dòng)窗口內(nèi)的最大值/最小值閾值為其平均 if (ppg_bp threshold ppg_bp prev_peak) candidate_peak ppg_bp; // 4. 檢測(cè)到下降沿后確認(rèn)一個(gè)脈搏波峰計(jì)算相鄰峰間的時(shí)間差 // 60 / (峰值間隔秒數(shù)) 瞬時(shí)心率 instant_bpm 60.0f / peak_interval_sec; // 5. 對(duì)最近8次瞬時(shí)心率做平均輸出心率 }這個(gè)算法在靜止?fàn)顟B(tài)下效果很好誤差能控制在±2bpm以內(nèi)。動(dòng)態(tài)狀態(tài)下需要用加速度數(shù)據(jù)做運(yùn)動(dòng)偽跡消除這個(gè)后面預(yù)警章節(jié)會(huì)講。血氧計(jì)算血氧飽和度SpO2計(jì)算的原理是氧合血紅蛋白和還原血紅蛋白對(duì)紅光660nm和紅外光880nm的吸收率不同。MAX30102同時(shí)輸出紅光和紅外兩路PPG信號(hào)通過(guò)計(jì)算交流分量與直流分量的比值得到R值再查標(biāo)定曲線得到SpO2。// SpO2計(jì)算的簡(jiǎn)化模型 float ratio (AC_red / DC_red) / (AC_ir / DC_ir); float spo2 110.0f - 25.0f * ratio; // 經(jīng)驗(yàn)擬合公式實(shí)際需標(biāo)定注意這個(gè)公式只是簡(jiǎn)化版真正的標(biāo)定曲線需要大量的多受試者數(shù)據(jù)擬合。原型階段讓血氧值落在95%-99%的合理區(qū)間即可醫(yī)療級(jí)精度需要嚴(yán)格的臨床標(biāo)定流程。體溫計(jì)算NTC熱敏電阻的阻值與溫度呈非線性關(guān)系我用的是Steinhart-Hart方程float ntc_to_temp(uint16_t adc_val) { float resistance 100000.0f / (4095.0f / (float)adc_val - 1.0f); float steinhart log(resistance / 100000.0f); // 對(duì)100k NTC、B值約3950經(jīng)驗(yàn)參數(shù) float temp_k 1.0f / (1.0f / 298.15f (1.0f / 3950.0f) * steinhart); return temp_k - 273.15f; }實(shí)際使用時(shí)要對(duì)著標(biāo)準(zhǔn)溫度計(jì)做兩點(diǎn)或三點(diǎn)標(biāo)定修正B值的批次差異。這步不做測(cè)出來(lái)的體溫可能偏差0.5℃以上。3.3 通信協(xié)議讓數(shù)據(jù)“說(shuō)人話”BLE模塊和STM32之間走的是串口透?jìng)鞯@不意味著直接把裸數(shù)據(jù)發(fā)出去就行。為了讓手機(jī)端或上位機(jī)能準(zhǔn)確解析我定義了一套簡(jiǎn)潔的幀協(xié)議。字節(jié)位置內(nèi)容說(shuō)明0幀頭 0xAA 0x55兩字節(jié)幀頭用于幀同步2設(shè)備ID單字節(jié)多設(shè)備區(qū)分3數(shù)據(jù)長(zhǎng)度有效載荷長(zhǎng)度4數(shù)據(jù)載荷心率、血氧、體溫、運(yùn)動(dòng)狀態(tài)、預(yù)警標(biāo)志等N校驗(yàn)字節(jié)累加和校驗(yàn)或CRC8實(shí)際解析時(shí)用狀態(tài)機(jī)接收收到0xAA后進(jìn)入了找0x55的狀態(tài)。校驗(yàn)失敗就丟棄整幀重新找?guī)^不采用逐字節(jié)重傳因?yàn)樯韰?shù)的實(shí)時(shí)性高于可靠性偶爾丟一幀并不影響整體曲線。手機(jī)端我用了一個(gè)通用的BLE串口工具調(diào)試后續(xù)做成完整App可以解析這個(gè)幀格式把實(shí)時(shí)波形和預(yù)警彈窗展示出來(lái)。4. 預(yù)警判斷機(jī)制與場(chǎng)景聯(lián)動(dòng)預(yù)警系統(tǒng)是整個(gè)項(xiàng)目從“監(jiān)測(cè)工具”升級(jí)為“健康守護(hù)終端”的核心模塊。這一部分關(guān)鍵在于如何減少誤報(bào)和漏報(bào)因?yàn)檎`報(bào)多了用戶會(huì)關(guān)掉預(yù)警漏報(bào)少了設(shè)備的意義又打了折扣。4.1 多級(jí)閾值與防誤報(bào)策略生理參數(shù)預(yù)警不能簡(jiǎn)單設(shè)一個(gè)硬閾值超過(guò)就報(bào)警。真實(shí)的生理信號(hào)本來(lái)就存在波動(dòng)單次數(shù)值超限可能是傳感器偶發(fā)誤差也可能是佩戴松動(dòng)的瞬時(shí)偽跡。我的方案是“多級(jí)閾值 連續(xù)確認(rèn)機(jī)制”。參數(shù)正常范圍一級(jí)預(yù)警需關(guān)注二級(jí)預(yù)警需處理心率50-100 bpm100-120 或 40-50大于120 或 小于40血氧95%-100%90%-94%小于90%體溫36.0-37.3℃37.3-38.0℃大于38.0℃或低于35.5℃跌倒——加速度突變并伴隨姿態(tài)變化所謂連續(xù)確認(rèn)機(jī)制就是連續(xù)5次每500ms一次檢測(cè)到超限才確認(rèn)預(yù)警觸發(fā)。這個(gè)策略能過(guò)濾掉大部分偶發(fā)異常。一級(jí)預(yù)警以O(shè)LED提示和藍(lán)牙推送為主二級(jí)預(yù)警則直接啟動(dòng)蜂鳴器和振動(dòng)馬達(dá)。心率超限的判斷尤其要結(jié)合運(yùn)動(dòng)狀態(tài)。靜止?fàn)顟B(tài)下心率105 bpm確實(shí)需要警惕但如果佩戴者正在跑步機(jī)上105 bpm完全正常。所以我引入了動(dòng)態(tài)閾值調(diào)整根據(jù)MPU6050實(shí)時(shí)計(jì)算的運(yùn)動(dòng)強(qiáng)度對(duì)心率預(yù)警閾值進(jìn)行動(dòng)態(tài)偏移。劇烈運(yùn)動(dòng)時(shí)心率閾值上調(diào)到180 bpm血氧閾值下探到92%。4.2 運(yùn)動(dòng)識(shí)別與跌倒檢測(cè)MPU6050的數(shù)據(jù)不只是給預(yù)警做輔助判斷它本身就是一個(gè)獨(dú)立的監(jiān)測(cè)項(xiàng)跌倒檢測(cè)就是其中最有價(jià)值的功能之一。跌倒檢測(cè)的經(jīng)典算法是基于合加速度的突變。三軸加速度的合加速度計(jì)算公式如下float acc_mag sqrt(ax * ax ay * ay az * az);靜止站立時(shí)合加速度接近1g約9.8 m/s2。跌倒過(guò)程會(huì)有一個(gè)明顯的特征波形先是失重階段合加速度下降到0.5g以下然后是撞擊階段合加速度瞬間沖到2.5g以上最后是靜止階段合加速度回到1g且持續(xù)數(shù)秒。我用一個(gè)簡(jiǎn)單狀態(tài)機(jī)來(lái)識(shí)別這個(gè)模式檢測(cè)到合加速度小于0.6g進(jìn)入“疑似失重”狀態(tài)在2秒內(nèi)檢測(cè)到合加速度大于2.8g進(jìn)入“疑似撞擊”狀態(tài)撞擊后加速度恢復(fù)靜止且持續(xù)3秒判定為跌倒這個(gè)算法不是萬(wàn)能的比如緩慢滑倒的波形就和摔倒不一樣。但它能覆蓋大部分跌倒場(chǎng)景作為可穿戴設(shè)備的本地預(yù)警已經(jīng)夠用。更精確的方案需要結(jié)合姿態(tài)角、氣壓計(jì)高度變化等輔助信息屬于后續(xù)迭代方向。4.3 預(yù)警觸發(fā)后的交互反饋預(yù)警觸發(fā)后的反饋鏈路是我驗(yàn)證過(guò)比較實(shí)用的方案本地OLED屏幕顯示異常參數(shù)和預(yù)警等級(jí)蜂鳴器間歇性鳴叫振動(dòng)馬達(dá)以固定節(jié)奏震動(dòng)BLE模塊向手機(jī)端推送預(yù)警幀。每10秒重復(fù)一次直到用戶按按鍵確認(rèn)或參數(shù)恢復(fù)正常。人機(jī)交互設(shè)計(jì)上有一個(gè)細(xì)節(jié)值得注意蜂鳴器和振動(dòng)馬達(dá)不能同時(shí)持續(xù)工作否則在待機(jī)狀態(tài)下耗電很快。我是讓蜂鳴器響2秒、停3秒振動(dòng)馬達(dá)響1秒、停4秒錯(cuò)開(kāi)工作并伴隨OLED點(diǎn)亮提示。這樣既保證提醒效果又控制功耗。按鍵處理上加了一個(gè)簡(jiǎn)單的消抖和長(zhǎng)按邏輯短按切換OLED顯示頁(yè)面長(zhǎng)按3秒關(guān)閉報(bào)警。這個(gè)交互邏輯測(cè)試下來(lái)比“單次按鍵直接關(guān)”更防誤觸。5. 調(diào)試過(guò)程實(shí)錄與常見(jiàn)問(wèn)題排查這一章整理我實(shí)際調(diào)試中遇到的典型問(wèn)題和解法。這些經(jīng)驗(yàn)在芯片手冊(cè)上基本學(xué)不到屬于必須親自踩坑才能積累的東西。5.1 傳感器讀數(shù)異常的經(jīng)典場(chǎng)景I2C偶爾通信失敗現(xiàn)象MAX30102偶發(fā)讀回全0xFF程序掛死在等待應(yīng)答的循環(huán)里。排查后發(fā)現(xiàn)是I2C上拉電阻選的太大——換了4.7k之后穩(wěn)定。還有一個(gè)隱藏問(wèn)題I2C中斷優(yōu)先級(jí)設(shè)置不當(dāng)在ADC中斷處理過(guò)程中I2C被搶占導(dǎo)致時(shí)序超時(shí)。解決方法是把I2C中斷優(yōu)先級(jí)調(diào)到最高并在讀操作里加超時(shí)退出機(jī)制。PPG波形噪聲太大這是我調(diào)得最久的一個(gè)問(wèn)題。第一版PCB做出來(lái)后MAX30102的PPG波形在靜止?fàn)顟B(tài)下依然毛刺很多。多方排查后定位到兩個(gè)原因一個(gè)是指夾式或手環(huán)式佩戴結(jié)構(gòu)的光路設(shè)計(jì)不合理環(huán)境光從模塊側(cè)面漏進(jìn)了光電二極管另一個(gè)是LED驅(qū)動(dòng)電流設(shè)置過(guò)大導(dǎo)致信號(hào)飽和。最后處理辦法是給傳感器模組加了遮光泡棉并把LED電流從8mA降到4mA采樣動(dòng)態(tài)范圍從過(guò)載狀態(tài)恢復(fù)正常。體溫讀數(shù)和實(shí)際差距大這不是電路問(wèn)題是標(biāo)定問(wèn)題。NTC的B值理論值和實(shí)際值有批次差異加上ADC參考電壓的誤差直接算出來(lái)偏差0.5℃。解決方法是做兩點(diǎn)標(biāo)定用恒溫槽或標(biāo)準(zhǔn)體溫計(jì)做對(duì)照修正程序里的溫度偏移量。實(shí)測(cè)下來(lái)兩點(diǎn)標(biāo)定后誤差能壓到±0.1℃以內(nèi)。5.2 無(wú)線通信中的坑BLE透?jìng)髂K的調(diào)試也有幾個(gè)典型問(wèn)題配對(duì)后經(jīng)常掉線排查發(fā)現(xiàn)是模塊電源受電機(jī)或蜂鳴器工作時(shí)的瞬態(tài)壓降影響電壓跌落超過(guò)模塊的低壓復(fù)位閾值。處理辦法是增加一個(gè)100uF儲(chǔ)能電容并且在蜂鳴器驅(qū)動(dòng)電路上并聯(lián)續(xù)流二極管和RC吸收。這是典型的“電源大電流毛刺干擾”問(wèn)題示波器上一測(cè)就清清楚楚。串口數(shù)據(jù)亂碼重點(diǎn)檢查兩個(gè)模塊的地是不是共地。BLE模塊和主控用同一個(gè)電源時(shí)通常沒(méi)問(wèn)題但如果BLE模塊單獨(dú)供電信號(hào)線又不共地串口的參考電位不同數(shù)據(jù)必然亂。我的方案是全部用同一個(gè)3.3V電源軌串口直接連PA9/PA10沒(méi)有再隔離。5.3 實(shí)測(cè)效果與評(píng)估整套系統(tǒng)完成聯(lián)調(diào)后我做了幾組測(cè)試。靜止?fàn)顟B(tài)下的心率與醫(yī)用指夾式血氧儀對(duì)比誤差在±2bpm以內(nèi)血氧在靜止?fàn)顟B(tài)下和參考設(shè)備誤差不超過(guò)1%體溫在靜態(tài)環(huán)境下誤差±0.1℃標(biāo)定后運(yùn)動(dòng)狀態(tài)下心率的跟隨性還行但血氧在劇烈運(yùn)動(dòng)時(shí)會(huì)有明顯偏差這是因?yàn)檫\(yùn)動(dòng)偽跡讓PPG的交流分量失真了。后面如果要優(yōu)化方向就是加自適應(yīng)濾波用加速度信號(hào)做參考做LMS干擾對(duì)消屬于典型的學(xué)術(shù)研究方向。低功耗實(shí)測(cè)正常監(jiān)測(cè)態(tài)整機(jī)電流7.8mAOLED關(guān)閉、傳感器占空比工作的情況下400mAh電池能跑接近兩天。這個(gè)水平作為穿戴設(shè)備原型是合格的離商用設(shè)備一顆紐扣電池跑一個(gè)月還有距離但優(yōu)化方向很清楚。最后的幾點(diǎn)個(gè)人體會(huì)做完整套系統(tǒng)我最深的體會(huì)是可穿戴醫(yī)療項(xiàng)目最難的不是任何一個(gè)單一模塊而是整個(gè)系統(tǒng)的“鏈條完整性”。傳感器信號(hào)處理、低功耗策略、通信協(xié)議、預(yù)警算法每個(gè)環(huán)節(jié)的問(wèn)題都會(huì)在聯(lián)調(diào)階段集中爆發(fā)。尤其是信號(hào)鏈路上的微小細(xì)節(jié)——濾波電容的位置、I2C上拉的阻值、佩戴結(jié)構(gòu)的遮光設(shè)計(jì)——任何一環(huán)不到位最終數(shù)據(jù)就不好看。如果你是剛開(kāi)始做類似的STM32項(xiàng)目我的建議是先別急著追新器件和新框架把MAX30102和MPU6050這兩個(gè)成熟模塊調(diào)好再一步步疊加功能。先把靜態(tài)數(shù)據(jù)測(cè)準(zhǔn)再考慮動(dòng)態(tài)場(chǎng)景最后再上預(yù)警和低功耗。這套順序能幫你少走很多彎路。