LEDC Fade
Posted: Sat Aug 01, 2020 2:09 pm
Hello guys.
I struggle with the LEDC API and the fade functionality...
My code:
First in my opinion this is maybe an error or should give some warning:
If I increase the frequency of the timer to 5000Hz the LEDC_TEST_FADE_TIME isn't 1000ms anymore. Same when the frequency is too low (10Hz)...
Maybe you can explain why this causes problems?
Then there are some more questions:
Why is there no fade_stop functionality so I can stop the fading immediately?
Is there any reason? I would like to stop and start the fading at every time...
For example I want to stop fading and after that i want to set the value of the LED with ledc_set_duty & ledc_update_duty.
Thank you
I struggle with the LEDC API and the fade functionality...
My code:
Code: Select all
#include <stdio.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/queue.h" // for xQueue* stuff
#include "driver/ledc.h"
#include "esp_err.h"
#define LEDC_HS_TIMER LEDC_TIMER_0
#define LEDC_HS_MODE LEDC_HIGH_SPEED_MODE
#define LEDC_HS_CH0_GPIO (2)
#define LEDC_HS_CH0_CHANNEL LEDC_CHANNEL_0
#define LEDC_HS_CH1_GPIO (5)
#define LEDC_HS_CH1_CHANNEL LEDC_CHANNEL_1
#define LEDC_TEST_CH_NUM (2)
#define LEDC_TEST_DUTY (8000)
#define LEDC_TEST_FADE_TIME (1000)
#define GPIO_INPUT_IO_0 4
#define GPIO_INPUT_PIN_SEL (1ULL<<GPIO_INPUT_IO_0)
#define ESP_INTR_FLAG_DEFAULT 0
static xQueueHandle gpio_evt_queue = NULL;
static bool fade_inverted = false;
static xQueueHandle evt_queue = NULL;
// ISR routine for changing fade direction of LEDC demo
int led_fade_stop = false;
static void IRAM_ATTR gpio_isr_handler(void* arg)
{
uint32_t gpio_num = (uint32_t) arg;
int abc = 2;
xQueueSendFromISR(gpio_evt_queue, &gpio_num, NULL);
xQueueSendFromISR(evt_queue, &abc, NULL);
}
static void gpio_task_example(void* arg)
{
uint32_t io_num;
for(;;) {
if(xQueueReceive(gpio_evt_queue, &io_num, portMAX_DELAY)) {
led_fade_stop = 2;
printf("GPIO[%d] intr, val: %d\n", io_num, gpio_get_level(io_num));
}
}
}
static void IRAM_ATTR toggle_fade_isr( void *dummy ) {
fade_inverted = !fade_inverted;
xQueueSendFromISR(evt_queue, &fade_inverted, NULL);
}
void app_main(void)
{
gpio_config_t io_conf;
//interrupt of rising edge
io_conf.intr_type = GPIO_PIN_INTR_POSEDGE;
//bit mask of the pins, use GPIO4/5 here
io_conf.pin_bit_mask = GPIO_INPUT_PIN_SEL;
//set as input mode
io_conf.mode = GPIO_MODE_INPUT;
//enable pull-up mode
io_conf.pull_up_en = 1;
//disable pull-down mode
io_conf.pull_down_en = 0;
gpio_config(&io_conf);
//change gpio intrrupt type for one pin
gpio_set_intr_type(GPIO_INPUT_IO_0, GPIO_INTR_ANYEDGE);
//create a queue to handle gpio event from isr
gpio_evt_queue = xQueueCreate(10, sizeof(uint32_t));
xTaskCreate(gpio_task_example, "gpio_task_example", 2048, NULL, 10, NULL);
//install gpio isr service
gpio_install_isr_service(ESP_INTR_FLAG_DEFAULT);
//hook isr handler for specific gpio pin
gpio_isr_handler_add(GPIO_INPUT_IO_0, gpio_isr_handler, (void*) GPIO_INPUT_IO_0);
//remove isr handler for gpio number.
gpio_isr_handler_remove(GPIO_INPUT_IO_0);
//hook isr handler for specific gpio pin again
gpio_isr_handler_add(GPIO_INPUT_IO_0, gpio_isr_handler, (void*) GPIO_INPUT_IO_0);
int ch;
evt_queue = xQueueCreate(1, sizeof(uint32_t)); // never more than one event
ledc_timer_config_t ledc_timer = {
.duty_resolution = LEDC_TIMER_13_BIT, // resolution of PWM duty
.freq_hz = 5000, // frequency of PWM signal
.speed_mode = LEDC_HS_MODE, // timer mode
.timer_num = LEDC_HS_TIMER, // timer index
.clk_cfg = LEDC_AUTO_CLK, // Auto select the source clock
};
// Set configuration of timer0 for high speed channels
ledc_timer_config(&ledc_timer);
ledc_channel_config_t ledc_channel[LEDC_TEST_CH_NUM] = {
{
.channel = LEDC_HS_CH0_CHANNEL,
.duty = 0,
.gpio_num = LEDC_HS_CH0_GPIO,
.speed_mode = LEDC_HS_MODE,
.hpoint = 0,
.intr_type = LEDC_INTR_FADE_END,
.timer_sel = LEDC_HS_TIMER
},
{
.channel = LEDC_HS_CH1_CHANNEL,
.duty = 0,
.gpio_num = LEDC_HS_CH1_GPIO,
.speed_mode = LEDC_HS_MODE,
.hpoint = 0,
.intr_type = LEDC_INTR_FADE_END,
.timer_sel = LEDC_HS_TIMER
},
};
// Set LED Controller with previously prepared configuration
for (ch = 0; ch < LEDC_TEST_CH_NUM; ch++) {
ledc_channel_config(&ledc_channel[ch]);
}
// Initialize fade service.
ledc_fade_func_install(ESP_INTR_FLAG_SHARED);
ledc_isr_register(toggle_fade_isr, NULL, ESP_INTR_FLAG_IRAM|ESP_INTR_FLAG_SHARED, NULL);
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);
}
while (1) {
int inverted;
if( xQueueReceive(evt_queue, &inverted, portMAX_DELAY)) {
if(inverted == 2)
{
printf("inverted == 2\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);
}*/
for (ch = 0; ch < LEDC_TEST_CH_NUM; ch++) {
ledc_stop(ledc_channel[ch].speed_mode, ledc_channel[ch].channel,0);
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(10 / portTICK_PERIOD_MS);
for (ch = 0; ch < LEDC_TEST_CH_NUM; ch++) {
ledc_set_fade_with_time(ledc_channel[ch].speed_mode,
ledc_channel[ch].channel, inverted == 1? 0 : LEDC_TEST_DUTY, LEDC_TEST_FADE_TIME);
ledc_fade_start(ledc_channel[ch].speed_mode,
ledc_channel[ch].channel, LEDC_FADE_NO_WAIT);
}
break;
}
printf("Fade %s GetTickckount: %dms\n", inverted == 1? "out" : "in", xTaskGetTickCount()*1000/configTICK_RATE_HZ );
for (ch = 0; ch < LEDC_TEST_CH_NUM; ch++) {
ledc_set_fade_with_time(ledc_channel[ch].speed_mode,
ledc_channel[ch].channel, inverted == 1? 0 : LEDC_TEST_DUTY, LEDC_TEST_FADE_TIME);
ledc_fade_start(ledc_channel[ch].speed_mode,
ledc_channel[ch].channel, LEDC_FADE_NO_WAIT);
}
}
vTaskDelay(1);
}
}
If I increase the frequency of the timer to 5000Hz the LEDC_TEST_FADE_TIME isn't 1000ms anymore. Same when the frequency is too low (10Hz)...
Maybe you can explain why this causes problems?
Then there are some more questions:
Why is there no fade_stop functionality so I can stop the fading immediately?
Is there any reason? I would like to stop and start the fading at every time...
For example I want to stop fading and after that i want to set the value of the LED with ledc_set_duty & ledc_update_duty.
Thank you