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?
#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()-----------------------------------
#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();
}
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.