MCP23017 Library Port

@peekay123 We’ve hooked the MCP23017 up to an Arduino Uno and it runs just fine

(I work with Chad)

So you guys know that i2c is broken in the web IDE right now, don’t you?

There is a fix in master that will be in the web IDE soon, but right now you need to compile locally to have working i2c.


@bko I forgot that was in the wild! Thanks!

1 Like

Hey guys,

I tried to use the MCP23017 library and default Inputs/Outputs are working perfectly. Unfortunately the interrupt example is not working. I connected the MCP23017 the same way like in the button example but with a connection between D2 and the INTA of the MCP23017.

The Spark receives an interrupt when I connect D2 to VCC, but the MCP23017 isn’t sending an interrupt to the Spark.

Has anyone an idea why the example with the interrupt isn’t working?

Thanks in advance!

Edit: here is my Fritzing Layout:

and this is my simplest Interrupt Test Script:

#include "Adafruit_MCP23017/Adafruit_MCP23017.h"

Adafruit_MCP23017 mcp;

byte SparkIntPIN=D2;

byte button=7;

void setup(){
  mcp.pinMode(button, INPUT);
  mcp.pullUp(button, HIGH); 


void handleInterrupt(){
  Serial.println("Interrupt detected!");
  uint8_t pin=mcp.getLastInterruptPin();
  uint8_t val=mcp.getLastInterruptPinValue();

@Trekky, do you have loop() anywhere in there? Even if it’s empty, it needs to be there.

@peekay123 Yes the loop function is there, but I left it out for a better readability

@Trekky, I don’t have an MCP23017 so when I ported the library, I could not test the examples and relied on @chad_bean to do the testing

I do notice, however, that you don’t have any pull-ups on the I2C lines, which are required by the Core. I’ll have another look at the code I ported just in case I missed something. :smile:

@peekay123 sorry I forgot to add the pull-ups in my fritzing, but the are on the I2C lines.

I compared the code with the code from adafruit for the arduino and didn’t see a difference. Can someone other test the MCP23017 with interrupts or explain the library?

@peekay123 if you want a MCP23017 to test with this, get in touch with me with an address and I’ll send you one ASAP.

@JackANSI, thanks for the fantastic offer! I just found out I have an Adafruit RGB LCD shield that uses an MCP23017 and has some buttons. I’m pretty sure I can use it to do some tests. I should be able to get to it tomorrow. :smile:

1 Like

@Trekky, I got the interrupts working! I was testing using my an Adafruit LCD shield which I had to add a wire to for the INTA line back to the Spark. The code is one of the examples from the MCP library adapted to the LCD shield (buttons are wired to specific pins). I will be posting the code a little later.

@JackANSI, I have the full Adafruit LCD library running so if you need it let me know. :smile:

@peekay123 Really? What was your trick? I’m excited to see the code for the working interrupts.
Is the wiring in my example wrong? Did you connect INTA to D2 of the Spark?

@Trekky, it is working using the Adafruit RGB Shield as a test platform. First, you can’t connect the INTA output to D2 of the Core as it is not 5V tolerant (!) On the shield, I had to solder a wire from pin 20 (INTA) of the MCP23017 and connect it to pin D3 of the Core. I also found a little oddity in the RGBLCDShield library which used pinMode. It turns out that the Arduino definitions for INPUT and OUTPUT are opposite those for the Core!

The combo of both libraries required to use the RGBLCDShield is here. I included the HelloWorld example and also the interrupt example which shows the use of interrupts from the MCP23017. @Trekky, you can modify interrupt.ino to test interrupts without the shield easily.

@JackANSI, if you want a working RGBLCDShield library, there you go! :smile:

@peekay123 I’m very interested in I2C working in general. I use a MCP23017 in chip form on one of my projects in my home (an audio source switcher). Having this chip working saves me from redoing the whole thing when I switch that from a Pi to a core or photon.


If I had to pick an adafruit product or two directly:
A. Bi-color bar graph (based on Holtek HT16K33)

B. The MCP23008 based I2C character backpack

If you wanted another challenge and need either or both of them I can provide a gift certificate to cover that and provide incentive :smiley:

@JackANSI, check out the IDE for libraries. the MCP23008 lib is there, the LCD library for the backpack needs to be ported and the bi-color bargraph is a no brainer to port :stuck_out_tongue: I’ll see what I can over the next few days. As for the gift certificate, donate to your local food bank and make a small difference on my behalf :sunny:


@peekay123 you got it.

1 Like

@peekay123 Thank you very much for your effort. The interrupts are working now! For the record the correct working layout is below.


I have tested around with the MCP23017 and like to share my experiences.

I figured out that the MCP Interrupt Register must be read to recognize interrupts correct. That means after the initialisation of the MCP and after the interrupt occured it must be cleared with mcp.readGPIOAB().
I added a functional example here (thank you @peekay123 for the inspiration) .

The corresponding description is in the datasheet:

The interrupt will remain active until the INTCAP or GPIO register is read. Writing to these registers will not affect the interrupt. The interrupt condition will be cleared after the LSb of the data is clocked out during a read command of GPIO or INTCAP.
The first interrupt event will cause the port contents to be copied into the INTCAP register. Subsequent interrupt conditions on the port will not cause an interrupt to occur as long as the interrupt is not cleared by a read of INTCAP or GPIO.



with just a few lines, the inverse input function can be added.
Usefull for buttons driving the internal pullups low.

add in the .h file

void inputInvert(uint8_t p, uint8_t d);       

add in the .cpp file

* Sets the invert register to either normal or invert
void Adafruit_MCP23017::inputInvert(uint8_t p, uint8_t d) {


mcp.inputInvert( pin, HIGH );    // invert input
mcp.inputInvert( pin, LOW );     // normal input

pin 0…15

1 Like

Hi, I’m working on a project where I need to expand a Photon’s number of digital GPIO’s to around 60…

It seems an ideal solution to me to use four MCP23017 I/O expander ICs.

I tried the library examples with one IC today and everything works perfectly. The fact that you can configure every one of the 16 I/O pins as INPUT and OUTPUT is exactly what I need!

I know the 3 hardware address pins 15~17 are used to determine the I2C bus address for the chip, but I cannot figure out how to address pins on each of the four ICs…

All library examples contain this line:

mcp.begin(); // use default address 0

I guess to address 3 more chips, you should hardwire them to address 1, 2, 3 and use an extra identifier in the code, right?

Can anybody help?