Data logger sometimes stops writing to the sd(FIXED)

Hello everyone,
My name is Paul and I am currently working on a project, where i want to measure accelerations while toothbrushing.
The device i built consists of a ESP32 connected to an IMU(Lsm6ds3) and RTC(DS3231) connected via I2C and a micro sd adapter connected via SPI. The system is powered by a CR123a 3V lithium battery.

The ESP32 goes into deepsleep between the measurements to save battery. To wake up the ESP32 i configured the IMU so that if motion exceeds a certain value it generates an interrupt to wake the ESP up and start measuring.

To get a sufficient sampling frequency i am using a FIFO buffer on the IMU so i only need to write the Data to the SD card in big chunks.

Generally everything works fine but when testing the device i run into some problems time to time..
Sometimes everything works as a charm and i get a txt with the current boot number as a name. Thats how i already collected toothbrushing data over 2 weeks :raised_hands:

But then most of the time it stops wokring at some point. For troubleshooting i am currently testing everything with usb connection and looking at the SD data afterwards.

First of all here is my code (if something is not clear please let me know!)

#include "SparkFunLSM6DS3.h"
#include "Wire.h"
#include "SPI.h"
#include "FS.h"
#include "SD.h"
#include "WiFi.h"
#include "RTClib.h"

#include <Preferences.h>
Preferences preferences;

RTC_DS3231 rtc;
LSM6DS3 myIMU(I2C_MODE, 0x6B);

RTC_DATA_ATTR int booter = 0;
RTC_DATA_ATTR int reseter = 0;
char fileName[10]; 
uint8_t int1Status = 0;
uint8_t saver = 0;

void setup( void ) {

  //Settings for the IMU:
  myIMU.settings.gyroEnabled = 1;  //Can be 0 or 1
  myIMU.settings.gyroRange = 2000;   //Max deg/s.  Can be: 125, 245, 500, 1000, 2000
  myIMU.settings.gyroSampleRate = 833;   //Hz.  Can be: 13, 26, 52, 104, 208, 416, 833, 1666
  myIMU.settings.gyroBandWidth = 200;  //Hz.  Can be: 50, 100, 200, 400;
  myIMU.settings.gyroFifoEnabled = 1;  //Set to include gyro in FIFO
  myIMU.settings.gyroFifoDecimation = 1;  //set 1 for on /1

  myIMU.settings.accelEnabled = 1;
  myIMU.settings.accelRange = 16;      //Max G force readable.  Can be: 2, 4, 8, 16
  myIMU.settings.accelSampleRate = 833;  //Hz.  Can be: 13, 26, 52, 104, 208, 416, 833, 1666, 3332, 6664, 13330
  myIMU.settings.accelBandWidth = 200;  //Hz.  Can be: 50, 100, 200, 400;
  myIMU.settings.accelFifoEnabled = 1;  //Set to include accelerometer in the FIFO
  myIMU.settings.accelFifoDecimation = 1;  //set 1 for on /1
  myIMU.settings.tempEnabled = 1;
  
    //Non-basic mode settings
  myIMU.settings.commMode = 1;

  //FIFO control settings
  myIMU.settings.fifoThreshold = 100;  //Can be 0 to 4096 (16 bit bytes)
  myIMU.settings.fifoSampleRate = 200;  //Hz.  Can be: 10, 25, 50, 100, 200, 400, 800, 1600, 3300, 6600
  myIMU.settings.fifoModeWord = 6;  //FIFO mode.

  //  //Error accumulation variable
  uint8_t errorAccumulator = 0;
  uint16_t errorsAndWarnings = 0;
  uint8_t dataToWrite = 0;  //Temporary variable



  Serial.begin(115200);  // start serial for output
  delay(100); //relax...
  Serial.println("ESP came out of reset.\n");


  //store the number of boots in Flash memory and assign its value to a volatile integer "booter". 
  //The boot counter "reseter" is a seperate volatile counter, that goes to 0 once the ESP32 looses power or is resetet
  
     preferences.begin("my-app", false);
     unsigned int counter = preferences.getUInt("counter", 0);
     counter++;
     booter = counter;
     Serial.printf("Current counter value: %u\n", counter);    
     Serial.printf("Current booter value: %u\n", booter);       
     Serial.printf("Current reseter value: %u\n", reseter);
     preferences.putUInt("counter", counter);                   // Store the counter to the Preferences
     preferences.end();                                         // Close the Preferences


  //Start the RTC and programm the time of code upload to it if it is the first boot of the ESP32
  if (! rtc.begin()) {
    Serial.println("Couldn't find RTC");
    }

 if(booter == 1 ){
  rtc.adjust(DateTime(F(__DATE__), F(__TIME__)));
  }
    
setupSDCard();
setupIMU();

}


void setupSDCard(){
  if(!SD.begin()){
      return;
  }
  uint8_t cardType = SD.cardType();
  if(cardType == CARD_NONE){
      return;
  }

}

void setupIMU(){
  Wire.begin();
  Wire.setClock(800000L);
  
        if( myIMU.begin() != 0 ){
          Serial.println("Problem starting the sensor");
          Serial.println(myIMU.begin());
          }
        else{
          Serial.println("Sensor started.");
          }
          
        uint8_t dataToWrite = 0;                                               //Temporary variable

        
        Serial.println("Configuring FIFO");
        myIMU.fifoBegin();
        Serial.println("fifo Begin done");
        
        Serial.println("Clearing out the FIFO...");
        myIMU.fifoClear();
        Serial.println("Fifo clear");
        }

void int1ISR()
{
  int1Status++;
}

void saveSD()               //if button is pushed saver is updated
{
saver++;
}


void loop(){
         
          float temp;  //This is to hold read data
          uint16_t tempUnsigned;

 
  //get the current Date 
  DateTime now = rtc.now();
  int day=now.day();int month=now.month(); int year=now.year();int hour=now.hour();int minute=now.minute();int second=now.second();

  //create a txt with the bootcount number as name
    snprintf(fileName, 9, "/%03d.txt", reseter);
    File file = SD.open(fileName ,FILE_APPEND); 

  //print the boot number and number of resets in the file for troubleshooting  
    file.print(reseter);file.print(". Reset_boot, ");file.print(booter);file.print(". Boot:\n"); 
    file.print("Recording started at:\n"); 
    file.print(day);file.print(".");file.print(month);file.print(".");file.print(year);file.print(" - ");
    file.print(hour);file.print(":");file.print(minute);file.print(","); file.print(second);file.print("\n ");
    file.print("Time in millis;Gx;Gy;Gz;X;Y;Z\n");  


    
    attachInterrupt(digitalPinToInterrupt(15), saveSD, RISING);     // interrupt to stop the programm later to allow the SD beeing pulled after file is closed 
    File file = SD.open(fileName ,FILE_APPEND);                     // open the txt

       int milli = millis();
       while(millis()-milli <5000){                                 //set recording time
            
          while( ( myIMU.fifoGetStatus() & 0x8000 ) == 0 ) {        //let the FIFO bee filled to threshold
            };  
            
                     
          while( ( myIMU.fifoGetStatus() & 0x1000 ) == 0 ) {        //as long as fifo is not emptied loop and write the IMU data(3Gyro & 3Axis) from FIFO
               
                file.print(millis());file.print(";"); 
 
                temp = myIMU.calcAccel(myIMU.fifoRead());
                file.print(temp);file.print(";");
                
                temp = myIMU.calcAccel(myIMU.fifoRead());
                file.print(temp);file.print(";");

                temp = myIMU.calcAccel(myIMU.fifoRead());
                file.print(temp);file.print(";");
                
                temp = myIMU.calcAccel(myIMU.fifoRead());
                file.print(temp);file.print(";");
                
                temp = myIMU.calcAccel(myIMU.fifoRead());
                file.print(temp);file.print(";");

                temp = myIMU.calcAccel(myIMU.fifoRead()); 
                file.print(temp);file.print(";");file.print("\n ");
                 
          }
        
          tempUnsigned = myIMU.fifoGetStatus();
          Serial.print("Outside of Fifo");Serial.print("\n");
          
 

          if(saver>0){                                                //if button is pushed the file is closed and the SD stopped so it can be removed without data loss                                          
                  file.print("The recording stopped save!\n"); 
                  Serial.println("stopping logging");
                  file.close();
                  delay(500);
                  SD.end();
                  Serial.println("SD out");
                  delay(1000);
                  esp_deep_sleep_start();    
          }
       }
                  
                    
myIMU.fifoClear();                                                    // clear out and stop the FIFO
myIMU.fifoEnd();

file.print("recording stoppedt");
file.print("\n"); 
file.close();                                                         //close the file 


detachInterrupt(digitalPinToInterrupt(15));                           //remove the Interrupt for the SD removal before deep sleeping

Serial.println("Going to sleep");
delay(500);
SD.end();                                                             //end the SD card to reduce current consumption


          

          myIMU.writeRegister( LSM6DS3_ACC_GYRO_TAP_CFG1, 0x00 );         //Settings for the IMU to generate interrupt if motion is over threshold
          myIMU.writeRegister( LSM6DS3_ACC_GYRO_WAKE_UP_DUR, 0x00 );
          myIMU.writeRegister( LSM6DS3_ACC_GYRO_WAKE_UP_THS, 0x01 );
          myIMU.writeRegister( LSM6DS3_ACC_GYRO_MD1_CFG, 0x20 );
          myIMU.writeRegister( LSM6DS3_ACC_GYRO_CTRL2_G, 0x00 );
          
          attachInterrupt(digitalPinToInterrupt(13), int1ISR, RISING);    //Set pin 13 to detect interrupt from IMU
          
reseter++;                                                                //update volatile counter                                                             



  esp_sleep_enable_ext0_wakeup(GPIO_NUM_13,1);                            //allow external wake up and go to sleep
  esp_deep_sleep_start();                
}

What i already found out is, that sometimes within the FIFO loop the Programm gets stuck for some time(maybe 5-10sek) but continues afterwards and restarts again. If this happens there is no data written to the SD anymore, even if i can see the system booting up and running several times in the monitor..

I know that writing to SD can cause quite some pain and i looked some probems up, but couldnt find something, that would explain this behaviour. If the System starts booting up again it should at least create new files again or?

I am thankfull for any kind of help or critisism.

For anyone struggling with the same problem:
It turned out to be a SD card problem..
I had to try several SD Cards and found, that some were working fine and others sometimes crashed. This is the one i am using now which works:
SDSQUNR-032G-GN6TA


even some other more expensive sandisk 32gb did not work!

Thanks for sharing.
I bought a couple of older 8GB microSD memory cards for my Arduino projects because of compatibility problems.
I noticed your question 12 days ago, but I didn't know what to do with it. Sadly no one replied :cry: I hope you are not disappointed. Keep asking you Arduino-problems.

This may be true but, if you later find that it isn't, you might note that opening and closing the file each trip round the loop is bad practice. It will probably lead you to grief eventually. I don't know if the type of card has any bearing on this.

The loop is running for 3minutes in my final code. The file is only beeing opened once before and closed afterwards, so that should be ok!

The last Tests were all positive and i managed to get 10 datasets of people brushing their teeth for 7 days :slight_smile: