Skip to content

countio enhancements #5606

Closed
Closed

Description

@dhalbert

countio.Counter was originally added to handle rotary encoders, but it can also be used as a general-purpose pin-interrupt detector. However, it could use some more functionality.

  • Right now Counter only counts falling edges. Generalize it to handle rising edges, and also transitions in either direction.
  • Provide an atomic fetch-and-clear operation, to avoid losing any counts. Some implementations use PWM instead of interrupts. It's not clear we can do this atomically cleanly.
  • Add an async method so you can await changes in the count. This is not really necessary: polling works, and maybe eventually we will add triggering an asyncio.Event.
  • Add pullup/pulldown control.

Activity

  1. added this to the Long term milestone on Nov 21, 2021
  2. mrdalgaard commented on Nov 22, 2021

    @mrdalgaard

    Great enhancements.
    Also allowing to control pulls (pullup/pulldown), just like alarm and digitalio allows would be nice

  3. tonsofpcs commented on Jan 4, 2022

    @tonsofpcs

    @dhalbert Just read through your comments on #5803 there. It looks like it will be quite useful, thank you!

    I'm curious, as I bounce between micropython and circuitpython for a project here due to differing demands, is there a way to tell how much time has elapsed in a pin state?

    In the mentioned project I have a relatively slow speed serial protocol that depends on high pulse duration to determine 0/1 (0.8ms vs 1.2ms, with reset as high > 2ms OR low > 0.4ms). I've been able to decode it cleanly with 'flipping' interrupts in micropython, discerning values at > 2ms, > 1ms, and > .2 ms high and > 3ms low, through the use of utime.ticks_us() but I'd prefer to handle everything in circuitpython as the rest of my code is much cleaner and able to rely on existing libraries.

  4. dhalbert commented on Jan 4, 2022

    @dhalbert
    CollaboratorAuthor

    @tonsofpcs For that, you may want to try pulseio.PulseIn. We are also doing some pulse train work to read floppy discs right now, but I don't know if that will be generalized.

  5. dhalbert commented on Jan 4, 2022

    @dhalbert
    CollaboratorAuthor

    Fixed by #5803.

  6. felker commented on Mar 11, 2023

    @felker

    Really excited about this functionality--- I am working my way through https://learn.adafruit.com/cooperative-multitasking-in-circuitpython-with-asyncio/handling-interrupts right now.

    Is it possible to extend the functionality to read from the pin within the Counter context? I have a https://www.adafruit.com/product/3218 toggle switch connected to an M4, with the switch pins connecting a 3.3V and the input pin on the board. I want an interrupt to behave differently based on whether the switch transition to ON or OFF. But I don't seen an obvious way to read the state of the pin. I think the guide could really benefit from 1 more complicated example that uses countio.

  7. dhalbert commented on Mar 11, 2023

    @dhalbert
    CollaboratorAuthor

    @felker
    I agree that there are use caes for reading the current state of the countio.Counter() pin, and that could be added to this API.

    However, toggle switch (or any mechanical switch) is going to bounce. Instead of using countio for this, I suggest you use keypad to register switch transitions, as in https://learn.adafruit.com/cooperative-multitasking-in-circuitpython-with-asyncio/handling-interrupts#handling-interrupts-with-keypad-3106485. keypad has debouncing built in, and doesn't have to be used to pushbutton switches -- it could be used with toggle switches as well. Depending on the bounce characteristics of the switch you have, you may need to lengthen the polling interval. The keypad event (pressed or released) will implicitly give you the current state of the switch.

  8. felker commented on Mar 11, 2023

    @felker

    @dhalbert that is actually great to hear, since I switched to keypad after getting stuck with countio and it seems to be working quite well!

    I observed debounce with countio and tried to fix it by changing await asyncio.sleep(0) to await asyncio.sleep(0.01), but clearly that did not help.

    Is that how I would lengthen the polling interval in the keypad approach?

    It would be great to add a paragraph or example to that interrupt guide encapsulating the info in your comment.

  9. dhalbert commented on Mar 11, 2023

    @dhalbert
    CollaboratorAuthor

    Is that how I would lengthen the polling interval in the keypad approach?

    The interval argument in the keypad.Keys() constructor specifies the polling interval. A switch that bounces for longer might need a longer interval. If you see multiple events on a single switch throw, lengthen interval.

    It would be great to add a paragraph or example to that interrupt guide encapsulating the info in your comment.

    Will do -- thanks for the suggestion!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions