The MCP23017 is a popular I/O expander IC that allows you to increase the number of I/O pins available to a microcontroller. In this code example, we’ll interface an MCP23017 with an ESP8266 NodeMCU board to control LEDs. The ESP8266 NodeMCU will communicate with the MCP23017 via the I2C protocol to toggle the LEDs connected to the MCP23017’s GPIO pins. This setup provides a straightforward way to expand the number of GPIO pins available for controlling external devices.
Read more: ESP8266 NodeMCU Interface – MCP23017Contents
MCP23017 with LED Interface
- Required NodeMCU Modules (Firmware): GPIO Module, I2C Module, Node Module,
- Required Hardware and Software Tools are ESP8266 with Programmer (or) NodeMCU Dev Kit, MCP23017, LED,
- The required software tool is the ESPlorer IDE Tool.
MCP23017 lua Module code
`lua
-- https://www.aruneworld.com/embedded/espressif/esp32/esp32_nodemcu/
-- Tested By : Arun(20170212)
-- Example Name : AEW_MCP23017_LEDs.lua
------------------------------------------------------------------------------------------
-- i2c setup
local id = 0 -- always 0
local pinSDA = 2 -- 1~12, IO index
local pinSCL = 1 -- 1~12, IO index
local speed = i2c.SLOW -- only i2c.SLOW supported
-- Rotate LEDs
Shift_1 = {1,2,4,8,16,32,64,128}
Shift_2 = {128,64,32,16,8,4,2,1}
-- CONSTANTS
local MCP23017_ADDRESS = 0x21 -- you can change this id, I used 0x21
-- MCP23017 registers (everything except direction defaults to 0)
local IODIRA = 0x00 -- I/O DIRECTION REGISTE (0 = output, 1 = input (Default))
local IODIRB = 0x01
local IPOLA = 0x02 -- INPUT POLARITY REGISTER (0 = normal, 1 = inverse)
local IPOLB = 0x03
--GPINTEN – INTERRUPT-ON-CHANGE PINS
local GPINTENA = 0x04 -- Interrupt on change (0 = disable, 1 = enable)
local GPINTENB = 0x05
local DEFVALA = 0x06 -- Default comparison for interrupt on change (interrupts on opposite)
local DEFVALB = 0x07
local INTCONA = 0x08 -- Interrupt control (0 = interrupt on change from previous, 1 = interrupt on change from DEFVAL)
local INTCONB = 0x09
local IOCON = 0x0A -- IO Configuration: bank/mirror/seqop/disslw/haen/odr/intpol/notimp
--IOCON = 0x0B -- same as = 0x0A
local GPPUA = 0x0C -- GPIO PULL-UP RESISTOR REGISTERull-up resistor (0 = disabled, 1 = enabled)
local GPPUB = 0x0D
local INFTFA = 0x0E -- Interrupt flag (read only): (0 = no interrupt, 1 = pin caused interrupt)
local INFTFB = 0x0F
local INTCAPA = 0x10 -- Interrupt capture (read only): value of GPIO at time of last interrupt
local INTCAPB = 0x11
local GPIOA = 0x12 -- Port value. Write to change, read to obtain value
local GPIOB = 0x13
local OLLATA = 0x14 -- Output latch. Write to latch output.
local OLLATB = 0x15
local chip1 = 0x20 -- MCP23017 is on I2C address = 0x20
local chip2 = 0x21 -- MCP23017 is on I2C address = 0x21
-- user-defined function: read from reg_addr content of dev_addr
function read_reg(MCP23017_ADDRESS, reg_addr)
i2c.start(id)
i2c.address(id, MCP23017_ADDRESS, i2c.TRANSMITTER)
i2c.write(id, reg_addr)
i2c.stop(id)
i2c.start(id)
i2c.address(id, MCP23017_ADDRESS, i2c.RECEIVER)
c = string.byte(i2c.read(id, 1))
i2c.stop(id)
return c
end
--write MCP23017 start
function write_reg(MCP23017_ADDRESS, reg_addr, reg_val)
i2c.start(id)
i2c.address(id, MCP23017_ADDRESS, i2c.TRANSMITTER)
i2c.write(id, reg_addr)
i2c.write(id, reg_val)
i2c.stop(id)
end
--write MCP23017 end
--MCP Initialize start
function init(MCP23017_ADDRESS)
write_reg(MCP23017_ADDRESS, IOCON, 0x60) -- BANK=0, MIRROR=1, SEQOP=1, DISSLW=0, HAEN=0, ODR=0, INTPO=0, bit0=nil
write_reg(MCP23017_ADDRESS, IODIRA, 0x00) -- Port A as Output
write_reg(MCP23017_ADDRESS, GPIOA, 0xFF) -- Set All port A pins High
end
--MCP Initialize end
-----------Main Program start------------------
i2c_speed = i2c.setup(id, pinSDA, pinSCL, speed) -- Initialize the I²C module.
if i2c_speed ~= nil then
print("i2c Speed : "..i2c_speed)
print("i2c init done")
else
print("i2c
Code Explanation
Section | Description for ESP8266 NodeMCU Interface MCP23017 |
---|---|
Introduction | This code demonstrates the interfacing of MCP23017 with the ESP8266 NodeMCU board using the I2C communication protocol. |
I2C Setup | Sets up the parameters for I2C communication, including the I2C ID, SDA and SCL pins, and speed. |
Constants | Defines constants for MCP23017 registers and addresses used in the code. |
User-Defined Functions | Includes functions to read and write data from/to MCP23017 registers. |
MCP Initialization | Initializes the MCP23017 by configuring its IOCON register and setting Port A as output with all pins high. |
Main Program | Initializes the I2C module, initializes the MCP23017, defines functions for LED blinking and shifting, and starts a timer to periodically shift the LEDs. |
Uses
This code example demonstrates the use of the MCP23017 I/O expander with an ESP8266 NodeMCU board. It showcases how to set up communication between the ESP8266 and the MCP23017 via the I2C protocol and how to control LEDs connected to the MCP23017’s GPIO pins.
Specifically, the code accomplishes the following tasks:
- Sets up the I2C communication between the ESP8266 NodeMCU and the MCP23017.
- Initializes the MCP23017 by configuring its registers.
- Implements functions to read from and write to the MCP23017 registers.
- Defines functions to control the LEDs connected to the MCP23017.
- Defines a main loop function to shift LEDs connected to the MCP23017 GPIO pins.
- Sets up a timer to execute the main loop function periodically.
Overall, this code serves as a practical example of how to interface an ESP8266 NodeMCU with an MCP23017 to expand the available GPIO pins for controlling external components such as LEDs.