Skip to content

Instantly share code, notes, and snippets.

@maleadt
Created September 18, 2011 09:38
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save maleadt/1224913 to your computer and use it in GitHub Desktop.
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.
////////////////////////////////////////////////////////////////////////
// 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