4051 input "addressing" offset

Hi there,

I have a Pro Mini attempting to talk to 4 4051s, and have some odd behaviour:

When selecting inputs 0, 1, 2, ..., 7 I actually get inputs 1, 2, 3, ..., 0.
I've tried getting the arduino to give me debug info via serial (hopefully clear from the code, as I'm having trouble thinking of how to describe it), but it's not making any sense to me...

Digital pins 6, 7, 8 are connected to the select pins on all 4051s, and each 4051 output has it's own input to the arduino, via an RC debounce (hence the 2ms delay on each time round the read loop - I now realise why software debounce is preferred!)

// inout pin numbers
const byte inA = 5; // Mux outs -> Arduino ins
const byte inB = 4;
const byte inC = 3;
const byte inD = 2;

const byte mux[3] = {8, 7, 6}; // Mux control lines


// Switch positions
byte switchesA[8] = {0, 0, 0, 0, 0, 0, 0, 0};  // 8 switches on inA - switchesA[0] is encoder switch
byte switchesB[8] = {0, 0, 0, 0, 0, 0, 0, 0};  // 8 switches on inB - switchesB[0] is encoderA pulse
byte switchesC[8] = {0, 0, 0, 0, 0, 0, 0, 0};  // 8 switches on inC - switchesC[0] is encoderB pulse
byte switchesD[8] = {0, 0, 0, 0, 0, 0, 0, 0};  // 8 switches on inD



void setup() {
  pinMode(inA, INPUT_PULLUP);
  pinMode(inB, INPUT_PULLUP);
  pinMode(inC, INPUT_PULLUP);
  pinMode(inD, INPUT_PULLUP);
  
  pinMode(mux[0], OUTPUT);
  pinMode(mux[1], OUTPUT);
  pinMode(mux[2], OUTPUT);
  
  Serial.begin(9600);
  
}

void loop() {
  for(byte i=0; i <= 7; i++) {
   for(byte j=2; j <3; j--) { //write to mux control lines (Done backwards just to help me visualise the counting more easily)
     if(bitRead(i, j)) {
        digitalWrite(mux[j], HIGH);
        
        Serial.print(1);
        
//        Serial.print(mux[j]);
//        Serial.print("HIGH");
//        Serial.print(i);
//        Serial.print('\t');
        
      }
      else {
        digitalWrite(mux[j], LOW);
        
        Serial.print(0);
        
//        Serial.print(mux[j]);
//        Serial.print("LOW");
//        Serial.print(i);
//        Serial.print('\t');
        
      }
//      Serial.print(i);
//      Serial.print(j);
//      Serial.print("\t");

    }

    switchesA[i] = digitalRead(inA);
    switchesB[i] = digitalRead(inB);
    switchesC[i] = digitalRead(inC);
    switchesD[i] = digitalRead(inD);

    Serial.print(' ');
    Serial.print(i);
        
    Serial.print(' ');
    Serial.print(switchesA[i]);
    Serial.print(switchesB[i]);
    Serial.print(switchesC[i]);
    Serial.print(switchesD[i]);
    Serial.print('\t');
    

    delay(10);
//    Serial.print('\n');

    
  }

//  for(byte i=0; i <= 7; i++)
//  Serial.print(switchesA[i]);
//
//  Serial.print('\t');
//
//  for(byte i=0; i <= 7; i++)
//  Serial.print(switchesB[i]);
//
//  Serial.print('\t');
//
//  for(byte i=0; i <= 7; i++)
//  Serial.print(switchesC[i]);
//
//  Serial.print('\t');
//
//  for(byte i=0; i <= 7; i++)
//  Serial.print(switchesD[i]);

  Serial.print('\n');

  delay(200);
    
}

Any suggestions would be appreciated!

for(byte j=2; j <3; j--)

Check that middle term j<3 when counting down.

No, that is correct. After j = 0, j++ overflows and exits the loop as j > 3. I could use int and j < 0, but it seemed wasteful...

memphis32:
No, that is correct. After j = 0, j++ overflows and exits the loop as j > 3. I could use int and j < 0, but it seemed wasteful...

Yes that would work with the overflow but that is not very good practice. Why do you think j < 0 is wasteful?

How have you got this wired up exactly? If the inputs appear in the wrong order it is often a sign of incorrect wiring.

What I don't understand about this is why you have the same pin which is connected to the multiplexer being read into four different arrays. It seems to be the wrong way round. All the four arrays will contain the same thing, that is the current state of the input pin ( pin 3 ) of the multiplexer in all 8 locations of each array.

Um, doesn't look that way to me...?

// inout pin numbers
const byte inA = 5; // Mux outs -> Arduino ins
const byte inB = 4;
const byte inC = 3;
const byte inD = 2;

// Switch positions
byte switchesA[8] = {0, 0, 0, 0, 0, 0, 0, 0};  // 8 switches on inA - switchesA[0] is encoder switch
byte switchesB[8] = {0, 0, 0, 0, 0, 0, 0, 0};  // 8 switches on inB - switchesB[0] is encoderA pulse
byte switchesC[8] = {0, 0, 0, 0, 0, 0, 0, 0};  // 8 switches on inC - switchesC[0] is encoderB pulse
byte switchesD[8] = {0, 0, 0, 0, 0, 0, 0, 0};  // 8 switches on inD

---------------------------------------------------------

    switchesA[i] = digitalRead(inA);
    switchesB[i] = digitalRead(inB);
    switchesC[i] = digitalRead(inC);
    switchesD[i] = digitalRead(inD);

Um, doesn't look that way to me...?

That doesn't stop it being true.

Now I am still waiting on that schematic. Maybe that will clear it up.

Array switchesA takes from input pin 5, switchesB from pin 4, switchesC from pin 3, switchesD from pin 2, for i = 0 -> 7 (each address of the mux). I'm afraid I'm not following how you're seeing it...
Bad wiring would account for swapped addresses, not rotated.
Layout included (I can draw up a schem if this is inadequate)

Unfortunately a layout is almost totally useless in situations like this.

Bad wiring would account for swapped addresses, not rotated.

Well it is shifted down by one, almost as if you are reading the last state of the multiplex switch not the current one.
You could try adding a short delay after the address is set up and before the inputs are read like this

    delay(1);
    switchesA[i] = digitalRead(inA);
    switchesB[i] = digitalRead(inB);
    switchesC[i] = digitalRead(inC);
    switchesD[i] = digitalRead(inD);

The other thing is that have you connected all the multiplexer inputs to something, that is they are not just floating are they? Floating inputs leads to cross talk so it is normal to connect a pull up or down resistor on each multiplex input.

I'll try the delay after the address - I was under the impression that the 4051s were faster than I'd need them to be. If that works, it was obviously the wrong impression!!

It works with the delay between adressing and reading. I'd realised that the hardware debounce was affecting following readings, but it hadn't occured to me that the output of the debounce was still lingering from the previous reading.

Having just read what I've written, I've essentially just said the same thing twice, so I'm kicking myself it wasn't obvious to me before!!

Oh, and thankyou!

I'd realised that the hardware debounce was affecting following readings,

Not sure what you mean here. Debounce is used on inputs not outputs.

Because I was setting the address, then immediately taking a reading, the RC debounce was still holding the previous value. I had set a delay after the reading to compensate for my excessive filtering, but it was between the addressing and reading that it was required.

I think I know what I'm trying to say, but I don't think it's coming across right...

Because I was setting the address, then immediately taking a reading, the RC debounce was still holding the previous value.

There should be no need for any debounce when writing to the address decoders.

If you want to do some debouncing on the values you have read then you need to check the values you have read into the arrays against the value you read last time. If you detect a change, then hold off reading the multiplexed array again until after the debounce time.