Previous Entry 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



  • 1
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);

}

  • 1
?

Log in