peterhinch / micropython-samples

Assorted code ideas, unofficial MP FAQ, plus index to my other repositories.
MIT License
442 stars 91 forks source link

Encoders #23

Closed IhorNehrutsa closed 2 years ago

IhorNehrutsa commented 2 years ago

These changes may seem extremely grandiose and time-consuming, but if you look at the commits, it will be much easier. I tested all encoders, except the encoders/encoder.py

The ESP32: New features PCNT() and QUAD(). #6639 will conform to this PR.

IhorNehrutsa commented 2 years ago

This PR is backwards compatible. It brings all encoders to a base consistent API structure. Hope for approval. Thanks for your time.

peterhinch commented 2 years ago

The purpose of my micropython-samples repo is to provide code samples. This is distinct from my other repos which aim to produce fully supported applications which work "out of the box". The encoder samples exist to illustrate these points:

  1. To illustrate the exclusive or algorithm which is fast and minimal.
  2. To discuss the fundamental problems in interfacing to encoders.
  3. To discuss the issues in interfacing an interrupt driven encoder driver with uasyncio applications.

The encoder code samples exist to illustrate the points in the doc. As such I regard them as complete.

If you decide to produce and support a library of encoder interfaces please provide me with a URL and I will be happy to link to it in my docs. Aside from that I don't plan to introduce any changes to my code, which serves its intended purpose as a set of samples to adapt or build on.

IhorNehrutsa commented 2 years ago

Please cherry-pick the commit Encoders/encoder_timed.py: Fix ZeroDivisionError

IhorNehrutsa commented 2 years ago

The tested code is:

import utime
from machine import Pin
from encoder_timed import EncoderTimed
enc = EncoderTimed(Pin(16), Pin(17))
print(utime.ticks_us(), enc.tlast, enc.tprev)
print(enc.rate())

If you run it less than 2 seconds after the reset, a ZeroDivisionError will be raised:

>>> from machine import reset
>>> reset()
ets Jun  8 2016 00:22:57

rst:0xc (SW_CPU_RESET),boot:0x13 (SPI_FAST_FLASH_BOOT)
configsip: 0, SPIWP:0xee
clk_drv:0x00,q_drv:0x00,d_drv:0x00,cs0_drv:0x00,hd_drv:0x00,wp_drv:0x00
mode:DIO, clock div:2
load:0x3fff0030,len:5556
load:0x40078000,len:12696
load:0x40080400,len:4308
entry 0x400806b0
MicroPython v1.15-234-gfa8aa5779-dirty on 2021-10-06; ESP32 module with ESP32
Type "help()" for more information.
>>> %Run -c $EDITOR_CONTENT
1523114 0 0
Traceback (most recent call last):
  File "<stdin>", line 6, in <module>
  File "encoder_timed.py", line 45, in rate
ZeroDivisionError: divide by zero
>>> 
IhorNehrutsa commented 2 years ago

Please cherry-pick the commit Encoders: Fix position rounding

It replaces

  self._pos = value // self.scale

to

  self._pos = round(value / self.scale)
peterhinch commented 2 years ago

If you run it less than 2 seconds after the reset, a ZeroDivisionError will be raised

Good point, I never thought to test that case. I have changed the code to hopefully cater for all possible cases to ensure that .rate() can never divide by zero or produce invalid results. I've also incorporated the rounding fix.

Thank you for those suggestions.