Arduino e cd74hc4067

Ciao a tutti, vorrei esporvi il mio problema.
Sto usando il cd74hc4067 come demux per avere 16 pulsanti che poi verranno letti dal mio arduino mega, e fin qui ci siamo... il problema sorge quando ne devo mettere piu di uno in parallelo... non trovo nulla su internet e non trovo una soluzione, perfavore aiutatemi.
Lascio tutto qui sotto, grazie in anticipo.



//Per fare un multiMux in teoria basta copiare e usare multiplexer2[16][4] e sig2
//funziona ancche con 2 mux
const int sig1 = 6;
const int sig2 = 7;

const int controlPin[4] = {2,3, 4, 5};

const int multiplexer[16][4] = { {0,0,0,0}, //canale 0
                           {0,0,0,1}, //canale 1
                           {0,0,1,0}, //canale 2
                           {0,0,1,1}, //canale 3
                           {0,1,0,0}, //canale 4
                           {0,1,0,1}, //canale 5
                           {0,1,1,0}, //canale 6
                           {0,1,1,1}, //canale 7
                           {1,0,0,0}, //canale 8
                           {1,0,0,1}, //canale 9
                           {1,0,1,0}, //canale 10
                           {1,0,1,1}, //canale 11
                           {1,1,0,0}, //canale 12
                           {1,1,0,1}, //canale 13
                           {1,1,1,0}, //canale 14
                           {1,1,1,1}  //canale 15
                         };
                         
const int multiplexer2[16][4] = { {0,0,0,0}, //canale 0
                           {0,0,0,1}, //canale 1
                           {0,0,1,0}, //canale 2
                           {0,0,1,1}, //canale 3
                           {0,1,0,0}, //canale 4
                           {0,1,0,1}, //canale 5
                           {0,1,1,0}, //canale 6
                           {0,1,1,1}, //canale 7
                           {1,0,0,0}, //canale 8
                           {1,0,0,1}, //canale 9
                           {1,0,1,0}, //canale 10
                           {1,0,1,1}, //canale 11
                           {1,1,0,0}, //canale 12
                           {1,1,0,1}, //canale 13
                           {1,1,1,0}, //canale 14
                           {1,1,1,1}  //canale 15
                         };                         



void setup() {
  
 for(int i=0; i<4; i++)
  {
    pinMode(controlPin[i], OUTPUT);// set pin as output
    digitalWrite(controlPin[i], HIGH); // set initial state as HIGH 
 }

  pinMode(sig1, INPUT_PULLUP);// set SIG pin as output
  digitalWrite(sig1, HIGH);//lo metto high per i button in pullup

pinMode(sig2, INPUT_PULLUP);// set SIG pin as output
digitalWrite(sig2, HIGH);//lo metto high per i button in pullup

  
  Serial.begin(9600);

}

void loop() {
  //MUX1
   for(int i=0; i<16; i++){
        interfaccia(i);
        digitalRead(i);
        digitalRead(sig1);
                
        //Serial.println(digitalRead(sig1));
        
        //FUNZIONA
        if (digitalRead(sig1) == LOW){ 
        switch (i) {
    case 0:
      Command0Mux1();
      break;
    case 1:
      Command1Mux1();
      break;
    case 2:
      Command2Mux1();    
      break;
    case 3:
      Command3Mux1();
      break;
    case 4:
      Command4Mux1();
      break;
    case 5:
      Command5Mux1();
      break;
    case 6:
      Command6Mux1();
      break;  
    case 7:
      Command7Mux1();    
      break;
    case 8:
      Command8Mux1();
      break;
    case 9:
      Command9Mux1();
      break;
    case 10:
      Command10Mux1();    
      break;
    case 11:
      Command11Mux1();
      break;
    case 12:
      Command12Mux1();
      break;   
    case 13:
      Command13Mux1();
      break; 
    case 14:
      Command14Mux1(); 
      break;
    case 15:
      Command15Mux1();
      break;

    default:
      break;
  }
  }
  }
 //DA FARE LE FUNZIONI Command1Mux2();
//MUX2  
for(int i=0; i<16; i++){
        interfaccia2(i);
        digitalRead(i);
        digitalRead(sig2);
                
        //Serial.println(digitalRead(sig2));
        
        //FUNZIONA
        if (digitalRead(sig2) == LOW){ 
        switch (i) {
    case 0:
      Command0Mux2();
      break;
    case 1:
      Command1Mux2();
      break;
    case 2:
      Command2Mux2();    
      break;
    case 3:
      Command3Mux2();
      break;
    case 4:
      Command4Mux2();
      break;
    case 5:
      Command5Mux2();
      break;
    case 6:
      Command6Mux2();
      break;  
    case 7:
      Command7Mux2();    
      break;
    case 8:
      Command8Mux2();
      break;
    case 9:
      Command9Mux2();
      break;
    case 10:
      Command10Mux2();    
      break;
    case 11:
      Command11Mux2();
      break;
    case 12:
      Command12Mux2();
      break;   
    case 13:
      Command13Mux2();
      break; 
    case 14:
      Command14Mux2(); 
      break;
    case 15:
      Command15Mux2();
      break;

    default:
      break;
  }
  }
  }

}



void interfaccia (int canale) {
    digitalWrite(controlPin[0], multiplexer[canale][0]);
    digitalWrite(controlPin[1], multiplexer[canale][1]);
    digitalWrite(controlPin[2], multiplexer[canale][2]);
    digitalWrite(controlPin[3], multiplexer[canale][3]);

     
      /* Serial.print(canale);
       Serial.print (": ");
       Serial.print(multiplexer[canale][3]);
       Serial.print(multiplexer[canale][2]);
       Serial.print(multiplexer[canale][1]);
       Serial.println(multiplexer[canale][0]); 

       
       delay(500);*/
}


void interfaccia2 (int canale) {
    digitalWrite(controlPin[0], multiplexer[canale][0]);
    digitalWrite(controlPin[1], multiplexer[canale][1]);
    digitalWrite(controlPin[2], multiplexer[canale][2]);
    digitalWrite(controlPin[3], multiplexer[canale][3]);

     
      /* Serial.print(canale);
       Serial.print (": ");
       Serial.print(multiplexer[canale][3]);
       Serial.print(multiplexer[canale][2]);
       Serial.print(multiplexer[canale][1]);
       Serial.println(multiplexer[canale][0]); 

       
       //delay(500);*/
}






void Command0Mux1() {
  Serial.println("Command 1 funziona?");

}

void Command1Mux1() {
  Serial.println("Command 2 funziona?");

}
void Command2Mux1() {
  Serial.println("Command 3 funziona?");

}
void Command3Mux1() {
  Serial.println("Command 4 funziona?");

}

void Command4Mux1() {
  Serial.println("Command 5 funziona?");

}

void Command5Mux1() {
  Serial.println("Command 6 funziona?");

}

void Command6Mux1() {
  Serial.println("Command 7 funziona?");

}

void Command7Mux1() {
  Serial.println("Command 8 funziona?");

}

void Command8Mux1() {
  Serial.println("Command 9 funziona?");

}

void Command9Mux1() {
  Serial.println("Command 10 funziona?");

}

void Command10Mux1() {
  Serial.println("Command 11 funziona?");

}

void Command11Mux1() {
  Serial.println("Command 12 funziona?");

}

void Command12Mux1() {
  Serial.println("Command 13 funziona?");

    }

void Command13Mux1() {
  Serial.println("Command 14 funziona?");

}

void Command14Mux1() {
  Serial.println("Command 15 funziona?");

}

void Command15Mux1() {
  Serial.println("Command 16 funziona?");
}

void Command0Mux2() {
  Serial.println("Command 1 funziona?");

}

void Command1Mux2() {
  Serial.println("Command 2 funziona?");

}
void Command2Mux2() {
  Serial.println("Command 3 funziona?");

}
void Command3Mux2() {
  Serial.println("Command 4 funziona?");

}

void Command4Mux2() {
  Serial.println("Command 5 funziona?");

}

void Command5Mux2() {
  Serial.println("Command 6 funziona?");

}

void Command6Mux2() {
  Serial.println("Command 7 funziona?");

}

void Command7Mux2() {
  Serial.println("Command 8 funziona?");

}

void Command8Mux2() {
  Serial.println("Command 9 funziona?");

}

void Command9Mux2() {
  Serial.println("Command 10 funziona?");

}

void Command10Mux2() {
  Serial.println("Command 11 funziona?");

}

void Command11Mux2() {
  Serial.println("Command 12 funziona?");

}

void Command12Mux2() {
  Serial.println("Command 13 funziona?");

    }

void Command13Mux2() {
  Serial.println("Command 14 funziona?");

}

void Command14Mux2() {
  Serial.println("Command 15 funziona?");

}

void Command15Mux2() {
  Serial.println("Command 16 funziona?");
}


Credo che tu stia facendo un po' di confusione. Non ti serve duplicare la "tabella" dei pin per ogni multiplexer che usi in quando li hai collegati (giustamente) tutti ai medesimi pin.
Quello che cambia è il pin di lettura del segnale che devi cambiare in base al multiplexer che vuoi leggere.
Ovvero se vuoi leggere il segnale dal pin 3 di un qualsiasi multiplexer devi impostare i vari enable (Es. 0011) e poi leggere il pin corrispondente del multiplexer che ti interessa, in base al tuo codice pin 6 per il primo, 7 per il secondo e così via.
Altra cosa quando imposti il pin come INPUT_PULLUP non serve la succesiva digitalwrite, serviva un tempo quando non era previsto il parametro INPUT_PULLUP.
Puoi anche pensare di mettere in un array i pin dei segnali dei multiplexer in modo da poterli leggere in modo che potrai usare un ciclo per impostare tutte le porte in modo più agevole.
Inoltre grazie all'array potrai anche leggere la porta giusta usando la matematica (da 0 a 15 primo elemento, da 16 a 31 secondo ecc.)

Grazie mille della risposta.

Quello che cambia è il pin di lettura del segnale che devi cambiare in base al multiplexer che vuoi leggere.

Intendi quello che io chiamo "Sig" giusto?
in tal caso in teoria lo sto gia facendo, no?

Quello che cambia è il pin di lettura del segnale che devi cambiare in base al multiplexer che vuoi leggere.
Ovvero se vuoi leggere il segnale dal pin 3 di un qualsiasi multiplexer devi impostare i vari enable (Es. 0011) e poi leggere il pin corrispondente del multiplexer che ti interessa, in base al tuo codice pin 6 per il primo, 7 per il secondo e così via.

Cosa intendi con "devi impostare i vari enable" in che senso? io so che gli enable servono a "accendere" o "spegnere" l'integrato con 5v o 0 v

Se non vedo male, quelle schedine hanno un pin EN (enable) che è stato connesso fisso a LOW ...
... se invece, usi gli stessi pin per gli indirizzi ed un solo pin come ingresso di Arduino, poi selezionando con il pin EN quale schedina vuoi usare, abiliti solo quella e le altre restano disabilitate.

Guglielmo

Non andrebbe bene per la mia situazione, perche io ho la necessità di leggere ogni pulsante e mandare un comando diverso per ognuno di esso.
Quindi ho bisogno di leggere contemporaneamente tutti i multiplexer e poi agire in base a quale Out e di quale multiplexer viene letto come HIGH (perche sono in pullup).
Spero di essere stato chiaro.
Grazie mille.

Si lo stai facendo di impostare N pin per ogni Sig ma stai duplicando inutilmente la matrice che ti permette di decidere qauale pin leggere tramite i S0,S1,S2,S3 e questo non serve.
Come ti ha spiegato anche Guglielmo puoi decidere di usare (come fai ora) N pin per leggere i vari multiplexer oppure usare un solo ingresso per leggere il segnale (Sig) e N pin per pilotare i vari pin Enable che ora hai messo fisso a LOW e quindi sempre tutti attivi i multiplexer.

Non andrebbe bene per la mia situazione, perche io ho la necessità di leggere ogni pulsante e mandare un comando diverso per ognuno di esso.
Quindi ho bisogno di leggere contemporaneamente tutti i multiplexer e poi agire in base a quale Out e di quale multiplexer viene letto come HIGH (perche sono in pullup).
Spero di essere stato chiaro.
Grazie mille.

Non molto... anche se sono tutti attivi per sapere quale multiplexer ha il segnale a LOW devi leggere le porte ad una ad una, a questo punto leggere N porte o leggerne una attivando di volta in volta i vari enable non ti cambia assolutamente nulla.
In ogni caso se a te torna meglio non sussistono problemi a mantenere tutti gli EN a LOW fisso e leggere le N porte per capire cosa è stato premuto e dove

Provo a spiegarmi meglio, ho dei pulsanti attaccati a questi multiplexer, che quando vengono cliccati mandano un comando, ad esempio "scrivi 1-2-3" etcc quindi ho la necessità di avere tutti i mux attivi cosi da sapere quando e quale pulsante e' stato premuto, cosi da mandare questo fantomatico comando.
Quindi non posso attivare un mux alla volta, perche ho bisogno che mi legga lo stato di tutti i pulsanti in ogni momento, cosi che, quando premo uno dei tot pulsanti lo legge e manda il relativo comando.
Se facessi come dite voi non potrei fare questa cosa qui, perche dovrei attivarne uno per poi leggerlo e poi spengerlo e attivarne un altro per poi leggerlo e poi spengerlo e cosi via.
Sempre Grazie della vostra disponibilità.

Allora, Arduino ha porte ad 8bit quindi COMUNQUE tu più di una porta alla volta NON puoi leggere quindi ... dimentica il termine contemporaneamente, con più di 8 pin, perché NON esiste.

Nel caso migliore puoi leggere al massimo 8 bit in un colpo (se l'hardware è configurato come si deve e i pin sono tutti messi sui bit di una singola porta). Se devi leggere più di 8 pin devi fare letture consecutive,

In reltà si fa benissimo come ti stiamo dicendo ... la velocità di scansione dei mux deve essere elevata così si ha l'IMPRESSIONE di leggere tutto assieme, in realtà si legge sempre in sequenza.

Guglielmo

  1. A che serve quella digitalRead(i); e digitalRead(sig2); piazzata nel for ??
  2. crea un array ANCHE per i pin sig, inutile avere array per i vari pin e poi ti fai sig1,sig2, etc.
    con due cicli for fai tutto. Un ciclo for mux=0 to 6 e poi dentro un for can=0 to 15
  3. vedi la tua funzione "interfaccia" e "interfaccia2" cosa cambia ? Nulla. Quindi non serve e non serve un altro array multiplexer2 (sempre 16 valori da 0000 a 1111 sono)
  4. ma perchè tutte quelle Command10Mux1(); ?? Devi fare cose molto diverse dentro a quelle funzioni ??
    fanne una passando piuttosto 2 parametri: CommandMux(10,1); o anche CommandMux(can,mux); // variabili dei 2 cicli for
#define NUM_MUX 7
byte sig[NUM_MUX] = {6,7,8,9,10,11,12};    // basta byte inutile int !!
...
for(byte mux=0; mux<NUM_MUX; mux++)
{ for(byte can=0; can<16; can++)
  { interfaccia(can);              // digitalRead(can); a che caspita serve ??
    byte val=digitalRead(sig[mux]);
    if (val == LOW)
    { CommandMux(can,mux);
    }
  }
}
...
void CommandMux(byte p_can, byte p_mux)
{ Serial.print("mux:");   Serial.print(p_mux);
  Serial.print("  can:"); Serial.println(p_can);
}

Ma per lo OP

Non ti è chiaro che è inutile cercare la contemporaneità assoluta degli input

Quando le funzioni eseguite sono bloccanti?

Tutto quel tuo lungo e complicato programma si riduce a un for' una decodifica degli indirizzi e un array di puntatori a funzione...

Per leggere lo stato di i ahhaha, mi serviva per leggere i in quel caso ovvero il sig1 cosi che quando diventava low entrava nel if e poi nello switch case.

ok ora vedo come posso migliorarlo

Lo miglioro grazie

Ad ogni command dovrò mandare una nota midi differente, credo vada bene anche come l'hai fatta tu

Beh

Mettiamo un po' di prescrizioni

Quanti pulsanti?
E vedo dei potenziometri, quanti canali analogici?

Ciao a tutti, e' da mesi che sto progettando questa console che manda segnali midi (per comunicare con questo protocollo con altre macchine, software etc..) con 130 pulsanti (di cui 24 indipendenti, ovvero che collego senza Multiplexer cosi da poterli cliccare insieme) 11 fader e 4 encoder.

Per il tutto ho ovviamente optato per arduino mega (atmega16u2 cosi da renderlo input midi a lavoro finito) , con 7 Multiplexer CD74HC4067 per i pulsanti che citavo prima, 11 potenziometri fader 10k SC6080GH e 4 encoder EC11.

NO, il tuo codice è scritto così:
digitalRead(sig1); <--- NON serve a nulla
//Serial.println(digitalRead(sig1));
//FUNZIONA
if (digitalRead(sig1) == LOW){ <--- solo qui legge ed è utile

Comunque ti ho scritto parte del codice sopra

Lo so ma non sono troppo abile nella programmazione, lo faccio a livello hobbystico e questo e' il mio primo vero lavoro, di progettazione fisica, hardware e software.
Vi sono infinitamente grato dei consigli che mi state dando veramente.

Si, piu tardi mi metto a rifare tutto il codice come si deve.
Grazie millee

Di nulla.
Quando vedi nel tuo codice robba del tipo:
case 0: Command0Mux1(); break;
case 1: Command1Mux1(); break;
....
case 1: Command0Mux0(); break;
etc.
Devi avere subito il sospetto che poi fare una unica funzione con uno o due parametri parametri

Non so per il midi, standard che non conosco

Ma per gli input te la cavi con una UNO

Qualche multiplexer in cascata

Due differenti canali di multiplexer uno per digitali e uno per analogico
8 pin
Altri 8 per gli encoder
1 analogico
2 per la seriale

Avanzi un pin
Cosa ci vuoi fare?