CentraleSupélec LMF, UMR CNRS 9021
Département informatique Laboratoire Méthodes Formelles
Bât Breguet, 3 rue Joliot-Curie Bât 650 Ada Lovelace, Université Paris Sud
91190 Gif-sur-Yvette, France Rue Noetzlin, 91190 Gif-sur-Yvette, France
Tutoriel Pyboard

Table des matières

La pyboard est une carte équipée d'un processeur STM32F4 et conçue pour le développement sous Micropython.

Elle est très facile à utiliser grâce à son système de fichiers (elle se comporte comme une clef USB quand on la branche) et son interpréteur python (accessible sur un port série) qui permet de prototyper très rapidement.

Premier contact

Pour programmer la pyboard, il suffit de disposer d'un éditeur de texte. Une fois la pyboard connectée à votre ordinateur, ouvrez le volume qui a dû apparaître (probablement sous le nom PYBFLASH). Vous devriez y trouver :

  • boot.py, qui contient le code exécuté au démarrage de la carte
  • main.py, qui contient le code exécuté après le démarrage
  • pybcdc.inf, driver de port série pour Windows
  • README.txt

Pour exécuter du code sur la pyboard, il suffit de le placer dans le fichier main.py d'éjecter le volume et de redémarrer la carte en appuyant sur son bouton RST.

Écrivez le code suivant dans le fichier main.py, enregistrez le fichier, éjectez le volume et faites redémarrer la pyboard :

import pyb

leds = [pyb.LED(i+1) for i in range(4)]
i = 0
while True :
  for j in range(4) :
    if j == i :
      leds[j].on()
    else:
      leds[j].off()

  pyb.delay(100)
  i = (i+1)%4

Vous devriez voir les 4 LEDs de la carte s’allumer successivement.

La ligne 1 importe le module pyb qui permet d'accéder aux fonctionnalités de la pyboard. À la ligne 3, on utilise la classe pyb.LED qui gère les 4 LEDs de la pyboard. On construit notamment la liste de ces 4 LEDs (qui sont numérotées à partir de 1, d'où le +1 dans le constructeur de LED).

Ligne 4, on initialise la variable i, qui indique quelle LED doit être allumée, à 0 (ce qui correspond à la LED 1, qui est rouge). Les lignes 5 à 13 vont faire s'allumer successivement chacune des LEDs, i variant de 0 à 3 grâce à l'addition modulo 4 de la ligne 13. Les lignes 6 à 10 ont pour rôle d'allumer la LED choisie (celle qui correspond à i) et d'éteindre les 3 autres. La ligne 12 fait attendre 100ms, la ligne 13 fait passer à la LED suivante, en revenant à 0 si on dépasse 3.

%

Dans un terminal

Il est assez fastidieux de devoir éjecter le volume et de redémarrer la carte à chaque modification du code. De plus, pour expérimenter, il est plus agréable de pouvoir interagir avec l'interpréteur python. On va pour cela utiliser le port série de la carte.

Voyez les instructions du site officiel (en anglais) pour référence. Je donne ci-dessous ma version en français.

Ceci n'est plus nécessaire sous Windows X

Il faut tout d'abord installer le driver qui va permettre d'utiliser le port série USB de la pyboard. Ce driver se trouve sur le volume USB de la pyboard, c'est le fichier pybcdc.inf.

Pour l'installer, ouvrez le gestionnaire de périphériques et trouvez la pyboard dans la liste de périphériques (elle devrait être annotée par un symbole indiquant qu'elle ne fonctionne pas encore). Faites un clic droit, choisissez "Propriétés" et installez le driver en le choisissant manuellement (ne laissez pas Windows le rechercher automatiquement). Une fois l'installation terminée, regardez dans le gestionnaire de périphérique à quel port est associée la pyboard (par exemple COM4 ou COM12).

Pour vous connecter à la pyboard, il vous faut un émulateur de terminal. Le mieux est de télécharger PuTTY.

Vous n'avez plus qu'à vous connecter au port COM de la pyboard avec votre émulateur de terminal. Avec PuTTY, cliquez sur "Session" dans le panneau de gauche, puis sélectionnez "Serial" dans le panneau de droite, saisissez le port COM de la pyboard dans le champ "Serial Line", et finalement, cliquez sur "Open".

Vous pouvez également utiliser le script Powershell pyterm.ps1 disponible sur ce dépôt Github.

Si vous avez installé PuTTY et rshell (avec pip3 install rshell), cette video vous montre comment utiliser pyload et pyterm sous Windows X.

Notez bien que je ne suis pas un utilisateur régulier de Windows et que ces informations comportent peut-être des erreurs. Merci de me les signaler afin que je puisse corriger cette page.

Le port série apparaît automatiquement sur Mac comme /dev/tty.usbmodem<xyz>, où <xyz> est un entier, et comme /dev/ttyACM0 sous Linux. Vous pouvez utiliser screen, minicom ou picocom pour vous y connecter. Sous MacOS, picocom est le plus facile à utiliser et fonctionne également avec les cartes ESP32 sous Micropython.

Pour éviter de devoir chercher le nom du périphérique, j'utilise un script nommé pyterm qui me connecte à la première pyboard qu'il trouve.

pyterm est disponible sur ce dépôt Github

Exemple de session :

~ $ pyterm 
picocom v3.1

port is        : /dev/tty.usbmodem345D355133332
flowcontrol    : none
baudrate is    : 115200
parity is      : none
databits are   : 8
stopbits are   : 1
escape is      : C-a

... autres informations supprimées ...

Type [C-a] [C-h] to see available commands
Terminal ready

>>> 
ici, j'ai tapé Ctrl-D pour redémarrer la carte
MPY: sync filesystems
MPY: soft reboot
MicroPython v1.11 on 2019-05-29; PYBv1.0 with STM32F405RG
Type "help()" for more information.
>>> import pyb
>>> led = pyb.LED(1)
>>> led.on()
>>> led.off()
>>> 
ici, j'ai tapé Ctrl-A suivi de Ctrl-X pour quitter picocom
Terminating...
Thanks for using picocom
~ $ 

Ceci fonctionne également avec une carte ESP32 sous Micropython.

Executer un fichier Python

Plutôt que de taper directement du code Python dans l'interpréteur de la carte, il est souvent plus pratique d'éditer son code dans un fichier et de le faire exécuter ensuite par l'interpréteur de la carte.

Il existe pour cela une commande pyboard, mais il faut lui donner explicitement le périphérique sur lequel on souhaite exécuter le fichier. Par exemple pyboard --device /dev/cu.usbmodem3472354933332 mon_programme.py

De même que pour pyterm (voir plus haut), j'utilise un script pyload qui détecte les pyboards disponibles et utilise la première si aucune n'est précisée :

pyload est disponible sur ce dépôt Github

Ceci fonctionne également avec une carte ESP32 sous Micropython.

Une alternative, quand on programme une pyboard, est de copier le fichier sur la pyboard (elle apparaît comme un volume nommé PYBFLASH), puis de se connecter au REPL de la carte (avec pyterm par exemple) et de taper :

import moncode

si le fichier est moncode.py.

rshell

Rshell est un environnement de développement en ligne de commande pour MicroPython. Une traduction en français de sa documentation est disponible sur le wiki de MC Hobby

De même que pour les commandes picocom et pyboard, j'utilise un script pyrshell qui détecte les pyboards présentes et s'y connecte automatiquement.

pyrshell est disponible sur ce dépôt Github

Ceci fonctionne également avec une carte ESP32 sous Micropython. C'est d'ailleurs une manière simple d'accéder au système de fichier sur ESP32, car il n'apparaît pas comme un disque externe, contrairement à ce qui se passe avec la pyboard.

Pour installer Micropython sur une ESP32, consultez le tutoriel (en anglais).

Quelques exemples

Je propose ici quelques exemple de code pour pyboard ou pour ESP32 sous MicroPython, qui ne font appel qu'au matériel disponible sur la carte. Vous n'aurez pas besoin d'accessoires, à part le cable USB pour connecter la carte à votre ordinateur.

Allumer et éteindre une LED LED

On utilise ici le bouton disponible sur la carte (USR sur la pyboard, BOOT sur l'ESP32) pour allumer la LED intégrée à la carte. La LED ne reste allumée que tant que l'on maintient le bouton enfoncé.

Cet exemple montre comment configurer les ports, lire et modifier leur état, sur la pyboard et l'ESP32 :

"""
Allumer la LED intégrée lorsque le bouton poussoir est enfoncé.

Le code permettant de créer les pattes d'entrées-sorties, ainsi que leur nom, 
diffèrent sur la pyboard et sur l'ESP32, mais la structure du code est ma même.

Nous récupérons tout d'abord l'objet correspondant à la patte d'entrée à laquelle
est connecté le bouton poussoir. Ce bouton connecte la patte à la masse quand il 
est pressé. Afin d'avoir un niveau logique haut quand le bouton est relâché, nous
configurons la patte avec une résistance qui la tire par défaut au niveau haut 
(c'est le rôle de l'argument Pin.PULL_UP dans la création de l'objet Pin).

Ensuite, nous récupérons l'objet correspondant à la patte à laquelle est connectée 
la LED, et nous la configurons comme sortie. Sur la pyboard, nous utilisons Pin.OUT_PP,
qui est l'équivalent de Pin.OUT sur l'ESP32. Il s'agit d'une sortie classique, qui 
impose son niveau électrique. Il existe également un mode collecteur ouvert (open drain),
qui n'impose que le niveau bas et laisse flotter librement la sortie quand elle est à 1.
The mode correspond à la constante Pin.OUT_OD sur la pyboard, et Pin.OPEN_DRAIN sur
l'ESP32.

Le code principal est le même pour les deux cartes : une boucle infinie consulte l'état 
du bouton poussoir. Si la patte est à 0, c'est que le bouton est pressé, et on allume 
la LED. Sinon, c'est que le bouton est relâché (et la résistance tire l'entrée au niveau
haut), donc on éteint la LED.
"""
import sys

def main() :
  if sys.platform == 'pyboard' :
    """
    Si nous sommes sur une pyboard, configurer les pattes pour
    le bouton USR et la LED bleue
    """
    from pyb import Pin

    button = Pin('B3', Pin.IN, Pin.PULL_UP)
    led = pyb.Pin('B4', Pin.OUT_PP)
  elif sys.platform == 'esp32' :
    """
    Si nous sommes sur une ESP32, configurer les pattes pour
    le bouton BOOT et la LED intégrée (qui est bleue sur le modèle que j'utilise)
    """
    from machine import Pin

    button = Pin(0, Pin.IN, Pin.PULL_UP)
    led = Pin(2, Pin.OUT) # Remplacer 2 par 1 sur certaines cartes
  else:
    print('Carte Micropython inconnue')
    return

  while True :
    """
    Si le bouton est enfoncé, on allumer la LED, sinon, on l'éteint
    """
    if button.value() == 0 :
      led.on()
    else :
      led.off()

if __name__ == "__main__" :
  """
  Si le fichier est importé, ne rien exécuter.
  Si le fichier est exécuté, appeler la fonction main.
  """
  main()

Allumer et éteindre une LED, autre version LED 2

On utilise ici le bouton disponible sur la carte (USR sur la pyboard, BOOT sur l'ESP32) pour allumer ou éteindre la LED intégrée à la carte à chaque fois que l'on appuie sur le bouton.

"""
Allumer ou éteindre la LED à chaque fois que le bouton intégré est pressé.

Le code permettant de créer les pattes d'entrées-sorties, ainsi que leur nom, 
diffèrent sur la pyboard et sur l'ESP32, mais la structure du code est ma même.

Nous récupérons tout d'abord l'objet correspondant à la patte d'entrée à laquelle
est connecté le bouton poussoir. Ce bouton connecte la patte à la masse quand il 
est pressé. Afin d'avoir un niveau logique haut quand le bouton est relâché, nous
configurons la patte avec une résistance qui la tire par défaut au niveau haut 
(c'est le rôle de l'argument Pin.PULL_UP dans la création de l'objet Pin).

Ensuite, nous récupérons l'objet correspondant à la patte à laquelle est connectée 
la LED, et nous la configurons comme sortie. Sur la pyboard, nous utilisons Pin.OUT_PP,
qui est l'équivalent de Pin.OUT sur l'ESP32. Il s'agit d'une sortie classique, qui 
impose son niveau électrique. Il existe également un mode collecteur ouvert (open drain),
qui n'impose que le niveau bas et laisse flotter librement la sortie quand elle est à 1.
The mode correspond à la constante Pin.OUT_OD sur la pyboard, et Pin.OPEN_DRAIN sur
l'ESP32.

Le code principal est le même pour les deux cartes : une boucle infinie consulte l'état 
du bouton poussoir. Si la patte est à 0, c'est que le bouton est pressé, et on inverse 
l'état de la LED, puis on attend que le bouton soit relâché en bouclant tant qu'il 
reste enfoncé. Sans cette attente, nous ne pourrions pas faire la différence entre 
un nouvel appui sur le bouton et le fait qu'il reste enfoncé.
"""
import sys

def main() :
  if sys.platform == 'pyboard' :
    """
    Si nous sommes sur une pyboard, configurer les pattes pour
    le bouton USR et la LED bleue
    """
    from pyb import Pin

    button = Pin('B3', Pin.IN, Pin.PULL_UP)
    led = pyb.Pin('B4', Pin.OUT_PP)
  elif sys.platform == 'esp32' :
    """
    Si nous sommes sur une ESP32, configurer les pattes pour
    le bouton BOOT et la LED intégrée (qui est bleue sur le modèle que j'utilise)
    """
    from machine import Pin

    button = Pin(0, Pin.IN, Pin.PULL_UP)
    led = Pin(2, Pin.OUT)
  else:
    print('Carte Micropython inconnue')
    return

  while True :
    """
    Si le bouton est pressé, inverser l'état de la LED
    """
    if button.value() == 0 :
      led.value(not led.value())
      """
      Attendre que le bouton soit relâché
      """
      while button.value() == 0 :
        pass


if __name__ == "__main__" :
  """
	Si le fichier est importé, ne rien exécuter.
	Si le fichier est exécuté, appeler la fonction main.
  """
  main()

On fait ici simplement clignoter la LED intégrée à la carte. Cet exemple montre comment attendre l'écoulement d'une durée.

"""
Faire clignoter la LED intégrée à l'aide d'une boucle infinie.

L'initialisation de la patte de sortie qui pilote la LED diffère sur la pyboard
et sur l'ESP32, comme dans les exemples précédents. La fonction à appeler pour
attendre un nombre donné de millisecondes n'est pas la même sur les deux cartes, 
on définit donc une fonction wait_ms qui est codée de manière adéquate selon la 
carte utilisée.
"""
import sys

def main() :
  if sys.platform == 'pyboard' :
    from pyb import Pin, delay

    led = pyb.Pin('B4', Pin.OUT_PP)
    def wait_ms(milliseconds) :
      delay(milliseconds)
  elif sys.platform == 'esp32' :
    from machine import Pin
    from time import sleep_ms

    led = Pin(2, Pin.OUT)
    def wait_ms(milliseconds) :
      sleep_ms(milliseconds)
  else:
    print('Carte Micropython inconnue')
    return

  """
  Cette boucle infinie allume la LED, attend 500ms, éteint la LED, 
  attend 500ms et recommence.
  """
  while True :
    led.on()
    wait_ms(500)
    led.off()
    wait_ms(500)

if __name__ == "__main__" :
  """
  N'exécuter le code de la fonction que si le fichier n'est pas simplement importé.
  """
  main()

Faire clignoter une LED avec un timer LED et timer

On fait ici clignoter la LED intégrée à la carte à l'aide d'un timer. Cet exemple montre comment configurer un timer pour exécuter une tâche périodiquement.

"""
Utiliser un timer pour faire clignoter la LED intégrée.

La seule partie commune aux versions pour pyboard et pour ESP32 est la
fonction appelée lorsque le timer arrive à échéance.
Cette fonction inverse l'état de la LED à l'aide de l'opérateur "not".

Les versions spécifiques à chaque carte sont toutefois peu différentes.
On retrouve les classiques différences de nom pour la patte reliée à la LED et 
la création de l'objet Pin.
La création du timer est également différente :
  - sur la pyboard, il faut choisir un timer matériel (ici, le numéro 4), 
    et la périodicité est donnée par la fréquence du timer en Hertz.
  - sur l'ESP32, on peut utiliser un timer "virtuel", de numéro -1, 
    et la périodicité est donnée par la période du timer en millisecondes.
"""
import sys

def main() :
  """
  Cette fonction sera appelée à chaque fois que le timer arrive à échéance,
  il est important de déclarer le paramètre qui lui sera passé lors de l'appel,
  même si on ne s'en sert pas.
  """
  def timer_callback(timer) :
    led.value(not led.value())

  if sys.platform == 'pyboard' :
    """
    Sur la pyboard, on utilise la patte B4 pour accéder à la LED bleue, et
    on configure le timer numéro 4 à 2Hz pour faire clignoter la LED.
    """
    from pyb import Pin, Timer

    led = pyb.Pin('B4', Pin.OUT_PP)
    timer = Timer(4, freq=2, callback=timer_callback)
  elif sys.platform == 'esp32' :
    """
    Sur l'ESP32, on utilise la patte 2 pour accéder à la LED intégrée, et
    on alloue un timer virtuel de période 500ms pour faire clignoter la LED.
    Afin que le timer soit réarmé à chaque échéance, on le configure en mode PERIODIC.
    """
    from machine import Pin, Timer

    led = Pin(2, Pin.OUT)
    timer = Timer(-1)
    timer.init(period=500, mode=Timer.PERIODIC, callback=timer_callback)
  else:
    print('Carte Micropython inconnue')
    return

if __name__ == "__main__" :
  main()
  if sys.platform == "esp32" :
    """
    Sur l'ESP32, la carte est redémarrée à la fin du script Python, il faut
    donc garder l'interpréteur actif pour que le timer ne soit pas réinitialisé
    immédiatement.
    """
    while True :
      pass

Choisir la luminosité d'une LED avec la PWM LED et PWM

La modulation de largeur d'impulsion (Pulse Width Modulation en anglais) est une technique qui permet de faire varier la tension moyenne d'un signal binaire. Elle évite de recourir à un convertisseur numérique-analogique pour faire varier la puissance transmise à une LED ou à un moteur à courant continu.

Le principe est de faire varier le rapport cyclique (rapport du temps passé au niveau haut sur la période du signal) d'un signal de fréquence suffisamment élevée pour être imperceptible. Par exemple, à 5kHz, le clignotement d'une LED alimentée en PWM n'est pas perçu par l'œil. En faisant varier le rapport cyclique de 0% à 100%, on passe d'une LED éteinte à une LED allumée à sa luminosité maximale. Dans la réalité, la LED est allumée et éteinte 5000 fois par seconde, mais on ne perçoit que la luminosité moyenne, qui est proportionnelle au rapport cyclique. Il est d'ailleurs plus facile de choisir la luminosité de la LED en PWM qu'en réglant sa tension d'alimentation avec un convertisseur numérique-analogique, car la réponse de la luminosité en fonction de la tension n'est pas linéaire.

On fait ici varier périodiquement la luminosité de la LED intégrée en modifiant progressivement le rapport cyclique du signal PWM.

"""
Faire varier la luminosité d'une LED grâce à la PWM.
"""
import sys

def main() :
  if sys.platform == 'pyboard' :
    from pyb import Pin, Timer, delay

    """
    Sur la pyboard, l'attente se fait avec la fonction delay du module pyb,
    et le réglage de rapport cyclique se donne directement en pourcentage
    """
    def wait_ms(milliseconds) :
      delay(milliseconds)

    def set_pwm_pct_duty(pwm, pct) :
      pwm.pulse_width_percent(pct)

    """
    Sur la pyboard, on retrouve la LED bleue sur la patte B4, et il faut 
    choisir un timer qui a un canal PWM connecté à cette patte pour pouvoir
    la piloter. Ici, il s'agit du canal 1 du timer 4.
    """
    led = pyb.Pin('B4', Pin.OUT_PP)
    timer = Timer(3, freq=5000)
    pwm = timer.channel(1, mode=Timer.PWM, pin=led)
  elif sys.platform == 'esp32' :
    from machine import Pin, PWM
    from time import sleep_ms

    """
    Sur l'ESP32, l'attente se fait avec la fonction sleep_ms du module machine,
    et le réglage de rapport cyclique se donne en 1/1024 (résolution sur 10 bits)
    """
    def wait_ms(milliseconds) :
      sleep_ms(milliseconds)

    def set_pwm_pct_duty(pwm, pct) :
      pwm.duty((1024*pct)//100)

    """
    Sur l'ESP32, on retrouve la LED intégrée sur la patte 2, et la PWM 
    est gérée par un objet PWM qu'il suffit de configurer pour une patte 
    et une fréquence données.
    """
    led = Pin(2, Pin.OUT)
    pwm = PWM(led, freq=5000)
  else:
    print('Carte Micropython inconnue')
    return

  """
  Notre programme part d'une intensité (pourcentage de la période où le signal est haut)
  nulle et l'augmente d'une unité toutes les 10 millisecondes. Si on dépasse 100%, le
  pas de changement passe à -1 et l'intensité diminue toutes les 10ms. Lorsqu'on arrive
  à 0, le pas est remis à 1 et l'intensité augmente de nouveau.
  """
  intensity = 0
  step = 1
  while True :
    set_pwm_pct_duty(pwm, intensity)
    wait_ms(10)
    if intensity >= 100 :
      step = -1
    if intensity <= 0 :
      step = 1
    intensity += step

if __name__ == "__main__" :
  main()

Allumer et éteindre la LED intégrée avec des interruptions Interruptions

Nous avons vu plus haut comment allumer et éteindre la LED intégrée à chaque fois qu'on appuie sur le bouton poussoir de la carte. Cette solution monopolise le processeur qui passe son temps à scruter l'état du bouton poussoir pour détecter les appuis. Elle peut être déléguée au matériel, qui peut nous prévenir automatiquement lorsque le signal d'une patte d'entrée passe de 1 à 0 (ou de 0 à 1, il suffit de choisir ce qui nous intéresse). Le processeur est alors déchargé de ce travail de scrutation et peut faire des choses plus utiles.

Le problème est de savoir comment le processeur est prévenu lorsque le matériel détecte un changement de valeur du signal sur une patte. C'est le mécanisme de traitement des interruptions qui va permettre au matériel de signaler un changement. Quand un changement de valeur pour lequel on a demandé à être prévenu se produit, le traitement que fait le processeur est interrompu, et il va exécuter le code d'une fonction que l'on aura indiquée.

Il y a des limites à ce que l'on peut faire dans cette fonction, et on ne peut notamment pas créer de nouveaux objets car il est possible que nous ayons interrompu le processeur alors qu'il était justement en train de créer un objet, et que la mémoire soit dans un état transitoire où le marquage des espaces libres et des espaces occupés n'est pas à jour. Il est malheureusement assez facile de créer des objets sans s'en rendre compte en Python, par exemple en faisant une division qui crée un flottant, on en ajoutant un élement à une liste ou un dictionnaire qui se redimensionne.

On se limitera donc à du code court qui fait peu de calculs et qui se contente de mettre à jour des variables globales.

import sys

def main() :
  """
  Cette fonction sera appelée à chaque fois que le bouton sera enfoncé.
  Elle ne fait qu'inverser l'état de la LED.
  Attention : il est très important de déclarer le paramètre qu'elle reçoit,
  même si on ne l'utilise pas.
  """
  def irq_handler(irq_line) :
    led.value(not led.value())

  if sys.platform == 'pyboard' :
    from pyb import Pin, ExtInt

    """
    Sur la pyboard, le bouton USR est connecté à la patte B3, que l'on
    configure en entrée avec une résistance de pull up.
    La LED bleue est connectée à la patte B4, que l'on configure en sortie.
    L'interruption se configure grâce à un objet ExtInt que l'on crée pour
    appeler la fonction irq_handler à chaque fois que la patte associée au
    bouton passe de 1 à 0 (IRQ_FALLING).
    """
    button = Pin('B3', Pin.IN, Pin.PULL_UP)
    led = pyb.Pin('B4', Pin.OUT_PP)
    irq = ExtInt(button, ExtInt.IRQ_FALLING, Pin.PULL_UP, irq_handler)
  elif sys.platform == 'esp32' :
    from machine import Pin

    """
    Sur l'ESP32, le bouton BOOT est connecté à la patte 0, que l'on
    configure en entrée avec une résistance de pull up.
    La LED intégrée est connectée à la patte 2, que l'on configure en sortie.
    L'interruption se configure grâce à la méthode irq de la classe Pin, que l'on
    utilise pour appeler la fonction irq_handler à chaque fois que la patte associée 
    au bouton passe de 1 à 0 (IRQ_FALLING).
    """
    button = Pin(0, Pin.IN, Pin.PULL_UP)
    led = Pin(2, Pin.OUT)
    irq = button.irq(trigger=Pin.IRQ_FALLING, handler=irq_handler)
  else:
    print('Carte Micropython inconnue')
    return

if __name__ == "__main__" :
  main()
  if sys.platform == "esp32" :
    """
    Sur l'ESP32, la carte est redémarrée à la fin du script Python, il faut
    donc garder l'interpréteur actif pour que la gestion des interruptions que 
    nous avons mise en place ne soit pas réinitialisée immédiatement.
    """
    while True :
      pass