|
| 1 | +#include <Wire.h> |
| 2 | +#include "MAX30105.h" |
| 3 | +#include "spo2_algorithm.h" |
| 4 | + |
| 5 | +MAX30105 particleSensor; |
| 6 | + |
| 7 | +#define MAX_BRIGHTNESS 255 |
| 8 | + |
| 9 | +#if defined(__AVR_ATmega328P__) || defined(__AVR_ATmega168__) |
| 10 | + |
| 11 | +//Arduino Uno doesn't have enough SRAM to store 100 samples of IR led data and red led data in 32-bit format |
| 12 | +//To solve this problem, 16-bit MSB of the sampled data will be truncated. Samples become 16-bit data. |
| 13 | +uint16_t irBuffer[100]; //infrared LED sensor data |
| 14 | +uint16_t redBuffer[100]; //red LED sensor data |
| 15 | + |
| 16 | +#else |
| 17 | +uint32_t irBuffer[100]; //infrared LED sensor data |
| 18 | +uint32_t redBuffer[100]; //red LED sensor data |
| 19 | +#endif |
| 20 | + |
| 21 | +int32_t bufferLength; //data length |
| 22 | +int32_t spo2; //SPO2 value |
| 23 | +int8_t validSPO2; //indicator to show if the SPO2 calculation is valid |
| 24 | +int32_t heartRate; //heart rate value |
| 25 | +int8_t validHeartRate; //indicator to show if the heart rate calculation is valid |
| 26 | + |
| 27 | +byte pulseLED = 11; //Must be on PWM pin |
| 28 | +byte readLED = 13; //Blinks with each data read |
| 29 | + |
| 30 | +void setup() |
| 31 | +{ |
| 32 | + Serial.begin(115200); // initialize serial communication at 115200 bits per second: |
| 33 | + |
| 34 | + pinMode(pulseLED, OUTPUT); |
| 35 | + pinMode(readLED, OUTPUT); |
| 36 | + |
| 37 | + // Initialize sensor |
| 38 | + if (!particleSensor.begin(Wire, I2C_SPEED_FAST)) //Use default I2C port, 400kHz speed |
| 39 | + { |
| 40 | + Serial.println(F("MAX30105 was not found. Please check wiring/power.")); |
| 41 | + while (1); |
| 42 | + } |
| 43 | + |
| 44 | + Serial.println(F("0")); |
| 45 | + while (Serial.available() == 0) ; //wait until user presses a key |
| 46 | + Serial.read(); |
| 47 | + |
| 48 | + byte ledBrightness = 60; //Options: 0=Off to 255=50mA |
| 49 | + byte sampleAverage = 4; //Options: 1, 2, 4, 8, 16, 32 |
| 50 | + byte ledMode = 2; //Options: 1 = Red only, 2 = Red + IR, 3 = Red + IR + Green |
| 51 | + byte sampleRate = 100; //Options: 50, 100, 200, 400, 800, 1000, 1600, 3200 |
| 52 | + int pulseWidth = 411; //Options: 69, 118, 215, 411 |
| 53 | + int adcRange = 4096; //Options: 2048, 4096, 8192, 16384 |
| 54 | + |
| 55 | + particleSensor.setup(ledBrightness, sampleAverage, ledMode, sampleRate, pulseWidth, adcRange); //Configure sensor with these settings |
| 56 | +} |
| 57 | + |
| 58 | +void loop() |
| 59 | +{ |
| 60 | + bufferLength = 100; //buffer length of 100 stores 4 seconds of samples running at 25sps |
| 61 | + |
| 62 | + //read the first 100 samples, and determine the signal range |
| 63 | + for (byte i = 0 ; i < bufferLength ; i++) |
| 64 | + { |
| 65 | + while (particleSensor.available() == false) //do we have new data? |
| 66 | + particleSensor.check(); //Check the sensor for new data |
| 67 | + |
| 68 | + redBuffer[i] = particleSensor.getRed(); |
| 69 | + irBuffer[i] = particleSensor.getIR(); |
| 70 | + particleSensor.nextSample(); //We're finished with this sample so move to next sample |
| 71 | + |
| 72 | + Serial.print(F("red=")); |
| 73 | + Serial.print(redBuffer[i], DEC); |
| 74 | + Serial.print(F(", ir=")); |
| 75 | + Serial.println(irBuffer[i], DEC); |
| 76 | + } |
| 77 | + |
| 78 | + //calculate heart rate and SpO2 after first 100 samples (first 4 seconds of samples) |
| 79 | + maxim_heart_rate_and_oxygen_saturation(irBuffer, bufferLength, redBuffer, &spo2, &validSPO2, &heartRate, &validHeartRate); |
| 80 | + |
| 81 | + //Continuously taking samples from MAX30102. Heart rate and SpO2 are calculated every 1 second |
| 82 | + while (1) |
| 83 | + { |
| 84 | + //dumping the first 25 sets of samples in the memory and shift the last 75 sets of samples to the top |
| 85 | + for (byte i = 25; i < 100; i++) |
| 86 | + { |
| 87 | + redBuffer[i - 25] = redBuffer[i]; |
| 88 | + irBuffer[i - 25] = irBuffer[i]; |
| 89 | + } |
| 90 | + |
| 91 | + //take 25 sets of samples before calculating the heart rate. |
| 92 | + for (byte i = 75; i < 100; i++) |
| 93 | + { |
| 94 | + while (particleSensor.available() == false) //do we have new data? |
| 95 | + particleSensor.check(); //Check the sensor for new data |
| 96 | + |
| 97 | + digitalWrite(readLED, !digitalRead(readLED)); //Blink onboard LED with every data read |
| 98 | + |
| 99 | + redBuffer[i] = particleSensor.getRed(); |
| 100 | + irBuffer[i] = particleSensor.getIR(); |
| 101 | + particleSensor.nextSample(); //We're finished with this sample so move to next sample |
| 102 | + |
| 103 | + //send samples and calculation result to terminal program through UART |
| 104 | + Serial.print(F("red=")); |
| 105 | + Serial.print(redBuffer[i], DEC); |
| 106 | + Serial.print(F(", ir=")); |
| 107 | + Serial.print(irBuffer[i], DEC); |
| 108 | + |
| 109 | + Serial.print(F(", HR=")); |
| 110 | + Serial.print(heartRate, DEC); |
| 111 | + |
| 112 | + Serial.print(F(", HRvalid=")); |
| 113 | + Serial.print(validHeartRate, DEC); |
| 114 | + |
| 115 | + Serial.print(F(", SPO2=")); |
| 116 | + Serial.print(spo2, DEC); |
| 117 | + |
| 118 | + Serial.print(F(", SPO2Valid=")); |
| 119 | + Serial.println(validSPO2, DEC); |
| 120 | + } |
| 121 | + |
| 122 | + //After gathering 25 new samples recalculate HR and SP02 |
| 123 | + maxim_heart_rate_and_oxygen_saturation(irBuffer, bufferLength, redBuffer, &spo2, &validSPO2, &heartRate, &validHeartRate); |
| 124 | + } |
| 125 | +} |
0 commit comments