PCF8574 IO Expander Board - Tutorial/example requested

I’m looking to start a project (an internet-connected, openHAB enabled busy board for my kids!) and my plans involve significantly more IO pins than the photon has.

I have been looking at the PCF8574 as a means to connect a bunch of switches to the setup. I have found some Arduino tutorials for the IC but nothing specific to the Particle platform.

I have seen some discussion on the Particle forum so I believe it is compatible, but none of the examples I found included any code.

Does anyone know of either an Arduino-based PCF8574 tutorial that’s code compatible with Particle, or have a Particle-based PCF8574 project they’d be willing to share? I think I could get it off the ground if I could see some basic coding examples.

Have you got a link to the Arduino library to look at?
But with enhanced Arduino compatibility of system 0.6.2 you could just try to build the code and see if it compiles.

SparkFun has a retired break out board that you might be able to base some code from (firmware/library) for the chip you specify.

Otherwise, there are some other alternatives with active (user contributed) libraries:

Adafruit_MCP23017 1.0.2 136 Adafruit_MCP23017 I2C expander library adapted for Spark
MCP23008-I2C 0.0.10 47 A version of Ladyada's MCP23008 8-bit I2C IO Expander library, ported for use on Spark Core.
mcp23s17 0.2.0 23 A C++ wrapper for the Microchip MCP23S17.
MCP23S17_bd78 0.0.1 14 Library for MCP23S17 SPI IO expander. Originally written for Arduino by Cort Buffington & Keith Neufeld.
Adafruit_MCP23008 1.0.6 5 Adafruit_MCP23008 I2C expander library adapted for Particle IDE
MCP23008-RK 0.0.1 0 Particle driver for 8-port I2C GPIO Expander MCP23008

Several based on the MCP23* series. AdaFruit has a breakout board:

The update product that replaced the retired product above is the SX1509 and there is a library within Particle for that board.

SparkFunSX1509 2.0.2 7 Arduino library and hardware files for the SX1509 IO Expander Breakout board.

Some alternative options with libraries available in the Particle library.

I use the MCP23008 I2C GPIO expander in my I2C tutorial, see the “GPIO Expanders” section. There’s a link to the Particle library there as well.

4 Likes

Thanks for the suggestions! I’ve had a busy weekend and haven’t had a chance to dig in. I originally wanted to go with the PCF8574 because I already had a few of them, but it’s looking like it might be easier to just run with the MCP230xx.

@ScruffR I tried a few Arduino tutorials for the PFC8574 but couldn’t get any of them to compile… probably problems with the libraries; I decided to go the MCP230xxx route.

@rickkas7 Someday, I’ll learn to check the code before I buy the parts… I ended up buying some MCP23017 chips instead of the MCP23008. I liked the idea of having more pins per chip and didn’t realize it wasn’t supported by your library.

I will order some MCP23008… but before I do, is it possible to modify the library to work with the MCP23017? I tried connecting it to the Photon and just using pins 0-7 but that approach didn’t work. I haven’t had a chance to dig in beyond that.

@rickkas7 Disregard, I got the MCP23017 working with an Adafruit library I found in the IDE. Not sure how I missed it the first time… Thanks for the tutorial; even though I used a different library it’s the best explanation I’ve ever seen for using i2c in a variety of ways!

Now the fun can begin in earnest!

2 Likes

I did make a MCP23017-RK library that has the same API as the MCP23008-RK but has support for all 16 GPIO pins.

There’s no reason to switch if you have it working with the Adafruit library, just providing the link in case someone finds this post through search.

3 Likes

@rickkas7 This is great… thanks for your efforts.

One quick question - I’m looking at hooking up several MCP23017 chips, along with some PCA9685 PWM expanders. Should I use pullup resistors near every device, or just one set close to the Particle?

One pull-up resistor (2.2K to 10K) on each of SDA and SCL, ideally near the Photon/Electron, though you can put it anywhere.

But only one set, not one per MCP230xx.

@rickkas7 Sounds good. Thanks for the clarification. I’m developing a breakout board for the MCP23017 and wanted to get this clear.

I’m making great progress, though some may say I’m going a bit overboard. :slight_smile:

4 Likes

I’m working on adding more control inputs to my setup but I’m struggling to add more than one MCP23008 or MCP23017 to my Photon. I can’t find an example that references how to define addresses manually; what’s the right way to do that?

@dome, there are 3 hardware address select lines (A0, A1, A2) for setting the I2C address. For example the MCP2308 datasheet says:

The four most significant bits of the slave address are fixed (0100 for MCP23008) and the remaining three bits are user-defined hardware address bits (pins A2, A1 and A0).

@peekay123,

Thanks, though I should have been more clear. I’ve already set the device to address 0x41 in hardware, but I can’t figure out how to define this in software. Every code example I find (for any library) just uses a single chip with the default address.

Edit: not that it matters, but the address I set is 0x21.

My libraries support multiple devices/addresses:

MCP23008-RK
MCP23017-RK

They’re in the community libraries as well, but the documentation is at the links above.

3 Likes

Thanks, I didn’t find the github pages on my checks. That’s exactly what I needed!

I had success with this library:
https://forum.hobbycomponents.com/viewtopic.php?t=2190

#include "HCPCF8574.h"

HCPCF8574 pcf8574(0x20);

void setup() {
  Serial.begin(9600);
  Serial.println("Vers003");
  pcf8574.init();
  delay(100);

  for(uint8_t i=0; i<8; i++){
    pcf8574.pinMode(i, OUTPUT);
  }

  delay(100);

  Serial.println("Load each pin HIGH and read each");
  for(uint8_t i=0; i<8; i++){
    pcf8574.pinWrite(i, HIGH);
  }

  delay(100);

  for(uint8_t i=0; i<8; i++){
    Serial.printlnf("%i:%i", i, pcf8574.pinRead(i));
  }

  Serial.println("Load each pin LOW and read each");
  for(uint8_t i=0; i<8; i++){
    pcf8574.pinWrite(i, LOW);
  }

  delay(100);

  for(uint8_t i=0; i<8; i++){
    Serial.printlnf("%i:%i", i, pcf8574.pinRead(i));
  }

  Serial.println("Write port with 0x55 then read port");
  pcf8574.portWrite(0b01010101);
  delay(100);
  int pw1 = pcf8574.portRead();
  Serial.printlnf("%#4x",pw1);

  Serial.println("Write port with 0xAA then read port");
  pcf8574.portWrite(pw1<<1);
  delay(100);
  int pw2 = pcf8574.portRead();
  Serial.printlnf("%#4x",pw2);
}

void loop() {}

Output:

1 Like