How to emulate an open-collector output for newer processors ?

Hi,
I want to update the SoftwareWire library: SoftwareWire/SoftwareWire.cpp at master · Testato/SoftwareWire · GitHub
to make it work with the Arduino Due, Zero, 101, and Adafruit M0 and other processors.

The current version uses writing to registers, and will I will add a AVR check over that.
The other processors will use the normal Arduino functions digitalWrite() and pinMode().

For the AVR chips, to change a pin from INPUT (high impedance) to OUTPUT LOW, first the output register is set for a low value, and after that the direction register is set for output. That is the typical sequence for ATmega chips.

How can I do that for other processors ? To make a good transistion from high impedance to OUTPUT LOW, without making the I2C bus HIGH, not even for a nanosecond.

Koepel:
Hi,
I want to update the SoftwareWire library: SoftwareWire/SoftwareWire.cpp at master · Testato/SoftwareWire · GitHub
to make it work with the Arduino Due, Zero, 101, and Adafruit M0 and other processors.

The current version uses writing to registers, and will I will add a AVR check over that.
The other processors will use the normal Arduino functions digitalWrite() and pinMode().

For the AVR chips, to change a pin from INPUT (high impedance) to OUTPUT LOW, first the output register is set for a low value, and after that the direction register is set for output. That is the typical sequence for ATmega chips.

How can I do that for other processors ? To make a good transistion from high impedance to OUTPUT LOW, without making the I2C bus HIGH, not even for a nanosecond.

To simulate an open collector / open drain output, connect a small diode (like a 1N4148) between the AVR output pin and what it's driving.

The stripe or band on the diode points towards the AVR, the other end goes to the device you're driving.

With the diode there, the AVR can pull the node DOWN, but it can't push it UP.

Lastly note that this will give you about a 0.7 volt drop (that is, logic zero will not be close to 0 volts, but more like 0.7 volts).

This SHOULDN'T cause any problems... give it a try.

(edit to add): Note that you will need a pullup resistor on the node (as you would with any OC/OD output).

Krupski:
To simulate an open collector / open drain output, connect a small diode (like a 1N4148) between the AVR output pin and what it's driving.

I think you kind of missed the point of what the OP is doing.

Isn't it possible to put those pins into an open drain mode? (open collector implies BJTs, which nobody uses anymore, the analogous mode with fets is open drain). Check the datasheet for the processor.

DrAzzy:
Isn't it possible to put those pins into an open drain mode? (open collector implies BJTs, which nobody uses anymore, the analogous mode with fets is open drain). Check the datasheet for the processor.

What do you mean "those pins"? This is a software I2C. Did you mean, "the pins on those processors", I guess?

It is a software I2C, therefor the Arduino pins (for software SDA and SCL) must change between input and output+low. They may never become output+high.

I don't want to use a diode, because then it is no longer a drop-in replacement for the Wire library.

Call it open-drain if you want to :wink:
I still say that I2C / 1-Wire / DHT is a open-collector bus, even if that is an old term. The AVR chips can change very nicely change between input and output+low.

My question is how to do that for the newer boards.
I prefer normal Arduino functions, but maybe that is not possible.

The OneWire uses defines (which I don't fully understand) for every processor : OneWire/OneWire.h at master · PaulStoffregen/OneWire · GitHub
Is this DHT library compatible with the Due and other boards ? I don't think so. GitHub - adafruit/DHT-sensor-library: Arduino library for DHT11, DHT22, etc Temperature & Humidity Sensors

Is there a common way to do this, or is everyone using their own low level register tweaks which are different for every type of processor ?

I mean the pins on the microcontroller that are being used for software I2C. What the heck else would I mean?

Most of the fancier processors let you set pins to be open drain mode. I don't know if that is exposed in normal Arduino functions though...

DrAzzy:
I mean the pins on the microcontroller that are being used for software I2C. What the heck else would I mean?

Possibly the TWI pins. They have special functionality.

aarg:
I think you kind of missed the point of what the OP is doing.

I based my reply on the thread title:

How to emulate an open-collector output for newer processors ?

DrAzzy:
Isn't it possible to put those pins into an open drain mode? (open collector implies BJTs, which nobody uses anymore, the analogous mode with fets is open drain). Check the datasheet for the processor.

I looked at the data sheet for the 328P and 2560... both of them do not seem to have any way to disable the top of the "totem pole" driver.

Krupski:
I looked at the data sheet for the 328P and 2560... both of them do not seem to have any way to disable the top of the "totem pole" driver.

It is disabled when it is in the logic low condition. So if you leave it in the low state, you can emulate an open drain by alternately selecting input and output mode.

However, not all "open drain" outputs can tolerate voltages greater than VCC. This is one of them.

I don't want a complete open-drain or open-collector bus. It is just a simple two state logic: either input or output+low.
That means it will not be compatible with other voltages, which is normal, since the Arduino pins in hardware I2C (TWI) mode are not compatible with other voltages either.

The Software I2C is already working. It is possible to create for example a number of I2C busses on a Arduino Uno. Now I want to make it work for newer processors.

Well, I'm looking at Figure 31-3, Section 6.1 of the AT91SAM3X8E doc for the Due. It looks good there.

Page 621 ? Yes, okay, but that is also a Atmel chip.
Could I do this ?

// make the pin active, pull it low
digitalWire( pin, LOW);
pinMode( pin, OUTPUT);

// release the pin, make it high impedance
pinMode( pin, INPUT);

If that is possible, what about the others, for example the Arduino 101, and other boards.