ESP32-C3 LEDC frequency changes in light sleep

NP-ISI
Posts: 2
Joined: Tue Jul 08, 2025 1:43 pm

ESP32-C3 LEDC frequency changes in light sleep

Postby NP-ISI » Wed Jul 16, 2025 3:01 pm

Hi everyone,

I posted an issue here https://github.com/espressif/esp-idf/issues/16246 but I'm not sure that it's a software issue and did not get an answer there so I'm opening this topic.

I'm using a custom board with ESP32-C3-MINI-1, the chip is ESP32-C3 (QFN32) (revision v0.4).
The esp idf version is 5.4.1

What is the expected behavior?
LEDC frequency should not change in light sleep.

What is the actual behavior?
LEDC frequency is reduced by almost 20% in light sleep.

Steps to reproduce
From ledc_basic_example:
1. Set clk_cfg to LEDC_USE_RC_FAST
2. Enable RC_FAST domain to be active during sleep => esp_sleep_pd_config(ESP_PD_DOMAIN_RC_FAST, ESP_PD_OPTION_ON);
3. Allow pin to change during sleep => gpio_sleep_sel_dis(LEDC_OUTPUT_IO);
4. Change some basic parameters to be closer to the actual usecase
5. Add a flag for sleep state to see it on a scope

Code: Select all

#include <stdio.h>
#include "driver/ledc.h"
#include "esp_err.h"
#include "esp_sleep.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"

#define LEDC_TIMER              LEDC_TIMER_1
#define LEDC_MODE               LEDC_LOW_SPEED_MODE
#define LEDC_OUTPUT_IO          (2) // Define the output GPIO
#define LEDC_CHANNEL            LEDC_CHANNEL_1
#define LEDC_DUTY_RES           LEDC_TIMER_10_BIT // Set duty resolution to 10 bits
#define LEDC_DUTY               (102) // Set duty to 10%. (2 ** 10) * 10% = 102
#define LEDC_FREQUENCY          (2400) // Frequency in Hertz. Set frequency at 2.4 kHz
#define GPIO_FLAG_SLEEP         (3)

static void example_ledc_init(void)
{
    // Prepare and then apply the LEDC PWM timer configuration
    ledc_timer_config_t ledc_timer = {
        .speed_mode       = LEDC_MODE,
        .duty_resolution  = LEDC_DUTY_RES,
        .timer_num        = LEDC_TIMER,
        .freq_hz          = LEDC_FREQUENCY,  // Set output frequency at 2.4 kHz
        .clk_cfg          = SOC_MOD_CLK_RC_FAST
    };
    ESP_ERROR_CHECK(ledc_timer_config(&ledc_timer));

    // Prepare and then apply the LEDC PWM channel configuration
    ledc_channel_config_t ledc_channel = {
        .speed_mode     = LEDC_MODE,
        .channel        = LEDC_CHANNEL,
        .timer_sel      = LEDC_TIMER,
        .intr_type      = LEDC_INTR_DISABLE,
        .gpio_num       = LEDC_OUTPUT_IO,
        .duty           = 0, // Set duty to 0%
        .hpoint         = 0,
    };
    ESP_ERROR_CHECK(ledc_channel_config(&ledc_channel));
}

static void gpio_init(){
    // Configure the GPIO for the sleep flag output
    gpio_config_t io_conf = {
        .intr_type = GPIO_INTR_DISABLE,
        .pin_bit_mask = (1ULL << GPIO_FLAG_SLEEP),
        .mode = GPIO_MODE_OUTPUT,
        .pull_up_en = 0,
        .pull_down_en = 0,
    };
    gpio_config(&io_conf);
    gpio_set_level(GPIO_FLAG_SLEEP, 0); // Set the GPIO to low initially
}

void app_main(void)
{
    // Set the LEDC peripheral configuration
    example_ledc_init();
    gpio_init();
    esp_sleep_enable_timer_wakeup(300000);	// set sleep duration to 300ms
    gpio_sleep_sel_dis(LEDC_OUTPUT_IO);
    gpio_sleep_sel_dis(GPIO_FLAG_SLEEP);
    esp_sleep_pd_config(ESP_PD_DOMAIN_RC_FAST, ESP_PD_OPTION_ON);

    while(1){
        // Set duty to 10%
        ESP_ERROR_CHECK(ledc_set_duty(LEDC_MODE, LEDC_CHANNEL, LEDC_DUTY));
        ESP_ERROR_CHECK(ledc_update_duty(LEDC_MODE, LEDC_CHANNEL));
        vTaskDelay(pdMS_TO_TICKS(300)); // Wait for 300ms

        gpio_set_level(GPIO_FLAG_SLEEP, 1); // Set GPIO to high to indicate sleep state
        esp_light_sleep_start();    //sleep for 300ms
        gpio_set_level(GPIO_FLAG_SLEEP, 0); // Set GPIO to low to indicate wake state

        vTaskDelay(pdMS_TO_TICKS(300)); // Wait for another 300ms before setting duty to 0%

        // Set duty to 0%
        ESP_ERROR_CHECK(ledc_set_duty(LEDC_MODE, LEDC_CHANNEL, 0));
        ESP_ERROR_CHECK(ledc_update_duty(LEDC_MODE, LEDC_CHANNEL));

        vTaskDelay(pdMS_TO_TICKS(2000)); // Wait 2s in off state
    }   
}


More Information

The frequency returns to the correct value when the chip exits the sleep state, as shown below.
Yellow : LEDC_OUTPUT_IO
Blue : GPIO_FLAG_SLEEP
The top part of the screenshot shows the whole acquisition of 1s. The bottom part shows a zoomed extract of the acquisition.

Frequency is normal right before sleep (2.402kHz)
Image


It drops during sleep (2.040kHz)
Image


Then goes back to normal in wake state (2.402kHz)
Image



The frequency drop is not the same across all boards
Since my post on github, I did more tests on other boards. I observed drops in frequency from 5% up to 30%.

The frequency is not stable during light sleep
The frequency is stable in wake state, but it oscillates by a few percent during light sleep

Hardware
The board is powered by usb, the module is supplied (3.3V) by an LDO (TLV75733PDBVR)
The pin with the PWM is connected to the gate of a MOSFET


Any ideas on what could cause this behaviour?

Thanks

Sprite
Espressif staff
Espressif staff
Posts: 10593
Joined: Thu Nov 26, 2015 4:08 am

Re: ESP32-C3 LEDC frequency changes in light sleep

Postby Sprite » Fri Jul 18, 2025 3:36 am

Hm, I'd expect some deviation (because you're running of a RC osc, which is dependent on temperature, voltage supply, ...) but not 30%. Not sure what's going on there. You may be better off switching to something that is derived from the crystal, though.

NP-ISI
Posts: 2
Joined: Tue Jul 08, 2025 1:43 pm

Re: ESP32-C3 LEDC frequency changes in light sleep

Postby NP-ISI » Mon Aug 04, 2025 4:22 pm

After experimenting with the XTAL clock source, I found out that the problem was between chair and keyboard. Simply adding the following line to ledc_channel solved it (the drops were much lower and the jitter was gone).

Code: Select all

.sleep_mode		= LEDC_SLEEP_MODE_KEEP_ALIVE,

Who is online

Users browsing this forum: No registered users and 1 guest