SD issues

hello everyone,

I have a project where I am attempting to log data from a 9 degrees of freedom sensor to an SD card. My components are a outsourced SD card reader very similar to the sparkfun SD reader (https://www.sparkfun.com/products/544), an Adafruit 9-DOF Absolute Orientation IMU Fusion Breakout - BNO055 ( I tried to use the sparkfun 9dof sensor stick, but There was just no figuring it out, so I had to go with this one) and an arduino uno. I am sucessfully taking data from the 9dof and recording it on the SD. And every time I push the toggle on/off button, I have it open a new file to write orientation data to(all named 1 number higher than the previous file), But my project right now is to open a new file number, again one higher than the last one created, when power is turned off and on again .( since this will be powered by a battery, I need to be able to turn it off and on to conserve battery). To do that, I made a file named “var file.txt” to store what file the SD is on. That way when you power cycle the SD library can read var file and go to that file number instead of restarting at file one and overwriting data from before. However, right now, whenever the arduino tries to read “var file” it sees nothing. I trouble shooted for a while and then used the SD.exists() fuction to see if var file even exists. and it doesn’t! But, if the file doesn’t exist, the SD library should create one when you try to open it. and when you plug the microSD into a computer, Var file is on the card. And of course, The toggle on/off button still makes a new file every time you do that! Does anybody know why arduino thinks a file doesn’t exist?

This is my really messy code:

#include <Wire.h>
#include <Adafruit_Sensor.h>
#include <Adafruit_BNO055.h>
#include <utility/imumaths.h>
#include <SPI.h>
#include <SD.h>

const int chipSelect = 10;
String filename = "";

/* This driver uses the Adafruit unified sensor library (Adafruit_Sensor),
   which provides a common 'type' for sensor data and some helper functions.
   
   To use this driver you will also need to download the Adafruit_Sensor
   library and include it in your libraries folder.

   You should also assign a unique ID to this sensor for use with
   the Adafruit Sensor API so that you can identify this particular
   sensor in any data logs, etc.  To assign a unique ID, simply
   provide an appropriate value in the constructor below (12345
   is used by default in this varfile).
   
   Connections
   ===========
   Connect SCL to analog 5
   Connect SDA to analog 4
   Connect VDD to 3-5V DC
   Connect GROUND to common ground
    
   History
   =======
   2015/MAR/03  - First release (KTOWN)
*/

/* Set the delay between fresh samples */
#define BNO055_SAMPLERATE_DELAY_MS (50)
   
Adafruit_BNO055 bno = Adafruit_BNO055(55);
int filenum = 1;
const byte onoff = 9;
const byte RecLED = 8;

/**************************************************************************/
/*
    Displays some basic information on this sensor from the unified
    sensor API sensor_t type (see Adafruit_Sensor for more information)
*/
/**************************************************************************/
void displaySensorDetails(void)
{
  sensor_t sensor;
  bno.getSensor(&sensor);
  Serial.println("------------------------------------");
  Serial.print  ("Sensor:       "); Serial.println(sensor.name);
  Serial.print  ("Driver Ver:   "); Serial.println(sensor.version);
  Serial.print  ("Unique ID:    "); Serial.println(sensor.sensor_id);
  Serial.print  ("Max Value:    "); Serial.print(sensor.max_value); Serial.println(" xxx");
  Serial.print  ("Min Value:    "); Serial.print(sensor.min_value); Serial.println(" xxx");
  Serial.print  ("Resolution:   "); Serial.print(sensor.resolution); Serial.println(" xxx");  
  Serial.println("------------------------------------");
  Serial.println("");
  delay(500);
  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:
    return;
  }
  Serial.println("card initialized.");
}

/**************************************************************************/
/*
    Arduino setup function (automatically called at startup)
*/
/**************************************************************************/
void setup(void) 
{
  
  Serial.begin(115200);
  Serial.println("Orientation Sensor Test"); Serial.println("");
  
  /* Initialise the sensor */
  if(!bno.begin())
  {
    /* There was a problem detecting the BNO055 ... check your connections */
    Serial.print("Ooops, no BNO055 detected ... Check your wiring or I2C ADDR!");
    while(1);
    
  }
  pinMode(onoff,INPUT);
  pinMode(RecLED,OUTPUT);
 
 File dataFile = SD.open("var file.txt");
  Serial.println(dataFile.available());
  // if the file is available, read from it:
  if (dataFile) {
    while (dataFile.available()) {
      char weep = dataFile.read();
      Serial.write(weep);
      filename += weep;
    }
    dataFile.close();
  }
  // if the file isn't open, pop up an error:
  else {
    Serial.println("error opening var file.txt");
  }
  if(filename.length() == 0){
    Serial.println("nothing read.");
  }
  Serial.println("read" + filename + " from var file.txt");
  filenum = filename.toInt();
  File rewritefile = SD.open("var file.txt",FILE_WRITE);
  if(rewritefile){
   rewritefile.seek(0);
   rewritefile.print(filenum++);
  }
  rewritefile.close();
 
  delay(1000);
    
  /* Display some basic information on this sensor */
  displaySensorDetails();

  bno.setExtCrystalUse(true);
  digitalWrite(RecLED,HIGH);
  
}

/**************************************************************************/
/*
    Arduino loop function, called once 'setup' is complete (your own code
    should go here)
*/
/**************************************************************************/
void loop(void) 
{
  if(digitalRead(onoff) == HIGH){
    digitalWrite(RecLED,LOW);
    delay(1000);
    while(digitalRead(onoff)==LOW);
    filenum++ ; 
    filename = String(filenum);
    File filefile = SD.open("var file.txt",FILE_WRITE);
     filefile.seek(0);
     filefile.print(filenum);
    filefile.close();
    
    
  }
  /* Get a new sensor event */ 
  sensors_event_t event; 
  bno.getEvent(&event);
  String dataString = "";
  /* Display the floating point data */
  Serial.print("X: ");
  Serial.print(event.orientation.x, 4);
  dataString += " X: ";
  dataString += event.orientation.x, 4;
  Serial.print("\tY: ");
  Serial.print(event.orientation.y, 4);
  dataString += " Y: ";
  dataString += event.orientation.y, 4;
  Serial.print("\tZ: ");
  Serial.print(event.orientation.z, 4);
  dataString += " Z: ";
  dataString += event.orientation.z, 4;
  Serial.println("");
   File dataFile = SD.open(filename +".txt", FILE_WRITE);

   //if the file is available, write to it:
    if(dataFile) {
    dataFile.println(dataString);
    dataFile.close();
  }
  // if the file isn't open, pop up an error:
   else {
    Serial.println("error opening "+ filename + ".txt");
  }
  
 //  delay(BNO055_SAMPLERATE_DELAY_MS);
}

another problem is in the rewritefile part In setup(). in this part, the arduino is intended to overwrite the existing number in var file with var file plus one, or what the next file read should be. And somehow, it does open the file this time, and writes to it. only, when it writes, it doesn’t overwrite, it just appends. Why would that be?

Thank you for reading this hole very long question in it’s entirety, And I hope you can answer one of these questions, but either way, thank you.

Sincerely,

a very confused

the Hermanoid, age 12.

From the SD library online documentation:

https://www.arduino.cc/en/Reference/SDCardNotes

File Naming

FAT file systems have a limitation when it comes to naming conventions. You must use the 8.3 format, so that file names look like “NAME001.EXT”, where “NAME001” is an 8 character or fewer string, and “EXT” is a 3 character extension. People commonly use the extensions .TXT and .LOG. It is possible to have a shorter file name (for example, mydata.txt, or time.log), but you cannot use longer file names. Read more on the 8.3 convention.

My guess is it cannot find the file “var file.txt” because it has a space in it. I don’t have experience with the sd library, but back in the DOS/FAT16 days spaces didn’t do well in 8.3 files. Where as modern OS-es can handle longer filenames with various character sets without problems.

Also, if the file does exist from your OS point of view try to open it with a Hex-editor to see exactly which characters are stored in it. There may be corruption of the text going on preventing proper filename creation or recognition.

And since you are logging debug messages to the serial port, please post that data too! It may help us in figuring out what goes wrong. Now we need to guess what the code receives as input data and what it is doing with that.

https://en.wikipedia.org/wiki/8.3_filename

Spaces are indeed disallowed in 8.3 filenames.

Thank you valen, thank was 1 of the things wrong.

I asked a techy friend of mine and he pointed out that I initialize the card after I read out the sensor, which happens after all of the reading off of var file (I renamed it varifile) So I fixed that and It reads varifile nicely.It even started overwriting data on varifile when varifile updates instead of appending, although I don’t get quite how.

Sorry to all about not adding in the serial window output, here is what it looks like now after changing the initialization:

Orientation Sensor Test

1

read6 from varifile.txt


Sensor: BNO055

Driver Ver: 1

Unique ID: 55

Max Value: 0.00 xxx

Min Value: 0.00 xxx

Resolution: 0.01 xxx


Initializing SD card…X: 0.0000 Y: 0.0000 Z: 0.0000

X: 0.0000 Y: 0.0000 Z: 0.0000

X: 0.0000 Y: 0.0000 Z: 0.0000

X: 0.0000 Y: 0.0000 Z: 0.0000

(and more sensor data.)

and if anyone whats to see my updated code:

#include <Wire.h>
#include <Adafruit_Sensor.h>
#include <Adafruit_BNO055.h>
#include <utility/imumaths.h>
#include <SPI.h>
#include <SD.h>

const int chipSelect = 10;
String filename = "";

/* This driver uses the Adafruit unified sensor library (Adafruit_Sensor),
   which provides a common 'type' for sensor data and some helper functions.
   
   To use this driver you will also need to download the Adafruit_Sensor
   library and include it in your libraries folder.

   You should also assign a unique ID to this sensor for use with
   the Adafruit Sensor API so that you can identify this particular
   sensor in any data logs, etc.  To assign a unique ID, simply
   provide an appropriate value in the constructor below (12345
   is used by default in this varfile).
   
   Connections
   ===========
   Connect SCL to analog 5
   Connect SDA to analog 4
   Connect VDD to 3-5V DC
   Connect GROUND to common ground
    
   History
   =======
   2015/MAR/03  - First release (KTOWN)
*/

/* Set the delay between fresh samples */
#define BNO055_SAMPLERATE_DELAY_MS (50)
   
Adafruit_BNO055 bno = Adafruit_BNO055(55);
int filenum = 1;
const byte onoff = 9;
const byte RecLED = 8;

/**************************************************************************/
/*
    Displays some basic information on this sensor from the unified
    sensor API sensor_t type (see Adafruit_Sensor for more information)
*/
/**************************************************************************/
void displaySensorDetails(void)
{
  sensor_t sensor;
  bno.getSensor(&sensor);
  Serial.println("------------------------------------");
  Serial.print  ("Sensor:       "); Serial.println(sensor.name);
  Serial.print  ("Driver Ver:   "); Serial.println(sensor.version);
  Serial.print  ("Unique ID:    "); Serial.println(sensor.sensor_id);
  Serial.print  ("Max Value:    "); Serial.print(sensor.max_value); Serial.println(" xxx");
  Serial.print  ("Min Value:    "); Serial.print(sensor.min_value); Serial.println(" xxx");
  Serial.print  ("Resolution:   "); Serial.print(sensor.resolution); Serial.println(" xxx");  
  Serial.println("------------------------------------");
  Serial.println("");
  delay(500);
  Serial.print("Initializing SD card...");

}

/**************************************************************************/
/*
    Arduino setup function (automatically called at startup)
*/
/**************************************************************************/
void setup(void) 
{
   if (!SD.begin(chipSelect)) {
    Serial.println("Card failed, or not present");
    // don't do anything more:
    return;
  }
  Serial.println("card initialized.");
  
  Serial.begin(115200);
  Serial.println("Orientation Sensor Test"); Serial.println("");
  
  /* Initialise the sensor */
  if(!bno.begin())
  {
    /* There was a problem detecting the BNO055 ... check your connections */
    Serial.print("Ooops, no BNO055 detected ... Check your wiring or I2C ADDR!");
    while(1);
    
  }
  pinMode(onoff,INPUT);
  pinMode(RecLED,OUTPUT);
 
 File dataFile = SD.open("varifile.txt");
  Serial.println(dataFile.available());
  // if the file is available, write to it:
  if (dataFile) {
    while (dataFile.available()) {
      char weep = dataFile.read();
      filename += weep;
    }
    dataFile.close();
  }
  // if the file isn't open, pop up an error:
  else {
    Serial.println("error opening varifile.txt");
  }
  Serial.println("read" + filename + " from varifile.txt");
  filenum = filename.toInt();
  filenum++;
  filename = "";
  filename = String(filenum);
  File rewritefile = SD.open("varifile.txt",FILE_WRITE);
  if(rewritefile){
   rewritefile.seek(0);
   rewritefile.print(filenum++);
  }
  rewritefile.close();
 
  delay(1000);
    
  /* Display some basic information on this sensor */
  displaySensorDetails();

  bno.setExtCrystalUse(true);
  digitalWrite(RecLED,HIGH);
  
}

/**************************************************************************/
/*
    Arduino loop function, called once 'setup' is complete (your own code
    should go here)
*/
/**************************************************************************/
void loop(void) 
{
  if(digitalRead(onoff) == HIGH){
    digitalWrite(RecLED,LOW);
    delay(1000);
    while(digitalRead(onoff)==LOW);
    filenum++ ; 
    filename = String(filenum);
    Serial.println("restarting on file " + filename + ".txt");
    File filefile = SD.open("varifile.txt",FILE_WRITE);
     filefile.seek(0);
     filefile.print(filenum);
    filefile.close();
    
    
  }
  /* Get a new sensor event */ 
  sensors_event_t event; 
  bno.getEvent(&event);
  String dataString = "";
  /* Display the floating point data */
  Serial.print("X: ");
  Serial.print(event.orientation.x, 4);
  dataString += " X: ";
  dataString += event.orientation.x, 4;
  Serial.print("\tY: ");
  Serial.print(event.orientation.y, 4);
  dataString += " Y: ";
  dataString += event.orientation.y, 4;
  Serial.print("\tZ: ");
  Serial.print(event.orientation.z, 4);
  dataString += " Z: ";
  dataString += event.orientation.z, 4;
  Serial.println("");
   File dataFile = SD.open(filename +".txt", FILE_WRITE);

   //if the file is available, write to it:
    if(dataFile) {
    dataFile.println(dataString);
    dataFile.close();
  }
  // if the file isn't open, pop up an error:
   else {
    Serial.println("error opening "+ filename + ".txt");
  }
  
 //  delay(BNO055_SAMPLERATE_DELAY_MS);
}

So now that the SD card has been figured out, I have another off-topic-but-still-the-same-project-question.

I know a Sparkfun forum is no place to be asking about adafruit stuff, but does anyone know how to get G-forces and speed from the adafruit absolute IMU?

Thank you,

The hermanoid, age 12.

hermanoid:
Thank you valen, thank was 1 of the things wrong.

I asked a techy friend of mine and he pointed out that I initialize the card after I read out the sensor, which happens after all of the reading off of var file (I renamed it varifile) So I fixed that and It reads varifile nicely.It even started overwriting data on varifile when varifile updates instead of appending, although I don’t get quite how.

When opening a file I suppose it starts writing at the beginning of it. If you want to append to it then after opening the file you should go to the end of the file and start writing from there. The functions (or class methods I suppose) position and size should help with that.

https://www.arduino.cc/en/Reference/FileSize

https://www.arduino.cc/en/Reference/FilePosition

I know a Sparkfun forum is no place to be asking about adafruit stuff, but does anyone know how to get G-forces and speed from the adafruit absolute IMU?

Those IMU’s cannot measure linear speed by themselves, only rotational speed. To get linear speed you would need to get the accelerations of each axis, multiply each of them by the time step, and add each to the current speed variable (of that axis). Then you use the Pythagoras formula to calculate the total length of the vector. (did you get that in math class yet?)

For accuracy you want to do this with as short times steps as possible, thus as frequently as possible. As with longer timesteps the accelerations you measure do not represent the actual average acceleration value. Therefore you will add a lot of numbers that are slightly off from actual, and this will introduce errors (differences from actual) in the result. Sooner or later these sums of errors become so great that the calculated speed becomes useless because the accelerometer has a totally different speed or direction. And you will need other methods to re-calibrate or fix the speed.

I don’t have links ready with a better explanation, or tutorials about this. Google will help with that, or just search the Sparkfun forum. Because you are not the first by far that has asked this.

The Bosch BNO055 sensor has the capacity to subtract the gravity vector and give you the resultant linear acceleration vector. However, the accuracy of this operation is so poor that the resulting data cannot be used in most cases to estimate speed and position of a typical robot.

Furthermore for this to work at all, the sensor has to be accurately calibrated, and the Adafruit engineers forgot to write the code to access the on-chip calibration functions. Someone posted a clunky mod on the Adafruit user forum to do so, but I just discovered it, and have not yet been able to get it to work.

For more info on the capabilities of the BNO055, see the sensor data sheet, and for a more detailed explanation of why integrating acceleration to get velocity and position doesn’t work with present-day sensors, see http://www.chrobotics.com/library/accel … n-velocity (beware a few numerical errors in the Table).

If you want to use your SparkFun sensor stick with state of the art software, see the open source contributions from RichardsTech, which support it. https://github.com/richards-tech/RTIMULib-Arduino

I posted a how to for using this package with the Pololu AltIMU10 here: http://forum.pololu.com/viewtopic.php?f=32&t=9833