/* Embarcatech: 21-01-2025
Autor: Marcio Barbosa
4 - Microcontroladores - Tarefa 1 - Firmware Embarcado
exerc_5. Controlar os três LEDs RGB usando o módulo PWM e interrupções.
1. O LED vermelho deve ser acionado com um PWM de 1kHz.
2. 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%.
3. O LED azul deve ser acionado com um PWM de 10kHz.
Para realizar este experimento, foi necessário os seguintes componentes:
1 x Raspberry Pi Pico W ,
3 x LED (RGB)
3 x Resistor de 330 ohms
*/
#include <stdio.h>
#include "pico/stdlib.h"
#include "pico/cyw43_arch.h"
#include "hardware/pwm.h"
// Definição dos pinos dos LEDs RGB
#define LED_R 12 // Pino do LED Vermelho
#define LED_B 13 // Pino do LED Azul
#define LED_G 14 // Pino do LED Verde
// Constantes para o PWM
const uint16_t PERIOD = 2000; // Período do PWM (valor máximo do contador)
const float CLOCK_DIVIDER = 16.0; // Divisor fracional do clock para o PWM
volatile uint16_t duty_cycle_r = 5; // duty cycle inicial do LED vermelho
// Função para configurar PWM
void setup_pwm(uint pin, float freq, uint16_t duty) {
gpio_set_function(pin, GPIO_FUNC_PWM); // Configura o pino do LED para função PWM
uint slice = pwm_gpio_to_slice_num(pin); // Obtém o slice do PWM associado ao pino do LED
// Configuração do clock do PWM
float clock_div = 125000000 / (freq * PERIOD); //https://forums.raspberrypi.com/viewtopic.php?t=317593
pwm_set_clkdiv(slice, clock_div); // Define o divisor de clock do PWM
pwm_set_wrap(slice, PERIOD); // Configura o valor máximo do contador (período do PWM)
// Configura o duty cycle
pwm_set_gpio_level(pin, (duty * PERIOD) / 100); // Define o nível inicial do PWM para o pino do LED
pwm_set_enabled(slice, true); // Habilita o PWM no slice correspondente
}
// Função para alterar duty cycle do LED vermelho a cada 2 segundos
bool update_duty_r(struct repeating_timer *t) {
duty_cycle_r += 5;
if (duty_cycle_r > 100) {
duty_cycle_r = 5; // Reinicia para 5%
}
// Atualiza PWM do LED vermelho
pwm_set_gpio_level(LED_R, (duty_cycle_r * PERIOD) / 100);
printf("Novo duty_cycle: %d%%\n", duty_cycle_r);
return true; // Mantém a interrupção ativa
}
int main() {
stdio_init_all();
// Configurar PWM para os LEDs
setup_pwm(LED_R, 1000, duty_cycle_r); // LED Vermelho - 1kHz, duty inicial 5%
setup_pwm(LED_B, 10000, 50); // LED Azul - 10kHz, duty fixo 50%
// Criar temporizador repetitivo para alterar o duty cycle do LED vermelho -- https://forums.raspberrypi.com/viewtopic.php?t=338620
struct repeating_timer timer; //passa a struct para atualizar o duty
add_repeating_timer_ms(1000, update_duty_r, NULL, &timer);
while (1) {
tight_loop_contents(); // Loop principal vazio, pois a interrupção cuida da atualização
}
}