⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 analog.c

📁 用AVR453开发的电池保护板的C语言程序,希望对大家有用!
💻 C
📖 第 1 页 / 共 3 页
字号:
/* This file has been prepared for Doxygen automatic documentation generation.*/
/*! \file *********************************************************************
 *
 * \brief
 *      Sampling and calculations.
 *
 * \par Application note:
 *      AVR453: Smart Battery Reference Design
 *
 * \par Documentation:
 *      For comprehensive code documentation, supported compilers, compiler
 *      settings and supported devices see readme.html
 *
 * \author
 *      Atmel Corporation: http://www.atmel.com \n
 *      Support email: avr@atmel.com \n
 *      Original author: Rob G. Fries - Apt Inc.\n
 *
 * $Revision: 2687 $
 * $URL: http://revisor.norway.atmel.com/AppsAVR8/avr453_Smart_battery_reference_design/tags/20071112_release/code/analog.c $
 * $Date: 2007-11-12 10:39:44 +0100 (ma, 12 nov 2007) $  \n
 ******************************************************************************/

/* Validation Test for Current Measurement:
Using the I-SIM circuit, apply 20.0mV to the ATmega406 CCADC input.
Read back the variable LatestCCI.  Multiply this value by 53.7uV/count.
You should get approximately 20,000uV, or 20mV.  The variable LatestCCI
is intended to be used for cell impedance measurements and is not filtered
or scaled in any way, but is a copy of the raw result of the instantaneous
CC reading.

The variable CCarray contains averaged 1-second Current readings based on the
results of the Instantaneous reading of the CCADC.  These calculations
assume a 5mOhm sense resistor.  To verify these readings, pick one
sample out of the CCarray and convert to decimal.  The value should be read
directly in mA.  If using 20mV as noted above, this would correspond to
a value of 20mV/5mOhm = 4000mA, therefore all non-zero elements in the array
should read approx. 4000 (decimal).

The Accumulator should also be tested, since its reading must also be
scaled in order to be read as mA.  Assuming 20mV applied to the input,
and each bit corresponding to 1.678uV, then each 1-second reading of the
CCADC accumulated result should be approx. 20mV/1.678uV = 0x2EF8.
This number must be multiplied by 3600 to convert from seconds to hours.
Dividing this result by 10727 will yield the current in mAHr, in this
case approximately 4000mAHr.


*/





//#include "iom406_320.h"
#include <iom406.h>     // IAR headerfile for Mega406 (EW 410)
#include <inavr.h>

#include "main.h"
#include "pack.h"

#define MODULE_ANALOG
#include "analog.h"

#define MODULE_CALIBRATION
#include "calibration.h"


#include "smbus.h"
#include "timer.h"	// (for access to the Timer32KHz variable)
#include "pwrmgmt.h"
#include "ee.h"


//Local prototypes (not exposed in analog.h)
void CCarray_Init(void);




//Local variables (not exposed in analog.h)

//signed long RunningAcc = 0;		//this must be externally visible for Hibernate mode estimated power loss
signed long MaxTopAcc = 0;
signed long MaxBottomAcc = 0;

unsigned char CC_delay_acc = 0;
unsigned char CC_delay_inst = 0;

//Calculated, calibrated results
unsigned int  CellV[4] = {0};
unsigned int  OnChipTemp = 0;

//Intermediate results
unsigned int  Thermistor[4] = {0};	// this hold an Ohmic value, scaled per "FixedThermistorPullup"
unsigned int  VPA4 = 0;			// this is V(ADC4) * 5


// The following variables are used for the 1-minute (approx) average of current flow.
// We treat CCarray as a circular buffer, containing the 64 most recent samples available.
// Each sample is properly scaled (mA) but does not include temperature or offset effects.
// These functions are kept local to this file and are not made public.
signed int CCarray[64];		//positive (charging) or negative (discharging).
char CCindex = 0;
char CCvalidsamples = 0;




//Support variables
unsigned int  ADCbuffer[10];		//raw converted results
unsigned int ADCgain[4];		//gain values for Cell1-4
unsigned int  VTgain;			//gain for on-chip temperature sensor
unsigned char ADCchannel;		//visible so we can force the start channel


#define FixedThermistorPullup 1000	/* ohmic value */

/* =====================================================================================
   =====================================================================================
   ===================================================================================== */


//Public functions (exposed in analog.h)

void SetMaxTopAcc(long value)
{
  MaxTopAcc = value;
}

void FullChargeReached(void)
{
  signed long temp;

  temp = RunningAcc - MaxBottomAcc;
  RunningAcc = MaxTopAcc = temp;
  MaxBottomAcc = 0;
  SMBvariables[SMBV_BattStatus][lobyte] &= ~FULLY_DISCHARGED;
  SMBvariables[SMBV_BattStatus][lobyte] |= FULLY_CHARGED;
}



void FullDischargeReached(void)
{
  MaxTopAcc -= RunningAcc;
  RunningAcc = MaxBottomAcc = 0;
  SMBvariables[SMBV_BattStatus][lobyte] |= FULLY_DISCHARGED;
  SMBvariables[SMBV_BattStatus][lobyte] &= ~FULLY_CHARGED;
}


/* =====================================================================================
   =====================================================================================
   ===================================================================================== */


//Assorted local-support math functions

unsigned int GetVoltage(void)	//also serves as "cmd = 9"
{
  unsigned int volt;

  volt = ReadCell(1);
  volt += ReadCell(2);
  if(PACKSTACK > 2)
    volt += ReadCell(3);
  if(PACKSTACK > 3)
    volt += ReadCell(4);
  return volt;
}	


long GetCharge(void)			//in mAHrs
{
  unsigned long calc = (RunningAcc / 10727);	// 10,727 LSB/mAh, see app-note for more details
  return calc;
}


long GetCharge_mAmins(void)	   //in mAmins
{
  unsigned long calc = (RunningAcc / 179);	// 10727 / 60 ~= 179
  return calc;
}


long GetChgUntilFull_mAmins(void)	//in mAmins
{
  unsigned long calc = (MaxTopAcc - RunningAcc);
  return (calc / 179);
}


unsigned int GetMaxChg(void)	//calculate the maximum charge that the pack is presently
                                //capable of holding (not same as DESIGN capacity)
{
  unsigned long calc = MaxTopAcc / 10727;
  return (unsigned int) calc;
}



/*
unsigned int GetCapacity(void)		//designed capacity @1C, in mAHr
{
  return PACK_DESIGNCAPTYP;
}


unsigned long GetCapacity_mAmins(void)	//designed capacity @1C, in mAmins
{
  return (PACK_DESIGNCAPTYP*60);
}
*/




/* =====================================================================================
   =====================================================================================
   ===================================================================================== */

//Functions to support specific SMBus Slave READ commands

unsigned int AtRateTTF(void)	// cmd = 5
{
  signed long calc;
  unsigned int temp = (unsigned int)SMBvar_int[SMBV_AtRate];

  if((signed int) temp > 0)	//For TTF, AtRate must be POSITIVE & NON-ZERO.
  {
    if(SMBvariables[SMBV_BattMode][hibyte] & CAPACITY_MODE)  //use mW
    {
      temp = 65535;			//optional mode, not implemented.
    }
    else //use mA in calculations
    {
      calc = PACK_DESIGNCAPTYP;
      calc = calc * 60;
      calc -= GetCharge_mAmins();
      temp = calc / temp;		// (mAmins / mA) = mins
    }
  }
  else	//error
    temp = 65535;

  return temp;
}


unsigned int AtRateTTE(void)	// cmd = 6
{
  signed long calc;
  unsigned int temp = (unsigned int)SMBvar_int[SMBV_AtRate];

  if((signed int) temp < 0)	//For TTE, AtRate must be NEGATIVE & NON-ZERO.
  {
    temp = -((signed int) temp);

    if(SMBvariables[SMBV_BattMode][hibyte] & CAPACITY_MODE)	//use mW
    {
      calc = GetCharge_mAmins() * PACK_MINV;	//this is now in uWmins
      calc = calc / 10000;			//this is now in 10mWmins
      temp = calc / temp;			// (10mWmins / 10mW) = mins
    }
    else //use mA in calculations
    {
      calc = GetCharge_mAmins();
      temp = calc / temp;			// (mAmins / mA) = mins
    }
  }
  else	//error
    temp = 65535;

  return temp;
}


unsigned int AtRateOK(void)	// cmd = 7
{
  unsigned long calc;				 //used as available capacity
  unsigned int temp = (unsigned int)SMBvar_int[SMBV_AtRate]; //used as total rate of consumption

  if((signed int) temp < 0)	//For AtRateOK, AtRate must be NEGATIVE & NON-ZERO.
  {
    temp = -((signed int) temp);

    if(SMBvariables[SMBV_BattMode][hibyte] & CAPACITY_MODE)	//use mW in calculations
    {
      calc = Current1Sec() * GetVoltage();	//in uW (alternate: can use PACK_MINV)
      calc = calc / 10000;			//in 10mW
      temp += calc;	//combine AtRate and present load; shouldn't overflow!

      calc = GetCharge_mAmins();
      calc = calc * PACK_MINV;
      calc = calc * 6;                          //this is now in mW-10Secs
      calc = calc / 10;				//this is now in 10mW-10Secs
    }
    else //use mA in calculations
    {
      temp += Current1Sec();			//add in the present discharge rate too!
      calc = GetCharge_mAmins() * 6;		//convert to 10-second rate
    }

    if(calc > temp)
      temp = 65535;	//return TRUE, as there is enough energy.
    else
      temp = 0;		//return FALSE. We're almost dead!
  }
  else	//error
    temp = 65535;

  return temp;
}


unsigned int GetTemperature(void)	// cmd = 8
{ // Returns temperature of MEGA406, in 0.1 degrees Kelvin.
  return ReadTemperature(0);	//channel 0 is the on-chip sensor.
}



unsigned char RelativeSOC(void) 	// cmd = 13
{
  unsigned long charge = (RunningAcc * 100) / MaxTopAcc;
//  return (unsigned int) charge;
  return (unsigned char) charge;
}


unsigned int AbsoluteSOC(void)		// cmd = 14
{
  unsigned long charge = (GetCharge() * 100);
  charge = charge / PACK_DESIGNCAPTYP;
  return (unsigned int) charge;
}


unsigned int RemainingCap(void)		// cmd = 15
{ //! \todo  This implementation does not take into account C/5 vs 1C capacity delta.
  unsigned long calc;
  unsigned int charge = GetCharge();	//in mAH

  if(SMBvariables[SMBV_BattMode][hibyte] & CAPACITY_MODE)	//use mW in calculations
  {
    calc = charge * GetVoltage();	//in uWH
    charge = calc  / 10000;		//in 10mWH
  }

  return charge;
}



unsigned int FullChgCap(void)		//cmd = 16
{ //! \todo  This implementation does not take into account C/5 vs 1C capacity delta.
  unsigned long calc = GetMaxChg();

  if(SMBvariables[SMBV_BattMode][hibyte] & CAPACITY_MODE)	//use mW in calculations
  {
    calc = calc * PACK_NOMINALV;
    calc = calc / 10000;
  }

  return (unsigned int) calc;
}


// Pass in 0 for 1-sec basis, 1 for 1-minute avg'd basis.
unsigned int TimeToEmpty(unsigned char avgd)	//cmd = 17,18; how many mins until battery is discharged at present rate
{
  signed int rate;
  unsigned long presentrate;
  unsigned long cap;

  if(0 == avgd)
    rate = Current1Sec();
  else
    rate = CCarray_Average();

  if(rate >= 0)
    return 65535;

  rate = -rate;

  if(SMBvariables[SMBV_BattMode][hibyte] & CAPACITY_MODE)	//use mW in calculations
  {
    //First, determine actual rate of Wattage being used.
    presentrate = rate * GetVoltage();		//this is in uW scale

    //Next, determine capacity at pack's minimum V (full discharge)
    cap = GetCharge_mAmins() * PACK_MINV;	//this is in uWmins scale

    //Divide uWmins by uW and you get minutes.
    cap = cap / presentrate;
  }
  else
  {
    cap = GetCharge_mAmins() / rate;	// (mAmins / mA) = minutes
  }

  return (unsigned int) cap;
}




unsigned int AvgTimeToFull(void)	//cmd = 19
{
  signed int rate;
  unsigned long presentrate;
  unsigned long cap;

  rate = Current1Sec();
  if(rate <= 0)
    return 65535;


  if(SMBvariables[SMBV_BattMode][hibyte] & CAPACITY_MODE)	//use mW in calculations
  {
    //First, determine actual rate of Wattage being used.
    presentrate = rate * GetVoltage();		//this is in uW scale

    //Next, determine capacity at pack's minimum V (full discharge)
    cap = GetChgUntilFull_mAmins() * PACK_MINV;	//this is in uWmins scale

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -