Logging Temperature Data

I am trying to log temperature to an SD2/2GB SanDisk card. I am using the DS1307 to time stamp the data and this breakout board from Sparkfun to hold the SD card http://www.sparkfun.com/products/204 and DS18B20 temperature sensors to take temperature readings. Whenever the DS18B20s read in -192 degrees F the SD card file reads

2010/10/3 14:15:35
Internal Sensor: 4294967169 C 4294967100 F
External Sensor: 4294967169 C 4294967100 F

which is perfectly how I want it to be formatted except the temperature is completely wrong. If I get the DS18B20 to read in the correct temperature the SD card file reads

2011102214150
IInIntInteInterInternInternaInternalInternal Internal SInternal SeInternal SenInternal SensInternal SensoInternal SensorInternal Sensor:29 C C 84
EExExtExteExterExternExternaExternalExternal External SExternal SeExternal SenExternal SensExternal SensoExternal SensorExternal Sensor:29 C C 84

Any ideas? I don’t know why sometimes I read in the temperature and it reads -192 degrees F and when I read upload the sketch it reads in 84 degrees Celsius or why the temperature change causes the SD file to screw up.

Code:

#include <SdFat.h>
#include <SdFatUtil.h>
#include <OneWire.h>
#include <DallasTemperature.h>
#include <WProgram.h>
#include <Wire.h>
#include <DS1307.h>

#define error(s) error_P(PSTR(s))
#define ONE_WIRE_BUS 3
#define TEMPERATURE_PRECISION 12

Sd2Card card;
SdVolume volume;
SdFile root;
SdFile file;

OneWire oneWire(ONE_WIRE_BUS);
DallasTemperature sensors(&oneWire);

DeviceAddress insideThermometer = { 0x28, 0xA3, 0xDB, 0xFF, 0x02, 0x00, 0x00, 0x91 };
DeviceAddress outsideThermometer = { 0x28, 0x86, 0xCA, 0xFF, 0x02, 0x00, 0x00, 0x7D };

float tempC,tempF;
int hour, minute, seconds, day, month, year;

char name = “TEMPLOG.TXT”;

void error_P(const char* str)
{
PgmPrint("Error: ");
SerialPrintln_P(str);
if(card.errorCode())
{
PgmPrint("SD error: ");
Serial.print(card.errorCode(), HEX);
Serial.print(’,’);
Serial.println(card.errorData(),HEX);
}
while(1);
}

void writeCRLF(SdFile& f)
{
f.write((uint8_t*) “\r\n”,2);
}

void writeNumber(SdFile& f, uint32_t n)
{
uint8_t buf[10];
uint8_t i = 0;
do{
i++;
buf[sizeof(buf) - i] = n%10 + ‘0’;
n /= 10;
}while(n);
f.write(&buf[sizeof(buf) - i],i);
}

void writeString(SdFile& f, char *str)
{
uint8_t n;
for(n = 0; str[n]; n++)
{
f.write((uint8_t *)str,n);
}
}

void getTemperature(DeviceAddress deviceAddress)
{
sensors.requestTemperatures();
tempC = sensors.getTempC(deviceAddress);
tempF = DallasTemperature::toFahrenheit(tempC);
}

void getTimeDate()
{
hour = RTC.get(DS1307_HR,TRUE);
minute = RTC.get(DS1307_MIN, false);
seconds = RTC.get(DS1307_SEC, false);
day = RTC.get(DS1307_DATE,false);
month = RTC.get(DS1307_MTH,false);
year = RTC.get(DS1307_YR,false);
}

void setup()
{
Serial.begin(9600);
Serial.println(“Type any character to start”);
while(!Serial.available());
Serial.println();

sensors.begin();
Serial.println(“Initialising Sensors.”);

sensors.setResolution(insideThermometer, TEMPERATURE_PRECISION);
sensors.setResolution(outsideThermometer, TEMPERATURE_PRECISION);
delay(100);

RTC.stop();
RTC.set(DS1307_SEC,0);
RTC.set(DS1307_MIN,15);
RTC.set(DS1307_HR,14);
RTC.set(DS1307_DOW,6);
RTC.set(DS1307_DATE,22);
RTC.set(DS1307_MTH,10);
RTC.set(DS1307_YR,11);
RTC.start();

Serial.println(“Initialising SD Card…”);

if(!card.init(SPI_HALF_SPEED))
{
error(“card.init failed”);
}

if(!volume.init(&card))
{
error(“volume.init failed”);
}

if(!root.openRoot(&volume))
{
error(“openRoot failed”);
}
Serial.println(“SD Card initialised successfully”);
Serial.println();
}

void loop()
{
Serial.println(“File Opened.”);
file.open(&root, name, O_CREAT | O_APPEND | O_WRITE);
getTimeDate();
file.timestamp(7,year,month,day,hour,minute,seconds);

getTemperature(insideThermometer);
Serial.print(“Inside: “);
Serial.print(tempC);
Serial.print(” C “);
Serial.print(tempF);
Serial.println(” F”);
writeNumber(file,year);
writeString(file,"/");
writeNumber(file,month);
writeString(file,"/");
writeNumber(file,day);
writeString(file,"/");
writeNumber(file,hour);
writeString(file,"/");
writeNumber(file,minute);
writeString(file,"/");
writeNumber(file,seconds);
writeCRLF(file);
writeString(file, "Internal Sensor: ");
writeNumber(file, tempC);
writeString(file, " C “);
writeNumber(file,tempF);
writeString(file, " F”);
writeCRLF(file);

getTemperature(outsideThermometer);
Serial.print("Outside: “);
Serial.print(tempC);
Serial.print( " C “);
Serial.print(tempF);
Serial.println(” F”);
writeString(file, "External Sensor: ");
writeNumber(file,tempC);
writeString(file, " C “);
writeNumber(file,tempF);
writeString(file, " F”);
writeCRLF(file);
writeCRLF(file);

Serial.println(“Data Written”);
file.close();
Serial.println(“File Closed.”);
Serial.println();
delay(10000);
}

Whenever the DS18B20s read in -192 degrees F the SD card file reads

Perhaps passing a negative number to this function:

void writeNumber(SdFile& f, uint32_t n)

is not advised. The u, in case you've forgotten, stands for unsigned (i.e. positive only).

PaulS:

Whenever the DS18B20s read in -192 degrees F the SD card file reads

Perhaps passing a negative number to this function:

void writeNumber(SdFile& f, uint32_t n)

is not advised. The u, in case you've forgotten, stands for unsigned (i.e. positive only).

I tried this and still got: 20111022141523 IInIntInteInterInternInternaInternalInternal Internal SInternal SeInternal SenInternal SensInternal SensoInternal SensorInternal Sensor:28 C C 83 EExExtExteExterExternExternaExternalExternal External SExternal SeExternal SenExternal SensExternal SensoExternal SensorExternal Sensor:28 C C 83

I tried this

Tried what?

PaulS:

I tried this

Tried what?

I changed void writeNumber(SdFile& f, uint32_t n) to void writeNumber(SdFile& f, int32_t n), but still got the same result string wise. I found the issue though it was in the writeString function. Although your suggestion did fix the -192 coming out as a different number so thank you.

It would involve a big re-write, which might not be welcome... but in case others are reading this, and thinking of starting something similar...

The DS18B20's return the temperature as a (relatively) simple 16 bit number. I tend to keep it fairly simple "inside" my programs, converting it to "human friendly" form late in the day, around the time it is to come "out" of the system, appear on the screen. Avoids all those nasty issues of fractions and negative numbers!

Of course, depending on which 1-Wire library you are using, you may not "see" the raw data from the DS18B20.