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: Having trouble reading the Data Memory (first byte is always 64 decimal)

Part Number: BQ27441-G1

I'm trying to use the gauge (as part of the Sparkfun Battery Babysitter) to characterize salvaged 18650 cells. The basic data is coming back fine but when trying to read the R_a RAM resistance values [1] the first byte always comes back as the value 64 (decimal). As far as I can tell from check a few other data memory blocks the first byte for all of them is coming back as 64.

I'm using an Arduino to talk to the gauge over I2C and using the following code snippets to read and dump the data memory data

#define BQ27441_EXTENDED_OPCONFIG 0x3A // OpConfig()
#define BQ27441_EXTENDED_CAPACITY 0x3C // DesignCapacity()
#define BQ27441_EXTENDED_DATACLASS 0x3E // DataClass()
#define BQ27441_EXTENDED_DATABLOCK 0x3F // DataBlock()
#define BQ27441_EXTENDED_BLOCKDATA 0x40 // BlockData()
#define BQ27441_EXTENDED_CHECKSUM 0x60 // BlockDataCheckSum()
#define BQ27441_EXTENDED_CONTROL 0x61 // BlockDataControl()
#define BQ27441_ID_R_A_RAM 89 // R_a RAM

uint8_t data[32];
data[0] = 0x00;
lipo.i2cWriteBytes(BQ27441_EXTENDED_CONTROL, data , 1);
data[0] = BQ27441_ID_R_A_RAM;
lipo.i2cWriteBytes(BQ27441_EXTENDED_DATACLASS, data , 1);

lipo.i2cReadBytes(BQ27441_EXTENDED_BLOCKDATA, data, 32);
for (int i = 0; i < 32; i++) {
Serial.print(String(data[i]) + " ");
}
Serial.println("");

// Read a specified number of bytes over I2C at a given subAddress
int16_t BQ27441::i2cReadBytes(uint8_t subAddress, uint8_t * dest, uint8_t count)
{
	int16_t timeout = BQ72441_I2C_TIMEOUT;	
	Wire.beginTransmission(_deviceAddress);
	Wire.write(subAddress);
	Wire.endTransmission(true);
	
	Wire.requestFrom(_deviceAddress, count);
	while ((Wire.available() < count) && timeout--)
		delay(1);
	if (timeout)
	{
		for (int i=0; i<count; i++)
		{
			dest[i] = Wire.read();
		}
	}
	
	return timeout;
}

// Write a specified number of bytes over I2C to a given subAddress
uint16_t BQ27441::i2cWriteBytes(uint8_t subAddress, uint8_t * src, uint8_t count)
{
	Wire.beginTransmission(_deviceAddress);
	Wire.write(subAddress);
	for (int i=0; i<count; i++)
	{
		Wire.write(src[i]);
	}	
	Wire.endTransmission(true);
	
	return true;	
}

Example output 

64 90 0 90 0 93 0 106 0 78 0 70 0 80 0 81 0 67 0 61 0 77 0 90 0 181 1 218 2 242 0 0

[1] http://www.ti.com/lit/ug/sluuac9a/sluuac9a.pdf Section 6.3 Table 6.4

  • The app note got me part way there. 

    I went through each step the Sparkfun library did including computing a checksum which is not needed on read but it does it anyway for some reason. When it computed the checksum I'd get correct data excluding the first byte, if I remove that and all the other "extraneous" calls I'd get garbage. Skimming the app note I noticed a mention of waiting for some time on write and figured maybe the checksum was effectively doing that on read so I added an explicit wait and now I get fully correct data with the code below. I'm not sure if it's the gauge or something in the Arduino that needs to wait but I'm not doing anything performance sensitive enough to care about a 1ms wait so I'm going to just live with that for the time being.

    uint8_t data[32];
    data[0] = BQ27441_ID_R_A_RAM;
    lipo.i2cWriteBytes(BQ27441_EXTENDED_DATACLASS, data, 1);
    data[0] = 0;
    lipo.i2cWriteBytes(BQ27441_EXTENDED_DATABLOCK, data, 1);
    delay(1); // We get bad data without this!!
    lipo.i2cReadBytes(BQ27441_EXTENDED_BLOCKDATA, data, 32);