Encoder through 74HC4051

Status
Not open for further replies.

AdmiralCrunch

Well-known member
Hi

I have asked a while ago about how to mux encoders. someone pointed me to this solution
https://forum.pjrc.com/threads/5100...o-expander-16x?p=175635&viewfull=1#post175635

..which worked perfectly as I can remember.

I had to pause my for a while and now I got back to work.. but this solution reads me
0
1

or

0
-1

.. when muxing a encoder through two 4051s.
(when I connect the encoder directcly to the teensy, everything works well)

this is my code now:
Code:
#define ENCODER_DO_NOT_USE_INTERRUPTS
#include <Encoder.h>

#define inhibit 29
#define A 30
#define B 31
#define C 32
#define encodersA 8
#define encodersB 9

Encoder myEnc[8] = {
  Encoder(encodersA, encodersB), Encoder(encodersA, encodersB), Encoder(encodersA, encodersB), Encoder(encodersA, encodersB), 
  Encoder(encodersA, encodersB), Encoder(encodersA, encodersB), Encoder(encodersA, encodersB), Encoder(encodersA, encodersB)
};
long position[8]  = {
  -999, -999, -999, -999, -999, -999, -999, -999
};
uint8_t encIncNum[8] = {
  0, 1, 2, 3, 4, 5, 6, 7
};


void setup() {
  // put your setup code here, to run once:
  pinMode(inhibit, OUTPUT);
  pinMode(A, OUTPUT);
  pinMode(B, OUTPUT);
  pinMode(C, OUTPUT);

  Serial.begin(9600);
  while ( !Serial && (millis() < 4000) ) {
    Serial.println("LOADING SERIAL PORT ...");
  }  
}


uint8_t i = 0;
void loop() {

  
  readInputs(i);
  
  i++;
  if(i >= 0) { // only one encoder connected so far, all other 4051-inputs wired to GND
    i = 0;
  }
}

void selectAddress(uint8_t a) {
  digitalWrite(inhibit, HIGH);
  digitalWrite(A, a & 0x1);
  digitalWrite(B, (a >> 1) & 0x1);
  digitalWrite(C, (a >> 2) & 0x1);
  digitalWrite(inhibit, LOW);
}

void readEnc(uint8_t enc) {
  long newPos = myEnc[enc].read();
  if (newPos != position[enc]) {
    position[enc] = newPos;
    Serial.println(position[enc]);
   
    myEnc[enc].write(0);
  }
}

void readInputs(uint8_t i) {
  selectAddress(i);
  delayMicroseconds(50);
  readEnc(i);
}

can someone see the problem, why I only get 0,1,0,-1 ?
 
Hi

I have asked a while ago about how to mux encoders. someone pointed me to this solution
https://forum.pjrc.com/threads/5100...o-expander-16x?p=175635&viewfull=1#post175635

..which worked perfectly as I can remember.

I had to pause my for a while and now I got back to work.. but this solution reads me
0
1

or

0
-1

.. when muxing a encoder through two 4051s.
(when I connect the encoder directcly to the teensy, everything works well)

this is my code now:
Code:
#define ENCODER_DO_NOT_USE_INTERRUPTS
#include <Encoder.h>

#define inhibit 29
#define A 30
#define B 31
#define C 32
#define encodersA 8
#define encodersB 9

Encoder myEnc[8] = {
  Encoder(encodersA, encodersB), Encoder(encodersA, encodersB), Encoder(encodersA, encodersB), Encoder(encodersA, encodersB), 
  Encoder(encodersA, encodersB), Encoder(encodersA, encodersB), Encoder(encodersA, encodersB), Encoder(encodersA, encodersB)
};
long position[8]  = {
  -999, -999, -999, -999, -999, -999, -999, -999
};
uint8_t encIncNum[8] = {
  0, 1, 2, 3, 4, 5, 6, 7
};


void setup() {
  // put your setup code here, to run once:
  pinMode(inhibit, OUTPUT);
  pinMode(A, OUTPUT);
  pinMode(B, OUTPUT);
  pinMode(C, OUTPUT);

  Serial.begin(9600);
  while ( !Serial && (millis() < 4000) ) {
    Serial.println("LOADING SERIAL PORT ...");
  }  
}


uint8_t i = 0;
void loop() {

  
  readInputs(i);
  
  i++;
  if(i >= 0) { // only one encoder connected so far, all other 4051-inputs wired to GND
    i = 0;
  }
}

void selectAddress(uint8_t a) {
  digitalWrite(inhibit, HIGH);
  digitalWrite(A, a & 0x1);
  digitalWrite(B, (a >> 1) & 0x1);
  digitalWrite(C, (a >> 2) & 0x1);
  digitalWrite(inhibit, LOW);
}

void readEnc(uint8_t enc) {
  long newPos = myEnc[enc].read();
  if (newPos != position[enc]) {
    position[enc] = newPos;
    Serial.println(position[enc]);
   
    myEnc[enc].write(0);
  }
}

void readInputs(uint8_t i) {
  selectAddress(i);
  delayMicroseconds(50);
  readEnc(i);
}

can someone see the problem, why I only get 0,1,0,-1 ?

You are only getting 0,1,0,-1 because you read the encoder, print the value, and reset the value back to zero one right after the next. If you want to get higher or lower values than 1 or -1 you would have to spin the encoders really fast whenever the read cycle comes around with your current code.
 
You are only getting 0,1,0,-1 because you read the encoder, print the value, and reset the value back to zero one right after the next. If you want to get higher or lower values than 1 or -1 you would have to spin the encoders really fast whenever the read cycle comes around with your current code.

The code you followed was intended to be used as data increment and data decrement midi control change message so the 1,0,-1 was the desired behavior in order to achieve that.
 
I also tried a modified version of this..

I have moved the setAdress() to setup, as I have only one encoder connected for testing/debugging.. I also have removed the digital.write(0) after the reading.
but still the same ..


Code:
#define ENCODER_DO_NOT_USE_INTERRUPTS
#include <Encoder.h>

#define inhibit 29
#define A 30
#define B 31
#define C 32
#define encodersA 8
#define encodersB 9

Encoder myEnc[8] = {
  Encoder(encodersA, encodersB), Encoder(encodersA, encodersB), Encoder(encodersA, encodersB), Encoder(encodersA, encodersB), 
  Encoder(encodersA, encodersB), Encoder(encodersA, encodersB), Encoder(encodersA, encodersB), Encoder(encodersA, encodersB)
};
long position[8]  = {
  -999, -999, -999, -999, -999, -999, -999, -999
};
uint8_t encIncNum[8] = {
  0, 1, 2, 3, 4, 5, 6, 7
};

void setup() {
  pinMode(inhibit, OUTPUT);
  pinMode(A, OUTPUT);
  pinMode(B, OUTPUT);
  pinMode(C, OUTPUT);

  Serial.begin(9600);
  while ( !Serial && (millis() < 4000) ) {
    Serial.println("LOADING SERIAL PORT ...");
  }  

  selectAddress(0);
}


void loop() {

  long newPos = myEnc[enc].read();
  if (newPos != position[enc]) {
    position[enc] = newPos;
    Serial.println(position[enc]);
  }
  delayMicroseconds(50);

}

void selectAddress(uint8_t a) {
  digitalWrite(inhibit, HIGH);
  digitalWrite(A, a & 0x1);
  digitalWrite(B, (a >> 1) & 0x1);
  digitalWrite(C, (a >> 2) & 0x1);
  digitalWrite(inhibit, LOW);
}
 
Did you remember to put pull-up resistors on the A and B lines of your encoder? I think I ran into that issue before, but I’m not positive if it was the same thing and whether or not that fixed it.
 
Did you remember to put pull-up resistors on the A and B lines of your encoder? I think I ran into that issue before, but I’m not positive if it was the same thing and whether or not that fixed it.

yes, I have wired a 3.3k-resistor between each A/B-pins from the encoder to 3.3V

should I try a smaller resistor?
 
yes, I have wired a 3.3k-resistor between each A/B-pins from the encoder to 3.3V

should I try a smaller resistor?

A smaller resister shouldn’t be necessary, I used 10k in mine at least, as far as I can tell the code you used should have functioned correctly. The only issue I can spot is that the delayMicrosends should happen directly after the selectAddress, but that shouldn’t effect it as far as I know since the address doesn’t change at all in this code.
 
Maybe try using a voltmeter to check if both signals are ok.

Probably best to connect directly to the pins and run the normal example to check it's working. Then you can see how the voltages change. If you turn *very* slowly, you should be able to see each signal alternate between LOW to HIGH.

If you run it with the mux chip continuously selected to the right channel, you should see the same signals on both sides of the mux and of course at the Teensy pins. If something about the hardware isn't connected correctly, you'll probably see one or both signals stuck high or low somewhere.
 
Maybe try using a voltmeter to check if both signals are ok.

the encoders work fine, I have connected them all directly and it works as wished.

I now have managed to get one encoder workig with the two 4051s, but when I connect a second encoder to pin 2 of each 4051, I again have this behaviour but only on pin2.. the encoder on pin1 works fine.

oO

Code:
#define ENCODER_DO_NOT_USE_INTERRUPTS
#include <Encoder.h>

#define inhibit 29
#define A 30
#define B 31
#define C 32
#define encodersA 8
#define encodersB 9

Encoder myEnc[8] = {
  Encoder(encodersA, encodersB), Encoder(encodersA, encodersB), Encoder(encodersA, encodersB), Encoder(encodersA, encodersB), 
  Encoder(encodersA, encodersB), Encoder(encodersA, encodersB), Encoder(encodersA, encodersB), Encoder(encodersA, encodersB)
};
long position[8]  = {
  -999, -999, -999, -999, -999, -999, -999, -999
};
uint8_t encIncNum[8] = {
  0, 1, 2, 3, 4, 5, 6, 7
};

void setup() {
  pinMode(inhibit, OUTPUT);
  pinMode(A, OUTPUT);
  pinMode(B, OUTPUT);
  pinMode(C, OUTPUT);

  Serial.begin(9600);
  while ( !Serial && (millis() < 4000) ) {
    Serial.println("LOADING SERIAL PORT ...");
  }  

  
}


void loop() {
selectAddress(0);
delayMicroseconds(50);
long newPos = myEnc[0].read();
  if (newPos != position[0]) {
    position[0] = newPos;
     Serial.print("enc0: "); Serial.println(position[0]);
  }

selectAddress(1);
delayMicroseconds(50);
long newPos1 = myEnc[1].read();
  if (newPos1 != position[1]) {
    position[1] = newPos1;
     Serial.print("enc1: "); Serial.println(position[1]);
  }

 
  
}

void selectAddress(uint8_t a) {
  digitalWrite(inhibit, HIGH);
  digitalWrite(A, a & 0x1);
  digitalWrite(B, (a >> 1) & 0x1);
  digitalWrite(C, (a >> 2) & 0x1);
  digitalWrite(inhibit, LOW);
}
 
Status
Not open for further replies.
Back
Top