This Lua script demonstrates how to interface the MCP23008 GPIO expander with an ESP8266 NodeMCU board. The MCP23008 provides an easy way to expand the number of GPIO pins available for use, which can be particularly useful when working with microcontrollers like the ESP8266 that have limited GPIO pins.
Read more: ESP8266 NodeMCU Interface – MCP23008By using the I2C protocol, the ESP8266 communicates with the MCP23008 to control its GPIO pins. This script sets up the MCP23008, configures its GPIO pins as inputs or outputs, and demonstrates reading the state of input pins (buttons) and controlling the output pins (LEDs).
The script showcases how to initialize the MCP23008, set pin directions, configure pull-up resistors, and read/write GPIO states. Additionally, it periodically reads the state of input pins (buttons) and prints their status, providing a practical example of interfacing with external components using the MCP23008.
Overall, this script serves as a practical guide for implementing GPIO expansion with the MCP23008 on the ESP8266 NodeMCU platform.
Required
- Required NodeMCU Modules (Firmware) : GPIO Module, I2C Module, Node Module,
- Required Hardware and Software Tools are ESP8266 with Programmer (or) NodeMCU Dev Kit, MCP23008, LED,
- Required software tool is ESPlorer IDE Tool.
MCP23008 with LED Interface
`lua
----------------------------------------
-- https://www.aruneworld.com/embedded/espressif/esp32/esp32_nodemcu/
-- Tested By : Arun(20170212)
-- Example Name : AEW_MCP23008_LEDs.lua
----------------------------------------
-- Constant device address.
local MCP23008_ADDRESS = 0x20
-- Registers' address as defined in the MCP23008's datasheet
local MCP23008_IODIR = 0x00
local MCP23008_IPOL = 0x01
local MCP23008_GPINTEN = 0x02
local MCP23008_DEFVAL = 0x03
local MCP23008_INTCON = 0x04
local MCP23008_IOCON = 0x05
local MCP23008_GPPU = 0x06
local MCP23008_INTF = 0x07
local MCP23008_INTCAP = 0x08
local MCP23008_GPIO = 0x09
local MCP23008_OLAT = 0x0A
-- Default value for i2c communication
local id = 0
-- pin modes for I/O direction
M.INPUT = 1
M.OUTPUT = 0
-- pin states for I/O i.e. on/off
M.HIGH = 1
M.LOW = 0
-- Weak pull-up resistor state
M.ENABLE = 1
M.DISABLE = 0
-- Write function: Writes one byte to a register
local function write(registerAddress, data)
i2c.start(id)
i2c.address(id, MCP23008_ADDRESS, i2c.TRANSMITTER)
i2c.write(id, registerAddress)
i2c.write(id, data)
i2c.stop(id)
end
-- Read function: Reads the value of a register
local function read(registerAddress)
i2c.start(id)
i2c.address(id, MCP23008_ADDRESS, i2c.TRANSMITTER)
i2c.write(id, registerAddress)
i2c.stop(id)
i2c.start(id)
i2c.address(id, MCP23008_ADDRESS, i2c.RECEIVER)
local data = 0x00
data = i2c.read(id, 1) -- we expect only one byte of data
i2c.stop(id)
return string.byte(data) -- i2c.read returns a string so we convert to its int value
end
-- Begin function: Sets the MCP23008 device address's last three bits
function M.begin(address, pinSDA, pinSCL, speed)
MCP23008_ADDRESS = bit.bor(MCP23008_ADDRESS, address)
i2c.setup(id, pinSDA, pinSCL, speed)
end
-- Write GPIO function: Writes a byte of data to the GPIO register
function M.writeGPIO(dataByte)
write(MCP23008_GPIO, dataByte)
end
-- Read GPIO function: Reads a byte of data from the GPIO register
function M.readGPIO()
return read(MCP23008_GPIO)
end
-- Write IODIR function: Writes one byte of data to the IODIR register
function M.writeIODIR(dataByte)
write(MCP23008_IODIR, dataByte)
end
-- Read IODIR function: Reads a byte from the IODIR register
function M.readIODIR()
return read(MCP23008_IODIR)
end
-- Write GPPU function: Writes a byte of data to the GPPU register
function M.writeGPPU(dataByte)
write(MCP23008_GPPU, dataByte)
end
-- Read GPPU function: Reads the GPPU (Pull-UP resistors register) byte
function M.readGPPU()
return read(MCP23008_GPPU)
end
-- ESP-01 GPIO Mapping as per GPIO Table in https://github.com/nodemcu/nodemcu-firmware
local gpio0, gpio2 = 3, 4
-- Setup MCP23008
M.begin(0x0, gpio2, gpio0, i2c.SLOW)
M.writeIODIR(0x00) -- make all GPIO pins as outputs
M.writeGPIO(0x00) -- make all GPIO pins off/low
-- Count function: Reads the value from the GPIO register, increases the read value by 1,
-- and writes it back so the LEDs will display a binary count up to 255 or 0xFF in hex.
local function count()
local gpio = 0x00
gpio = mcp23008.readGPIO()
if gpio < 0xff then
mcp23008.writeGPIO(gpio + 1)
else
mcp23008.writeGPIO(0x00)
end
end
-- Run count() every 100ms
tmr.alarm(0,100,1,count)
Explanation
Section | Description for ESP8266 NodeMCU Interface MCP23008 |
---|---|
Header Comments | Contains information about the source, author, and example name. |
Constants | Defines constant values for the MCP23008’s device address and various register addresses. |
Global Variables | Initializes the id variable to represent the I2C interface index. |
Pin Modes and States | Defines constants for input and output modes, as well as pin states for I/O operations. |
Write and Read Functions | Functions to write data to and read data from MCP23008 registers via I2C communication. |
Initialization Function | Sets up the MCP23008 device address and initializes I2C communication. |
GPIO Control Functions | Functions to write to and read from the GPIO register of the MCP23008. |
I/O Direction Control Functions | Functions to control the input/output direction register (IODIR) of the MCP23008. |
Pull-Up Resistor Configuration Functions | Functions to control the pull-up resistor configuration register (GPPU) of the MCP23008. |
Main Setup | Maps GPIO pins for SDA and SCL, and initializes the MCP23008 with specific configurations. |
LED Counting Function | Reads the current value from the GPIO register, increments it by 1, and writes it back to create a binary count pattern on the LEDs. |
Timer Setup | Sets up a timer to execute the LED counting function (count ) every 100ms. |
MCP23008 with Buttons Interface
This Lua code sets up communication between an ESP8266 NodeMCU and an MCP23008 I/O expander via the I2C protocol. It defines functions to write and read from the MCP23008’s registers, as well as functions to control the GPIO pins and their states. Finally, it continuously monitors the state of the GPIO pins connected to buttons and prints the state every 2 seconds.
---------------------------------------- -- https://www.aruneworld.com/embedded/espressif/esp8266/esp8266_nodemcu/ -- Tested By : Arun(20170212) -- Example Name : AEW_MCP23008_Buttons.lua ---------------------------------------- -- Constant device address. local MCP23008_ADDRESS = 0x20 -- Registers' address as defined in the MCP23008's datasheet local MCP23008_IODIR = 0x00 local MCP23008_IPOL = 0x01 local MCP23008_GPINTEN = 0x02 local MCP23008_DEFVAL = 0x03 local MCP23008_INTCON = 0x04 local MCP23008_IOCON = 0x05 local MCP23008_GPPU = 0x06 local MCP23008_INTF = 0x07 local MCP23008_INTCAP = 0x08 local MCP23008_GPIO = 0x09 local MCP23008_OLAT = 0x0A -- Default value for i2c communication local id = 0 -- pin modes for I/O direction M.INPUT = 1 M.OUTPUT = 0 -- pin states for I/O i.e. on/off M.HIGH = 1 M.LOW = 0 -- Weak pull-up resistor state M.ENABLE = 1 M.DISABLE = 0 -- Write function: Writes one byte to a register local function write(registerAddress, data) i2c.start(id) i2c.address(id, MCP23008_ADDRESS, i2c.TRANSMITTER) i2c.write(id, registerAddress) i2c.write(id, data) i2c.stop(id) end -- Read function: Reads the value of a register local function read(registerAddress) i2c.start(id) i2c.address(id, MCP23008_ADDRESS, i2c.TRANSMITTER) i2c.write(id, registerAddress) i2c.stop(id) i2c.start(id) i2c.address(id, MCP23008_ADDRESS, i2c.RECEIVER) local data = i2c.read(id, 1) i2c.stop(id) return string.byte(data) end -- Begin function: Sets the MCP23008 device address's last three bits function M.begin(address, pinSDA, pinSCL, speed) MCP23008_ADDRESS = bit.bor(MCP23008_ADDRESS, address) i2c.setup(id, pinSDA, pinSCL, speed) end -- Write GPIO function: Writes a byte of data to the GPIO register function M.writeGPIO(dataByte) write(MCP23008_GPIO, dataByte) end -- Read GPIO function: Reads a byte of data from the GPIO register function M.readGPIO() return read(MCP23008_GPIO) end -- Write IODIR function: Writes one byte of data to the IODIR register function M.writeIODIR(dataByte) write(MCP23008_IODIR, dataByte) end -- Read IODIR function: Reads a byte from the IODIR register function M.readIODIR() return read(MCP23008_IODIR) end -- Write GPPU function: Writes a byte of data to the GPPU register function M.writeGPPU(dataByte) write(MCP23008_GPPU, dataByte) end -- Read GPPU function: Reads the GPPU (Pull-UP resistors register) byte function M.readGPPU() return read(MCP23008_GPPU) end -- ESP-01 GPIO Mapping as per GPIO Table in https://github.com/nodemcu/nodemcu-firmware local gpio0, gpio2 = 3, 4 -- Setup the MCP23008 M.begin(0x0, gpio2, gpio0, i2c.SLOW) M.writeIODIR(0xff) M.writeGPPU(0xff) -- Show buttons state function function showButtons() local gpio = M.readGPIO() for pin = 0, 7 do local pinState = bit.band(bit.rshift(gpio, pin), 0x1) if pinState == M.HIGH then pinState = "HIGH" else pinState = "LOW" end print("Pin " .. pin .. ": " .. pinState) end print("\r\n") end tmr.alarm(0, 2000, 1, showButtons) -- run showButtons() every 2 seconds
Explanation
Section | Description |
---|---|
Header Comments | Contains information about the source, author, and example name. |
Constants | Defines constant values for the MCP23008’s device address and various register addresses. |
Global Variables | Initializes the id variable to represent the I2C interface index. |
Pin Modes and States | Defines constants for input and output modes, as well as pin states for I/O operations. |
Write and Read Functions | Functions to write data to and read data from MCP23008 registers via I2C communication. |
Initialization Function | Sets up the MCP23008 device address and initializes I2C communication. |
GPIO Control Functions | Functions to write to and read from the GPIO register of the MCP23008. |
I/O Direction Control Functions | Functions to control the input/output direction register (IODIR) of the MCP23008. |
Pull-Up Resistor Configuration | Functions to control the pull-up resistor configuration register (GPPU) of the MCP23008. |
Main Setup | Maps GPIO pins for SDA and SCL, and initializes the MCP23008 with specific configurations. |
Show Buttons State Function | Reads the state of each GPIO pin (button), prints the state, and repeats every 2 seconds. |