diff options
author | Uwe Freese <thebreaker@rockbox.org> | 2002-12-14 12:10:29 +0000 |
---|---|---|
committer | Uwe Freese <thebreaker@rockbox.org> | 2002-12-14 12:10:29 +0000 |
commit | 5f02797b2e6916cf5f1428415beb96e43a20cf7a (patch) | |
tree | 3bcffc9338efe0148c161e1d7d45cc01141be68f | |
parent | 3c9a109ec242ab58ebc9862b8af32fc9a83138d7 (diff) |
added trickle charge
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@2982 a1c6a512-1295-4272-9138-f99709370657
-rw-r--r-- | apps/debug_menu.c | 2 | ||||
-rw-r--r-- | firmware/powermgmt.c | 95 | ||||
-rw-r--r-- | firmware/powermgmt.h | 10 |
3 files changed, 77 insertions, 30 deletions
diff --git a/apps/debug_menu.c b/apps/debug_menu.c index 2dbe472456..d4e28ab2e2 100644 --- a/apps/debug_menu.c +++ b/apps/debug_menu.c @@ -825,6 +825,8 @@ bool view_battery(void) snprintf(buf, 30, "Est. remaining: %d m", battery_time()); lcd_puts(0, 6, buf); + snprintf(buf, 30, "Trickle sec: %d/60", trickle_sec); + lcd_puts(0, 7, buf); #ifdef HAVE_CHARGE_CTRL #endif break; diff --git a/firmware/powermgmt.c b/firmware/powermgmt.c index 69b28b9f31..c1a546af72 100644 --- a/firmware/powermgmt.c +++ b/firmware/powermgmt.c @@ -33,6 +33,7 @@ #include "mpeg.h" #include "usb.h" #include "powermgmt.h" +#include "../apps/settings.h" #ifdef SIMULATOR @@ -96,7 +97,8 @@ char power_message[POWER_MESSAGE_LEN] = ""; char charge_restart_level = CHARGE_RESTART_HI; int powermgmt_last_cycle_startstop_min = 20; /* how many minutes ago was the charging started or stopped? */ -int powermgmt_last_cycle_level = 0; /* which level had the batteries at this time? */ +int powermgmt_last_cycle_level = 0; /* which level had the batteries at this time? */ +int trickle_sec = 0; /* how many seconds should the charger be enabled per minute for trickle charging? */ #endif @@ -275,36 +277,23 @@ static void handle_auto_poweroff(void) /* * This power thread maintains a history of battery voltage * and implements a charging algorithm. - * Battery 'fullness' can be determined by the voltage drop, see: - * - * http://www.nimhbattery.com/nimhbattery-faq.htm questions 3 & 4 - * http://www.powerpacks-uk.com/Charging%20NiMh%20Batteries.htm - * http://www.angelfire.com/electronic/hayles/charge1.html (soft start idea) - * http://www.powerstream.com/NiMH.htm (discouraging) - * http://www.panasonic.com/industrial/battery/oem/images/pdf/nimhchar.pdf - * http://www.duracell.com/oem/Pdf/others/nimh_5.pdf (discharging) - * http://www.duracell.com/oem/Pdf/others/nimh_6.pdf (charging) - * - * Charging logic which we're starting with (by Linus, Hes, Bagder): - * - * 1) max 16 hrs charge time (just in negative delta detection fails) - * 2) Stop at negative delta of 5 mins - * 3) Stop at 15 mins of zero-delta or below - * 4) minimum of 15 mins charge time before 2) is applied - * 5) after end of charging, wait for charge go down 80% - * before charging again if in 'no-use overnight charging mode' - * and down to 10% if in 'fixed-location mains-powered usage mode' + * For a complete description of the charging algorithm read + * docs/CHARGING_ALGORITHM. */ + static void power_thread(void) { int i; int avg, ok_samples, spin_samples; + int current = 0; #ifdef HAVE_CHARGE_CTRL int delta; int charged_time = 0; int charge_max_time_now = 0; - int charge_pause = 0; /* no charging pause at the beginning */ + int charge_pause = 0; /* no charging pause at the beginning */ + bool trickle_enabled = false; /* enable trickle charging only after a complete charging cycle */ + int trickle_time = 0; /* how many minutes trickle charging already? */ #endif while (1) @@ -343,6 +332,7 @@ static void power_thread(void) /* calculate estimated remaining running time */ /* not charging: remaining running time */ /* charging: remaining charging time */ + #ifdef HAVE_CHARGE_CTRL if (charger_enabled) /* if taking the nocharge battery level, charging lasts 30% longer than the value says */ @@ -353,11 +343,15 @@ static void power_thread(void) } else { powermgmt_est_runningtime_min = (100 - battery_level()) * BATTERY_CAPACITY / 100 * 60 / CURRENT_CHARGING; } - else + else { #endif - powermgmt_est_runningtime_min = battery_level() * BATTERY_CAPACITY / 100 * 60 / CURRENT_NORMAL; + current = CURRENT_NORMAL; + if (global_settings.backlight_timeout == 1) /* LED always on */ + current += CURRENT_BACKLIGHT; + powermgmt_est_runningtime_min = battery_level() * BATTERY_CAPACITY / 100 * 60 / current; #ifdef HAVE_CHARGE_CTRL + } if (charge_pause > 0) charge_pause--; @@ -377,6 +371,7 @@ static void power_thread(void) snprintf(power_message, POWER_MESSAGE_LEN, "Chg tmout %d min", charge_max_time_now); /* disable charging for several hours from this point, just to be sure */ charge_pause = CHARGE_PAUSE_LEN; + /* no trickle charge here, because the charging cycle didn't end the right way */ } else { if (charged_time > CHARGE_MIN_TIME) { /* have charged continuously over the minimum charging time, @@ -400,6 +395,10 @@ static void power_thread(void) snprintf(power_message, POWER_MESSAGE_LEN, "end negd %d %dmin", delta, charged_time); /* disable charging for several hours from this point, just to be sure */ charge_pause = CHARGE_PAUSE_LEN; + /* enable trickle charging */ + trickle_enabled = true; + trickle_sec = CURRENT_NORMAL * 60 / CURRENT_CHARGING; /* first guess, maybe consider if LED backlight is on, disk is active,... */ + trickle_time = 0; } else { /* if we didn't disable the charger in the previous test, check for low positive delta */ delta = ( power_history[POWER_HISTORY_LEN-1] * 100 @@ -416,12 +415,44 @@ static void power_thread(void) snprintf(power_message, POWER_MESSAGE_LEN, "end lowd %d %dmin", delta, charged_time); /* disable charging for several hours from this point, just to be sure */ charge_pause = CHARGE_PAUSE_LEN; + /* enable trickle charging */ + trickle_enabled = true; + trickle_sec = CURRENT_NORMAL * 60 / CURRENT_CHARGING; /* first guess, maybe consider if LED backlight is on, disk is active,... */ + trickle_time = 0; } } } } - } else { - /* charged inserted but not enabled */ + } else { /* charged inserted but not enabled */ + + /* trickle charging */ + if (trickle_enabled) { + /* adjust trickle charge time */ + if ( ((trickle_time <= TOPOFF_MAX_TIME) + && (power_history[POWER_HISTORY_LEN-1] > TOPOFF_VOLTAGE)) + || ((trickle_time > TOPOFF_MAX_TIME) + && (power_history[POWER_HISTORY_LEN-1] > TRICKLE_VOLTAGE)) ) { /* charging too much */ + trickle_sec--; + } else { /* charging too less */ + trickle_sec++; + } + + if (trickle_sec > 24) trickle_sec = 24; + if (trickle_sec < 1) trickle_sec = 1; + + /* charge the calculated amount of seconds */ + charger_enable(true); + sleep(HZ * trickle_sec); + charger_enable(false); + + /* trickle charging long enough? */ + + if (trickle_time++ > TRICKLE_MAX_TIME + TOPOFF_MAX_TIME) { + trickle_enabled = false; + trickle_sec = 0; /* show in debug menu that trickle is off */ + } + } + /* if battery is not full, enable charging */ if (battery_level() < charge_restart_level) { if (charge_pause) { @@ -438,10 +469,10 @@ static void power_thread(void) /* enable the charger after the max time calc is done, because battery_level */ /* depends on if the charger is on */ - DEBUGF("power: charger inserted and battery not full, enabling\n"); + DEBUGF("power: charger inserted and battery not full, enabling\n"); powermgmt_last_cycle_level = battery_level(); powermgmt_last_cycle_startstop_min = 0; - charged_time = 0; + charged_time = 0; charger_enable(true); @@ -460,6 +491,8 @@ static void power_thread(void) DEBUGF("power: charger disconnected, disabling\n"); powermgmt_last_cycle_level = battery_level(); powermgmt_last_cycle_startstop_min = 0; + trickle_enabled = false; + trickle_sec = 0; /* show in debug menu that trickle is off */ charger_enable(false); snprintf(power_message, POWER_MESSAGE_LEN, "Charger disc"); } @@ -470,7 +503,13 @@ static void power_thread(void) #endif /* HAVE_CHARGE_CTRL*/ /* sleep for roughly a minute */ - sleep(HZ*(60 - POWER_AVG_N * POWER_AVG_SLEEP)); +#ifdef HAVE_CHARGE_CTRL + i = 60 - trickle_sec - POWER_AVG_N * POWER_AVG_SLEEP; +#else + i = 60 - POWER_AVG_N * POWER_AVG_SLEEP; +#endif + if (i > 0) + sleep(HZ*(i)); handle_auto_poweroff(); } diff --git a/firmware/powermgmt.h b/firmware/powermgmt.h index 8e8209bc43..21bdb9c4fb 100644 --- a/firmware/powermgmt.h +++ b/firmware/powermgmt.h @@ -30,7 +30,7 @@ #define POWER_HISTORY_LEN 2*60 /* 2 hours of samples, one per minute */ #define POWER_AVG_N 4 /* how many samples to take for each measurement */ -#define POWER_AVG_SLEEP 10 /* how long do we sleep between each measurement */ +#define POWER_AVG_SLEEP 9 /* how long do we sleep between each measurement */ #define CHARGE_END_NEGD 6 /* stop when N minutes have passed with * avg delta being < -0.05 V */ @@ -41,9 +41,14 @@ #define POWER_MESSAGE_LEN 32 /* power thread status message */ #define CHARGE_MAX_TIME 8*60 /* minutes: maximum charging time */ #define CHARGE_MIN_TIME 10 /* minutes: minimum charging time */ -#define CHARGE_RESTART_HI 95 /* %: when to restart charging in 'charge' mode */ +#define CHARGE_RESTART_HI 85 /* %: when to restart charging in 'charge' mode */ + /* attention: if set too high, normal charging is started in trickle mode */ #define CHARGE_RESTART_LO 10 /* %: when to restart charging in 'discharge' mode */ #define CHARGE_PAUSE_LEN 60 /* how many minutes to pause between charging cycles */ +#define TOPOFF_MAX_TIME 90 /* After charging, go to top off charge. How long should top off charge be? */ +#define TOPOFF_VOLTAGE 565 /* which voltage is best? (centivolts) */ +#define TRICKLE_MAX_TIME 12*60 /* After top off charge, go to trickle charge. How long should trickle charge be? */ +#define TRICKLE_VOLTAGE 545 /* which voltage is best? (centivolts) */ extern char power_message[POWER_MESSAGE_LEN]; extern char charge_restart_level; @@ -52,6 +57,7 @@ extern int powermgmt_last_cycle_startstop_min; /* how many minutes ago was the c extern int powermgmt_last_cycle_level; /* which level had the batteries at this time? */ extern int battery_lazyness[20]; /* how does the battery react when plugging in/out the charger */ +extern int trickle_sec; /* trickle charge: How many seconds per minute are we charging actually? */ #endif /* HAVE_CHARGE_CTRL */ |