Hi! I have an issue with my SD Card that I just can't figure out. I have tried this code with an arduino mega and leonardo and they both have stopped uploading data to the SD card after an hour or two when the computer is unplugged from the device. The board is connected to a 5V ready mico-sd breakout board, a sparkfun rtc module, an sdi12 sensor, and a digital temperature sensor. I have tried using the SD card library and have tried to change everything I can from strings to char but the sdi12 sensor requires some things in String format. Let me know if you have any idea what could be wrong.
Here is my code:
#include <Arduino.h>
#include <EEPROM.h>
#include <Wire.h>
#include <SDI12.h>
#include <SPI.h>
#include <OneWire.h>
#include <DallasTemperature.h>
#include <SdFat.h>
#include <SparkFunDS1307RTC.h>
#define ONE_WIRE_BUS 9
#define SERIAL_BAUD 115200 /*!< The baud rate for the output serial port */
#define DATA_PIN 11 /*!< The pin of the SDI-12 data bus */
#define POWER_PIN -1 /*!< The sensor power pin (or -1 if not switching power) */
extern unsigned int __bss_end;
extern unsigned int __heap_start;
extern void *__brkval;
OneWire oneWire(ONE_WIRE_BUS);
DallasTemperature sensors(&oneWire);
SDI12 mySDI12(DATA_PIN);
char c[] = "";
const int chipSelect = 53;
int k = 0;
const char space[] = " "; //used fof all the spaces
static int8_t lastSecond = -1;
//char fileName[9] = "data.txt";
String temp = "";
float result = 0;
SdFat sd;
SdFile file;
uint8_t numSensors = 0;
// keeps track of active SDI12 addresses
bool isActive[64] = {
0,
};
//------------free memory function-------------
int freeMemory() {
int free_memory;
if((int)__brkval == 0)
free_memory = ((int)&free_memory) - ((int)&__bss_end);
else
free_memory = ((int)&free_memory) - ((int)__brkval);
return free_memory;
}
//--------------------------decimal to char--------------------------
char decToChar(byte i) {
if (i < 10) return i + '0';
if ((i >= 10) && (i < 36)) return i + 'a' - 10;
if ((i >= 36) && (i <= 62))
return i + 'A' - 36;
else
return i;
}
//---------------------checks active sdi12 sensors------------------------
boolean checkActive(char i) {
String myCommand = "";
myCommand = "";
myCommand += (char)i; // sends basic 'acknowledge' command [address][!]
myCommand += "!";
for (int j = 0; j < 3; j++) { // goes through three rapid contact attempts
mySDI12.sendCommand(myCommand);
delay(100);
if (mySDI12.available()) { // If we here anything, assume we have an active sensor
mySDI12.clearBuffer();
return true;
}
}
mySDI12.clearBuffer();
return false;
}
//---------------char to string-----------
String convertToString(char* a)
{
int i;
String s = "";
int size = strlen(a);
for (i = 0; i < size-2; i++) {
s = s + a[i];
}
return s;
}
//----------sdi12 repeated function for 1M1!--------------
String getsdi(char i, String meas_type, char sdiResponse, uint8_t cmd_number){
int numResults = 0;
mySDI12.clearBuffer();
String command = "";
command += i;
command += "M";
command += meas_type;
command += "!";
//Serial.println(command);
mySDI12.sendCommand(command);
delay(100);
String sdi= mySDI12.readStringUntil('\n');
Serial.print(sdi);
sdi.trim();
String sdiResponse2 = sdi.substring(0,1);
Serial.print(sdiResponse2); //address
Serial.print(", ");
uint8_t wait = sdi.substring(1, 4).toInt();
Serial.print(wait);
Serial.print(", ");
sdiResponse2 = sdiResponse2 + ", " + sdi.substring(1, 4); //address, wait_time
numResults = sdi.substring(4).toInt();
Serial.print(numResults);
Serial.print(", ");
sdiResponse2 = sdiResponse2 + ", " + sdi.substring(4); //address, wait_time, number of results
unsigned long timerStart = millis();
while ((millis() - timerStart) < (1000UL * (wait + 1))) {
if (mySDI12.available()) // sensor can interrupt us to let us know it is done early
{
Serial.print(millis() - timerStart);
Serial.print(", ");
mySDI12.clearBuffer();
break;
}
}
delay(30);
mySDI12.clearBuffer();
if(numResults >0) {
return getResults(i, numResults, sdiResponse2, cmd_number);
}
String sdiString = convertToString(sdiResponse);
return sdiString;
}
///---------1D0! part of sdi12 response--------------------------------------------------------
String getResults(char i, int resultsExpected, String sdiResponse, uint8_t cmd_number) {
result = 0;
int pointer = 0;
int a = 0;
String sdiString;
String sdiResponse2;
uint8_t resultsReceived = 0;
while(resultsReceived < resultsExpected && cmd_number<=9){
String command = "";
command = "";
command += i;
command += "D";
command += cmd_number;
command += "!";
mySDI12.sendCommand(command);
uint32_t start = millis();
while(mySDI12.available() < 3 && (millis() - start) <1500){}
mySDI12.read();
char c = mySDI12.peek();
if(c == '+') {mySDI12.read(); }
while(mySDI12.available()) {
char c = mySDI12.peek();
if(c == '-' || (c >= '0' && c <= '9') || c == '.'){
float result = mySDI12.parseFloat(SKIP_NONE);
Serial.print(String(result, 10));
if(pointer == 0)
{
sdiString = sdiResponse;
sdiResponse2 = sdiString + ", " + String(result, 5);
}else{
sdiResponse2 = (sdiResponse2) + ", " + String(result, 5);
}
if(result != -9999) {resultsReceived++; }
}else if(c== '+'){
mySDI12.read();
Serial.print(", ");
pointer = pointer + 1;
}else{
mySDI12.read();
}
delay(10);
}
if(resultsReceived < resultsExpected) {Serial.print(", ");}
cmd_number=cmd_number + 1;
}
mySDI12.clearBuffer();
return sdiResponse2;
}
//-----------------------------------------------------------------
String printTime(){
String timee = String(rtc.hour()) + ":";
//rtc.autoTime();
if (rtc.minute() < 10){
timee.concat("0");
}
timee.concat(String(rtc.minute()));
timee.concat(":");
if (rtc.second() < 10){
timee.concat("0");
}
timee.concat(String(rtc.second()));
timee.concat(" , ");
timee.concat(String(rtc.month()));
timee.concat("/");
timee.concat(String(rtc.date()));
timee.concat("/");
timee.concat(String(rtc.year()));
return(timee);
}
//----------------------------------------------
void printInfo(char i) {
String command = "";
command += (char)i;
command += "I!";
mySDI12.sendCommand(command);
delay(100);
String sdiResponse = mySDI12.readStringUntil('\n');
sdiResponse.trim();
// allccccccccmmmmmmvvvxxx...xx<CR><LF>
Serial.print(sdiResponse.substring(0, 1)); // address
Serial.print(", ");
Serial.print(sdiResponse.substring(1, 3).toFloat() / 10); // SDI-12 version number
Serial.print(", ");
Serial.print(sdiResponse.substring(3, 11)); // vendor id
Serial.print(", ");
Serial.print(sdiResponse.substring(11, 17)); // sensor model
Serial.print(", ");
Serial.print(sdiResponse.substring(17, 20)); // sensor version
Serial.print(", ");
Serial.print(sdiResponse.substring(20)); // sensor id
Serial.print(", ");
}
//-----------------------------------------------------
void setup(void) {
char on[23] = "Opening SDI-12 bus...";
char powerup[23] = "Powering up sensors...";
char initialize[25] = "Initializing SD card...";
char fail[27] = "Card failed or not present";
char success[] = "Card initiliazed.";
char num_sense[] = "Total number of sensors: ";
int k =0;
Serial.begin(SERIAL_BAUD);
Wire.begin();
delay(300);
sensors.begin();
mySDI12.begin();
Serial.println(on);
Serial.print(initialize);
//see if card is present
if(sd.begin(53, SPI_HALF_SPEED)){
Serial.println(success);
}else{
Serial.println(fail);
}
delay(2000);
rtc.begin();
rtc.autoTime();
//rtc.setTime(0, 10, 35, 04, 06, 07, 2022);
delay(2000);
//SPI.begin();
while(!Serial)
;
delay(500);
if (POWER_PIN > 0) { //if power pin is on (>0) then it should be put as that
Serial.println(powerup);
pinMode(POWER_PIN, OUTPUT);
digitalWrite(POWER_PIN, HIGH); //writing a high or low value to the power pin
delay(200);
}
for (byte i = 0; i < 62; i++) {
char addr = decToChar(i);
if (checkActive(addr)) {
numSensors++;
isActive[i] = 1;
printInfo(addr);
Serial.println();
}
}
Serial.print(num_sense);
Serial.println(numSensors);
}
void loop(void ) {
char wiper[] = "";
const char rtcFail[22] = "RTC get datetime fail";
int hour, minute, second, day, month, year = 0;
String datatime = "";
char myCommand[4] = "1M!";
char sdiResponse[100];
if(file.open("data.csv", O_CREAT | O_WRITE | O_APPEND)){
if(k==0){
file.println("Time (hour:min:sec, month/day/year, Temperature, sensor address, est. measuring time, number of measurements, measurement 1, measurement 2, SRAM available");
}
rtc.update();
datatime = printTime();
file.print(datatime);
Serial.print(datatime);
file.print(", ");
Serial.print(", ");
sensors.requestTemperatures();
delay(1000);
float temp = sensors.getTempCByIndex(0);
file.print(temp);
Serial.print(temp);
file.print(", ");
Serial.println(", ");
digitalWrite(LED_BUILTIN, HIGH);
String commands[] = {"", "1", "2", "3", "4", "5", "6", "7", "8", "9"};
for (uint8_t a = 0; a < 1; a++) {
// measure one at a time
for (byte i = 0; i < 62; i++) {
char addr = decToChar(i);
if (isActive[i]) {
Serial.print(millis() / 1000);
Serial.print(millis());
Serial.print(", ");
String temp0 = getsdi(addr, commands[a], sdiResponse, 0);
int str_len = temp0.length() + 1;
temp0.toCharArray(sdiResponse, str_len);
}
}
}
Serial.print(sdiResponse);
file.print(sdiResponse);
Serial.print(", ");
file.print(", ");
int memory_available = freeMemory();
Serial.print(memory_available);
file.print(memory_available);
file.println();
if(k==100){
k = 0;
file.sync();
}
file.close();
Serial.println();
k= k+1;
}else{
Serial.println("Failed to open the file");
while(!sd.begin()){
delay(1000);
Serial.println("Starting SD");
}
}
delay(30000);
}