3.13. Generare segnali analogici con PWM e un filtro RC¶
L’ADC legge le tensioni su un pin. L’operazione opposta, ovvero produrre su un pin una tensione intermedia tra 0 V e Vcc, è più difficile, perché un’uscita GPIO sa pilotare solo le sue due alimentazioni. Il sostituto standard consiste nel commutare il pin tra le alimentazioni abbastanza velocemente da rendere la tensione media il valore di interesse.
3.13.1. Modulazione di larghezza di impulso¶
Un segnale modulato in larghezza di impulso (PWM) è un’onda quadra a frequenza fissa il cui tempo di livello alto, cioè la frazione di ogni ciclo trascorsa a Vcc anziché a massa, viene impostato via software. Quella frazione è il duty cycle. La tensione media della forma d’onda è il duty cycle moltiplicato per Vcc:
V_avg = duty × Vcc
Un duty cycle del 25 % dà in media Vcc / 4; un duty cycle del 50 % dà Vcc / 2; un duty cycle del 75 % dà 3 × Vcc / 4.
PWM con duty cycle del 25 %, 50 % e 75 %. La tensione media segue il duty cycle.¶
La frequenza viene impostata al momento della configurazione del PWM; il duty cycle è ciò che il software modifica al volo. La classe machine.PWM incapsula un canale di un timer hardware che genera la forma d’onda senza l’intervento della CPU: una volta configurato, il segnale prosegue alla frequenza e al duty cycle scelti finché non vengono modificati.
3.13.2. La classe machine.PWM¶
Costruisci un’istanza di PWM con il pin e una frequenza e un duty cycle iniziali:
from machine import PWM, Pin
pwm = PWM(Pin("P7"), freq=20_000, duty_u16=32768)
Questo avvia un’onda quadra a 20 kHz con duty cycle del 50 % su P7. Due metodi modificano l’uscita al volo:
pwm.duty_u16(16384) # change to 25 % (16384 / 65535)
pwm.freq(5_000) # change to 5 kHz
duty_u16() accetta un intero a 16 bit senza segno che associa 0 a «sempre basso» e 65535 a «sempre alto». freq() imposta la frequenza portante in hertz.
Nota
Tutti i canali PWM sullo stesso timer hardware condividono la frequenza. Chiamare freq() su un canale modifica ogni altro canale collegato a quel timer. Usa canali di timer diversi quando le uscite devono funzionare a frequenze diverse.
Chiama deinit() per rilasciare il canale del timer quando l’uscita non serve più.
3.13.3. Mediazione con un filtro passa-basso RC¶
Il PWM grezzo non è una tensione regolare; è un’onda quadra la cui media è ciò che ci interessa. Per estrarre quella media, fai passare il PWM attraverso un filtro passa-basso, la stessa combinazione di resistore e condensatore usata per l’antirimbalzo degli interruttori in Debouncing.
PWM attraverso un filtro passa-basso RC: il condensatore media l’onda quadra in una tensione continua proporzionale al duty cycle.¶
La frequenza di taglio del filtro, ovvero il confine tra le frequenze che lascia passare e quelle che blocca, è determinata dallo stesso prodotto RC che dava la costante di tempo per il circuito antirimbalzo:
f_c = 1 / (2π × R × C)
Affinché il filtro estragga una tensione continua pulita da un ingresso PWM, la frequenza di taglio deve essere molto più bassa della frequenza PWM stessa. La componente continua (frequenza 0) passa inalterata; la prima armonica del PWM (alla frequenza PWM) viene attenuata di circa f_c / f_PWM. Un rapporto di 1 / 200 riduce l’ondulazione residua all’uscita a circa lo 0.5 % dell’escursione di ingresso.
Un punto di partenza ragionevole per un valore di consegna a variazione lenta:
Frequenza PWM
f_PWM = 20 kHz, ben al di sopra della banda audio e facile da generare in modo pulito per il timer.Valori del filtro
R = 1.6 kΩ,C = 1 µF, che dannof_c = 1 / (2π × 1.6 kΩ × 1 µF) ≈ 100 Hz.
La soppressione di 200× alla portante riduce l’escursione completa del PWM a circa Vcc / 200 di ondulazione residua in V_out, ovvero circa 16 mV a 3,3 V.
Due note pratiche:
L’impedenza di uscita del filtro è all’incirca
R. Qualsiasi carico a valle che assorbe corrente trasformaRe il carico in un partitore che tiraV_outal di sotto della media ideale, esattamente come il partitore nella pagina Leggere segnali analogici con l’ADC. Alimenta un pin ADC o un buffer ad alta impedenza, non un carico che assorbe milliampere.Il condensatore impiega circa
5 × R × C ≈ 8 msad assestarsi quando il duty cycle cambia;V_outinsegue l’impostazione del duty con quel ritardo. Per un valore di consegna che deve aggiornarsi più velocemente, aumenta la frequenza di taglio (RoCpiù piccoli) e accetta più ondulazione.