API pin watch
Se proviamo a tradurre watch in italiano, la prima traduzione sarà orologio, le altre, guardare e osservare sono più calzanti in questo caso. Osservare lo stato di un pin e agire in relazione allo stato di questo. La funzione pin_watch() abilita l'osservazione di un pin, mentre pin_watch_stop() la disabilità. Sotto vediamo il prototipo delle due funzioni che ci serve per capire come usarle.
L'argomento pin_t pin sappiamo cosa essere, per cui concentriamoci sull'argomento di tipo pin_watch_config_t, il quale è una struttura così composta:
user_data deve contenere un puntatore che verrà usato come argomento nella funzione di callback pin_change.
edge ci permette di specificare per quale fronte del segnale vogliamo che sia chiamata la callback pin_change. Il campo edge può assumere i seguenti valori:
FALLING
Una transizioneHigh -> Lowdetermina la chiamata a funzione callback specificata nel campopin_change.RISING
Una transizioneLow -> Highdetermina la chiamata a funzione callback specificata nel campopin_change.BOTH
Una transizioneHigh -> LowoLow -> Highdetermina la chiamata a funzione callback specificata nel campopin_change.
Sembra complicato, ma come vedrete risulta abbastanza semplice configurare e abilitare l'osservazione di un pin. Attenzione però ad abilitare più osservazioni sullo stesso pin, vedremo dopo cosa possiamo fare e cosa no, per adesso lo usiamo nel modo più utile e frequente. Vediamo subito quanto semplice sia l'inizializzazione e la chiamata a pin_watch() presente nella funzione chip_init():
Aggiungiamo l'implementazione della seguente callback dopo la funzione chip_init() e proviamo a compilare:
Scopriamo che il compilatore esce con un messaggio di errore per niente chiaro, il messaggio mette in risalto il nome del simbolo wcb_inp che è il nome che abbiamo dato alla funzione di callback. Risolviamo questo errore nel modo standard che prevede di inserire sempre i prototipi delle funzioni in testa dopo le include, oppure all'interno di un header file. Il codice seguente in effetti ora compila correttamente. Ricordiamoci che stiamo scrivendo codice C da dare in pasto al compilatore C e questo dovrebbe farci apprezzare la semplificazione di cui godiamo usando arduino.
Simulando il codice e premendo il pulsante, la CHIP CONSOLE viene inondata di messaggi, il motivo di ciò è legato alla simulazione del pulsante vero, che è sempre afflitto da rimbalzi dei contatti elettromeccanici, difatti cliccando sul pulsante (vedi Fig.2) possiamo disabilitare i rimbalzi e ad ogni pressione avremo una sola stampa.
![]() |
| Fig.1: Collegamenti di test pin_watch |
Risulta sicuramente utile osservare questi rimbalzi dei contatti e wokwi ci permette di farlo in modo abbastanza semplice. Quindi riabilitiamo il rimbalzo (Fig.2), aggiungiamo l'analizzatore logico pigiando il pulsante blu (+), alla comparsa della lista dei componenti, scorriamo verso la fine fino ad incontrare l'analizzatore. Colleghiamo GND con il GND e il pin D7 con il pin INP. Avviamo la simulazione e premiamo il pulsante, proviamo a fare il tutto nell'arco di 1-2 secondi e fermiamo la simulazione. Wokwi ci chiede di salvare il file wokwi-logic.vcd, salviamolo. Questo file può essere visualizzato dal programma PulseView (sigrok) o da GtkWave. Possiamo osservare i rimbalzi dei contatti in Fig.3.
![]() |
| Fig.3: Primo rimbalzo alla pressione a 435ms. Rimbalzo al rilascio dopo 465ms |
![]() |
| Fig.2: Disabbilita/abilita il rimbalzo. |
Per fortuna i segnali digitali non rimbalzano, per tale motivo ci dobbiamo preoccupare dei rimbalzi solo quando colleghiamo pulsante, interruttore o relay ad un ingresso digitale.
Adesso vediamo come possiamo risolvere il problema del rimbalzo dei contatti con il solo fine di mostrare l'uso di pin_watch(), pin_watch_stop() e timer_start(). Il programma è lo stesso del precedente a cui aggiungiamo dei campi alla struttura chip_state_t e una funzione callback di un timer. Vediamo di seguito le modifiche alla struttura.
Tre campi, dove gcnt è una variabile da 8-bit che useremo come contatore generico. wcfg_inp è la variabile di tipo pin_watch_config_t già usata in precedenza ma non faceva parte della struttura. tid_deb ci serve che sia nella struttura perché nella funzione tcb_debounce chiamiamo timer_stop(chip->tid_deb).
Passiamo alla funzione chip_init() dove inizializziamo il timer chip->tid_deb senza avviarlo, a seguire configuriamo chip->wcfg_inp e abilitiamo l'osservazione del pin chiamando pin_watch(). Nota che edge è impostato a FALLING, quindi ad ogni transizione da HIGH -> LOW verrà eseguita la funzione wcb_inp().
Passiamo ad analizzare la funzione wcb_inp():
Notate subito la chiamata a pin_watch_stop(), seguendo c'è l'avvio del timer ciclico che chiama la funzione tcb_debounce() ogni 5 millesimi di secondo. In questo momento l'osservazione del pin è disabilitata per cui il treno di impulsi del pulsante non ha conseguenze, allora invertiamo lo stato di chip->on_off e stampiamo on o off. Il timer da 5ms ci serve per riabilitare l'osservazione del pin ma solo se il suo stato è HIGH per 2 volte consecutive il che significa che il pulsante è stato rilasciato. Vediamo tutto ciò dentro la funzione seguente:
Tiriamo le somme: abbiamo imparato che quando ci serve avviare/abilitare timer/pin_watch durante la simulazione ci serve aggiungere nella struttura chip_state_t una variabile di tipo timer_t e pin_watch_config_t. Mentre non ha alcuna utilità aggiungere una variabile di tipo timer_config_t nella struttura perché timer_init() non deve essere eseguita durante la simulazione ma soltanto all'inizio dentro la funzione chip_init(). Questo vuole dire che il timer una volta configurato non può essere modificato, mentre una pin_watch_config_t può essere modificata in ogni momento.
Adesso possiamo prenderci la briga di introdurre questa funzionalità per accendere/spegnere il generatore di segnale pwm desritto nell'articolo precendete con il solo scopi di vedere quanto abbiamo imparato e se questo è sufficiente da permetterci di integrare questa funzionalità.
Limiti di pin_watch
Osservando il prototipo di pin_watch() notiamo che restituisce un valore di tipo bool. Restituisce true se l'osservazione del pin ha avuto successo, altrimenti restituisce false. Quando restituisce false vuole dire che c'è già abilitata l'osservazione dello stesso pin. Ad esempio:
L'ultima chiamata restituisce false. Se rimuoviamo il commento alla pin_watch_stop(chip->inp), l'ultima chiamata restituisce true. Quindi possiamo avere più configurazioni da abilitare con pin_watch, ma quella abilitata deve essere fermata prima di potere chiamare pin_watch sullo stesso pin. In altre parole non ci possono essere più osservazioni attive sullo stesso pin.

Quest'opera è distribuita con Licenza Creative Commons Attribuzione - Condividi allo stesso modo 4.0 Internazionale


