BQ7690x2 Arduino I2C Communication CRC Issue Fix (BQ7697202PFBR)

🔺 Issue Description

If you're using BQ7697202BMS AFE in your project you might face the problem when using any library.

Image

The answer if CRC, because it's enabled by default for this particular part number ( (BQ7697202PFBR )) for all commands, but typical library doesn't support it:

Image

I connected logic analyzer and here is how it looks when

Image
Image

When using library without CRC you will see incorrect data because second byte is CRC when it's enabled:

Image

🔧 Issue Fix

So, to fix this you can add CRC support for each command or change communication type to Fast I2C Mode (without CRC). I'll show the simplest way (second):

Image

The host can write the 0x29e7 SWAP_TO_I2C() subcommand to change the communications interface to I2C fast mode (Settings:Configuration:Comm Type = 8) immediately, without needing to enter CONFIG_UPDATE mode:

Image

Add this code before library initialization:

  1. /* Set I2C Fast Mode without CRC */
  2. Wire.beginTransmission(0x08); // Begin with the device I2C address
  3. Wire.write(0x3E); // Set the device's address pointer (ie 3E)
  4. Wire.write(0xE7); // Send LSB (0xE7) of command SWAP_TO_I2C() 0x29E7
  5. Wire.write(0x36); // crc8 of {0x10, 0x3E, 0xE7}
  6. Wire.write(0x29); // Send MSB (0x29) of command SWAP_TO_I2C() 0x29E7
  7. Wire.write(0xDF); // crc8 of {0x29}
  8. Wire.endTransmission(true); // End I2C transmit

Here how it should looks on logic analyzer:

Image

✔ Fixed

Now when reading cell's voltage and internal temperature values are correct:

Image

Note 1: when IC not powered it wouldn't be able to communicate.

Note 2: disabling CRC should be performed after AFE power connection.

🗓 Note about CRC

For calculation CRC for this IC you can you follow cpp function:

  1. uint8_t crc8(const uint8_t* data, size_t len, uint16_t key) {
  2. uint8_t crc = 0;
  3. for (size_t ptr = 0; ptr < len; ptr++) {
  4. for (int k = 0; k < 8; k++) {
  5. uint8_t i = 0x80 >> k; // bit mask: 128, 64, 32 &hellip; 1
  6. if (crc & 0x80) {
  7. crc = (crc << 1) ^ (uint8_t)key;
  8. } else {
  9. crc = crc << 1;
  10. }
  11. if (data[ptr] & i) {
  12. crc ^= (uint8_t)key;
  13. }
  14. }
  15. }
  16. return crc;
  17. }

Here is what you should get:

  1. const uint8_t testData[] = {0x10, 0x14, 0x11, 0x67};
  2. const uint16_t crcKey = 0x107; // CRC-8/SMBUS polynomial
  3.  
  4. uint8_t result = crc8(testData, sizeof(testData), crcKey);
  5.  
  6. Serial.printf("CRC8 check = 0x%02X\n", result);
  7.  
  8.  

Library

🟦 GitHub: https://github.com/fotherja/BQ76952/tree/main

💿 Source (copy): BQ76952-main_20260403.zip

Add changing AFTER reset function:

Image

685
No comments yet. Be the first to add a comment!
Cookies?