#include <stdio.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "driver/gpio.h"
#include "driver/ledc.h"
#include "driver/uart.h"
#include "esp_timer.h"
/* Pinos (iguais ao seu Wokwi) */
#define LED1_GPIO 4
#define LED2_GPIO 5
#define LED3_GPIO 6
#define LED4_GPIO 7
#define BTN_A_GPIO 10
#define BTN_B_GPIO 11
#define BUZZ_GPIO 12
/* UART */
#define UART_PORT UART_NUM_0
#define UART_BAUD 115200
/* LEDC */
#define LEDC_MODE LEDC_LOW_SPEED_MODE
#define DUTY_RES LEDC_TIMER_10_BIT
#define MAX_DUTY ((1 << 10) - 1) // 1023
#define LED_FREQ_HZ 1000
#define LED_TIMER LEDC_TIMER_0
#define BUZZ_TIMER LEDC_TIMER_1
#define CH_LED1 LEDC_CHANNEL_0
#define CH_LED2 LEDC_CHANNEL_1
#define CH_LED3 LEDC_CHANNEL_2
#define CH_LED4 LEDC_CHANNEL_3
#define CH_BUZZ LEDC_CHANNEL_4
/* Estados simples */
static volatile bool btn_b_enabled = true;
static volatile bool led1_on = false;
static volatile bool led2_on = false;
/* Helpers PWM */
static void set_duty(ledc_channel_t ch, uint32_t duty) {
if (duty > MAX_DUTY) duty = MAX_DUTY;
ledc_set_duty(LEDC_MODE, ch, duty);
ledc_update_duty(LEDC_MODE, ch);
}
static void buzzer_on(uint32_t freq_hz) {
ledc_set_freq(LEDC_MODE, BUZZ_TIMER, freq_hz);
set_duty(CH_BUZZ, MAX_DUTY / 2);
}
static void buzzer_off(void) {
set_duty(CH_BUZZ, 0);
}
/* Task: toca buzzer por 1,5s */
static void buzzer_beep_task(void *arg) {
(void)arg;
buzzer_on(1200);
vTaskDelay(pdMS_TO_TICKS(1500));
buzzer_off();
vTaskDelete(NULL);
}
/* ISR dos botões */
static void IRAM_ATTR gpio_isr(void *arg) {
int pin = (int)(intptr_t)arg;
if (pin == BTN_A_GPIO) {
led1_on = !led1_on;
set_duty(CH_LED1, led1_on ? MAX_DUTY : 0);
}
if (pin == BTN_B_GPIO) {
if (!btn_b_enabled) return;
// dispara uma task para desligar depois de 1,5s
xTaskCreate(buzzer_beep_task, "beep", 2048, NULL, 10, NULL);
}
}
/* Timer software: a cada 2s alterna LED2 */
static void timer_2s_cb(void *arg) {
(void)arg;
led2_on = !led2_on;
set_duty(CH_LED2, led2_on ? MAX_DUTY : 0);
}
/* UART: 'a' desativa B, 'b' reativa B */
static void uart_task(void *arg) {
(void)arg;
uint8_t c;
while (1) {
int n = uart_read_bytes(UART_PORT, &c, 1, pdMS_TO_TICKS(100));
if (n == 1) {
if (c == 'a' || c == 'A') btn_b_enabled = false;
if (c == 'b' || c == 'B') btn_b_enabled = true;
}
}
}
/* Init LEDC */
static void ledc_init_all(void) {
// Timer LEDs (1kHz)
ledc_timer_config_t t_led = {
.speed_mode = LEDC_MODE,
.timer_num = LED_TIMER,
.duty_resolution = DUTY_RES,
.freq_hz = LED_FREQ_HZ,
.clk_cfg = LEDC_AUTO_CLK
};
ledc_timer_config(&t_led);
// Timer buzzer (freq muda)
ledc_timer_config_t t_buzz = {
.speed_mode = LEDC_MODE,
.timer_num = BUZZ_TIMER,
.duty_resolution = DUTY_RES,
.freq_hz = 1000,
.clk_cfg = LEDC_AUTO_CLK
};
ledc_timer_config(&t_buzz);
// 4 canais LEDs
ledc_channel_config_t c1 = {.gpio_num=LED1_GPIO, .speed_mode=LEDC_MODE, .channel=CH_LED1, .timer_sel=LED_TIMER, .duty=0, .hpoint=0};
ledc_channel_config_t c2 = {.gpio_num=LED2_GPIO, .speed_mode=LEDC_MODE, .channel=CH_LED2, .timer_sel=LED_TIMER, .duty=0, .hpoint=0};
ledc_channel_config_t c3 = {.gpio_num=LED3_GPIO, .speed_mode=LEDC_MODE, .channel=CH_LED3, .timer_sel=LED_TIMER, .duty=0, .hpoint=0};
ledc_channel_config_t c4 = {.gpio_num=LED4_GPIO, .speed_mode=LEDC_MODE, .channel=CH_LED4, .timer_sel=LED_TIMER, .duty=0, .hpoint=0};
ledc_channel_config(&c1);
ledc_channel_config(&c2);
ledc_channel_config(&c3);
ledc_channel_config(&c4);
// canal buzzer
ledc_channel_config_t cb = {.gpio_num=BUZZ_GPIO, .speed_mode=LEDC_MODE, .channel=CH_BUZZ, .timer_sel=BUZZ_TIMER, .duty=0, .hpoint=0};
ledc_channel_config(&cb);
buzzer_off();
}
/* Init botões */
static void buttons_init(void) {
gpio_config_t in = {
.pin_bit_mask = (1ULL << BTN_A_GPIO) | (1ULL << BTN_B_GPIO),
.mode = GPIO_MODE_INPUT,
.pull_up_en = GPIO_PULLUP_ENABLE, // botão pro GND
.pull_down_en = GPIO_PULLDOWN_DISABLE,
.intr_type = GPIO_INTR_NEGEDGE
};
gpio_config(&in);
gpio_install_isr_service(0);
gpio_isr_handler_add(BTN_A_GPIO, gpio_isr, (void*)(intptr_t)BTN_A_GPIO);
gpio_isr_handler_add(BTN_B_GPIO, gpio_isr, (void*)(intptr_t)BTN_B_GPIO);
}
/* Init UART */
static void uart_init_all(void) {
uart_config_t cfg = {
.baud_rate = UART_BAUD,
.data_bits = UART_DATA_8_BITS,
.parity = UART_PARITY_DISABLE,
.stop_bits = UART_STOP_BITS_1,
.flow_ctrl = UART_HW_FLOWCTRL_DISABLE
};
uart_driver_install(UART_PORT, 1024, 0, 0, NULL, 0);
uart_param_config(UART_PORT, &cfg);
}
void app_main(void) {
uart_init_all();
ledc_init_all();
buttons_init();
// Timer 2s
esp_timer_handle_t t2s;
esp_timer_create_args_t args = {
.callback = timer_2s_cb,
.arg = NULL,
.dispatch_method = ESP_TIMER_TASK,
.name = "t2s"
};
esp_timer_create(&args, &t2s);
esp_timer_start_periodic(t2s, 2 * 1000 * 1000);
xTaskCreate(uart_task, "uart", 2048, NULL, 5, NULL);
while (1) {
/* Fase 3: fading */
for (int d = 0; d <= (int)MAX_DUTY; d += 8) {
set_duty(CH_LED1, d);
set_duty(CH_LED2, d);
set_duty(CH_LED3, d);
set_duty(CH_LED4, d);
vTaskDelay(pdMS_TO_TICKS(10));
}
for (int d = (int)MAX_DUTY; d >= 0; d -= 8) {
set_duty(CH_LED1, d);
set_duty(CH_LED2, d);
set_duty(CH_LED3, d);
set_duty(CH_LED4, d);
vTaskDelay(pdMS_TO_TICKS(10));
}
/* Fase 4: buzzer 500..2000..500 */
for (int f = 500; f <= 2000; f += 20) {
buzzer_on((uint32_t)f);
vTaskDelay(pdMS_TO_TICKS(10));
}
for (int f = 2000; f >= 500; f -= 20) {
buzzer_on((uint32_t)f);
vTaskDelay(pdMS_TO_TICKS(10));
}
buzzer_off();
}
}