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