Battery percentage

float readBatteryVoltage() {
  int rawValue = analogRead(batteryPin) ;
  // Convert rawValue to voltage (adjust these values based on your setup)
  float voltage = rawValue * (4.2/ 1023);
  return voltage;
}

int calculateBatteryPercentage(float voltage) {
  // Determine your battery's voltage range and corresponding capacity
  float minVoltage = 0.0; // Minimum voltage
  float maxVoltage = 1023; // Maximum voltage

  // Calculate battery percentage based on voltage range
  int batteryPercentage = map(voltage, minVoltage, maxVoltage, 0, 100) ;
  batteryPercentage = constrain(batteryPercentage, 0, 100); // Limit to 0-100

  return batteryPercentage;
}

I need help in displaying battery percentage, this current coding helps to display them in percentile form(100,75,50,25, 0 ) instead of exact percentage reading, how can i modify them?

fyi it is a 12 V battery pack into a voltage divider and dropped to 4.2 V going into pin A2.

You are right, im sorry i didnt change the coding properly

float readBatteryVoltage() {
  int rawValue = analogRead(batteryPin) ;
  // Convert rawValue to voltage (adjust these values based on your setup)
  float voltage = rawValue * (4.2/ 1023);
  return voltage;
}

int calculateBatteryPercentage(float voltage) {
  // Determine your battery's voltage range and corresponding capacity
  float minVoltage = 10.8; // Minimum voltage
  float maxVoltage = 12.6; // Maximum voltage

  // Calculate battery percentage based on voltage range
  int batteryPercentage = map(voltage, minVoltage, maxVoltage, 0, 100) ;
  batteryPercentage = constrain(batteryPercentage, 0, 100); // Limit to 0-100

  return batteryPercentage;
}

But the 2x16 LCD with I2C Module is still showing (100,75,50,25, 0). I have read some sources saying it might be the Arduino bit transfer limit, im not sure.
Thanks for the correction.

Hello willi12345

Post a schematic of the hardware setup.

#include <LiquidCrystal_I2C.h>
LiquidCrystal_I2C lcd(0x27, 16, 2); // I2C address 0x27, 16 column and 2 rows
const int batteryPin = A2;

void setup() {
  lcd.init(); // initialize the lcd
  lcd.backlight();
  lcd.clear();
}

void loop() {
  float variableBattery = readBatteryVoltage(); // Implement your function to read voltage

  int batteryPercentage = calculateBatteryPercentage(variableBattery);

    lcd.print(" Batt=");
    lcd.print(batteryPercentage);
    lcd.print("%");

    delay(1000); }


float readBatteryVoltage() {
  int rawValue = analogRead(batteryPin) ;
  // Convert rawValue to voltage (adjust these values based on your setup)
  float voltage = rawValue * (4.2/ 1023);
  return voltage;
}

int calculateBatteryPercentage(float voltage) {
  // Determine your battery's voltage range and corresponding capacity
  float minVoltage = 3.6; // Minimum voltage
  float maxVoltage = 4.2; // Maximum voltage

  // Calculate battery percentage based on voltage range
  int batteryPercentage = map(voltage, minVoltage, maxVoltage, 0, 100) ;
  batteryPercentage = constrain(batteryPercentage, 0, 100); // Limit to 0-100

  return batteryPercentage;
}

This is the complete coding, thank you so much for your patience. :blush:

This is the schematic of the hardware set up

Try working in millivolts instead of volts.

float readBatteryVoltage() {
  int rawValue = analogRead(batteryPin) ;
  // Convert rawValue to voltage (adjust these values based on your setup)
  float voltage = rawValue * (4200.0/ 1024);
  return voltage;
}

int calculateBatteryPercentage(float voltage) {
  // Determine your battery's voltage range and corresponding capacity
  float minVoltage = 10800; // Minimum voltage
  float maxVoltage = 12600; // Maximum voltage

  // Calculate battery percentage based on voltage range
  int batteryPercentage = map(voltage, minVoltage, maxVoltage, 0, 100) ;
  batteryPercentage = constrain(batteryPercentage, 0, 100); // Limit to 0-100

  return batteryPercentage;
}

I think the problem is to do with the map() function using integer maths.

1 Like

Thanks for the suggestions, i have tried and it doesnt work :grin:

How is the Arduino powered ? If that is battery as well then simply using Vcc may not tell you much because the analog values are relative to Vcc unless you explicitly use the internal reference voltage. Search for "Arduino secret voltmeter" or similar.

Note that terminal voltage only gives a very loose indication of battery "percentage" - especially with Lithium-based batteries...

1 Like

Strange, it works for me.

(I'm using the Serial Monitor and not an LCD)

1 Like

@willi12345

Battery voltage won't tell you much about the actual battery capacity.
For a Li-ion battery the voltage will read 3.7V during 80% of the discharge time.
During he first 10% it will be above 3.7V and during the last 10% it will be below 3.7V.
So it's not surprising to only see numbers like 100, 75 50, 25.

2 Likes

Yes it is surprising since nothing in his code rounds the value to a factor of 25

If you had say that it's not suprising to see 100% during long time, then 120% (constraints to 100 with his code) and then 70% for eg for 10 last pourcent of its charge, then okay it's not surprising.

But pls have a better look to what he asked and you'll see that this is NOT normal

So do you have a solution to his problem?

Nope I don't since in his code there is no part of it that rounds the value to a factor of 25 according to me... That's why it's not normal and actually even surprising

Correcting you from saying it is not surprising doesn't mean I have a solution. It's just to avoid people that don't know a lot about this stuff to think that something in that code makes the batteryPercentage variable's value rounded to a factor of 25

Peace

Hello willi12345

Consider this small sketch. You might rearrange the voltage levels wrt to procentage given by batterie used.

Have a nice day and enjoy coding in C++.

//https://forum.arduino.cc/t/battery-percentage/1160621
#define ProjectName "Battery percentage"
// make variables
constexpr float R1 {10000.0};
constexpr float R2 {20000.0};
constexpr float VoltageDivider {(R1 + R2) / R1};
constexpr uint8_t PotPin {A2};
// make application
void setup()
{
  Serial.begin(115200);
  Serial.println(ProjectName);
}
void loop()
{
  delay(1000);
  float voltageMeasured {analogRead(PotPin) * 5.0 / 1023.0 * VoltageDivider};
  Serial.print(voltageMeasured), Serial.println(F(" volt"));
  switch ((int)(voltageMeasured * 100.0))
  {
    case 1270 ... 1500: Serial.println(F("100%")); break;
    case 1260 ... 1269: Serial.println(F("90%")); break;
    case 1250 ... 1259: Serial.println(F("80%")); break;
    case 1220 ... 1249: Serial.println(F("50%")); break;
    case 1180 ... 1219: Serial.println(F("10%")); break;
    default: Serial.println(F("change batterie RIP")); break;
  };
}
1 Like

What a lovely way to make a blinking LED!!

1 Like

Oops, that one can go out.

I have adjusted the sketch.

Thanks for the advice.

The processor core in the Arduino has nothing else to do.

@willi12345 , that is exactly your problem. Try changing your function to the old-school linear interpolation:

int calculateBatteryPercentage(float voltage) {
  // Determine your battery's voltage range and corresponding capacity
  float minVoltage = 3.6; // Minimum voltage
  float maxVoltage = 4.2; // Maximum voltage

  return constrain(100 * (voltage - minVoltage) / (maxVoltage - minVoltage),0,100);
}

1 Like

Many ways to skin a cat.
digitalWrite(ledPin, bitRead(millis(), 8));
Leo..