Hi there,
I'm working on a product that charges a 4.2V lithium cell using a BQ25890 configured over I2C by a microcontroller. What I see is that the battery doesn't complete a saturation charge. Instead, the BQ25890 reports that the charging cycle is complete by setting CHRG_STAT to 2'b11 when it was still providing a significant amount of current.
I can connect to the microcontroller via a UART, so can print register reads and writes. Writes are reported as a list of hex values (one per register). The raw UART output when charging is:
W: 0x00 0x66 0x06 0x40 0x5a 0x27 0x10 0x5e
This is 8 bytes that are written over I2C. The first is the address, so this is saying:
- Set REG00 to 0x66 (EN_HIZ=0; EN_ILIM=1; IINLIM=2A)
- Set REG01 to 0x06 (BHOT=0, BCOLD=0, VINDPM_OS=600mV)
- Set REG02 to 0x40 (CONV_START=0, CONV_RATE=1, BOOST_FREQ=0, ICO_EN=HVDCP_EN=MAXC_EN=FORCE_DPDM=AUTO_DPDM_EN=0)
- Set REG03 to 0x5a (BAT_LOADEN=0, WD_RST=1, OTG_CONFIG=0, CHG_CONFIG=1, SYS_MIN=3.5V)
- Set REG04 to 0x27 (EN_PUMPX=0, ICHG=2.496A)
- Set REG05 to 0x10 (IPRECHG=128mA, ITERM=64mA)
- Set REG06 to 0x5e (VREG=4.208, BATLOWV=1, VRECHG=0)
The configuration tells the charger to charge with up to 2.5A input current to a voltage of 4.2V with no clever USB handshaking (because there's actually a big 12V power supply to power the whole lot).
As well as writing configuration data, the firmware also reads status information (REG0B through REG12) and dumps it over UART. Here is the last read that is written over UART before charging completes:
R: 0x16 0x00 0x52 0x5f 0x60 0x33 0xdc 0x1a
Starting at REG0B, this means:
- REG0B=0x16 (CHRG_STAT=2'b10, PG_STAT=1)
- REG0C=0x00 (No faults reported)
- REG0D=0x52 (FORCE_VINDPM=0, VINDPM=4.4V)
- REG0E=0x5f (THERM_STAT=0, BATV=4.204V)
- REG0F=0x60 (SYSV=4.224V)
- REG10=0x33 (TSPCT=23.715%)
- REG11=0xdc (VBUS_GD=1, VBUSV=11.8V)
- REG12=0x1a (ICHGR=1.3A)
The firmware is designed to write this "please charge" configuration until it sees CHRG_STAT go to 2'b11 (which would imply that the charging has finished), at which point an LED turns green to report to the user that we're done. The firmware still carries on writing to the BQ25890 (to avoid the watchdog tripping), but now sets CHG_CONFIG=0 to disable charging.
Unfortunately, with this setup the charge stops before charging is complete: my bench power supply shows that we were still supplying a significant charging current. Looking at the register contents reported over UART (see above), it appears that we show that charge completes when ICHRGR=1.3A, which is rather high for a termination current(!)
I've altered the code so that on charge completion we don't do any writes to the chip and let the charger run for longer without telling it to disable charging. Here's the resulting UART trace, with approximately one entry per second. I've added the comments on the right by hand.
R: 0x16 0x00 0x52 0x5f 0x60 0x34 0xdc 0x1a
R: 0x16 0x00 0x52 0x5f 0x60 0x34 0xdc 0x1a
R: 0x16 0x00 0x52 0x5f 0x60 0x34 0xdc 0x1a
R: 0x16 0x00 0x52 0x5f 0x60 0x33 0xdc 0x1a
R: 0x16 0x00 0x52 0x5f 0x60 0x33 0xdc 0x1a
R: 0x1e 0x00 0x52 0x5f 0x60 0x33 0xde 0x00 // CHRG_STAT=2'b11: we've finished charging?
R: 0x1e 0x00 0x52 0x58 0x64 0x33 0xde 0x00
R: 0x1e 0x00 0x52 0x58 0x64 0x33 0xde 0x00
R: 0x1e 0x00 0x52 0x58 0x5d 0x33 0xde 0x00
R: 0x1e 0x00 0x52 0x58 0x5d 0x34 0xde 0x00
R: 0x1e 0x00 0x52 0x58 0x5b 0x34 0xde 0x00
R: 0x1e 0x00 0x52 0x58 0x5b 0x34 0xde 0x00
R: 0x16 0x00 0x52 0x58 0x5b 0x34 0xde 0x00
R: 0x16 0x00 0x52 0x5f 0x60 0x35 0xdc 0x1b // Oh no we hadn't! Let's charge some more.
R: 0x16 0x00 0x52 0x5f 0x60 0x35 0xdc 0x1b
R: 0x16 0x00 0x52 0x5f 0x60 0x35 0xdc 0x1b
R: 0x16 0x00 0x52 0x5f 0x60 0x35 0xdc 0x1b
R: 0x16 0x00 0x52 0x5f 0x60 0x35 0xdc 0x1a
R: 0x16 0x00 0x52 0x5f 0x60 0x35 0xdc 0x1a
R: 0x16 0x00 0x52 0x5f 0x60 0x35 0xdc 0x1a
R: 0x16 0x00 0x52 0x5f 0x60 0x35 0xdc 0x1a
R: 0x16 0x00 0x52 0x5f 0x60 0x35 0xdc 0x1a
R: 0x16 0x00 0x52 0x5f 0x60 0x35 0xdc 0x1a
R: 0x16 0x00 0x52 0x5f 0x60 0x35 0xdc 0x1a
R: 0x16 0x00 0x52 0x5f 0x60 0x34 0xdc 0x1a
R: 0x16 0x00 0x52 0x5f 0x60 0x34 0xdc 0x1a
R: 0x16 0x00 0x52 0x5f 0x60 0x34 0xdc 0x1a
R: 0x16 0x00 0x52 0x5f 0x60 0x34 0xdc 0x1a
R: 0x16 0x00 0x52 0x5f 0x60 0x34 0xdc 0x1a
R: 0x16 0x00 0x52 0x5f 0x60 0x34 0xdc 0x1a
R: 0x16 0x00 0x52 0x5f 0x60 0x34 0xdc 0x1a
R: 0x16 0x00 0x52 0x5f 0x60 0x34 0xdc 0x1a
R: 0x1e 0x00 0x52 0x5f 0x60 0x33 0xde 0x00 // Now we're done?
R: 0x1e 0x00 0x52 0x58 0x63 0x33 0xde 0x00
R: 0x16 0x00 0x52 0x58 0x5c 0x33 0xde 0x00
R: 0x1e 0x00 0x52 0x58 0x5c 0x33 0xde 0x00
R: 0x1e 0x00 0x52 0x58 0x5b 0x34 0xde 0x00
R: 0x1e 0x00 0x52 0x58 0x5c 0x34 0xde 0x00
R: 0x16 0x00 0x52 0x58 0x5b 0x34 0xde 0x00
R: 0x16 0x00 0x52 0x58 0x5b 0x34 0xde 0x00
R: 0x16 0x00 0x52 0x5f 0x60 0x35 0xdc 0x1b // Apparently not...
R: 0x16 0x00 0x52 0x5f 0x60 0x35 0xdc 0x1b
R: 0x16 0x00 0x52 0x5f 0x60 0x35 0xdc 0x1b
R: 0x16 0x00 0x52 0x5f 0x60 0x35 0xdc 0x1a
R: 0x16 0x00 0x52 0x5f 0x60 0x35 0xdc 0x1a
R: 0x16 0x00 0x52 0x5f 0x60 0x35 0xdc 0x1a
R: 0x16 0x00 0x52 0x5f 0x60 0x35 0xdc 0x1a
R: 0x16 0x00 0x52 0x5f 0x60 0x35 0xdc 0x1a
R: 0x16 0x00 0x52 0x5f 0x60 0x35 0xdc 0x1a
R: 0x16 0x00 0x52 0x5f 0x60 0x35 0xdc 0x1a
R: 0x16 0x00 0x52 0x5f 0x60 0x35 0xdc 0x1a
R: 0x16 0x00 0x52 0x5f 0x60 0x34 0xdc 0x1a
R: 0x16 0x00 0x52 0x5f 0x60 0x34 0xdc 0x19
R: 0x16 0x00 0x52 0x5f 0x60 0x34 0xdc 0x19
R: 0x16 0x00 0x52 0x5f 0x60 0x34 0xdc 0x19
R: 0x16 0x00 0x52 0x5f 0x60 0x34 0xdc 0x19
R: 0x16 0x00 0x52 0x5f 0x60 0x34 0xdc 0x19
R: 0x16 0x00 0x52 0x5f 0x60 0x34 0xdc 0x19
R: 0x16 0x00 0x52 0x5f 0x60 0x34 0xdc 0x19
R: 0x16 0x00 0x52 0x5f 0x60 0x34 0xdc 0x19
R: 0x1e 0x00 0x52 0x5f 0x60 0x34 0xdc 0x19
You can see the charging status switch on and off. The CHRG_STAT register is visible in the first hex value of each line: it is 2'b10 (which would mean fast charging) when the hex value is 0x16 and is 2'b11 (which would mean charge complete) when the hex value is 0x1e.
Can anyone suggest why this cycling behaviour would happen? And how can my firmware distinguish between "I'm taking a break from charging because <insert reason here>" and "We're really done. Tell the user so."?
Many thanks,
Rupert