文章目录
[+]
运动过程中,都须要关注的一个参数便是自己的心率,心率过高过低都弗成,以是检测心率是一个很主要的参数。
现在最普遍的心率传感器便是PulseSensor 脉搏心率传感器

可以检测心率和脉搏;
事理紧张便是通过光反射,转化为电压旗子暗记,单片机通过ADC采集电压,然后在通过算法得到心率和心跳;
个中算法部分代码都是现成,我们利用时只须要把ADC配置好,读取数据就可以得到须要的参数;
算法部分:
[C] 纯文本查看 复制代码
?
01020304050607080910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485void SensorTimer_handler(void){ float temp = 0; unsigned int runningTotal; ADC_GetData(&Signal); // read the Pulse Senso temp = Signal 1.818; Signal = (u16)temp-1; sampleCounter += 2; // keep track of the time in mS with this variable Num = sampleCounter - lastBeatTime; // monitor the time since the last beat to avoid noise ADC_StartConvert(ADC_CH_1_DIV_5, 0, 1); //restart ADC conversion // find the peak and trough of the pulse wave if(Signal < thresh && Num > (IBI/5)3){ // avoid dichrotic noise by waiting 3/5 of last IBI if (Signal < T){ // T is the trough T = Signal; // keep track of lowest point in pulse wave } } if(Signal > thresh && Signal > P){ // thresh condition helps avoid noise P = Signal; // P is the peak } // keep track of highest point in pulse wave // NOW IT'S TIME TO LOOK FOR THE HEART BEAT // signal surges up in value every time there is a pulse if (Num > 250){ // avoid high frequency noise if ( (Signal > thresh) && (Pulse == 0) && (Num > (IBI/5)3) ){ Pulse = 1; // set the Pulse flag when we think there is a pulse// HAL_GPIO_WritePin(GPIOA,GPIO_PIN_5,GPIO_PIN_SET); // 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 = 0; // clear secondBeat flag for(int i=0; i<=9; i++){ // seed the running total to get a realisitic BPM at startup rate[i] = IBI; } } if(firstBeat){ // if it's the first time we found a beat, if firstBeat == TRUE firstBeat = 0; // clear firstBeat flag secondBeat = 1; // set the second beat flag // sei(); // enable interrupts again return; // IBI value is unreliable so discard it } // keep a running total of the last 10 IBI values runningTotal = 0; // clear the runningTotal variable for(int i=0; i<=8; i++){ // shift data in the rate array rate[i] = rate[i+1]; // and drop the oldest IBI value runningTotal += rate[i]; // add up the 9 oldest IBI values } rate[9] = IBI; // add the latest IBI to the rate array runningTotal += rate[9]; // add the latest IBI to runningTotal runningTotal /= 10; // average the last 10 IBI values BPM = 60000/runningTotal; // how many beats can fit into a minute? that's BPM! QS = 1; // set Quantified Self flag // QS FLAG IS NOT CLEARED INSIDE THIS ISR } } if (Signal < thresh && Pulse == 1){ // when the values are going down, the beat is over// HAL_GPIO_WritePin(GPIOA,GPIO_PIN_5,GPIO_PIN_RESET); // turn off pin 13 LED Pulse = 0; // reset the Pulse flag so we can do it again amp = P - T; // get amplitude of the pulse wave thresh = amp/2 + T; // set thresh at 50% of the amplitude P = thresh; // reset these for next time T = thresh; } if (Num > 2500){ // if 2.5 seconds go by without a beat thresh = 512; // set thresh default P = 512; // set P default T = 512; // set T default lastBeatTime = sampleCounter; // bring the lastBeatTime up to date firstBeat = 1; // set these to avoid noise secondBeat = 0; // when we get the heartbeat back } TMR32_ClearFlag(MXC_TMR2);}读值:
[C] 纯文本查看 复制代码
?
01020304050607080910111213141516171819202122232425262728293031323334353637383940414243444546474849int BPM; // used to hold the pulse rateu16 Signal; // holds the incoming raw dataint IBI = 600; // holds the time between beats, must be seeded! unsigned char Pulse = 0; // true when pulse wave is high, false when it's lowunsigned char QS = 0; // becomes true when Arduoino finds a beat.int rate[10]; // array to hold last ten IBI valuesunsigned long sampleCounter = 0; // used to determine pulse timingunsigned long lastBeatTime = 0; // used to find IBIint P =426; // used to find peak in pulse wave, seededint T = 426; // used to find trough in pulse wave, seededint thresh = 426; // used to find instant moment of heart beat, seededint amp = 100; // used to hold amplitude of pulse waveform, seededint Num;unsigned char firstBeat = 1; // used to seed rate array so we startup with reasonable BPMunsigned char secondBeat = 0; // used to seed rate array so we startup with reasonable BPMvoid sendDataToProcessing(char symbol, int dat ){ putchar(symbol); // symbol prefix tells Processing what type of data is coming printf(\"大众%d\r\n\公众,dat); // the data to send culminating in a carriage return}int Sensor_Task(void){ static u32 PointM = 0; uint16_t adc_val[4]; unsigned int overflow[4]; uint8_t fmtstr[40]; / Initialize ADC / if( ( OsDelayCCnt - PointM ) >= T_20MS) { PointM = OsDelayCCnt; / Convert channel 0 / sendDataToProcessing('S', Signal); // send Processing the raw Pulse Sensor data if (QS == 1) { User.BPM = BPM; User.IBI = IBI; sendDataToProcessing('B',BPM); // send heart rate with a 'B' prefix sendDataToProcessing('Q',IBI); // send time between beats with a 'Q' prefix QS = 0; // reset the Quantified Self flag for next time } / Delay for 1/4 second before next reading / }}显示:
[C] 纯文本查看 复制代码
?
0102030405060708091011121314151617181920212223void OLED_Task(void){ static u32 PointM = 0; static u8 mState = 0; char Data_Time[9] = \公众hh:mm:ss\公众; char Data_Data[11] = \公众yyyy-mm-dd\公众; char Data_Sensor[19] = \"大众BMP:xxxx IBI:xxxx\"大众; LCD_P8x16Str(36,0,\"大众MAX32630\"大众); // LCD_P8x16Str(0,2,\"大众EEWORLD\公众);// LCD_P8x16Str(0,4,\"大众Smart Watch\公众); if( ( OsDelayCCnt - PointM ) >= T_1S) { PointM = OsDelayCCnt;// LCD_CLS(); sprintf(Data_Sensor,\"大众BMP:%03d IBI:%04d\"大众,User.BPM,User.IBI); LCD_P8x16Str(0,2,Data_Sensor); sprintf(Data_Data,\"大众%04d-%02d-%02d\"大众,User.RtcTime.Year + 2000,User.RtcTime.Mon,User.RtcTime.Day); LCD_P8x16Str(0,4,Data_Data); sprintf(Data_Time,\公众%02d:%02d:%02d\"大众,User.RtcTime.Hour,User.RtcTime.Min,User.RtcTime.Sec); LCD_P8x16Str(0,6,Data_Time); }} 








