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>
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!