SLUAAM4 December   2023 BQ76905 , BQ76907

 

  1.   1
  2.   Abstract
  3.   Trademarks
  4. 1Direct Commands
    1. 1.1 Alarm Enable - 0x66
    2. 1.2 Cell 1 Voltage - 0x14
    3. 1.3 Internal Temperature - 0x28
    4. 1.4 CC2 Current - 0x3A
    5. 1.5 Direct Command Summary
      1. 1.5.1 Disabling Auto Refresh
  5. 2Subcommands
    1. 2.1 DEVICE_NUMBER - 0x0001
    2. 2.2 FET_ENABLE - 0x0022
    3. 2.3 RESET - 0x0012
    4. 2.4 CB_ACTIVE_CELLS - 0x0083
    5. 2.5 Subcommand Summary
  6. 3Reading and Writing RAM Registers
    1. 3.1 Read Enabled Protections A
    2. 3.2 Enter CONFIG_UPDATE Mode
    3. 3.3 Write Enabled Protections A
    4. 3.4 Write VCell Mode
    5. 3.5 Exit CONFIG_UPDATE Mode
    6. 3.6 Reading and Writing RAM Registers Summary
  7. 4I2C With CRC
  8. 5Simple Code Examples
  9. 6References

Simple Code Examples

The following example code is written in Python and designed to communicate to the BQ7690x device from a PC through an EV2400 module or through the USB connector on the BQ76905 or BQ76907 Evaluation Module. The code shows the creation of simple I2C Read and Write functions, a DataRAM_Read function, (which can also be used to execute subcommands since these follow the same format), and a DataRAM_Write function that shows the calculation of checksum and length. The main section of the code goes through all of the examples covered in the first three sections of this document.

This simple code example is intended to illustrate the basic command structure for I2C commands. Microcontroller code examples are also available for I2C.

'''
/* BQ7690x example Program demonstrates examples for direct commands, subcommands, and writing / reading from device RAM.
'''
I2C_ADDR = 0x10  # BQ7690x default responder address
numCells = 5    # Set to 7 for BQ76907
def DataRAM_Read(addr, length):
    '''
    Write address location to 0x3E and read back from 0x40
    Used to read dataflssh and for subcommands
    '''
    addressBlock = [(addr%256), (addr/256)]
    I2C_Write(I2C_ADDR, 0x3E, addressBlock)
    value = I2C_Read(I2C_ADDR, 0x40,length)
    return value
def DataRAM_Write(addr, block):
    '''
    Write address location to 0x3E and Checksum,length to 0x60
    Used to write dataflssh
    Add 2 to length for Rev A0 of Octane
    '''
    addressBlock = [(addr%256), (addr/256)]
    wholeBlock = addressBlock + block
    I2C_Write(I2C_ADDR, 0x3E, wholeBlock)             # Write Data Block
    # Write Data Checksum and length to 0x60, required for RAM writes
    I2C_Write(I2C_ADDR, 0x60, [~sum(wholeBlock) & 0xff, len(wholeBlock)+2])
    return        
def ReadCellVoltage(cell):
    '''
    Reads a specific cell voltage
    '''
    cmd_addr = 0x14 + (cell * 2)
    result = I2C_Read(I2C_ADDR, cmd_addr, 2)
    print ("Cell", cell, " = ", (result[1]*256 + result[0]), " mV")
    return 
def ReadAllCellVoltages():
    '''
    Reads all cell voltages, Stack voltage, PACK voltage, and LD voltage
    '''
    cmd_addr = 0x12
    for i in range(0,numCells):
        cmd_addr += 2
        result = I2C_Read(I2C_ADDR, cmd_addr,2)
        print ("Cell", (i+1), " = ", (result[1]*256 + result[0]), " mV")
    result = I2C_Read(I2C_ADDR, 0x26,2)
    print ("Stack Voltage = ", (result[1]*256 + result[0]), " mV")
    result = I2C_Read(I2C_ADDR, 0x22,2)
    print "REG18 Voltage = ", (result[1]*256 + result[0]), " ADC Counts"
    result = I2C_Read(I2C_ADDR, 0x24,2)
    print ("VSS Voltage = ", (result[1]*256 + result[0]), " ADC Counts")
    return
def crc8(b,key):
    crc = 0
    ptr = 0
    for j in range(len(b),0,-1):
        for k in range(8):
            i = 128 / (2**k)
            if ((crc & 0x80) != 0):
                crc = crc * 2
                crc = crc ^ key
            else:
                crc = crc * 2
            if ((b[ptr] & i) != 0):
                crc = crc ^ key
        ptr = ptr + 1
    return crc
##########################################
#  Start of Main Script
##########################################
################ Direct Command Examples ################
#Write Alarm Enable to 0x0060 - FULLSCAN, ADSCAN
I2C_Write(I2C_ADDR, 0x66, [0x60, 0x00])
#Read Voltage on Cell #1
result = I2C_Read(I2C_ADDR, 0x14, 2)
print ("Cell 1 = ", (result[1]*256 + result[0]), " mV")
#Read Internal Temperature
result = I2C_Read(I2C_ADDR, 0x28, 2)
print ("Internal Temp = ", ((result[1]*256 + result[0])), "degrees C")
#Read CC2 Current Measurement
result = I2C_Read(I2C_ADDR, 0x3A, 2)
print ("CC2", (result[1]*256 + result[0]), " mA")
################ Subcommand Examples ################
## Command-only Subcomands ##
#Read Device Number
b = DataRAM_Read(0x0001,6)
print ("Device_Number = " '{0:04X}'.format(b[1]*256+b[0]))
#FET_ENABLE
I2C_Write(I2C_ADDR, 0x3E, [0x22, 0x00])
#Cell Balance Write Command - starts balancing on specified cells when written
DataRAM_Write(0x0083, [0x02])
#Cell Balance Read Command - read which cells are being balanced
b = DataRAM_Read(0x0083,1)
print ("Cell Balancing = 0x" '{0:02X}'.format(b[0]))
#RESET - returns device to default settings
I2C_Write(I2C_ADDR, 0x3E, [0x12, 0x00])
sleep(2)
# Read 'Enabled Protections A' RAM register 0x9024
b = DataRAM_Read(0x9024,1)
print ("Enabled Protections A = 0x" '{0:02X}'.format(b[0]))
#Set CONFIG_UPDATE Mode (RAM registers can be written while in
#CONFIG_UPDATE mode and will take effect after exiting CONFIG_UPDATE mode
I2C_Write(I2C_ADDR, 0x3E, [0x90, 0x00])
#Write to 'Enabled Protections A' RAM register to enable CUV protection
DataRAM_Write(0x9024, [0xE1])
#Write to 'VCell Mode' RAM register to configure for a 9-cell battery
DataRAM_Write(0x901B, [0x04])
#Exit CONFIG_UPDATE Mode
I2C_Write(I2C_ADDR, 0x3E, [0x92, 0x00])
# CRC8 Example Calculation
TestValue = [0x10, 0x14, 0x11, 0x68]
crcKey = 0x107
check = 0xff & crc8(TestValue,crcKey)
print "crc8 check = 0x" '{0:02X}'.format(check)
ReadAllCellVoltages()

The output from running the example Python script on a BQ76905 Evaluation Module follows.

('Cell 1 = ', 3089, ' mV')
('Internal Temp = ', 29, 'degrees C')
('CC2', 45, ' mA')
Device_Number = 7605
Cell Balancing = 0x02
Enabled Protections A = 0xA1
crc8 check = 0x33
('Cell', 1, ' = ', 3089, ' mV')
('Cell', 2, ' = ', 3082, ' mV')
('Cell', 3, ' = ', 3093, ' mV')
('Cell', 4, ' = ', 3089, ' mV')
('Cell', 5, ' = ', 3089, ' mV')
('Stack Voltage = ', 15471, ' mV')
REG18 Voltage =  19153  ADC Counts
('VSS Voltage = ', 3, ' ADC Counts')