I2C Repeated start

Amir_El
Posts: 17
Joined: Thu Nov 19, 2020 3:55 pm

I2C Repeated start

Postby Amir_El » Sun Nov 22, 2020 4:03 pm

Hi, i'm developing an i2c driver for the sensor Si7021, I noticed that the commands that have repeated start in its sequence give me a noncorrect response. i would like to be sure if the way I'm doing it is correct.

Image

function to read the register:

Code: Select all

void Reset_Si7021(void)
{
    uint8_t Stored_Value;
    esp_err_t Get_I2C_Response = ESP_OK;

    printf(" Reset fn. start");
    // Reading the User Reg.
    i2c_cmd_handle_t CMD = i2c_cmd_link_create();

    i2c_master_start(CMD);
    i2c_master_write_byte(CMD, (Si7021_ADDR << 1) | Write_Bit, Want_Ack);
    i2c_master_write_byte(CMD, 0xE7, Want_Ack);         // read user reg.
    i2c_master_start(CMD);
    i2c_master_write_byte(CMD, (Si7021_ADDR << 1) | Read_Bit, Want_Ack);
    Get_I2C_Response = i2c_master_read_byte(CMD, &Stored_Value, NACK_VAL);
    i2c_master_stop(CMD);
    i2c_master_cmd_begin(I2C_NUM_0, CMD, 1000 / portTICK_RATE_MS);
    i2c_cmd_link_delete(CMD);   
    
    if( Get_I2C_Response == ESP_OK)
    {
        printf("\nStored User Reg. Data: %X\n",Stored_Value);
    }

    else
    {
        printf("\nReset fn. Error\n");
    }
}
The Result that I get is that
Stored_Value = 18
, how ever when i move this function in another .h file the results
become
Stored_Value = 15


When I do this

Code: Select all

    
     i2c_master_read_byte(CMD, &Stored_Value, NACK_VAL);
    i2c_master_stop(CMD);
    Get_I2C_Response = i2c_master_cmd_begin(I2C_NUM_0, CMD, 1000 / portTICK_RATE_MS);
    i2c_cmd_link_delete(CMD);   
    
    if( Get_I2C_Response == ESP_OK)
    {
        printf("\nStored User Reg. Data: %X\n",Stored_Value);
    }

    else
    {
        printf("\nReset fn. Error\n");
    }
I get
Reset fn. Error

what could be the mistake I did in the code? ( I don't have a logic analyzer at the moment)

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

Re: I2C Repeated start

Postby mikemoy » Mon Nov 23, 2020 5:10 am

Have you had a look at the I2C examples?

https://github.com/espressif/esp-idf/tr ... herals/i2c

Amir_El
Posts: 17
Joined: Thu Nov 19, 2020 3:55 pm

Re: I2C Repeated start

Postby Amir_El » Mon Nov 23, 2020 7:38 am

honestly, I didn't, but I found the solution to the problem, when I checked the error, it was a "Timeout error", searching a little bit

I found that configuring the
timeout
with the function

Code: Select all

i2c_set_timeout()
solved the issue.



would you please explain the use of the "size" in the "Example" Code?

Code: Select all

          if (size > 1) {
                               i2c_master_read(cmd, data_rd, size - 1, ACK_VAL);
                            }	
                               i2c_master_read_byte(cmd, data_rd + size - 1, NACK_VAL);
  

tonykenny
Posts: 2
Joined: Sun Nov 29, 2020 2:07 pm

Re: I2C Repeated start

Postby tonykenny » Sun Nov 29, 2020 2:11 pm

I'm having similar issues, it's certainly a more complicated library than the Arduino 'Wire'.
The examples are actually difficult to follow, very complex scenarios and instead we'd benefit from a simple master write / slave read example.

Did you add any value to the timeout method call?

I've created this simple method and it appears to send the data via I2C that I can see on my scope, but, the receiving device MCP23018 isn't behaving as expected. I use the same address / register / data in another project using Wire and it works fine. Maybe there's a stop/ack bit being added somewhere. I'll try to get time to compare each of them on the scope.

Code: Select all

void writeI2c(uint8_t regaddr, int data)
{
    i2c_cmd_handle_t cmd = i2c_cmd_link_create();
    i2c_master_start(cmd);
    i2c_master_write_byte(cmd, (MCP_ADDRESS << 1) | WRITE_BIT, ACK_CHECK_EN);
    i2c_master_write_byte(cmd, regaddr, ACK_CHECK_EN);
    i2c_master_write_byte(cmd, data, ACK_CHECK_EN);
    i2c_master_stop(cmd);
    i2c_master_cmd_begin(I2C_MASTER_NUM, cmd, 1000 / portTICK_RATE_MS);
    i2c_cmd_link_delete(cmd);
}

tonykenny
Posts: 2
Joined: Sun Nov 29, 2020 2:07 pm

Re: I2C Repeated start

Postby tonykenny » Sun Nov 29, 2020 7:30 pm

I solved my problem with this by adding | WRITE_BIT to each of the write_byte calls. Not sure what it does exactly, I'm still quite new to C and I2C too :) I'll dig further to work out exactly what's happening, I'm not the type to just settle for 'it works' :)

Code: Select all

void writeI2c(uint8_t regaddr, int data)
{
    i2c_cmd_handle_t cmd = i2c_cmd_link_create();
    i2c_master_start(cmd);
    i2c_master_write_byte(cmd, (MCP_ADDRESS << 1) | WRITE_BIT, ACK_CHECK_EN);
    i2c_master_write_byte(cmd, regaddr | WRITE_BIT, ACK_CHECK_EN);
    i2c_master_write_byte(cmd, data | WRITE_BIT, ACK_CHECK_EN);
    i2c_master_stop(cmd);
    i2c_master_cmd_begin(I2C_MASTER_NUM, cmd, 1000 / portTICK_RATE_MS);
    i2c_cmd_link_delete(cmd);
}

Amir_El
Posts: 17
Joined: Thu Nov 19, 2020 3:55 pm

Re: I2C Repeated start

Postby Amir_El » Mon Nov 30, 2020 9:37 am

Hi tonykenny

As I'm running the ESP32 on 80Mhz, the Maximum timeout I used is =
1048575
.

For your code, I don't think adding a write bit solved your issue since :

Code: Select all

regaddr | WRITE_BIT
just means that you do a logical Or operation with the
WRITE_BIT value which = 0.


So probably you did something else in your code that fixed the issue.

Who is online

Users browsing this forum: ChatGPT-User, Semrush [Bot] and 5 guests