Tuesday, February 23, 2010

Coulomb Counter

One technique for battery capacity reporting relies on the coulomb counter. The principle of operation involved in coulomb counting is computing the difference between the coulombs injected into a battery and the coulombs taken out of the battery. The capacity of the battery is then reported by comparing the coulomb count relative to a reference coulomb count value that corresponds to maximum battery capacity. For instance, if the coulomb count of a battery is half of the reference value, the battery capacity is reported to be 50 percent. Other known existing techniques of battery capacity reporting are primarily based on measuring battery voltage.

Monday, February 22, 2010

Hints for writing a battery driver in linux

This was my very first driver development in linux, a battery/energy/power driver.

Linux kernel provides a power supply core driver located in drivers/power/. The core power supply driver includes power_supply_core.c, power_supply_sysfs.c.

This core driver includes a structure power_supply defined in include/linux/power_supply.h. Here is the snapshot of the structure

struct power_supply {
const char *name;
enum power_supply_type type;
enum power_supply_property *properties;
size_t num_properties;

char **supplied_to;
size_t num_supplicants;

int (*get_property)(struct power_supply *psy,
enum power_supply_property psp,
union power_supply_propval *val);
void (*external_power_changed)(struct power_supply *psy);

/* For APM emulation, think legacy userspace. */
int use_for_apm;

/* private */
struct device *dev;
struct work_struct changed_work;

#ifdef CONFIG_LEDS_TRIGGERS
struct led_trigger *charging_full_trig;
char *charging_full_trig_name;
struct led_trigger *charging_trig;
char *charging_trig_name;
struct led_trigger *full_trig;
char *full_trig_name;
struct led_trigger *online_trig;
char *online_trig_name;
#endif
};

It also creates a class entry in /sys/class/power_supply/ to expose the properties to the user space from the kernel space. This can be achieved by filling appropriate data to the structure power_supply.

In simple words the battery/energy/power driver has to provide API or data and hook up with the core driver structure power_supply and register to the kernel core power supply driver. The rest of the part of exposing the driver data to the user space is taken care by the core driver.

Brief overview of the structure and means of hooking up to it.
The structre power_supply has 11 elements and 19 in case led in involved.
  1. name - refers to the name of the battery/energy/power driver. Should not involve white space and an entry by this name is being created in /sys/class/power_supply/
  2. type - specify the type. Can be either of the following defined in the enum power_supply_type(include/linux/power_supply.h)
  3. properties - this plays a very important role and is the most important of all. This is of type enum and includes the one defined in enum power_supply_property(defined in include/linux/power_supply.h)
  4. num_properties - number of properties. In the definition enum power_supply_properties there are 36 elements. The driver is free to have only the requiered elements among these 36 elements. This is mentioned in the above element properties and the count is num_properties.
  5. supplied_to - a meaningful string representing the name of the driver different from the first element name. This indicated as to for which device the supply is being provided.
  6. get_property - it is a function pointer. This function has a switch statement with the elements of properties (enum power_supply_property) as cases. The aim of this function is to provide/update your battery/energy/power driver parameters.
  7. external_power_supply_changed - a function pointer. This is a function that tell what has to be done if there is a change in power resource.
  8. changed_work - work function to update the parameters of the driver.
As already said the element properties(enum power_supplu_property) is the most important one. Here is the brief description
  • POWER_SUPPLY_PROP_STATUS - status of the device can be one of the following (POWER_SUPPLY_STATUS_UNKNOWN, POWER_SUPPLY_STATUS_CHARGING, POWER_SUPPLY_STATUS_DISCHARGING, POWER_SUPPLY_STATUS_NOT_CHARGING, POWER_SUPPLY_STATUS_FULL)
  • POWER_SUPPLY_PROP_HEALTH - battery health, can be one among(POWER_SUPPLY_HEALTH_UNKNOWN, POWER_SUPPLY_HEALTH_GOOD, POWER_SUPPLY_HEALTH_OVERHEAT, POWER_SUPPLY_HEALTH_DEAD, POWER_SUPPLY_HEALTH_OVERVOLTAGE, POWER_SUPPLY_HEALTH_UNSPEC_FAILURE, POWER_SUPPLY_HEALTH_COLD)
  • POWER_SUPPLY_PROP_PRESENT - this can have a boolean value. If the device is present the value should be one, else zero
  • POWER_SUPPLY_PROP_ONLINE - this can have a boolean value. If this device is doing some work then its value should be one. For ex consider the device as AC/Mains, if the charging is through Mains/AC then its value is one.
  • POWER_SUPPLY_PROP_TECHNOLOGY - represents the technology of the battery(POWER_SUPPLY_TECHNOLOGY_UNKNOWN, POWER_SUPLY_TECHNOLOGY_NiMH, POWER_SUPLY_TECHNOLOGY_LION, POWER_SUPPLY_TECHNOLOGY_LIPO, POWER_SUPPLY_TECHNOLOGY_LiFe, POWER_SUPPLY_TECHNOLOGY_NiCd, POWER_SUPPLY_TECHNOLOGY_LiMn)
  • POWER_SUPPLY_PROP_VOLTAGE_MAX - the maximum threshold voltage of the device(in uV)
  • POWER_SUPPLY_PROP_VOLTAGE_MIN - the lower threshold voltage of the device upto which the device is powered on.(in uV)
  • POWER_SUPPLY_PROP_VOLTAGE_NOW - present voltage of the device(in uV)
  • POWER_SUPPLY_PROP_VOLTAGE_AVG - average voltage of the device(in uV)
  • POWER_SUPPLY_PROP_CURRENT_NOW - present current of the device(in uA)
  • POWER_SUPPLY_PROP_CURRENT_AVG - average current(in uA)
  • POWER_SUPPLY_PROP_CHARGE_NOW - amount of charge in the device(in uAh)
  • POWER_SUPPLY_PROP_CHARGE_AVG - average charge in the device(in uAh)
  • POWER_SUPPLY_PROP_CAPACITY - the present capacity of the battery in terms of percentage. This is being used by application to graphically show the current capacity of the battery.
  • POWER_SUPPLY_PROP_TEMP - present temperature of the device in deg cel