Battery Benchmark Tool Script

I made a tiny script to benchmark the battery life which I find that could be pretty useful for uConsole.

uConsole has a voltage floor of ~3.18v. This means that we could never reach the marked capacity from the batteries we bought. Most 3.7V batteries has a voltage floor of ~2.8v.

For example, for the famous Samsung 35E, if you check the graph above:

Let’s assume that you’re running a light load on the uConsole. You didn’t enable anything power consuming. This means that no heavy load, no NVME drives, no SDR, no LORA, no active web browsing… just… letting it sit there. Typically, this cost about 5-6w. If you’re using 18650, then dual 18650 would translate to ~0.8Amps. If you’re using LiPo pouch batteries, then it would translate to ~1.6 amps.

If you’re using SDR with light load (no denoise, no image decoding or other fancy features, just listen to radio), then that’s about 6.5-7.5watts. For dual 18650 that’s about ~1amps, and for lipo that’s about ~2amps.

If you’re using a full-fledge uConsole, you would hit the wall hard by forcing it run at 25w. Which is pretty stressful for both powering options. For 18650s that means a ~3.4 amps load, which is still reasonable though not optimal, and for Lipo that’s ~6.8 amps!

No LiPo battery on the market can do that currently with a single pouch. For higher loads you definitely would need a parallel system.

Using the results above, we can get:

Using 35E (3500mah each, 7000 in total):

Light load: you can get 11.25whr each cell, so 22.5whr in total.

Heavy load: you can get 10.25whr each, and 20.5 in total.

Using Lipo (9858102, 10000mah):

My test is that under light load depending on the cell you got you can get anywhere from 24whr to 31whr.

I haven’t tested heavy load situation yet as I don’t have a NVME drive installed.



Here is how to run the test script:

  1. Copy and paste the script into an empty file, like battery_tester.py, save it as your home folder.
  2. Run it with this command: nohup python battery_tester.py
  3. then press Ctrl+Z
  4. then type in command: bg
  5. then you should see it generating a text file logging the battery status.
  6. you can monitor the log by using command: watch -n 3 “tail -n 3 ~/battery_output_log.txt”
  7. after the uConsole crashed due to battery low, you can reboot the system, and type in this command to see the last voltage and whrs used: tail -n 15 ~/battery_output_log.txt
  8. You can also use the head - n 5 ~/battery_output_log.txt command to see when the test started. So that you can get a runtime estimation.

The script:

#!/usr/bin/env python3

import time
import traceback
from datetime import datetime

CURRENT_PATH = "/sys/class/power_supply/axp20x-battery/current_now"
VOLTAGE_PATH = "/sys/class/power_supply/axp20x-battery/voltage_now"
LOG_FILE = "battery_output_log.txt"

INTERVAL = 0.1  # seconds

# Convert (uV * uA * seconds) → mWh
UV_UA_TO_MWH = 1e-9 / 3600.0


def read_int(path):
    with open(path, "r") as f:
        return int(f.read().strip())


def main():
    total_mwh = 0.0
    last_time = time.time()

    with open(LOG_FILE, "a") as log:
        log.write("\n=============================\n")
        log.write(f"Discharge session started at {datetime.now()}\n")

        try:
            while True:
                now = time.time()
                dt = now - last_time
                last_time = now

                try:
                    current_uA = read_int(CURRENT_PATH)
                    voltage_uV = read_int(VOLTAGE_PATH)
                except Exception:
                    log.write("\n--- DRIVER FAILURE ---\n")
                    log.write(f"Time: {datetime.now()}\n")
                    log.write(traceback.format_exc())
                    log.write(f"Output energy before crash: {total_mwh:.3f} mWh\n")
                    log.flush()
                    break

                # Discharge = negative current
                if current_uA < 0:
                    discharge_uA = -current_uA  # make positive magnitude
                    total_mwh += voltage_uV * discharge_uA * dt * UV_UA_TO_MWH

                # Convert only for display
                voltage_V = voltage_uV / 1_000_000
                current_A = current_uA / 1_000_000

                log.write(
                    f"{datetime.now()}, "
                    f"V={voltage_V:.3f}V, "
                    f"I={current_A:.3f}A, "
                    f"Output={total_mwh:.3f} mWh\n"
                )
                log.flush()

                time.sleep(INTERVAL)

        except KeyboardInterrupt:
            log.write("\n--- Stopped by user ---\n")
            log.write(f"Time: {datetime.now()}\n")
            log.write(f"Final discharge energy: {total_mwh:.3f} mWh\n")
            log.flush()


if __name__ == "__main__":
    main()

4 Likes

i don’t understand power, what does 24whr’s mean?

its a measure equivalent of a power consumption ie 24 watts per hour. to get the mAh, you need the formula mAh=(Whx1000)/V

24 watts * hours. it’s the energy units. comparable to joules if you multiply it by 3600.

mAh is not a good way to calculate the energy because nowadays more and more batteries are not using 3.7V nominal voltage anymore. But if it’s a battery that has 3.7V nominal voltage and 3500mah, then you get 3.7*3500/1000 = 12.95 Whr out of it when it’s fully depleted. However with uConsole you can’t fully deplete that battery because it would crash before the battery can be fully depleted.