peterhinch / micropython-samples

Assorted code ideas, unofficial MP FAQ, plus index to my other repositories.

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Encoders: please test different variants of interrupt-based quadrature encoders

IhorNehrutsa opened this issue · comments

Upload to MicroPython device drivers

  1. https://github.com/peterhinch/micropython-samples/blob/master/encoders/encoder_portable.py
    and
  2. https://github.com/IhorNehrutsa/MicroPython-quadrature-incremental-encoder/blob/main/quad_irq.py

Use https://github.com/IhorNehrutsa/MicroPython-quadrature-incremental-encoder/blob/main/quad_irq_test.py
with hardware encoder.
You may test both encoders by comment/uncomment line 7
https://github.com/IhorNehrutsa/MicroPython-quadrature-incremental-encoder/blob/bce72144e7047e083acb3083041fcddd0e27b7ad/quad_irq_test.py#L7
and line 9
https://github.com/IhorNehrutsa/MicroPython-quadrature-incremental-encoder/blob/bce72144e7047e083acb3083041fcddd0e27b7ad/quad_irq_test.py#L9

I tested both drivers on ESP32

  1. This driver catch all possible interrupts in phases A and B (contact bounces - jitter)
    image
    It overestimates Encoder.position() too much.

  2. This driver uses an encoder State transitions from https://en.wikipedia.org/wiki/Incremental_encoder
    Encoder.position () is much more accurate. The deviation is 0 or +-1 or +-2 per revolution.

Could you test drivers on other MicroPython ports?

Interesting though this is, I'm not in a position to spend time on this at the moment. I can offer these general comments.

The algorithm I use has the potential to be rock solid. I implemented it in hardware for an industrial CNC machine which required absolute accuracy from an optical encoder. I implemented synchronisation exactly as described in the Wikipedia article. Synchronisation is absolutely critical. I know most people implement a state machine, but I also know that this approach can be bit-perfect.

However an interrupt driven software based implementation is an entirely different thing, and it is vulnerable to a number of possible sources of error. Firstly there is no synchronisation unless you implement it in hardware. So there is no limit to the rate at which transitions may occur (think electrical interference or your dirty bounces). This means interrupts can be missed. Further they may be missed by occurring while a higher priority interrupt is being serviced. There may even be metastability issues in the silicon. Lastly, platforms like ESP32 and ESP8266 support only soft IRQ's which can have latencies on the order of 10-100ms. Interrupts will be missed.

The above observations are algorithm-independent.

In terms of practical outcomes, as I declare in the docs my solution is not bit-perfect even with hard IRQ's and an optical encoder. I seriously doubt that a bit-perfect software-only solution is possible. In a typical application with an encoder switch bit-perfect accuracy is not required, especially as there is often user feedback. I use an encoder switch in my micro-gui library which has been extensively tested on Pyboard D, ESP32 and Pico. The visual feedback from the GUI means that discrepancies are undetectable.