-
-
Notifications
You must be signed in to change notification settings - Fork 8.5k
Update esp32.RMT module to the new API #16293
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
6b14d89 to
1cb1e6c
Compare
9247d15 to
77ed23a
Compare
|
Thank you. I have been trying to figure this out but with little success. When working with neopixel strips I noticed that the legacy RMT IDF4 + Bitstream has some oddness (extra bytes, noise) and the legacy bitbang is erratic on startup. With C++ and ESPIDF I get good results with RMT IDF 5, but haven't been able to integrated with micropython or bitbang. If I can help with testing, let me know. Thanks again |
|
@ricksorensen testing would be great, since my use cases are limited here (433MHz key fob emulator). At least in this application, it has been working perfectly. The only known showstopper is calling RMT.disable() while transmitting, sometimes it panics with a WDT interrupt timeout, but only on ESP32, not in an ESP32-C3 board. Smeels more like an ESP-IDF issue. |
|
@elvis-epx I can get some evaluation done at the end of this week.... fingers crossed. IDF 5.2.2 is the plan (I can try others, but I have some issues with 5.2.3 and 5.3.1 that I have not resolved yet) Today (Friday 20241129 CST) I ran a few simple experiments. Boards:
I then tried simple
wiith subsequent writes giving A few experiments seem to indicate that if number of bytes sent is 1 or 2 then the timeout occurs. On the C3 RMT printed some more debug information:
I will try some other experiments at end of weekend possibly. Thanks again- Rick |
|
@ricksorensen Have pushed an additional commit 9cdb7dd that should fix at least items 2.1 and 3. We weren't waiting on TX completion for long enough and were treating the timeout as a fatal error, not running the cleanup code lines right after. |
|
@elvis-epx Thank you all, this is a great feature update. hope it can be released in the stable version soon. Does the ESP32-C3 require specific IO pins to properly use the RMT function for receiving infrared signals? |
As far as I know, any pin capable of input can do RMT. I have only one C3 (devkit-rust-1) and play with the onboard led pin (Pin 7). |
|
@ricksorensen good catch, one possible workaround is to keep the channel for the bitstream after the first use (do not delete it, so not calling rmt_del_channel() and not exercising the offending behavior). |
|
Yes that is a work around- to store and save the allocated RTM channel for
a bitstream. Can you change the pin assigned to an active RTM channel?
Maybe (extreme pseudo code:)
if no bitstream RTM, instantiate one
else assign new pin to RTM
transfer data
do not delete/disable channel/encoder/ .
Add new function to release bitstream.
…On Wed, Dec 4, 2024 at 5:50 PM Elvis Pfützenreuter ***@***.***> wrote:
@ricksorensen <https://github.com/ricksorensen> good catch, one possible
workaround is to keep the channel for the bitstream after the first use (do
not delete it, so not calling rmt_del_channel() and not exercising the
offending behavior).
—
Reply to this email directly, view it on GitHub
<#16293 (comment)>,
or unsubscribe
<https://github.com/notifications/unsubscribe-auth/AA5QPQESRXQNHGRRCVWRZKD2D6IN7AVCNFSM6AAAAABSLVHTG6VHI2DSMVQWIX3LMV43OSLTON2WKQ3PNVWWK3TUHMZDKMJYG44TCMBXGU>
.
You are receiving this because you were mentioned.Message ID:
***@***.***>
--
Rick Sorensen
***@***.***
651-470-5511
|
|
@ricksorensen no, if the pin changes, we need to release the channel and create another one, so there is extra logic. We can try calling esp_rom_gpio_connect_out_signal() before rmt_del_channel(), if it works, it is a cheaper solution. |
|
The RTM class seems to work well-
Worth trying again, but I believe the problem is the pin reset in the
del_channel function which adds PULL_UP to the pin. Maybe if the
micropython API is to allow independent bitstream we could override the
del_channel function and remove the pin reset?
Most boards use bitbanging for bitstream I believe. The micropython
bitbang for ESP32 seems to work- but it has a timing glitch on the first
few pulses--- maybe from the RTOS? I have been fiddling with the bitbang
too but have not figured out how to get the timing on the first few bit
pulses correct.
EDIT: I just noticed that the rmt_del_channel on ESP IDF 5.3.1 does NOT reset the pin. Unfortunately I cannot get 5.3.1 to work for my builds yet (not knowledgable enough on esp tools).. I have changed the rmt_common.c function on 5.2.2 to remove the reset and will test tomorrow.
…On Wed, Dec 4, 2024 at 6:34 PM Elvis Pfützenreuter ***@***.***> wrote:
@ricksorensen <https://github.com/ricksorensen> no, if the pin changes,
we need to release the channel and create another one, so there is extra
logic. We can try calling esp_rom_gpio_connect_out_signal() before
rmt_del_channel(), if it works, it is a cheaper solution.
—
Reply to this email directly, view it on GitHub
<#16293 (comment)>,
or unsubscribe
<https://github.com/notifications/unsubscribe-auth/AA5QPQD4VAJNSHS4H4NETFL2D6NSXAVCNFSM6AAAAABSLVHTG6VHI2DSMVQWIX3LMV43OSLTON2WKQ3PNVWWK3TUHMZDKMJYHAZTSMZVGA>
.
You are receiving this because you were mentioned.Message ID:
***@***.***>
--
Rick Sorensen
***@***.***
651-470-5511
|
|
@ricksorensen nice, so this moves the ball to ESP-IDF court. It is not the only issue stemming from ESP-IDF in this PR (see FIXMEs). Have tried changing the position of esp_rom_gpio_connect_out_signal() without success (nothing changes or the problem is worsened). Delaying channel release is also not a perfect solution because a) suppose a use case where 2 or more pins are bitstream'ed in parallel b) the pull up still happens, albeit in a delayed moment, so it would only solve the problem for the rather narrow case that only 1 pin is bitstream'ed. |
|
I have an ad hoc work around which only affects EDIT: @elvis-epx I think I figured out how to include the I have not verified the 5.3.1 config. |
|
I have keen anticipation for this as my application requires high speed temporal dithering of dozens of neopixels. A solution that does not block the main core while data is streaming is critical. Any solution that also minimizes setup and teardown associated with each stream is ideal, as there need to be hundreds of streams per second for flicker-free dithering Thank you for your efforts. |
|
@seanmpuckett Rember there are only a finite number of RMT channels- I believe 8 on ESP32 and ESP32S3 and only 2 on ESP32C3 (single mcu too) . |
6bcd481 to
4d77fa6
Compare
|
@ricksorensen pushed additonal commit with your suggested changes, confirmed they fixed the issue here as well. |
|
@ricksorensen tested with ESP-IDF 5.3.2 with the help of PR #15733. The long pulse problem reappears since gpio_reset_pin() was moved from rmt_common.c to rmt_tx.c, and calling base->destroy() directly no longer avoids it. |
Replace deprecated parameter. Co-authored-by: Angus Gratton <[email protected]> Signed-off-by: Elvis Pfützenreuter <[email protected]>
Fix parameter name. Co-authored-by: Angus Gratton <[email protected]> Signed-off-by: Elvis Pfützenreuter <[email protected]>
Make text more general. Co-authored-by: Angus Gratton <[email protected]> Signed-off-by: Elvis Pfützenreuter <[email protected]>
|
This relates and if the case points to an ESP IDF issue: https://forum.arduino.cc/t/esp32s3-rmt-no-free-tx-channels-opening-third-channel/1310503 My prior builds all used 5.4.2 , trying to build with 5.5.1 to see if the behavior changes. ... no change sadly. |
Thanks @ricksorensen, that does sound like the same issue. If so then seems like it'd be enough for MicroPython to change the |
|
Better check with @elvis-epx about the reason for setting it to 64 |
I believe it's always been 64 in MicroPython, because this is the RAM block size on original ESP32 (and maybe S2?) Block size of 48 is a hardware change on the newer SoCs. |
The ESP-IDF documentation recommends the minimum to be 64 when DMA is not used. https://docs.espressif.com/projects/esp-idf/en/stable/esp32/api-reference/peripherals/rmt.html#rmt-resource-allocation "If DMA is not used, this field controls the size of the dedicated memory block owned by the channel, which should be at least 64." We can change the minimum/defaults to |
|
Thanks for that information @elvis-epx and @projectgus. If you look at https://docs.espressif.com/projects/esp-idf/en/stable/esp32c3/api-reference/peripherals/rmt.html#rmt-resource-allocation "If DMA is not used, this field controls the size of the dedicated memory block owned by the channel, which should be at least 48." I think @elvis-epx suggestion to use |
Just sent a commit amending this. |
|
Should this be updated in The RMT instance in machine_bitstream is short lived so may not be as important. |
Good catch, amended the commit. |
Use the SOC_RMT_MEM_WORDS_PER_CHANNEL macro which is a natural default (and recommended minimum) size for the RMT symbol buffer, instead of 64. Signed-off-by: Elvis Pfutzenreuter <[email protected]>
projectgus
left a comment
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.
Looks great to me, thanks for persisting with this PR @elvis-epx!
Have also confirmed no more issues allocating both TX channels on ESP32-C6.
Fix a couple documentation issues related to resolution_hz. Signed-off-by: Elvis Pfutzenreuter <[email protected]>
Documentation was still referring to an RMT.disable() method that was removed in favor of RMT.active([boolean]). Signed-off-by: Elvis Pfutzenreuter <[email protected]>
- Style issues. - Make sure RMT.active() returns True only when there is an ongoing transmission. - RMT object pollable as POLLOUT instead of POLLIN. Signed-off-by: Elvis Pfutzenreuter <[email protected]>
Documentation was mentioning a clock_div property that is no longer printed in the string representation of an RMT object. Signed-off-by: Elvis Pfutzenreuter <[email protected]>
- Fix type handling of optional int keyword args. - Test tx_ongoing properly (true only if positive). - Fix error message, should start with lowercase. - Do not return poll bits that have not been requested. Signed-off-by: Elvis Pfutzenreuter <[email protected]>
Let it fall through to outside the ifdef when RMT is unavailable. Signed-off-by: Elvis Pfutzenreuter <[email protected]>


Summary
The current esp32.RMT module uses a legacy API from ESP-IDF 4.x. The ESP-IDF 5.x offers a new API, which is overall better, and easier to implement the RX side in the future. This PR updates the module and the documentation, preserving the current MicroPython RMT API as much as possible.
The bitstream RMT implementation was updated as well, since ESP-IDF does not allow an image to reference legacy and new APIs at the same time (it resets right after boot with an error message, even if neither module is imported).
Testing
Tested on ESP32, ESP32-S3, ESP32-C3 and ESP32-C6. (Commenters may have tested on other variants.) We have tested all aspects of the RMT API and all seem to work fine.