Arduino library · Input

PCF8574: eight extra pins with no registers to set

The PCF8574 is the simplest I2C I/O expander there is: it has no registers, only one byte. Write a byte and the eight pins, P0 to P7, take its bits; read a byte and you get the levels on the pins. It is the chip on the backpack of most 16x2 I2C LCDs, and on its own it adds eight pins for buttons and LEDs.

Built in on Mokxi: #include <PCF8574.h> and it builds, with nothing to install. Free, and no account needed.

What PCF8574 (Rob Tillaart) and PCF8574 library (Renzo Mischianti) does

Its outputs are quasi-bidirectional. A 0 pulls a pin hard to ground, but a 1 only lets it rise through a weak internal current of about 100 µA, which is also how a pin becomes an input: write it high, and an outside switch can pull it low. So wire LEDs from VCC through a resistor to the pin, lit when you write LOW, and buttons from the pin to GND.

Two different libraries are called PCF8574 and both use PCF8574.h: Rob Tillaart’s (read8(), write(pin, value), toggle()) and Renzo Mischianti’s (pinMode(), digitalWrite(), digitalRead() on P0 to P7). Check which one a tutorial uses before copying its calls. The address is 0x20 to 0x27 from the A0 to A2 pins, or 0x38 to 0x3F on a PCF8574A.

Library Manager namePCF8574 (Rob Tillaart) and PCF8574 library (Renzo Mischianti)
AuthorRob Tillaart, Renzo Mischianti
Include#include <PCF8574.h>
Boardsevery board Mokxi compiles for but ATtiny85
In the simulatorSimulated: it runs against the part the way it does on the bench.
Parts it drivesI/O expander, PCF8574

Install it

It builds on every board Mokxi compiles for but ATtiny85.

In Mokxi it is built in: #include <PCF8574.h> and the sketch compiles, with no download, no zip and no Library Manager.

On a real board, install "PCF8574 (Rob Tillaart) and PCF8574 library (Renzo Mischianti)" by Rob Tillaart, Renzo Mischianti from the Arduino IDE’s Library Manager (Sketch, Include Library, Manage Libraries), or add PCF8574 (Rob Tillaart) and PCF8574 library (Renzo Mischianti) to lib_deps in PlatformIO. Mokxi follows the calls of release 0.4.5 and 2.4.0, so a sketch written here builds there too.

What to know in the simulator: Both libraries use this file name, so one class carries both sets of calls. Mischianti’s interrupt pin and encoder helpers are not here.

ESP32-C3 · Arduino Uno · Arduino Nano · Arduino Mega 2560 · Arduino Leonardo · SparkFun Pro Micro · Arduino Micro · ESP32-C6 · Raspberry Pi Pico · Raspberry Pi Pico W · Seeed XIAO SAMD21 · STM32 · STM32 Nucleo-F411RE · STM32 Blue Pill · micro:bit V2 · Arduino Uno R4 · ESP32 DevKit · ESP32-S3-DevKitC-1 · ESP8266 NodeMCU · Arduino Pro Mini 3.3 V · Seeed XIAO ESP32-C3 · ESP32-C3 SuperMini · Seeed XIAO ESP32-C6 · ESP32-DevKitC V4 · LOLIN32 Lite · Wemos D1 R32 · Cheap Yellow Display · TTGO T-Display · Seeed XIAO ESP32-S3 · Arduino Nano ESP32 · Arduino Nano RP2040 Connect · Seeed XIAO RP2040 · Waveshare RP2040-Zero · Arduino Uno R4 WiFi

The calls you will use

In the order a sketch meets them.

PCF8574 pcf(0x20)

The expander at address 0x20. Both libraries take the address in the constructor.

pcf.begin()

Starts I2C and writes the pins high, so they all start as inputs (Tillaart), or applies the modes set with pinMode() first (Mischianti).

pcf.isConnected()

True when the chip acknowledges at its address.

pcf.write(0, LOW)

Tillaart: pulls P0 low, which lights an LED wired from VCC. write8(0xF0) sets all eight pins at once.

pcf.read8()

Tillaart: reads all eight pins as one byte. read(7) reads one pin.

uint8_t pins = pcf.read8();
if (!(pins & 0x80)) Serial.println("button on P7 pressed");

pcf.toggle(3)

Tillaart: flips one output.

pcf.pinMode(P0, OUTPUT)

Mischianti: sets a pin’s mode before begin(). Then digitalWrite(P0, LOW) and digitalRead(P7) work like the board’s own.

Example: An LED and a button on a PCF8574

On the Arduino Uno R3. It runs in the browser exactly as printed.

sketch.ino · Arduino Uno R3
#include <PCF8574.h>

PCF8574 pcf(0x20);

void setup() {
  Serial.begin(9600);
  if (!pcf.begin()) {
    Serial.println("PCF8574 not found");
    return;
  }
  Serial.println("PCF8574 found");
  pcf.write(0, LOW);  // P0 sinks the LED's current: it lights
  Serial.print("P7 reads ");
  Serial.println(pcf.read(7));
  Serial.print("port 0x");
  Serial.println(pcf.read8(), HEX);
}

void loop() {}

Wiring

  • Arduino Uno R3 A4 to I/O expander, PCF8574 SDA
  • Arduino Uno R3 A5 to I/O expander, PCF8574 SCL
  • Arduino Uno R3 5V to I/O expander, PCF8574 VCC
  • Arduino Uno R3 GND to I/O expander, PCF8574 GND
  • Arduino Uno R3 5V to Resistor 1
  • Resistor 2 to LED A
  • LED C to I/O expander, PCF8574 P0

Open it in the editor, wired and ready to run

Common errors and how to fix them

The LED does not light when the pin is written HIGH

A PCF8574 cannot source current: HIGH is only a weak pull-up. Wire the LED and resistor from VCC to the pin and write LOW to light it, or drive a transistor for bigger loads.

A button input always reads LOW, or always HIGH

An input must be written HIGH first so the switch can pull it down, and the switch should go to GND. If an output call wrote 0 to that bit, the pin is held low and reads LOW regardless.

'class PCF8574' has no member named 'pinMode'

The installed library is Rob Tillaart’s and the sketch was written for Renzo Mischianti’s, or the reverse. Install the one the tutorial used, or translate: write() and read() are Tillaart’s, digitalWrite() and digitalRead() Mischianti’s.

Try PCF8574 (Rob Tillaart) and PCF8574 library (Renzo Mischianti) without installing anything

Open the example, change the sketch, and keep your version in a free account.