RobTillaart / PCF8575

Arduino library for PCF8575 - 16 channel I2C IO expander
MIT License
74 stars 10 forks source link
arduino i2c io-expander

Arduino CI Arduino-lint JSON check GitHub issues

License: MIT GitHub release PlatformIO Registry

PCF8575

Arduino library for PCF8575 - 16 channel I2C IO expander.

Description

The library gives easy control over the 16 pins of the PCF8575 chips.

Base address = 0x20 + 0..7 depending on address pins A0..A2.

type address-range notes
PCF8575 0x20 to 0x27 same range as PCF8574 !
PCF8575C 0x20 to 0x27 need pull up in input mode. See #36, to be verified.

So you can connect up to 8 PCF8575 on one I2C bus, giving access to 8 x 16 = 128 IO lines. To maximize IO lines combine 8 x PCF8575 + 8 x PCF8574A giving 128 + 64 = 192 IO lines. Be sure to have a well dimensioned power supply.

The library allows to read and write both single pins or 16 pins at once. Furthermore some additional functions are implemented that are playful and useful.

Related to the PCF8574 8 channel IO expander library https://github.com/RobTillaart/PCF8574.

Interrupts intro

The PCF8575 has an interrupt output line (INT) to notify an MCU that one of the input lines has changed. This can be used to prevent active polling of the PCF8574, which can be more efficient.

From the datasheet:

An interrupt is generated by any rising or falling edge of the port inputs in the input mode. After time, (Tiv), INT is valid. Resetting and reactivating the interrupt circuit is achieved when data on the port is changed to the original setting or data is read from, or written to, the port that generated the interrupt. Resetting occurs in the read mode at the acknowledge bit after the rising edge of the SCL signal, or in the write mode at the acknowledge bit after the high-to-low transition of the SCL signal.

So there are three scenarios how the INT is reset.

  1. pins revert to original state (lesser known).
  2. read from the device (well known)
  3. write to the device (well known)

This implies that polling the PCF8574 can miss an INT in scenario 1. (see #48) In practice if you have faster polling than your signals changes this would not be a problem. E.g. tactile switches and a polling frequency > 100 Hz will work.

Interrupts library

The library cannot handle the PCF8575 interrupts as it has no code for it. The user should catch the interrupt in his own code to set a flag and can use the library to see which line has changed.

There is one example to show how interrupts can be handled:

A more advanced interrupt handler would not set a boolean flag in the interrupt routine but increase a counter (uint8_t or larger). Then it would be possible to see that:

  1. an interrupt occurred. (counter > 0)
  2. if one or more interrupts are not handled (counter > 1)

A minimal example that shows catching missed interrupts:

0.2.0 Breaking change

Version 0.2.0 introduced a breaking change. You cannot set the pins in begin() any more. This reduces the dependency of processor dependent Wire implementations. The user has to call Wire.begin() and can optionally set the Wire pins before calling begin().

Related

16 bit port expanders

8 bit port expanders

I2C Clock

Testing showed that the PCF8575 still works at 600 KHz and failed at 800 KHz. These values are outside the specs of the datasheet so they are not recommended. However when performance is needed you can try to overclock the chip.

TODO test to fill the table

clock speed Read Write Notes
100000 spec datasheet
200000
300000
400000 max advised speed
500000 not recommended
600000 not recommended
700000 not recommended
800000 crash crash not recommended

Interface

#include "PCF8575.h"

PCF8575_INITIAL_VALUE is a define that can be set compile time or before the include of "pcf8575.h" to overrule the default value used with the begin() call.

Constructor

Read and Write

Button

The "button" functions are to be used when you mix input and output on one IC. It does not change / affect the pins used for output by masking these. Typical usage is to call setButtonMask() once in setup as pins do not (often) change during program execution.

Background - https://github.com/RobTillaart/Arduino/issues/38

Special

Select

Some convenience wrappers.

Miscellaneous

Error codes

name value description
PCF8575_OK 0x00 no error
PCF8575_PIN_ERROR 0x81 pin number out of range
PCF8575_I2C_ERROR 0x82 I2C communication error

Testing

Testing the initial library is done by Colin Mackay (thanks!). Platforms used for testing include: Nano, ESP32 and Seeed Xiao.

Operation

See examples.

It is advised to use pull-up or pull-down resistors so the lines have a defined state at startup.

Future

Must

Should

Could

Wont

Support

If you appreciate my libraries, you can support the development and maintenance. Improve the quality of the libraries by providing issues and Pull Requests, or donate through PayPal or GitHub sponsors.

Thank you,