1-Wire, DS18B20... How do I search the bus?

FWIW, I currently have 4 1-wire devices hooked up to my Arduino,
2 1820's and 2 18B20's and have not had a single problem although
the distance between the Arduino and my sensors is about 6-inches (15-cm).
[Yeah, I know, not very useful 'cept for testing the sensors]

Longer runs will probably require a stronger pullup resistor (lower
resistance) on the data line (I'm using the standard 4K7-ohm resistor)
and probably low-capacitive cabling like CAT-5 or 5e. Longer runs
may possibly preclude the use of parasitic power and require Vcc to
be brought down the cable as well.

Dallas Semi (now part of Maxim IC) has a number of documents with
regards to longer 1-wire network cabling if that's what you're dealing
with.

Rusty -- Can you hook up a couple more devices and see if search still works? I found that the OneWire search code would fail when adding the 5th or 4th device, depending on which devices were already on the bus. I assume this is because the particular id bit patterns lead the search algorithm toward or away from the faulty logic. Perhaps having two different device codes is protecting you from the faulty logic too. -- Ward

Ward,
I've dumped 4 1820's and 2 18B20's onto my Arduino. I'm having no
problems with the search algorithm although search() is only called
after a system reset/powerup. Parasitic power is NOT used and the
data line has a 4k7 ohm resistor pulling it up to +5v.

I have now commented out line 268 as suggested by Waffle, deleted the OneWire.o file to cause a recompile, and tested the revised code with seven devices. It works.

For those who might want to duplicate this fix, here is a print out of the area in question with the commented line in place.

263 } else { // we are blazing new tree, take the 0
264 a = 0;
265 searchJunction = i;
266 done = 0;
267 }
268 // lastJunction = i;
269 }
270 if ( a) address[ ibyte] |= ibit;
271 else address[ ibyte] &= ~ibit;

I had the same problem as soon as I added a 6th device to my prototype DS18B20 network (parasite powered). Only 2 devices were affected; as soon as I removed either of them, the search function worked properly. The symptom of the problem was a search that endlessly cycled between device 28 C6 and 28 5E

My devices (all values in hex):

28 78 09 06 02 00 00 92
28 1C 23 02 02 00 00 C6
28 C6 0D 06 02 00 00 99 <-- remove either device 28 C6
28 5E FB 05 02 00 00 3B <-- or device 28 5E for search to work
28 01 47 02 02 00 00 D9
28 D9 FF 05 02 00 00 4B

Once I commented out line 268 and recompiled the OneWire library, all devices work fine.

Rx

YAY! Thank you.

This is great, I was stuck with the same problem: I could connect the AAG weather station (3 sensors) but when i tried to add one more ds18s20 the search program got in a loop.
Thank you for the detailed solution.

I've been banging my head over this problem for two days now. I finally wised up and decided to check the forums. :o

My problem manifested itself only when I recompiled the OneWire.cpp source code. I finally figured out that if I linked to the supplied object file, everything worked fine. I guess the problem must have gotten fixed at some point, and the OneWire.o file updated in the library, but not the source.

How can we get the source code updated in the library so others won't experience this? I sure would like to have those two days back!

Has there been a long term fix for this issue at this time?

I have a bus of 10 DS18S20s and the arduino still gets confused and goes into a loop in the same way mentioned my the original poster.

When I put 4 on the same bus it seems to work okay, when I put 6 on the same bus it works for a bit then goes into a loop, when I put 10 on a bus the whole thing just goes into the loop.

I changed the OneWire.CPP file as advised above and made sure the object file was removed and recompiled.

I cant split the bus up into 2 by 5 sensor buses because at least one of the sensor loops has already been installed during construction and its got more than 10 sensors on it already in difficult to re-wire locations.

crunch, I've re-coded the search function from the ground-up. Hopefully this fixes the bug once and for all. You can download this new version of the library here: http://waffle.netlogistics.com.au/arduino/OneWire8.zip

Let me know how it goes. If it works I'll update the playground article.

Waffle,

This works better, but not perfectly. Now I can have 6 sensors on the bus if I swap a new one in it will be detected.

No more addresses.
Unique ID=2C:EF:4:1:8:0:

Unique ID=52:F9:39:1:8:0:

Unique ID=41:7F:39:1:8:0:

Unique ID=5D:F9:39:1:8:0:

Unique ID=CB:B:5:1:8:0:

Unique ID=FB:E8:38:1:8:0:

No more addresses.

If I insert a 7th sensor

No more addresses.
Unique ID=2C:EF:4:1:8:0:

Unique ID=52:F9:39:1:8:0:

Unique ID=41:7F:39:1:8:0:

Unique ID=5D:F9:39:1:8:0:

Unique ID=CB:B:5:1:8:0:

Unique ID=1B:0:0:0:0:2:   <--- Point I put the new sensor onto the bus

Unique ID=1B:0:0:0:0:2:

Unique ID=1B:0:0:0:0:2:

Unique ID=1B:0:0:0:0:2:

The above will just continue in an infinite loop.

Is there any more information I can provide for you to help?

Can you give me the seven addresses (all eight bytes of each) of the devices when placed together that cause the loop problem? Then I'll be able to test the search algorithm on that combination of addresses to work out where the problem is.

The following addresses

2C:EF:4:1:8:0:
52:F9:39:1:8:0:
41:7F:39:1:8:0:
5D:F9:39:1:8:0:
CB:B:5:1:8:0:
7A:4D:5:1:8:0
7:48:5:1:8:0
FB:E8:38:1:8:0
41:7F:39:1:8:0

Furhter testing indicates 7A:4D:5:1:8:0 when added to the bus in certain combinations will cause a loop

Further: 7A.... causes problems but then so do other ones added after 6....

Hmm...?

I've just noticed something, these should be 32byte values (similar to a mac address on a network card) some of the values are being truncated if they are 0... ?

for instance 7A:4D:5:1:8:0 SHOULD be 7A:4D:50:10:80:00 or 7A:4D:05:01:08:00 ?

I checked the algorithm against your device addresses and it seems to be fine so I'm not sure what's causing your problem.

As for the 7A:4D:5:1:8:0, it should be 7A:4D:05:01:08:00. This is just a result of the Serial.Print function discarding the leading 0 for each byte. It's not a problem.

I don't know what else to do about your problem except for you to avoid using the search function and just address all the devices on the bus individually.

After many frustrating evenings, I finally fixed the problem on mine (7 sensors) by completely replacing the search method in OneWire.cpp with the reference search implementation at the bottom of the maxim page: Mixed-signal and digital signal processing ICs | Analog Devices.
It works fine now. I originally tried to reconcile the existing code with the flowchart on that page, but it was just too convoluted for me to follow.
It wasn't too hard to replace. I had to modify the reset_search() method to clear the appropriate variables (just like in the reference OWFirst() method) and add a line from the original search to copy the address from the ROM_NO array to the one that is passed in to the method.

Thanks. Maybe you can help with getting the playground page updated with the fixes you made? (I have fingers crossed)

I tried to update the playground, but was told I have "insufficient privileges". :-?

If anyone wants my updated OneWire library, it can be downloaded at http://www.depowell.com/Arduino/OneWireUpdatedSearch.zip. It should be a drop-in replacement for OneWire.cpp and OneWire.h.

Okay, I just put 7 sensors on a bus (one by one) and watched what it did. the 7th still made it loop.

This is using omnitronic's new library..

There must be somethign a lot more fundamental at fault here than simply recoding the search function. Is it possible that there is a hardware limitation?

My electronics and programing experience is very small. I can work with what other people have done and expand on it bit by bit. But I am not much use at the whole low level diagnostics stuff. ALl I can really do here is test what other people have done and say "not in my implimentation"

Yes indeed it seems to be hardware related. The only thing I can suggest is using a pull-up resistor in the range of 1.5 - 2 kOhm as opposed to the normal 4.7 kOhm.

I had the same looping problem with the search function. The looping seems to depend on the individual addresses for some reason, not on the number of sensors. Anyway, I rewrote the search algorithm.

I had my new version working successfully with up to 12 sensors, and I haven't seen it loop yet. This was with Arduino 11. For the record, I was using a 4K7 resistor.

Here is my code for the search routine:

//
// Perform a search. If this function returns a '1' then it has
// enumerated the next device and you may retrieve the ROM from the
// OneWire::address variable. If there are no devices, no further
// devices, or something horrible happens in the middle of the
// enumeration then a 0 is returned.  If a new device is found then
// its address is copied to newAddr.  Use OneWire::reset_search() to
// start over.
//
// searchJunction is the branch on the current address at which the
//    current search is to continue -
//    prior to this point the path follows the previous address
//    after this point, at each junction, 0 is selected
// lastJunction is the last unexplored junction on the present path.
//    the next search will continue from here
// 
uint8_t OneWire::search(uint8_t *newAddr)
{
  uint8_t i = 0;
  char lastJunction = -1;

  if ( searchExhausted) return 0;
  searchExhausted = 1; // the search is exhausted unless we find another junction

  if ( !reset()) return 0;
  write( 0xf0, 0);    // send search ROM

  for( i = 0; i < 64; i++) {
    uint8_t a = read_bit( );
    uint8_t nota = read_bit( );
    uint8_t ibyte = i/8;
    uint8_t ibit = 1<<(i&7);

    if ( a && nota) return 0;  // I don't think this should happen, this means nothing responded, but maybe if
    // something vanishes during the search it will come up.
    if ( !a && !nota) {                    // if at a junction, then
      if ( i < searchJunction) {           // if before search junction
        if ( address[ ibyte]&ibit)  a = 1; // follow previous address
        else a = 0;
      }
      else { 
        if ( i == searchJunction) a = 1;// at the search junction take the new branch.
        else a = 0;                     // past the search junction, on a new branch so select 0
      }
      if (!a) {             // if 0 is chosen
        lastJunction = i;   // set last junction
        searchExhausted = 0; // continue the search
      }
    }

    if (a) address[ibyte] |= ibit; // set address bit
    else address [ibyte] &= ~ibit;
    write_bit( a);
  } // end of address bit loop
  searchJunction = lastJunction;                    // set searchJunction for the next call to Search

  for ( i = 0; i < 8; i++) newAddr[i] = address[i]; // copy found address into output address
  return 1;  
}
#endif

And I put this in the header after Tom Pollard's note to clarify the version:

Modified to work with larger numbers of devices - avoids loop.
Tested in Arduino 11 alpha with 12 sensors.
26 Sept 2008 -- Robin James

If you are not sure how to update your library, do it this way:
first make a copy of your existing library, and put it in a safe place - i.e. not in "libraries". This is insurance!
Then in OneWire.cpp, delete the search routine and replace it with the one above. Also add the new header comment.
Filnally, delete the file OneWire.o. This will be regenerated when you restart Arduino.

I would have posted the full files here, but the size limitation does not permit this. A would have updated the library too, but I'm a newbie, and I'm clueless about how to go about it.

A couple of final comments:
As others have said, it is best to hard code the addresses instead of using the search routine every time. This is not as difficult as you may think.
Secondly, it is better and more robust to use more than one bus. This way, if something goes wrong you don't lose all of your sensors at once.
Would someone care to post some examples?