Having trouble getting updated/current data from IMU to print into SD

I am using an Arduino Uno, a Datalogger Shield and an IMU LSM9DS1. I am able to print things to the SD card, but whenever I run the code, the data is just repeated over and over again without updating with new values. Attached is my code and serial output. Any ideas how to fix this? Thank you!

#include <Arduino_LSM9DS1.h>
#include <SPI.h>
#include <SD.h>

const int chipSelect = 10;

void setup() {
  // Open serial communications and wait for port to open:
  Serial.begin(9600);
  while (!Serial) {
    ; // wait for serial port to connect. Needed for native USB port only
  }


  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.");
}

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

  // read three sensors and append to the string:
  if (IMU.accelerationAvailable() && IMU.gyroscopeSampleRate()) {
    // Read acceleration data
    IMU.readAcceleration(x, y, z);
    dataString += String(x) + ",";
    dataString += String(y) + ",";
    dataString += String(z) + ",";

    // Read gyroscope data
    IMU.readGyroscope(x, y, z);
    dataString += String(x) + ",";
    dataString += String(y) + ",";
    dataString += String(z);

    // Open the file
    File plzWork = SD.open("data.txt", FILE_WRITE);

    // If the file is available, write to it
    if (plzWork) {
      plzWork.println(dataString);
      plzWork.close();
      // print to the serial port too:
      Serial.println(dataString);
    } else {
      Serial.println("error opening datalog.txt");
    }
  }

  // Add a delay if needed to control the sampling rate
  delay(1000);  // Adjust the delay based on your desired sampling rate
}

The first thing to do with a new sensor library is to run one of the unmodified library examples, to see if it works as you expect.

On the Arduino Uno, avoid using Strings. They cause memory corruption and unexpected crashes.

All of this can be eliminated, and the same result accomplished with .print() statements. That frees up program and SRAM memory as well.

    dataString += String(x) + ",";
    dataString += String(y) + ",";
    dataString += String(z);

The IMU works I have tested it several times. For some reason it just refuses to update when I start using the datalogger. I even tried rewriting the code like 4 deferent ways.

#include <Arduino_LSM9DS1.h>
#include <SPI.h>
#include <SD.h>

const int chipSelect = 10;

void setup() {
  // Open serial communications and wait for port to open:
  Serial.begin(9600);
  while (!Serial) {
    ; // wait for serial port to connect. Needed for native USB port only
  }


  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.");
}

void loop() {
  float ax, ay, az;
  float gx, gy, gz;

  // read three sensors:
  if (IMU.accelerationAvailable() && IMU.gyroscopeAvailable()) {
    IMU.readAcceleration(ax, ay, az);
    IMU.readGyroscope(gx, gy, gz);

    // 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("datalog.txt", FILE_WRITE);

    // if the file is available, write to it:
    if (dataFile) {
      // write acceleration data to the file:
      dataFile.print(ax, 2);
      dataFile.print(",");
      dataFile.print(ay, 2);
      dataFile.print(",");
      dataFile.print(az, 2);
      dataFile.print(",");

      // write gyroscope data to the file:
      dataFile.print(gx, 2);
      dataFile.print(",");
      dataFile.print(gy, 2);
      dataFile.print(",");
      dataFile.println(gz, 2);

      dataFile.close();
      
    }
    // if the file isn't open, pop up an error:
    else {
      Serial.println("error opening datalog.txt");
    }

    // print to the serial port:
    Serial.print("Acceleration: ");
    Serial.print(ax);
    Serial.print(", ");
    Serial.print(ay);
    Serial.print(", ");
    Serial.print(az);
    Serial.print(" | Gyroscope: ");
    Serial.print(gx);
    Serial.print(", ");
    Serial.print(gy);
    Serial.print(", ");
    Serial.println(gz);

    // delay or add additional logic here as needed
    delay(1000); // or adjust based on your desired sampling rate
  }
}


I suspect part of the problem is that you are opening the file, writing a tiny bit of data and closing it again. That is an extremely slow operation, which also dramatically increases the SD card current draw and error rate.

It is a common beginner mistake that affects loop timing and the stability of a marginal power supply, which could in turn interfere with the IMU function.

So, open the file once in setup, and close it only when you are finished collecting data.

How do I continuously draw data without closing it

What do you mean by "draw data"?

I made a function that records data for 15 seconds before closing the SD card but all the values were repeated again. The IMU works and the timestamp is updating witch means the data is updating but for some reason the readings from the IMU do not change. Thank you for your help!

#include <Arduino_LSM9DS1.h>
#include <SD.h>

const int chipSelect = 10;
const unsigned long recordingDuration = 15000;  // Recording duration in milliseconds (15 seconds)

void setup() {
  Serial.begin(9600);
  while (!Serial);
  Serial.print("Initializing SD card...");

  if (!SD.begin(chipSelect)) {
    Serial.println("Card failed, or not present");
    while (1);
  }
  Serial.println("Card initialized.");
}

void recordData(File &dataFile) {
  unsigned long startTime = millis();
  unsigned long currentTime;

  while ((currentTime = millis()) - startTime < recordingDuration) {
    float ax, ay, az;
    float gx, gy, gz;

    // read three sensors:
    if (IMU.accelerationAvailable() && IMU.gyroscopeAvailable()) {
      IMU.readAcceleration(ax, ay, az);
      IMU.readGyroscope(gx, gy, gz);

      // if the file is available, write to it:
      if (dataFile) {
        dataFile.print("Timestamp: ");
        dataFile.print(currentTime);
        dataFile.print(" | Acceleration: ");
        dataFile.print(ax, 2);
        dataFile.print(", ");
        dataFile.print(ay, 2);
        dataFile.print(", ");
        dataFile.print(az, 2);
        dataFile.print(" | Gyroscope: ");
        dataFile.print(gx, 2);
        dataFile.print(", ");
        dataFile.print(gy, 2);
        dataFile.print(", ");
        dataFile.println(gz, 2);
      } else {
        Serial.println("Error writing to datalog.txt");
        return;  // Exit the function if there's an error
      }

      // print to the serial port:
      Serial.print("Timestamp: ");
      Serial.print(currentTime);
      Serial.print(" | Acceleration: ");
      Serial.print(ax);
      Serial.print(", ");
      Serial.print(ay);
      Serial.print(", ");
      Serial.print(az);
      Serial.print(" | Gyroscope: ");
      Serial.print(gx);
      Serial.print(", ");
      Serial.print(gy);
      Serial.print(", ");
      Serial.println(gz);
    } else {
      Serial.println("Sensor data not available");
    }

    delay(1000);  // Adjust the delay based on your desired sampling rate
  }
}

void loop() {
  File dataFile = SD.open("datalog.txt", FILE_WRITE);

  if (dataFile) {
    Serial.println("Recording data for 15 seconds...");
    recordData(dataFile);
    dataFile.close();
    Serial.println("Recording complete");
  } else {
    Serial.println("Error opening datalog.txt");
  }


}

Result:
Timestamp: 5258 | Acceleration: -1.65, -1.69, -1.72 | Gyroscope: 1032.29, 1016.66, 1001.04

Timestamp: 6290 | Acceleration: -1.65, -1.69, -1.72 | Gyroscope: 1032.29, 1016.66, 1001.04

Timestamp: 7325 | Acceleration: -1.65, -1.69, -1.72 | Gyroscope: 1032.29, 1016.66, 1001.04

Timestamp: 8357 | Acceleration: -1.65, -1.69, -1.72 | Gyroscope: 1032.29, 1016.66, 1001.04

Timestamp: 9390 | Acceleration: -1.65, -1.69, -1.72 | Gyroscope: 1032.29, 1016.66, 1001.04

Timestamp: 10422 | Acceleration: -1.65, -1.69, -1.72 | Gyroscope: 1032.29, 1016.66, 1001.04

Timestamp: 11455 | Acceleration: -1.65, -1.69, -1.72 | Gyroscope: 1032.29, 1016.66, 1001.04

Timestamp: 12491 | Acceleration: -1.65, -1.69, -1.72 | Gyroscope: 1032.29, 1016.66, 1001.04

Timestamp: 13524 | Acceleration: -1.65, -1.69, -1.72 | Gyroscope: 1032.29, 1016.66, 1001.04

Timestamp: 14558 | Acceleration: -1.65, -1.69, -1.72 | Gyroscope: 1032.29, 1016.66, 1001.04

Recording complete

In the revised code, I don't see a coding mistake that could cause such behavior, except that the loop function will run over and over again, either overwriting or appending junk to the data file. Things that should run only once go in setup().

Have you verified that the sensor returns different values, when using one of the sensor library examples?

Yes it provides accurate and varying values

Then a start with an exact copy of that working program, and add the SD card code to the copy, bit by bit, to see if and where something goes wrong.

First bit: just initialize the SD card, but don't do anything else.

That's how I created my original code. It goes wrong as soon as I start adding the data to the SD card. Basically from Serial.print(x) to dataFile.print(x).

Please post the last correctly working intermediate.

The one just for the IMU without the SD card?

#include <Arduino_LSM9DS1.h>
#include "SD.h"
#include <Wire.h>
#include "RTClib.h"


void setup() {
  // put your setup code here, to run once:

 Serial.begin(9600);
  while (!Serial);
  Serial.println("Started");

  if (!IMU.begin()) {
    Serial.println("Failed to initialize IMU!");
    while (1);
  }

}

void loop() {
  // put your main code here, to run repeatedly:

float x, y, z;

  if (IMU.accelerationAvailable() && IMU.gyroscopeSampleRate()) {
   Serial.println();
    IMU.readAcceleration(x, y, z);
    Serial.print(x);
    Serial.print('\t');
    Serial.print(y);
    Serial.print('\t');
    Serial.println(z);


    IMU.readGyroscope(x, y, z);
  
    Serial.print(x);
    Serial.print('\t');
    Serial.print(y);
    Serial.print('\t');
    Serial.println(z);

    IMU.readMagneticField(x, y, z);
    
    Serial.print(x);
    Serial.print('\t');
    Serial.print(y);
    Serial.print('\t');
    Serial.println(z);


  }


}

No, the last correctly working intermediate, with some SD functions, but no datafile.print().

The only other intermediate was the first example I posted where I appended it to a string.

Then you did not follow the suggestions in post #10 while creating the failing code.

To find the problem, you have to debug code additions one by one.

Start from working code and add the few lines required to initialize the SD card.

If that does not cause a failure, add a line or two to open the output file, but don't write anything to it. And so on.

Which Arduino are you using?

On the Uno and the like, running out of dynamic memory causes unpredictable behavior, and the SD card takes a big chunk of it.

Please post the memory report that appears just before upload.

Sketch uses 16748 bytes (51%) of program storage space. Maximum is 32256 bytes.
Global variables use 1334 bytes (65%) of dynamic memory, leaving 714 bytes for local variables. Maximum is 2048 bytes.

Which sketch?

You are very close to running out of memory, because opening the SD file takes 512 of the 714 bytes remaining.