Multiple DS18B20, read problems

Hello,

I've got two DS18B20 with "waterproof" housing and communicate using the OneWire library and an old Arduino NG. I brew beer from time to time and I'm checking if these sensors will work for monitoring the process. This means they will be in very warm water, sometimes boiling hot.
I got everything working with the code below at room temperature. I then proceeded to put one of them in some water while i heated it until it was boiling. At about 65-70C I stopped getting values from the sensor that was not in the water. Sometimes it reported back but with a weird device adress. A few more C and they both stopped working. I then disconnected the sensor that was not in the water and the other sensor started working again. When the boiled sensor cooled down they both worked again.

My theory is that when larger values are returned from the sensor it will somehow interfere with the onewire communication alltogether. Any ideas?

I got the code from a guide on the interwebs. I modified it somewhat so that it would only print device adress and temperature for my project.

#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) {
  int HighByte, LowByte, TReading, SignBit, Tc_100, Whole, Fract;
  byte i;
  byte present = 0;
  byte data[12];
  byte addr[8];

  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(" ");
  }
  Serial.print("\n");

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

  if ( addr[0] == 0x10) {
      Serial.print("Device is a DS18S20 family device.\n");
  }
  else if ( addr[0] == 0x28) {
//      Serial.print("Device is a DS18B20 family device.\n");
  }
  else {
      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
  // 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.println();
  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

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

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

  Serial.print("\n");
}

You might find it easier to use the DallasTemperature library instead. It's doing much the same as yours behind the scenes, but you don't need to worry about having fat fingered something when you adapted that code.

Pinky:
My theory is that when larger values are returned from the sensor it will somehow interfere with the onewire communication altogether. Any ideas?

The DS18B20 is good for 125C. If your theory was correct, everybody would know about it by now and the device would have been superceded, or Dallas would be out of business. I wouldn't like to say the sensor is dud. They can take a lot of abuse.

The code looks junk. Here is something that works. Check the Hacktronics tutorial.

//  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
//  code uses Arduino LCD stuff, for shield on Freetronics EtherTen.
//  Serial print commands are for PLX-DAQ


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

LiquidCrystal lcd(8,9,56,5,6,7); // patchwire is D4 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);
  Serial.println("LABEL,Time,TempIn,TempOut,diff");
  // 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);
    Serial.print("DATA,TIME,       "); 
  flag = 0;
  //Get the sensor readings. There are two of them
  sensors.requestTemperatures();

  GetandPrint(InThermo);
  InTemp=tempC;
  flag = 1;

  GetandPrint(OutThermo); 
  diff = tempC - InTemp;
  Serial.print (diff); 
  Serial.println(" ,  ");

} 

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

I've tried using the DallasTemperature library earlier. I chose not to use it because it needs a lot of my precious memory. I'm on a NG with the ATMEGA8 so I dont have a lot to spare. The modifications of that code was simply commenting out a few println's to keep only the output i wanted. The original is here, on the playground: http://playground.arduino.cc/Learning/OneWire.

I'll do the experiment again using the DallasTemperature lib anyway. I'll report right back when it's done.

Not much luck for me today. I used the very simple code below and it wont even detect my sensors if they are both connected. No problem one at a time though.
I've wired my sensors exactly like this:

#include <OneWire.h>

#include <DallasTemperature.h>


 
// Data wire is plugged into pin 10 on the Arduino
#define ONE_WIRE_BUS 10
 
// 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);
DeviceAddress tmp_address; 
int numberOfDevices;
void setup(void)
{
  // start serial port
  Serial.begin(9600);
  Serial.println("Looking for sensors...");
  // Start up the library
  sensors.begin();
  delay(6000);

numberOfDevices = sensors.getDeviceCount();
Serial.print("Found ");
Serial.print(numberOfDevices);
Serial.println(" sensors. Starting now...");
}
 
 
void loop(void)
{
  // call sensors.requestTemperatures() to issue a global temperature
  // request to all devices on the bus
  sensors.requestTemperatures(); // Send the command to get temperatures
for(int i=0;i<numberOfDevices; i++)
  {
    Serial.print(i);
    Serial.print(":");
    Serial.println(sensors.getTempCByIndex(i));
    delay(100);
    
  }
  Serial.println();
  delay(1000);
  
 
}

While that diagram may be kosher, I fail to see the point in doing it that way.

Just try connecting

  1. both 5v to 5v
  2. both gnd to gnd
  3. both signal to signal
  4. add the 4.7 pullup

thereby removing all doubts.

The point is using what's called parasitic mode. Read more about that here: Arduino Playground - OneWire

That being said i did try it the way you described and got the exact same result.

Just to make sure that the library detected that parasite mode was being used add this after the delay(6000) in setup.

  if(sensors.isParasitePowerMode())Serial.println("parasite powered");
  else Serial.println("NOT parasite powered");

Pete

No, the point is, there is no point. And the first par under

Powering OneWire devices

makes (faintly) interesting reading, where the words "often" and "probably" come up more than they should.

As I said, the devices seem very robust, so I guess that leaves your code....

el_supremo:
Just to make sure that the library detected that parasite mode was being used add this after the delay(6000) in setup.

  if(sensors.isParasitePowerMode())Serial.println("parasite powered");

else Serial.println("NOT parasite powered");




Pete

Now that's interesting. I put everything back to parasitic mode, but the printout says NOT parasite powered... I triple checked the connections.

Nick_Pyner:
No, the point is, there is no point.

There is a point, but that is not the point of this conversation. Almost all examples using the DS18B20 sensor is using that setup, thats why I chose it.

the words "often" and "probably" come up more than they should

But that isn't the datasheet.

the printout says NOT parasite powered

The begin function in the Dallas library searches the bus for devices. For each device that answers it checks to see if the device is parasite powered. If so, it sets a "parasite" flag and then assumes everything is parasite powered after that. It doesn't think your bus is parasite powered.
The problem, I think, is that the resistor you are using is too high a value for parasite mode. Try a 1k5 - that's what I'm using on a bus that has four DS18B20.

Pete

I've never been able to get them to work in parasite mode. Obviously it's achievable, but you might as well eliminate one source of possible problems while you're debugging.

OK, I went the non-parasitic way. Again.
Now things are working intermittently. Below is an output example:

Looking for sensors...
NOT parasite powered
Found 2 sensors. Starting now...
0:22.00
1:22.56

0:-127.00
1:22.56

0:-127.00
1:22.00

0:22.00
1:-127.00

0:22.00
1:22.50

0:21.94
1:21.94

0:21.94
1:22.44

0:-127.00
1:22.44

0:21.94
1:22.37

0:21.87
1:-127.00

0:21.87
1:22.37

0:-127.00
1:-127.00

EDIT: This is weird. Left it running for a few minutes and the errors are getting further and further inbetween. Do these things need to warm up? LOL :slight_smile:
Anyway it would seem we are on to something with parasitic mode not being detected and me needing glasses. I don't know what I did between the different times I set up the non parasitic wiring but it must have been something.

It seems I am getting the -127 readings only when touching the sensor cables. I got them waterproofed with 1.8m cable and as soon as I touch the cable or sensor housing (all plastic) i get -127 readings. How can that be?

EDIT: And also i did another boil test. Somewhere around 80C i start getting -127 readings as well. sigh

You are using screened cable and decoupling capacitors on each device? You can't often get away with unscreened cable
in an electrically noisy environment. Adding supply decoupling will reduce the chances of noise problems too.

One of the reasons parasite power isn't easy to get working is that you cannot use decoupling with it.

And no, DS18B20's don't have a warming-up period.

Pinky:
I've wired my sensors exactly like this:

And now you are talking about cabling, which is just as well, as that could be the problem - bad cables and bad connections. The 127 suggests sensor not connected but I guess it could also mean "connected but unreadable".

You might be better off proving the point with the breadboard setup you alluded to.

Having said that, I got caught short with my local installation and chanced using 1.2m of cheapo four-conductor I had to hand. I think it worked, but luck, the short length, and an electrically-quiet suburban environment probably had lot to do with it.

Wiring/cabling:
I've connected it all on a breadboard, but the sensors have 1.8m cables that they where delivered with.

So I solved the problem with faulty readings when touching the cables, it seems to have been bad grounding that was the problem. I found them to be very stable if my computer (laptop) was not plugged into an external power source and i used a 9V battery to power the arduino.

Still I have the problem where if both sensors are connected I cannot get a reading above ~84C. If I disconnect one sensor when that happens I get the values just fine.

Could be inadequate power.

The power-on reset value of the temperature register is +85°C and I think I saw it when I was starving it with supply via USB.

That might be it. I gotta admit I'm new to the electronics-part of this. I do have a separate power supply that can give me 5 or 9V and 1.5A. Got any wiring suggestions, or should i just plug it to the external 9V power-connector on the arduino?

No wiring, just check the polarity and use 9v. The 1.5A is plenty. Don't be tempted to use the 5v. It sounds kosher but it isn't enough for the on board regulators to do their job, and there is no need to tempt fate by applying it directly to the Vin pin.