Go Down

Topic: 1-Wire, DS18B20... How do I search the bus? (Read 25420 times) previous topic - next topic

omnitronic

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!

crunch

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.

Waffle

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.

crunch

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.  
Code: [Select]

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  

Code: [Select]
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?

Waffle

#19
Jun 27, 2009, 08:58 am Last Edit: Jun 27, 2009, 09:00 am by Waffle Reason: 1
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.

crunch

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     ?    

Waffle

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.

omnitronic

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: http://www.maxim-ic.com/appnotes.cfm/an_pk/187.  
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.

pwillard

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

omnitronic

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.

crunch

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"



Waffle

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.

robin

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:
Code: [Select]
//
// 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:

Code: [Select]
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?

omnitronic

Couple of thoughts - Crunch, are you sure that you are rebuilding the OneWire object every time, and not just reusing the previous object file? Make sure you delete the OneWire.o file before clicking verify.

Also, I tried using a 47K resistor on mine, it wouldn't work at all like that.  I've found that 1K is about right.

And finally, I found that periodic interrupts play havoc with the search function. If you are using a periodic ISR, try executing a noInterrupts() call just before calling the search to turn off interrupts, and then execute an interrupts() call afterwards to turn them back on.

crunch

#29
Jun 28, 2009, 11:44 pm Last Edit: Jun 29, 2009, 01:16 am by crunch Reason: 1
After reading the advice above and seeing that OTHER people have been able to make this concept work,  I figured it HAD to be something I was doing wrong rather than a coding error in the library.   (I couldnt see how I would be the first person to find the error)

I got frustrated with this whole problem  this morning and did the following:

1)  Re-Downloaded the latest Arduino engine
2)  Re-Downloaded the OneWire library
3)  Went to the original source example for the onewire library and used that
4)  Ripped out all the hook up wires on the proto-board and replaced them
5)  Replaced the resister.   Double checked it to be a 4.7k resister.

NOW I have 8 DS18S20's on the bus and they are reading properly.    So I dont know which of the above made it work but it just does now.

I am going to work out how to get more room on my prototyping board and get more sensors onto the bus.  Hopefully it reads all 15 of them.     Then I can start playing with the actual production sensors.
I appreciate the time you guys have done on this!.    

Go Up