I'm using an Arduino Uno, 2 rotary encoders and a basic encoder code without any interrupts, ie examples that can be found on the Internet. If only one encoder is used and only one encoder program or code is used, there are no problems and everything works properly. If 2 encoders are connected, by turning one or the other clockwise everything works correctly, but by turning counterclockwise, the Arduino still registers as if it were rotating clockwise, ie the position is incremented and skips every now and then steps. Only if the encoder rotates slowly then it is possible to decrement the position but skip the steps again. I can't understand why problems arise if the code is literally copied to another encoder, and in the previous case we know that the code is correct when we use one encoder. I have tried various examples and pin configurations, but the problem is always the same, for one encoder it works perfectly, and copying the code for the other causes these problems. Also, I have tried different boards and encoders and it's the same thing. I would really appreciate if someone has a solution without interrupts because I don't wanna buy another board that support multiple interrupts.
We need to see your code. Read the forum guidelines to see how to properly post code and some hints on how to get the most from this forum.
Use the IDE autoformat tool (ctrl-t or Tools, Auto format) before posting code in code tags.
And a schematic showing how the wiring should be. Also data sheet for the encoders or a link to where you got them.
And photos showing how the wiring actually is.
I use the Encoder library. That library supports using multiple encoders on non-interrupt pins.
/* Read Quadrature Encoder
Connect Encoder to Pins encoder0PinA, encoder0PinB, and +5V.
Sketch by max wolf / www.meso.net
v. 0.1 - very basic functions - mw 20061220
*/
int val;
int encoder0PinA = 3;
int encoder0PinB = 4;
int encoder0Pos = 0;
int encoder0PinALast = LOW;
int n = LOW;
void setup() {
pinMode (encoder0PinA, INPUT);
pinMode (encoder0PinB, INPUT);
Serial.begin (9600);
}
void loop() {
n = digitalRead(encoder0PinA);
if ((encoder0PinALast == LOW) && (n == HIGH)) {
if (digitalRead(encoder0PinB) == LOW) {
encoder0Pos--;
} else {
encoder0Pos++;
}
Serial.print (encoder0Pos);
Serial.print ("/");
}
encoder0PinALast = n;
}
It is copy pasted for the other encoder, and of course variable names are changed.
Encoder datasheet:
Thanks for the code tags and formatting.
Post a schematic showing how the encoders are wired, please.
Post the code that does not work.
I tried using the library you provided and it works great. Thank you very much. The only thing is that it counts in 4 steps but I don't see that as a problem. Thanks again, the library is very nice and user friendly.
To get 1 count per click divide the read by 4 as shown in the modified basic example below.
/* Encoder Library - Basic Example
http://www.pjrc.com/teensy/td_libs_Encoder.html
This example code is in the public domain.
*/
#include <Encoder.h>
// Change these two numbers to the pins connected to your encoder.
// Best Performance: both pins have interrupt capability
// Good Performance: only the first pin has interrupt capability
// Low Performance: neither pin has interrupt capability
Encoder myEnc(5, 6);
// avoid using pins with LEDs attached
void setup()
{
Serial.begin(9600);
Serial.println("Basic Encoder Test:");
}
long oldPosition = -999;
void loop()
{
long newPosition = myEnc.read() / 4; // divide by 4 to get 1 count/click
if (newPosition != oldPosition)
{
oldPosition = newPosition;
Serial.println(newPosition);
}
}
Do you maybe know if there is some way to stop or pause counting? For example, when position crosses 0, I don't want it to go any lower. Same on the other side, when position crosses 255, I don't want it to go any higher. I tought that you can just assign new value to position and in the next iteration it would start from that but actually the program always knows the position of encoder no matter what value you assign to it.
Like this?
#include <Encoder.h>
Encoder myEnc(3, 4);
void setup()
{
Serial.begin(115200);
Serial.println("Encoder Test:");
}
long oldPosition = -999;
void loop()
{
long newPosition = myEnc.read() / 4;
if (newPosition <= 0)
{
newPosition = 0;
myEnc.write(0);
}
if (newPosition >= 255)
{
newPosition = 255;
myEnc.write(255);
}
if (newPosition != oldPosition)
{
oldPosition = newPosition;
Serial.println(newPosition);
}
}
Yeah, exactly. I wrote the same thing but didn't know that you can write to encoder because I can't find the documentation of library to see all the available functions.
The Encoder library documentation can be found here. There are only 3 functions, the constructor, read() and write().
Encoder myEnc(pin1, pin2);
Create an Encoder object, using 2 pins. You may create mulitple Encoder objects, where each uses its own 2 pins. The first pin should be capable of interrupts. If both pins have interrupt capability, both will be used for best performance. Encoder will also work in low performance polling mode if neither pin has interrupts.
myEnc.read();
Returns the accumulated position. This number can be positive or negative.
myEnc.write(newPosition);
Set the accumulated position to a new number.
The read() function returns an int (uint32_t) data type and the write(int) takes an int (uint32_t) data type as the argument.
The Encoder.h file also has some documentation.
Thank you very much for useful information.
This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.