[BATT Fix][GB SENSE Kernel] Calibration under Sense and solution for 15% shutdowns!

Search This thread

theGanymedes

Senior Member
Oct 3, 2010
474
253
Hi everyone!

As a desire user myself, some of us are already familiar of what I'm talking about: the famous problem of Desire shutting itself down while it was showing a percentage of 15 (or sometimes even higher) percentages!

This problem is a troublemaker, because it's causing the battery to deplete deeply - which is a bad thing for a Li-Ion battery - and also causing you unguarded: you think that you have enough battery to make it home, but hey; your device is dead!


The reason?

The cause of the problem is battery aging. Even though Li-Ion batteries don't have memory effect problems, they are batteries after all and like every battery they get older and lose their capacity.

Ideally (old or new) the battery shows 3200 mV when empty and 4180 (sometimes 4200) mV when it's full. This never changes unlike NiMH batteries - it's why Li-Ion batteries are told "never to suffer from memory effect". The thing is, cells get older in time and even though they always yield the same voltages, they might not last the same (mAh value gets lower). This is called "aging" in batteries.

In HTC Desire device, there is a Battery Controller chip (it's Maxim DS2784 Chip) that is responsible with the battery capacity, percentage estimation; as well as aging compensation. However, during my examinations (since I did have this 15% shut down problem myself) I've noticed something major in the HTC Desire Sense Kernel sources:

A small code piece in ds2784 battery driver which is written with a false assumption is causing your Desire to think it has full "brand new" capacity, which is not the case if you're owner of an aged one! Due to this, your device thinks it has more capacity, when it's actually empty (which occurs at 15-20% depending on the battery) and shutting down at weird percentages.

Solution?

Well, it's something called "Battery Calibration" which more info can be found on this thread (especially check post #3 for the instructions) : http://xdaforums.com/showthread.php?t=765609
(It's Nexus One dev. forum, but don't mind it - the process is exactly the same for us)

The thing about this calibration is; you have to do it under CM or Oxygen ROM's, because it requires a modified AOSP kernel. During my checks, I've seen that this is actually simply because the Sense kernel lacks some sysfs entries - other than that, Sense driver is also capable of doing this calibration - with the help of Jon Richard's "Battery Calibrator" (available at the Play Store (Market) ).

Also, the calibration data normally (I don't really know why) gets erased when you charge your device while off - the way to fix this is available in here: http://xdaforums.com/showpost.php?p=23317695&postcount=2112

OK.. Is this all?

No. Actually this part is more important.

While I'm including this piece to the Sense Kernel, I've seen the following buggy code piece, which is resetting your battery capacity to 1392 mA - which is wrong (too much) if your battery is aged one:

Code:
if ((htc_batt_info.rep.level != 100) &&
	(htc_batt_info.rep.guage_status_reg & 0x80) &&
	(htc_batt_info.rep.batt_current <= 80) &&
	(htc_batt_info.rep.full_acr == 0)) {

	acr[0] = 0x0d;
	acr[1] = 0x87;
	w1_ds2784_write(di->w1_dev, acr, DS2784_REG_ACCUMULATE_CURR_MSB, 2);
	htc_batt_info.rep.full_acr = 1;
	pr_info("[HTC_BATT] Current Full ACR = %x %x\n", acr[0], acr[1]);
	pr_info("[HTC_BATT] Recharging should set ACR to 100 percent\n");
}

Noticed the "acr" part? That's the part where the driver wrongly assigning 1393 mAh to the DS2784 chip.

If you're to read DS2784 battery specification, under "ACR Housekeeping" part, the following is written ;(ACR - Accumulated Capacity register - the register which shows your current capacity of battery as mAh):

ACR Housekeeping
The ACR value is adjusted occasionally to maintain the coulomb count within the model curve boundaries. When
the battery is charged to full (CHGTF set), the ACR is set equal to the age scaled full lookup value at the present
temperature.

It clearly states that the ACR value, by chip itself, is already updated to the Full value available in ROM chip! The driver doesn't need to do that (and doesn't need to do that WRONG AT ALL!).

This is the problem, because we calibrate our batteries, and then simply because of a buggy assignment of the driver, we lose all the calibration we made!

Cut the story.. Can you fix this?

Well, already did. Attached to the end of this post, there is a "ds2784_battery.c" file which all the stuff I mentioned in this post is applied to. In the kernel source, change in the kernel source dir drivers/power/ds2784_battery.c file with the one I provided and recompile the kernel - voila, you can now calibrate your battery and it no longer will screw your calibration.

Diff patch?

Available below.

Do I have to compile kernel myself? I'm not a geek like you, man!

Flashable recovery zip for kernel is added to the post (named ahmet-exp4_*.zip)!

And here is what completes the circle: The Battery Calibrator App, modified to work with our kernel!

Can be downloaded here
------------

EDIT: I've added the patch file, and also changed the source file itself - I mistakenly forgot to uncomment the parts which include the sysfs interface, sorry :)

-----

ADDENDUM (11.03.12)
: CFS Version is included to the post. Soon, I shall include the Droidzone's battfix into it for high capacity batteries as well, but I kinda think that Droidzone's fix is "not complete" so I'll rewrite it from scratch and thus it does take some time. I guess I can put it next weekend.

-----

ADDENDUM (13.03.12): An improved (?) version of Droidzone's Extended Battery fix has been enabled into the battery driver. Also, HAVS and SVS versions are added for those who prefer (version string does keep these info too, if you forget in the future ;) ). Diff patch is updated with the changes.

About extended batt-fix: Please note that I couldn't test the driver with an Extended battery, but I changed the register parts, so it should run with any battery now since it reads all the data from the Chip's EEPROM instead of using "hardcoded" values.

I also lowered the RSSI values in iw_wl.h file -> now your wifi should not drop so easily as it was in the past (it was -91; I made it -110 ;) ). Diff and edited file are added.

NOTE: My kernels do include nearly all I/O schedulers inside, so that you can change them as you like. If you think your device doesn't perform well with the read/write operations to sd-card or MTD partitions, you can change your I/O scheduler following way:

first, query the modes. You can google-search them to learn what they mean ;) :
--> cat /sys/block/mmcblk0/queue/scheduler (for mmc card)
--> cat /sys/block/mtdblockX/queue/scheduler (for internal memory. X becomes partition number: you can query it with "cat /proc/mtd")

After this, you can pick one and apply that - for instance, say, you picked BFQ (I like it ;) ):

--> echo "bfq" > /sys/block/mmcblk0/queue/scheduler (for mmc card - same applies to MTD too, if you need)

WHY BFQ? Because since SD-cards are Solid State Disks, so they don't have a mechanical head thus V(R) or such schedulers which are optimised for access times are not so optimised for us I think. Instead, we should aim towards the schedulers which takes "load" into consideration. BFQ is one of such schedulers.

I just checked it with my device, I tell you: the results are really amazing :) How much a scheduler matters is exemplified really :D
-----

ADDENDUM (15 March 2012): CFS_SVS Version is updated to EXP5; because of some freeze up problems. This version doesn't add anything else, so the old files still stay at EXP4 version ;)

NOTE: I don't have 2Way Call recording sources, so my kernels don't have that feature (I cannot do everything, can I :p )


---------------
Thank you very much for the donations of Sally Mack
I really appreciate it :) You really save my life with your donations :)
 

Attachments

  • BatteryCalibrator.apk
    420.5 KB · Views: 9,470
  • battery_130312.patch
    13.1 KB · Views: 900
  • ds2784_battery.c
    52.7 KB · Views: 917
  • wifi.patch
    648 bytes · Views: 270
  • wl_iw.h
    7.5 KB · Views: 155
  • ahmet-exp4_cfs_havs.zip
    2.4 MB · Views: 1,413
  • ahmet-exp4_bfs_havs.zip
    2.4 MB · Views: 790
  • ahmet-exp4_bfs_svs.zip
    2.4 MB · Views: 645
  • ahmet-exp5_cfs_svs.zip
    2.4 MB · Views: 2,116
Last edited:

theGanymedes

Senior Member
Oct 3, 2010
474
253
F A Q

1- I open the app, but all the values look empty!

It's because you are not using a compatible kernel. As far as I know, only mine and Droidzone's latest kernels do have the necessary patches, so switch to one of them.

2-I cannot drop to 3201 mV!

Some batteries cannot drop into that level, it's true. If your device turns off at higher voltages - like 3400 mV - you can use this value for your registers instead. Please read the following pages or DS2784 chip spec.to use your own value here (key registers are 62 and 63)

3- I drop to 3201 mV, it says "plug the charger" and I plugged. Still device turns off!

This is due to Sense kernels using a different power supply drivers than AOSP kernels; and due to Sense kernels being "less sensitive" to the changes in battery status, thus not sensing the charger plugged it. In order to overcome this, you must decrease your battery usage to a minimum so that your battery can last a little more - just enough for Power Supply driver to sense it. To achive this:

1- At about 3350 mV values, turn on the Airplane mode; decrease the screen brightness to a very low value.
2- Once the program tells you to plug in, plug in right away and then turn your screen off with the power button.

If your device is not turned off within 2 minutes, your learning phase should have begun.

4- Still the phone turns off at 3201 mV!

It's very much likely those solutions above will work; but in case they don't and you want an "easier" calibration - try calibration at some AOSP ROM like Cyanogen Mode ROM or Oxygen ROM (i.e. you have to change your ROM at least temporarily) . AOSP kernels are more "open" to calibration.


5- Do I need "ahmet" kernels for AOSP?

No. All current AOSP Roms come with a modified kernel that's already supporting the calibration - and they are also free of the Sense kernel bug mentioned above since they're completely written from scratch!


6- Can I change ROMs or Kernels after the calibration?

Changing ROMs are OK as long as you use ahmet or Droidzone's latest kernels (i.e. kernels that support calibration) with your new ROM. You should flash the ROM prior to booting your device for the first time.

NOTE HERE: If you're to flash AOSP ROM, don't use ahmet-exp kernels with them since ahmet-exp kernels are Sense kernels. All AOSP ROMs are calibration friendly anyway.

Changing kernels is a tad more tricky: you can change into the kernels that support calibration only: that is either into ahmet-exp or Droidzone kernels.
 
Last edited:

nomatterbv

Member
Apr 19, 2010
40
9
Brasov
Good work, I'm glad that somebody found a solution for this problem.
I'm waiting for the fix, can't wait to test it and see how it goes after that, if it'll help my batt and increases it's life.
What else to say, thumbs up and keep up the good work.
 

nomatterbv

Member
Apr 19, 2010
40
9
Brasov
So is needed one battery calibration after change the kernel?

Tapatalking

After every flash/ROM change it is advised to wipe battery stats and calibrate it if you flashed while your phone was plugged in to USB or charger.
This is logic, new ROM, new stats.a battery stats wipe is advised as I said but calibration...I don't think so, you need to do that just once (as I saw on other threads).
What I do after flashing a new ROM/kernel is just to let the phone discharge untill it shuts down, charge till it's full and wipe battery stats.
 

ironjon

Senior Member
After every flash/ROM change it is advised to wipe battery stats and calibrate it if you flashed while your phone was plugged in to USB or charger.
This is logic, new ROM, new stats.a battery stats wipe is advised as I said but calibration...I don't think so, you need to do that just once (as I saw on other threads).
What I do after flashing a new ROM/kernel is just to let the phone discharge untill it shuts down, charge till it's full and wipe battery stats.

I' ve done that many times and my phone still shutdown at 15% aprox

Tapatalking
 

nomatterbv

Member
Apr 19, 2010
40
9
Brasov
I' ve done that many times and my phone still shutdown at 15% aprox

Tapatalking

I flashed the ROM which is in my signature, optimised it and I don't have that problem any more (it shuts down at 2-3%, when it reaches that % it drops down to 0 instantly).
Try to flash other ROM and change kernel, also use the latest RIL and Radio, it might help you. for me it worked.
Just wait untill theGanymedes posts the fix, flash it and see if it'll help you out, it'll need some tests but anyway, I think it will help.
 

ironjon

Senior Member
I flashed the ROM which is in my signature, optimised it and I don't have that problem any more (it shuts down at 2-3%, when it reaches that % it drops down to 0 instantly).
Try to flash other ROM and change kernel, also use the latest RIL and Radio, it might help you. for me it worked.
Just wait untill theGanymedes posts the fix, flash it and see if it'll help you out, it'll need some tests but anyway, I think it will help.

Thx

I'm trying to fix it with the latest bananacakes' sources but I got some errors:

jon@jon-laptop:~/android/kernel/bananacakes-bravo_2.6.35_gb-mr-f42e76d$ make ARCH=arm CROSS_COMPILE=arm-linux-androideabi- -j10
CHK include/linux/version.h
CHK include/generated/utsrelease.h
make[1]: `include/generated/mach-types.h' is up to date.
CALL scripts/checksyscalls.sh
CHK include/generated/compile.h
GEN .version
CHK include/generated/compile.h
UPD include/generated/compile.h
CC init/version.o
LD init/built-in.o
LD .tmp_vmlinux1
mm/built-in.o: In function `frontswap_curr_pages':
/home/jon/android/kernel/bananacakes-bravo_2.6.35_gb-mr-f42e76d/mm/frontswap.c:235: undefined reference to `swap_list'
/home/jon/android/kernel/bananacakes-bravo_2.6.35_gb-mr-f42e76d/mm/frontswap.c:235: undefined reference to `swap_info'
mm/built-in.o: In function `frontswap_shrink':
/home/jon/android/kernel/bananacakes-bravo_2.6.35_gb-mr-f42e76d/mm/frontswap.c:207: undefined reference to `try_to_unuse'
/home/jon/android/kernel/bananacakes-bravo_2.6.35_gb-mr-f42e76d/mm/frontswap.c:214: undefined reference to `swap_info'
/home/jon/android/kernel/bananacakes-bravo_2.6.35_gb-mr-f42e76d/mm/frontswap.c:214: undefined reference to `swap_list'
mm/built-in.o: In function `__frontswap_flush_area':
/home/jon/android/kernel/bananacakes-bravo_2.6.35_gb-mr-f42e76d/mm/frontswap.c:153: undefined reference to `swap_info'
mm/built-in.o: In function `__frontswap_flush_page':
/home/jon/android/kernel/bananacakes-bravo_2.6.35_gb-mr-f42e76d/mm/frontswap.c:139: undefined reference to `swap_info'
mm/built-in.o: In function `__frontswap_get_page':
/home/jon/android/kernel/bananacakes-bravo_2.6.35_gb-mr-f42e76d/mm/frontswap.c:125: undefined reference to `swap_info'
mm/built-in.o: In function `__frontswap_put_page':
/home/jon/android/kernel/bananacakes-bravo_2.6.35_gb-mr-f42e76d/mm/frontswap.c:104: undefined reference to `swap_info'
make: *** [.tmp_vmlinux1] Error 1

Better to wait the patch :D
 

Drefsab

Senior Member
May 18, 2010
874
176
great work this is something I'm really glad to see as I get caught out by this bug a lot, the question is now are there any pro compiled kernel flashes available that use this.

Im using Runnymede AIO v6.0.7 SE so would need a sense based kernel that works well with that.
 

nomatterbv

Member
Apr 19, 2010
40
9
Brasov
great work this is something I'm really glad to see as I get caught out by this bug a lot, the question is now are there any pro compiled kernel flashes available that use this.

Im using Runnymede AIO v6.0.7 SE so would need a sense based kernel that works well with that.

You'll find here everything you need, including sense kernels :)
 

Alex-V

Inactive Recognized Developer
Aug 26, 2008
9,514
5,254
wow...nice thing...good work... :) thx for this...

but i hope we can get a diff patch...as i think if i use your file the batt charge fix is gone or...did you use droidzone patch also..?

with kind regards
 

Droidzone

Inactive Recognized Developer
Sep 24, 2010
5,531
2,283
Kochi
www.droidzone.in
OnePlus 9 Pro
wow...nice thing...good work... :) thx for this...

but i hope we can get a diff patch...as i think if i use your file the batt charge fix is gone or...did you use droidzone patch also..?

with kind regards

You can use this. :)

Thanks, theGanymedes. This was on my todo list for a long time.
 

Attachments

  • 0007-Battery-calibration-driver.patch
    12.7 KB · Views: 161

theGanymedes

Senior Member
Oct 3, 2010
474
253
Yeah, SNQ didn't release his sources, alas.

And thank you Droidzone! I don't know what would we do without you :) However, your patch is faulty - for some reason, it messes all the file. I've included the patch that'll do it correctly to the first post ;)

About the battery fix - I didn't touch that part but know that bananacakes's sources do have them.

Compiled kernel is delaying a little bit - because my toolchain is faulty, for some reason producing unbootable kernels - going to upload it to the first post when it's ready.

Also another thing: since the sysfs interface placement is different than AOSP kernels, the battery calibrator app on the Market doesn't work with our patch - the files necessary for the program to work is in somewhere else in our system. So, I'll try to find a way to "create symbolical links" or if I can't, I'll rewrite the app - apparently Jon Richards didn't publish his sources for the app :/
 

Top Liked Posts

  • There are no posts matching your filters.
  • 53
    Hi everyone!

    As a desire user myself, some of us are already familiar of what I'm talking about: the famous problem of Desire shutting itself down while it was showing a percentage of 15 (or sometimes even higher) percentages!

    This problem is a troublemaker, because it's causing the battery to deplete deeply - which is a bad thing for a Li-Ion battery - and also causing you unguarded: you think that you have enough battery to make it home, but hey; your device is dead!


    The reason?

    The cause of the problem is battery aging. Even though Li-Ion batteries don't have memory effect problems, they are batteries after all and like every battery they get older and lose their capacity.

    Ideally (old or new) the battery shows 3200 mV when empty and 4180 (sometimes 4200) mV when it's full. This never changes unlike NiMH batteries - it's why Li-Ion batteries are told "never to suffer from memory effect". The thing is, cells get older in time and even though they always yield the same voltages, they might not last the same (mAh value gets lower). This is called "aging" in batteries.

    In HTC Desire device, there is a Battery Controller chip (it's Maxim DS2784 Chip) that is responsible with the battery capacity, percentage estimation; as well as aging compensation. However, during my examinations (since I did have this 15% shut down problem myself) I've noticed something major in the HTC Desire Sense Kernel sources:

    A small code piece in ds2784 battery driver which is written with a false assumption is causing your Desire to think it has full "brand new" capacity, which is not the case if you're owner of an aged one! Due to this, your device thinks it has more capacity, when it's actually empty (which occurs at 15-20% depending on the battery) and shutting down at weird percentages.

    Solution?

    Well, it's something called "Battery Calibration" which more info can be found on this thread (especially check post #3 for the instructions) : http://xdaforums.com/showthread.php?t=765609
    (It's Nexus One dev. forum, but don't mind it - the process is exactly the same for us)

    The thing about this calibration is; you have to do it under CM or Oxygen ROM's, because it requires a modified AOSP kernel. During my checks, I've seen that this is actually simply because the Sense kernel lacks some sysfs entries - other than that, Sense driver is also capable of doing this calibration - with the help of Jon Richard's "Battery Calibrator" (available at the Play Store (Market) ).

    Also, the calibration data normally (I don't really know why) gets erased when you charge your device while off - the way to fix this is available in here: http://xdaforums.com/showpost.php?p=23317695&postcount=2112

    OK.. Is this all?

    No. Actually this part is more important.

    While I'm including this piece to the Sense Kernel, I've seen the following buggy code piece, which is resetting your battery capacity to 1392 mA - which is wrong (too much) if your battery is aged one:

    Code:
    if ((htc_batt_info.rep.level != 100) &&
    	(htc_batt_info.rep.guage_status_reg & 0x80) &&
    	(htc_batt_info.rep.batt_current <= 80) &&
    	(htc_batt_info.rep.full_acr == 0)) {
    
    	acr[0] = 0x0d;
    	acr[1] = 0x87;
    	w1_ds2784_write(di->w1_dev, acr, DS2784_REG_ACCUMULATE_CURR_MSB, 2);
    	htc_batt_info.rep.full_acr = 1;
    	pr_info("[HTC_BATT] Current Full ACR = %x %x\n", acr[0], acr[1]);
    	pr_info("[HTC_BATT] Recharging should set ACR to 100 percent\n");
    }

    Noticed the "acr" part? That's the part where the driver wrongly assigning 1393 mAh to the DS2784 chip.

    If you're to read DS2784 battery specification, under "ACR Housekeeping" part, the following is written ;(ACR - Accumulated Capacity register - the register which shows your current capacity of battery as mAh):

    ACR Housekeeping
    The ACR value is adjusted occasionally to maintain the coulomb count within the model curve boundaries. When
    the battery is charged to full (CHGTF set), the ACR is set equal to the age scaled full lookup value at the present
    temperature.

    It clearly states that the ACR value, by chip itself, is already updated to the Full value available in ROM chip! The driver doesn't need to do that (and doesn't need to do that WRONG AT ALL!).

    This is the problem, because we calibrate our batteries, and then simply because of a buggy assignment of the driver, we lose all the calibration we made!

    Cut the story.. Can you fix this?

    Well, already did. Attached to the end of this post, there is a "ds2784_battery.c" file which all the stuff I mentioned in this post is applied to. In the kernel source, change in the kernel source dir drivers/power/ds2784_battery.c file with the one I provided and recompile the kernel - voila, you can now calibrate your battery and it no longer will screw your calibration.

    Diff patch?

    Available below.

    Do I have to compile kernel myself? I'm not a geek like you, man!

    Flashable recovery zip for kernel is added to the post (named ahmet-exp4_*.zip)!

    And here is what completes the circle: The Battery Calibrator App, modified to work with our kernel!

    Can be downloaded here
    ------------

    EDIT: I've added the patch file, and also changed the source file itself - I mistakenly forgot to uncomment the parts which include the sysfs interface, sorry :)

    -----

    ADDENDUM (11.03.12)
    : CFS Version is included to the post. Soon, I shall include the Droidzone's battfix into it for high capacity batteries as well, but I kinda think that Droidzone's fix is "not complete" so I'll rewrite it from scratch and thus it does take some time. I guess I can put it next weekend.

    -----

    ADDENDUM (13.03.12): An improved (?) version of Droidzone's Extended Battery fix has been enabled into the battery driver. Also, HAVS and SVS versions are added for those who prefer (version string does keep these info too, if you forget in the future ;) ). Diff patch is updated with the changes.

    About extended batt-fix: Please note that I couldn't test the driver with an Extended battery, but I changed the register parts, so it should run with any battery now since it reads all the data from the Chip's EEPROM instead of using "hardcoded" values.

    I also lowered the RSSI values in iw_wl.h file -> now your wifi should not drop so easily as it was in the past (it was -91; I made it -110 ;) ). Diff and edited file are added.

    NOTE: My kernels do include nearly all I/O schedulers inside, so that you can change them as you like. If you think your device doesn't perform well with the read/write operations to sd-card or MTD partitions, you can change your I/O scheduler following way:

    first, query the modes. You can google-search them to learn what they mean ;) :
    --> cat /sys/block/mmcblk0/queue/scheduler (for mmc card)
    --> cat /sys/block/mtdblockX/queue/scheduler (for internal memory. X becomes partition number: you can query it with "cat /proc/mtd")

    After this, you can pick one and apply that - for instance, say, you picked BFQ (I like it ;) ):

    --> echo "bfq" > /sys/block/mmcblk0/queue/scheduler (for mmc card - same applies to MTD too, if you need)

    WHY BFQ? Because since SD-cards are Solid State Disks, so they don't have a mechanical head thus V(R) or such schedulers which are optimised for access times are not so optimised for us I think. Instead, we should aim towards the schedulers which takes "load" into consideration. BFQ is one of such schedulers.

    I just checked it with my device, I tell you: the results are really amazing :) How much a scheduler matters is exemplified really :D
    -----

    ADDENDUM (15 March 2012): CFS_SVS Version is updated to EXP5; because of some freeze up problems. This version doesn't add anything else, so the old files still stay at EXP4 version ;)

    NOTE: I don't have 2Way Call recording sources, so my kernels don't have that feature (I cannot do everything, can I :p )


    ---------------
    Thank you very much for the donations of Sally Mack
    I really appreciate it :) You really save my life with your donations :)
    18
    I have read a lot about the calibration and the issues with it, and summarized a few sources to ONE BIG TUTORIAL (if you find mistakes, write me pls):

    Advanced Battery Calibration for HTC Desire and Nexus One on NON-SENSE KERNELS


    Intro:
    This will actually calibrate your battery, unlike other methods out there. After calibration, empty will be at 0% not some arbitrary value like 18%. After the real calibration, step 4 is really important, because somehow the phone resets a value when you charge it while it’s turned off, so don’t forget this!


    Be careful!:
    When entering the values for the battery registers, pay particular attention that the entered values are the correct ones which are shown below. Failure to enter these values correctly could result in your battery being permanently bricked. You have been warned! I take no responsibility for any damage!


    Pre-requisites:
    • compatible kernel installed (Cyanogenmod, Oxygen, and probably more) - Sense Kernels need a bit more tweaking, what you can read here: http://xdaforums.com/showthread.php?t=1534892
    • Patience
    • Jon Richards’ “Nexus One Battery Calibrator” application a.k.a. NOBCAP (available on google play), installed
    • An almost dead battery (that is mis-reporting its capacity) with what you think is about ~2% remaining – i.e. if your battery dies at 18%, get ready at about 20%
    • AC battery charger at the ready


    Process:

    0. Run NOBCAP

    a. If General tab displays fields but no values, kernel is wrong, see pre-requisites
    b. If General tab displays fields filled with values, kernel is right, enable airplane mode on the phone

    1. Use the battery calibrator app v.1.3.0 to do the following:

    a. Open the app and go to menu>settings and check all boxes. Auto-on airplane mode is optional
    b. set your age to 100 using the battery app under the Learn Prep tab and press Save
    c. set your full40 to 1452mAh in the same tab if using the stock capacity OEM battery and press Save
    NOTE: set your full40 to 1650mAh or higher if using an aftermarket battery and save

    2. In the Learn Prep tab:

    a.set your aEvolts to 3201 (type on each line: Register:0x 66 Value: a4 and press save)
    b. set your stop charging current to <20mA (Register:0x 65 Value: 06 and press save)
    c. if Capacity/mAh drops to near empty prior to 3201mV being reached, the app will automatically raise capacity by 200mAh so phone doesn't auto-shutdown prior to reaching 3201mV

    3. Achieving Learn Mode with the app:

    a. turn learn mode on in Learn Mode tab
    NOTE: to hit learn mode you must keep your current mA above -200mA draw at the empty point! The app will automatically enable GPS polling to keep you above the required minimum current draw. Hint: Set screen brightness to maximum!
    b. wait for mV to drop to 3201mV (the learn mode pop-up box will appear & learnf button will light up)
    c. insert charger IMMEDIATELY! (You will see a pop-up message saying Learn Mode is active.)
    d. turn off and close any open apps you have running, but leave Battery Calibrator open.
    e. put phone into airplane mode so that you don’t get unexpected current draw near the full point.
    f. set SetCPU profile to disable overclocking. (set min/max to the same value, ie. 998\998max)
    g. charge for a full 4 hrs with stock battery and screen off, 5 hrs for larger capacity batterys. (When charging completes, the CHGTF flag will be lit, Battery Status Register 0x81 displayed, your battery calibrated.)
    NOTE: if you want to, you can actually use your phone until the charge reaches 80-90%, then use airplane mode and DO NOT touch the phone, peek, turn on the screen....DO NOTHING but walk away til time is up.
    h. unplug and reboot, your new age should be set automatically. Learn is now complete and your phone should now charge to 100% and die at 0-1%. Also, some have reported having to manually power down/power up with the new app to have age reset by the application. If age isn’t change upon reboot, try power off/power on.

    4.) Make the calibration permanent (thx to user "theGanymedes"):

    Since the battery age value is somehow rewritten to 94% when you charge your phone whilst turned off, I recommend editing the full40 value accordingly. In order to do that, first start and successfully complete a learning cycle; and then reboot (or power on/off). After this, you shall see the age value of your battery (say XX%).

    Now, you should calculate "real" mAh value using this:

    Code:
    REAL Capacity = "Real" Full40 Value (1452 in Stock etc.) x Age Percentage (0.XX)
    Now, we must recalculate the "fake" Full40 value and write it to EEPROM, so that our battery will be always calibrated (even charged off):

    Code:
    "Fake" Full40 = Real Capacity / 0.94
    First, we're setting the age back to 94% - it's because the phone does this when charged off anyway. Then write this new “fake” value to Full40 assignment area in the Learn Prep app in the application, press Save and you're done.. Congrulatulations, you just calibrated your battery, even when it's charged off. NOTE: Since some internal calculations also use Full40 value, I recommend you to write rounded to next value, rather than truncated.

    5.) Didn’t work?:
    Phone dies to early?:

    That might be because some kernels do use a different power supply drivers, and these drivers don't update values so often as chip does. Try writing manually the value of "04" to register 0x10 when your battery reaches to 10% or so.
    Learn Failure:

    If your new age shows 94% upon rebooting, then learn mode failed and you need to do it again, paying close attention as charging nears 80% and above. This is where learn mode can be lost by rogue apps, auto-updates, calls, etc pulling the current down below the minimum prematurely.

    Note1: As current gets close to <50-60mA don't touch the phone or you may artifically increase the current draw pulling it below 20mA and it will end the learn cycle prematurely. Airplane mode helps prevent that.

    Note2: Learn mode cannot be achieve with the phone off. Leave the phone on until learn is complete and the battery status register shows 0x81. Done!

    Sources:
    http://xdaforums.com/showpost.php?p=7850480&postcount=3
    http://xdaforums.com/showthread.php?t=765609&highlight=0x10&page=212
    http://xdaforums.com/showthread.php?t=765609&highlight=0x10&page=213
    http://forum.oxygen.im/viewtopic.php?id=723
    http://xdaforums.com/showthread.php?t=1534892

    https://github.com/dvgrhl/BatteryCalibrator
    http://jonrichards.net/
    See page 25 of 43 at http://datasheets.maxim-ic.com/en/ds/DS2784.pdf for flag explanations.
    See page 30 of 43 at http://datasheets.maxim-ic.com/en/ds/DS2784.pdf for register explanations.
    5
    F A Q

    1- I open the app, but all the values look empty!

    It's because you are not using a compatible kernel. As far as I know, only mine and Droidzone's latest kernels do have the necessary patches, so switch to one of them.

    2-I cannot drop to 3201 mV!

    Some batteries cannot drop into that level, it's true. If your device turns off at higher voltages - like 3400 mV - you can use this value for your registers instead. Please read the following pages or DS2784 chip spec.to use your own value here (key registers are 62 and 63)

    3- I drop to 3201 mV, it says "plug the charger" and I plugged. Still device turns off!

    This is due to Sense kernels using a different power supply drivers than AOSP kernels; and due to Sense kernels being "less sensitive" to the changes in battery status, thus not sensing the charger plugged it. In order to overcome this, you must decrease your battery usage to a minimum so that your battery can last a little more - just enough for Power Supply driver to sense it. To achive this:

    1- At about 3350 mV values, turn on the Airplane mode; decrease the screen brightness to a very low value.
    2- Once the program tells you to plug in, plug in right away and then turn your screen off with the power button.

    If your device is not turned off within 2 minutes, your learning phase should have begun.

    4- Still the phone turns off at 3201 mV!

    It's very much likely those solutions above will work; but in case they don't and you want an "easier" calibration - try calibration at some AOSP ROM like Cyanogen Mode ROM or Oxygen ROM (i.e. you have to change your ROM at least temporarily) . AOSP kernels are more "open" to calibration.


    5- Do I need "ahmet" kernels for AOSP?

    No. All current AOSP Roms come with a modified kernel that's already supporting the calibration - and they are also free of the Sense kernel bug mentioned above since they're completely written from scratch!


    6- Can I change ROMs or Kernels after the calibration?

    Changing ROMs are OK as long as you use ahmet or Droidzone's latest kernels (i.e. kernels that support calibration) with your new ROM. You should flash the ROM prior to booting your device for the first time.

    NOTE HERE: If you're to flash AOSP ROM, don't use ahmet-exp kernels with them since ahmet-exp kernels are Sense kernels. All AOSP ROMs are calibration friendly anyway.

    Changing kernels is a tad more tricky: you can change into the kernels that support calibration only: that is either into ahmet-exp or Droidzone kernels.
    4
    How to make battery "think" it's full easier

    Please note that this process does actually let your battery think it's charged to full before it's topped-up, so you might lose, say, up to 10 minutes of battery power after doing this process.

    How to make your battery think it's full in shorter amount of time?

    What's the theory?

    Well, while calibrating our batteries, we write 0x06 to the 65th register area - this area is what's keeping the IMIN (minimum charge current) value, which is used by the DS2784 chip in order to sense the "charge full" event.

    Since there is no "absolute" way to find out when the charge is full in Li-ion batteries, the chip makes a very nice way to overcome this difficulty: since it continuously checks the current level of battery; it makes an assumption such that the battery will be full when the current level is positive and is below of IMIN value for the last two readings (remember we saying that the current should not be ever negative when learning occurs? This is why - if current becomes negative, battery doesn't raise "battery is full" event and learning becomes half-baked!)

    Before the calibration starts, we set the address 65 to 06 - which corresponds to 20.1 mA; so when the battery current level drops below 20mA and is positive for the last two readings; the battery is respected as to be full.

    When the "battery full" even is raised, the DS2784 chip automatically increases the percentage to 100% and ACR (current capacity) level to "full40 * age" value - so basicly it resets the counters to "full" state.

    However, 20mA is really a low value - we actually completely fill our cells with this value. Due to this, it takes longer time to hit 100%, because "real" full capacity can only be hit during saturated-charge cycles - which requires quite long time.

    If you think that it's annoying to wait till your batteries so full that it can't even keep another electron in it ( :) ), you can of course make it "less sensitive" so that the battery will think it's full earlier. Normally, in stock devices, this already applied; but we've overwritten that in calibration.

    To exemplify this case, consider those values: in stock case HTC marks the battery full when current is below 80 mA, whilst we wait till 20mA - this is actually one of the reasons why your battery stays for longer time after it's calibrated - It's simply because we really make it full :)

    You may say that "we overcharge our batteries and this is bad!" but, that's not the case: the batteries are overcharge protected with DS2784. We simply charge it "higher".

    What should we do if we want it to be less sensitive again?


    Well, it's simple. First wait till your battery drops below 90%, so "Charged to Full" flag is cleared. After this, apply those steps; and it'll be done:

    --NOTE: The IMIN value in register 65 is kept in 50 microVolt values. In order to convert this to current(mA) value, we must multiply(divide) this value with 50 * 67 and then divide(multiply) with 1000 while reading (writing to) this value from the register.

    Example: My battery chip has 06 (hex) value in register 65.

    06(hex) = 6 decimal

    6 * 50 * 67 / 1000 = 20.1 mA <--- so my battery currently thinks it's full when current is positive and below 20 mA

    ----
    Let's say, I want it to be 50mA So:

    50 * 1000 / ( 50 * 67) = 14.925 ~= 15 <-- (we can only use integers so we round)

    15 (dec) -> F (hex) <- so I should write F to register 65.

    --> Note: after writing 15 to register 65; you actually make IMIN value 50.2 ;)

    ----
    What if I want to make it 35mAh - which is a better value I think?

    35 * 1000 / (50 * 67) = 10.44 ~= 10 (or 11 if you prefer)

    10 (dec) -> A (hex)
    11 (dec) -> B (hex)

    so I write A (or B) to register 65. This makes my battery raise "battery full" when current level drops below 33.50 mA (or 36.85 mA).

    ---
    NOTE: You can read the register's value with the Battery Calibrator App, using "Dump registers" function - you have to find the 65'th register in that dump (6th from the left on the "60 - " line)
    4
    Good news guys! I finaly did it, calibrated the battery and I don't have any more the shut down issue/problem at 15% and calibrated the battery too.

    Here is what you have to do:

    1. Download the BatteryCalibrator.apk from #1 post,
    2. Set your screen time-out to 10 minutes,
    3. Run the app,
    4. Go to Menu - Settings and:
    a. CHECK: GPS polling, ACR adjustment, advanced options,
    b. UNCHECK: Airplane and Wake lock.
    5. Go to LearnPrep tab:
    a. Set age: 100% --> save,
    b. For OEM batteries set mAh: 1452 --> save; for aftermarket batteries set mAh: 1650 --> save
    c. Register: 0x66, Value: a4 -> save
    d. Register: 0x65, Value: 06 -> save
    e. Register: 0x10, Value: 04 -> save
    6. Go to LearnMode tab,
    7. Scroll down and Set Detect Learn Mode to ON,
    8. When Real-Time Voltage (µV) <= 3201000, i.e. when the battery is “empty”, the app will prompt you to quickly plug in your charger,
    9. If you were successful here, the learn-flag LEARNF will now be lit and your battery charging,
    10. LYPTFA - Leave your phone the .... alone,
    11. When charging completes, the CHGTF flag will be lit, Battery Status Register 0x81 displayed, your battery calibrated,
    12. Unplug. Reboot and enjoy your new battery life :)

    Note: I have a stock 1452mAh batt

    After a lot of searching, coffee and smoke I found out how to REALY calibrate the battery.
    NOTE: ALL CREDITS go to paschadee from the oxygen forums!It's not my work, I don't take any credits for this!

    If you need more information about the calibration you can visit the forum and read more, Here is the forum located.
    If it helped don't be shy to hit the Thanks button >_<
    Best regards.