3.13. Generación de señales analógicas con PWM y un filtro RC¶
El ADC lee tensiones en un pin. Lo contrario (producir una tensión intermedia entre 0 V y Vcc en un pin) es más difícil, porque una salida GPIO solo sabe cómo controlar sus dos raíles. El sustituto estándar es conmutar el pin entre los raíles lo bastante rápido como para que la tensión media sea lo que te interesa.
3.13.1. Modulación por ancho de pulso¶
Una señal modulada por ancho de pulso (PWM) es una onda cuadrada de frecuencia fija cuyo tiempo en alto (la fracción de cada ciclo que pasa en Vcc en lugar de en tierra) se establece por software. Esa fracción es el ciclo de trabajo. La tensión media de la forma de onda es el ciclo de trabajo multiplicado por Vcc:
V_avg = duty × Vcc
Un ciclo de trabajo del 25 % promedia Vcc / 4; un ciclo de trabajo del 50 %, Vcc / 2; un ciclo de trabajo del 75 %, 3 × Vcc / 4.
PWM con ciclos de trabajo del 25 %, 50 % y 75 %. La tensión media sigue al ciclo de trabajo.¶
La frecuencia se establece cuando se configura el PWM; el ciclo de trabajo es lo que el software cambia sobre la marcha. La clase machine.PWM envuelve un canal de temporizador por hardware que genera la forma de onda sin ayuda de la CPU: una vez configurada, la señal continúa a la frecuencia y el ciclo de trabajo elegidos hasta que se modifique.
3.13.2. La clase machine.PWM¶
Construye una instancia de PWM con el pin y una frecuencia y ciclo de trabajo iniciales:
from machine import PWM, Pin
pwm = PWM(Pin("P7"), freq=20_000, duty_u16=32768)
Eso inicia una onda cuadrada de 20 kHz con un ciclo de trabajo del 50 % en P7. Dos métodos cambian la salida sobre la marcha:
pwm.duty_u16(16384) # change to 25 % (16384 / 65535)
pwm.freq(5_000) # change to 5 kHz
duty_u16() toma un entero sin signo de 16 bits que asigna 0 a «siempre en bajo» y 65535 a «siempre en alto». freq() establece la frecuencia portadora en hercios.
Nota
Cada canal PWM del mismo temporizador por hardware comparte su frecuencia. Llamar a freq() en un canal cambia todos los demás canales conectados a ese temporizador. Usa canales de temporizadores distintos cuando las salidas deban funcionar a frecuencias diferentes.
Llama a deinit() para liberar el canal del temporizador cuando ya no se necesite la salida.
3.13.3. Promediado con un filtro RC paso bajo¶
El PWM en bruto no es una tensión suave; es una onda cuadrada cuya media es lo que queremos. Para extraer esa media, pasa el PWM por un filtro paso bajo: la misma combinación de resistencia y condensador utilizada para el antirrebote de interruptores en Eliminación de rebotes (debouncing).
PWM a través de un filtro RC paso bajo: el condensador promedia la onda cuadrada hasta obtener una tensión continua proporcional al ciclo de trabajo.¶
La frecuencia de corte del filtro (la frontera entre las frecuencias que deja pasar y las que bloquea) viene dada por el mismo producto RC que daba la constante de tiempo para el circuito antirrebote:
f_c = 1 / (2π × R × C)
Para que el filtro extraiga una tensión continua limpia a partir de una entrada PWM, la frecuencia de corte debe ser mucho menor que la propia frecuencia del PWM. La componente continua (frecuencia 0) pasa sin cambios; el armónico fundamental del PWM (a la frecuencia del PWM) se atenúa aproximadamente en f_c / f_PWM. Una relación de 1 / 200 reduce el rizado residual en la salida hasta cerca del 0.5 % de la excursión de entrada.
Un punto de partida razonable para una consigna de cambio lento:
Frecuencia del PWM
f_PWM = 20 kHz: muy por encima del audio, y fácil de generar de forma limpia para el temporizador.Valores del filtro
R = 1.6 kΩ,C = 1 µF: que danf_c = 1 / (2π × 1.6 kΩ × 1 µF) ≈ 100 Hz.
La supresión de 200× en la portadora reduce la excursión completa del PWM hasta aproximadamente Vcc / 200 de rizado residual en V_out: unos 16 mV a 3,3 V.
Dos notas prácticas:
La impedancia de salida del filtro es aproximadamente
R. Cualquier carga aguas abajo que consuma corriente convierteRy la carga en un divisor que tira deV_outpor debajo de la media ideal, exactamente igual que el divisor de la página Lectura de señales analógicas con el ADC. Alimenta un pin de ADC o un búfer de alta impedancia, no una carga que absorba miliamperios.El condensador tarda unos
5 × R × C ≈ 8 msen estabilizarse cuando cambia el ciclo de trabajo;V_outse retrasa respecto al ajuste del ciclo de trabajo en esa cantidad. Para una consigna que deba actualizarse más rápido, sube la frecuencia de corte (RoCmás pequeñas) y acepta más rizado.