Page 1 of 2
Rotary encoder with asyncio?
Posted: Sat Feb 27, 2021 10:56 am
by ilium007
Is there a rotary encoder library that makes use of micropython-async (
https://github.com/peterhinch/micropython-async) instead of interrupts?
I have been playing with uencoder (
https://gitlab.com/WiLED-Project/uencoder) but would like to see how this could be implemented using asyncio.
I am assuming I would need to create two asyncio tasks to replace the pin interrupts
Code: Select all
if use_interrupts:
mode = Pin.IRQ_RISING | Pin.IRQ_FALLING
self.pin_A_irq = self.pin_A.irq(trigger=mode, handler=self.process)
self.pin_B_irq = self.pin_B.irq(trigger=mode, handler=self.process)
# TODO: Implement a polling-only method, with asyncio
This is a case for interrupts or hardware
Posted: Sat Feb 27, 2021 2:25 pm
by pythoncoder
Much as I frequently advocate
uasyncio rather than interrupts, this is an exception. Please look at
this link.
Encoders present a challenge because they can produce a stream of pulses which don't signify motion. This happens if the machine stops with the encoder at a physical transition between on and off: any vibration can result in a string of pulses as the optical device jitters around an edge. The algorithm for dealing with this is simple, but does need to be capable of a fast response.
The solution is to have an interrupt driven process which maintains a position value: the latter may then be read by your
uasyncio code as required.
The Pyboard can do even better as it can be configured to decode one or two encoders in hardware. This enables it to handle very fast rotation rates.
Re: This is a case for interrupts or hardware
Posted: Sun Mar 27, 2022 11:15 am
by ilium007
pythoncoder wrote: ↑Sat Feb 27, 2021 2:25 pm
The Pyboard can do even better as it can be configured to decode one or two encoders in hardware. This enables it to handle very fast rotation rates.
Sorry to dig this up again but have only just got back into this project after building a house and all the mess that is Covid.
Do you have some more info on using the STM32F405 hardware quadrature decoding? I'm using an Adafruit STM32F405 board because I couldn't easily get hold of a Pyboard to test with.
*Edit* found the info here:
https://github.com/dhylands/upy-example ... encoder.py
Re: Rotary encoder with asyncio?
Posted: Sun Mar 27, 2022 6:50 pm
by rkompass
Have a look at
https://github.com/dhylands/upy-examples encoder2.py and encoder3.py.
Re: Rotary encoder with asyncio?
Posted: Mon Mar 28, 2022 9:15 am
by pythoncoder
@illum07 Since posting the above I wrote
this class for interfacing an encoder to
uasyncio.
The driver uses interrupts to handle the transitions, but performs callbacks in a
uasyncio context. Simple interrupt driven drivers have the drawback that callbacks occur in an IRQ context and are subject to all the limitations that involves. In this driver the callbacks have no such limitations. Also the driver enables the encoder's sensitivity to be controlled, so that callbacks occur only when the position has changed by N edges.
Re: Rotary encoder with asyncio?
Posted: Mon Mar 28, 2022 10:28 am
by ilium007
Thanks, I'll take a look.
Re: Rotary encoder with asyncio?
Posted: Mon Mar 28, 2022 11:09 am
by ilium007
I have had an initial look at the Encoder class but can't make it read anything through its value() method. I have set up an Encoder object and passed in the two machine.Pin's from the rotary encoder. I have tested that the encoder is producing quadrature grey code with an oscilloscope.
Code: Select all
>>> from machine import Pin
>>> from encoder import Encoder
>>>
>>> pina = Pin("A4", Pin.IN, Pin.PULL_UP)
>>> pinb = Pin("A5", Pin.IN, Pin.PULL_UP)
>>> encoder1 = Encoder(pina, pinb)
>>> encoder1.value()
0
>>> encoder1.value()
0
>>>
I get no value change when turning the encoder
Re: Rotary encoder with asyncio?
Posted: Mon Mar 28, 2022 11:16 am
by ilium007
Where in encoder.py does the class do the actual grey code decoding?
Re: Rotary encoder with asyncio?
Posted: Mon Mar 28, 2022 2:03 pm
by pidou46
They have been multiple attempts to include PCNT esp32's hardware counter in firmware, but it stalled.
As a workaround, I have jump on a AS5600 magnetic encoder.
The main advantages I found is :
- it's super easy to setup mechanically
- setup is been done using i2c bus
- reading can done via i2c, 0-1vcc
- absolute measurement
- fast response time
- quit precise, given the resolution. I haven't made any measurement of the real precision.
- low cost
https://fr.aliexpress.com/item/10050035 ... 5e5bQzdDeb
drawback: it is limited to one turn
I hope hardware pulse counter of esp32 will be supported one day, but until now I quite happy with this workaround.
Re: Rotary encoder with asyncio?
Posted: Mon Mar 28, 2022 8:24 pm
by ilium007
I’m using the Adafruit STM32F405 board to prototype with.