Archos V1 recorder charging path #2927 by Alun Thomas

git-svn-id: svn://svn.rockbox.org/rockbox/trunk@8898 a1c6a512-1295-4272-9138-f99709370657
This commit is contained in:
Jörg Hohensohn 2006-03-04 09:48:53 +00:00
parent c7838b8418
commit ea5df70e46
3 changed files with 88 additions and 36 deletions

View file

@ -176,3 +176,4 @@ Aaron F. Gonzalez
Aleksey Kozyulin Aleksey Kozyulin
Jani Kinnunen Jani Kinnunen
Rui Marinho Rui Marinho
Alun Thomas

View file

@ -39,10 +39,10 @@
#define POWER_HISTORY_LEN 2*60 /* 2 hours of samples, one per minute */ #define POWER_HISTORY_LEN 2*60 /* 2 hours of samples, one per minute */
#define CHARGE_END_NEGD 6 /* stop when N minutes have passed with #define CHARGE_END_SHORTD 6 /* stop when N minutes have passed with
* avg delta being < -0.05 V */ * avg delta being < -0.05 V */
#define CHARGE_END_ZEROD 50 /* stop when N minutes have passed with #define CHARGE_END_LONGD 50 /* stop when N minutes have passed with
* avg delta being < 0.005 V */ * avg delta being < -0.02 V */
#ifndef SIMULATOR #ifndef SIMULATOR

View file

@ -175,7 +175,8 @@ charge_state_type charge_state; /* charging mode */
#ifdef HAVE_CHARGE_CTRL #ifdef HAVE_CHARGE_CTRL
int long_delta; /* long term delta battery voltage */ int long_delta; /* long term delta battery voltage */
int short_delta; /* short term delta battery voltage */ int short_delta; /* short term delta battery voltage */
bool disk_activity_last_cycle = false; /* flag set to aid charger time
* calculation */
char power_message[POWER_MESSAGE_LEN] = ""; /* message that's shown in char power_message[POWER_MESSAGE_LEN] = ""; /* message that's shown in
debug menu */ debug menu */
/* percentage at which charging /* percentage at which charging
@ -580,7 +581,12 @@ static void power_thread_sleep(int ticks)
battery_status_update(); battery_status_update();
} }
#ifdef HAVE_CHARGE_CTRL
if (ata_disk_is_active()) {
/* flag hdd use for charging calculation */
disk_activity_last_cycle = true;
}
#endif
#if defined(DEBUG_FILE) && defined(HAVE_CHARGE_CTRL) #if defined(DEBUG_FILE) && defined(HAVE_CHARGE_CTRL)
/* /*
* If we have a lot of pending writes or if the disk is spining, * If we have a lot of pending writes or if the disk is spining,
@ -608,9 +614,15 @@ static void power_thread(void)
int i; int i;
short *phps, *phpd; /* power history rotation pointers */ short *phps, *phpd; /* power history rotation pointers */
#ifdef HAVE_CHARGE_CTRL #ifdef HAVE_CHARGE_CTRL
unsigned int target_voltage; /* desired topoff/trickle voltage level */ unsigned int target_voltage = TRICKLE_VOLTAGE; /* desired topoff/trickle
int charge_max_time_now = 0; /* max. charging duration, calculated at * voltage level */
beginning of charging */ int charge_max_time_idle = 0; /* max. charging duration, calculated at
* beginning of charging */
int charge_max_time_now = 0; /* max. charging duration including
* hdd activity */
int minutes_disk_activity = 0; /* count minutes of hdd use during
* charging */
int last_disk_activity = CHARGE_END_LONGD + 1; /* last hdd use x mins ago */
#endif #endif
/* initialize the voltages for the exponential filter */ /* initialize the voltages for the exponential filter */
@ -669,19 +681,23 @@ static void power_thread(void)
powermgmt_last_cycle_startstop_min = 0; powermgmt_last_cycle_startstop_min = 0;
if(battery_percent >= START_TRICKLE_CHG) { if(battery_percent >= START_TRICKLE_CHG) {
charge_state = TRICKLE; charge_state = TRICKLE;
target_voltage = TRICKLE_VOLTAGE;
} else { } else {
charge_state = TOPOFF; charge_state = TOPOFF;
target_voltage = TOPOFF_VOLTAGE;
} }
} else { } else {
/* /*
* Start the charger full strength * Start the charger full strength
*/ */
i = CHARGE_MAX_TIME_1500 * battery_capacity / 1500; i = CHARGE_MAX_TIME_1500 * battery_capacity / 1500;
charge_max_time_now = charge_max_time_idle =
i * (100 + 35 - battery_percent) / 100; i * (100 + 35 - battery_percent) / 100;
if (charge_max_time_now > i) { if (charge_max_time_idle > i) {
charge_max_time_now = i; charge_max_time_idle = i;
} }
charge_max_time_now = charge_max_time_idle;
snprintf(power_message, POWER_MESSAGE_LEN, snprintf(power_message, POWER_MESSAGE_LEN,
"ChgAt %d%% max %dm", battery_level(), "ChgAt %d%% max %dm", battery_level(),
charge_max_time_now); charge_max_time_now);
@ -699,26 +715,44 @@ static void power_thread(void)
} }
} }
if (charge_state == CHARGING) { if (charge_state == CHARGING) {
snprintf(power_message, POWER_MESSAGE_LEN, /* alter charge time max length with extra disk use */
"Chg %dm, max %dm", powermgmt_last_cycle_startstop_min, if (disk_activity_last_cycle) {
charge_max_time_now); minutes_disk_activity++;
charge_max_time_now = charge_max_time_idle +
(minutes_disk_activity * 2 / 5);
disk_activity_last_cycle = false;
last_disk_activity = 0;
} else {
last_disk_activity++;
}
/* /*
* Check the delta voltage over the last X minutes so we can do * Check the delta voltage over the last X minutes so we can do
* our end-of-charge logic based on the battery level change. * our end-of-charge logic based on the battery level change.
*(no longer use minimum time as logic for charge end has 50
* minutes minimum charge built in)
*/ */
if (powermgmt_last_cycle_startstop_min > CHARGE_MIN_TIME) { if (powermgmt_last_cycle_startstop_min > CHARGE_END_SHORTD) {
short_delta = power_history[0] - short_delta = power_history[0] -
power_history[CHARGE_END_NEGD - 1]; power_history[CHARGE_END_SHORTD - 1];
} }
if (powermgmt_last_cycle_startstop_min > CHARGE_END_ZEROD) {
if (powermgmt_last_cycle_startstop_min > CHARGE_END_LONGD) {
/* /*
* Scan the history: if we have a big delta in the middle of * Scan the history: the points where measurement is taken need to
* our history, the long term delta isn't a valid end-of-charge * be fairly static. (check prior to short delta 'area')
* indicator. * (also only check first and last 10 cycles - delta in middle OK)
*/ */
long_delta = power_history[0] - long_delta = power_history[0] -
power_history[CHARGE_END_ZEROD - 1]; power_history[CHARGE_END_LONGD - 1];
for(i = 0; i < CHARGE_END_ZEROD; i++) {
for(i = CHARGE_END_SHORTD; i < CHARGE_END_SHORTD + 10; i++) {
if(((power_history[i] - power_history[i+1]) > 5) ||
((power_history[i] - power_history[i+1]) < -5)) {
long_delta = 777777;
break;
}
}
for(i = CHARGE_END_LONGD - 11; i < CHARGE_END_LONGD - 1 ; i++) {
if(((power_history[i] - power_history[i+1]) > 5) || if(((power_history[i] - power_history[i+1]) > 5) ||
((power_history[i] - power_history[i+1]) < -5)) { ((power_history[i] - power_history[i+1]) < -5)) {
long_delta = 888888; long_delta = 888888;
@ -727,21 +761,26 @@ static void power_thread(void)
} }
} }
snprintf(power_message, POWER_MESSAGE_LEN,
"Chg %dm, max %dm", powermgmt_last_cycle_startstop_min,
charge_max_time_now);
/* /*
* End of charge criteria (any qualify): * End of charge criteria (any qualify):
* 1) Charged a long time * 1) Charged a long time
* 2) DeltaV went negative for a short time * 2) DeltaV went negative for a short time ( & long delta static)
* 3) DeltaV was close to zero for a long time * 3) DeltaV was negative over a longer period (no disk use only)
* Note: short_delta and long_delta are centivolts * Note: short_delta and long_delta are centivolts
*/ */
if ((powermgmt_last_cycle_startstop_min > charge_max_time_now) || if ((powermgmt_last_cycle_startstop_min >= charge_max_time_now) ||
(short_delta <= -5) || (long_delta < 5)) (short_delta <= -5 && long_delta < 5 ) || (long_delta < -2 &&
{ last_disk_activity > CHARGE_END_LONGD)) {
if (powermgmt_last_cycle_startstop_min > charge_max_time_now) { if (powermgmt_last_cycle_startstop_min > charge_max_time_now) {
DEBUGF("power: powermgmt_last_cycle_startstop_min > charge_max_time_now, " DEBUGF("power: powermgmt_last_cycle_startstop_min > charge_max_time_now, "
"enough!\n"); "enough!\n");
/* have charged too long and deltaV detection did not /*
work! */ *have charged too long and deltaV detection did not
*work!
*/
snprintf(power_message, POWER_MESSAGE_LEN, snprintf(power_message, POWER_MESSAGE_LEN,
"Chg tmout %d min", charge_max_time_now); "Chg tmout %d min", charge_max_time_now);
/* /*
@ -753,6 +792,16 @@ static void power_thread(void)
powermgmt_last_cycle_level = battery_percent; powermgmt_last_cycle_level = battery_percent;
powermgmt_last_cycle_startstop_min = 0; powermgmt_last_cycle_startstop_min = 0;
charge_state = TRICKLE; charge_state = TRICKLE;
/*
* set trickle charge target to a relative voltage instead
* of an arbitrary value - the fully charged voltage may
* vary according to ambient temp, battery condition etc
* trickle target is -0.15v from full voltage acheived
* topup target is -0.05v from full voltage
*/
target_voltage = power_history[0] - 15;
} else { } else {
if(short_delta <= -5) { if(short_delta <= -5) {
DEBUGF("power: short-term negative" DEBUGF("power: short-term negative"
@ -760,12 +809,16 @@ static void power_thread(void)
snprintf(power_message, POWER_MESSAGE_LEN, snprintf(power_message, POWER_MESSAGE_LEN,
"end negd %d %dmin", short_delta, "end negd %d %dmin", short_delta,
powermgmt_last_cycle_startstop_min); powermgmt_last_cycle_startstop_min);
target_voltage = power_history[CHARGE_END_SHORTD - 1]
- 5;
} else { } else {
DEBUGF("power: long-term small " DEBUGF("power: long-term small "
"positive delta, enough!\n"); "positive delta, enough!\n");
snprintf(power_message, POWER_MESSAGE_LEN, snprintf(power_message, POWER_MESSAGE_LEN,
"end lowd %d %dmin", long_delta, "end lowd %d %dmin", long_delta,
powermgmt_last_cycle_startstop_min); powermgmt_last_cycle_startstop_min);
target_voltage = power_history[CHARGE_END_LONGD - 1]
- 5;
} }
/* /*
* Switch to top-off charging. * Switch to top-off charging.
@ -778,7 +831,8 @@ static void power_thread(void)
} }
else if (charge_state > CHARGING) /* top off or trickle */ else if (charge_state > CHARGING) /* top off or trickle */
{ {
/* Time to switch from topoff to trickle? /*
*Time to switch from topoff to trickle?
*/ */
if ((charge_state == TOPOFF) && if ((charge_state == TOPOFF) &&
(powermgmt_last_cycle_startstop_min > TOPOFF_MAX_TIME)) (powermgmt_last_cycle_startstop_min > TOPOFF_MAX_TIME))
@ -786,6 +840,7 @@ static void power_thread(void)
powermgmt_last_cycle_level = battery_percent; powermgmt_last_cycle_level = battery_percent;
powermgmt_last_cycle_startstop_min = 0; powermgmt_last_cycle_startstop_min = 0;
charge_state = TRICKLE; charge_state = TRICKLE;
target_voltage = target_voltage - 10;
} }
/* /*
* Adjust trickle charge time (proportional and integral terms). * Adjust trickle charge time (proportional and integral terms).
@ -793,10 +848,6 @@ static void power_thread(void)
* plugged in, but it doesn't appear to be necessary and will * plugged in, but it doesn't appear to be necessary and will
* generate more heat [gvb]. * generate more heat [gvb].
*/ */
if(charge_state == TOPOFF)
target_voltage = TOPOFF_VOLTAGE;
else
target_voltage = TRICKLE_VOLTAGE;
pid_p = target_voltage - battery_centivolts; pid_p = target_voltage - battery_centivolts;
if((pid_p > PID_DEADZONE) || (pid_p < -PID_DEADZONE)) if((pid_p > PID_DEADZONE) || (pid_p < -PID_DEADZONE))