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. :-)}
Quanti e quali canali supportano interrupt?
Tutti non li ho mai usati ma né la documentazione RPi https://www.raspberrypi.org/documentation/usage/gpio/ né quella RPi.GPIO https://sourceforge.net/p/raspberry-gpio-python/wiki/Inputs/ indicano esclusioni, quindi direi tutti i pin di segnale dopo averli configurati come input:
GPIO.setup(…, GPIO.IN)
Ottimo! su Arduino dipende dal modello, e spesso sono solo alcuni canali.
Farò qualche prova al più presto.
Poi raccontami. 🙂
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
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).