3.13. Geração de sinal analógico com PWM e um filtro RC¶
O ADC lê tensões num pino. O oposto – produzir uma tensão intermédia entre 0 V e Vcc num pino – é mais difícil, porque uma saída GPIO apenas sabe como conduzir os seus dois rails. A substituição padrão é comutar o pino entre os rails suficientemente rápido para que a tensão média seja o que nos interessa.
3.13.1. Modulação por largura de impulso¶
Um sinal modulado por largura de impulso (PWM) é uma onda quadrada a uma frequência fixa cujo tempo em alto – a fração de cada ciclo passada em Vcc em vez de massa – é definida em software. Essa fração é o ciclo de trabalho. 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 % tem uma média de Vcc / 4; um ciclo de trabalho de 50 % de Vcc / 2; um ciclo de trabalho de 75 % de 3 × Vcc / 4.
PWM a 25 %, 50 % e 75 % de ciclo de trabalho. 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 envolve um canal de temporizador de hardware que gera a forma de onda sem intervenção do CPU – uma vez configurado, o sinal continua à frequência e ciclo de trabalho escolhidos até ser alterado.
3.13.2. A classe machine.PWM¶
Construa uma instância PWM com o pino e uma frequência e ciclo de trabalho iniciais:
from machine import PWM, Pin
pwm = PWM(Pin("P7"), freq=20_000, duty_u16=32768)
Isto inicia uma onda quadrada a 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() aceita um número inteiro sem sinal de 16 bits mapeando 0 para «sempre em baixo» e 65535 para «sempre em alto». freq() define a frequência portadora em hertz.
Nota
Todos os canais PWM no mesmo temporizador de hardware partilham a sua frequência. Chamar freq() num canal altera todos os outros canais ligados a esse temporizador. Use canais de temporizadores diferentes quando as saídas precisam de funcionar a frequências diferentes.
Chame deinit() para libertar o canal do temporizador quando a saída já não for necessária.
3.13.3. Suavização com um filtro passa-baixo RC¶
O PWM em bruto não é uma tensão suave; é uma onda quadrada cuja média é o que pretendemos. Para extrair essa média, passe o PWM por um filtro passa-baixo – a mesma combinação de resistor e condensador usada para eliminar a rejeição de contacto em Eliminação de ressalto.
PWM através de um filtro passa-baixo RC: o condensador suaviza a onda quadrada numa tensão DC proporcional ao ciclo de trabalho.¶
A frequência de corte do filtro – o limite entre as frequências que este deixa passar e as que bloqueia – é definida pelo mesmo produto RC que deu a constante de tempo para o circuito de eliminação de rejeição de contacto:
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 inferior à própria frequência PWM. A componente DC (frequência 0) passa sem alterações; o harmónico fundamental do PWM (à frequência PWM) é atenuado por aproximadamente f_c / f_PWM. Um rácio de 1 / 200 reduz o ripple residual na saída para cerca de 0.5 % da excursão de entrada.
Um ponto de partida razoável para um ponto de ajuste de variação lenta:
Frequência PWM
f_PWM = 20 kHz– bem acima do áudio, e fácil de gerar de forma limpa pelo temporizador.Valores do filtro
R = 1.6 kΩ,C = 1 µF– dandof_c = 1 / (2π × 1.6 kΩ × 1 µF) ≈ 100 Hz.
A supressão de 200× na portadora reduz a excursão total do PWM para aproximadamente Vcc / 200 de ripple residual em V_out – cerca de 16 mV a 3,3 V.
Duas notas práticas:
A impedância de saída do filtro é aproximadamente
R. Qualquer carga a jusante que drene corrente transformaRe a carga num divisor que puxaV_outabaixo da média ideal, exatamente como o divisor na página Leitura analógica com o ADC. Alimente um pino ADC ou um buffer de alta impedância, não uma carga que absorva miliamperes.O condensador demora cerca de
5 × R × C ≈ 8 msa estabilizar quando o ciclo de trabalho muda;V_outatrasa o valor de ciclo de trabalho definido por esse tempo. Para um ponto de ajuste que precise de atualizar mais rapidamente, aumente a frequência de corte (RouCmenor) e aceite mais ripple.