Expanding the number of digital outputs with the ExtraOutputs library

Hi everyone, I've written a small library to interface the very cheap 74HC595 IC, for expanding the digital outputs of the Arduino, and I think it would be usefull to explain how you can use it.

you can get the library here: http://www.pauloricca.com/index.php?a=blog&idpost=18

Basically the principle is the same as in here: http://www.arduino.cc/en/Tutorial/ShiftOut you can use the same hardware layout described in this tutorial, but as you may notice down below, the code isn't that simple to follow and to replicate.

Using the ExtraOutputs library, all you need to do is to create an instance of the ExtraOutputs class, tell it to which pins the IC's are connected, and how many IC's you have connected to each other: ExtraOutputs extraOutputs(latchPin, clockPin, dataPin, numberOfChips);

Then, when you need to change the state of a pin, just use the digitalWrite function, as if you were dealing with Arduino pins: extraOutputs.digitalWrite(pinNumber, HIGH/LOW);

pin numbers go from 0 to 7 on the first IC, 8 to 15 on the second and so on..

Although it's not compulsory, If you are writing to the IC's very often you might want to add a 0.1uf capacitor from pin 12 to Ground

That's it! :) hope you find it usefull..

Cheers Paulo

I'm pretty sure such a library has already been written; in fact, I think more than once. I'm not belittling your accomplishment, but since this part seems to be a commonly used part, plus the fact that there are more than one shift-register IC out there - I think the community needs to standardized and consolidate the various libraries into a single version (much like the LCD and Servo libraries). Ideally, the library would just have a few standard methods, plus a setup function (where you define which IC you are using, plus what pins it uses). Just my opinion, though...


Hi cr0sh, Thanks for your input, I may not have found all the libraries you refer but the ones I've found didn't really simplify that much the task of extending the arduino's output pins, while maintaining the simplicity that we all love about the arduino.. (please send me a link to a simple one, I really haven't found one) what I've chose to do was to pick one IC that most people seem to be using, mainly for it's price I guess, and make it as simple to use as the standard libraries. I do agree with you that it would be nice to have it standardized for using it with other shift registers, I'll try to look into other libraries to see if we could merge some code Thanks! Paulo

I've looked more carefully and I've found a library fairly close to mine, http://nootropicdesign.com/ez-expander/#library Apparently, both libraries will work for any shift register, not only the 595, but I don't have any other in here to test. At first look, the main difference is that ExtraOutputs can be used with any number of IC's, not just 2, because the ez-expander library is designed to work with the shield that has only 2 595's.

Apart from that, both classes and methods are actually very similar, I haven't seen this one because I don't think the library is linked on the arduino site, only the shield.

Although it’s not compulsory, If you are writing to the IC’s very often you might want to add a 0.1uf capacitor from pin 12 to Ground

Don’t do this!

This will only capacitively load the latch pin (pin 12) and the arduino pin connected to it. Amazingly noone have removed that error from the shiftout tutorial yet (http://www.arduino.cc/en/Tutorial/ShiftOut). I guess this is where you got it from. Btw I’m not trying to belittle your effort either, just offering some advice.

Though 0.1 uF is not much, it will for a tiny split second load the pins above spec. In practice there are some resistance involved (from the arduino output pin, mostly…), and hence introducing a time lag. Unless this is what you want (and add some more resistors in the path - though not really good practice on non-schmitt-trigger digital inputs), do not just hang a capacitor on a signal line.

Instead, hang the 0.1 uF across the power near the chip, between VCC and GND (pin 16 and 8 on the '595). Might not be necessary on every chip, maybe you can get away with every other or so. Depends on how much noise there is on the power and how much noise the shiftout registers introduce - which is what the 0.1 uF will help suppress when connected across the power, near the chip. This is called decoupling the power. Grumpy Mike on this forum have written a nice tutorial on that: De-coupling

How about expanding it to make it In & Out vs just out? Then it'd be great for a higher current capabilty universal shift-in and shift-out part like the 74AC299PC.

Thanks Raron! The layout I used came from that tutorial, I didn't know I was loading the arduino too much, nice tip, I will definitely try your solution out. I was using this to drive a 8x8 matrix and I really needed the capacitor.. without it, the image came out wrong, maybe because I was refreshing it too quickly, the 0.1uf solved it.

That's a nice idea CrossRoads, I'll try to get my hands on one of those, it would surely be quite useful to have both input and output!

Newark.com has them for 56 cents, I bought a tube of 20 to use on future projects, and to replace 74F374s that I have wired up as shift registers - the F374s drive LEDs and they flash as the bits clock thru to the final state, but they are good for 24mA as well so nice & bright.

CrossRoads: Newark.com has them for 56 cents, I bought a tube of 20 to use on future projects, and to replace 74F374s that I have wired up as shift registers - the F374s drive LEDs and they flash as the bits clock thru to the final state, but they are good for 24mA as well so nice & bright.

Cool, I didn't know about these IC's Great tips everyone :) thanks a lot!

they flash as the bits clock thru to the final state

That's usually an issue I would think although it looks nice :) Also with 374 you would have to wire each Q to the next D wouldn't you?

There are a 1000 SIPO registers out there, look at the TLC5916 and TLC5927 for direct LED driving.

The point is that they (almost) all work the same so that shouldn't concern you as the writer of a library I don't think, except if you are providing tutes with diagrams.

I gather you define the number of chips then for example set OP 56 high. That sounds nice and simple.

One of my pet gripes with the normal digitalWrite() is that you have to call it a dozen times to set a lot of pins, this would be the same but even worse because of course you may have to do a 100 odd shifts for each call.

I would like to see an extension that writes a whole byte to one of the chips, eg

digitalWriteByte(chip_num, val);

and maybe one that writes to an offset and is not tied to the chip boundaries

digitalWriteByteOffset(offset, val);

Both these would be trivial to write and add some value I think.


Yup, I wrapped the outputs back around to the inputs, have posted the schematics here previously. I had a bunch of the F374s on hand and needed a quick shift function with LED drive capability, all wire wrapped up so it was quick to do. I've got the 74AC299s now, will use those next.

Actually had a couple of 74HC595s that drive transistors for 12V strings of LEDs, worked those into a couple of designs too, had to create another control line for the output register clock. I am pretty flexible about finding solutions.

Hey Rob, I see your point, I may add that to the library.. What I've done to avoid the hundreds of shifts was to define a "manual mode".. the ez-expander guy did something similar too. this way, you set the values and when you're ready to go, you signal the library to shift them out.

OK, that's almost the same thing, at least at the sharp end, still needs a lot of code lines though. That method is better if there are several non-contiguous pins. A byte method is neater for 8 consecutive bits.


Yep, I see what you mean, I think I'll add that too. Thanks!

nice work, but can open all output in same time ? thank you

Hey ejasoft, thanks :) I'm not sure what you mean by open the outputs but with this library you can set all outputs to HIGH or LOW using the digitalWriteAll(HIGH|LOW) and you can use the manualMode() to set the values on a buffer with the digitalWrite() and then output the values all at once with the output() method