[Python] Interruption sur le port GPIO

[Python] Interruption sur le port GPIO

Avant d’aller plus loin, il est nécessaire de définir ce qu’est une interruption.
En informatique, informatique embarquée, ou électronique, une interruption est un processus qui est déclenché de manière asynchrone afin de permettre un éventuel traitement temps-réel des données.

Afin d’illustrer concrètement le phénomène, voici un exemple d’usage. Imaginez que vous vouliez allumer une LED lorsque vous appuyez sur un bouton qui est relié à une des bornes de votre GPIO.
Il existe pour cela plusieurs possibilités la manière brutale :

1- mettre une boucle de test dans le programme principale qui va tester l’état du bouton à chaque itération du programme principale
2- si l’état du bouton passe à l’état attendu qui peut être True(Vrai) ou False(Faux) alors on appelle une fonction de traitement

Le problème de ce genre de méthode est que si les tâches de votre programme principal sont alors le traitement de l’état du bouton sera alors effectué une fois par tâche.
Par conséquent, si le traitement de la tâche associée au bouton, il est impossible d’avoir une réaction immédiate (« temps-réel »).
Dans le pire des cas, on pourra même rater des phénomènes se produisant sur le bouton.
En effet, imaginons que le bouton sur le GPIO soit un bouton poussoir. L’appui sur le bouton produit un signal d’état positif (+5V. NB : Cela pour être 0V suivant le câblage de votre bouton) pendant quelques millisecondes, or si le traitement dans votre programme principal est de quelques secondes, la probabilité de rater le phénomène d’appui est plus importante que la probabilité de l’attraper au vol!!!!

Pour limiter tous ces problèmes, il est préférable d’utiliser le mécanisme d’interruption.
En pratique, cela va permettre d’exécuter une portion de code dès que le bouton sera pressé en quittant temporairement le programme principal puis en y retournant dès que cette portion de code sera exécutée.

Pour mettre en œuvre cela en python, on va utiliser l’instruction « add_event_detect » de la librairie RPi.GPIO qui permet de configurer une interruption.
Plus particulièrement, on va associer une broche à une fonction qui sera appelée que l’évènement va se produire sur la broche en question pour exemple :

 GPIO.add_event_detect(7, GPIO.RISING, callback=my_callback, bouncetime=300)

Dans ce sa on va déclencher l’appel à la fonction my_callback lors d’un passage à l’état haut (GPIO.RISING) sar la broche 7.
On notera que la paramètre bouncetime=300 correspond au temps pendant lequel l’interruption ne sera pas sensible [aux rebonds du bouton](TODO: mettre un lien vers un article de définition du rebond d’un bouton).

Par conséquent, on obtient à minima le code suivant :

import RPi.GPIO as GPIO


def init():
    # configuration de la broche 7 en entree
    GPIO.setmode(GPIO.BCM)
    GPIO.setup(7, GPIO.IN)
    # definition de l'interruption
    GPIO.add_event_detect(7, GPIO.RISING, callback=my_callback, bouncetime=300)


def my_callback():
    # callback = function which call when a signal rising edge on pin 7
    print("Vous avez appuyez sur le bouton de la patte 7")


if __name__ == '__main__':

    # 1- initiation de la l'interruption
    init()
    # 2- boucle infini = tache principale
    while True:
pass

La fonction init initialise le GPIO et «accroche» la fonction my callback() à la broche 7.

Attention cependant, dans l’exemple qui précède, tous les traitements sont réalisés dans la fonction de callback.
Cette façon de faire est intéressante pour gagner un maximum de temps.
Cependant il est nécessaire d’avoir un minimum de chose à réaliser dans cette boucle.
En effet, le risque de freezer le programme dans son ensemble est important.

D’une manière générale, une bonne pratique est (lorsque l’exécution de la fonction n’est pas cruciale et que le temps-reél tient) de mettre un flag à True(Vrai) dans le callback et de lancer l’exécution de la fonction de traitement à partir du programme principal.

Le programme ci-dessous illustre le fonctionnement :

import RPi.GPIO as GPIO


# variable globale qui sera vue dans toutes les fonctions
flag_callback = False

def init():
    # configuration de la broche 7 en entree
    GPIO.setmode(GPIO.BCM)
    GPIO.setup(7, GPIO.IN)
    # definition de l'interruption
    GPIO.add_event_detect(7, GPIO.RISING, callback=my_callback, bouncetime=300)
    # initialisation du flag
    flag_callback = False


def my_callback():
    # function qui sera appelé lorsque le programme sur interrompu
    flag_callback = True


def process_ny_callback():
    print("Interruption détectée sur la broche 7")

if __name__ == '__main__':

    # 1- initiation de la l'interruption
    init()
    # 2- boucle infini = tache principale
    while True:
        # 3- si une interruption c'est produite alors on lance le traitement c
        # adéquat
        if flag_callback == True:
            process_ny_callback()
    pass

Vous pourrez retrouver les sources sur le repo github suivant : https://github.com/clemaitre58/20181002_interruption.

Alors prêt à attaquer les interruptions avec Python?

Laisser un commentaire

Votre adresse de messagerie ne sera pas publiée. Les champs obligatoires sont indiqués avec *

Ce site utilise Akismet pour réduire les indésirables. En savoir plus sur comment les données de vos commentaires sont utilisées.