Puoi farlo usando interrupt esterni. La maggior parte degli Arduinos lo supporta solo su un numero limitato di pin. Per i dettagli completi, consultare la documentazione su attachInterrupt().
Supponendo che tu stia utilizzando uno Uno, potresti farlo in questo modo:
void pinChanged()
{
//...
}
void setup()
{
pinMode(2, INPUT);
attachInterrupt(0, pinChanged, CHANGE);
}
void loop()
{
}
Questo chiamerà pinChanged()ogni volta che viene rilevata una modifica sull'interrupt esterno 0. Su Uno, che corrisponde al pin GPIO 2. La numerazione degli interrupt esterni è diversa su altre schede, quindi è importante controllare la relativa documentazione.
Vi sono tuttavia limiti a questo approccio. La pinChanged()funzione personalizzata viene utilizzata come routine di servizio di interruzione (ISR). Ciò significa che il resto del codice (tutto in loop()) viene temporaneamente arrestato durante l'esecuzione della chiamata. Al fine di prevenire l'interruzione di qualsiasi tempismo importante, si dovrebbe mirare a rendere gli ISR il più rapidamente possibile.
È anche importante notare che durante il tuo ISR non verranno eseguiti altri interrupt. Ciò significa che tutto ciò che si basa sugli interrupt (come il core delay()e le millis()funzioni) potrebbe non funzionare correttamente al suo interno.
Infine, se il tuo ISR deve modificare eventuali variabili globali nello schizzo, di solito dovrebbero essere dichiarate come volatile, ad esempio:
volatile int someNumber;
Questo è importante perché dice al compilatore che il valore potrebbe cambiare inaspettatamente, quindi si dovrebbe fare attenzione a non utilizzare copie / cache non aggiornate.