This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

BQ40Z50-R2: SMBus communication problem with command 0x44 ManufacturerBlockAccess()

Part Number: BQ40Z50-R2
Other Parts Discussed in Thread: BQ40Z50

Hi,

I`m using an ESP32-Wrover-E to send/receive data to/from BQ40Z50-R2.

I`m able to read all data stored in flash from all registers (I`m using FULL ACCESS mode as security mode).

For instance, as it can be seen it below, I`m setting a two bytes register using the CMD 0x00, and just after reading its value using the command 0x44. The reading values are correct.

       

The problem is that when I try to write some value at the same register (0x438C Cell 3 Min Voltage) , it doesn`t work. As you can see, there is no ACK when I try to send the 0x44 command:

BUT the weird thing is that when I use the 0x44 command to read any register (after setting it by using CMD 0x00 - the first picture shows this), the command receives an ACK and works fine!!!!

Thanks in advance!!!!

  • Hi Samir,

    Is this issue just happening with just the 0x438C address or can you not write to any of the other addresses?

    If possible, can you please share the code that you are using to write to the address to look over?

    For future reference, the Lifetime parameters such as Cell 3 Min Voltage should not be altered other than if they are reset after an issue. The Lifetime parameters are used for the gauge to keep measurements over time to be referred to if an issue occurs.

    Regards,

    Anthony Baldino

  • Hi Anthony,

    Thanks for the reply.

    Is this issue just happening with just the 0x438C address or can you not write to any of the other addresses?

    I can`t write in any of the other addresses  using 0x44 command. For example, I`ve tried to write on 0x48B8 (LED Blink Period) but the same "error" has happened.

    I wonder if it is possible to use the command 0x00 for writing on addresses.

    If possible, can you please share the code that you are using to write to the address to look over?

    uint32_t BQ40Z50_set_Cellmin(){
    uint32_t result = 0;
        uint8_t datav[2];
        bq40z50_reg_ManufactBlock data_;
        memset(&datav, 0, sizeof(datav));  
        memset(&data_, 0, sizeof(data_));
        data_.command_general[0]=0x8C;
        data_.command_general[1]=0x43;
        datav[0]=0x8C;
        datav[1]=0x43;
        datav[2]=0x80;
        datav[3]=0x3E;
        result = i2c_write_two_bytes(BQ40R50_I2C_ADDR,0x00,&(data_.command_general[0]));
        result |= i2c_write_block_DataFlash(BQ40R50_I2C_ADDR,&datav,sizeof(datav));

       
        return result;
    }

    esp_err_t i2c_write_two_bytes(uint8_t device_addr, uint8_t reg_addr, uint8_t *data)
    {
       
        i2c_cmd_handle_t cmd = i2c_cmd_link_create();
        i2c_master_start(cmd);
        i2c_master_write_byte(cmd, (device_addr << 1) | I2C_MASTER_WRITE, ACK_CHECK_EN);
        i2c_master_write_byte(cmd, reg_addr, ACK_CHECK_EN);
        i2c_master_write_byte(cmd, data[0], ACK_CHECK_EN);
        i2c_master_write_byte(cmd, data[1], ACK_CHECK_EN);
        i2c_master_stop(cmd);
        esp_err_t ret = i2c_master_cmd_begin(I2C_MASTER_NUM, cmd, 1000 / portTICK_PERIOD_MS);
        i2c_cmd_link_delete(cmd);
        return ret;
    }

    esp_err_t i2c_write_block_DataFlash(uint8_t device_addr, uint8_t *data,  uint8_t data_Size )
    {
        i2c_cmd_handle_t cmd = i2c_cmd_link_create();
        i2c_master_start(cmd);
        i2c_master_write_byte(cmd, (device_addr << 1) | I2C_MASTER_WRITE, ACK_CHECK_EN);
        i2c_master_write_byte(cmd, 0x44, ACK_CHECK_EN);
        i2c_master_write_byte(cmd, data_Size,ACK_CHECK_EN);
        for (int i=0;i<data_Size;i++){
            i2c_master_write_byte(cmd, data[i], ACK_CHECK_EN);
        }
        //PEC byte
        i2c_master_write_byte(cmd,0x00,ACK_CHECK_EN);
        i2c_master_stop(cmd);
        esp_err_t ret = i2c_master_cmd_begin(I2C_MASTER_NUM, cmd, 1000 / portTICK_PERIOD_MS);
        i2c_cmd_link_delete(cmd);
        return ret;
    }

    For future reference, the Lifetime parameters such as Cell 3 Min Voltage should not be altered other than if they are reset after an issue. The Lifetime parameters are used for the gauge to keep measurements over time to be referred to if an issue occurs.

    Good to know. I just selected the Cell 3 Min Voltage randomly.

    Thanks for your help!

    Cheers

  • Hi Samir,

    I believe for the changing of the Data Flash Parameters, 0x44 should be used:

    Can you please confirm that the address is being sent here a 0x8C 0x43?

    Regards,

    Anthony Baldino

  • Hi Anthony,

    Thanks for the update.

    I've finally realized what was going on. In terms of SMBus communication (PHY level), the master needs to send a data frame exactly like this:

    0x0B+ write bit  |  0x44  | 0x0B+ write bit  | data size (number of bytes) | register address (from 0x4000 to 0x5FFF) | value to be stored in the register

    There is no need to send the PEC byte. The following capture sets 0x1111 to the register 0x4924.

    Cheers,

  • Hi Samir,

    Understood, that looks like it is following the correct process for the write. I'm glad you got it working!

    Regards,

    Anthony Baldino