Lucas Silva Lopes (Student ID #: 0887016)
Chinh Nguyen Ngoc Tran (Student ID #: 50649247) 
 BME 60A 
Project 3 
Heart Rate Monitor  
Dear Dr. Botnivick, Eric, and Jue,  
In this project, we tried to build an optical heart rate monitor that reads the heart rate 
as  accurately  as  possible.  In  order  to  do  so,  many  steps  were  required.  We  used 
paperboard, electrical tape, LEDs and a light sensor along with the Arduino board to 
create the device. We then used Labview to write the code. The hardest part was to 
figure out an absolute way to distinguish between a good signal and a bad signal, so 
we  could  show  only  reliable  values  of  heart rate.  Many  steps  were  described  in  the 
report. We hope you like our project.  
Sincerely!           
Approach Description:  
We  divide  our  project  into  four  parts:  Data  acquisition,  signal  processing,  interface 
and data logging.  
In the first part of our Project, which was data acquisition, we used paperboard and 
electrical tape to make a support for the LEDs in order to keep them stable on top of 
the  sensor  and  pointing  to  it.  Also,  we  found  out  that  using  just  one  LED  was  not 
sufficient;  especially  in  a  dim  room  with  only  light  coming  from  the  outside,  more 
LEDs  were  required  for  the  experiment  to  be  effective.  Thus,  we  used  three  LEDs 
instead of just one. By keeping the LEDs still, above and pointing to the sensor while 
one little finger lie on it, we were able to acquire good data  several times  in at least 
two  very  different  conditions  (day  and  night).  Therefore,  we  made  this  our  standard 
device.  
In  the  second  part  of  our  project,  we  had  to  write  a  code  to  smooth  the  signal, 
detrend it, and find its period. We used methods described in class, such as: moving 
average  filtering,  median  rank  filtering,  linear  fitting  and  autocorrelation.  The  period 
was found after the autocorrelation function graph.  
In the third part, we had to create an interface for the device user. We had to decide 
which values to show and which values not to show. More precisely, we had to find a 
way  to  decide,  regardless  the  ambient  conditions:  is  the  signal  pattern  acquired 
mostly  due  to  the  pulsatile  nature  of  the  circulatory  system  or  not?  After  trying 
different  ways  of  measuring  this  attribute,  we  found  out  that  the  difference  between 
the  center  peak  of  a  normalized  autocorrelation  curve  and  the  peak  to  its  right  is 
really helpful to decide whether a signal is acceptably periodic or not.   
There are some other attributes we could have used to decide if a signal is good or 
not, such as the area under the processed  signal after taking its modulus; however, 
even though these attributes work well visually, when you try to normalize them, they 
are  no  longer  eligible  to  differentiate  between  a  good  signal  and  a  bad  signal.  Its 
important  to  normalize  because  periodic  functions  are  characterized  by  different 
attribute values depending on the ambient light conditions. We also tried other ways 
besides  normalization  to  make  these  values  the  same  regardless  the  ambient 
conditions, but they all turned out unsuccessfully.   
In the last part,  we added data logging into our project, so data can be opened in a 
spreadsheet program for viewing or creating graphs.      
Code Description:  
In  the  first  part  of  the  code,  we  just  acquire  data  continuously  from  the  sensor. We 
use  an  acquisition  speed  of  200  Hz  and  acquire  600  samples,  giving  a  total  of  3   
seconds of data acquisition.   
In  the  second  part,  we  process  the  acquired  signal.  First  we  use  a  filter  express  vi 
and  select  smoothing  as  filtering  type. We  select  a  5  half-width  moving  average,  in 
other words a moving average of 11 points. We then convert the filtered signal, which 
is in dynamic data type (includes additional attributes such as date and time the data 
was  acquired)  to  waveform  data  type.  Later  we  ignore  the  11  first  elements  of  the 
curve  because  the  moving  average  algorithm  creates  an  artificial  rise  in  the 
beginning  of  the  curve.  We  use  a  median  filter  vi,  with  left  and  right  ranks  equal  to 
five.  We  calculate  a  linear  fitting  and  subtract  it  to  detrend  the  data.  At  last,  we 
calculate the autocorrelation function of the signal.  
In  the  third  part,  we  first  normalize  the  autocorrelation  function,  we  get  rid  of  the 
negative values by adding 1 to everything, and make the maximum value 1 again by 
dividing the function by 2. Now the distance between the center peak and the peak to 
its right is a number between 0 and 1, which is more intuitive, similar to percentage. 
Then  we  find  the  peaks.  The  difference  between  their  indexes  is  the  period  of  the 
signal and the difference between their values is the number between 0 and 1. Now 
we  calculate  the  heart  rate  by  changing  the  units  of  the  period  from  indexes  to 
seconds, taking its inverse (which is the frequency in hertz) and multiplying it by 60, 
which  gives  the  heart  rate  in  beats  per  minute.  We  then  convert  it  to  a  string 
constant,  so  when  the  distance  between  the  peaks  is  less  than  0.3  (value found  by 
observation of various periodic and non periodic signals) we show the heart rate, and 
when it is greater than 0.3, we show Try again.  
In the last part, we allow the user to define a path to the data. It can be appended to 
a preexisting file or saved into a new one.