// Custom chips playground
// See https://link.wokwi.com/custom-chips-alpha for more info

#include <Adafruit_GFX.h>        // OLED Library
#include <Adafruit_SSD1306.h>    // OLED Library
#include <Wire.h>                // I2C  Library
#include "MAX30105.h"            // MAX3010x library
#include "heartRate.h"           // Heart rate calculating algorithm


MAX30105 particleSensor;

const byte RATE_SIZE = 4;        // Increase this for more averaging. 4 is good.
byte rates[RATE_SIZE];           // Array of heart rates
byte rateSpot = 0;
long lastBeat = 0;               // Time at which the last beat occurred
float beatsPerMinute;
int beatAvg;
const int LM35_PIN = 35;

#define SCREEN_WIDTH 128         // OLED display width, in pixels
#define SCREEN_HEIGHT 64         // OLED display height, in pixels
#define OLED_RESET    -1         // Reset pin # (or -1 if sharing Arduino reset pin)

Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET); //Declaring the display name (display)



void setup() {
  Serial.begin(115200);
  Wire.setClock(400000);                         // Set I2C speed to 400kHz
  display.begin(SSD1306_SWITCHCAPVCC, 0x3C);     // Start the OLED display
  display.setTextColor(WHITE);

  // Initialize sensor
  particleSensor.begin(Wire, I2C_SPEED_FAST);    // Use default I2C port, 400kHz speed
  particleSensor.setup();                        // Configure sensor with default settings
  particleSensor.setPulseAmplitudeRed(0x0A);     // Turn Red LED to low to indicate sensor is running


}

void loop() {

  int sensorValue = analogRead(LM35_PIN); // Lecture de la valeur analogique du capteur
  float voltage = sensorValue * (3.3 / 4095.0); // Conversion de la valeur analogique en tension (pour ESP32, la plage de valeurs analogiques est de 0 à 4095 pour une tension de 0 à 3.3V)
  float temperature  = voltage * 100.0; // La tension du LM35 est de 10mV/°C (0.01V/°C)
  long irValue = particleSensor.getIR();   
  long redValue = particleSensor.getRed();    

    float SpO2 = calculateSpO2(irValue, redValue);
          // Reading the IR value it will permit us to know if there's a finger on the sensor or not
    
  if (irValue > 50000)
  {

    if (checkForBeat(irValue) == true)                  //If a heart beat is detected, call checkForBeat as frequent as possible to get accurate value
    {
      long delta = millis() - lastBeat;                 //Measure duration between two beats
      lastBeat = millis();
      beatsPerMinute = 60 / (delta / 1000.0);           //Calculating the BPM
      if (beatsPerMinute < 255 && beatsPerMinute > 20)  //To calculate the average we strore some values (4) then do some math to calculate the average
      {
        rates[rateSpot++] = (byte)beatsPerMinute;       //Store this reading in the array
        rateSpot %= RATE_SIZE;                          //Wrap variable

        //Take average of readings
        beatAvg = 0;
        for (byte x = 0 ; x < RATE_SIZE ; x++)
          beatAvg += rates[x];
        beatAvg /= RATE_SIZE;
      }

        Serial.print("BPM:");
        Serial.print(beatAvg);
        
        Serial.print("SpO2:");
        Serial.print(SpO2);
        
        Serial.print("Temp:");
        Serial.print(temperature);
        
        display.clearDisplay();
        display.setTextSize(1);
        display.setCursor(0, 0);
        display.print("temp:");
        display.print(temperature);
        display.display();

        /*
        display.setCursor(0, 45);
        display.setTextSize(1);
        display.print("SpO2 :");
        display.print(SpO2);

        display.setCursor(0, 60);
        display.setTextSize(1);
        display.print("temp :");
        display.print(temperature);

        display.display();
        */
       
      
        /*
         display.setCursor(0, 20);
         display.print("SpO2 :");
        display.print(SpO2);
        display.setCursor(0, 45);
         display.print("Temp :");
        display.print(temperature);
        display.display();
        */
        
      }
    }
  }

     float calculateSpO2 (float irValue, float redValue) {
  // Placeholder calculation - You'll need a proper algorithm for accurate SpO2 calculation
  // This is a simple placeholder to illustrate the concept
  float ratio = redValue / irValue;
  float SpO2 = 100 - 17 * ratio; // This is a simplified calculation

  return SpO2;
     }
  /*
  else
  {
   display.clearDisplay();
    display.setTextSize(3);
    display.setCursor(0, 20);
    display.print("BPM:");
    display.print(0);
    display.setCursor(0, 45);
    display.setTextSize(1);
    display.print("Place your finger in sensor and wait..");
    display.display();
  }
}
*/
LM35Breakout
Oximeter MAX30102Breakout