--- -- @description Expands the ESP8266's GPIO to 8 more I/O pins via I2C with the MCP23008 I/O Expander -- MCP23008 Datasheet: http://ww1.microchip.com/downloads/en/DeviceDoc/21919e.pdf -- Tested on NodeMCU 0.9.5 build 20150213. -- @date March 02, 2015 -- @author Miguel -- GitHub: https://github.com/AllAboutEE -- YouTube: https://www.youtube.com/user/AllAboutEE -- Website: http://AllAboutEE.com -------------------------------------------------------------------------------- local moduleName = ... local M = {} _G[moduleName] = M -- Constant device address. local MCP23008_ADDRESS = 0x20 -- Registers' address as defined in the MCP23008's datashseet -- luacheck: push no unused 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 -- luacheck: pop -- 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 --- -- @name write -- @description Writes one byte to a register -- @param registerAddress The register where we'll write data -- @param data The data to write to the register -- @return void ---------------------------------------------------------- local function write(registerAddress, data) i2c.start(id) i2c.address(id,MCP23008_ADDRESS,i2c.TRANSMITTER) -- send MCP's address and write bit i2c.write(id,registerAddress) i2c.write(id,data) i2c.stop(id) end --- -- @name read -- @description Reads the value of a regsiter -- @param registerAddress The reigster address from which to read -- @return The byte stored in the register ---------------------------------------------------------- local function read(registerAddress) -- Tell the MCP which register you want to read from i2c.start(id) i2c.address(id,MCP23008_ADDRESS,i2c.TRANSMITTER) -- send MCP's address and write bit i2c.write(id,registerAddress) i2c.stop(id) i2c.start(id) -- Read the data form the register i2c.address(id,MCP23008_ADDRESS,i2c.RECEIVER) -- send the MCP's address and read bit local 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 it's int value end --- --! @name begin --! @description Sets the MCP23008 device address's last three bits. -- Note: The address is defined as binary 0100[A2][A1][A0] where -- A2, A1, and A0 are defined by the connection of the pins, -- e.g. if the pins are connected all to GND then the paramter address -- will need to be 0x0. -- @param address The 3 least significant bits (LSB) of the address -- @param pinSDA The pin to use for SDA -- @param pinSCL The pin to use for SCL -- @param speed The speed of the I2C signal -- @return void --------------------------------------------------------------------------- function M.begin(address,pinSDA,pinSCL,speed) MCP23008_ADDRESS = bit.bor(MCP23008_ADDRESS,address) i2c.setup(id,pinSDA,pinSCL,speed) end --- -- @name writeGPIO -- @description Writes a byte of data to the GPIO register -- @param dataByte The byte of data to write -- @return void ---------------------------------------------------------- function M.writeGPIO(dataByte) write(MCP23008_GPIO,dataByte) end --- -- @name readGPIO -- @description reads a byte of data from the GPIO register -- @return One byte of data ---------------------------------------------------------- function M.readGPIO() return read(MCP23008_GPIO) end --- -- @name writeIODIR -- @description Writes one byte of data to the IODIR register -- @param dataByte The byte of data to write -- @return void ---------------------------------------------------------- function M.writeIODIR(dataByte) write(MCP23008_IODIR,dataByte) end --- -- @name readIODIR -- @description Reads a byte from the IODIR register -- @return The byte of data in IODIR ---------------------------------------------------------- function M.readIODIR() return read(MCP23008_IODIR) end --- -- @name writeGPPU The byte to write to the GPPU -- @description Writes a byte of data to the -- PULL-UP RESISTOR CONFIGURATION (GPPU)REGISTER -- @param databyte the value to write to the GPPU register. -- each bit in this byte is assigned to an individual GPIO pin -- @return void ---------------------------------------------------------------- function M.writeGPPU(dataByte) write(MCP23008_GPPU,dataByte) end --- -- @name readGPPU -- @description Reads the GPPU (Pull-UP resistors register) byte -- @return The GPPU byte i.e. state of all internal pull-up resistors ------------------------------------------------------------------- function M.readGPPU() return read(MCP23008_GPPU) end return M