Multiplexer vs. shift register vs. serial vs. i2c?

I have come to understand that there are various ways to expand the number on digital I/O's and analog in's on the arduino board.

In particular I've been looking at the 4051 analog multiplexer like this (more analog in's):

www.arduino.cc/playground/Learning/4051

...and the 74HC595 shift register like this (more digital I/O's):

www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1185507207;start=all

I also read that there are other ways like using the serial and something called i2c?!

I would like to ask what the pros and cons are in using the different options? Price, complexity, speed, number of pins used, etc...?

(I only know the 4051 uses 1 analog plus 3 I/O's and the 74HC595 uses 3 I/O's)

I'd also like to ask if it's possible (and prudent?) to control SERVOS via a shift register (or other)?

Aniss

There is a good survey of the common options for extending the number of outputs you can control on Tom Igoe's website, here. The comparison chart at the bottom of that page has a lot of what you are asking.

There are also I/O extenders like the pcf8574, MCP23017, MAX6956 and others.

Thanks for the input, Andy and Ron. :slight_smile:

I checked out the page Andy mentioned as well as the chips Ron mentioned. The PCF8574 and MCP23017 are both i2c based I/O expanders, and the MAX6956 is something called SPI (which introduces a 5th option of expansion thereby further adding to my confusion).

What I wish to do is drive 12 servos, have (atleast) 13 analog in's and still have a few (atleast 2) I/O's to spare. I then found out I could use a multiplexer (like the 4051) to expand the number of analog in's. It would give me 6-1+8=13 analog in's in total. The problem with that is that it uses 3 digital I/O's and I have only 2 left (since 12 are reserved for servos).

So...all suggestions are still more than welcome...Especially I'd like to hear about experiences with I2C and this SPI fellow, or the possibilities (and problems?) of driving SERVOS through a shift register or multiplexer...

Aniss

Ah...also I've come to understand that an I2C port expander uses only 2 analog IN's to provide a LOT of digital I/O's. But I don't know whether it also can provide additional analog in's?

For I2C servo controling try this: SD20
The last revision don't need the external resonator! (now it is inside)

A similar offering on E-bay has a expander (servo channels, A/D, D/A,stepper control, motor control, etc) utilizing I2C or serial communications.

http://cgi.ebay.com/ws/eBayISAPI.dll?ViewItem&item=170360638864&ssPageName=STRK:MEWAX:VRI

Cheers guys :slight_smile:

I'll be looking into those options later today. Allthough it seems a bit like overkill: 20 (!!) additional servos! :o When all I need is a few extra I/O pins to control an analog multiplexer (for more analog in's) while reserving 12 I/O's for servos.

And it would seem that the I2C's cannot provide extra analog in's. So I'll need a bigger analog multiplexer since the I2C takes up 2 analog in's. But perhaps it's not a bad option and definately nice to know it exists. :slight_smile:

But still...All tips are more than welcome....

And it would seem that the I2C's cannot provide extra analog in's

Well there are lots of A/Ds with an I2C interface:-

And you get 4 analogue inputs with a PCF8591 and more if you put your own data selector on the front end.
Like:-
http://www.thebox.myzen.co.uk/Hardware/Transistor_Tester.html
That circuit has 16 analogue inputs.

Hi Aniss
Instead of just lining up more components and links I thought I would give you a brief overview of IO expansions.

Using the IO pins on the Arduino is FAST (several 100kHz is no problem), but as you say limited in number.

Next step is to use a latch or multiplexor:
3 IO pins can be set into 8 different combinations, from 000 to 111.
Each combination, say 010, connects you to one IO pin on the multiplexor, which then can be set or read through a 4th pin, depending on if it is an input or output.
Here you have expanded 3+1 IOs to 8, but you can only reach one of the 8 at one time. It is a little more complicated to handle and a little slower than direct IO. (4+1 to 16 IOs exist also).

Next step again is to use a shift register.
It is almost the same thing as a multiplexor, but instead of having 3, 4 or more parallel address inputs it only has one serial input; the address bits are sent one by one to the serial input (shifted in). Normally 2 more wires are used for handshaking (bit rate and message start/stop). Typically an address and data are sent in one message, or an address is sent out, status is sent back. By sending an 8-bit address you can select 256 IOs with 3 wires! The penalty is again more SW and slower handling.

SPI is nothing but a standard for sending serial data between components as I just described. SPI is supported by Arduino. The components can be any kind of cirquitry; a LED controller like the MAX7221, general IO (digital and analog, in and out), a digitally controlled amplifier etc.

1-wire and I2C work in a similar way by sending serial data, but are designed for attaching stuff on a larger distance from the processor, up to a few hundred meters! In these systems you normally have a master (the microcontroller or PC) and several slaves. Each slave is passive until its address turns up. Then it acts, depending on the data sent after the address and type of device. Again there is a large number of different devices you can attach to a 1-Wire or I2C bus. And as usual the penalty is more software and SLOW traffic (a few Hz). The basic drivers are however available for Arduino. 1Wire is quite simple while the I2C can be complicated with multiple masters etc.

The next step after this is the CAN bus, USB, TCP/IP... but that's another story.

Hope this gives you and others a base. Good luck!

Ove Fredriksson

1 Like

Sorry to be picky but while 1 wire bus can be a long distance you can't get anywhere close to a hundred meters with a I2C bus. About two meters is pushing it.

Ah, thanks Mike, I shouldn't really have included I2C as I have no practical experience of it, have just looked at the specs. I guess I2C is much faster than 1-Wire?

Thanks guys! And in particular thanks to Frederikson for taking the time to write an overview of the diferent types. Even if you were wrong about the I2C. I knew how the multiplexer works but the rest was pretty obscure to me, so it was very useful. :slight_smile:

It looks like I still have some research to do before I find the right solution for me, but I'm learning new stuff every day and that's what's important.

And just one more question: Am I correct to assume that an SPI port expander uses 4 I/O's no matter how many channels we're talking?

"Am I correct to assume that an SPI port expander uses 4 I/O's no matter how many channels we're talking?"

Well... no. If you mean "can SPI control more than one unit". SPI (as far as I know) is from one unit to another, e.g. 1 Arduino to 1 multiplexer. Just like a printer port on a PC. But then the multiplexer can have any number of IOs. For 2 multiplexers you need 2 x 4 IOs - well 2 x 3 IOs is enough if you communicate in one direction only.

There are however exceptions. For instance the LED display controller MAX7221 can be cascaded; the SPI message goes from the Arduino to the IN pin on the first MAX, and from the OUT pin to the IN pin on the next MAX etc. But you can't really address the second MAX, the Arduino only sees one receiver. You send a long message and the first half is sent on to the second MAX (see the LedControl library on http://arduino.cc/en/Reference/Libraries). A bit tricky, but it is normally handled by the driver. There are other units that can be cascaded like this.

The 1-Wire bus can have 255 units attached to the wire (= multidrop), and each message starts with an address. The processor can talk to each individual completely independent of the others.

Well... no. If you mean "can SPI control more than one unit". SPI (as far as I know) is from one unit to another, e.g. 1 Arduino to 1 multiplexer.

OK?! Now I'm a bit confused again..I was under the impression that SPI based I/O port expanders like these...

...kind of worked like a multiplexer/shift register, only using another protocol for communication?! Namely the SPI protocol requiring 4 I/O's to function...

  1. MISO -> Master In / Slave Out
  2. MOSI -> Master Out / Slave In
  3. SCLK -> Serial Clock
  4. SS -> Slave Select

...which I've read on several websites. For instance...

For 2 multiplexers you need 2 x 4 IOs - well 2 x 3 IOs is enough if you communicate in one direction only.

I'm not sure I understand?! A multiplexer requires 3+1=4 pins for 8 channels (5 for 16 channels). 3 for selecting channel and 1 for the actual communication. How is it possible to use less even if I only need to communicate in one direction?

About cascading: hopefully I wont have to go there...

The funny thing is that this whole ordeal started cause I'm short of 1 (yes ONE) I/O pin. Had Arduino had 15 I/0's I could have reserved 12 for servos, used 3 for the 74HC595 and used 3 of the 74HC595 channels (plus one analog 1) for the 4051. Thus leaving me with 13 analog in's and 5 74HC595 channels to spare. A perfect, simple and CHEAP (less than 2 us$) solution.

But that's not the case so here I am researching ALL alternatives.. :-/

Had Arduino had 15 I/0's

Just a point, you do know you can use the analogue input pins as normal digital I/O pins?

A multiplexer requires 3+1=4 pins for 8 channels (5 for 16 channels). 3 for selecting channel and 1 for the actual communication.

In general a multiplexer needs 2 to the power of n plus 1 wires where n is the number of channels so the above is right for your case of 8 channels.

How is it possible to use less even if I only need to communicate in one direction?

By using time division multiplexing of which serial is an example. There are two types of serial synchronous and asynchronous. The latter is what the normal serial communications uses and requires agreed baud rates between transmitter and receiver and extra redundant (non data) bits to allow synchronisation.
Synchronous communication either transmits the clock signal separately like I2C or SPI or the clock signal is embedded in the modulation like a lot of transmitted systems for say digital TV. For serial you always need 1 data channel (or 2 if you want full duplex communications) The clock is optional but I2C and SPI require it. Then I2C uses a software of addressing what slave it wants to talk to and SPI uses (mainly) hardware in the form of chip enable lines, although some devices also have a software component to the addressing.

So basically you are right in needing 4 wires for SPI and 2 wires for I2C. However, SPI transfer is much faster than I2C and can take place at typically around 10 to 20 MHz where as I2C is mainly 100KHz, although some devices will go at 400Khz.

you do know you can use the analogue input pins as normal digital I/O pins?

:smiley: Haha...No I had no idea that was the case (allthough now that you mention it I seem to remember reading that a long time ago before I even got my Arduino). That pretty much changes the whole perspective.

Thanks a lot for letting me know (and for your advice in general).

Man I love this forum..if people were that nice and helpful in every day life, life would be like 100 times more pleasant :slight_smile:

Ah, sorry I got things mixed up myself.

Well... no. If you mean "can SPI control more than one unit". SPI (as far as I know) is from one unit to another, e.g. 1 Arduino to 1 multiplexer. Just like a printer port on a PC. But then the multiplexer can have any number of IOs. For 2 multiplexers you need 2 x 4 IOs - well 2 x 3 IOs is enough if you communicate in one direction only.

Let me rephrase:

Well... no. If you mean "can SPI control more than one unit". SPI is from one unit to another, e.g. 1 Arduino to 1 IO unit. Just like a printer port on a PC. But then the IO unit can have any number of IOs. For 2 units you need 2 x 4 IOs - well 2 x 3 IOs is enough if you communicate in one direction only.

I shouldn't have said "multiplexers", that confused the issue.

You said

...kind of worked like a multiplexer/shift register, only using another protocol for communication?! Namely the SPI protocol requiring 4 I/O's to function...

  1. MISO -> Master In / Slave Out
  2. MOSI -> Master Out / Slave In
  3. SCLK -> Serial Clock
  4. SS -> Slave Select

You are absolutely right! But data is sent with MOSI and received with MISO, so if you are only sending, MISO is not needed.

Now I have to back paddle a bit:
The simple way of connecting 2 SPI units is to do what I said - 3 wires x 2.
But you CAN connect several SPI units to the same data (MISO/MOSI) and clock wires in parallel, and give each slave unit a separate SS wire. When the SS wire is HIGH, the slave is blocked. Just set one of the SS pins to LOW to select that slave. (Just picked that up myself on another thread! Suggest you read "Understanding SPI" started by SirPoonga).

Yes, isn't it interresting/frustrating how one seemingly simple problem can grow - and grow and grow... >:(

But you learn a lot! I've learned a thing or two by trying to assist you, having to sort my own thoughts out. And you have given me lots of nice links - thanks! :slight_smile:

Back to your original problem: have you considered Arduino Mega? It has a LOT more IOs. It costs a little more, but may be cheaper and simpler than multiplexers etc. But not as fun :wink:

Hm... lots of people have read this thread. Maybe I should add a page to the Arduino Playground, like an introduction to the deeper info on Tom Igoe's website (see Reply 1 in this thread).

Hi Ove Frederikson (a very Scandinavian name..Swedish?..I'm Danish myself).

Thanks for all your advice and sorry for the late reply. No time to play these last few days.. :frowning:

As you mention a tutorial covering ALL the different options for port expansion would surely be an awesome addition to the Arduino playground, so if you're up to it?.... Everybody playing around with Arduino may sooner or later need a few more pins. And it's not really that easy to research. Especially if you're not allready quite a wiz in the field of IC's...like me. :-/

And about the SPI...I was aware that several SPI slaves could share the MOSI, MISO and SCLK. In particular from this page:

www.totalphase.com/support/kb/10045/

I'm still considering all options but now that I know that the analog in's can be used as digital I/O's I'm probably gonna go with the simplest and cheapest solution namely shift registers and analog multiplexers like the 74HC595 and the 4051 (though I'd like to find an appropiate 16 channel ditto). These chips are readily available (even here in Argentina where I live now) and cheap (less than 1 $ each).

And I did consider buying an Arduino Mega..but as a last option. Those things cost almost 90 $ here. Quite a difference from the less than 2 $ shift register/analog multiplexer solution. PLUS it only has 12 analog in's (I need 13) and I don't really need 48 (!!!) I/O's (for the time being anyway), nor the extra memory or eprom.

I also considered buying another Atmega328 chip (which I'm going to anyway for other purposes) and use it as a slave. But it seems like a bit of a hassle having to program 2 chips etc..

So right now I wanna try to find a 16 channel analog multiplexer and that should do it. Any tips in that direction would be highly appreciated?! :slight_smile:

Surely one of these (74HC4067 / 74HCT4067) should do the trick: