PCF8574 i2c digital I/O expander

Spread the love

Library to use i2c pcf8574 IC with arduino and esp8266.

This IC can control (until 8) digital devices like button or led with 2 only pins.

Can read and write digital value with only 2 wire (perfect for ESP-01).

I try to simplify the use of this IC, with a minimal set of operation.

How I2c Works

I2C works with it’s two wires, the SDA(data line) and SCL(clock line).

Both these lines are open-drain, but are pulled-up with resistors.

Usually there is one master and one or multiple slaves on the line, although there can be multiple masters, but we’ll talk about that later.

Both masters and slaves can transmit or receive data, therefore, a device can be in one of these four states: master transmit, master receive, slave transmit, slave receive.


You can find my library here.

To download.

Click the DOWNLOADS button in the top right corner, rename the uncompressed folder PCF8574.

Check that the PCF8574 folder contains PCF8574.cpp and PCF8574.h.

Place the PCF8574 library folder your /libraries/ folder.

You may need to create the libraries subfolder if its your first library.

Restart the IDE.

IC or Module

You can use a normal IC or module.

pcf8574 IC
pcf8574 module


I try to simplify the use of this IC, with a minimal set of operation.

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

On constructor you must pas the address of i2c, you can use A0, A1, A2 pins to change the address, you can find the address value here (to check the adress use this guide I2cScanner)

PCF8574(uint8_t address);

for esp8266 if you want specify SDA e SCL pin use this:

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

You must set input/output mode:

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

then IC as you can see in the image have 8 digital input/output:

PCF8574 schema
pcf8574 pinout

So to read all analog input in one trasmission you can do (even if I use a 10millis debounce time to prevent too much read from i2c):

	PCF8574::DigitalInput di = PCF8574.digitalReadAll();
	Serial.print("READ VALUE FROM PCF P1: ");
	Serial.print(" - ");
	Serial.print(" - ");
	Serial.print(" - ");

To follow a request (you can see It on issue #5) I create a define variable to work with low memori device, if you decomment this line on .h file of the library:

// #define PCF8574_LOW_MEMORY

Enable low memory props and gain about 7byte of memory, and you must use the method to read all like so:

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

where di is a byte like 1110001, so you must do a bitwise operation to get the data, operation that I already do in the “normal” mode, here an example:

   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;

if you want read a single input:

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

If you want write a digital value you must do:

PCF8574.digitalWrite(P1, HIGH);


PCF8574.digitalWrite(P1, LOW);

You can also use interrupt pin: You must initialize the pin and the function to call when interrupt raised from PCF8574

// Function interrupt
void keyPressedOnPCF8574();

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

Remember you can’t use Serial or Wire on interrupt function.

The better way is to set only a variable to read on loop:

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

For the examples I use this wire schema on breadboard: 


Usefully links

You may also like...