emulate open collector

With the need to drive some electronics with open collector / open drain outputs from Arduino, I just realized that it may just be possible to emulate open collectors with a bit of smart programming. Maybe I'm not the first to come up with this idead, maybe someone has tried it before and has good or bad experience with this method.

The idea is to use the ATmega's internal pull up resistor when in HIGH state as follows: - To emulate an open collecter / open drain output LOW: => pinMode( n , OUTPUT ); digitalWrite( n , LOW );

  • To emulate an open collector / open drain output HIGH: => pinMode( n , INPUT ); digitalWrite( n , HIGH );

If this works, it'd save an external resistor, transistor and the programmed logic does not need to be inverted.

Thoughts anyone? Anyone tried it before? Caveats? ...

That's how the I2C bus works, but you don't need to set the output HIGH if using external pull-up resistors:

void setup ()
  digitalWrite (pin, LOW) ;

void loop ()
  pinMode (pin, OUTPUT) ; // drive pin low
  pinMode (pin, INPUT) ; // hi-Z state

That's a smart option too!

But I was hoping to reduce the number of external components as much as possible because I haven't got a PCB, ... The only thing I'm worried about with my option is if the slopes will stay well defined during the time that the pin is switched from output to input and ........ enabling the pull up. That'd be solved with yours.


Direct port manipulation would mean changing pin direction and output within a fraction of a us of each other, rather than the several us that pinMode() and digitalWrite() take to execute.

Also the builtin pull-ups are "between 20k and 50k" which is rather weak for some uses (long I2C or OneWire buses for instance). I2C recommends 4k7.

The weak resistance is a good point, didn't realize the internal pull up's are that large.

My proof of concept runs on an Arduino Mega, but I eventually need it for an ATtiny, so I'm fiddling with direct registers anyway :)

Today I pulled out my oscilloscope and checked the slopes with the internal pull-up trick. It is a drama, the waveform doesn't even remotely look like it is digital! This was easily solved with an external 10k pull-up as suggested!

Thanks MarkT

This might create misunderstandings about why OPEN COLLECTOR is popular.

One of the primary reasons that open collector outputs exist at all is for interfacing with NON-TTL level devices such as driving analog circuits or higher power transistors. Example: An open collector output can be attached to a circuit using 24V or so, you can have ttl chip have a 24v output because the last transistor has its collector connected externally from the rest of chip. The collector is not referencing 5V logic inside the chip. Any kind of internal pullup changes that.

Your solution only seems to work in cases where you are using open collector so you can have a pin go into a HI-Z state, such as used with open collector "OR" circuits.

The nice property of open-collector / open-drain outputs is that you can connect several outputs together without risking anything burning out - even if several outputs are active at the same time. A good example is the OneWire bus, which is a very clever design...