How to get this LSM9DS1 code run faster?

So I wrote this code to write data from a LSM9DS1sensor to a SD card. It's currently writing one set of data per every 20ms. I want it to write one set per 10ms. Does anyone know how to do that? (I'm a totally arduino noob, only started learning programming for this project).

#include <SPI.h>
#include <Wire.h>
#include <SparkFunLSM9DS1.h>
#include <SD.h>
LSM9DS1 imu;
#define PRINT_CALCULATED
#define PRINT_SPEED 250
static unsigned long lastPrint = 0;
#define DECLINATION -8.58
const int chipSelect = 4; //sets a variable that is an integer//

void setup() {
  // Open serial communications and wait for port to open:
  Serial.begin(115200);
  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.");

  Wire.begin();
  if (imu.begin() == false) // with no arguments, this uses default addresses (AG:0x6B, M:0x1E) and i2c port (Wire).
  {
    Serial.println("Failed to communicate with LSM9DS1.");
    Serial.println("Double-check wiring.");
    Serial.println("Default settings in this sketch will " \
                   "work for an out of the box LSM9DS1 " \
                   "Breakout, but may need to be modified " \
                   "if the board jumpers are.");
    while (1);
  }
}//checks if serial and SD card connection is good//

void loop() {
  if ( imu.gyroAvailable() )
  {
    imu.readGyro();
  }
  if ( imu.accelAvailable() )
  {
    imu.readAccel();
  }
  if ( imu.magAvailable() )
  {
    imu.readMag();
  }
  unsigned long mytime;
  mytime = millis();
  String dataString = "Gx=";
  for (int analogPin = 0; analogPin < 1; analogPin++) {
    float sensor = imu.calcGyro(imu.gx);
    dataString += String(sensor);
    String comma1 = ", Gy=";
    dataString += String(comma1);
    float sensor2 = imu.calcGyro(imu.gy);
    dataString += String(sensor2);
    String comma2 = ", Gz=";
    dataString += String(comma2);
    float sensor3 = imu.calcGyro(imu.gz);
    dataString += String(sensor3);
  }
  String dataStringac = "ax=";
  for (int analogPin = 0; analogPin < 1; analogPin++) {
    float sensorac = imu.calcAccel(imu.ax);
    dataStringac += String(sensorac);
    String comma1ac = ", ay=";
    dataStringac += String(comma1ac);
    float sensor2ac = imu.calcAccel(imu.ay);
    dataStringac += String(sensor2ac);
    String comma2ac = ", az=";
    dataStringac += String(comma2ac);
    float sensor3ac = imu.calcAccel(imu.az);
    dataStringac += String(sensor3ac);
  }
  String dataStringm = "mx=";
  for (int analogPin = 0; analogPin < 1; analogPin++) {
    float sensorm = imu.calcMag(imu.mx);
    dataStringm += String(sensorm);
    String comma1m = ", my=";
    dataStringm += String(comma1m);
    float sensor2m = imu.calcMag(imu.my);
    dataStringm += String(sensor2m);
    String comma2m = ", mz=";
    dataStringm += String(comma2m);
    float sensor3m = imu.calcMag(imu.mz);
    dataStringm += String(sensor3m);
  }
  File dataFile = SD.open("datalog5.txt", FILE_WRITE);
  if (dataFile) {
    dataFile.println(dataString);
    dataFile.println(dataStringac);
    dataFile.println(dataStringm);
    dataFile.println(mytime);
    dataFile.close();
    Serial.println(dataString);
    Serial.println(dataStringac);
    Serial.println(dataStringm);
  }
  else {
    Serial.println("error opening datalog5.txt");
  }
}

Read the forum guidelines to see how to properly post code and some hints on how to get the most from this forum.
Use the IDE autoformat tool (ctrl-t or Tools, Auto format) before posting code in code tags.

The code as posted is very hard to follow without any indenting. It is also hard to copy to a text editor or the IDE. Properly posting code is important if you want help.

Which Arduino board?

Comments:
Only open your file ONCE in setup().
Consider how you will close the file so the last block of data is written to the card.
Consider the SD card buffer is 512 byes and will ONLY be written to the card when the buffer is filled and that will take a significant amount of time. Right now you are likely only measuring the time to fill the buffer in memory.
Good luck,
Paul

#include <SPI.h>
#include <Wire.h>
#include <SparkFunLSM9DS1.h>
#include <SD.h>
LSM9DS1 imu;
#define PRINT_CALCULATED
#define PRINT_SPEED 250
static unsigned long lastPrint = 0;
#define DECLINATION -8.58
const int chipSelect = 4; //sets a variable that is an integer//

void setup() {
  // Open serial communications and wait for port to open:
  Serial.begin(115200);
  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.");

  Wire.begin();
  if (imu.begin() == false) // with no arguments, this uses default addresses (AG:0x6B, M:0x1E) and i2c port (Wire).
  {
    Serial.println("Failed to communicate with LSM9DS1.");
    Serial.println("Double-check wiring.");
    Serial.println("Default settings in this sketch will " \
                   "work for an out of the box LSM9DS1 " \
                   "Breakout, but may need to be modified " \
                   "if the board jumpers are.");
    while (1);
  }
}//checks if serial and SD card connection is good//

void loop() {
  if ( imu.gyroAvailable() )
  {
    imu.readGyro();
  }
  if ( imu.accelAvailable() )
  {
    imu.readAccel();
  }
  if ( imu.magAvailable() )
  {
    imu.readMag();
  }
  unsigned long mytime;
  mytime = millis();
  String dataString = "Gx=";
  for (int analogPin = 0; analogPin < 1; analogPin++) {
    float sensor = imu.calcGyro(imu.gx);
    dataString += String(sensor);
    String comma1 = ", Gy=";
    dataString += String(comma1);
    float sensor2 = imu.calcGyro(imu.gy);
    dataString += String(sensor2);
    String comma2 = ", Gz=";
    dataString += String(comma2);
    float sensor3 = imu.calcGyro(imu.gz);
    dataString += String(sensor3);
  }
  String dataStringac = "ax=";
  for (int analogPin = 0; analogPin < 1; analogPin++) {
    float sensorac = imu.calcAccel(imu.ax);
    dataStringac += String(sensorac);
    String comma1ac = ", ay=";
    dataStringac += String(comma1ac);
    float sensor2ac = imu.calcAccel(imu.ay);
    dataStringac += String(sensor2ac);
    String comma2ac = ", az=";
    dataStringac += String(comma2ac);
    float sensor3ac = imu.calcAccel(imu.az);
    dataStringac += String(sensor3ac);
  }
  String dataStringm = "mx=";
  for (int analogPin = 0; analogPin < 1; analogPin++) {
    float sensorm = imu.calcMag(imu.mx);
    dataStringm += String(sensorm);
    String comma1m = ", my=";
    dataStringm += String(comma1m);
    float sensor2m = imu.calcMag(imu.my);
    dataStringm += String(sensor2m);
    String comma2m = ", mz=";
    dataStringm += String(comma2m);
    float sensor3m = imu.calcMag(imu.mz);
    dataStringm += String(sensor3m);
  }
  File dataFile = SD.open("datalog5.txt", FILE_WRITE);
  if (dataFile) {
    dataFile.println(dataString);
    dataFile.println(dataStringac);
    dataFile.println(dataStringm);
    dataFile.println(mytime);
    dataFile.close();
    Serial.println(dataString);
    Serial.println(dataStringac);
    Serial.println(dataStringm);
  }
  else {
    Serial.println("error opening datalog5.txt");
  }
}

Sorry, is this good now? Also, I'm using an adalogger feather M0 board.

Hi, is there an example on how to only open file once in setup? I'm not exactly sure how to do so.

Move the ".open()" statement to setup(), and in loop(), just use .write() or .print().

Close the file when you are all done collecting data. If you don't, you will lose at most the last 512 bytes written, which is usually not a problem.

1 Like

Hi, I'm getting an error saying "dataFile was not defined" when I pasted the File dataFile statement to setup. What am I doing wrong?

Not posting the revised code.

#include <SPI.h>
#include <Wire.h>
#include <SparkFunLSM9DS1.h>
#include <SD.h>
LSM9DS1 imu;
#define PRINT_CALCULATED
#define PRINT_SPEED 250
static unsigned long lastPrint = 0;
#define DECLINATION -8.58
const int chipSelect = 4; //sets a variable that is an integer//

void setup() {
  // Open serial communications and wait for port to open:
  Serial.begin(115200);
  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.");

  Wire.begin();
  if (imu.begin() == false) // with no arguments, this uses default addresses (AG:0x6B, M:0x1E) and i2c port (Wire).
  {
    Serial.println("Failed to communicate with LSM9DS1.");
    Serial.println("Double-check wiring.");
    Serial.println("Default settings in this sketch will " \
                   "work for an out of the box LSM9DS1 " \
                   "Breakout, but may need to be modified " \
                   "if the board jumpers are.");
    while (1);
  }
  File dataFile = SD.open("datalog5.txt", FILE_WRITE);
}//checks if serial and SD card connection is good//

void loop() {
  if ( imu.gyroAvailable() )
  {
    imu.readGyro();
  }
  if ( imu.accelAvailable() )
  {
    imu.readAccel();
  }
  if ( imu.magAvailable() )
  {
    imu.readMag();
  }
  unsigned long mytime;
  mytime = millis();
  String dataString = "Gx=";
  for (int analogPin = 0; analogPin < 1; analogPin++) {
    float sensor = imu.calcGyro(imu.gx);
    dataString += String(sensor);
    String comma1 = ", Gy=";
    dataString += String(comma1);
    float sensor2 = imu.calcGyro(imu.gy);
    dataString += String(sensor2);
    String comma2 = ", Gz=";
    dataString += String(comma2);
    float sensor3 = imu.calcGyro(imu.gz);
    dataString += String(sensor3);
  }
  String dataStringac = "ax=";
  for (int analogPin = 0; analogPin < 1; analogPin++) {
    float sensorac = imu.calcAccel(imu.ax);
    dataStringac += String(sensorac);
    String comma1ac = ", ay=";
    dataStringac += String(comma1ac);
    float sensor2ac = imu.calcAccel(imu.ay);
    dataStringac += String(sensor2ac);
    String comma2ac = ", az=";
    dataStringac += String(comma2ac);
    float sensor3ac = imu.calcAccel(imu.az);
    dataStringac += String(sensor3ac);
  }
  String dataStringm = "mx=";
  for (int analogPin = 0; analogPin < 1; analogPin++) {
    float sensorm = imu.calcMag(imu.mx);
    dataStringm += String(sensorm);
    String comma1m = ", my=";
    dataStringm += String(comma1m);
    float sensor2m = imu.calcMag(imu.my);
    dataStringm += String(sensor2m);
    String comma2m = ", mz=";
    dataStringm += String(comma2m);
    float sensor3m = imu.calcMag(imu.mz);
    dataStringm += String(sensor3m);
  }

  if (dataFile) {
    dataFile.println(dataString);
    dataFile.println(dataStringac);
    dataFile.println(dataStringm);
    dataFile.println(mytime);
    dataFile.close();
    Serial.println(dataString);
    Serial.println(dataStringac);
    Serial.println(dataStringm);
  }
  else {
    Serial.println("error opening datalog5.txt");
  }
}

Sorry here it is

Yes, thank you.

The variable "dataFile" is defined only in setup. Declare it as a global, outside of setup() and loop() e.g.

File dataFile;

Also, it is a bad idea to use Strings. They are completely unnecessary, and will cause memory problems and program crashes on AVR based Arduinos.

Just use dataFile.print() statements to put the data on the SD card.

#include <SPI.h>
#include <Wire.h>
#include <SparkFunLSM9DS1.h>
#include <SD.h>
LSM9DS1 imu;
#define PRINT_CALCULATED
#define PRINT_SPEED 250
static unsigned long lastPrint = 0;
#define DECLINATION -8.58
const int chipSelect = 4; //sets a variable that is an integer//
File dataFile;
void setup() {
  // Open serial communications and wait for port to open:
  Serial.begin(115200);
  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.");

  Wire.begin();
  if (imu.begin() == false) // with no arguments, this uses default addresses (AG:0x6B, M:0x1E) and i2c port (Wire).
  {
    Serial.println("Failed to communicate with LSM9DS1.");
    Serial.println("Double-check wiring.");
    Serial.println("Default settings in this sketch will " \
                   "work for an out of the box LSM9DS1 " \
                   "Breakout, but may need to be modified " \
                   "if the board jumpers are.");
    while (1);
  }
}//checks if serial and SD card connection is good//

void loop() {
  if ( imu.gyroAvailable() )
  {
    imu.readGyro();
  }
  if ( imu.accelAvailable() )
  {
    imu.readAccel();
  }
  if ( imu.magAvailable() )
  {
    imu.readMag();
  }
  unsigned long mytime;
  mytime = millis();
  String dataString = "Gx=";
  for (int analogPin = 0; analogPin < 1; analogPin++) {
    float sensor = imu.calcGyro(imu.gx);
    dataString += String(sensor);
    String comma1 = ", Gy=";
    dataString += String(comma1);
    float sensor2 = imu.calcGyro(imu.gy);
    dataString += String(sensor2);
    String comma2 = ", Gz=";
    dataString += String(comma2);
    float sensor3 = imu.calcGyro(imu.gz);
    dataString += String(sensor3);
  }
  String dataStringac = "ax=";
  for (int analogPin = 0; analogPin < 1; analogPin++) {
    float sensorac = imu.calcAccel(imu.ax);
    dataStringac += String(sensorac);
    String comma1ac = ", ay=";
    dataStringac += String(comma1ac);
    float sensor2ac = imu.calcAccel(imu.ay);
    dataStringac += String(sensor2ac);
    String comma2ac = ", az=";
    dataStringac += String(comma2ac);
    float sensor3ac = imu.calcAccel(imu.az);
    dataStringac += String(sensor3ac);
  }
  String dataStringm = "mx=";
  for (int analogPin = 0; analogPin < 1; analogPin++) {
    float sensorm = imu.calcMag(imu.mx);
    dataStringm += String(sensorm);
    String comma1m = ", my=";
    dataStringm += String(comma1m);
    float sensor2m = imu.calcMag(imu.my);
    dataStringm += String(sensor2m);
    String comma2m = ", mz=";
    dataStringm += String(comma2m);
    float sensor3m = imu.calcMag(imu.mz);
    dataStringm += String(sensor3m);
  }
  if (dataFile) {
    dataFile = SD.open("datalog5.txt", FILE_WRITE);
    dataFile.println(dataString);
    dataFile.println(dataStringac);
    dataFile.println(dataStringm);
    dataFile.println(mytime);
    dataFile.close();
    Serial.println(dataString);
    Serial.println(dataStringac);
    Serial.println(dataStringm);
  }
  else {
    Serial.println("error opening datalog5.txt");
  }
}

I modified the code, but now it skips straight to "error opening datalog5.txt". Also, the sensor I'm using somehow doesn't work with the print function unless I convert it to a string :cry:

The following line has to be moved to "setup()" below the code that initializes the SD card.

#include <SPI.h>
#include <Wire.h>
#include <SparkFunLSM9DS1.h>
#include <SD.h>
LSM9DS1 imu;
#define PRINT_CALCULATED
#define PRINT_SPEED 250
static unsigned long lastPrint = 0;
#define DECLINATION -8.58
const int chipSelect = 4; //sets a variable that is an integer//
File dataFile;
void setup() {
  // Open serial communications and wait for port to open:
  Serial.begin(115200);
  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.");
  dataFile = SD.open("datalog5.txt", FILE_WRITE);
  Wire.begin();
  if (imu.begin() == false) // with no arguments, this uses default addresses (AG:0x6B, M:0x1E) and i2c port (Wire).
  {
    Serial.println("Failed to communicate with LSM9DS1.");
    Serial.println("Double-check wiring.");
    Serial.println("Default settings in this sketch will " \
                   "work for an out of the box LSM9DS1 " \
                   "Breakout, but may need to be modified " \
                   "if the board jumpers are.");
    while (1);
  }
}//checks if serial and SD card connection is good//

void loop() {
  if ( imu.gyroAvailable() )
  {
    imu.readGyro();
  }
  if ( imu.accelAvailable() )
  {
    imu.readAccel();
  }
  if ( imu.magAvailable() )
  {
    imu.readMag();
  }
  unsigned long mytime;
  mytime = millis();
  String dataString = "Gx=";
  for (int analogPin = 0; analogPin < 1; analogPin++) {
    float sensor = imu.calcGyro(imu.gx);
    dataString += String(sensor);
    String comma1 = ", Gy=";
    dataString += String(comma1);
    float sensor2 = imu.calcGyro(imu.gy);
    dataString += String(sensor2);
    String comma2 = ", Gz=";
    dataString += String(comma2);
    float sensor3 = imu.calcGyro(imu.gz);
    dataString += String(sensor3);
  }
  String dataStringac = "ax=";
  for (int analogPin = 0; analogPin < 1; analogPin++) {
    float sensorac = imu.calcAccel(imu.ax);
    dataStringac += String(sensorac);
    String comma1ac = ", ay=";
    dataStringac += String(comma1ac);
    float sensor2ac = imu.calcAccel(imu.ay);
    dataStringac += String(sensor2ac);
    String comma2ac = ", az=";
    dataStringac += String(comma2ac);
    float sensor3ac = imu.calcAccel(imu.az);
    dataStringac += String(sensor3ac);
  }
  String dataStringm = "mx=";
  for (int analogPin = 0; analogPin < 1; analogPin++) {
    float sensorm = imu.calcMag(imu.mx);
    dataStringm += String(sensorm);
    String comma1m = ", my=";
    dataStringm += String(comma1m);
    float sensor2m = imu.calcMag(imu.my);
    dataStringm += String(sensor2m);
    String comma2m = ", mz=";
    dataStringm += String(comma2m);
    float sensor3m = imu.calcMag(imu.mz);
    dataStringm += String(sensor3m);
  }
  if (dataFile) {
    dataFile.println(dataString);
    dataFile.println(dataStringac);
    dataFile.println(dataStringm);
    dataFile.println(mytime);
    Serial.println(dataString);
    Serial.println(dataStringac);
    Serial.println(dataStringm);
  }
  else {
    Serial.println("error opening datalog5.txt");
  }
}

My code now looks like this. It writes one set of data to the SD card and that's it for some reason.

That has nothing to do with the sensor. If you want to understand what you were doing wrong, post the code that you tried to use, along with the error message.

For example, you can replace all of this (note that the for loop does nothing useful)

  String dataString = "Gx=";
  for (int analogPin = 0; analogPin < 1; analogPin++) {
    float sensor = imu.calcGyro(imu.gx);
    dataString += String(sensor);
    String comma1 = ", Gy=";
    dataString += String(comma1);
    float sensor2 = imu.calcGyro(imu.gy);
    dataString += String(sensor2);
    String comma2 = ", Gz=";
    dataString += String(comma2);
    float sensor3 = imu.calcGyro(imu.gz);
    dataString += String(sensor3);
}
...
  dataFile.println(dataString);

With this:

  dataFile.print("Gx = ");
  dataFile.print(imu.calcGyro(imu.gx));
  dataFile.print(", Gy = ");
  dataFile.print(imu.calcGyro(imu.gy));
  dataFile.print(", Gz =  ");
  dataFile.println(imu.calcGyro(imu.gz));

Which is smaller, faster, easier to read and does not create memory problems.

  dataFile.print("Gx = ");
  dataFile.print(", ");
  dataFile.print(imu.calcGyro(imu.gx));
  dataFile.print(", Gy = ");
  dataFile.print(imu.calcGyro(imu.gy));
  dataFile.print(", Gz =  ");
  dataFile.println(imu.calcGyro(imu.gz));

Yeah this was what I tried to do at the start actually, but it just resulted in the data written to the file be all 0's. It only somehow writes correct values until I changed the data type to String.

You may have tried to do that, but you made one or more mistakes.

#include <Wire.h>
#include <SPI.h>
#include <SD.h>
#include <SparkFunLSM9DS1.h>
LSM9DS1 imu;

#define PRINT_CALCULATED

#define PRINT_SPEED 250 
static unsigned long lastPrint = 0;

#define DECLINATION -8.58 

void printGyro();
void printAccel();
void printMag();
void printAttitude(float ax, float ay, float az, float mx, float my, float mz);

const int chipSelect = 4;

void setup() {


  Serial.begin(115200);

  Wire.begin();

  while (!Serial);

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

  if (!SD.begin(chipSelect)) {

    Serial.println("initialization failed. Things to check:");

    Serial.println("1. is a card inserted?");

    Serial.println("2. is your wiring correct?");

    Serial.println("3. did you change the chipSelect pin to match your shield or module?");

    Serial.println("Note: press reset or reopen this serial monitor after fixing your issue!");

    while (true);

  }

  Serial.println("initialization done.");
}

void loop() {
  if ( imu.gyroAvailable() )
  {
    imu.readGyro();
  }
  if ( imu.accelAvailable() )
  {
    imu.readAccel();
  }
  if ( imu.magAvailable() )
  {
    imu.readMag();
  }
  if ((lastPrint + PRINT_SPEED) < millis())
  {
    printGyro();  
    printAccel(); 
    printMag(); 
    printAttitude(imu.ax, imu.ay, imu.az,
                  -imu.my, -imu.mx, imu.mz);
    Serial.println();

    lastPrint = millis(); 
  }
}

void printGyro()
{
  File dataFile = SD.open("datalog.txt", FILE_WRITE);
  if (dataFile) {
    
      dataFile.print("G: ");
      dataFile.print(imu.calcGyro(imu.gx));
      dataFile.print(",");
      dataFile.print(imu.calcGyro(imu.gy));
      dataFile.print(",");
      dataFile.print(imu.calcGyro(imu.gz));
      dataFile.print(" deg/s");
   dataFile.close();
  }
}
void printAccel()
{
  File dataFile = SD.open("datalog.txt", FILE_WRITE);
  if (dataFile) {
    dataFile.print("A = "); 
      dataFile.print(imu.calcAccel(imu.ax));
      dataFile.print(",");
      dataFile.print(imu.calcAccel(imu.ay));
      dataFile.print(",");
      dataFile.print(imu.calcAccel(imu.az));
      dataFile.print(" g");
    dataFile.close();  
  }   
}
void printMag()
{
  File dataFile = SD.open("datalog.txt", FILE_WRITE);
  if (dataFile) {
    dataFile.print("M = "); 
      dataFile.print(imu.calcMag(imu.mx));
      dataFile.print(",");
      dataFile.print(imu.calcMag(imu.my));
      dataFile.print(",");
      dataFile.print(imu.calcMag(imu.mz));
      dataFile.print(" gauss");
    dataFile.close();
  }
}
void printAttitude(float ax, float ay, float az, float mx, float my, float mz)
{
  float roll = atan2(ay, az);
  float pitch = atan2(-ax, sqrt(ay * ay + az * az));

  float heading;
  if (my == 0)
    heading = (mx < 0) ? PI : 0;
  else
    heading = atan2(mx, my);

  heading -= DECLINATION * PI / 180;

  if (heading > PI) heading -= (2 * PI);
  else if (heading < -PI) heading += (2 * PI);

  heading *= 180.0 / PI;
  pitch *= 180.0 / PI;
  roll  *= 180.0 / PI;

  File dataFile = SD.open("datalog.txt", FILE_WRITE);
  if (dataFile) {
    dataFile.print("Pitch, Roll: ");
    dataFile.print(pitch);
    dataFile.print(", ");
    dataFile.print(roll);
    dataFile.print("Heading: ");
    dataFile.print(heading);
  dataFile.close();
  }
} 

This was the code that I tried to directly print.

The print statements look fine. The error must be elsewhere.

To debug that code, replace the dataFile.print() statements with Serial.print() to see what values should have appeared on the SD card.