Trending

Increase I/O pins of Arduino/ESP8266 –MCP23017

Introduction-

A port expander is an IC that can increase I/O ports on your Arduino/ESP8266.
I/O expanders sometimes have more current output per pin than Arduino/ESP8266.

MCP23017

A 28 pin DIP IC.  Its 16-bit serial expander (In simple words 16 I/O port expander). It uses I2C Communication.

I2C Basics

A communication protocol in which only 2 wire is used. Up to 128 devices can be connected through 2 pins unless their addresses are different.

Communication  Steps

  1. A data packet is sent from a microprocessor to all devices connected to i2c port.
  2. Data packet contains address of the desired slave device.
  3. Each slave compares address received to its own address , if matches, replies ACK (acknowledge) bit.
  4. Then sending and receiving of data proceeds.


Wiring and Circuit

mcp1mcp2

MCP is divided into two parts PORT A (GPA Pins) and Port B (GPB Pins)

Note-

For ESP8266 you have to connect a 4.7K resistor between pin SDA and 3.3v (or VCC).
In above circuit, you can connect LEDs (in series with a resistor if required ) to “GP” pins only.
Addressing – Address of MCP23017 will change according to the connection of A0 A1 A2 pins on MCP.

Coding

Without External/Additional Library

It is a difficult task to control this IC without a library . So we will be talking about basics not real coding in Arduino IDE.
To set port A (i.e GPA ports) to output
Wire.beginTransmission(0x20);  //This line will begin transmission at address 0x20. This is the address of MCP23017 according to ciruit.
Wire.write(0x00); // IODIRA register
Wire.write(0x00); // set entire PORT A to output
Wire.endTransmission();   //This will end transmission 

Then to set port B to outputs, we use
Wire.beginTransmission(0x20); // MCP address
Wire.write(0x01); // IODIRB register
Wire.write(0x00); // set entire PORT B to output
Wire.endTransmission();

To control Port A , this will be in void loop()
Wire.beginTransmission(0x20);
Wire.write(0x12); // address port A
Wire.write(X);  // value to send
Wire.endTransmission();

To control Port B , this will be also in void loop()
Wire.beginTransmission(0x20);
Wire.write(0x13); // address PORT B
Wire.write(X);  // value to send
Wire.endTransmission();
Here X is a byte of data which will tell MCP to turn on or off specific pins. Each bit of data (i.e 0 or 1) will specify state of pin . Each place of bit corresponds to pin number.
For example to set pin 0 – high, 1-high, 2-High and all low , we have to send 11100000 which translates to  224 in decimal. So X = 224.
To use Port B as Input
Wire.beginTransmission(0x20);
Wire.write(0x13); // address PORT B
Wire.endTransmission();
Wire.requestFrom(0x20, 1); // request one byte of data
byte input=Wire.read(); // store incoming byte into "input"
This is how MCP23017 works , a Library seems really necessary here, so we have.

With Library

Install Adafruit MCP23017 Library from inside Arduino IDE. Click here to know how to install Library.
The code below is self-explanatory.

#include <Wire.h> // Wire.h
#include <Adafruit_MCP23017.h>

Adafruit_MCP23017 mcp;

void setup() {
mcp.begin();      // use default address 0
mcp.pinMode(1, OUTPUT); //This is pin GPA0,so pin 2 will be GPA1, pin 7 will be GPA7, pin 8 will be GPB0 
mcp.pinMode(0, INPUT);
mcp.pullUp(0, HIGH);  // turn on a 100K pullup internally
pinMode(13, OUTPUT);  // use the Arduino internal LED as debugging
}

void loop() { 
digitalWrite(13, mcp.digitalRead(0)); // The LED will 'echo' the button
//Blinking on GPA0
mcp.digitalWrite(1,HIGH); 
delay(1000);
mcp.digitalWrite(1,LOW);
delay(1000);
}

No comments