3.14. Gradation de LED par PWM#
La page Générer un signal analogique avec une PWM et un filtre RC utilisait un filtre passe-bas RC pour extraire une tension continue d’un signal PWM. Pour une LED, le filtre n’est pas nécessaire – l’œil humain lui-même effectue le moyennage.
Lorsqu’une LED est allumée et éteinte plus vite qu’environ 60 Hz, le système visuel cesse de distinguer les impulsions individuelles et perçoit une luminosité constante égale à la sortie lumineuse moyenne. Un rapport cyclique de 50 % se lit comme à peu près la moitié de la luminosité ; 25 % comme un quart ; 10 % comme faible.
Le câblage est le même que pour une LED externe statique sur Sortie GPIO – une résistance de limitation de courant en série avec la LED, dimensionnée selon les règles de Notions d’électronique. Le changement ne porte que sur le logiciel : la broche fonctionne en sortie PWM au lieu d’un simple Pin.OUT.
3.14.1. Choisir la fréquence#
Pour la gradation de LED, la fréquence PWM doit seulement franchir le seuil de scintillement de l’œil :
En dessous d’environ 60 Hz, l’œil voit franchement les impulsions.
En dessous d’environ 200 Hz, la vision périphérique et les mouvements oculaires rapides peuvent encore révéler du scintillement.
1 kHz est confortablement au-dessus de tout cela et constitue une valeur par défaut typique.
Il n’y a pas de limite supérieure significative pour une petite LED sur un GPIO ; de 1 kHz à 10 kHz, le comportement est identique pour l’œil.
3.14.2. Fondu#
Une boucle de fondu en ouverture / fondu en fermeture balaie le rapport cyclique de l’arrêt jusqu’au plein régime puis retour, en s’attardant brièvement à chaque palier :
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)
À 1 kHz de PWM et des paliers de 5 ms, l’œil perçoit un fondu fluide dans les deux directions, la luminosité apparente suivant la valeur du rapport cyclique.
La luminosité perçue n’est pas strictement linéaire en fonction du rapport cyclique – la réponse de l’œil suit approximativement une loi quadratique ou cubique – de sorte qu’un balayage linéaire de duty_u16 ne ressemble pas à un balayage linéaire de luminosité. Pour un fondu perceptivement plus régulier, faites varier le rapport cyclique selon une courbe.
Une astuce pratique en nombres entiers consiste à incrémenter un compteur 8 bits et à utiliser son carré comme rapport cyclique. 255 × 255 = 65025 est à l’arrondi près de la pleine échelle, donc le balayage couvre toute la plage :
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)
Le fondu paraît désormais à peu près régulier en luminosité apparente, de l’arrêt au plein régime.