-->
Page 1 of 1

Simple i2c example - MCP23017

PostPosted: Sat Nov 29, 2014 6:29 pm
by sancho
I connected MCP23017 to the ESP8266 and used the i2c functions.
The code uses the port A on MCP, sets the port to output and sends values from 0 to 255.
Thanks to gerardwr for pointing out the reset problem - if the for-loop is running too long, the watchdog kicks in and reboots the whole ESP.
Here is the code for steps from 0 to 255:
Code: Select all    id=0
    sda=8
    scl=9

    -- initialize i2c, set pin1 as sda, set pin0 as scl
    i2c.setup(id,sda,scl,i2c.SLOW)

    -- user defined function: read from reg_addr content of dev_addr
    function read_reg(dev_addr, reg_addr)
      i2c.start(id)
      i2c.address(id, dev_addr ,i2c.TRANSMITTER)
      i2c.write(id,reg_addr)
      i2c.stop(id)
      i2c.start(id)
      i2c.address(id, dev_addr,i2c.RECEIVER)
      c=i2c.read(id,1)
      i2c.stop(id)
      return c
    end

    function write_reg(dev_addr, reg_addr, reg_val)
      i2c.start(id)
      i2c.address(id, dev_addr, i2c.TRANSMITTER)
      i2c.write(id, reg_addr)
      i2c.write(id, reg_val)
      i2c.stop(id)
    end

    -- get content of register 0xAA of device 0x77
    write_reg(0x20, 0x00, 0x00) -- set bank A to output

    for i=0,255 do
      print("Setting bank A to value " .. i)
      write_reg(0x20, 0x12, i)
      tmr.delay(100000)
      tmr.wdclr()
    end


Just for fun, I made a small K.I.T.T. animation using timer function - fair warning, you will have to reset the device to get out of the loop ;)
Code: Select all    id=0
    sda=8
    scl=9

    -- initialize i2c, set pin1 as sda, set pin0 as scl
    i2c.setup(id,sda,scl,i2c.SLOW)

    -- user defined function: read from reg_addr content of dev_addr
    function read_reg(dev_addr, reg_addr)
      i2c.start(id)
      i2c.address(id, dev_addr ,i2c.TRANSMITTER)
      i2c.write(id,reg_addr)
      i2c.stop(id)
      i2c.start(id)
      i2c.address(id, dev_addr,i2c.RECEIVER)
      c=i2c.read(id,1)
      i2c.stop(id)
      return c
    end

    function write_reg(dev_addr, reg_addr, reg_val)
      i2c.start(id)
      i2c.address(id, dev_addr, i2c.TRANSMITTER)
      i2c.write(id, reg_addr)
      i2c.write(id, reg_val)
      i2c.stop(id)
    end

    -- get content of register 0xAA of device 0x77
    write_reg(0x20, 0x00, 0x00) -- set bank A to output
    i = 1
    dir = 1
    print("")

    tmr.alarm(250,1,function()
      write_reg(0x20, 0x12, i)
      print("I = " .. i)
      dir = (i == 1) and (dir == -1) and 1 or (i == 128) and (dir == 1) and -1 or dir
      i = (dir == 1) and i * 2 or i / 2
    end
    )


The electrical connection for MCP23017:
Pin 9 (VDD) to 3v3
Pin 10 (VSS) to GND
Pin 12 (SCL) to ESP GPIO2
Pin 13 (SDA) to ESP GPIO0
Pin 15 (A0) to GND
Pin 16 (A1) to GND
Pin 17 (A2) to GND
Pin 18 (nRESET) to 3v3

Enjoy!

Re: Simple i2c example - MCP23017

PostPosted: Sat Nov 29, 2014 6:59 pm
by gerardwr
Cool , next time a Youtube video 8-)

Re: Simple i2c example - MCP23017

PostPosted: Mon Dec 01, 2014 8:45 am
by martinayotte
I got my MCP23017 working too, attached on GPIO12 and GPIO13 of my ESP-03, using the modified code from https://github.com/zarya/esp8266_i2c_driver. Here are the modified defines :
Code: Select all#define I2C_SDA_MUX PERIPHS_IO_MUX_MTDI_U
#define I2C_SDA_FUNC FUNC_GPIO12
#define I2C_SDA_PIN 12

#define I2C_SCK_MUX PERIPHS_IO_MUX_MTCK_U
#define I2C_SCK_FUNC FUNC_GPIO13
#define I2C_SCK_PIN 13

Re: Simple i2c example - MCP23017

PostPosted: Tue Dec 02, 2014 7:00 pm
by hansaya
how can i use I2c with BH1750?

I have this code but it does not work

Code: Select all#include "ets_sys.h"
#include "os_type.h"
#include "osapi.h"
#include "c_types.h"

#include "user_interface.h"
#include "BH1750.h"
#include "i2c_master.h"

#define i2c_start i2c_master_start
#define i2c_writeByte i2c_master_writeByte
#define i2c_getAck i2c_master_getAck
//#define ets_printf os_printf
#define i2c_stop i2c_master_stop
#define ets_delay_us os_delay_us
#define i2c_readByte i2c_master_readByte
#define i2c_setAck i2c_master_setAck



///////////////////////////////////////////////////////////////
//BH1750
///////////////////////////////////////////////////////////////
int ICACHE_FLASH_ATTR
test_light_sensor()
{
    uint8 ack;
    uint8 dtmp1,dtmp2;
    uint16 res;
    int data;
    i2c_start();
    i2c_writeByte(0x46+0); // sensor address  + write bit
        if(i2c_getAck() )
        {
            os_printf("addr not ack r \n");
            i2c_stop();
            return;
        }
    i2c_writeByte(0x23); // config one time L-resolution mode
        if(i2c_getAck() )
        {
            os_printf("data not ack 1 \n");
            i2c_stop();
            return;
        }
    i2c_stop();
    ets_delay_us(30000);//  wait measure time, 24ms at most
    i2c_start();
    i2c_writeByte(0x46+0x1);//  sensor address + read bit
            if(i2c_getAck() )
        {
            os_printf("addr not ack w \n");
            i2c_stop();
            return;
        }
     dtmp1=i2c_readByte();//read MSB
     i2c_setAck(0);
     dtmp2=i2c_readByte();//read LSB
     i2c_setAck(1);           //NACK READY FOR STOP
     i2c_stop();
     res=( (dtmp1<<8)|dtmp2 );
     data=(res*10+6)/12;  //CAL VALUE
     os_printf("light sensor reg: 0x%x ;  val : %d [lx] \n\n",res,data);
    return data;

}