DS18B20 gives inaccurate readings

I've had a box with LCD readout of 4 DS18B20 temp sensors for several months and it works well, occationally i have it log data. Over the summer it was accurate compared to a household thermometer (insides) and weather.com (outsides).

I just purchased a digital 5/2 day thermostat with an LCD readout that puts the temp inside at 3-4 degrees LOWER than the DS18B20 sensor right next to the thermostat. 67 by thermostat, 71 by sensor. Now that it's winter the outside sensor reads about 15-20 degrees HIGHER than weather.com. 0 degrees reads about 18 degrees by the sensor.

Has anyone experienced this? I didn't notice until I saw the thermostat reading being different... Is there a calibration I can do in software, or would re-scaling somehow fix it? I'm not sure why so much temperature drift. I would have thought it would be accurate no matter what the temp.

#include <OneWire.h>
#include <NewSoftSerial.h>
#include <SPI.h>
#include <Ethernet.h>


/* DS18B20 Temperature Address Locations

Mudroom   =   28 45 D5 F6 1 0 0 DF
Inside    =   28 B5 CF F6 1 0 0 6C
Outside   =   28 D7 F2 AF 2 0 0 6
Garage    =   28 E6 4 B0 2 0 0 44

Scans through 4 sensors and prints the embedded serial code for each with array addr[].
Then it does a temperature lookup for each device and prints the temp.
NewSoftSerial for LCD prints, Serial for debug.
*/

// Serial LCD initialization
NewSoftSerial LCDSerial(2, 3);
int bl = LOW;
int backlight;

// Temperature sensor initialization
OneWire  ds(5);  // on pin 5
byte i;
byte present = 0;
byte data[12];
byte addr[8];
int Temp;

// What sensor is being read indication
int inside = 0;
int outside = 0;
int mudroom = 0;
int garage = 0;

// Temperature storage variables
int inside_temp;
int outside_temp;
int mudroom_temp;
int garage_temp;

void set_backlight(int backlight){
  LCDSerial.print(0x7C, BYTE);
  LCDSerial.print(backlight, BYTE);
  delay(100);
  bl = HIGH;
//  Serial.println("backlight on");
}

void backlight_off(){
  LCDSerial.print(0x7C, BYTE);
  LCDSerial.print(128, BYTE);
  bl = LOW;
//  Serial.println("backlight off");
}

void clear_lcd(){
  LCDSerial.print(0xFE, BYTE);
  LCDSerial.print(01, BYTE);
  delay(100);
//  Serial.println("LCD Clear");
}

void setup(void) {
  Serial.begin(9600);
  LCDSerial.begin(9600);
  
  clear_lcd();
  set_backlight(145);
  LCDSerial.print("Startup");
  delay(500);
  LCDSerial.print(".");
  delay(500);
  LCDSerial.print(".");
  delay(500);
  LCDSerial.print(".");
  delay(1000);
  backlight_off();
  clear_lcd();
}

void printTemp(){
  if ( OneWire::crc8( addr, 7) != addr[7]) {
      Serial.print("CRC is not valid!\n");
      return;
  }
  if ( addr[0] != 0x28) {
      Serial.print("Device is not a DS18B20 family device.\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();
//    Serial.print(data[i], HEX);
//    Serial.print("  ");
  }
  Temp=(data[1]<<8)+data[0];//take the two bytes from the response relating to temperature
  Temp=Temp>>4;  //divide by 16 to get pure celcius readout
  Temp=Temp*1.8+32;

  if(inside == HIGH){
    inside_temp = Temp;
    Serial.print(inside_temp);
  }
  else if(outside == HIGH){
    outside_temp = Temp;
    Serial.print(outside_temp);
  }
  else if(mudroom == HIGH){
    mudroom_temp = Temp;
    Serial.print(mudroom_temp);
  }
  else if(garage == HIGH){
    garage_temp = Temp;
    Serial.print(garage_temp);
  }
  inside = LOW;
  outside = LOW;
  mudroom = LOW;
  garage = LOW;
  //  Serial.print("Temperature = ");
  //  Serial.print(Temp);
  Serial.println(); 
} 

void loop(void) {
  if ( !ds.search(addr)) {
      Serial.println();

        if(bl == LOW){
        set_backlight(145);
        delay(100);
        bl = HIGH;
        }
        clear_lcd();
        LCDSerial.print("In:  ");
        LCDSerial.print(inside_temp);
        LCDSerial.print(" Out: ");
        LCDSerial.print(outside_temp);
        LCDSerial.print(" Mud: ");
        LCDSerial.print(mudroom_temp);
        LCDSerial.print(" Gar: ");
        LCDSerial.print(garage_temp);
        delay(10000);
      ds.reset_search();
      return;
  }
    
  if(addr[1] == 0xB5){
    Serial.print("Inside : ");
    inside = HIGH;
    printTemp();
  }
  else if(addr[1] == 0xD7){
    Serial.print("Outside : ");
    outside = HIGH;
    printTemp();
  }
  else if(addr[1] == 0x45){
    Serial.print("Mudroom : ");
    mudroom = HIGH;
    printTemp();
  }
  else if(addr[1] == 0xE6){
    Serial.print("Garage : ");
    garage = HIGH;
    printTemp();
  }
}

Indoors: I'd trust the DS18B20 over the thermostat any day. And are they right next to each other?

Forgive me saying so in an Arduino forum, but: Electronics are an unreliable pain in the place that gets tired if you spend too long on the computer... and I don't mean your fingers!

It may be hard to find... perhaps eBay?... but if you really want to have some fun, get a quality thermometer, as used by chemists, working on the expansion of a liquid. Bind the DS18B20 and the bulb of the thermometer together (even that introduces a problem... some thermometers are designed to sense (mostly) the bulb's tture, others require that the whole thing be the measured tture) and see what you get!

===
Outdoors: There used to be a very active forum (well, newsgroup) at Dallas Semiconductor discussing weather monitoring. Sadly, Dallas got bored, and I haven't seen a GOOD weather forum since, but hunt around. The difficulties of obtaining a good outdoor temperature reading are legion, and non-professional installations frequenly read high, prasticularly during the day (sun heating the place the thermometer is sited), but also sometimes even at night (heat leaking from nearby house)

===
For a shareware program to record and display ttures (and windspeed, barometric pressure, etc, etc... accessible from web) with a Windows PC, see...

By right next to eachother I mean within 6 feet, but same hieght off the ground, same distance from any heat source, approxamately same air circulation. The outside I'd say is affected by the garage because it's poking out the top of the garage door about 6" away... Maybe too close to be accurate.

I will try to move the sensors around and see what I get. If nothing else, I'll know if it's "cold" out. And the thermostat runs the heater, so the inside one isn't critical either... Approxamately knowing is I guess good enough.

Inside:

By right next to eachother I mean within 6 feet, but same hieght off the ground, same distance from any heat source...

Mounted on a wall, I'd guess? And what's behind the wall behind each of them?

And the sensor in the thermostat: On a pcb, I bet. A pcb with electricity in it... which can generate heat.

At...

http://mon277rr.dyndns.org/

... the three horizontal red/yellow lines are ttures from "adjacent" Dallas sensors... and the "hot" one is on a small pcb with just a little low voltage circuitry for other things.

(Sorry about the lack of scale on the Y-axis.)

Outside:

And is the wall it is in front of north facing? South? East or West?

You can compare them meaningfully if both sensors are under the same forced-ventilation. The variation of air-temp within a room is substantial. Convective plumes and radiant heat will vary a lot around the typical room.