/** ****************************************************************************** * @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. * *

© COPYRIGHT 2022 AMG

****************************************************************************** */ /** @addtogroup mBMS2 * @{ */ /* Includes ------------------------------------------------------------------*/ #include #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( . )| +---+", // 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******/