How to create a struct for MAX30102 and ML90614

Hello!

I have two separate codes for my MLX90614 and MAX30102, but I want to create a global structure to store and transfer their data simultaneously. I'd like to ask assistance on how to do it as I am still not that very good at programming, I'd be very grateful.

ML90614 Code:

#include <Adafruit_MLX90614.h>

Adafruit_MLX90614 mlx = Adafruit_MLX90614();
float temp;

void setup() 
{
  Serial.begin(115200);
  while (!Serial);
  Serial.println("Adafruit MLX90614 test");
  if (!mlx.begin()) 
  {
    Serial.println("Error connecting to MLX sensor. Check wiring.");
    while (1);
  }
}

void loop() 
{
  // MLX90614
  temp = mlx.readObjectTempC();
  Serial.println("MLX90614 = "); 
  Serial.print(temp); 
  Serial.println("\xC2\xB0 C"); // display the degree symbol in the serial monitor
  delay(1000);
}

MAX30102 Code:

#include <Wire.h>
#include "MAX30105.h"    // sparkfun MAX3010X library
MAX30105 particleSensor;
#include "arduinoFFT.h" //FFT library
arduinoFFT FFT;

double avered       = 0; 
double aveir        = 0;
double sumirrms     = 0;
double sumredrms    = 0;
int    i            = 0;
int    Num          = 100;  // calculate SpO2 by this sampling interval
float  ESpO2;               // initial value of estimated SpO2
double FSpO2        = 0.7;  // filter factor for estimated SpO2
double frate        = 0.95; // low pass filter for IR/red LED value to eliminate AC component
#define TIMETOBOOT    3000  // wait for this time(msec) to output SpO2
#define SCALE         88.0  // adjust to display heart beat and SpO2 in the same scale
#define SAMPLING      100   //25 //5     // if you want to see heart beat more precisely, set SAMPLING to 1
#define FINGER_ON     30000 // if red signal is lower than this, it indicates your finger is not on the sensor
#define USEFIFO
#define PULSE_SAMPLES 256
#define SAMPLE_FREQ   50

// --- For Heart Rate ---
byte   rateSpot         = 0;
long   lastBeat         = 0;  // Time at which the last beat occurred
int    beatAvg          = 0;
bool   detect_high      = 0;
// ----------------------

double redArray[PULSE_SAMPLES]; // array to store samples from the sensor
double vReal[PULSE_SAMPLES];
double vImag[PULSE_SAMPLES];
double beatsPerMinute = 0;

void setup()
{
   Serial.begin(115200);
   Serial.setDebugOutput(true);
   Serial.println();
   Serial.println("Running...");
   delay(1000);

   // Initialize sensor
   while (!particleSensor.begin(Wire, I2C_SPEED_FAST)) //Use default I2C port, 400kHz speed
   {
      Serial.println("MAX30102 was not found. Please check wiring/power/solder jumper at MH-ET LIVE MAX30102 board. ");
      //while (1);
   }

   //Setup to sense a nice looking saw tooth on the plotter
   byte ledBrightness = 0x7F;  // Options: 0=Off to 255=50mA
   byte sampleAverage = 4;     // Options: 1, 2, 4, 8, 16, 32
   byte ledMode       = 2;     // Options: 1 = Red only, 2 = Red + IR, 3 = Red + IR + Green
   //Options: 1 = IR only, 2 = Red + IR on MH-ET LIVE MAX30102 board
   int sampleRate     = 200;   // Options: 50, 100, 200, 400, 800, 1000, 1600, 3200
   int pulseWidth     = 411;   // Options: 69, 118, 215, 411
   int adcRange       = 16384; // Options: 2048, 4096, 8192, 16384
  
   // Set up the wanted parameters
   particleSensor.setup(ledBrightness, sampleAverage, ledMode, sampleRate, pulseWidth, adcRange); //Configure sensor with these settings
   particleSensor.enableDIETEMPRDY();
}

void loop() //For Heart Rate
{   
   uint32_t ir, red, green;
   double fred, fir;
   double SpO2 = 0; //raw SpO2 before low pass filtered
   float red_beat = 0;
   
#ifdef USEFIFO
   particleSensor.check();               // Check the sensor, read up to 3 samples

   while (particleSensor.available()) 
   {  // Do we have new data
#ifdef MAX30105
      red = particleSensor.getFIFORed(); // Sparkfun's MAX30105
      ir  = particleSensor.getFIFOIR();  // Sparkfun's MAX30105
#else
      red = particleSensor.getFIFOIR();  // why getFOFOIR output Red data by MAX30102 on MH-ET LIVE breakout board
      ir  = particleSensor.getFIFORed(); // why getFIFORed output IR data by MAX30102 on MH-ET LIVE breakout board
#endif

      i++;
      i = i % PULSE_SAMPLES; // wrap around every 256 samples
      fred = (double)red;
      fir  = (double)ir;
      redArray[i] = fred; // populate the array
      avered = avered * frate + (double)red * (1.0 - frate); //average red level by low pass filter
      aveir = aveir * frate + (double)ir * (1.0 - frate); //average IR level by low pass filter
      sumredrms += (fred - avered) * (fred - avered); //square sum of alternate component of red level
      sumirrms += (fir - aveir) * (fir - aveir);//square sum of alternate component of IR level

      particleSensor.nextSample(); // We're finished with this sample so move to next sample
     
      if ((i == 0) && ((i % SAMPLING) == 0)) 
      {
        for (int idx=0; idx < PULSE_SAMPLES; idx++)
         {
            vReal[idx] = redArray[idx];
            vImag[idx] = 0.0;

            //Serial.println(redArray[idx]);
         }

         FFT = arduinoFFT(vReal, vImag, PULSE_SAMPLES, SAMPLE_FREQ); /* Create FFT object */
         FFT.Windowing(FFT_WIN_TYP_HAMMING, FFT_FORWARD); /* Weigh data */
         FFT.Compute(FFT_FORWARD); /* Compute FFT */
         FFT.ComplexToMagnitude(); /* Compute magnitudes */

         double peak = FFT.MajorPeak();

         // print in beats per minute
         beatsPerMinute = peak * 60;

         if ( millis() > TIMETOBOOT) {
          float ir_forGraph = (2.0 * fir - aveir) / aveir * SCALE;
          float red_forGraph = (2.0 * fred - avered) / avered * SCALE;
          //truncation for Serial plotter's autoscaling
          if ( ir_forGraph > 100.0) ir_forGraph = 100.0;
          if ( ir_forGraph < 80.0) ir_forGraph = 80.0;
          if ( red_forGraph > 100.0 ) red_forGraph = 100.0;
          if ( red_forGraph < 80.0 ) red_forGraph = 80.0;
          // Print out red and IR sensor reading to serial interface for monitoring...
          //Serial.print("Red: "); Serial.print(red); Serial.print(","); Serial.print("Infrared: "); Serial.print(ir); Serial.print(".    ");
          float temperature = particleSensor.readTemperatureF();
          }
         if (ir < FINGER_ON) // no finger on the sensor
         {
           Serial.println("No finger detected");
           break;
          }
          if(ir > FINGER_ON)
         {
           Serial.print("SpO2: ");
           Serial.print(ESpO2);
           Serial.println("%");
           Serial.print("BPM: ");
           Serial.println(beatsPerMinute);
          }     
        if ((i % Num) == 0) {
        double R = (sqrt(sumredrms)/avered) / (sqrt(sumirrms) / aveir);
         // Serial.println(R);
        SpO2 = -23.3 * (R - 0.4) + 100; //http://ww1.microchip.com/downloads/jp/AppNotes/00001525B_JP.pdf -- I don't see this directly in the App Note... look here https://github.com/espressif/arduino-esp32/issues/4561
        ESpO2 = FSpO2 * ESpO2 + (1.0 - FSpO2) * SpO2;//low pass filter
        //  Serial.print(SpO2);Serial.print(",");Serial.println(ESpO2);
        sumredrms = 0.0; sumirrms = 0.0; i = 0;
        break;
        }
      }
    }
#endif

}

Hello spiderhorse01

Take a view here to gain the knowledge:

https://www.learncpp.com/cpp-tutorial/introduction-to-structs-members-and-member-selection/

Have a nice day and enjoy coding in C++.

1 Like

this doesn't sound like a data structure issue

since you're reading a temperature from both devices, do you want a program where both devices are used at the same time or a program either device can be used to read temperature?

Hello,

I'll be using the MLX90614 for reading the temperature. I have already removed lines of the MAX30102 collecting temperature data. My goal is to simply use the MAX30102 to collect SpO2 and Heart Rate.

why do you think this is a structure issue?

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.