8000 docs/library/machine: Add docs for Counter and Encoder. · micropython/micropython@7ace9a2 · GitHub
[go: up one dir, main page]

Skip to content

Commit 7ace9a2

Browse files
jonathanhoggjimmo
authored andcommitted
docs/library/machine: Add docs for Counter and Encoder.
Add documentation for `machine.Counter` and `machine.Encoder` as currently implemented by the esp32 port, but intended to be implemented by other ports. Originally authored by: Ihor Nehrutsa <Ihor.Nehrutsa@gmail.com> and Jonathan Hogg <me@jonathanhogg.com>. Signed-off-by: Jim Mussared <jim.mussared@gmail.com>
1 parent 6fc75bf commit 7ace9a2

File tree

6 files changed

+198
-0
lines changed

6 files changed

+198
-0
lines changed

docs/esp32/quickref.rst

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -445,6 +445,26 @@ Use the :ref:`esp32.PCNT <esp32.PCNT>` class::
445445
counter.value(0) # reset counter
446446
count = counter.value(0) # read and reset
447447

448+
The PCNT hardware supports monitoring multiple pins in a single unit to
449+
implement quadrature decoding or up/down signal counters.
450+
451+
See the :ref:`machine.Counter <machine.Counter>` and
452+
:ref:`machine.Encoder <machine.Encoder>` classes for simpler abstractions of
453+
common pulse counting applications. These classes are implemented as thin Python
454+
shims around the ``PCNT()`` class::
455+
456+
from machine import Pin, Counter
457+
458+
counter = Counter(0, Pin(2)) # create a counter as above and start it
459+
count = counter.value() # read the count as an arbitrary precision signed integer
460+
461+
encoder = Encoder(0, Pin(12), Pin(14)) # create an encoder and begin counting
462+
count = encoder.value() # read the count as an arbitrary precision signed integer
463+
464+
Note that the id of these ``Counter()`` and ``Encoder()`` objects is an
465+
arbitrary number, each uniquely identified object will be allocated a free PCNT
466+
unit.
467+
448468

449469
Software SPI bus
450470
----------------

docs/library/esp32.rst

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -275,6 +275,10 @@ abstractions of common pulse counting applications.
275275
value. Thus the ``IRQ_ZERO`` event will also trigger when either of these
276276
events occurs.
277277

278+
See the :ref:`machine.Counter <machine.Counter>` and
279+
:ref:`machine.Encoder <machine.Encoder>` classes for simpler abstractions of
280+
common pulse counting applications.
281+
278282

279283
.. _esp32.RMT:
280284

docs/library/machine.Counter.rst

Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
.. currentmodule:: machine
2+
.. _machine.Counter:
3+
4+
class Counter -- pulse counter
5+
==============================
6+
7+
Counter implements pulse counting by monitoring an input signal and counting
8+
rising or falling edges.
9+
10+
Minimal example usage::
11+
12+
from machine import Pin, Counter
13+
14+
counter = Counter(0, Pin(0, Pin.IN)) # create Counter for pin 0 and begin counting
15+
value = counter.value() # retrieve current pulse count
16+
17+
Availability: **ESP32**
18+
19+
Constructors
20+
------------
21+
22+
.. class:: Counter(id, ...)
23+
24+
Returns the singleton Counter object for the the given *id*. Values of *id*
25+
depend on a particular port and its hardware. Values 0, 1, etc. are commonly
26+
used to select hardware block #0, #1, etc.
27+
28+
Additional arguments are passed to the :meth:`init` method described below,
29+
and will cause the Counter instance to be re-initialised and reset.
30+
31+
On ESP32, the *id* corresponds to a :ref:`PCNT unit <esp32.PCNT>`.
32+
33+
Methods
34+
-------
35+
36+
.. method:: Counter.init(src, *, ...)
37+
38+
Initialise and reset the Counter with the given parameters:
39+
40+
- *src* specifies the input pin as a :ref:`machine.Pin <machine.Pin>` object.
41+
May be omitted on ports that have a predefined pin for a given hardware
42+
block.
43+
44+
Additional keyword-only parameters that may be supported by a port are:
45+
46+
- *edge* specifies the edge to count. Either ``Counter.RISING`` (the default)
47+
or ``Counter.FALLING``. *(Supported on ESP32)*
48+
49+
- *direction* specifies the direction to count. Either ``Counter.UP`` (the
50+
default) or ``Counter.DOWN``. *(Supported on ESP32)*
51+
52+
- *filter_ns* specifies a minimum period of time in nanoseconds that the
53+
source signal needs to be stable for a pulse to be counted. Implementations
54+
should use the longest filter supported by the hardware that is less than
55+
or equal to this value. The default is 0 (no filter). *(Supported on ESP32)*
56+
57+
.. method:: Counter.deinit()
58+
59+
Stops the Counter, disabling any interrupts and releasing hardware resources.
60+
A Soft Reset should deinitialize all Counter objects.
61+
62+
.. method:: Counter.value([value])
63+
64+
Get, and optionally set, the counter value as a signed integer.
65+
Implementations must aim to do the get and set atomically (i.e. without
66+
leading to skipped counts).
67+
68+
This counter value could exceed the range of a :term:`small integer`, which
69+
means that calling :meth:`Counter.value` could cause a heap allocation, but
70+
implementations should aim to ensure that internal state only uses small
71+
integers and therefore will not allocate until the user calls
72+
:meth:`Counter.value`.
73+
74+
For example, on ESP32, the internal state counts overflows of the hardware
75+
counter (every 32000 counts), which means that it will not exceed the small
76+
integer range until ``2**30 * 32000`` counts (slightly over 1 year at 1MHz).
77+
78+
In general, it is recommended that you should use ``Counter.value(0)`` to reset
79+
the counter (i.e. to measure the counts since the last call), and this will
80+
avoid this problem.
81+
82+
Constants
83+
---------
84+
85+
.. data:: Counter.RISING
86+
Counter.FALLING
87+
88+
Select the pulse edge.
89+
90+
.. data:: Counter.UP
91+
Counter.DOWN
92+
93+
Select the counting direction.

docs/library/machine.Encoder.rst

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
.. currentmodule:: machine
2+
.. _machine.Encoder:
3+
4+
class Encoder -- quadrature decoding
5+
====================================
6+
7+
Encoder implements decoding of quadrature signals as commonly output from
8+
rotary encoders, by counting either up or down depending on the order of two
9+
input pulses.
10+
11+
Minimal example usage::
12+
13+
from machine import Pin, Encoder
14+
15+
counter = Counter(0, Pin(0, Pin.IN), Pin(1, Pin.IN)) # create Encoder for pins 0, 1 and begin counting
16+
value = counter.value() # retrieve current count
17+
18+
Availability: **ESP32**
19+
20+
Constructors
21+
------------
22+
23+
.. class:: Encoder(id, ...)
24+
25+
Returns the singleton Encoder object for the the given *id*. Values of *id*
26+
depend on a particular port and its hardware. Values 0, 1, etc. are commonly
27+
used to select hardware block #0, #1, etc.
28+
29+
Additional arguments are passed to the :meth:`init` method described below,
30+
and will cause the Encoder instance to be re-initialised and reset.
31+
32+
On ESP32, the *id* corresponds to a :ref:`PCNT unit <esp32.PCNT>`.
33+
34+
Methods
35+
-------
36+
37+
.. method:: Encoder.init(phase_a, phase_b, *, ...)
38+
39+
Initialise and reset the Encoder with the given parameters:
40+
41+
- *phase_a* specifies the first input pin as a
42+
:ref:`machine.Pin <machine.Pin>` object.
43+
44+
- *phase_b* specifies the second input pin as a
45+
:ref:`machine.Pin <machine.Pin>` object.
46+
47+
These pins may be omitted on ports that have predefined pins for a given
48+
hardware block.
49+
50+
Additional keyword-only parameters that may be supported by a port are:
51+
52+
- *filter_ns* specifies a minimum period of time in nanoseconds that the
53+
source signal needs to be stable for a pulse to be counted. Implementations
54+
should use the longest filter supported by the hardware that is less than
55+
or equal to this value. The default is 0 (no filter). *(Supported on ESP32)*
56+
57+
- *phases* specifies the number of signal edges to count and thus the
58+
granularity of the decoding. e.g. 4 phases corresponds to "4x quadrature
59+
decoding", and will result in four counts per pulse. Ports may support
60+
either 1, 2, or 4 phases and the default is 1 phase. *(Supported on ESP32)*
61+
62+
.. method:: Encoder.deinit()
63+
64+
Stops the Encoder, disabling any interrupts and releasing hardware resources.
65+
A Soft Reset should deinitialize all Encoder objects.
66+
67+
.. method:: Encoder.value([value])
68+
69+
Get, and optionally set, the encoder value as a signed integer.
70+
Implementations should aim to do the get and set atomically.
71+
72+
See :meth:`machine.Counter.value` for details about overflow of this value.

docs/library/machine.rst

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -262,6 +262,8 @@ Classes
262262
machine.I2S.rst
263263
machine.RTC.rst
264264
machine.Timer.rst
265+
machine.Counter.rst
266+
machine.Encoder.rst
265267
machine.WDT.rst
266268
machine.SD.rst
267269
machine.SDCard.rst

docs/reference/glossary.rst

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -188,6 +188,13 @@ Glossary
188188
Most MicroPython boards make a REPL available over a UART, and this is
189189
typically accessible on a host PC via USB.
190190

191+
small integer
192+
MicroPython optimises the internal representation of integers such that
193+
"small" values do not take up space on the heap, and calculations with
194+
them do not require heap allocation. On most 32-bit ports, this
195+
corresponds to values in the interval ``-2**30 <= x < 2**30``, but this
196+
should be considered an implementation detail and not relied upon.
197+
191198
stream
192199
Also known as a "file-like object". A Python object which provides
193200
sequential read-write access to the underlying data. A stream object

0 commit comments

Comments
 (0)
0