I2C MCP23016

I've been trying for a while to get just flash some lights on one of the IO ports of a MCP23016 with the Arduino Diecimila using the wire.h lib. I don't think the following code initializes the I2C port correctly. With a scope there is no clock or data on the SCL or SDA lines, they just stay pulled high. Any help would be greatly appreciated.

#include <Wire.h>

// address in datasheet defined as 010 0abc (note, 7 bits)
// abc = 000
#define address 0x20
#define GP0     0x00    // write to here will also write to OLAT0
#define OLAT0   0x02
#define IPOL0   0x04    // input polarity (inversion)
#define IODIR0  0x06    // io direction reg;  1=input
#define IOCON0  0x0A

void setup()
{
  Serial.begin(9600);
  Serial.println("Start");

  Wire.begin(); // join i2c bus (address optional for master)
  Wire.beginTransmission(address);
  Wire.send(IODIR0);    // io direction register 0
  Wire.send(0x00);      // all outputs
  Wire.endTransmission();    // stop transmitting
}

byte x = 0;

void loop()
{
  Wire.beginTransmission(address); // transmit to device #4
  Wire.send(GP0);                  // sends one byte 
  Wire.send(x);
  Wire.endTransmission();          // stop transmitting

  Serial.println(x);
  x++;
  delay(500);  // wait a while
}

Hello, I'm having problems with mcp23016 too, Did your circuit works?

Thanks.

This is my working code for the mcp23016.
Note address 0x21 and io_int I use just to make it work.

If this dont work its hardware !!!!!!
check addressing lines and the cap resistor .

#include <Wire.h>
int x = 0;
int io_address =  B100001;
int wait_delay = 500;
void setup()
{
  Wire.begin();        // join i2c bus (address optional for master)
  Serial.begin(9600);  // start serial for output
  io_int();
}

void loop()
{
  write_io(6,0);
  write_io(7,0);
  delay(wait_delay);
  write_io(0,0);  // all off
  write_io(1,0);  // all off
  delay(wait_delay); 
  
  write_io(0,255);  // all on
  write_io(1,255);  // all on
  delay(wait_delay);
 } 

void io_int()
  {   
    write_io(6,0),write_io(7,0);
    write_io(0,0),write_io(1,0); 
} // end of int_io

int read_io(int cmd_reg)
{
int tmp;  
Wire.beginTransmission(io_address);
Wire.send(cmd_reg); // 0 or 1 -- GP0 or GP1
Wire.endTransmission();
Wire.requestFrom(io_address, 1);
tmp=Wire.receive();
return tmp;
}  // end of read_io

void write_io(int cmd_reg, int push_this)
{
  Wire.beginTransmission(io_address);
  Wire.send(cmd_reg),Wire.send(push_this); // reset register pointer then set GP0 to push_this // use (0,??)
  Wire.endTransmission();
} // end of write_io

Sorry to suggest this but you are using analogue pins 4 & 5 not digital pins.
Also I would recommend 4K7 pull up resistors.

The address 0x20 is correct if all the address lines on the 23016 are connected to ground. Have you got the RC for the oscillator connected.

Just used four of these on my Arduinocaster (see exhibition part of forum)

IT'S WORKS!!!!

And my code works too, what stupid thing, the problem were the resistors and the init rutine, I'm using a board with relays and mpc23016 and seeing the diagram again I saw that already had the pull up resistors in SDA and SCL, so I removed my resistors and WORKS.

Thanks to everyone for your help.

It was not easy, but I learned a lot.

I just got two of these 16 relay boards which use the MCP23016 controller and noticed that nobody had anything that really worked so today I wrote two simple programs that really work. This is a 12V board. There is no place to connect +5V from the I2C connector, so don't do it, you only need GND, SDA and SCL.

/****************************************************************************** 
Test Program for the 12CZXRELAY16 Board from inexglobal.com
16 Relay Scanner Night Rider Style (for the fun of it)
made by EdArmstrong@testelectronics.com
December 27th 2010
* 
******************************************************************************/ 

#include <Wire.h> 

//#define MCP23016_I2C_WRITE 0x40 //do not use, the chip is 7 bit so the library adds a LSB bit so 0x40 becomes 0x20
//#define MCP23016_I2C_READ 0x41  //do not use
#define MCP23016_I2C 0x20 //the library adds last bit so it makes it a 0x40

// COMMAND BYTE TO REGISTER RELATIONSHIP 
#define GP0 0x00 // PORT0 first 8 relays
#define GP1 0x01 // PORT1 second 8 relays
#define OLAT0 0x02 // LATCH0 command to write on latch 0 first 8 relays
#define OLAT1 0x03 // LATCH1 command to write on latch 1 second 8 relays
#define IPOL0 0x04 // INPUT POLARITY PORT REGISTER 0 
#define IPOL1 0x05 // INPUT POLARITY PORT REGISTER 1 
#define IODIR0 0x06 // I/O DIRECTION REGISTER 0 
#define IODIR1 0x07 // I/O DIRECTION REGISTER 1 
#define INTCAP0 0x08 // INTERRUPT CAPTURE REGISTER 0 
#define INTCAP1 0x09 // INTERRUPT CAPTURE REGISTER 1 
#define IOCON0 0x0A // I/O EXPANDER CONTROL REGISTER 0 
#define IOCON1 0x0B // I/O EXPANDER CONTROL REGISTER 1 

#define PAUSE 100

void setup()
{
  Wire.begin(); // join i2c bus (address optional for master)
  write_io (IODIR0, 0x00); //sets direction to output
  write_io (IODIR1, 0x00);
  write_io (GP0, B00000000); //clears all relays
  write_io (GP1, B00000000);
  delay (PAUSE);
}


void loop()
{
  write_io (GP0, B00000001);
  delay (PAUSE);
  write_io (GP0, B00000010);
  delay (PAUSE);
  write_io (GP0, B00000100);
  delay (PAUSE);
  write_io (GP0, B00001000);
  delay (PAUSE);
  write_io (GP0, B00010000);
  delay (PAUSE);
  write_io (GP0, B00100000);
  delay (PAUSE);
  write_io (GP0, B01000000);
  delay (PAUSE);
  write_io (GP0, B10000000);
  delay (PAUSE);
  write_io (GP0, B00000000);
 
  
  write_io (GP1, B00000001);
  delay (PAUSE);
  write_io (GP1, B00000010);
  delay (PAUSE);
  write_io (GP1, B00000100);
  delay (PAUSE);
  write_io (GP1, B00001000);
  delay (PAUSE);
  write_io (GP1, B00010000);
  delay (PAUSE);
  write_io (GP1, B00100000);
  delay (PAUSE);
  write_io (GP1, B01000000);
  delay (PAUSE);
  write_io (GP1, B10000000);
  delay (PAUSE);
  write_io (GP1, B01000000);
  delay (PAUSE);
  write_io (GP1, B00100000);
  delay (PAUSE);
  write_io (GP1, B00010000);
  delay (PAUSE);
  write_io (GP1, B00001000);
  delay (PAUSE);
  write_io (GP1, B00000100);
  delay (PAUSE);
  write_io (GP1, B00000010);
  delay (PAUSE);
  write_io (GP1, B00000001);
  delay (PAUSE);
  write_io (GP1, B00000000);
  
  
  write_io (GP0, B10000000);
  delay (PAUSE);
  write_io (GP0, B01000000);
  delay (PAUSE);
  write_io (GP0, B00100000);
  delay (PAUSE);
  write_io (GP0, B00010000);
  delay (PAUSE);
  write_io (GP0, B00001000);
  delay (PAUSE);
  write_io (GP0, B00000100);
  delay (PAUSE);
  write_io (GP0, B00000010);
  delay (PAUSE);
  write_io (GP0, B00000001);

}
 
 
 void write_io(int command, int value)
{
  Wire.beginTransmission(MCP23016_I2C);
  Wire.send(command),Wire.send(value); // reset register pointer then set GP0 to push_this // use (0,??)
  Wire.endTransmission();
}

Here is the other program

/****************************************************************************** 
Test Program for the 12CZXRELAY16 Board from inexglobal.com
16 Relay Scanner
made by EdArmstrong@testelectronics.com
December 27th 2010
* 
******************************************************************************/ 

#include <Wire.h> 

//#define MCP23016_I2C_WRITE 0x40 //do not use, the chip is 7 bit so the library adds a LSB bit so 0x40 becomes 0x20
//#define MCP23016_I2C_READ 0x41  //do not use
#define MCP23016_I2C 0x20 //the library adds last bit so it makes it a 0x40

// COMMAND BYTE TO REGISTER RELATIONSHIP 
#define GP0 0x00 // PORT0 first 8 relays
#define GP1 0x01 // PORT1 second 8 relays
#define OLAT0 0x02 // LATCH0 command to write on latch 0 first 8 relays
#define OLAT1 0x03 // LATCH1 command to write on latch 1 second 8 relays
#define IPOL0 0x04 // INPUT POLARITY PORT REGISTER 0 
#define IPOL1 0x05 // INPUT POLARITY PORT REGISTER 1 
#define IODIR0 0x06 // I/O DIRECTION REGISTER 0 
#define IODIR1 0x07 // I/O DIRECTION REGISTER 1 
#define INTCAP0 0x08 // INTERRUPT CAPTURE REGISTER 0 
#define INTCAP1 0x09 // INTERRUPT CAPTURE REGISTER 1 
#define IOCON0 0x0A // I/O EXPANDER CONTROL REGISTER 0 
#define IOCON1 0x0B // I/O EXPANDER CONTROL REGISTER 1 

#define PAUSE 200

void setup()
{
  Wire.begin(); // join i2c bus (address optional for master)
  write_io (IODIR0, 0x00); //sets direction to output
  write_io (IODIR1, 0x00);
  write_io (GP0, B00000000); //clears all relays
  write_io (GP1, B00000000);
  delay (PAUSE);
}


void loop()
{
  write_io (GP0, B00000001);
  delay (PAUSE);
  write_io (GP0, B00000010);
  delay (PAUSE);
  write_io (GP0, B00000100);
  delay (PAUSE);
  write_io (GP0, B00001000);
  delay (PAUSE);
  write_io (GP0, B00010000);
  delay (PAUSE);
  write_io (GP0, B00100000);
  delay (PAUSE);
  write_io (GP0, B01000000);
  delay (PAUSE);
  write_io (GP0, B10000000);
  delay (PAUSE);
  write_io (GP0, B00000000);
 
  
  write_io (GP1, B00000001);
  delay (PAUSE);
  write_io (GP1, B00000010);
  delay (PAUSE);
  write_io (GP1, B00000100);
  delay (PAUSE);
  write_io (GP1, B00001000);
  delay (PAUSE);
  write_io (GP1, B00010000);
  delay (PAUSE);
  write_io (GP1, B00100000);
  delay (PAUSE);
  write_io (GP1, B01000000);
  delay (PAUSE);
  write_io (GP1, B10000000);
  delay (PAUSE);
  write_io (GP1, B00000000);

}
 
 
 void write_io(int command, int value)
{
  Wire.beginTransmission(MCP23016_I2C);
  Wire.send(command),Wire.send(value); // reset register pointer then set GP0 to push_this // use (0,??)
  Wire.endTransmission();
}

This way is much more intuitive for controlling the relays: I couldnt get it to work at first because B00000000 only works with 8 bits or less. Then I discovered 0b000000000000000 works with however many bits you want.

/****************************************************************************** 
Test Program for the 12CZXRELAY16 Board from inexglobal.com
16 Relay Scanner Night Rider Style (for the fun of it)
made by EdArmstrong@testelectronics.com
January 02 2011
* 
******************************************************************************/ 

#include <Wire.h> 

//#define MCP23016_I2C_WRITE 0x40 //do not use, the chip is 7 bit so the library adds a LSB bit so 0x40 becomes 0x20
//#define MCP23016_I2C_READ 0x41  //do not use
#define MCP23016_I2C 0x20 //the library adds last bit so it makes it a 0x40

// COMMAND BYTE TO REGISTER RELATIONSHIP 
#define GP0 0x00 // PORT0 first 8 relays
#define GP1 0x01 // PORT1 second 8 relays
#define OLAT0 0x02 // LATCH0 command to write on latch 0 first 8 relays
#define OLAT1 0x03 // LATCH1 command to write on latch 1 second 8 relays
#define IPOL0 0x04 // INPUT POLARITY PORT REGISTER 0 
#define IPOL1 0x05 // INPUT POLARITY PORT REGISTER 1 
#define IODIR0 0x06 // I/O DIRECTION REGISTER 0 
#define IODIR1 0x07 // I/O DIRECTION REGISTER 1 
#define INTCAP0 0x08 // INTERRUPT CAPTURE REGISTER 0 
#define INTCAP1 0x09 // INTERRUPT CAPTURE REGISTER 1 
#define IOCON0 0x0A // I/O EXPANDER CONTROL REGISTER 0 
#define IOCON1 0x0B // I/O EXPANDER CONTROL REGISTER 1 

#define PAUSE 100

void setup()
{
  Wire.begin(); // join i2c bus (address optional for master)
  write_io (IODIR0, 0x00); //sets direction to output
  write_io (IODIR1, 0x00);
  write_io (GP0, B00000000); //clears all relays
  write_io (GP1, B00000000);
  delay (PAUSE);
}


void loop()
  {
  set_data (0b0000000000000001);
  delay (PAUSE);
  set_data (0b0000000000000010);
  delay (PAUSE);
  set_data (0b0000000000000100);
  delay (PAUSE);
  set_data (0b0000000000001000);
  delay (PAUSE);
  set_data (0b0000000000010000);
  delay (PAUSE);
  set_data (0b0000000000100000);
  delay (PAUSE);
  set_data (0b0000000001000000);
  delay (PAUSE);
  set_data (0b0000000010000000);
  delay (PAUSE);
  set_data (0b0000000100000000);
  delay (PAUSE);
  set_data (0b0000001000000000);
  delay (PAUSE);
  set_data (0b0000010000000000);
  delay (PAUSE);
  set_data (0b0000100000000000);
  delay (PAUSE);
  set_data (0b0001000000000000);
  delay (PAUSE);
  set_data (0b0010000000000000);
  delay (PAUSE);
  set_data (0b0100000000000000);
  delay (PAUSE);
  set_data (0b1000000000000000);
  delay (PAUSE);
  
  set_data (0b0100000000000000);
  delay (PAUSE);
  set_data (0b0010000000000000);
  delay (PAUSE);
  set_data (0b0001000000000000);
  delay (PAUSE);
  set_data (0b0000100000000000);
  delay (PAUSE);
  set_data (0b0000010000000000);
  delay (PAUSE);
  set_data (0b0000001000000000);
  delay (PAUSE);
  set_data (0b0000000100000000);
  delay (PAUSE);
  set_data (0b0000000010000000);
  delay (PAUSE);
  set_data (0b0000000001000000);
  delay (PAUSE);
  set_data (0b0000000000100000);
  delay (PAUSE);
  set_data (0b0000000000010000);
  delay (PAUSE);
  set_data (0b0000000000001000);
  delay (PAUSE);
  set_data (0b0000000000000100);
  delay (PAUSE);
  set_data (0b0000000000000010);
  delay (PAUSE);
  }
 
 
 void write_io(int command, int value)
{
  Wire.beginTransmission(MCP23016_I2C);
  Wire.send(command),Wire.send(value); // send command then send value
  Wire.endTransmission();
}

 void set_data (word data)
 {
  write_io(GP0,lowByte(data)); // send low byte
  write_io(GP1,highByte(data)); // send high byte
 }

This program below uses mathematics to scan the relays like KnightRider. Nobody is ever really going to scan relays like KnightRider in any real application, but I just wanted to prove to myself in a fun way that this program really works with the mathematics and maybe practice some binary mathematics. The program above is the best method for setting relays, this program below is just for fun. I could have done a binary count, but I didn't want to wear out relay #1 playing around before I actually put this board to use in my application.

/****************************************************************************** 
Test Program for the 12CZXRELAY16 Board from inexglobal.com
16 Relay Scanner Night Rider Style (for the fun of it)
made by EdArmstrong@testelectronics.com
January 02 2011
* 
******************************************************************************/ 

#include <Wire.h> 

//#define MCP23016_I2C_WRITE 0x40 //do not use, the chip is 7 bit so the library adds a LSB bit so 0x40 becomes 0x20
//#define MCP23016_I2C_READ 0x41  //do not use
#define MCP23016_I2C 0x20 //the library adds last bit so it makes it a 0x40

// COMMAND BYTE TO REGISTER RELATIONSHIP 
#define GP0 0x00 // PORT0 first 8 relays
#define GP1 0x01 // PORT1 second 8 relays
#define OLAT0 0x02 // LATCH0 command to write on latch 0 first 8 relays
#define OLAT1 0x03 // LATCH1 command to write on latch 1 second 8 relays
#define IPOL0 0x04 // INPUT POLARITY PORT REGISTER 0 
#define IPOL1 0x05 // INPUT POLARITY PORT REGISTER 1 
#define IODIR0 0x06 // I/O DIRECTION REGISTER 0 
#define IODIR1 0x07 // I/O DIRECTION REGISTER 1 
#define INTCAP0 0x08 // INTERRUPT CAPTURE REGISTER 0 
#define INTCAP1 0x09 // INTERRUPT CAPTURE REGISTER 1 
#define IOCON0 0x0A // I/O EXPANDER CONTROL REGISTER 0 
#define IOCON1 0x0B // I/O EXPANDER CONTROL REGISTER 1 

#define PAUSE 100

void setup()
{
  Wire.begin(); // join i2c bus (address optional for master)
  write_io (IODIR0, 0x00); //sets direction to output
  write_io (IODIR1, 0x00);
  write_io (GP0, B00000000); //clears all relays
  write_io (GP1, B00000000);
  delay (PAUSE);
}


void loop()
  {
  for (long i=1; i<65536; i*=2)
    {
    set_data (i);
    delay (PAUSE);
    }
  for (word i=16384; i>1; i/=2)
    {
    set_data (i);
    delay (PAUSE);
    }
  }
 
 void write_io(int command, int value)
{
  Wire.beginTransmission(MCP23016_I2C);
  Wire.send(command),Wire.send(value); // send command then send value
  Wire.endTransmission();
}

 void set_data (word data)
 {
  write_io(GP0,lowByte(data)); // send low byte
  write_io(GP1,highByte(data)); // send high byte
 }