Gestione interrupt su RaspberryPi (ARM Cortex-A7)

  • Giovasci
  • Autore della discussione
  • Nuovo Utente
  • Nuovo Utente
Di più
7 Anni 8 Mesi fa #1 da Giovasci
Buongiorno a tutti, ho spulciato tutti i thread in cui si parla di RaspberryPi ma non ho trovato niente al riguardo.
Spero sia la sessione giusta, in caso vi chiedo gentilmente di spostare la discussione nel posto più appropriato.

Bene, detto questo veniamo al dunque!

Ho trovato diversi esempi su internet su come utilizzare gli interrupt su questa scheda, tuttavia non riesco a trovare una guida esaustiva al riguardo!

I problemi che ho al momento sono due:
- come passo delle variabili alle funzioni chiamate dall'interrupt?
- come gestisco il rimbalzo?

passiamo direttamente al codice, così ragioniamo su un esempio concreto!

Le domande relative le scrivo direttamente come commenti nel codice:
Code:
import RPi.GPIO as GPIO import time GPIO.setmode (GPIO.BCM) GPIO.setup (20, GPIO.IN, pull_up_down = GPIO.PUD_UP ) time_stamp = time.time() def switch_detect(channel): print 'Falling edge detected on pin:', channel GPIO.add_event_detect(20, GPIO.FALLING, callback=switch_detect, bouncetime=300) # nella definizione la funzione switch_detect accetta un parametro, qui non gliene viene passato nessuno. # Come fa a sapere quanto vale "channel"? GPIO.cleanup() # a cosa serve questo comando?


Inoltre vorrei contare quante volte viene premuto il bottone.
Per farlo pensavo ad una cosa del genere:
Code:
... n = 0 def switch_detect(channel, n): print 'Falling edge detected on pin:', channel print 'n:', n GPIO.add_event_detect(20, GPIO.FALLING, callback=switch_detect(n), bouncetime=300) ...

Però in questo modo ottengo il seguente errore: TypeError: Parameter must be callable

Come posso passare un parametro ad una funzione chiamata tramite interrupt?


Passiamo al problema del DEBOUNCE.
Per quanto riguarda il debounce faccio riferimento a quanto appreso da questo sito:
raspi.tv/2013/how-to-use-interrupts-with...-and-rpi-gpio-part-2

Quindi aggiungere il parametro bouncetime=300 equivale a modificare la definizione della funzione "switch_detect" nel modo seguente:
Code:
def switch_detect(channel): global time_stamp time_now = time.time() if (time_now - time_stamp) >= 0.3: print 'Falling edge detected on pin:', channel time_stamp = time_now

Giusto?

In questo modo si evita che l'interrupt si verifichi due volte consecutive in un intervallo minore di 300ms e questo risolve il problema del rimbalzo in fase di pressione dello switch, tuttavia rimane il problema in fase di rilascio, infatti possono essere generati dei fronti di discesa anche quando il bottone viene rilasciato, sbaglio?
E questo può accadere in un istante di tempo qualsiasi...

Infatti spesso viene stampata la scritta "Falling edge detected on pin: 20" nel momento in cui rilascio lo switch.

Come risolvo questo problema?
Dopo l'esecuzione della funzione aggiungo un controllo sullo stato del bottone in modo che resti in attesa finché non viene rilasciato? Questa parte conviene gestirla tramite polling o interrupt?


Grazie mille a tutti in anticipo!

Si prega Accesso o Crea un account a partecipare alla conversazione.

  • Mauro Laurenti
  • Moderatore
  • Moderatore
Di più
7 Anni 7 Mesi fa #2 da Mauro Laurenti
Risposta da Mauro Laurenti al topic Gestione interrupt su RaspberryPi (ARM Cortex-A7)
Posso fare qualche considerazione in generale.

Le funzioni delle interruzioni sono un poco particolari, e in generale non accettano parametri.
Se devi gestire una variabile puoi usarne una globale ma devi essere certo che solo una funzione alla volta acceda a questa. Se hai un solo thread/funzione non è un problema.
In maniera più elegante puoi fare una funzione di incremento che richiami in quelle delle interruzioni, in maniera da accedere alla variabile in maniera "ordinata". Python non supporta variabili private per cui l'utilizzo della funzione aiuta fino ad un certo punto ma ordina le idee.

Per il ritardo dopo la lettura potresti usar time.sleep(0.02)
Normalmente qualche decina di ms basta
dopo la chiamata dell'interrupt puoi aspettare 0.02 o più secondi e poi leggere il pulsante. se è ancora attivo è un evento valido.

Non sono certo di come Python gestisca gli interrupt, ma credo che mascheri gli stessi fino a che non si esca dalla relativa funzione dell'interrupt stesso.
All'uscita dell'interrupt bisogna vedere se viene mantenuto memoria di un eventuale evento o meno come nelle MCU, ma è una specifica che bisogna leggere sul manuale o fare qualche prova.

Ho programmato RPi in Python ma solo per semplici esempi. Ora sto usando il C/C++ ma sono a metà del corso...

Saluti,

Mauro

Si prega Accesso o Crea un account a partecipare alla conversazione.

Moderatori: Mauro LaurentiMatteo Garia

Registrati al sito

Accedi a tutte le risorse e articoli non visibili pubblicamente, puoi registrarti con pochi passi.

Registrati al sito LaurTec.