Expanding digital IO ports on a microcontroller – Part 1

First of all: why would you need to do this? Why not simply choose a more suitable microcontroller – one with a greater IO count?

Well, this approach is “reserved” for those “rare” circumstances when the microcontroller has already been chosen for you, but the IO count is simply not enough.

What is the purpose of me doing it? I bought (some time ago) a robot chassis for an Arduino based rover so that I could quickly assemble it and experiment with different control algorithms for a fully automated rover. The package came with all sorts of different parts one could integrate in their rover. The problem was, you could not integrate them all at once and even if you managed to “somehow” do it, you would end up exhausting all of your Arduino Uno pins (read: it doesn’t really need to be an Arduino!).

This page (Digital I/O Expansion) gives an excellent overview on the different ways one might solve this. It’s worth reading it. Short and simple – yet very informative!

The 3 most used approaches are, expansion through:

  1. SPI
  2. I2C, and/or
  3. shift registers (more or less the same principle i.e. serial in – parallel out).

The article referenced above discusses few other (even RS232 as a viable alternative!).

The key point that binds all of them together – you need at least 1 free pin on your existing microcontroller to be able to increase your IO pin count. If you are opting for any of the three mentioned above (SPI, I2C and/or shift registers), you’re going to need 2-3 (max. 4 in the case of SPI) free pins. Otherwise, you’re out of luck!

Before continuing with my choice of approach, I would just like to point to this explanation on shift registers from Sparkfun. IMHO, this is probably the most pragmatic explanation out there! For a more detailed explanation, this one from All About Circuits (Shift Registers)!

I have chosen the I2C approach. Why? Because I had bought the IC already and there was no point in trying anything else at this time.

Some links I found useful: I2C Tutorial: Digital I/O Expansion with PCF8574 I2C ModuleArduino and PCF8574 IO Expander – Binary Counter and I2C Bus Read / Write, and Unofficial guide to PCF8574 i/o expansion I2C bus.

My approach was: (1) simulate everything, (2) test on a breadboard, (3) solder everything on a perfboard and (4) re-test everything!



Everyone who’s into electronics, will recognize the graphics styling! Yes, it’s Proteus from Labcenter Electronics Ltd. What an amazing piece of software!

With the help of a friend who uses Proteus professionally, I drew the circuit above which basically, is a an Arduino Uno, two port expanders (one dedicated solely for inputs while the other one solely for outputs), 8 switches (actually one x8 DIP switch) and 8 LEDs. I have also connected the pin 13 of U2 to pin 2 of the Uno while pin 13 of U3 is pulled high only and not connected to the corresponding Arduino pin. The intention was: as soon as any of the (additional) inputs (on U2) change their state, the program logic should “scan” across and see which one exactly and activate the appropriate (additional) output (on U3).

Here is the terminal output:



and the oscilloscope, capturing the interrupt:


And here’s the link to the source code. I have used this library to make my first program and all in all, the simulation went smoothly – with one exception – as soon as I start the simulation, I can notice all outputs going HIGH for ‘a split second’!? I suspect it’s coming from the library itself, which is why I am changing my strategy:

  1. simulate everything
  2. test on a breadboard
  3. solder everything on a perfboard (e.g. in a shield-like form factor?)
  4. re-test everything
  5. re-program without the use of the library, and
  6. re-test again!

The second step makes no sense if you’re going to use a simulator. Furthermore, I could definetely refactor the code and use some of the already provided built-in functionality in the library, bus as I am going to do step 5

On the topic of a simulator, there are certainly plenty out there which are 100% free, but in my opinion, if you are developing regularly and want to take your projects on a more professional level, I strongly believe purchasing a license for Proteus is worth it!

Next up, Part 2 – creating a shield like board and reprogramming everything using nothing but the Wire library.