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.

[参考译文] BQ27531-G1:无法为电池充电或在具有充电器 BQ24196的 BQ27531-G1电量监测计上启用 OTG

Guru**** 2386620 points
Other Parts Discussed in Thread: BQ24196, BQ27531-G1, EV2400
请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

https://e2e.ti.com/support/power-management-group/power-management/f/power-management-forum/1129719/bq27531-g1-unable-to-charge-battery-or-enable-otg-on-bq27531-g1-fuel-gauge-with-charger-bq24196

器件型号:BQ27531-G1
主题中讨论的其他器件:BQ24196EV2400

我们有一个嵌入式 Linux 设计项目、该项目使用 BQ27531-G1电量监测计来控制 BQ24196、监控电压、SOC、电流并启用 USB OTG。

在之前的版本中、我们仅使用 BQ24196、但随着时间的推移、我们意识到无法保存寄存器值并监控某些值(SOC、电压等)。 因此、我们认为我们应该切换到 BQ27531-G1 IC。

我们有哪些材料?

我们不使用评估板。 我们与嵌入式 Linux 通信。 这是我们使用的原理图:

对于通信、我们使用的是 python3 smbus2、代码位于以下位置。

from smbus2 import SMBus
from smbus2 import i2c_msg
import time
import RPi.GPIO as GPIO

BQ27531_I2C_ADDRESS                         = 0x55

BQ27531_SS_KEY0                             = 0x3672  
BQ27531_SS_KEY1                             = 0x0414

BQ27531_FAS_KEY0                            = 0x0000  
BQ27531_FAS_KEY1                            = 0x0000

BQ27531_CMD_CNTL							= 0x00
BQ27531_CMD_AT_RATE							= 0x02
BQ27531_CMD_AT_RATE_TIME_TO_EMPTY			= 0x04
BQ27531_CMD_TEMP							= 0x06
BQ27531_CMD_VOLTAGE							= 0x08
BQ27531_CMD_FLAGS							= 0x0A
BQ27531_CMD_NOMINAL_CAPACITY				= 0x0C
BQ27531_CMD_FULL_CAPACITY					= 0x0E
BQ27531_CMD_REMAINING_CAPACITY				= 0x10
BQ27531_CMD_FULL_CHARGE_CAPACITY			= 0x12
BQ27531_CMD_AVERAGE_CURRENT					= 0x14
BQ27531_CMD_TIME_TO_EMPTY					= 0x16
BQ27531_CMD_REMAINING_CAPACITY_UNFIL		= 0x18
BQ27531_CMD_STANDBY_CURRENT					= 0x1A
BQ27531_CMD_REMAINING_CAPACITY_FILTERED		= 0x1C	
BQ27531_CMD_PROG_CHARGING_CURRENT			= 0x1E	
BQ27531_CMD_PROG_CHARGING_VOLTAGE			= 0x20
BQ27531_CMD_FULL_CHARGE_CAPACITY_UNFIL		= 0x22	
BQ27531_CMD_AVERAGE_POWER					= 0x24
BQ27531_CMD_FULL_CHARGE_CAPACITY_FIL		= 0x26
BQ27531_CMD_STATE_OF_HEALTH					= 0x28
BQ27531_CMD_CYCLE_COUNT						= 0x2A
BQ27531_CMD_STATE_OF_CHARGE					= 0x2C
BQ27531_CMD_TRUE_SOC						= 0x2E
BQ27531_CMD_INSTANTANEOUS_CURRENT_READING	= 0x30
BQ27531_CMD_INTERNAL_TEMPERATURE			= 0x32
BQ27531_CMD_CHARGING_LEVEL					= 0x34
BQ27531_CMD_LEVEL_TAPER_CURRENT				= 0x6E
BQ27531_CMD_CALC_CHARGING_CURRENT			= 0x70
BQ27531_CMD_CALC_CHARGING_VOLTAGE			= 0x72

BQ27531_CNTL_CONTROL_STATUS                 = 0x0000
BQ27531_CNTL_DEVICE_INFO		            = 0x0001
BQ27531_CNTL_FW_VERSION			            = 0x0002
BQ27531_CNTL_HW_VERSION			            = 0x0003
BQ27531_CNTL_OTG_ENABLE			            = 0x0015
BQ27531_CNTL_OTG_DISABLE		            = 0x0016
BQ27531_CNTL_DIV_CUR_ENABLE		            = 0x0017
BQ27531_CNTL_CHG_ENABLE			            = 0x001A
BQ27531_CNTL_CHG_DISABLE		            = 0x001B
BQ27531_CNTL_GG_CHGRCTL_ENABLE	            = 0x001C
BQ27531_CNTL_GG_CHGRCTL_DISABLE	            = 0x001D
BQ27531_CNTL_SEALED				            = 0x0020
BQ27531_CNTL_RESET	                        = 0x0041

BQ27531_STATUS_FAS		                    = (1<<14)
BQ27531_STATUS_SS		                    = (1<<13)
BQ27531_STATUS_CSV		                    = (1<<12)
BQ27531_STATUS_CCA		                    = (1<<11)
BQ27531_STATUS_BCA		                    = (1<<10)
BQ27531_STATUS_OCVCMDCOMP	                = (1<<9)
BQ27531_STATUS_OCVFAL		                = (1<<8)

BQ27531_STATUS_INITCOMP		                = (1<<7)
BQ27531_STATUS_HIBERNATE	                = (1<<6)
BQ27531_STATUS_SNOOZE	                    = (1<<5)
BQ27531_STATUS_SLEEP		                = (1<<4)
BQ27531_STATUS_LDMD			                = (1<<3)
BQ27531_STATUS_RUP_DIS		                = (1<<2)
BQ27531_STATUS_VOK			                = (1<<1)
BQ27531_STATUS_QEN			                = (1<<0)

BQ27531_FLAG_OT				                = (1<<15)
BQ27531_FLAG_UT				                = (1<<14)
BQ27531_FLAG_CALMODE		                = (1<<12)
BQ27531_FLAG_DIV_CUR		                = (1<<11)
BQ27531_FLAG_GG_CHGRCTL_EN	                = (1<<10)
BQ27531_FLAG_FC				                = (1<<9)
BQ27531_FLAG_CHG			                = (1<<8)
BQ27531_FLAG_OCV_GD			                = (1<<5)
BQ27531_FLAG_WAIT_ID		                = (1<<4)
BQ27531_FLAG_BAT_DET		                = (1<<3)
BQ27531_FLAG_SOC1			                = (1<<2)
BQ27531_FLAG_SYSDOWN		                = (1<<1)
BQ27531_FLAG_DSG			                = (1<<0)

GPIO_OTG_PIN = 6
GPIO_CE_PIN  = 13
GPIO_PSEL_PIN = 19

def dec_to_bool(value):
    return 1 if value > 0 else 0

def bq27531_print_status(data):
    print(f"Control Status: FAS: {dec_to_bool(data & BQ27531_STATUS_FAS)}, SS: {dec_to_bool(data & BQ27531_STATUS_SS)}, CSV: {dec_to_bool(data & BQ27531_STATUS_CSV)}, CCA: {dec_to_bool(data & BQ27531_STATUS_CCA)}, BCA: {dec_to_bool(data & BQ27531_STATUS_BCA)}, OCVCMDCOMP:   {dec_to_bool(data & BQ27531_STATUS_OCVCMDCOMP)}, OCVFAIL: {dec_to_bool(data & BQ27531_STATUS_OCVFAL)}, INITCOMP: {dec_to_bool(data & BQ27531_STATUS_INITCOMP)}, HIBERNATE: {dec_to_bool(data & BQ27531_STATUS_HIBERNATE)}, SNOOZE: {dec_to_bool(data & BQ27531_STATUS_SNOOZE)}, SLEEP: {dec_to_bool(data & BQ27531_STATUS_SLEEP)}, LDMD: {dec_to_bool(data & BQ27531_STATUS_LDMD)}, RUP_DIS: {dec_to_bool(data & BQ27531_STATUS_RUP_DIS)}, VOK: { dec_to_bool(data & BQ27531_STATUS_VOK)}, QEN: {dec_to_bool(data & BQ27531_STATUS_QEN)}");

def bq27531_print_flags(data):
    print(f"Flags Status: OT:{dec_to_bool(data & BQ27531_FLAG_OT)}, UT: {dec_to_bool(data & BQ27531_FLAG_UT)}, CALMODE: {dec_to_bool(data & BQ27531_FLAG_CALMODE)}, DIV_CUR: {dec_to_bool(data & BQ27531_FLAG_DIV_CUR)}, GG_CHGRCTL_EN: {dec_to_bool(data & BQ27531_FLAG_GG_CHGRCTL_EN)} , FC: {dec_to_bool(data & BQ27531_FLAG_FC)}, CHG: {dec_to_bool(data & BQ27531_FLAG_CHG)}, OCV_GD:{dec_to_bool(data & BQ27531_FLAG_OCV_GD)}, WAIT_ID: {dec_to_bool(data & BQ27531_FLAG_WAIT_ID)}, BAT_DET: {dec_to_bool(data & BQ27531_FLAG_BAT_DET)}, SOC1: {dec_to_bool(data & BQ27531_FLAG_SOC1)}, SYSDOWN: {dec_to_bool(data & BQ27531_FLAG_SYSDOWN)}, DSG: {dec_to_bool(data & BQ27531_FLAG_DSG)}");

def bq27531_prepare_subcommand_packets(subcommand):
    return [subcommand & 0xFF, (subcommand >> 8) & 0xFF]

def bq27531_read_command(i2c_bus, command, len = 2):
    if len == 1:
        return i2c_bus.read_byte_data(BQ27531_I2C_ADDRESS, command)
    else:
        return i2c_bus.read_word_data(BQ27531_I2C_ADDRESS, command); 

def bq27531_read_subcommand(i2c_bus, subcommand):
    i2c_bus.write_i2c_block_data(BQ27531_I2C_ADDRESS, BQ27531_CMD_CNTL, bq27531_prepare_subcommand_packets(subcommand));
    return bq27531_read_command(i2c_bus, BQ27531_CMD_CNTL)

def bq27531_start_otg(i2c_bus):
    i2c_bus.write_i2c_block_data(BQ27531_I2C_ADDRESS, BQ27531_CMD_CNTL, bq27531_prepare_subcommand_packets(BQ27531_CNTL_OTG_ENABLE))

def bq27531_stop_otg(i2c_bus):
    i2c_bus.write_i2c_block_data(BQ27531_I2C_ADDRESS, BQ27531_CMD_CNTL, bq27531_prepare_subcommand_packets(BQ27531_CNTL_OTG_DISABLE))

def bq27531_start_charge(i2c_bus):
    i2c_bus.write_i2c_block_data(BQ27531_I2C_ADDRESS, BQ27531_CMD_CNTL, bq27531_prepare_subcommand_packets(BQ27531_CNTL_CHG_ENABLE))

def bq27531_stop_charge(i2c_bus):
    i2c_bus.write_i2c_block_data(BQ27531_I2C_ADDRESS, BQ27531_CMD_CNTL, bq27531_prepare_subcommand_packets(BQ27531_CNTL_CHG_DISABLE))

def bq27531_start_gg_controller_charge(i2c_bus):
    i2c_bus.write_i2c_block_data(BQ27531_I2C_ADDRESS, BQ27531_CMD_CNTL, bq27531_prepare_subcommand_packets(BQ27531_CNTL_GG_CHGRCTL_ENABLE))

def bq27531_stop_gg_controller_charge(i2c_bus):
    i2c_bus.write_i2c_block_data(BQ27531_I2C_ADDRESS, BQ27531_CMD_CNTL, bq27531_prepare_subcommand_packets(BQ27531_CNTL_GG_CHGRCTL_DISABLE))

def bq27531_reset(i2c_bus):
    i2c_bus.write_i2c_block_data(BQ27531_I2C_ADDRESS, BQ27531_CMD_CNTL, bq27531_prepare_subcommand_packets(BQ27531_CNTL_RESET))

def bq24196_registers(i2c_bus):
    registers = []

    for i in range(-1, 10):
        registers.append(bq27531_read_command(i2c_bus, i + 0x75, len = 1))

    return registers;

def bq24196_print_registers(registers):
    for i in range(len(registers)):
        if i != len(registers) - 1:
            print(f"REG{i - 1}: {hex(registers[i])}, ", end = '')
        else:
            print(f"REG{i - 1}: {hex(registers[i])}")

def bq27531_unseal(i2c_bus):
    i2c_bus.write_i2c_block_data(BQ27531_I2C_ADDRESS, BQ27531_CMD_CNTL, bq27531_prepare_subcommand_packets(BQ27531_SS_KEY1))
    i2c_bus.write_i2c_block_data(BQ27531_I2C_ADDRESS, BQ27531_CMD_CNTL, bq27531_prepare_subcommand_packets(BQ27531_SS_KEY0))
    time.sleep(2)

    start_time = int(round(time.time() * 1000))
    while (int(round(time.time() * 1000)) - start_time <= 10 * 1000):
        status = bq27531_read_subcommand(bus, BQ27531_CNTL_CONTROL_STATUS);
        bq27531_print_status(status)
        if status & BQ27531_STATUS_SS == 0:
            return True

        time.sleep(2)

    return False;

def bq27531_seal(i2c_bus):
    i2c_bus.write_i2c_block_data(BQ27531_I2C_ADDRESS, BQ27531_CMD_CNTL, bq27531_prepare_subcommand_packets(BQ27531_CNTL_SEALED))
    time.sleep(2)

    start_time = int(round(time.time() * 1000))
    while (int(round(time.time() * 1000)) - start_time <= 10 * 1000):
        status = bq27531_read_subcommand(bus, BQ27531_CNTL_CONTROL_STATUS);
        bq27531_print_status(status)
        if status & BQ27531_STATUS_SS != 0:
            return True

        time.sleep(2)

    return False;

with SMBus(1) as bus:
    print("---------------------------------------------------------------------------------------------------------")    
    print("Started BQ27531 Test!")

    GPIO.setmode(GPIO.BCM)
    GPIO.setup(GPIO_OTG_PIN, GPIO.OUT)
    GPIO.setup(GPIO_CE_PIN, GPIO.OUT)
    GPIO.setup(GPIO_PSEL_PIN, GPIO.OUT)

    GPIO.output(GPIO_OTG_PIN, GPIO.HIGH)
    GPIO.output(GPIO_CE_PIN, GPIO.LOW)
    GPIO.output(GPIO_PSEL_PIN, GPIO.LOW)

    seal_process_result = False;

    device_type             = bq27531_read_subcommand(bus, BQ27531_CNTL_DEVICE_INFO)
    firmware_version        = bq27531_read_subcommand(bus, BQ27531_CNTL_FW_VERSION)
    hardware_version        = bq27531_read_subcommand(bus, BQ27531_CNTL_HW_VERSION)
    print("--------------------")
    charger_status          = bq24196_registers(bus)
    status                  = bq27531_read_subcommand(bus, BQ27531_CNTL_CONTROL_STATUS)
    flags                   = bq27531_read_command(bus, BQ27531_CMD_FLAGS)

    print(f"Device Type: {device_type}, Firmware Version: {firmware_version}, Hardware Version: {hardware_version}")
    bq27531_print_flags(flags);
    bq27531_print_status(status)
    bq24196_print_registers(charger_status)
    print("--------------------")
    
    counter_start_otg = 0;

    while True: 
        try:
            voltage                 = bq27531_read_command(bus, BQ27531_CMD_VOLTAGE)
            prog_voltage            = bq27531_read_command(bus, BQ27531_CMD_PROG_CHARGING_VOLTAGE)
            calc_voltage            = bq27531_read_command(bus, BQ27531_CMD_CALC_CHARGING_VOLTAGE)
            prog_current            = bq27531_read_command(bus, BQ27531_CMD_PROG_CHARGING_CURRENT)
            calc_current            = bq27531_read_command(bus, BQ27531_CMD_CALC_CHARGING_CURRENT)
            temp                    = bq27531_read_command(bus, BQ27531_CMD_TEMP) / 10 - 273.1
            int_temp                = bq27531_read_command(bus, BQ27531_CMD_INTERNAL_TEMPERATURE) / 10 - 273.1
            soc                     = bq27531_read_command(bus, BQ27531_CMD_STATE_OF_CHARGE)
            charger_status          = bq24196_registers(bus)
            status                  = bq27531_read_subcommand(bus, BQ27531_CNTL_CONTROL_STATUS)
            flags                   = bq27531_read_command(bus, BQ27531_CMD_FLAGS)

            print(f"Voltage:     {voltage} mV, Calc. Voltage: {calc_voltage} mV, Prog. Voltage: {prog_voltage} mV")
            print(f"Calc. Current: {calc_current} mA, Prog. Current: {prog_current} mA")
            print(f"Temp:        {temp}")
            print(f"Int. Temp:   {int_temp}")
            print(f"SOC:         %{soc}");    
            bq27531_print_flags(flags);
            bq27531_print_status(status)
            bq24196_print_registers(charger_status)
            print("--------------------")

            counter_start_otg += 1

            if counter_start_otg >= 10:
                print("Setting OTG settings...")
                print("--------------------")
                bq27531_stop_gg_controller_charge(bus)
                bq27531_stop_charge(bus)
                bq27531_start_otg(bus)
                counter_start_otg = 0;

            """
            if status & BQ27531_STATUS_SS:
                print("Sent unseal command.")
                unseal_process_result = bq27531_unseal(bus)
                print(f"Remove Unseal Process: {unseal_process_result}")

                if unseal_process_result:
                    bq27531_print_flags(flags);
                    bq27531_print_status(status) 
            else:
                print("Sent seal command.")
                seal_process_result = bq27531_seal(bus)
                print(f"Remove Seal Process: {seal_process_result}")

                if seal_process_result:
                    bq27531_print_flags(flags);
                    bq27531_print_status(status) 
            """
            time.sleep(0.5)
        except KeyboardInterrupt:
            GPIO.cleanup()
            break
        

    print("Good bye...")

我们尝试了什么?

我们发送了一些命令来测试我们是否可以与 BQ27531-G1通信。 例如电压、SOC、温度、内部温度、器件类型、 固件版本、硬件版本等。 我们得到了一些信息:

  • 器件类型:1329 (稳定)、  
  • 固件版本:258 (不稳定有时得到65285)、
  • 硬件版本:168 (不稳定有时得到65281、65535)
  • 电压3993mV (稳定)、计算得出的电压:0mV、可编程 电压:0mV (稳定)
  • 计算 电流:0mA (稳定)、可编程 电流:0mA (稳定)、平均 电流:-593mA (稳定)
  • 温度:       179.8°C (稳定)
  • 内部 温度:  54.5°C (稳定)
  • SoC:        %22 (不稳定、数据值高度可变)
  • 标志状态:OT:1、UT:0、CALMODE:0、DIV_CUR:0、GG_CHGRCTL_EN:0、 FC:0、CHG:0、OCV_GD:1、WAIT_ID:1、BAT_DET:1、 SOC1:0、SYSDOWN:0、DSG:1
  • 控制状态:FAS:0、SS:0、CSV:0、CCA:0、BCA:0、 OCVCMDCOMP:  1、OCVFAIL:0、INITCOMP:1、休眠:0、贪睡:0、 睡眠:0、LDMD:0、RUP_DIS:1、VOK:0、QEN:0 (不稳定、 FAS 和 SS 位发生非常动态的变化。 有时 FAS 或 SS 可以为0或1。 但是、即使我们从未发送过密封或解封命令)
  • BQ24196充电器状态:REG-1:0x80、REG0:0x37、REG1:0x1b、REG2:0x60、REG3:0x11、 REG4:0xb2、REG5:0x9a、REG6:0x3、REG7:0x4b、REG8:0x0、 REG9:0x80

2.对于开始充电或启用 OTG、我们知道必须 REG01处更改充电器配置位01以进行充电、更改10/11以用于 OTG。 但我们无法更改位。 BQ27531-G1不允许更改充电器配置位。 因此、为了进行尝试、我们发送了不同的数据、其中有不同的启用启动充电方案(每个方案的结果都相同):

  • 仅发送充电使能子命令(当 OTG 引脚= 0、CE 引脚= 0、PSEL = 0时)
  • 发送充电使能和电量监测计充电控制器使能(当 OTG 引脚= 0、CE 引脚= 0、PSEL = 0时)
  • 发送禁用 OTG、充电使能和电量监测计充电控制器使能(OTG 引脚= 0、CE 引脚= 0、PSEL = 0)

或启动 OTG (每个方案的结果都相同)

  • 仅发送 OTG 使能子命令(当 OTG 引脚= 1、CE 引脚= 0、PSEL = 0时)
  • 发送 OTG 启用和充电禁用子命令(当 OTG 引脚= 0、CE 引脚= 0、PSEL = 0时)
  • 发送 OTG 启用、充电禁用和电量监测计充电控制器禁用子命令(OTG 引脚= 0、CE 引脚= 0、PSEL = 0)

正如我们在检查控制状态信息时看到的、我们可以看到存在过热信息。 我们试图将其删除、认为它可能是问题的原因。 但这次我们注意到密封和拆封操作不能正常工作。 当我们发送 SS 密钥打开密封时、我们发现它没有改变任何东西。 但有时我们会突然看到 SS 和 FAS 值同时为0或1。

因此、我们无法激活 OTG、也无法开始充电。 我们认为问题是过热、我们认为 BQ27531-G1由于过热而未执行任何操作、但为了解决此问题、我无法密封或打开密封件。 我们认为沟通没有问题、我们可以读取显示值、但我们不知道该怎么办、我们已经走了很多路?

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    您好、Tarik、

    能够可靠地读取寄存器值似乎是一个问题。 器件不应在密封或未密封之间随机切换、除非之前已输入密封命令并且器件已复位(如果曾经向器件发出密封命令、监测计将始终在复位后被密封)。 我建议使用 EV2400来确保我的怀疑是正确的。 我希望当您使用 EV2400时、我们能够缩小可能导致这种不准确读取密封/未密封值的范围、因为我希望 EV2400能够可靠地读回这些值。

    此致、

    杰克逊