two multiplexer's

Hello everyone!
I’m building a midi controller with 12 rotary potentiometers, 12 sliding potentiometers and 12 buttons.
I’m using an arduino micro and two multiplexer’s 4067.
I’ve already made the hardware connections, and everything is working.
My difficulty is in the code, which I do not understand.
I found a code that is even almost what I need. But this code uses only one multiplexer and I use two.
The code is open sorce and I contacted its creator and asked permission to use it.

Can someone help me add a multiplexer to the code?

*/
#include "MIDIUSB.h"
 
#include <Multiplexer4067.h> // Multiplexer CD4067 library >> https://github.com/sumotoy/Multiplexer4067
#include <Thread.h> // Threads library >> https://github.com/ivanseidel/ArduinoThread
#include <ThreadController.h> // Mesma lib de cima
//#include "digitalIOPerformance.h" 

/////////////////////////////////////////////
// buttons
const byte muxNButtons = 4; // *coloque aqui o numero de entradas digitais utilizadas no multiplexer
const byte muxNButtons2 = 4;
const byte NButtons = 4; // *coloque aqui o numero de entradas digitais utilizadas
const byte totalButtons = muxNButtons + muxNButtons2 + NButtons;
const byte muxButtonPin[muxNButtons] = {12, 13, 14, 15}; // *neste array coloque na ordem desejada os pinos das portas digitais utilizadas
const byte muxButtonPin2[muxNButtons2] = {12, 13, 14, 15};
const byte buttonPin[NButtons] = {18, 19, 20, 21}; // *neste array coloque na ordem desejada os pinos das portas digitais utilizadas
int buttonCState[totalButtons] = {0}; // estado atual da porta digital
int buttonPState[totalButtons] = {0}; // estado previo da porta digital

/////////////////////////////////////////////
// debounce
unsigned long lastDebounceTime = 0;  // the last time the output pin was toggled
unsigned long debounceDelay = 5;    // the debounce time; increase if the output flickers

/////////////////////////////////////////////
// potentiometers
const byte NPots = 24; // *coloque aqui o numero de entradas analogicas utilizadas
const byte muxPotPin[NPots] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11}; // *neste array coloque na ordem desejada os pinos das portas analogicas, ou mux channel, utilizadas
const byte muxPotPin1[NPots] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11};
int potCState[NPots] = {0}; // estado atual da porta analogica
int potPState[NPots] = {0}; // estado previo da porta analogica
int potVar = 0; // variacao entre o valor do estado previo e o atual da porta analogica
int lastCcValue[NPots] = {0};

/////////////////////////////////////////////
// pot reading
int TIMEOUT = 50; //quantidade de tempo em que o potenciometro sera lido apos ultrapassar o varThreshold
byte varThreshold = 4; //threshold para a variacao no sinal do potenciometro
boolean potMoving = true; // se o potenciometro esta se movendo
unsigned long pTime[NPots] = {0}; // tempo armazenado anteriormente
unsigned long timer[NPots] = {0}; // armazena o tempo que passou desde que o timer foi zerado

/////////////////////////////////////////////
// midi
byte midiCh = 0; // *Canal midi a ser utilizado
byte note = 36; // *Nota mais grave que sera utilizada
byte cc = 1; // *CC mais baixo que sera utilizado

/////////////////////////////////////////////
// Multiplexer
Multiplexer4067 mplex = Multiplexer4067(2, 3, 4, 5, A9);
Multiplexer4067 mplex2 = Multiplexer4067(2, 3, 4, 5, A8);

/////////////////////////////////////////////
// threads - programa cada atividade do Arduino para acontecer em um determinado tempo
ThreadController cpu; //thread master, onde as outras vao ser adicionadas
Thread threadReadPots; // thread para controlar os pots

/////////////////////////////////////////////

void setup() {

  mplex.begin(); // inicializa o multiplexer

  for (int i = 0; i < NButtons; i++) { // inicializa os botoes como input utilizando o pull up resistor
    pinMode(buttonPin[i], INPUT_PULLUP);
  }

  pinMode(A9, INPUT_PULLUP);

  /////////////////////////////////////////////
  // threads
  threadReadPots.setInterval(10);
  threadReadPots.onRun(readPots);
  cpu.add(&threadReadPots);
  /////////////////////////////////////////////

}

void loop() {

  cpu.run();
  readButtons();

}


/////////////////////////////////////////////
// read buttons

void readButtons() {

  for (int i = 0; i < muxNButtons; i++) { //reads buttons on mux
    int buttonReading = mplex.readChannel(muxButtonPin[i]);
    //buttonCState[i] = map(mplex.readChannel(muxButtonPin[i]), 22, 1023, 0, 2); // stores on buttonCState
    if (buttonReading > 1000) {
      buttonCState[i] = HIGH;
    }
    else {
      buttonCState[i] = LOW;
    }
    //Serial.print(buttonCState[i]); Serial.print("   ");
  }
  //Serial.println();

  for (int i = 0; i < NButtons; i++) { //read buttons on Arduino
    buttonCState[i + muxNButtons] = digitalRead(buttonPin[i]); // stores in the rest of buttonCState
  }

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

    if ((millis() - lastDebounceTime) > debounceDelay) {

      if (buttonCState[i] != buttonPState[i]) {
        lastDebounceTime = millis();

        if (buttonCState[i] == LOW) {
          noteOn(potMidiCh(), note + i, 127);  // Channel 0, middle C, normal velocity
          MidiUSB.flush();
          //MIDI.sendNoteOn(note + i, 127, potMidiCh()); // envia NoteOn(nota, velocity, canal midi)
          //Serial.print("Note: "); Serial.print(note + i); Serial.println(" On");
          buttonPState[i] = buttonCState[i];
        }
        else {
          noteOn(potMidiCh(), note + i, 0);  // Channel 0, middle C, normal velocity
          MidiUSB.flush();
          //MIDI.sendNoteOn(note + i, 0, potMidiCh());
          //Serial.print("Note: "); Serial.print(note + i); Serial.println(" Off");
          buttonPState[i] = buttonCState[i];
        }
      }
    }

  }

}


/////////////////////////////////////////////
//read potentiometers

void readPots() {

  for (int i = 0; i < NPots - 1; i++) { // le todas entradas analogicas utilizadas, menos a dedicada a troca do canal midi
    potCState[i] = mplex.readChannel(muxPotPin[i]);
  }

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

    potVar = abs(potCState[i] - potPState[i]); // calcula a variacao da porta analogica

    if (potVar >= varThreshold) {  //sets a threshold for the variance in the pot state, if it varies more than x it sends the cc message
      pTime[i] = millis(); // armazena o tempo previo
    }
    timer[i] = millis() - pTime[i]; // reseta o timer
    if (timer[i] < TIMEOUT) { // se o timer for menor que o tempo maximo permitido significa que o potenciometro ainda esta se movendo
      potMoving = true;
    }
    else {
      potMoving = false;
    }

    if (potMoving == true) { // se o potenciometro ainda esta se movendo, mande o control change
      int ccValue = map(potCState[i], 22, 1022, 0, 127);
      if (lastCcValue[i] != ccValue) {
        controlChange(11, cc + i, ccValue); // manda control change (channel, CC, value)
        MidiUSB.flush();
        //MIDI.sendControlChange(cc + i, map(potCState[i], 0, 1023, 0, 127), 11); // envia Control Change (numero do CC, valor do CC, canal midi)
        //Serial.print("CC: "); Serial.print(cc + i); Serial.print(" value:"); Serial.println(map(potCState[i], 22, 1023, 0, 127));
        potPState[i] = potCState[i]; // armazena a leitura atual do potenciometro para comparar com a proxima
        lastCcValue[i] = ccValue;
      }
    }
  }

}

/////////////////////////////////////////////
// calculates midi channel based on pot position
int potMidiCh () {
  int potCh =  map(mplex.readChannel(muxPotPin[9]), 22, 1023, 0, 4);

  if (potCh == 4) {
    potCh = 3;
  }
  
  return potCh + midiCh;
}

/////////////////////////////////////////////
// Arduino (pro)micro midi functions Arcore Library
//void noteOn(byte channel, byte pitch, byte velocity) {
//  MIDIEvent noteOn = {0x09, 0x90 | channel, pitch, velocity};
//  MIDIUSB.write(noteOn);
//}
//
//void noteOff(byte channel, byte pitch, byte velocity) {
//  MIDIEvent noteOff = {0x08, 0x80 | channel, pitch, velocity};
//  MIDIUSB.write(noteOff);
//}

/////////////////////////////////////////////
// Arduino (pro)micro midi functions MIDIUSB Library
void noteOn(byte channel, byte pitch, byte velocity) {
  midiEventPacket_t noteOn = {0x09, 0x90 | channel, pitch, velocity};
  MidiUSB.sendMIDI(noteOn);
}

void noteOff(byte channel, byte pitch, byte velocity) {
  midiEventPacket_t noteOff = {0x08, 0x80 | channel, pitch, velocity};
  MidiUSB.sendMIDI(noteOff);
}

void controlChange(byte channel, byte control, byte value) {
  midiEventPacket_t event = {0x0B, 0xB0 | channel, control, value};
  MidiUSB.sendMIDI(event);
}

Fliper_DJ_MidiUsb2.ino (8.17 KB)

Have you done anything with the code? Or are you looking for somebody to provide you with working code for your muxes integrated into the sample midi code?

How is the second multiplexer wired?

Yes, I have write some things in code, I have done what I can do... I'm looking for help, someone that can tell me what is missing.

The second multiplexer is wired just like the first, sharing the ports S0, S1, S2, S3 and with diferent SIG.
12 pontentiometer's and 4 buttons in each one.

Your sketch only has one Multiplexer4067 declared:

Multiplexer4067 mplex = Multiplexer4067(2, 3, 4, 5, A9);

For that you use pins 2, 3, 4, and 5 for address and Pin A9 (a.k.a.D9) for analog input.

To use a second 4067 you will need to declare a second Multiplexer4067 with a different name and using a different analog input pin. I think you can share the address pins since you will only be reading one multiplexer at a time.

Something like this?

Multiplexer4067 mplex = Multiplexer4067(2, 3, 4, 5, A9);
Multiplexer4067 mplex2 = Multiplexer4067(2, 3, 4, 5, A8);

helderjose:
Something like this?

Multiplexer4067 mplex = Multiplexer4067(2, 3, 4, 5, A9);

Multiplexer4067 mplex2 = Multiplexer4067(2, 3, 4, 5, A8);

Yes. That would work.