HotAirGun/I2cController
I2cController
Come Questa board usa un GPIO expander i2c per interfacciare:
- display LCD compatibile con hd44780
- encoder digitale a rotella + click
- pulsanti (fino a 5 se usati assieme a display ed encoder)
MCP23017
Il controller e' basato sull'integrato MCP23017 un GPIO expander di Microchip che permettere di aggiungere pin digitali sul bus i2c. Questa pagina [GPIO aggiuntivi MCP23x17] fornisce diverse informazioni sul chip.
MCP23017 supporta la gestione degli interrupt sui pin in ingresso, e' possibile qui attivare una segnalazione di avviso verso Arduino in caso un pulsante cambi di stato o l'encoder venga ruotato.
L'integrato ha due port chiamati PORT A e PORT B ognuno con 8 pin, ogni PORT ha un pin dedicato per la gestione degli interrupt, noi comunque useremo per input solo il PORT A.
I pin in input vengono configurati con pullup perciò verranno collegati a massa e l'interrupt verrà generato quando il segnale ha un fronte di discesa.
Software
Per la gestione del controller abbiamo utilizzato due librerie già sviluppate da altri:
- LiquidTWI2 libreria usata anche per la gestione dei display per stampanti 3D
- Adafruit-MCP23017-Arduino-Library libreria sviluppata da Adafruit per la configurazione di MCP23017
Alle due librerie che abbiamo fuso per sfruttare il lavoro già fatto e rendere più intuitivi i settaggi abbiamo aggiunto qualche funzione per velocizzare la configurazione dell'encoder e dei bottoni.
contr.setupEncoder(EN_A,EN_B,EN_C); // Encoder setup
Per settare l'encoder basta specificare i due pin dei contatti della rotella e quello connesso al click.
uint8_t btnCross[BTN_NUM] = { BTN_1, BTN_2, BTN_3, BTN_4, BTN_5}; // Five button on cross disposition, setup function contr.setIntCross(btnCross, BTN_NUM);
Configuriamo anche i 5 bottoni che useremo disposti a croce con una funzione specifica.
Gestione degli interrupt
Abbiamo visto sopra che bottoni ed encoder generano interrupt per risparmiare i tempi di polling ad ogni ciclo.
Scrivere un programma per microcontrollori usando gli eventi e' un po' diverso rispetto alla programmazione tradizionale vedi Wikipedia.
Nel nostro caso imposteremo arduino per gestire un evento di fronte di discesa sul pin D3 che genera all'interno di arduino un Interrupt chiamato int1 (la funzione digitalPinToInterrupt in base al pin ed al tipo di board utilizzata si occupa di calcolare quale sia l'interrupt corrispondente sulla nostra board.
// Interrupts from the MCP will be handled by this PIN on Arduino byte arduinoIntPin = 3; attachInterrupt(digitalPinToInterrupt(arduinoIntPin), intCallBack, FALLING);