Hello everyone
I've been trying to count using a rotary encoder for a project, however, the rotary encoder counts one step then on the next step the program sort of stops and the serial monitor does so, nothing works, and then if I rotate it one step further everything goes back to normal, but it does the same thing on the next step. So at one step it stops the program and nothing runs, then at the other everything is back to normal and this keeps happening at alternate steps.
This is the encoder i am using.
below is the code.
#include <Arduino.h>
#define CLK 12
#define DIO 11
const int PinA = 2; //PinA = CLK pin
const int PinB = 3; //PinB = DT pin
const int PinSW = 8; //PinSW = switch pin
int lastCount = 50;
// Updated by the ISR
volatile int count = 50;
unsigned long previoustime;
// ISR function
void isr () {
static unsigned long lastInterruptTime = 0;
unsigned long interruptTime = millis();
// If interrupts come faster than 5ms, assume it's a bounce and ignore
if (interruptTime - lastInterruptTime > 5) {
if (digitalRead(PinB) == LOW)
{count-- ;}
else { count++ ;}
//Restrict count from going above 56 and below 50
if (count == 57){count = 50;}
else if (count == 49){count = 56;}
}
lastInterruptTime = interruptTime;
}
void setup() {
Serial.begin(9600);
pinMode(PinA, INPUT);
pinMode(PinB, INPUT);
pinMode(PinSW, INPUT_PULLUP);
attachInterrupt(digitalPinToInterrupt(PinA), isr, LOW);
Serial.println("Ready to go!");
}
void loop() {Serial.println(count);}
Hope everyone is able to understand what I'm trying to ask.
Thanks for your time.
Hi Larry,
I have used the rotary encoder module directly, without adding any additional capacitors, it has the 10k ohm resistors already only the resistor dor the switch was not placed(now connected with the pullup resistor).
each pin of the encoder is connected directly to the Arduino as defined by the code, and yes I have given 5v.
Hi Sherman,
I have tried both FALLING and CHANGE.
Both of them resulted in the same problem.
I will share more pictures of what the problem is as @LarryD said, and hopefully it will make it more clear.
What do you get with this simple test code without interrupts? I test the code on my Uno with a rotary encoder like yours and I get the expected output (see below).
I think you may have a fundamental misunderstanding of how the encoder works. You're trying to use one input as a step indication, and sample the other input to work out the direction. This has a serious problem. If the encoder shaft is rotating back and forth around the point where the 'clock' input changes, but not going far enough to change the other input, your counter will act as if the unit was continuously moving in one direction. You will also miss a count 50% of the time whenever the direction of movement changes.
A better way to look at the output of the encoder is to consider it as a two bit Grey Code counter. That counts in the following sequence:
0 0
0 1
1 1
1 0
0 0
Notice that whether you count up or down, only one bit changes each time. what your code needs to do is grab both the input values as soon as either input changes. compare the current value with the previous value, and increment or decrement the count as appropriate.
I don't know how comfortable you are with bit shifting, but what I would do is something like this:
const int greyLookup[]={0,1,99,-1,-1,0,99,+1,99,-1,0,+1,+1,99,-1,0};
static int previous;
int current;
current = (digitalRead(PinA)<1)+digitalRead(PinB);
count += greyLookup[ (previous<<2) + current ];
previous = current;
What that code is doing is using the two bits from thee previous count, shifting them over and adding the two bits of the previous count. The result of that is used as an index into a table. The table values are the amount to add or subtract from the count. The values set to 99 are combinations of current and previous that can only happen if a step gets missed.