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.

BQ27441-G1: Initial CheckSum out-of-range, Design Capacity not changing since CheckSum not changing

Part Number: BQ27441-G1

Tool/software:

Hi,

I'm currently designing to implement the BQ27441 to monitor a portable battery (MLP523450) using a ESP32-C6-WROOM1 for the I2C communication. All code for this is within Arduino IDE and using the ESP32 SDK provided. In summary, this battery has a total capacity of 1000mAh (0x03e8 in hex) and the problem I'm encountering is that the default design capacity is not changing to what i need it to be. Below I provided all the code I have to implement the design capacity change following the flowchart provided in Figure 1 of "Quickstart Guide for bq27441-G1" along with the Serial Terminal Logs of the code coming from the ESP32. Please let me know if either I'm sending the data wrong, or I'm doing my CheckSum Calculation wrong.

Code (It was not letting me send the code as a block like the Serial Terminal Logs): 

```

#include <Wire.h>

#define SDA_PIN 21 // Default SDA pin for ESP32
#define SCL_PIN 22 // Default SCL pin for ESP32
#define DEVICE_ADDRESS 0x55 // Your I2C device address
void writeByte(uint8_t reg, uint8_t data) {
Wire.beginTransmission(DEVICE_ADDRESS);
Wire.write(reg);
Wire.write(data);
Wire.endTransmission();
}

uint8_t readByte(uint8_t reg) {
Wire.beginTransmission(DEVICE_ADDRESS);
Wire.write(reg);
Wire.endTransmission(false); // Restart condition
Wire.requestFrom(DEVICE_ADDRESS, 1);
return Wire.available() ? Wire.read() : 0xFF; // Return 0xFF if no data
}

void writeWord(uint8_t reg, uint16_t data) {
Wire.beginTransmission(DEVICE_ADDRESS);
Wire.write(reg);
Wire.write(data & 0xFF); // LSB
Wire.write((data >> 8) & 0xFF); // MSB
//Serial.println(); Serial.printf("The Following Word Was Written to reg (0x%02x): \nLSB: %02x \n",reg, data & 0xFF); Serial.printf("MSB: %02x \n", (data >> 8) & 0xFF);
Wire.endTransmission();
}

uint16_t readWord(uint8_t reg) {
Wire.beginTransmission(DEVICE_ADDRESS);
Wire.write(reg);
Wire.endTransmission(false);
Wire.requestFrom(DEVICE_ADDRESS, 2);
if (Wire.available() < 2) return 0xFFFF; // Error value
uint8_t lsb = Wire.read();
uint8_t msb = Wire.read();
return (msb << 8) | lsb;
}

void reading_registers(uint8_t reg){
Serial.printf("(LSB) for reg 0x%02X: 0x%02X\n", reg, readByte(reg));
Serial.printf("(MSB) for reg 0x%02X: 0x%02X\n", reg + 0x01, readByte(reg + 0x01));
}

void Debug_OldStuff(uint8_t reg, String name){
Serial.printf("%s (%02x) MSB: ", name.c_str(), reg);
Serial.println(readByte(reg), HEX);
Serial.printf("%s (%02x) LSB: ", name.c_str(), reg + 0x1);
Serial.println(readByte(reg + 0x01), HEX);
}

void setup() {
// Start serial communication
Serial.begin(115200);
// Start I2C communication
Wire.end();
delay(1000);
Wire.begin(SDA_PIN, SCL_PIN, 100000);

delay(1000); // Delay to ensure the device has settled


// Unseal device by sending the appropriate keys to control(0x00 and 0x01), sends (0x8000) command
writeByte(0x00, 0x00);
writeByte(0x01, 0x80);
writeByte(0x00, 0x00);
writeByte(0x01, 0x80);

Serial.printf("Register 0x00 before entering CFGUPDATE: %02x \n", readWord(0x00));

uint8_t flags_register_before_CFGUPDATE = readByte(0x06);
Serial.print("Flags Register Before Entering CFGUPDATE (reg: 0x06): "); Serial.print(flags_register_before_CFGUPDATE, BIN); Serial.printf(" (In Hex: %02x)\n", flags_register_before_CFGUPDATE);

writeWord(0x00, 0x0013);
delay(1000);
Serial.printf("Register 0x00 after entering CFGUPDATE: %02x \n", readWord(0x00));

uint8_t flags_register_old = readByte(0x06);
Serial.print("Flags Register Before Entering CFGUPDATE (reg: 0x06): "); Serial.print(flags_register_old, BIN); Serial.printf(" (In Hex: %02x)\n", flags_register_old);

// Write 0x00 to 0x61 to enable block data memory control
writeByte(0x61, 0x00);
Serial.println("Wrote 0x00 to 0x61");
Serial.printf("Register 0x61: %02x \n", readByte(0x61));

// Write 0x52 to 0x3E to access the state subclass containing the design capacity parameter
writeByte(0x3E, 0x52);
Serial.println("Wrote 0x52 to 0x3E");
Serial.printf("Register 0x3E: %02x \n", readByte(0x3E));

// Write 0x00 to 0x3F to access the first block offset
writeByte(0x3F, 0x00);
Serial.println("Wrote 0x00 to 0x3F");
Serial.printf("Register 0x3F: %02x \n", readByte(0x3F));

// Read checksum
uint8_t checksum_old = readByte(0x60);
Serial.print("Checksum: ");
Serial.println(checksum_old, HEX);
Serial.println();

// Read both design capacity bytes starting at 0x4A (offset = 10)
uint8_t old_des_cap_msb = readByte(0x4A);
uint8_t old_des_cap_lsb = readByte(0x4B);
Debug_OldStuff(0x4A, "Old Design Capacity");

// Write new design capacity (1000mAh = 0x03E8)

writeByte(0x4A, 0x03);
writeByte(0x4B, 0xE8);
Debug_OldStuff(0x4A, "New Design Capacity");

// Read and print new design capacity registers
Serial.print("New Design Capacity: ");
Serial.println(readWord(0x4A), HEX);

// Read and write design energy (0x4C, 0x4D)
uint8_t old_des_en_msb = readByte(0x4C);
uint8_t old_des_en_lsb = readByte(0x4D);
Debug_OldStuff(0x4C, "Old Design Energy");

writeByte(0x4C, 0x0E);
writeByte(0x4D, 0x74);
delay(100);
Debug_OldStuff(0x4C, "New Design Energy");
Serial.print("New Design Energy: ");
Serial.println(readWord(0x4C), HEX);

// Read and write terminate voltage (0x50, 0x51)
uint8_t old_termVolt_msb = readByte(0x50);
uint8_t old_termVolt_lsb = readByte(0x51);
Debug_OldStuff(0x50, "Old Terminal Voltage");

writeByte(0x50, 0x0B);
writeByte(0x51, 0xB8);
delay(100);
Debug_OldStuff(0x50, "New Terminal Voltage");
Serial.print("New Terminal Voltage: ");
Serial.println(readWord(0x50), HEX);

// Read and write taper rate (0x5B, 0x5C)
uint8_t old_taperRate_msb = readByte(0x5B);
uint8_t old_taperRate_lsb = readByte(0x5C);
Debug_OldStuff(0x5B, "Old Taper Rate");

writeByte(0x5B, 0x00);
writeByte(0x5C, 0xC8);

delay(100);
Debug_OldStuff(0x5B, "New Taper Rate");
Serial.print("New Taper Rate: ");
Serial.println(readWord(0x5B), HEX);
Serial.println();

// Compute new checksum (simple placeholder calculation)
uint8_t temp = (0xFF - checksum_old - old_des_cap_msb - old_des_cap_lsb - old_des_en_msb - old_des_en_lsb - old_termVolt_msb - old_termVolt_lsb - old_taperRate_msb - old_taperRate_lsb) % 256;
uint8_t checksum_new = 0XFF - ((temp + 0x03 + 0xE8 + 0x0E + 0x74 + 0xB + 0xB8 + 0xC8) % 256);

Serial.printf("Checksum Variables debug: checksumold 0x%02X; temp1: 0x%02X; temp2: 0x%02X; checksumnew: 0x%02X\n", checksum_old, temp, checksum_new + 0xFF, checksum_new);
delay(1000);
Serial.print("New checksum: ");
Serial.println(checksum_new, HEX);
// Write new checksum to 0x60
writeByte(0x60, checksum_new);
delay(1000);

Serial.print("Wrote new checksum to 0x60: ");
Serial.println(readByte(0x60), HEX);

// Exit CFGUPDATE mode by sending SOFT_RESET subcommand (0x0042)
// writeWord(0x00, 0x0041); // Force DF update
//delay(100);
writeWord(0x00, 0x0043); // Exit_CFGUPDATE
writeWord(0x00, 0x0042); // Soft reset
delay(1000);

uint8_t flags_register_new = readByte(0x06);
Serial.print("Flags Register 0x06: "); Serial.print(flags_register_new, BIN); Serial.printf(" (In Hex: %02x)\n", flags_register_new);

while ((flags_register_new & 0x10) == 1){
writeWord(0x00, 0x0042); // Soft reset
delay(100);
uint8_t flags_register_new = readByte(0x06);
Serial.print("TRYING TO CHANGE CFGUPDATE TO 0 (2b10001000) 0x06: "); Serial.print(flags_register_new, BIN); Serial.printf(" (In Hex: %02x)\n", flags_register_new);
}
// Return to sealed mode by sending Control(0x0020) subcommand
writeWord(0x00, 0x0020);
Serial.println("Wrote 0x0020 to 0x00");
Serial.println();

Serial.println("Design capacity registers:");
reading_registers(0x3c);
Serial.println("Voltage registers:");
reading_registers(0x04);
Serial.println("State of charge registers:");
reading_registers(0x1c);

Serial.println("Configuration Complete!\n\n\n\n");
delay(10000);
}

void loop() {
// Main loop, do nothing here.
}

```
Serial Terminal Logs:

Register 0x00 before entering CFGUPDATE: 00 
Flags Register Before Entering CFGUPDATE (reg: 0x06): 10001000 (In Hex: 88)
Register 0x00 after entering CFGUPDATE: 00 
Flags Register Before Entering CFGUPDATE (reg: 0x06): 10011000 (In Hex: 98)
Wrote 0x00 to 0x61
Register 0x61: 00 
Wrote 0x52 to 0x3E
Register 0x3E: 52 
Wrote 0x00 to 0x3F
Register 0x3F: 00 
Checksum: 2C

Old Design Capacity (4a) MSB: 5
Old Design Capacity (4b) LSB: 3C
New Design Capacity (4a) MSB: 3
New Design Capacity (4b) LSB: E8
New Design Capacity: E803
Old Design Energy (4c) MSB: 13
Old Design Energy (4d) LSB: 60
New Design Energy (4c) MSB: E
New Design Energy (4d) LSB: 74
New Design Energy: 740E
Old Terminal Voltage (50) MSB: C
Old Terminal Voltage (51) LSB: 80
New Terminal Voltage (50) MSB: B
New Terminal Voltage (51) LSB: B8
New Terminal Voltage: B80B
Old Taper Rate (5b) MSB: 0
Old Taper Rate (5c) LSB: 64
New Taper Rate (5b) MSB: 0
New Taper Rate (5c) LSB: C8
New Taper Rate: C800

Checksum Variables debug: checksumold 0x2C; temp1: 0x2F; temp2: 0x1D7; checksumnew: 0xD8
New checksum: D8
Wrote new checksum to 0x60: 2C
Flags Register 0x06: 10001000 (In Hex: 88)
Wrote 0x0020 to 0x00

Design capacity registers:
(LSB) for reg 0x3C: 0x3C
(MSB) for reg 0x3D: 0x05
Voltage registers:
(LSB) for reg 0x04: 0xF9
(MSB) for reg 0x05: 0x0F
State of charge registers:
(LSB) for reg 0x1C: 0x5F
(MSB) for reg 0x1D: 0x00
Configuration Complete!