Dear All,
As stated in the title, I'm close to get rotary encoder decoding. But not enough as it doesn't work.
So as I'm stuck, I have written below code in order to understand the mechanical behavior of my encoder.
I know there is a lot of threads (here and at other places) about this subject, and I have aleady tried al lot of solutions or approach that can be find over there. But I'm still struggling...
The rotary encoder is a CTS288 (full ref is 288T232R161A2); Rotary encoder Datasheet.
I have 2 of them, and both show the same behavior.
The project is a Sim Racing wheel, using this encoder as +/- knobs for TC and ABS.
This model of encoder is widely used for this purpose.
I've tried with a cheap rotary encoder from a Beginner kit, behavior is identical.
The ESP32 is from AZ Delivery; ESP32 Datasheet
Current pins are 12 and 25, but was previously 18 and 19.
All pins can be used for interrupts.
Software debounce is created without delay() function (because of interrupts).
Simple debounce attempt, don't be shy if it is inapproppriate or very badly coded!
I have manually controlled the encoder (multimeter in continuity mode), both pin acts as it is supposed to do (2 bits Gray code: 00, 01, 11, 10, 00, ....).
But I still have issue with:
- Same values randomly read 2 times in a row, despite rotating the shaft even with 1 click (whatever is the direction or the speed).
- Values don't follow the correct sequence (00, 01, 11, 10, 00...)
Please, could you have a look on the code hereunder?
- I would like to know first if there is an obvious mistake in my code
- If so, please could you lead me without providing the solution directly?
// Software Debouncing - Mechanical Rotary Encoder
// Rotary CLK to pin 12
// Rotary DT to pin 25
#define encoder0PinA 12
#define encoder0PinB 25
unsigned long previousMillis = 0;
const long debounce = 80;
int previousStateA;
int previousStateB;
int currentStateA;
int currentStateB;
int flag;
void setup() {
pinMode(encoder0PinA, INPUT_PULLUP); // Using internal pullup resistor
pinMode(encoder0PinB, INPUT_PULLUP);
attachInterrupt(encoder0PinA, rotEncoder, CHANGE); // Need to detect both rising or falling signal
attachInterrupt(encoder0PinB, rotEncoder, CHANGE);
previousStateA = digitalRead(encoder0PinA); // Storage of state before the interrupt
previousStateB = digitalRead(encoder0PinB);
Serial.begin (115200);
}
void rotEncoder() {
unsigned long currentMillis = millis();
if (currentMillis - previousMillis >= debounce) {
previousMillis = currentMillis;
currentStateA = digitalRead(encoder0PinA); // Simple read of current HIGH or LOW state
currentStateB = digitalRead(encoder0PinB);
Serial.print("A: "); Serial.print(currentStateA);
Serial.print(" "); Serial.print(currentStateB);
Serial.println(" :B"); // Serial prints only for debugging; won't be used in final code
if (previousStateA == currentStateA && previousStateB == currentStateB) { // Triggerd only if current state of both pins are equal to previous
flag = 1;
}
previousStateA = currentStateA;
previousStateB = currentStateB;
}
}
void loop() {
if (flag == 1) {
Serial.println("Same values as previous!");
flag = 0;
}
}
Exemple of Serial monitor (rotating the encoder in one direction only:
19:39:36.132 -> A: 1 1 :B
19:39:36.132 -> Same values as previous!
19:39:36.822 -> A: 0 1 :B
19:39:37.469 -> A: 1 0 :B
19:39:38.158 -> A: 1 0 :B
19:39:38.158 -> Same values as previous!
19:39:38.942 -> A: 0 1 :B
19:39:39.726 -> A: 0 1 :B
19:39:39.726 -> Same values as previous!
19:39:40.369 -> A: 0 0 :B
19:39:40.968 -> A: 1 0 :B
19:39:41.614 -> A: 1 1 :B
19:39:42.213 -> A: 0 1 :B
19:39:42.812 -> A: 0 0 :B
19:39:43.504 -> A: 1 0 :B
19:39:44.195 -> A: 1 1 :B
19:39:44.792 -> A: 0 0 :B
19:39:45.390 -> A: 0 0 :B
19:39:45.390 -> Same values as previous!
19:39:46.036 -> A: 1 0 :B
19:39:46.681 -> A: 0 1 :B
Thank you in advance for your time!