diff options
| author | Jonathan Hogg <me@jonathanhogg.com> | 2022-09-12 18:37:22 +0100 |
|---|---|---|
| committer | Damien George <damien@micropython.org> | 2025-08-02 00:00:03 +1000 |
| commit | 641ca2eb0624fc0df2b358f1a4652525af123fd7 (patch) | |
| tree | 42d2585a96a49aeeece189b3d10824414dfcd632 | |
| parent | 327655905e9f523070301f2f35459197d46db4fb (diff) | |
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>
| -rw-r--r-- | docs/esp32/quickref.rst | 15 | ||||
| -rw-r--r-- | docs/library/esp32.rst | 3 | ||||
| -rw-r--r-- | docs/library/machine.Counter.rst | 93 | ||||
| -rw-r--r-- | docs/library/machine.Encoder.rst | 72 | ||||
| -rw-r--r-- | docs/library/machine.rst | 2 | ||||
| -rw-r--r-- | docs/reference/glossary.rst | 7 |
6 files changed, 192 insertions, 0 deletions
diff --git a/docs/esp32/quickref.rst b/docs/esp32/quickref.rst index 7127cc402..2c667a0f0 100644 --- a/docs/esp32/quickref.rst +++ b/docs/esp32/quickref.rst @@ -587,6 +587,21 @@ Use the :ref:`esp32.PCNT <esp32.PCNT>` class:: The PCNT hardware supports monitoring multiple pins in a single unit to implement quadrature decoding or up/down signal counters. +See the :ref:`machine.Counter <machine.Counter>` and +:ref:`machine.Encoder <machine.Encoder>` classes for simpler abstractions of +common pulse counting applications:: + + from machine import Pin, Counter + + counter = Counter(0, Pin(2)) # create a counter as above and start it + count = counter.value() # read the count as an arbitrary precision signed integer + + encoder = Encoder(0, Pin(12), Pin(14)) # create an encoder and begin counting + count = encoder.value() # read the count as an arbitrary precision signed integer + +Note that the id passed to these ``Counter()`` and ``Encoder()`` objects must be +a PCNT id. + Software SPI bus ---------------- diff --git a/docs/library/esp32.rst b/docs/library/esp32.rst index 0cf0ebc62..e5f39c7f5 100644 --- a/docs/library/esp32.rst +++ b/docs/library/esp32.rst @@ -336,6 +336,9 @@ implemented as thin Python shims around :class:`PCNT`. value. Thus the ``IRQ_ZERO`` event will also trigger when either of these events occurs. +See the :ref:`machine.Counter <machine.Counter>` and +:ref:`machine.Encoder <machine.Encoder>` classes for simpler abstractions of +common pulse counting applications. .. _esp32.RMT: diff --git a/docs/library/machine.Counter.rst b/docs/library/machine.Counter.rst new file mode 100644 index 000000000..f89a6d5b4 --- /dev/null +++ b/docs/library/machine.Counter.rst @@ -0,0 +1,93 @@ +.. currentmodule:: machine +.. _machine.Counter: + +class Counter -- pulse counter +============================== + +Counter implements pulse counting by monitoring an input signal and counting +rising or falling edges. + +Minimal example usage:: + + from machine import Pin, Counter + + counter = Counter(0, Pin(0, Pin.IN)) # create Counter for pin 0 and begin counting + value = counter.value() # retrieve current pulse count + +Availability: **ESP32** + +Constructors +------------ + +.. class:: Counter(id, ...) + + Returns the singleton Counter object for the the given *id*. Values of *id* + depend on a particular port and its hardware. Values 0, 1, etc. are commonly + used to select hardware block #0, #1, etc. + + Additional arguments are passed to the :meth:`init` method described below, + and will cause the Counter instance to be re-initialised and reset. + + On ESP32, the *id* corresponds to a :ref:`PCNT unit <esp32.PCNT>`. + +Methods +------- + +.. method:: Counter.init(src, *, ...) + + Initialise and reset the Counter with the given parameters: + + - *src* specifies the input pin as a :ref:`machine.Pin <machine.Pin>` object. + May be omitted on ports that have a predefined pin for a given hardware + block. + + Additional keyword-only parameters that may be supported by a port are: + + - *edge* specifies the edge to count. Either ``Counter.RISING`` (the default) + or ``Counter.FALLING``. *(Supported on ESP32)* + + - *direction* specifies the direction to count. Either ``Counter.UP`` (the + default) or ``Counter.DOWN``. *(Supported on ESP32)* + + - *filter_ns* specifies a minimum period of time in nanoseconds that the + source signal needs to be stable for a pulse to be counted. Implementations + should use the longest filter supported by the hardware that is less than + or equal to this value. The default is 0 (no filter). *(Supported on ESP32)* + +.. method:: Counter.deinit() + + Stops the Counter, disabling any interrupts and releasing hardware resources. + A Soft Reset should deinitialize all Counter objects. + +.. method:: Counter.value([value]) + + Get, and optionally set, the counter value as a signed integer. + Implementations must aim to do the get and set atomically (i.e. without + leading to skipped counts). + + This counter value could exceed the range of a :term:`small integer`, which + means that calling :meth:`Counter.value` could cause a heap allocation, but + implementations should aim to ensure that internal state only uses small + integers and therefore will not allocate until the user calls + :meth:`Counter.value`. + + For example, on ESP32, the internal state counts overflows of the hardware + counter (every 32000 counts), which means that it will not exceed the small + integer range until ``2**30 * 32000`` counts (slightly over 1 year at 1MHz). + + In general, it is recommended that you should use ``Counter.value(0)`` to reset + the counter (i.e. to measure the counts since the last call), and this will + avoid this problem. + +Constants +--------- + +.. data:: Counter.RISING + Counter.FALLING + + Select the pulse edge. + +.. data:: Counter.UP + Counter.DOWN + + Select the counting direction. diff --git a/docs/library/machine.Encoder.rst b/docs/library/machine.Encoder.rst new file mode 100644 index 000000000..fc2de3208 --- /dev/null +++ b/docs/library/machine.Encoder.rst @@ -0,0 +1,72 @@ +.. currentmodule:: machine +.. _machine.Encoder: + +class Encoder -- quadrature decoding +==================================== + +Encoder implements decoding of quadrature signals as commonly output from +rotary encoders, by counting either up or down depending on the order of two +input pulses. + +Minimal example usage:: + + from machine import Pin, Encoder + + counter = Counter(0, Pin(0, Pin.IN), Pin(1, Pin.IN)) # create Encoder for pins 0, 1 and begin counting + value = counter.value() # retrieve current count + +Availability: **ESP32** + +Constructors +------------ + +.. class:: Encoder(id, ...) + + Returns the singleton Encoder object for the the given *id*. Values of *id* + depend on a particular port and its hardware. Values 0, 1, etc. are commonly + used to select hardware block #0, #1, etc. + + Additional arguments are passed to the :meth:`init` method described below, + and will cause the Encoder instance to be re-initialised and reset. + + On ESP32, the *id* corresponds to a :ref:`PCNT unit <esp32.PCNT>`. + +Methods +------- + +.. method:: Encoder.init(phase_a, phase_b, *, ...) + + Initialise and reset the Encoder with the given parameters: + + - *phase_a* specifies the first input pin as a + :ref:`machine.Pin <machine.Pin>` object. + + - *phase_b* specifies the second input pin as a + :ref:`machine.Pin <machine.Pin>` object. + + These pins may be omitted on ports that have predefined pins for a given + hardware block. + + Additional keyword-only parameters that may be supported by a port are: + + - *filter_ns* specifies a minimum period of time in nanoseconds that the + source signal needs to be stable for a pulse to be counted. Implementations + should use the longest filter supported by the hardware that is less than + or equal to this value. The default is 0 (no filter). *(Supported on ESP32)* + + - *phases* specifies the number of signal edges to count and thus the + granularity of the decoding. e.g. 4 phases corresponds to "4x quadrature + decoding", and will result in four counts per pulse. Ports may support + either 1, 2, or 4 phases and the default is 1 phase. *(Supported on ESP32)* + +.. method:: Encoder.deinit() + + Stops the Encoder, disabling any interrupts and releasing hardware resources. + A Soft Reset should deinitialize all Encoder objects. + +.. method:: Encoder.value([value]) + + Get, and optionally set, the encoder value as a signed integer. + Implementations should aim to do the get and set atomically. + + See :meth:`machine.Counter.value` for details about overflow of this value. diff --git a/docs/library/machine.rst b/docs/library/machine.rst index 3c22aa9af..7acaddde8 100644 --- a/docs/library/machine.rst +++ b/docs/library/machine.rst @@ -268,6 +268,8 @@ Classes machine.I2S.rst machine.RTC.rst machine.Timer.rst + machine.Counter.rst + machine.Encoder.rst machine.WDT.rst machine.SD.rst machine.SDCard.rst diff --git a/docs/reference/glossary.rst b/docs/reference/glossary.rst index efaa8f607..ab0b22049 100644 --- a/docs/reference/glossary.rst +++ b/docs/reference/glossary.rst @@ -188,6 +188,13 @@ Glossary Most MicroPython boards make a REPL available over a UART, and this is typically accessible on a host PC via USB. + small integer + MicroPython optimises the internal representation of integers such that + "small" values do not take up space on the heap, and calculations with + them do not require heap allocation. On most 32-bit ports, this + corresponds to values in the interval ``-2**30 <= x < 2**30``, but this + should be considered an implementation detail and not relied upon. + stream Also known as a "file-like object". A Python object which provides sequential read-write access to the underlying data. A stream object |
