3.14. Regolazione della luminosità dei LED con il PWM¶
La pagina Generare segnali analogici con PWM e un filtro RC utilizzava un filtro passa-basso RC per estrarre una tensione continua da un segnale PWM. Per un LED il filtro non è necessario: è l’occhio umano stesso a effettuare la media.
Quando un LED viene acceso e spento più velocemente di circa 60 Hz, il sistema visivo smette di risolvere i singoli impulsi e percepisce una luminosità costante pari all’emissione luminosa media. Un duty cycle del 50 % appare all’incirca come metà luminosità; il 25 % come un quarto; il 10 % come fioco.
Il cablaggio è lo stesso di un LED esterno statico in Uscita GPIO – una resistenza di limitazione della corrente in serie con il LED, dimensionata usando le regole di Nozioni di base di elettronica. La differenza è solo nel software: il pin funziona come uscita PWM invece di un semplice Pin.OUT.
3.14.1. Scelta della frequenza¶
Per la regolazione della luminosità dei LED la frequenza PWM deve solo superare la soglia di sfarfallio dell’occhio:
Al di sotto di ~60 Hz l’occhio vede direttamente gli impulsi.
Al di sotto di ~200 Hz la visione periferica e i movimenti oculari rapidi possono ancora rivelare lo sfarfallio.
1 kHz è comodamente al di sopra di tutto ciò ed è un valore predefinito tipico.
Non esiste un limite superiore rilevante per un piccolo LED su un GPIO; qualsiasi valore da 1 kHz a 10 kHz appare uguale all’occhio.
3.14.2. Dissolvenza¶
Un ciclo di dissolvenza in entrata / dissolvenza in uscita fa variare il duty cycle da spento a completamente acceso e ritorno, sostando brevemente a ogni passo:
import time
from machine import PWM, Pin
led = PWM(Pin("P7"), freq=1000, duty_u16=0)
while True:
for d in range(0, 65535, 256):
led.duty_u16(d)
time.sleep_ms(5)
for d in range(65535, 0, -256):
led.duty_u16(d)
time.sleep_ms(5)
Con PWM a 1 kHz e passi da 5 ms l’occhio vede una dissolvenza fluida in entrambe le direzioni, con la luminosità apparente che segue il valore del duty.
La luminosità percepita non è strettamente lineare rispetto al duty cycle – la risposta dell’occhio segue all’incirca una legge quadratica o cubica – quindi una variazione lineare di duty_u16 non appare come una variazione lineare della luminosità. Per una dissolvenza percettivamente più fluida, si faccia variare il duty seguendo una curva.
Un comodo trucco basato solo su interi consiste nell’incrementare un contatore a 8 bit e usare il suo quadrato come duty cycle. 255 × 255 = 65025 è entro l’arrotondamento del fondo scala, quindi la variazione copre l’intero intervallo:
import time
from machine import PWM, Pin
led = PWM(Pin("P7"), freq=1000, duty_u16=0)
while True:
for step in range(256):
led.duty_u16(step * step) # 0..65025, roughly quadratic
time.sleep_ms(5)
for step in range(255, -1, -1):
led.duty_u16(step * step)
time.sleep_ms(5)
La dissolvenza ora appare all’incirca uniforme in luminosità apparente, da spento a pieno regime.