-
Notifications
You must be signed in to change notification settings - Fork 7.6k
RMT: using rmt_write_sample async with all 8 channels has signficant staggered starts of last few channels #2885
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
Comments
Had a look on it and it seems to be a scheduler issue rather than anything to do with buffers. Each RMT channel has a fixed amount of memory blocks allocated which are exclusive to RMT (eg. not shared outside). These blocks can be re-allocated within RMT (between channels), but you have to do so manually. This issue - where the start of transmission on the last few channels is Ergo, as the issuing of the RMT transfers is pushed closer to the maximum rate, the transmissions start to run more and more in parallel over all 8 channels! - albeit at a slightly reduced "frame rate" (lagging behind). I did tests with The result: There was, however, one ill-effect ... The resulting update rate was slightly lagging behind. While pushing the data @ 80 updates per second, only about 75 frames made it to the outputs. But good news is, that the amount of outputted frames over a certain time period remains constant & consistent over all channels 👍 The bottom line though being, that this issue should be moved over to the ESP-IDF repo, as the problem most likely is not directly related to the Arduino ESP32 core.. Howgh. |
This issue has been automatically marked as stale because it has not had recent activity. It will be closed in 14 days if no further activity occurs. Thank you for your contributions. |
It is not stale. It is linked to an active issue in the espressif/Arduino-esp32 repo and an active issue in the makuna\NeoPixelBus repo. |
@me-no-dev FYI... |
[STALE_SET] This issue has been automatically marked as stale because it has not had recent activity. It will be closed in 14 days if no further activity occurs. Thank you for your contributions. |
. |
[STALE_CLR] This issue has been removed from the stale queue. Please ensure activity to keep it openin the future. |
[STALE_SET] This issue has been automatically marked as stale because it has not had recent activity. It will be closed in 14 days if no further activity occurs. Thank you for your contributions. |
Still waiting the IDF fix to provide a work around to the problem; as currently there is no exposed way to work around it. |
[STALE_CLR] This issue has been removed from the stale queue. Please ensure activity to keep it openin the future. |
[STALE_SET] This issue has been automatically marked as stale because it has not had recent activity. It will be closed in 14 days if no further activity occurs. Thank you for your contributions. |
still waiting on an exposed solution. |
[STALE_CLR] This issue has been removed from the stale queue. Please ensure activity to keep it openin the future. |
I have seen some issues with this as well. |
I also would appreciate to see this issue solved. I need to make user programmable pulses with nanoseconds accuracy on 4 different pins exactly at the same time as these need to drive multiple IGBT gate drivers. I haven't found any other possibilities to generate precise pulses as short as 12.5 ns on ESP32. |
It seems like if 1 chanel hasnt completed TX before you ask the next to do so, the 1st TX gets borked. and so on. There needs to be a way to iether poll the RMT for a TX Completed message(which seems possible via its internal flags, but each time i test it its always saying TX complete). |
[STALE_SET] This issue has been automatically marked as stale because it has not had recent activity. It will be closed in 14 days if no further activity occurs. Thank you for your contributions. |
keeping alive waiting on the IDF related bug to be fixed. |
[STALE_CLR] This issue has been removed from the stale queue. Please ensure activity to keep it openin the future. |
still not fixed |
Need this feature too... If this is possible then I can do super high-speed SPI. currently, there is a long 'wait' time between consecutive SPI transfers. |
We will consider this issue when we will work on RMT refactoring to use ESP-IDF API. |
@VojtechBartoska this is also reproduced using the IDF API per @Makuna. |
@Makuna @VojtechBartoska 1- It's not Arduino related. The code here presented is IDF only related. // from setup()
for (uint8_t ch = 0; ch < RMT_CHANNEL_MAX; ch++) {
initChannel(static_cast<rmt_channel_t>(ch), static_cast<gpio_num_t>(ChannelPins[ch]));
}
// from loop()
for (uint8_t ch = 0; ch < RMT_CHANNEL_MAX; ch++) {
writeChannel(static_cast<rmt_channel_t>(ch));
} Therefore it will take time (CPU cycles) to actually write each channel in sequence and this will always create a delayed output. The closest way to make it work is to start (enable RMT_TX_START_CH bit in RMT_CHnCONF1_REG) of all channels in a single CPU clock. But this is impossible because each channel has its own Peripheral Registers in different addresses. In other words: not using IDF, but writing bare metal code to manipulate the registers directly as described in the TRM using SoC: #include "soc/gpio_reg.h"
#include "soc/rmt_struct.h" TRM: https://www.espressif.com/sites/default/files/documentation/esp32_technical_reference_manual_en.pdf Another possible solution is to not use RMT. But instead use I2S with parallel sending 8 bits in 8 GPIOs from a data buffer at a desired frequency (data rate). This will produce a perfect parallel in synch signal to all the 8 GPIOs. But this is a completely different way of solving the product/project. Final words about the issueThis is not Arduino related and the IDF refactoring #6024 will make no difference to this issue. |
In my opinion, this issue should be closed. |
@Makuna @VojtechBartoska This is the potential solution - use FastLED LIB
Researching about it, I've found FastLED Code that does exactly what I have just proposed: |
Capturing this here was meant to track a side conversation at the time of the possibility of an Arduino API being exposed. The IDF linked issue was just waiting on them to provide a unified "take action" so that I could change my code to only support either a single channel show (with this issue still a problem) or a unified show (all channels start at once) but it kept getting closed AND I never got any message on how to proceed (as there was no way for me to implement a unified show since the required code was hidden behind the IDF API). Unless I completely rewrite all my RMT, doing only one part so directly to hardware will cause far too much maintenance for me when the IDF changes. |
@Makuna ESP32 RMT can't start all channels at once because of its internal Register structure. Each channel has its own Register with associated TX_Enable bit. In order to start all the channels at once, it would be necessary to exist some other register structure for the peripheral. Therefore, it is impossible to IDF, or any other software layer, to make it happen. One way to do something very close to it, with a ready-to-use code, would be using the FastLed Library based on the example presented in these links: https://github.com/FastLED/FastLED/blob/master/src/platforms/esp/32/clockless_rmt_esp32.h I hope it helps you in your project. |
I put together a modified sketch that uses a modified RMT driver (all in the sketch folder) I think that this code will help you in accomplishing your project. I hope it helps you and others. |
I'm closing it as there is no feedback, Issue is labelled as 'Type: For reference' and can be reopened if needed. |
@SuGlider thank you for the modified driver! Are you aware of any limitations it introduces or is it an improvement all around? It might be hard to have changes merged on the driver level and would require a lot of testing, but it definitely looks very promising (Sorry that I am ignorant to the inner workings of the RMT peripheral, I'm just a power user of @Makuna 's NeoPixelBus library) |
The issue I have seen with FastLED is that the RMT was not shareable with other libraries. There is an instance of my library being used with an IR library that uses RMT hardware also. The project is an IR remote controlled LED light system, rather common commercial product. |
It is an addon on top of the current IDF RMT driver. The result is a faster way to start all RMT channel almost at the same time. I think it won't be incorporated to IDF neither to Arduino, thus there is this problem with long term support. |
I am using Arduino/PIO and also looking at a high speed multi-output SPI using clock_div=1, and so far my findings are good, albeit similar to the above I am able to start my RMT outputs within a new clock cycles of each other by using direct register writes and I am able to send 6 bytes with clock and latch in ~2us The first three channels (clock, latch and dataA) all start fully synchronised - great ! Its like the RMT struggles with outputting more than 3 channels at precisely the same time |
Hardware:
Board: ESP32 Dev Module
Core Installation version: 1.0.2 (latest public release)
IDE name: Arduino IDE
Flash Frequency: 40Mhz (default)
PSRAM enabled: no (default)
Upload Speed: 921600 (default)
Computer OS: Windows 10
Description:
When using the
rmt_write_sample
, with no wait (async) with all 8 channels, the last few channels have significant delay before the pulses are started.Channel 5 has a 1.5ms stagger from the first, which is significant from the first four.
Channel 6 has a 14.5ms stagger from the first (as captured above as dx field), which seems way out of reasonability. This seems related to a channel buffer becoming available. The timing shows that while the last pulse of channel 0 is still presently being sent, it is just sending the extended low side of the last pulse; so it will not be calling translate again for that channel; seemingly making it available to start sending channel 6.
Sketch:
The text was updated successfully, but these errors were encountered: