DS18S20P code issues

I’m having problems getting getting the correct temperature from a DS18S20P using an Arduino Diecimila. I don’t know C, but am trying to use the Arduino to teach me.

The wiring is:
GND to GND
VDD to GND
PIN10 to DQ
5V to 4.7K Ohm to DQ

My Diecimila software is version 0011.
The code is from http://www.arduino.cc/playground/Learning/OneWire
I’m also using (linked from the page above) “The most recent [OneWire library]” http://homepage.mac.com/wtpollard/Software/FileSharing7.html

I’m not sure why the sample code only prints the temperature in HEX. It would seem more useful in HEX, C, and F.

I decided to try a section of code from the forums to convert it to F. http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1208206686 (Reply #2)

Here is my code:

#include <OneWire.h>

/* DS18S20 Temperature chip i/o
 
 */

OneWire  ds(10);  // on pin 10

void setup(void) {
  // initialize inputs/outputs
  // start serial port
  Serial.begin(9600);
}

void loop(void) {
  byte i;
  byte present = 0;
  byte data[12];
  byte addr[8];
  int Temp;
  if ( !ds.search(addr)) {
      //Serial.print("No more addresses.\n");
      ds.reset_search();
      return;
  }
  
  Serial.print("R=");
  for( i = 0; i < 8; i++) {
    Serial.print(addr[i], HEX);
    Serial.print(" ");
  }

  if ( OneWire::crc8( addr, 7) != addr[7]) {
    Serial.print("CRC is not valid!\n");
    return;
  }
  
  if ( addr[0] != 0x10) {
      Serial.print("Device is not a DS18S20 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
  // we might do a ds.depower() here, but the reset will take care of it.
  
  present = ds.reset();
  ds.select(addr);    
  ds.write(0xBE);         // Read Scratchpad

  Serial.print("P=");  
  Serial.print(present,HEX);
  Serial.print(" ");
  for ( i = 0; i < 9; i++) {           // we need 9 bytes
    data[i] = ds.read();
    Serial.print(data[i], HEX);
    Serial.print(" ");
  }
  
  Serial.print(" CRC=");
  Serial.print( OneWire::crc8( data, 8), HEX);
  Serial.print("  ");
  
  //get temp in something besides hex
  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

  //next line is Fahrenheit conversion
  Temp=Temp*1.8+32; // comment this line out to get celcius
  
  Serial.print("Temperature=");//output the temperature to serial port
  Serial.print(Temp);
  Serial.println();

}

The output I’m getting is

R=10 5A D4 F 1 8 0 1C P=1 46 0 4B 46 FF FF F 10 9E  CRC=9E  Temperature=39
R=10 5A D4 F 1 8 0 1C P=1 46 0 4B 46 FF FF F 10 9E  CRC=9E  Temperature=39
R=10 5A D4 F 1 8 0 1C P=1 46 0 4B 46 FF FF 10 10 6A  CRC=6A  Temperature=39
R=10 5A D4 F 1 8 0 1C P=1 46 0 4B 46 FF FF 10 10 6A  CRC=6A  Temperature=39

My mercury thermometer is reading in the mid 90’s Fahrenheit. (Yes, it’s HOT here!)

Where am I going wrong?

You are using floating point math with an int (Temp). Try changing the datatype of Temp.

  Temp=Temp>>4;//divide by 16 to get pure celcius readout

Ok, got the code to work correctly by changing the above line to

  Temp=Temp>>1; //divide by 2 to get pure celcius readout of DS18S20

I was able to verify this by commenting out the request for temp, and just reading the default temp. (85C (185F) according to the datasheet)

This has to do with where the data to the left of the decimal is stored, since the DS18S20 has less resolution than the DS18B20.

I'll write up a bigger explanation in the next few days.