From a403c3b56c8f2b2f3b3b82806416170cbd96efb4 Mon Sep 17 00:00:00 2001 From: Grazvydas Ignotas Date: Mon, 20 Jun 2011 23:23:08 +0300 Subject: [PATCH] pndevmapperd: add basic charge control Battery monitor thread now will also do charger control using the new on/off switch provided by kernel: - turn on charging when capacity goes below certain configured threshold - turn it off when it reaches configured capacity AND charge current goes below configured threshold. Using initial threshold from David Goldsmith. --- apps/pndevmapperd.c | 54 ++++++++++++++++++++++++++-- deployment/etc/pandora/conf/eventmap | 7 ++++ include/pnd_device.h | 7 ++++ lib/pnd_device.c | 23 ++++++++++++ 4 files changed, 88 insertions(+), 3 deletions(-) diff --git a/apps/pndevmapperd.c b/apps/pndevmapperd.c index 2214aae..2e1f651 100644 --- a/apps/pndevmapperd.c +++ b/apps/pndevmapperd.c @@ -126,6 +126,11 @@ unsigned char b_shutdown = 1; // %age battery to force a shutdown! unsigned int b_shutdelay = 30; // delay for shutdown script unsigned char b_warned = 0; // Shutdown attempted char *b_shutdown_script = NULL; +unsigned char bc_enable = 1; // enable charger control +unsigned char bc_stopcap = 99; // battery capacity threshold as stop condition 1 +unsigned int bc_stopcur = 80000; // charge current threshold as stop condition 2, in uA +unsigned char bc_startcap = 95; // battery capacity threshold to resume charging +char *bc_charge_device = NULL; // charger /sys/class/power_supply/ device, changes between kernel versions /* get to it */ @@ -367,6 +372,9 @@ int main ( int argc, char *argv[] ) { } else if ( strncmp ( k, "battery.", 8 ) == 0 ) { // not consumed here, skip silently + } else if ( strncmp ( k, "battery_charge.", 15 ) == 0 ) { + // not consumed here, skip silently + } else { // uhhh pnd_log ( pndn_warning, "Unknown config key '%s'; skipping.\n", k ); @@ -415,6 +423,26 @@ int main ( int argc, char *argv[] ) { b_shutdown_script = strdup ( pnd_conf_get_as_char ( evmaph, "battery.shutdown_script" ) ); pnd_log ( pndn_rem, "Battery shutdown script set to %s", b_shutdown_script ); } + if ( pnd_conf_get_as_int ( evmaph, "battery_charge.enable" ) != PND_CONF_BADNUM ) { + bc_enable = pnd_conf_get_as_int ( evmaph, "battery_charge.enable" ); + pnd_log ( pndn_rem, "Battery charge enable set to %u", bc_enable ); + } + if ( pnd_conf_get_as_int ( evmaph, "battery_charge.stop_capacity" ) != PND_CONF_BADNUM ) { + bc_stopcap = pnd_conf_get_as_int ( evmaph, "battery_charge.stop_capacity" ); + pnd_log ( pndn_rem, "Battery charge stop capacity set to %u", bc_stopcap ); + } + if ( pnd_conf_get_as_int ( evmaph, "battery_charge.stop_current" ) != PND_CONF_BADNUM ) { + bc_stopcur = pnd_conf_get_as_int ( evmaph, "battery_charge.stop_current" ); + pnd_log ( pndn_rem, "Battery charge stop current set to %u", bc_stopcur ); + } + if ( pnd_conf_get_as_int ( evmaph, "battery_charge.start_capacity" ) != PND_CONF_BADNUM ) { + bc_startcap = pnd_conf_get_as_int ( evmaph, "battery_charge.start_capacity" ); + pnd_log ( pndn_rem, "Battery charge start capacity set to %u", bc_startcap ); + } + if ( pnd_conf_get_as_char ( evmaph, "battery_charge.device" ) != NULL ) { + bc_charge_device = strdup ( pnd_conf_get_as_char ( evmaph, "battery_charge.device" ) ); + pnd_log ( pndn_rem, "Battery charge device set to %s", bc_charge_device ); + } /* do we have anything to do? */ @@ -842,6 +870,8 @@ void sigalrm_handler ( int n ) { pnd_log ( pndn_debug, "---[ SIGALRM ]---\n" ); int batlevel = pnd_device_get_battery_gauge_perc(); + int uamps = 0; + pnd_device_get_charge_current ( &uamps ); if ( batlevel < 0 ) { #if 0 @@ -855,9 +885,8 @@ void sigalrm_handler ( int n ) { // first -- are we critical yet? if so, shut down! if ( batlevel <= b_shutdown && b_shutdown_script) { - int mamps = 0; - if ( pnd_device_get_charge_current ( &mamps ) && mamps > 100 ) { + if ( uamps > 100 ) { // critical battery, but charging, so relax. b_warned = 0; } else { @@ -865,7 +894,7 @@ void sigalrm_handler ( int n ) { // Avoid warning again till re-powered b_warned = 1; int x; - pnd_log ( pndn_error, "Battery Current: %d\n", mamps ); + pnd_log ( pndn_error, "Battery Current: %d\n", uamps ); pnd_log ( pndn_error, "CRITICAL BATTERY LEVEL -- shutdown the system down! Invoke: %s\n", b_shutdown_script ); @@ -886,6 +915,25 @@ void sigalrm_handler ( int n ) { } + // charge monitoring + if ( bc_enable && bc_charge_device != NULL ) { + + int charge_enabled = pnd_device_get_charger_enable ( bc_charge_device ); + if ( charge_enabled < 0 ) + pnd_log ( pndn_error, "ERROR: Couldn't read charger enable control\n" ); + else { + + if ( charge_enabled && batlevel >= bc_stopcap && 0 < uamps && uamps < bc_stopcur ) { + pnd_log ( pndn_debug, "Charge stop conditions reached, disabling charging\n" ); + pnd_device_set_charger_enable ( bc_charge_device, 0 ); + } + else if ( !charge_enabled && batlevel <= bc_startcap ) { + pnd_log ( pndn_debug, "Charge start conditions reached, enabling charging\n" ); + pnd_device_set_charger_enable ( bc_charge_device, 1 ); + } + } + } + // is battery warning already active? if ( b_active ) { // warning is on! diff --git a/deployment/etc/pandora/conf/eventmap b/deployment/etc/pandora/conf/eventmap index 4a558fe..97877eb 100644 --- a/deployment/etc/pandora/conf/eventmap +++ b/deployment/etc/pandora/conf/eventmap @@ -28,3 +28,10 @@ blink_interval 2 # frequency of blink blink_duration 50000 # how long a blink lasts, in uSecs shutdown_threshold 5 # battery %age we force a shutdown (to save the SD!) shutdown_script /usr/pandora/scripts/op_battlow.sh + +[battery_charge] +enable 1 # enable charger control? +stop_capacity 99 # battery capacity threshold as stop condition 1 +stop_current 80000 # charge current threshold as stop condition 2, in uA +start_capacity 95 # battery capacity threshold to resume charging +device twl4030_bci_battery diff --git a/include/pnd_device.h b/include/pnd_device.h index 2003cf9..e094573 100644 --- a/include/pnd_device.h +++ b/include/pnd_device.h @@ -21,6 +21,7 @@ extern "C" { #define PND_DEVICE_FRAMEBUFFER "/dev/fb0" #define PND_DEVICE_NUB1 "/dev/input/js1" #define PND_DEVICE_NUB2 "/dev/input/js2" +#define PND_DEVICE_POWER_BASE "/sys/class/power_supply" #define PND_DEVICE_BATTERY_GAUGE_PERC "/sys/class/power_supply/bq27500-0/capacity" #define PND_DEVICE_CHARGE_CURRENT "/sys/class/power_supply/bq27500-0/current_now" @@ -58,6 +59,12 @@ unsigned int pnd_device_get_clock ( void ); int pnd_device_get_battery_gauge_perc ( void ); unsigned char pnd_device_get_charge_current ( int *result ); // returns + - current; if charging, current is +ve. +/* return the battery charger enable state; 1 or 0 + * On error, returns value < 0 + */ +int pnd_device_get_charger_enable ( const char *device ); +unsigned char pnd_device_set_charger_enable ( const char *device, unsigned char v ); + // LCD to set on/off // Backlight control diff --git a/lib/pnd_device.c b/lib/pnd_device.c index e158711..2e86928 100644 --- a/lib/pnd_device.c +++ b/lib/pnd_device.c @@ -103,6 +103,29 @@ unsigned char pnd_device_get_charge_current ( int *result ) { return ( 0 ); } +int pnd_device_get_charger_enable ( const char *device ) { + char fullname [ 100 ]; + char buffer [ 100 ]; + + snprintf ( fullname, sizeof ( fullname ), PND_DEVICE_POWER_BASE "/%s/enable", device ); + + if ( pnd_device_open_read_close ( fullname, buffer, 100 ) ) { + return ( atoi ( buffer ) ); + } + + return ( -1 ); +} + +unsigned char pnd_device_set_charger_enable ( const char *device, unsigned char v ) { + char fullname [ 100 ]; + char buffer [ 100 ]; + + snprintf ( fullname, sizeof ( fullname ), PND_DEVICE_POWER_BASE "/%s/enable", device ); + sprintf ( buffer, "%u", v ); + + return ( pnd_device_open_write_close ( fullname, buffer ) ); +} + unsigned char pnd_device_set_led_power_brightness ( unsigned char v ) { char buffer [ 100 ]; -- 2.39.2