@@ -195,6 +195,148 @@ Constants
195
195
196
196
Used in `idf_heap_info `.
197
197
198
+
199
+ .. _esp32.PCNT :
200
+
201
+ PCNT
202
+ ----
203
+
204
+ This class provides access to the ESP32 hardware support for pulse counting.
205
+ There are 8 pulse counter units, with id 0..7.
206
+
207
+ See the :ref: `machine.Counter <machine.Counter >` and
208
+ :ref: `machine.Encoder <machine.Encoder >` classes for simpler and portable
209
+ abstractions of common pulse counting applications. These classes are
210
+ implemented as thin Python shims around :class: `PCNT `.
211
+
212
+ .. class :: PCNT(id, *, ...)
213
+
214
+ Returns the singleton PCNT instance for the given unit ``id ``.
215
+
216
+ Keyword arguments are passed to the ``init() `` method as described
217
+ below.
218
+
219
+ .. method :: PCNT.init(*, ...)
220
+
221
+ (Re-)initialise a pulse counter unit. Supported keyword arguments are:
222
+
223
+ - ``channel ``: see description below
224
+ - ``pin ``: the input Pin to monitor for pulses
225
+ - ``rising ``: an action to take on a rising edge - one of
226
+ ``PCNT.INCREMENT ``, ``PCNT.DECREMENT `` or ``PCNT.IGNORE `` (the default)
227
+ - ``falling ``: an action to take on a falling edge (takes the save values
228
+ as the ``rising `` argument).
229
+ - ``mode_pin ``: ESP32 pulse counters support monitoring a second pin and
230
+ altering the behaviour of the counter based on its level - set this
231
+ keyword to any input Pin
232
+ - ``mode_low ``: set to either ``PCNT.HOLD `` or ``PCNT.REVERSE `` to
233
+ either suspend counting or reverse the direction of the counter (i.e.,
234
+ ``PCNT.INCREMENT `` behaves as ``PCNT.DECREMENT `` and vice versa)
235
+ when ``mode_pin `` is low
236
+ - ``mode_high ``: as ``mode_low `` but for the behaviour when ``mode_pin ``
237
+ is high
238
+ - ``filter ``: set to a value 1..1023, in ticks of the 80MHz clock, to
239
+ enable the pulse width filter
240
+ - ``min ``: set to the minimum level of the counter value when
241
+ decrementing (-32768..-1) or 0 to disable
242
+ - ``max ``: set to the maximum level of the counter value when
243
+ incrementing (1..32767) or 0 to disable
244
+ - ``threshold0 ``: sets the counter value for the
245
+ ``PCNT.IRQ_THRESHOLD0 `` event (see ``irq `` method)
246
+ - ``threshold1 ``: sets the counter value for the
247
+ ``PCNT.IRQ_THRESHOLD1 `` event (see ``irq `` method)
248
+ - ``value ``: can be set to ``0 `` to reset the counter value
249
+
250
+ The hardware initialisation is done in stages and so some of the keyword
251
+ arguments can be used in groups or in isolation to partially reconfigure a
252
+ unit:
253
+
254
+ - the ``pin `` keyword (optionally combined with ``mode_pin ``) can be used
255
+ to change just the bound pin(s)
256
+ - ``rising ``, ``falling ``, ``mode_low `` and ``mode_high `` can be used
257
+ (singly or together) to change the counting logic - omitted keywords
258
+ use their default (``PCNT.IGNORE `` or ``PCNT.NORMAL ``)
259
+ - ``filter `` can be used to change only the pulse width filter (with 0
260
+ disabling it)
261
+ - each of ``min ``, ``max ``, ``threshold0 `` and ``threshold1 `` can
262
+ be used to change these limit/event values individually; however,
263
+ setting any will reset the counter to zero (i.e., they imply
264
+ ``value=0 ``)
265
+
266
+ Each pulse counter unit supports two channels, 0 and 1, each able to
267
+ monitor different pins with different counting logic but updating the same
268
+ counter value. Use ``channel=1 `` with the ``pin ``, ``rising ``, ``falling ``,
269
+ ``mode_pin ``, ``mode_low `` and ``mode_high `` keywords to configure the
270
+ second channel.
271
+
272
+ The second channel can be used to configure 4X quadrature decoding with a
273
+ single counter unit::
274
+
275
+ pin_a = Pin(2, Pin.INPUT, pull=Pin.PULL_UP)
276
+ pin_b = Pin(3, Pin.INPUT, pull=Pin.PULL_UP)
277
+ rotary = PCNT(0, min=-32000, max=32000)
278
+ rotary.init(channel=0, pin=pin_a, falling=PCNT.INCREMENT, rising=PCNT.DECREMENT, mode_pin=pin_b, mode_low=PCNT.REVERSE)
279
+ rotary.init(channel=1, pin=pin_b, falling=PCNT.DECREMENT, rising=PCNT.INCREMENT, mode_pin=pin_a, mode_low=PCNT.REVERSE)
280
+ rotary.start()
281
+
282
+ .. method :: PCNT.value([value])
283
+
284
+ Call this method with no arguments to return the current counter value.
285
+
286
+ If the optional *value * argument is set to ``0 `` then the counter is
287
+ reset (but the previous value is returned). Read and reset is not atomic and
288
+ so it is possible for a pulse to be missed. Any value other than ``0 `` will
289
+ raise an error.
290
+
291
+ .. method :: PCNT.irq(handler=None, trigger=PCNT.IRQ_ZERO)
292
+
293
+ ESP32 pulse counters support interrupts on these counter events:
294
+
295
+ - ``PCNT.IRQ_ZERO ``: the counter has reset to zero
296
+ - ``PCNT.IRQ_MIN ``: the counter has hit the ``min `` value
297
+ - ``PCNT.IRQ_MAX ``: the counter has hit the ``max `` value
298
+ - ``PCNT.IRQ_THRESHOLD0 ``: the counter has hit the ``threshold0 `` value
299
+ - ``PCNT.IRQ_THRESHOLD1 ``: the counter has hit the ``threshold1 `` value
300
+
301
+ ``trigger `` should be a bit-mask of the desired events OR'ed together. The
302
+ ``handler `` function should take a single argument which is the
303
+ :class: `PCNT ` instance that raised the event.
304
+
305
+ This method returns a callback object. The callback object can be used to
306
+ access the bit-mask of events that are outstanding on the PCNT unit.::
307
+
308
+ def pcnt_irq(pcnt):
309
+ flags = pcnt.irq().flags()
310
+ if flags & PCNT.IRQ_ZERO:
311
+ # reset
312
+ if flags & PCNT.IRQ_MAX:
313
+ # overflow...
314
+ ... etc
315
+
316
+ pcnt.irq(handler=pcnt_irq, trigger=PCNT.IRQ_ZERO | PCNT.IRQ_MAX | ...)
317
+
318
+ **Note: ** Accessing ``irq.flags() `` will clear the flags, so only call it
319
+ once per invocation of the handler.
320
+
321
+ The handler is called with the MicroPython scheduler and so will run at a
322
+ point after the interrupt. If another interrupt occurs before the handler
323
+ has been called then the events will be coalesced together into a single
324
+ call and the bit mask will indicate all events that have occurred.
325
+
326
+ To avoid race conditions between a handler being called and retrieving the
327
+ current counter value, the ``value() `` method will force execution of any
328
+ pending events before returning the current counter value (and potentially
329
+ resetting the value).
330
+
331
+ Only one handler can be in place per-unit. Set ``handler `` to ``None `` to
332
+ disable the event interrupt.
333
+
334
+ .. Note ::
335
+ ESP32 pulse counters reset to *zero * when reaching the minimum or maximum
336
+ value. Thus the ``IRQ_ZERO `` event will also trigger when either of these
337
+ events occurs.
338
+
339
+
198
340
.. _esp32.RMT :
199
341
200
342
RMT
0 commit comments