Dallas 1-wire (ONEWIRE lib) implementation: drive or float high?

I was just comparing my own old implementation of the Dallas 1-wire protocol with the library one (ONEWIRE v.1.2.0). In the latter, in the write_bit() subroutine, the master drives the bus high by setting the output of the chosen DQ pin high. However, the data sheet of the Dallas DS18b20 does not mention actually driving the bus high, but rather just letting the master DQ pin float and thus the bus is pulled high by the pull-up resistor. The data sheet only mentions driving the bus low, by master or slave, and letting the bus be pulled high by the pull up. See the picture below from the data sheet.

So my question is if there is any benefit of driving the bus high instead just floating the pin (i.e., setting it to input mode)?

Hmm, driving it high without an (inline) resistor could give contention problems, when the slave tries to pull it down again.

Dr_Strangelove, your implementation sounds correct and I agree with MORA that yours sounds safer.
I’ve just started using Photon myself and haven’t connected it to a single-wire chip yet, but I do have prior experience working with products which use the SDQ protocol (virtually identical to 1-wire) like bq2022A. I know that SDQ/1-wire use open-drain connections on both the host and the slave devices (just like I2C does). I assume that the ONEWIRE library may work because it at least should be letting the pin float while it’s listening for data from the slave.

When thinking more about it I am wondering how the ports of the Core/Photon MCUs are implemented? My assumption of a tri-state port with a high-impedance mode was actually based working with the Microchip PICs. The data sheet for the STM ARM M3 MCUs state that the output is either push/pull or open drain but don’t mention how the input mode behaves. However, setting an open-drain port to high simply puts the output transistor in a non-conducting mode but does not provide any direct connection to Vdd. So an output high on the Core/Photon MCUs would be the same as releasing the bus after all and the term driving is a misnomer?

Check out this thread for USART based implementation that uses external circuits but seems to be more analogous to what you are thinking. Disclaimer…I don’t fully understand what you are saying but I remembered this thread as it has some common taxonomy around the Open Drain and such.

1 Like

I’d agree that this implementation is not in line with 1-wire specs, but since this is a user contribution you should maybe file an issue in his GitHub repo.
If it was a hardware backed implementation of 1-wire (as for example the on-board Wire object for I2C) it would definetly use open drain (let pull-up deal with HIGH and active drain LOW) rather than push/pull.

Other libraries do such thing with switching between (OUTPUT/LOW) and (INPUT) to mimik the hardware backed behaviour for bit banging…

@LukeUSMC – Using the USART as a means to avoid those pesky delays is certainly a very good idea. But it’s not really what I was trying to figure out with my post. I am just thinking out loud so I understand it’s difficult to understand what I’m driving at. But to clarify: I want to know, given a 1-wire bus and the open-drain output of of core/photon MCUs, if there is a difference between putting a pin in output HIGH or in input mode?

@ScruffR – Thanks for the suggestion, but I would like to have an answer to my question above before filing any issues since it might not matter which way it is done for the core/photon MCUs.

We can ping @BDub on this to get an official Particle statement, but I’d say you shouldn’t drive a 1-wire bus HIGH for the reason @MORA has given.
Also the protocol states that HIGH level is provided by one pull-up resistor common to all devices and never mentions driving the bus HIGH.

This could even be harmful for the GPIOs in multi-master 1-wire setups, if one drives HIGH while another pulls LOW without current limiting resistors inline (which you don’t want in a 1-wire bus).

Could you point us to the reference where you found the term driving, to correct it if required?

Sure, I can do that. I assume it is Hotaman’s OneWireSpark github repo that is the “official particle” library and in it the OneWire.cpp file is the interesting one. In subroutine write_bit(), on lines 201 and 214, the output pin is set to high and the comment states the that the output pin is driven high. Interestingly, in the subroutine reset(), the pin is set to input mode (and the comment says “allow it to float”) on line 178 when the desired result is actually exactly the same as in write_bit(). That is, the bus should be released and be allowed to be pulled high by the bus-common pull up.

I see!
As said, it’s a member contribution, so not “official” but “contributed for public use” - just to free Particle from any liability :wink:

Not exactly, as you already pointed out before.
While the voltage will be pretty much the same for both ways, the possible current draw when pulling low will differ considerably.
Hence the actual driving high, should not happen (IMHO), but I’ve already opened an issue about this on the repo and hope that @Hotaman will respond here too
https://github.com/Hotaman/OneWireSpark/issues/13

Having looked a little more into the reference manual for the STM32F205 it turns out that its GPIO ports can be configured with either a push-pull or open-drain output. This is selectable as can be seen by the figure below. So I my original statement about open drain was not the whole truth. Either way I think the Core/Photons are always configured as push-pull outputs unless the user goes deep and manipulates the control registers directly. Thus, it is very probable that the 1-wire library (Hotaman’s) does not follow the 1-wire spec and drives the output high.

My guess is that the code has been adapted numerous times for different MCU architectures but that the original Dallas implementation was for a MCU with only open-drain outputs.

Hello everyone. Just as background, I have been using 1-wire devices since the very first devices were released. I did the original ASM code for PIC processors which was ported to the AVR, PSoC, and several others by myself. I did not write the C version in the Particle OneWire lib. I just made it work and I maintain it for all of you. It is clearly a derivative of my original work. Connecting the output pin directly to the 1-wire buss is not exactly per the spec but it IS electrically compliant with the spec. I will explain the specifics here.

The bus is as an open collector based bus with a single pull-up resister. So, the only way to actually be in 100% compliance would be to use a transistor since there are usually no open collector outputs available on most MCUs. There is a work around for totem pole outputs that provides the same electrical profile. The proper implementation using a totem pole output is to set the output register (bus bit) LOW, then toggle the Data Direction Register between input and output rather than the output register. This drives the bus LOW (output), and allows it to float HIGH (input) exactly like an open collector. This is how I implement this bus on a modern MCU and how the OneWire lib is implemented.

As noted in the previous post, the STM32 outputs can be configured to support an open collector (drain), but there is more to consider…

One little problem when using parasitic power, some devices, like DS18S20’s need more power than is available through the pull-up to do internal processing. In this case, Dallas recommended using ‘strong drive’ or some such thing which was to place a transistor in parallel with the pull-up resistor so you can connect the bus to Vcc through the transistor, bypassing the resistor and providing plenty of power, still only using 2 wires total (bus & GND). This solution also addressed the older processors that could only drive 2-3ma. Our modern MCUs can typically drive >20ma per pin and looking at the totem pole above, you can see the top of the pole is exactly what we need!

The two options for power hungry devices:

1> Obvious solution - Hook up the power pin. This is the ONLY option that frees the bus during conversions! This is not an option for iButtons though.

2> Not so obvious - drive the pin HIGH (possible on modern MCUs) giving us 3 states, LOW, Float, HIGH.

I use the latter approach, and typically connect an unused IO line to the 1-wire power bus for complete flexibility.

Bit reads always leave the bus floating since in read mode, the device needs to drive the bus low.

The Write function has the option of leaving the bus driven HIGH or leaving it floating so you can provide power when needed without any extra hardware. This is why I choose this approach, it is electrically compliant with the spec and app notes, yet completely flexible in how you want to run the bus based on your application and devices used.

Make sure you read the specs on the devices your using and get creative using them. For example when using multiple temp sensors, send a broadcast convert command, wait for the conversion then read all devices. This allows the reading of many devices ~ every second instead of just one.

I have been using this same basic code for more that two decades, it is as solid as it gets and the most flexible solution available. The OneWire lib isn’t perfect and there are places where I would like to do some clean up, but, these ARM MCUs are zippy fast and have plenty of resources so there isn’t much of a reason to do it like there is on a 2K PIC running at 4MHz.

Thanks to @ScruffR for bringing this thread to my attention. I hope I addressed your questions, if not, send’em my way. I try to check in every few days or so but I can get busy from time to time. I will respond when I have time.

5 Likes

Ok I read all the comments and I have a bit more to add.

I worked with Particle on deciding whether Particle should take over the OneWire lib as an ‘Official’ lib. I don’t personally care either way.

Considering my experience with 1-Wire devices and the current work load on Particle developers, I retained control of the lib. Particle is helping me out by providing early access to the Electron so the lib is already fully tested on that platform.

I use a lot of 1-wire devices in my projects. I have additional examples in the works but could really use some input from all of you on what devices your using these days besides the standard DS18x20s. The DS2438 Smart Battery Monitor is supported for Temp readings in the 18x20 example now. I am working on a complete example for that part and a current project is using the DS2408 8-bit switch if anyone is interested I could make an example for it as well.

I like constructive criticism, I don’t like speculation and I hate WAGs. If your not sure, ask or study the code to generate questions. I love to help people learn new things when they want to learn and I have a vast knowledge base to share with well over 35 years of experience in hardware, software, networking, and embedded systems. I’m sure I don’t know all the tricks, but I use many of them daily.

Using a 1-wire master will free up some cpu cycles over bit banging but adds additional cost and complexity. I prefer to design my systems in such a way that the wasted cycles are a moot point. The typical uses for 1-wire are fairly low speed and should not cause any problems in a properly designed system. That’s just the way I roll and all projects are different so your mileage may vary.

2 Likes

@Hotaman, thanks for the thorough explanation. I now understand the your reasoning, and the code, better. However, I think I had a valid reason for raising my concern/question due to the obvious discrepancy between the DS18b20 read/write illustration (valid for both external and parasitic power) and the code. For the DS18b20 driving the DQ pin high is only needed during temp conversions and copies to the EEPROM, and not during writes. At least that’s how I read the DS18b20 data sheet. So I hope you understand my confusion.

Anyways, I think we have exhausted this topic. Thanks again.

PS. For Europeans, WAGs = Wifes And Girlfriends, and not in a positive sense. Use cautiously :wink:

@Dr_Strangelove, I guess in this case the acronym rather stands for “Wild Ass Guess” - but maybe only since I am European :wink:

But we could ask @Hotaman on this one again, to avoid making the same mistake to guess wrong twice :sunglasses:

@Hotaman I wanted to share that your code also made it possible for the Bluz to be tested and verified as working with the DS18B20 temp sensors. Thanks for your contributions to the community!

2 Likes

LOL! Thanks for the chuckles guys and gals (are there any gals here?) None of my comments were direct to anyone here, I was just ticked at a co-worker and I guess I let off a little steam, sorry if anyone took offense at my verbiage, none was intended, I was just sharing a bit :slight_smile:

In this case, WAG = Wild Ass Guess so @ScruffR wins a free pat on the back! (and a beer if we ever meet in person)
Particle should have a dev conference, so many awesome people here I’d like to meet!

@Dr_Strangelove, Yes, normally the data line is left floating, then on the last write to start a conversion/write you set the flag high so the buss is left driven HIGH while you do other things during the conversion/write . The point is that you are in control of how it behaves. So hook up the power line and leave it floating all the time if you like :smile: Or you can burn another IO pin to control an external tranny (is it still ok to use that word?) and go the way of the original App Note for iButtons.

While sending a byte from the master to the slave (crap another one of those words) the master is in control of the buss so it doesn’t matter how the pin gets HIGH while sending the byte, the only thing that matters is what state it is left in after the byte is sent. Note that driving the pin HIGH while sending can improve the signaling depending on how many devices, run length, pull-up value, etc. Of course it is only a one way solution so might be a moot point depending on the situation.

@LukeUSMC Glad it helped! If I read your handle correctly, THANK YOU! for your service!

I think I’ll get back to playing with my pile of APA102 LEDs now, they are so much fun! I’m helping a bit on the FastLED lib. Need to get hardware SPI support in there, these little gems are crazy fast!

Have a GREAT weekend!

2 Likes

Yes sir you did and it was absolutely my pleasure. Thank you just the same.

+1 on a Particle Dev conference…

Not to be confused with SWAG… the Scientific Wild Ass Guess :wink:

Thanks for the explanation.

Maybe the confusion is based on when the bus is released and when its being used.

The master can use high to send signals, and maxim app notes explains this multiple places, since its needed for parasitic powering, alternatively triggering a transistor to provide more current.

But when the transaction is over eventually the master needs to let the pin float, so that the slaves can pull it down to communicate.
When using all 3 wires, the issue is solved by giving the sensors a dedicated power line so theres no need to strongly drive the bus to provide power.