/*
Modifique o exemplo de código apresentado na videoaula (reproduzido abaixo) para controlar os três LEDs RGB da placa BitDogLab usando o módulo PWM e interrupções, seguindo as orientações a seguir:
O LED vermelho deve ser acionado com um PWM de 1kHz.
O duty cycle deve ser iniciado em 5% e atualizado a cada 2 segundos em incrementos de 5%. Quando atingir o valor máximo, deve retornar a 5%.
O LED azul deve ser acionado com um PWM de 10kHz.
*/
#include <stdio.h>
#include "pico/stdlib.h"
#include "hardware/pwm.h"
// Definição dos pinos dos LEDs
#define LED_VERM_PIN 13 // LED Vermelho (1 kHz)
#define LED_AZUL_PIN 12 // LED Azul (10 kHz)
#define LED_VERDE_PIN 11 // LED Verde (fixo)
// Parâmetros de PWM
const float CLK_DIV = 16.0;
const uint16_t PERIOD_1KHZ = 1250; // 1 kHz = (125Mhz / (16 * 1250))
const uint16_t PERIOD_10KHZ = 125; // 10 kHz = (125Mhz / (16 * 125))
const uint16_t DUTY_STEP = 5; // Incremento de 5%
const uint32_t TEMPO_ATUALIZACAO = 2000; // Atualiza a cada 2 segundos
const uint32_t PWM_REFRESH_LEVEL = 40000; // Suavização do fade
// Duty cycle inicial
uint16_t duty_cycle_vermelho = PERIOD_1KHZ * DUTY_STEP / 100;
uint16_t duty_cycle_azul = PERIOD_10KHZ * DUTY_STEP / 100;
// Configuração do PWM para um LED específico
void setup_pwm(uint pin, uint16_t period, uint16_t duty_cycle) {
gpio_set_function(pin, GPIO_FUNC_PWM);
uint slice = pwm_gpio_to_slice_num(pin);
pwm_set_clkdiv(slice, CLK_DIV);
pwm_set_wrap(slice, period);
pwm_set_gpio_level(pin, duty_cycle);
pwm_set_enabled(slice, true);
}
// Manipulador de interrupção para suavizar fade dos LEDs Vermelho e Azul
void pwm_irq_handler() {
static uint32_t count = 0;
static uint8_t up_down_verm = 1;
static uint8_t up_down_azul = 1;
uint slice_verm = pwm_gpio_to_slice_num(LED_VERM_PIN);
uint slice_azul = pwm_gpio_to_slice_num(LED_AZUL_PIN);
pwm_clear_irq(slice_verm);
pwm_clear_irq(slice_azul);
if (count++ < PWM_REFRESH_LEVEL) return;
count = 0;
// Atualiza LED Vermelho (fade)
if (up_down_verm) {
duty_cycle_vermelho += PERIOD_1KHZ * DUTY_STEP / 100;
if (duty_cycle_vermelho >= PERIOD_1KHZ) up_down_verm = 0;
} else {
duty_cycle_vermelho -= PERIOD_1KHZ * DUTY_STEP / 100;
if (duty_cycle_vermelho <= PERIOD_1KHZ * DUTY_STEP / 100) up_down_verm = 1;
}
pwm_set_gpio_level(LED_VERM_PIN, duty_cycle_vermelho);
// Atualiza LED Azul (fade)
if (up_down_azul) {
duty_cycle_azul += PERIOD_10KHZ * DUTY_STEP / 100;
if (duty_cycle_azul >= PERIOD_10KHZ) up_down_azul = 0;
} else {
duty_cycle_azul -= PERIOD_10KHZ * DUTY_STEP / 100;
if (duty_cycle_azul <= PERIOD_10KHZ * DUTY_STEP / 100) up_down_azul = 1;
}
pwm_set_gpio_level(LED_AZUL_PIN, duty_cycle_azul);
}
// Atualiza o duty cycle dos LEDs Vermelho e Azul a cada 2s e imprime os valores no terminal
void update_duty_cycles() {
static absolute_time_t last_update = 0;
if (absolute_time_diff_us(last_update, get_absolute_time()) < TEMPO_ATUALIZACAO * 1000) {
return;
}
last_update = get_absolute_time();
// Imprime os valores dos duty cycles no terminal
printf("LED Vermelho: %d%% | LED Azul: %d%%\n",
(duty_cycle_vermelho * 100) / PERIOD_1KHZ,
(duty_cycle_azul * 100) / PERIOD_10KHZ);
}
// Configuração do PWM para LEDs Vermelho e Azul com fade
void setup_pwm_fade() {
setup_pwm(LED_VERM_PIN, PERIOD_1KHZ, duty_cycle_vermelho);
setup_pwm(LED_AZUL_PIN, PERIOD_10KHZ, duty_cycle_azul);
uint slice_verm = pwm_gpio_to_slice_num(LED_VERM_PIN);
uint slice_azul = pwm_gpio_to_slice_num(LED_AZUL_PIN);
pwm_clear_irq(slice_verm);
pwm_clear_irq(slice_azul);
pwm_set_irq_enabled(slice_verm, true);
pwm_set_irq_enabled(slice_azul, true);
irq_set_exclusive_handler(PWM_IRQ_WRAP, pwm_irq_handler);
irq_set_enabled(PWM_IRQ_WRAP, true);
}
int main() {
stdio_init_all();
setup_pwm_fade();
setup_pwm(LED_VERDE_PIN, 1000, 500); // LED Verde fixo (50% duty cycle)
while (true) {
update_duty_cycles();
sleep_ms(100);
}
}