0% found this document useful (0 votes)
7 views7 pages

Heart Rate Monitor Code for LCD Display

The document defines variables and functions for reading heart rate data from a sensor and displaying the results on an LCD. It initializes peripherals, sets up interrupts to read sensor data every 2ms, calculates heart rate in BPM, and displays the results on the LCD screen.
Copyright
© All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
7 views7 pages

Heart Rate Monitor Code for LCD Display

The document defines variables and functions for reading heart rate data from a sensor and displaying the results on an LCD. It initializes peripherals, sets up interrupts to read sensor data every 2ms, calculates heart rate in BPM, and displays the results on the LCD screen.
Copyright
© All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd

Sbit LCD_RS at RD0_bit;

Sbit LCD_EN at RD6_bit;

Sbit LCD_D4 at RD5_bit;

Sbit LCD_D5 at RD4_bit;

Sbit LCD_D6 at RD3_bit;

Sbit LCD_D7 at RD2_bit;

Sbit LCD_RS_Direction at TRISD0_bit;

Sbit LCD_EN_Direction at TRISD6_bit;

Sbit LCD_D4_Direction at TRISD5_bit;

Sbit LCD_D5_Direction at TRISD4_bit;

Sbit LCD_D6_Direction at TRISD3_bit;

Sbit LCD_D7_Direction at TRISD2_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;

OSCCON.IRCF0=0;

OSCCON.IRCF1=1;
OSCCON.IRCF2=1;

ANSELA=0x01;

ANSELB=0x00;

ANSELC=0x00;

ANSELD=0x00;

ANSELE=0x00;

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);

Common questions

Powered by AI

Timer0 plays a critical role by providing time-based interruptions every 2 milliseconds to facilitate the continuous sampling of the pulse signal. The Timer0 is configured using `T0CON = 0xC5` to control the operation of Timer0 with pre-scaler settings, followed by initializing `TMR0L = 0x06` to ensure timely recurring interrupts. During each interrupt, the heart rate sensor samples the signal, updates the sample counter, checks conditions for pulse detection, and dynamically adjusts the threshold. By ensuring periodic execution, Timer0 allows real-time monitoring of heart signal data to accurately measure and respond to changes in pulse rate .

Configuration of the PIC18F452 microcontroller encompasses both hardware and software settings. Hardware setup involves connecting the pulse sensor to analog pin RA0 (pulsePin = 0), using a pin (RD13) to blink an LED at each detected heartbeat (blinkPin = 13), and initializing the LCD on port D for outputs. Software configuration involves setting up the initial values for signal processing variables, configuring the ADC with `ADC_Init()`, and establishing Timer0 to interrupt every 2ms using `InitTimer0()`. The initialization also requires setting up oscillator control for frequency scaling and ensuring the ADC operates correctly with specific `ANSEL` register settings for each port .

Initialization involves several key steps such as setting up the oscillator control (OSCCON) to adjust clock frequency, configuring analog ports (ANSx registers) to ensure proper analog signal input and digital output, and initializing Timer0 for time-sensitive operations. The Liquid Crystal Display (LCD) is also initialized and prepared to display introductory messages, while critical pulse detection variables are initialized to track heart signal data accurately. Lastly, ADC and interrupts are configured to work in tandem, accommodating real-time signal processing before entering the main operation loop where data acquisition and processing occur .

The rate array stores the last ten inter-beat interval (IBI) values, providing a basis for calculating an accurate heart rate. Every time a new IBI is calculated following a heartbeat detection, the oldest value in the rate array is replaced with the latest IBI value, and the running total is updated by removing the oldest and adding the newest IBI. This running total is divided by ten to yield an average IBI, which stabilizes short-term variability in BPM calculation, resulting in a realistic BPM that accounts for fluctuations across multiple cardiac cycles .

The system detects a pulse by monitoring changes in signal amplitude in relation to a dynamically adjusted threshold. When the incoming analog signal exceeds the threshold while satisfying the conditions of non-high frequency noise and sufficient time since the last beat, it sets a Pulse flag indicating pulse detection. The threshold is adjusted dynamically after detecting the beat. If the signal surpasses the threshold and is associated with the rising section of a pulse wave, the Pulse flag is engaged. Once the pulse has passed and the signal decreases, the amplitude is computed as the difference between the peak (P_cnt) and the trough values. The new threshold is then set as halfway between the amplitude and trough, i.e., the amplitude is divided by two and added to the trough. This ensures the threshold adapts to the signal's dynamic range for accurate pulse detection .

The IBI, representing the duration in milliseconds between successive heartbeats, is a crucial measure for determining the heart rate. Initially seeded with 600 milliseconds, the IBI is dynamically updated with each beat detection, being the elapsed time between the current and last beat, aiding in calculating BPM. Maintaining accurate IBI measurements ensures realistic BPM outputs. The system calculates an average IBI using a running total of the last ten IBI values, stored within an array, facilitating a responsive and accurate heart rate analysis by smoothing short-term fluctuations .

The LCD serves as an interface between the heart rate monitoring system and the user, displaying initialization messages and real-time pulse data. Upon startup, it presents the message 'ELECTRONIC HEART RATE MONITOR,' positioned at the first row and scrolls leftward. After initialization, the LCD shows 'HEART RATE (BPM)' on the first row. On the second row, it displays the calculated BPM value obtained by converting it from integer to a string format, ensuring clarity and user engagement by updating every two seconds as new pulse information is available .

The system calculates the BPM by averaging the intervals between heartbeats, known as inter-beat intervals (IBI). Initially, it seeds the rate array with the IBI value from the first two detected beats. For the first detected beat, the system discards the IBI as it is unreliable. During subsequent pulses, it keeps a running total of the last ten IBI values. By dividing the accumulated total by ten, it computes the average IBI, from which the BPM is calculated as 60000 divided by the average IBI, ensuring accuracy over time. This initialization helps stabilize BPM readings by accounting for initial fluctuations .

The system detects prolonged periods without a heartbeat—defined as more than 2.5 seconds—by checking if `N_cnt` exceeds 2500. In these cases, it resets critical variables to their default values: the threshold (`Thresh`), peak count (`P_cnt`), and trough (`Trough`) are all set to 512. This reset helps eliminate potential noise-induced errors and stabilizes the system upon return of a detectable heartbeat. The re-establishment to default values ensures a quick reset of conditions that could otherwise mislead readings, so effective recovery from noise and preparation for pulse resumption occur within the system .

The system avoids false positive detections due to noise by implementing various threshold and timing checks. It sets an initial threshold at 512 and adjusts dynamically based on real-time amplitude analyses between peaks and troughs to differentiate valid pulses from noise. Furthermore, signals are cross-verified against conditions like minimized acceptable time intervals between beats (greater than one-fifth of the IBI multiplied by three). Additionally, a noise prevention mechanism is embedded to disregard any signals that do not align with a detected range stipulated by `N_cnt > 250`—a time period to prevent noise mimicking a heartbeat .

You might also like