Thanks Jim P. This is working for me. If useful, consider it. Even with imperfections, works fine. I ran the knob as faster as my fingers could, with no fails. I found few examples in the web. Sorry if this is not the place to publish.
// This code is for a debounced hardware, checking debounce/timing fails
// Hardware:
// 10k pullUp, then 1k series, then 100nF (RC = 0.0011s), then ports of any
schmitt-trigger IC
// davidllpz - 01/26
#include <PinChangeInterrupt.h> //
#define CLK_A 5
#define DT_B 6
#define SW_PushB 7
volatile int counter = 0;
int CLK_status;
int lastCounter;
void setup() {
Serial.begin(9600);
pinMode(CLK_A, INPUT_PULLUP);
pinMode(DT_B, INPUT_PULLUP);
pinMode(SW_PushB, INPUT_PULLUP);
attachPinChangeInterrupt(digitalPinToPinChangeInterrupt(CLK_A), getCLK_A, RISING);
}
void loop() {
// Your stuff here
}
// (ISR)
void getCLK_A() {
CLK_status = digitalRead(CLK_A);
if (digitalRead(DT_B) != CLK_status) {
counter++; // Clockwise
if (counter != lastCounter + 1) {
Serial.println ("Failed!");
}
lastCounter = counter;
} else {
counter--; // Counter-clockwise
if (counter != lastCounter - 1) {
Serial.println ("Failed!");
}
lastCounter = counter;
}
Serial.print("Counter: ");
Serial.println(counter);
}
Thanks. Even ‘lastCounte = counter’ must be out of ‘else’, and other stuffs that can be simplified. What matters is that it works. I speeded up my fingers and don’t fails. Matters the hardware too.
10k pull-up. OK.
1k / 100nF hardware debounce. OK.
Schmitt trigger IC. Not necessary.
INPUT_PULLUP. Not necessary.
Ports of ATmega328P contain Schmitt triggers.
You increment a number and immediately check if it has incremented.
It may miss pulses, count ghost pulses, but will never print "failed" (unless CPU is really broken).
Turns out nope but you can hardware debounce or even software debounce…
I look at Gray Code and see that only 1 bit changes per step;
A B
0 0
1 0
1 1
0 1
0 0
In a state machine same direction movement could advance state on the first change or maybe 1ms later (debounce switch usually takes 2+ms) watch the other pin while the first finishes debouncing… or something like that, this is just a notion to speed the potential turn speed.
Change direction, same bit changes… gotta watch them both for ‘the ringer’, already complicates the above but what I see is that while either bit bounces, there is a window to decide&act take advantage of. Turn fast enough, both could be bouncing at the same x-many reads but since the 1st transition that starts the bounce sets the read state instead of waiting for stability, we get moar cyclez though we still have to catch end of bounce before the next click transition. I assume both pins would be read on the same port giving 2 bits at high frequency.
There are encoders with more than 2 data pins AFAIK.
Some encoders have sliding contacts. Bouncing is likely.
Some encoders have optical discs. No bounce unless shaft is vibrating.
Some even have an analog pick-up and convert it to the outputs.
‘In general’, it is recommended less instruction into ISR. In this case, prints once when interrupts occur. Otherwise, any loop will print. You choose. But not necessarily rules are broken…
I was not trying to say "no printing inside an ISR is a law that you must obey", but it is a rule of best practice to return control to the mcu for time-sensitive tasks. Printing takes "forever" so inc/dec/flag in the ISR and exit, then take care of those events in "the loops."
It's like a clutch in a car. You can shift a car by using the accelerator or the brake and coming to a stop. That's a "rule" that can be broken, but effects the power train and your driving experience, and using the "rule" of the clutch makes it better. You are "right" in whatever decision you make. I just won't fly on any of your airplanes.