Read Motor Speed Better By Making The RP2040 PIO Do It

A quadrature encoder provides a way to let hardware read movement (and direction) of a shaft, and they can be simple, effective, and inexpensive devices. But [Paulo Marques] observed that …read more

Apr 30, 2025 - 00:26
 0
Read Motor Speed Better By Making The RP2040 PIO Do It

A quadrature encoder provides a way to let hardware read movement (and direction) of a shaft, and they can be simple, effective, and inexpensive devices. But [Paulo Marques] observed that when it comes to reading motor speeds with them, what works best at high speeds doesn’t work at low speeds, and vice versa. His solution? PicoEncoder is a library providing a lightweight and robust method of using the Programmable I/O (PIO) hardware on the RP2040 to get better results, even (or especially) from cheap encoders, and do it efficiently.

The results of the sub-step method (blue) resemble a low-pass filter, but is delivered with no delay or CPU burden.

The output of a quadrature encoder is typically two square waves that are out of phase with one another. This data says whether a shaft is moving, and in what direction. When used to measure something like a motor shaft, one can also estimate rotation speed. Count how many steps come from the encoder over a period of time, and use that as the basis to calculate something like revolutions per minute.

[Paulo] points out that one issue with this basic method is that the quality depends a lot on how much data one has to work with. But the slower a motor turns, the less data one gets. To work around this, one can use a different calculation optimized for low speeds, but there’s really no single solution that handles high and low speeds well.

Another issue is that readings at the “edges” of step transitions can have a lot of noise. This can be ignored and assumed to average out, but it’s a source of inaccuracy that gets worse at slower speeds. Finally, while an ideal encoder has individual phases that are exactly 50% duty cycle and exactly 90 degrees out of phase with one another. This is almost never actually the case with cheaper encoders. Again, a source of inaccuracy.

[Paulo]’s solution was to roll his own method with the RP2040’s PIO, using a hybrid approach to effect a “sub-step” quadrature encoder. Compared to simple step counting, PicoEncoder more carefully tracks transitions to avoid problems with noise, and even accounts for phase size differences present in a particular encoder. The result is a much more accurate calculation of motor speed and position without any delays. Most of the work is done by the PIO of the RP2040, which does the low-level work of counting steps and tracking transitions without any CPU time involved. Try it out the next time you need to read a quadrature encoder for a motor!

The PIO is one of the more interesting pieces of functionality in the RP2040 and it’s great to see it used in a such a clever way. As our own Elliot Williams put it when he evaluated the RP2040, the PIO promises never having to bit-bang a solution again.