summaryrefslogtreecommitdiff
path: root/firmware
diff options
context:
space:
mode:
authorJörg Hohensohn <hohensoh@rockbox.org>2006-03-04 09:48:53 +0000
committerJörg Hohensohn <hohensoh@rockbox.org>2006-03-04 09:48:53 +0000
commitea5df70e4699e1603bf21cf715fc997dade66004 (patch)
tree082c108c02769d4d04016273974c897770f2a649 /firmware
parentc7838b8418a739e9f4f0e6c6a0e58bb51f38e527 (diff)
downloadrockbox-ea5df70e4699e1603bf21cf715fc997dade66004.tar.gz
rockbox-ea5df70e4699e1603bf21cf715fc997dade66004.zip
Archos V1 recorder charging path #2927 by Alun Thomas
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@8898 a1c6a512-1295-4272-9138-f99709370657
Diffstat (limited to 'firmware')
-rw-r--r--firmware/export/powermgmt.h6
-rw-r--r--firmware/powermgmt.c117
2 files changed, 87 insertions, 36 deletions
diff --git a/firmware/export/powermgmt.h b/firmware/export/powermgmt.h
index a5dbcd10bd..b9ac996fc0 100644
--- a/firmware/export/powermgmt.h
+++ b/firmware/export/powermgmt.h
@@ -39,10 +39,10 @@
39 39
40#define POWER_HISTORY_LEN 2*60 /* 2 hours of samples, one per minute */ 40#define POWER_HISTORY_LEN 2*60 /* 2 hours of samples, one per minute */
41 41
42#define CHARGE_END_NEGD 6 /* stop when N minutes have passed with 42#define CHARGE_END_SHORTD 6 /* stop when N minutes have passed with
43 * avg delta being < -0.05 V */ 43 * avg delta being < -0.05 V */
44#define CHARGE_END_ZEROD 50 /* stop when N minutes have passed with 44#define CHARGE_END_LONGD 50 /* stop when N minutes have passed with
45 * avg delta being < 0.005 V */ 45 * avg delta being < -0.02 V */
46 46
47#ifndef SIMULATOR 47#ifndef SIMULATOR
48 48
diff --git a/firmware/powermgmt.c b/firmware/powermgmt.c
index ff635486c1..e4330a48c0 100644
--- a/firmware/powermgmt.c
+++ b/firmware/powermgmt.c
@@ -175,7 +175,8 @@ charge_state_type charge_state; /* charging mode */
175#ifdef HAVE_CHARGE_CTRL 175#ifdef HAVE_CHARGE_CTRL
176int long_delta; /* long term delta battery voltage */ 176int long_delta; /* long term delta battery voltage */
177int short_delta; /* short term delta battery voltage */ 177int short_delta; /* short term delta battery voltage */
178 178bool disk_activity_last_cycle = false; /* flag set to aid charger time
179 * calculation */
179char power_message[POWER_MESSAGE_LEN] = ""; /* message that's shown in 180char power_message[POWER_MESSAGE_LEN] = ""; /* message that's shown in
180 debug menu */ 181 debug menu */
181 /* percentage at which charging 182 /* percentage at which charging
@@ -580,7 +581,12 @@ static void power_thread_sleep(int ticks)
580 battery_status_update(); 581 battery_status_update();
581 582
582 } 583 }
583 584#ifdef HAVE_CHARGE_CTRL
585 if (ata_disk_is_active()) {
586 /* flag hdd use for charging calculation */
587 disk_activity_last_cycle = true;
588 }
589#endif
584#if defined(DEBUG_FILE) && defined(HAVE_CHARGE_CTRL) 590#if defined(DEBUG_FILE) && defined(HAVE_CHARGE_CTRL)
585 /* 591 /*
586 * If we have a lot of pending writes or if the disk is spining, 592 * If we have a lot of pending writes or if the disk is spining,
@@ -608,9 +614,15 @@ static void power_thread(void)
608 int i; 614 int i;
609 short *phps, *phpd; /* power history rotation pointers */ 615 short *phps, *phpd; /* power history rotation pointers */
610#ifdef HAVE_CHARGE_CTRL 616#ifdef HAVE_CHARGE_CTRL
611 unsigned int target_voltage; /* desired topoff/trickle voltage level */ 617 unsigned int target_voltage = TRICKLE_VOLTAGE; /* desired topoff/trickle
612 int charge_max_time_now = 0; /* max. charging duration, calculated at 618 * voltage level */
613 beginning of charging */ 619 int charge_max_time_idle = 0; /* max. charging duration, calculated at
620 * beginning of charging */
621 int charge_max_time_now = 0; /* max. charging duration including
622 * hdd activity */
623 int minutes_disk_activity = 0; /* count minutes of hdd use during
624 * charging */
625 int last_disk_activity = CHARGE_END_LONGD + 1; /* last hdd use x mins ago */
614#endif 626#endif
615 627
616 /* initialize the voltages for the exponential filter */ 628 /* initialize the voltages for the exponential filter */
@@ -669,19 +681,23 @@ static void power_thread(void)
669 powermgmt_last_cycle_startstop_min = 0; 681 powermgmt_last_cycle_startstop_min = 0;
670 if(battery_percent >= START_TRICKLE_CHG) { 682 if(battery_percent >= START_TRICKLE_CHG) {
671 charge_state = TRICKLE; 683 charge_state = TRICKLE;
684 target_voltage = TRICKLE_VOLTAGE;
672 } else { 685 } else {
673 charge_state = TOPOFF; 686 charge_state = TOPOFF;
687 target_voltage = TOPOFF_VOLTAGE;
674 } 688 }
675 } else { 689 } else {
676 /* 690 /*
677 * Start the charger full strength 691 * Start the charger full strength
678 */ 692 */
679 i = CHARGE_MAX_TIME_1500 * battery_capacity / 1500; 693 i = CHARGE_MAX_TIME_1500 * battery_capacity / 1500;
680 charge_max_time_now = 694 charge_max_time_idle =
681 i * (100 + 35 - battery_percent) / 100; 695 i * (100 + 35 - battery_percent) / 100;
682 if (charge_max_time_now > i) { 696 if (charge_max_time_idle > i) {
683 charge_max_time_now = i; 697 charge_max_time_idle = i;
684 } 698 }
699 charge_max_time_now = charge_max_time_idle;
700
685 snprintf(power_message, POWER_MESSAGE_LEN, 701 snprintf(power_message, POWER_MESSAGE_LEN,
686 "ChgAt %d%% max %dm", battery_level(), 702 "ChgAt %d%% max %dm", battery_level(),
687 charge_max_time_now); 703 charge_max_time_now);
@@ -699,26 +715,44 @@ static void power_thread(void)
699 } 715 }
700 } 716 }
701 if (charge_state == CHARGING) { 717 if (charge_state == CHARGING) {
702 snprintf(power_message, POWER_MESSAGE_LEN, 718 /* alter charge time max length with extra disk use */
703 "Chg %dm, max %dm", powermgmt_last_cycle_startstop_min, 719 if (disk_activity_last_cycle) {
704 charge_max_time_now); 720 minutes_disk_activity++;
721 charge_max_time_now = charge_max_time_idle +
722 (minutes_disk_activity * 2 / 5);
723 disk_activity_last_cycle = false;
724 last_disk_activity = 0;
725 } else {
726 last_disk_activity++;
727 }
705 /* 728 /*
706 * Check the delta voltage over the last X minutes so we can do 729 * Check the delta voltage over the last X minutes so we can do
707 * our end-of-charge logic based on the battery level change. 730 * our end-of-charge logic based on the battery level change.
731 *(no longer use minimum time as logic for charge end has 50
732 * minutes minimum charge built in)
708 */ 733 */
709 if (powermgmt_last_cycle_startstop_min > CHARGE_MIN_TIME) { 734 if (powermgmt_last_cycle_startstop_min > CHARGE_END_SHORTD) {
710 short_delta = power_history[0] - 735 short_delta = power_history[0] -
711 power_history[CHARGE_END_NEGD - 1]; 736 power_history[CHARGE_END_SHORTD - 1];
712 } 737 }
713 if (powermgmt_last_cycle_startstop_min > CHARGE_END_ZEROD) { 738
739 if (powermgmt_last_cycle_startstop_min > CHARGE_END_LONGD) {
714 /* 740 /*
715 * Scan the history: if we have a big delta in the middle of 741 * Scan the history: the points where measurement is taken need to
716 * our history, the long term delta isn't a valid end-of-charge 742 * be fairly static. (check prior to short delta 'area')
717 * indicator. 743 * (also only check first and last 10 cycles - delta in middle OK)
718 */ 744 */
719 long_delta = power_history[0] - 745 long_delta = power_history[0] -
720 power_history[CHARGE_END_ZEROD - 1]; 746 power_history[CHARGE_END_LONGD - 1];
721 for(i = 0; i < CHARGE_END_ZEROD; i++) { 747
748 for(i = CHARGE_END_SHORTD; i < CHARGE_END_SHORTD + 10; i++) {
749 if(((power_history[i] - power_history[i+1]) > 5) ||
750 ((power_history[i] - power_history[i+1]) < -5)) {
751 long_delta = 777777;
752 break;
753 }
754 }
755 for(i = CHARGE_END_LONGD - 11; i < CHARGE_END_LONGD - 1 ; i++) {
722 if(((power_history[i] - power_history[i+1]) > 5) || 756 if(((power_history[i] - power_history[i+1]) > 5) ||
723 ((power_history[i] - power_history[i+1]) < -5)) { 757 ((power_history[i] - power_history[i+1]) < -5)) {
724 long_delta = 888888; 758 long_delta = 888888;
@@ -727,22 +761,27 @@ static void power_thread(void)
727 } 761 }
728 } 762 }
729 763
764 snprintf(power_message, POWER_MESSAGE_LEN,
765 "Chg %dm, max %dm", powermgmt_last_cycle_startstop_min,
766 charge_max_time_now);
730 /* 767 /*
731 * End of charge criteria (any qualify): 768 * End of charge criteria (any qualify):
732 * 1) Charged a long time 769 * 1) Charged a long time
733 * 2) DeltaV went negative for a short time 770 * 2) DeltaV went negative for a short time ( & long delta static)
734 * 3) DeltaV was close to zero for a long time 771 * 3) DeltaV was negative over a longer period (no disk use only)
735 * Note: short_delta and long_delta are centivolts 772 * Note: short_delta and long_delta are centivolts
736 */ 773 */
737 if ((powermgmt_last_cycle_startstop_min > charge_max_time_now) || 774 if ((powermgmt_last_cycle_startstop_min >= charge_max_time_now) ||
738 (short_delta <= -5) || (long_delta < 5)) 775 (short_delta <= -5 && long_delta < 5 ) || (long_delta < -2 &&
739 { 776 last_disk_activity > CHARGE_END_LONGD)) {
740 if (powermgmt_last_cycle_startstop_min > charge_max_time_now) { 777 if (powermgmt_last_cycle_startstop_min > charge_max_time_now) {
741 DEBUGF("power: powermgmt_last_cycle_startstop_min > charge_max_time_now, " 778 DEBUGF("power: powermgmt_last_cycle_startstop_min > charge_max_time_now, "
742 "enough!\n"); 779 "enough!\n");
743 /* have charged too long and deltaV detection did not 780 /*
744 work! */ 781 *have charged too long and deltaV detection did not
745 snprintf(power_message, POWER_MESSAGE_LEN, 782 *work!
783 */
784 snprintf(power_message, POWER_MESSAGE_LEN,
746 "Chg tmout %d min", charge_max_time_now); 785 "Chg tmout %d min", charge_max_time_now);
747 /* 786 /*
748 * Switch to trickle charging. We skip the top-off 787 * Switch to trickle charging. We skip the top-off
@@ -753,6 +792,16 @@ static void power_thread(void)
753 powermgmt_last_cycle_level = battery_percent; 792 powermgmt_last_cycle_level = battery_percent;
754 powermgmt_last_cycle_startstop_min = 0; 793 powermgmt_last_cycle_startstop_min = 0;
755 charge_state = TRICKLE; 794 charge_state = TRICKLE;
795
796 /*
797 * set trickle charge target to a relative voltage instead
798 * of an arbitrary value - the fully charged voltage may
799 * vary according to ambient temp, battery condition etc
800 * trickle target is -0.15v from full voltage acheived
801 * topup target is -0.05v from full voltage
802 */
803 target_voltage = power_history[0] - 15;
804
756 } else { 805 } else {
757 if(short_delta <= -5) { 806 if(short_delta <= -5) {
758 DEBUGF("power: short-term negative" 807 DEBUGF("power: short-term negative"
@@ -760,12 +809,16 @@ static void power_thread(void)
760 snprintf(power_message, POWER_MESSAGE_LEN, 809 snprintf(power_message, POWER_MESSAGE_LEN,
761 "end negd %d %dmin", short_delta, 810 "end negd %d %dmin", short_delta,
762 powermgmt_last_cycle_startstop_min); 811 powermgmt_last_cycle_startstop_min);
812 target_voltage = power_history[CHARGE_END_SHORTD - 1]
813 - 5;
763 } else { 814 } else {
764 DEBUGF("power: long-term small " 815 DEBUGF("power: long-term small "
765 "positive delta, enough!\n"); 816 "positive delta, enough!\n");
766 snprintf(power_message, POWER_MESSAGE_LEN, 817 snprintf(power_message, POWER_MESSAGE_LEN,
767 "end lowd %d %dmin", long_delta, 818 "end lowd %d %dmin", long_delta,
768 powermgmt_last_cycle_startstop_min); 819 powermgmt_last_cycle_startstop_min);
820 target_voltage = power_history[CHARGE_END_LONGD - 1]
821 - 5;
769 } 822 }
770 /* 823 /*
771 * Switch to top-off charging. 824 * Switch to top-off charging.
@@ -778,7 +831,8 @@ static void power_thread(void)
778 } 831 }
779 else if (charge_state > CHARGING) /* top off or trickle */ 832 else if (charge_state > CHARGING) /* top off or trickle */
780 { 833 {
781 /* Time to switch from topoff to trickle? 834 /*
835 *Time to switch from topoff to trickle?
782 */ 836 */
783 if ((charge_state == TOPOFF) && 837 if ((charge_state == TOPOFF) &&
784 (powermgmt_last_cycle_startstop_min > TOPOFF_MAX_TIME)) 838 (powermgmt_last_cycle_startstop_min > TOPOFF_MAX_TIME))
@@ -786,6 +840,7 @@ static void power_thread(void)
786 powermgmt_last_cycle_level = battery_percent; 840 powermgmt_last_cycle_level = battery_percent;
787 powermgmt_last_cycle_startstop_min = 0; 841 powermgmt_last_cycle_startstop_min = 0;
788 charge_state = TRICKLE; 842 charge_state = TRICKLE;
843 target_voltage = target_voltage - 10;
789 } 844 }
790 /* 845 /*
791 * Adjust trickle charge time (proportional and integral terms). 846 * Adjust trickle charge time (proportional and integral terms).
@@ -793,10 +848,6 @@ static void power_thread(void)
793 * plugged in, but it doesn't appear to be necessary and will 848 * plugged in, but it doesn't appear to be necessary and will
794 * generate more heat [gvb]. 849 * generate more heat [gvb].
795 */ 850 */
796 if(charge_state == TOPOFF)
797 target_voltage = TOPOFF_VOLTAGE;
798 else
799 target_voltage = TRICKLE_VOLTAGE;
800 851
801 pid_p = target_voltage - battery_centivolts; 852 pid_p = target_voltage - battery_centivolts;
802 if((pid_p > PID_DEADZONE) || (pid_p < -PID_DEADZONE)) 853 if((pid_p > PID_DEADZONE) || (pid_p < -PID_DEADZONE))