Skip to content

Commit

Permalink
Reorganized settable parameters and fixed minor bugs.
Browse files Browse the repository at this point in the history
Placed all crucial and adjustable parameters in a single spot in
algorithm_by_RF.h. Changing sampling frequency and/or sampling time
should now be more straightforward. Changed the type of “i” index in
RD117_ARDUINO.ino in anticipation of higher sampling rates.
  • Loading branch information
aromring committed May 24, 2018
1 parent e34e194 commit 8c87c6b
Show file tree
Hide file tree
Showing 3 changed files with 40 additions and 19 deletions.
14 changes: 7 additions & 7 deletions RD117_ARDUINO.ino
Original file line number Diff line number Diff line change
Expand Up @@ -142,7 +142,7 @@ void setup() {
dataFile.print(F("Time[s]\tSpO2\tHR\tClock\tRatio\tCorr"));
#endif
#ifdef SAVE_RAW_DATA
int8_t i;
int32_t i;
// These are headers for the red signal
for(i=0;i<BUFFER_SIZE;++i) {
dataFile.print("\t");
Expand All @@ -158,17 +158,17 @@ void setup() {
timeStart=millis();
}

//Continuously taking samples from MAX30102. Heart rate and SpO2 are calculated every 4 seconds
//Continuously taking samples from MAX30102. Heart rate and SpO2 are calculated every ST seconds
void loop() {
float n_spo2,ratio,correl; //SPO2 value
int8_t ch_spo2_valid; //indicator to show if the SPO2 calculation is valid
int32_t n_heart_rate; //heart rate value
int8_t ch_hr_valid; //indicator to show if the heart rate calculation is valid
int8_t i;
int32_t i;
char hr_str[10];

//buffer length of 100 stores 4 seconds of samples running at 25sps
//read 100 samples, and determine the signal range
//buffer length of BUFFER_SIZE stores ST seconds of samples running at FS sps
//read BUFFER_SIZE samples, and determine the signal range
for(i=0;i<BUFFER_SIZE;i++)
{
while(digitalRead(oxiInt)==1); //wait until the interrupt pin asserts
Expand All @@ -183,7 +183,7 @@ void loop() {
#endif
}

//calculate heart rate and SpO2 after 100 samples (4 seconds of samples) using Robert's method
//calculate heart rate and SpO2 after BUFFER_SIZE samples (ST seconds of samples) using Robert's method
rf_heart_rate_and_oxygen_saturation(aun_ir_buffer, BUFFER_SIZE, aun_red_buffer, &n_spo2, &ch_spo2_valid, &n_heart_rate, &ch_hr_valid, &ratio, &correl);
elapsedTime=millis()-timeStart;
millis_to_hours(elapsedTime,hr_str); // Time in hh:mm:ss format
Expand All @@ -202,7 +202,7 @@ void loop() {
#endif

#ifdef TEST_MAXIM_ALGORITHM
//calculate heart rate and SpO2 after 100 samples (4 seconds of samples) using MAXIM's method
//calculate heart rate and SpO2 after BUFFER_SIZE samples (ST seconds of samples) using MAXIM's method
float n_spo2_maxim; //SPO2 value
int8_t ch_spo2_valid_maxim; //indicator to show if the SPO2 calculation is valid
int32_t n_heart_rate_maxim; //heart rate value
Expand Down
2 changes: 1 addition & 1 deletion algorithm_by_RF.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ void rf_heart_rate_and_oxygen_saturation(uint32_t *pun_ir_buffer, int32_t n_ir_b
*/
{
int32_t k;
static int32_t n_last_peak_interval=FS; // Initialize it to 25, which corresponds to heart rate of 60 bps, RF
static int32_t n_last_peak_interval=INIT_INTERVAL;
float f_ir_mean,f_red_mean,f_ir_sumsq,f_red_sumsq;
float f_y_ac, f_x_ac, xy_ratio;
float beta_ir, beta_red, x;
Expand Down
43 changes: 32 additions & 11 deletions algorithm_by_RF.h
Original file line number Diff line number Diff line change
Expand Up @@ -35,24 +35,45 @@
#define ALGORITHM_BY_RF_H_
#include <arduino.h>

#define FS 25 //sampling frequency
#define BUFFER_SIZE (FS*4)
#define FS60 (FS*60) // Conversion factor for heart rate
#define MAX_HR 125 // Maximal heart rate
#define MIN_HR 40 // Minimal heart rate

const int32_t LOWEST_PERIOD = FS60/MAX_HR; // Minimal distance between peaks
const int32_t HIGHEST_PERIOD = FS60/MIN_HR; // Maximal distance between peaks
// RF: Sum of squares of numbers from 0 to 99, inclusively, centered around the 49.5 mean
const float sum_X2 = 83325;
const float mean_X = (float)(BUFFER_SIZE-1)/2.0; // 49.5
/*
* Settable parameters
* Leave these alone if your circuit and hardware setup match the defaults
* described in this code's Instructable. Typically, different sampling rate
* and/or sample length would require these paramteres to be adjusted.
*/
#define ST 4 // Sampling time in s. WARNING: if you change ST, then you MUST recalcuate the sum_X2 parameter below!
#define FS 25 // Sampling frequency in Hz. WARNING: if you change FS, then you MUST recalcuate the sum_X2 parameter below!
// Sum of squares of ST*FS numbers from -mean_X (see below) to +mean_X incremented be one. For example, given ST=4 and FS=25,
// the sum consists of 100 terms: (-49.5)^2 + (-48.5)^2 + (-47.5)^2 + ... + (47.5)^2 + (48.5)^2 + (49.5)^2
// The sum is symmetrc, so you can evaluate it by multiplying its positive half by 2. It is precalcuated here for enhanced
// performance.
const float sum_X2 = 83325; // WARNING: you MUST recalculate this sum if you changed either ST or FS above!
#define MAX_HR 125 // Maximal heart rate. To eliminate erroneous signals, calculated HR should never be greater than this number.
#define MIN_HR 40 // Minimal heart rate. To eliminate erroneous signals, calculated HR should never be lower than this number.
// Typical heart rate. Set it to the upper value of the expected heart rate range in a given application. Obviously, it must be
// in between MIN_HR and MAX_HR. For example, if HR in an overnight measurement varies between 46 and 65, but 90% of the time
// stays between 50 and 60, then set it to 60.
// WARNING: This is a CRUCIAL parameter! Proper HR evaluation depends on it.
#define TYPICAL_HR 60
// Minimal ratio of two autocorrelation sequence elements: one at a considered lag to the one at lag 0.
// Good quality signals must have such ratio greater than this minimum.
const float min_autocorrelation_ratio = 0.5;
// Pearson correlation between red and IR signals.
// Good quality signals must have their correlation coefficient greater than this minimum.
const float min_pearson_correlation = 0.8;

/*
* Derived parameters
* Do not touch these!
*
*/
const int32_t BUFFER_SIZE = FS*ST; // Number of smaples in a single batch
const int32_t FS60 = FS*60; // Conversion factor for heart rate from bps to bpm
const int32_t LOWEST_PERIOD = FS60/MAX_HR; // Minimal distance between peaks
const int32_t HIGHEST_PERIOD = FS60/MIN_HR; // Maximal distance between peaks
const int32_t INIT_INTERVAL = FS60/TYPICAL_HR; // Seed value for heart rate determination routine
const float mean_X = (float)(BUFFER_SIZE-1)/2.0; // Mean value of the set of integers from 0 to BUFFER_SIZE-1. For ST=4 and FS=25 it's equal to 49.5.

void rf_heart_rate_and_oxygen_saturation(uint32_t *pun_ir_buffer, int32_t n_ir_buffer_length, uint32_t *pun_red_buffer, float *pn_spo2, int8_t *pch_spo2_valid, int32_t *pn_heart_rate,
int8_t *pch_hr_valid, float *ratio, float *correl);
float rf_linear_regression_beta(float *pn_x, float xmean, float sum_x2);
Expand Down

0 comments on commit 8c87c6b

Please sign in to comment.