multiplex/demultiplex: 24 inputs + 24 outputs

Hello eveyone! I am a freshman here and a very beginner in Arduino.
I am a student in Venice and I am starting to prototype my thesis project: an interactive garment which involves 24 LEDs fading.
I’d like to use an Arduino Lilypad or at least a Duemilanove (on which I am doing some basic stuff).
My problem is the following: how do I manage 24 indipendent INPUTS (switches or photocells) each one connected to an OUTPUT?
From what I have read so far it seems that the 4051 multiplexer/demultiplexer is what I need, but apparently I need 6 of them (3 for the inputs - 8x3channels = 24inputs + 3 for the outputs - 8x3 as well). But do I have enough pins on the Duemilanove or Lilypad? How will I manage the inputs/outputs?

I hope I did the math right… If not, please tell me… :frowning:

If anyone could help me that would be extremely appreciated. If you also have some code to show me on how you managed similar issues that would be awesome.

Please help.
Cheers,
Noidsign

4051 multiplexer/demultiplexer

The 4051 will do for inputs but is not really suitable for outputs because it's not latched, ie the pins won't stay in the state you leave them when you move to another pin.

Also the 4067 will handle 16 channels so 2 of them will to 32 inputs.

For outputs a 74xx595-style shift register would be better, however the 595 isn't suitable for driving LEDs by itself so you also need high-current buffers and other versions of this chip with high-current capability.


Rob

Thank you Greynomad! Do you have any link to share in which I can get how to connect the 4067 (or 4051) and the 74xx595 to the Duemilanove? That would be pure mercyness. Thank you!

I think I lost part of the replay... "595 isn't suitable for driving LEDs by itself so you also need high-current buffers and other versions of this chip with high-current capability" what do you suggest?

This comes up a lot, I'll have to do a drawing one day :)

Meanwhile, with two 4067s you need 4 control pins to select 1 of 16 channels on both chips, then either two more pins to select between the two 4067s or one pin and an inverter. (ignore the Picaxe reference)

As for the SR outputs, there's a tute in the playground somewhere I think, also look at the Arduino shiftOut() function.

As mentioned though the 595 is not suitable for driving LEDs and it needs another driver chip and a resistor per LED. So a better choice is something like the TLC5917/7, these work the same way as the 595 but have high- and limited-current outputs so no extra components.

Also look at the TCL5926/7, they do 16 channels.

No drawing for that I'm afraid.


Rob

how do I manage 24 indipendent INPUTS (switches or photocells) each one connected to an OUTPUT?

For the digital IO lines switches the Centipede shield might be an option See http://macetech.com/store/index.php?main_page=product_info&products_id=23 It does not provide analog in (ADC) lines so its only half of a solution but it might help.

So far... What I understood is that I can use 4067 one connected to the other for the INPUTS, and a series of TLC5917/7 (or TLC5926/7) for the OUTPUTS (remembering that I'll nedd to match each INPUT with one single OUTPUT which is a fading LED). Is that correct?!

The problem is... if I Google TLC5917 I can't fine anything helpful, as well as for the TLC5926... Maybe I am just becoming dumb in the searching... I appreciated the sarcasm of the other links, but this time I think I am really not able to find anything helpful... Please somene prove me I am wrong...

I can't fine anything helpful

The second hit is the data sheet how more useful can it get?

Also try the TLC5940, there is even an arduino library for that.

Thank you all so much. Now I'll look through datasheets, circuits and codes and hopefully quite soon. I'll keep you updated with the progress (and more likely with the stucks). Thanks again to everyone!

Hello there!
So far I stared getting in the logic of mux/demux. I managed to make some LEDs fade controlled by a 4051. (yeeeeehi!) Now I am trying to understand how to control the inputs.
I checked this tutorial http://www.arduino.cc/playground/Learning/4051, but I cannot get the inputs. Let me clear this. I connected the Enable pin6 on the 4051 to the analogPin 4 on the Arduino, and in the loop I added this part of code:

result = analogRead(4);

if(result < 1020) {
Serial.println(0);
}
else{
Serial.println(1);
}

Now… I don’t know which pin is on/off… Is there a way to make this more clear? Expecially because later on I’ll need to match each “button” with each LED… Many thanks!

I connected the Enable pin6 on the 4051 to the analogPin 4 on the Arduino

No this pin is an input for this experiment you want to connect it to ground. The Z pin is the one you want to connect to the arduino's analogue input.

I managed to make some LEDs fade controlled by a 4051.

Using this chip as an output multiplexer is very bad practice and is the wrong way to do things. It is an input multiplexer.

Hi Grumpy_Mike! And thanks for the suggestion.
So, now I made the circuit properly for the INPUT part. The only thing is that I cannot understand how to know which exactely pin is the one that is switching on/off… Let me explain better.
I am using the following code. Now I am using only 1 switch but then I will have 24 switches and I would like to know which one is the one switching on, so that I will be able to map each LED with the maching switch.

int s0 = 10;
int s1 = 9;
int s2 = 8;

int a;
int b;
int c;

int r0 = 0;
int r1 = 0;
int r2 = 0;
int rowTTL = 0;
int count = 0; // just a count

int binTTL = {
0, 1, 2, 3, 4, 5, 6, 7};

int inPin = 4;
int result;

void setup(){
pinMode(s0, OUTPUT);
pinMode(s1, OUTPUT);
pinMode(s2, OUTPUT);
Serial.begin(9600);
}

void loop(){

for(int i=0; i<8; i++){

rowTTL = binTTL*;*

  • sendABCTTL(rowTTL);*
  • result = analogRead(inPin);*
  • if(result < 1020) { // no contact*
  • Serial.println(0);*
  • }*
  • else{*
  • Serial.println(1); // contact!*
  • }*
  • delay(500);*
  • }*
    void sendABCTTL(int rowTTL){
  • switch(rowTTL) {*
  • case 0:*
  • digitalWrite(s0, LOW);*
  • digitalWrite(s1, LOW);*
  • digitalWrite(s2, LOW);*
  • break;*
  • case 1:*
  • digitalWrite(s0, HIGH);*
  • digitalWrite(s1, LOW);*
  • digitalWrite(s2, LOW);*
  • break;*
  • case 2:*
  • digitalWrite(s0, LOW);*
  • digitalWrite(s1, HIGH);*
  • digitalWrite(s2, LOW);*
  • break;*
  • case 3:*
  • digitalWrite(s0, HIGH);*
  • digitalWrite(s1, HIGH);*
  • digitalWrite(s2, LOW);*
  • break;*
  • case 4:*
  • digitalWrite(s0, LOW);*
  • digitalWrite(s1, LOW);*
  • digitalWrite(s2, HIGH);*
  • break;*
  • case 5:*
  • digitalWrite(s0, HIGH);*
  • digitalWrite(s1, LOW);*
  • digitalWrite(s2, HIGH);*
  • break;*
  • case 6:*
  • digitalWrite(s0, LOW);*
  • digitalWrite(s1, HIGH);*
  • digitalWrite(s2, HIGH);*
  • break;*
  • case 7:*
  • digitalWrite(s0, HIGH);*
  • digitalWrite(s1, HIGH);*
  • digitalWrite(s2, HIGH);*
  • break;*
  • }*
    }
    Any suggestion on how to get the pin that is switching on/off?
    I didn’t quite get why not to use the 4051 also for the OUTPUTS… The file in arduino.cc www.arduino.cc/playground/Learning/4051 says it’s a multiplexer/demultiplexer if I didn’t understand wrong…

I didn’t quite get why not to use the 4051 also for the OUTPUTS…

The 4051 does not have latched outputs, so for exampe if you are controlling OP4 then all the other OPs are at a high-impedance state and whatever they are supposed to be controlling will do whatever it likes. Move to OP5 and OP4 floats etc etc.

I can only see this working for OPs if you are doing some form of multiplexing.

Any suggestion on how to get the pin that is switching on/off?

I don’t understand this.


Rob

Hello again guys.
I am really stuck with this…
I am posting what I tried to do with no results… Hopefully someone can help me and tell me where I am wrong because I cannot figure it out and it’s quite frustrating…
So I connected everything like this, thinking to have different results when using a strong light on the photoresistor

And I used this code:

int r0 = 0;      //value select pin at the 4051 (s0)
int r1 = 0;      //value select pin at the 4051 (s1)
int r2 = 0;      //value select pin at the 4051 (s2)
int row = 0;     // storing the bin code
int count = 0;    // just a count
int  bin [] = {
  0, 1, 10, 11, 100, 101, 110, 111};//bin = binSr, some times it is so easy
int val = 0;

void setup(){

  pinMode(7, OUTPUT);    // s0
  pinMode(6, OUTPUT);    // s1
  pinMode(5, OUTPUT);    // s2

  Serial.begin(9600);
}

void loop () {

  for (count=0; count<=7; count++) {
    row = bin[count];      
    r0 = row & 0x01;
    r1 = (row>>1) & 0x01;
    r2 = (row>>2) & 0x01;
    digitalWrite(7, r0);
    digitalWrite(6, r1);
    digitalWrite(5, r2);    

    val = analogRead(0);
   if ( bin[count] == 0 )
    {
      Serial.print("y0: ");
      Serial.println(val);
    };    

       if ( bin[count] == 1 )
    {
      Serial.print("y1: ");
      Serial.println(val);
    };
    
       if ( bin[count] == 10 )
    {
      Serial.print("y2: ");
      Serial.println(val);
    };
    
       if ( bin[count] == 11 )
    {
      Serial.print("y3: ");
      Serial.println(val);
    };

    if ( bin[count] == 100 )
    {
      Serial.print("y4: ");
      Serial.println(val);
    };
    
       if ( bin[count] == 101 )
    {
      Serial.print("y5: ");
      Serial.println(val);
    };
    
       if ( bin[count] == 110 )
    {
      Serial.print("y6: ");
      Serial.println(val);
    };
    
       if ( bin[count] == 111 )
    {
      Serial.print("y7: ");
      Serial.println(val);
    };

    delay (250);
  }  // end of for

} // end of loop

But unfortunately the results “printed” are completely irrelevant. They appear to be quite random, and there is no diffrerence between the one in which I have the photoresistor and the others (I also used the photoresitor by its own in order to see if the problem was that, but it works quite good)
I am really stuck because I don’t understand what’s going on :frowning:
It would be great if you could give me some help. Thanks a lot again.

Sorry the img didn't load.

I just realized I am a total dumb... I connected the 100ohm resitor to the Gnd and the photoresitor leg on the +5V and everything went ok... Well actually not everything... Is there a reason why the values are in an inverse proportion with light? Like - lot of light -->(not so) low value (let's say 600) - few light --> high value (1020)

And why doesn't it change that much? I have a solar lamp just in the top of it and I am melting but no lower value there...

What’s the value of your LDR? If it’s a lot higher than the 100R then the reading won’t change much. Try a larger resister.

As for the inversion, the LDR is reducing it’s R with more light, either invert the reading in the code or swap the LDR and R.


Rob

Thanks for the suggestions!

Just another question…

Now the INPUTS part seems to work quite fine…
But I still have some issues on the OUTPUTS…
I am trying with only one LED directly connected to pin 3 (PWM) on my Arduino Duemilanove.
What I’d like it to do is to fadeIn when low light is detected and fadeOut when light gets back to a normal… Right now it just augment/diminguish its brightness of (i think, well it looks like that) 1 step and it’s very low luminescence… Any ideas why this is happening?

here is the code

int s0 = 7;
int s1 = 6;
int s2 = 5;

int rowTTL = 0;

int leds[16] = {
  1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16};
int l;
int  binTTL [] = {  
  0, 1, 2, 3, 4, 5, 6, 7};//bin = bin?r, some times it is so easy

int bright = 1;

int inPin_1to8 = 0;  
int inPin_9to16 = 5;

int threshold = 1017;

int result_1to8;
int result_9to16;



void setup(){
  pinMode(s0, OUTPUT);
  pinMode(s1, OUTPUT);
  pinMode(s2, OUTPUT);
  Serial.begin(9600);
}



void loop(){


  for(int i=0; i<8; i++){

    digitalWrite(s0,bitRead(i, 0));
    digitalWrite(s1,bitRead(i, 1));
    digitalWrite(s2,bitRead(i, 2));

    result_1to8 = analogRead(inPin_1to8);
    result_9to16 = analogRead(inPin_9to16);

    for(int e=0; e<2; e++) {
      l = ((i+1)+8*e);
      Serial.print("sensor nr: ");
      Serial.print((i+1)+8*e);
      Serial.print(" is ");


      if (e == 0) {
        if(result_1to8 < threshold) {
          bright = bright - 1;
          bright = constrain(bright, 0, 255);
          analogWrite(leds[l-1], bright);
          Serial.println(result_1to8);
          Serial.print("bright: ");
          Serial.println(bright);

        }
        else {
          bright = bright + 1;
          bright = constrain(bright, 0, 255);
          analogWrite(leds[l-1], bright);
          
          Serial.println(result_1to8);
          Serial.print("bright: ");
          Serial.println(bright);

        }
      } 
      else if (e == 1) {
        if(result_9to16 < threshold) { // no contact
          Serial.println(result_9to16);
          Serial.print("bright: ");
          Serial.println(bright);

        }
        else{
          Serial.println(result_9to16); // contact!
          Serial.print("bright: ");
          Serial.println(bright);

        } 
      }    
    }
  }
}//end loop

(thanks to tomek for explaining me how to go on)

I got a little step further, but not very much. I tried to use an if statement in the fadingUp() and fadingDown() voids, but the fading is too slow. But if I use a for loop it’s just too fast without the delay, which I’d rather not to use, because I feel scared it might affect the input detection as well as causing problems when I’ll use the TLC 5940 instead of just one PWM pin.

Any suggestion, please, is more than appreciated…
Here is the code

int s0 = 7;
int s1 = 6;
int s2 = 5;

int rowTTL = 0;
int leds[16] = {
  1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16};

int bright[16] = {
  1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16};
boolean fadeUp;
unsigned long fadeMillis = 0;


int l;
int  binTTL [] = {  
  0, 1, 2, 3, 4, 5, 6, 7};//bin = bin?r, some times it is so easy


int inPin_1to8 = 0;  
int inPin_9to16 = 5;

int threshold = 1020;

int result_1to8;
int result_9to16;



void setup(){
  pinMode(s0, OUTPUT);
  pinMode(s1, OUTPUT);
  pinMode(s2, OUTPUT);
  Serial.begin(9600);
}



void loop(){

  for(int i=0; i<8; i++){
    digitalWrite(s0,bitRead(i, 0));
    digitalWrite(s1,bitRead(i, 1));
    digitalWrite(s2,bitRead(i, 2));

    result_1to8 = analogRead(inPin_1to8);
    result_9to16 = analogRead(inPin_9to16);

    for(int e=0; e<2; e++) {
      l = ((i+1)+8*e); //this tells me which sensor is being reading
  
      if (e == 0) {
        if(result_1to8 < threshold) { // no contact
          fadeUp = false;
          if (fadeUp == false){
            fadingDown();
          }
        }
       else if(result_1to8 > threshold){
          fadeUp = true;
          if (fadeUp == true){
          fadingUp();
          }
        }
      }
      else if (e == 1) {
        if(result_9to16 < threshold) { // no contact
        }
        else{
        } 
      }    
    }
  }
}//end loop

void fadingDown(){
  if (millis() - fadeMillis >= 5)
  {
    fadeMillis = millis();
    
    for (int i = 255; i>0; i--){
      bright[l-1]--;
      bright[l-1] = constrain(bright[l-1], 0, 255);
      analogWrite(leds[l-1], bright[l-1]);
    }
    if (result_1to8 > threshold){
        fadeUp = true;
      
    }
  }
}

void fadingUp(){
  if (millis() - fadeMillis >= 5)
  {
    fadeMillis = millis();
    for (int i = 0; i<255; i++){
        bright[l-1]++;
        bright[l-1] = constrain(bright[l-1], 0, 255);
        analogWrite(leds[l-1], bright[l-1]);
    }

      if (result_1to8 < threshold){
        fadeUp = false;
      }
    }
  }