Jaspers Heart Rate Receiver

Updated 24-Nov-2010

Short description:
A heart rate receiver was build in hardware and connected to a PIC microcontroller to be able to display hart reate to a LCD display. The PIC microcontroller is programmed in C to measure the time between heart beats, displays the beats per minute (BPM) and the time (timems) between consequent heart beats. The microcontroller sends the the BPM through a serial communication cable to the PC.

Hardware:
- Polar heart rate transmitter belt
- MikroE EasyPIC5 development board with a PIC16F887 microcontroller and  a 2x16 character HD44780 compatible LCD display
- MikroE  MicroC Pro compiler for PIC
- Polar RMCM-01 heart rate receiver module

Below: Left: The PCB with the Polar RMCM-01 heart rate receiver and 3V voltage regulator. Right: Polar heart rate transmitter belt

 The Polar heart rate module is mounted together with a 3V voltage regulator and is supplied with 5V and GND from the EasyPIC5 development board. The output from the Polar RMCM01 module  is connected to Port B pin 7 (RB7) of the development board.

 Above is the schematic of the 3V voltage regulator and a Polar heart rate module

 The 2x16 character in the development board displays BPM and the beat to beat interval. In this picture my heart rate was very low.

Program code  description:
Internally of the PIC16F887 a timer interrupt increases a counter with one every 1ms. This is the base of the time measurement. On every heart beat the RMCM-01 module outputs a short positive pulse on pin RB7 of the PIC16F887. In the program, the RMCM-01 pulse generates a heart beat interrupt. When a heart beat intterupt occurs the value of the counter is the heart beat interval in ms and the counter is set back to 0. The PIC16F887 is running at a 8 Mhz clock. I chose to use timer2 of the PIC16F887 because timer 2 uses a prescaler (/4), a compare value(100) and a postscaler(/5) to generate a interrupt every 1ms. Calculation: 8Mhz*(/4)*(/4)*100*(/5)=1kHz or 1ms.

The code:
/* Project name:
     Jaspers heart rate receiver using timer2
 * Description:
     The code displays heart Beats Per Minute(BPM) and time between heart beats
     (ms) on the LCD display and also send it through uart.
 * Test configuration:
     MCU:             PIC16F887
     Dev.Board:       EasyPIC5
     Oscillator:      HS, 8 MHz
     Ext. Modules:    LCD 2x16
     Ext. Hardware:   Polar RMCM-01 Heart Rate receiver on RB7
     SW:              mikroC PRO for PIC
 * NOTES:
     - Turn on LCD backlight switch (SW9.7) on development board. */

// LCD module connections
sbit LCD_RS at RB4_bit;
sbit LCD_EN at RB5_bit;
sbit LCD_D4 at RB0_bit;
sbit LCD_D5 at RB1_bit;
sbit LCD_D6 at RB2_bit;
sbit LCD_D7 at RB3_bit;
sbit LCD_RS_Direction at TRISB4_bit;
sbit LCD_EN_Direction at TRISB5_bit;
sbit LCD_D4_Direction at TRISB0_bit;
sbit LCD_D5_Direction at TRISB1_bit;
sbit LCD_D6_Direction at TRISB2_bit;
sbit LCD_D7_Direction at TRISB3_bit;

volatile unsigned int CNT;
volatile unsigned short DisplayBPMflag = 0;
unsigned short BPM;
unsigned int timems, count;
char txtBPM[6],txtTimems[6] ;

void interrupt(void){
     if(INTCON.RBIF){                       // check portB interrupt on change
      if (PORTB.B7){                        // check RB7 on rising edge
       CNT = count;                         // Copy count2 value to CNT
       count = 0 ;                          // reset count2 value
       DisplayBPMFlag = 1;                  // set flag that the BPM can be put to LCD in the main loop
      }
      INTCON.RBIF = 0;                      // Clear RB interrupt flag at rising AND at falling edge
     }
     if(PIR1.TMR2IF){
       PIR1.TMR2IF = 0;                     // clear timer2 interrupt flag
       count++;                             // increase by 1
     }
}

void main(){
    ANSEL = ANSELH  = 0;        // ALL set as Digital I/O
    TRISB = 0xC0;               // Set RB7 and RB6 as input, rest is output

    Lcd_Init();                 // Start LCD
    Lcd_Cmd(_LCD_CLEAR);        // Clear LCD
    Lcd_Cmd(_LCD_CURSOR_OFF);   // Cursor off
    Lcd_Out(1,1,"BPM");         // Write text in first row
    Lcd_Out(1,9,"Time(ms)");    // Write text in second row

    INTCON = 0;                 // Clear INTCON register
    INTCON.PEIE = 1;            // Periphereal interrupt enable
    INTCON.RBIE = 1;            // RB PORT interrupt on change enable
    IOCB.IOCB7  = 1;            // RB PIN 7 interrupt on change enable
    INTCON.RBIF = 0;            // Clear RB port interrupt on change flag

    T2CON = 0x21;               // prescaler 1:4, postscaler 1:5 (osc/4)
    PR2 = 100;                  // count to 100 (this results in an interrupt every 1ms)
    PIR1.TMR2IF = 0;            // timer2 to PR2 interrupt flag bit p86
    T2CON.TMR2ON  = 1;          // Timer2 ON
    PIE1.TMR2IE = 1;            // Timer2 interrupt enable
    INTCON.GIE  = 1;            // Global interrupt enable bit

    uart1_init(9600);           // Initializes serial communication at 9600 bps

    while(1){                            // program loops around in here
         if(displayBPMFlag == 1){
         DisplayBPMFlag = 0;           // clear displayBPMflag
           if(CNT>250&CNT<2000){         // When heart rate is in normal range (30-240BPM)
              BPM = 60000/CNT;           // calculate BPM
              Timems = CNT; }            // time(ms)
           else{BPM = 0; timems = 0;}    // otherwise display 0
           ByteToStr(BPM, txtBPM);       // convert BPM to string
           Lcd_Out(2,1,txtBPM);          // display BPM string on LCD
           WordToStr(timems, txtTimems); // convert Timems to string
           Lcd_Out(2,12,txtTimems);      // display Timems string on LCD
           uart1_write(BPM);             // send BPM through uart
           //uart1_write(timems>>8);       // send high byte of timems through uart
           //uart1_write(timems);          // send low  byte of timems through uart
         }
   }
}

Future:
In the future I want to display a heart rate graph on the PC screen. Eventually I would like to make a simple game. The goal is to quickly induce relaxation (or reduce stress) by means of bio-feedback of the heart rate change. Breathing in temporary increases heart rate and breathing out temporary decrease heart rate. Variation of heart rate is called heart rate variability, and is still in research these days. The goal is to maximize the change of heart rate. Therefor I want to display the change in heart rate. Points are scored when the change in heart rate is large and when the time increases. When a certain amount of points are scored (after 5 minutes) you will be very relaxed.