My code behaving weirdly for 22 x pots with 3 x 4051 Mux's - Teensy2

Status
Not open for further replies.
Hi,

So i am still trying to sort out my multiplexing code for analog inputs using arrays.

Thanks VERY much to Lukas from www.lbsfilm.at for the original code ! GENIUS :)

My edited Code :

Code:
#include <MIDI.h>


// Here I'm defining the address pins for the multiplexers
int multiAddr0 = 0;
int multiAddr1 = 1;
int multiAddr2 = 2; 


// Here I'm declaring some arrays for storing old vallues
int faderValue = 0;
int previous[] = {  
  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; 
int preprevious[] = {
  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
  
  
void setup() {
Serial.begin(9600); 
  // put your setup code here, to run once
  
  //Setting the address pins to output
  pinMode(multiAddr0, OUTPUT);
  pinMode(multiAddr1, OUTPUT);
  pinMode(multiAddr2, OUTPUT);

}

void loop() {
  // put your main code here, to run repeatedly:
  
  // multiplexer loop

  for(int input = 7; input > -1; input--)          // This is the first for loop, switching through the addresses
  {

    for(int multi = 2; multi > -1; multi--)       //this is the second loop,nested in the above, switching through the 3 multiplexers on each address
    {
      int faderNumber = multi * 8 + input;     // calculating the potis number to store its value in the arrays

      faderValue = (analogRead(multi)/8);     // reading from the corresponding analog input 

      if (faderValue != previous[faderNumber])    // checking for a change
      {
        if (faderValue != preprevious[faderNumber]) // checking for a change again in the preprevious array (Just to make sure the analog to digital converter isn't flickering between two values)
        {
          usbMIDI.sendControlChange(faderNumber,faderValue, 2); 
          preprevious[faderNumber] = previous[faderNumber];     // ... store the current previous number in preprevious
          previous[faderNumber] = faderValue;                          // and store the current number in previous

        }
      }  


    }
    
    switch (input){ // this switch case statement in the first loop switches the 3 BEC (Binary-Encoded-Decimal) Bits for the address selection
    case 0:
      digitalWrite(multiAddr0,LOW);
      digitalWrite(multiAddr1,LOW);
      digitalWrite(multiAddr2,LOW);
      break;

    case 1:
      digitalWrite(multiAddr0,HIGH);
      break;

    case 2:
      digitalWrite(multiAddr0,LOW);
      digitalWrite(multiAddr1,HIGH);
      break;

    case 3:
      digitalWrite(multiAddr0,HIGH);
      break;

    case 4:
      digitalWrite(multiAddr0,LOW);
      digitalWrite(multiAddr1,LOW);
      digitalWrite(multiAddr2,HIGH);
      break;

    case 5:
      digitalWrite(multiAddr0,HIGH);
      break;

    case 6:
      digitalWrite(multiAddr0,LOW);
      digitalWrite(multiAddr1,HIGH);
      break;

    case 7:
      digitalWrite(multiAddr0,HIGH);
      break;


    }
  }

  //end multiplexer

}

Problems:

1. The pots aren't in numerical order as i've connected them EG: pot1-pot8 to the mux1 (connected to A0)

2. The midi signals are corrupt EG: controllers are getting mixed together like this on controller 3 :
Screen Shot 2014-09-03 at 9.47.49 AM.png

3. Sometimes controller 16 repeatedly sends values without any faders being touched.

Questions:

1. What is the correct pin order to connect the pots to the mux's so that they appear as pot1 - controller1, pot2 - controller2 etc ?
this is what i have now:
74HC4051_d.png

2. How do i get the correct controller messages to send though usb midi?

3. Are there any code errors that are to blame?
 
I cannot directly address your code however there are some conditions that must be satisfied in order to properly utilize a CD4051 8 to one Mux chip.
A, B, C are binary data sent to the MUX address pins to address the particular mux channel required, Note that the address inputs's cannot exceed Vcc and ground as they are digital pins. The teensy has an unipolar input. Thus the inputs Must lie between Vcc and the Vee pin on the Mux in order to keep the Mux chip happy ie not go beyond the ground. So the Vee point must be connected to an analog ground (for low noise). If the Vee pin is floating so will the I/O pin as the device is a bilateral transmission gate. As a side note available from the Datasheet (use the National Semi one, The TI sheet might be confusing) no input can exceed the VCC to GND and the Vee pin must (for bipolar operation operation connect to a negative (well filtered and bypassed) source that is at least one diode (.63V) below the maximum negative voltage being measured. the same is true of the max positive input voltage ie Vin +.63V. Latchup and undefined operation are the general case when these parameters are not respected.. The worst thing that can be done with the CD405XBE is to not configure the Vee pin properly followed by forgetting that the on resistance of any gate is both Vcc dependent and is ~ 1K to 400 ohms ohms as Vcc rises, the on channel resistance decreases. and according to the CDXXXX family specifications is characterized from 3 to 15 V, Vcc.
In that the analog ground (Vee) is the most negative point.. If Bi-polar voltages must be measured an op-amp must be used to shift the ground level of the input signal to VCC/2. Of course proper gain and scaling do apply to meet the above conditions.
The rest is readily abstracted from the data sheet. A useful addition is a voltage follower to reduce the input impedance of the SAR sampling capacirotRC timing involved in charging the ADC sampling capacitor.
Ideal is one per channel to reduce to possibility of crosstalk through cabling and PCB layout but for many cases a voltage follower is good on the common I/O pin.. While remembering to add the address date to select each mux cip as required or tristate the enable pins for the MUX chips that arent't being used. When the Enable pin is high the outputs tri state.. The data sheet however is the final authority.
I've used this part family for crystal selection @ 15 MHZ with no issues but good layout is important for HF use..

Doc
 
Last edited:
Perhaps the issue is that (lacking a full schematic) you aren't handling the inhibit properly. The inhibit is a deselect device control. To be able to "Stack" two or more devices you might use the inhibit lead to disable all but the selector you need data from or make it a great deal simpler by using a CD4067BE (1 of 16 data selector) which will handle 16 I/O connections to one point... Providing 5 data control lines for addressing is easily done. The 5th address line would connect to the first selector inhibit and an inverter from that point to the second selector inhibit while the a - d address lines are connected together. This will create a 5 bit address capacity enabling you to address 32 i/o's. If you must use the CD4051BE the inhibit on each chip must be held high to disable that selector or in other words wire 2 4051's the same as 2 4067's where the high address bit is the selector control a 0 on it will enable the chip and a 1 will disable the chip.. making a 22 channel analog data selector would require 3 CD4051BE's or 2 CD4067BE's... If by Any slight chance (They are really OLD parts, discontinued in the mid 70's) you have CD4051AE or CD4067AE parts save them as antiques and buy the BE (Buffered) parts instead. THe AE parts had a somewhat unusual issue issue where the on channel resistance varied with the VCC and could be 2 X 1 or more from 3 to 15 Vcc and IIRC a big issue with bipolar use.
The selector logic is simple, The usual error made when using that family of parts was not properly dealing with the Vee (most negative supply lead) which needed to be grounded for single supply or connected to the -V supply for bipolar use or in multiple selector use, each inhibit was held low to select that chip only.
I would, Were I you... post both a schematic and the code used for this project.. The CD40XX series of transmission gates are simple to use and frequently were used as "Glue" or as Don Lancaster (Cmos Cookbook) called them MML "Mickey Mouse Logic". But there is little to beat the simplicity and ease of use of a bidirectional selectable analog gate today.. Single channel devices, CD4016 and CD4066 were invaluable analog switches... I've even made level controls by PWM'ing the control lead on a CD4016 to "adjust" the on time, the the output level for a 20 KHz max audio stream I remember using an SE555 variable duty cycle oscillator to control a CD4016 where I used a 200 KHZ switch frequency and varied it's duty cycle..

Doc
 
Last edited:
hey garthtaylor, im working on a project that is going to use around 8 of the 4051s

im still in the testing stage so im only using 3 at the moment.

im not very good at reading the code so this is mine that im useing at the moment
Code:
const byte sensor0 = 16;// where the multiplexer in/out
const byte sensor1 = 14;// port is connected
const byte touch0 = 0;
const byte addressA = 2; // the multiplexer address
const byte addressB = 3; // select lines (A/B/C)
const byte addressC = 4;


void setup ()
  {
  Serial.begin (115200);
  pinMode (addressA, OUTPUT); 
  pinMode (addressB, OUTPUT); 
  pinMode (addressC, OUTPUT); 
  }

int readSensor0 (const byte which)
  {
  digitalWrite (addressA, (which & 1) ? HIGH : LOW);
  digitalWrite (addressB, (which & 2) ? HIGH : LOW);
  digitalWrite (addressC, (which & 4) ? HIGH : LOW);
  delay(200);
   return analogRead (sensor0)*0.125;
 } 
int readSensor1 (const byte which)
{
  digitalWrite (addressA, (which & 1) ? HIGH : LOW);
  digitalWrite (addressB, (which & 2) ? HIGH : LOW);
  digitalWrite (addressC, (which & 4) ? HIGH : LOW);
  delay(200);
  return analogRead (sensor1);
 }
int readtouch0 (const byte which)
{
  digitalWrite (addressA, (which & 1) ? HIGH : LOW);
  digitalWrite (addressB, (which & 2) ? HIGH : LOW);
  digitalWrite (addressC, (which & 4) ? HIGH : LOW); 
  delay (200);
  return touchRead (touch0);
}
void loop (){
	
  for (byte i = 0; i <=7; i++) {
    Serial.print ("IC 0, Sensor ");
    Serial.print (i);
    Serial.print (", reads: ");
    Serial.println (readSensor0 (i));
   
    Serial.print ("IC 1, Sensor ");
    Serial.print (i);
    Serial.print (", reads: ");
    Serial.println (readSensor1 (i));
   
    Serial.print ("IC 2, Sensor ");
    Serial.print (i);
    Serial.print (", reads: ");
    Serial.println (readtouch0 (i));
    }}

u will have to change the touch stuff to work with what ur doing.

but the way this scans the pots is
1st 4051 pin0
2nd 4051 pin0
3rd 4051 pin0
1st 4051 pin1
2nd 4051 pin1
3rd 4051 pin1
1st 4051 pin2
2nd 4051 pin2
3rd 4051 pin2
1st 4051 pin3
2nd 4051 pin3
3rd 4051 pin3
...
1st 4051 pin7
2nd 4051 pin7
3rd 4051 pin7 //then repeats after
1st 4051 pin0
2nd 4051 pin0
3rd 4051 pin0

i havent got to the point of doing it in a array or sending in midi but i hope this helps you as it took me ages to work it out and im sure theres a cleaner way to do it other then the way im doing it
 
If you have carefully read the logic table for the CD4051BE you can short circuit a bit of your selection logic by using the inhibit pin (6) as when held high it will tristate the chip output... So all the control logic could be handled by an 8 bit shift register... three outputs for the address lines and 3 for the inhibit pins will allow 1 of 24 inputs to be selected with a byte and simple counters to create the I/O address and what are essentially Chip Select addresses.. A CD4094BE and three CD4051BE's.
Addressing the 24 inputs would could well require 6 bits of data with two spare outputs and 32 bits can easily be handled by two CD4067BE's, and a 2N3904 to invert the inhibit pin from the 5th bit where the inhibit pin is inverted by the fifth bit to enable tho other pin.. Fewer holes but the 4067 isn't as common as the the 4051.
There are some very similar cmos crossbar ic's but those. I fear are becoming pure unobtanium.. If your switching requirements were purely digital (mine so far address analog and digital switching) you 'could' use a Pro Mini too as a PLD. Or for really simple switching a EEprom.. like a 27C64 or a 28C128 as an addressable LUT..
Many times, I've used them for 7 segment displays with ULN 2803's as the current source or sink with a 555 as the mux clock driving a CD4017 data selector and anode/cathode display muxers.. Long in the past.. but still viable as concepts...

Doc
 
Last edited:
Status
Not open for further replies.
Back
Top