Domesticating an encoder

Status
Not open for further replies.

bcnx

Active member
Hi all,

I have connected a rotary encoder to a Teensy 3.2 by means of digital pin 0 for the switch (switching to ground) and digital pins 1 and 2 to the rotating parts.
I am using the Encoder library and I based my code on the example code on the relevant page:

Code:
 //Rotary encoder
  long Value2Knob1 = Knob1.read();
  delay(250);
  if (Value2Knob1 != Value1Knob1) {
    //Serial.print("Knob1: ");
    //Serial.println(Value2Knob1);
    if ( Value2Knob1 < Value1Knob1 ) {
      Serial.println("---");
      Index1 = Index1 - 1;
      if ( Index1 <= -1 ) {
        Index1 = 11;
      }
    }
    
    if ( Value2Knob1 > Value1Knob1 ) {
      Serial.println("+++"); 
      Index1 = Index1 + 1;
      if ( Index1 >= 12 ) {
        Index1 = 0; 
      }
    }

The problem is that one a turn to either side, the volume of registered values is not equal: sometimes I get one value, then three, then two. I need the encoder to reliably just register one change at the time, so the rest of the code triggers reliably. The only way I managed to do this, was to add a long delay (250 ms and up). As I am also updating a TFT screen in the "loop" part, this delay is not acceptable.

Can anyone give me a hint on how to get this working? I was thinking about a time based buffer, but that would also hold up the execution of the program.

Cheers all,

BC
 
Last edited:
Probably contact bouncing. You should debounce the encoder in hardware (see suggested filter circuit in this datasheet) or use a optical/magnetical encoder that does not bounce (like the Bourns EM14). As I understand it the encoder library is intended for use with bounce free encoders as it uses interrupts so as to not miss a single pulse.

Kind regards,

Gerrit
 
Gerrit,

I did not know the correct English term (we call it "kontakt dender" in Dutch, as you probably know judging by your name), but I think you are indeed correct on the "bouncing". I will add these filter circuit and report back.

Thanks a lot,

BC
 
Cheers Thereminingenieur,

Nice to have two options. I will need to balance the better one in terms of cost: the physical solution or the software solution.

BC
 
Heh, true, yes! But it adds a bit to the complexity of the software. I will study it carefully to see of I understand it all and will then decide on tackling this in software or hardware. I am using a prototype now that is still open for changes.

Thanks for your suggestion in any case!

BC
 
Oh, certainly not necessarily, but if I am going to use software, I make it a point to fully understand what I am doing, otherwise it will be harder to troubleshoot.

BC
 
Debouncing in software is certainly the simplest solution, probably makes more sense than using hardware debouncing for cheap encoders.

Kind regards,

Gerrit
 
Hi Theremingenieur,

I find it difficult to determine what the core logic of your software is. Could you briefly describe what your method is?

Cheers,

BC
 
... and I thought that the code was self-explaining. In addition, I added the following description:
The approach to filter bouncing is as follows: Knowing that the rotary knob will pull down and let up pins A and B alternating, there is no reason to handle for example multiple consecutive interrupts (due to contact bouncing) on pinA after the first one. That's why the first pinA interrupt will disable further pinA interrupts with a quick port config register write until an interrupt at pinB will occur, which will disable pinB interrupts and re-enable pinA interrupts and vice versa. That means that independent of contact bouncing, for turning the rotary knob by one detent, only exactly 4 interrupts A-B-A-B or B-A-B-A will be fired and handled, not more.

No idea what to add...
 
Hi,

thank you for the description, it creates more clarity for me. I may understand incorrectly, but your code seems to expect that one rotates one way, and next the other way. But will it also work when one turns one way, pauses and turn the same way again?

thanks,

BC
 
That must be a misunderstanding. You may rotate in either way, pause, and rotate again in either direction without problems.
Problems occur only if you hold the encoder knob in the middle of two detents and wobble around without going to one stable detention position. That is what users normally don’t do, and none of the encoder libraries which I’ve seen and tested over the years does handle this unusual case correctly. My code has at least the advantage that it does not hang if you decide to reverse the direction half way between two detents. It risks just to miss occasionally one single count (the next one after such an undefined event).
Why don’t you just try it out? It’s still free... But if you find it useful for your project, you are free to send me a few stropwafels ;-)
 
You mean stroopwafels? I believe that is a Dutch thing, but I will check.
All kidding aside: I greatly appreciate (your) free software, but I always force myself to only use what I understand. I should be able to do so now I understand the register thingie.
 
Status
Not open for further replies.
Back
Top