既然已經可以用脈搏計聽到脈搏的變化,那麼可不可以看到脈搏數目的變化呢?
當然可以,效果就會這樣,分成兩個圖表,上面是脈搏波形,下面是脈搏數(BPM)的變化圖。
程式我已經寫好了,就放在這裡。使用上唯一需要注意的是,盡量讓閾值落在第一高峰和第二高峰之間,程式會自動微調,但若突然大規模變動還是要自己調整,你可以按A增加閾值、按B降低閾值。
如果想要呈現長時間的資料,你可以縮小瀏覽器,按下【ctrl -】,若要放大則是【ctrl +】
計算BPM的基礎
其實我們每次心跳間隔並不是完全相同的。舉例來說,如果你的一分鐘心跳數是60下,這並不代表你每次心跳間隔就是1000毫秒,它可能是這次到下次的間隔是1010毫秒,下次到下下次是950毫秒...,在一分鐘內的時間內,一共搏動了60下。
每次心跳間隔的時間稱為 Interbeat interval (IBI) ,如果是用ECG的波形來看,通常是用前後兩個RR之間的間隔來計算,所以也稱為 R-R interval
每次心跳間隔不相同的這個現象稱為心率變異性,這在後面的文章會再提到,是可以用來評估自律神經狀況的。
回到脈搏數這件事,在以下介紹的程式中,就是用這個心跳間隔時間來計算每次的脈搏有多快,例如間隔是 1010 ms,那麼該次心跳的BPM就是 60x1000/1010 = 59.4,下次間隔是950 ms,則BPM是 60x1000/950 = 63.16,以此類推。
以下是關於程式設計的細節
峰值偵測
- 峰值的點會比前一個點和後一個點高。這個很明顯,能長成這樣的才會是峰
- 峰必須高於閾值。這條件很重要,不然隨便一個波動都可能會被偵測成峰
- PPG的波形裡會有兩個峰,第二個峰叫做重搏峰,這在我們談到血管狀況評估時會再提到。排除重搏峰的方式,我就用「峰之間的時間差必須大於某個數值」
在micro:bit的程式裡,我就用這個函式來偵測峰值,傳入的三個item都是陣列元素,每個item內有兩個元素,第一個是時間戳記,第二個是感測的數值。拿來比較的都是陣列中的第二個元素(index為1)。
三個元素是用queue的資料結構儲存,一個queue只會存放三個元素,每次新的資料變成新的元素從queue的尾端放入,然後開始偵測中間那個元素是不是峰值。
如果出現峰值,就會把時間紀錄下來跟前一個峰值時間做運算,算出新的峰的BPM。最後將每次的脈搏波形和BPM都從序列埠印出。
序列埠輸出
這裡用了一個技巧,讓micro:bit的圖表能同時呈現兩種不同資訊。首先脈搏波形的部分是用【序列寫入一行文字】,而BPM則是用【序列寫入值】,兩種不同的輸出方式,就會讓micro:bit用兩個圖表來顯示。
而在脈搏波形的部分,同時輸出了5種數字,第一個是偵測到的脈搏訊號,第二個則是閾值,第三個到第五個的900、400、650,則是用來限制Y軸的顯示範圍,同時也來做訊號的參考比較。因為makecode的圖表顯示預設會用當下畫面裡的最大值和最小值來當範圍,如果沒有做這些限制的話,圖表會因為當下數值的範圍而自動產生垂直縮放,這在後續做一些生理狀況觀察時,會不方便比較。
閾值的部分,雖然我已經用一個IIR Filter(alpha = 0.99)去獲取直流成分來產生動態閾值,但還是可能需要調整,你可以直接按A或B去調整閾值的範圍,使它落在第一高峰和第二高峰的數值範圍之間。