心率計可以將連接到板子上的心率傳感器數(shù)據(jù)采集下來并使用算法計算心率值,并通過串口傳輸?shù)街付ǖ慕K端設(shè)備。可以直接接USB-TLL模塊傳輸?shù)絇C端或者通過藍牙模塊傳輸?shù)绞謾C端。
單片機源程序如下:
- //******************************說明********************************/
- #include "stdio.h"
- #include "common.h"
- #include "heartRateProcess.h"
- #define false 0
- #define true 1
- #define FOSC 11059200L //系統(tǒng)時鐘
- #define BAUD 115200 //波特率
- #define T0MS (65536-FOSC/12/500) //500HZ in 12T MODE
- #define BUFFER_SIZE 10
- #define ADC_POWER 0x80 //ADC POWER CONTROL BIT
- #define ADC_FLAG 0x10 //ADC COMPLETE FLAG
- #define ADC_START 0x08; //ADC START CONTROL BIT
- #define ADC_SPEEDLL 0x00 //540 CLOCKS
- #define ADC_SPEEDL 0x20 //360 CLOCKS
- #define ADC_SPEEDH 0x40 //180 CLOCKS
- #define ADC_SPEEDHH 0x60 //90 CLOCKS
- #define ADC_MASK 0x01
- #define BLUE_SHIFT (1U << 5)
- #define BLUE_ON (GPIOD_PCOR = BLUE_SHIFT)
- #define BLUE_OFF (GPIOD_PSOR = BLUE_SHIFT)
- #define BLUE_TOGGLE (GPIOD_PTOR = BLUE_SHIFT)
- unsigned int BPM; // 用于保存脈沖速率
- unsigned int Signal; // 持有傳入的原始數(shù)據(jù)
- unsigned int IBI = 600; // 保持心跳之間的空隙,必須種子!
- unsigned char Pulse = false; // 當脈沖波高時真,低為假
- int rate[10]; // 數(shù)組來保存最后十IBI值
- unsigned long sampleCounter = 0; // used to determine pulse timing用于確定脈沖定時
- unsigned long lastBeatTime = 0; // used to find IBI
- int Peak =255; // used to find peak in pulse wave, seeded用來尋找峰值脈沖波,播種
- int Trough = 10; // used to find trough in pulse wave, seededsed中找到谷底脈搏波,播種
- int thresh = 60; // used to find instant moment of heart beat, seeded查找心跳的瞬間
- int amp = 100; // used to hold amplitude of pulse waveform, seeded用于保存脈沖波形的振幅,接種
- unsigned char firstBeat = true; // used to seed rate array so we startup with reasonable BPM用于種子率陣列,所以我們啟動與合理的BPM
- unsigned char secondBeat = false; // used to seed rate array so we startup with reasonable BPM用于種子率陣列,所以我們啟動與合理的BPM
- // Timer 0中斷子程序,每2MS中斷一次,讀取AD值,計算心率值
- //采樣率500Hz
- unsigned char heartRateCalc(unsigned char buf,uint16* ratte)
- {
- int N;
- unsigned char i,j;
- unsigned char QS = false; // becomes true when 51 finds a beat.
- char cmd[100];
- uint16 len;
- // keep a running total of the last 10 IBI values保持過去10 個心跳間隙值運行總數(shù)
- unsigned int runningTotal = 0; // clear the runningTotal variable 清除正在運行的總變量
- j=0;
-
- Signal = buf; // read the Pulse Sensor 讀取脈搏傳感器
- sampleCounter += 2; // keep track of the time in mS with this variable追蹤這個變量在毫秒級
- N = sampleCounter - lastBeatTime; // monitor the time since the last beat to avoid noise因為最后一次心跳監(jiān)測時間可避免噪音
-
- // 找到脈搏波的波谷
- if(Signal < thresh && N > (IBI/5)*3)
- { // 避免重脈噪聲最后IBI等待4/5
- if (Signal < Trough)
- { // T is the trough;T是波谷
- Trough = Signal; // 跟蹤最低點的脈沖波
- }
- }
- // 找到脈搏波的波峰
- if(Signal > thresh && Signal > Peak)
- { // thresh condition helps avoid noise閾值條件有助于避免噪音
- Peak = Signal; // P is the peak; P是峰
- } // keep track of highest point in pulse wave跟蹤最高點的脈沖波
- // NOW IT'S TIME TO LOOK FOR THE HEART BEAT 現(xiàn)在是時候去尋找心跳
- // signal surges up in value every time there is a pulse每次有一個脈沖信號涌起的價值
- if (N > 250)
- { // avoid high frequency noise 避免了高頻噪音
- if ( (Signal > thresh) && (Pulse == false) && (N > (IBI)*0.6) )
- {
- Pulse = true; // set the Pulse flag when we think there is a pulse當我們認為有脈沖時設(shè)置脈沖標志
- // blinkPin=0; // turn on pin 13 打開LED引腳
- IBI = sampleCounter - lastBeatTime; // measure time between beats in mS
- lastBeatTime = sampleCounter; // keep track of time for next pulse
- if(secondBeat)
- { // if this is the second beat, if secondBeat == TRUE
- secondBeat = false; // clear secondBeat flag清零第二拍標志
- // for(i=0; i<=9; i++)
- // { // seed the running total to get a realisitic BPM at startup在啟動時獲得真實BPM運行總數(shù)
- // rate[9] = IBI;
- // }
- }
- if(firstBeat)
- { // if it's the first time we found a beat, if firstBeat == TRUE
- firstBeat = false; // clear firstBeat flag 清零第一拍標志
- secondBeat = true; // set the second beat flag設(shè)置第二拍標志
- // EA=1; // enable interrupts again再次啟用中斷
- Pulse = false;
- return QS; // IBI value is unreliable so discard itIBI值是不可靠的,所以將其丟棄
- }
- BLUE_ON;
- //程序運行到這里表示已經(jīng)找到第二個節(jié)拍
- //存放節(jié)拍的數(shù)組依次往前移位,留下最后一個來裝新得到的節(jié)拍周期
- for(i=0; i<=8; i++)
- { // shift data in the rate array移動數(shù)組中的數(shù)據(jù)
- rate[i]= rate[i+1]; // and drop the oldest IBI value 并刪除最舊的IBI值
- runningTotal += rate[i]; // add up the 9 oldest IBI values將9個最古老的IBI值加起來
- }
- //存放最新的節(jié)拍周期
- rate[9] = IBI; // add the latest IBI to the rate array添加最新IBI的速度陣列
- runningTotal += rate[9]; // add the latest IBI to runningTotal加上最新的IBI運行數(shù)
- runningTotal /= 10; // average the last 10 IBI values 平均最近10個IBI值
- BPM = 60000/runningTotal; // how many beats can fit into a minute? that's BPM!有多少心跳可以放入一分鐘?這是BPM的!
- if(BPM>200)BPM=200; //限制BPM最高顯示值
- if(BPM<30)BPM=30; //限制BPM最低顯示值
- QS = true; // set Quantified Self flag 設(shè)置量化自我標志
- len=sprintf(cmd,"Peak=%d,thresh=%d,Trough=%d,amp=%d,IBI=%d,N=%d,BPM=%d\r\n",Peak,thresh,Trough,amp,IBI,N,BPM);
- // IntfWrite(0,cmd,len);
- // QS FLAG IS NOT CLEARED INSIDE THIS ISR; QS標志不會被清除這里面中斷服務(wù)程序
- }
- }
- //檢測下降
- if (Signal < thresh && Pulse == true) // when the values are going down, the beat is over當值正在下降,節(jié)拍結(jié)束
- {
- BLUE_OFF;// turn off pin 13 LED
- Pulse = false; // reset the Pulse flag so we can do it again復(fù)位脈沖標志,所以我們可以再做一次
- amp = Peak - Trough; // get amplitude of the pulse wave得到的脈搏波的振幅
- thresh = amp/2 + Trough; // set thresh at 50% of the amplitude設(shè)定閾值的幅度的50%
- Peak = thresh; // reset these for next time為下一次復(fù)位
- Trough = thresh;
- len=sprintf(cmd,"fall edge:Peak=%d,thresh=%d,Trough=%d,amp=%d,IBI=%d,N=%d,BPM=%d\r\n",Peak,thresh,Trough,amp,IBI,N,BPM);
- // IntfWrite(0,cmd,len);
- }
- //重新初始化
- if (N > 2500) // if 2.5 seconds go by without a beat 如果2.5秒去,沒有一個節(jié)拍
- {
- thresh = 50; // set thresh default設(shè)置默認的閾值
- Peak = 155; // set P default默認設(shè)置P
- Trough = 10; // set T default默認設(shè)置T
- lastBeatTime = sampleCounter; // bring the lastBeatTime up to date 最后一拍的時間
- firstBeat = true; // set these to avoid noise
- secondBeat = false; // when we get the heartbeat back
- Pulse = false;
- }
- //EA=1; // enable interrupts when youre done!允許中斷時,大功告成!
- *ratte=BPM;
- return QS;
- }// end isr
- void filter(uint8* buf,unsigned char len)
- {
- static uint8 x0=50,x1=50;
- uint8 i,temp;
- uint8 k=1,throd=10;
- uint8 Buff[BUFFER_SIZE+2];
- uint8 buffback[BUFFER_SIZE];
- memcpy(Buff+2,buf,len);
- //for(i=0;i<len;len++)
- // Buff[i+2]=buf[i];
- Buff[0]=x0;
- Buff[1]=x1;
- for(i=0;i<len;len++)
- if(abs(Buff[i+1]-Buff[i])>throd)
- buffback[i]=(Buff[i+2]+Buff[i])/2;
- else
- buffback[i]=Buff[i+1];
- x0=Buff[BUFFER_SIZE];
- x1=Buff[BUFFER_SIZE+1];
- }
復(fù)制代碼
所有資料51hei提供下載:
HeartRateTestPrj.7z
(428.99 KB, 下載次數(shù): 9)
2019-4-5 03:44 上傳
點擊文件名下載附件
下載積分: 黑幣 -5
|