PaulStoffregen / OneWire

Library for Dallas/Maxim 1-Wire Chips
http://www.pjrc.com/teensy/td_libs_OneWire.html
579 stars 382 forks source link

OneWire MultiBus #46

Open megavolts opened 6 years ago

megavolts commented 6 years ago

Hi All,

For a recurring project, I am using several strings of DS18B20 temperature sensors, and I would like to have each string on a separate onewire bus and storing them in a common array that I can loop over. I know this has been a recurring topic in the Arduino community. The best solution was given by @prashantdev a couple of years ago with a fork of the arduino-OneWire library of Norbert Truchsess. I stumble on that topic when it was a little bit necrobump by @2mik a couple of month ago (https://github.com/milesburton/Arduino-Temperature-Control-Library/issues/47).

I was wondering if the modification of Prashant could be implemented into the official OneWire library. It is describe as an extra no arguments constructor to simplify multiple OneWire buse use, allowing for easier construction of arrays of OneWire buses, in the limited environment provided by Arduino (https://github.com/prashantdev/arduino-OneWire).

Thanks for considering it.

Marc

orgua commented 6 years ago

and what is the advantage of more than one bus? you can easily manage to get all the data from at least 30 sensors over one bus.

dvv commented 6 years ago

E.g. 1-wire does not like star bus topology.

orgua commented 6 years ago

why shouldn't it work? Stub-length is only a limitation with high-speed busses. we are far far away from that! even with overdrive you can have about 600 km long stubs (each) until you have a real problem with signal quality. so as a rule of thumb, just keep it shorter than 1/10, so 60km and you are golden. Calculation:

dvv commented 6 years ago

The point is in degraded reliability due to signal reflections. In my case of 5-hand star topology of 20 meters branches it dropped beyond device recognition.

27 окт. 2017 г. 17:38 пользователь "inʒo" notifications@github.com написал:

why shouldn't it work? Stub-length is only a limitation with high-speed busses. we are far far away from that! even with overdrive you can have about 600 km long stubs (each) until you have a real problem with signal quality. so as a rule of thumb, just keep it shorter than 1/10, so 60km and you are golden. Calculation:

— You are receiving this because you commented.

Reply to this email directly, view it on GitHub https://github.com/PaulStoffregen/OneWire/issues/46#issuecomment-339990310, or mute the thread https://github.com/notifications/unsubscribe-auth/AAM5hzMeWBQK3IuxR2QGcSvZ-2J4IxZyks5swervgaJpZM4QG7rY .

Humancell commented 6 years ago

Per the question:

"and what is the advantage of more than one bus? you can easily manage to get all the data from at least 30 sensors over one bus."

We find it much easier from a maintenance aspect with our sensors to have one probe per pin, since we can then easily direct the user to the correct connector and have them change out a bad probe. For some time we used the bus, and still use it for some applications, but when we have - for example - four probes in close proximity we put one on each pin.

orgua commented 6 years ago

ok, but instantiating an array of these onewire-masters isn't a problem. the lib can do that right now. you can choose the pins by your liking. so i would close the issue.

@dvv: i disproved your point in the comment before. i was talking exactly of these reflections. the effect is not visible in onewire, because it is too slow, you need stubs much longer than 60km. we have a house with at least 1000m of cable, each room, each floor, even into the garden. and it works flawlessly with 50 sensors. And star config is even helping signal quality in this case. your problem lies somewhere else.

dvv commented 6 years ago

@orgua I'm really glad your setup goes such well, mine not (I believe there's too much EMI around). To cope, I preferred to dispense some other pins to drive each branch in separate, and this solved the issues. So my point was just I would like some sugar to support multiple branches ) Thank you

orgua commented 6 years ago

@dvv i'm pretty certain it is not emi either. You're mixing up some things. onewire is driven all the time. Yes, EMI is possible, but you have to live next to a tesla-coil. Floating input pins are another story.... Have you checked with a scope?

and what is the problem with multiple branches? just write something like

OneWire ow_a(10), ow_b(11), ow_c(12), ow_d(13);

you can even store the pointers to them in an array:

OneWire* owArray[4] = {&ow_a, &ow_b, &ow_c, &ow_d};

and use it later by accessing it in a loop like

for (uint8_t index = 0; index < 4; ++index) owArray[index]->reset();

orgua commented 6 years ago

and if you are lazy you should even be able to write something like this:

OneWire ow[2] = {OneWire(10), OneWire(11) };

// and later:
ow[0].search(addr);
dvv commented 6 years ago

I doubt one can drive a 60km line with an avr pin. It's not about the signal speed but about the line capacity. I use separate power line and pull the bus up with even 2.2k and it's still failing. No scope.

lcapossio commented 6 years ago

I've done this exact thing in my project (https://github.com/lcapossio/fresca). I don't think updating the library is gonna help. In my project I had an even bigger issue, I wanted to have an array of pointers to sensors, which could be of two types, DS18B20 and DHT22 (and even more in the future). I ended up doing a class that instantiates the array dynamically and resolves the pointer according to what type of sensor is currently at that index ('fresca_sensor class').

prashantdev commented 6 years ago

@megavolts Thanks for considering my solution as good. As I mentioned somewhere in my own notes, the strict programmer in me refuses to accept a kludgy algorithm implementation. Loops are soo much nicer to handle an array of anything, than writing repeated code.

Regarding the all-sensors-on-one-wire vs multi-pin debate, I guess it is simply a matter of personal preference or project requirement. I too prefer to have a plug and play solution, where an off the shelf sensor can replace an older one without reprogramming the microcontroller with it's id. I'm willing to see the other side - where people prefer to have one wire. The use-case certainly has it's uses, and an attraction of less wires going around. In the end, individual viewpoints matter little. What matters is what fits your case.

winginitau commented 6 years ago

I'm having similar issues with the star topology. At most I can run 3x sensors from one bus (and yes with pull ups down to 2.2k). To save memory, I instantiate OneWire as a local variable inside a static function each time the sensors need to be read. Though I think that is causing heap fragmentation over time causing the arduino to lock up after a few hours. 2x questions for you guys:

  1. Is your 10k/2.2k resistor close to the sensor or at the arduino end? Mine are at the arduino end which could be causing the star topology problems.
  2. Is anyone else instantiating OneWire each time it is used? I note there is no destructor method in the class.
orgua commented 6 years ago

@winginitau with three 2.2k resistors you burn almost 5mA when pulling the line down. One 2.2k res on the arduino-side is enough. Onewire is very slow, star config with several hundred meters would be fine. Are your sensors bus powered?

you can't put onewire into a local variable, it is just a pointer or reference. Depending on your instantiation you have a memory leak. And don't worry, by specifying no destructor c++ will use a default one.

winginitau commented 6 years ago

@orgua thanks for your response. I've got 3x buses. Sensors by bus: 1: 2x: ~6m each; 2: 3x: 3m,3m,2m; 3: 1x: 20m; Not parasite powered. arduino, rpi, relays, radio modem, and sensors all powered directly from a regulated 5v (5.2v) supply from a 24v system. I ended up making my own breakout board with everything securely plugged and the ability to plug different resistors across the 3x signals to +ve (pulling them high which I think is right) - because I was having so much trouble getting them stable. For each bus I started with 10k resistors and worked down until I get reasonable reliability. Cant recall now the exact values but I think 2x are at 2.2k, one at 4.7k. The reliability changes drastically with thermal conditions. At night (now) the cabling and system is down to about 12 degrees C. During day (up to 30 C), they become more unreliable - sometimes not discovered on bus, sometime returning 80C on the 20m run (should be ~19), sometimes returning -127 (0xFF). Yes they do take time to read - no problem, though it varies from instantaneous up to about 1sec, again depending on thermal conditions.

In my config, I enumerate the sensors as "if_num". Then in a static function "GetTemperature(uint8_t if_num) determine the bus_pin via #defines and % modulo math and call them as:

    OneWire one_wire(bus_pin); 
    DallasTemperature temp_sensors(&one_wire);     
    temp_sensors.begin();

    DeviceAddress d;
    memcpy_P(d, devices[if_num], sizeof(DeviceAddress));

    temp_sensors.requestTemperaturesByAddress(d);
    temp_c = temp_sensors.getTempC(d);  

and return it.

Noted - yes Onewire is a pointer (to an instance). Noted - default destructor - thanks. C++ still coming slowly!

What do you think?

(full project here: https://github.com/winginitau/FodderFactory )