Pages: [1] 2   Go Down
Author Topic: 1 Wire DS18B20  (Read 2860 times)
0 Members and 1 Guest are viewing this topic.
California
Offline Offline
Sr. Member
****
Karma: 2
Posts: 433
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

I am using this library to get temperature from my two DS18B20 chips. I have tried using this code, the code in the library example and using the modifications on the first linked page and I still get weird results. Even with just one chip connected. Here is the example code unmodified:

Code:
#include <OneWire.h>

// OneWire DS18S20, DS18B20, DS1822 Temperature Example
//
// http://www.pjrc.com/teensy/td_libs_OneWire.html
//
// The DallasTemperature library can do all this work for you!
// http://milesburton.com/Dallas_Temperature_Control_Library

OneWire  ds(10);  // on pin 10

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

void loop(void) {
  byte i;
  byte present = 0;
  byte type_s;
  byte data[12];
  byte addr[8];
  float celsius, fahrenheit;
  
  if ( !ds.search(addr)) {
    Serial.println("No more addresses.");
    Serial.println();
    ds.reset_search();
    delay(250);
    return;
  }
  
  Serial.print("ROM =");
  for( i = 0; i < 8; i++) {
    Serial.write(' ');
    Serial.print(addr[i], HEX);
  }

  if (OneWire::crc8(addr, 7) != addr[7]) {
      Serial.println("CRC is not valid!");
      return;
  }
  Serial.println();
 
  // the first ROM byte indicates which chip
  switch (addr[0]) {
    case 0x10:
      Serial.println("  Chip = DS18S20");  // or old DS1820
      type_s = 1;
      break;
    case 0x28:
      Serial.println("  Chip = DS18B20");
      type_s = 0;
      break;
    case 0x22:
      Serial.println("  Chip = DS1822");
      type_s = 0;
      break;
    default:
      Serial.println("Device is not a DS18x20 family device.");
      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("  Data = ");
  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.println();

  // convert the data to actual temperature

  unsigned int raw = (data[1] << 8) | data[0];
  if (type_s) {
    raw = raw << 3; // 9 bit resolution default
    if (data[7] == 0x10) {
      // count remain gives full 12 bit resolution
      raw = (raw & 0xFFF0) + 12 - data[6];
    }
  } else {
    byte cfg = (data[4] & 0x60);
    if (cfg == 0x00) raw = raw << 3;  // 9 bit resolution, 93.75 ms
    else if (cfg == 0x20) raw = raw << 2; // 10 bit res, 187.5 ms
    else if (cfg == 0x40) raw = raw << 1; // 11 bit res, 375 ms
    // default is 12 bit resolution, 750 ms conversion time
  }
  celsius = (float)raw / 16.0;
  fahrenheit = celsius * 1.8 + 32.0;
  Serial.print("  Temperature = ");
  Serial.print(celsius);
  Serial.print(" Celsius, ");
  Serial.print(fahrenheit);
  Serial.println(" Fahrenheit");
}

and I get these results:

Code:
ROM = 28 18 9E CF 0 0 0 52
  Chip = DS18B20
  Data = 1 F8 FD 0 0 1F FF 8 10 EA  CRC=EA
  Temperature = 3836.00 Celsius, 6936.80 Fahrenheit
ROM = 28 6F 73 D1 0 0 0 54
  Chip = DS18B20
  Data = 1 F0 FD 0 0 1F FF 10 10 5A  CRC=5A
  Temperature = 3832.00 Celsius, 6929.60 Fahrenheit
No more addresses.

After using the modifications on that page I get different numbers, but still very strange:
Code:
ROM = 28 18 9E CF 0 0 0 52
  Chip = DS18B20
  Data = 1 F8 FD 0 0 1F FF 8 10 EA  CRC=EA
  Temperature = -32.50 Celsius, -26.50 Fahrenheit
ROM = 28 6F 73 D1 0 0 0 54
  Chip = DS18B20
  Data = 1 F0 FD 0 0 1F FF 10 10 5A  CRC=5A
  Temperature = -33.00 Celsius, -27.40 Fahrenheit
No more addresses.
This room is about 27C. When I hold a chip the number rises(as in gets closer to 0) so it's not just inverted or something.

When I use the Dallas Temperature IC Control Library I get these results:
Code:
Dallas Temperature IC Control Library Demo
Locating devices...Found 2 devices.
Parasite power is: OFF
Device 0 Address: 28189ECF00000052
Device 1 Address: 286F73D100000054
Device 0 Resolution: 9
Device 1 Resolution: 9
Requesting temperatures...DONE
Device Address: 28189ECF00000052 Temp C: -32.50 Temp F: -26.50
Device Address: 286F73D100000054 Temp C: -33.00 Temp F: -27.40

I am using the pullup resistor and using external power supply... What is goin on here?

Thanks
« Last Edit: November 08, 2012, 01:34:53 am by stoopkid » Logged

Global Moderator
Offline Offline
Brattain Member
*****
Karma: 452
Posts: 18694
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
Temperature = 3832.00 Celsius, 6929.60 Fahrenheit
...

Device Address: 28189ECF00000052 Temp C: -32.50 Temp F: -26.50

Clearly you are living in one of those places that suffers from extreme temperature variations. Are you still alive?
Logged

UK
Offline Offline
Shannon Member
****
Karma: 184
Posts: 11197
-
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

How are you powering the sensor?
Logged

I only provide help via the forum - please do not contact me for private consultancy.

Offline Offline
Edison Member
*
Karma: 35
Posts: 1429
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

See the Known Bugs section on the PJRC page. You have to apply those two patches to the code for it to work properly.

Pete
Logged

Where are the Nick Gammons of yesteryear?

Dee Why NSW
Offline Offline
Full Member
***
Karma: 5
Posts: 206
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

I couldn't get any of that Miles Burton stuff to work, but this does.

It is currently for 2x DS18B20s and gives the difference.

Code:
//  This Arduino sketch reads DS18B20 "1-Wire" digital
//  temperature sensors.
//  Copyright (c) 2010 Mark McComb, hacktronics LLC
//  License: http://www.opensource.org/licenses/mit-license.php (Go crazy)
//  Tutorial:
//  http://www.hacktronics.com/Tutorials/arduino-1-wire-tutorial.html
//  messed about, compacted, and metricated by Nick Pyner

//  Research your own LCD pins!

#include <OneWire.h>
#include <DallasTemperature.h>
#include <LiquidCrystal.h>

LiquidCrystal lcd(8,9,14,5,6,7); // patchwire is to A0 (pin14) on this proto
int flag;
// Data wire is on pin 3
#define ONE_WIRE_BUS 3
// Setup a oneWire instance to communicate with any OneWire devices
OneWire oneWire(ONE_WIRE_BUS);

// Pass our oneWire reference to Dallas Temperature.
DallasTemperature sensors(&oneWire);

// Assign the addresses of your 1-Wire temp sensors.
DeviceAddress InThermo = {  
  0x28, 0x69, 0xC2, 0xB0, 0x03, 0x00, 0x00, 0X9F };
DeviceAddress OutThermo = {
  0x28, 0x7A, 0x8B, 0xC0, 0x03, 0x00, 0x00, 0x2F };

//temperature variables
float InTemp, OutTemp, diff, drain, flow, power, tempC;

void setup(void)
{
  // start serial port
  Serial.begin(9600);

  // set up the LCD's number of columns and rows:
  lcd.begin(16, 2);
 
  // Print a message to the LCD.
  lcd.print("temp in     out");    

  // Start up the library
  sensors.begin();

  sensors.setResolution(InThermo, 12);
  sensors.setResolution(OutThermo, 12);
}

void loop(void)
{
  delay(1000);
  flag = 0;
  //Get the sensor readings. There are two of them
  sensors.requestTemperatures();
  Serial.print("  Input temp : ");
  GetandPrint(InThermo);
  InTemp=tempC;
  flag = 1;
  Serial.print("      Output temp   : ");
  GetandPrint(OutThermo);
  diff = tempC - InTemp;
  Serial.print("      diff  : ");
  Serial.print (diff);
  diff=diff+15;//dummy
  flow=10;//dummy
  power=diff*flow/14.34;   //real
  Serial.print("      flow  l/min   : ");
  Serial.print(flow);
  Serial.print("      power (kW)   : ");
  Serial.print(power);
  Serial.println();
}

void GetandPrint(DeviceAddress deviceAddress)
{
tempC = sensors.getTempC(deviceAddress);
  if (tempC == -127.00) {
    Serial.print("Error getting temperature");
  }
  else {
    Serial.print(tempC);
  }
  lcd.setCursor (1,1);
  if (flag==1)
    (
    lcd.setCursor (11,1)
      );
  lcd.print (tempC);
}

On looking at yours: Firstly, the most notable line is the comment

// The DallasTemperature library can do all this work for you!

This is true, but you don't appear to have it included it.

Secondly, note that I'm a newbie but I am working in this arena and your sketch looks utterly alien to me, and yet it does claim to work with the DS18B20. I can't even see any reference to the probes' addresses, a line like

DeviceAddress OutThermo = { 0x28, 0x7A, 0x8B, 0xC0, 0x03, 0x00, 0x00, 0x2F };

which is what the Dallas one-wire system is all about and, without them, you would probably sink at the mooring. This may be because you really are working without the Dallas libraries and the abovementioned comment is just that - a comment. In that event I submit you should take it as seriously actionable advice instead.

You should find the code I attach quite typical for the job, and hopefully helpful too.
« Last Edit: November 08, 2012, 06:37:01 pm by NickPyner » Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 3
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Nick,

Thanks for posting that code, it will be very helpful to me when I start working on my next project, where I want to place temperature sensors in multiple (at least 10) remote locations and use the Arduino to collect and store the sensor data.

I'm just starting my research on the various components that I'll need for the project, when I saw this topic. It sounds like you may have done something similar and was wondering if I could ask you a few questions.

  • In the datasheet for the DS18B20 I haven't been able to find what maximum length the data line (wire) for the sensors can be as I would like to be able to put all my sensors on a single data line that would most likely exceed 500 feet. Would there be a need to some how boost or repeat the signal with a distance this large? If so, what would you suggest?
  • Are you powering the sensors with an external power source or are you in using them in "parasite mode"?
  • Can you post a Fritzing diagram to show how you have the temperature sensors wired to the Arduino?

Thanks for any information/links that you can provide.

Regards,
--Greg
Logged

Global Moderator
Offline Offline
Brattain Member
*****
Karma: 452
Posts: 18694
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

See this maybe: http://arduino.cc/forum/index.php/topic,21762.0.html
Logged

Offline Offline
Edison Member
*
Karma: 35
Posts: 1429
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
which is what the Dallas one-wire system is all about and, without them, you would probably sink at the mooring.
The example code posted by the OP in his first message doesn't need a device address. It checks all devices on the I2C and looks for a DS18B20 and then talks that. All that is needed to get that code working is to apply the two fixes at http://www.pjrc.com/teensy/td_libs_OneWire.html#bugs

Pete
Logged

Where are the Nick Gammons of yesteryear?

Dee Why NSW
Offline Offline
Full Member
***
Karma: 5
Posts: 206
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Wow! This is getting serious, but I'm afraid I'm not sure I can be of much help

 
In the datasheet for the DS18B20 I haven't been able to find what maximum length the data line (wire) for the sensors can be as I would like to be able to put all my sensors on a single data line that would most likely exceed 500 feet. Would there be a need to some how boost or repeat the signal with a distance this large? If so, what would you suggest?

This is a completely different extreme for me. My remote is 500 miles but I just take the DS18B20 with the cable it comes with. In my case it is 5m! I have seen them 10m but I wouldn't be surprised if they don't get any longer, so you are right to ask the question.

Clearly there are two problems, power out and signal back, and, at 500 feet, I'm betting you will have at least one of them.  A 5v supply at the remote point may fix both.  

 
Quote
Are you powering the sensors with an external power source or are you in using them in "parasite mode"?

My sensors just get their power off the board.  I have two at this stage and they simply plug into a (very) short prototyping shield.
I simply set it up according to this tutorial

http://www.hacktronics.com/Tutorials/arduino-1-wire-tutorial.html

Note that there is just one common pull-up resistor.

 
Quote
Can you post a Fritzing diagram to show how you have the temperature sensors wired to the Arduino?

I'm not sure that would help. It is a one-wire system and the tut. above says it all. I just did exactly what it said.  What you really need to know about is stuff I don't know about, which are all to do with size and scale. If I was doing it, I imagine I would make up a separate distribution board with a single three core cable that plugs into one of my temp terminals.  

You may find you are obliged to use a wireless link. There is a whole arena covering that. I'm not talking about WiFi, it's something else, but I don't know anything about it. It's called something like Zigbee and I believe it may work with the Teensy MCU, which talks Arduino.

On reflection, you may find this a more practical solution. Teensys are so cheap they are probably cheaper than the cable you are talking about!! And don't even talk about the stress incurred installing it - all 500 feet.....,  
« Last Edit: November 08, 2012, 09:46:56 pm by NickPyner » Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 3
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Nick Gammon,

Thanks for the link, there is a nice article related to reliable long distance 1-wire networks:

http://www.maximintegrated.com/app-notes/index.mvp/id/148

Nick Pryner,

Thanks for the link to the tutorial, I'll definitely check it out.

Regards,
--Greg
Logged

Dee Why NSW
Offline Offline
Full Member
***
Karma: 5
Posts: 206
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Keep us posted, Greg.

Needless to say, my remote installations will be on the internet. In one station this is going to be painless. In another, it might not be and I need to plan for any contingency. This is not about such huge distances, just local built environment making the internet connection difficult.  Right now I am about to explore bluetooth but I will be very interested to hear how you go.
Logged

California
Offline Offline
Sr. Member
****
Karma: 2
Posts: 433
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

I am powering the sensor from the arduino's 5v.

I have applied the patches, the second results I posted are from after patching. They are the same results as the Dallas Library.

The sketch I used for the last results is this:
Code:
#include <OneWire.h>
#include <DallasTemperature.h>

// Data wire is plugged into port 2 on the Arduino
#define ONE_WIRE_BUS 2
#define TEMPERATURE_PRECISION 9

// Setup a oneWire instance to communicate with any OneWire devices (not just Maxim/Dallas temperature ICs)
OneWire oneWire(ONE_WIRE_BUS);

// Pass our oneWire reference to Dallas Temperature.
DallasTemperature sensors(&oneWire);

// arrays to hold device addresses
DeviceAddress insideThermometer, outsideThermometer;

void setup(void)
{
  // start serial port
  Serial.begin(9600);
  Serial.println("Dallas Temperature IC Control Library Demo");

  // Start up the library
  sensors.begin();

  // locate devices on the bus
  Serial.print("Locating devices...");
  Serial.print("Found ");
  Serial.print(sensors.getDeviceCount(), DEC);
  Serial.println(" devices.");

  // report parasite power requirements
  Serial.print("Parasite power is: ");
  if (sensors.isParasitePowerMode()) Serial.println("ON");
  else Serial.println("OFF");

  // assign address manually.  the addresses below will beed to be changed
  // to valid device addresses on your bus.  device address can be retrieved
  // by using either oneWire.search(deviceAddress) or individually via
  // sensors.getAddress(deviceAddress, index)
  //insideThermometer = { 0x28, 0x1D, 0x39, 0x31, 0x2, 0x0, 0x0, 0xF0 };
  //outsideThermometer   = { 0x28, 0x3F, 0x1C, 0x31, 0x2, 0x0, 0x0, 0x2 };

  // search for devices on the bus and assign based on an index.  ideally,
  // you would do this to initially discover addresses on the bus and then
  // use those addresses and manually assign them (see above) once you know
  // the devices on your bus (and assuming they don't change).
  //
  // method 1: by index
  if (!sensors.getAddress(insideThermometer, 0)) Serial.println("Unable to find address for Device 0");
  if (!sensors.getAddress(outsideThermometer, 1)) Serial.println("Unable to find address for Device 1");

  // method 2: search()
  // search() looks for the next device. Returns 1 if a new address has been
  // returned. A zero might mean that the bus is shorted, there are no devices,
  // or you have already retrieved all of them.  It might be a good idea to
  // check the CRC to make sure you didn't get garbage.  The order is
  // deterministic. You will always get the same devices in the same order
  //
  // Must be called before search()
  //oneWire.reset_search();
  // assigns the first address found to insideThermometer
  //if (!oneWire.search(insideThermometer)) Serial.println("Unable to find address for insideThermometer");
  // assigns the seconds address found to outsideThermometer
  //if (!oneWire.search(outsideThermometer)) Serial.println("Unable to find address for outsideThermometer");

  // show the addresses we found on the bus
  Serial.print("Device 0 Address: ");
  printAddress(insideThermometer);
  Serial.println();

  Serial.print("Device 1 Address: ");
  printAddress(outsideThermometer);
  Serial.println();

  // set the resolution to 9 bit
  sensors.setResolution(insideThermometer, TEMPERATURE_PRECISION);
  sensors.setResolution(outsideThermometer, TEMPERATURE_PRECISION);

  Serial.print("Device 0 Resolution: ");
  Serial.print(sensors.getResolution(insideThermometer), DEC);
  Serial.println();

  Serial.print("Device 1 Resolution: ");
  Serial.print(sensors.getResolution(outsideThermometer), DEC);
  Serial.println();
}

// function to print a device address
void printAddress(DeviceAddress deviceAddress)
{
  for (uint8_t i = 0; i < 8; i++)
  {
    // zero pad the address if necessary
    if (deviceAddress[i] < 16) Serial.print("0");
    Serial.print(deviceAddress[i], HEX);
  }
}

// function to print the temperature for a device
void printTemperature(DeviceAddress deviceAddress)
{
  float tempC = sensors.getTempC(deviceAddress);
  Serial.print("Temp C: ");
  Serial.print(tempC);
  Serial.print(" Temp F: ");
  Serial.print(DallasTemperature::toFahrenheit(tempC));
}

// function to print a device's resolution
void printResolution(DeviceAddress deviceAddress)
{
  Serial.print("Resolution: ");
  Serial.print(sensors.getResolution(deviceAddress));
  Serial.println();   
}

// main function to print information about a device
void printData(DeviceAddress deviceAddress)
{
  Serial.print("Device Address: ");
  printAddress(deviceAddress);
  Serial.print(" ");
  printTemperature(deviceAddress);
  Serial.println();
}

void loop(void)
{
  // call sensors.requestTemperatures() to issue a global temperature
  // request to all devices on the bus
  Serial.print("Requesting temperatures...");
  sensors.requestTemperatures();
  Serial.println("DONE");

  // print the device information
  printData(insideThermometer);
  printData(outsideThermometer);
}

Nick, your code gives me these results:
Code:
  Input temp : -36.06      Output temp   : -36.50      diff  : -0.44      flow  l/min   : 10.00      power (kW)   : 10.16
  Input temp : -36.06      Output temp   : -36.50      diff  : -0.44      flow  l/min   : 10.00      power (kW)   : 10.16
  Input temp : -36.06      Output temp   : -36.50      diff  : -0.44      flow  l/min   : 10.00      power (kW)   : 10.16
  Input temp : -36.00      Output temp   : -36.50      diff  : -0.50      flow  l/min   : 10.00      power (kW)   : 10.11


This code from the hacktronics page give me a similar result(yes these are my addresses):
Code:
// This Arduino sketch reads DS18B20 "1-Wire" digital
// temperature sensors.
// Tutorial:
// http://www.hacktronics.com/Tutorials/arduino-1-wire-tutorial.html

#include <OneWire.h>
#include <DallasTemperature.h>

// Data wire is plugged into pin 3 on the Arduino
#define ONE_WIRE_BUS 3

// Setup a oneWire instance to communicate with any OneWire devices
OneWire oneWire(ONE_WIRE_BUS);

// Pass our oneWire reference to Dallas Temperature.
DallasTemperature sensors(&oneWire);

// Assign the addresses of your 1-Wire temp sensors.
// See the tutorial on how to obtain these addresses:
// http://www.hacktronics.com/Tutorials/arduino-1-wire-address-finder.html

DeviceAddress insideThermometer = { 0x28, 0x18, 0x9E, 0xCF, 0x00, 0x00, 0x00, 0x52 };
DeviceAddress outsideThermometer = { 0x28, 0x6F, 0x73, 0xD1, 0x00, 0x00, 0x00, 0x54 };

void setup(void)
{
  // start serial port
  Serial.begin(9600);
  // Start up the library
  sensors.begin();
  // set the resolution to 10 bit (good enough?)
  sensors.setResolution(insideThermometer, 10);
  sensors.setResolution(outsideThermometer, 10);
}

void printTemperature(DeviceAddress deviceAddress)
{
  float tempC = sensors.getTempC(deviceAddress);
  if (tempC == -127.00) {
    Serial.print("Error getting temperature");
  } else {
    Serial.print("C: ");
    Serial.print(tempC);
    Serial.print(" F: ");
    Serial.print(DallasTemperature::toFahrenheit(tempC));
  }
}

void loop(void)
{
  delay(2000);
  Serial.print("Getting temperatures...\n\r");
  sensors.requestTemperatures();
 
  Serial.print("Inside temperature is: ");
  printTemperature(insideThermometer);
  Serial.print("\n\r");
  Serial.print("Outside temperature is: ");
  printTemperature(outsideThermometer);
  Serial.print("\n\r\n\r");
}
results:
Code:
Getting temperatures...

Inside temperature is: C: -35.75 F: -32.35

Outside temperature is: C: -36.25 F: -33.25



So basically with all of these different codes and libraries, I am getting consistent results but they are not accurate. Could there be a problem with my chips? What else could be going on?

Thanks
Logged

Offline Offline
Edison Member
*
Karma: 116
Posts: 2205
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

There are something seriously wrong with your code (some of which are quite obvious).

For example, the first sensor returns 0xf801 -> that should have been translated into a negative temperature but you got 1000+c.

Read the datasheet and  understand what 9-bit or 10-bit resolution means, and what 2's complement means.
Logged

Dee Why NSW
Offline Offline
Full Member
***
Karma: 5
Posts: 206
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote from: stoopkid
Could there be a problem with my chips? What else could be going on?

I don't think there is the slightest need to understand two complements in order to work that out. The answer is "very probably" to the first, and "not much" to the second.

I'm afraid I sent you a later version of my sketch with some dummy commands in it but that is irrelevant. What is relevant is that the Hacktronics DS18B20 section works perfectly. In the light of that, the fact that your code gives results consistent with mine clearly suggests there is nothing wrong with that either. Further, even in the unlikely event that your code isn't kosher, that is not your real problem.

So there are really only three things that can be wrong.

1. The Arduino, presumably proven OK by other means

2. The chips

3. The connection between them.

Addressing item 3 first, if you wire the chips the wrong way round, they get seriously hot. Unfortunately, I can't recall what reading they produce, if any. If this is what has happened, you won't be left in any doubt about it, but they will also survive - if you wake up to it reasonably quickly. If you have done a sloppy job soldering up a proto shield, I guess it is possible to get spurious signals. I don't know anything about that but I suspect they would not be consistent.

After that, I can't see that there is much left, and the bone points to item 2.

On reflection, The only thing that points away from faulty chips is the consistency. That would suggest that both are faulty, and the fault is the same, which sounds a bit too much of a coincidence.
Hummm... In the light of that, I suggest you check the wiring order. Trust me, if one is wrong, the other will be too. That's consistency.... You might even get a quick test by touching the probe - briefly. Indeed I suggest you do this before you read up on twos complements.
Logged

Offline Offline
Edison Member
*
Karma: 35
Posts: 1429
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Let's start with something that is known to work. The code below works on a Duemilanove wired as described here.
For parasite power the DS18B20 is wired so that the two outer leads are connected to ground. The middle lead has a 1.5k pullup resistor to +5V. The middle lead is also connected to pin 8 on the Arduino. Then run this code:
Code:
#include <OneWire.h>

// http://datasheets.maxim-ic.com/en/ds/DS18B20.pdf

// OneWire DS18S20, DS18B20, DS1822 Temperature Example
//
// http://www.pjrc.com/teensy/td_libs_OneWire.html
// The two bugs in the conversion of the temperature have been fixed.
// The first bug didn't handle the precision correctly for anything
// other than 12 bits.
// The second bug was that the temperature was converted as an
// unsigned int which meant that it wouldn't convert a negative
// temperature correctly.

OneWire  ds(8);

// SELECT a precision here
// t_precision #bits -  delay(ms)
//      0        9   -   93.75
//      1       10   -  187.5
//      2       11   -  375
//      3       12   -  750
#define ds18b20_PRECISION 2
unsigned char t_precision = ds18b20_PRECISION;

// DS18B20 address data
byte addr[8][8];
byte data[12];
const unsigned char t_mask[4] = {
  0x7, 0x3, 0x1, 0x0};

void print_rom(byte *p)
{
  Serial.print("ROM =");
  for(int i = 0; i < 8; i++) {
    Serial.write(' ');
    if(*p < 10)Serial.print(" ");
    Serial.print(*p++, HEX);
  }
  Serial.println(" "); 
}


void setup(void)
{
  byte i,numdev;
  byte present = 0;
  byte type_s;
  float celsius, fahrenheit;

  Serial.begin(9600);
  i = 0;
  Serial.println("");
  Serial.println("");
  while(ds.search(addr[i])) {
    if (OneWire::crc8(addr[i], 7) != addr[i][7]) {
      print_rom(addr[i]);
      Serial.println("CRC is not valid! - ignored");
      continue;
    }
    print_rom(addr[i]);
    i++;
  }
  if(i == 0) {
    Serial.println("Nothing found");
    Serial.println();
    ds.reset_search();
    delay(250);
    return;
  }
  numdev = i;

  for(int j=0;j<numdev;j++) {
    Serial.println();
    // This clears the alarm registers and sets the precision
    ds.select(addr[j]);   
    ds.write(0x4E,0);
    // write zero into the alarm registers
    ds.write(0,0);
    ds.write(0,0);
    // and write t_precision into the configuration register
    // to select the precision of the temperature
    ds.write(t_precision << 5,0);
    // Write them to the EEPROM
    ds.write(0x48,1);

    delay(20);
    ds.depower();
    // the first ROM byte indicates which chip
    switch (addr[j][0]) {
    case 0x10:
      Serial.print("  Chip = DS18S20 ");  // or old DS1820
      type_s = 1;
      break;
    case 0x28:
      Serial.print("  Chip = DS18B20 ");
      type_s = 0;
      break;
    case 0x22:
      Serial.print("  Chip = DS1822  ");
      type_s = 0;
      break;
    default:
      Serial.println("Device is not a DS18x20 family device.");
      continue;
    }
    print_rom(addr[j]);

    ds.reset();
    ds.select(addr[j]);
#define PARASITE
#ifdef PARASITE
    ds.write(0x44,1);         // start conversion, with parasite power on at the end
#else
    ds.write(0x44,0);
#endif
    delay(1000);

    // we might do a ds.depower() here, but the reset will
    // take care of it.
    present = ds.reset();
    ds.select(addr[j]);   
    ds.write(0xBE,0);         // Read Scratchpad

    Serial.print("present=");
    Serial.print(present,HEX);
    Serial.print(" prec=");
    Serial.print(t_precision);
    Serial.print(" Data = ");
    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.println();

    // BUG - this must NOT be unsigned otherwise it won't handle
    // negative temperatures.
    int raw = (data[1] << 8) | data[0];
    // The original version of this code had a bad bug here which
    // only worked when it was reading with 12-bit precision.
    // This code fixes it (and emailed the author).
    //  int cfg = (data[4] & 0x60) >> 5;
    // For now, override the precision stored in the device until I can
    // figure out why the code is not setting it.
    int cfg = t_precision;
    raw &= ~t_mask[cfg];
    celsius = (float) raw / 16.0;
    Serial.print("  Temperature = ");
    Serial.print(celsius,4);
    Serial.println(" Celsius");
    //  fahrenheit = celsius * 1.8 + 32.0;
    //  Serial.print(fahrenheit);
    //  Serial.println(" Fahrenheit");

  } // END OF FOR J LOOP

}


void loop(void)
{
}

It produces this output:
Code:
ROM = 28 B9 E6 79  3  0  0 16

  Chip = DS18B20 ROM = 28 B9 E6 79  3  0  0 16
present=1 prec=2 Data = 53 1 4B 46 7F FF D 10 E9  CRC=E9
  Temperature = 21.1250 Celsius

This code scans the bus so you don't need to know the address of the chip.

Pete
Logged

Where are the Nick Gammons of yesteryear?

Pages: [1] 2   Go Up
Jump to: