The cable is only about 50mm long, inside a device.I'd suggest also adding 10K or 1K pulldowns to the unused signal wires, to damp them.
How long is the cable from the encoder? If it's more than a couple of metres I'd suggest using proper RS422 line receivers, such as a 26C32 with eg. 150 Ohm termination.
How are you trying to count the encoder steps? Interrupts generated by pin level changes, or from a timer so you read at fixed intervals?
but your issue sounds like you're not debouncing the inputs
Not many for this particular encoder with a line driver output & when you do find them they all have the same issues as what I am having.There are probably hundreds of encoder examples for Arduino out there, why not try using google.
Usually they are connected with pull-ups rather than pull-downs? - but your issue sounds like you're not debouncing the inputs?.
I don't know, but trying it won't do any harm.Not many for this particular encoder with a line driver output & when you do find them they all have the same issues as what I am having.
I did not realise that an optical encoder needs to be debounced?
I thought it best to ask people who actually can help rather than use google, you don't know what you get!
Do I really need to debounce this?
The main reason I didn't worry about debouncing is that it takes time & missed pulses are sure to follow.I don't know, but trying it won't do any harm.
But there's so much Arduino stuff out there, it's always worth having a look and seeing how other people are doing it.
Yes, that's correct 1800 line one.From the data, that presumably means you are using an 1800 line one?
For that, I'd only interrupt on one signal, both edges, and when the interrupt occurs read the other signal to get the step direction.
If necessary, connect one signal to two pins with interrupts on opposite levels, then in each interrupt read the B level. The combination of A rising or falling plus B level give the 3600 count and direction info.
I was unsure if I needed a line receiver for the very short length of cable that I am using, about 50mm long.I have used line driver quadrature encoder style outputs for decades and I have always used a RS485 line receiver to match the line driver style output of the encoder, never had any problems using very long distance runs.
RS-485 Serial Interface Explained | Same Sky
With a world of serial interfaces available, it can be hard to understand their differences and when to use each one. As my favorite engineering professor would always say, “The wonderful thing about standards is that there are so many of them to choose from.” Encoders today are...www.cuidevices.com
I'll have a look at that Les, thank you.Here is a copy of some code that may help you. I found is some years ago when I was planning on building a quadrature decoder using one of the ATtiny range. I did not take much notice of it at the time as I work mainly with assembler. I seems to use assembler embeded in C code so it should be quicker than pure C code.
Les.
Yes, I get what you are saying.Do you have to use that Arduino?
A PIC with a configurable logic cell module such as a 16F18323 or 16F18446 can pretty much read an encoder in hardware.
Or some of the more powerful DSPIC or PIC24 MC version devices have dedicated quadrature input modules.
eg.
That has a quadrature interface with 32 bit position register; see section 17 of the data sheet.
The DSPIC or PIC24 are also far better for driving graphics displays - that one has 256K flash and 32K RAM, with a 16 bit CPU.
Or, if you want to stick with the Arduino IDE, I've used an ESP32 devkit C with this library in one gadget:
GitHub - madhephaestus/ESP32Encoder: A Quadrature and half quadrature PCNT peripheral driven encoder library supporting 8 encoders
A Quadrature and half quadrature PCNT peripheral driven encoder library supporting 8 encoders - madhephaestus/ESP32Encodergithub.com
That uses some of the hardware peripherals; I only used it for a digital pot style encoder so no idea how well it works.
For the 16F18323 or other PICs that have the CLC module, it needs a few lines to configure it, then just the count increment in one interrupt routine and the decrement in the other.
/*
Dogman 15/12/2023.
Quadrature Encoder - Line Driver Output.
7200 Pulses Per Revolution - Resolution of 0.05 Degrees.
Oled 128 x 32 I2C Display.
Debounce of Button to Zero the display is not required for this application.
This Sketch has tested to be Repeatable & Accurate using a Pro Mini 5V version.
It is recommended to delete or comment out all "Serial Functions" upon installation.
Maximum rpm is unknown at this stage as this is to be used at hand rotation speeds.
*/
#include <Wire.h>
#include <Adafruit_SSD1306.h>
#define SCREEN_WIDTH 128 // OLED display width, in pixels
#define SCREEN_HEIGHT 32 // OLED display height, in pixels
#define OLED_RESET -1
#define SCREEN_ADDRESS 0x3C
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);
#define PULSES_PER_REV 7200 // Adjust this to match the encoder pulses.
int encPinA = 2; // Interrupt Pins, 2 & 3.
int encPinB = 3;
int ZeroPin = 4; // Button to Zero Display.
volatile int lastEnc = 0;
volatile long encValue = 0;
long lastencValue = 0;
int lastMSB = 0;
int lastLSB = 0;
void setup() {
display.begin();
Serial.begin(115200); // Delete on installation.
pinMode(encPinA, INPUT_PULLUP); // Enable onboard pullup resistors.
pinMode(encPinB, INPUT_PULLUP);
pinMode(ZeroPin, INPUT_PULLUP);
attachInterrupt(0, updateEnc, CHANGE); // Call updateEncoder() when any pin level change occurs.
attachInterrupt(1, updateEnc, CHANGE);
}
void updateEnc() { // Keep this out of the loop.
int MSB = digitalRead(encPinA); // MSB = most significant bit.
int LSB = digitalRead(encPinB); // LSB = least significant bit.
int enc = (MSB << 1) | LSB; // Converting the 2 pin value to single number.
int sum = (lastEnc << 2) | enc; // Adding it to the previous encoded value.
if (sum == 0b1101 || sum == 0b0100 || sum == 0b0010 || sum == 0b1011) encValue++;
if (sum == 0b1110 || sum == 0b0111 || sum == 0b0001 || sum == 0b1000) encValue--;
lastEnc = enc; // Storage value for the next time
}
void loop() {
if (digitalRead(ZeroPin) == LOW) { // Set Display to Zero
encValue = 0;
}
display.clearDisplay();
display.setTextSize(3);
display.setTextColor(SSD1306_WHITE);
display.setCursor(0, 0);
display.print((encValue % 7200 * 360.0 / PULSES_PER_REV), 2); // Convert pulses to degrees - 0.05 degree resolution.
display.display();
Serial.println((encValue % 7200 * 360.0 / PULSES_PER_REV), 2); // Delete on installation.
Serial.println(encValue); // Delete on installation.
delay(5);
}
We use cookies and similar technologies for the following purposes:
Do you accept cookies and these technologies?
We use cookies and similar technologies for the following purposes:
Do you accept cookies and these technologies?