@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!
@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.
@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 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
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) {
updateRegisterBit(p,(d==INPUT),MCP23017_IPOLA,MCP23017_IPOLB);
}
useage
mcp.inputInvert( pin, HIGH ); // invert input
mcp.inputInvert( pin, LOW ); // normal input
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?
You’ll need to instantiate an instance of the class for each MCP23017 and use the address you assigned them in the mcp.begin(addr) routine. You may not have noticed but it’s overloaded to also take a parameter, the address.
If you’re using the online code editor, there’s a little github icon that shows next to Library name once its selected. This takes you right to the firmware source for the library.
Great @jbeacon and @ScruffR !
I scrolled through the library: it’s a masterpiece!
But it goes far beyond my capabilities to interpret how to use all possibilities without an example…
If I take one of the existing examples “toggle.ino” (LINK), I would like to try it out with a second MCP23017 chip.
So, the first thing I do is set an address with the three pins:
Below is part of the “toggle.ino” sketch.
It says: “// use default address 0”
I guess the default address “0” mentioned in the example is actually HEX address “0x20”, right?
Suppose I select for the second chip address “0x21”, that must then be address “1” to use in my sketch. OK?
The questions for me are:
How do I indicate both address 1 and 2 for my two chips
How do I repeat the same commands for the corresponding pins on the two chips?
Adafruit_MCP23017 mcp;
void setup() { mcp.begin(); // use default address 0
Sorry to bump this thread but is there any way to change the wirespeed for these calls (i need it to be as fast as possible) and perhaps do digitalWriteFast against the chip?
I want to use one of these to control 16 triac devices for ac dimming so increasing the speed of read and writes would be great. The triac relies on millisecond timing so i need to speed my calls up as much as possible
@bigjme, the fastest wire speed supported by the Photon is 400KHz.
All digital writes via the MCP23017 are done via a set of I2C commands so there is no "digitalWriteFast" that can be done.
There is, however, an SPI version of the chip (MCP23S17) that can handle 10MHz SPI. I believe I have seen an SPI library for this version of the chip. At that speed, you could control all 16 channels within the target timeframe.
@bigjme, yes, that is the way to change the speed. The docs about setClockSpeed() say:
Sets the I2C clock speed. This is an optional call (not from the original Arduino specs.) and must be called once before calling begin(). The default I2C clock speed is 100KHz and the maximum clock speed is 400KHz.