Hi Ti guys.
I've a custom development board with the BQ25790 on it. I want to use it to charge a 3-cell battery from the 5V source. For now it is connected in the VBUS only mode. It is also important that automatic recharge is working.
MY GOAL
So what I want is when VBUS is applied, charging should start and finish when VBAT is 12600mV. Then when VBAT falls bellow 11800mV the charging should restart automatically without any pin toggle or register read/write. Don't know it the termination is needed or if it is connected with the automatic recharge process (didn't find that info in the datasheet)...
BQ25790 is initialized at the boot in the "bq25790_init" function. Then its status is displayed every second inthe function "bq25790_monitor". When INT pin of the BQ25790 is pulled low the "bq25790_on_int_low" is called and then the flag registers (REG22 - REG27) are read in the "bq25790_process" function.
SO WHAT IS THE PROBLEM
At that point the battery voltage is around 12V and VBUS is applied, charging cycle started and status line from charger is:
VBAT: 11954mV, IBAT: 295mA, CHG STATUS: 3, BAT PRESENT: 1, S0: 0x89, S1: 0x63, S2: 0x01, S3: 0x00, S4: 0x00, F0: 0x00, F1: 0x00
So this looks normal, current flows in the battery and charging mode is "CC charging" (status 3 from the datasheet). Then when battery voltage increases, charging status changes to "CV charging" (status 4) and the IBAT current decreases. If the load is connected to the VSYS at this time, battery voltage drops and charging status changes back to "CC charging" and the IBAT register value increases, which is normal operation.
But then at a random time charger gets stuck at the status "CC charging" but the IBAT register values is 0, also there is no current coming in or out of the battery (SHIP FET isn't used here.), but battery voltage is around 12.2V which means it should be charging. Following are some line from the monitor function:
VBAT: 12332mV, IBAT: 277mA, CHG STATUS: 4, BAT PRESENT: 1, S0: 0x89, S1: 0x83, S2: 0x01, S3: 0x00, S4: 0x00, F0: 0x00, F1: 0x00
CHG_FLAG1: 0x80
VBAT: 12332mV, IBAT: 277mA, CHG STATUS: 3, BAT PRESENT: 1, S0: 0x89, S1: 0x63, S2: 0x01, S3: 0x00, S4: 0x00, F0: 0x00, F1: 0x00
CHG_FLAG1: 0x80
VBAT: 12459mV, IBAT: 278mA, CHG STATUS: 4, BAT PRESENT: 1, S0: 0x89, S1: 0x83, S2: 0x01, S3: 0x00, S4: 0x00, F0: 0x00, F1: 0x00
CHG_FLAG1: 0x80
VBAT: 12494mV, IBAT: 274mA, CHG STATUS: 3, BAT PRESENT: 1, S0: 0x89, S1: 0x83, S2: 0x01, S3: 0x00, S4: 0x00, F0: 0x00, F1: 0x00
CHG_FLAG1: 0x80
...
VBAT: 12547mV, IBAT: 215mA, CHG STATUS: 3, BAT PRESENT: 1, S0: 0x89, S1: 0x63, S2: 0x01, S3: 0x00, S4: 0x00, F0: 0x00, F1: 0x00
VBAT: 12190mV, IBAT: 107mA, CHG STATUS: 3, BAT PRESENT: 1, S0: 0x89, S1: 0x63, S2: 0x01, S3: 0x00, S4: 0x00, F0: 0x00, F1: 0x00
VBAT: 12001mV, IBAT: 53mA, CHG STATUS: 3, BAT PRESENT: 1, S0: 0x89, S1: 0x63, S2: 0x01, S3: 0x00, S4: 0x00, F0: 0x00, F1: 0x00
VBAT: 12001mV, IBAT: 53mA, CHG STATUS: 3, BAT PRESENT: 1, S0: 0x89, S1: 0x63, S2: 0x01, S3: 0x00, S4: 0x00, F0: 0x00, F1: 0x00
VBAT: 11865mV, IBAT: 26mA, CHG STATUS: 3, BAT PRESENT: 1, S0: 0x89, S1: 0x63, S2: 0x01, S3: 0x00, S4: 0x00, F0: 0x00, F1: 0x00
VBAT: 11865mV, IBAT: 13mA, CHG STATUS: 3, BAT PRESENT: 1, S0: 0x89, S1: 0x63, S2: 0x01, S3: 0x00, S4: 0x00, F0: 0x00, F1: 0x00
VBAT: 11783mV, IBAT: 13mA, CHG STATUS: 3, BAT PRESENT: 1, S0: 0x89, S1: 0x63, S2: 0x01, S3: 0x00, S4: 0x00, F0: 0x00, F1: 0x00
VBAT: 11756mV, IBAT: 6mA, CHG STATUS: 3, BAT PRESENT: 1, S0: 0x89, S1: 0x63, S2: 0x01, S3: 0x00, S4: 0x00, F0: 0x00, F1: 0x00
VBAT: 11756mV, IBAT: 6mA, CHG STATUS: 3, BAT PRESENT: 1, S0: 0x89, S1: 0x63, S2: 0x01, S3: 0x00, S4: 0x00, F0: 0x00, F1: 0x00
VBAT: 11747mV, IBAT: 3mA, CHG STATUS: 3, BAT PRESENT: 1, S0: 0x89, S1: 0x63, S2: 0x01, S3: 0x00, S4: 0x00, F0: 0x00, F1: 0x00
VBAT: 11715mV, IBAT: 1mA, CHG STATUS: 3, BAT PRESENT: 1, S0: 0x89, S1: 0x63, S2: 0x01, S3: 0x00, S4: 0x00, F0: 0x00, F1: 0x00
VBAT: 11715mV, IBAT: 1mA, CHG STATUS: 3, BAT PRESENT: 1, S0: 0x89, S1: 0x63, S2: 0x01, S3: 0x00, S4: 0x00, F0: 0x00, F1: 0x00
VBAT: 11715mV, IBAT: 1mA, CHG STATUS: 3, BAT PRESENT: 1, S0: 0x89, S1: 0x63, S2: 0x01, S3: 0x00, S4: 0x00, F0: 0x00, F1: 0x00
VBAT: 11696mV, IBAT: 0mA, CHG STATUS: 3, BAT PRESENT: 1, S0: 0x89, S1: 0x63, S2: 0x01, S3: 0x00, S4: 0x00, F0: 0x00, F1: 0x00
VBAT: 11696mV, IBAT: 0mA, CHG STATUS: 3, BAT PRESENT: 1, S0: 0x89, S1: 0x63, S2: 0x01, S3: 0x00, S4: 0x00, F0: 0x00, F1: 0x00
And then here it is stuck and it won't start automaticall recharge procedure. There are two ways to start new charging cycle:
1. To reconnect the VBUS power supply (5V).
2. To set EN_CHG bit 0 and then back to 1 but usually this must be done a few times to restart charging cycle.
So what am I doing wrong and what am I missing. Kindly asking you to help me out.
SIMPLIFIED FUNCTIONS
Following is the init procedure (simplified for better readability):
void bq25790_init(void){
set_bq25790_CE_pin(HIGH); // Disable charging
bq25790_termination_ctrl.reg_rst = 1; // Reset the BQ25790 and wait 250ms
HAL_Delay(250);
bq25790_read_all_registers(); // Read all registers - default values are same as the one from the datasheet...
bq25790_chg_ctrl1.wdt = 0; // Disable wdt
bq25790_chg_ctrl1.wdt_rst = 1; // Reset watchdog status
bq25790_prechg_ctrl.iprechg = 1; // Set the pre-charge current regulation limit to 40 mA.
bq25790_inp_v_lim.vinpm = 0x28; // Set the input voltage regulation limit (VINDPM) to 4000mV (open circuit voltage).
bq25790_chgr_i_lim.ichg = 0x1E; // To set max. constant-current (CC) charging regulation limit to 300mA.
bq25790_inp_i_lim.iindpm = 0x14A; // To set input current regulation limit to 3300mA.
// VSYSMIN is automatically set to 9000mV because of the hardware configuration, and a read of the register confirms that.
// VREG is is automatically set to 12600mV because of the hardware configuration, and a read of the register confirms that.
bq25790_rechg_ctrl.trechg = 3; // Battery recharge deglich time 2048ms
bq25790_rechg_ctrl.vrechg = 0x0F; // Automatic recharge at 11800mV -> (800mV - 50mV) / 50mV = 0x0F
bq25790_adc_ctrl.adc_avg = 1; // Running average
bq25790_adc_ctrl.adc_en = 1; // Enable ADC converter
bq25790_adc_ctrl.adc_rate = 0; // 15-bit effective resolution
bq25790_ntc_ctrl1.ts_ignore = 1; // Ignor temperature sensor - Not populated on the PCB
// Now when registers are set, enable charging
set_bq25790_CE_pin(LOW);
bq25790_chg_ctrl0.en_chg = 1;
}
Then a function for monitoring is called every second and when the INT pin goes low (simplified for better readability):
void bq25790_monitor(){ // Called every second and when the INT pin goes low...
bq25790_read_registers_from_tick(); // Here read all the necessary registers
PRINTF( "VBAT: %dmV, "
"IBAT: %dmA, "
"CHG STATUS: %d, "
"BAT PRESENT: %d, "
"S0: 0x%02X, "
"S1: 0x%02X, "
"S2: 0x%02X, "
"S3: 0x%02X, "
"S4: 0x%02X, "
"F0: 0x%02X, "
"F1: 0x%02X\n",
bq25790_vbat_adc.vbat_adc,
bq25790_ibat_adc.ibat_adc,
bq25790_chg_status1.chg_stat,
bq25790_chg_status2.vbat_present_stat,
*(uint8_t*)&bq25790_chg_status0,
*(uint8_t*)&bq25790_chg_status1,
*(uint8_t*)&bq25790_chg_status2,
*(uint8_t*)&bq25790_chg_status3,
*(uint8_t*)&bq25790_chg_status4,
*(uint8_t*)&bq25790_fault_status0,
*(uint8_t*)&bq25790_fault_status1
);
}
Then there is also the interrupt callback and interrupt callback handling function (simplified for better readability):
void bq25790_on_int_low(void){ // Function must return fast (ISR function)
// This function is called every time when "INT" pin of the BQ25790 is pulled low.
handle_bq25790_interrupt++; (defined as global int)
}
void bq25790_process(void){ // Function can take time (called from main every 1ms)
if(handle_bq25790_interrupt){
handle_bq25790_interrupt--;
bq25790_read_flag_registers(); // Read all flag registers
if (*(uint8_t*)&bq25790_chg_flag0 > 0) PRINTF("CHG_FLAG0: 0x%02X\n", *(uint8_t*)&bq25790_chg_flag0);
if (*(uint8_t*)&bq25790_chg_flag1 > 0) PRINTF("CHG_FLAG1: 0x%02X\n", *(uint8_t*)&bq25790_chg_flag1);
if (*(uint8_t*)&bq25790_chg_flag2 > 0) PRINTF("CHG_FLAG2: 0x%02X\n", *(uint8_t*)&bq25790_chg_flag2);
if (*(uint8_t*)&bq25790_chg_flag3 > 0) PRINTF("CHG_FLAG3: 0x%02X\n", *(uint8_t*)&bq25790_chg_flag3);
if (*(uint8_t*)&bq25790_fault_flag0 > 0) PRINTF("FAULT_FLAG0: 0x%02X\n", *(uint8_t*)&bq25790_fault_flag0);
if (*(uint8_t*)&bq25790_fault_flag1 > 0) PRINTF("FAULT_FLAG1: 0x%02X\n", *(uint8_t*)&bq25790_fault_flag1);
bq25790_monitor();
}
}
Best regards,
Aleš Zupanc, firmware developer
PoLabs d.o.o. 1000 Ljubljana, Slovenia