Gestione efficiente delle porte GPIO del Raspberry Pi con interrupt e chiamate asincrone

raspberry-pi

Nonostante la libreria RPi.GPIO disponga già da diversi anni di funzioni per gestire le porte GPIO in maniera asincrona spesso vedo ancora tutorial che suggeriscono, ad esempio, di rilevare la pressione di un tasto utilizzando il semplice polling.

Cioè, per esemplificare, qualcosa del genere:

import RPi.GPIO as GPIO

while True:
    if (GPIO.input(25)):
        print("Click!")

Come primo approccio può andare anche bene ma se vogliamo che il nostro programma sia efficiente e non sovraccarichi troppo il sistema con un loop infinito lasciandolo libero anche di svolgere altre funzioni è consigliabile utilizzare un’altra tecnica.

Possiamo usare la funzione add_event_detect() per chiedere alla libreria di eseguire una nostra procedura al verificarsi di un determinato evento:

import RPi.GPIO as GPIO

def click(channel):
    print("Click!")

GPIO.add_event_detect(25, GPIO.RISING, callback=click)

In questo caso la funzione click() verrà eseguita in un thread separato al presentarsi di un fronte di salita sulla porta 25.

Tale fronte di salita, ad esempio, potrebbe essere determinato dal rilascio di un pulsante collegato alla porta se questa è stata collegata con una resistenza di pull-up.

Una volta agganciata la funzione di callback all’evento che ci interessa, nel nostro programma potremo tranquillamente dedicarci ad altri compiti o anche solo non fare nulla, risparmiando energia, nel caso il sistema sia alimentato a batteria.

Al verificarsi dell’evento richiesto, la nostra routine di gestione verrà comunque sempre messa in esecuzione in maniera asincrona e in un thread indipendente dal resto del programma.

{Come impostare la configurazione di una porta o anche come gestire la molteplicità di fronti di salita provenienti da un singolo rilascio del pulsante, come quasi sempre capita quando meccanica ed elettronica interagiscono, con tecniche di debouncing o antirimbalzo lo vedremo magari in un altro post. Se ti interessa qualcuno di questi argomenti o approfondire quelli trattati nel post scrivimi una nota nei commenti. :-)}

 

 

6 commenti su “Gestione efficiente delle porte GPIO del Raspberry Pi con interrupt e chiamate asincrone”

  1. Buongiorno, mi hanno segnalato il suo post e le chiedo un supporto.
    Ho una funzione del genere:
    #! /usr/bin/python
    import time # Importa libreria per la gestione dei timer
    import os
    # Inizializzazione GPIO
    import RPi.GPIO as GPIO # Importa libreria GPIO

    buttonPin1 = 26 #Da 26 a 17 sono i pin di raspberry

    GPIO.setmode(GPIO.BCM)
    GPIO.setup(buttonPin1,GPIO.IN)
    persistency = 0

    while True :
    if (GPIO.input(buttonPin1)): #Se la condizione cambia esegui contatto1.sh
    persistency += 1
    if(persistency > 7): #check input persistency for 200 ms
    os.system(“/home/Allarmi/contatto1.sh hipath 0911 1001”)
    persistency = 0
    time.sleep(60)
    else:
    time.sleep(0.02) #Wait 20 ms
    else:
    persistency = 0
    time.sleep(0.02) #Wait 20 ms

    Voglio monitorare lo stato di 8 pin contemporaneamente ed eseguire un file sh quando cambia lo stato di uno degli 8 pin.
    Come potrei ottimizzare utilizzando la funzione add_event_detect() ?
    Grazie e buona giornata

    1. Salve Giuseppe, benvenuto!

      Per monitorare 8 pin può chiamare 8 volte la GPIO.add_event_detect(), una per ciascun pin.
      Le 8 chiamate dovranno essere fatte una volta soltanto, poi ci penserà la libreria a controllare ripetutamente lo stato dei pin.
      Naturalmente i pin andranno mantenuti a Vcc o a GND tramite una resistenza esterna oppure usando quella di PULL-UP interna.

      In ciascuna chiamata dovrà inserire una funzione che verrà invocata ogni volta che viene rilevato lo stato del pin. Dentro tale funzione metterà quello che serve (ad esempio la chiamata a os.system).

Lascia un commento

Il tuo indirizzo email non sarà pubblicato. I campi obbligatori sono contrassegnati *