One-wire temperature logger

From Hamsterworks Wiki!

Jump to: navigation, search

An Arduino project to send the temperature to a PC. Uses a DS18B20 sensor from Sure Electronics (http://www.sureelectronics.net/goods.php?id=1020). A large portion of this is from http://www.arduino.cc/playground/Learning/OneWire

Note After logging the temperature for a couple of days I have recorded 104 corrupt samples out of in 80576 (usually very high or very low values, but sometimes only a few degrees out). I then realized that I wasn't testing the CRC for the data packet in the transfer, so I've added that in.

Given the randomness of the error I suspect it is a conflict between the one-wire library and a timer interrupt. The simplest workaround is use the median value of the last three samples. If this is truly random then errors should drop to less than one in 600,000 (or about one per week, rather than one every 13 minutes or so).

Update I've made sure I'm using the latest one-wire library (version 2.1 from http://www.pjrc.com/teensy/td_libs_OneWire.html) and errors have gone away. Here's a graph of 66,436 samples made over a couple of days - no bad reads!

Temp graph.png

// Sense and then send the temperature to the PC over serial port at approximately once per second.

#include <OneWire.h>


OneWire ds(10); // DS18S20 Temperature chip i/o on pin 10

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

void loop(void) {
  byte i, present = 0;
  byte data[12], addr[8];
  byte LowByte, HighByte, Whole, Fract;
  word TReading, SignBit, Tc_100;

  if ( !ds.search(addr)) {
      delay(1000);
      ds.reset_search();
      return;
  }

  if ( OneWire::crc8( addr, 7) != addr[7]) {
      Serial.print("Addr CRC is not valid!\n");
      return;
  }

  if ( addr[0] != 0x28) {
      Serial.print("Device family is not recognized: 0x");
      Serial.println(addr[0],HEX);
      return;
  }

  ds.reset();
  ds.select(addr);
  ds.write(0x44,1);         // start conversion, with parasite power on at the end

  delay(1000);     // maybe 750ms is enough, maybe not

  present = ds.reset();
  ds.select(addr);    
  ds.write(0xBE);         // Read Scratchpad

  for ( i = 0; i < 9; i++)           // we need 9 bytes
    data[i] = ds.read();
  
  if( OneWire::crc8( data, 8) != data[8])
  {
      Serial.print("Data CRC is not valid!\n");
      return;
  }  

  LowByte = data[0];
  HighByte = data[1];
  TReading = (HighByte << 8) + LowByte;
  SignBit = TReading & 0x8000;  // test most significant bit
  if (SignBit) // negative
     TReading = (TReading ^ 0xffff) + 1; // 2's comp

  Tc_100 = (6 * TReading) + TReading / 4;    // multiply by (100 * 0.0625) or 6.25

  Whole = Tc_100 / 100;  // separate off the whole and fractional portions
  Fract = Tc_100 % 100;


  if (SignBit) // If its negative
       Serial.print("-");
  Serial.print(Whole);
  Serial.print(".");
  if (Fract < 10)
    Serial.print("0");
  Serial.print(Fract);
  Serial.print("\n");
}

Personal tools