Skip to content
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

ESP32 Incorrect timing on the last few items when sending more than certain rmt_item32 at a time through RMT (IDFGH-3580) #5524

Closed
weixiongmei opened this issue Jul 1, 2020 · 5 comments
Labels
Resolution: Done Issue is done internally Status: Done Issue is done internally

Comments

@weixiongmei
Copy link

weixiongmei commented Jul 1, 2020

Problem Description

When I tried to send more than 20 items by using esp_err_trmt_write_items, the timing of the last few rmt_item32 being incorrect.

CODE

#define RMT_TX_CHANNEL RMT_CHANNEL_0
#define CONFIG_EXAMPLE_RMT_TX_GPIO 15

#define RATIO (float)(40000000 / 1e9)
#define WS2812_T0H_NS (uint32_t)(350 * RATIO)
#define WS2812_T0L_NS (uint32_t)(850 * RATIO)
#define WS2812_T1H_NS (uint32_t)(600 * RATIO)
#define WS2812_T1L_NS (uint32_t)(600 * RATIO)
#define WS2812_RESET_US (uint32_t)(80 * 1000 * RATIO)

static const rmt_item32_t morse_on[] = {
    {{{WS2812_T0H_NS, 1, WS2812_T0L_NS, 0}}},
    {{{WS2812_T0H_NS, 1, WS2812_T0L_NS, 0}}},
    {{{WS2812_T0H_NS, 1, WS2812_T0L_NS, 0}}},
    {{{WS2812_T0H_NS, 1, WS2812_T0L_NS, 0}}},
    {{{WS2812_T0H_NS, 1, WS2812_T0L_NS, 0}}},
    {{{WS2812_T0H_NS, 1, WS2812_T0L_NS, 0}}},
    {{{WS2812_T0H_NS, 1, WS2812_T0L_NS, 0}}},
    {{{WS2812_T0H_NS, 1, WS2812_T0L_NS, 0}}},

    {{{WS2812_T0H_NS, 1, WS2812_T0L_NS, 0}}},
    {{{WS2812_T0H_NS, 1, WS2812_T0L_NS, 0}}},
    {{{WS2812_T0H_NS, 1, WS2812_T0L_NS, 0}}},
    {{{WS2812_T0H_NS, 1, WS2812_T0L_NS, 0}}},
    {{{WS2812_T0H_NS, 1, WS2812_T0L_NS, 0}}},
    {{{WS2812_T0H_NS, 1, WS2812_T0L_NS, 0}}},
    {{{WS2812_T0H_NS, 1, WS2812_T0L_NS, 0}}},
    {{{WS2812_T0H_NS, 1, WS2812_T0L_NS, 0}}},

    {{{WS2812_T0H_NS, 1, WS2812_T0L_NS, 0}}},
    {{{WS2812_T0H_NS, 1, WS2812_T0L_NS, 0}}},
    {{{WS2812_T0H_NS, 1, WS2812_T0L_NS, 0}}},
    {{{WS2812_T0H_NS, 1, WS2812_T0L_NS, 0}}},
    {{{WS2812_T0H_NS, 1, WS2812_T0L_NS, 0}}},
    {{{WS2812_T0H_NS, 1, WS2812_T0L_NS, 0}}},
    {{{WS2812_T0H_NS, 1, WS2812_T0L_NS, 0}}},
    {{{WS2812_T0H_NS, 1, WS2812_T0L_NS, 0}}},
};

static const rmt_item32_t morse_off[] = {
    {{{WS2812_T0H_NS, 1, WS2812_T0L_NS, 0}}},
    {{{WS2812_T0H_NS, 1, WS2812_T0L_NS, 0}}},
    {{{WS2812_T0H_NS, 1, WS2812_T0L_NS, 0}}},
    {{{WS2812_T0H_NS, 1, WS2812_T0L_NS, 0}}},
    {{{WS2812_T0H_NS, 1, WS2812_T0L_NS, 0}}},
    {{{WS2812_T0H_NS, 1, WS2812_T0L_NS, 0}}},
    {{{WS2812_T0H_NS, 1, WS2812_T0L_NS, 0}}},
    {{{WS2812_T0H_NS, 1, WS2812_T0L_NS, 0}}},
};
/*
 * Initialize the RMT Tx channel
 */
static void rmt_tx_init(void)
{
  config.tx_config.loop_en = false;
  config.rmt_mode = RMT_MODE_TX;
  config.tx_config.carrier_en = false;
  config.tx_config.idle_level = RMT_IDLE_LEVEL_LOW;
  config.tx_config.idle_output_en = false;
  config.tx_config.carrier_duty_percent = 50;
  config.clk_div = 2;

  ESP_ERROR_CHECK(rmt_config(&config));
  ESP_ERROR_CHECK(rmt_driver_install(config.channel, 0, 0));
}
void app_main()
{
  rmt_tx_init();
  uint8_t size = 24; //When sending less than 20 items the timing has no problem.
  while (true)
  {
   rmt_write_items(RMT_TX_CHANNEL, morse_on, size, true);
    vTaskDelay(100 / portTICK_PERIOD_MS);
  }
}

Environment

IDF: v4.2-dev-1905-g625bd5eb1
Toolchain version: esp-2020r2
Compiler version: 8.2.0

  • Development Kit: ESP32-Wrover-Kit
  • Build System: Make
  • Operating System: macOS
  • Power Supply: USB

Screenshots Sending Less Than 20 Items

Screen Shot 2020-06-30 at 9 49 24 PM

## Screenshots Sending Over 20 Items

Screen Shot 2020-06-30 at 9 45 52 PM

Screen Shot 2020-06-30 at 9 45 56 PM

@github-actions github-actions bot changed the title ESP32 Incorrect timing on the last few items when sending more than certain rmt_item32 at a time through RMT ESP32 Incorrect timing on the last few items when sending more than certain rmt_item32 at a time through RMT (IDFGH-3580) Jul 1, 2020
@Alvin1Zhang
Copy link
Collaborator

Thanks for reporting, we will look into.

@wilhelmw201
Copy link

wilhelmw201 commented Jul 2, 2020

Hi, weixiongmei,

Thank you for your detailed description, however I was unable to reproduce the problem with your code. Here is the code that I used:

#include "sdkconfig.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "esp_log.h"
#include "driver/rmt.h"

#define RMT_TX_CHANNEL RMT_CHANNEL_0

#define RATIO (float)(40000000 / 1e9)
#define WS2812_T0H_NS (uint32_t)(350 * RATIO)
#define WS2812_T0L_NS (uint32_t)(850 * RATIO)
#define WS2812_T1H_NS (uint32_t)(600 * RATIO)
#define WS2812_T1L_NS (uint32_t)(600 * RATIO)
#define WS2812_RESET_US (uint32_t)(80 * 1000 * RATIO)

static const rmt_item32_t morse_on[] = {
    {{{WS2812_T0H_NS, 1, WS2812_T0L_NS, 0}}},
    {{{WS2812_T0H_NS, 1, WS2812_T0L_NS, 0}}},
    {{{WS2812_T0H_NS, 1, WS2812_T0L_NS, 0}}},
    {{{WS2812_T0H_NS, 1, WS2812_T0L_NS, 0}}},
    {{{WS2812_T0H_NS, 1, WS2812_T0L_NS, 0}}},
    {{{WS2812_T0H_NS, 1, WS2812_T0L_NS, 0}}},
    {{{WS2812_T0H_NS, 1, WS2812_T0L_NS, 0}}},
    {{{WS2812_T0H_NS, 1, WS2812_T0L_NS, 0}}},

    {{{WS2812_T0H_NS, 1, WS2812_T0L_NS, 0}}},
    {{{WS2812_T0H_NS, 1, WS2812_T0L_NS, 0}}},
    {{{WS2812_T0H_NS, 1, WS2812_T0L_NS, 0}}},
    {{{WS2812_T0H_NS, 1, WS2812_T0L_NS, 0}}},
    {{{WS2812_T0H_NS, 1, WS2812_T0L_NS, 0}}},
    {{{WS2812_T0H_NS, 1, WS2812_T0L_NS, 0}}},
    {{{WS2812_T0H_NS, 1, WS2812_T0L_NS, 0}}},
    {{{WS2812_T0H_NS, 1, WS2812_T0L_NS, 0}}},

    {{{WS2812_T0H_NS, 1, WS2812_T0L_NS, 0}}},
    {{{WS2812_T0H_NS, 1, WS2812_T0L_NS, 0}}},
    {{{WS2812_T0H_NS, 1, WS2812_T0L_NS, 0}}},
    {{{WS2812_T0H_NS, 1, WS2812_T0L_NS, 0}}},
    {{{WS2812_T0H_NS, 1, WS2812_T0L_NS, 0}}},
    {{{WS2812_T0H_NS, 1, WS2812_T0L_NS, 0}}},
    {{{WS2812_T0H_NS, 1, WS2812_T0L_NS, 0}}},
    {{{WS2812_T0H_NS, 1, WS2812_T0L_NS, 0}}},
};

static void rmt_tx_init(void)
{
  rmt_config_t config;
  config.channel = RMT_TX_CHANNEL;
  config.mem_block_num = 1;
  config.gpio_num = 15;

  config.tx_config.loop_en = false;
  config.rmt_mode = RMT_MODE_TX;
  config.tx_config.carrier_en = false;
  config.tx_config.idle_level = RMT_IDLE_LEVEL_LOW;
  config.tx_config.idle_output_en = false;


  config.clk_div = 2;

  ESP_ERROR_CHECK(rmt_config(&config));
  ESP_ERROR_CHECK(rmt_driver_install(config.channel, 0, 0));
  
}
void app_main()
{
  rmt_tx_init();
  uint8_t size = 24; //When sending less than 20 items the timing has no problem.
  while (true)
  {
   rmt_write_items(RMT_TX_CHANNEL, morse_on, size, true);
    vTaskDelay(1000 / portTICK_PERIOD_MS);
  }
}

I was able to get a stable signal of 360ns high - 840 ns low on my computer with a esp32wroverb. Could you please test with the above program?

@weixiongmei
Copy link
Author

@wilhelmw201 Hi, I tried your code, the timing of the last few items still incorrect, is your external memory enabled? I upload the my sdkconfig file to see is it causing the problem or not. Thanks~~

sdkconfig.zip

@wilhelmw201
Copy link

Hi weixiongmei,

thank you for your response. The problem is caused by the power management unit. For now, please disable PM, or use a power management lock to keep the PM from interfering with the APB clock when RMT is not complete.

An example of using the power management lock:

esp_pm_lock_handle_t hd;
esp_pm_lock_create(ESP_PM_APB_FREQ_MAX, 0, "my_rmt_apb_lock", &hd);

then,

esp_pm_lock_acquire(hd);
rmt_write_items(RMT_TX_CHANNEL, my_data, size, true); // this function needs to block, or sleep for some ticks or something
esp_pm_lock_release(hd);

@weixiongmei
Copy link
Author

@wilhelmw201, Thank you so much, it's fixed~~

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Resolution: Done Issue is done internally Status: Done Issue is done internally
Projects
None yet
Development

No branches or pull requests

4 participants