#include <stdio.h>
#include "driver/gpio.h" // Librería para controlar los pines GPIO
#include "driver/ledc.h" // Librería para controlar los LEDs con PWM (modulación por ancho de pulso)
#include "freertos/FreeRTOS.h" // Librería de FreeRTOS para manejar tareas y retrasos
#include "freertos/task.h" // Librería para las tareas de FreeRTOS
// Definir los pines GPIO para los LEDs
#define LED1_GPIO GPIO_NUM_18 // LED 1 conectado al pin GPIO 18
#define LED2_GPIO GPIO_NUM_19 // LED 2 conectado al pin GPIO 19
#define LED3_GPIO GPIO_NUM_21 // LED 3 conectado al pin GPIO 21
// Definir los pines GPIO para los botones
#define BUTTON1_GPIO GPIO_NUM_23 // Botón 1 conectado al pin GPIO 23
#define BUTTON2_GPIO GPIO_NUM_22 // Botón 2 conectado al pin GPIO 22
#define BUTTON3_GPIO GPIO_NUM_25 // Botón 3 conectado al pin GPIO 25
// Variables que almacenan el brillo de cada LED (inicialmente 0 = apagado)
int brightness1 = 0;
int brightness2 = 0;
int brightness3 = 0;
// Variables para recordar el estado anterior de los botones (inicialmente 1 = no presionado)
int lastButtonState1 = 1;
int lastButtonState2 = 1;
int lastButtonState3 = 1;
// Declaración de la función que cambia el brillo de los LEDs
int changeBrightness(int currentBrightness);
// Función para configurar un LED con PWM (modulación por ancho de pulso)
void configure_led_pwm(int led_channel, int gpio_num) {
// Configuración del temporizador para PWM con 16 bits de resolución
ledc_timer_config_t ledc_timer = {
.speed_mode = LEDC_HIGH_SPEED_MODE, // Modo de alta velocidad
.timer_num = LEDC_TIMER_0, // Número de temporizador
.duty_resolution = LEDC_TIMER_16_BIT, // Resolución de 16 bits (65535 niveles de brillo)
.freq_hz = 200, // Frecuencia de 200 Hz para la señal PWM
.clk_cfg = LEDC_AUTO_CLK // Configuración automática del reloj
};
ledc_timer_config(&ledc_timer); // Aplicar la configuración del temporizador
// Configurar un canal de PWM para un LED específico
ledc_channel_config_t ledc_channel = {
.speed_mode = LEDC_HIGH_SPEED_MODE, // Modo de alta velocidad
.channel = led_channel, // Canal para este LED
.timer_sel = LEDC_TIMER_0, // Asignar el temporizador configurado antes
.intr_type = LEDC_INTR_DISABLE, // No queremos interrupciones
.gpio_num = gpio_num, // El pin GPIO al que está conectado el LED
.duty = 0, // Inicialmente apagado (duty cycle = 0)
.hpoint = 0 // Punto inicial de la señal PWM
};
ledc_channel_config(&ledc_channel); // Aplicar la configuración del canal PWM
}
// Función principal del programa (lo que se ejecuta cuando el ESP32 arranca)
void app_main(void) {
// Configurar PWM para los 3 LEDs
configure_led_pwm(LEDC_CHANNEL_0, LED1_GPIO); // Configura LED 1
configure_led_pwm(LEDC_CHANNEL_1, LED2_GPIO); // Configura LED 2
configure_led_pwm(LEDC_CHANNEL_2, LED3_GPIO); // Configura LED 3
// Configurar los botones como entradas
gpio_config_t io_conf; // Crear una estructura para la configuración
io_conf.intr_type = GPIO_INTR_DISABLE; // Desactivar interrupciones para los botones
io_conf.mode = GPIO_MODE_INPUT; // Configurarlos como entradas
io_conf.pin_bit_mask = (1ULL << BUTTON1_GPIO) | (1ULL << BUTTON2_GPIO) | (1ULL << BUTTON3_GPIO); // Especificar qué pines usar
io_conf.pull_up_en = GPIO_PULLUP_ENABLE; // Activar resistencias pull-up internas
io_conf.pull_down_en = GPIO_PULLDOWN_DISABLE; // Desactivar resistencias pull-down
gpio_config(&io_conf); // Aplicar la configuración
// Bucle infinito (el código se ejecuta una y otra vez)
while (true) {
// Leer el estado actual de los botones (0 = presionado, 1 = no presionado)
int buttonState1 = gpio_get_level(BUTTON1_GPIO);
int buttonState2 = gpio_get_level(BUTTON2_GPIO);
int buttonState3 = gpio_get_level(BUTTON3_GPIO);
// Si el botón 1 fue presionado (cambio de 1 a 0)
if (buttonState1 == 0 && lastButtonState1 == 1) {
// Cambiar el brillo del LED 1
brightness1 = changeBrightness(brightness1);
// Aplicar el nuevo brillo al LED 1 usando PWM
ledc_set_duty(LEDC_HIGH_SPEED_MODE, LEDC_CHANNEL_0, brightness1);
ledc_update_duty(LEDC_HIGH_SPEED_MODE, LEDC_CHANNEL_0);
}
// Actualizar el estado anterior del botón 1
lastButtonState1 = buttonState1;
// Si el botón 2 fue presionado (cambio de 1 a 0)
if (buttonState2 == 0 && lastButtonState2 == 1) {
// Cambiar el brillo del LED 2
brightness2 = changeBrightness(brightness2);
// Aplicar el nuevo brillo al LED 2 usando PWM
ledc_set_duty(LEDC_HIGH_SPEED_MODE, LEDC_CHANNEL_1, brightness2);
ledc_update_duty(LEDC_HIGH_SPEED_MODE, LEDC_CHANNEL_1);
}
// Actualizar el estado anterior del botón 2
lastButtonState2 = buttonState2;
// Si el botón 3 fue presionado (cambio de 1 a 0)
if (buttonState3 == 0 && lastButtonState3 == 1) {
// Cambiar el brillo del LED 3
brightness3 = changeBrightness(brightness3);
// Aplicar el nuevo brillo al LED 3 usando PWM
ledc_set_duty(LEDC_HIGH_SPEED_MODE, LEDC_CHANNEL_2, brightness3);
ledc_update_duty(LEDC_HIGH_SPEED_MODE, LEDC_CHANNEL_2);
}
// Actualizar el estado anterior del botón 3
lastButtonState3 = buttonState3;
// Esperar 50 milisegundos para evitar que el botón detecte múltiples pulsaciones rápidas (antirrebote)
vTaskDelay(50 / portTICK_PERIOD_MS);
}
}
// Función que cambia el brillo de los LEDs en tres niveles: apagado, 10%, y 100%
int changeBrightness(int currentBrightness) {
if (currentBrightness == 0) {
return 6553; // Aproximadamente 10% de 65535 (máximo para resolución de 16 bits)
} else if (currentBrightness == 6553) {
return 65535; // 100% del brillo
} else {
return 0; // Apagado
}
}