Defining a data structure for multiple sensors to read at one go

Hello All,
My query is a bit straight forward.
I have multiple sensors (MPU, GPS, Pressure, Heart rate sensor) and I am accessing them from different fucntions.

Now, I want all the sensors to combine in a data structure and read the data from different sensors all at once.

Below is the code where I have written seperate sensor function in loop and reading them one at a time.

#include <TinyGPS++.h>
#include <SoftwareSerial.h>
#include <Wire.h>
#include <SimpleTimer.h>
#include "MAX30100_PulseOximeter.h"

#define REPORTING_PERIOD_MS     500
PulseOximeter pox;

const int MPU_addr = 0x68; // I2C address of the MPU-6050
int16_t AcX, AcY, AcZ, Tmp, GyX, GyY, GyZ;

SimpleTimer timer;

static const int RXPin = 4, TXPin = 3;
static const uint32_t GPSBaud = 9600;

// The TinyGPS++ object
TinyGPSPlus gps;

// The serial connection to the GPS device
SoftwareSerial GPS(RXPin, TXPin);

int fsrPin = A0;     // the FSR and 10K pulldown are connected to a0
int fsrReading;     // the analog reading from the FSR resistor divider

const int numReadings=10;
float filterweight=0.5;
uint32_t tsLastReport = 0;
uint32_t last_beat=0;
int readIndex=0;
int average_beat=0;
int average_SpO2=0;
bool calculation_complete=false;
bool calculating=false;
bool initialized=false;
byte beat=0;

void setup() {

  Serial.begin(9600);
  GPS.begin(GPSBaud);
  pox.begin();
  pox.setOnBeatDetectedCallback(onBeatDetected);   
  initial_display();
  
}

void loop() {
  // put your main code here, to run repeatedly:
GPSfunc();
Pressurefunc();
MPUfunc();
Heartratefunc();
}

void GPSfunc(){
  while (GPS.available() > 0){
    gps.encode(GPS.read());
    if (gps.location.isUpdated()){
      // Latitude in degrees (double)
      Serial.print("Latitude= "); 
      Serial.print(gps.location.lat(), 6);      
      // Longitude in degrees (double)
      Serial.print(" Longitude= "); 
      Serial.println(gps.location.lng(), 6); 
    
      // Year (2000+) (u16)
      Serial.print("Year = "); 
      Serial.println(gps.date.year()); 
      // Month (1-12) (u8)
      Serial.print("Month = "); 
      Serial.println(gps.date.month()); 
      // Day (1-31) (u8)
      Serial.print("Day = "); 
      Serial.println(gps.date.day()); 

      // Raw time in HHMMSSCC format (u32)
      Serial.print("Raw time in HHMMSSCC = "); 
      Serial.println(gps.time.value()); 

      
    }
  }
}

void Pressurefunc(){
  fsrReading = analogRead(fsrPin);
  Serial.print("Analog reading = ");
  Serial.print(fsrReading);     // the raw analog reading
  
 
}


void GetValues()
{
  Wire.beginTransmission(MPU_addr);
  Wire.write(0x3B);  // starting with register 0x3B (ACCEL_XOUT_H)
  Wire.endTransmission(false);
  Wire.requestFrom(MPU_addr, 14, true); // request a total of 14 registers

  AcX = Wire.read() << 8 | Wire.read(); // 0x3B (ACCEL_XOUT_H) & 0x3C (ACCEL_XOUT_L)
  AcY = Wire.read() << 8 | Wire.read(); // 0x3D (ACCEL_YOUT_H) & 0x3E (ACCEL_YOUT_L)
  AcZ = Wire.read() << 8 | Wire.read(); // 0x3F (ACCEL_ZOUT_H) & 0x40 (ACCEL_ZOUT_L)
  Tmp = Wire.read() << 8 | Wire.read(); // 0x41 (TEMP_OUT_H) & 0x42 (TEMP_OUT_L)
  GyX = Wire.read() << 8 | Wire.read(); // 0x43 (GYRO_XOUT_H) & 0x44 (GYRO_XOUT_L)
  GyY = Wire.read() << 8 | Wire.read(); // 0x45 (GYRO_YOUT_H) & 0x46 (GYRO_YOUT_L)
  GyZ = Wire.read() << 8 | Wire.read(); // 0x47 (GYRO_ZOUT_H) & 0x48 (GYRO_ZOUT_L)
  
}

void MPUfunc(){
  Wire.begin();
  Wire.beginTransmission(MPU_addr);
  Wire.write(0x6B);  // PWR_MGMT_1 register
  Wire.write(0);     // set to zero (wakes up the MPU-6050)
  Wire.endTransmission(true);

  timer.setInterval(200L, GetValues);

  timer.run(); //to loop the reading
  }

void onBeatDetected()
{
//  show_beat();
  last_beat=millis();
}

void display_calculating(int j)
{
  if (not calculating) {
      calculating=true;
    initialized=false;
  }
  Serial.print(". ");
}
void display_values()
{
  Serial.println("");
  Serial.print(average_beat);
  Serial.println(" Bpm");
  Serial.print("SpO2 ");
  Serial.print(average_SpO2);
  Serial.println("%"); 
}

void initial_display() 
{
  if (not initialized) 
  {
    Serial.print("Place finger on the sensor");  
    initialized=true;
  }
}

void calculate_average(int beat, int SpO2) 
{
  if (readIndex==numReadings) {
    calculation_complete=true;
    calculating=false;
    initialized=false;
    readIndex=0;
    display_values();
  }
  
  if (not calculation_complete and beat>30 and beat<220 and SpO2>50) {
    average_beat = filterweight * (beat) + (1 - filterweight ) * average_beat;
    average_SpO2 = filterweight * (SpO2) + (1 - filterweight ) * average_SpO2;
    readIndex++;
    display_calculating(readIndex);
  }
}

void Heartratefunc(){
  pox.update();
  if ((millis() - tsLastReport > REPORTING_PERIOD_MS) and (not calculation_complete)) {
        calculate_average(pox.getHeartRate(),pox.getSpO2());
        tsLastReport = millis();
    }
    if ((millis()-last_beat>10000)) {
      calculation_complete=false;
      average_beat=0;
      average_SpO2=0;
      initial_display();
    }
}
]

Now, I want to read all the sensor data al at once and compute for next level of processing (kalman computation)

Here is the structure I have declared.

#define SENSORMAX 100
typedef short int16;
typedef struct sensorData {
int16 accelX;
int16 accelY;
int16 accelZ;
int16 gyrpX;
int16 gyroY;
int16 gyroZ;
float temperature;
float lat;
float long;
float heartrate;
float pressure;
} SENSORDATA;

SENSORDATA sensorFusion[SENSORMAX];
int  currIndex = 0;   //Current index into sensorFusion
int  dataCount = 0;  //Number of valid sensor data in sensorFusion

So, how can I pass the serial data to the struct type variable so that I can read the data elements all at once?

Please Help!

I presume that you know how to access each data element of the struct by using structName.dataElementName

How are you receiving the data to be stored ?
You mention Serial but the code snippet has nothing in it relating to serial input or reading any sensors

A complete sketch would make it easier to provide help

Thank you for your reply..
In the first code snippet, I am directly reading the sensor values and printing them on the serial monitor.

In the second case, I created a struct and want to store the sensor values in the struct datatype variable from different sensors. I am unable to do that..(some people are also using memcpy for that)

To make things clear..

MPU is I2C interface and the Axx and Gyro values are read and written on serial monitor

GPS is Neo6m with TinyGPS++ (printing the lat and long and priting them on serial monitor, using software serial in this case for Tx and Rx at 3 & 4)

Pressure sensor interfaced to A0 pin and printing the value on serial monitor

Heart rate sensor is I2C interface..reading teh heart beat and prinintg it over serial monitor..

Also, I am using a hardware serial for Bluetooth at pins 0 & 1 to send the same serial data over bluetooth..

So now, I want a single data structure for all the above sensors and print it over serial monitor at a single go...

Turns out, as per my calculation , for each iteration in loop, around 40 bytes of data must be written. So the array index SENSORMAX is I chose is 100 for that reason.

~40 bytes is divided as below

Axx X,Y,Z, Gyro X,Y,Z, are all int16 - 12 bytes, float Temperature - 4 bytes - 16 bytes total

GPS - 8 bytes (float lat and float long)

Pressure - float pressure(4 bytes)

Heart rate - float heart rate (4 bytes)

Can you rewrite the code using struct..

Thanks in Advance!

Could anyone please help me..I am really confused at this point!

UKHeliBob..Yes I know how to access a data element from a structure...!

Consider the following pseudo code:

SENSORDATA data_packet;

void loop()
{
   read_sensor1(); //we want to fill data at index 0
   read_sensor2(); //we want to fill data starting at index 6
}

void read_sensor1()
{
   //fill data from sensor1 at start_index here;
   data_packet.accelX = ...;
   data_packet.accelY = ...;
   ...
}

voi read_sensor2()
{
   //filll data
   data_packet.temperature = ...;
   data_packet.lat = ...;
   data_packet.long = ...;
}

Code edited.

MachineLearner:
UKHeliBob..Yes I know how to access a data element from a structure...!

So instead of

 AcX = Wire.read() << 8 | Wire.read(); // 0x3B (ACCEL_XOUT_H) & 0x3C (ACCEL_XOUT_L)

why not do

  theStruct.AcX = Wire.read() << 8 | Wire.read(); // 0x3B (ACCEL_XOUT_H) & 0x3C (ACCEL_XOUT_L)

instead

Once the data is in the struct you will still need to write code to output each of its elements separately by name. There is no magic "print the struct" command available to you.

Thanks UKHeliBob and Ard_NEW for your comments...I got it!..