Maker Pro
Maker Pro

Heart Rate Monitor Design Problem (CCS Compiler) Software

Hi i am designing a heart rate monitor via photoplethysmography, the signal is derived in to port A0 of the PIC as illustrated. I am looking to display results via a 2 thresholds that was set with respect to the voltage reference towards a 10 bit ADC. This is my code, could someone identify any thing wrong with it??

#include <16F877.h>
#device ADC=10
#use delay(crystal=8000000)

/* Main.c file generated by New Project wizard
*
* Created: Thu Apr 16 2015
* Processor: PIC16F877
* Compiler: CCS for PIC
*/

#include "LCD.c"
#include <float.h>
#include <stdlib.h>
#include <string.h>
#use RS232(baud=9600, xmit=PIN_C7, rcv=PIN_C6)
#use delay(clock = 8000000)

#fuses HS, NOWDT, NOPROTECT, PUT, NOBROWNOUT, NOLVP, NOWRT, NODEBUG
//A/D Control Register
#BYTE ADCON0 = 0x1F

#define LCD_ENABLE_PIN PIN_B3
#define LCD_RS_PIN PIN_B1
#define LCD_RW_PIN PIN_B2
#define LCD_DATA4 PIN_D4
#define LCD_DATA5 PIN_D5
#define LCD_DATA6 PIN_D6
#define LCD_DATA7 PIN_D7

#define Analog_In PIN_A0
#define bool int
#define BUFFER_SIZE 10

// define globals
const int TIMER_STOP_TIME = 15000; // pulses stop time in milliseconds
const int MOVING_AVG_SIZE = 10;
char message[BUFFER_SIZE];
int ring_buffer[BUFFER_SIZE];
int rb_start = 0;
int rb_end = 0;
const int16 PULSE_UPPER_THRESHOLD = 460;
const int16 PULSE_LOWER_THRESHOLD = 376;
int pulse_display;
int pulse_count = 0;
int ready = 0;
int heart_pulse = 0;
int timer_count = 0;
int16 timer_ms = 0;
int16 volt = 0;

// function prototypes
void LCD_DISP();
void read_ADC_Data();
void initialize();
int is_below_upper_threshold(int q);
int is_above_lower_threshold(int q);
void write_rb(int val);
int get_time_duration();
void reset_timer();

// 262 milliseconds timer interval
#int_TIMER1
void TIMER1_isr()
{
timer_count++;
}

#int_AD
void AD_isr()
{
delay_ms(500);
setup_adc(ADC_CLOCK_DIV_32);
setup_adc_ports(AN0_AN1_VSS_VREF);
set_adc_channel(0);
}

void main()
{
initialize();
read_ADC_Data();
}

// resets the timer counter for a new time duration
void reset_timer()
{
timer_count = 0;
}

// returns the time elapsed from last timer reset (reset_timer)
int get_time_duration()
{
return 262 * timer_count; // 262: see TIMER1_isr
}

void LCD_DISP()
{
lcd_init();
Delay_ms(50);
putc(254); putc(1); delay_ms(10); //Clear Display
Delay_ms(100);
printf("Heart Rate:"); putc(heart_pulse);
}

void read_ADC_Data()
{
// pulse definition: hits first upper threshold from above it then hits
// lower threshold and then hits upper threshold again -> that is one full pulse
// hit_upperthreshold is only true if the upperthreshold is hit from above it
int hit_upperthreshold = false;
// hit_lowerthreshold can only be true if the upper threshold has first been
// hit (hit_upperthreshold = true)
int hit_lowerthreshold = false;
int prev_value_above_upper_threshold = false;
int i;
int1 timer_started = false;
int16 adc_value;
for (i=0; i<5; i++)
{
output_high(PIN_B4); // Green LED on while no input
delay_ms(250);
output_low(PIN_B4);
}
// start reading adc values as long they are coming
while (input(Analog_In))
{
AD_isr();
adc_value = read_adc(); // Read ADC values - in built function
output_high(PIN_B5); // Yellow LED on 'Buffer'
delay_ms(2000);

if (is_below_upper_threshold(adc_value) == true)
{
if(prev_value_above_upper_threshold == true)
{
// we hit the upper threshold from above the upperthreshold
// so we have (start of) a new pulse
hit_upperthreshold = true;
if (pulse_count == 0)
{
reset_timer(); // saves the current time so the duration can be calculated
timer_started = true;
}
// only those adc values which are between lower_threshold and
// upper_threshold will be added to the ring buffer:
if(is_above_lower_threshold(adc_value) == true)
write_rb(adc_value); // Ring buffer receives adc value
}
prev_value_above_upper_threshold = false;
}
else // we are above the upper threshold
{
prev_value_above_upper_threshold = true;
}
if((hit_upperthreshold == true) && (is_above_lower_threshold(adc_value) == false))
{
// hit upper threshold and now lower threshold
hit_lowerthreshold = true;
}
else if((hit_lowerthreshold == true) && (is_below_upper_threshold(adc_value) == false))
{
// hit upper threshold then lower threshold and now uppert hreshold again
// so one pulse is now finished
pulse_count++;
// zero threshold-hit flags
hit_upperthreshold = false;
hit_lowerthreshold = false;
}
// Condition if timer reaches 15 seconds
if (timer_started && (get_time_duration() >= TIMER_STOP_TIME))
{
// Stop timer and perform heart pulse calculations
heart_pulse = pulse_count * 4; // Such calculations provides BPM
LCD_DISP();
delay_ms(1000);
output_low(PIN_B4); // Green LED off
output_low(PIN_B5); // Yellow LED off while no input
// initialize the while-loop for the next heart rate calculations:
pulse_count = 0;
timer_started = false; // wait for the next pulse to start using timer again
prev_value_above_upper_threshold = false;
// zero the threshold-hit flags
hit_upperthreshold = false;
hit_lowerthreshold = false;
}
}
}

/*
initialize:
Function to initialize the globals and the in built functions accrodingly
*/
void initialize()
{
// the circular buffer
int q;
for (q = 0; q < BUFFER_SIZE; q++)
{
ring_buffer[q] = 0;
}
//I/O PORTS
output_D(255); //PortD as OUTPUT

// Interrupts
enable_interrupts(int_timer1);
enable_interrupts(INT_AD);
enable_interrupts(GLOBAL);

//Timer1
setup_timer_1(T1_INTERNAL|T1_DIV_BY_8); //262 ms overflow

// init display start
lcd_init();
}

/*
is_above_lower_threshold:
Function for threshold setup. Checks if a value is above the lower threshold.
*/
int is_above_lower_threshold(int q)
{
return ((q > PULSE_LOWER_THRESHOLD) ? true : false);
}

/*
is_below_upper_threshold:
Function for threshold setup. Checks if a value is below the upper threshold.
*/
int is_below_upper_threshold(int q)
{
return ((q < PULSE_UPPER_THRESHOLD) ? true : false);
}

/*
write_rb:
Writes val to ring buffer ring_buffer[].
*/
void write_rb(int val)
{
ring_buffer[rb_end++] = val; // Ring buffer designed to shift, therefore end value increments(shifts)
if (rb_end == BUFFER_SIZE) // If rb_end on the last location
rb_end = 0; // loop round
if (rb_end == rb_start) // if they overlap, increment the start value as well
rb_start++;
if (rb_start == BUFFER_SIZE) // If rb_start on the last location
rb_start = 0; // loop round
}
capture-png.84591
capture-png.84591
 
Top