Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
I_Helmet
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
21_22-J 62
I_Helmet
Commits
0cc4c520
Commit
0cc4c520
authored
Apr 30, 2022
by
Balasuriya D.A.M.
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Spo2 and pulse rate sensor Test
parent
e4a64d43
Changes
1
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
429 additions
and
0 deletions
+429
-0
IT18021080/IoT Project/SpO2___Pulse_rate/KY-039_only_SpO2___Pulse_rate.ino
...oject/SpO2___Pulse_rate/KY-039_only_SpO2___Pulse_rate.ino
+429
-0
No files found.
IT18021080/IoT Project/SpO2___Pulse_rate/KY-039_only_SpO2___Pulse_rate.ino
0 → 100644
View file @
0cc4c520
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
#define maxperiod_siz 80 // max number of samples in a period
#define measures 10 // number of periods stored
#define samp_siz 4 // number of samples for average
#define rise_threshold 3 // number of rising measures to determine a peak
// a liquid crystal displays BPM
LiquidCrystal_I2C
lcd
(
0x27
,
16
,
2
);
int
T
=
20
;
// slot milliseconds to read a value from the sensor
int
sensorPin
=
A1
;
int
REDLed
=
3
;
int
IRLed
=
4
;
byte
sym
[
3
][
8
]
=
{
{
B00000
,
B01010
,
B11111
,
B11111
,
B01110
,
B00100
,
B00000
,
B00000
},{
B00000
,
B00000
,
B00000
,
B11000
,
B00100
,
B01000
,
B10000
,
B11100
},{
B00000
,
B00100
,
B01010
,
B00010
,
B00100
,
B00100
,
B00000
,
B00100
}
};
void
setup
()
{
Serial
.
begin
(
9600
);
Serial
.
flush
();
pinMode
(
sensorPin
,
INPUT
);
pinMode
(
REDLed
,
OUTPUT
);
pinMode
(
IRLed
,
OUTPUT
);
// initialize the LCD
lcd
.
init
();
lcd
.
backlight
();
// turn off leds
digitalWrite
(
REDLed
,
LOW
);
digitalWrite
(
IRLed
,
LOW
);
for
(
int
i
=
0
;
i
<
8
;
i
++
)
lcd
.
createChar
(
i
,
sym
[
i
]);
}
void
loop
()
{
bool
finger_status
=
true
;
float
readsIR
[
samp_siz
],
sumIR
,
lastIR
,
reader
,
start
;
float
readsRED
[
samp_siz
],
sumRED
,
lastRED
;
int
period
,
samples
;
period
=
0
;
samples
=
0
;
int
samplesCounter
=
0
;
float
readsIRMM
[
maxperiod_siz
],
readsREDMM
[
maxperiod_siz
];
int
ptrMM
=
0
;
for
(
int
i
=
0
;
i
<
maxperiod_siz
;
i
++
)
{
readsIRMM
[
i
]
=
0
;
readsREDMM
[
i
]
=
0
;}
float
IRmax
=
0
;
float
IRmin
=
0
;
float
REDmax
=
0
;
float
REDmin
=
0
;
double
R
=
0
;
float
measuresR
[
measures
];
int
measuresPeriods
[
measures
];
int
m
=
0
;
for
(
int
i
=
0
;
i
<
measures
;
i
++
)
{
measuresPeriods
[
i
]
=
0
;
measuresR
[
i
]
=
0
;
}
int
ptr
;
float
beforeIR
;
bool
rising
;
int
rise_count
;
int
n
;
long
int
last_beat
;
for
(
int
i
=
0
;
i
<
samp_siz
;
i
++
)
{
readsIR
[
i
]
=
0
;
readsRED
[
i
]
=
0
;
}
sumIR
=
0
;
sumRED
=
0
;
ptr
=
0
;
while
(
1
)
{
//
// turn on IR LED
digitalWrite
(
REDLed
,
LOW
);
digitalWrite
(
IRLed
,
HIGH
);
// calculate an average of the sensor
// during a 20 ms (T) period (this will eliminate
// the 50 Hz noise caused by electric light
n
=
0
;
start
=
millis
();
reader
=
0.
;
do
{
reader
+=
analogRead
(
sensorPin
);
n
++
;
}
while
(
millis
()
<
start
+
T
);
reader
/=
n
;
// we got an average
// Add the newest measurement to an array
// and subtract the oldest measurement from the array
// to maintain a sum of last measurements
sumIR
-=
readsIR
[
ptr
];
sumIR
+=
reader
;
readsIR
[
ptr
]
=
reader
;
lastIR
=
sumIR
/
samp_siz
;
//
// TURN ON RED LED and do the same
digitalWrite
(
REDLed
,
HIGH
);
digitalWrite
(
IRLed
,
LOW
);
n
=
0
;
start
=
millis
();
reader
=
0.
;
do
{
reader
+=
analogRead
(
sensorPin
);
n
++
;
}
while
(
millis
()
<
start
+
T
);
reader
/=
n
;
// we got an average
// Add the newest measurement to an array
// and subtract the oldest measurement from the array
// to maintain a sum of last measurements
sumRED
-=
readsRED
[
ptr
];
sumRED
+=
reader
;
readsRED
[
ptr
]
=
reader
;
lastRED
=
sumRED
/
samp_siz
;
//
// R CALCULATION
// save all the samples of a period both for IR and for RED
readsIRMM
[
ptrMM
]
=
lastIR
;
readsREDMM
[
ptrMM
]
=
lastRED
;
ptrMM
++
;
ptrMM
%=
maxperiod_siz
;
samplesCounter
++
;
//
// if I've saved all the samples of a period, look to find
// max and min values and calculate R parameter
if
(
samplesCounter
>=
samples
){
samplesCounter
=
0
;
IRmax
=
0
;
IRmin
=
1023
;
REDmax
=
0
;
REDmin
=
1023
;
for
(
int
i
=
0
;
i
<
maxperiod_siz
;
i
++
)
{
if
(
readsIRMM
[
i
]
>
IRmax
)
IRmax
=
readsIRMM
[
i
];
if
(
readsIRMM
[
i
]
>
0
&&
readsIRMM
[
i
]
<
IRmin
)
IRmin
=
readsIRMM
[
i
];
readsIRMM
[
i
]
=
0
;
if
(
readsREDMM
[
i
]
>
REDmax
)
REDmax
=
readsREDMM
[
i
];
if
(
readsREDMM
[
i
]
>
0
&&
readsREDMM
[
i
]
<
REDmin
)
REDmin
=
readsREDMM
[
i
];
readsREDMM
[
i
]
=
0
;
}
R
=
(
(
REDmax
-
REDmin
)
/
REDmin
)
/
(
(
IRmax
-
IRmin
)
/
IRmin
)
;
}
// check that the Ear is placed inside
// the sensor. If the Ear is missing
// RED curve is under the IR.
//
if
(
lastRED
<
lastIR
)
{
if
(
finger_status
==
true
)
{
finger_status
=
false
;
lcd
.
clear
();
lcd
.
setCursor
(
0
,
0
);
lcd
.
print
(
"No Ear?"
);
Serial
.
print
(
"No Ear ?"
);
}
}
else
{
if
(
finger_status
==
false
)
{
lcd
.
clear
();
finger_status
=
true
;
lcd
.
setCursor
(
10
,
0
);
lcd
.
print
(
"c="
);
lcd
.
setCursor
(
0
,
0
);
lcd
.
print
(
"bpm"
);
lcd
.
setCursor
(
0
,
1
);
lcd
.
print
(
"SpO"
);
lcd
.
write
(
1
);
//2
lcd
.
setCursor
(
10
,
1
);
lcd
.
print
(
"R="
);
}
}
float
avR
=
0
;
int
avBPM
;
int
SpO2
=
-
19
*
R
+
112
;
if
(
finger_status
==
true
){
// lastIR holds the average of the values in the array
// check for a rising curve (= a heart beat)
if
(
lastIR
>
beforeIR
)
{
rise_count
++
;
// count the number of samples that are rising
if
(
!
rising
&&
rise_count
>
rise_threshold
)
{
lcd
.
setCursor
(
3
,
0
);
lcd
.
write
(
0
);
// <3
// Ok, we have detected a rising curve, which implies a heartbeat.
// Record the time since last beat, keep track of the 10 previous
// peaks to get an average value.
// The rising flag prevents us from detecting the same rise
// more than once.
rising
=
true
;
measuresR
[
m
]
=
R
;
measuresPeriods
[
m
]
=
millis
()
-
last_beat
;
last_beat
=
millis
();
int
period
=
0
;
for
(
int
i
=
0
;
i
<
measures
;
i
++
)
period
+=
measuresPeriods
[
i
];
// calculate average period and number of samples
// to store to find min and max values
period
=
period
/
measures
;
samples
=
period
/
(
2
*
T
);
int
avPeriod
=
0
;
int
c
=
0
;
// c stores the number of good measures (not floating more than 10%),
// in the last 10 peaks
for
(
int
i
=
1
;
i
<
measures
;
i
++
)
{
if
(
(
measuresPeriods
[
i
]
<
measuresPeriods
[
i
-
1
]
*
1.1
)
&&
(
measuresPeriods
[
i
]
>
measuresPeriods
[
i
-
1
]
/
1.1
)
)
{
c
++
;
avPeriod
+=
measuresPeriods
[
i
];
avR
+=
measuresR
[
i
];
}
}
m
++
;
m
%=
measures
;
lcd
.
setCursor
(
12
,
0
);
lcd
.
print
(
String
(
c
)
+
" "
);
// bpm and R shown are calculated as the
// average of at least 5 good peaks
avBPM
=
60000
/
(
avPeriod
/
c
)
;
avR
=
avR
/
c
;
// if there are at last 5 measures
lcd
.
setCursor
(
12
,
1
);
if
(
c
==
0
)
lcd
.
print
(
" "
);
else
lcd
.
print
(
String
(
avR
)
+
" "
);
// if there are at least 5 good measures...
if
(
c
>
4
)
{
//
// SATURTION IS A FUNCTION OF R (calibration)
// Y = k*x + m
// k and m are calculated with another oximeter
int
SpO2
=
-
19
*
R
+
112
;
lcd
.
setCursor
(
4
,
0
);
if
(
avBPM
>
40
&&
avBPM
<
220
)
lcd
.
print
(
String
(
avBPM
)
+
" "
);
//else lcd.print("---");
lcd
.
setCursor
(
4
,
1
);
if
(
SpO2
>
70
&&
SpO2
<
150
)
lcd
.
print
(
" "
+
String
(
SpO2
)
+
"% "
);
//else lcd.print("--% ");
}
else
{
if
(
c
<
3
)
{
// if less then 2 measures add ?
lcd
.
setCursor
(
3
,
0
);
lcd
.
write
(
2
);
//bpm ?
lcd
.
setCursor
(
4
,
1
);
lcd
.
write
(
2
);
//SpO2 ?
}
}
}
}
else
{
// Ok, the curve is falling
rising
=
false
;
rise_count
=
0
;
lcd
.
setCursor
(
3
,
0
);
lcd
.
print
(
" "
);
}
// to compare it with the new value and find peaks
beforeIR
=
lastIR
;
}
// finger is inside
// PLOT everything
// Serial.print(lastIR);
//Serial.print(",");
//Serial.print(lastRED);
/*
* Serial.print(",");
Serial.print(R);
Serial.print(",");
Serial.print(IRmax);
Serial.print(",");
Serial.print(IRmin);
Serial.print(",");
Serial.print(REDmax);
Serial.print(",");
Serial.print(REDmin);
Serial.print(",");
Serial.print(avR);
Serial.print(",");
Serial.print(avBPM); */
if
(
finger_status
==
true
){
Serial
.
println
(
"SpO2 = "
);
Serial
.
println
(
SpO2
);
Serial
.
println
(
"BPM = "
);
Serial
.
println
(
avBPM
);
Serial
.
println
();
}
else
{
Serial
.
println
(
"No Finger"
);
}
if
(
60
<
avBPM
<
100
)
{
digitalWrite
(
9
,
HIGH
);
digitalWrite
(
13
,
LOW
);
}
else
{
digitalWrite
(
9
,
LOW
);
//Serial.print("MQ135 = ");Serial.println(sensorValue, DEC); // prints the value read
}
if
(
avBPM
>
120
)
{
digitalWrite
(
13
,
HIGH
);
digitalWrite
(
9
,
LOW
);
}
else
if
(
avBPM
<
40
)
{
digitalWrite
(
13
,
HIGH
);
digitalWrite
(
9
,
LOW
);
//Serial.print("MQ135 = ");Serial.println(sensorValue, DEC); // prints the value read
}
// considered best practice in a simple sketch.
// handle the arrays
ptr
++
;
ptr
%=
samp_siz
;
}
// loop while 1
delay
(
10000
);
}
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment