/* * LEDC driver para 3 LEDs (R,G,B) controlados via ULN2003 */ #include #include "freertos/FreeRTOS.h" #include "freertos/task.h" #include "driver/ledc.h" #include "esp_err.h" #include "ledc_driver.h" // Pode ser futuramente ligado a uma opção de Kconfig. // Para o teu hardware (comum a 12 V via ULN2003), visto do ESP é ativo-alto. #define IS_ACTIVE_HIGH 1 #define LEDC_LS_TIMER LEDC_TIMER_2 #define LEDC_LS_MODE LEDC_LOW_SPEED_MODE // Canais usados: 2, 3, 4 #define LEDC_CH_RED LEDC_CHANNEL_2 #define LEDC_CH_GREEN LEDC_CHANNEL_3 #define LEDC_CH_BLUE LEDC_CHANNEL_4 #define LEDC_NUM_CHANNELS (3) #define LEDC_DUTY_RES LEDC_TIMER_13_BIT #define LEDC_DUTY_MAX (8192 - 1) #define LEDC_FREQUENCY (5000) // 5 kHz static ledc_channel_config_t ledc_channel[LEDC_NUM_CHANNELS] = { { .channel = LEDC_CH_RED, .duty = 0, .gpio_num = -1, // preenchido em runtime .speed_mode = LEDC_LS_MODE, .hpoint = 0, .timer_sel = LEDC_LS_TIMER, }, { .channel = LEDC_CH_GREEN, .duty = 0, .gpio_num = -1, .speed_mode = LEDC_LS_MODE, .hpoint = 0, .timer_sel = LEDC_LS_TIMER, }, { .channel = LEDC_CH_BLUE, .duty = 0, .gpio_num = -1, .speed_mode = LEDC_LS_MODE, .hpoint = 0, .timer_sel = LEDC_LS_TIMER, }, }; esp_err_t ledc_init(gpio_num_t gpio_red, gpio_num_t gpio_green, gpio_num_t gpio_blue) { // Configuração do timer ledc_timer_config_t ledc_timer = { .duty_resolution = LEDC_DUTY_RES, .freq_hz = LEDC_FREQUENCY, .speed_mode = LEDC_LS_MODE, .timer_num = LEDC_LS_TIMER, .clk_cfg = LEDC_AUTO_CLK, }; esp_err_t err = ledc_timer_config(&ledc_timer); if (err != ESP_OK) { return err; } // Atribuir GPIOs aos canais ledc_channel[0].gpio_num = gpio_red; ledc_channel[1].gpio_num = gpio_green; ledc_channel[2].gpio_num = gpio_blue; // Configurar canais for (int ch = 0; ch < LEDC_NUM_CHANNELS; ch++) { err = ledc_channel_config(&ledc_channel[ch]); if (err != ESP_OK) { return err; } } return ESP_OK; } esp_err_t ledc_set_rgb(uint32_t red, uint32_t green, uint32_t blue) { if (red > 255) red = 255; if (green > 255) green = 255; if (blue > 255) blue = 255; red = red * LEDC_DUTY_MAX / 255; green = green * LEDC_DUTY_MAX / 255; blue = blue * LEDC_DUTY_MAX / 255; if (!IS_ACTIVE_HIGH) { red = LEDC_DUTY_MAX - red; green = LEDC_DUTY_MAX - green; blue = LEDC_DUTY_MAX - blue; } ledc_set_duty(LEDC_LS_MODE, LEDC_CH_RED, red); ledc_update_duty(LEDC_LS_MODE, LEDC_CH_RED); ledc_set_duty(LEDC_LS_MODE, LEDC_CH_GREEN, green); ledc_update_duty(LEDC_LS_MODE, LEDC_CH_GREEN); ledc_set_duty(LEDC_LS_MODE, LEDC_CH_BLUE, blue); ledc_update_duty(LEDC_LS_MODE, LEDC_CH_BLUE); return ESP_OK; } esp_err_t ledc_clear(void) { return ledc_set_rgb(0, 0, 0); }