Skip to content

Générer des tensions variables par PWM en sortie de la Pi Pico avec MicroPython

Vous avez dit PWM ??

Tension PWM

Le PWM est l’acronyme de Pulse Width Modulation, que l’on appelle en français MLI pour Modulation de Largeur d’Impulsion.

Le PWM une technique utilisée pour générer une tension variable (ici entre 0 et 3.3V) en utilisant des sorties logiques.

Le PWM s’appuie sur la variation temporelle d’un signal logique (ici d’une tension basse 0V à une autre tension haute de 3.3V)

Image title

Le PWM permet de générer des tensions dont la valeur moyenne peut être modifiée.

Le signal PWM peut être configuré logiciellement en fonction de la largeur et de la fréquence de l’impulsion souhaitée.

Performance du PWM sur la Pi Pico

PWM sur la Pi Pico

Les signaux PWM ne sont pas générés en permanence par le microprocesseur, mais par des blocs matériels spécifiques.

Il suffit de configurer une seule fois les blocs PWM dans le script pour que le signal soit généré en permanence en arrière-plan.

Une sortie d’un bloc PWM est rattachée à une broche de la carte.

Le microprocesseur est alors disponible pour exécuter d’autres tâches.

Chaque bloc PWM peut avoir une fréquence indépendante.

Caractéristiques du PWM sur la Pi Pico
Plage de fréquence du signal PWM de 7 Hz à 125 Mhz
Fréquence PWM indépendante 8
Sortie PWM 16
Résolution de la largeur d’impulsion 65536 valeurs possibles (16 bits)

Note

En pratique, dans la majorité des cas, une fréquence PWM autour de 1000 Hz sera suffisante.

Dans certains cas, c’est intéressant de choisir une fréquence > 20kHz pour éviter d’entendre un bruit à l’oreille quand on pilote un moteur par exemple.

PWM via MicroPython avec la Pi Pico

PWM avec MicroPython

L’utilisation de PWM avec MicroPython est très simple.

MicroPython fait abstraction du hardware et sélectionne automatiquement un bloc PWM disponible.

La configuration consiste à associer un objet PWM à un objet Pin et de choisir la fréquence PWM.

1
2
3
4
5
from machine import Pin, PWM

pin = Pin(14, mode=Pin.OUT)
pin_avec_pwm = PWM(pin)
pwm_led.freq(1_000)

L'objet logiciel pin_avec_pwm est représentatif de la broche 14 à laquelle on a associé un bloc matériel PWM.

L'appel de la fonction .freq(1_000) de l'objet logiciel pin_avec_pwm permet de configurer la fréquence à 1000Hz.

Codes équivalents

Les 2 codes sont suivants équivalents.

1
2
from machine import Pin
from machine import PWM
1
from machine import Pin, PWM
Codes équivalents

Les 2 codes sont suivants équivalents.

1
2
3
4
5
from machine import Pin, PWM

pin = Pin(14, mode=Pin.OUT)
pin_avec_pwm = PWM(pin)
pwm_led.freq(1_000)
1
2
3
4
from machine import Pin, PWM

pin_avec_pwm = PWM(Pin(14, mode=Pin.OUT))
pwm_led.freq(1_000)
Note

En python, on peut utiliser des underscores _ pour rendre les grands nombres plus lisibles.

Par exemple, pour écrire 1 MHz, au lieu d’avoir 1000000 on peut écrire 1_000_000.

PWM avec MicroPython (suite)

On fait ensuite appel à la fonction .duty_u16() pour choisir la largeur d’impulsion avec une valeur comprise entre 0 et 65535.

Pour visualiser les variations de la tension via le PWM, on peut utiliser la LED intégrée de la carte Raspberry Pi Pico avec le script suivant :

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
from machine import Pin, PWM

broche_led = 25

pwm_led = PWM(Pin(broche_led, mode=Pin.OUT))

pwm_led.freq(1_000)

while True:
    for donnee_duree_impulsion in range(0, 65_536):
        pwm_led.duty_u16(donnee_duree_impulsion)

Explication

Ici la ligne de code 11 est répétée 65536 fois d'affilée avec donnee_duree_impulsion évoluant de 0 à 65535.

11
pwm_led.duty_u16(donnee_duree_impulsion)

Ces 65536 répétitions sont elles-mêmes répétées tant que la carte est alimentée.

PWM avec MicroPython (suite)

Pour rendre la chose plus intuitive, on peut spécifier uniquement le pourcentage de la largueur d’impulsion (rappport cyclique) et ensuite appliquer une formule.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
from machine import Pin, PWM
import time

broche_led = 25

pwm_led = PWM(Pin(broche_led, mode=Pin.OUT))

pwm_led.freq(1_000)

while True:
    for rapport_cyclique in range(0, 101):
        donnee_duree_impulsion = int((rapport_cyclique/100)*65535)

        pwm_led.duty_u16(donnee_duree_impulsion)

        time.sleep_ms(10)

La luminosité de la LED va ainsi être modifiée en variant entre 0 et 100% la largeur de l’impulsion.

Exercice 4.1

Exécuter le programme précédent.

Dernier exemple

Avec tout ce que l’on a vu précédemment, on propose à présent le script suivant :

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
from machine import Pin, PWM

broche_led = 25

pwm_led = PWM(Pin(broche_led, mode=Pin.OUT))

pwm_led.freq(1_000)

while True:
    for donnee_duree_impulsion in range(0,65_536, 5):
        pwm_led.duty_u16(donnee_duree_impulsion)
    for donnee_duree_impulsion in range(65_535,-1, -5):
        pwm_led.duty_u16(donnee_duree_impulsion)

Explication

Pour obtenir une variation de tension plus rapide, on fait varier le donnee_duree_impulsion de 5 en 5 avec range(0, 65_536, 5).

Pour décrémenter une valeur, on utilise un pas négatif de -5 : range(65_535, -1, -5).

Exercice 4.2

Exécuter le programme précédent.