Files
LFP_48V_mBMS_FW/APP_R3221/App/Source/afe_comm.c

981 lines
26 KiB
C

/**
******************************************************************************
* @file afe_comm.c
* @author AMG Energy Solution Team
* @version V1.0.0
* @date 07-Feb-2022
* @brief This file provides all the headers of afe communication functions.
******************************************************************************
* @attention
*
* THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS
* WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE
* TIME. AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY
* DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING
* FROM THE CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE
* CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS.
*
* <h2><center>&copy; COPYRIGHT 2022 AMG</center></h2>
******************************************************************************
*/
/** @addtogroup mBMS2
* @{
*/
/* Includes ------------------------------------------------------------------*/
#include <includes.h>
#include "afe_comm.h"
#include "usart.h"
#include "i2c.h"
#include "asutil.h"
#include "malloc.h"
#include "delay.h"
#include "device_param.h"
#include "brtc.h"
#include "console.h"
#include "bq769x0.h"
#include "io.h"
/* Private define ------------------------------------------------------------*/
#define AFE_COMM_TASK_TIME 100 // 50ms TASK
#define PACK_BUF_MAX 20
/* Private typedef -----------------------------------------------------------*/
typedef struct
{
uint32_t Tick;
uint16_t Timeout;
uint8_t Commfail;
uint8_t Init;
} TAfeCommState, *PAfeCommState;
typedef struct
{
uint16_t cVolt[DEVICE_MAX_CELL + 1];
} TPackBuf, *PPackBuf;
typedef struct
{
uint16_t cell_fail : 1;
uint16_t ocv_alarm : 1;
uint16_t ocv_shutdown : 1;
uint16_t odv_alarm : 1;
uint16_t odv_shutdown : 1;
uint16_t cell_balance : 1;
uint16_t reserved : 10;
} TCellAlarm, *PCellAlarm;
typedef struct _TCellData
{
uint16_t volt;
TCellAlarm alarm;
} TCellData, *PCellData;
/* Private macro -------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
TAfeCommState AfeCommState;
uint16_t PackBufCh = 0;
TPackBuf PackBuf[PACK_BUF_MAX];
uint32_t Balance_Avg, disBalance_Avg;
uint8_t disCellBalancingFlag;
uint8_t CellBalancingMode = 0; // 0: even, 1: odd
uint16_t setBalValue = 0;
uint8_t CB_Rest = false;
uint32_t CB_Tick = 0;
uint32_t disCB_Tick = 0;
uint16_t ManualBalValue = 0;
uint8_t ManualBalFlag = 0;
uint8_t Afe_ShutDonwFlag = 0;
/* Private function prototypes -----------------------------------------------*/
void AfeCommProcess(void);
void AfeUpdateData(void);
void CellVoltagePutBuf(void);
void MakeCellAvgData(void);
void Cell_AutoBalancing(uint32_t rBal);
void Cell_ManualBalancing(uint32_t rBal);
/* Private functions ---------------------------------------------------------*/
/**
* @brief Initialize for AFE (Analog Front End) Communication
* @param None
* @retval None
*/
void AfeCommInit(void)
{
bq769x0_construct();
memset(&AfeCommState, 0x00, sizeof(TAfeCommState));
device_status.battery_status.bit.ACB = true;
bq769x0_begin(0, 0);
}
/**
* @brief Application Task for AFE (Analog Front End) Communication
* @param None
* @retval None
*/
void App_TaskAfeComm(void)
{
AfeCommInit();
while (DEF_TRUE)
{
if (Afe_ShutDonwFlag == true)
{
}
else
{
AfeCommProcess();
AfeUpdateData();
if (DIDState(2) == cOCCUR)
{
bq769x0_ResetAlert();
}
}
delay_os_ms(AFE_COMM_TASK_TIME);
}
}
void AfeUpdateData(void)
{
device_value.Heartbeat = OptimeStamp;
device_status.battery_status.bit.AFE = AfeCommState.Commfail;
}
uint8_t BuffFlag = true;
void AfeCommProcess(void)
{
uint32_t rTmp = 0;
bq769x0_updateData();
CellVoltagePutBuf();
MakeCellAvgData();
rTmp = getCellBalStatus();
if (device_status.battery_status.bit.ACB) {
Cell_AutoBalancing(rTmp);
} else {
Cell_ManualBalancing(rTmp);
}
}
void CellVoltagePutBuf(void)
{
uint32_t nCells, ch, tmp, sectSum[3];
uint32_t adcGain2 = device_calib_data.cal.voltage.BatV_Gain;
ch = PackBufCh;
nCells = getNumberOfCells();
for (int i = 0; i < nCells; i++) {
tmp = getCellVoltage(i + 1) * adcGain2 / 10000;
PackBuf[ch].cVolt[i] = tmp; // Cell 15
}
if (BuffFlag == true) {
BuffFlag = false;
for (int i = 0; i < DEVICE_MAX_CELL; i++) {
for (int k = 0; k < PACK_BUF_MAX; k++) {
PackBuf[k].cVolt[i] = PackBuf[ch].cVolt[i];
}
}
}
// Cell Volt Avg
sectSum[0] = 0;
sectSum[1] = 0;
sectSum[2] = 0;
for (int i = 0; i < DEVICE_MAX_CELL; i++) {
tmp = 0;
for (int k = 0; k < PACK_BUF_MAX; k++) {
tmp += PackBuf[k].cVolt[i];
}
device_value.Cell.voltage[i] = (uint16_t)(tmp / PACK_BUF_MAX);
sectSum[i / 5] += device_value.Cell.voltage[i];
}
for (int i = 0; i < 3; i++) {
device_value.SectVoltage[i] = sectSum[i];
}
PackBufCh++;
PackBufCh %= PACK_BUF_MAX;
}
void MakeCellAvgData(void)
{
uint32_t sum;
TMinMax min, max;
sum = 0;
memset(&min, 0x00, sizeof(TMinMax));
memset(&max, 0x00, sizeof(TMinMax));
for (int i = 0; i < DEVICE_MAX_CELL; i++)
{
if (i == 0)
{
max.value = device_value.Cell.voltage[i];
max.num = i;
min.value = device_value.Cell.voltage[i];
min.num = i;
}
if (max.value < device_value.Cell.voltage[i])
{
max.value = device_value.Cell.voltage[i];
max.num = i;
}
if (min.value > device_value.Cell.voltage[i])
{
min.value = device_value.Cell.voltage[i];
min.num = i;
}
sum += device_value.Cell.voltage[i];
}
device_value.BatVoltage = sum / 10;
device_value.Cell.avg.Max.value = max.value;
device_value.Cell.avg.Max.num = max.num;
device_value.Cell.avg.Min.value = min.value;
device_value.Cell.avg.Min.num = min.num;
device_value.Cell.avg.diff = max.value - min.value;
device_value.Cell.avg.avg = (uint16_t)(sum / DEVICE_MAX_CELL);
}
void dec_cb_tick(uint16_t tick)
{
if (CB_Tick > tick)
CB_Tick -= tick;
else
CB_Tick = 0;
}
void Cell_AutoBalancing1(uint32_t rBal)
{
uint16_t bal = 0;
uint8_t setBal = false;
PDEVICE_PARAM param = &device_param;
// for (int i = 0; i < DEVICE_MAX_CELL; i++)
// {
// if ((rBal >> i) & 0x0001)
// {
// bal |= (uint16_t)(1 << i);
// }
// }
bal = rBal;
// device_status.cellbalance.value = bal;
if (CB_Rest == true)
{
if (CB_Tick == 0)
{
CB_Rest = false;
CB_Tick = param->chg_ctrl.cell_bal_cfg.Cell_Balance_Interval * 1000;
setBal = true;
}
}
else
{
if (CB_Tick == 0)
{
CB_Rest = true;
CB_Tick = param->chg_ctrl.cell_bal_cfg.Cell_Balance_Interval * 1000;
setBal = true;
}
}
if (device_status.battery_status.bit.CB == true)
{
// Before cell balancing status is ON
// if (device_value.Cell.avg.Max.value < param->chg_ctrl.cell_bal_cfg.Cell_Balance_Threshold) {
if (device_value.Cell.avg.Max.value < 3400) {
device_status.battery_status.bit.CB = false;
setBalValue = 0;
} else if (device_value.Cell.avg.diff < (param->chg_ctrl.cell_bal_cfg.Cell_Balance_Min - 5)) {
if (device_status.warning.bit.cell_over_voltage == 0) {
device_status.battery_status.bit.CB = false;
setBalValue = 0;
}
}
} else {
// Before cell balancing status is OFF
// if (device_value.Cell.avg.Max.value > (param->chg_ctrl.cell_bal_cfg.Cell_Balance_Threshold + param->chg_ctrl.cell_bal_cfg.Cell_Balance_Window))
if (device_value.Cell.avg.Max.value > 3450) {
if (device_value.Cell.avg.diff > param->chg_ctrl.cell_bal_cfg.Cell_Balance_Min) {
device_status.battery_status.bit.CB = true;
} else if (device_status.warning.bit.cell_over_voltage) {
device_status.battery_status.bit.CB = true;
}
}
}
if (device_status.battery_status.bit.CB == true)
{
if (setBal == true)
{
if (CB_Rest == false)
{
if (device_value.Cell.avg.Max.value > device_param.chg_ctrl.term_cfg.CB_Limit_Voltage)
{
Balance_Avg = device_param.chg_ctrl.term_cfg.CB_Limit_Voltage;
}
else if (device_value.Cell.avg.Min.value > 3580)
{
if ((device_value.Cell.avg.Max.value - device_value.Cell.avg.avg) > 20)
{
Balance_Avg = device_value.Cell.avg.avg + 10;
}
else
{
if ((device_value.Cell.avg.avg - device_value.Cell.avg.Min.value) > 20)
Balance_Avg = device_value.Cell.avg.avg + 2;
else
Balance_Avg = device_value.Cell.avg.avg + 5;
}
}
else
{
if (device_value.Cell.avg.diff > 100)
{
if ((device_value.Cell.avg.Max.value - device_value.Cell.avg.avg) > (device_value.Cell.avg.avg - device_value.Cell.avg.Min.value))
Balance_Avg = device_value.Cell.avg.avg + 20;
else
Balance_Avg = device_value.Cell.avg.avg - 20;
}
else if (device_value.Cell.avg.diff > 80)
{
if ((device_value.Cell.avg.Max.value - device_value.Cell.avg.avg) > (device_value.Cell.avg.avg - device_value.Cell.avg.Min.value))
Balance_Avg = device_value.Cell.avg.avg + 15;
else
Balance_Avg = device_value.Cell.avg.avg - 15;
}
else if (device_value.Cell.avg.diff > 60)
{
if ((device_value.Cell.avg.Max.value - device_value.Cell.avg.avg) > (device_value.Cell.avg.avg - device_value.Cell.avg.Min.value))
Balance_Avg = device_value.Cell.avg.avg + 10;
else
Balance_Avg = device_value.Cell.avg.avg - 10;
}
else if (device_value.Cell.avg.diff > 40)
{
if ((device_value.Cell.avg.Max.value - device_value.Cell.avg.avg) > (device_value.Cell.avg.avg - device_value.Cell.avg.Min.value))
Balance_Avg = device_value.Cell.avg.avg + 5;
else
Balance_Avg = device_value.Cell.avg.avg - 5;
}
else if (device_value.Cell.avg.diff > 30)
{
if ((device_value.Cell.avg.Max.value - device_value.Cell.avg.avg) > (device_value.Cell.avg.avg - device_value.Cell.avg.Min.value))
Balance_Avg = device_value.Cell.avg.avg + 2;
else
Balance_Avg = device_value.Cell.avg.avg - 2;
}
else if (device_value.Cell.avg.diff > 20)
{
if ((device_value.Cell.avg.Max.value - device_value.Cell.avg.avg) > (device_value.Cell.avg.avg - device_value.Cell.avg.Min.value))
Balance_Avg = device_value.Cell.avg.avg + 2;
else
Balance_Avg = device_value.Cell.avg.avg - 2;
}
else if (device_value.Cell.avg.diff > 10)
{
if ((device_value.Cell.avg.Max.value - device_value.Cell.avg.avg) > (device_value.Cell.avg.avg - device_value.Cell.avg.Min.value))
Balance_Avg = device_value.Cell.avg.avg + 1;
else
Balance_Avg = device_value.Cell.avg.avg - 1;
}
else
{
Balance_Avg = device_value.Cell.avg.avg;
}
}
if (Balance_Avg < 3350) Balance_Avg = 3600;
bal = 0;
for (int i = 0; i < DEVICE_MAX_CELL; i++)
{
if (device_value.Cell.voltage[i] > Balance_Avg)
{
bal = bal | (1 << i);
}
else if ((device_value.Cell.voltage[i] > 3350) && ((device_status.cov_warning_cell.uValue >> i) == 1))
{
bal = bal | (1 << i);
}
// else if ((device_value.Cell.voltage[i] > Balance_Avg) || ((device_status.cov_warning_cell.uValue >> i) == 1))
// {
// bal = bal | (1 << i);
// }
}
setBalValue = bal;
// bq769x0_updateBalancingSwitches(setBalValue, CellBalancingMode);
bq769x0_updateBalancingSwitches(setBalValue, 0);
// if (CellBalancingMode == 0) CellBalancingMode = 1; else CellBalancingMode = 0;
}
else
{
// CB Rest time
bal = setBalValue;
// for (int i = 0; i < DEVICE_MAX_CELL; i++)
// {
// if ((device_status.cov_warning_cell.uValue >> i) == 1)
// {
// bal = bal | (1 << i);
// }
// }
bq769x0_updateBalancingSwitches(bal, 1);
}
}
}
else
{
if (bal != 0x0000)
{
setBalValue = 0;
bq769x0_updateBalancingSwitches(setBalValue, 0);
}
}
device_status.cellbalance.value = setBalValue;
}
void Cell_AutoBalancing(uint32_t rBal)
{
uint16_t bal = 0;
uint8_t setBal = false;
PDEVICE_PARAM param = &device_param;
bal = rBal;
switch (CB_Rest)
{
case 0:
if (CB_Tick == 0) {
CB_Rest = 1;
CB_Tick = param->chg_ctrl.cell_bal_cfg.Cell_Balance_Interval * 1000;
setBal = true;
}
break;
case 1:
if (CB_Tick == 0) {
if ((device_value.Cell.avg.Min.value > 3500) && (device_value.Cell.avg.diff < 15)) {
CB_Rest = 2;
CB_Tick = param->chg_ctrl.cell_bal_cfg.Cell_Balance_Interval * 1000 * 3;
} else {
CB_Rest = 0;
CB_Tick = param->chg_ctrl.cell_bal_cfg.Cell_Balance_Interval * 1000;
}
setBal = true;
}
break;
case 2:
if (CB_Tick == 0) {
CB_Rest = 0;
CB_Tick = param->chg_ctrl.cell_bal_cfg.Cell_Balance_Interval * 1000;
setBal = true;
}
break;
default:
CB_Rest = 0;
break;
}
if (device_status.battery_status.bit.CB == true)
{
// Before cell balancing status is ON
if (device_value.Cell.avg.Max.value < param->chg_ctrl.cell_bal_cfg.Cell_Balance_Threshold) {
device_status.battery_status.bit.CB = false;
setBalValue = 0;
}
else if (device_value.Cell.avg.diff < (param->chg_ctrl.cell_bal_cfg.Cell_Balance_Min - 3))
{
if (device_status.warning.bit.cell_over_voltage == 0) {
device_status.battery_status.bit.CB = false;
setBalValue = 0;
}
}
}
else
{
// Before cell balancing status is OFF
if (device_value.Cell.avg.Max.value > (param->chg_ctrl.cell_bal_cfg.Cell_Balance_Threshold + param->chg_ctrl.cell_bal_cfg.Cell_Balance_Window))
{
if (device_value.Cell.avg.diff > param->chg_ctrl.cell_bal_cfg.Cell_Balance_Min)
device_status.battery_status.bit.CB = true;
else if (device_status.warning.bit.cell_over_voltage)
device_status.battery_status.bit.CB = true;
}
}
if (device_status.battery_status.bit.CB == true)
{
if (setBal == true)
{
switch (CB_Rest) {
case 0:
if (device_value.Cell.avg.Max.value > device_param.chg_ctrl.term_cfg.CB_Limit_Voltage)
{
Balance_Avg = device_param.chg_ctrl.term_cfg.CB_Limit_Voltage;
}
else if (device_value.Cell.avg.Min.value > 3580)
{
if ((device_value.Cell.avg.Max.value - device_value.Cell.avg.avg) > 20)
{
Balance_Avg = device_value.Cell.avg.avg + 10;
}
else
{
if ((device_value.Cell.avg.avg - device_value.Cell.avg.Min.value) > 20)
Balance_Avg = device_value.Cell.avg.avg + 2;
else
Balance_Avg = device_value.Cell.avg.avg + 5;
}
}
else
{
if (device_value.Cell.avg.diff > 100)
{
if ((device_value.Cell.avg.Max.value - device_value.Cell.avg.avg) > (device_value.Cell.avg.avg - device_value.Cell.avg.Min.value))
Balance_Avg = device_value.Cell.avg.avg + 20;
else
Balance_Avg = device_value.Cell.avg.avg - 20;
}
else if (device_value.Cell.avg.diff > 80)
{
if ((device_value.Cell.avg.Max.value - device_value.Cell.avg.avg) > (device_value.Cell.avg.avg - device_value.Cell.avg.Min.value))
Balance_Avg = device_value.Cell.avg.avg + 15;
else
Balance_Avg = device_value.Cell.avg.avg - 15;
}
else if (device_value.Cell.avg.diff > 60)
{
if ((device_value.Cell.avg.Max.value - device_value.Cell.avg.avg) > (device_value.Cell.avg.avg - device_value.Cell.avg.Min.value))
Balance_Avg = device_value.Cell.avg.avg + 10;
else
Balance_Avg = device_value.Cell.avg.avg - 10;
}
else if (device_value.Cell.avg.diff > 40)
{
if ((device_value.Cell.avg.Max.value - device_value.Cell.avg.avg) > (device_value.Cell.avg.avg - device_value.Cell.avg.Min.value))
Balance_Avg = device_value.Cell.avg.avg + 5;
else
Balance_Avg = device_value.Cell.avg.avg - 5;
}
else if (device_value.Cell.avg.diff > 30)
{
if ((device_value.Cell.avg.Max.value - device_value.Cell.avg.avg) > (device_value.Cell.avg.avg - device_value.Cell.avg.Min.value))
Balance_Avg = device_value.Cell.avg.avg + 2;
else
Balance_Avg = device_value.Cell.avg.avg - 2;
}
else if (device_value.Cell.avg.diff > 20)
{
if ((device_value.Cell.avg.Max.value - device_value.Cell.avg.avg) > (device_value.Cell.avg.avg - device_value.Cell.avg.Min.value))
Balance_Avg = device_value.Cell.avg.avg + 2;
else
Balance_Avg = device_value.Cell.avg.avg - 2;
}
else if (device_value.Cell.avg.diff > 10)
{
if ((device_value.Cell.avg.Max.value - device_value.Cell.avg.avg) > (device_value.Cell.avg.avg - device_value.Cell.avg.Min.value))
Balance_Avg = device_value.Cell.avg.avg + 1;
else
Balance_Avg = device_value.Cell.avg.avg - 1;
}
else
{
Balance_Avg = device_value.Cell.avg.avg;
}
}
if (Balance_Avg < 3350) Balance_Avg = 3600;
bal = 0;
for (int i = 0; i < DEVICE_MAX_CELL; i++)
{
if (device_value.Cell.voltage[i] > Balance_Avg)
{
bal = bal | (1 << i);
}
else if ((device_value.Cell.voltage[i] > 3350) && ((device_status.cov_warning_cell.uValue >> i) == 1))
{
bal = bal | (1 << i);
}
// else if ((device_value.Cell.voltage[i] > Balance_Avg) || ((device_status.cov_warning_cell.uValue >> i) == 1))
// {
// bal = bal | (1 << i);
// }
}
setBalValue = bal;
bq769x0_updateBalancingSwitches(setBalValue, 0);
break;
case 1:
// CB Rest time
bal = setBalValue;
bq769x0_updateBalancingSwitches(bal, 1);
break;
case 2:
setBalValue = 0;
bal = setBalValue;
bq769x0_updateBalancingSwitches(bal, 1);
for (int i = 0; i < DEVICE_MAX_CELL; i++)
{
if ((device_status.cov_warning_cell.uValue >> i) == 1)
{
bal = bal | (1 << i);
}
}
break;
default:
CB_Rest = 0;
break;
}
}
}
else
{
if (bal != 0x0000)
{
setBalValue = 0;
bq769x0_updateBalancingSwitches(setBalValue, 0);
}
}
device_status.cellbalance.value = setBalValue;
}
void SetManualBalancing(uint8_t flag, uint32_t cNo)
{
ManualBalFlag = flag;
if (ManualBalFlag == true)
{
device_status.battery_status.bit.ACB = false;
if (cNo >= 1)
ManualBalValue |= (1 << (cNo - 1));
}
else
{
device_status.battery_status.bit.ACB = true;
ManualBalValue = 0;
}
}
void Cell_ManualBalancing(uint32_t rBal)
{
uint16_t bal = 0;
PDEVICE_PARAM param = &device_param;
for (int i = 0; i < DEVICE_MAX_CELL; i++) {
if ((rBal >> i) & 0x0001) {
bal |= (uint16_t)(1 << i);
}
}
device_status.cellbalance.value = bal;
if (ManualBalFlag == true) {
if (CB_Tick == 0) {
CB_Tick = param->chg_ctrl.cell_bal_cfg.Cell_Balance_Interval * 1000;
if (CellBalancingMode == 0) CellBalancingMode = 1; else CellBalancingMode = 0;
}
// if (ManualBalValue != bal)
bq769x0_updateBalancingSwitches(ManualBalValue, CellBalancingMode);
}
else
{
if (bal != 0)
bq769x0_updateBalancingSwitches(0, 0);
}
}
/* Public Status Function ************************************************************/
uint16_t GetBalanceAvg(void)
{
return Balance_Avg;
}
uint16_t GetBalanceFlag(void)
{
return device_status.battery_status.bit.CB;
}
/* Display Function ******************************************************************/
#ifdef CONSOLE_DEBUG
void AfeDisplayStatus(uint8_t p);
void ODisplayBalancingValue(uint8_t p)
{
float aParam;
if (p || (disBalance_Avg != Balance_Avg))
{
aParam = (float)Balance_Avg / 1000;
FloatNormalOutIntXY(71, 10 , aParam, 5, 3);
disBalance_Avg = Balance_Avg;
}
if (p || (disCellBalancingFlag != GetBalanceFlag()))
{
if (GetBalanceFlag() == true)
YellowOutXY(68, 11, (uint8_t *)"O");
else
GreenOutXY(68, 11, (uint8_t *)"X");
disCellBalancingFlag = GetBalanceFlag();
}
if (p || ((disCB_Tick / 1000) != (CB_Tick / 1000)))
{
aParam = (float)(disCB_Tick / 1000);
FloatNormalOutIntXY(70, 11,aParam, 6, 0);
disCB_Tick = CB_Tick;
}
//
// AfeDisplayStatus(p);
}
const char AfeMODE_STR[][84] =
{
// 1 2 3 4 5 6 7 8
// 123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
"\r\n+--[Battery : ]---+---+---+---+---+---+---+---+---+---+--------------------+", // 2
"\r\n| | B |OCA|TCA|TDA|AFE|RSV|ZVC|F-C|F-D| Warning ( )HEX|", // 3
"\r\n| HeartB ( ) | S |INI|MD |FC |FD |RXM|ZVC|F-C|F-D| Protection( )HEX|", // 4
"\r\n+---------------------+---+---+---+---+---+---+---+---+---+-[CELL AVG ]--------+", // 5
"\r\n| B-Volt ( . )V | W |RSV|RSV|RSV|L-C|LTD|LTC|HTD|HTC| C-MAX ( . )V |", // 6
"\r\n| Current ( . )A | N |RSV|RSV|OCD|OCC|CUV|SUV|COV|SOV| C-AVG ( . )V |", // 7
"\r\n| SOC ( . )% +---+---+---+---+---+---+---+---+---+ C-MIN ( . )V |", // 8
"\r\n| | P |AFE|RSV|SC |RSV|LTD|LTC|HTD|HTC| C-DIFF ( . )V |", // 9
"\r\n+---------------------+ T |RSV|RSV|OCD|OCC|CUV|SUV|COV|SOV| CB AVG ( . )V |", // 0
"\r\n| F-Capa ( . )AH +---+---+---+---+---+---+---+---+---+ [ ] |", // 1
"\r\n+---------------------+ AFE STATUS ( ) UV TRIP ( ) +-[TEMP AVG ]--------+", // 2
"\r\n| Operate( )| CTRL1 ( ) OV TRIP ( ) | T-MAX ( . )C |", // 3
"\r\n| Status ( )| CTRL2 ( ) | T-AVG ( . )C |", // 4
"\r\n| | PROTECT( - - ) | T-MIN ( . )C |", // 5
"\r\n+--[Cell Volt]--------+ M( )| T-DIFF ( . )C |", // 6
"\r\n|( . )( . )( . )+---------+---------+---------+-----+---+----------------+", // 7
"\r\n|( . )( . )( . )|T1( . )|T3( . )|F1( . )| +-<INFORMATION>--+", // 8
"\r\n|( . )( . )( . )| | | | |DATE: / / |", // 9
"\r\n|( . )( . )( . )|T2( . )|T4( . )|F2( . )| |TIME: : : |", // 0
"\r\n|( . )( . )( . )| | | | |L-REBOOT ( )|", // 1
"\r\n+---------------------+---------+---------+---------+---------+----------------+", // 2
"\r\n s : SETTING d : DIAGNOSTIC " // 3
};
void AfemodeScreen(void)
{
for (int i = 0; i < 22; i++)
{
printf("%s", AfeMODE_STR[i]);
delay_os_ms(2);
}
}
int dis_numberOfCells;
uint8_t dis_AfeStatus;
uint8_t dis_AfeCtrl1;
uint8_t dis_AfeCtrl2;
uint8_t dis_AfeUvTrip;
uint8_t dis_AfeOvTrip;
uint8_t dis_AfeProtect[3];
int dis_cellVoltages[MAX_NUMBER_OF_CELLS]; // mV
uint32_t dis_batVoltage; // mV
int dis_temperatures[MAX_NUMBER_OF_THERMISTORS]; //
uint8_t dis_balStatus[3];
int dis_adcGain = 0; // uV/LSB
int dis_adcOffset = 0; // mV
extern int adcGain; // uV/LSB
extern int adcOffset; // mV
void AfeDisplayStatus(uint8_t p)
{
uint8_t text[20];
uint32_t sts = 0;
sts = getAfeStatus();
if (p || (dis_AfeStatus != sts))
{
sprintf((char *)text, "%02X", sts);
GreenOutXY(35, 12, text);
dis_AfeStatus = sts;
}
sts = getAfeCtrl1();
if (p || (dis_AfeCtrl1 != sts))
{
sprintf((char *)text, "%02X", sts);
GreenOutXY(35, 13, text);
dis_AfeCtrl1 = sts;
}
sts = getAfeCtrl2();
if (p || (dis_AfeCtrl2 != sts))
{
sprintf((char *)text, "%02X", sts);
GreenOutXY(35, 14, text);
dis_AfeCtrl2 = sts;
}
for (int i = 0; i < 3; i++)
{
sts = getAfeProtect(i);
if (p || (dis_AfeProtect[i] != sts))
{
sprintf((char *)text, "%02X", sts);
GreenOutXY(29 + (i * 3), 15, text);
dis_AfeProtect[i] = sts;
}
}
sts = getAfeUvTrip();
if (p || (dis_AfeUvTrip != sts))
{
sprintf((char *)text, "%02X", sts);
GreenOutXY(55, 12, text);
dis_AfeUvTrip = sts;
}
sts = getAfeOvTrip();
if (p || (dis_AfeOvTrip != sts))
{
sprintf((char *)text, "%02X", sts);
GreenOutXY(55, 13, text);
dis_AfeOvTrip = sts;
}
sts = getBatteryVoltage();
if (p || (dis_batVoltage != sts))
{
sprintf((char *)text, "%6.3f", (float)sts / 1000);
GreenOutXY(51, 14, text);
dis_batVoltage = sts;
}
for (int i = 0; i < 3; i++)
{
if (p || (dis_device_value.SectVoltage[i] != device_value.SectVoltage[i]))
{
sprintf((char *)text, "%7.3f", (float)device_value.SectVoltage[i] / 1000);
GreenOutXY(38 + (i * 7), 15, text);
dis_device_value.SectVoltage[i] = device_value.SectVoltage[i];
}
}
if (p || (dis_adcGain != adcGain))
{
sprintf((char *)text, "%04X", adcGain);
GreenOutXY(32, 16, text);
dis_adcGain = adcGain;
}
if (p || (dis_adcOffset != adcOffset))
{
sprintf((char *)text, "%04X", adcOffset);
GreenOutXY(40, 16, text);
dis_adcOffset = adcOffset;
}
}
uint8_t AfeSetBal(uint8_t *text, uint8_t aDevice)
{
uint16_t size, i, j;
int32_t aParam[4];
uint8_t temp[10];
uint8_t ret;
ret = 0;
size = 0;
while (text[size] != 0x00) size++; /* Measure total string length */
switch (aDevice)
{
case '0' : // Cell Balance Parameter Setting
i = 0;
if (size < 1 ) return(1);
j = FIND_CHAR((uint8_t *)&text[i], temp, size - i, ' ');
i = i + j + 1;
temp[j] = 0x00;
aParam[0] = StrToInt(temp, j);
SetManualBalancing(true, aParam[0]);
break;
case '1': // Cellbal off
SetManualBalancing(false, text[2] - 0x30);
break;
default:
ret = 1;
break;
}
return(ret); /* Setting value OK */
}
/* Command processing in SETTING STATE */
int8_t Process_DataAfeModeSet(uint8_t *text, uint16_t size)
{
uint16_t i, ret;
/* Invalid command if space is in first position */
if (size > 1) {if (text[1] != ' ') return(0);}
text[size] = 0x00;
ret = 1;
switch (text[0])
{
case 'o': /* Switch to operating mode */
screenmode = OP_MODE;
ViewScreen();
break;
case 's': /* Switch to setting status */
screenmode = SET_MODE;
ViewScreen();
break;
case 'd': /* Switch to diagnostic mode */
screenmode = DIAG_MODE;
ViewScreen();
break;
case '0': // OCV Alarm Parameter Setting
case '1': // OCV Alarm Parameter Setting
i = AfeSetBal(&text[2], text[0]);
if (i == 0)
UserMessage("COMMAND COMPLETE");
else if (i == 1)
UserMessage("COMMAND FORMAT ERROR"); /* setting format error */
else
UserMessage("COMMAND LIMIT ERROR"); /* setting limit error */
break;
default :
ret = 0;
break;
}
return(ret);
}
#endif // #ifdef CONSOLE_DEBUG
/*******************(C)COPYRIGHT 2022 AMG ********************END OF FILE******/