Copyright ©

Mongoose OS Forum

ATTENTION! This forum has moved to:

Do not post any new messages.

ESP32 and I2C

It seems every now and then I run into issues with I2c.
However, the problem I have now is that I ported my application to esp32. I configured my mos.yml file to use gpio 0 and 2 for I2c. This works fine on the esp8266 module, but is not working on esp32.
I don't see the pins toggling. There is no activity on the I2c lines.

Any thoughts?


  • It appears that there is a difference between the I2C low level driver on the ESP8266, and the ESP32.

    I have a BMP180 module which I interface with via I2C. It communicates perfectly with the ESP8266 module. However when interfaced with the ESP32 module, the I2C bus hangs, with the SDA line being held low. The master is not able to release the bus with a stop command.

    Has anyone run into this problem?

  • The Master is not able to send a NACK after reading the last byte from the slave device.

  • jocodejocode US
    edited July 2017
    Try using GPIO 21 & 22. Has success using I2C to communicate with LIS3DH accelerometer and ESP32. If you want share code, let me know where in GutHub.
  • The issues I'm having are similar to what is captured here:

    My question is this:
    How do I know which driver mongoose-os uses for the i2c routine. Does it use the routines defined in "esp32_i2c_master.c" or "mgos_i2c_gpio.c". Both files have the same functions "mgos_i2c_read", so I'm not sure how we select which driver is used by mongoose.

    Any help is welcome.

  • rojerrojer Dublin, Ireland

    implementation is selected with MGOS_ENABLE_I2C_GPIO build_var. it is false on esp32, true on esp8266. try setting


    in mos.yml

    yes, hardware I2C on esp32 is problematic. i spent a lot of time debugging it, but it's still wonky. might be a good idea to just ditch it and use bit-banging.

  • @rojer for ESP32, in mos.yml, used this settings:

    - ["i2c.enable", true]
    - ["i2c.sda_gpio", 21]
    - ["i2c.scl_gpio", 22]

    I2C seems to be working.

    Do I need to enable build_vars: MGOS_ENABLE_I2C_GPIO? What does it do?

  • So after 4 days of beating my head against the wall, I finally got some where with this issue.
    My I2C configuration is as follow:

      # Enable I2C
      - ["i2c.enable", "b", true, {title: "Enable I2C"}]
      - ["i2c.freq", "i", 100000, {title: "I2C bus speed"}]
      - ["i2c.unit_no", "i", 0, {title: "Which hardware unit ot use, 0 or 1"}]
      - ["i2c.sda_gpio", "i", 2, {title: "GPIO to use for SDA"}]
      - ["i2c.scl_gpio", "i", 0, {title: "GPIO to use for SCL"}]

    with MGOS_ENABLE_I2C_GPIO set to "0", this means that the mos will use the driver in the "src" folder, as opposed to the driver in the "common/gpio" folder. In other words, the driver does not bit-bang the I2C SDA/SCL lines when MGOS_ENABLE_I2C_GPIO is set to "0".

    Some I2C slave devices, like the BMP180 which I'm using require the I2C master to send a NACK when reading out the last byte. The non bit-banging version of the mgos I2C driver does not send a NACK when the last byte is read out of a slave device. This causes the device to lock up the I2C mode. Calling mgos_i2c_stop does not fix the issue. Also, I bit-banged the I2C SCL line to unlock the bus, however, this did not restore communication with the BMP180. This problem does not exist with the bit-banged version of the I2C driver, which the ESP8266 uses. This is why my code works on the ESP8266, but not the ESP32.

    So, I decided to modify my code to use the ESP-IDF I2C drivers which will allow me to send a NACK signal when reading the last byte from the device.
    See discussion more discussion on this issue here

    To use the bit-banged version of the mgos I2C driver, I have to set MGOS_ENABLE_I2C_GPIO to "1". Whenever I do this my application crashes. I can't move my I2C SDA/SCL pins to other GPIOs because my board is already built. So I don't know if the bit banged version of the driver would solve the problem, though I suspect it would, since the same code works for my ESP8266 module.

    For example, my i2c read function looks like this:

    bool i2c_master_read_slave(uint8_t dev_addr, uint8_t reg_addr, uint8_t* data_rd, size_t size)
        /* Code per ESP-IDF */
        size_t rxlen = size;
        bool value;
        bool ACK_CHECK_EN = true;
        bool ACK_VAL = true;
        bool NACK_VAL = true;
        i2c_master_write_slave(dev_addr, reg_addr, data_rd, 0);
        i2c_cmd_handle_t cmd = i2c_cmd_link_create();
        value = i2c_master_write_byte(cmd, dev_addr << 1 | I2C_MASTER_READ, ACK_CHECK_EN);
        if(rxlen > 1) {
            value |= i2c_master_read(cmd, data_rd, rxlen-1, ACK_VAL);
        value |= i2c_master_read_byte(cmd, data_rd + rxlen-1, NACK_VAL);
        value |= i2c_master_stop(cmd);
        value |= i2c_master_cmd_begin(1, cmd, 1000);
        LOG(LL_DEBUG, ("addr: 0x%x, size: %d\n", dev_addr, size));
        return value;
  • rojerrojer Dublin, Ireland

    @only1chi well, congratulations - you re-discovered :)
    we don't send the nack because ESP32's I2C is just wretched, here is the place where it should happen, but if i do it like that, all hell breaks loose.
    i spent untold amount of time trying to get it to work, and settled on doing HW but without nack. it still breaks down sometimes.
    i think i'll make bitbang the default, HW I2C seems unsalvageable at this point. it's sad that espressif won't even acknowledge the bug.

    that said, bitbang does work on ESP32, i just verified. you don't need to move the pins or even change the configuration, bitbang driver uses the same i2c.sda_gpio and i2c.scl_gpio keys to configure the pins. after changing the setting, do a clean rebuild (mos build --clean).

  • rojerrojer Dublin, Ireland
    edited July 2017

    actually, bitbang I2C is the default on ESP32, and has been since Jun 5 (6c48405), so unless you actively enabled it, or using a pretty old clone of mOS, you should be good.

  • @rojer I did return to the i2c bit bang driver. Apparently in order to use this, I shouldn't try to configure the frequency.
    I got communications working with BMP180 with the bit bang driver.

    Thanks for the pointer.

Sign In or Register to comment.