Page 1 of 1

LEDC Fade

Posted: Thu Oct 08, 2020 12:32 pm
by AlexESP32
Hello guys,

I don't understand the functionality of the LEDC Fade.
I would like to illustrate my problems with following example project. I took the ledc example project and only did few adjustments and then the LEDs do something garbage:

I changed the GPIO Pins to PIN 18,19,23,33 and changed the while loop. All the other stuff stay the same.

The while loop is the following:

Code: Select all

    while (1) {
        printf("1. LEDC fade up to duty = %d\n", LEDC_TEST_DUTY);
        for (ch = 0; ch < LEDC_TEST_CH_NUM; ch++) {
            ledc_set_fade_with_time(ledc_channel[ch].speed_mode,
                    ledc_channel[ch].channel, LEDC_TEST_DUTY, LEDC_TEST_FADE_TIME);
            ledc_fade_start(ledc_channel[ch].speed_mode,
                    ledc_channel[ch].channel, LEDC_FADE_NO_WAIT);
        }
// 1. adjustment: comment out the vTaskDelay
        //vTaskDelay(LEDC_TEST_FADE_TIME / portTICK_PERIOD_MS);

        printf("2. LEDC fade down to duty = 0\n");
        for (ch = 0; ch < LEDC_TEST_CH_NUM; ch++) {
            ledc_set_fade_with_time(ledc_channel[ch].speed_mode,
                    ledc_channel[ch].channel, 0, LEDC_TEST_FADE_TIME);
            ledc_fade_start(ledc_channel[ch].speed_mode,
                    ledc_channel[ch].channel, LEDC_FADE_NO_WAIT);
        }
        vTaskDelay(LEDC_TEST_FADE_TIME / portTICK_PERIOD_MS);

        printf("3. LEDC set duty = %d without fade\n", LEDC_TEST_DUTY);
        for (ch = 0; ch < LEDC_TEST_CH_NUM; ch++) {
            ledc_set_duty(ledc_channel[ch].speed_mode, ledc_channel[ch].channel, LEDC_TEST_DUTY);
            ledc_update_duty(ledc_channel[ch].speed_mode, ledc_channel[ch].channel);
        }
        vTaskDelay(1000 / portTICK_PERIOD_MS);
// 2. adjustment: comment out the following for loop
/*		
        printf("4. LEDC set duty = 0 without fade\n");
        for (ch = 0; ch < LEDC_TEST_CH_NUM; ch++) {
            ledc_set_duty(ledc_channel[ch].speed_mode, ledc_channel[ch].channel, 0);
            ledc_update_duty(ledc_channel[ch].speed_mode, ledc_channel[ch].channel);
        }
        vTaskDelay(1000 / portTICK_PERIOD_MS);*/
    }
So as you can see I only comment out a few lines.
The result looks like:

Code: Select all

I (311) cpu_start: Starting scheduler on PRO CPU.
I (0) cpu_start: Starting scheduler on APP CPU.
1. LEDC fade up to duty = 4000
2. LEDC fade down to duty = 0
W (337) ledc: LEDC FADE TOO SLOW
W (337) ledc: LEDC FADE TOO SLOW
3. LEDC set duty = 4000 without fade
1. LEDC fade up to duty = 4000
2. LEDC fade down to duty = 0
W (4337) ledc: LEDC FADE TOO SLOW
3. LEDC set duty = 4000 without fade
1. LEDC fade up to duty = 4000
2. LEDC fade down to duty = 0
3. LEDC set duty = 4000 without fade
Now 1 LED is always on and the other 3 are fading. Why there is 1 LED always on an why there is the warning message "ledc: LEDC FADE TOO SLOW"?

Thank you ;)

Re: LEDC Fade

Posted: Tue Oct 13, 2020 6:39 am
by AlexESP32
Hey,

This question is still there...

Is the answer too trivial then please let me know :D Because I dispair with this issue...

Thank you.

Re: LEDC Fade

Posted: Mon Aug 29, 2022 6:07 am
by FlorianR
Hi There,
did you find an Answer? I have the same issue...

Re: LEDC Fade

Posted: Fri Jul 19, 2024 2:35 pm
by maurospi
Check `ledc.c:1222-1244`.

The warning means that in order to fade the duty cycle in the time you specified (LEDC_TEST_FADE_TIME) you would have to increase the duty in smaller steps than the minimum.

You can fix this by either:
- lowering your PWM freq so that each cycle takes longer.
- lowering the fade time so that each step is higher than the minimum.
- increasing the change difference to that each step is higher than the minimum.

Choose one or many of the three above according to your project specs.

Cheers!

Code: Select all

    
    uint32_t duty_delta = target_duty > duty_cur ? target_duty - duty_cur : duty_cur - target_duty;
    ...
    uint32_t total_cycles = max_fade_time_ms * freq / 1000;
    ...    
    if (total_cycles > duty_delta)
    {
        scale = 1;
        cycle_num = total_cycles / duty_delta;
        if (cycle_num > LEDC_LL_DUTY_CYCLE_MAX)
        {
            ESP_LOGW(LEDC_TAG, LEDC_FADE_TOO_SLOW_STR); // The warning you see
            cycle_num = LEDC_LL_DUTY_CYCLE_MAX;
        }
    }