SD card issue

Hi everyone,

I have a simple code that can open an SD card, write data to it, then close the SD card.

But what I want to achieve is to open the SD card early on, then do a for loop for 50 samples writing 50 bits of data, then close the SD card once all the samples have been written.

I gave this a go but when I separate the open/write/close operations it returns an error saying 'logFile' not declared in this scope. Any help?

This is the simple code to open/write/close the SD card, but i want to separate the open and close operations from the write.

  File logFile = SD.open("TEST12.csv", FILE_WRITE);
  logFile.print(dataString);
  logFile.print(time);
  logFile.print(", ");
  logFile.print(a);
  logFile.print(", ");
  logFile.println(x);
  logFile.close();

Is there a different syntax for writing to an open file? I don't see how the code should vary from above. Sorry for the noobie question, thanks for any help!

I want to do this to try and save time and sample/write data at a faster rate. I did some tests with time stamps and found the time taken to open and close it was larger than purely the write operation.

Thanks!

It depends how you split your code. So please show your attempt (complete).

The below will write 50 times the same line :wink:

  File logFile = SD.open("TEST12.csv", FILE_WRITE);
  if(logFile != NULL)
  {
    for(int cnt = 0; cnt<50;cnt++)
    {
      logFile.print(dataString);
      logFile.print(time);
      logFile.print(", ");
      logFile.print(a);
      logFile.print(", ");
      logFile.println(x);
    }
    logFile.close();
  }

I gave this a go but when I separate the open/write/close operations it returns an error saying 'logFile' not declared in this scope. Any help?

Can you please provide a small test sketch which demonstrates the problem.

I did some tests with time stamps and found the time taken to open and close it was larger than purely the write operation.

What data are you attempting to log, and what are the requirements? How much data and how fast is it coming?

Do you understand that the data to be written is buffered, and only physically written the card on a file.close (or file.flush). The max buffer size is 512 bytes, and the fastest logging routines have multiple buffers, and block writes of full buffers.

SdFat.h is faster than the IDE SD.h library, and you may want to take a look at it. It contains several examples of fast logging.

So heres my code…

// 14.4Hz sample rate

#include <SD.h>
#include <Wire.h>
#include <Adafruit_BMP085.h>
Adafruit_BMP085 bmp;
float a;
float p=1;
float q=0.1;
float k=0.5;
float r=10;
float x=0;
int id = 1;
int buttonpin = 7;
int ledpin = 5;
int active = 0;
int samples = 50;
int CS_pin = 10;
int pow_pin = 8;

void setup() 
{
  
  Serial.begin(9600);
  if (!bmp.begin()) {
    Serial.println("Could not find a valid BMP085 sensor, check wiring!");
    while (1) {
    }
  }
  pinMode(CS_pin, OUTPUT);
  pinMode(pow_pin, OUTPUT);
  digitalWrite(pow_pin, HIGH);
  pinMode(buttonpin, INPUT);
  pinMode(ledpin, OUTPUT);
  
  File logFile = SD.open("TEST12.csv", FILE_WRITE);
 if(logFile)
 {
  String header = "ID, Time (s), Altitude (m)";
  logFile.println(header); 
  logFile.close();
 }
  
}

void loop() {
  
  int buttonstate = digitalRead(buttonpin);
  
  if (buttonstate == 1 && active ==0)
  {
    active = 1;
    delay(400);
    File logFile = SD.open("TEST12.csv", FILE_WRITE);
   
  }
  
  if (active ==1 && id<samples)
  {
    digitalWrite(ledpin, HIGH);
  }
  else{
    digitalWrite(ledpin, LOW);
  }
  
  if (id<samples && active==1)
  {
  float time = millis();
  float clock =time/1000;
  String dataString = String(id) + ", ";
  a = bmp.readAltitude(bmp.readPressure());
  Serial.print("Real altitude = ");
  Serial.print(a);
  Serial.print(" meters");
  
  p=p+q;
  k=p/(p+r);
  x=x+k*(a-x);
  p=(1-k)*p;
  
  
  logFile.print(dataString);
  logFile.print(time);
  logFile.print(", ");
  logFile.print(a);
  logFile.print(", ");
  logFile.println(x);
  
  
  Serial.print(", ");
  Serial.print(x);
  Serial.print(", ");
  Serial.println(clock);
  id=id+1;
  }
  
  if(id==samples-1){
    logFile.close();
  }
}

If i put the ‘open’ and ‘close’ operation either side of the ‘write’ part then it works fine. The code basically takes an altitude reading and writes it to the SD card. With the current setup i was getting around 14Hz which is quite good but i was looking for a bit faster which would allow me to do other things.

From your last code

void loop() {

  int buttonstate = digitalRead(buttonpin);

  if (buttonstate == 1 && active == 0)
  {
    active = 1;
    delay(400);
    File logFile = SD.open("TEST12.csv", FILE_WRITE);

  }

logFile is only known within the if.

void loop() {

  static File logFile = NULL;
  int buttonstate = digitalRead(buttonpin);

  if (buttonstate == 1 && active == 0)
  {
    active = 1;
    delay(400);
    // only open if n ot open yet
    if(logFile == NULL)
      logFile = SD.open("TEST12.csv", FILE_WRITE);

  }
  ...
  ...

  if (id == samples - 1)
  {
    logFile.close();
    logFile = NULL;
  }

You might want to add some more checking to make sure that you don't attempt to write if logFile is NULL (e.g. because the file could not be opened).

The declaration (instantiation) of File logFile is not done correctly and you are getting scope issues. Do it once at the head of the file, and then just use logFile. You want to check if the 50 samples are going to fill a 512 byte buffer.

// 14.4Hz sample rate

#include <SD.h>
#include <Wire.h>
#include <Adafruit_BMP085.h>
Adafruit_BMP085 bmp;
float a;
float p = 1;
float q = 0.1;
float k = 0.5;
float r = 10;
float x = 0;
int id = 1;
int buttonpin = 7;
int ledpin = 5;
int active = 0;
int samples = 50;
int CS_pin = 10;
int pow_pin = 8;

File logFile; //add this here

void setup()
{

  Serial.begin(9600);
  if (!bmp.begin()) {
     Serial.println("Could not find a valid BMP085 sensor, check wiring!");
    while (1) {
     }
   }
  pinMode(CS_pin, OUTPUT);
  pinMode(pow_pin, OUTPUT);
  digitalWrite(pow_pin, HIGH);
  pinMode(buttonpin, INPUT);
  pinMode(ledpin, OUTPUT);

  //File logFile = SD.open("TEST12.csv", FILE_WRITE);
  logFile = SD.open("TEST12.csv", FILE_WRITE);
  if (logFile)
  {
    String header = "ID, Time (s), Altitude (m)";
    logFile.println(header);
    logFile.close();
  }
}

void loop() {

  int buttonstate = digitalRead(buttonpin);

  if (buttonstate == 1 && active == 0)
  {
    active = 1;
    delay(400);
    //File logFile = SD.open("TEST12.csv", FILE_WRITE);
    logFile = SD.open("TEST12.csv", FILE_WRITE);

  }

  if (active == 1 && id < samples)
  {
    digitalWrite(ledpin, HIGH);
  }
  else {
    digitalWrite(ledpin, LOW);
  }

  if (id < samples && active == 1)
  {
    float time = millis();
    float clock = time / 1000;
    String dataString = String(id) + ", ";
     a = bmp.readAltitude(bmp.readPressure());
    Serial.print("Real altitude = ");
    Serial.print(a);
    Serial.print(" meters");

    p = p + q;
    k = p / (p + r);
    x = x + k * (a - x);
    p = (1 - k) * p;


    logFile.print(dataString);
    logFile.print(time);
    logFile.print(", ");
    logFile.print(a);
    logFile.print(", ");
    logFile.println(x);


    Serial.print(", ");
    Serial.print(x);
    Serial.print(", ");
    Serial.println(clock);
    id = id + 1;
   
  }

   if(id==samples-1){
      logFile.close();
    }
}