La **Modulación por Ancho de Pulso** (PWM, por sus siglas en inglés) es una técnica digital para simular señales analógicas o controlar la potencia entregada a una carga variando la proporción de tiempo en que la señal digital está activa (HIGH) dentro de un período constante.
Para generar una señal PWM mediante hardware interno se utilizan tres registros principales del temporizador:
El Ciclo de Trabajo (Duty Cycle, $D$) representa el porcentaje de tiempo activo en un período:
$$ D = \left(\frac{t_{ON}}{T}\right) \times 100\% = \left(\frac{CCR}{ARR + 1}\right) \times 100\% $$
El voltaje promedio equivalente ($V_{prom}$) aplicado al componente es directo a su ciclo de trabajo:
$$ V_{prom} = V_{max} \times \left(\frac{D}{100}\right) $$
Un pin GPIO de microcontrolador solo entrega una corriente limitada (típicamente 8 a 20 mA). Para manejar un Buzzer acústico o la modulación de una válvula proporcional, se requiere una etapa de potencia de desacoplamiento con un transistor BJT o MOSFET.
| Componente Hardware | Conexión / Pin MCU | Propósito en el Sistema |
|---|---|---|
| Buzzer Piezoeléctrico Pasivo | TIM3_CH1 (Ej. Pin PA6) vía Transistor NPN (2N2222) | Retroalimentación auditiva (Beeps) al pulsar el teclado capacitivo. |
| Resistencia de Base ($R_B$) | 1 kΩ entre Pin MCU y Base del Transistor | Limitación de corriente para la conmutación saturada del BJT. |
| Diodo Antiparalelo (Flyback) | 1N4148 en paralelo con la carga inductiva/piezo | Protección contra picos de tensión inducida en conmutación. |
El siguiente código muestra cómo cambiar dinámicamente la frecuencia y el Ciclo de Trabajo ($CCR$) de un canal Timer PWM en C para generar patrones de audio breves (Beeps de confirmación) al interactuar con la interfaz.
#include <stdint.h>
#include <stdbool.h>
// Registros abstractos simulados de Hardware PWM (Timer 3, Canal 1)
typedef struct {
volatile uint32_t CR1;
volatile uint32_t PSC;
volatile uint32_t ARR;
volatile uint32_t CCR1;
} PWM_Timer_TypeDef;
#define TIM3_BASE ((PWM_Timer_TypeDef *) 0x40000400)
/**
* @brief Configura la frecuencia y el duty cycle del PWM para el Buzzer.
* @param frecuencia_hz Frecuencia deseada del tono en Hz.
* @param duty_porcentaje Ciclo de trabajo (0 a 100 %).
*/
void PWM_EstablecerTono(uint32_t frecuencia_hz, uint8_t duty_porcentaje) {
if (frecuencia_hz == 0 || duty_porcentaje == 0) {
// Silenciar PWM
TIM3_BASE->CCR1 = 0;
return;
}
uint32_t reloj_timer = 84000000; // 84 MHz
uint32_t prescaler = 83; // F_cnt = 1 MHz (1 tick = 1 us)
// Período total = 1,000,000 us / Frecuencia
uint32_t arr_valor = (1000000 / frecuencia_hz) - 1;
// Asignación de registros
TIM3_BASE->PSC = prescaler;
TIM3_BASE->ARR = arr_valor;
// Cálculo del valor del registro Compare según el Duty Cycle
if (duty_porcentaje > 100) duty_porcentaje = 100;
TIM3_BASE->CCR1 = ((arr_valor + 1) * duty_porcentaje) / 100;
}
/**
* @brief Emite un beep rápido de confirmación acústica no bloqueante.
*/
void EmitirBeepTeclado(void) {
// Generar tono claro de 2.7 kHz al 50% de volumen/potencia
PWM_EstablecerTono(2700, 50);
}
void DetenerTono(void) {
PWM_EstablecerTono(0, 0);
}
int main(void) {
// En el inicio del sistema
PWM_EstablecerTono(0, 0);
while (1) {
// Simulación: Si se detecta un toque válido en el Teclado Capacitivo 4x4
bool tecla_presionada = false; // Bandera procedente del driver I2C
if (tecla_presionada) {
EmitirBeepTeclado();
// Utilizar un Timer No-Bloqueante para llamar DetenerTono() a los 50ms
}
}
return 0;
}
Confirmación Auditiva para Panel Capacitivo e Interfaz HMI.
Al no existir botones mecánicos con "clic" en el teclado 4x4 capacitivo que diseñaste en KiCad, el usuario carece de la sensación de respuesta física. La implementación de modulación PWM dedicada te permite activar tonos audibles limpios e instantáneos ante cada pulsación confirmada por I2C. Esto eleva la seguridad y usabilidad del Despachador de Gas LP en entornos industriales ruidosos, informando al operador que la orden de despacho o comando de seguridad ha sido aceptado por el firmware.
1. Si un Timer tiene un registro $ARR = 1999$ y se configura un valor $CCR1 = 500$, ¿cuál es el ciclo de trabajo (Duty Cycle) resultante?
Respuesta: Usando la fórmula: $D = \frac{CCR}{ARR + 1} \times 100\% = \frac{500}{2000} \times 100\% = 25\%$.
2. ¿Por qué se prefiere ajustar el brillo de una pantalla o la velocidad de un motor mediante PWM en lugar de usar una resistencia variable analógica?
Respuesta: Por eficiencia energética. En PWM el transistor commuta entre corte (corriente 0) y saturación (caída de voltaje casi 0), minimizando la disipación de calor por potencia ($P = V \times I$), a diferencia de un elemento lineal que disipa el exceso en forma de calor.