Pages: [1]   Go Down
Author Topic: Problem with invalid temperature readings  (Read 466 times)
0 Members and 1 Guest are viewing this topic.
Offline Offline
Newbie
*
Karma: 0
Posts: 26
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Hope someone can help me out with this.  I have two arduinos in a master/slave relationship.  The slave has a DS18B20 temp chip (running in parasite mode).  It continuously polls the chip for the temp and waits for a request from the master.  Here's a code snippet from the slave sketch:
Code:
void setup(){
  Wire.begin(4);                // join i2c bus with address #4
}

void loop()
{
  get_temp(); 
  Wire.onRequest(requestEvent);  // acknowledge a poll from master
  delay(100);
}

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

  if ( !ds.search(addr)) {
      ds.reset_search();
      Serial.print("bad address");
      return;
  }
 
  if ( OneWire::crc8( addr, 7) != addr[7]) {
      Serial.print("CRC is not valid!\n");
      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();
  }
 
  LowByte = data[0];
  HighByte = data[1];
  TReading = (HighByte << 8) + LowByte;
  SignBit = TReading & 0x8000;  // test most sig 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

  //get the whole and fraction in Celcius
  Whole = Tc_100 / 100;  // separate off the whole and fractional portions
  Fract = Tc_100 % 100;

  Temp=(data[1]<<8)+data[0];//take the two bytes from the response relating to temperature
  Temp=Temp/16;//divide by 16 to get pure celcius readout
  Temp=Temp*1.8+32; // convert to Fahrenheit
}
 
void requestEvent()
{
  INPUTFloatPtr = (byte*) &Temp;
  Data[0] = INPUTFloatPtr[0];
  Data[1] = INPUTFloatPtr[1];
  Data[2] = INPUTFloatPtr[2];
  Data[3] = INPUTFloatPtr[3];
  Wire.send(Data,4);
}



Now, the master code reads the temp from the slave and posts the current temp as well as the high and low.  The problem I've been having is that I occasionally get an invalid temp (such as 31.9, -2106.5, 526.8, etc.)  This is measuring an aquarium water temp.  That by itself would not be a big problem as I have attempted to put code in the sketch that compares the current temp reading with the last reading and ignoring any reading that is more than one degree more or less than the previous reading.  Here's a code snippet from the master sketch:
Code:
void loop()
{
  i = millis()/1000;
  poll_slave();  // get temp from slave
   lcd.cursorTo(0,0);
  lcd.print("Tmp:");
  lcd.print(floatToString(buffer,temp,1));  // convert temp from float to string and print it
 
  // compare to high and low
  if (temp > HiTemp)  // update high temp
  {
    HiTemp = temp;
    if (DisplayHour < 10)
    {
      sprintf(Hibuffer, "%01d:%02d%c%c%d/%d",DisplayHour, minute, ampm, ' ', month, dayOfMonth);
    }
    else
    {
      sprintf(Hibuffer, "%02d:%02d%c%c%d/%d",DisplayHour, minute, ampm, ' ', month, dayOfMonth);
    }
    // print high temp and time of high
    lcd.cursorTo(1,0);
    lcd.print("Hi ");
    lcd.print(floatToString(buffer,HiTemp,1));  // convert temp from float to string and print it
    lcd.print(" ");
    lcd.print(Hibuffer);

  }
  if (temp < LoTemp)  // update low temp
  {
    LoTemp = temp;
    if (DisplayHour < 10)
    {
      sprintf(Lobuffer, "%01d:%02d%c%c%d/%d",DisplayHour, minute, ampm, ' ', month, dayOfMonth);
    }
    else
    {
      sprintf(Lobuffer, "%02d:%02d%c%c%d/%d",DisplayHour, minute, ampm, ' ', month, dayOfMonth);
    }
    // print low temp and time of low
    lcd.cursorTo(2,0);
    lcd.print("Lo ");
    lcd.print(floatToString(buffer,LoTemp,1));  // convert temp from float to string and print it
    lcd.print(" ");
    lcd.print(Lobuffer);
  }
//*********************
void poll_slave()
{
  Wire.beginTransmission(4);
  Wire.requestFrom(4, 4);

  if(Wire.available())
  {
    int i = 0;
    while(Wire.available())    // slave may send less than requested
    {
      data[i] = Wire.receive();
      i = i + 1;
    }
    delay(500);
    union temp_tag {
      byte temp_b[4];
      float temp_fval;
    }
    temp_union;
    temp_union.temp_b[0] = data[0];
    temp_union.temp_b[1] = data[1];
    temp_union.temp_b[2] = data[2];
    temp_union.temp_b[3] = data[3];
    temp = temp_union.temp_fval;
  }
  Wire.endTransmission();
 
  // attempt to trap invalid temps
  if (FirstPass = true)
  {
    LastTemp = temp;
    FirstPass = false;
  }
  else
  { 
    if (temp > LastTemp + 1 || temp < LastTemp - 1)  //temp needs to be a full degree +/- than previous reading to be valid
    {
      temp = LastTemp;
    }
    else
    {
      LastTemp = temp;
    } 
  }
}


Now, the problem is the last few lines of code don't always catch a stray temp reading.  Anybody got any ideas?

Thanx in advance.
Logged

Global Moderator
Netherlands
Online Online
Shannon Member
*****
Karma: 227
Posts: 14051
In theory there is no difference between theory and practice, however in practice there are many...
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
ignoring any reading that is more than one degree more or less than the previous reading.
Code:
if (temp > LastTemp + 1 || temp < LastTemp - 1)  //temp needs to be a full degree +/- than previous reading to be valid

The if condition just test the opposite of what you want ...
Logged

Rob Tillaart

Nederlandse sectie - http://arduino.cc/forum/index.php/board,77.0.html -
(Please do not PM for private consultancy)

Pages: [1]   Go Up
Jump to: