手機 - Nokia N900 - Debian - Battery Calibration



參考資訊:
http://talk.maemo.org/showpost.php?p=1053809&postcount=846

N900 BQ27200電路圖


步驟如下:
1. 電池充滿電
2. 執行如下命令:

$ sudo apt-get install i2c-tools -y
$ sudo rmmod bq27xxx_battery_i2c
$ sudo rmmod bq27xxx_battery
$ sudo rmmod rx51_battery
$ sudo dd if=/dev/zero of=/dev/null bs=1M &
$ sudo ./bq27200.sh 5

3. 拔掉充電器
4. 接著讓機器放電到0%,電源管理IC就會自動校準

bq27200.sh

#!/bin/sh

# Assuming 30 mOhm sense resistance
RS=21

debugecho()
{
    if [ $LOOPMODE -eq 0 ]; then
        echo $*
    fi
}

debugechon()
{
    if [ $LOOPMODE -eq 0 ]; then
        echo -n $*
    fi
}

dot()
{
    debugechon "."
}

LOOPMODE=0
LOOPCOUNT=0
if [ -n "$1" ] ; then
    if [ $(($1)) -gt 5 ] ; then
        LOOPMODE=$(($1))
    else
        LOOPMODE=5
    fi
fi

echo LOOPMODE=$LOOPMODE

doit=1
while [ $doit -eq 1 ] ; do ## MAIN LOOP ##

doit=0
############## Data acquisition ##############

#debugechon "About to stop bme. "
#killall -STOP bme_RX-51
#debugecho "Bme stopped."
# sleep 1;
debugechon "Reading values"

AR=$(i2cget -y 2 0x55 0x02 w) ; dot
ARTTE=$(i2cget -y 2 0x55 0x04 w); dot
VOLT=$(i2cget -y 2 0x55 0x08 w) ; dot
TEMP=$(i2cget -y 2 0x55 0x06 w) ; dot
CSOC=$(i2cget -y 2 0x55 0x2c)  ; dot
RSOC=$(i2cget -y 2 0x55 0x0b)  ; dot
NAC=$(i2cget -y 2 0x55 0x0c w) ; dot
CACD=$(i2cget -y 2 0x55 0x0e w) ; dot
CACT=$(i2cget -y 2 0x55 0x10 w); dot
AI=$(i2cget -y 2 0x55 0x14 w)  ; dot
TTF=$(i2cget -y 2 0x55 0x18 w) ; dot
TTE=$(i2cget -y 2 0x55 0x16 w) ; dot
FLAGS=$(i2cget -y 2 0x55 0x0A) ; dot


if [ $LOOPMODE -eq 0 ] ; then
    CYCL=$(i2cget -y 2 0x55 0x28 w) ; dot
    CYCLTL=$(i2cget -y 2 0x55 0x2a w) ; dot
    SI=$(i2cget -y 2 0x55 0x1A w) ; dot
    STTE=$(i2cget -y 2 0x55 0x1C w); dot
    MLI=$(i2cget -y 2 0x55 0x1e w) ; dot
    MLTTE=$(i2cget -y 2 0x55 0x20 w); dot
    LMD=$(i2cget -y 2 0x55 0x12 w) ; dot

    ILMD=$(i2cget -y 2 0x55 0x76); dot
    EDVF=$(i2cget -y 2 0x55 0x77); dot
    EDV1=$(i2cget -y 2 0x55 0x78); dot
    ISLC=$(i2cget -y 2 0x55 0x79); dot
    DMFSD=$(i2cget -y 2 0x55 0x7A); dot
    TAPER=$(i2cget -y 2 0x55 0x7B); dot
    #TODO: PKCFG
    IMLC=$(i2cget -y 2 0x55 0x7D); dot
fi

debugecho "done."
#debugechon  "Waking up bme."
#killall -CONT bme_RX-51
#debugecho "Done. "
debugecho ""

############## Calculate ##############

CSOC=$(($CSOC))                      # CSOC Compensated state of charge %. CACT/LMD * 100
RSOC=$(($RSOC))                      # RSOC Relative state of charge %. NAC/LMD * 100
NAC=$(($NAC * 3570 / $RS / 1000))    # NAC Nominal available capaciy, mAh.
CACD=$(($CACD * 3570 / $RS / 1000))  # CACD Discharge rate compensated available capacity, mAh.
CACT=$(($CACT * 3570 / $RS / 1000))  # CACT Temperature compensated CACD, mAh.
AI=$(($AI * 3570 / $RS / 1000))      # AI Average (last 5.12 seconds) current, mA.
VOLT=$(($VOLT))                      # VOLT Battery voltage, mV.
TTF=$(($TTF))                        # TTF Time to Full minutes. 65535 if no charging.
TTE=$(($TTE))                        # TTE Time to Empty minutes. 65535 if charging.

F=$(($FLAGS))
FLAGS_CHARGE=$(($F/128))             # There is charging activity. AI is measuring charge current.
F=$(($F-$F/128*128))
FLAGS_NOACT=$(($F/64))               # No charge/discharge activity detected.
F=$(($F-$F/64*64))
FLAGS_IMIN=$(($F/32))                # Charge current has tapered off (battery charge is near/at completion)
F=$(($F-$F/32*32))
FLAGS_CI=$(($F/16))                  # Capacity inaccurate. >32 cycles since last learning cycle.
F=$(($F-$F/16*16))
FLAGS_CALIP=$(($F/8))                # External offset calibration in progress.
F=$(($F-$F/8*8))
FLAGS_VDQ=$(($F/4))                  # Valid discharge. All requirements met for learning the battery's capacity when reaching EDV1
F=$(($F-$F/4*4))
FLAGS_EDV1=$(($F/2))                 # First end of discharge-voltage flag. Battery voltage is at or below preprogrammed EDV1 threshold. If VDQ is 1, LMD is updated and VDQ set to 0.
F=$(($F-$F/2*2))
FLAGS_EDVF=$F                        # Final end of discharge-voltage flag. The battery has discharged to 0% threshold.


if [ $LOOPMODE -eq 0 ] ; then
    AR=$(($AR * 3570 / $RS / 1000))      # AR At-rate
    ARTTE=$(($ARTTE))                    # At-rate time to empty
    LMD=$(($LMD * 3570 / $RS / 1000))    # LM Last measured discharge, mAh.
    SI=$(($SI * 3570/ $RS / 1000))       # SI Standby Current, mA.
    STTE=$(($STTE))                      # STTE Time to empty at standby, minutes.
    MLI=$(($MLI * 3570 / $RS / 1000))    # MLI Maximum Load Current, mA.
    MLTTE=$(($MLTTE))                    # MLTTE Time to empty at maximum load, minutes.
    CYCL=$(($CYCL))                      # CYCL Cycles since last learning cycle (last time LMD was updated)
    CYCLTL=$(($CYCLTL))                  # CYCLTL Cycles since last full reset.

    ILMD=$(($ILMD * 913920 / $RS / 1000)) # eeprom Initial Last Measured Discharge. LMD = ILMD if no valid learning cycle has been completed.
    EDVF=$(($EDVF * 8 + 8*256))           # eeprom End of discharge voltage threshold.
    EDV1=$(($EDV1 * 8 + 8*256))           # eeprom 6.25% Capacity voltage threshold.
    ISLC=$(($ISLC * 7140 / $RS / 1000))   # eeprom Initial standby load current.

    # DMF in bits 4:7
    DMF=$(($DMFSD/16))
    # SD in bits 0:3
    SD=$(($DMFSD-$DMF*16))
    DMF=$(($DMF * 4900))                 # eeprom Digital Magnitude Filter, nanoVolts
    SD=$((1610 / $SD))                   # eeprom Self Discharge rate, thousandth of percent (1/1000 %) per day at 25 degrees celcius

    AGELMD=$(($TAPER/128))               # eeprom Battery capacity aging estimation on/off
    TAPER=$(($TAPER-$AGELMD*128))
    TAPER=$(($TAPER * 228000 / $RS / 1000))  # eeprom Taper current mA

    IMLC=$(($IMLC * 457000 / $RS / 1000))    # eeprom Initial Max Load Current
fi

############## Display ##############

if [ $LOOPMODE -eq 0 ] ; then 
    echo -n CSOC: $CSOC "% "
    echo RSOC: $RSOC "%"
    echo Average Current: $AI mA
    echo -n TTF: $(($TTF)) "minutes "
    echo TTE: $(($TTE)) minutes

    echo -n NAC: $NAC "mAh "
    echo -n CACD: $CACD "mAh "
    echo CACT: $CACT "mAh "

    echo -n SI: $SI "mA "
    echo  STTE: $STTE "minutes"

    echo -n MLI: $MLI "mA "
    echo  MLTTE: $MLTTE "minutes"

    echo -n AR: $AR "mA "
    echo ARTTE: $ARTTE "minutes"

    echo Last Measured Discharge: $LMD mAh
    echo Cycle Count since Learning: $CYCL Total Cycle Count since last full reset: $CYCLTL
    echo Reported Battery Voltage: $VOLT mV
    echo Battery Gauge die Temperature: $(($TEMP * 250 / 1000 - 273)) C
    echo -e "Flags:\t" $FLAGS
    echo -e "\t" Charge:$FLAGS_CHARGE NOACT:$FLAGS_NOACT IMIN:$FLAGS_IMIN CI:$FLAGS_CI CALIP:$FLAGS_CALIP VDQ:$FLAGS_VDQ EDV1:$FLAGS_EDV1 EDVF: $FLAGS_EDVF
    echo -e "eeprom data:"
    echo -e "\t" ILMD=$ILMD EDVF=$EDVF EDV1=$EDV1 ISLC=$ISLC
    echo -e "\t" DMF=$DMF nanoVolt SD=$SD thousandths of percent per day
    echo -e "\t" AGELMD=$AGELMD TAPER=$TAPER mA
    echo -e "\t" IMLC=$IMLC mA
else # loopmode
    if [ $LOOPCOUNT -eq 0 ] ; then
        LOOPCOUNT=24
        echo -e "      mv   RSOC CSOC mA   NAC  CACD CACT TTF   TTE   TEMP EDV1 LOW"
    fi
    LOOPCOUNT=$(($LOOPCOUNT-1))

    C=$AI
    if [ $FLAGS_CHARGE -eq 0 ] ; then
        C="-"$C
    fi
    printf "$(date +%H:%M) %4d %-3d  %-3d  %-4d %-4d %-4d %-4d %-5d %-5d %-3d %d\n" $VOLT $RSOC $CSOC $C $NAC $CACD $CACT $TTF $TTE $(($TEMP * 250 /1000 - 273)) $FLAGS_EDV1 

    if [ $FLAGS_EDV1 -eq 1 ] ; then
        poweroff
    fi

    sleep $LOOPMODE
    doit=1
fi # if loopmode

done # main