Go Down

Topic: Multiplexing Rotary Encoders (Read 1 time) previous topic - next topic

Terumi

Hello people,
Yesterday I managed to multiplex 4 rotary encoders using 2 hc4051c multiplexers.
Although everything was going ok when I tried for the first time, after some modifications (disconnected and reconnected my encoders and made an extra Serial.print in my code) only the rotary encoder on pin 7 was playing correctly, all other encoders had constantly their b pin high. Did I burn something?

When I was trying to make an encoder work with my arduino I figured I needed a pullup resistor otherwise I could make any code work.

Now that I have multiplexers in between, although I have set the input pins on the arduino to INPUT_PULLUP where the multiplexers send values, I don't know if this is the proper thing to do.

my code is:

Code: [Select]

int val;
int encoder0PinA = 5;
int encoder0PinB = 6;
int encoder0Pos = 0;
int encoder0PinALast = LOW;
int n = LOW;
int k = LOW;
byte encoders[4] = {4, 6, 7, 5};
int encoderValues[4] = {0, 0, 0, 0};
int previousEncoderPinAState[4] = {LOW, LOW, LOW, LOW};
int previousEncoderPinBState[4] = {LOW, LOW, LOW, LOW};

int midiNoteValues[8]; // array to hold the midi note number
int durationValues[8];
int velocityValues[8];
bool dirtyFlags[] = { true, true, true, true, true, true, true, true };
int *modeValues[] = { midiNoteValues, durationValues, velocityValues };
//char *notes = "aAbcCdDefFgG";
byte mode = 0;

const byte muxInput = A0;  // where the multiplexer in/out port is connected
const byte s0 = 4;
const byte s1 = 3;
const byte s2 = 2;

bool potValueChanged = true; //bool to know if pot value changed, needed for display update

int readSensor (const byte which)
{
  // select correct MUX channel on both muxes
  digitalWrite (s2, (which & 1) ? HIGH : LOW);  // low-order bit
  digitalWrite (s1, (which & 2) ? HIGH : LOW);
  digitalWrite (s0, (which & 4) ? HIGH : LOW);  // high-order bit
  //return analogRead (muxInput); // now read the sensor

  //read the values on encoderPinA and encoderPinB (the one comes from the first mux, and the other from the other).
  n = digitalRead(encoder0PinA);
  k = digitalRead(encoder0PinB);


  if ((previousEncoderPinAState[which] == LOW) && (n == HIGH)) {
    if (digitalRead(encoder0PinB) == LOW) {
      encoderValues[which] = encoderValues[which] - 1;
    } else {
      encoderValues[which] = encoderValues[which] + 1;
    }
    Serial.print("Encoder ");
    Serial.print(which);
    Serial.print(" value: ");
    Serial.println (encoderValues[which]);
  }
  previousEncoderPinAState[which] = n;

}

void getPotValues()
{
  for (int i = 0; i <= 3; i ++)
  {
    readSensor(encoders[i]);
  }
}

void setup() {
  pinMode (encoder0PinA, INPUT_PULLUP);
  pinMode (encoder0PinB, INPUT_PULLUP);
  pinMode (s0, OUTPUT);
  pinMode (s1, OUTPUT);
  pinMode (s2, OUTPUT);
  Serial.begin (9600);
}

void loop() {
  getPotValues();
}



Thank you!

PaulRB

#1
Feb 20, 2019, 08:32 pm Last Edit: Feb 20, 2019, 08:41 pm by PaulRB
+1 Karma for using code tags and posting a proper schematic.



Your schematic could be simplified and improved by using a few 5V and GND symbols so there aren't so many crossed lines making the wiring hard to follow.

What I don't understand is why you are using two multiplexer chips to save only 3 Arduino pins, when you don't seem to be short of Arduino pins?

Terumi

Thank you!
I'm using 2 multiplexers because my circuit will include 9 buttons and a lcd screen. I know I could use a bigger arduino but right now I'm in the process of learning. I started one month ago, and now I know the pins of hc4051 by heart  :)

Thank you for you advise

PerryBebbington

Also ++Karma for the same reason :)

As you only want to select 4 outputs you don't need C connected to the Adruino, connect it to 5V, then only inputs 4,5, 6 and 7 ill be active and you save another pin.

I don't understand why you have not used inputs 0, 1, 2 and 3. It doesn't matter but I am curious to why.

I confess to not reading your code, but does it take into account that D2 must always be high for reading the last 4 inputs on the encoders?

You could use a 4052 which has 2 * 4 input multiplexers in one package.

Using the internal pull up resistors should be fine. I don't think you have done anything that will cause harm.

To test further I suggest you write some test code that outputs a very slowly changing (maybe every 15 seconds) binary output (00, 01, 10, 11) on D3 and D4 and use a meter or 'scope to check which encoder is actually connected to D5 and D6.

Terumi

I'm about to use 4 more encoders, that is why I'm using these inputs.
Nice idea Perry, I'll try it as soon as I have me multimeter delivered to me.
Thank you for your suggestions!

:)

PaulRB

#5
Feb 21, 2019, 12:30 am Last Edit: Feb 21, 2019, 12:40 am by PaulRB
So... 8 encoders, 9 buttons, an LCD (16x2 or 20x4?) and serial comms for midi (pins 0 & 1) ?

I would recommend getting a serial (i2c) backpack for the LCD. Makes the wiring simpler and needs only two Arduino pins (must be A4 & A5 on Nano).

For the buttons and encoders, you could wire them as a matrix. A 5 X 5 matrix would be just enough for your encoders and buttons and would need 10 Arduino pins. No multiplexer chips required.

Terumi

The screen is 20x4 and has already i2c connection.

I've never thought about matrices because some operations have to be simultaneously one two, even three controls (maybe I'm wrong in thinking that this cannot be done with matrices).

Do you have any suggested read about this subject?

Also, whist tinkering with what I've made so far, I realized that pushing the encoders to the breadboard *sometimes* made them function properly, but not all of them.
Whenever I have a single encoder directly to arduno pins, it works as expected without any need for pushing.
I soldered on a perfboad my design (because the encoder feet are flimsy,  but either a single one works (a random one),  either none of them does.

I had the same effects when I was trying to make one to work until I activated pin pull up on the arduino pins.

I haven't found anything yet describing a design with muxes and rotary encoders, I'm still not sure if indeed they work together.  :(

PaulRB

You can ensure that a matrix can accurately read switches pressed simultaneously in a matrix by attaching a small diode in series with each switch (so two diodes for each rotary encoder). This prevents the "ghosting" effect that can cause false switch detections if diodes are not used.

PaulRB

The problem that can happen with rotary encoders and multiplexers is that pulses can be missed if the scanning is not fast enough. This is also true if they are part of a matrix. Even encoders connected directly to the Arduino pins can miss pulses if the code is not written correctly. With basic encoders this should not be an insurmountable problem. With high precision encoders which can be moved at a high speed, interrupts are sometimes needed to avoid loosing pulses.

Your problem still sounds like a wiring issue. A multimeter should help you find the problem.

PerryBebbington


Quote
The problem that can happen with rotary encoders and multiplexers is that pulses can be missed if the scanning is not fast enough.
I agree with that. When I was trying to read 4 encoders I discovered that I needed to read them every millisecond at least to get a reliable output. I checked the output with an oscilloscope and discovered I didn't need to turn them very fast to get a pulse about 1ms wide, hence the need to read them that often. If you are going to read 4 of them in a matrix or via multiplexers you have to scan the lot every millisecond, so every 250 microseconds you have to be scanning an encoder. 


dougp

It is possible to transfer the encoder work to a dedicated IC.
Everything we call real is made of things that cannot be regarded as real.  If quantum mechanics hasn't profoundly shocked you, you haven't understood it yet. - Niels Bohr

No private consultations undertaken!

PaulRB

I discovered that I needed to read them every millisecond at least to get a reliable output.
It will depend on how many steps per revolution the encoder has and how fast you turn it.

For a basic, 24-step, 2-channel encoder, for example, you would get 96 "edges" per revolution (48 per channel). Revolving at one revolution per second, the edges would be about 10ms apart.

If using a 5 x 5 matrix, scanning one row/column per ms would be just about fast enough.

But if the OP's encoders are higher resolution or will be spinning faster, then things will be more difficult.

Optimising the code by using direct port manipulation might help, but there could still be problems if anything momentarily delays the scanning.

Terumi

Thank you guys. It was a wiring problem. Today I borrowed a multimeter and I saw that one of my multiplexers was not getting +5volts. I had some cold joins (is this what they call them?).

When I fixed my soldering everything worked just perfect! As for the speed, it is adequate. I'm making a midi sequencer, not medical equipment or some other time critical operations.

Now, the rotary encoders feature a push button. I could use a third multiplexer to utilize them, but I'm thinking that I could use a matrix, just to learn about them.

I don't know what the pros and cons are but I'll have a look and I'll decide. Multiplexers are inexpensive and, if they require less wiring they might be preferable.

Thank you all for your help.

:)

PaulRB

#13
Feb 22, 2019, 08:14 am Last Edit: Feb 22, 2019, 08:29 am by PaulRB
Search for pictures of "wet" vs. "dry" solder joints on Google.

Multiplexers don't require less wiring than a matrix and are not faster. They will certainly make your circuit more complex. I can't see any point using mixing multiplexers for some buttons and a matrix for others in the same circuit.

What you could do, however, is use multiplexers to drive a matrix. This would save even more Arduino pins. Using one multiplexer to drive the matrix rows and another multiplexer to drive the columns, you could make a matrix of 64 buttons using only 7 Arduino pins, for example.

The push buttons on the encoders: are these 8 more buttons that you did not mention before, or are they 8 of the 9 buttons you mentioned?

If they are extra, you have a total of 33 buttons to scan. So your matrix could be 5x8 or 6x6.

It may be possible to combine two multiplexers into a 16-way multiplexer, so your matrix could be 3x16.

Terumi

Quote from: PaulRB link=msg=4069112
The push buttons on the encoders: are these 8 more buttons that you did not mention before, or are they 8 of the 9 buttons you mentioned?
These are the eight of the nine I mentioned.
And here is the job so far...




Go Up