Is there any way, either with arduino "language" functions or, preferably, with AVR PIN and PORT register setting in which one can toggle a pin between being a HIGH output and a floating pin? I've got a situation where I need a bunch of separate chips to all share an output wire and it should act in an "OR" kind of fashion, all pins sit on it, if any are HIGH the line goes HIGH, else all are floating a resistor pulls the line low. Obviously I can't toggle between HIGH and LOW as depending on what different chips sharing the line did I could end up with a HIGH and LOW pin on the same conductor and a damaginly large current flowing between them and wrecking both. I've done this kind of thing before with some Raspberry Pi stuff where the BCM2835 chip in it lets you turn on and off pullups on each output, but I don't know if the ATMEGA328P has pins which can have pullups set and unset and floating states created. Thanks
Using pinMode() and redefining the pin as an input makes the pin Hi-z.
pinMode() writes to the processors data direction register.
Turning on pull-ups is done either with pinMode() or writing to the processors PORTx register only after the DDRx bit has been set.
It is possible to "pre-set" the output value, that makes it possible to toggle between high-impedance and a strong output level.
The DHT, OneWire, and software I2C libraries all use that. But they use "open-drain", which was called "open-collector" in the past. They toggle between high-impedance and a strong LOW.
When a Arduino is turned on, the default is already pre-set to LOW. So as soon as you call
pinMode( pin, OUTPUT); then the pin turns into a strong LOW. All you have to do, is to pre-set it to HIGH.
Writing a HIGH level as pre-set value to a input pin turns on the internal pullup resistors. Only after the
pinMode( pin, HIGH); the pin turns into strong high output.
So the output pin goes: strong low --> weak high --> strong high. That is never a problem.
Set a pin high-impedance:
pinMode( pin, INPUT);
Set a pin strong HIGH:
digitalWrite( pin, HIGH); // pre-set the output to high, also enables the internal pullup pinMode( pin, OUTPUT); // output (set to pre-set value)
You can toggle pinMode() between INPUT and INPUT_PULLUP. That wouldn't give you a strong high, just a 30K or so pullup resistor. But if the external pulldown is 1Meg, that might still work.