-
-
Notifications
You must be signed in to change notification settings - Fork 8.2k
Addition of a machine.Counter class (ESP32 only initially) #5496
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
Lots of discussion on slack: https://micropython.slack.com/archives/C48TVHRQC/p1578293600192800 |
Example usage:: | ||
|
||
from machine import Counter, Pin | ||
ctr = Counter(0, pin=4) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
pin=Pin(4)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes & no... I'm copying the conversation from the slack thread https://micropython.slack.com/archives/C48TVHRQC/p1578281256187400?thread_ts=1578281225.187300&cid=C48TVHRQC:
jimmo 1 day ago
the general idea is that anything that takes a pin should be able to accept either a machine.Pin instance or a port-specific value
jimmo 1 day ago
so on STM32, the port-specific value is a string, which is either a "CPU" pin name (e.g. PA1) or a "BOARD" pin name (e.g. "X1" on a pyboard, or "A0", "D12", etc on an arduino-layout-compatible board)
each board definition defines a pins.csv which maps the board pins to CPU pins, and the CPU pins are generated automatically based on which stm32 part it is (edited)
jimmo 1 day ago
on ESP32, the port-specific value is the pin number, and the pins.csv board mapping etc isn't implemented (i recently added basic support for board definitions, and hopefulyl someone who is more involved with ESP32 can finish it off and add pins.csv)
[...]
TvE 1 day ago
Is it OK to use pin numbers (ints) on the esp32 now and then later the code can test the type of the pin parameter and if it's a string look up the pin by name and if it's a Pin use that?
jimmo 1 day ago
yes, that will at least be compatible with the rest of ESP32
jimmo 1 day ago
i hope that in the future that just a few extra calls to the esp32 version of pin_find will be all that's required
jimmo 1 day ago
then ESP32 will support pin number, pin name, and pin obj in all cases
Thanks for opening this, I like that you're starting with the docs. This definition looks good. I unfortunately cannot weigh in on how this affects other ports as I am only really familiar with ESP32 hardware. |
Easy to read docs page: https://micropython-tve.readthedocs.io/en/counter/library/machine.Counter.html |
So there doesn't seem to be any way to do periodic counting (like how a frequency counter works). How would I accurately count how many pulses occur in 1 second? How would you use this for the doing RPM measurements? Seems this would be more suitable for long time periods with relatively fewer pulses? |
I would sample the counter value in a periodic timer and calculate RPM based on delta_count / delta_time. But from your question I assume you're looking for something more accurate?
Possibly. Is there a different way you would use the hardware to get more precise frequency counts (whether esp32 PCNT, stm32 timer, or other)? |
I think what I'm looking for would best be implemented using the MCPWM, since it has a "capture" capability. Couple of years ago, I was looking into implementing that for MP. Maybe I should revisit. |
Initial implementation, interrupts not yet implemented. |
Is there plan to merge this PR anytime soon ? Counting periodic or eratic pluses is a very common use case for microcontroler, I'm surprised by the low interest it leverage. Never the less thanks tve for this addition |
@dpgeorge we probably need some of your opinion on this interface; I'm sure you've given it plenty of thought in the past! |
@tve thanks for working on this idea/proposal. It's nice to see that you started with docs with a clear description of the behaviour that is hardware agnostic. I would be supportive of this addition, although there doesn't seem to be that much interest in it (yet). In terms of general availability across ports (the following goes for most additions to
A few suggestions about the PR itself:
|
@dpgeorge thanks for the review and suggestions. My plan was to wait for one of the "call ESP-IDF functions from loadable modules" PRs to be merged and then to rework this PR as an example that uses the new functionality. Ideally using some auto-generated espidf class such that this PR can be 100% python... IMHO the thing for you to think about is what you'd like to see in the MP repo once one can call ESP-IDF from loadable modules. E.g. the entire set of machine classes could be deleted from MP and implemented by other people in their own private repos. That probably wouldn't be all that great. So what should be in MP and what should be strewn around github et. al.? |
I'm closing this PR in favor of https://github.com/tve/mpy-lib/tree/master/esp32-counter which uses native module linking against esp-idf in order to implement a Counter class in pure python with automatically generated stubs for the ESP-IDF pcnt_* functions. That repo is based on #5711 |
That's a good question. I guess the short answer is that the main MP repo here should provide basic, fundamental classes that work the same across all ports (eg machine.Pin, ADC, PMW), and anything which is port-specific (like esp32 RMT) could be a loadable .mpy file. And if an .mpy extension proves to be useful and widely used then it could make its way into this repo.
Just so I understand: that esp32-counter uses a combination of 1) dynamic loadable native modules, 2) a large port-specific table of exported symbols (from the IDF), and 3) a stub generator which makes a reduced set of C stub functions that are needed by the Python code and which are then dynamically loaded (ie not part of a statically available That sounds like a good way to do it. |
Yes. The table in #5711 has 670 functions and thus uses ~2680 bytes, dunno whether you consider that "large"... If you weigh it against the size of all the pending PRs which could be declined with a polite "please implement this as a loadable module" then the table is tiny ;-).
Edit: forgot to add: I'm using a small hacky stub generator, which is in the repo I linked to. Not sure this is what I would recommend to others, but would be interesting to have some discussion... |
That's a secondary thing which we can discuss later, and for the moment is nicely self-contained within that esp32-counter example. The primary thing is to work out how to expose port-specific symbols to the dynamic loader. |
I try to figure out own it will behave for the module (counter for instance) end user : Based on tve repository, I understand that one will have to download 2 files:
I guess the *.py file could also be a *.mpy
Does I understand it well ? |
I believe it would be good practice to check in the compiled mpy, perhaps also the generated modpcnt.c stubs.
Yes. |
This PR proposes the addition of a machine.Counter class that uses a timer or counter register depending on the architecture to count transitions on an input pin and to optionally generate interrupts when the counter wraps around.
Right now this PR only consists of the documentation so the design can be debated before much code gets written. (The docs can be viewed in semi-formatted state by using the view file entry of the 3-dots menu at the right of the file's diff.)