SOLVED: DS18B20 temp probe failure with long cable

Hello forum,

I found this read only thread which got me in the right direction in solving my failing probes on long cables.

https://forum.arduino.cc/index.php?topic=20574.0

I did what the contributors suggested and replaced the 4.7k resitor with a 2.2k one and it sends back a reasonable value, mostly just when I plug in the sensor, and then it sends back -127.

I use a MEGA with a total of 6 probes. The first two have cable of around 3 meters (works fine) the second pair is on roughly 8 meter cable (works fine) and the last set on about 18 meter cable, and its here that I'm having a challenge. I use CAT 6 SFTP cable and I doubled up one twisted pair to send 5V to the sensors and doubled up another pair to send GND.

I power these 6 probes with a DC converter that takes 12V from a continually charged 9Ah 12V battery and makes available 5A at 5V. The signal wires coming back from each probe goes to its own digital pin, from 2 and ending at 7. The two problematic (long) cables are on pins 2 and 3.

In the thread I mentioned above someone mentioned the need to change the onewire.cpp file, but this was back in 2009 and when looking at the current version (I use 2.3.4) it seems like these delays have been included.

If someone here could tell me if the current onewire.cpp is adequate to deal with long cable runs, or if I should change anything here, I would appreciate some advice. Also, if I need to change anything on the hardware side I would appreciate some guidance.

Thanks,
Hein

This is the onewire.cpp that I currently have:

void OneWire::write_bit(uint8_t v)
{
 IO_REG_TYPE mask=bitmask;
 volatile IO_REG_TYPE *reg IO_REG_ASM = baseReg;

 if (v & 1) {
 noInterrupts();
 DIRECT_WRITE_LOW(reg, mask);
 DIRECT_MODE_OUTPUT(reg, mask); // drive output low
 delayMicroseconds(10);
 DIRECT_WRITE_HIGH(reg, mask); // drive output high
 interrupts();
 delayMicroseconds(55);
 } else {
 noInterrupts();
 DIRECT_WRITE_LOW(reg, mask);
 DIRECT_MODE_OUTPUT(reg, mask); // drive output low
 delayMicroseconds(65);
 DIRECT_WRITE_HIGH(reg, mask); // drive output high
 interrupts();
 delayMicroseconds(5);
 }
}

//
// Read a bit. Port and bit is used to cut lookup time and provide
// more certain timing.
//
uint8_t OneWire::read_bit(void)
{
 IO_REG_TYPE mask=bitmask;
 volatile IO_REG_TYPE *reg IO_REG_ASM = baseReg;
 uint8_t r;

 noInterrupts();
 DIRECT_MODE_OUTPUT(reg, mask);
 DIRECT_WRITE_LOW(reg, mask);
 delayMicroseconds(3);
 DIRECT_MODE_INPUT(reg, mask); // let pin float, pull up will raise
 delayMicroseconds(10);
 r = DIRECT_READ(reg, mask);
 interrupts();
 delayMicroseconds(53);
 return r;
}
1 Like

Did you also try filter capacitors across the arduino supply rails - such as across arduino 5V pin and arduino GND? Multiple decoupling capacitor in parallel? -SOLVED - General Electronics - Arduino Forum

Also take a look at : click here

The guy/girl used a 1.2 K resistor for their pullup resistor.

1 Like

Hang on, each cable must have one data wire only. The data wire should be paired with ground always.
All the devices on one cable share the data line.

1 Like

Southpark:
Did you also try filter capacitors across the arduino supply rails - such as across arduino 5V pin and arduino GND? Multiple decoupling capacitor in parallel? -SOLVED - General Electronics - Arduino Forum

Also take a look at : click here

The guy/girl used a 1.2 K resistor for their pullup resistor.

I have not tried any caps, I will start playing with this tomorrow. Found this video very informative on why multiple caps may be necessary for this higher frequency chip:

1 Like

MarkT:
Hang on, each cable must have one data wire only.

Ok - I see now that I've not done what I guess is accepted as standard connecting of multiple probes. I have separate data lines for each probe. Would it make a difference though? I realise I've wasted some cable by doing this and I will definitely change the way I run cable in multiple probes in future, but having seperate data lines won't be the cause of the problem, right?

MarkT:
The data wire should be paired with ground always.

Do you mean the data and ground lines must be a twisted pair? This isn't the case with my installation, I can change it and see what it does.

1 Like

heinburgh:
I have not tried any caps, I will start playing with this tomorrow.

Before trying the caps. Try the 1.2 K resistor first.

1 Like

heinburgh:
Ok - I see now that I've not done what I guess is accepted as standard connecting of multiple probes. I have separate data lines for each probe. Would it make a difference though?

Absolutely. Lots of crosstalk is the obvious danger, and lack of termination resistor at the end of each data line.

OneWire means one data wire.

Ok I'm revisiting my 6 x DS18B20 probes at the end of a 14m CAT 5 cable. The installation will be such that the probes tap into the cable at different intervals up to the last one where the cable terminates. But for the sake of testing I have all six probes connected at the end of the cable. I added a 2.2k resistor across 5V and the signal wires. I've tried powering the probes from the MEGA 5V supply as well as from a seperate 5V / 5A supply with the same results.

Questions to the forum:

  1. When using cat 5, do I improve or worsen the situation when I bundle up a twisted pair to lower impedance? In other words one joined pair for 5V, one joined pair for GND and one joined pair for signal. Is it better to just use a single wire instead of doubling up?

  2. Does it make a difference whether the probes are all connected to the cat 5 cable where it terminates as opposed to joining the probes along the length of the cable at different intervals?

  3. When adding caps as @Southpark suggested across the power rails, what size would be appropriate here?

  4. Would it help to slow down the frequency, and if so, how can I do this using the OneWire library?

With my current setup I'm testing them with a sketch that scans for all available chips and gets their temps every second. Results are very random, sometimes it picks up all six probes but only retrieves one or two temps, sometimes it picks up zero probes and anything inbetween.

What can I do to improve these results?

16:34:15.731 -> Locating devices...Found 2 devices.
16:34:15.768 -> 
16:34:15.768 -> Sensor 1 : 30.12⸮C  |  86.22⸮F
16:34:15.768 -> Sensor 2 : -127.00⸮C  |  -196.60⸮F
16:34:15.801 -> 
16:34:17.068 -> Locating devices...Found 6 devices.
16:34:17.068 -> 
16:34:17.068 -> Sensor 1 : -127.00⸮C  |  -196.60⸮F
16:34:17.101 -> Sensor 2 : -127.00⸮C  |  -196.60⸮F
16:34:17.138 -> Sensor 3 : 28.31⸮C  |  82.96⸮F
16:34:17.138 -> Sensor 4 : -127.00⸮C  |  -196.60⸮F
16:34:17.172 -> Sensor 5 : -127.00⸮C  |  -196.60⸮F
16:34:17.172 -> Sensor 6 : -127.00⸮C  |  -196.60⸮F
16:34:17.243 -> 
16:34:18.218 -> Locating devices...Found 0 devices.
16:34:18.253 -> 
16:34:18.253 -> 
16:34:19.287 -> Locating devices...Found 1 devices.
16:34:19.321 -> 
16:34:19.321 -> Sensor 1 : 30.00⸮C  |  86.00⸮F
16:34:19.356 -> 
16:34:20.332 -> Locating devices...Found 0 devices.
16:34:20.368 -> 
16:34:20.368 -> 
16:34:21.424 -> Locating devices...Found 1 devices.
16:34:21.458 -> 
16:34:21.458 -> Sensor 1 : 30.19⸮C  |  86.34⸮F
16:34:21.458 -> 
16:34:22.542 -> Locating devices...Found 2 devices.
16:34:22.580 -> 
16:34:22.580 -> Sensor 1 : 30.06⸮C  |  86.11⸮F
16:34:22.580 -> Sensor 2 : -127.00⸮C  |  -196.60⸮F
16:34:22.617 -> 
16:34:23.656 -> Locating devices...Found 1 devices.
16:34:23.656 -> 
16:34:23.656 -> Sensor 1 : -127.00⸮C  |  -196.60⸮F
16:34:23.689 -> 
16:34:24.754 -> Locating devices...Found 2 devices.
16:34:24.788 -> 
16:34:24.788 -> Sensor 1 : 30.12⸮C  |  86.22⸮F
16:34:24.826 -> Sensor 2 : 29.56⸮C  |  85.21⸮F
16:34:24.859 -> 
16:34:26.023 -> Locating devices...Found 3 devices.
16:34:26.023 -> 
16:34:26.023 -> Sensor 1 : -127.00⸮C  |  -196.60⸮F
16:34:26.058 -> Sensor 2 : -127.00⸮C  |  -196.60⸮F
16:34:26.058 -> Sensor 3 : -127.00⸮C  |  -196.60⸮F
16:34:26.092 -> 
16:34:27.102 -> Locating devices...Found 1 devices.
16:34:27.140 -> 
16:34:27.140 -> Sensor 1 : -127.00⸮C  |  -196.60⸮F
16:34:27.140 -> 
16:34:28.285 -> Locating devices...Found 3 devices.
16:34:28.319 -> 
16:34:28.319 -> Sensor 1 : -127.00⸮C  |  -196.60⸮F
16:34:28.319 -> Sensor 2 : 29.69⸮C  |  85.44⸮F
16:34:28.355 -> Sensor 3 : -127.00⸮C  |  -196.60⸮F
16:34:28.393 -> 
16:34:29.461 -> Locating devices...Found 2 devices.
16:34:29.497 -> 
16:34:29.497 -> Sensor 1 : -127.00⸮C  |  -196.60⸮F
16:34:29.531 -> Sensor 2 : -127.00⸮C  |  -196.60⸮F
16:34:29.568 -> 
16:34:30.551 -> Locating devices...Found 0 devices.
16:34:30.586 -> 
16:34:30.586 -> 
16:34:31.572 -> Locating devices...Found 0 devices.
16:34:31.610 -> 
16:34:31.610 -> 
16:34:32.657 -> Locating devices...Found 1 devices.
16:34:32.657 -> 
16:34:32.657 -> Sensor 1 : 30.19⸮C  |  86.34⸮F
16:34:32.690 -> 
16:34:33.797 -> Locating devices...Found 2 devices.
16:34:33.834 -> 
16:34:33.834 -> Sensor 1 : 30.19⸮C  |  86.34⸮F
16:34:33.834 -> Sensor 2 : 29.62⸮C  |  85.32⸮F
16:34:33.871 -> 
16:34:34.876 -> Locating devices...Found 0 devices.
16:34:34.911 -> 
16:34:34.911 -> 
16:34:35.946 -> Locating devices...Found 1 devices.
16:34:35.982 -> 
16:34:35.982 -> Sensor 1 : 30.19⸮C  |  86.34⸮F
16:34:36.019 -> 
16:34:37.260 -> Locating devices...Found 6 devices.
16:34:37.293 -> 
16:34:37.293 -> Sensor 1 : 30.12⸮C  |  86.22⸮F
16:34:37.327 -> Sensor 2 : 29.69⸮C  |  85.44⸮F
16:34:37.362 -> Sensor 3 : -127.00⸮C  |  -196.60⸮F
16:34:37.396 -> Sensor 4 : 30.25⸮C  |  86.45⸮F
16:34:37.469 -> Sensor 5 : -127.00⸮C  |  -196.60⸮F
16:34:37.469 -> Sensor 6 : -127.00⸮C  |  -196.60⸮F

The sketch:

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

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

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

// Pass oneWire reference to DallasTemperature library
DallasTemperature sensors(&oneWire);

int deviceCount = 0;
float tempC;

void setup(void)
{
  
}

void loop(void)
{ 
  
  sensors.begin();  // Start up the library
 // sensors.setResolution(12);
  Serial.begin(19200);
  
  // locate devices on the bus
  Serial.print("Locating devices...");
  Serial.print("Found ");
  deviceCount = sensors.getDeviceCount();
  Serial.print(deviceCount, DEC);
  Serial.println(" devices.");
  Serial.println("");
  
  
  // Send command to all the sensors for temperature conversion
  sensors.requestTemperatures(); 
  
  // Display temperature from each sensor
  for (int i = 0;  i < deviceCount;  i++)
  {
    Serial.print("Sensor ");
    Serial.print(i+1);
    Serial.print(" : ");
    tempC = sensors.getTempCByIndex(i);
    Serial.print(tempC);
    Serial.print((char)176);//shows degrees character
    Serial.print("C  |  ");
    Serial.print(DallasTemperature::toFahrenheit(tempC));
    Serial.print((char)176);//shows degrees character
    Serial.println("F");
  }
  
  Serial.println("");
  delay(1000);
}

One 100nF ceramic cap per chip, as normal for almost everything out there. You can share a cap for sensors that are next to each other, but each chip needs its decoupling cap next to it, not far away.

OneWire doesn't have a frequency, the timing is fixed in stone.

You don't understand twisted pairs. The net current of each pair should be zero, so that you'd pair
signal+ground in one pair, +5V/ground in another pair.

Do not connect any part of the circuit to anything metal at the far end, its only connection to ground must be at the
Arduino end.

MarkT:
You don't understand twisted pairs. The net current of each pair should be zero, so that you'd pair
signal+ground in one pair, +5V/ground in another pair.

But it is impossible to balance the current in those pairs. When the sensor asserts a HIGH on the data wire, some current comes in the power wire and goes out on the data wire. When it asserts a LOW, the "pair" is data and ground. Worse, those currents may be seperated in time: the power going out the data wire is actually coming from the decoupling capacitor, not the power wire.

Without a balanced-unbalanced conversion, which is completely unwarranted in this application, there is no benefit and some disadvantages to using twisted pair cable.

Update on my progress:

I tried with a 2k resistor across 5v and signal, and the results were still a bit sketchy. I didn't have a 1.2k with me so I used the 2k with 4k7 in parallel and all of a sudden the readings were consistently present.

This was with the 14m cable rolled up and lying next to me, so I uncoiled it throughout the house and suddenly readings came 50/50, different probes showing up and disappearing randomly. So I changed the wiring as @MarkT suggested, 5v and GND in a twisted pair, as well as DATA and GND in a pair - the results are much better, but still missing the odd probe every 3rd cycle or so.

The cable I have is non-shielded cat5, so I'm guessing if I change this to shielded it should solve the problem.

I'll post the results here as soon as I get the new cable.

Final update: So the shielded CAT5 cable is 3 hours drive away. While arranging to get a roll of it I rummaged through my stuff and found some shielded screen cable which has two insulated core (VERY thin wire) with a third uninsulated core, and the lot is very well shielded with solid foil.

I cut off an 18 meter piece of it, soldered all the probes onto the end, wacked it into the MEGA and they are purring like little kittens.

So my solution:

-> 1.2k resistor across 5V and SIGNAL at the arduino (substituted with 2k and 4.7k in parallel)
-> shielded 3 core (non-twisted) shielded cable
-> no caps used.

PS: For those interested in getting accurate readings using DS18B20 probes, I just used the method outlined here:

And now I have all six probes never more than 0.1 degrees apart. With all six frequently being at exactly the same value, when I display the values with one decimal place. These close values maintained all the way from boiling point back to room temperature, without the values ever varying more than 0.1 degrees.

And the probes never miss a beat, on my 18 meter cable (plus 3 meter lead on each probe.) I am very pleased at the moment.

Great! Thanks for the feedback.

So today I tried something different, instead of having the long cable with all six probes connected in parallel at the end of the cable, I tapped a probe from the cable at 2m intervals. When I got to the third probe, my arduino wouldn't recognise any of them. So I removed the third probe, tested, and the arduino read the first two just fine. Then I added another probe, and the Arduino wouldn't read any of them. Then I left the first two as is, and connected the remaining four at the same point in parallel, and the arduino reads them all ok most of the time. Every tenth or so read one of the probes would go missing, on the next read it will come back and another one will go missing, next read its back and another one missing, then all probes back again and reading well for few reads.

What am I missing here??

This is the code I run to search for all probes and read their temps every 15 seconds.

void beginProbes()
{
  sensors.begin();
  Serial.print("Locating devices...");
  Serial.print("Found ");
  Serial.print(sensors.getDeviceCount(), DEC);
  Serial.println(" devices.");

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

  if (!sensors.getAddress(probe01, 0)) Serial.println("Unable to find address for Device 0");
  if (!sensors.getAddress(probe02, 1)) Serial.println("Unable to find address for Device 1");
  if (!sensors.getAddress(probe03, 2)) Serial.println("Unable to find address for Device 2");
  if (!sensors.getAddress(probe04, 3)) Serial.println("Unable to find address for Device 3");
  if (!sensors.getAddress(probe05, 4)) Serial.println("Unable to find address for Device 4");
  if (!sensors.getAddress(probe06, 5)) Serial.println("Unable to find address for Device 5");

  Serial.print("Device 0 Address: ");
  printAddress(probe01);
  Serial.println();

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

  Serial.print("Device 2 Address: ");
  printAddress(probe03);
  Serial.println();

  Serial.print("Device 3 Address: ");
  printAddress(probe04);
  Serial.println();

  Serial.print("Device 4 Address: ");
  printAddress(probe05);
  Serial.println();

  Serial.print("Device 5 Address: ");
  printAddress(probe06);
  Serial.println();

  sensors.setResolution(probe01, TEMPERATURE_PRECISION);
  sensors.setResolution(probe02, TEMPERATURE_PRECISION);
  sensors.setResolution(probe03, TEMPERATURE_PRECISION);
  sensors.setResolution(probe04, TEMPERATURE_PRECISION);
  sensors.setResolution(probe05, TEMPERATURE_PRECISION);
  sensors.setResolution(probe06, TEMPERATURE_PRECISION);

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

  Serial.print("Device 1 Resolution: ");
  Serial.print(sensors.getResolution(probe02), DEC);
  Serial.println();
  
  Serial.print("Device 2 Resolution: ");
  Serial.print(sensors.getResolution(probe03), DEC);
  Serial.println();

  Serial.print("Device 3 Resolution: ");
  Serial.print(sensors.getResolution(probe04), DEC);
  Serial.println();
   
  Serial.print("Device 4 Resolution: ");
  Serial.print(sensors.getResolution(probe05), DEC);
  Serial.println();

  Serial.print("Device 5 Resolution: ");
  Serial.print(sensors.getResolution(probe06), DEC);
  Serial.println();

}

After they're found and initiated I send the instruction to check temps:

  Serial.print("Requesting temperatures...");
  sensors.requestTemperatures();
  Serial.println("DONE");

And then I extract the value:

void printTemperature(DeviceAddress deviceAddress)
{
  temporary = sensors.getTempC(deviceAddress);
}

Now would be a great time to have an oscilloscope to see what is really going on with the levels on the data wire. You might have the pullup too strong so the sensors can't pull it all the way down to the LOW threshold or you may have it too weak and it takes too long for the HIGH threshold.

You haven't said how they are powered. Are you using parasite power or you have 5V on the long cable too?

Your code snippets don't show you waiting for the conversion time required between requesting a reading and reading it.

It's powered by 5V.

There is no delay between requesting and reading the value, what would be an appropriate delay?

I need to get a scope.

Up to one second "conversion time" is required for parasite-powered. 5v powered can work faster.

The basic library hides this detail by just delaying an appropriate time.