主题中讨论的其他器件:BQ24196、 EV2400
我们有一个嵌入式 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由于过热而未执行任何操作、但为了解决此问题、我无法密封或打开密封件。 我们认为沟通没有问题、我们可以读取显示值、但我们不知道该怎么办、我们已经走了很多路?