Page 2 of 2

Re: I²C clock problem

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

Re: I²C clock problem

Posted: Mon Jan 28, 2019 9:30 am
by persan666
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 10604 times
DFS turned off and without power locks.
DFS off 100KHz.png
DFS off 100KHz.png (102.56 KiB) Viewed 10604 times

Re: I²C clock problem

Posted: Mon Jan 28, 2019 11:20 am
by persan666
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 10599 times

Re: I²C clock problem

Posted: Mon Jan 28, 2019 11:09 pm
by mrrosen
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

Re: I²C clock problem

Posted: Tue Jan 29, 2019 8:10 am
by persan666


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 10574 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 10574 times

Re: I²C clock problem

Posted: Tue Feb 05, 2019 6:01 pm
by dragondgold
@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.

Re: I²C clock problem

Posted: Wed Feb 13, 2019 11:48 am
by persan666
@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.

Re: I²C clock problem

Posted: Wed Feb 13, 2019 7:26 pm
by gunar.kroeger
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.

Re: I²C clock problem

Posted: Wed Feb 13, 2019 7:44 pm
by dragondgold
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.