Hi everyone
I built a project that has a rotary encoder with push button in it but didn't work well so I tried THIS example code.
It keeps outputting nonstop unless I give the rotary a notch in either direction but it will start outputting crazy if it's moved.
I'm using one of those without board so no VIN.
Any thoughts?
Post your code so we can see it without clicking on a link
The problem is that the code is fundamentally rubbish. The code from a rotary encoder should be a self correcting code, but that code isn't.
I would use a library that takes that into account like this one:-
Rotary Library
from Encoder Library, for Measuring Quadarature Encoded Position or Rotation Signals
It implements this state machine.
Note there are a lot of Arduino rotary encoder libraries that do not to this correctly but their authors think they do.
First of all, use Physical 10K pullups and add a 10nF capacitor (to GND) on all 3 pins.
Then show us your code.
what host microcontroller are you using?
show a schematic of wiring?
try using the internal pullup resistors
pinMode(CLK, INPUT_PULLUP);
pinMode(DT, INPUT_PULLUP);
pinMode(SW, INPUT_PULLUP);
It sounds like contact bounce, give us a schematic as requested by @horace and the code as requested by @mancera1979.
This is the library I used
I think the code is messy since I had to edit it a lot.
If internal pullup doesn't work I'll use external.
But I specifically used a example code that didn't use external and it kept dancing around.
It's an Uno.
Wiring is
Main Pin --> D3
Sec Pin --> D4
BTN Pin --> D5
All with 100nF cap to GND
if the encoder code is using interrupts the interrupt enabled pins on the UNO are 2 and 3
This the example code for rotary encoder without VIN and it does have the internal pullup in it
// Define the connections to the Arduino
const int pinCLK = 2; // Connect to CLK on the rotary encoder
const int pinDT = 3; // Connect to DT on the rotary encoder
const int pinSW = 4; // Connect to SW on the rotary encoder
// Variables to hold the current and last encoder position
volatile int encoderPos = 0;
int lastEncoderPos = 0;
// Interrupt service routine for CLK
void isrCLK() {
if (digitalRead(pinDT) != digitalRead(pinCLK)) {
encoderPos++; // Clockwise
} else {
encoderPos--; // Counterclockwise
}
}
// Interrupt service routine for SW
void isrSW() {
// Implement switch functionality (e.g., reset position)
encoderPos = 0;
}
void setup() {
pinMode(pinCLK, INPUT_PULLUP);
pinMode(pinDT, INPUT_PULLUP);
pinMode(pinSW, INPUT_PULLUP);
// Attach the interrupt service routines
attachInterrupt(digitalPinToInterrupt(pinCLK), isrCLK, CHANGE);
attachInterrupt(digitalPinToInterrupt(pinSW), isrSW, FALLING);
Serial.begin(9600);
}
void loop() {
if (lastEncoderPos != encoderPos) {
Serial.print("Encoder Position: ");
Serial.println(encoderPos);
lastEncoderPos = encoderPos;
}
}
The encoder in the example from post #1 is soldered onto a board that already includes the resistors and handles debounce with a simple 1 ms delay.
I seem to remember using the td_libs_Encoder library on a UNO and it worked OK
But... is the common pin connected to GND? Then there's still the debounce issue (post #4), and finally the correct edge detection (post #3 — one encoder step involves reading four edges). And interrupts are not a magical solution — in fact, they can introduce additional concurrency issues with other parts of the code.
That example is for encoder with board and VIN.
Post 12 is example without.
I tested it again with example code from post #12 and button doesn't work and it prints positions erratically mostly up and can't go down without cap, and just one position up and one position down with cap regardless of the direction of the nob.
What is the library you used? I expected to see a link to it, but the rest of the reply is just blank.
I don't see any libiary being used in your post#12 either.
Are you just spamming us?
This is rubbish, and it will produce random movements. ANY A/D converter only produces a result that is plus or minus one significant bit, so asking if it is not equal to the last one will produce what you see.
This line should be:-
if (abs(lastEncoderPos - encoderPos) > threshold){
with threshold being a variable containing how much movement you must have before you trigger a pulse. I would recommend that you start this at 4 or 8 and see how that goes.
and
You may just have a bad encoder.
Do you have a DMM to do some testing?