[SOLVED]Logging multiple temp sensors questions(step by step)

Have you tested how much free memory you have (or, more likely, don't have)?

The SD library uses 512+ bytes of SRAM. That's 1/4 of the SRAM on a 328-based Arduino.

Hi Paul,

still not...how can I do that? I would be hard to loose all the free memory of a Mega 2560.

vespapierre:
I would like to have sd logging in case going offline..

That's fine, I am doing the same thing, but that's not the same as sending the SD file to cosm.

.all I have to find where and how to put that sd codes...Sd involved in the concept...

The code below is about 36k. I am currently in the throes of moving to Mega 2560. While I'm sure this can be written more elegantly, it probably won't save enough to squeeze into a Uno.

/*
/*From cosm library example and lifts from a lot of others
 particularly from Stanley in Kuala Lumpur.
 Use your own DS18B20 addresses, keys etc.
 
 */
#include <LiquidCrystal.h>
#include <SD.h>
#include <string.h>
#include "RTClib.h"

RTC_DS1307 RTC;
File myFile;
char filename[] = "00000000.CSV";
#include "Wire.h"
#define DS1307_ADDRESS 0x68

#include <OneWire.h>
#include <DallasTemperature.h>
#include <SPI.h>
#include <Ethernet.h>
#include <HttpClient.h>
#include <Cosm.h>

byte InThermo[8] =  {
  0x28, 0x69, 0xC2, 0xB0, 0x03, 0x00, 0x00, 0X9F};
byte OutThermo[8] = {
  0x28, 0x7A, 0x8B, 0xC0, 0x03, 0x00, 0x00, 0x2F};
#define ONE_WIRE_BUS 3
OneWire oneWire(ONE_WIRE_BUS);
DallasTemperature sensors(&oneWire);

byte mac[] = { 
  0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };

char cosmKey[] = "l6ab.....................................0Zz0g";

int sensorPin = 3;
int  second, minute, hour, weekDay, monthDay, month, year;
float InTemp, OutTemp;

// Define the strings for our datastream IDs
char sensorId0[] = "InThermo";
char sensorId1[] = "OutThermo";
//char sensorId2{} = "DrainThermo"

const int bufferSize = 100;
char bufferValue[bufferSize]; // enough space to store the string we're going to send

CosmDatastream datastreams[] = {
  CosmDatastream(sensorId0, strlen(sensorId0), DATASTREAM_FLOAT),
  CosmDatastream(sensorId1, strlen(sensorId1), DATASTREAM_FLOAT),
  //    CosmDatastream(sensorId2, strlen(sensorId2), DATASTREAM_FLOAT),
};

// Finally, wrap the datastreams into a feed
CosmFeed feed(83153, datastreams, 2 /*put your number here */);

EthernetClient client;
CosmClient cosmclient(client);

LiquidCrystal lcd(8,9,16,5,6,7);

void setup() {

  Wire.begin();
  Serial.begin(9600);
  delay(300);//Wait for newly restarted system to stabilize
  Serial.print("Temperature measurement");
  Serial.print("Initializing SD card...");

  pinMode(10, OUTPUT);

  if (!SD.begin(4)) {
    Serial.println("initialization failed!");
    return;
  }

  Serial.println("initialization done.");

  sensors.setResolution(InThermo, 12);
  sensors.setResolution(OutThermo, 12);

  Serial.println("Starting multiple datastream upload to Cosm...");
  Serial.println();

  while (Ethernet.begin(mac) != 1)
  {
    Serial.println("Error getting IP address via DHCP, trying again...");
    delay(10000);
  }
}

void loop() {

  GetClock();
  PrintDate;

  sensors.requestTemperatures();
  Serial.println("Read sensor value ");

  InTemp = (sensorValue(InThermo));
  OutTemp = (sensorValue(OutThermo));  
  // float Drain = (sensorValue(DrainThermo));  

  datastreams[0].setFloat(InTemp);
  datastreams[1].setFloat(OutTemp);

  Serial.println(datastreams[0]);
  Serial.println(datastreams[1]);
  /*
  datastreams[2].setFloat(DrainTemp);
   Serial.println(datastreams[2].getFloat(DrainTemp));
   */
  // LCD stuff will go here

  if (second == 0 || second == 10 || second == 20 || second == 30 || second == 40 || second == 50) 
  {
    myFile = SD.open("data.csv", FILE_WRITE);//<<<<<<<<<<<<< OPEN
    WriteSD;
    int ret=0;
    delay(200);// Delay... must not be too short.
    Serial.println("Uploading it to Cosm");
    ret = cosmclient.put(feed, cosmKey);    // SEND FEED TO COSM
    Serial.print("cosmclient.put returned "); // tell us about it
    Serial.println(ret);                      // pray to God it says 200
    myFile.println();
    myFile.close();//>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>CLOSE
  }
    delay(200);// Delay... must not be too short.
    Serial.println();
    delay(800);
}

//sensorValue function
float sensorValue (byte deviceAddress[])
{
  float tempC = sensors.getTempC (deviceAddress);
  return tempC;
}


byte bcdToDec(byte val)  {
  // Convert binary coded decimal to normal decimal numbers
  return ( (val/16*10) + (val%16) );
}

void GetClock(){
  // Reset the register pointer
  Wire.beginTransmission(DS1307_ADDRESS);
  byte zero = 0x00;
  Wire.write(zero);
  Wire.endTransmission();
  Wire.requestFrom(DS1307_ADDRESS, 7);

  second = bcdToDec(Wire.read());
  minute = bcdToDec(Wire.read());
  hour = bcdToDec(Wire.read() & 0b111111); //24 hour time
  weekDay = bcdToDec(Wire.read()); //0-6 -> sunday - Saturday
  monthDay = bcdToDec(Wire.read());
  month = bcdToDec(Wire.read());
  year = bcdToDec(Wire.read());
}

void PrintDate () {
  Serial.print(monthDay);
  Serial.print("/");
  Serial.print(month);
  Serial.print("/");
  Serial.print(year);
  Serial.print("     ");
  Serial.print(hour);
  Serial.print(":");
  Serial.print(minute);
  Serial.print(":");

  if (second < 10)
  {
    Serial.print("0");
  };

  Serial.print(second);
  Serial.print("         ");
}

void WriteSD () {

  myFile.print(monthDay);
  myFile.print("/");
  myFile.print(month);
  myFile.print("/");
  myFile.print(year);
  myFile.print(",  ");
  myFile.print(hour);
  myFile.print(":");
  myFile.print(minute);
  myFile.print(":");
  myFile.print(second);
  myFile.print(",         ");

  myFile.print(InTemp);
  myFile.print(",    ");
  myFile.print(OutTemp);
  myFile.print(",    ");
}

@NickPyner: I don't think the OP is sending the csv file like in an FTP sense, which I do with Mega/Ethernet shield on a regular basis.
http://www.arduino.cc/playground/Code/FTP

I think he is opening the file and sending the text from the file to the server. I do that too. On big html pages on a server, I can save a bunch of both program and SRAM by putting the header and footer of my html page in files on the SD.

sorry for my english...I'm not sending a file, I'm just sending the values ( char ) to the server as the API needs...
about cosm...all is in your comment int the code : "pray to God it says 200" :):):slight_smile:
I have already created a cosm feeding, but I prefer Thingspeak because it can be open on android too..and dynamic...

vespapierre:
sorry for my english...I'm not sending a file, I'm just sending the values ( char ) to the server as the API needs...

OK, I'm glad we have that sorted out. Actually I was just thinking about this under the shower and, if the time intervals are OK, there really shouldn't be any problem reading the datastream off the SD card and the code I posted should be adaptable. In my case the intervals are the same and I will try that out.

about cosm...all is in your comment int the code : "pray to God it says 200" :):):slight_smile:
I have already created a cosm feeding, but I prefer Thingspeak because it can be open on android too..and dynamic...

I have had some bumps with cosm, but it ran perfectly for several days when I last used it. I will try Thingspeak soon.

SurferTim:
@NickPyner: I don't think the OP is sending the csv file like in an FTP sense, which I do with Mega/Ethernet shield on a regular basis.
Arduino Playground - FTP

Fine, but I don't see any evidence therein of communication with cosm or the like, which is what this is about. However, it turns out that you are correct, he is not engaging in FTP after all, which is proabaly a good thing. I am yet to be convinced of any merit in sending a datastream off the card, but maybe the OP can adapt the code I posted.

I am going to suggest doing what PaulS recommended. This works on my Mega2560.

// include the freeRam function in your sketch
int freeRam() {
  extern int __heap_start,*__brkval;
  int v;
  return (int)&v - (__brkval == 0 ? (int)&__heap_start : (int) __brkval);  
}

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

  // then use it like this
  Serial.print("SRAM free: ");
  Serial.println(freeRam());  
}

void loop() {
}

Free SRAM is 6063.

Is that at the end of the setup function? Or just before the logFile call?

at end of the setup is 6063.
during loop after some cycles 5910.

anyway is the pageadd size ok?? now it is 140. strange was if I tried to modify to 139 or 141 log has been failed.. ( just a guess...)

update: maybe pageadd size can be tricky, but I don't understand at the moment...if the size changed to 60, log failed all the time...changing to 128, just 3-4 lines in the log and then no more...??? :~ trying with size 128 and external power supply, not usb...-->log is empty...

Try reducing it. Set pageAdd[64]. I don't see anything you are putting in that array that would be that big.

not ok...

2012-12-04,20:47:19,15,3,3;

2012-12-04,20:47:52,15,3,3;

Back to basics. This does just the SD and ethernet, and works good on my Mega. I used my server with a php page, and pin 4 for my SD card. I sent the same parameters as below.

#include <SD.h>
#include <SPI.h>
#include <Ethernet.h>

//variables

int temp0;
int temp1;
int temp2;
char pageAdd[64];

byte mac[] = {  0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };
// change to your server
IPAddress server(184,106,153,149);
EthernetClient client;

// **********************************SETUP*****************************************************
void setup(void)
{

  // start serial port
  Serial.begin(9600);

  // disable w5100 while setting up SD
  pinMode(10,OUTPUT);
  digitalWrite(10,HIGH);

  //start SD
  Serial.print(F("Starting SD..."));
  if(!SD.begin(8)) Serial.println(F("failed"));
  else Serial.print(F("ok "));

  // Start w5100
  Serial.print(F("Starting w5100..."));
  if(!Ethernet.begin(mac)) Serial.println(F("failed"));
  else Serial.print(F("ok "));

  // this corrects a bug in the Ethernet.begin() function
  digitalWrite(10,HIGH);

  Serial.print(F("IP: "));
  Serial.println(Ethernet.localIP());

  delay(2000);
  Serial.println(F("Ready"));

}


//********************************************LOOP**************************************

void loop(void)
{ 
  delay(5000);

  temp0 = 1;
  temp1 = 2;
  temp2 = 3;
  
  //datetime
  char sdate[11] = "2012-12-04"; 
  char stime[9] ="12:34:56"; 
  Serial.print(stime); 
  Serial.print(" "); 
  Serial.print(sdate); 
  Serial.println();  
   
  if(!logFile(sdate,stime,temp0,temp1,temp2)) Serial.println(F("Log failed"));
  else Serial.println(F("Log ok"));
  
  sprintf(pageAdd,"/update?key=XXXXXXXXXXXXXXX&field1=%u&field2=%u&field3=%u",temp0,temp1,temp2); 

  if(!getPage(server,pageAdd)) Serial.print(F("Fail "));
  else Serial.print(F("Pass "));
  
}
int logFile(char* sdate, char* stime, int temp0, int temp1, int temp2) {
  File fh = SD.open("test.txt",FILE_WRITE);
  if(!fh) {
    Serial.println(F("Open fail"));
    return 0;
  }

  sprintf(pageAdd,"%s,%s,%i,%i,%i;",sdate,stime,temp0,temp1,temp2);
  fh.println(pageAdd);
  fh.close();
  return 1;
}
byte getPage(IPAddress ipBuf,char *page)
{
  int inChar;
  char outBuf[128];

  Serial.print(F("connecting..."));

  if(client.connect(ipBuf,80))
  {
    Serial.println(F("connected"));

    sprintf(outBuf,"GET %s HTTP/1.0\r\n\r\n",page);
    client.write(outBuf);
  } 
  else
  {
    Serial.println(F("failed"));
    return 0;
  }

  // connectLoop controls the hardware fail timeout
  int connectLoop = 0;

  while(client.connected())
  {
    while(client.available())
    {
      inChar = client.read();
      Serial.write(inChar);
      // set connectLoop to zero if a packet arrives
      connectLoop = 0;
    }

    connectLoop++;

    // if more than 10000 milliseconds since the last packet
    if(connectLoop > 10000)
    {
      // then close the connection from this end.
      Serial.println();
      Serial.println(F("Timeout"));
      client.stop();
    }
    // this is a delay for the connectLoop timing
    delay(1);
  }

  Serial.println();

  Serial.println(F("disconnecting."));
  // close client end
  client.stop();

  return 1;
}

This works, correct?

after deleting logfile, first two attempt was fail, than log ok on serial...logfile looks:

2012-12-04,12:34:56,1,2,3;

2012-12-04,12:34:56,1,2,3;

so this is not ok!

Here is mine using that code:
2012-12-04,12:34:56,1,2,3;
2012-12-04,12:34:56,1,2,3;
2012-12-04,12:34:56,1,2,3;
2012-12-04,12:34:56,1,2,3;
2012-12-04,12:34:56,1,2,3;
2012-12-04,12:34:56,1,2,3;
2012-12-04,12:34:56,1,2,3;
2012-12-04,12:34:56,1,2,3;
2012-12-04,12:34:56,1,2,3;
2012-12-04,12:34:56,1,2,3;
2012-12-04,12:34:56,1,2,3;
2012-12-04,12:34:56,1,2,3;
2012-12-04,12:34:56,1,2,3;
2012-12-04,12:34:56,1,2,3;
2012-12-04,12:34:56,1,2,3;
2012-12-04,12:34:56,1,2,3;
2012-12-04,12:34:56,1,2,3;
2012-12-04,12:34:56,1,2,3;
2012-12-04,12:34:56,1,2,3;

ohh...bad news... means I have problems with the hw ?

edit: I'm using arduino 102....is it a problem?? or should I change the sd card? it is 128 mb.

I don't know about the smaller SD cards. I use a 2GB SanDisk, and it is working good.

I noticed the SD card adapter uses voltage divider resistors instead of a logic level converter. I hear that will cause problems too.

ok so does it seems to be the end of this story?

Hi,

so the story is ended! I have managed to fix the problem! Issues:

  • old card (128MB) has been changed to a 2GB Sandisk card
  • card has been formatted by the formatter of sdcard.org
  • delay(100) values has been inserted before writing to file, after writing to file, before and after closing he write process
  • SD and wiznet are switching manually during the process ( HIGH and LOW )
  • SPI bus speed is running on HALF speed

After a day it is running fine with no errors! Further tests in progress!
Thanks for everyone for help, especially for SurferTim,NickPyner and PaulS.