Download as pdf or txt
Download as pdf or txt
You are on page 1of 6

/* Pulse oximeter

A voltage signal is detected on pin A0 with an AC component due to heart beats filtered and
amplified. Heart rate is obtained from

the frequency of this signal.

To eliminate noise, each data point used is the result of averaging several measures in a short
period of time (a few tens of milliseconds), and then getting a sample

of several of these points for a duration of a few seconds.

For each sample we find the minima and calculate the period from the time between
successive minima. We then take the periods obtained and in order to get a more accurate

result, we calculate the median (or, alternatively, the mean).

The heart rate obtained is printed in multiples of 2 (because of lack of precision more detail is
unnecessary). The process is repeated in the loop function indefinitely.

Results are printed on serial monitor and on LCD screen.

*/

#include <Wire.h>

#include <LiquidCrystal_I2C.h>

LiquidCrystal_I2C lcd(0x3F,16,2);

//Declaration of variables that will be used later on in the code

double long t0=0; // Time reference for the time of the first minimum

int values[150]; // Vector to store values of voltage for each sample

int times[150]; // Vector to store values of time for each sample

int n=0; // Index for each data point


int count=0; // Counter for the averaging of the signal

int long sensorValue=0; // Reference value for the averaging of the signal

long tprev=0; // Reference time for the time when each sampling starts

int l=0; // Counter for the number of minima in each sample

double vector[15]; // Vector to store the minima; the number of minima depends on
the time length of the sample and the heart rate, but it should be < 15

//This is executed only once

void setup(){

Serial.begin(9600); // Begin serial communication

Serial.println("Please wait"); // Print "Please wait"

lcd.init();

lcd.backlight();

lcd.print("Please wait");

//This is executed indefinitely

void loop(){

int mk; // Index for the position of the heart rate closest to the mean in
each sample

double HR; // Heart rate

count++; // Count starts at 0 and adds 1 with each loop

sensorValue = analogRead(A0)+sensorValue; // Successive voltage values are measured and


added up for each loop (for each count)

if (count==500){ // After 500 loops (about 50 milliseconds), we divide the sum


of all the values obtained so far
double avsensorValue=sensorValue/500.0; // by the number of measures (or counts) to
get the average value, store it and store the ending

values[n]=avsensorValue; // time of the interval. Since this isn't the time of the
point but the time of the last value of

times[n]=millis()-tprev; // the averaged sample, there will be a small possible error


in the period which will translate in

count=0; // a possible error of 1-2 beats per minute (bpm) in the heart
rate. This will not be significant, though.

sensorValue=0;

n++; // The counter, sensorValue and n values are updated to continue


getting averaged values

if(n>149){ // When our data sample is full, we analyse the data to get the
heart rate (a few seconds will have past)

for(int m=10;m<139;m++){ // For each m, we check if its average voltage value is


lower than a few of its neighbours, that is, if it is

// a local minimum

int minim=1023;

for(int k=m-10;k<=m+10;k++){

if(values[k]<minim){

minim=values[k];

mk=k;

if (mk==m){ // If it is a local minimum, then we calculate the period as the


difference between its time and the time of

double T=times[m]-t0; // the previous minimum. For the first value, only the
time of the minimum is obtained (t0=0) and no period

if(t0>0){ // nor heart rate is calculated. When the next minimum is found,
then t0>0 and equal to the time of the first

HR=60.0/T*1000; // minimum is used to calculate the period and heart rate

if(HR>50&&HR<150){ // The heart rate value obtained is only considered if it is


within some reasonable boundaries
l++; // Each time a heart rate value is measured, it is stored in vector
and one unit is added to l to count for

vector[l-1]=HR; // the number of minima detected (some minima might be


skipped if the signal is not clean enough).

t0=times[m]; // t0 is updated us the time of the last minimum recorded

// Now that we have a vector with the first l values storing the heart rates measured in the
sample (from vector[0] to vector[l-1]), we try to get the most

// accurate value in 2 ways:

//With the mean: we calculate the mean and we eliminate the value farthest from it; we
repeat this process until only two values remain, and we take the

//mean of both values

int g=l;

while(g>2){

double long valor=0;

for(int k=0;k<g;k++){

valor=valor+vector[k];

double mean=valor/g;

double disp=0;

for(int k=0;k<g;k++){

if(abs(vector[k]-mean)>=disp){

disp=abs(vector[k]-mean);

mk=k;

}
double disc=vector[g-1];

vector[g-1]=vector[mk];

//Serial.println(vector[mk]);

vector[mk]=disc;

g=g-1;

double long valor=0;

for(int k=0;k<g;k++){

valor=valor+vector[k];

double mean=valor/g;

double avHR=int(mean/2)*2;

Serial.println("Your heartbeat: ");

Serial.println(avHR);

lcd.clear();

lcd.print("Heart rate:"+String(avHR));

//With the median: we calculate the median and use it as the heart rate value

// for(int k=0;k<l-1;k++){ // Sort the vector

// for(int h=0;h<l-(k+1);h++){

// if(vector[h]>vector[h+1]){

// int t=vector[h];

// vector[h]=vector[h+1];

// vector[h+1]=t;

// }

// }

// }

//

// // For odd values of l


// if(l%2!=0){ // Calculate the median and print it (or print
the average of median and mean)

// Serial.println("Your heartbeat (bpm): ");

// Serial.println(int(vector[int(l/2)]/10)*5); // The values printed are expressed


in multiples of 5

// }

// // For even values of l

// else{

// Serial.println("Your heatbeat (bpm): ");

// Serial.println(int(((vector[l/2-1]+vector[l/2])/2)/10)*5);

// }

n=0; // Reinitialize n

tprev=millis(); // Update starting time for the next sample

t0=0; // Reinitialize reference time for the first


minimum of the next sample

l=0; // Reinitialize number of minima detected in the


next sample

You might also like