i find this code for heart rate monitor and its working 100%
but i have two question
1- this code read puls rate from pin AN0 analoge -- but when remove my finger why its not give me zero?? result will be same
how to add to the code to give me zero 0 when no puls in
2- another question why he program mcu to be as counter puls from timer 0 and other interrupt pin
why he put puls to analog pin
complete code file in attachment
Mod edit: code tags-JohnInTX
but i have two question
1- this code read puls rate from pin AN0 analoge -- but when remove my finger why its not give me zero?? result will be same
how to add to the code to give me zero 0 when no puls in
2- another question why he program mcu to be as counter puls from timer 0 and other interrupt pin
why he put puls to analog pin
complete code file in attachment
C:
// >>> Pulse Sensor purple wire goes to Analog Pin 0 <<<
//Pulse Sensor sample aquisition and processing happens in the background via Timer0 interrupt. 2mS sample rate.
//The following variables are automatically updated:
//Signal : int that holds the analog signal data straight from the sensor. updated every 2mS.
//IBI : int that holds the time interval between beats. 2mS resolution.
//BPM : int that holds the heart rate value, derived every beat, from averaging previous 10 IBI values.
//QS : boolean that is made true whenever Pulse is found and BPM is updated. User must reset.
//Pulse : boolean that is true when a heartbeat is sensed then false .
//THIS PROGRAM WAS TESTED ON A PIC18F452 RUNNING AT 32MHz HS_PLLx4
/*************************************************************************/
sbit LCD_RS at RD2_bit;
sbit LCD_EN at RD3_bit;
sbit LCD_D4 at RD4_bit;
sbit LCD_D5 at RD5_bit;
sbit LCD_D6 at RD6_bit;
sbit LCD_D7 at RD7_bit;
sbit LCD_RS_Direction at TRISD2_bit;
sbit LCD_EN_Direction at TRISD3_bit;
sbit LCD_D4_Direction at TRISD4_bit;
sbit LCD_D5_Direction at TRISD5_bit;
sbit LCD_D6_Direction at TRISD6_bit;
sbit LCD_D7_Direction at TRISD7_bit;
enum {FALSE = 0, TRUE = 1};
char intro_msg[] = "ELECTRONIC HEART RATE MONITOR";
char temp_str[8], disp_result;
int rate[10]; // array to hold last ten IBI values
unsigned long sampleCounter = 0; // used to determine pulse timing
unsigned long lastBeatTime = 0; // used to find IBI
int Peak =512; // used to find peak in pulse wave, seeded
int Trough = 512; // used to find trough in pulse wave, seeded
int thresh = 512; // used to find instant moment of heart beat, seeded
int amp = 100; // used to hold amplitude of pulse waveform, seeded
bit firstBeat; // used to seed rate array so we startup with reasonable BPM
bit secondBeat; // used to seed rate array so we startup with reasonable BPM
int pulsePin = 0; // Pulse Sensor purple wire connected to analog pin 0
int blinkPin = 13; // pin to blink led at each beat
int runningTotal = 0; // clear the runningTotal variable
// these variables are volatile because they are used during the interrupt service routine!
unsigned int BPM; // used to hold the pulse rate
unsigned int Signal; // holds the incoming raw data
unsigned int IBI = 600; // holds the time between beats, must be seeded!
bit Pulse ; // true when pulse wave is high, false when it's low
bit QS;
int N_cnt, P_cnt;
int i = 0;
void InitTimer0(){ //timer0 is set to Interrupt every 2ms. PIC18F452 is running at 32MHz
T0CON = 0xC5;
TMR0L = 0x06;
GIE_bit = 1;
TMR0IE_bit = 1;
}
void Interrupt(){
GIE_bit = 0;
if (TMR0IF_bit){ //every 2ms
//READ HEART RATE FROM LCD
Signal = ADC_Get_Sample(0);
sampleCounter += 2;
N_cnt = sampleCounter - lastBeatTime;
if(Signal < thresh && N_cnt > (IBI/5)*3){
if (Signal < Trough){
Trough = Signal;
}
}
if(Signal > thresh && Signal > P_cnt){
P_cnt = Signal;
}
// NOW IT'S TIME TO LOOK FOR THE HEART BEAT
// signal surges up in value every time there is a pulse
if (N_cnt > 250){ // avoid high frequency noise
if ( (Signal > thresh) && (Pulse == FALSE) && (N_cnt > (IBI/5)*3) ){
Pulse = TRUE; // set the Pulse flag when we think there is a pulse
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
rate[I] = 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
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(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 = TRUE; // set Quantified Self flag
// QS FLAG IS NOT CLEARED INSIDE THIS ISR
}
}
if (Signal < thresh && Pulse == TRUE){ // when the values are going down, the beat is over
Pulse = FALSE; // reset the Pulse flag so we can do it again
amp = P_cnt - Trough; // get amplitude of the pulse wave
thresh = amp/2 + Trough; // set thresh at 50% of the amplitude
P_cnt = thresh; // reset these for next time
Trough = thresh;
}
if (N_cnt > 2500){ // if 2.5 seconds go by without a beat
thresh = 512; // set thresh default
P_cnt = 512; // set P default
Trough = 512; // set T default
lastBeatTime = sampleCounter; // bring the lastBeatTime up to date
firstBeat = TRUE; // set these to avoid noise
secondBeat = FALSE; // when we get the heartbeat back
}
TMR0IF_bit = 0;
TMR0L = 0x06;
GIE_bit =1;
}// end isr
GIE_bit =1; // enable interrupts when youre done!
}
void main() {
int g;
Pulse = FALSE;
QS = FALSE;
firstBeat = TRUE;
secondBeat = FALSE;
Lcd_Init(); //initialize LCD
Lcd_Cmd(_LCD_CLEAR); // Clear display
Delay_ms(200);
Lcd_Cmd(_LCD_CURSOR_OFF);
Delay_ms(200);
Lcd_Out(1,1, intro_msg);
Delay_ms(1500); // First row
for(g=0; g<sizeof(intro_msg)-16; g++) { // Move text to the right 4 times
Lcd_Cmd(_LCD_SHIFT_LEFT);
Delay_ms(250);
}
Lcd_Cmd(_LCD_CLEAR); // Clear display
Delay_ms(200);
ADC_Init();
InitTimer0();
while(1){
if (QS == TRUE){ //New Pulse detected
Lcd_Out(1,1,"HEART RATE (BPM)");
Lcd_Out(2,1," ");
IntToStr(BPM, temp_str);
Lcd_Out(2,8,temp_str);
//Delay_ms(2000);
}
}
}
Attachments
-
57.3 KB Views: 28
Last edited by a moderator: