[DS18x20][SOLVED] Reading DS1820 and DS18x20 on the same bus

Hoi friends,

i am trying to read Temperature sensors DS1820 (the very old one) and the new DS18x20 (DS18S20, DS18B20) on the same bus.
Due they have different parameters i played around to get the read all together on the same bus (pin).

Here is my code so far:

#include <OneWire.h>
#include <DallasTemperature.h>
 
OneWire  ds(17); //pin für ds1820

/*
0x10, 0x98, 0xB4, 0x3C, 00x0, 00x8, 00x0, 0x97
0x10, 0x67, 0xC0, 0x3C, 00x0, 00x8, 00x0, 0xB3
0x28, 0x53, 0x91, 0xCA, [color=brown]00x4, 00x0, 00x0[/color], 0xAF
*/
 
//DeviceAdresses
DeviceAddress sensor1 = { 0x10, 0x98, 0xB4, 0x3C, 0x0, 0x8, 0x0, 0x97 };
DeviceAddress sensor2 = { 0x10, 0x67, 0xC0, 0x3C, 0x0, 0x8, 0x0, 0xB3 };
DeviceAddress sensor3 = { 0x28, 0x53, 0x91, 0xCA, [color=brown]0x4, 0x0, 0x0[/color], 0xAF };
// DeviceAddress sensor3 = { 0x28, 0x53, 0x91, 0xCA, [color=brown]00x4, 00x0, 00x0[/color], 0xAF }; - causes error while compiling

char sensor1Name[] = "DS1820   - Resistor : ";
char sensor2Name[] = "DS1820   + Resistor : ";
char sensor3Name[] = "DS18B20 + Resistor : ";
 
void setup(void) 
{
  Serial.begin(9600);
}
 
void writeTimeToScratchpad(byte* address)
{
  //reset the bus
  ds.reset();
  //select our sensor
  ds.select(address);
  //CONVERT T function call (44h) which puts the temperature into the scratchpad
  ds.write(0x44,1);
  //sleep a second for the write to take place
  delay(1000);
}
 
void readTimeFromScratchpad(byte* address, byte* data)
{
  //reset the bus
  ds.reset();
  //select our sensor
  ds.select(address);
  //read the scratchpad (BEh)
  ds.write(0xBE);
  for (byte i=0;i<9;i++){
    data[i] = ds.read();
  }
}
 
float getTemperature(byte* address)
{
  int tr;
  byte data[12];
 
  writeTimeToScratchpad(address);
 
  readTimeFromScratchpad(address,data);
 
  //put in temp all the 8 bits of LSB (least significant byte)
  tr = data[0];
 
  //check for negative temperature
  if (data[1] > 0x80)
  {
    tr = !tr + 1; //two's complement adjustment
    tr = tr * -1; //flip value negative.
  }
 
  //COUNT PER Celsius degree (10h)
  int cpc = data[7];
  //COUNT REMAIN (0Ch)
  int cr = data[6];
 
  //drop bit 0
  tr = tr >> 1;
 
  return tr - (float)0.25 + (cpc - cr)/(float)cpc;
}
 
void loop(void) 
{
  float temp1 = getTemperature(sensor1);
  float temp2 = getTemperature(sensor2);
  float temp3 = getTemperature(sensor3);
 
  Serial.print(sensor1Name);
  Serial.print(temp1);
  Serial.println(" Celsius");
 
  Serial.print(sensor2Name);
  Serial.print(temp2);
  Serial.println(" Celsius");
 
  Serial.print(sensor3Name);
  Serial.print(temp3);
  Serial.println(" Celsius");
 
  Serial.println();
  delay(1000);
}

As you can see at the brown marked parts the values of the new DS18B20 (begins with 28 instead of 10) i had to remode the leading 0(zero) to fit the belongings of the compiler - if not, it causes an error even when i test the code.

WITH these manipulations 8) the sketch runs, but gives wrong result (the other two shows about correct 21.50 degree celsius) with 30.5 degress celsius.
When i touch it short, it jumps up to 62 degree celsius.

So, i know something about the MSB and LSB but not enough :smiley: to get them work together.

Did anyone know what to do to get it work ? :roll_eyes:

Hey, I was about to post my own question about a similar issue (first post for me).
From looking at your code, the only thing i realize is that you are far more competent than I am with everything related to electronics.
I used the Dallas temperature library, and frankly it works quite fine (using DS18B20 and DS18S20) and is simple.
I successfuly managed to hook up 6 B types along with 1 S type. It might also work with the "old" ones, as you call them.
Would gladly upload the code had I known how to make that neat frame with the "code:" title the way you did.
Nevertheless, I kinda ran into my own little problem that I would like to solve (not to take the spotlight away from yours, ill share it after we get to fix yours).

Simple click on the #-Button above the text windows or write [ Code ] or [ /Code ] (without spaces) and insert the code via copy and paste between these marks.

#include <OneWire.h>
#include <DallasTemperature.h>
// Data wire is plugged into pin 3 on the Arduino
#define ONE_WIRE_BUS 3
#define TEMPERATURE_PRECISION 10
// Setup a oneWire instance to communicate with any OneWire devices (not just Maxim/Dallastemperature ICs)
OneWire oneWire(ONE_WIRE_BUS);
// Pass our oneWire reference to Dallas Temperature.
DallasTemperature sensors(&oneWire);
// arrays to hold device addresses – replace with your sensors addresses
DeviceAddress device_0 = { 0x28, 0x08, 0xC0, 0x96, 0x03, 0x00, 0x00, 0x91 };
DeviceAddress device_1 = { 0x28, 0xF9, 0x02, 0xF7, 0x04, 0x00, 0x00, 0x10 };
DeviceAddress device_2 = { 0x28, 0x76, 0x9A, 0x7E, 0x04, 0x00, 0x00, 0x1D };
DeviceAddress device_3 = { 0x28, 0x4D, 0xFF, 0x7D, 0x04, 0x00, 0x00, 0x43 };
DeviceAddress device_4 = { 0x28, 0x7E, 0xD3, 0x7E, 0x04, 0x00, 0x00, 0xA6 };
DeviceAddress device_5 = { 0x28, 0x15, 0xAF, 0x7E, 0x04, 0x00, 0x00, 0xD1 };

void setup(){
    // start serial port
    Serial.begin(9600);
    // Start up the library
    sensors.begin();  
    Serial.println("Initialising...");
    Serial.println();
    // set the resolution
    sensors.setResolution(device_0, TEMPERATURE_PRECISION);
    sensors.setResolution(device_1, TEMPERATURE_PRECISION);
    sensors.setResolution(device_2, TEMPERATURE_PRECISION);
    sensors.setResolution(device_3, TEMPERATURE_PRECISION);
    sensors.setResolution(device_4, TEMPERATURE_PRECISION);
    sensors.setResolution(device_5, TEMPERATURE_PRECISION);
  }
// 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 K: ");
    Serial.println(tempC+273.15);
}
void loop(){
     sensors.requestTemperatures();
      // print the temperatures
    Serial.print("Device 0 Temp:");
    printTemperature(device_0);
    Serial.print("Device 1 Temp:");
    printTemperature(device_1);
    Serial.print("Device 2 Temp:");
    printTemperature(device_2);
    Serial.print("Device 3 Temp:");
    printTemperature(device_3);
    Serial.print("Device 4 Temp:");
    printTemperature(device_4);
    Serial.print("Device 5 Temp:");
    printTemperature(device_5);
    Serial.println();
    delay(10000);
}

Its a modification of a sample i found somewhere... perhaps on the library's wiki, can't remember.
you can find more details here: http://www.ay60dxg.com/doc/loguino/class_dallas_temperature.html
Anyways, devices 1-5 are cable sensors (should be DS18B20) placed along a 3-meter cable (cut, connected and wrapped),
and device 0 (it says on it that it is also a DS18B20, contrary to what i posted earlier) is a small one placed on the matrix.
My problem, and i have checked it, appears to be that when the program gets to the line "sensors.begin();",
it gets stuck there (doesnt go on to serial printing and such - inf loop?).
If i unplug device 0 or the cable with devices 1-5 (either one, doesnt matter), the program suddenly continues,
and if i plug them back, it goes on as if there was no problem ever (correct readings every 10 secs).
Alternatively, if i delete the "begin" line whatsoever, the program works fine from start to finish.
I understand nothing from looking at the "begin" command reference (provided link above).
my questions are:

  1. Why the hell does it get stuck on that line, is it the arrangement of the sensors or their type or what?
  2. Whats the importance of the "begin" command, especially if the code works fine without it?
    shouldnt it be some kind of obligatory condition for the sensors item to "ignite"??

Thought maybe because you guys are more familiar with serial communication you might know the answer.

Any help would be greatly appreciated :slight_smile:
And i hope this library might ease your way in getting readings from the sensors.

I found this sample, too - but it seems not work for me as i testest.
The follwoing code works and shall have the advantage to read the sensors "byIndex".

Doesnt know why in the moment, but it works :wink:

i found the fowlloing site where the main things of OneWire-Bus can be found (only in german, but you can translate the site with google).

Parasite Power:

Non-parasite Power:

Another interesting i found was the kind of wiring-methods for the bus and the sensors, so i had found an mistake in my bus-topology and make it more effectiv:
Tree :
Restrictions : 50 - 100 meter / 10 - 20 sensors

Tree with
short lines : NEARLY OPTIMAL
Restrictions : up to 100 meter

Line : OPTIMAL
Restricitons : up to 150 meter

Star :
Restrictions : up to 100 meter / =< 10 sensors

Ring (noGo) :
Restrictions : no function :wink:

I have to read (besides 9 other kinds of sensor datas) anout 20 DS18x20 datas, and some of the topologies? can only handle up to 10.

Here is my test-code for the 1st Three:

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

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

//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);

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

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


void loop(void)
{
 Serial.println();
 Serial.println();
 Serial.println("DS18x20_MIX_OK Sketch");
 Serial.println();
sensors.requestTemperatures(); //to issue a global temperature
//request to all devices on the bus
Serial.println("Requesting temperatures");
sensors.requestTemperatures(); //Send the command to get temperatures
Serial.print("Temperature for Device 1 is: ");
Serial.println(sensors.getTempCByIndex(0));
Serial.println("DONE");
sensors.requestTemperatures(); //Send the command to get temperatures
Serial.print("Temperature for Device 2 is: ");
Serial.println(sensors.getTempCByIndex(1));
Serial.println("DONE");
sensors.requestTemperatures(); //Send the command to get temperatures
Serial.print("Temperature for Device 3 is: ");
Serial.println(sensors.getTempCByIndex(2));
Serial.println("DONE");
//Why „byIndex“? You can have more than one IC on the same bus. 0 refers to the first IC on the wire
}

The problem with stucking i had also: 3 sensors worked fine, the forth one also, but only the 1st time.
Then (in the serial monitor) the 3rd and the 4th sensor where also be repeated and even when i disconnect them, the monitor shows still the same datas (without sensor XD)

Only after a hardware reset all works fine again...

So i read these site and there was written, that it would ALWAYS be better to connect all 3 Pins of EACH DS18x20 with the bus and not to use parasite power.

So, resoldered my complete bus (1st time only the 1st sensor had a resistor, the following used parasite power) and now all is good ! :smiley:

1-Wire | Elaborated Networks GmbH

thx for the link, Informative site, bookmarked!

Thanks Trixi for the very detailed and informative post.

I think i wil have a tree with short lines (really sort, may be 5 cm, to made me able to place the sensors in the correct site -outdoor-maintaining the main cable in position -inside a cover to protect from the environment).

However, you said something interesting:

1st time only the 1st sensor had a resistor

Do you mean that each sensor should have its own resistor? This is the first time i readed something like that. My idea, and what i readed here and there in this forum and everywhere, is that the resistor is one per bus... Could you confirm that with a configuration of multiple sensors it works? Thanks!

As i have tested out each one needs one :wink:
I also read never about that, but all descriptions are for sensors of the same type.

If not, it will read (beginning from the first one on the bus) until it reaches the first other-type-ds18xxx (in my case the 4th one).
Then the reading will return each second (seems that the bus hangs) with the same device AND the device before !

Maybe because it is a mix of different types a 4,7k is needed at each sensor.

Also i disabled the begin.sensors(); part, because then an error occurs.
As i read the Devices byIndex(x), it works as long as the sensor adresses are defined before :grin:

On Nick Gammon's Website i found the following hint:

The Atmega328 is configured to use internal pull-up resistors which may be adequate for short cable runs.
Warning: for multiple I2C devices, or longer cable runs, the 4.7K pull-up resistor (for each line) is recommended

Thanks Trixi!

But i undestand that each line means each cable with one or more sensors... so, one per line, not per sensor...
However, it is great to know that one resistor per sensor works for you!!

I will test it!
Thanks for the tip!

A.R.Ty:
On Nick Gammon's Website i found the following hint:

The Atmega328 is configured to use internal pull-up resistors which may be adequate for short cable runs.
Warning: for multiple I2C devices, or longer cable runs, the 4.7K pull-up resistor (for each line) is recommended

This totally throws me. If you have a star topology, this implies that you need one resistor for each leg, but if they are all shorted together at the port pin, does this mean that the resistor should be at the end of the line and the connection should be 3-wire (eg, not parasitic)? OK, time for a test--for two long legs, will a 2.2K resistor do the job. Back soon.

Well, blow me down. With two 30' cables the "address finder" code could find each address when only one was connected at time (with 4.67K resistor). Did not work with both cables. I added another 4.7K to the port pin and viola', both addresses popped up.

This doesn't seem to have anything [much] to do with the load presented by multiple DS1820s, but only how many wires are coming together at the port. Admittedly, these 22-4 cables have relatively high cable capacitance. The same experiment using 24 gauge pairs didn't require the added resistor. I assume the if the 22-4 cables were significantly shorter, they would work with one resistor. Emphasize "assume."

Hoi,

yes, youre right: if you use different wires (on the same bus) you need to terminate each wire with a 4.7k, no matter what topology you use: star, tree, bus etc.