Problem

Hi,

I have three Arduinos (mega) with me now. Following code is working smoothly on 2 of them but one stops responding after printing header.
Problem here is, this faulty Arduino runs the other examples codes (like LED blink and other small codes) but not this.
What possibly went wrong? I also have checked SD card with other ones, there isn't any problem.
Any idea?

thanks.

Z

#include <SD.h>
#include <Wire.h>
#include <SPI.h>
int CS_pin = 4;
int SD_led = 8;
#include "floatToString.h"
#include "RTClib.h"
RTC_DS1307 RTC;
float COValue = 0;
float NO2Value = 0;
float O3Value = 0;
float e_NO2Value = 0;
float e_NOValue = 0;
float e_COValue = 0;
float celsius = 0, kelvin=0;
#include <math.h>
int dustPin=0;
int ledPower=2;
int delayTime=280;
int delayTime2=40;
float offTime=9680;
float ZeroPercentVoltage = 0.8;
float val = 0;
float RH = 0;
float max_voltage = 3.27;

void setup()
{
  Wire.begin();
  Serial.begin(9600);
  SPI.begin();
  Serial.println("Initializing Card");
  pinMode(53, OUTPUT);
  //digitalWrite(53, HIGH);
  RTC.begin();
  pinMode(ledPower,OUTPUT);
  pinMode(5, OUTPUT);
  if (!SD.begin(CS_pin))
  {
      Serial.println("Card Failure");
      return;
  }
  Serial.println("Card Ready");
  
  //Write Log File Header
  File logFile = SD.open("LOG.csv", FILE_WRITE);
  if (logFile)
  {
    logFile.println(", , , , , , , , ,"); //Just a leading blank line, incase there was previous data
    String header = "Date_Time, Temp, Humidity(%), e_NO2_Vout, e_NO_Vout, e_CO_Vout, CO_Vout, NO2_Vout, O3_Vout, Dust_Vout";
    logFile.println(header);
    logFile.close();
    Serial.println(header);
  }
  else
  {
    Serial.println("Couldn't open log file");
  }
  
}

void loop()
{
  
  char* date_time = (char*) calloc(80,sizeof(char));
  char* CO_Vout = (char*) calloc(80,sizeof(char));
  char* NO2_Vout = (char*) calloc(80,sizeof(char));
  char* O3_Vout = (char*) calloc(80,sizeof(char));
  char* cel = (char*) calloc(80,sizeof(char));
  char* hum = (char*) calloc(80,sizeof(char));
  char* e_NO2_Vout = (char*) calloc(80,sizeof(char));
  char* e_NO_Vout = (char*) calloc(80,sizeof(char));
  char* e_CO_Vout = (char*) calloc(80,sizeof(char));
  
  NO2Value = analogRead(1) * 0.004882812;
  COValue = analogRead(2) * 0.004882812;
  O3Value = analogRead(3) * 0.004882812;
  
  kelvin = analogRead(4) * 0.004882812 * 100;
  celsius = (kelvin - 273.15) - 15;
  
  val = analogRead(5);
  max_voltage = (3.27-(0.006706*celsius));
  RH = ((((val/1023)*5)-ZeroPercentVoltage)/max_voltage)*100;
  
  digitalWrite(ledPower,LOW);
  delayMicroseconds(delayTime);
  int dust_Vout = analogRead(dustPin);
  delayMicroseconds(delayTime2);
  digitalWrite(ledPower,HIGH);
  delayMicroseconds(offTime);
  
  e_NO2Value = analogRead(8) * 0.004882812;
  e_NOValue = analogRead(9) * 0.004882812;
  e_COValue = analogRead(10) * 0.004882812;
  
  floatToString(CO_Vout, COValue, 8);
  floatToString(NO2_Vout, NO2Value, 8);
  floatToString(O3_Vout, O3Value, 8);
  floatToString(cel, celsius, 1);
  floatToString(hum, RH, 1);
  floatToString(e_NO2_Vout, e_NO2Value, 8);
  floatToString(e_NO_Vout, e_NOValue, 8);
  floatToString(e_CO_Vout, e_COValue, 8);
  
  DateTime now = RTC.now();
  sprintf(date_time,"%d/%d/%d %d:%d:%d",now.day(),now.month(),now.year(),now.hour(),now.minute(),now.second());
  String dataString = String(date_time) + ", " + String(cel) + ", " + String(hum) + ", " + String(e_NO2_Vout) + ", " + String(e_NO_Vout) + ", " + String(e_CO_Vout) + ", " + String(CO_Vout) + ", " + String(NO2_Vout) + ", " + String(O3_Vout) + ", " + String(dust_Vout); 
  // String dataString = String(date_time) + ", " + String(cel) + ", " + String(hum) + ", " + String(CO_Vout) + ", " + String(NO2_Vout) + ", " + String(O3_Vout) + ", " + String(dust_Vout); 
  File logFile = SD.open("LOG.csv", FILE_WRITE);
  if (logFile)
  {
    logFile.println(dataString);
    logFile.close();
    Serial.println(dataString);
    pinMode(SD_led, OUTPUT);
    digitalWrite(SD_led, HIGH);
  }
  else
  {
    Serial.println("Couldn't open log file");
  }
  
  delay(60000);
  digitalWrite(SD_led, LOW);
  
  free(date_time);
  date_time = NULL;
  
  free(CO_Vout);
  CO_Vout = NULL;
  
  free(NO2_Vout);
  NO2_Vout = NULL;
  
  free(O3_Vout);
  O3_Vout = NULL;
  
  free(cel);
  cel = NULL;
  
  free(hum);
  hum = NULL;
  
  free(e_NO2_Vout);
  e_NO2_Vout = NULL;
  
  free(e_NO_Vout);
  e_NO_Vout = NULL;
  
  free(e_CO_Vout);
  e_CO_Vout = NULL;
}

I'm wondering why you are dynamically allocating and freeing memory on every pass through loop. You never check that the allocations actually succeed. You simply assume that they did.

Since you need all the allocations to succeed, and since the sizes are constant, static arrays seem a much better fit. Then, the compiler will tell you if there is a problem.

Of course, a size of 80 bytes when you then store 8 bytes in the string seems a waste, as does the overuse of the String class.

Thanks Paul,
Actually I was static allocation in the beginning but then I changed to dynamic only for testing.
Here is the code.

#include <SD.h>
#include <Wire.h>
#include <SPI.h>
int CS_pin = 4;
int SD_led = 8;
#include "floatToString.h"
#include "RTClib.h"
RTC_DS1307 RTC;
float COValue = 0;
float NO2Value = 0;
float O3Value = 0;
float e_NO2Value = 0;
float e_NOValue = 0;
float e_COValue = 0;
float celsius = 0, kelvin=0;
#include <math.h>
int dustPin=0;
int ledPower=2;
int delayTime=280;
int delayTime2=40;
float offTime=9680;
float ZeroPercentVoltage = 0.8;
float val = 0;
float RH = 0;
float max_voltage = 3.27;

  char date_time[10];
  char CO_Vout[10];
  char NO2_Vout[10];
  char O3_Vout[10];
  char cel[10];
  char hum[10];
  char e_NO2_Vout[10];
  char e_NO_Vout[10];
  char e_CO_Vout[10];

void setup()
{
  Wire.begin();
  Serial.begin(9600);
  SPI.begin();
  Serial.println("Initializing Card");
  pinMode(53, OUTPUT);
  //digitalWrite(53, HIGH);
  RTC.begin();
  pinMode(ledPower,OUTPUT);
  pinMode(5, OUTPUT);
  if (!SD.begin(CS_pin))
  {
      Serial.println("Card Failure");
      return;
  }
  Serial.println("Card Ready");
  
  //Write Log File Header
  File logFile = SD.open("LOG.csv", FILE_WRITE);
  if (logFile)
  {
    logFile.println(", , , , , , , , ,"); //Just a leading blank line, incase there was previous data
    String header = "Date_Time, Temp, Humidity(%), e_NO2_Vout, e_NO_Vout, e_CO_Vout, CO_Vout, NO2_Vout, O3_Vout, Dust_Vout";
    logFile.println(header);
    logFile.close();
    Serial.println(header);
  }
  else
  {
    Serial.println("Couldn't open log file");
  }
  
}

void loop()
{
  
  char* date_time = (char*) calloc(80,sizeof(char));
  char* CO_Vout = (char*) calloc(80,sizeof(char));
  char* NO2_Vout = (char*) calloc(80,sizeof(char));
  char* O3_Vout = (char*) calloc(80,sizeof(char));
  char* cel = (char*) calloc(80,sizeof(char));
  char* hum = (char*) calloc(80,sizeof(char));
  char* e_NO2_Vout = (char*) calloc(80,sizeof(char));
  char* e_NO_Vout = (char*) calloc(80,sizeof(char));
  char* e_CO_Vout = (char*) calloc(80,sizeof(char));
  
  NO2Value = analogRead(1) * 0.004882812;
  COValue = analogRead(2) * 0.004882812;
  O3Value = analogRead(3) * 0.004882812;
  
  kelvin = analogRead(4) * 0.004882812 * 100;
  celsius = (kelvin - 273.15) - 15;
  
  val = analogRead(5);
  max_voltage = (3.27-(0.006706*celsius));
  RH = ((((val/1023)*5)-ZeroPercentVoltage)/max_voltage)*100;
  
  digitalWrite(ledPower,LOW);
  delayMicroseconds(delayTime);
  int dust_Vout = analogRead(dustPin);
  delayMicroseconds(delayTime2);
  digitalWrite(ledPower,HIGH);
  delayMicroseconds(offTime);
  
  e_NO2Value = analogRead(8) * 0.004882812;
  e_NOValue = analogRead(9) * 0.004882812;
  e_COValue = analogRead(10) * 0.004882812;
  
  floatToString(CO_Vout, COValue, 8);
  floatToString(NO2_Vout, NO2Value, 8);
  floatToString(O3_Vout, O3Value, 8);
  floatToString(cel, celsius, 1);
  floatToString(hum, RH, 1);
  floatToString(e_NO2_Vout, e_NO2Value, 8);
  floatToString(e_NO_Vout, e_NOValue, 8);
  floatToString(e_CO_Vout, e_COValue, 8);
  
  DateTime now = RTC.now();
  sprintf(date_time,"%d/%d/%d %d:%d:%d",now.day(),now.month(),now.year(),now.hour(),now.minute(),now.second());
  String dataString = String(date_time) + ", " + String(cel) + ", " + String(hum) + ", " + String(e_NO2_Vout) + ", " + String(e_NO_Vout) + ", " + String(e_CO_Vout) + ", " + String(CO_Vout) + ", " + String(NO2_Vout) + ", " + String(O3_Vout) + ", " + String(dust_Vout); 
  // String dataString = String(date_time) + ", " + String(cel) + ", " + String(hum) + ", " + String(CO_Vout) + ", " + String(NO2_Vout) + ", " + String(O3_Vout) + ", " + String(dust_Vout); 
  File logFile = SD.open("LOG.csv", FILE_WRITE);
  if (logFile)
  {
    logFile.println(dataString);
    logFile.close();
    Serial.println(dataString);
    pinMode(SD_led, OUTPUT);
    digitalWrite(SD_led, HIGH);
  }
  else
  {
    Serial.println("Couldn't open log file");
  }
  
  delay(60000);
  digitalWrite(SD_led, LOW);
}

But this doesn't solve the problem.

  char* date_time = (char*) calloc(80,sizeof(char));
  char* CO_Vout = (char*) calloc(80,sizeof(char));
  char* NO2_Vout = (char*) calloc(80,sizeof(char));
  char* O3_Vout = (char*) calloc(80,sizeof(char));
  char* cel = (char*) calloc(80,sizeof(char));
  char* hum = (char*) calloc(80,sizeof(char));
  char* e_NO2_Vout = (char*) calloc(80,sizeof(char));
  char* e_NO_Vout = (char*) calloc(80,sizeof(char));
  char* e_CO_Vout = (char*) calloc(80,sizeof(char));

Is still there...

Sorry for that.
I forgot to remove that when I pasted the code for forum.
Just now I burned this 'exact' code in all 3 Arduinos. As before, only 2 are working.

#include <SD.h>
#include <Wire.h>
#include <SPI.h>
int CS_pin = 4;
int SD_led = 8;
#include "floatToString.h"
#include "RTClib.h"
RTC_DS1307 RTC;
float COValue = 0;
float NO2Value = 0;
float O3Value = 0;
float e_NO2Value = 0;
float e_NOValue = 0;
float e_COValue = 0;
float celsius = 0, kelvin=0;
#include <math.h>
int dustPin=0;
int ledPower=2;
int delayTime=280;
int delayTime2=40;
float offTime=9680;
float ZeroPercentVoltage = 0.8;
float val = 0;
float RH = 0;
float max_voltage = 3.27;

  char date_time[10];
  char CO_Vout[10];
  char NO2_Vout[10];
  char O3_Vout[10];
  char cel[10];
  char hum[10];
  char e_NO2_Vout[10];
  char e_NO_Vout[10];
  char e_CO_Vout[10];

void setup()
{
  Wire.begin();
  Serial.begin(9600);
  SPI.begin();
  Serial.println("Initializing Card");
  pinMode(53, OUTPUT);
  //digitalWrite(53, HIGH);
  RTC.begin();
  pinMode(ledPower,OUTPUT);
  pinMode(5, OUTPUT);
  if (!SD.begin(CS_pin))
  {
      Serial.println("Card Failure");
      return;
  }
  Serial.println("Card Ready");
  
  //Write Log File Header
  File logFile = SD.open("LOG.csv", FILE_WRITE);
  if (logFile)
  {
    logFile.println(", , , , , , , , ,"); //Just a leading blank line, incase there was previous data
    String header = "Date_Time, Temp, Humidity(%), e_NO2_Vout, e_NO_Vout, e_CO_Vout, CO_Vout, NO2_Vout, O3_Vout, Dust_Vout";
    logFile.println(header);
    logFile.close();
    Serial.println(header);
  }
  else
  {
    Serial.println("Couldn't open log file");
  }
  
}

void loop()
{

  NO2Value = analogRead(1) * 0.004882812;
  COValue = analogRead(2) * 0.004882812;
  O3Value = analogRead(3) * 0.004882812;
  
  kelvin = analogRead(4) * 0.004882812 * 100;
  celsius = (kelvin - 273.15) - 15;
  
  val = analogRead(5);
  max_voltage = (3.27-(0.006706*celsius));
  RH = ((((val/1023)*5)-ZeroPercentVoltage)/max_voltage)*100;
  
  digitalWrite(ledPower,LOW);
  delayMicroseconds(delayTime);
  int dust_Vout = analogRead(dustPin);
  delayMicroseconds(delayTime2);
  digitalWrite(ledPower,HIGH);
  delayMicroseconds(offTime);
  
  e_NO2Value = analogRead(8) * 0.004882812;
  e_NOValue = analogRead(9) * 0.004882812;
  e_COValue = analogRead(10) * 0.004882812;
  
  floatToString(CO_Vout, COValue, 8);
  floatToString(NO2_Vout, NO2Value, 8);
  floatToString(O3_Vout, O3Value, 8);
  floatToString(cel, celsius, 1);
  floatToString(hum, RH, 1);
  floatToString(e_NO2_Vout, e_NO2Value, 8);
  floatToString(e_NO_Vout, e_NOValue, 8);
  floatToString(e_CO_Vout, e_COValue, 8);
  
  DateTime now = RTC.now();
  sprintf(date_time,"%d/%d/%d %d:%d:%d",now.day(),now.month(),now.year(),now.hour(),now.minute(),now.second());
  String dataString = String(date_time) + ", " + String(cel) + ", " + String(hum) + ", " + String(e_NO2_Vout) + ", " + String(e_NO_Vout) + ", " + String(e_CO_Vout) + ", " + String(CO_Vout) + ", " + String(NO2_Vout) + ", " + String(O3_Vout) + ", " + String(dust_Vout); 
  // String dataString = String(date_time) + ", " + String(cel) + ", " + String(hum) + ", " + String(CO_Vout) + ", " + String(NO2_Vout) + ", " + String(O3_Vout) + ", " + String(dust_Vout); 
  File logFile = SD.open("LOG.csv", FILE_WRITE);
  if (logFile)
  {
    logFile.println(dataString);
    logFile.close();
    Serial.println(dataString);
    pinMode(SD_led, OUTPUT);
    digitalWrite(SD_led, HIGH);
  }
  else
  {
    Serial.println("Couldn't open log file");
  }
  
  delay(60000);
  digitalWrite(SD_led, LOW);
}

Any solution?

Not really. If you the same software on three different sets of hardware, and one set fails, its probably a hardware issue. Try swapping shields around, if you are using them.

dxw00d:
Not really. If you the same software on three different sets of hardware, and one set fails, its probably a hardware issue. Try swapping shields around, if you are using them.

I was using ethernet shield logging data on SD card. I removed it and SD related lines from the code but even though this Mega is not not responding much to this code.
What is confusing me is that this set works fine with example codes, I have tested a few, but not with the code others are running fine on.

Here

#include <SD.h>
#include <Wire.h>
#include <SPI.h>
int CS_pin = 4;
int SD_led = 8;
#include "floatToString.h"
#include "RTClib.h"
RTC_DS1307 RTC;
float COValue = 0;
float NO2Value = 0;
float O3Value = 0;
float e_NO2Value = 0;
float e_NOValue = 0;
float e_COValue = 0;
float celsius = 0, kelvin=0;
#include <math.h>
int dustPin=0;
int ledPower=2;
int delayTime=280;
int delayTime2=40;
float offTime=9680;
float ZeroPercentVoltage = 0.8;
float val = 0;
float RH = 0;
float max_voltage = 3.27;

  char date_time[10];
  char CO_Vout[10];
  char NO2_Vout[10];
  char O3_Vout[10];
  char cel[10];
  char hum[10];
  char e_NO2_Vout[10];
  char e_NO_Vout[10];
  char e_CO_Vout[10];

void setup()
{
  Wire.begin();
  Serial.begin(9600);
  SPI.begin();

  pinMode(53, OUTPUT);
  //digitalWrite(53, HIGH);
  RTC.begin();
  pinMode(ledPower,OUTPUT);
  pinMode(5, OUTPUT);
  String header = "Date_Time, Temp, Humidity(%), e_NO2_Vout, e_NO_Vout, e_CO_Vout, CO_Vout, NO2_Vout, O3_Vout, Dust_Vout";
  Serial.println(header);
}

void loop()
{
  NO2Value = analogRead(1) * 0.004882812;
  COValue = analogRead(2) * 0.004882812;
  O3Value = analogRead(3) * 0.004882812;
  
  kelvin = analogRead(4) * 0.004882812 * 100;
  celsius = (kelvin - 273.15) - 15;
  
  val = analogRead(5);
  max_voltage = (3.27-(0.006706*celsius));
  RH = ((((val/1023)*5)-ZeroPercentVoltage)/max_voltage)*100;
  
  digitalWrite(ledPower,LOW);
  delayMicroseconds(delayTime);
  int dust_Vout = analogRead(dustPin);
  delayMicroseconds(delayTime2);
  digitalWrite(ledPower,HIGH);
  delayMicroseconds(offTime);
  
  e_NO2Value = analogRead(8) * 0.004882812;
  e_NOValue = analogRead(9) * 0.004882812;
  e_COValue = analogRead(10) * 0.004882812;
  
  pinMode(SD_led, OUTPUT);
  digitalWrite(SD_led, HIGH);
  
  floatToString(CO_Vout, COValue, 8);
  floatToString(NO2_Vout, NO2Value, 8);
  floatToString(O3_Vout, O3Value, 8);
  floatToString(cel, celsius, 1);
  floatToString(hum, RH, 1);
  floatToString(e_NO2_Vout, e_NO2Value, 8);
  floatToString(e_NO_Vout, e_NOValue, 8);
  floatToString(e_CO_Vout, e_COValue, 8);
  
DateTime now = RTC.now();
  sprintf(date_time,"%d/%d/%d %d:%d:%d",now.day(),now.month(),now.year(),now.hour(),now.minute(),now.second());
  String dataString = String(date_time) + ", " + String(cel) + ", " + String(hum) + ", " + String(e_NO2_Vout) + ", " + String(e_NO_Vout) + ", " + String(e_CO_Vout) + ", " + String(CO_Vout) + ", " + String(NO2_Vout) + ", " + String(O3_Vout) + ", " + String(dust_Vout); 
  Serial.println(dataString);
  pinMode(SD_led, OUTPUT);
  digitalWrite(SD_led, HIGH);
  delay(59000);
  digitalWrite(SD_led, LOW);
  delay(1000);

At the bottom of the code:

  DateTime now = RTC.now();
  sprintf(date_time,"%d/%d/%d %d:%d:%d",now.day(),now.month(),now.year(),now.hour(),now.minute(),now.second());
  String dataString = String(date_time) + ", " + String(cel) + ", " + String(hum) + ", " + String(e_NO2_Vout) + ", " + String(e_NO_Vout) + ", " + String(e_CO_Vout) + ", " + String(CO_Vout) + ", " + String(NO2_Vout) + ", " + String(O3_Vout) + ", " + String(dust_Vout); 
  Serial.println(dataString);
  pinMode(SD_led, OUTPUT);
  digitalWrite(SD_led, HIGH);
  delay(59000);
  digitalWrite(SD_led, LOW);
  delay(1000);

LED turns on without printing the datastring on screen and it never turns off.

Are you sure you're not running out of RAM? Seems like you're being pretty liberal with use of floating points as well as the String class - which tends to be pretty fat and bloated.

DateTime now = RTC.now();
  sprintf(date_time,"%d/%d/%d %d:%d:%d",now.day(),now.month(),now.year(),now.hour(),now.minute(),now.second());
  String dataString = String(date_time) + ", " + String(cel) + ", " + String(hum) + ", " + String(e_NO2_Vout) + ", " + String(e_NO_Vout) + ", " + String(e_CO_Vout) + ", " + String(CO_Vout) + ", " + String(NO2_Vout) + ", " + String(O3_Vout) + ", " + String(dust_Vout); 
  Serial.println(dataString);
  pinMode(SD_led, OUTPUT);
  digitalWrite(SD_led, HIGH);
  delay(59000);
  digitalWrite(SD_led, LOW);
  delay(1000);

Could be re-written like so:

#include <avr/pgmspace.h>

int _outputserialchar( char c, FILE *t) {
	Serial.write( c );
	return 1;
} 

void setup()
{
  fdevopen( &_outputserialchar, 0); 
  
  //All your other setup stuff here
}

void loop()
{
  
  //All your other loop stuff here
  
  DateTime now = RTC.now();
  sprintf_P(date_time,PSTR("%d/%d/%d %d:%d:%d"),now.day(),now.month(),now.year(),now.hour(),now.minute(),now.second());
  printf_P(PSTR("%s, %s, %s, %s, %s, %s, %s, %s, %s, %s\r\n"), date_time, cel, hum, e_N02_Vout, e_NO2_Vout, e_CO_Vout, CO_Vout, NO2_Vout, O3_Vout, dust_Vout); 

  pinMode(SD_led, OUTPUT);
  digitalWrite(SD_led, HIGH);
  delay(59000);
  digitalWrite(SD_led, LOW);
  delay(1000);
}

It should compile, but I couldn't test it since i don't have the DateTime library. That alone would free up a huge chunk of memory.

Edit: Yes, you can argue that printf isn't the most efficient of things to do either, but it's still going to be better than declaring 10 new string classes just for ease of concatenation.

If memory really is the issue (quite possible), you'd probably want to re-write the printf again and do it in small steps with minimal variable usage.

Hi tgm,

Strangely, after 3 hours of rest it worked again. Problem probably was with heating of board or something.
Your code also worked, thanks. I suppose Arduino will have more free memory now.
I will monitor it over the weekend to see if again it stops working and update you.

Best,
Z