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
Jani Kinnunen
Rui Marinho
Alun Thomas

View File

@ -39,10 +39,10 @@
#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 */
#define CHARGE_END_ZEROD 50 /* stop when N minutes have passed with
* avg delta being < 0.005 V */
#define CHARGE_END_LONGD 50 /* stop when N minutes have passed with
* avg delta being < -0.02 V */
#ifndef SIMULATOR

View File

@ -175,7 +175,8 @@ charge_state_type charge_state; /* charging mode */
#ifdef HAVE_CHARGE_CTRL
int long_delta; /* long 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
debug menu */
/* percentage at which charging
@ -580,7 +581,12 @@ static void power_thread_sleep(int ticks)
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 we have a lot of pending writes or if the disk is spining,
@ -608,9 +614,15 @@ static void power_thread(void)
int i;
short *phps, *phpd; /* power history rotation pointers */
#ifdef HAVE_CHARGE_CTRL
unsigned int target_voltage; /* desired topoff/trickle voltage level */
int charge_max_time_now = 0; /* max. charging duration, calculated at
beginning of charging */
unsigned int target_voltage = TRICKLE_VOLTAGE; /* desired topoff/trickle
* voltage level */
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
/* initialize the voltages for the exponential filter */
@ -669,19 +681,23 @@ static void power_thread(void)
powermgmt_last_cycle_startstop_min = 0;
if(battery_percent >= START_TRICKLE_CHG) {
charge_state = TRICKLE;
target_voltage = TRICKLE_VOLTAGE;
} else {
charge_state = TOPOFF;
target_voltage = TOPOFF_VOLTAGE;
}
} else {
/*
* Start the charger full strength
*/
i = CHARGE_MAX_TIME_1500 * battery_capacity / 1500;
charge_max_time_now =
charge_max_time_idle =
i * (100 + 35 - battery_percent) / 100;
if (charge_max_time_now > i) {
charge_max_time_now = i;
if (charge_max_time_idle > i) {
charge_max_time_idle = i;
}
charge_max_time_now = charge_max_time_idle;
snprintf(power_message, POWER_MESSAGE_LEN,
"ChgAt %d%% max %dm", battery_level(),
charge_max_time_now);
@ -699,26 +715,44 @@ static void power_thread(void)
}
}
if (charge_state == CHARGING) {
snprintf(power_message, POWER_MESSAGE_LEN,
"Chg %dm, max %dm", powermgmt_last_cycle_startstop_min,
charge_max_time_now);
/* alter charge time max length with extra disk use */
if (disk_activity_last_cycle) {
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
* 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] -
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
* our history, the long term delta isn't a valid end-of-charge
* indicator.
* Scan the history: the points where measurement is taken need to
* be fairly static. (check prior to short delta 'area')
* (also only check first and last 10 cycles - delta in middle OK)
*/
long_delta = power_history[0] -
power_history[CHARGE_END_ZEROD - 1];
for(i = 0; i < CHARGE_END_ZEROD; i++) {
power_history[CHARGE_END_LONGD - 1];
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) ||
((power_history[i] - power_history[i+1]) < -5)) {
long_delta = 888888;
@ -727,22 +761,27 @@ 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):
* 1) Charged a long time
* 2) DeltaV went negative for a short time
* 3) DeltaV was close to zero for a long time
* 2) DeltaV went negative for a short time ( & long delta static)
* 3) DeltaV was negative over a longer period (no disk use only)
* Note: short_delta and long_delta are centivolts
*/
if ((powermgmt_last_cycle_startstop_min > charge_max_time_now) ||
(short_delta <= -5) || (long_delta < 5))
{
if ((powermgmt_last_cycle_startstop_min >= charge_max_time_now) ||
(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) {
DEBUGF("power: powermgmt_last_cycle_startstop_min > charge_max_time_now, "
"enough!\n");
/* have charged too long and deltaV detection did not
work! */
snprintf(power_message, POWER_MESSAGE_LEN,
/*
*have charged too long and deltaV detection did not
*work!
*/
snprintf(power_message, POWER_MESSAGE_LEN,
"Chg tmout %d min", charge_max_time_now);
/*
* Switch to trickle charging. We skip the top-off
@ -753,6 +792,16 @@ static void power_thread(void)
powermgmt_last_cycle_level = battery_percent;
powermgmt_last_cycle_startstop_min = 0;
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 {
if(short_delta <= -5) {
DEBUGF("power: short-term negative"
@ -760,12 +809,16 @@ static void power_thread(void)
snprintf(power_message, POWER_MESSAGE_LEN,
"end negd %d %dmin", short_delta,
powermgmt_last_cycle_startstop_min);
target_voltage = power_history[CHARGE_END_SHORTD - 1]
- 5;
} else {
DEBUGF("power: long-term small "
"positive delta, enough!\n");
snprintf(power_message, POWER_MESSAGE_LEN,
"end lowd %d %dmin", long_delta,
powermgmt_last_cycle_startstop_min);
target_voltage = power_history[CHARGE_END_LONGD - 1]
- 5;
}
/*
* Switch to top-off charging.
@ -778,7 +831,8 @@ static void power_thread(void)
}
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) &&
(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_startstop_min = 0;
charge_state = TRICKLE;
target_voltage = target_voltage - 10;
}
/*
* 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
* generate more heat [gvb].
*/
if(charge_state == TOPOFF)
target_voltage = TOPOFF_VOLTAGE;
else
target_voltage = TRICKLE_VOLTAGE;
pid_p = target_voltage - battery_centivolts;
if((pid_p > PID_DEADZONE) || (pid_p < -PID_DEADZONE))