Files
LFP_48V_mBMS_FW/APP_R3323/App/Source/io.c

745 lines
18 KiB
C

/**
******************************************************************************
* @file io.c
* @author AMG Energy Solution Team
* @version V1.0.0
* @date 07-Feb-2022
* @brief This file provides all the codes of I/O 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 "io.h"
#include "led.h"
#include "relay.h"
#include "buck.h"
#include "dev_addr.h"
#include "asutil.h"
#include "device_param.h"
#include "dflash_sf1.h"
//#include "log.h"
#include "delay.h"
//#include "modbus.h"
#include "buzzer.h"
#include "alarm.h"
//#include "pwm.h"
#include "brtc.h"
/* Private typedef -----------------------------------------------------------*/
typedef struct // Input PortNo 0..4 * 8 channels
{
// PORT Information
int16_t PortNo;
uint8_t NormalOpen; // Normal state logic level (0 or 1)
uint8_t Enabled; // Enable device?
int16_t RefPort; // Module disconnection reference Port
uint8_t State; // Current state of device
uint8_t OldState; // Previous state of device
// Chattering
uint8_t UsedChat; // Enable chattering filter
// MultiChat; // If OCCUR Chatt = 100, NORMAL Chatt = ChatTime, ex) Cable Open
uint8_t ChatState;
uint16_t AlarmChatTime; // Chattering Time (1 = 1ms)
uint16_t ReleaseChatTime; // Chattering Time (1 = 1ms)
uint16_t ChatCount; // Chattering internal counter
// Using Information
uint8_t Changed;
// Temp Var
uint8_t BakEnabled; // Flag for screen display
uint8_t StateFlag; // Flag for state storage
} TDIDeviceRec, *PDIDeviceRec;
/* Private define ------------------------------------------------------------*/
#define IO_TASK_TIME 1 // 50ms TASK
#define IO_ALARM_TIME 500 // 3000ms Alarm Delay
#define LED_ONOFF_TIME 200 // 500ms
#define DIDCount 4
/* Private macro -------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
uint8_t device_addr = 0;
TDIDeviceRec DID[DIDCount], BakDID[DIDCount];
TDEVICE_STATUS alarm_device_status;
uint8_t AlarmLed = false;
uint8_t AlarmLedFlag = false;
uint16_t AlarmLedTick = 0;
uint8_t BuzzerWarning = false;
uint8_t BuzzerProtection = false;
uint8_t AlarmBuzzerFlag = false;
uint16_t AlarmBuzzerTick = 0;
uint8_t RunLedFlag = false;
uint16_t RunLedTick = 0;
uint8_t SocLedFlag = false;
uint16_t SocLedTick = 0;
uint8_t SocLed[4] = { 0 };
uint8_t RemoteReset = false;
/* Private function prototypes -----------------------------------------------*/
void IO_Relay_Control(void);
void Buzzer_Process(void);
void Led_Process(void);
void InitDIO(int16_t port, int16_t ref_port, uint8_t io_type, uint16_t alarm_time, uint16_t release_time, uint8_t enable);
void Check_DI(void);
void AnalysisDI(PDIDeviceRec aDID);
void dec_led_time(uint32_t tick);
void dec_buzzer_time(uint32_t tick);
/* Private function ----------------------------------------------------------*/
void InitDIODevice(void)
{
LED_Init();
LED_On(LED_ALL);
delay_os_ms(1000);
LED_Off(LED_ALL);
LED_On(LED_G);
Buck_ctrl_Init();
Relay_Init();
DevAddrInit();
for (int i = 0; i < DIDCount; i++) {
DID[i].Enabled = true;
DID[i].PortNo = -1; // Undefine Port
DID[i].RefPort = -1; // Not used ref Port
DID[i].State = cNORMAL;
DID[i].OldState = cNORMAL;
DID[i].Changed = false;
DID[i].UsedChat = true;
DID[i].AlarmChatTime = 0;
DID[i].ReleaseChatTime = 0;
DID[i].ChatCount = 0;
DID[i].ChatState = cINITVALUE;
DID[i].BakEnabled = cINITVALUE; // Flag for screen display
DID[i].StateFlag = cINITVALUE; // Flag for state storage DID[i].Enabled = true;
}
InitDIO(DI_DISCHA_RELAY , -1, cNormalClose, IO_ALARM_TIME, IO_ALARM_TIME, true);
InitDIO(DI_CHARGE_RELAY , -1, cNormalClose, IO_ALARM_TIME, IO_ALARM_TIME, true);
InitDIO(DI_PRE_CHG_RELAY, -1, cNormalClose, IO_ALARM_TIME, IO_ALARM_TIME, true);
memset(&alarm_device_status, 0x00, sizeof(TDEVICE_STATUS));
}
void InitDIO(int16_t port, int16_t ref_port, uint8_t io_type, uint16_t alarm_time, uint16_t release_time, uint8_t enable)
{
DID[port].Enabled = enable;
DID[port].PortNo = port;
DID[port].RefPort = ref_port;
DID[port].NormalOpen = io_type;
DID[port].AlarmChatTime = alarm_time;
DID[port].ReleaseChatTime = release_time;
}
uint8_t GetDevAddrIO(void)
{
return device_addr;
}
void SetRemoteReset(void)
{
RemoteReset = true;
}
void App_TaskIO(void)
{
InitDIODevice();
while (DEF_TRUE) {
device_addr = GetDevAddr();
Check_DI();
ProcessAlarm();
IO_Relay_Control();
Led_Process();
// Buzzer_Process();
if (RemoteReset == true) {
delay_os_ms(100);
NVIC_SystemReset();
}
delay_os_ms(IO_TASK_TIME);
}
}
void DecIOTaskTick(uint32_t tick)
{
dec_led_time(tick);
dec_buzzer_time(tick);
}
void Check_DI(void)
{
int16_t i;
for (i = 0; i < DIDCount; i++) {
DID[i].Changed = false;
AnalysisDI(&DID[i]);
}
device_status.battery_status.bit.DSG_S = (DIDState(DI_DISCHA_RELAY ) != cNORMAL) ? 1 : 0;
device_status.battery_status.bit.CHG_S = (DIDState(DI_CHARGE_RELAY ) != cNORMAL) ? 1 : 0;
device_status.battery_status.bit.ZVC_S = (DIDState(DI_PRE_CHG_RELAY) != cNORMAL) ? 1 : 0;
}
uint8_t GetIOBit(uint16_t port)
{
uint8_t result = 0;
switch (port) {
case DI_DISCHA_RELAY : result = Relay_Status(DI_DISCHA_RELAY ); break;
case DI_CHARGE_RELAY : result = Relay_Status(DI_CHARGE_RELAY ); break;
case DI_PRE_CHG_RELAY: result = Relay_Status(DI_PRE_CHG_RELAY); break;
default:
break;
}
return result;
}
void AnalysisDI(PDIDeviceRec aDID)
{
uint16_t ChatTime;
uint8_t BitState;
if (aDID->PortNo == -1) return; /* Undefined DI PORT */
aDID->OldState = aDID->State;
aDID->Changed = false;
aDID->StateFlag = true;
BitState = GetIOBit(aDID->PortNo);
if (aDID->NormalOpen == cNormalClose) BitState ^= aDID->NormalOpen;
if (aDID->UsedChat == true)
{
if (aDID->State == cNORMAL)
ChatTime = aDID->AlarmChatTime;
else
ChatTime = aDID->ReleaseChatTime;
if (aDID->ChatState == BitState)
{
if (aDID->ChatCount < 10000) aDID->ChatCount += IO_TASK_TIME;
}
else
aDID->ChatCount = 0;
aDID->ChatState = BitState;
if (aDID->ChatCount < ChatTime) BitState = aDID->State;
}
if (aDID->RefPort != -1) /* CABLE OPEN or FAIL reference PORT */
{
if (DID[aDID->RefPort].State == cOCCUR)
{
BitState = cUNKNOWN;
aDID->Changed = DID[aDID->RefPort].Changed;
}
}
if (BitState != aDID->OldState) /* State changed */
{
aDID->Changed = true;
aDID->OldState = BitState;
aDID->State = BitState;
aDID->StateFlag = true; /* Flag for state storage */
}
}
void DIDAlarmHistory(PDIDeviceRec aDID,uint8_t msg1,uint8_t msg2,uint8_t msg3,uint8_t msg4)
{
if (aDID->Enabled == true){
if (aDID->Changed)
{
// switch (aDID->State) {
// case cNORMAL : ADD_RUN_HISTORY(true,osENVIR,0,0,msg1,msg2);
// break;
// case cOCCUR : ADD_RUN_HISTORY(true,osENVIR,0,0,msg1,msg3);
// break;
// case cUNKNOWN: ADD_RUN_HISTORY(true,osENVIR,0,0,msg1,msg4);
// break;
// }
}
}
}
void DoorAlarmHistory(PDIDeviceRec aDID,uint8_t msg1,uint8_t msg2,uint8_t msg3,uint8_t msg4)
{
if (aDID->Enabled == true)
{
if (aDID->Changed)
{
switch (aDID->State)
{
case cNORMAL :
// ADD_RUN_HISTORY(true,osENVIR,0,0,msg1,msg2);
break;
case cOCCUR :
// ADD_RUN_HISTORY(true,osENVIR,0,0,msg1,msg3);
break;
case cUNKNOWN:
// ADD_RUN_HISTORY(true,osENVIR,0,0,msg1,msg4);
break;
}
}
}
}
uint8_t DIDState(uint16_t i) // return cNORMAL, cDISABLE, cOCCUR, cUNKNOWN
{
uint8_t Alarmflag;
Alarmflag = cNORMAL;
if (DID[i].Enabled != true) Alarmflag = cDISABLE; // No Alarm
else
{
if (DID[i].State == cOCCUR) Alarmflag = cOCCUR;
if (DID[i].RefPort != -1)
{
if (DID[DID[i].RefPort].State == cOCCUR)
{
Alarmflag = cUNKNOWN; // fail
}
}
}
return(Alarmflag);
}
uint8_t relay_test_mode = false;
uint8_t chg_relay_test = false;
uint8_t dch_relay_test = false;
uint8_t pre_relay_test = false;
void IO_Relay_Control(void)
{
if (relay_test_mode) {
if (chg_relay_test) { Relay_On(DO_CHG_RELAY_ID); }
else { Relay_Off(DO_CHG_RELAY_ID); }
if (dch_relay_test) { Relay_On(DO_DSG_RELAY_ID); }
else { Relay_Off(DO_DSG_RELAY_ID); }
if (pre_relay_test) { Relay_On(DO_PRE_CHG_RELAY_ID); }
else { Relay_Off(DO_PRE_CHG_RELAY_ID); }
} else {
if (device_status.battery_status.bit.INIT) {
if (device_status.battery_status.bit.CHG_C == RON) Relay_On(DO_CHG_RELAY_ID);
else Relay_Off(DO_CHG_RELAY_ID);
if (device_status.battery_status.bit.DSG_C == RON) Relay_On(DO_DSG_RELAY_ID);
else Relay_Off(DO_DSG_RELAY_ID);
if (device_status.battery_status.bit.ZVC_C == RON) Relay_On(DO_PRE_CHG_RELAY_ID);
else Relay_Off(DO_PRE_CHG_RELAY_ID);
}
}
}
void dec_led_time(uint32_t tick)
{
if (AlarmLedTick > 0) {
if (AlarmLedTick > tick) AlarmLedTick -= tick;
else AlarmLedTick = 0;
}
if (RunLedTick > 0) {
if (RunLedTick > tick) RunLedTick -= tick;
else RunLedTick = 0;
}
if (SocLedTick > 0) {
if (SocLedTick > tick) SocLedTick -= tick;
else SocLedTick = 0;
}
}
void Alarm_Led_ProcessInSleep(void)
{
if (AlarmLedFlag == true) {
if (AlarmLedTick == 0) {
LED_On(LED_R);
AlarmLedTick = 500;
AlarmLedFlag = false;
}
} else {
if (AlarmLedTick == 0) {
LED_Off(LED_R);
AlarmLedTick = 5000;
AlarmLedFlag = true;
}
}
}
void Alarm_Led_Process(void)
{
switch (device_status.alarm_status) {
case 0: // Normal
LED_Off(LED_R);
break;
case 1: // Warning
if (AlarmLedFlag == true) {
if (AlarmLedTick == 0) {
LED_On(LED_R);
AlarmLedTick = 1000;
AlarmLedFlag = false;
}
} else {
if (AlarmLedTick == 0) {
LED_Off(LED_R);
AlarmLedTick = 1000;
AlarmLedFlag = true;
}
}
break;
case 2: // Protection
LED_On(LED_R);
break;
case 3: // WarmingUp
LED_Off(LED_R);
break;
}
}
void RUN_LED_Process(void)
{
switch (device_status.op_status) {
case 0: // Standby
LED_On(LED_G);
break;
case 1: // Charging
LED_On(LED_G);
break;
case 2: // Discharging
if (RunLedFlag == true) {
if (RunLedTick == 0) {
LED_On(LED_G);
RunLedTick = 1000;
RunLedFlag = false;
}
} else {
if (RunLedTick == 0) {
LED_Off(LED_G);
RunLedTick = 1000;
RunLedFlag = true;
}
}
break;
case 3: // Floating
LED_On(LED_G);
break;
}
}
void SOC_LED_Buf_Clear(void)
{
for (int i = 0; i < 4; i++) SocLed[i] = 5;
}
void SOC_LED_Buf(uint32_t soc, uint16_t mode)
{
switch (mode) {
case 0: // Standby
for (int i = 0; i < 4; i++) {
if (SocLed[i] == 2) {
SocLed[i] = 1;
} else if (SocLed[i] == 3) {
SocLed[i] = 0;
} else if (SocLed[i] == 5) {
if (soc > 750) {
switch (i) {
case 0: SocLed[i] = 1; break;
case 1: SocLed[i] = 1; break;
case 2: SocLed[i] = 1; break;
case 3: SocLed[i] = 1; break;
}
} else if (soc > 500) {
switch (i) {
case 0: SocLed[i] = 1; break;
case 1: SocLed[i] = 1; break;
case 2: SocLed[i] = 1; break;
case 3: SocLed[i] = 0; break;
}
} else if (soc > 250) {
switch (i) {
case 0: SocLed[i] = 1; break;
case 1: SocLed[i] = 1; break;
case 2: SocLed[i] = 0; break;
case 3: SocLed[i] = 0; break;
}
} else if (soc > 0) {
switch (i) {
case 0: SocLed[i] = 1; break;
case 1: SocLed[i] = 0; break;
case 2: SocLed[i] = 0; break;
case 3: SocLed[i] = 0; break;
}
} else {
SocLed[i] = 0;
}
}
}
break;
case 1: // Charging
if (soc > 750) {
SocLed[0] = 1;
SocLed[1] = 1;
SocLed[2] = 1;
if (SocLed[3] == 1) SocLed[3] = 2;
else if (SocLed[3] == 0) SocLed[3] = 3;
} else if (soc > 500) {
SocLed[0] = 1;
SocLed[1] = 1;
if (SocLed[2] == 1) SocLed[2] = 2;
else if (SocLed[2] == 0) SocLed[2] = 3;
SocLed[3] = 0;
} else if (soc > 250) {
SocLed[0] = 1;
if (SocLed[1] == 1) SocLed[1] = 2;
else if (SocLed[1] == 0) SocLed[1] = 3;
SocLed[2] = 0;
SocLed[3] = 0;
} else if (soc > 0) {
if (SocLed[0] == 1) SocLed[0] = 2;
else if (SocLed[0] == 0) SocLed[0] = 3;
SocLed[1] = 0;
SocLed[2] = 0;
SocLed[3] = 0;
} else {
SocLed[0] = 0;
SocLed[1] = 0;
SocLed[2] = 0;
SocLed[3] = 0;
}
break;
case 2: // Discharging
if (soc > 750) {
SocLed[0] = 1;
SocLed[1] = 1;
SocLed[2] = 1;
if (SocLed[3] == 2) SocLed[3] = 1;
else if (SocLed[3] == 3) SocLed[3] = 0;
} else if (soc > 500) {
SocLed[0] = 1;
SocLed[1] = 1;
if (SocLed[2] == 2) SocLed[2] = 1;
else if (SocLed[2] == 3) SocLed[2] = 0;
SocLed[3] = 0;
} else if (soc > 250) {
SocLed[0] = 1;
if (SocLed[1] == 2) SocLed[1] = 1;
else if (SocLed[1] == 3) SocLed[1] = 0;
SocLed[2] = 0;
SocLed[3] = 0;
} else if (soc > 0) {
if (SocLed[0] == 2) SocLed[0] = 1;
else if (SocLed[0] == 3) SocLed[0] = 0;
SocLed[1] = 0;
SocLed[2] = 0;
SocLed[3] = 0;
} else {
SocLed[0] = 0;
SocLed[1] = 0;
SocLed[2] = 0;
SocLed[3] = 0;
}
break;
case 3: // Floating
if (soc >= 1000) {
SocLed[0] = 1;
SocLed[1] = 1;
SocLed[2] = 1;
SocLed[3] = 1;
} else {
for (int i = 0; i < 4; i++) {
if (SocLed[i] == 2) SocLed[i] = 1;
else if (SocLed[i] == 3) SocLed[i] = 0;
}
}
break;
case 4: // WarmingUp
if (soc > 750) {
SocLed[0] = 1;
SocLed[1] = 1;
SocLed[2] = 1;
SocLed[3] = 1;
} else if (soc > 500) {
SocLed[0] = 1;
SocLed[1] = 1;
SocLed[2] = 1;
SocLed[3] = 0;
} else if (soc > 250) {
SocLed[0] = 1;
SocLed[1] = 1;
SocLed[2] = 0;
SocLed[3] = 0;
} else if (soc > 0) {
SocLed[0] = 1;
SocLed[1] = 0;
SocLed[2] = 0;
SocLed[3] = 0;
} else {
SocLed[0] = 0;
SocLed[1] = 0;
SocLed[2] = 0;
SocLed[3] = 0;
}
break;
}
}
void SOC_LED_Control(uint8_t no, uint8_t onoff)
{
switch (no) {
case 0: if (onoff) LED_On(LED_SOC_0); else LED_Off(LED_SOC_0); break;
case 1: if (onoff) LED_On(LED_SOC_1); else LED_Off(LED_SOC_1); break;
case 2: if (onoff) LED_On(LED_SOC_2); else LED_Off(LED_SOC_2); break;
case 3: if (onoff) LED_On(LED_SOC_3); else LED_Off(LED_SOC_3); break;
}
}
void SOC_LED_Process(void)
{
SOC_LED_Buf(device_value.RelativeStateOfCharge, device_status.op_status);
for (int i = 0; i < 4; i++) {
switch (SocLed[i]) {
case 0: // LED Off
SOC_LED_Control(i, 0);
break;
case 1: // LED On
SOC_LED_Control(i, 1);
break;
case 2: // LED Toggle
case 3: // LED Toggle
if (SocLedFlag == true) {
if (SocLedTick == 0) {
SOC_LED_Control(i, 1); // On
SocLedTick = 1000;
SocLedFlag = false;
}
} else {
if (SocLedTick == 0) {
SOC_LED_Control(i, 0); // Off
SocLedTick = 1000;
SocLedFlag = true;
}
}
break;
}
}
}
void Led_Process(void)
{
if (GetSleepMode() == 0) {
Alarm_Led_Process();
RUN_LED_Process();
SOC_LED_Process();
} else {
LED_Off(LED_SOC_0);
LED_Off(LED_SOC_1);
LED_Off(LED_SOC_2);
LED_Off(LED_SOC_3);
LED_Off(LED_G);
Alarm_Led_ProcessInSleep();
}
}
void Alarm_Buzzer_Update(void)
{
alarm_device_status.warning.value = device_status.warning.value;
alarm_device_status.protect.value = device_status.protect.value;
}
void Alarm_Buzzer_Process(void)
{
uint8_t buzzer = false;
if (alarm_device_status.warning.value < device_status.warning.value) {
buzzer = true;
} else {
alarm_device_status.warning.value = device_status.warning.value;
}
BuzzerWarning = buzzer;
buzzer = false;
if (alarm_device_status.protect.value < device_status.protect.value) {
buzzer = true;
} else {
alarm_device_status.protect.value = device_status.protect.value;
}
BuzzerProtection = buzzer;
}
void dec_buzzer_time(uint32_t tick)
{
if (AlarmBuzzerTick > 0) {
if (AlarmBuzzerTick > 0) AlarmBuzzerTick -= tick;
else AlarmBuzzerTick = 0;
}
}
void Buzzer_Process(void)
{
Alarm_Buzzer_Process();
if (BuzzerProtection) {
// Protection
if (AlarmBuzzerFlag == true) {
if (AlarmBuzzerTick == 0) {
Buzzer(false);
AlarmBuzzerTick = 500;
AlarmBuzzerFlag = false;
}
} else {
if (AlarmBuzzerTick == 0) {
Buzzer(true);
AlarmBuzzerTick = 500;
AlarmBuzzerFlag = true;
}
}
} else if (BuzzerWarning) {
// Warning
if (AlarmBuzzerFlag == true) {
if (AlarmBuzzerTick == 0) {
Buzzer(false);
AlarmBuzzerTick = 1000;
AlarmBuzzerFlag = false;
}
} else {
if (AlarmBuzzerTick == 0) {
Buzzer(1);
AlarmBuzzerTick = 1000;
AlarmBuzzerFlag = true;
}
}
} else {
Buzzer(false);
}
}
/*******************(C)COPYRIGHT 2022 AMG ********************END OF FILE******/