Arduino Mini Pro: Use I2C pin as open drain digital pin

I am working on a project that interfaces with a device over SPI. The Arduino will act as the spi slave device. The miso output to the other device is expected to be an open drain.

Since the i2c pins on the Arduino Mini Pro are open drains, is it possible to use those pins as regular digital out pins?

If not, what is the simplest circuit needed to create an open drain output for the Arduino?

  1. Without external circuit you cannot make true open drain output from any pin of Arduino - there are protection diodes from any pin to Vcc which should not be present on open drain output (reset pin may be the only exception but applying high voltage on this pin may put the chip into programming mode IIRC).
  2. If the protection diode is not a problem you can simulate the open drain behavior on any pin by switching between pinMode(INPUT) and pinMode(OUTPUT). Or changing DDRnx while PORTnx is 0.
  3. If the protection diode is problem or you want to use hardware SPI you may use transistor to make open drain (collector) output. If you use one transistor the output will be inverted - you need to invert data before you send them.

Open drain? Don't conflate SPI with I2C, they're two different standards.

The atmega328 supports hardware based SPI master and slave with four pre-assigned pins. SPI does not require open drain, only a means of releasing control of MISO by the slave when it is no longer being addressed. Tri-stating the output works just fine. What I don't know is if exsisting SPI libraries for Arduino support this control, I honestly doubt it as there is next to nothing published when using the Arduino as a slave. About the only good reference on the web is:

And scroll down to where you see "How to make an SPI slave".

The protection diodes are not an issue, they only conduct when voltage applied to the pin exceeds VDD or VSS by 200-300mv.

jonesaaronj:
I am working on a project that interfaces with a device over SPI. The Arduino will act as the spi slave device.
SPI requires MISO to be tri-stated when not being driven, its not open drain

No, SPI requires inactive slaves to tri-state MISO and active slaves to drive it push-pull. The Arduino
hardware SPI driver already knows how to do slave mode, you don't have to worry about it. Read
the section of the datasheet on the SPI hardware for full details of how to setup slave mode.

Since the i2c pins on the Arduino Mini Pro are open drains, is it possible to use those pins as regular digital out pins?

No, they are perfectly regular pins.

If not, what is the simplest circuit needed to create an open drain output for the Arduino?

All Arduino pins can be operated pseudo-open-drain, just go digitalWrite(pin, LOW) and toggle
with pinMode (pin, INPUT) and pinMode (pin, OUTPUT).

This isn't true open-drain since the pin may not be pulled higher than Vcc. The I2C library code
knows how to do pseudo-open-drain for you.

avr_fred:
The protection diodes are not an issue, they only conduct when voltage applied to the pin exceeds VDD or VSS by 200-300mv.

Well we don't know what OP wants. Maybe he is just confused. But maybe he needs to interface something with SPI-like protocol where open drain is used for voltage level shifting. In this case protection diodes ARE big issue.

avr_fred:
Open drain? Don't conflate SPI with I2C, they're two different standards.

I'm not mixing SPI and I2C. The device I am interfacing with is using SPI and is expecting the MISO to be an open drain. I brought up I2C because the ATmega328 has a built in I2C interface which uses open collectors.

MarkT:
No, they are perfectly regular pins.

They are most certainly not perfectly regular pins. The ATmega328 has a built in I2C interface and these pins are open collectors/open drain.
https://playground.arduino.cc/Main/WireLibraryDetailedReference#inside

This reference goes into detail about how the i2c part of the chip is a separate processing unit. The more I read about it the less likely it seams to me that I will be able to access these pins directly.

Smajdalf:
Well we don't know what OP wants. Maybe he is just confused. But maybe he needs to interface something with SPI-like protocol where open drain is used for voltage level shifting. In this case protection diodes ARE big issue.

I am most certainly confused as a regular state of being :slight_smile: But yes, I am interfacing with a device that is SPI-like. The protocol is SPI with an additional ACK line. The MISO and ack lines are not push-pull, it is expecting both to be an open collector on the slave device (arduino)

avr_fred:
The atmega328 supports hardware based SPI master and slave with four pre-assigned pins. SPI does not require open drain, only a means of releasing control of MISO by the slave when it is no longer being addressed. Tri-stating the output works just fine. What I don't know is if exsisting SPI libraries for Arduino support this control, I honestly doubt it as there is next to nothing published when using the Arduino as a slave. About the only good reference on the web is:

Gammon Forum : Electronics : Microprocessors : SPI - Serial Peripheral Interface - for Arduino

And scroll down to where you see "How to make an SPI slave".

I am also interfacing my Arduino Pro Mini with a usb host shield, which uses the standard SPI pins. Is it possible to create multiple instances of the SPI object with different pin assignments?

MarkT:
All Arduino pins can be operated pseudo-open-drain, just go digitalWrite(pin, LOW) and toggle
with pinMode (pin, INPUT) and pinMode (pin, OUTPUT).

I have read on other forums this is not good practice. does switching pin mode happen fast enough for a high speed use case like this? And how much current can the device sink before protection circuit is overwhelmed.

However, none of the forums I've seen this discussed in have had a proper solution. is there just a small circuit I can add to the output pin to convert it to an open drain. like the most minimal circuit?

jonesaaronj:
They are most certainly not perfectly regular pins.

YES THEY ARE! They are fully functional normal pins, with the added functionality of being connected to the hardware I2C. They're pins A4 and A5 (the same pins as the analog inputs, which can also be used as outputs like any other digital pin) - they are available separately on the Arduino Uno to allow improved compatibility with boards where the I2C pins are not also A4/A5 (ex, Leo/Mega) - whichever pins double as I2C pins are connected to the pins marked SCL/SDA in the corner of the board. The I2C pins have no special functionality w/regards to supporting open drain output.

DrAzzy:
YES THEY ARE! They are fully functional normal pins, with the added functionality of being connected to the hardware I2C. They're pins A4 and A5 (the same pins as the analog inputs, which can also be used as outputs like any other digital pin) - they are available separately on the Arduino Uno to allow improved compatibility with boards where the I2C pins are not also A4/A5 (ex, Leo/Mega) - whichever pins double as I2C pins are connected to the pins marked SCL/SDA in the corner of the board. The I2C pins have no special functionality w/regards to supporting open drain output.

Yep, I was wrong. Sorry. Still just trying to understand how to create an open drain. Is switching between input and output sufficient? Because, other places don't seem to indicate it's quite that simple.

Switching between INPUT and OUTPUT is open drain except for the protection diodes. As long as voltage applied to the pin is between GND and Vcc it is OK. If the voltage may be out of this range it is problem. You may use external transistor for this. For example small signal N channel MOSFET, gate to the pin, drain to bus and source to GND. But logic will be reversed - when pin is HIGH the MOSFET will open and pull the bus LOW. You need to compensate in SW.

To be fair HW I2C is not "just regular pin driven via another means". When TWI (Two Wire Interface, Atmel's name for I2C) is active the pins have slew rate limiting and input spike filtering - features not accessible when the pin is used as GPIO.