Page 1 of 1

Seeking Assistance to Reduce Delay in PWM Pulse Output

Posted: Mon Jun 12, 2023 8:16 am
by hkqwerty
Hello everyone,

I am currently working on a project where I am using the ESP32's LEDC module to generate a pulse output in response to an input trigger. However, I am facing an issue with a delay of one full cycle before the first rising edge of the pulse is generated. I am seeking help to eliminate this delay.

Ideally, I would like to achieve a situation where the rising edge of the pulse is generated within 30 microseconds after receiving the trigger.

Here's a summary of the problem and the steps I have taken so far:

Symptoms:
- I have implemented the pulse output using the LEDC module on the ESP32, triggered by an input signal.
- The pulse's frequency is set to 500Hz, but there is a delay of approximately 2.010ms from the moment the trigger is received until the output is generated.
- I believe this 2ms delay corresponds to one full cycle.

Steps taken:
- I have observed that the behavior differs when I execute the "ledc_timer_config" function every time a trigger is received versus only changing the duty cycle.
- If I execute "ledc_timer_config" before generating the pulse output, it consistently introduces a delay of around 2.010ms.
- By changing the duty cycle to either 0 or any other value, I can observe that the first rising edge occurs within a range of 100 microseconds to 2ms.
- Upon checking the counter value of the timer being used, I discovered that when the counter value is closer to overflow, the delay is smaller, whereas when the counter value is farther from overflow, the delay is larger.
- Unfortunately, I cannot directly set the counter value as it is read-only.

I would greatly appreciate any suggestions or insights into how I can eliminate or reduce this delay. My goal is to generate the rising edge of the pulse within 30 microseconds after receiving the trigger.

Thank you in advance for your help and suggestions!
  1.     ledc_timer_config_t ledc_timer =
  2.     {
  3.         .speed_mode         = LEDC_HIGH_SPEED_MODE,
  4.         .duty_resolution    = LEDC_TIMER_14_BIT,
  5.         .timer_num          = LEDC_TIMER_0,
  6.         .freq_hz            = 500,
  7.         .clk_cfg            = LEDC_AUTO_CLK
  8.     };
  9.  
  10.     if (ledc_timer_config(&ledc_timer) != ESP_OK)
  11.     {
  12.         Serial.println("ledc setup failed!");
  13.     }
  14.  
  15.     ledc_channel_config_t ledc_channel =
  16.     {
  17.         .gpio_num           = GPIO_NUM_14,
  18.         .speed_mode         = LEDC_HIGH_SPEED_MODE,
  19.         .channel            = LEDC_CHANNEL_0,
  20.         .intr_type          = LEDC_INTR_DISABLE,
  21.         .timer_sel          = LEDC_TIMER_0,
  22.         .duty               = 0,
  23.         .hpoint             = 0
  24.     };
  25.  
  26.     ledc_channel_config(&ledc_channel);
  27.     ledc_set_duty(LEDC_HIGH_SPEED_MODE, LEDC_CHANNEL_0, DUTY);
  28.     ledc_update_duty(LEDC_HIGH_SPEED_MODE, LEDC_CHANNEL_0);
Best regards,
hkqwerty

Re: Seeking Assistance to Reduce Delay in PWM Pulse Output

Posted: Tue Jun 13, 2023 3:54 pm
by bidrohini

Code: Select all

ledc_timer_config_t ledc_timer = {
    .speed_mode         = LEDC_HIGH_SPEED_MODE,
    .duty_resolution    = LEDC_TIMER_14_BIT,
    .timer_num          = LEDC_TIMER_0,
    .freq_hz            = 500,
    .clk_cfg            = LEDC_AUTO_CLK
};

if (ledc_timer_config(&ledc_timer) != ESP_OK) {
    Serial.println("ledc setup failed!");
}

ledc_channel_config_t ledc_channel = {
    .gpio_num           = GPIO_NUM_14,
    .speed_mode         = LEDC_HIGH_SPEED_MODE,
    .channel            = LEDC_CHANNEL_0,
    .intr_type          = LEDC_INTR_DISABLE,
    .timer_sel          = LEDC_TIMER_0,
    .duty               = 0,
    .hpoint             = 0  // Adjust this value for phase alignment
};

ledc_channel_config(&ledc_channel);
ledc_set_duty(LEDC_HIGH_SPEED_MODE, LEDC_CHANNEL_0, 0);  // Set initial duty to 0
ledc_update_duty(LEDC_HIGH_SPEED_MODE, LEDC_CHANNEL_0);

// ... Wait for trigger event ...

// Upon trigger event:
ledc_set_duty(LEDC_HIGH_SPEED_MODE, LEDC_CHANNEL_0, DUTY);  // Set desired duty cycle
ledc_update_duty(LEDC_HIGH_SPEED_MODE, LEDC_CHANNEL_0);
Give this a try.

Re: Seeking Assistance to Reduce Delay in PWM Pulse Output

Posted: Tue Jun 04, 2024 7:08 am
by krector
I too noticed this behavior.

I added code to save LEDC_LSTIMER0_VALUE_REG in an array every 5 usec for 1.5 milliseconds (300 values) after the call to ledc_update_duty().

I tried this with two values for ledc_timer_config_t.duty_resolution, 10 and 11 with the following results.

1. .duty_resolution = 10 (0-1024)

In this case, LEDC_LSTIMER0_VALUE_REG remains at zero (000) for .560 msec before beginning to count and then counted to 1024 before setting output high to start the duty phase of the first period. That is 1.315 msec after the call to ledc_update_duty().

value output
0 0 0
1 0 0
2 0 0
.
.
.
110 0 0
111 0 0
112 1 0
113 7 0
114 14 0
115 21 0
.
.
.
262 1013 0
263 1020 0
264 3 1
265 9 1
.
.
.

2. .duty_resolution = 11 (0-2048)

In this case, LEDC_LSTIMER0_VALUE_REG had counted to 495 before the first sample and then counted to 2048 before setting output high to start the duty phase of the first period. It took .570 msec to count from 495 to 2048.

value output
0 495 0
1 523 0
2 536 0
3 548 0
.
.
.
112 2016 0
113 2029 0
114 2043 0
115 9 0
116 22 1
117 35 1
.
.
.

Conclusion:

Using code based on the ESP LEDC example and described in the ESP-IDF Programming Guide, Version 5.2.2, the initial period following LEDC configuration is not a standard period and does not include a duty phase.

The duration of this initial period depends on the duty resolution. When duty resolution is 10 bits, this initial period does not begin until approximately 550 usec after the call to ledc_update_duty().

When duty resolution is greater than 10 bits, this initial period begins some time after the timer has counted up some number of counts and ends when the timer reaches the duty resolution, with no duty phase. The timer may be reset to zero after the call to ledc_update_duty() to cause the initial period to be the expected number of counts, but there will still not be a duty phase during this initial period.

In my experiments, setting duty to zero and then setting duty to the desired value as suggested by @bidrohini does not solve this problem.

My application does not require instant response after the configuration so I simply added a wait loop until the timer value was correct.

Re: Seeking Assistance to Reduce Delay in PWM Pulse Output

Posted: Tue Jun 04, 2024 8:29 am
by ok-home
Hi,
You will most likely encounter delays when processing the trigger for your task,
most likely the mcpwm module will work best for you
https://github.com/espressif/esp-idf/bl ... ple_main.c