IO expander Library
I’ll wrote a library for the arduino that can communicate with a MCP23016 pin expander. That microchip works on the I2C bus and has 16 i/o ports. The library provides the user a interface just like the interface you use for the normal I/O ports.
This library uses the Two Wire library as base to communicate through the I2C bus. The rest of the class is really straight forward and simplistic, but it provides just the things you need to keep your code clean and tidy ;).
Download
- Source code
- Breadboard sketch
- Video example
- Datasheet MCP23016
- Datasheet MCP23017
- Datasheet MCP23018
- Datasheet microchip interfacing with the MCP23016
Versions
08-02-2011 – start of the project
19-02-2011 – v0.2 intial release
20-02-2011 – v0.3 improvements submitted by robtillaart, support added for the MCP23017 and MCP23018 (not tested yet)
Future work
Microchip also has the MCP23017, MCP23s17, MCP23018 and the MCP23s18. So far i know these are refined models and has essentially the same function. The communication is slightly diffrent and I think it would be nice if this library can become universal for this whole family of chips. In version 0.3 I’ve added the support necessarie for the other versions of the chip. I’ve did this from the datasheets and could’t test it.
I’m looking for someone who has one of these chips to test some things out!
Functions
IOexpander();
This is the constructor, nothing more to tell.
bool init(uint8_t address, uint8_t device_type);
This function initializes the class, it has to be called before the class operates. The function parameter address is the i2c address the chip uses, the device_type can be set with the values (MCP23016, MCP23017 and MCP23018)
bool pinMode(uint8_t port, uint8_t pin, bool mode);
The rest of the functions are just like u used to on the arduino. The pinmode function sets a pin on output or input. Just call it like pinMode(0,1,OUTPUT); and pin 0.1 is a ouput port.
bool pinModePort(uint8_t port, bool mode);
Just like the pinMode function but then for a whole port, handy i think!
bool digitalWrite(uint8_t port,uint8_t pin, bool value);
Like u used to, call it with the HIGH and LOW as a value, that keeps your program readable! It only affects a pin when you set it to ouput mode
bool digitalWritePort(uint8_t port, bool value);
Same construction as with the pinMode, a handy function to write a whole port to a LOW or HIGH value at once! (keep in mind that the whole port has to be in output mode!!
int digitalRead(uint8_t port,uint8_t pin);
No need for any more info, gets the state of the pin. Returns also when the port is in output mode.
Thank you very much all is working.
Hey Romik,
Good to hear! currently i’m so busy with my graduation that there is no time left to complete the future work that i’ve described. In about 3 months i’ll continue with completing this and adding more classes on this website.
i get that it says that that there is no comunication with the i/o expander 😦
mcp23016 chip, got two, rebuild the schematic a few times, i don’t know what’s wrong 🙂
any thoughts?
Hi Rob,
Dit you try the example project that i’ve include with the source?
This message comes directly from the wire library endTransmission function and means that the communication was unsuccessful. I’ve found a small flaw in my lib, the endTransmission function returns a error code, but my lib only gives a generic error back. I don’t think the error code will help a lot, but you could look into it.
Dit you also place the capacitor from the schematic? I use a 33 pF capacitor and a 3K9 Ohm resistor.
i build the schematic i found on the site where i bought the i/o expander, works perfectly now 🙂
Nice to hear!
Maybe you can share the sollution you’ve found?
gr!
well this is how i solved it:
http://www.iprototype.nl/products/components/ics/pinexpander
used the pdf called aansluitschema(pdf) and worked from there. 🙂
by the way any chance of you implementing this function where you can send data like a shift register then shift out the data? i’ve seen in the data sheet that it’s possible 🙂
Hey Koenwar,
I’ve been using your library successfully so far with one MCP23016; now I need to add a second one to my board; how can I differentiate the commands I send through IOexpander, and should I use the same pins on the Arduino board to connect it?
Thanks,
gcaglion
Hai Gcaglion,
That’s the fun part of I2C! it’s a bus! just connect the scl and sda pins from the first mcp to the second mcp. Now change the adress of the second mcp bychanging the one of the adress pins a0,a1,a2 pins from negative to positive. By example, a0 “-” , a1 ” -” and 2 “+”. In the code you must make a second instance of the IOexpender class like this:
IOexpander IOexp1;
IOexpander IOexp2;
IOexp1.init(0x20, MCP23016);
IOexp2.init(0x21, MCP23016);
IOexp1.pinModePort(0,OUTPUT);
IOexp1.pinModePort(1,INPUT);
IOexp2.pinModePort(0,OUTPUT);
IOexp2.pinModePort(1,INPUT);
etc….
I never tried this before, but it should work! let me know how it wend!
gr
Thanks gr,
I’m trying to make this work, but so far, after connecting scl and sda, power and ground, the output pins of the second mcp seems to be synchronized with the first one…
I’m not sure what you mean by changing the address of pin a0,a1,a2, however: should this be written in code, or what?
Thanks,
G
lol, no check the datasheet of the mcp23016, chapter “1.6 Address Decode”. the I2C address is hardwired on the outside of the chip on pin A0, A1 and A2!
Thank you again;
I have been trying to connect any combination of (a0,a1,a2) to vcc and ground, but every time I connect any of those pins to vcc, Arduino itself simply shuts off, as if there were a short circuit.
I’ve also tried to put a 4k7 resistor between, say, a0 and vcc; in this case, everything reverts back to the original status (e.g., the two mcps are in sync)… Am I missing something else??
woow!!, yes you have to use a 4k7 resistor between vcc and the address ports!
dit you tried to connect a1 to ground, a2 to ground and a0 with the 4k7 resistor to vcc? otherwise try it with a0 and a1 to ground and a2 to vcc (with the 4k7 😉 ) and set the address of the second chip on 0x24
if you look in this file:
Click to access 00245a.pdf
you can see on page 14 that they use a 4k7 resistor of the a0 to a2 pins? so it should work!
Yes, I’ve tried all possible combinations of a0,a1,a2 connecting to vcc and ground, always inserting a 4k7 resistor: every time, the 2nd mcp behaves exactly like the first one, and the code returns the error message about not being able to find the second mcp.
At one pint I even thought I might have fried a0 on the second mcp, by connecting it to vcc without the 4k7, but then I tried to change the address of the first mcp (with the 4k7:-)), and it didn’t make any difference either (that is, the first mcp address is always 0x20).
Not really sure at this point what is going on here…
how strange…i’m really curious what goes wrong here 😉
something to test:
1. change in the code the addr to something like 0x00. it should do nothing now 😉
2. whats the voltage on the pins??
AAAHHH! I rebuilt the breadboard from scratch, and just realized I had A0 of the second pin also touching the ground! (That also explains Arduino was shorting out when trying to connect A0 to ground…)
Now everything works perfectly with these 16 LEDs; time to go on with the project and replace them with steppers dir and step pins!
Thanks a lot koenwar, you have been really helpful!
lol haha! you’re welcome!
Good to hear that you can use the lib for more than one ioexpender. I’ll graduate tomorrow, after that i’m planning to complete my work on this lib and get it on the arduino site!
Did you graduate? Did you make it?
If so Congratulations! 🙂
Here is a Question that involves your Library and the mcp23016 i/o expander,
Basically, I Am going to attempt to Write a Library of my own involving the mcp23016 i/o expander, with which I want to control a lcd over I2c, and well I wanted to ask if I may take a look at your library (at your code) and possibly use it 🙂
since the mcp23016 has 16 i/o pins I’ll have something like 6 pins left with to do as one pleases 🙂
And I might be wanting to use some piece’s of you library to make this easier on the user of the I2cLcd (me in this case). and That is why I ask you permission to maybe use some of you library code 🙂
I’ll credit you off course, if I were able to get it to work, Then I’ll probably put it online as this maybe be very useful to other also 🙂
My nick on arduino.cc is Duality,
Greetings from,
Duality.
Hi Duality,
Yes, graduated with honors, i’m very pleased! haha…
But sure, off course you may use it. I wonder if you can get the timing right!! i’ve no idea how fast the ports react.
greets Koen
Hi,
I can initialize the display, and blink a cursor
^^
so happy 😛
greetings from,
Duality
I did it!
My library works!
It’s far from ready, but it does all the things it should do with a 16×2 screen,
now going to Work on, So it gonna be compatible with some different sizes of screens.
if you want to see it in action!
look: http://www.youtube.com/watch?v=jXh2ijKs4Us
Turn the volume down, it can be on high volume some times, crapy cam 🙂
I hope that somewhere in the future I can remove some of the parts I used form you library,
that it will be smaller.
beside’s I am going to recommand your library for easy use with this expander,
because I designed the Pcb in such a way it’s not only usable as Lcd, but also As IOexpander 🙂
Greetings,
Duality
link is down ?
i see, working on that now…
thank you,
can you may provide a link on hotfile or something like that ?
because i want to start working with your great lib
Hi, the source code is online again. I’m looking for a permanent sollution.
grtz
maybe you could put it online on github or something 🙂
thank you 😀