-
-
Notifications
You must be signed in to change notification settings - Fork 8.7k
mimxrt: Add Quadrature Encoder and Pulse Counter classes. #12347
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
base: master
Are you sure you want to change the base?
Conversation
6b55548 to
1365224
Compare
1365224 to
2ecbf50
Compare
|
Code size report: |
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## master #12347 +/- ##
=======================================
Coverage 98.38% 98.38%
=======================================
Files 171 171
Lines 22298 22298
=======================================
Hits 21937 21937
Misses 361 361 ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
2ecbf50 to
d45030c
Compare
d45030c to
508d754
Compare
508d754 to
3de0c7e
Compare
e6d0969 to
54abc06
Compare
|
@dpgeorge @projectgus Now that the Encoder/Counter classes are available for ESP32, I have rebased and retested the implementation for MIMXRT. Since the Encoder/Counter hardware differs between ESP32 and MIMXRT, the ESP32 oriented test in extmod_hardware show quite a few deviations. Major reasons:
|
|
Thanks @robert-hh for updating and noting these differences. (I think it's a good example of the potential for tests to find these hardware-specific parts as well.)
The ESP32 version of this class has a documented port-specific
I think the solution for these will probably be I am a bit surprised that |
|
Good day @projectgus, thank you for the swift reply. Obviously one can skip the test for the FALLING edge of the counter. I did not look in detail why the Pin value() cannot read back when the Pin was configured for Encoder/Counter. Probably it's because for Encoder/Counter a PIN is configured for a different ALT mode. So maybe the test has to be changed to configure the Pin for machine.Pin mode first, make the connectivity test and then configure it as Encoder/Counter. I wondered why there is the connectivity test at all. The other tests to not have it. |
|
So I added an emulation for phases and adapted the test scripts, taking into account the not-supported options and the fact, that different to ESP32 the MIMXRT expects 4 transitions to count from 0 to 1. For ESP32, setting the initial value of pulses to -1 fixes that. |
b6eb32c to
d115ab6
Compare
|
Sorry I didn't reply last week, @robert-hh - the updated PR looks great to me, thanks for accommodating the limits in the API and tests! I don't think I have any mimxrt board set up to do any local tests on, unfortunately (there might be a Teensy 4 hiding somewhere, will look later).
I borrowed this from Ihor's test PR, but it's something I support building into tests - especially hardware-in-loop tests. The idea is to have a quick and user-friendly way to differentiate "the test environment is broken" from "the driver is broken". More than once I've had some unusual pattern of failures and spent too long debugging them before realising a wire is loose, or some equivalent prerequisite is missing (i.e with MicroPython, forgetting to do As you observe, MicroPython's tests don't have much of this kind of thing (yet) - but I think that's to the project's detriment. It costs time even for core developers (like me) who run the test suite a lot, but for developers who aren't already very familiar with the project then it's even more limiting. We get a lot of PRs from new(ish) contributors who are competent developers, but the relevant tests either haven't been run, or they ran and failed and the developer hasn't dug in to figure out why. (Sorry for dropping in this somewhat tangential rant. cc @hmaerki and @dpgeorge as I know they've been thinking about tests an awful lot, lately.) In the particular case of the connections test for Counter/Encoder, I think skipping them on mimxrt - as you've done here - is fine for now. Long term, putting them in a separate TestCase at the top of the same file (so they're run without the setUp step that inits the Encoder and muxes the pins) will probably allow them to pass on more platforms, but I can look at that in a follow-up if you like. |
That's what #16112 is trying to address, although it's gotten pretty lost among all the other PRs. Might be nice to get that merged, I use it all the time now.
We are definitely missing a simple But also, I think we need to break out all this board wiring configuration into separate files, one for each board, that can be reused in all hardware-related tests. That's something I'm working on now. |
I'm not familiar with the mechanics of unittest, so I do not object if you look at that later. |
d115ab6 to
5d33af4
Compare
a27d3a4 to
7e6278e
Compare
|
@dpgeorge I have rearranged the commits a little bit, and more squashing can be done to the test-related commits and the two about documentation. |
|
Thanks @robert-hh for updating the docs. It's now much clearer how the mimxrt code matches the existing docs (and esp32 implementation) and what's been added. So there's now two things to do here:
Ideally (1) and (2) would be separate PRs, because (1) is much easier to review and merge, whereas (2) may take some back and forth to finalise the enhanced API. But I can understand that might be more effort than you have time for. So it's up to you how to proceed, ether split this PR into two where the first just implements existing documented behaviour, or keep it as one PR and it'll take a bit more time to review. |
|
Thank you for the comment. The decision is hard to make, because the underlying hardware between MIMXRT and ESP32 is different. Of course I can reduce behavior and the set of options and methods to being as close as possible to the ESP's PCNT/Encoder/Counter triple. But doing that by removing code and putting it back in later seems error prone. I would prefer leaving the extra code in and just disabling it with a compile switch.
P.S.: Being a pensioner, I should have every time of the world. But since everyone assumes this (and asks me to do this or that), it's way less. Anyhow, time is not a problem. |
Yes, but you already did a great job to get the existing tests passing on mimxrt, so the API matches pretty well already.
OK, thanks for the detailed list of differences. Don't change anything for now and leave it with me. I'll do a more thorough review and we can take it from there. |
7e6278e to
076cc5c
Compare
|
I made a minor fix to dealing with the phases argument. Besides that all is as it was. Looking though the code again I noticed, that the I could change the implementation of the |
OK, that sounds like a good change. Having min/max arguments seem a lot more general (to other ports) than cpc.
Yes please. The suggested changes for that would be:
|
076cc5c to
7e59393
Compare
|
I made the suggested changes.
The names of the trigger events are still not changed. They could change to: IRQ_MATCH into IRQ_THRESHOLD0 Another change is the behavior of the index and home pins. They do now different things. The index pin transition now just increments or decrements the cycles counter. The home pin transition just resets the pulse counter. The documentation is not yet updated. That will be done when the code is settled. |
7e59393 to
e108cb9
Compare
These classes are base on the Quadrature Encoder blocks of the i.MXRT MCUs. The i.MXRT 102x has two encoders, the other ones four. The i.MXRT 101x does not support this function. It is implemented as two classes, Encoder and Counter. The number of pins that can be uses as inputs is limited by the MCU architecture and the board schematics. The Encoder class supports: - Defining the module - Defining the input pins. - Defining a pin for an index signal. - Defining a pin for a Home signal. - Defining an output pin showing the compare match signal. - Setting the number of cycles per revolution. - Setting the initial value for the position. - Setting the counting direction. - Setting a glitch filter. - Setting the value counter as signed or unsigned integers. - Defining callbacks for getting to a specific position, overrun and underrun (starting the next revolution). These callbacks can be hard interrupts to ensure short latency. The encoder counts all phases of a cycle. The span for the position is 2**32, for the revolution is 2**16. The highest input frequency is CPU-Clock/24. The Counter mode counts single pulses on input A of the Encoder. The configuration support: - Defining the module - Defining the input pin. - Defining the counting direction, either fixed or controlled by the level of an input pin. - Defining a pin for an index signal. - Defining an ouput pin showing th compare match signal. - Setting the counter value. - Setting the glitch filter. - Returing the value counter as signed or unsigned integer. - Defining a callback which is called at a certain value. - Add settings for MIMXRT1015. The MIMXRT1015 MCU has only one encoder/counter unit. The counting range is 0 - 2**32-1 and a 16 bit overrun counter. The highest input frequency is CPU-Clock/12. Signed-off-by: robert-hh <robert@hammelrath.com>
Which covers the additional code for MIMXRT117x family. Adapt for PR8813 - Optimise mp_obj_type_t storage. Signed-off-by: robert-hh <robert@hammelrath.com>
Signed-off-by: robert-hh <robert@hammelrath.com>
Signed-off-by: robert-hh <robert@hammelrath.com>
This is just an emulation at the API. The hardware will always count all phases. Signed-off-by: robert-hh <robert@hammelrath.com>
This is the MIMXRT specific version, compliant to the documentation of PR micropython#8072 in the basic methods. Signed-off-by: robert-hh <robert@hammelrath.com>
For Teensy 4.x. The connectivity tests and the falling edge of the counter test are skipped. Signed-off-by: robert-hh <robert@hammelrath.com>
Because it requires a different configuration of the pins (in `setUp`). Eg on mimxrt pins used for an Encoder cannot be read. Signed-off-by: Damien George <damien@micropython.org>
Because it requires a different configuration of the pins (in `setUp`). Eg on mimxrt pins used for a `machine.Counter` cannot be read. Signed-off-by: Damien George <damien@micropython.org>
- Drop the separate documentation file for Encoder/Counter and move the related documentation into the common Encoder/Counter documents. - Move the Encoder/Counter pinout to the mimxrt pinout document. - Use Teensy D0/D1 Pins for the tests. Signed-off-by: robert-hh <robert@hammelrath.com>
"max" used to be cpc before, and "min" was be added by using the same mechanism of modulus counting. It deviates slightly from the ESP32 variant, in that the counter rolls over/under when hitting the margins instead of just falling back to 0. Signed-off-by: robert-hh <robert@hammelrath.com>
- The home signal clears the counter register(s). - The index signal increased/decreases the cycles register. It is increased for inputs a/b = 1, decreased for input a/b = 0. Both signals can be assigned to the same pin. - Clear all counters on calling init(). Signed-off-by: robert-hh <robert@hammelrath.com>
e108cb9 to
758a41b
Compare
|
The documentation is updated, and the |
758a41b to
c4a618a
Compare
The implementation of the irq() method uses now the common code from
runtim/mpirq including the irq().flags() and irq().trigger() methods.
This required moving the definition of the match compare value to a
different place. The compare match value is now defined by a keyword
option of the init() method.
Side change: Rearrange a few lines of code in the keyword argument lists
and local dictionaries, making them more similar for
Encoder and Counter. Fix a typo.
Signed-off-by: robert-hh <robert@hammelrath.com>
Always treat values at the API as signed. Signed-off-by: robert-hh <robert@hammelrath.com>
Reflecting the actual code state after implementing review comments. Signed-off-by: robert-hh <robert@hammelrath.com>
c4a618a to
a1179e8
Compare
This PR adds Quadrature Encoder and Pulse Counter classes based on the Encoder hardware of the mimxrt MCUs. The base methods are as simple as possible, with options to make use of the hardware features supporting fast encoder sensors, like index pulses.
Tested with a slow manual encoder and a simulation of fast encoder/counter signals up to a input frequency of 25 MHz.
The PR is a re-submit of PR #7911, which could not be reopened. The conversation at that PR applies here as well (except for the UART part).