Because of the holidays, TI E2E™ design support forum responses will be delayed from Dec. 25 through Jan. 2. Thank you for your patience.

BQ25731: UPS POWER IC

Part Number: BQ25731
Other Parts Discussed in Thread: , EV2400, BQSTUDIO

Tool/software:

Subject: Issues with Battery Charging Control, Status Updates, Battery Voltage , and I2C Communication for BQ25731

I am currently facing several issues while working with the BQ25731 battery management system over I2C. These issues are hindering the proper functioning of the system, and I require assistance in troubleshooting the issues.

1. Charging Not Enabling

I am unable to enable charging via I2C commands. The following command:

sudo i2cset -y 1 0x6b 0x10 0x01 # Enable charging

fails consistently with the error message:

Error: Write failed

Despite multiple attempts and verifying that the register address and data are correct, charging is not being enabled.

2. Charging Gets Disabled After Some Time

Even when I manage to enable charging, it gets disabled after some time without any clear indication or trigger. This suggests a possible issue with either the register settings or hardware configuration that might be causing the system to automatically disable charging.

3. Failure to Read Battery Status and Voltage Updates

When attempting to read the battery voltage and status registers, I consistently encounter the following issues:
The battery voltage and charge percentage are not updating as expected.
The Battery Status and Voltage registers are either returning incorrect values or not providing updates at all.
Specific registers such as 0x2C (battery voltage) are returning constant values (e.g., 0x00), which may suggest communication issues or incorrect register settings.

4. Continuous Remote I/O Errors

I am experiencing continuous Remote I/O errors while trying to read from or write to the I2C bus, particularly when accessing certain registers related to battery status and voltage. These errors occur during basic I2C operations such as reading or writing to the battery management IC.

this is code

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <pigpio.h> // Switching to pigpio for better GPIO control
#include <fcntl.h>
#include <sys/ioctl.h>
#include <linux/i2c-dev.h>

#define BQ25731_ADDR 0x6b // I2C address of BQ25731
#define BQ25731_CHARGE_ON 0x01 // To turn on charging
#define BQ25731_CHARGE_OFF 0x00 // To turn off charging
#define BQ25731_STATUS 0x20 // Battery status register
#define BQ25731_CONTROL 0x23 // Battery control register
#define BQ25731_INPUTVOLTAGE 0X0A // Input voltage register
#define BQ25731_CHARGE_CURRENT 0x03 // Battery charge current register
#define BQ25731_CHARGE_VOLTAGE 0x05 // Battery charge voltage register
#define BQ25731_OTGVOLTAGE 0x07 // Overvoltage protection register
#define BQ25731_OTGCURRENT 0x09 // Overcurrent protection register
#define MAX_BATTERY_PERCENTAGE 100 // Max battery percentage
#define LOW_BATTERY_THRESHOLD 20 // Low battery warning threshold (in percentage)
#define MIN_BATTERY_VOLTAGE 10.5 // Minimum voltage before shutdown (for lead-acid batteries)

#define LEAD_ACID_MAX_VOLTAGE 14.4 // Maximum charging voltage for lead-acid battery
#define LEAD_ACID_MIN_VOLTAGE 10.5 // Minimum voltage before shutdown (for lead-acid batteries)
#define LEAD_ACID_CHARGE_CURRENT 1.0 // Charge current in Amps (for example, 1A for a 10Ah battery)
#define LEAD_ACID_OVER_VOLTAGE 14.7 // Overvoltage protection threshold (for lead-acid battery)
#define LEAD_ACID_OVER_CURRENT 2.0 // Overcurrent protection threshold (in Amps)

int fd; // File descriptor for I2C
int BATTERY_PER; // Battery percentage
float BATTERY_VOLTAGE; // Battery voltage (calculated based on IC registers)
char buffer[3]; // Buffer for I2C communication

void initBQ25731(void);
int BATTERY_STATUS(float BATTERY_VOLTAGE);
void monitor_battery_status(void);
void enable_charging(void);
void disable_charging(void);
float read_battery_voltage(void);
void set_battery_charge_voltage(float voltage);
void set_battery_charge_current(float current);
void set_overvoltage_protection(float voltage);
void set_overcurrent_protection(float current);

void initBQ25731() {
if ((fd = open("/dev/i2c-1", O_RDWR)) < 0) {
perror("Failed to open the I2C bus");
exit(1);
}
if (ioctl(fd, I2C_SLAVE, BQ25731_ADDR) < 0) {
perror("Failed to access BQ25731 IC");
exit(1);
}
}
int BATTERY_STATUS(float BATTERY_VOLTAGE){
int soc = 0;
if(BATTERY_VOLTAGE >= 12.7){
soc = 100;
}else if(BATTERY_VOLTAGE >= 12.5 && BATTERY_VOLTAGE < 12.7){
soc = 75;
}else if(BATTERY_VOLTAGE >= 12.3 && BATTERY_VOLTAGE < 12.5){
soc = 50;
}else if(BATTERY_VOLTAGE >= 12.0 && BATTERY_VOLTAGE > 12.3){
soc = 25;
}else if(BATTERY_VOLTAGE < 11.0){
soc = 0;
}
return soc;
}

void monitor_battery_status() {
BATTERY_STATUS(BATTERY_VOLTAGE);

if (BATTERY_PER < LOW_BATTERY_THRESHOLD) {
printf("Warning: Battery is below %d%%\n", LOW_BATTERY_THRESHOLD);
enable_charging();
} else if (BATTERY_PER >= MAX_BATTERY_PERCENTAGE) {
printf("Battery is fully charged.\n");
disable_charging();
}
}

void enable_charging() {
buffer[0] = BQ25731_CONTROL;
buffer[1] = BQ25731_CHARGE_ON;
if (write(fd, buffer, 2) != 2) {
perror("Failed to enable charging");
} else {
printf("Charging enabled.\n");
}
}

void disable_charging() {
buffer[0] = BQ25731_CONTROL;
buffer[1] = BQ25731_CHARGE_OFF;
if (write(fd, buffer, 2) != 2) {
perror("Failed to disable charging");
} else {
printf("Charging disabled.\n");
}
}

void set_battery_charge_voltage(float voltage) {
int voltage_value = (int)(voltage * 10);

buffer[0] = BQ25731_CHARGE_VOLTAGE;
buffer[1] = (voltage_value >> 8) & 0xFF;
buffer[2] = voltage_value & 0xFF;

if (write(fd, buffer, 3) != 3) {
perror("Failed to set charge voltage");
} else {
printf("Charge voltage set to %.2fV\n", voltage);
}
}

void set_battery_charge_current(float current) {
int current_value = (int)(current * 10);

buffer[0] = BQ25731_CHARGE_CURRENT;
buffer[1] = current_value;

if (write(fd, buffer, 2) != 2) {
perror("Failed to set charge current");
} else {
printf("Charge current set to %.2fA\n", current);
}
}

void set_overvoltage_protection(float voltage) {
int voltage_value = (int)(voltage * 10);

buffer[0] = BQ25731_OTGVOLTAGE;
buffer[1] = (voltage_value >> 8) & 0xFF;
buffer[2] = voltage_value & 0xFF;

if (write(fd, buffer, 3) != 3) {
perror("Failed to set overvoltage protection");
} else {
printf("Overvoltage protection set to %.2fV\n", voltage);
}
}

void set_overcurrent_protection(float current) {
int current_value = (int)(current * 10);

buffer[0] = BQ25731_OTGCURRENT;
buffer[1] = current_value;

if (write(fd, buffer, 2) != 2) {
perror("Failed to set overcurrent protection");
} else {
printf("Overcurrent protection set to %.2fA\n", current);
}
}
float read_battery_voltage() {
buffer[0] = 0x2C; // VBAT Register address (Low byte)

if (write(fd, buffer, 1) != 1) {
perror("Failed to write battery voltage register");
return -1.0;
}

if (read(fd, buffer, 2) != 2) {
perror("Failed to read battery voltage");
return -1.0;
}

int voltage_mV = (buffer[1] << 8) | buffer[0]; // High byte << 8 | Low byte

return voltage_mV / 1000.0; // Return voltage in volts
}

int main() {
if (gpioInitialise() < 0) { // Initialize pigpio library
fprintf(stderr, "pigpio initialization failed\n");
return 1;
}

initBQ25731();

set_battery_charge_voltage(LEAD_ACID_MAX_VOLTAGE);
set_battery_charge_current(LEAD_ACID_CHARGE_CURRENT);
set_overvoltage_protection(LEAD_ACID_OVER_VOLTAGE);
set_overcurrent_protection(LEAD_ACID_OVER_CURRENT);

unsigned long last_check_time = gpioTick();

while (1) {
unsigned long current_time = gpioTick();

if (current_time - last_check_time >= 1000000) {
monitor_battery_status();
last_check_time = current_time;
}
BATTERY_PER = BATTERY_STATUS(BATTERY_VOLTAGE);
printf("BATTERY PERCENTAGE : %d%%\n",BATTERY_PER);
BATTERY_VOLTAGE = read_battery_voltage();
if (BATTERY_VOLTAGE != -1) {
printf("Battery Voltage: %.2fV\n", BATTERY_VOLTAGE);
if (BATTERY_VOLTAGE < LEAD_ACID_MIN_VOLTAGE) {
printf("Warning: Battery voltage too low! Disabling charging.\n");
disable_charging();
}
}

usleep(500000); // Sleep for 0.5 seconds to avoid high CPU usage
}

gpioTerminate();
return 0;
}

//here mainly we are facing the issue with read_battery_voltage() ,enable_charging,disable_charging

  • Hi Sai,

    Unfortunately, no one is available to support this post until after the U.S. Thanksgiving Holiday.  I apologize for the delay.

    Regards,

    Jeff

  • Hi  Jeff F,

    May I know when your team is available to support this issue?

    Best Regards,

    Sai Ravali.

  • Hello,

    Due to the U.S. holiday our responses will be delayed, sorry for the inconvenience.

    Sincerely,

    Wyatt Keller

  •  Hi Wyatt Keller,

    As today is December 2nd , I wanted to kindly follow up regarding the resolution of the issue we discussed earlier, let me know when support will be available?

  • Hi, Sai,

    Thanks for your patience. 

    I think this is related to communication issue, however, we don't support any custom code debugging. I would suggest you ordering a BQ25731EVM and its associated EV2400. 

    BQStudio handles all the I2C code and communication. 

    www.ti.com/.../BQ25731EVM

    Regards,

    Tiger

  • Hi,Tiger,

    Thank you for your response.However i am currently facing some challenges with configuring and monitoring the battery voltage and charging status :

    1.I am unable to charge the battery with 0x00/01 ,0x03/02 for charge the current ,0x05/04 for charge the voltage.

    Output:

    i2cset -y 1 0x2B 0x00 0x01
    Error: Write failed
    sudo i2cset -y 1 0x2B 0x00 0x01 0x02 0x05 i
    Error: Write failed
    sudo i2cset -y 1 0x2B 0x00 0x02 0x05 0x01 i
    Error: Write failed

    2.I am unable to read the battery voltage register with 0x2C/2D and even after enabling the ADCOption() Using register 0x3B/3A.

    Output:


    Charging Voltage set to 14.40 V
    Charging Current set to 1.00 A
    Input Voltage (VBUS): 126 mV
    Charging enabled
    Fault Status: 0x41
    Fault detected! Resetting faults...
    Faults cleared
    Battery Voltage: 0.00 V
    Battery Voltage: 0.00 V
    Actually while measuring with mutli-meter battery having 12v charge.

    3.Additionally,the charging  status shows very low values,approximattely 260v and 0A

    Output:

    Charging Voltage set to 14.40 V
    Charging Current set to 1.00 A
    Charging enabled
    Input Voltage (VBUS): 126 mV
    Battery Current (IBAT): 0 mA

  • Hi, Sai,

    I am not sure how the i2c code works. I would suggest you probing the SDA and CLK to see if it conforms to the I2C timing diagram. 

    Regards,

    Tiger

  • Hi,Tiger,

    I am unable to read the battery voltage register with 0x2C/2D and even after enabling the ADCOption() Using register 0x3B/3A.

    Output:


    Charging Voltage set to 14.40 V
    Charging Current set to 1.00 A
    Input Voltage (VBUS): 126 mV
    Charging enabled
    Fault Status: 0x41
    Fault detected! Resetting faults...
    Faults cleared
    Battery Voltage: 0.00 V
    Battery Voltage: 0.00 V
    Actually while measuring with mutli-meter battery having 12v charge.

    this is o/p value while running the commands:

    sudo i2cset -y 1 0x6B 0x3B 0x01
    sudo i2cset -y 1 0x6B 0x3B 0x40
    sleep 1

    sudo i2cget -y 1 0x6B 0x2c
    0x00
    sudo i2cget -y 1 0x6B 0x2D
    0x00

    2.Additionally,the charging  status shows very low values in mv and 0A

    Output:

    Charging Voltage set to 14.40 V
    Charging Current set to 1.00 A
    Charging enabled
    Input Voltage (VBUS): 126 mV
    Battery Current (IBAT): 0 mA
    and also battery charging also not happening...

    Regards,

    Sai Ravali.

  • You need a GUI to see the register values. 

    www.ti.com/.../BQSTUDIO