SD card removal during run time

Adafruit Ethernet, Motor, Proto, Wave, Datalogger, GPS Shields - etc!

Moderators: adafruit_support_bill, adafruit

Please be positive and constructive with your questions and comments.
Locked
User avatar
mromero
 
Posts: 94
Joined: Fri Mar 18, 2016 12:10 pm

SD card removal during run time

Post by mromero »

I am running an adafruit datalogger shield with an Metro 328 arduino. I would like to runtime remove the SD card for reading. Ideally while program is running i can remove the SD card read it, put back on the arduino and it keeps collecting data. Every time i have tried my program i can remove the SD card but when i put it back in on a running arduino with datalogger it cant write to the card anymore? I can see the data correctly on the serial but keep getting " error opening data.txt". Is my only option to resend the program every time i remove the SD card for reading on the computer or is there code i can add to the program below so it continues where it left off? Also do i need to power down the arduino to prevent corruption of the SD card?

Code: Select all

#include <SD.h>//sd card
#include <Wire.h>
#include <SPI.h>
#include <RTClib.h>// clock
#include <Adafruit_Sensor.h>
#include <Adafruit_BME280.h>

#define SEALEVELPRESSURE_HPA (1013.25)

Adafruit_BME280 bme; // I2C for T, RH, altitude, atm press
RTC_PCF8523 rtc;// clock on datalogger

// create file
File myFile;
String Date,Time,Temperature, Pressure, Altitude, Humidity, Data;


///----------------------------------------------------------------------------
void setup() {

  //start clock
  rtc.begin();
  
  Serial.begin(115200);
  delay(2000);
  
 //clock 
 if (! rtc.begin()) {
    Serial.println("Couldn't find RTC");
    Serial.flush();
    while (1) delay(10);
  }
    if (! rtc.isrunning()) {
    Serial.println("RTC is NOT running, let's set the time!");
    // When time needs to be set on a new device, or after a power loss, the
    // following line sets the RTC to the date & time this sketch was compiled
    rtc.adjust(DateTime(F(__DATE__), F(__TIME__)));
    // This line sets the RTC with an explicit date & time, for example to set
    // January 21, 2014 at 3am you would call:
    // rtc.adjust(DateTime(2014, 1, 21, 3, 0, 0));
  }


  //bme280 sensor
  unsigned status;
 
  status = bme.begin();
    
  if (!status) {
    Serial.println("BME280 not connected properly. Check circuit!");
    while (1); 
  }
  Serial.print("Initializing SD card...");
  if (!SD.begin(10)) {
    Serial.println("initialization failed!");
    while (1);
  }
  Serial.println("initialization done.");
  myFile = SD.open("data.txt", FILE_WRITE); 
  if (myFile) {
    myFile.println( "Date, Time, Temperature(°C), Pressure(hPa), Altitude(m), Humidity(%) \r\n");
    myFile.close();
  } 
  else {
    Serial.println("error opening data.txt");
  }
 
}//---------------close void setup()-----------------------------------
 

User avatar
adafruit_support_bill
 
Posts: 88096
Joined: Sat Feb 07, 2009 10:11 am

Re: SD card removal during run time

Post by adafruit_support_bill »

Please post your complete code so we can see what the loop() function does.

User avatar
mromero
 
Posts: 94
Joined: Fri Mar 18, 2016 12:10 pm

Re: SD card removal during run time

Post by mromero »

Code: Select all

#include <SD.h>//sd card
#include <Wire.h>
#include <SPI.h>
#include <RTClib.h>// clock
#include <Adafruit_Sensor.h>
#include <Adafruit_BME280.h>

#define SEALEVELPRESSURE_HPA (1013.25)

Adafruit_BME280 bme; // I2C for T, RH, altitude, atm press
RTC_PCF8523 rtc;// clock on datalogger

// create file
File myFile;
String Date,Time,Temperature, Pressure, Altitude, Humidity, Data;


///----------------------------------------------------------------------------
void setup() {

  //start clock
  rtc.begin();
  
  Serial.begin(115200);
  delay(2000);
  
 //clock 
 if (! rtc.begin()) {
    Serial.println("Couldn't find RTC");
    Serial.flush();
    while (1) delay(10);
  }
    if (! rtc.isrunning()) {
    Serial.println("RTC is NOT running, let's set the time!");
    // When time needs to be set on a new device, or after a power loss, the
    // following line sets the RTC to the date & time this sketch was compiled
    rtc.adjust(DateTime(F(__DATE__), F(__TIME__)));
    // This line sets the RTC with an explicit date & time, for example to set
    // January 21, 2014 at 3am you would call:
    // rtc.adjust(DateTime(2014, 1, 21, 3, 0, 0));
  }


  //bme280 sensor
  unsigned status;
 
  status = bme.begin();
    
  if (!status) {
    Serial.println("BME280 not connected properly. Check circuit!");
    while (1); 
  }
  Serial.print("Initializing SD card...");
  if (!SD.begin(10)) {
    Serial.println("initialization failed!");
    while (1);
  }
  Serial.println("initialization done.");
  myFile = SD.open("data.txt", FILE_WRITE); 
  if (myFile) {
    myFile.println( "Date, Time, Temperature(°C), Pressure(hPa), Altitude(m), Humidity(%) \r\n");
    myFile.close();
  } 
  else {
    Serial.println("error opening data.txt");
  }
 
}//---------------close void setup()-----------------------------------


void loop() { //-------------------------------------------------------


   

  // make a string for assembling the data to log:
     data_logging();
     
     delay(20000);//time between writting to sd card: delay(ms) 1000=1sec ; 900,000=15 min use this for final use 20,000 for testing
    
}//----------------close void loop()----------------------------------

//--------------------subroutines------------------------------------

void data_logging() {


  String Temperature = String(bme.readTemperature(), 2);
  String Pressure = String(bme.readPressure()/ 100.0F, 2);
  String Altitude = String(bme.readAltitude(SEALEVELPRESSURE_HPA), 2);
  String Humidity = String(bme.readHumidity(), 2);
 
  
  Data = Temperature + "," + Pressure + "," + Altitude + "," + Humidity ;
  Serial.print("Save data: ");
  Serial.println(Data);

  myFile = SD.open("data.txt", FILE_WRITE);
  if (myFile) {
    Serial.print("Writing to data.txt...");
    
    //time stamp
    DateTime now = rtc.now();
    myFile.print(now.year(), DEC);
    myFile.print('/');
    myFile.print(now.month(), DEC);
    myFile.print('/');
    myFile.print(now.day(), DEC);
    myFile.print(",");
    myFile.print(now.hour(), DEC);
    myFile.print(':');
    myFile.print(now.minute(), DEC);
    myFile.print(",");//delimeter between time and data
    //
    myFile.println(Data);//ln adds carriage return
    myFile.close();
    Serial.println("done.");
  } else {
    Serial.println("error opening data.txt");
  }  
  Serial.println();
} 

User avatar
mromero
 
Posts: 94
Joined: Fri Mar 18, 2016 12:10 pm

Re: SD card removal during run time

Post by mromero »

the output for this code is weird the data is wrong and the altitude is negative

Image
Attachments
data output.png
data output.png (17.74 KiB) Viewed 150 times

User avatar
adafruit_support_bill
 
Posts: 88096
Joined: Sat Feb 07, 2009 10:11 am

Re: SD card removal during run time

Post by adafruit_support_bill »

If you pull the card in the middle of the write, you will most likely corrupt it. Your loop has 20 seconds between writes, so the odds are relatively small, but it is still possible to corrupt the card.

In any case, once you re-insert the card, you need to re-initialize it. One way is to press the reset button after re-inserting the card. That will re-run setup() and start over.

A more graceful way is to call the SD.end() function when the card is removed and call SD.begin() again when it is re-inserted.

There is a thread on the subject here in the Arduino forum:
https://forum.arduino.cc/t/sd-eject-re- ... n/610784/7

Locked
Please be positive and constructive with your questions and comments.

Return to “Arduino Shields from Adafruit”