using MCP23017 I/O expander for inputs

Hello,

I am trying to use a MCP23017 I/O expander to add the number of I/O pins that are available on my Arduino Mega 2560. i am most interested in adding inputs, to detect voltage across a sum of 160 pins, and reporting the address of the logic "high" signal.

Here is the code that i got off this tutorial is: Tutorial: Maximising your Arduino’s I/O ports with MCP23017 | tronixstuff.com

 /*
 Example 41.2 - Microchip MCP23017 with Arduino
 http://tronixstuff.com/tutorials > chapter 41
 John Boxall | CC by-sa-nc
 */
// pins 15~17 to GND, I2C bus address is 0x20
#include "Wire.h"
byte inputs=0;
void setup()
{
 Serial.begin(9600);
 Wire.begin(); // wake up I2C bus
}
void loop()
{
 Wire.beginTransmission(0x20);
 Wire.write(0x13); // set MCP23017 memory pointer to GPIOB address
 Wire.endTransmission();
 Wire.requestFrom(0x20, 1); // request one byte of data from MCP20317
 inputs=Wire.read(); // store the incoming byte into "inputs"
 if (inputs>0) // if a button was pressed
 {
 Serial.println(inputs, BIN); // display the contents of the GPIOB register in binary
 delay(200); // for debounce
 }
}

The issue with this code is it only checks the B port, and i would like to declare the A port as a input as well. Any idea on how i would do this?

flytyer232:
Hello,

I am trying to use a MCP23017 I/O expander to add the number of I/O pins that are available on my Arduino Mega 2560. i am most interested in adding inputs, to detect voltage across a sum of 160 pins, and reporting the address of the logic “high” signal.

Here is the code that i got off this tutorial is: http://tronixstuff.com/2011/08/26/tutorial-maximising-your-arduinos-io-ports/

 /*

Example 41.2 - Microchip MCP23017 with Arduino
http://tronixstuff.com/tutorials > chapter 41
John Boxall | CC by-sa-nc
*/
// pins 15~17 to GND, I2C bus address is 0x20
#include “Wire.h”
byte inputs=0;
void setup()
{
Serial.begin(9600);
Wire.begin(); // wake up I2C bus
}
void loop()
{
Wire.beginTransmission(0x20);
Wire.write(0x13); // set MCP23017 memory pointer to GPIOB address
Wire.endTransmission();
Wire.requestFrom(0x20, 1); // request one byte of data from MCP20317
inputs=Wire.read(); // store the incoming byte into “inputs”
if (inputs>0) // if a button was pressed
{
Serial.println(inputs, BIN); // display the contents of the GPIOB register in binary
delay(200); // for debounce
}
}




The issue with this code is it only checks the B port, and i would like to declare the A port as a input as well. Any idea on how i would do this?

I would suggest you read the Microchips Data Sheet for the MCP23017. It will tell you how to configure the gpio pins as input, even assign pullup resistors to the inputs and how to read the current values on the gpio pins.

MCP23017 data sheet

I would set the gpio pins to input by setting register 0 = 0xff, 1= 0xff, then if you wanted pullups Set register 0x0C = 0xff, and 0x0D = 0xff. then read from 0x12 and 0x13.

Chuck.

Thanks!!!

I got it to work by using the MCP23017 library.

#include <Adafruit_MCP23017.h>
#include <String.h>
Adafruit_MCP23017 mcp1;
Adafruit_MCP23017 mcp2;
Adafruit_MCP23017 mcp3;


// pins 15~17 to GND, I2C bus address is 0x20
#include "Wire.h"
//Definiation
#define addr1 0 //addr 1=A2 low, A1 low, A0 low = "000"
#define addr2 1 //addr 2 = A2 low, A1 low, A0 high = "001"
#define addr3 2 //addr 3= A2 low ,  A1 high, A0 low=  "010" 

const byte GPIOA = 0x12; //Register address of port A
const byte GPIOB = 0x13; //Register address of port B

int arry[100];

long Absolute_value = 0;
long Board_Num = 0;

byte inputs=0;
void setup()
{
 mcp1.begin(addr1);
 mcp2.begin(addr2);
 mcp3.begin(addr3);
 
 mcp1.pinMode(0, INPUT);
 mcp1.pinMode(1, INPUT);
 mcp1.pinMode(2, INPUT);
 mcp1.pinMode(3, INPUT);
 mcp1.pinMode(4, INPUT);
 mcp1.pinMode(5, INPUT);
 mcp1.pinMode(6, INPUT);
 mcp1.pinMode(7, INPUT);
 mcp1.pinMode(8, INPUT);
 mcp1.pinMode(9, INPUT);
 mcp1.pinMode(10, INPUT);
 mcp1.pinMode(11, INPUT);
 mcp1.pinMode(12, INPUT);
 mcp1.pinMode(13, INPUT);
 mcp1.pinMode(14, INPUT);
 mcp1.pinMode(15, INPUT);
 
 mcp2.pinMode(0, INPUT);
 mcp2.pinMode(1, INPUT);
 mcp2.pinMode(2, INPUT);
 mcp2.pinMode(3, INPUT);
 mcp2.pinMode(4, INPUT);
 mcp2.pinMode(5, INPUT);
 mcp2.pinMode(6, INPUT);
 mcp2.pinMode(7, INPUT);
 mcp2.pinMode(8, INPUT);
 mcp2.pinMode(9, INPUT);
 mcp2.pinMode(10, INPUT);
 mcp2.pinMode(11, INPUT);
 mcp2.pinMode(12, INPUT);
 mcp2.pinMode(13, INPUT);
 mcp2.pinMode(14, INPUT);
 mcp2.pinMode(15, INPUT);
 
 mcp3.pinMode(0, INPUT);
 mcp3.pinMode(1, INPUT);
 mcp3.pinMode(2, INPUT);
 mcp3.pinMode(3, INPUT);
 mcp3.pinMode(4, INPUT);
 mcp3.pinMode(5, INPUT);
 mcp3.pinMode(6, INPUT);
 mcp3.pinMode(7, INPUT);
 mcp3.pinMode(8, INPUT);
 mcp3.pinMode(9, INPUT);
 mcp3.pinMode(10, INPUT);
 mcp3.pinMode(11, INPUT);
 mcp3.pinMode(12, INPUT);
 mcp3.pinMode(13, INPUT);
 mcp3.pinMode(14, INPUT);
 mcp3.pinMode(15, INPUT);

 
 Serial.begin(9600);
 
// Wire.begin(); // wake up I2C bus
}
    void source (int pin) //Sourcing function in the class, this needs works to get working 
  {
    //pin = 0;
    mcp1.pinMode (0, OUTPUT);
    mcp1.digitalWrite (0, HIGH);
delay (1000);
  }
void loop()
{

  //Serial.print("hello");
  for (int i = 0; i<16; i++)
  {
      arry[i] = mcp1.digitalRead(i);
  
  }
  for (int i = 0; i<16; i++)
  {
      arry[i+15] = mcp2.digitalRead(i);
  
  }
  
  for (int i = 0; i<16; i++)
  {
      arry[i+31] = mcp3.digitalRead(i);
  
  }

  for (int i = 0; i<100; i++)
  {
   Serial.print (i);
   Serial.print(":");
   Serial.println (arry[i]);
   
  }
  delay(200);

  for (int i = 0; i<100; i++)
  {
    if(arry[i] == 1)
    {
      Absolute_value = (Board_Num*160) + i + 1;
     // Serial.print ("Absolute_value");
      //Serial.print (":");
      //Serial.println(Absolute_value, DEC);
    }
  }
  Serial.print ("Absolute_value");
  Serial.print (":");
  Serial.println(Absolute_value, DEC);
  Absolute_value = 0;
  
  
  
};

One thing that i cannot figure out, is how to use MCP23017 in a class. I tried to make a class, so i didn’t have to do all these definitions, and so i could switch input and output on command. Unfortunately, the class doesn’t work. In fact, i don’t get anything over the serial port, like the coded “hello”, or “goodbye”. Any idea what is going on?

#include <Adafruit_MCP23017.h>
#include <String.h>
Adafruit_MCP23017 mcp1;
Adafruit_MCP23017 mcp2;
Adafruit_MCP23017 mcp3;

 
#include "Wire.h"
//Definiation
#define addr1 0 //addr 1=A2 low, A1 low, A0 low = "000"
#define addr2 1 //addr 2 = A2 low, A1 low, A0 high = "001"
#define addr3 2 //addr 3= A2 low ,  A1 high, A0 low=  "010" 

int lower_pin_bound = 0; //lower bound for set of digital pins being read, on GPIO of MCP23017
int upper_pin_bound = 15; //upper bound for set of digital pins being read




const byte GPIOA = 0x12; //Register address of port A
const byte GPIOB = 0x13; //Register address of port B

byte inputs=0;




//**************************************************  class process logic  **********************************************************************     ********************************************//




bool arry[100];

class processLogic
{
   int myPin;     //class object, myPin, will be used to process a particular integer pin number
   bool myState;  //class object, myState, will be used to store the digital reading of myPin, as a true/false, high/low
   
   //constructor
   public:
   processLogic( int pin)
  {
    myPin = pin;           //assigned passed integer, "pin", to class object "myPin"
    mcp1.pinMode(myPin, INPUT); //setting the pinMode of class object, "myPin" as a input. This feature can be changed throughout the code. 
    //pinMode (myPin, OUTPUT);
    
    myState = false;       //iniatlizing class object, "myState", as a false 
  }

  bool scan(int myPin)    //declaring class function "scan" which will scan the pin number passed to the class, read as "myPin"
  {
    mcp1.begin(addr1);
    mcp1.pinMode(myPin, INPUT);
    myState = mcp1.digitalRead(myPin);//assigned the "myState" to hold the memory of the read pin
    return myState;
  }

  void detect(int pin)  //class function "detect" which will compared the stored value of the read pin, "myState". if it is true, it will report. 
  {
    myPin = pin;
    myState = this->scan(pin); //this calls the function "scan", in the class that is local the "detect"
    if (myState == true)
    {
      arry[pin] = true;  //Writing the the master section of the array, denoted by [0][pin]
    }
    else
    {
      arry[pin] = false; //Writing the the master section of the array, denoted by [0][pin]
    }
  }
  
  void source (int pin) //Sourcing function in the class, this needs works to get working 
  {
    myPin = pin;
    pinMode (myPin, OUTPUT);
    digitalWrite (myPin, HIGH);

  }
};

processLogic myLogic(0); //delcaring a class member, myLogic
void setup()
{
 Serial.begin(9600);

 mcp2.begin(addr2);
 mcp3.begin(addr3);
 

 
// Wire.begin(); // wake up I2C bus
}
void loop()
{ 
  Serial.println("hello");
  
  for(int i = lower_pin_bound; i < upper_pin_bound; i++) //this while looper will cycle through the lower and upper pins, scanning and reporting the state of each pin, printing across the serial communication port. 
  {
    myLogic.detect(i); //"myLogic" is a declared object of class "processLogic", which then is calls class function "detect", passing it integer "i". detect will call scan inside of itself. 
  }
  Serial.print("goodbye");
  for (int j = 0; j < 100; j++)
  { 
      Serial.print(j);
      Serial.print(" : ");
      Serial.println(arry[j]);
  }
  
  if(mcp1.digitalRead(0) == HIGH)
  {
   Serial.print ("1");
   Serial.print(":");
   Serial.println ("HIGH");
   //delay(1000);
  }
  delay(200);

  if(mcp2.digitalRead(0) == HIGH)
  {
   Serial.print ("2");
   Serial.print(":");
   Serial.println ("HIGH");
   //delay(1000);
  }
  delay(200);
  
if (mcp3.digitalRead(0) == HIGH)
{
  Serial.print ("3");
   Serial.print(":");
   Serial.println ("HIGH");

  
}
   delay(200);
 
}