Created
September 18, 2011 09:38
-
-
Save maleadt/1224913 to your computer and use it in GitHub Desktop.
Arduino sketch to monitor the temperature using a DS18S20 and save the values in the EEPROM.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
//////////////////////////////////////////////////////////////////////// | |
// Configuration | |
// | |
// Headers | |
#include <OneWire.h> | |
#include <EEPROM.h> | |
// OneWire interface (change this to the port your sensor is on) | |
OneWire ow(2); | |
// Sensor identification (change this to your sensor) | |
// TODO: detect the available sensors | |
byte sensor[8] = {0x10, 0x30, 0x55, 0x25, 0x01, 0x08, 0x00, 0x7D}; | |
// Data format definitions | |
#define DATA_HEADER_SIZE 3 | |
#define DATA_FOOTER_SIZE 1 | |
//////////////////////////////////////////////////////////////////////// | |
// Routines | |
// | |
// | |
// DS18S20 handling | |
// | |
void writeTimeToScratchpad(byte* address){ | |
//reset the bus | |
ow.reset(); | |
//select our sensor | |
ow.select(address); | |
//CONVERT T function call (44h) which puts the temperature into the scratchpad | |
ow.write(0x44,1); | |
//sleep a second for the write to take place | |
delay(1000); | |
} | |
void readTimeFromScratchpad(byte* address, byte* data){ | |
//reset the bus | |
ow.reset(); | |
//select our sensor | |
ow.select(address); | |
//read the scratchpad (BEh) | |
ow.write(0xBE); | |
for (byte i=0;i<9;i++){ | |
data[i] = ow.read(); | |
} | |
} | |
float getTemperature(byte* address){ | |
int tr; | |
byte data[12]; | |
writeTimeToScratchpad(address); | |
readTimeFromScratchpad(address,data); | |
//put in temp all the 8 bits of LSB (least significant byte) | |
tr = data[0]; | |
//check for negative temperature | |
if (data[1] > 0x80){ | |
tr = !tr + 1; //two's complement adjustment | |
tr = tr * -1; //flip value negative. | |
} | |
//COUNT PER Celsius degree (10h) | |
int cpc = data[7]; | |
//COUNT REMAIN (0Ch) | |
int cr = data[6]; | |
//drop bit 0 | |
tr = tr >> 1; | |
//calculate the temperature based on this formula : | |
//TEMPERATURE = TEMP READ - 0.25 + (COUNT PER Celsius Degree - COUNT REMAIN) / (COUNT PER Celsius Degree) | |
return tr - (float)0.25 + (cpc - cr)/(float)cpc; | |
} | |
// | |
// Temperature conversion | |
// | |
// TODO: low byte packing might be wrong | |
// TODO: fixed-point math? | |
byte packTemperature(float temperature) { | |
// Extract low and high bytes | |
byte high, low; | |
high = (byte) temperature; | |
low = 100 * (temperature - high); | |
// Pack | |
byte data = 0; | |
data |= high << 2; | |
data |= low & B00000011; | |
return data; | |
} | |
float unpackTemperature(byte data) { | |
// Extract high and low part | |
unsigned int high, low; | |
high = data >> 2; | |
low = data & B00000011; | |
// Create float | |
float temperature = high + low/100.0; | |
return temperature; | |
} | |
// | |
// Temperature storage | |
// | |
boolean checkData() { | |
// Process the header | |
byte magic; | |
unsigned short entries; | |
readHeader(&magic, &entries); | |
if (magic != 42) { | |
Serial.println("MAGIC"); | |
return false; | |
} | |
if (entries > 512-DATA_HEADER_SIZE-DATA_FOOTER_SIZE) { | |
Serial.println("SIZE"); | |
return false; | |
} | |
// Calculate the checksum | |
byte checksum = 0; | |
for (int i = 0; i < entries; i++) { | |
checksum += EEPROM.read(DATA_HEADER_SIZE+i); | |
} | |
byte checksum_saved; | |
readFooter(DATA_HEADER_SIZE+entries, &checksum_saved); | |
if (checksum != checksum_saved) { | |
Serial.println("CHECKSUM"); | |
return false; | |
} | |
return true; | |
} | |
void readHeader(byte* magic, unsigned short *entries) { | |
// Magic | |
*magic = EEPROM.read(0); | |
// Entries | |
byte high, low; | |
high = EEPROM.read(1); | |
low = EEPROM.read(2); | |
*entries = low + 256*((unsigned short) high); | |
} | |
void readFooter(unsigned int offset, byte *checksum) { | |
// Checksum | |
*checksum = EEPROM.read(offset); | |
} | |
void updateHeader(unsigned short entries) { | |
// Entries | |
byte high, low; | |
high = entries / 256; | |
low = entries % 256; | |
EEPROM.write(1, high); | |
EEPROM.write(2, low); | |
} | |
void updateFooter(unsigned int offset, byte checksum) { | |
// Checksum | |
EEPROM.write(offset, checksum); | |
} | |
void resetData() { | |
EEPROM.write(0, 42); | |
updateHeader(0); | |
updateFooter(DATA_HEADER_SIZE, 0); | |
} | |
void appendEntry(byte data) { | |
// Read the header | |
byte magic; | |
unsigned short entries; | |
readHeader(&magic, &entries); | |
// Read the footer | |
byte checksum; | |
readFooter(DATA_HEADER_SIZE+entries, &checksum); | |
// Save the entry | |
EEPROM.write(DATA_HEADER_SIZE+entries, data); | |
// Update the header | |
updateHeader(entries+1); | |
// Update the footer | |
checksum += data; | |
updateFooter(DATA_HEADER_SIZE+entries+1, checksum); | |
} | |
float readEntry(int i) { | |
if (i >= 512-DATA_HEADER_SIZE-DATA_FOOTER_SIZE) { | |
return 0; | |
} | |
byte data = EEPROM.read(DATA_HEADER_SIZE+i); | |
float temperature = unpackTemperature(data); | |
return temperature; | |
} | |
//////////////////////////////////////////////////////////////////////// | |
// Main | |
// | |
void setup(void) { | |
// Setup communication | |
Serial.begin(9600); | |
// Check the saved data | |
Serial.print("Saved data: "); | |
if (checkData()) { | |
Serial.println("valid"); | |
byte magic; | |
unsigned short entries; | |
readHeader(&magic, &entries); | |
Serial.println("-- START DATA DUMP --"); | |
for (int i = 0; i < entries; i++) { | |
Serial.print("Entry "); | |
Serial.print(i); | |
Serial.print(": "); | |
Serial.print(readEntry(i)); | |
Serial.println(" degrees Celcius"); | |
} | |
Serial.println("-- END DATA DUMP --"); | |
} else { | |
Serial.println("INVALID!"); | |
resetData(); | |
} | |
} | |
void loop(void) { | |
// Get the temperature | |
float temperature; | |
temperature = getTemperature(sensor); | |
// Print it | |
Serial.print("Current temperature: "); | |
Serial.print(temperature); | |
Serial.println(" degrees C"); | |
// Convert it | |
byte data = packTemperature(temperature); | |
// Save it | |
appendEntry(data); | |
// Sleep 10 minutes | |
delay(600*1000); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment