Teensy LC and 74HC4067 16 channel multiplexer wiring

megant

Member
Hey Teensinians!

Currently I develop a 64 knob MIDI controller, which worked fine with an Arduino Uno R3, but I decided to change the basic board to Teensy LC because of the hybrid MIDI and serial mode USB (debugging of hacked firmware on R3 was a terrible nightmare). My only problem is I don't know exactly the correct wiring between Teensy LC and a 74HC4067E (I have four of them). Somewhere I found a diagram:

https://forum.pjrc.com/attachment.php?attachmentid=11610&d=1506315763

but it's about Teensy and CD74HC4051 breakout board which is a bit different animal. I need some instruction. ;)

Thanx
 
That diagram looks fine.

The 74HC4051 works the same way, except it is only 8 signals instead of 16, and it takes only 3 wires to control instead of 4.

There are many possible ways to use 8 of these to get 64 inputs. But the simplest way is to use 8 of the analog input pins on Teensy, where the output of each 74HC4051 connects to a different analog input pin. The 3 control signals are connected to the same pins on all 8 of the 74HC4051.

You can find a diagram on the MIDI page. Scroll down to "Connecting Many Buttons & Knobs/Sliders".

https://www.pjrc.com/teensy/td_midi.html
 
That diagram looks fine.

The 74HC4051 works the same way, except it is only 8 signals instead of 16, and it takes only 3 wires to control instead of 4.

There are many possible ways to use 8 of these to get 64 inputs. But the simplest way is to use 8 of the analog input pins on Teensy, where the output of each 74HC4051 connects to a different analog input pin. The 3 control signals are connected to the same pins on all 8 of the 74HC4051.

You can find a diagram on the MIDI page. Scroll down to "Connecting Many Buttons & Knobs/Sliders".

https://www.pjrc.com/teensy/td_midi.html

Yes, but I'd like to use my existing 74HC4067-s. My problem is that on my quoted diagram S0, S1, S2 and S3 is connected to Teensy's 0, 1, 2, 3 but when I checked the paper which has been sent with Teensy LC, I realized PIN 2 is not a serial port, but simply a digital pin. What should I do? ;)
 
These are just ditgitalRead pins controlling the mux directly.... there is no serial in that diagram because the mux doesn't use serial.

The author misidentified the part in the thread you got that from 4051 is an eight channel MUX.

(https://forum.pjrc.com/threads/46571-Teensy-LC-CD74HC4051-multiplex-Midi-problem)

I tried this code to test 16 pots.

Code:
// ******CONSTANT VALUES******** 
// customize code behaviour here!
const int muxTimeMin = 100; // minimum micro-seconds between MUX reads
const int channel = 1; // MIDI channel
const int A_PINS = 16; // number of Analog PINS (these are now MUX pins)
const int D_PINS = 3; // number of Digital PINS
const int ON_VELOCITY = 99; // note-one velocity sent from buttons (should be 65 to  127)

// define the CC ID numbers on which to send them..
const int CCID[A_PINS] = {21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36}; // set your own CC values for the 16 MUX pins

const int dbt = 8; // a threshold value for how big the dead-band is before recalc

//******VARIABLES***********
//mapping of mux to teensy digital pins
int pin_Out_S0 = 0;
int pin_Out_S1 = 1;
int pin_Out_S2 = 2;
int pin_Out_S3 = 3;
int pin_In_Mux1 = A0;
//the state of the mux channels(initialized to zero)
int Mux1_State[16] = {0};
int Mux1_State_Lagged[16] = {0};
//elapsedMicros mux1Updated;
elapsedMillis mux1Updated; // switch to millis to troubleshoot 
byte i = 0; // index for mux loop
// a data array and a lagged copy to tell when MIDI changes are required
byte data[A_PINS];
byte dataLag[A_PINS]; // when lag and new are not the same then update MIDI CC value


void setup(){}//need this even if you don't use it

//************LOOP**************
void loop() {
  getMUX1Data();
  // other work here... mux is called once in each loop rather than updating all in every loop
  while (usbMIDI.read()) {
     // controllers must call .read() to keep the queue clear even if they are not responding to MIDI
  }
}


//************MUX1 SECTION**************
void getMUX1Data(){  
  if (mux1Updated>muxTimeMin) {

     Mux1_State[i] = analogRead(pin_In_Mux1);

     Serial.println(i, DEC);
     Serial.println(Mux1_State[i]); 
     Serial.println(Mux1_State_Lagged[i]);
     Serial.println(dbt);
     Serial.println("--------");

    if(abs(Mux1_State[i] - Mux1_State_Lagged[i]) > dbt ) {
      Mux1_State_Lagged[i] = Mux1_State[i];
      data[i] = Mux1_State[i]>>3;
      if (data[i] != dataLag[i]){ 
        dataLag[i] = data[i];
        usbMIDI.sendControlChange(CCID[i], data[i], channel);
//
//        Serial.print("MUX_PIN: ");
//        Serial.print(i,DEC); 
//        Serial.print(" CC: ");
//        Serial.print(CCID[i],DEC); 
//        Serial.print(" DATA HEX: ");
//        Serial.println(data[i],HEX); 
      }
    }
    // set mux control pins for next pass
    digitalWrite(pin_Out_S0, HIGH && (i & B00000001));
    digitalWrite(pin_Out_S1, HIGH && (i & B00000010));
    digitalWrite(pin_Out_S2, HIGH && (i & B00000100));
    digitalWrite(pin_Out_S3, HIGH && (i & B00001000));
    
    //reset timer
    mux1Updated = 0; 
    //increment index
    i++;
    if (i>15)   {i=0;}
    
  }
}

It works weird. I built 16 pots with one 74HC4067E and Teensy LC for testing purposes. When I turn 1st pot, it works well, but nothing happens when I try the same with the rest.
 
Now, I solved it by rewriting everything from scratch.

Code:
int s0 = 0;
int s1 = 1;
int s2 = 2;
int s3 = 3;

//Mux in “SIG” pin
int SIG_pin = A0;
int lastPotValues[16] = {0};
int stepNum = 8;
int value = 0;
int midi_value = 0;

int controlPin[4] = {s0, s1, s2, s3}; 
int muxChannel[16][4] = { {0,0,0,0}, //channel 0 
                          {1,0,0,0}, //channel 1 
                          {0,1,0,0}, //channel 2 
                          {1,1,0,0}, //channel 3 
                          {0,0,1,0}, //channel 4 
                          {1,0,1,0}, //channel 5 
                          {0,1,1,0}, //channel 6 
                          {1,1,1,0}, //channel 7 
                          {0,0,0,1}, //channel 8 
                          {1,0,0,1}, //channel 9 
                          {0,1,0,1}, //channel 10 
                          {1,1,0,1}, //channel 11 
                          {0,0,1,1}, //channel 12 
                          {1,0,1,1}, //channel 13 
                          {0,1,1,1}, //channel 14 
                          {1,1,1,1} //channel 15 
                          };
int midiControlData[16] = {20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35};                          

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

  digitalWrite(s0, LOW);
  digitalWrite(s1, LOW);
  digitalWrite(s2, LOW);
  digitalWrite(s3, LOW);

  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 ++) {
    if (abs(readMux(i) - lastPotValues[i]) > stepNum) {
      value = readMux(i);
      midi_value = round(value / stepNum);
      
      Serial.print("Value at channel ");
      Serial.print(i);
      Serial.print(" is : ");
      Serial.println(midi_value);
      sendMidiData(i, midi_value);
      lastPotValues[i] = readMux(i);
    }
  }

  while (usbMIDI.read()) {
    // ignore incoming messages
  }
} 

int readMux(int channel) {
   //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 = analogRead(SIG_pin); //return the value 
  return val;
}

void sendMidiData(int muxChannel, int midi_value) {
  usbMIDI.sendControlChange(midiControlData[muxChannel], midi_value, 1);
}
 
Nice that you were able to write your own.

FYI you've used my code from that thread before I got the mux myself to test... I forgot to set up the control pins as outputs so the mux is frozen on 0.

The working version is here https://forum.pjrc.com/threads/4657...x-Midi-problem?p=155027&viewfull=1#post155027

Maybe you're the man who knows the answer. I built up 64 pots with 4 74HC4067. I works, but.... there is a very interesting phenomenon. The pots connected (thru multiplexer) to A0 and A1 has the range from ~128 to 1008, but A2 and A3 has from ~240 to ~880. Is it official or just accidental?
 
That's not good... I've not studied your code but perhaps there isn't sufficient time between setting the control pins for the MUX and the read command.

There's no reason it shouldn't have full range if you had it before the MUX version.

You could try my code and see if you're seeing anything like it (the version where I enabled the output pins).
 
That's not good... I've not studied your code but perhaps there isn't sufficient time between setting the control pins for the MUX and the read command.

There's no reason it shouldn't have full range if you had it before the MUX version.

You could try my code and see if you're seeing anything like it (the version where I enabled the output pins).

Well, your code handles 16 pots and my 16 pots version also worked correctly. I think my problem must be some voltage issue. Here is the 64 pots version:

Code:
int s0 = 0;
int s1 = 1;
int s2 = 2;
int s3 = 3;

//Mux in “SIG” pin
int lastPotValues[64] = {0};
int stepNum = 8;

int controlPin[4] = {s0, s1, s2, s3};
int muxChannel[16][4] = { {0, 0, 0, 0}, //channel 0
  {1, 0, 0, 0}, //channel 1
  {0, 1, 0, 0}, //channel 2
  {1, 1, 0, 0}, //channel 3
  {0, 0, 1, 0}, //channel 4
  {1, 0, 1, 0}, //channel 5
  {0, 1, 1, 0}, //channel 6
  {1, 1, 1, 0}, //channel 7
  {0, 0, 0, 1}, //channel 8
  {1, 0, 0, 1}, //channel 9
  {0, 1, 0, 1}, //channel 10
  {1, 1, 0, 1}, //channel 11
  {0, 0, 1, 1}, //channel 12
  {1, 0, 1, 1}, //channel 13
  {0, 1, 1, 1}, //channel 14
  {1, 1, 1, 1} //channel 15
};
int midiControlData[64] = {20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35,
                           40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55,
                           60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75,
                           80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95
                          };

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

  digitalWrite(s0, LOW);
  digitalWrite(s1, LOW);
  digitalWrite(s2, LOW);
  digitalWrite(s3, LOW);
  Serial.begin(9600);
}

void loop() {

  //Loop through and read all 16 values
  //Reports back Value at channel 6 is: 346
  for (int muxInput = 0; muxInput < 4; muxInput++) {
    for (int muxChn = 0; muxChn < 16; muxChn++) {

      int value = readMux(muxInput, muxChn);
      int ccIndex = muxInput * 16 + muxChn;
      
      if (abs(value - lastPotValues[ccIndex]) > stepNum) {
        int midiValue = round(value / stepNum);

        Serial.print("Value at channel ");
        Serial.print(ccIndex + 1);
        Serial.print(" is : ");
        Serial.println(value);
        sendMidiData(ccIndex, midiValue);
        lastPotValues[ccIndex] = value;
      }
    }
  }


  while (usbMIDI.read()) {
    // ignore incoming messages
  }
}

int readMux(int muxInput, int muxChn) {
  //loop through the 4 sig
  for (int i = 0; i < 4; i ++) {
    digitalWrite(controlPin[i], muxChannel[muxChn][i]);
  }

  int val = analogRead(A0 + muxInput);
  return val;
}

void sendMidiData(int ccIndex, int midiValue) {
  usbMIDI.sendControlChange(midiControlData[ccIndex], midiValue, 1);
}
 
If the muxInput loop is in the interior the muxes won't have to switch as much.

If you set the mux controls right after a read for the next setting the mux has time to switch while your code is busy setting up for the next pass.

Reading too soon after the mux is changed is very likely the issue.
 
Last edited:
If the muxInput loop is in the interior the muxes won't have to switch as much.

If you set the mux controls right after a read for the next setting the mux has time to switch while your code is busy setting up for the next pass.

Reading too soon after the mux is changed is very likely the issue.

Well I made this modification, but the effect is the same. I think it is nothing to do with the position of mux channel setting.

Code:
int s0 = 0;
int s1 = 1;
int s2 = 2;
int s3 = 3;

//Mux in “SIG” pin
int lastPotValues[64] = {0};
int stepNum = 8;

int controlPin[4] = {s0, s1, s2, s3};
int muxChannel[16][4] = { {0, 0, 0, 0}, //channel 0
  {1, 0, 0, 0}, //channel 1
  {0, 1, 0, 0}, //channel 2
  {1, 1, 0, 0}, //channel 3
  {0, 0, 1, 0}, //channel 4
  {1, 0, 1, 0}, //channel 5
  {0, 1, 1, 0}, //channel 6
  {1, 1, 1, 0}, //channel 7
  {0, 0, 0, 1}, //channel 8
  {1, 0, 0, 1}, //channel 9
  {0, 1, 0, 1}, //channel 10
  {1, 1, 0, 1}, //channel 11
  {0, 0, 1, 1}, //channel 12
  {1, 0, 1, 1}, //channel 13
  {0, 1, 1, 1}, //channel 14
  {1, 1, 1, 1} //channel 15
};
int midiControlData[64] = {20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35,
                           40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55,
                           60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75,
                           80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95
                          };

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

  digitalWrite(s0, LOW);
  digitalWrite(s1, LOW);
  digitalWrite(s2, LOW);
  digitalWrite(s3, LOW);
  Serial.begin(9600);
}

void loop() {

  //Loop through and read all 16 values
  //Reports back Value at channel 6 is: 346
  for (int muxInput = 0; muxInput < 4; muxInput++) {
    for (int muxChn = 0; muxChn < 16; muxChn++) {

      int value = readMux(muxInput);
[COLOR="#FF0000"]      setMuxControl(muxChn + 1);[/COLOR]
      int ccIndex = muxInput * 16 + muxChn;

      Serial.println(value);
      
      if (abs(value - lastPotValues[ccIndex]) > stepNum) {
        int midiValue = round(value / stepNum);

        Serial.print("Value at channel ");
        Serial.print(ccIndex + 1);
        Serial.print(" is : ");
        Serial.println(value);
        sendMidiData(ccIndex, midiValue);
        lastPotValues[ccIndex] = value;
      }
    }
  }


  while (usbMIDI.read()) {
    // ignore incoming messages
  }
}

void setMuxControl(int muxChn) {
  //loop through the 4 sig
  for (int i = 0; i < 4; i ++) {
    digitalWrite(controlPin[i], muxChannel[muxChn][i]);
  }
}

int readMux(int muxInput) {
  int val = analogRead(A0 + muxInput);
  return val;
}

void sendMidiData(int ccIndex, int midiValue) {
  usbMIDI.sendControlChange(midiControlData[ccIndex], midiValue, 1);
}
 
This is a fixed version of the previous code:

Code:
int s0 = 0;
int s1 = 1;
int s2 = 2;
int s3 = 3;

//Mux in “SIG” pin
int lastPotValues[64] = {0};
int stepNum = 8;

int controlPin[4] = {s0, s1, s2, s3};
int muxChannel[16][4] = { {0, 0, 0, 0}, //channel 0
  {1, 0, 0, 0}, //channel 1
  {0, 1, 0, 0}, //channel 2
  {1, 1, 0, 0}, //channel 3
  {0, 0, 1, 0}, //channel 4
  {1, 0, 1, 0}, //channel 5
  {0, 1, 1, 0}, //channel 6
  {1, 1, 1, 0}, //channel 7
  {0, 0, 0, 1}, //channel 8
  {1, 0, 0, 1}, //channel 9
  {0, 1, 0, 1}, //channel 10
  {1, 1, 0, 1}, //channel 11
  {0, 0, 1, 1}, //channel 12
  {1, 0, 1, 1}, //channel 13
  {0, 1, 1, 1}, //channel 14
  {1, 1, 1, 1} //channel 15
};
int midiControlData[64] = {20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35,
                           40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55,
                           60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75,
                           80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95
                          };

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

  digitalWrite(s0, LOW);
  digitalWrite(s1, LOW);
  digitalWrite(s2, LOW);
  digitalWrite(s3, LOW);
  Serial.begin(9600);
}

void loop() {

  //Loop through and read all 16 values
  //Reports back Value at channel 6 is: 346
  for (byte muxInput = 0; muxInput < 4; muxInput++) {
    for (int muxChn = 0; muxChn < 16; muxChn++) {

     [COLOR="#FF0000"] int nextMuxChn = (muxChn < 15) ? muxChn + 1 : 0;[/COLOR]
      int value = readMux(muxInput, nextMuxChn);
      int ccIndex = muxInput * 16 + muxChn;
      
      if (abs(value - lastPotValues[ccIndex]) > stepNum) {
        int midiValue = round(value / stepNum);

        Serial.print("Value at channel ");
        Serial.print(ccIndex + 1);
        Serial.print(" is : ");
        Serial.println(value);
        sendMidiData(ccIndex, midiValue);
        lastPotValues[ccIndex] = value;
      }
    }
  }


  while (usbMIDI.read()) {
    // ignore incoming messages
  }
}

void setMuxControl(int muxChn) {
  //loop through the 4 sig
  for (int i = 0; i < 4; i ++) {
    digitalWrite(controlPin[i], muxChannel[muxChn][i]);
  }
}

int readMux(byte muxInput, int nextMuxChn) {
  int val = analogRead(A0 + muxInput);
[COLOR="#FF0000"]  setMuxControl(nextMuxChn);[/COLOR]
  return val;
}

void sendMidiData(int ccIndex, int midiValue) {
  usbMIDI.sendControlChange(midiControlData[ccIndex], midiValue, 1);
}
 
I'm sure that it's not about time, but voltage. I have 9 breadboards and tons of wires. Some of them are shorter, some of them are much longer (depends on the distance from teensy lc). Maybe when I built it with Arduino Uno R3 before, 5v was enough to tolerate the wire jungle, but 3.3v isn't.
 
It is about voltage...
My theory was the voltage is still stabilizing at the Teensy pin when read samples it.

If you slow the code down with a delay after write and before read this should eliminate this and if the readings are still wonky then it's not the primary cause.

If you're correct reading voltages with a multi meter between wipers and ground should confirm.
 
...If you're correct reading voltages with a multi meter between wipers and ground should confirm.
...or try a test program that only reads one pot and writes the raw value to serial monitor... if it's electrical the readings should still have limited range.
 
Here's my code extended to multiple MUX (which I don't have!) in case you want to try it.
Code:
// ******CONSTANT VALUES******** 
// customize code behaviour here!
const int muxTimeMin = 25;        // minimum micro-seconds between MUX reads - higher values should be more stable but less responsive
const int channel = 1;            // MIDI channel
const int M_PINS = 16;            // number of MUX PINS 
const int MUX_COUNT = 4;          // number of MUX  
const int D_PINS = 3;             // number of Digital PINS
const int ON_VELOCITY = 99;       // note-one velocity sent from buttons (should be 65 to  127)
const int SO_PINS[4] = {0,1,2,3}; //array size is (M_PINS)^-2
const int MUX_READ[MUX_COUNT] = {A0,A1,A2,A3};        // Pins to SIGNAL on MUX - I only have one MUX to test so I ran all to A0 for testing

// define the CC ID numbers on which to send them: number of MUX by number of MUX channels
const int CCID[MUX_COUNT][M_PINS] = {{21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36},
                            {37,38,39,34,41,42,43,44,45,46,47,48,49,50,51,52},
                            {53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68},
                            {69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84}}; // set your own CC values for the 4x16 MUX pins

const int dbt = 8; // a threshold value for how big the dead-band is before recalc - set higher to minimize excess MIDI if inputs are noisy

//******VARIABLES***********
//the read values of the mux channels and their lagged readings (difference triggers updating MIDI values)
int Mux_Reading[MUX_COUNT][M_PINS] = {0};
int Mux_Reading_Lagged[MUX_COUNT][M_PINS] = {0};
elapsedMicros muxUpdated; // timer counter (micros) 


byte j = 0; // index for mux chanel select loop - needs to be global 
// THIS IS KEY! - 'j' is not used in a 'for' statement but is incremented with each main loop call


//********SETUP**********
void setup() {
  //set SO pins for MUX control as output
  for (int i = 0; i<MUX_COUNT; i++){
    pinMode(SO_PINS[i], OUTPUT); 
  } 
}

//************LOOP**************
void loop() {
  getMUXData();
  // other work here... mux are called once in each loop rather than updating all in every loop
  while (usbMIDI.read()) {
     // controllers must call .read() to keep the queue clear even if they are not responding to MIDI
  }
}


//************MUX SECTION**************
void getMUXData(){  
  if (muxUpdated>muxTimeMin) {
  for (int i = 0; i<MUX_COUNT; i++){
    Mux_Reading[i][j] = analogRead(MUX_READ[i]);
    if(abs(Mux_Reading[i][j] - Mux_Reading_Lagged[i][j]) > dbt ) {
      Mux_Reading_Lagged[i][j] = Mux_Reading[i][j];
      usbMIDI.sendControlChange(CCID[i][j], Mux_Reading[i][j]>>3, channel);
    }
  }
  muxUpdated = 0;   //reset timer
  j++; // increment global counter variable before setting up MUX control for the next pass!
  if (j>=M_PINS)   {j=0;} // rollowver at 16
    // 
    for (int i = 0; i<4; i++){
      // bit-fiddle to set the i-th pin to HIGH IFF binary version of j contains i-th multiplier (i-th power of 2)
      digitalWrite(SO_PINS[i], (boolean) (j & (int) pow(2,i))); 
    } 
  }
}
I tested by pointing at the same SIGNAL pin of my single MUX in place of what would be four signal lines... it seems to work in that any output on my test pot will send four CC messages...

My code includes a minimum time parameter to ensure the MUX is not read too soon after it's set.

It occurs to me your problem my be actual wiring error(s) rather than parasitic capacitance or similar issues.

Details on how you grounded everything, how you powered your MUX etc. might get you some advice from those who know this stuff.
 
Last edited:
...or try a test program that only reads one pot and writes the raw value to serial monitor... if it's electrical the readings should still have limited range.

I built a simple one pot test which is directly connected to Teensy LC. It works fine.
After that I inserted a 74HC4067 between the pot and Teensy LC. Its behavior was like before.
I think the problem is 3.3v is not enough for 74HC4067 to work well. Maybe I should try
driving the MUX with 5v. I have to insert resistors before Teensy analog inputs (where the MUX output connected to), right?
 
The mux should be 5v supplied. On resistance goes way up with low supply voltage. The specs don't cite 3.3v performance but at lower voltages it does say output becomes non linear and recommends for digital signals only.

Make sure you power the pots with 3.3v only.
 
I don't think grounding issues would explain the range problem but I they can lead to accuracy and-or stability problems particularly with all that wiring.

Here's a good read http://www.analog.com/en/analog-dialogue/articles/staying-well-grounded.html

It's mostly about pc design.

For the breadboard stage I think you mostly want the voltage dividers star grounded to some degree (at least by mux groups or in fours) and returned via the AGND.

I'm not sure if the mux are connected to AGND or not.

I was using GND thinking they're high speed but I'm wondering if they should be treated as analog fot the same reasons ADCs are.

These issues tend not to matter very much for midi at 7-bit resolution in my experience but I've never built with mux.*

*Not an EE... ymmv
 
Last edited:
The mux should be 5v supplied. On resistance goes way up with low supply voltage. The specs don't cite 3.3v performance but at lower voltages it does say output becomes non linear and recommends for digital signals only.

Make sure you power the pots with 3.3v only.

Well, I tried your code with both 3.3 and 5 volts. When used 5 volts, I also used 10k resistors on analog inputs and 20K resistors on groud (to reduce 5v to 3.3), but wasn't able to reach the full 0..127 midi range at all. I have no more ideas to solve this problem. Paul?
 
First of all, a schematic and a picture of your circuit board and setup would be helpful to find eventual problems. Second, a systematic step by step diagnose with an approved circuit and manually setting the MUX address pins to toggle through all the MUX entries and verifying simultaneously the MUX output/ADC input with a voltmeter or an oscilloscope could make sure that all circuit problems are solved before one starts looking for problems in the software or the Teensy.
 
Well, I tried your code with both 3.3 and 5 volts. When used 5 volts, I also used 10k resistors on analog inputs and 20K resistors on ground (to reduce 5v to 3.3), but wasn't able to reach the full 0..127 midi range at all. I have no more ideas to solve this problem. Paul?

The 3.3 v supply onboard the T3.x is regulated, I'm pretty sure it's a better source than a passive voltage divider....

I have only ever used the 3.3 volt supply with voltage dividers from the T3.x's and it's always worked for me including my single mux tests...

As Theremingenieur suggests getting actual voltage readings from the pots and from the signal pin of the mux by manually setting the control inputs would really help narrow down the source of your issue and posting something like a schematic of the typically pot configuration would definitely help others spot potential problems.

@Theremingenieur - should MUX be to AGND or GND if their SIGNAL is from voltage dividers tied to AGND?
 
@Theremingenieur - should MUX be to AGND or GND if their SIGNAL is from voltage dividers tied to AGND?

GND. IIRC, the input/output switching with these MOSFET switches is basically floating (within the allowed limits) and only the control section refers to VSS. Even a very dirty GND could not "modulate" the switches' on resistance strong enough to see any effect.
 
Back
Top