Logging data to SD card on RedBoard ESP32 IoT

I’m collecting data from two 6DoF IMUs using the ESP32 IoT Redboard and a Qwiic I2C MUX (ports 0 & 1).

I can view the data in the serial monitor but I’m not able to log it to the on-board SD card. I was previously able to create a file and write “Hello World” to it, so I know the card is formatted correctly and the problem is with my code, which I developed by resourcing a datalogging example and combining it with what I already having working.

#include <Wire.h>
#include "SparkFun_ISM330DHCX.h"
#include "FS.h"
#include "SD.h"
#include "SPI.h"

SparkFun_ISM330DHCX myISM;

#define NUMBER_OF_SENSORS 2

// For Datalogging to SD Card
const int chipSelect = 5;

// Structs for X,Y,Z data
sfe_ism_data_t accelData;
sfe_ism_data_t gyroData;



void setup()
{
  Serial.begin(115200);
  Serial.println("Qwiic Mux Shield Read Example - Trevor's Edit v08");

  // Datalogger Setup

  Serial.print("Initializing SD card...");

  // see if the card is present and can be initialized:
  if (!SD.begin(chipSelect)) {
    Serial.println("Card failed, or not present");
    // don't do anything more:
    while (1);
  }
  Serial.println("card initialized.");

  Wire.begin();

  //Initialize all the sensors
  for (byte x = 0 ; x < NUMBER_OF_SENSORS ; x++)
  {
    enableMuxPort(x); //Tell mux to connect to port X
     if (!myISM.begin()) {
    Serial.println("Did not begin.");
    while (1)
      ;
  }

  // Reset the device to default settings. This if helpful is you're doing multiple
  // uploads testing different settings.
  myISM.deviceReset();

  // Wait for it to finish reseting
  while (!myISM.getDeviceReset()) {
    delay(1);
  }

  Serial.println("Reset.");
  Serial.println("Applying settings.");
  delay(100);

  myISM.setDeviceConfig();
  myISM.setBlockDataUpdate();

  // Set the output data rate and precision of the accelerometer
  myISM.setAccelDataRate(ISM_XL_ODR_416Hz);
  myISM.setAccelFullScale(ISM_2g);

  // Set the output data rate and precision of the gyroscope
  myISM.setGyroDataRate(ISM_GY_ODR_416Hz);
  myISM.setGyroFullScale(ISM_125dps);

  // Turn on the accelerometer's filter and apply settings.
  myISM.setAccelFilterLP2();
  myISM.setAccelSlopeFilter(ISM_LP_ODR_DIV_100);

  // Turn on the gyroscope's filter and apply settings.
  myISM.setGyroFilterLP1();
  myISM.setGyroLP1Bandwidth(ISM_XTREME);
    disableMuxPort(x);
  }

  Serial.println("Mux Shield online");

}

void loop()
{
  // make a string for assembling the data to log:
  String dataString = "";

  // read sensors and append to the string: 
  for (byte x = 0 ; x < NUMBER_OF_SENSORS ; x++)
  {
    int sensor = analogRead(x);
    dataString += String(sensor);
    if (x < 2) {
      dataString += ",";
  }

  char fileName[] = "datalogger.txt";
   
  // open the file. note that only one file can be open at a time,
  // so you have to close this one before opening another.
  File dataFile = SD.open("datalogger.txt", FILE_WRITE);  
  
  // if the file is available, write to it:
  if (dataFile) {
    dataFile.println(dataString);
    dataFile.close();
    // print to the serial port too:
    Serial.println(dataString);
  }
  
  // if the file isn't open, pop up an error:
  else {
    Serial.println("error opening datalogger.txt");
  }

  enableMuxPort(x); //Tell mux to connect to this port, and this port only

    if (myISM.checkStatus()) {
    myISM.getAccel(&accelData);
    myISM.getGyro(&gyroData);
    Serial.print(x);
    Serial.print(" ");
    Serial.print("Accelerometer: ");
    Serial.print("X: ");
    Serial.print(accelData.xData);
    Serial.print(" ");
    Serial.print("Y: ");
    Serial.print(accelData.yData);
    Serial.print(" ");
    Serial.print("Z: ");
    Serial.print(accelData.zData);
    Serial.println(" ");
    Serial.print(x);
    Serial.print(" ");
    Serial.print("Gyroscope: ");
    Serial.print("X: ");
    Serial.print(gyroData.xData);
    Serial.print(" ");
    Serial.print("Y: ");
    Serial.print(gyroData.yData);
    Serial.print(" ");
    Serial.print("Z: ");
    Serial.print(gyroData.zData);
    Serial.println(" ");
  }
    disableMuxPort(x); //Tell mux to disconnect from this port
  }

  delay(1000); //Wait for next reading
}

Running this sketch, I get the attached output in the Serial Monitor which leads me to believe I have the order of the code jumbled up.

I’m new to programming and have attempted to solve this on my own for 3 days with no success.

SerialMonitor_Output.png

Not sure what is causing the SDcard problem. I do see one other issue. You are only creating one instance of myISM. Switching the mux behind the driver’s back is a sure way of confusing things.

The best way to deal with this is to create an array of NUMBER_OF_SENSORS and then use x (which is your mux selector) to specify which one you are talking to at a time.

The declaration would be SparkFun_ISM330DHCX myISM[NUMBER_OF_SENSORS]; and you would refer to myISM

This will keep any private data (like cal values or states) separate for each sensor.

/mike

n1ist:
Not sure what is causing the SDcard problem. I do see one other issue. You are only creating one instance of myISM. Switching the mux behind the driver’s back is a sure way of confusing things.

The best way to deal with this is to create an array of NUMBER_OF_SENSORS and then use x (which is your mux selector) to specify which one you are talking to at a time.

The declaration would be SparkFun_ISM330DHCX myISM[NUMBER_OF_SENSORS]; and you would refer to myISM

This will keep any private data (like cal values or states) separate for each sensor.

/mike

Thank you for the reply Mike. I used an example from the Qwiic MUX Hookup Guide to develop this sketch and failed to include the additional code that is stored in a secondary tab titled “Mux_Control”.

The example: https://learn.sparkfun.com/tutorials/qw … no-example

The code:

/*
 Basic control and commands for the PCA9548A/TCA9548A I2C multiplexer
*/

#define MUX_ADDR 0x70 //7-bit unshifted default I2C Address

//Enables a specific port number
boolean enableMuxPort(byte portNumber)
{
  if(portNumber > 7) portNumber = 7;

  //Read the current mux settings
  Wire.requestFrom(MUX_ADDR, 1);
  if(!Wire.available()) return(false); //Error
  byte settings = Wire.read();

  //Set the wanted bit to enable the port
  settings |= (1 << portNumber);

  Wire.beginTransmission(MUX_ADDR);
  Wire.write(settings);
  Wire.endTransmission();

  return(true);
}

//Disables a specific port number
boolean disableMuxPort(byte portNumber)
{
  if(portNumber > 7) portNumber = 7;

  //Read the current mux settings
  Wire.requestFrom(MUX_ADDR, 1);
  if(!Wire.available()) return(false); //Error
  byte settings = Wire.read();

  //Clear the wanted bit to disable the port
  settings &= ~(1 << portNumber);

  Wire.beginTransmission(MUX_ADDR);
  Wire.write(settings);
  Wire.endTransmission();

  return(true);
}

This is the first I’ve had a chance to work on it again since the original posting, so I still haven’t figured out how to log the data to the SD card. If the additional information I provided yields any additional thoughts, I’d still like to hear them.

Trevor

I just looked at that example, and it is broken as described here. I have sent feedback to get it fixed. Thanks.

/mike

Apologies for the bad code example. This has now been fixed:

https://learn.sparkfun.com/tutorials/qw … no-example

Best wishes,

Paul