Last active
April 19, 2022 18:44
-
-
Save sicelo/0a0e895d81a6b73b26555d215dee296d to your computer and use it in GitHub Desktop.
Seed bq27200 capacity with rx51_battery data
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/bin/sh | |
RX51_CAPACITY="/sys/class/power_supply/rx51-battery/charge_full_design" | |
BQ27_CAPACITY="/sys/class/power_supply/bq27200-0/capacity" | |
set -e | |
# Confirm we have root permissions | |
# Unload bq27200 module if it is loaded and no capacity available | |
if lsmod | grep "bq27xxx_battery_i2c" &> /dev/null ; then | |
# If capacity is available, we have nothing to do. Exit | |
CAP=$(cat $BQ27_CAPACITY 2> /dev/null) | |
if [ $? -eq 0 ] && [ $CAP -gt 0 ]; then | |
# Unload rx51_battery (to keep upower happy) | |
modprobe -r rx51_battery | |
exit | |
fi | |
modprobe -r bq27xxx_battery_i2c &> /dev/null | |
fi | |
# check for presence of required tools (i2cset, cut) | |
# Reload bq27200 module if CI flag unset: it is normal battery empty condition | |
# Load rx51_battery. If unsuccessful, make up a capacity (1000mAh makes sense) | |
modprobe rx51_battery &> /dev/null | |
if [ $? -ne 0 ]; then | |
BAT_DESIGN_CAP=1000000 #1000mAh | |
else | |
# Get battery's design capacity as reported by rx51-battery | |
read BAT_DESIGN_CAP < $RX51_CAPACITY | |
fi | |
# Calculate capacity_now based on battery design_capacity | |
# Assume linear relationship between voltage and capacity (inaccurate) | |
read V_NOW < "/sys/class/power_supply/rx51-battery/voltage_now" | |
V_EDVF=3000000 | |
V_MAX=4200000 | |
V_DROP=$(($V_MAX - $V_NOW)) | |
V_RANGE=$(($V_MAX - $V_EDVF)) | |
PERCENT=$((100 * ($V_NOW - $V_EDVF) / $V_RANGE)) | |
CAP_NOW=$(($PERCENT * $BAT_DESIGN_CAP / 100)) | |
# bq27200 sense resistor is needed for calculations. On N900 it is 20 megOhms | |
RS=20 | |
# Convert design capacity to bq27200 NAC format | |
NAC=$(($CAP_NOW * $RS / 3570)) | |
NAC_HEX=$(printf "%04x\n" $NAC) | |
NAC_HEX_HI="0x"$(echo $NAC_HEX | cut -c -2 -) | |
NAC_HEX_LO="0x"$(echo $NAC_HEX | cut -c 3- -) | |
# write desired NAC to AR reg (0x02 & 0x03) | |
# write per byte because i2cset sometimes fails to write a full word | |
i2cset -f -y 2 0x55 0x02 $NAC_HEX_LO # low byte | |
i2cset -f -y 2 0x55 0x03 $NAC_HEX_HI # high byte | |
# Prepare mode register for the write operation | |
CNTRL_CURR=$(i2cget -f -y 2 0x55 0x01) | |
WRTNAC=32 # bit 5 in reg 0x01 | |
# For completeness, (at your own risk), you can also perform: | |
# 1. a partial reset of the chip (NAC, LMD, and CI are unaffected) by: | |
# PRST = 8 | |
# 2. a full reset of the chip (NAC, LMD, and CI also reset) by: | |
# FRST = 2 | |
CNTRL_NEW=$(printf "%#02x" $(($CNTRL_CURR + $WRTNAC))) | |
i2cset -f -y 2 0x55 0x01 $CNTRL_NEW | |
# Perform write of new NAC (via control register) | |
i2cset -f -y 2 0x55 0x00 0xa9 | |
# Reload bq27200 module | |
modprobe bq27xxx_battery_i2c | |
# Unload rx51_battery (to keep upower happy) | |
modprobe -r rx51_battery | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment