Ignorer et passer au contenu

Livraison offerte à partir de 50€ d'achats, livrée sous 48h !

Livraison à partir de seulement 2.50€ !

Contents Menu Expand Light mode Dark mode Auto light/dark mode

Générer des tensions variables grâce au PWM de la Pi Pico en MicroPython

(Mis à jour le 12/12/2022)

Le PWM, une manière astucieuse de créer des tensions variables sur des broches numériques.

Le PWM une technique utilisée pour générer une tension variable entre 0 et 3.3V en utilisant seulement des sorties numériques. Le PWM est l’acronyme de Pulse Width Modulation , que l’on appelle en français MLI pour Modulation de Largeur d’Impulsion . C’est une astuce qui s’appuie sur la variation temporelle d’un signal logique d’une tension basse 0V à une autre tension haute de 3.3 V.

Note

Le PWM permet de générer des tensions continues dont la valeur peut être modifiée. Il ne peut pas produire des tensions alternatives comme le ferait un DAC.

fonctionnement pwm micropython

Principe du PWM

En répétant très régulièrement des impulsions à une largeur définie, on peut considérer qu’en moyenne la tension obtenue est comprise entre 0V et 3.3V dont sa valeur est déterminée par :

\[V_{sortie} = V_{entree} \times \alpha\]

Avec α la largeur d’impulsion (duty cycle en anglais)

Le signal PWM peut être configuré en fonction de la largeur et de la fréquence de l’impulsion, ce qui peut être modifié en MicroPython.

En pratique, le PWM est souvent utilisé pour :

  • Réguler la vitesse d’un moteur

  • Moduler la luminosité des LED

  • Produire des notes de musique (avec un son similaire à celui des consoles rétro)

Performance du PWM sur la Raspberry 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. Les ressources du processeur sont alors disponibles pour exécuter d’autres tâches. Chaque bloc PWM peut avoir une fréquence indépendante.

Caractéristiques du PWM de la

Pi Pico

Plage de fréquence du signal PWM

7 Hz à 125 Mhz

Fréquence PWM indépendante

8

Sortie PWM

16

Résolution de la largeur d’impulsion

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 > 10kHz pour éviter d’entendre un bruit à l’oreille quand on pilote un moteur par exemple. 🙂

Le PWM sur MicroPython avec la Pico

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.

from machine import Pin, PWM

pin = Pin(25, mode=Pin.OUT)
pin_with_pwm = PWM(pin) # Attach PWM object on a pin

Note

En réunissant l’objet PWM qui se trouve aussi dans le module machine, nous pouvons importer les deux sur une seule ligne :

from machine import Pin
from machine import PWM

Les 2 codes sont équivalents.

from machine import Pin, PWM

Une fois que la broche de la carte est attachée à notre objet PWM, toutes les fonctions s’effectuent directement sur l’objet PWM. Contrairement au code Arduino où il faut spécifier le numéro de broche avec la fonction analogWrite(pin_number) .

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 .

On fait appel à la fonction .duty_u16() pour choisir la largeur d’impulsion avec une valeur comprise entre 0 et \(2^{16}-1\) (0-65535). La tension est directement appliquée sur la broche sélectionnée précédemment.

Avertissement

Si vous avez déjà utilisé MicroPython sur l’ESP32, vous remarquerez que u_16 est ajouté au nom de la fonction. Cela signifie que la fonction attend une valeur jusqu’à 16 bits (et pas jusqu’à 10 bits lorsque l’on utilise la fonction .duty() sur l’ESP32).

Pour voir 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 :

from machine import Pin, PWM

LED_BUITLTIN = 25 # For Raspberry Pi Pico

pwm_led = PWM(Pin(LED_BUITLTIN, mode=Pin.OUT)) # Attach PWM object on the LED pin

# Settings
pwm_led.freq(1_000)

while True:
    for duty in range(0,65_536):
        pwm_led.duty_u16(duty) # For Pi Pico

Avertissement

La fonction range(0, 65_536) compte entre 0 et 65 535, excluant le dernier élément.

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

from machine import Pin, PWM

LED_BUITLTIN = 25 # For Raspberry Pi Pico

pwm_led = PWM(Pin(LED_BUITLTIN, mode=Pin.OUT)) # Attach PWM object on the LED pin
pwm_led.freq(1_000)

duty_cycle = 50 # Between 0 - 100 %
pwm_led.duty_u16(int((duty_cycle/100)*65_535))

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

from machine import Pin, PWM
import time

LED_BUITLTIN = 25 # For Raspberry Pi Pico

pwm_led = PWM(Pin(LED_BUITLTIN, mode=Pin.OUT)) # Attach PWM object on the LED pin
pwm_led.freq(1_000)

while True:
    for duty in range(101): # Duty from 0 to 100 %
        pwm_led.duty_u16(int((duty/100)*65_535))
        time.sleep_ms(10)

Mini-Projet : Faire dimmer la LED intégrée de sa Raspberry Pi Pico

Avec tout ce que l’on a vu précédemment, ce script s’écrit naturellement :

from machine import Pin, PWM
import time

LED_BUITLTIN = 25 # For Raspberry Pi Pico

pwm_led = PWM(Pin(LED_BUITLTIN, mode=Pin.OUT)) # Attach PWM object on the LED pin

# Settings
pwm_led.freq(1_000)

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

Note

Pour obtenir une variation de tension plus rapide, on fait varier le duty 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) .