(solved) error when trying to use I2C

User avatar
mzimmers
Posts: 643
Joined: Wed Mar 07, 2018 11:54 pm
Location: USA

(solved) error when trying to use I2C

Postby mzimmers » Mon Nov 05, 2018 7:48 pm

Hi all -

We're experimenting with a fuel gauge that we'd connect via I2C. I'm trying to follow the docs, but my initial attempts are returning an error. Here's the code:

Code: Select all

const uint8_t FUEL_CELL_ADDR = 0x6c; // from MAX77818 data sheet.
const gpio_num_t GPIO_I2C_SDA = GPIO_NUM_18;
const gpio_num_t GPIO_I2C_SCL = GPIO_NUM_19;
const i2c_port_t I2C_PORT_NBR = I2C_NUM_0;
...
// i2cInit(): configures and installs the i2c driver.
void PowerMgr::i2cInit()
{
    m_i2c.mode = I2C_MODE_MASTER;
    m_i2c.sda_io_num = GPIO_I2C_SDA;
    m_i2c.sda_pullup_en = GPIO_PULLUP_DISABLE;
    m_i2c.scl_io_num = GPIO_I2C_SCL;
    m_i2c.scl_pullup_en = GPIO_PULLUP_DISABLE;
    m_i2c.master.clk_speed = CONFIG_I2C_MASTER_FREQUENCY;

    ESP_ERROR_CHECK(i2c_driver_install(I2C_PORT_NBR, I2C_MODE_MASTER, 16, 16, 0));
}

void PowerMgr::i2cWrite(uint8_t *buffOut, uint32_t len)
{
    esp_err_t err;
    // note about data (address) field: the ESP32 docs say to shift addresses one bit to the left,
    // but it appears that the addresses supplied in the MAX77818 data sheet already have been shifted.
    // keep this in mind when setting addresses from the datasheet.
    uint8_t data = (uint8_t) ((FUEL_CELL_ADDR) | I2C_MASTER_WRITE);

    m_i2c_cmd = i2c_cmd_link_create();
    ESP_ERROR_CHECK(i2c_master_start(m_i2c_cmd));
    ESP_ERROR_CHECK(i2c_master_write_byte(m_i2c_cmd, data, true));
    ESP_ERROR_CHECK(i2c_master_write(m_i2c_cmd, buffOut, len, true));
    ESP_ERROR_CHECK(i2c_master_stop(m_i2c_cmd));
    err = (i2c_master_cmd_begin(I2C_PORT_NBR, m_i2c_cmd, 1));
    if (err != ESP_OK)
    {
        ESP_LOGE(TAG, "i2cWrite(): error %x on i2c_master_cmd_begin.", err);
    }
    i2c_cmd_link_delete(m_i2c_cmd);
When I run, I get these errors:

Code: Select all

E (1765) i2c: C:/esp-idf/components/driver/i2c.c:537 (i2c_master_clear_bus):scl gpio number error
E (1765) PowerMgr: i2cWrite(): error 107 on i2c_master_cmd_begin.
Do I need to do something to those GPIO lines to properly initialize them before I call the code above? I don't really understand the error message, but I get the impression that it doesn't like my GPIO numbers.
Last edited by mzimmers on Wed Nov 07, 2018 3:03 pm, edited 1 time in total.

mikemoy
Posts: 599
Joined: Fri Jan 12, 2018 9:10 pm

Re: error when trying to use I2C

Postby mikemoy » Mon Nov 05, 2018 9:28 pm

I am using these pins for I2C.
#define I2C_EXAMPLE_MASTER_SCL_IO GPIO_NUM_5 // gpio number for I2C master clock
#define I2C_EXAMPLE_MASTER_SDA_IO GPIO_NUM_4 // gpio number for I2C master data

I also noticed that you init you have GPIO_PULLUP_DISABLE. Do you have external resistor pull-ups on both lines?


Here is my init.

Code: Select all

#define I2C_EXAMPLE_MASTER_SCL_IO          GPIO_NUM_5       // gpio number for I2C master clock
#define I2C_EXAMPLE_MASTER_SDA_IO          GPIO_NUM_4       // gpio number for I2C master data
#define I2C_EXAMPLE_MASTER_NUM             I2C_NUM_0        // I2C port number for master dev
#define I2C_EXAMPLE_MASTER_TX_BUF_DISABLE  0                // I2C master do not need buffer
#define I2C_EXAMPLE_MASTER_RX_BUF_DISABLE  0                // I2C master do not need buffer
#define I2C_EXAMPLE_MASTER_FREQ_HZ         100000           	// I2C master clock frequency 100000

bool initI2C(void)
{

    i2c_config_t conf;

    conf.mode = I2C_MODE_MASTER;
    conf.sda_io_num = I2C_EXAMPLE_MASTER_SDA_IO;
    conf.scl_io_num = I2C_EXAMPLE_MASTER_SCL_IO;
    conf.sda_pullup_en = GPIO_PULLUP_ENABLE;
    conf.scl_pullup_en = GPIO_PULLUP_ENABLE;
    conf.master.clk_speed = I2C_EXAMPLE_MASTER_FREQ_HZ;

    if (i2c_param_config(I2C_NUM_0, &conf) != ESP_OK)
    	return false;

    if (i2c_driver_install(I2C_NUM_0, I2C_MODE_MASTER, I2C_EXAMPLE_MASTER_RX_BUF_DISABLE, I2C_EXAMPLE_MASTER_TX_BUF_DISABLE, 0) != ESP_OK)
		return false;

    return true;
}
esp_err_t writeByte(uint8_t icAddress, uint8_t registerAddress, uint8_t writeValue)
{

	esp_err_t espRc;

    i2c_cmd_handle_t cmd = i2c_cmd_link_create();
    i2c_master_start(cmd);
    i2c_master_write_byte(cmd, (icAddress << 1) | I2C_MASTER_WRITE, ACK_CHECK_EN );
    i2c_master_write_byte(cmd, registerAddress, 1);
    i2c_master_write_byte(cmd, writeValue, 1);
    i2c_master_stop(cmd);

    espRc = i2c_master_cmd_begin(I2C_NUM_0, cmd, 10 / portTICK_RATE_MS);

    i2c_cmd_link_delete(cmd);

    return espRc;
}

User avatar
mzimmers
Posts: 643
Joined: Wed Mar 07, 2018 11:54 pm
Location: USA

Re: error when trying to use I2C

Postby mzimmers » Mon Nov 05, 2018 9:53 pm

Hi Mike - thanks for the code snippet. When I read it, I realized I'd missed a step in the docs, namely, the call to i2c_param_config(). I no longer get the error regarding a bad GPIO number. I still get an error 0x107, though, on my call to i2c_master_cmd_begin().

Not sure whether I should be enabling pullups or not; I'll check with my HW guy and report back. But I tried it both ways, with identical results.

mikemoy
Posts: 599
Joined: Fri Jan 12, 2018 9:10 pm

Re: error when trying to use I2C

Postby mikemoy » Mon Nov 05, 2018 10:06 pm

Just for giggles try increasing your ticks_to_wait, in i2c_master_cmd_begin. I think yous is way to short being a 1.
Having it larger does not hurt. For instance, even if you set it for 1 minute (a total exaggeration) it would still exit as soon as it got the response back.

https://docs.espressif.com/projects/esp ... TickType_t

User avatar
mzimmers
Posts: 643
Joined: Wed Mar 07, 2018 11:54 pm
Location: USA

Re: error when trying to use I2C

Postby mzimmers » Mon Nov 05, 2018 10:43 pm

I copied your writeByte() routine, figuring I'd have a better chance of success if I only tried to write one byte...same 0x107.

Code: Select all

esp_err_t PowerMgr::i2cWriteByte(uint8_t devAddr, uint8_t regAddr, uint8_t data)
{
    esp_err_t err;

    m_i2c_cmd = i2c_cmd_link_create();
    ESP_ERROR_CHECK(i2c_master_start(m_i2c_cmd));
    ESP_ERROR_CHECK(i2c_master_write_byte(m_i2c_cmd, (uint8_t) ((devAddr) | I2C_MASTER_WRITE), true));
    ESP_ERROR_CHECK(i2c_master_stop(m_i2c_cmd));
    err = (i2c_master_cmd_begin(I2C_PORT_NBR, m_i2c_cmd, 100));
    if (err != ESP_OK)
    {
        ESP_LOGE(TAG, "i2cWriteByte(): error %x on i2c_master_cmd_begin.", err);
    }
    i2c_cmd_link_delete(m_i2c_cmd);

    return err;
}
I should point out that the problem may legitimately be in the hardware, as our board is still in design. I just wanted to try to make sure my code was clean first.

BTW: this is what my final operation will look like (when I get it working):

Attachments
i2c.PNG
i2c.PNG (30.67 KiB) Viewed 18506 times

mikemoy
Posts: 599
Joined: Fri Jan 12, 2018 9:10 pm

Re: error when trying to use I2C

Postby mikemoy » Mon Nov 05, 2018 10:57 pm

I should point out that the problem may legitimately be in the hardware, as our board is still in design. I just wanted to try to make sure my code was clean first.
Gotcha, depending on how long that will take, maybe just hook up any I2C device from sparkfun / adafruit or amazon.

User avatar
mzimmers
Posts: 643
Joined: Wed Mar 07, 2018 11:54 pm
Location: USA

Re: error when trying to use I2C

Postby mzimmers » Mon Nov 05, 2018 11:48 pm

Shouldn't take too long, but I like your idea of having a different device available to test against. Do you have a recommendation for one that's relatively foolproof?

mikemoy
Posts: 599
Joined: Fri Jan 12, 2018 9:10 pm

Re: error when trying to use I2C

Postby mikemoy » Tue Nov 06, 2018 12:42 am

The best advise i can give when starting or using I2C on a new platform is use a I2C device that you can write to without having to read from. Reading is more difficult to debug on a new platform because you wont know if it's your writes or reads that are screwed up.
Most guys don't have a logic analyzer so they go at it in the blind and hope for the best :mrgreen:

I have my own boards that I built to test I2C on new platforms. But looking on the net for something I think this would be a good one to start with.
https://www.mikroe.com/led-driver-3-click

User avatar
fly135
Posts: 606
Joined: Wed Jan 03, 2018 8:33 pm
Location: Orlando, FL

Re: error when trying to use I2C

Postby fly135 » Tue Nov 06, 2018 3:36 am

mzimmers wrote:Shouldn't take too long, but I like your idea of having a different device available to test against. Do you have a recommendation for one that's relatively foolproof?
I recently bought one of these. It's an I2C device.

https://www.amazon.com/gp/product/B01N4 ... UTF8&psc=1

There is C code than can be downloaded, and I had no problem getting it to work. Or you can just read the chip id address to verify that it's responding to your I2C commands.

John A

User avatar
mzimmers
Posts: 643
Joined: Wed Mar 07, 2018 11:54 pm
Location: USA

Re: error when trying to use I2C

Postby mzimmers » Tue Nov 06, 2018 5:22 pm

Well, my HW guys have checked out the board and say it looks OK, so I'm inclined to think I'm doing something wrong.

Here's a code snippet of my attempt to implement the protocol described in the drawing in my above post.

Code: Select all

    m_i2c_cmd = i2c_cmd_link_create();
    ESP_ERROR_CHECK(i2c_master_start(m_i2c_cmd));
    ESP_ERROR_CHECK(i2c_master_write_byte(m_i2c_cmd, (uint8_t) ((devAddr) | I2C_MASTER_READ), true));
    ESP_ERROR_CHECK(i2c_master_write_byte(m_i2c_cmd, (uint8_t) regAddr, true));
    ESP_ERROR_CHECK(i2c_master_read(m_i2c_cmd, data, 2, I2C_MASTER_LAST_NACK))
    ESP_ERROR_CHECK(i2c_master_stop(m_i2c_cmd));
    err = (i2c_master_cmd_begin(I2C_PORT_NBR, m_i2c_cmd, 100));
Does anything jump out at you as wrong here?

Thanks.

Who is online

Users browsing this forum: Google [Bot] and 85 guests