Keyes rotary encoder keeps counting when i stop rotating it

Hello
I'm working on a volume knob for my PC. I have a keyes rotary encoder with a switch-button. I've connected everything up to my Arduino pro micro like this:

The img link doesnt work. Please see the image here:

sorry for the bad drawing..

I've tried different codes from this thread:
https://forum.arduino.cc/index.php?topic=242356.msg2703618#msg2703618

I allways get the same problem:

Sometimes (quite often) when i rotate the knob it gets in a state where it keeps incrementing the number. It's like i'm rotating it without touching it. If i twist it the other was it usually stops. It's often one directional (it happens when i twist right, not left).
From the serial print from one of the codes i tried it seems that the arduino doesn't even think i'm twisting the knob, but its still triggering:

"
PinA: 0 PinB: 1 Counter: 1113
PinA: 0 PinB: 0 Counter: 1114
PinA: 0 PinB: 0 Counter: 1115
PinA: 0 PinB: 1 Counter: 1114
PinA: 0 PinB: 0 Counter: 1115
PinA: 0 PinB: 0 Counter: 1116
PinA: 0 PinB: 0 Counter: 1117
PinA: 0 PinB: 1 Counter: 1116
PinA: 0 PinB: 0 Counter: 1117
"

I've tried disconnecting the 10k R from V++ and use the internal pull-up instead, same problem.

Sometimes it works for a while, then suddenly it happens.

The current code i'm, testing (i didnt write it myself) is this:

volatile boolean TurnDetected;
volatile boolean up;
static long virtualPosition=0;    // without STATIC it does not count correctly!!!

const int PinCLK=3;                   // Used for generating interrupts using CLK signal
const int PinDT=4;                    // Used for reading DT signal
const int PinSW=5;                    // Used for the push button switch

void isr ()  {                    // Interrupt service routine is executed when any CHANGE transition is detected on CLK
    volatile boolean CLK = digitalRead(PinCLK);
    volatile boolean DT = digitalRead(PinDT);
    up=((!CLK && DT)||(CLK && !DT));
   
    TurnDetected = true;
}

void setup ()  {
 pinMode(PinCLK,INPUT);
 pinMode(PinDT,INPUT);  
 pinMode(PinSW,INPUT);
 attachInterrupt (0,isr,CHANGE);   // interrupt 0 is always connected to pin 2 on Arduino UNO
 Serial.begin (9600);
 Keyboard.begin();
 Serial.println("Start");
 
}

void loop ()  {

 if (!digitalRead(PinSW)) {      // check if pushbutton is pressed
   virtualPosition=0;              // if YES, then reset counter to ZERO
   Serial.print ("Reset = ");      // Using the word RESET instead of COUNT here to find out a buggy encoder
   Serial.println (virtualPosition);
//   Keyboard.print("Resett");

 }  
 
 if (TurnDetected)  {       // do this only if rotation was detected
     if (up){
     virtualPosition++;
//     Keyboard.print("Volum opp");

     }
   else{
     virtualPosition--;
//     Keyboard.print("Volum ned");
   TurnDetected = false;          // do NOT repeat IF loop until new rotation detected

   }
   Serial.print ("Count = ");  
   Serial.println (virtualPosition);
 }
}

I'd be gratefull for any help. Please keep in mind that i'm a n00b on this stuff :slight_smile:

What do you have connected to pin 2 on the Arduino?
That pin causes external interrupt 0 and if it is not connected to anything, you will get random interrupts.

There is much better code available for rotary encoders.

jremington:
What do you have connected to pin 2 on the Arduino?

'
Nothing connected to pin 2. See the image here https://photos.google.com/photo/AF1QipPZOo1ogXB294c0eO4VEtKoY7WjjaKdSEYJLWZb

You're saying i have problems because nothing is connected?

Do have have an example of what you'd say is better code?

Thanks again

That code is wrong for various reasons.

Firstly you are not protecting accesses of volatile variables from interruption - the code
in loop looks at the two volatile variables while interrupts are flying around - never do this,
alway disable interrupts first, then read / write all the volatile variables as required, then
re-enable interrupts. This means you see and update a consistent state.

Secondly you only reset TurnDetected in one arm of the if, which is never going to work!

Your ISR should be updating virtualPosition itself, which should be volatile.
(you still need to read it with interrupts disabled because its 4 bytes and the Arduino is an
8 bit machine)

You are also failing to get full resolution of the encoder by only detecting change on one of the
quadrature pins, not both of them (you only get half the resolution of the encoder)

You're saying i have problems because nothing is connected?

Yes. If pin 2 is to be used as an interrupt input, you must connect it to whatever is supposed to cause the interrupt.

I suggest to abandon what you have and find some well thought out and tested code. Rotary (shaft) encoders have been discussed many times on the forum, so use the search function and do some reading.

Hi,
The google photos requires membership.

Use REPLY rather than QUICK REPLY and it has an attachment facility, so you can post your file as an attachment.

Thanks Tom.. :slight_smile:

You may find this thread to be helpful.

Well, as I said I've ripped this code of another thread here on rotary encorders. I tried 4-5 different codes suggested in that thread. Some using interupts and some who didn't.

I need to read up more on interupts, but i just wanted a code to test out the rot encoder..

As you see, there is nothing connected to pin 2. What should i connect to pin 2?

As of now, I've just gone with a potentiometer instead. It's not optimal at all, but it'll work as a temporary solution untill i figure this out.. I'll just use the change in R to trigger volume up/down.

Thanks a lot everyone for answers, I will try to make it up for it by answering question from people who are even more unskilled than myself!

You should remove Pin 2 from your code.
If you can't manage that then connect it to ground.