在先前的文章中,我們已經成功將 Raspberry Pi 打造為 DataDock,並利用 ConfigFS 開通了複合 USB 介面。然而,能通訊不代表通訊是可靠的。在邊緣運算 (Edge Computing) 中,最可怕的不是沒有資料,而是**「收到了看起來像樣,但其實已經錯位失真的垃圾資料」**。
今天,我將帶大家走過一段驚心動魄的實戰除錯過程。這是一場與醫療級 50Hz 連續 PPG (光體積變化描記圖) 及 3 軸加速度計 (ACC) 數據的攻防戰。我們將探討如何將脆弱的原型通訊協議,硬化成具備容錯、對齊與量化分析能力的「醫療級生產線」。
問題出在哪?硬體雜訊?還是傳輸漏失? 在通訊除錯中,最快釐清問題的方法就是「回到最底層的 Hex 原始碼」。經過仔細觀察原始二進位資料,我們發現 ST-50 傳輸的資料本身是完美的,但我們的解析器 (Parser) 在進行封包重組時,發生了致命的「位元錯位 (Bit-shift)」。
Byte 0: Command Header (0x04)
Byte 1 ~ 243: Payload (包含 27 組連續的 9-Byte 取樣點)
Byte 244: Checksum (1 Byte)
我們原本的寫法,在處理 50Hz 大量資料時,為了追求效能,不小心把檢查用的一顆 0x00 虛擬 Checksum Byte 給塞進了資料緩衝區中。 在連續的 [9 Bytes][9 Bytes][9 Bytes]... 陣列中,每 27 筆就多擠進一個 0x00,這就引發了可怕的骨牌效應。
位元錯位有多可怕? PPG 訊號是由 uint16 (2 Bytes) 組成。如果整個陣列往後退了 1 個 Byte,原本應該是 High Byte 的位置變成了前一個數值的 Low Byte,解讀出來的十進位數值就會瞬間產生幾萬的誤差,這就是我們看到全螢幕雜訊的原因!
解決方案:嚴格的框架與 Checksum 防線
我們重新改寫了 Parser,實作了嚴格的邊界對齊:
精準跳過 0x04 表頭。
計算 Payload 的 Checksum,若與封包尾部不符,寧可丟棄整個 245 Bytes 封包,也絕不讓一個錯位的 Byte 進入資料庫。
確實剝離多餘的檢查位元,讓 sync_engine.py 每一口都吃到最純粹的 9 Bytes。
3. 完美的「時間對齊」演算法
有了正確的數據,我們還需要精確的「時間軸」。 ST-50 為了節省頻寬,傳送的不是絕對時間,而是 t_diff(相對於前一個取樣點的毫秒差)。我們實作了一個「時間累加器 (Time Accumulator)」:
python
# 初始化
current_unix = start_time
# 每讀取一個取樣點
current_unix += (t_diff / 1000.0)
防呆機制:第一筆資料的 0xFF 硬體工程師在設計時,因為第一筆資料沒有「上一筆」,所以硬體會傳送 0xFF (255) 作為標記。如果在軟體解析時沒有針對 255 做防呆防護,整段時間軸就會無故延遲 0.235 秒!在需要精準時間差來計算心率變異度 (HRV) 的邊緣運算中,這種基線飄移是無法接受的。我們將其強制補償為標準頻率的 20ms,完美解決了時間偏移。
工具一:基礎確校 (qa_ppg_csv.py)
這支程式會在後台快速掃描數萬筆資料,檢查相鄰數值的變化量 (Delta)。它具備智慧容錯,能理解感測器剛接觸皮膚或拔下時的「物理性陡降」,自動給出綠色的 [PASS],證明資料完全沒有發生位元錯位。
工具二:訊號可用度量化 (signal_quality.py)
這是 Edge AI 的前置武器。程式將資料切分為每 2 秒的視窗,透過交叉比對 3 軸加速度計 (ACC) 的標準差與 PPG 的振幅。如果 ACC 劇烈震盪,程式會自動將該區段標記為「受運動干擾」。 最終,程式會輸出一個量化指標:「總體可用度 (例如:88.4% 極佳)」,讓後台能自動決定是否採用這筆醫療數據。
工具三:高品質視覺化 (plot_ppg.py)
將生硬的 CSV 數據瞬間轉化為高畫質的對齊折線圖。肉眼即可清晰看見:當圖表下方的 ACC 劇烈晃動時,上方的 PPG 波形就會完美對應出雜訊。這證實了我們的動態雜訊標記完全符合真實的物理連動!
小結
從滿天飛舞的雜訊,到現在能穩定產出如教科書般純淨的 PPG 與 ACC 連動波形。我們透過嚴格的通訊協議硬化與自動化確校工具鍊,正式讓 DataDock 達到了「醫療級研究數據」的收集標準。
這套穩固的地基,讓我們可以放心地往下一個階段邁進。明天,我們將帶著這些完美的數據,準備向雲端後台發起連線!