arduino

arduino_related


Arduino and everything related


Previous Entry Add to Memories Share Next Entry
i2c IO Expander
maha_peek_cartoon
tibman wrote in arduino_related

Need more digital IO ports?

Another i2c post. This one is about a 16 port IO Expander that works well with the arduino. I'm driving a bunch of leds with it now, i guess you could get eight of these things and drive 128 leds through i2c if you wanted.

Part Description: IC I/O Expander I2C 16B 28SDIP
Digikey part number: MCP23016-I/SP-ND
Price from Digikey: $1.90 US on 20 Sep 09

You will also need two additional parts to support the chip.
1x 33pF Cap
1x 3.9k Resistor

i2c,electronics,arduino
Wiring Diagram


Once the chip is setup, it's very easy to use. The device's i2c address is 0100xxx. Connecting an addr pin to ground makes it '0' and to +5v makes it '1'. This gives you enough addresses to use eight expanders at the same time. Also, this device didn't like i2c bus speed over 100k :(

I ended up writing a library (class) to manage the IO expander. It's kind of big so i'm just going to put the important bits here.



//Basic Write command
void Write(byte reg, byte data1, byte data2)
{
  Wire.beginTransmission(addr);
  Wire.send(reg); // Command
  Wire.send(data1);
  Wire.send(data2);
  Wire.endTransmission();
}

//Read inputs
void Read()
{
  //Set read from GP0
  Wire.beginTransmission(addr);
  Wire.send(0x00); // Command: Access to GP0
  Wire.endTransmission();
  //Recieve bytes from module
  Wire.requestFrom(addr,2); //only two bytes
  if(Wire.available())
  { io_data[0].set(Wire.receive()); io_data[1].set(Wire.receive());}
  else {Serial.println("ERROR: request from GP0 failed");} //FIXME - this should be removed
}



The Datasheet has a list of commands. The important ones are 0x06 (io direction) and 0x00 (pin status). All reads and writes have to be done in pairs. So even if you only want to read one pin, you have to read two bytes (16 bits) and extract the one you want.

I had a difficult time doing bitwise stuff (my first time really) and made a debug function to help. If you are having problems i recommend something like this, it helps so much.


I think it's a great little chip. If you ever feel like your arduino is running out of IO space, drop $2 into one of these. Well worth it!

electronics,arduino
Two leds and a Button hooked up to the IO Expander



IO Expander Code

(Anonymous)

2010-08-21 07:01 pm (UTC)

"I ended up writing a library (class) to manage the IO expander. It's kind of big so i'm just going to put the important bits here."

Would you kindly post a link to the complete library? This is all still new to me.

Re: IO Expander Code

tibman

2010-08-26 03:40 am (UTC)

No problem, it gets a lot easier once you get the chip setup and talking to the arduino. The library i made is still around but i'd like to rewrite it. Initially it was using an array of boolean values to hold the bits.. which turned out to be very inefficient. I discovered that bitwise operations is the way to go and hardcoded those operations into the sketch.

The important thing is that you can read and write bytes to the chip. The addr is a BYTE that is 01000000 if all the chip address pins are grounded. Using the Wire library you can fully communicate with the IO expander. Are you using the same chip from this tutorial?

I'll be visiting family this weekend but can rewrite this tutorial with the entire sketch posted, if that will help? I come from a programming background and have a hard time with the electronics parts instead of the coding ones... looking at this tutorial it isn't very helpful from a software viewpoint, hah. Sorry about that.

My Main problem is the "Wire.beginTransmission(addr);" part; compiling fails when I use the address of my device (0100111; all three address pins held high). I am using the MCP23008 (the little brother of what you used).

I finally got it compiled and on the board, but I still get no outputs. I wrote up this little test app, but it does not seem to work. Where am I going wrong? (btw...i know that this explanation is posted twice with an error between them; this site does not seem to like code posting)


#include
[Error: Irreparable invalid markup ('<wire.h>') in entry. Owner must fix manually. Raw contents below.]

I finally got it compiled and on the board, but I still get no outputs. I wrote up this little test app, but it does not seem to work. Where am I going wrong? (btw...i know that this explanation is posted twice with an error between them; this site does not seem to like code posting)


#include <Wire.h>

void setup()
{
Wire.begin();
}

byte out1 = 00000001;
byte out2 = 00000010;
byte out3 = 00000100;
byte out4 = 00001000;
byte out5 = 00010000;
byte out6 = 00100000;
byte out7 = 01000000;
byte out8 = 10000000;
byte zeroo = 00000000;
void loop()
{

Wire.beginTransmission(27);
Wire.send(0x00);
Wire.send(zeroo);
Wire.endTransmission();

Wire.beginTransmission(27);
Wire.send(0x0A);
Wire.send(out1);
Wire.endTransmission();
delay(1000);

Wire.beginTransmission(27);
Wire.send(0x0A);
Wire.send(out2);
Wire.endTransmission();
delay(1000);

Wire.beginTransmission(27);
Wire.send(0x0A);
Wire.send(out3);
Wire.endTransmission();
delay(1000);

Wire.beginTransmission(27);
Wire.send(0x0A);
Wire.send(out4);
Wire.endTransmission();
delay(1000);

Wire.beginTransmission(27);
Wire.send(0x0A);
Wire.send(out5);
Wire.endTransmission();
delay(1000);


Wire.beginTransmission(27);
Wire.send(0x0A);
Wire.send(out6);
Wire.endTransmission();
delay(1000);

Wire.beginTransmission(27);
Wire.send(0x0A);
Wire.send(out7);
Wire.endTransmission();
delay(1000);

Wire.beginTransmission(27);
Wire.send(0x0A);
Wire.send(out8);
Wire.endTransmission();
delay(1000);

}

I have been working on this all night with no luck....I'm loosing my mind! I even switched to a MCP23018 (they stopped making the MCP23016)...but no luck at all!

I set it up like this:
Pin1 = gnd
Pin3 = pin I used to check for changing voltage
Pin11 = 5v
Pin12 = Ardiuno Analog pin 5
Pin13 = Ardiuno Analog pin 4
Pin16 = 5v

...And I used this sketch as a test...but it still does not work.

http://snippets.dzone.com/posts/show/12149

I'm flying a white flag...I can't even figure out if my problem is wiring, software, or both. I just ordered a Centipede Shield with connectors....$25 shipped; I should have just done it from the start.

No problem man. I looked at your code and the address you are using (27) is B00011011. I'm not at a computer with the arduino ide installed but i think you need to put the B symbol before your binary. (byte out1 = 00000001) != (byte out1 = B00000001)

If you can link the datasheet for your chip, i can help you get it wired up. The hardware part is the difficult part for me, to be honest. But if your hardware is right, a few changes in software should get your IO expander working perfectly.

Going with a pre-made shield is definitely the easiest way to learn, imo. I could not find any shields like that mid-2009 so i had to find something simple and stumbled onto these cheap i2c chips. Once you get one i2c chip working, it'll open up more fun stuff like EEPROM, RTC, RAM, and Crypto. I hope you can get something working for you.

Instead of Wire.beginTransmission(27), try Wire.beginTransmission(71) or Wire.beginTransmission(B01000111);

Sketch

(Anonymous)

2010-10-05 03:31 pm (UTC)

Could you provide a link to the sketch?

Re: Sketch

(Anonymous)

2010-10-13 08:21 pm (UTC)

Yes, it will be posted before friday. I've reworked it into an easy to use library with example. Didn't realize how truely complicated it was until an anonymous poster started asking questions about it. Hopefully the library will clear things up and make it easier for everyone to use this chip.

https://sourceforge.net/projects/ioexpander/

There's the link. Currently only digitalWrite is working, i haven't had time to work on digitalRead. Take a look, if you have any questions i'd be glad to answer them.


That is really helpful. It provided me a number of ideas and I'll be placing them on my web site eventually. I'm bookmarking your blog and I'll be back. Thanks again!


This blog is bookmarked! I really love the stuff you have put here.


Pin 16 cant be used?

(Anonymous)

2011-06-27 08:49 pm (UTC)

Hello, the first this I would say is thank you for the lib.
But I cant manage to use pin 16 as a output, if i set it with
the pinMode function of your lib.

If I set all pins as output with:

> Wire.begin();
> Wire.beginTransmission(0x20);
> Wire.send(0x06);
> Wire.send(0x00); // DDR Port0 all output
> Wire.send(0x00); // DDR Port1 all output
> Wire.endTransmission();

Then I'm able to write to pin 16.

Is there any workaround to fix your pinMode?
Many thanks and sorry for my bad english.

Regards, Jack.
Cheers

Re: Pin 16 cant be used?

tibman

2011-06-28 03:15 am (UTC)

hmm, it's been a while since i've worked on this. But! Give me a few minutes to research an answer for you.

Ok, so it does the same thing if you use the io_expander blink example on pin 16 as well?

The only thing i can think of right now is the pin states are saved in arduino memory and not read from the io_device (to save on io). It's possible that what is in memory is different than what the device is actually set to. Try pulling power from the chip completely and resetting the arduino. I use a reset command (like in the example) to flush all the values and reset the chip, but there are some things it doesn't reset.

But there is also the possibility that i never even tested pin 16 : / I'll put a test setup together and see if i can reproduce your problem.

Edited at 2011-06-28 03:33 am (UTC)

Re: Pin 16 cant be used?

(Anonymous)

2011-06-28 07:04 pm (UTC)

There is completely nothing wrong with your lib.
I can write to pin 16.

I wrote a generic class for a handful of chips, and this
class needs a pin range to init correctly. The range I set
was 1 entry to short. <.< .. took me about 2 days to figure
that out.

Thank you for your feedback and the fast answer and the lib.
Regards, Jack.
Cheers

Re: Pin 16 cant be used?

tibman

2011-06-29 12:39 am (UTC)

yay! Glad to hear it's working for you. If you expand the library any, i'd love to add it to the SourceForge download. Just let me know how the credit should be given (in a readme or in the .cpp files and what it should say).

errors compiling

(Anonymous)

2013-06-25 02:43 pm (UTC)

hi,

I'm getting these errors when trying to compile your sketch with your IO_Expander library:



In file included from blink.pde:7:
/Users/sorenandreasen/Documents/Arduino/libraries/IO_Expander/IO_Expander.h:12:22: error: WProgram.h: No such file or directory
In file included from blink.pde:7:
/Users/sorenandreasen/Documents/Arduino/libraries/IO_Expander/IO_Expander.h:15: error: 'byte' does not name a type
/Users/sorenandreasen/Documents/Arduino/libraries/IO_Expander/IO_Expander.h:16: error: 'byte' does not name a type
/Users/sorenandreasen/Documents/Arduino/libraries/IO_Expander/IO_Expander.h:17: error: 'byte' does not name a type
/Users/sorenandreasen/Documents/Arduino/libraries/IO_Expander/IO_Expander.h:18: error: 'byte' does not name a type
/Users/sorenandreasen/Documents/Arduino/libraries/IO_Expander/IO_Expander.h:19: error: 'byte' does not name a type
/Users/sorenandreasen/Documents/Arduino/libraries/IO_Expander/IO_Expander.h:20: error: 'byte' does not name a type
/Users/sorenandreasen/Documents/Arduino/libraries/IO_Expander/IO_Expander.h:32: error: field 'byte' has incomplete type
/Users/sorenandreasen/Documents/Arduino/libraries/IO_Expander/IO_Expander.h:37: error: 'boolean' has not been declared
/Users/sorenandreasen/Documents/Arduino/libraries/IO_Expander/IO_Expander.h:38: error: 'boolean' does not name a type
/Users/sorenandreasen/Documents/Arduino/libraries/IO_Expander/IO_Expander.h:39: error: 'boolean' has not been declared
/Users/sorenandreasen/Documents/Arduino/libraries/IO_Expander/IO_Expander.h:44: error: 'boolean' does not name a type
/Users/sorenandreasen/Documents/Arduino/libraries/IO_Expander/IO_Expander.h:45: error: 'boolean' has not been declared
/Users/sorenandreasen/Documents/Arduino/libraries/IO_Expander/IO_Expander.h:49: error: 'byte' has not been declared
/Users/sorenandreasen/Documents/Arduino/libraries/IO_Expander/IO_Expander.h:50: error: 'byte' has not been declared
/Users/sorenandreasen/Documents/Arduino/libraries/IO_Expander/IO_Expander.h:52: error: 'byte' does not name a type
blink:10: error: no matching function for call to 'IO_Expander::IO_Expander(int)'
/Users/sorenandreasen/Documents/Arduino/libraries/IO_Expander/IO_Expander.h:23: note: candidates are: IO_Expander::IO_Expander()
/Users/sorenandreasen/Documents/Arduino/libraries/IO_Expander/IO_Expander.h:23: note: IO_Expander::IO_Expander(const IO_Expander&)


It appears to me that something is wrong in the library you made, but I'm not sure. Do you know?

Regards
Søren

Re: errors compiling

tibman

2013-06-25 11:55 pm (UTC)

It's been some years and the Arduino IDE has moved on a bit (yay progress). Give me a bit. I'll download the latest and see what's up.

EDIT:
Okay, fixed it. The IDE uses a different header now. Also the Wire library has changed a little bit. I can't login to sourceforge to replace the library right now. Do you have an email i can send it to? or would you prefer i put the code on pastebin or just under an lj-cut here?

Hope that your project is going well : )

Edited at 2013-06-26 02:12 am (UTC)

You are viewing arduino_related