meta-digi/meta-digi-dey/recipes-digi/dey-examples/files/battery_test/battery_calc.c

158 lines
5.0 KiB
C

/*
* battery_calc.c
*
* Copyright (C) 2010 by Digi International Inc.
* All rights reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 as published by
* the Free Software Foundation.
*
* Description: Simple battery characterization and time calculations.
* Specific battery details should be used to modify these calculations.
*
*/
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include "bat_test.h"
#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]))
typedef struct {
unsigned int voltage;
unsigned int percent;
} POWER_CAPABILITY;
/* From MC13892 Users Guide, Table 8.2-2 */
static int main_charging_current_table[] = {0,80,240,320,400,480,560,640,720,800,880,960,1040,1200,1600,0xFFFFFFFF /* Fully Open */};
/* Characterization of the battery charge and discharge curves */
static POWER_CAPABILITY chargingTable[] = { { 0xffff, 100 }, { 0xffff, 95 }, {
0xffff, 90 }, { 0xffff, 85 }, { 0xffff, 80 }, { 0xffff, 75 }, { 0xffff,
70 }, { 0xffff, 65 }, { 0xffff, 60 }, { 0xffff, 55 }, { 0xffff, 50 }, {
0xffff, 45 }, { 0xffff, 40 }, { 0xffff, 35 }, { 0xffff, 30 }, { 0xffff,
25 }, { 0xffff, 20 }, { 0xffff, 15 }, { 0xffff, 10 }, { 0xffff, 5 }, {
0xffff, 0 }, { 0, 0 } };
static POWER_CAPABILITY dischargingTable[] = { { 0xffff, 100 }, { 0xffff, 95 },
{ 0xffff, 90 }, { 0xffff, 85 }, { 0xffff, 80 }, { 0xffff, 75 }, {
0xffff, 70 }, { 0xffff, 65 }, { 0xffff, 60 }, { 0xffff, 55 }, {
0xffff, 50 }, { 0xffff, 45 }, { 0xffff, 40 }, { 0xffff, 35 }, {
0xffff, 30 }, { 0xffff, 25 }, { 0xffff, 20 }, { 0xffff, 15 }, {
0xffff, 10 }, { 0xffff, 5 }, { 0xffff, 0 }, { 0, 0 } };
void bat_parse_parameters( char * parms_list , unsigned int cdswitch )
{
POWER_CAPABILITY * pTable = cdswitch? dischargingTable:chargingTable;
int i = 0;
char * tmp = NULL;
if( (tmp = strtok(parms_list,",")) )
pTable[i++].voltage = (unsigned int)atoi( tmp );
while( (tmp = strtok(NULL,",")) && (i < (ARRAY_SIZE(chargingTable)-1)) )
pTable[i++].voltage = (unsigned int)atoi( tmp );
}
int bat_main_charging_current( unsigned int index )
{
return ( main_charging_current_table[ index%sizeof(main_charging_current_table) ] );
}
static void bat_dump_table( POWER_CAPABILITY * pTable )
{
int i;
for (i=0 ; i < (ARRAY_SIZE(chargingTable)-1) ; i++ ) {
printf("%d%%:%dmV\n",pTable[i].percent,pTable[i].voltage);
}
}
void bat_dump_tables( void )
{
POWER_CAPABILITY * pTable;
pTable = chargingTable;
printf("Charging table\n");
bat_dump_table(pTable);
pTable = dischargingTable;
printf("Discharging table\n");
bat_dump_table(pTable);
}
int bat_get_capacity ( POWER_SUPPLY_STATUS state , unsigned int voltage )
{
int i;
POWER_CAPABILITY * pTable;
int tableSize;
if ((state == POWER_SUPPLY_STATUS_DISCHARGING) || (state == POWER_SUPPLY_STATUS_NOT_CHARGING)) {
pTable = dischargingTable;
tableSize = sizeof(dischargingTable) / sizeof(dischargingTable[0]);
} else {
pTable = chargingTable;
tableSize = sizeof(chargingTable) / sizeof(chargingTable[0]);
}
for (i = 0; i < tableSize; i++) {
if (voltage >= pTable[i].voltage)
return pTable[i].percent;
}
return 0;
}
int bat_get_voltage( POWER_SUPPLY_STATUS state , unsigned int capacity)
{
int i;
POWER_CAPABILITY * pTable;
int tableSize;
if ((state == POWER_SUPPLY_STATUS_DISCHARGING) || (state == POWER_SUPPLY_STATUS_NOT_CHARGING)) {
pTable = dischargingTable;
tableSize = sizeof(dischargingTable) / sizeof(dischargingTable[0]);
} else {
pTable = chargingTable;
tableSize = sizeof(chargingTable) / sizeof(chargingTable[0]);
}
for (i = 0; i < tableSize; i++) {
if (capacity >= pTable[i].percent)
return pTable[i].voltage;
}
return 0;
}
/* Use a modified Peukert equation to use the battery hour rating and approximate the time to empty
* T = SxC/(I/(C/R))n x (R/C)
* Where:
* I = the discharge current in mA
* T = the time in hours
* C = capacity of the battery in mAh
* S = charge state (percentage of capacity)
* n = Peukert's exponent for that particular battery type
* R = the battery hour rating, i.e. 100 hour rating, 20 hour rating, 10 hour rating etc. Usually 20 hour rating.
*/
float bat_time_to_empty( unsigned int bat_percentage , unsigned int bat_current , unsigned int bat_capacity , float bat_peukert , unsigned int bat_rating )
{
return ( (float) bat_percentage/100*(float)bat_capacity/((float)bat_current/((float)bat_capacity/(float)bat_rating))*bat_peukert * ((float)bat_rating/(float)bat_capacity) );
}
/* Use a simple equation to approximate the time to full
*
* T = DxnxR/I
* Where:
* I = the charge current in mA
* T = the time in hours
* D = Discharge state (100 - capacity)
* n = The charge efficiency
* C = The capacity in mAh
*/
float bat_time_to_full( unsigned int bat_charging_current , unsigned int bat_capacity , float bat_charge_efficiency , unsigned int bat_percentage )
{
float bat_discharge_state = (100 - (float)bat_percentage)/100;
return((float)(bat_discharge_state)*bat_charge_efficiency*(float)bat_capacity/(float)bat_charging_current);
}