Multiplexer CD4051BE

Hello, I am currently learning how to use multiplexer to use in my midi controller project.
I have a CD 4051 which I would like to use with a teensy2.0. I am using 8 pushbuttons connected to each multiplexer ch.
I tested it with an arduino uno and it works perfectly with S0, S1 and S2 connected to pin 2,3,4 and Z (common ch) connected to pin 7. However if I change the common ch to any other pin it would not work (clearly I change the code to ensure that the variable "zInput" corresponds to the correct pin. I find it very frustrating as I cannot understand why it would only work on one pin.
I tried it on the teensy but I cannot get it to work in any pins there.

I am using the following code that I found on spurkfun website and adapted it to be digital read rather than analogue.

RESOLVED: I have just realised that I din't substitute this line int inputValue = digitalRead(7); with int inputValue = digitalRead(zInput);....

still learning....

/////////////////////
// Pin Definitions //
/////////////////////
const int selectPins[3] = {2, 3, 4}; // S0~2, S1~3, S2~4
const int zInput = 7; // Connect common (Z) to arduino pin

void setup() 
{
  Serial.begin(9600); // Initialize the serial port
  // Set up the select pins as outputs:
  for (int i=0; i<3; i++)
  {
    pinMode(selectPins[i], OUTPUT);
    digitalWrite(selectPins[i], HIGH);
  }
  pinMode(zInput, INPUT_PULLUP); // Set up Z as an input

  // Print the header:
  Serial.println("Y0\tY1\tY2\tY3\tY4\tY5\tY6\tY7");
  Serial.println("---\t---\t---\t---\t---\t---\t---\t---");
}

void loop() 
{
  // Loop through all eight pins. 
  for (byte pin=0; pin<=7; pin++)
  {
    selectMuxPin(pin); // Select one at a time
    int inputValue = digitalRead(7); // and read Z
    Serial.print(String(inputValue) + "\t");
  }
  Serial.println();
  delay(200);
}

// The selectMuxPin function sets the S0, S1, and S2 pins
// accordingly, given a pin from 0-7.
void selectMuxPin(byte pin)
{
  for (int i=0; i<3; i++)
  {
    if (pin & (1<<i))
      digitalWrite(selectPins[i], HIGH);
    else
      digitalWrite(selectPins[i], LOW);
  }
}

Did that fix it for the teensy also?

You can read 8 pushbuttons with 1 analog pin, a few resistors and no extra chip...

Yes thank you. Apparently it is working as expected with the teensy too. I am aware of the possibility of using one analogue pin to achieve the same thing and I am considering to use this method for my "mode select" buttons but I understand this can create problems if you press two buttons at the same time? Not that I will need to press two buttons at the same time but I still do not know what problems this can cause.

You are correct, generally speaking, the resistor technique is unsuitable for correctly detecting multiple button presses. If multiple button presses happen, an unexpected value will be read. If you choose the resistor values carefully, these unexpected values won't match any of the expected values and your code will be able to detect that and ignore the value. If you are not careful, some of the unexpected values will match one or more of the expected values and your code will not be able to detect that and could carry out the wrong action.

I think the method can be made to work, and be able to correctly detect each button, for a small number of buttons, but it requires some very careful choice of resistors!

Another technique you could consider is making your buttons into a matrix. 6 Arduino pins could scan a matrix of 9 buttons. 8 pins can scan 16 buttons. No extra chip is needed, but if you need to detect multiple presses, you need to add some extra diodes.

There is also a technique called Charlieplexing which is like using a matrix but with fewer pins. 4 pins can scan 12 buttons, 5 pins can scan 20 buttons. With this technique, you always need diodes, and multiple presses cannot be correctly detected.

Thank you very much for this information Paul. I think for the moment I will stick with using multiplexer and shift registers. I am, just learning how they work and how to code them - and still not very good at it - only coded a multiplexer so far not a shift register and I need a bit of time to digest all this stuff but it's good to know the other options as well and I will definitively be researching into this.

Another issue that I need to work out for my project is whether it is possible / convenient to use multiplexer or shift registers with rotary encoders. With Arduino I have used the library enableinterrupt which has enable me to use any pin as interrupt (even though arduino only has 2 pins with external interrupts). I am trying to find out if this can be done with the teensy but I cannot find any information online. I have three encoders and the teensy only has four pins with external interrupts. Logically I suppose multiplexer is not suitable as it connects one pin at the time....

I'm sure the teensy will have some equivalent to the pin-change interrupt library. I don't have a teensy so can't help you directly with that.

Rotary encoders can be difficult. I'm not sure multiplexers or ordinary shift registers are the best thing to use with them. There are chips called I/o extenders that are better for encoders. On most i/0 extenders, all the pins have interrupt capability. A single interrupt output goes back to the Arduino, so that the Arduino is alerted to read the chip because one of its inputs has changed. I/o extenders are either i2c or SPI bus, but SPI bus may be better for encoders because it is faster than i2c.

Great! I will definitively look into all this stuff. Thank you very much you have been really helpful!!! cheers!