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

© COPYRIGHT 2022 AMG

****************************************************************************** */ /** @addtogroup mBMS2 * @{ */ /* Includes ------------------------------------------------------------------*/ #include #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******/