PCF8574: un expander i2c I/O digitale

Spread the love

Libreria per l’utilizzo dell’integrato pcf8574 che sfrutta il protocollo i2c usabile sia con Arduino che gli esp8266.

Questo IC puo’ controllare (fino a 8) dispositivi digitali come bottono o led con solamente 2 pins.

Puo’ leggere e scrivere valori digitali con solamente 2 pins perfetto per un esp01 ad esempio.

Ho provato a semplificare l’uso di questo integrato con un set minimo di operazioni.

Come funziona il protocollo I2c

Il protocollo I2C funziona con due fili, l’SDA (dati) e SCL (clock).

Questi pin sono open-drain, e sono in pull-up con delle resistenze.

Di solito c’è un master e uno o più slave sulla linea, anche se possono esserci più master, ma ne parleremo in altra occasione.

Entrambi i master e gli slave possono trasmettere o ricevere dati, pertanto un dispositivo può trovarsi in uno di questi quattro stati: trasmissione master, ricezione master, trasmissione slave, ricezione slave.

IC o modulo

Puoi usare il normale integrato o i vari moduli a disposizione.

IC or Module

You can use a normal IC or module.

pcf8574 IC
pcf8574 module

Libreria

Puoi trovare la mia libreria qui .

Download

Fare clic sul pulsante DOWNLOADS nell’angolo in alto a destra, rinominare la cartella non compressa PCF8574.

Verificare che la cartella PCF8574 contenga PCF8574.cpp e PCF8574.h.

Collocare la cartella della libreria PCF8574 come / librerie / cartella.

Potrebbe essere necessario creare la sottocartella librerie se è la tua prima libreria.

Riavvia l’IDE.

Uso

Ho provato a semplificare l’uso di questo integrato con un set minimo di operazioni.

PCF8574P address map 0x20-0x27 PCF8574AP address map 0x38-0x3f

Sul costruttora devi passare l’indirizzo i2c che hai configurato tramite i pin A0, A1, A2 (per verificare l’indirizzo ti consiglio di usare questa guida I2cScanner)

PCF8574(uint8_t address);

per l’esp8266 se vuoi specificare i pins SDA e SCL usa questo costruttore:

PCF8574(uint8_t address, uint8_t sda, uint8_t scl);

Per ogni pin puoi configurare input o output mode:

	pcf8574.pinMode(P0, OUTPUT);
	pcf8574.pinMode(P1, INPUT);
	pcf8574.pinMode(P2, INPUT);

come puoi vedere dall’immagine l’IC ha 8 I/O digitali:

PCF8574 schema
pcf8574 pinout

Per leggere tutti i pin digitali in un’unica trasmissione puoi usare questo codice (questo non serve a prevenire troppe letture consecutive all’IC, internamente uso 10millis di tempo di debounce per prevenire un sovraccarico di letture):

	PCF8574::DigitalInput di = PCF8574.digitalReadAll();
	Serial.print("READ VALUE FROM PCF P1: ");
	Serial.print(di.p0);
	Serial.print(" - ");
	Serial.print(di.p1);
	Serial.print(" - ");
	Serial.print(di.p2);
	Serial.print(" - ");
	Serial.println(di.p3);

Per assecondare una richiesta specifica di un utente (issue #5) o creato una define per ridurre l’uso di memoria eliminando la struttura complessa di ritorno alla lettura complessiva, per attivarla devi decommentare la linea nel file .h della libreria:

// #define PCF8574_LOW_MEMORY

Abilitando il low memory guadagni circa 7byte di memoria, ed anche l’output del metodo che fa la lettura complessiva sarà modificato in questa maniera:

   byte di = pcf8574.digitalReadAll();
   Serial.print("READ VALUE FROM PCF: ");
   Serial.println(di, BIN);

dove c’è un byte 1110001, e potrai estrarre le stesse informazioni facendo delle operaizoni binarie sul byte stesso, qui un esempio:

   p0 = ((di & bit(0)>0)?HIGH:LOW;
   p1 = ((di & bit(1)>0)?HIGH:LOW;
   p2 = ((di & bit(2)>0)?HIGH:LOW;
   p3 = ((di & bit(3)>0)?HIGH:LOW;
   p4 = ((di & bit(4)>0)?HIGH:LOW;
   p5 = ((di & bit(5)>0)?HIGH:LOW;
   p6 = ((di & bit(6)>0)?HIGH:LOW;
   p7 = ((di & bit(7)>0)?HIGH:LOW;

se tu vuoi leggere un input singolo:

int p1Digital = PCF8574.digitalRead(P1); // read P1

se vuoi scrivere un valore digitale:

PCF8574.digitalWrite(P1, HIGH);

o:

	PCF8574.digitalWrite(P1, LOW);

Puoi inoltre usare un interrupt pin: dovrai inizializzare il pin e passare una funzione di callback che sarà chiamata quando l’interrupt sarà attivato dal PCF8574

// Function interrupt
void keyPressedOnPCF8574();

// Set i2c address
PCF8574 pcf8574(0x39, ARDUINO_UNO_INTERRUPT_PIN, keyPressedOnPCF8574);

Ricorda che non puoi usare comandi come Serial o Wire all’interno della funzione di interrupt.

Il sistema migliore sarà settare solamente una variabile da leggere all’interno del loop():

void keyPressedOnPCF8574(){
	// Interrupt called (No Serial no read no wire in this function, and DEBUG disabled on PCF library)
	 keyPressed = true;
}

Per gli esempi che trovate nella libreria ho usato questo schema di collegamento su una breadboard: 

Breadboard

Links utili

Potrebbero interessarti anche...