I started with the tutorial at http://www.arduino.cc/playground/Learning/4051. The concept is that using just three digital pins you can address one of eight channels at a time (which can be input or output, analog or digital). In total, you use four pins (three signal and one common) to get 8 I/O. That is a good deal and fairly straight forward.
It also occurred to me, that in a manner similar to what I had seen done with multiplexed displays, that by adding an additional common pin I could drive current in either direction and double the number of I/Os. That is not so straight forward, so let me try and explain.


Alright, if you are still with me, now all we have to do is multiply that by eight. The eight channels are accessed by addressing the 3 select pins (digital pins 14, 15, & 16) as follows:
Channel / Pin 16 / Pin 15 / Pin 14
0 - 0 0 0
1 - 0 0 1
2 - 0 1 0
3 - 0 1 1
4 - 1 0 0
5 - 1 0 1
6 - 1 1 0
7 - 1 1 1
Hey, that looks like a decimal to binary chart. Imagine that.
O.K., now to the breadboarded "proof of concept". I've split it into 4 banks of LEDs (8 total), and 4 banks of CdS cells (8 total), for a grand total of 16 I/O on 5 pins. Before you say, "wait, you can do that with a 4067 chip," let me just say that the 4051 was all I had handy, and that this trick will also work on 4067 if you want to get 32 I/O out of six pins. That is quite the math. Double your pins for the price of one!


Here is the pudding:
I hoped this helped you. It did me.
Here is the Arduino code (I'm not sure why the formatting gets spread out:
/*
* Example of getting 16 i/o from 5 pins using a CD4051
*
* Based on tutorial and code by david c. and tomek n.* for k3 / malmö högskola
* http://www.arduino.cc/playground/Learning/4051?action=sourceblock&ref=1
*/
int selPin[] = { 14, 15, 16 }; // select pins on 4051 (analog A0, A1, A2)
int commonPin[] = { 17, 18}; // common in/out pins (analog A3, A4)
int led[] = {LOW, LOW, LOW, LOW, LOW, LOW, LOW, LOW }; // stores eight LED states
int CdSVal[] = { 0, 0, 0, 0 }; // store last CdS readings
int cnt = 0; // main loop counter
int persistDelay = 100; // LED ontime in microseconds
void setup(){
Serial.begin(9600); // serial comms for troubleshooting (always)
for(int pin = 0; pin < 3; pin++){ // setup select pins
pinMode(selPin[pin], OUTPUT);
}
}
void loop(){
flashLEDs();
if (cnt == 0){
for(int x; x < 8; x++){
led[x] = random(2);
}
}
cnt++;
if (cnt > 100) { cnt = 0; }
}
void flashLEDs() {
for(int pin = 0; pin < 2; pin++) { // set common pins low
pinMode(commonPin[pin], OUTPUT);
digitalWrite(commonPin[pin], LOW);
}
for (int bank = 0; bank < 4; bank++) {
for(int pin = 0; pin < 3; pin++) { // parse out select pin bits
int signal = (bank >> pin) & 1; // shift & bitwise compare
digitalWrite(selPin[pin], signal);
}
if (led[bank * 2]){ // first LED
digitalWrite(commonPin[0], HIGH); // turn common on
delayMicroseconds(persistDelay); // leave led lit
digitalWrite(commonPin[0], LOW); // turn common off
}
if (led[bank * 2 + 1]){ // repeat for second LED
digitalWrite(commonPin[1], HIGH);
delayMicroseconds(persistDelay);
digitalWrite(commonPin[1], LOW);
}
}
}
Hi,
ReplyDeleteI am using EVK1100. I need to read voltages from Voltage divider, since EVK1100 has only 5 adc inputs and i have 8-10 sensor outputs i need to read on EVK1100. Can i use the method above to read the voltages on EVK1100 or is there any alternative method.
Kuamr
What diodes are you using? I was checking starter packages for the arduino and the included a 1N4007, but Jameco Electronics sells 3 types.
ReplyDelete-@ RCTFIER STND RECVRY O/J,RHS DIP8
-@ DIODE, 1N4007, DO-41, (10),GPP 1A 1000V
-@ DIODE,SIL REC,1N4007,1A,1000V PRV (10)
Are any of these similar to what you used?
P.S. Any chance you could upload the arduino code for this setup?
Can you post your code here please... Thank you very much.
ReplyDeleteAdded dusty code to the post. Use at your own risk.
ReplyDeleteHi Ken this is just great and easy to follow, thanks. I was wondering what diodes you used? I downloaded the Fritzing package but its missing a few parts. Once again great post.
ReplyDeleteThis is brilliant! thanks a lot for the information.
ReplyDeleteWhat's the purpose of the randomization in the loop?
ReplyDelete