I²C clock problem

mrrosen
Posts: 18
Joined: Tue Sep 26, 2017 12:53 am

Re: I²C clock problem

Postby mrrosen » Thu Jan 24, 2019 10:50 pm

Have you enabled Power Management? The DFS might be the cause of the issue as your i2c_master_read_slave doesnt include pm locks.

persan666
Posts: 28
Joined: Fri Feb 16, 2018 9:17 am

Re: I²C clock problem

Postby persan666 » Mon Jan 28, 2019 9:30 am

mrrosen wrote:
Thu Jan 24, 2019 10:50 pm
Have you enabled Power Management? The DFS might be the cause of the issue as your i2c_master_read_slave doesnt include pm locks.
Hi,

Thanks for your reply!

I have tried your suggestion, both using pm locks and disabled DFS in menuconfig:
The clock looks better now but it still behaves strange and do not communicate with the gauge IC with this frequency.

Code: Select all

  
void Initialize_pm_lock()
{
    esp_err_t ret;
    if((ret = esp_pm_lock_create(ESP_PM_APB_FREQ_MAX, 1, "CPU_FREQ_MAX", &pm_lock_handle)) != ESP_OK) {
        printf("pm config error %s\n", \
                ret == ESP_ERR_INVALID_ARG ? "ESP_ERR_INVALID_ARG" : \
                (ret == ESP_ERR_NOT_SUPPORTED ? "ESP_ERR_NOT_SUPPORTED" :\
                 "ESP_ERR_NO_MEM"));
    }
}
  
    
esp_err_t i2c_master_read_slave(i2c_port_t i2c_num, uint8_t slave_address, uint8_t registerAddress, uint8_t* data_rd, size_t size)
{
    i2c_cmd_handle_t cmd = i2c_cmd_link_create();
    i2c_master_start(cmd);

    i2c_master_write_byte(cmd, slave_address << 1 | I2C_MASTER_WRITE, I2C_ACK_CHECK_EN);
    i2c_master_write_byte(cmd, registerAddress, I2C_ACK_CHECK_EN);
    i2c_master_start(cmd);

    i2c_master_write_byte(cmd, slave_address << 1 | I2C_READ_BIT, I2C_ACK_CHECK_EN);
    if (size > 1) {
        i2c_master_read(cmd, data_rd, size - 1, I2C_ACK_VAL);
    }
    i2c_master_read_byte(cmd, data_rd + size - 1, I2C_NACK_VAL);
    i2c_master_stop(cmd);

    esp_pm_lock_acquire(pm_lock_handle);
    esp_err_t ret = i2c_master_cmd_begin(i2c_num, cmd, 100000 / portTICK_RATE_MS);
    esp_pm_lock_release(pm_lock_handle);
    
    i2c_cmd_link_delete(cmd);

    if(ret != ESP_OK)
    	ESP_LOGE(TAG, "i2c error: %s", esp_err_to_name(ret));

    return ret;
}
DFS turned on with power locks
DFS on with power locks 100KHz.png
DFS on with power locks 100KHz.png (91.29 KiB) Viewed 9885 times
DFS turned off and without power locks.
DFS off 100KHz.png
DFS off 100KHz.png (102.56 KiB) Viewed 9885 times

persan666
Posts: 28
Joined: Fri Feb 16, 2018 9:17 am

Re: I²C clock problem

Postby persan666 » Mon Jan 28, 2019 11:20 am

persan666 wrote:
Mon Jan 28, 2019 9:30 am
mrrosen wrote:
Thu Jan 24, 2019 10:50 pm
Have you enabled Power Management? The DFS might be the cause of the issue as your i2c_master_read_slave doesnt include pm locks.
Hi,

Thanks for your reply!

I have tried your suggestion, both using pm locks and disabled DFS in menuconfig:
The clock looks better now but it still behaves strange and do not communicate with the gauge IC with this frequency.

Code: Select all

  
void Initialize_pm_lock()
{
    esp_err_t ret;
    if((ret = esp_pm_lock_create(ESP_PM_APB_FREQ_MAX, 1, "CPU_FREQ_MAX", &pm_lock_handle)) != ESP_OK) {
        printf("pm config error %s\n", \
                ret == ESP_ERR_INVALID_ARG ? "ESP_ERR_INVALID_ARG" : \
                (ret == ESP_ERR_NOT_SUPPORTED ? "ESP_ERR_NOT_SUPPORTED" :\
                 "ESP_ERR_NO_MEM"));
    }
}
  
    
esp_err_t i2c_master_read_slave(i2c_port_t i2c_num, uint8_t slave_address, uint8_t registerAddress, uint8_t* data_rd, size_t size)
{
    i2c_cmd_handle_t cmd = i2c_cmd_link_create();
    i2c_master_start(cmd);

    i2c_master_write_byte(cmd, slave_address << 1 | I2C_MASTER_WRITE, I2C_ACK_CHECK_EN);
    i2c_master_write_byte(cmd, registerAddress, I2C_ACK_CHECK_EN);
    i2c_master_start(cmd);

    i2c_master_write_byte(cmd, slave_address << 1 | I2C_READ_BIT, I2C_ACK_CHECK_EN);
    if (size > 1) {
        i2c_master_read(cmd, data_rd, size - 1, I2C_ACK_VAL);
    }
    i2c_master_read_byte(cmd, data_rd + size - 1, I2C_NACK_VAL);
    i2c_master_stop(cmd);

    esp_pm_lock_acquire(pm_lock_handle);
    esp_err_t ret = i2c_master_cmd_begin(i2c_num, cmd, 100000 / portTICK_RATE_MS);
    esp_pm_lock_release(pm_lock_handle);
    
    i2c_cmd_link_delete(cmd);

    if(ret != ESP_OK)
    	ESP_LOGE(TAG, "i2c error: %s", esp_err_to_name(ret));

    return ret;
}
DFS turned on with power locks
DFS on with power locks 100KHz.png
DFS turned off and without power locks.
DFS off 100KHz.png
The last recordings where made using the modefied i2c_master_clear_bus function. Here is a recording using the orginal master branch:
Org master i2c_master_clear_bus DFS on with power locks 100KHz.png
Org master i2c_master_clear_bus DFS on with power locks 100KHz.png (73.47 KiB) Viewed 9880 times

mrrosen
Posts: 18
Joined: Tue Sep 26, 2017 12:53 am

Re: I²C clock problem

Postby mrrosen » Mon Jan 28, 2019 11:09 pm

persan666 wrote:
Mon Jan 28, 2019 11:20 am
persan666 wrote:
Mon Jan 28, 2019 9:30 am
mrrosen wrote:
Thu Jan 24, 2019 10:50 pm
Have you enabled Power Management? The DFS might be the cause of the issue as your i2c_master_read_slave doesnt include pm locks.
Hi,

Thanks for your reply!

I have tried your suggestion, both using pm locks and disabled DFS in menuconfig:
The clock looks better now but it still behaves strange and do not communicate with the gauge IC with this frequency.

Code: Select all

  
void Initialize_pm_lock()
{
    esp_err_t ret;
    if((ret = esp_pm_lock_create(ESP_PM_APB_FREQ_MAX, 1, "CPU_FREQ_MAX", &pm_lock_handle)) != ESP_OK) {
        printf("pm config error %s\n", \
                ret == ESP_ERR_INVALID_ARG ? "ESP_ERR_INVALID_ARG" : \
                (ret == ESP_ERR_NOT_SUPPORTED ? "ESP_ERR_NOT_SUPPORTED" :\
                 "ESP_ERR_NO_MEM"));
    }
}
  
    
esp_err_t i2c_master_read_slave(i2c_port_t i2c_num, uint8_t slave_address, uint8_t registerAddress, uint8_t* data_rd, size_t size)
{
    i2c_cmd_handle_t cmd = i2c_cmd_link_create();
    i2c_master_start(cmd);

    i2c_master_write_byte(cmd, slave_address << 1 | I2C_MASTER_WRITE, I2C_ACK_CHECK_EN);
    i2c_master_write_byte(cmd, registerAddress, I2C_ACK_CHECK_EN);
    i2c_master_start(cmd);

    i2c_master_write_byte(cmd, slave_address << 1 | I2C_READ_BIT, I2C_ACK_CHECK_EN);
    if (size > 1) {
        i2c_master_read(cmd, data_rd, size - 1, I2C_ACK_VAL);
    }
    i2c_master_read_byte(cmd, data_rd + size - 1, I2C_NACK_VAL);
    i2c_master_stop(cmd);

    esp_pm_lock_acquire(pm_lock_handle);
    esp_err_t ret = i2c_master_cmd_begin(i2c_num, cmd, 100000 / portTICK_RATE_MS);
    esp_pm_lock_release(pm_lock_handle);
    
    i2c_cmd_link_delete(cmd);

    if(ret != ESP_OK)
    	ESP_LOGE(TAG, "i2c error: %s", esp_err_to_name(ret));

    return ret;
}
DFS turned on with power locks
DFS on with power locks 100KHz.png
DFS turned off and without power locks.
DFS off 100KHz.png
The last recordings where made using the modefied i2c_master_clear_bus function. Here is a recording using the orginal master branch:
Org master i2c_master_clear_bus DFS on with power locks 100KHz.png
If you disabled DFS, you dont need the locks but Ive found DFS saves quite a bit of power, so its best to leave it on in the future (the PM lock should prevent further scl-messing-up-ness when DFS is turned on). I cant tell without a bit more information on the actual timing of your I2C transaction, but it looks like youre encountering the same issue I had talking to a BQ27621 (another TI battery monitor from the BQ35100 you are using). You should try adding this to right after you initialize I2C master:

Code: Select all

#define I2C_MASTER_TRANSACTION_TIMEOUT_MS  (10)
...
i2c_set_timeout(I2C_MASTER_PORT, I2C_APB_CLK_FREQ * I2C_MASTER_TRANSACTION_TIMEOUT_MS / 1000)
Details can be found here:
https://www.esp32.com/viewtopic.php?f=13&t=6203#p37174

persan666
Posts: 28
Joined: Fri Feb 16, 2018 9:17 am

Re: I²C clock problem

Postby persan666 » Tue Jan 29, 2019 8:10 am

mrrosen wrote:
Mon Jan 28, 2019 11:09 pm
persan666 wrote:
Mon Jan 28, 2019 11:20 am
persan666 wrote:
Mon Jan 28, 2019 9:30 am


Hi,

Thanks for your reply!

I have tried your suggestion, both using pm locks and disabled DFS in menuconfig:
The clock looks better now but it still behaves strange and do not communicate with the gauge IC with this frequency.

Code: Select all

  
void Initialize_pm_lock()
{
    esp_err_t ret;
    if((ret = esp_pm_lock_create(ESP_PM_APB_FREQ_MAX, 1, "CPU_FREQ_MAX", &pm_lock_handle)) != ESP_OK) {
        printf("pm config error %s\n", \
                ret == ESP_ERR_INVALID_ARG ? "ESP_ERR_INVALID_ARG" : \
                (ret == ESP_ERR_NOT_SUPPORTED ? "ESP_ERR_NOT_SUPPORTED" :\
                 "ESP_ERR_NO_MEM"));
    }
}
  
    
esp_err_t i2c_master_read_slave(i2c_port_t i2c_num, uint8_t slave_address, uint8_t registerAddress, uint8_t* data_rd, size_t size)
{
    i2c_cmd_handle_t cmd = i2c_cmd_link_create();
    i2c_master_start(cmd);

    i2c_master_write_byte(cmd, slave_address << 1 | I2C_MASTER_WRITE, I2C_ACK_CHECK_EN);
    i2c_master_write_byte(cmd, registerAddress, I2C_ACK_CHECK_EN);
    i2c_master_start(cmd);

    i2c_master_write_byte(cmd, slave_address << 1 | I2C_READ_BIT, I2C_ACK_CHECK_EN);
    if (size > 1) {
        i2c_master_read(cmd, data_rd, size - 1, I2C_ACK_VAL);
    }
    i2c_master_read_byte(cmd, data_rd + size - 1, I2C_NACK_VAL);
    i2c_master_stop(cmd);

    esp_pm_lock_acquire(pm_lock_handle);
    esp_err_t ret = i2c_master_cmd_begin(i2c_num, cmd, 100000 / portTICK_RATE_MS);
    esp_pm_lock_release(pm_lock_handle);
    
    i2c_cmd_link_delete(cmd);

    if(ret != ESP_OK)
    	ESP_LOGE(TAG, "i2c error: %s", esp_err_to_name(ret));

    return ret;
}
DFS turned on with power locks
DFS on with power locks 100KHz.png
DFS turned off and without power locks.
DFS off 100KHz.png
The last recordings where made using the modefied i2c_master_clear_bus function. Here is a recording using the orginal master branch:
Org master i2c_master_clear_bus DFS on with power locks 100KHz.png
If you disabled DFS, you dont need the locks but Ive found DFS saves quite a bit of power, so its best to leave it on in the future (the PM lock should prevent further scl-messing-up-ness when DFS is turned on). I cant tell without a bit more information on the actual timing of your I2C transaction, but it looks like youre encountering the same issue I had talking to a BQ27621 (another TI battery monitor from the BQ35100 you are using). You should try adding this to right after you initialize I2C master:

Code: Select all

#define I2C_MASTER_TRANSACTION_TIMEOUT_MS  (10)
...
i2c_set_timeout(I2C_MASTER_PORT, I2C_APB_CLK_FREQ * I2C_MASTER_TRANSACTION_TIMEOUT_MS / 1000)
Details can be found here:
https://www.esp32.com/viewtopic.php?f=13&t=6203#p37174
Thank you for your reply!

I almost thought this would be the right medicine for the problem but no there are still problems. I have included recordings with different frequencies and one can see where it goes wrong. I have done test using 10, 100, 400 Khz and only 10KHz works both with version 3.2 and master. I feel that I am close to a solution now but there is still something that is not quite rigth.
This is the 100KHz recording where it goes wrong.
3.2 DFS on with power locks 100KHz.png
3.2 DFS on with power locks 100KHz.png (78.43 KiB) Viewed 9855 times
This is a recording with 10KHz that works.
3.2 DFS on with power locks 10KHz.png
3.2 DFS on with power locks 10KHz.png (92.39 KiB) Viewed 9855 times

dragondgold
Posts: 6
Joined: Thu Jan 31, 2019 2:53 pm

Re: I²C clock problem

Postby dragondgold » Tue Feb 05, 2019 6:01 pm

@persan666 did you find any solution to the problem? I'm using a bq27441 fuel gauge and I'm experiencing the exact same problem, DFS is disabled and I increased the timeout time, I have no errors, just inconsistent clock when using 400 kHz.

persan666
Posts: 28
Joined: Fri Feb 16, 2018 9:17 am

Re: I²C clock problem

Postby persan666 » Wed Feb 13, 2019 11:48 am

dragondgold wrote:
Tue Feb 05, 2019 6:01 pm
@persan666 did you find any solution to the problem? I'm using a bq27441 fuel gauge and I'm experiencing the exact same problem, DFS is disabled and I increased the timeout time, I have no errors, just inconsistent clock when using 400 kHz.
Hi dragondgold,

Unfortunately I haven't found a solution yet. It seems that the problem is still that the timeout time is too short sometimes. It do gets better if I increase the timeout time but it is not enough when running 100KHz I2c and 240MHz CPU. It works with 50KHz. The recording above shows the timeout at the end.

If you find something, please let me know.

User avatar
gunar.kroeger
Posts: 143
Joined: Fri Jul 27, 2018 6:48 pm

Re: I²C clock problem

Postby gunar.kroeger » Wed Feb 13, 2019 7:26 pm

We are also getting all sorts of issues when i2c is set to a clock higher than 10kHz trying to communicate with a GPS module... had to change back to uart, but still looking for a solution.
"Running was invented in 1612 by Thomas Running when he tried to walk twice at the same time."

dragondgold
Posts: 6
Joined: Thu Jan 31, 2019 2:53 pm

Re: I²C clock problem

Postby dragondgold » Wed Feb 13, 2019 7:44 pm

I managed to get my bq27441 working with I2C at 400 kHz. As noted in the datasheet to get this working with speeds higher than 100 kHz there's some special sequence needed:

Image

I started experiencing this problem after having my I2C bus working at 400 kHz and then added the bq27441 fuel gauge and started experiencing these issues. After rewriting my driver to take this into account I managed to get it working at 400 kHz with 4 devices attached to the bus and 10k resistors as pull-up. So I guess the problem is mainly due to the fuel gauge and not the I2C driver? At least in my case.

Who is online

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