Functions | Variables

xpal_bat.c File Reference

Battery Management Routines for the eXPal Prototype A. More...

#include "config.h"
#include <stdio.h>
#include "xpal_bat.h"
#include "adc.h"
#include "xpal_power.h"
#include "xpal_async32khz.h"
#include <avr/eeprom.h>
#include "../hlog/config-params.h"


uint8_t hl_bat_GetBatStatus (void)
 Estimate the Battery condition and return the state for the.
uint16_t hl_bat_slow (void *p)
 Slow Timer Call.
void hl_InitBatMan (void)
 Init battery management system.


volatile uint8_t BatStatus
 Battery status byte.
volatile uint16_t BatVoltage
 voltage in mV
volatile int16_t BatGradient
 voltage gradient in mV
volatile int16_t BatGradientTimer
 Time periode where BatGradient is collected from [s].
int8_t adc_calibration = 80
 ADC calibration value.

Detailed Description

Battery Management Routines for the eXPal Prototype A.

This module contains routines for the following functions:
Basic Concept for the power management

The battery voltage is measured one time per second. In parallel with this measurement, the differences compared to the previous second are accumulated. When this gradient reaches a certain value, the system is checking the time that went over to reach the limit value. The actual battery status and type is derrived from the parameters voltage and time to reach a certain voltage difference. This way, the system shows some adaptive behaviour, depending on the discharge speed.

The Power management will use the following measurement units for all calculations:

Function Documentation

uint8_t hl_bat_GetBatStatus ( void   ) 

Estimate the Battery condition and return the state for the.

The battery voltage is evaluated to estimate the battery status


        // return old value when no reevaluation event happened
        if((BatStatus & HL_BAT_UPDATE) == 0){

                // return old value when no reevaluation event happened
                BatStatus &= ~(HL_BAT_NEWSTAT);

                // clear update state
                BatStatus &= ~(HL_BAT_UPDATE);

                // clear battery state
                BatStatus &= ~(HL_BAT_ST_MASK);                 

                if(BatVoltage >= HL_BAT_V_FOPMIN){
                        // we have enough power for full operation              
                        if (BatVoltage > HL_BAT_V_FOPMAX){
                                BatStatus |= HL_BAT_ST_FOPMAX;
                        }else if(BatVoltage > HL_BAT_V_FOP4){
                                BatStatus |= HL_BAT_ST_FOP4;
                        }else if(BatVoltage > HL_BAT_V_FOP3){
                                BatStatus |= HL_BAT_ST_FOP3;
                        }else if(BatVoltage > HL_BAT_V_FOP2){
                                BatStatus |= HL_BAT_ST_FOP2;
                        }else if(BatVoltage > HL_BAT_V_FOP1){
                                BatStatus |= HL_BAT_ST_FOP1;
                                BatStatus |= HL_BAT_ST_FOPMIN;
                        // we are in limited op mode now
                        if (BatVoltage > HL_BAT_V_LIM3){
                                BatStatus |= HL_BAT_ST_LIM3;
                        }else if(BatVoltage > HL_BAT_V_LIM2){
                                BatStatus |= HL_BAT_ST_LIM2;
                        }else if(BatVoltage > HL_BAT_V_LIM1){
                                BatStatus |= HL_BAT_ST_LIM1;
                        }else if(BatVoltage > HL_BAT_V_EMPTY){
                                BatStatus |= HL_BAT_ST_LIM1;
                                BatStatus |= HL_BAT_ST_EMPTY;
                // mark status as new value
                BatStatus |= HL_BAT_NEWSTAT;

                // !!!! debug
                printf("\n\r.%X %imV", BatStatus, BatVoltage);

        // Evaluate discharge Gradient
        if(BatGradient < HL_BAT_MAX_VOLT_GRADIENT){
                // Need to collect data on this value
                // useful code comming soon

                // !!!! debug
                printf(":%imV_%is \n\r", BatGradient, BatGradientTimer);

                BatGradientTimer = 1;
                BatGradient = 0;        

        return BatStatus;

uint16_t hl_bat_slow ( void *  p  ) 

Slow Timer Call.

Do slow operations for power management:

  • Check Bat Voltage
  • update status display
  • ...


        if ((HL_PWR_ST_OFF & hl_pwr_GetState()) != HL_PWR_ST_OFF){
                // If not in power off

                /* Evaluate last bat measurement */
                BatGradient -= (BatVoltage & ~HL_BAT_MEASURE_ACTIVE) - (adc_calibration + hl_adc_convert(hl_adc_result ()));
                BatVoltage = adc_calibration + hl_adc_convert(hl_adc_result ());

                // Do not count beyond max time value
                if (BatGradientTimer < HL_BAT_GRADIENT_COUNT_MAX){

                // Do only collect battery discharge for evaluation
                if (BatGradient > 0){
                        BatGradient = 0;
                        // Battery is recovering, check for update
                        BatStatus |= HL_BAT_UPDATE;

                // Check Battery when timer is running over Zero for startup check
                if(BatGradientTimer == 0){
                        BatStatus |= HL_BAT_UPDATE;

                // Check Battery when gradient exceeds threshold
                if (BatGradient < HL_BAT_MAX_VOLT_GRADIENT){
                        // Battery is recovering, check for update
                        BatStatus |= HL_BAT_UPDATE;

                /* Start new Bat voltage measurement */
                // hl_adc_select (adc_chan0);
                hl_adc_start ();
        return 0;

void hl_InitBatMan ( void   ) 

Init battery management system.


  • Variables
  • Bat Voltage measurement
  • Timer Registration

This function needs to be called early in main(), before the 1s timer is running to ensure that there is an initial value for the battery voltage available

The init function will take some time to do the first measurement.

    int8_t calvalue;
        BatVoltage = HL_BAT_VOLT_INVALID;
        BatGradient= 0;
        BatGradientTimer = HL_BAT_GRADIENT_COUNT_PON;

        // Start with low bat setting and activate update
        BatStatus = HL_BAT_ST_FOP1 & HL_BAT_UPDATE; 

        // Start initial voltage measurement

        // Do the initial measurement
        // This is required for the later gradient calculation

        /* read calibration value from EEPROM */
        calvalue = eeprom_read_byte (CFG_CALIB_BATT_VOLT);
        if (calvalue != 0xFF)
          adc_calibration = calvalue;

        BatVoltage = adc_calibration + hl_adc_convert(hl_adc_result ());

        // register 1s timer call back
        hl_asyn_Register1sTimer( (&hl_bat_slow), NULL);

Variable Documentation

int8_t adc_calibration = 80

ADC calibration value.

The calibration value is read from EEPROM during initialization. To get the corrected ADC output, use hl_adc_correct().

volatile int16_t BatGradientTimer

Time periode where BatGradient is collected from [s].

BatGradient was collected over this time [s].