Beruflich Dokumente
Kultur Dokumente
January 2019
Poximeter 2.2. Pulse Oximeter. Measures heart rate and blood oxygen concentration.
Two leds are turned on and off intermittently: the red led is turned on while the ir led is off;
then both of them are left off; then the IR led is turned on; then it is turned off again,
completing the cycle. The light from the led that's on rebounds off the finger (or other part of
the body) and hits a photodiode which produces a current. The current is then amplified,
converted into voltage and filtered, separating a DC and an AC component. We measure both
components for each of the three situations (once for each situation and cycle): red led on, ir
led
off; both leds off; and red led off, ir led on. This way we get values for the red and infrarred dc
and ac components, which we save in different vectors. This is repeated until we have a full
To get the period, we only use the AC red signal. We calculate the time distance between
minima. In one sample, we get a few values for the period; we average to get a more accurate
value.
by each corresponding term of the iredDC vector, and taking the average value of all these
ratios. To get the ratio of the AC components, we substract first the moving average of each
point
and then divide each new redAC point by the corresponding new iredAC point; we take the
average of all these ratios as the proper value, and from it we calculate the oxygen
concentration.
The heart rate and blood oxygen concentration are both displayed on the serial monitor and
the LCD screen.
WARNING: This code couldn't be properly verified because of inability to reduce noise in the
ired signal
*/
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
LiquidCrystal_I2C lcd(0x3F,16,2);
int n=0;// Index for each data point in the sample vectors
long tprev=0;// Reference time; time when each sampling starts (each sample starts at the
time of the last minimum)
int mk;
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
double long t0=0;// Time reference for the time of the first minimum
void setup(){
digitalWrite(irled,LOW);
}
// THE LOOP IS REPEATED ONCE FOR EACH SAMPLE VECTOR (the sample vector values are
reinitialized and the process is repeated)
void loop(){
while(n<dim){//While the number of obtained values is less than or equal to the size of the
sample vectors, it repeats the while instructions
// Turn the red led ON (ired led is OFF) and measure values of red(ac) and red(dc) signals
digitalWrite(rled,HIGH);
rdc=rdc+analogRead(A1);
// Turn the red led OFF (ired led is OFF) and measure values of ac and dc when both leds are
off
digitalWrite(rled,LOW);
delayMicroseconds(200);
//dc0=ac0+analogRead(A1);
// Turn the irled ON (red led is OFF) and measure values of ac and dc for ir
digitalWrite(irled,HIGH);
delayMicroseconds(200);
irac=irac+analogRead(A0);
irdc=irdc+analogRead(A1);
digitalWrite(irled,LOW);
delayMicroseconds(200);
// After maxcount loops (about 60 milliseconds), we divide the sum of all the values obtained
so far by the number of measures (or counts) to get the average value and store it
double racav=(rac-ac0)/maxcount;
double rdcav=(rdc-dc0)/maxcount; // The AC and DC values when both leds are off can
be substracted
rdcvalues[n]=rdcav;
iracvalues[n]=iracav;
irdcvalues[n]=irdcav;
times[n]=millis()-tprev; // The time for each sample vector starts at the time of the
last minimum (tprev)
rac=0;
rdc=0;
irac=0;
irdc=0;
ac0=0;
dc0=0;
n++; // The index for the number of data in the sample vector is
updated (n=0 for the first value)
// When our data sample is full (n=dim), we analyse the data to get the heart rate and AC
amplitudes rate
for(int m=y;m<dim-y;m++){// We go through al m in the sample vectors except the "y" first
ones and the "y" last ones
//For each m, take the y closest neighbour points to the left and right and find the minimum
value
int minim=1023;
for(int k=m-y;k<=m+y;k++){
if(racvalues[k]<minim){
minim=racvalues[k];
mk=k;
}
// If m itself is the minimum value, then we calculate the period as the time difference with
the previous minimum; otherwise, repeat the process with the next m
if (mk==m){
double T=times[m]-t0;
// If it is the first minimum, there is no previous minimum to compare with, but t0=0, so it
skips this loop. Otherwise, it enters the loop (t0>0) and the heart rate and amplitude quotient
// are calculated
if(t0>0){
if(HR>50&&HR<150){ // If the heart rate is lower than 50 or higher than 150, we assume the
value is wrong and don't store it
//We substract the moving average of the AC signals: for every m in each ac vector, we
calculate its average with the x values to the left and x values to the right; we then substract it
//from the point and do the fraction of red ac and ired ac for that value and store it in the
fracac vector
if(m>x-1&&m<dim-x){// We go through all m values except the "x" first ones and the "x" last
ones
for(int k=m-x;k<=m+x;k++){
RACmovav=RACmovav+racvalues[k];
IRACmovav=IRACmovav+iracvalues[k];
fracac[m-x]=(racvalues[m]-RACmovav/(2*x+1))/(iracvalues[m]-IRACmovav/(2*x+1));
}
double fracdc=0;
fracdc=rdcvalues[k]/irdcvalues[k]+fracdc;
double fracdcav=fracdc/(dim-2*x);
double R=0;
R=fracac[k]/fracdcav+R;
R=R/(dim-2*x);
SpO2=1/(1-(R*CHbOir-CHbOr)/(R*CHbir-CHbr))*100;
// CALCULATION OF PERIOD
int g=l;
while(g>2){
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;
// Place the value farthest from the average at the end of the vector
double disc=vector[g-1];
vector[g-1]=vector[mk];
vector[mk]=disc;
// Decrease g so that in the next loop the average is calculated for all the values except the
one/s we found was/were farthest from the average
g=g-1;
for(int k=0;k<g;k++){
valor=valor+vector[k];
double mean=valor/g;
double avHR=int(mean/2)*2;
// PRINT RESULTS
Serial.println(avHR);
lcd.clear();
lcd.setCursor(0,0);
lcd.print("Heart rate:"+String(avHR));
Serial.println(SpO2);
lcd.setCursor(1,0);
lcd.print("SpO2: "+String(SpO2));
//REINITIALIZE VALUES
n=0; // Reinitialize n