Skip to content

Commit bcd9efc

Browse files
committed
docs/machine.Counter: Document new Counter class.
Document a new Counter API, currently only implemented for the ESP32 port. Also add port-specific API to ESP32 quickref document.
1 parent fd9a998 commit bcd9efc

File tree

3 files changed

+167
-0
lines changed

3 files changed

+167
-0
lines changed

docs/esp32/quickref.rst

Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -313,6 +313,98 @@ ESP32 specific ADC class method reference:
313313
- ``ADC.WIDTH_11BIT``: 11 bit data
314314
- ``ADC.WIDTH_12BIT``: 12 bit data - this is the default configuration
315315

316+
Counter (pin pulse/edge counting)
317+
---------------------------------
318+
319+
The ESP32 provides up to 8 pulse counter peripherals depending on the hardware,
320+
with id 0..7. These can be configured to count rising and/or falling edges on
321+
any input pin.
322+
323+
Use the :ref:`machine.Counter <machine.Counter>` class::
324+
325+
from machine import Pin, Counter
326+
327+
counter = Counter(0, pin=Pin(2), rising=Counter.INCREMENT) # create counter
328+
counter.start() # start counter
329+
count = counter.value() # read count, -32768..32767
330+
counter.value(0) # reset counter
331+
count = counter.value(0) # read and reset
332+
333+
ESP32 specific Counter reference:
334+
335+
.. class:: Counter(id, *, pin, rising, falling, ...)
336+
337+
The constructor and ``init`` method support an additional set of
338+
keyword arguments over-and-above the basic
339+
:ref:`machine.Counter <machine.Counter>` API:
340+
341+
- ``mode_pin``: ESP32 pulse counters support monitoring a second pin and
342+
altering the behaviour of the counter based on its level - set this
343+
keyword to any input Pin
344+
- ``mode_low``: set to either ``Counter.HOLD`` or ``Counter.REVERSE`` to
345+
either suspend counting or reverse the direction of the counter (i.e.,
346+
``Counter.INCREMENT`` behaves as ``Counter.DECREMENT`` and vice versa)
347+
when ``mode_pin`` is low
348+
- ``mode_high``: as ``mode_low`` but for the behaviour when ``mode_pin``
349+
is high
350+
- ``filter``: set to a value 1..1023, in ticks of the 80MHz clock, to
351+
enable the pulse width filter
352+
- ``minimum``: set to the minimum level of the counter value when
353+
decrementing (-32768..0)
354+
- ``maximum``: set to the maximum level of the counter value when
355+
decrementing (0..32767)
356+
- ``threshold0``: sets the counter value for the
357+
``Counter.IRQ_THRESHOLD0`` event (see ``irq`` method)
358+
- ``threshold1``: sets the counter value for the
359+
``Counter.IRQ_THRESHOLD1`` event (see ``irq`` method)
360+
- ``channel``: see description below
361+
362+
Each pulse counter unit supports two channels, 0 and 1. By default, the
363+
constructor and ``init()`` method configure the 0 channel. Call the
364+
``init()`` method with ``channel=1`` to configure the other channel. Both
365+
channels update the same counter value, but are able to monitor different
366+
pins with different edge behaviour. The ``pin``, ``rising``, ``falling``,
367+
``mode_pin``, ``mode_low`` and ``mode_high`` keywords are per-channel, all
368+
other keyword arguments are per-unit and specifying them will override any
369+
previous configuration.
370+
371+
The second channel can be used to configure 4X quadrature decoding with a
372+
single counter unit::
373+
374+
pin_a = Pin(2, Pin.INPUT, pull=Pin.PULL_UP)
375+
pin_b = Pin(3, Pin.INPUT, pull=Pin.PULL_UP)
376+
rotary = Counter(0, pin=pin_a, falling=Counter.INCREMENT, rising=Counter.DECREMENT, mode_pin=pin_b, mode_low=Counter.REVERSE)
377+
rotary.init(channel=1, pin=pin_b, falling=Counter.DECREMENT, rising=Counter.INCREMENT, mode_pin=pin_a, mode_low=Counter.REVERSE)
378+
rotary.start()
379+
380+
.. method:: Counter.value([value])
381+
382+
Call this method with no arguments to return the current counter value or
383+
pass the value 0 to reset the counter and return the value before reset.
384+
ESP32 pulse counters do not support being set to any value other than 0.
385+
Reset and return is not atomic and so it is possible for a pulse to be
386+
missed.
387+
388+
.. method:: Counter.irq(trigger=Counter.IRQ_ZERO, handler=None)
389+
390+
ESP32 pulse counters support interrupts on these counter events:
391+
392+
- ``Counter.IRQ_ZERO``: the counter has reset to zero
393+
- ``Counter.IRQ_MINIMUM``: the counter has hit the ``minimum`` value
394+
- ``Counter.IRQ_MAXIMUM``: the counter has hit the ``maximum`` value
395+
- ``Counter.IRQ_THRESHOLD0``: the counter has hit the ``threshold0`` value
396+
- ``Counter.IRQ_THRESHOLD1``: the counter has hit the ``threshold1`` value
397+
398+
``trigger`` should be the desired events or'ed together and ``handler``
399+
should be a callable taking a single argument, which will be the Counter
400+
object. Only one handler can be in place per-unit. Set ``handler`` to
401+
``None`` to disable the event interrupt (or call ``irq`` with no arguments).
402+
403+
.. Note::
404+
ESP32 pulse counters reset to *zero* when reaching the minimum or maximum
405+
value. Thus the ``IRQ_ZERO`` event will also trigger when either of these
406+
events occurs.
407+
316408
Software SPI bus
317409
----------------
318410

docs/library/machine.Counter.rst

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
.. currentmodule:: machine
2+
.. _machine.Counter:
3+
4+
class Counter -- Pulse/Edge counter
5+
===================================
6+
7+
The Counter class provides hardware support for counting transitions on an input
8+
pin.
9+
10+
Example usage::
11+
12+
from machine import Pin, Counter
13+
14+
inp = Pin(2, Pin.INPUT)
15+
counter = Counter(0, pin=inp, rising=Counter.INCREMENT) # create a Counter on pin inp
16+
counter.start() # start counting transitions
17+
count = counter.value() # get the current count
18+
19+
.. Note::
20+
The Counter class is currently only implemented for the ESP32 port.
21+
22+
Constructor
23+
-----------
24+
25+
.. class:: Counter(id, *, pin, rising, falling)
26+
27+
Create a new Counter object with number ``id``. All ports should support
28+
at least one pulse counter with id 0, but may support a number of
29+
independent counters. ``pin`` is the :ref:`machine.Pin <machine.Pin>`
30+
to be monitored. For all ports, one of either the ``rising`` or
31+
``falling`` keyword arguments may be specified with either the
32+
``Counter.INCREMENT`` or ``Counter.DECREMENT`` constant to specify the
33+
edge and direction to count.
34+
35+
Counters begin in a stopped state, with count 0, and need to be started
36+
before they will count transitions of the pin.
37+
38+
Methods
39+
-------
40+
41+
.. method:: Counter.init(*, ...)
42+
43+
Reinitialize the Counter. See Constructor for keyword arguments.
44+
45+
.. method:: Counter.deinit()
46+
47+
Deinitialize the Counter.
48+
49+
.. method:: Counter.start()
50+
51+
Start the counter, i.e., monitor the pin for transitions.
52+
53+
.. method:: Counter.stop()
54+
55+
Stop the counter, i.e., finish monitoring the pin for transitions. The
56+
current counter value will be retained while the counter is stopped.
57+
58+
.. method:: Counter.value([value])
59+
60+
Returns the current counter value and optionally sets the counter value
61+
to the argument. All ports should support at least resetting the counter to
62+
0. A read and reset operation should be as close to atomic as possible for
63+
the hardware.
64+
65+
Constants
66+
---------
67+
68+
.. data:: Counter.INCREMENT
69+
70+
to increment the counter on an edge
71+
72+
.. data:: Counter.DECREMENT
73+
74+
to decrement the counter on an edge

docs/library/machine.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -200,6 +200,7 @@ Classes
200200
machine.Signal.rst
201201
machine.ADC.rst
202202
machine.PWM.rst
203+
machine.Counter.rst
203204
machine.UART.rst
204205
machine.SPI.rst
205206
machine.I2C.rst

0 commit comments

Comments
 (0)