Reading Rotary Encoder pulse output at fast RPM - Page 1
Forum section: electronics / general

author: AlwaysAbia
author_rank: Contributor
timestamp: March 04, 2024, 11:07:22 am
content: Second time poster here.I am using a 200 Pulse Rotary Encoder to determine the angular position of some rotary stage mechanism. What are some good ways to reliably count these pulses at high rotation speeds in order to accurately determine angular position? I have tried using an Arduino to see the changes in digitalRead(), which proved to fail at quite a low speed, then I tried registering each pulse using interrupts, but I think the Arduino Uno board ignores interrupts triggered during an ongoing ISR, so at higher speeds it would still miss some of the pulses. I was thinking of switching to an STM32 board since it offers a much higher clock speed.If you have any experience with reading high speed pulse inputs reliable, or have any suggestions and tips in general, I would be very happy to read them, Thank you :3

author: langwadt
author_rank: Super Contributor
timestamp: March 04, 2024, 12:02:04 pm
content: STM32 has quadrature decoding hardware in several timers, so that would be easy

author: Berni
author_rank: Super Contributor
timestamp: March 04, 2024, 12:08:22 pm
content: Quite a few MCUs (Like STM32, PIC, AVR, ESP..etc) have timers with a quadrature input feature where you just connect the A and B signals to it and they count up and down according to the encoder.But even at a count rate of like 10 000 pulses per second any decent MCU using interrupts with a well written ISR handler should keep up just fine.

author: H.O
author_rank: Frequent Contributor
timestamp: March 04, 2024, 06:41:17 pm
content: Yes, if possible use a chip with timer(s) capable of handling quadrature encoders directly.Or if your uC lacks such timer(s) you can use external logic to decode the encoder signals into up/down pulses and feed those into two standard timer/counters and then simply subtract one count from the other. The complexity of that logic depends on if you need x1, x2 or x4 decoding.There are ICs like the LS7183 but when I needed to this a while a back I programmed an 8 pin PIC to do the job and managed to get over 200.000 edges per second in x4 mode with code written in PIC BASIC PRO. If someone were to do it in assembly I imagine it would be even more capable.

author: SiliconWizard
author_rank: Super Contributor
timestamp: March 04, 2024, 08:36:43 pm
content: That's the rotary encoder itself that will have a hard time.

author: Ground_Loop
author_rank: Frequent Contributor
timestamp: March 04, 2024, 09:12:16 pm
content: I've done this with a PIC24 using a Capture/compare peripheral. I monitored a motor up to 15,000 RPM and four pulses per revolution without any problem at all. I didn't go any higher speed as the motor was only rated for 5000 rpm. I also have a 300 PPR optical encoder hooked to a STM32 timer/counter that doesn't miss a pulse up to around 1000 RPM.

author: langwadt
author_rank: Super Contributor
timestamp: March 04, 2024, 09:39:23 pm
content: afair the Omron type rotary encoder are rated for ~50-100kHz

author: selcuk
author_rank: Frequent Contributor
timestamp: March 04, 2024, 09:55:33 pm
content: Most affordable MCUs should count pulses coming out of such a mechanical device. But you cannot use software for high speeds. It will eventually skip some pulses. It should be done on a hardware peripheral. For example, I tried ESP32 PCNT peripheral to count a 20MHz input and it was fine.I didn't try myself but there is a rotary encoder example project if you consider using ESP32 series:https://github.com/espressif/esp-idf/tree/master/examples/peripherals/pcnt/rotary_encoder

author: Peabody
author_rank: Super Contributor
timestamp: March 04, 2024, 11:09:51 pm
content: Is this a mechanical rotary encoder? It seems you would need to have no bounce at all for it to work at high speeds, which might call for an optical encoder.An Arduino does not ignore interrupts that occur while another ISR is completing, but it will delay servicing the new interrupt, and that may be enough to throw things off. If you don't need millis() for anything, you can turn off that interrupt in an Arduino. But I think you're still going to be limited using an Arduino. The speed is probably too slow, and there's too much overhead unless you want to get down into assembler. But what's the situation with switch bounce?

author: PCB.Wiz
author_rank: Super Contributor
timestamp: March 04, 2024, 11:37:09 pm
content: Quote from: AlwaysAbia on March 04, 2024, 11:07:22 amHow fast is this needing to count ?You can buy LS7366R modules for $25, that will give you very large headroom in speed and number of bits.

author: mianos
author_rank: Regular Contributor
timestamp: March 05, 2024, 02:09:59 am
content: Coincidentally, after many years with the esp8266 and esp32, I just used the PCNT hardware in the esp32 last weekend.I tested it by counting my GPSDO's 10Mhz output through a TLV3501, catching the overflow/reset on a 25,000 count with an interrupt handler, 40 times a second.As far as I can tell it does not miss a single count. I need more hardware to verify less than about 10 missing.Im I pretty sure you should be abled to track an encoder with two PCNT channels.This said, I have some hardware that generates about 20,000 interrupts per second in the esp32, again, as far as I can see, (and much better verified), it does not miss any.

author: mino-fm
author_rank: Regular Contributor
timestamp: March 05, 2024, 09:20:34 am
content: Quote from: langwadt on March 04, 2024, 09:39:23 pmThat is no problem for Arduino (AVR). An example for ATTiny202 using IIC-connection:http://mino-elektronik.de/mt12_iic/mt12_iic.htm#qcnt_tiny202It works up to 400 kHz.

author: Atlan
author_rank: Frequent Contributor
timestamp: March 12, 2024, 03:21:15 pm
content: I have a 100imp optical encoder on the motor from the Washing machine and the atmega 328 performs PID regulation from 800 to 16000 rpm. On the lathe I have 2000imp up to 2000 rpm, it works on atmega328. Only on interrupt int0 or int1.

author: cv007
author_rank: Frequent Contributor
timestamp: March 12, 2024, 07:00:55 pm
content: QuoteMore info would be helpful- such as what kind of speeds involved, is this a single direction mechanism or is there direction changes involved, what is the encoder in use, is the encoder output 'clean' or conditioned in some way, etc.Counting pulses is relatively easy if there is no direction to worry about. In your case with a mega328 it has a 16bit counter that can use an external pin as its clock source (T1), and assuming only a single direction is involved and simply counting (clean) pulses is needed, the timer will do your counting via the encoder to T1.Once your timer is counting these pulses, then its just a matter of deciding how to deal with the timer- you could set to ctc mode with a TOP value of 199, where an irq (ICR1 for CTC mode 12) would handle overflow counting (if needed) and the timer value would have the current angular position in terms of 0-199. You then also have several compare match irq's to use if wanted, so can also interrupt at specific 'positions' if wanted.The T1 clock is not synchronous to the internal 16MHz clock, so there will be a few clock cycles delay syncing external to internal but there is not going to be any mechanical derived frequency where this would be a problem.

author: mino-fm
author_rank: Regular Contributor
timestamp: March 19, 2024, 10:41:03 am
content: In the mean time I made another very easy solution using RP2040 Pico-board. Maybe you didn't noticed that until now.https://www.eevblog.com/forum/projects/fast-12-ch-quadrature-decoder-abindex-rp2040-arduino/