Expand Port Arduino
Expand Port Arduino
https://youtu.be/ie8f_QkAmbU
Would you like to expand the IOs of your ESP32, ESP8266, or Arduino? And have you thought about the
possibility of 16 new GPIOs that can be controlled using the I2C bus? Well today, I'm going to introduce you
to the GPIO expander MCP23016. Also, I’ll show you how to communicate a microcontroller with the
MCP23016. I’ll also talk about creating a program where we’ll use only 2 pins of this microcontroller to
communicate with the expander. We’ll use these for controlling the LEDs and the button.
Introduction
The MCP23016 device provides 16 bits for GPIO expansion using the I2C bus. Each bit can be configured
individually (input or output).
The MCP23016 consists of multiple 8-bit settings for input, output, and polarity selection.
The expanders provide a simple solution when the IOs are needed for switches, sensors, buttons, and
LEDs, among other examples.
Characteristics
16 Input / Output pins (16 input standard)
Fast I2C bus clock frequency (0-400 kbits/s)
Three hardware address pins allow the use of up to eight devices
Interrupt Port Capture Recorder
Polarity reversing register for setting the polarity of the input port data
Compatible with most microcontrollers
An example that shows the magnitude of this expander is its use with ESP01, which can be connected to
up to eight expanders with only two IOS, reaching 128 GPIOs.
MCP23016
Here, we have the schematic of the expander, which has two groups of eight bits. This makes for a total of
16 ports. In addition to an interrupt pin, it has the CLK pin, which connects the capacitor and the resistor, which
are internally connected in a logic port. This is to form the clock, using the idea of a crystal oscillator, which
needs 1MHz clock. The TP pin is used to measure the clock. Pins A0, A1, and A2 are binary addresses.
CLOCK
The MCP23016 therefore uses an external RC circuit to determine the speed of the internal Clock. An
internal clock of 1 MHz is required (usually) for the device to work properly. The internal clock can be measured
on the TP pin. The recommended values for REXT and CEXT are shown below.
Address
To define the address of the MCP23016, we then use pins A0, A1, and A2. Just leave them at HIGH or
LOW for the address change.
The address will be formed as follows:
For example:
A0> GND, A1> GND, A2> GND (means 000, then 20 + 0 = 20)
Or else,
A0> HIGH, A1> GND, A2> HIGH (meaning 101, then 20 + 5 = 25)
Commands
Below is a table with the commands for communication. Let's use GP0 and GP1, as well as IODIR0 and
IODIR1.
Categories:
GP0 / GP1 - Data Port Registers
There are two registers that provide access to the two GPIO ports.
The register reading provides the status of the pins on that port.
Bit = 1> HIGH Bit = 0> LOW
IODIR0 / IODIR1
There are two registers that control the pin mode. (Input or Output)
Bit = 1> INPUT Bit = 0> OUTPUT
INTCAP0 / INTCAP1 - Interrupt Capture Registers
These are registers that contain the value of the port that generated the interrupt.
I show here the Wire class, which is the I2C communication in our core Arduino, which also allows the
expander to work with the Arduino Uno and Mega. However, the latter already has several IOs. We deal here
with the addresses of the chip, the access control, which are the codes of the registers, as well as the data.
Program
Our program consists of communicating the ESP32 with the MCP23016 to have more GPIOs to use. We
will then have a button and some LEDs connected to the MCP23016. We will control all of them using only the
I2C bus. Thus, only two ESP32 pins will be used. You can see the picture circuit below in the video.
ESP01
In this example, we have the GPIO0 connected in the SDA, and the GPIO2 connected in the SCL. We also
have a relay board, a buzzer, and an LED. On the other port, in GP1.0, we have one more LED with a resistor.
NodeMCU ESP-12E
In this case, the only difference from the first example is that you have connected D1 and D2 in the SDA
and SCL, respectively.
This time, the main difference from the other two examples is the button, and the three blinking LEDs. Here,
the SDA is connected to the GPIO19, while the SCL is connected to the GPIO23.
Setup
Here we have the functions to initialize four different types of microcontrollers. We also check the frequency,
set up the GPIOs, and set the pins. In the Loop, we check the status of the button.
void setup() {
Serial.begin(9600);
delay(1000);
Wire.begin(19,23); //ESP32
// Wire.begin(D2,D1); //nodemcu ESP8266
// Wire.begin(); //arduino
// Wire.begin(0,2);//ESP-01
Wire.setClock(200000); //frequencia
void loop() {
//verifica e o botão GP foi pressionado
checkButton(GP1);
} // end loop
ConfigurePort
In this step, we configure the mode of the GPIO pins and identify the mode of the ports.
ESP8266 Program
From here, we will see how the program we used in ESP-01 and in the nodeMCU ESP-12E was created,
which allows us to understand how differences between them are minimal.
We will only modify the line of the i2c communication constructor, which is the beginning method of the
Wire object.
Just uncomment the line according to the plate that we are going to compile.
Setup
Notice that the builder is still commented out. Therefore, uncomment according to your board (ESP-01 or
nodeMCU ESP12-E).
void setup() {
Serial.begin(9600);
delay(1000);
// Wire.begin(D2,D1); //nodemcu ESP8266
// Wire.begin(0,2); //ESP-01
Wire.setClock(200000); //frequencia
Loop
In the loop, we switch the pins every 1 second. Thus, when pin0 of GP0 is on, the pins of GP1 are off.
When pin0 of GP1 is on, the GP0 pins are off.
void loop() {
//seta o pino 7 do GP0 como HIGH e os demais como LOW
writeBlockData(GP0, B10000000);
//seta todos os pinos do GPIO1 como LOW
writeBlockData(GP1, B00000000);
delay(1000);
} // end loop
IMPORTANT
The variables and library used are the same as those of the program we did for ESP32, as well as the
configurePort and writeBlockData methods.
Files
Download the files:
PDF
INO (ESP8266)
INO (ESP32)