Beginner Multiplexing issues

Hi guys,
Sorry in advance for this being a very basic request.

I am very stuck with my current project which is making a 24-button MIDI controller.
I have sorted the hardware side of things, however am getting very stuck with the code and whatnot.
I am using a ProMicro as it natively supports USBMIDI (have tried and failed with a Mega in the past). My design uses 24 buttons, meaning that I need more I/O pins to work with than the Pro Micro offers. I have purchased and wired up a CD74HC4067 chip, but have failed to find the right resources online to help me.
I have tried using and understanding this code, however I do not understand the channels properly and every output is always 1.

//Mux control pins
int s0 = 8;
int s1 = 9;
int s2 = 10;
int s3 = 11;
int en = 15;

//Mux in “SIG” pin
int SIG_pin = 0;

void setup(){
pinMode(s0, OUTPUT);
pinMode(s1, OUTPUT);
pinMode(s2, OUTPUT);
pinMode(s3, OUTPUT);
pinMode(en, OUTPUT);

digitalWrite(s0, LOW);
digitalWrite(s1, LOW);
digitalWrite(s2, LOW);
digitalWrite(s3, LOW);
digitalWrite(en, LOW);
digitalWrite(SIG_pin, INPUT);

Serial.begin(9600);
}

void loop(){

//Loop through and read all 16 values
//Reports back Value at channel 6 is: 346
for(int i = 0; i < 16; i ++){ 
  Serial.print("Value at channel "); 
  Serial.print(i); Serial.print("is : "); 
  Serial.println(readMux(i)); 
  delay(10); 
  } 
} 


int readMux(int channel){ 
  int controlPin[] = {s0, s1, s2, s3}; 
  int muxChannel[16][4]={ {0,0,0,0}, 
  {1,0,0,0}, 
  {0,1,0,0}, 
  {1,1,0,0}, 
  {0,0,1,0}, 
  {1,0,1,0}, 
  {0,1,1,0}, 
  {1,1,1,0}, 
  {0,0,0,1}, 
  {1,0,0,1}, 
  {0,1,0,1}, 
  {1,1,0,1}, 
  {0,0,1,1}, 
  {1,0,1,1}, 
  {0,1,1,1}, 
  {1,1,1,1} }; 
  //loop through the 4 sig 
  for(int i = 0; i < 4; i ++){ 
    digitalWrite(controlPin[i], muxChannel[channel][i]); 
    } 
    //read the value at the SIG pin 
    int val = digitalRead(SIG_pin); //return the value 
    return val; 
    }

The diagram below is for demonstrating my system and how I have the multiplexer connected, just ignore the pin numbers as I have changed them in my code to suit my project.

Any help would be much appreciated, could someone also point me to a page where someone explains multiplexing properly as I feel like I still don't understand it fully.

Many thanks.

I believe your SIG pin needs to go to A0, not pin 3 as your layout shows.

When you say the output is always 1, do you mean that is what you are seeing on the Serial monitor?

The multiplexer connects one pin to 16, as chosen by the values placed on S0 to S3. Making the enable pin low will make enable the outputs. The problem is that the multiplexer has a fair amount of resistance in itself (it is really designed for analog switching) and so it is possible that the input pin of the Uno is never seeing the other state.

Please check the voltage at the SIG pin. It should be close to 5V in one state, and close to 0V in the other.

Are you simply trying to read a set of digital IO pins? If so, there are easier and better modules for that. A shift register, such a 74HC595 based module, may be a better choice.

Here is a tutorial that might help:

Before you can read 16 buttons, you need to be able to read 1 button. Have you tested that you can successfully read 1 button?

Disconnect any of your buttons from the multiplexer and connect it instead direct to the arduino input pin (after disconnecting the multiplexer). Obviously all 16 will now read the same, but can you read 1 and 0 when the button is pressed and not pressed?

I suggest this test because using this type of 4-pin button can be error prone. It can be difficult to know which of the 4 pins are permanently connected to each other and which are connected only when the button is pressed. The easy way to connect them correctly is to use only 2 diagonally opposite pins and leave the other 2 unconnected. It does not matter which 2 you choose.

I agree that this type of multiplexer is not the best option for you.

You can read 24 buttons, with no multiplexer or any other chip, and no resistors, using 10 Arduino pins, if you connect your buttons as a matrix. If you need to be able to read more than one button pressed at once, you will need to attach a small diode to each button, for example 1n4148 or similar.

My approach would be to connect three 8 bit parallel to serial chips (Example 74HC166) in series then in one clock cycle you latch the value of each of the switches and then shift the data in, you can detect any combination of buttons pressed with this method. This can be done with the SPI port or with the standard ports, your choice.

Thank you all for your advice, it seems as if I'm tackling the task in the wrong way, I have seen others create the same projects using this multiplexer yet I can't find their code.

I simply want to make a MIDI controller exactly like this example: 3D Printing a MIDI Controller - YouTube
only with 24 buttons instead of 16 and a Pro Micro instead of Leonardo.

Please help, thank you!

Did you mean pinMode?

Maybe you understand this sketch.
Reading two muxes can be done with only four lines of code.
I have used 12channels of each mux, for your 24 channel requirement.
It stores the current switch data in switchState[0] to switchState[23].
Untested.
Leo..

// two 74HC4067 mux boards
// switches between mux input and mux ground, optional 10k pull up to vcc
const byte controlPin[] {4, 5, 6, 7}; // control pins s0-s3
const byte mux1Common = 8;
const byte mux2Common = 9;
byte switchState[24]; // holds 24 channels

void setup() {
  Serial.begin(115200);
  pinMode(mux1Common, INPUT_PULLUP);
  pinMode(mux2Common, INPUT_PULLUP);
  for (byte i = 0; i < 4; i++) pinMode(controlPin[i], OUTPUT); // four control pins
}

void loop() {
  // read the switches
  for (byte i = 0; i < 12; i++) { // 12 channels per mux used
    for (byte s = 0; s < 4; s++) digitalWrite (controlPin[s], bitRead(i, s)); // set four control pins
    switchState[i] = digitalRead(mux1Common); // 0-11
    switchState[i + 12] = digitalRead(mux2Common); // 12-23
  }
  // print
  for (byte i = 0; i < 24; i++) {
    Serial.print(switchState[i]);
    Serial.print(",");
  }
  Serial.println();
}

Thank you for this.

It has helped me register a couple of the button pushes, making me wonder now about my physical connections. I am using only one CD74HC4067 board with the 16 pins, would the adapted code look something like this?:

// two 74HC4067 mux boards
// switches between mux input and mux ground, optional 10k pull up to vcc
const byte controlPin[] {2, 3, 4, 5}; // control pins s0-s3
const byte mux1Common = 15;
// const byte mux2Common = 9;
byte switchState[16]; // holds 24 channels

void setup() {
  Serial.begin(115200);
  pinMode(mux1Common, INPUT_PULLUP);
  //pinMode(mux2Common, INPUT_PULLUP);
  for (byte i = 0; i < 4; i++) pinMode(controlPin[i], OUTPUT); // four control pins
}

void loop() {
  // read the switches
  for (byte i = 0; i < 16; i++) { // 12 channels per mux used
    for (byte s = 0; s < 4; s++) digitalWrite (controlPin[s], bitRead(i, s)); // set four control pins
    switchState[i] = digitalRead(mux1Common); // 0-11
    //switchState[i + 12] = digitalRead(mux2Common); // 12-23
  }
  // print
  for (byte i = 0; i < 16; i++) {
    Serial.print(switchState[i]);
    Serial.print(",");
  }
  Serial.println();
}

Seems ok. Why don't you try it.
Leo..

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.