3.13. Gerando sinais analógicos com PWM e um filtro RC¶
O ADC lê tensões em um pino. O oposto – produzir uma tensão intermediária entre 0 V e Vcc em um pino – é mais difícil, porque uma saída GPIO só sabe acionar seus dois trilhos. O substituto padrão é chavear o pino entre os trilhos rápido o suficiente para que a tensão média seja o que importa.
3.13.1. Modulação por largura de pulso¶
Um sinal modulado por largura de pulso (PWM) é uma onda quadrada de frequência fixa cujo tempo em nível alto – a fração de cada ciclo gasta em Vcc em vez do terra – é definido por software. Essa fração é o ciclo de trabalho (duty cycle). A tensão média da forma de onda é o ciclo de trabalho multiplicado por Vcc:
V_avg = duty × Vcc
Um ciclo de trabalho de 25 % resulta em uma média de Vcc / 4; um ciclo de trabalho de 50 % em Vcc / 2; um ciclo de trabalho de 75 % em 3 × Vcc / 4.
PWM com ciclo de trabalho de 25 %, 50 % e 75 %. A tensão média acompanha o ciclo de trabalho.¶
A frequência é definida quando o PWM é configurado; o ciclo de trabalho é o que o software altera em tempo real. A classe machine.PWM encapsula um canal de timer de hardware que gera a forma de onda sem ajuda da CPU – uma vez configurado, o sinal continua na frequência e no ciclo de trabalho escolhidos até ser alterado.
3.13.2. A classe machine.PWM¶
Construa uma instância de PWM com o pino e uma frequência e um ciclo de trabalho iniciais:
from machine import PWM, Pin
pwm = PWM(Pin("P7"), freq=20_000, duty_u16=32768)
Isso inicia uma onda quadrada de 20 kHz com 50 % de ciclo de trabalho em P7. Dois métodos alteram a saída em tempo real:
pwm.duty_u16(16384) # change to 25 % (16384 / 65535)
pwm.freq(5_000) # change to 5 kHz
duty_u16() recebe um inteiro de 16 bits sem sinal que mapeia 0 para “sempre baixo” e 65535 para “sempre alto”. freq() define a frequência da portadora em hertz.
Nota
Cada canal de PWM no mesmo timer de hardware compartilha sua frequência. Chamar freq() em um canal altera todos os outros canais ligados àquele timer. Use canais de timers diferentes quando as saídas precisarem operar em frequências diferentes.
Chame deinit() para liberar o canal do timer quando a saída não for mais necessária.
3.13.3. Calculando a média com um filtro passa-baixas RC¶
O PWM bruto não é uma tensão suave; é uma onda quadrada cuja média é o que queremos. Para extrair essa média, passe o PWM por um filtro passa-baixas – a mesma combinação de resistor e capacitor usada para o debounce de chaves em Debouncing.
PWM através de um filtro passa-baixas RC: o capacitor calcula a média da onda quadrada, transformando-a em uma tensão DC proporcional ao ciclo de trabalho.¶
A frequência de corte do filtro – a fronteira entre as frequências que ele deixa passar e as que ele bloqueia – é definida pelo mesmo produto RC que deu a constante de tempo do circuito de debounce:
f_c = 1 / (2π × R × C)
Para que o filtro extraia uma tensão DC limpa de uma entrada PWM, a frequência de corte deve ser muito menor que a própria frequência do PWM. A componente DC (frequência 0) passa inalterada; o harmônico fundamental do PWM (na frequência do PWM) é atenuado por aproximadamente f_c / f_PWM. Uma razão de 1 / 200 reduz o ripple residual na saída para cerca de 0.5 % da variação da entrada.
Um ponto de partida razoável para um setpoint que muda lentamente:
Frequência do PWM
f_PWM = 20 kHz– bem acima da faixa de áudio, e fácil de o timer gerar de forma limpa.Valores do filtro
R = 1.6 kΩ,C = 1 µF– resultando emf_c = 1 / (2π × 1.6 kΩ × 1 µF) ≈ 100 Hz.
A supressão de 200× na portadora reduz a variação total do PWM para cerca de Vcc / 200 de ripple residual em V_out – aproximadamente 16 mV a 3,3 V.
Duas observações práticas:
A impedância de saída do filtro é aproximadamente
R. Qualquer carga a jusante que drene corrente transformaRe a carga em um divisor que puxaV_outabaixo da média ideal, exatamente como o divisor na página Lendo sinais analógicos com o ADC. Alimente um pino de ADC ou um buffer de alta impedância, não uma carga que drene miliamperes.O capacitor leva cerca de
5 × R × C ≈ 8 mspara estabilizar quando o ciclo de trabalho muda;V_outfica atrasado em relação ao ajuste do ciclo de trabalho por esse tempo. Para um setpoint que precise atualizar mais rápido, aumente a frequência de corte (RouCmenores) e aceite mais ripple.