Utilizzare un PCF8574ap per espandere le porte IO di Arduino

Capita di trovarci a realizzare applicazioni in cui il numero dei pin digitali richiesti, supera quelli disponibili sulla scheda Arduino UNO. In questi casi potremmo utilizzare una scheda con un numero maggiore di pin IO (ad esempio la Arduino MEGA, la Arduino DUE …) o scegliere dei circuiti esterni che danno la possibilità di espandere le porte IO utilizzando una comunicazione seriale I2C o SPI.

L’integrato PCF8574AP permette di risolvere questo problema fornendo 8 porte IO che possono essere gestite utilizzando il collegamento seriale I2C. Lo schema elettrico seguente mostra come collegare il pcf8574ap alla scheda Arduino Leonardo. L’unica osservazione riguarda le uscite del PCF8574, infatti come potete osservare i led non sono collegati direttamente alle porte dell’integrato ma bensì sono collegati tramite una resistenza alla linea dei 5Vdc. Questo perché l’integrato non è in grado di fornire la corrente sufficiente per alimentare il led; è quindi necessaria una resistenza di pull-up.

Arduino Leonardo PCF8574AP

Quando impostiamo, per esempio, il pin P0 al livello logico alto, otteniamo l’accensione del led perché la corrente che fluisce dall’alimentazione attraversa la resistenza e poi il led. Quando impostiamo il pin P0 al livello logico basso il led si spegne perché la corrente viene ‘assorbita’ dall’integrato. Nelle figure seguenti potete osservare quanto detto:

PCF8574ap led on

PCF8574 Led off

Il codice per testare il circuito è molto semplice e permette di accendere e spegnere i led collegati ai pin delle porte dell’integrato PCF8574AP:

[c]
#include <Wire.h>

void setup()
{
Wire.begin();
delay(1000);
}

void loop()
{
//imposto tutti i pin al livello
//logico alto
Wire.beginTransmission(0x38);
//invio un byte
Wire.write((byte)0b11111111);
//fine trasmissione
Wire.endTransmission();

delay(1000);

//imposto tutti i pin al livello
//logico basso
Wire.beginTransmission(0x38);
//invio un byte
Wire.write((byte)0b00000000);
//fine trasmissione
Wire.endTransmission();

delay(1000);
}
[/c]

Avendo espresso il valore in forma binaria riusciamo facilmente ad accendere o spegnere ogni led cambiando il valore di ogni singolo bit. Ad esempio questo codice accende e spegne solo il led sulla porta P0:

[c]
#include <Wire.h>

void setup()
{
Wire.begin();
delay(1000);
}

void loop()
{
//imposto il pin P0 al livello
//logico alto
Wire.beginTransmission(0x38);
//invio un byte
Wire.write((byte)0b00000001);
//fine trasmissione
Wire.endTransmission();

delay(1000);

//imposto il pin P0 al livello
//logico basso
Wire.beginTransmission(0x38);
//invio un byte
Wire.write((byte)0b00000000);
//fine trasmissione
Wire.endTransmission();

delay(1000);
}
[/c]

Leggere i valori in ingresso

La lettura degli ingressi avviene semplicemente effettuando una richiesta di un byte al PCF8574AP. L’integrato provvederà automaticamente, tramite la sua architettura interna, a fornire al master lo stato delle porte. Possiamo ad esempio collegare i pin da P0 a P7 a massa o alla +5Vdc e successivamente effettuare una lettura:

[c]
#include <Wire.h>

void setup()
{
Serial.begin(9600);
delay(6000);

Wire.begin();
delay(1000);
}

void loop()
{
Wire.requestFrom(0x38,1);
if(Wire.available())
{
Serial.println(Wire.read(), BIN);
}

delay(1000);
}
[/c]

il codice precedente printa in binario lo stato di ogni singola porta del PCF8574AP, ad esempio proviamo a mettere a massa i pin P0, P1, P2 e P3 e colleghiamo alla +5Vdc i pin P5, P6, P7, P8, sul serial monitor osserveremo la stringa 11110000.

Per semplicità ho utilizzato delle variabili scrivendole in binario ma nulla ci vieta di utilizzare le funzioni di bitwise per creare codice più professionale.