#include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include /*標準輸入輸出定義*/ #include /*標準函數庫定義*/ #include /*Unix 標準函數定義*/ #include /*檔控制定義*/ #include /*PPSIX 終端控制定義*/ #include /*錯誤號定義*/ #include #include #include #include #include #include #include "../../define.h" #include "internalComm.h" #include #define ARRAY_SIZE(A) (sizeof(A) / sizeof(A[0])) #define PASS 1 #define FAIL -1 #define YES 1 #define NO 0 #define TEN_MINUTES 600 #define ENV_TEMP_MIN 45 #define ENV_TEMP_MAX 50 #define DEFAULT_AC_INDEX 2 #define EQUAL 0 #define COLOR_MAX_LV 100 #define COLOR_MIN_LV 0 #define AC_DEFAULT_VOL 220 #define NO_DEFINE 255 #define NDEFAULT_AC_INDEX 2 struct SysConfigAndInfo *ShmSysConfigAndInfo; struct StatusCodeData *ShmStatusCodeData; struct FanModuleData *ShmFanModuleData; struct RelayModuleData *ShmRelayModuleData; struct LedModuleData *ShmLedModuleData; struct PsuData *ShmPsuData; struct OCPP16Data *ShmOCPP16Data; #define VIN_MAX_VOLTAGE_IEC 285 // 大於該值 : OVP #define VIN_MIN_VOLTAGE_IEC 160 // 小於該值 : UVP #define VIN_MAX_VOLTAGE_UL 315 // 大於該值 : OVP // 美規 (W) #define VIN_MIN_VOLTAGE_UL 210 // 小於該值 : UVP #define VIN_DROP_VOLTAGE 150 // 小於該值 : ac drop #define VOUT_MAX_VOLTAGE 995 #define VOUT_MIN_VOLTAGE 150 #define IOUT_MAX_CURRENT 50 #define MAX_FAN_SPEED 14000 #define MIN_FAN_SPEED 3000 #define NORMAL_FAN_SPEED 7000 // GFD Status #define GFD_IDLE 0 #define GFD_CABLECHK 1 #define GFD_PRECHARGE 2 #define GFD_CHARGING 3 // LED Intensity (rate) #define LED_INTENSITY_DARKEST 0.2 #define LED_INTENSITY_MEDIUM 0.6 #define LED_INTENSITY_BRIGHTEST 1 // EE Spec #define LED_BRIGHTNESS_LV_HIGH 1 #define LED_BRIGHTNESS_LV_MID 0.5 #define LED_BRIGHTNESS_LV_LOW 0.2 // 最小切換 Relay 電壓 #define SELF_TO_CHANGE_RELAY_STATUS 600 // 透過電壓確認 Relay 是否搭上的依據電壓 #define CHECK_RELAY_STATUS 300 #define CHECK_RELAY_STATUS_GAP 100 // 安全在停止充電程序中斷開 Relay 的電流 #define SEFETY_SWITCH_RELAY_CUR 20 // 確認 Relay Welding 電壓 #define RELAY_WELDING_DET 300 byte gunCount; byte acgunCount; // 槍資訊 struct ChargingInfoData *_chargingData[CHAdeMO_QUANTITY + CCS_QUANTITY + GB_QUANTITY]; struct ChargingInfoData *ac_chargingInfo[AC_QUANTITY]; bool _isOutputNoneMatch[CHAdeMO_QUANTITY + CCS_QUANTITY + GB_QUANTITY]; struct timeval _checkOutputNoneMatchTimer[CHAdeMO_QUANTITY + CCS_QUANTITY + GB_QUANTITY]; bool _isRelayWelding[CHAdeMO_QUANTITY + CCS_QUANTITY + GB_QUANTITY]; struct timeval _checkRelayWeldingTimer[CHAdeMO_QUANTITY + CCS_QUANTITY + GB_QUANTITY]; bool FindChargingInfoData(byte target, struct ChargingInfoData **chargingData); int Uart5Fd; char *relayRs485PortName = "/dev/ttyS5"; unsigned short fanSpeedSmoothValue = 500; bool isStopChargingCount = false; struct timeval _close_ac_contactor; struct timeval _priority_time; struct timeval _led_priority_time; struct timeval _ac_charging_comp; struct timeval _ac_preparing; struct timeb _ac_startChargingTime; struct timeb _ac_endChargingTime; unsigned short _setFanSpeed = 0; float _beforeChargingTotalEnergy = 0.0; byte _checkLedChanged = 3; Ver ver; PresentInputVoltage inputVoltage; PresentOutputVoltage outputVoltage; FanSpeed fanSpeed; Temperature temperature; AuxPower auxPower; Gfd gfd_adc; Gfd_config gfd_config; Gpio_in gpio_in; Gpio_out gpio_out; Relay outputRelay; Relay regRelay; Rtc rtc; Led_Color cur_led_color; Led_Color led_color; Ac_Status acStatus; Ac_Led_Status ledStatus; Ac_Alarm_code acAlarmCode; Ac_Charging_energy acChargingEnergy; Ac_Charging_current acChargingCurrent; #define AC_OVP 1 #define AC_UVP 2 #define AC_OCP 4 #define AC_OTP 8 #define AC_GMI_FAULT 16 #define AC_CP_ERROR 32 #define AC_AC_LEAKAGE 64 #define AC_DC_LEAKAGE 128 #define AC_SYSTEM_SELFTEST_FAULT 256 #define AC_HANDSHAKE_TIMEOUT 512 #define AC_EMC_STOP 1024 #define AC_RELAY_WELDING 2048 #define AC_GF_MODULE_FAULT 4096 #define AC_SHUTTER_FAULT 8192 #define AC_LOCKER_FAULT 16384 #define AC_POWER_DROP 32768 #define AC_CIRCUIT_SHORT 65536 #define AC_ROTARY_SWITCH_FAULT 131072 #define AC_RELAY_DRIVE_FAULT 262144 int _alarm_code[] = {AC_OVP, AC_UVP, AC_OCP, AC_OTP, AC_GMI_FAULT, AC_CP_ERROR, AC_AC_LEAKAGE , AC_DC_LEAKAGE, AC_SYSTEM_SELFTEST_FAULT, AC_HANDSHAKE_TIMEOUT, AC_EMC_STOP, AC_RELAY_WELDING , AC_GF_MODULE_FAULT, AC_SHUTTER_FAULT, AC_LOCKER_FAULT, AC_POWER_DROP, AC_CIRCUIT_SHORT , AC_ROTARY_SWITCH_FAULT, AC_RELAY_DRIVE_FAULT}; void PRINTF_FUNC(char *string, ...); unsigned long GetTimeoutValue(struct timeval _sour_time); #define DEBUG_INFO(format, args...) StoreLogMsg("[%s:%d][%s][Info] "format, __FILE__, __LINE__, __FUNCTION__, ##args) #define DEBUG_WARN(format, args...) StoreLogMsg("[%s:%d][%s][Warn] "format, __FILE__, __LINE__, __FUNCTION__, ##args) #define DEBUG_ERROR(format, args...) StoreLogMsg("[%s:%d][%s][Error] "format, __FILE__, __LINE__, __FUNCTION__, ##args) unsigned long GetTimeoutValue(struct timeval _sour_time) { struct timeval _end_time; gettimeofday(&_end_time, NULL); return 1000000 * (_end_time.tv_sec - _sour_time.tv_sec) + _end_time.tv_usec - _sour_time.tv_usec; } int StoreLogMsg(const char *fmt, ...) { char Buf[4096+256]; char buffer[4096]; va_list args; struct timeb SeqEndTime; struct tm *tm; va_start(args, fmt); int rc = vsnprintf(buffer, sizeof(buffer), fmt, args); va_end(args); memset(Buf,0,sizeof(Buf)); ftime(&SeqEndTime); SeqEndTime.time = time(NULL); tm=localtime(&SeqEndTime.time); if (ShmSysConfigAndInfo->SysConfig.SwitchDebugFlag == YES) { sprintf(Buf,"%02d:%02d:%02d.%03d - %s", tm->tm_hour,tm->tm_min,tm->tm_sec,SeqEndTime.millitm, buffer); printf("%s \n", Buf); } else { sprintf(Buf,"echo \"%04d-%02d-%02d %02d:%02d:%02d.%03d - %s\" >> /Storage/SystemLog/[%04d.%02d]SystemLog", tm->tm_year+1900,tm->tm_mon+1,tm->tm_mday,tm->tm_hour,tm->tm_min,tm->tm_sec,SeqEndTime.millitm, buffer, tm->tm_year+1900,tm->tm_mon+1); system(Buf); } return rc; } int DiffTimeb(struct timeb ST, struct timeb ET) { //return milli-second unsigned int StartTime, StopTime; StartTime = (unsigned int) ST.time; StopTime = (unsigned int) ET.time; return (StopTime - StartTime); } unsigned short MaxValue(unsigned short value1, unsigned short value2) { return value1 >= value2 ? value1 : value2; } void PRINTF_FUNC(char *string, ...) { va_list args; char buffer[4096]; va_start(args, string); vsnprintf(buffer, sizeof(buffer), string, args); va_end(args); DEBUG_INFO("%s \n", buffer); } //========================================== // Communication Function //========================================== void GetFwAndHwVersion_Fan() { if(Query_FW_Ver(Uart5Fd, Addr.Fan, &ver) == PASS) { // FanModuleData strcpy((char *) ShmFanModuleData->version, ver.Version_FW); // SystemInfo strcpy((char *) ShmSysConfigAndInfo->SysInfo.FanModuleFwRev, ver.Version_FW); //PRINTF_FUNC("GetFwAndHwVersion_Fan s1 = %s \n", ver.Version_FW); } if (Query_HW_Ver(Uart5Fd, Addr.Fan, &ver) == PASS) { // SystemInfo strcpy((char *) ShmSysConfigAndInfo->SysInfo.FanModuleHwRev, ver.Version_FW); //PRINTF_FUNC("GetFwAndHwVersion_Fan s2 = %s \n", ver.Version_HW); } } void GetFwAndHwVersion_Relay() { if (Query_FW_Ver(Uart5Fd, Addr.Relay, &ver) == PASS) { // RelayModuleData strcpy((char *) ShmRelayModuleData->version, ver.Version_FW); // SystemInfo strcpy((char *) ShmSysConfigAndInfo->SysInfo.RelayModuleFwRev, ver.Version_FW); //PRINTF_FUNC("GetFwAndHwVersion_Relay s1 = %s \n", ver.Version_FW); } if (Query_HW_Ver(Uart5Fd, Addr.Relay, &ver) == PASS) { // SystemInfo strcpy((char *) ShmSysConfigAndInfo->SysInfo.RelayModuleHwRev, ver.Version_FW); //PRINTF_FUNC("GetFwAndHwVersion_Relay s2 = %s \n", ver.Version_HW); } } void GetFwAndHwVersion_Led() { if (Query_FW_Ver(Uart5Fd, Addr.Led, &ver) == PASS) { // LedModuleData strcpy((char *) ShmLedModuleData->version, ver.Version_FW); // SystemInfo strcpy((char *) ShmSysConfigAndInfo->SysInfo.LedModuleFwRev, ver.Version_FW); PRINTF_FUNC("GetFwAndHwVersion_Led s1 = %s \n", ver.Version_FW); ShmLedModuleData->SelfTest_Comp = YES; } else { //PRINTF_FUNC("GetFwAndHwVersion_Led fail \n"); } } void GetFwVersion_AC() { if (Query_FW_Ver(Uart5Fd, Addr.AcPlug, &ver) == PASS) { ac_chargingInfo[0]->SelfTest_Comp = YES; strcpy((char *) ac_chargingInfo[0]->version, ver.Version_FW); } } void GetAcModelName() { memset(ShmSysConfigAndInfo->SysConfig.AcModelName, 0x00, sizeof(ShmSysConfigAndInfo->SysConfig.AcModelName)); if (Query_Model_Name(Uart5Fd, Addr.AcPlug, ShmSysConfigAndInfo->SysConfig.AcModelName) == PASS) { PRINTF_FUNC("ac model name = %s \n", ShmSysConfigAndInfo->SysConfig.AcModelName); } } void SetRtcData_Relay() { struct timeb csuTime; struct tm *tmCSU; ftime(&csuTime); tmCSU = localtime(&csuTime.time); // PRINTF_FUNC("Time : %04d-%02d-%02d %02d:%02d:%02d \n", tmCSU->tm_year + 1900, // tmCSU->tm_mon + 1, tmCSU->tm_mday, tmCSU->tm_hour, tmCSU->tm_min, // tmCSU->tm_sec); rtc.RtcData[0] = '0' + (tmCSU->tm_year + 1900) / 1000 % 10; rtc.RtcData[1] = '0' + (tmCSU->tm_year + 1900) / 100 % 10; rtc.RtcData[2] = '0' + (tmCSU->tm_year + 1900) / 10 % 10; rtc.RtcData[3] = '0' + (tmCSU->tm_year + 1900) / 1 % 10; rtc.RtcData[4] = '0' + (tmCSU->tm_mon + 1) / 10 % 10; rtc.RtcData[5] = '0' + (tmCSU->tm_mon + 1) / 1 % 10; rtc.RtcData[6] = '0' + (tmCSU->tm_mday) / 10 % 10; rtc.RtcData[7] = '0' + (tmCSU->tm_mday) / 1 % 10; rtc.RtcData[8] = '0' + (tmCSU->tm_hour) / 10 % 10; rtc.RtcData[9] = '0' + (tmCSU->tm_hour) / 1 % 10; rtc.RtcData[10] = '0' + (tmCSU->tm_min) / 10 % 10; rtc.RtcData[11] = '0' + (tmCSU->tm_min) / 1 % 10; rtc.RtcData[12] = '0' + (tmCSU->tm_sec) / 10 % 10; rtc.RtcData[13] = '0' + (tmCSU->tm_sec) / 1 % 10; if (Config_Rtc_Data(Uart5Fd, Addr.Relay, &rtc) == PASS) { //PRINTF_FUNC("SetRtc (RB) sucessfully. \n"); } } void SetRtcData_Fan() { struct timeb csuTime; struct tm *tmCSU; ftime(&csuTime); tmCSU = localtime(&csuTime.time); // PRINTF_FUNC("Time : %04d-%02d-%02d %02d:%02d:%02d \n", tmCSU->tm_year + 1900, // tmCSU->tm_mon + 1, tmCSU->tm_mday, tmCSU->tm_hour, tmCSU->tm_min, // tmCSU->tm_sec); rtc.RtcData[0] = '0' + (tmCSU->tm_year + 1900) / 1000 % 10; rtc.RtcData[1] = '0' + (tmCSU->tm_year + 1900) / 100 % 10; rtc.RtcData[2] = '0' + (tmCSU->tm_year + 1900) / 10 % 10; rtc.RtcData[3] = '0' + (tmCSU->tm_year + 1900) / 1 % 10; rtc.RtcData[4] = '0' + (tmCSU->tm_mon + 1) / 10 % 10; rtc.RtcData[5] = '0' + (tmCSU->tm_mon + 1) / 1 % 10; rtc.RtcData[6] = '0' + (tmCSU->tm_mday) / 10 % 10; rtc.RtcData[7] = '0' + (tmCSU->tm_mday) / 1 % 10; rtc.RtcData[8] = '0' + (tmCSU->tm_hour) / 10 % 10; rtc.RtcData[9] = '0' + (tmCSU->tm_hour) / 1 % 10; rtc.RtcData[10] = '0' + (tmCSU->tm_min) / 10 % 10; rtc.RtcData[11] = '0' + (tmCSU->tm_min) / 1 % 10; rtc.RtcData[12] = '0' + (tmCSU->tm_sec) / 10 % 10; rtc.RtcData[13] = '0' + (tmCSU->tm_sec) / 1 % 10; if (Config_Rtc_Data(Uart5Fd, Addr.Fan, &rtc) == PASS) { //PRINTF_FUNC("SetRtc (FB) sucessfully. \n"); } } void SetModelName_Fan() { if (Config_Model_Name(Uart5Fd, Addr.Fan, ShmSysConfigAndInfo->SysConfig.ModelName) == PASS) { PRINTF_FUNC("Set Model name PASS = %s \n", ShmSysConfigAndInfo->SysConfig.ModelName); } } // AC 三相輸入電壓 void GetPresentInputVol() { if (Query_Present_InputVoltage(Uart5Fd, Addr.Relay, &inputVoltage) == PASS) { // resolution : 0.1 ShmSysConfigAndInfo->SysInfo.InputVoltageR = ShmRelayModuleData->InputL1Volt = inputVoltage.L1N_L12; ShmSysConfigAndInfo->SysInfo.InputVoltageS = ShmRelayModuleData->InputL2Volt = inputVoltage.L2N_L23; ShmSysConfigAndInfo->SysInfo.InputVoltageT = ShmRelayModuleData->InputL3Volt = inputVoltage.L3N_L31; //********************************************************************************************************// // Vin (UVP) if (ShmSysConfigAndInfo->SysInfo.ChargerType == _CHARGER_TYPE_IEC) { if (inputVoltage.L1N_L12 < VIN_MIN_VOLTAGE_IEC) { PRINTF_FUNC("In Uvp L1N_L12 = %f \n", inputVoltage.L1N_L12); ShmStatusCodeData->AlarmCode.AlarmEvents.bits.SystemL1InputUVP = YES; } else ShmStatusCodeData->AlarmCode.AlarmEvents.bits.SystemL1InputUVP = NO; if (inputVoltage.L2N_L23 < VIN_MIN_VOLTAGE_IEC) { PRINTF_FUNC("In Uvp L2N_L23 = %f \n", inputVoltage.L2N_L23); ShmStatusCodeData->AlarmCode.AlarmEvents.bits.SystemL2InputUVP = YES; } else ShmStatusCodeData->AlarmCode.AlarmEvents.bits.SystemL2InputUVP = NO; if (inputVoltage.L3N_L31 < VIN_MIN_VOLTAGE_IEC) { PRINTF_FUNC("In Uvp L3N_L31 = %f \n", inputVoltage.L3N_L31); ShmStatusCodeData->AlarmCode.AlarmEvents.bits.SystemL3InputUVP = YES; } else ShmStatusCodeData->AlarmCode.AlarmEvents.bits.SystemL3InputUVP = NO; } else if (ShmSysConfigAndInfo->SysInfo.ChargerType == _CHARGER_TYPE_UL) { if (inputVoltage.L1N_L12 < VIN_MIN_VOLTAGE_UL) { PRINTF_FUNC("In Uvp L1N_L12 = %f \n", inputVoltage.L1N_L12); ShmStatusCodeData->AlarmCode.AlarmEvents.bits.SystemL1InputUVP = YES; } else ShmStatusCodeData->AlarmCode.AlarmEvents.bits.SystemL1InputUVP = NO; if (inputVoltage.L2N_L23 < VIN_MIN_VOLTAGE_UL) { PRINTF_FUNC("In Uvp L2N_L23 = %f \n", inputVoltage.L2N_L23); ShmStatusCodeData->AlarmCode.AlarmEvents.bits.SystemL2InputUVP = YES; } else ShmStatusCodeData->AlarmCode.AlarmEvents.bits.SystemL2InputUVP = NO; if (inputVoltage.L3N_L31 < VIN_MIN_VOLTAGE_UL) { PRINTF_FUNC("In Uvp L3N_L31 = %f \n", inputVoltage.L3N_L31); ShmStatusCodeData->AlarmCode.AlarmEvents.bits.SystemL3InputUVP = YES; } else ShmStatusCodeData->AlarmCode.AlarmEvents.bits.SystemL3InputUVP = NO; } //********************************************************************************************************// // Vin (OVP) if (ShmSysConfigAndInfo->SysInfo.ChargerType == _CHARGER_TYPE_IEC) { if (inputVoltage.L1N_L12 > VIN_MAX_VOLTAGE_IEC) { PRINTF_FUNC("In Ovp L1N_L12 = %f \n", inputVoltage.L1N_L12); ShmStatusCodeData->AlarmCode.AlarmEvents.bits.SystemL1InputOVP = YES; } else ShmStatusCodeData->AlarmCode.AlarmEvents.bits.SystemL1InputOVP = NO; if (inputVoltage.L2N_L23 > VIN_MAX_VOLTAGE_IEC) { PRINTF_FUNC("In Ovp L2N_L23 = %f \n", inputVoltage.L2N_L23); ShmStatusCodeData->AlarmCode.AlarmEvents.bits.SystemL2InputOVP = YES; } else ShmStatusCodeData->AlarmCode.AlarmEvents.bits.SystemL2InputOVP = NO; if (inputVoltage.L3N_L31 > VIN_MAX_VOLTAGE_IEC) { PRINTF_FUNC("In Ovp L3N_L31 = %f \n", inputVoltage.L3N_L31); ShmStatusCodeData->AlarmCode.AlarmEvents.bits.SystemL3InputOVP = YES; } else ShmStatusCodeData->AlarmCode.AlarmEvents.bits.SystemL3InputOVP = NO; } else if (ShmSysConfigAndInfo->SysInfo.ChargerType == _CHARGER_TYPE_UL) { if (inputVoltage.L1N_L12 > VIN_MAX_VOLTAGE_UL) { PRINTF_FUNC("In Ovp L1N_L12 = %f \n", inputVoltage.L1N_L12); ShmStatusCodeData->AlarmCode.AlarmEvents.bits.SystemL1InputOVP = YES; } else ShmStatusCodeData->AlarmCode.AlarmEvents.bits.SystemL1InputOVP = NO; if (inputVoltage.L2N_L23 > VIN_MAX_VOLTAGE_UL) { PRINTF_FUNC("In Ovp L2N_L23 = %f \n", inputVoltage.L2N_L23); ShmStatusCodeData->AlarmCode.AlarmEvents.bits.SystemL2InputOVP = YES; } else ShmStatusCodeData->AlarmCode.AlarmEvents.bits.SystemL2InputOVP = NO; if (inputVoltage.L3N_L31 > VIN_MAX_VOLTAGE_UL) { PRINTF_FUNC("In Ovp L3N_L31 = %f \n", inputVoltage.L3N_L31); ShmStatusCodeData->AlarmCode.AlarmEvents.bits.SystemL3InputOVP = YES; } else ShmStatusCodeData->AlarmCode.AlarmEvents.bits.SystemL3InputOVP = NO; } } } // 左右槍的 Relay 前後的輸出電壓 void GetPersentOutputVol() { if (Query_Present_OutputVoltage(Uart5Fd, Addr.Relay, &outputVoltage) == PASS) { // PRINTF_FUNC("Conn1 fuse 1 = %f \n", outputVoltage.behindFuse_Voltage_C1); // PRINTF_FUNC("Conn1 relay 1 = %f \n", outputVoltage.behindRelay_Voltage_C1); // PRINTF_FUNC("Conn2 fuse 2 = %f \n", outputVoltage.behindFuse_Voltage_C2); // PRINTF_FUNC("Conn2 relay 2 = %f \n", outputVoltage.behindRelay_Voltage_C2); //PRINTF_FUNC("outputVoltage.behindFuse_Voltage_C1 = %f \n", outputVoltage.behindFuse_Voltage_C1); //PRINTF_FUNC("outputVoltage.behindFuse_Voltage_C2 = %f \n", outputVoltage.behindFuse_Voltage_C2); ShmRelayModuleData->Gun1FuseOutputVolt = outputVoltage.behindFuse_Voltage_C1; ShmRelayModuleData->Gun1RelayOutputVolt = outputVoltage.behindRelay_Voltage_C1; ShmRelayModuleData->Gun2FuseOutputVolt = outputVoltage.behindFuse_Voltage_C2; ShmRelayModuleData->Gun2RelayOutputVolt = outputVoltage.behindRelay_Voltage_C2; for (int index = 0; index < gunCount; index++) { if (index == 0) { if (_chargingData[index]->Evboard_id == 0x01) { _chargingData[index]->FuseChargingVoltage = ShmRelayModuleData->Gun1FuseOutputVolt; _chargingData[index]->FireChargingVoltage = ShmRelayModuleData->Gun1RelayOutputVolt; } else if (_chargingData[index]->Evboard_id == 0x02) { _chargingData[index]->FuseChargingVoltage = ShmRelayModuleData->Gun2FuseOutputVolt; _chargingData[index]->FireChargingVoltage = ShmRelayModuleData->Gun2RelayOutputVolt; } } else if (index == 1) { _chargingData[index]->FuseChargingVoltage = ShmRelayModuleData->Gun2FuseOutputVolt; _chargingData[index]->FireChargingVoltage = ShmRelayModuleData->Gun2RelayOutputVolt; } //unsigned short Ovp = 0; //unsigned short Ocp = 0; //Ovp = MIN [VOUT_MAX_VOLTAGE, EV_BATTERY_VOLTAGE] // 最大輸出電壓與電池電壓最大值 //Ocp = MIN [IOUT_MAX_CURRENT, EV_CURRENT_REQ] // 最大輸出電流與需求電流最小值 if (_chargingData[index]->Type == _Type_Chademo) { //Ovp = MaxValue(_chargingData[index]->MaximumChargingVoltage, _chargingData[index]->EvBatteryMaxVoltage); //Ocp = MaxValue(_chargingData[index]->PresentChargingCurrent, ShmCHAdeMOData->ev[_chargingData[index]->type_index].ChargingCurrentRequest); } else if (_chargingData[index]->Type == _Type_CCS_2) { } } } } // 風扇速度 void GetFanSpeed() { //PRINTF_FUNC("Get fan board speed \n"); if (Query_Fan_Speed(Uart5Fd, Addr.Fan, &fanSpeed) == PASS) { ShmFanModuleData->PresentFan1Speed = fanSpeed.speed[0]; ShmFanModuleData->PresentFan2Speed = fanSpeed.speed[1]; ShmFanModuleData->PresentFan3Speed = fanSpeed.speed[2]; ShmFanModuleData->PresentFan4Speed = fanSpeed.speed[3]; // PRINTF_FUNC("SystemFanRotaSpeed_1 = %d \n", fanSpeed.speed[0]); // PRINTF_FUNC("SystemFanRotaSpeed_2 = %d \n", fanSpeed.speed[1]); // PRINTF_FUNC("SystemFanRotaSpeed_3 = %d \n", fanSpeed.speed[2]); // PRINTF_FUNC("SystemFanRotaSpeed_4 = %d \n", fanSpeed.speed[3]); // Config_Fan_Speed(Uart5Fd, Addr.Fan, &fanSpeed[0]); //SysInfoData (SystemFanRotaSpeed) } } // 讀取 Relay 狀態 void GetRelayOutputStatus() { if (Query_Relay_Output(Uart5Fd, Addr.Relay, ®Relay) == PASS) { regRelay.relay_event.bits.AC_Contactor = ShmSysConfigAndInfo->SysInfo.AcContactorStatus; } } // 確認 K1 K2 relay 的狀態 void CheckK1K2RelayOutput(byte index) { if (index == 0) { if (_chargingData[index]->Evboard_id == 0x01) { if (regRelay.relay_event.bits.Gun1_N == YES && regRelay.relay_event.bits.Gun1_P == YES) _chargingData[index]->RelayK1K2Status = YES; else _chargingData[index]->RelayK1K2Status = NO; if(_chargingData[index]->Type == _Type_CCS_2) { if (gunCount == 1) { if (regRelay.relay_event.bits.Gun1_N == YES && regRelay.relay_event.bits.CCS_Precharge == YES) _chargingData[index]->RelayKPK2Status = YES; else _chargingData[index]->RelayKPK2Status = NO; } else { if (_chargingData[index]->SystemStatus == S_CCS_PRECHARGE_ST0) _chargingData[index]->RelayKPK2Status = YES; else _chargingData[index]->RelayKPK2Status = NO; } } } else if (_chargingData[index]->Evboard_id == 0x02) { if (regRelay.relay_event.bits.Gun2_N == YES && regRelay.relay_event.bits.Gun2_P == YES) _chargingData[index]->RelayK1K2Status = YES; else _chargingData[index]->RelayK1K2Status = NO; if(_chargingData[index]->Type == _Type_CCS_2) { if (regRelay.relay_event.bits.Gun2_N == YES && regRelay.relay_event.bits.CCS_Precharge == YES) _chargingData[index]->RelayKPK2Status = YES; else _chargingData[index]->RelayKPK2Status = NO; } } } else if (index == 1) { if (regRelay.relay_event.bits.Gun2_N == YES && regRelay.relay_event.bits.Gun2_P == YES) _chargingData[index]->RelayK1K2Status = YES; else _chargingData[index]->RelayK1K2Status = NO; if(_chargingData[index]->Type == _Type_CCS_2) { if (regRelay.relay_event.bits.Gun2_N == YES && regRelay.relay_event.bits.CCS_Precharge == YES) _chargingData[index]->RelayKPK2Status = YES; else _chargingData[index]->RelayKPK2Status = NO; } } if (regRelay.relay_event.bits.Gun1_Parallel_N == YES && regRelay.relay_event.bits.Gun1_Parallel_P == YES) ShmSysConfigAndInfo->SysInfo.BridgeRelayStatus = YES; else ShmSysConfigAndInfo->SysInfo.BridgeRelayStatus = NO; // PRINTF_FUNC("Check Relay Output. index = %d, RelayKPK2Status = %d, BridgeRelayStatus = %d \n", // index, _chargingData[index]->RelayKPK2Status, ShmSysConfigAndInfo->SysInfo.BridgeRelayStatus); } void GetGfdAdc() { // define : 每 0.2 ~ 1 秒一次 // occur : <= 75k 歐姆 @ 150 - 750 Vdc // warning : >= 100 歐姆 && <= 500 歐姆 @ 150-750 Vdc if (Query_Gfd_Adc(Uart5Fd, Addr.Relay, &gfd_adc) == PASS) { for (int i = 0; i < gunCount; i++) { if (_chargingData[i]->Type == 0x09 && !ShmSysConfigAndInfo->SysConfig.AlwaysGfdFlag) { if ((_chargingData[i]->PresentChargingVoltage * 10) >= VOUT_MIN_VOLTAGE) _chargingData[i]->GroundFaultStatus = GFD_PASS; continue; } if (i == 0) { _chargingData[i]->GroundFaultStatus = gfd_adc.result_conn1; if (_chargingData[i]->GroundFaultStatus == GFD_FAIL) { PRINTF_FUNC("GFD Fail. index = %d, Step = %d, R = %d, Vol = %d \n", i, gfd_adc.rb_step_1, gfd_adc.Resister_conn1, gfd_adc.voltage_conn1); } else if (_chargingData[i]->GroundFaultStatus == GFD_WARNING) { PRINTF_FUNC("GFD Warning. index = %d, R = %d, Vol = %d \n", i, gfd_adc.Resister_conn1, gfd_adc.voltage_conn1); } } else if (i == 1) { _chargingData[i]->GroundFaultStatus = gfd_adc.result_conn2; if (_chargingData[i]->GroundFaultStatus == GFD_FAIL) { PRINTF_FUNC("GFD Fail. index = %d, Step = %d, R = %d, Vol = %d \n", i, gfd_adc.rb_step_2, gfd_adc.Resister_conn2, gfd_adc.voltage_conn2); } else if (_chargingData[i]->GroundFaultStatus == GFD_WARNING) { PRINTF_FUNC("GFD Warning. index = %d, R = %d, Vol = %d \n", i, gfd_adc.Resister_conn2, gfd_adc.voltage_conn2); } } } } } void GetGpioInput() { if (Query_Gpio_Input(Uart5Fd, Addr.Aux, &gpio_in) == PASS) { // AC Contactor Status if (gpio_in.AC_MainBreaker == 1) { // AC Main Breaker ON PRINTF_FUNC("RB AC Main Breaker. \n"); } if (gpio_in.SPD == 1) { // SPD (雷擊保護) ON PRINTF_FUNC("RB SPD. \n"); } if (gpio_in.Door_Open == 1) { // Door Open PRINTF_FUNC("RB Door Open. \n"); } if (gpio_in.GFD[0] == 1) { // GFD_1 Trigger } if (gpio_in.GFD[1] == 1) { // GFD_2 Trigger } if (gpio_in.AC_Drop == 1) { // AC Drop PRINTF_FUNC("RB AC Drop. \n"); } if (gpio_in.Emergency_IO == 1) { // Emergency IO ON PRINTF_FUNC("RB Emergency IO ON. \n"); } if (gpio_in.Button_Emergency_Press == 1) { // Emergency button Press } if (gpio_in.Button_On_Press == 1) { // On button Press } if (gpio_in.Button_Off_Press == 1) { // Off button Press } if (gpio_in.Key_1_Press == 1) { // key 1 press } if (gpio_in.Key_2_Press == 1) { // key 2 press } if (gpio_in.Key_3_Press == 1) { // key 3 press } if (gpio_in.Key_4_Press == 1) { // key 4 press } } } // 5V 12V 24V 48V void GetAuxPower() { if (Query_Aux_PowerVoltage(Uart5Fd, Addr.Fan, &auxPower) == PASS) { ShmSysConfigAndInfo->SysInfo.AuxPower48V = auxPower.voltage[0]; ShmSysConfigAndInfo->SysInfo.AuxPower24V = auxPower.voltage[1]; //ShmSysConfigAndInfo->SysInfo.AuxPower12V = auxPower.voltage[4]; //ShmSysConfigAndInfo->SysInfo.AuxPower5V = auxPower.voltage[6]; // aux power voltage //PRINTF_FUNC("aux1 = %x, \n", auxPower.voltage[0]); //PRINTF_FUNC("aux2 = %x, \n", auxPower.voltage[1]); } } void SetFanModuleSpeed() { FanSpeed _fanSpeed; _setFanSpeed += fanSpeedSmoothValue; if (_setFanSpeed >= ShmFanModuleData->SetFan1Speed) _setFanSpeed = ShmFanModuleData->SetFan1Speed; _fanSpeed.speed[0] = _setFanSpeed; _fanSpeed.speed[1] = _setFanSpeed; _fanSpeed.speed[2] = _setFanSpeed; _fanSpeed.speed[3] = _setFanSpeed; if (Config_Fan_Speed(Uart5Fd, Addr.Fan, &_fanSpeed) == PASS) { //PRINTF_FUNC("successfully Fan\n"); } } //========================================== // Common Function //========================================== void SetK1K2RelayStatus(byte index) { if (ShmPsuData->Work_Step >= _TEST_MODE && ShmPsuData->Work_Step <= _TEST_MODE) { if(regRelay.relay_event.bits.Gun1_N == NO) outputRelay.relay_event.bits.Gun1_N = YES; else if (regRelay.relay_event.bits.Gun1_P == NO) outputRelay.relay_event.bits.Gun1_P = YES; return; } if (_chargingData[index]->SystemStatus < S_PREPARING_FOR_EVSE) { if (_chargingData[index]->Evboard_id == 0x01) { if(regRelay.relay_event.bits.Gun1_P == YES) outputRelay.relay_event.bits.Gun1_P = NO; else if (regRelay.relay_event.bits.Gun1_N == YES) outputRelay.relay_event.bits.Gun1_N = NO; if (gunCount == 1 && _chargingData[index]->Type == _Type_CCS_2) { if(regRelay.relay_event.bits.CCS_Precharge == YES) outputRelay.relay_event.bits.CCS_Precharge = NO; } } else if (_chargingData[index]->Evboard_id == 0x02) { if(regRelay.relay_event.bits.Gun2_P == YES) outputRelay.relay_event.bits.Gun2_P = NO; else if (regRelay.relay_event.bits.Gun2_N == YES) outputRelay.relay_event.bits.Gun2_N = NO; if (_chargingData[index]->Type == _Type_CCS_2) { if(regRelay.relay_event.bits.CCS_Precharge == YES) outputRelay.relay_event.bits.CCS_Precharge = NO; } } } else if ((_chargingData[index]->SystemStatus >= S_PREPARING_FOR_EVSE && _chargingData[index]->SystemStatus <= S_CHARGING)) { if (_chargingData[index]->RelayWeldingCheck == YES) { if (_chargingData[index]->Evboard_id == 0x01) { if(regRelay.relay_event.bits.Gun1_N == NO) outputRelay.relay_event.bits.Gun1_N = YES; else if (regRelay.relay_event.bits.Gun1_P == NO) outputRelay.relay_event.bits.Gun1_P = YES; } else if (_chargingData[index]->Evboard_id == 0x02) { if(regRelay.relay_event.bits.Gun2_N == NO) outputRelay.relay_event.bits.Gun2_N = YES; else if (regRelay.relay_event.bits.Gun2_P == NO) outputRelay.relay_event.bits.Gun2_P = YES; } } } else if ((_chargingData[index]->SystemStatus >= S_TERMINATING && _chargingData[index]->SystemStatus <= S_COMPLETE)) { if ((_chargingData[index]->PresentChargingCurrent * 10) <= SEFETY_SWITCH_RELAY_CUR) { if (_chargingData[index]->Evboard_id == 0x01) { if(regRelay.relay_event.bits.Gun1_P == YES) outputRelay.relay_event.bits.Gun1_P = NO; else if (regRelay.relay_event.bits.Gun1_N == YES) outputRelay.relay_event.bits.Gun1_N = NO; } else if (_chargingData[index]->Evboard_id == 0x02) { if(regRelay.relay_event.bits.Gun2_P == YES) outputRelay.relay_event.bits.Gun2_P = NO; else if (regRelay.relay_event.bits.Gun2_N == YES) outputRelay.relay_event.bits.Gun2_N = NO; } } } else if (_chargingData[index]->SystemStatus == S_CCS_PRECHARGE_ST0) { if (_chargingData[index]->Evboard_id == 0x01) { if (_chargingData[index]->Type == _Type_CCS_2) { if (gunCount == 1) { if (regRelay.relay_event.bits.CCS_Precharge == NO) outputRelay.relay_event.bits.CCS_Precharge = YES; else if (regRelay.relay_event.bits.CCS_Precharge == YES) outputRelay.relay_event.bits.Gun1_P = NO; } } } else if (_chargingData[index]->Evboard_id == 0x02) { if (_chargingData[index]->Type == _Type_CCS_2) { if (regRelay.relay_event.bits.CCS_Precharge == NO) outputRelay.relay_event.bits.CCS_Precharge = YES; else if (regRelay.relay_event.bits.CCS_Precharge == YES) outputRelay.relay_event.bits.Gun2_P = NO; } } } else if (_chargingData[index]->SystemStatus == S_CCS_PRECHARGE_ST1) { if (_chargingData[index]->Evboard_id == 0x01) { if (_chargingData[index]->Type == _Type_CCS_2) { if (gunCount == 1) { if (regRelay.relay_event.bits.Gun1_P == NO) outputRelay.relay_event.bits.Gun1_P = YES; else if(regRelay.relay_event.bits.Gun1_P == YES) outputRelay.relay_event.bits.CCS_Precharge = NO; } } } else if (_chargingData[index]->Evboard_id == 0x02) { if (_chargingData[index]->Type == _Type_CCS_2) { if (regRelay.relay_event.bits.Gun2_P == NO) outputRelay.relay_event.bits.Gun2_P = YES; else if(regRelay.relay_event.bits.Gun2_P == YES) outputRelay.relay_event.bits.CCS_Precharge = NO; } } } } void CheckAcInputOvpStatus(byte index) { if (ShmStatusCodeData->AlarmCode.AlarmEvents.bits.SystemL1InputOVP == YES || ShmStatusCodeData->AlarmCode.AlarmEvents.bits.SystemL2InputOVP == YES || ShmStatusCodeData->AlarmCode.AlarmEvents.bits.SystemL3InputOVP == YES) { _chargingData[index]->StopChargeFlag = YES; } } void CheckPhaseLossStatus(byte index) { if (ShmStatusCodeData->AlarmCode.AlarmEvents.bits.SystemL1InputUVP == YES || ShmStatusCodeData->AlarmCode.AlarmEvents.bits.SystemL2InputUVP == YES || ShmStatusCodeData->AlarmCode.AlarmEvents.bits.SystemL3InputUVP == YES) { _chargingData[index]->StopChargeFlag = YES; } } void SetParalleRelayStatus() { // 之後雙槍單模機種,橋接都會上 if (gunCount >= 2) { if (_chargingData[0]->SystemStatus == S_BOOTING || _chargingData[1]->SystemStatus == S_BOOTING || (_chargingData[0]->SystemStatus == S_IDLE && _chargingData[1]->SystemStatus == S_IDLE)) { // 初始化~ 不搭橋接 if (regRelay.relay_event.bits.Gun1_Parallel_P == YES) outputRelay.relay_event.bits.Gun1_Parallel_P = NO; else if (regRelay.relay_event.bits.Gun1_Parallel_N == YES) outputRelay.relay_event.bits.Gun1_Parallel_N = NO; } else { if (_chargingData[0]->IsReadyToCharging == YES || _chargingData[1]->IsReadyToCharging == YES) { // ************需考慮在切換中 - 切開 relay 與搭回 relay 的時機點************ if (ShmSysConfigAndInfo->SysInfo.MainChargingMode == _MAIN_CHARGING_MODE_MAX) { if (ShmSysConfigAndInfo->SysInfo.ReAssignedFlag < _REASSIGNED_RELAY_M_TO_A) { // 最大充 - 搭上橋接 if (regRelay.relay_event.bits.Gun1_Parallel_N == NO) outputRelay.relay_event.bits.Gun1_Parallel_N = YES; else if (regRelay.relay_event.bits.Gun1_Parallel_P == NO) outputRelay.relay_event.bits.Gun1_Parallel_P = YES; } else { // 平均充 - 不搭 if (regRelay.relay_event.bits.Gun1_Parallel_P == YES) outputRelay.relay_event.bits.Gun1_Parallel_P = NO; else if (regRelay.relay_event.bits.Gun1_Parallel_N == YES) outputRelay.relay_event.bits.Gun1_Parallel_N = NO; } } else if (ShmSysConfigAndInfo->SysInfo.MainChargingMode == _MAIN_CHARGING_MODE_AVER) { if (ShmSysConfigAndInfo->SysInfo.ReAssignedFlag < _REASSIGNED_RELAY_A_TO_M) { // 平均充 - 不搭 if (regRelay.relay_event.bits.Gun1_Parallel_P == YES) outputRelay.relay_event.bits.Gun1_Parallel_P = NO; else if (regRelay.relay_event.bits.Gun1_Parallel_N == YES) outputRelay.relay_event.bits.Gun1_Parallel_N = NO; } else { // 最大充 - 搭上橋接 if (regRelay.relay_event.bits.Gun1_Parallel_N == NO) outputRelay.relay_event.bits.Gun1_Parallel_N = YES; else if (regRelay.relay_event.bits.Gun1_Parallel_P == NO) outputRelay.relay_event.bits.Gun1_Parallel_P = YES; } } } } } } void CheckAlarmOccur() { bool isErr = false; for(byte count = 0; count < sizeof(_alarm_code)/sizeof(_alarm_code[0]); count++) { if (acAlarmCode.AcAlarmCode & _alarm_code[count]) { isErr = true; switch(_alarm_code[count]) { case AC_OVP: ShmStatusCodeData->AlarmCode.AlarmEvents.bits.AcSystemInputOVP = YES; break; case AC_UVP: ShmStatusCodeData->AlarmCode.AlarmEvents.bits.AcSystemInputUVP = YES; break; case AC_OCP: ShmStatusCodeData->AlarmCode.AlarmEvents.bits.SystemAcOutputOCP = YES; break; case AC_OTP: ShmStatusCodeData->AlarmCode.AlarmEvents.bits.SystemAmbientOTP = YES; break; case AC_GMI_FAULT: ShmStatusCodeData->AlarmCode.AlarmEvents.bits.AcGroundfaultFail = YES; break; case AC_CP_ERROR: ShmStatusCodeData->InfoCode.InfoEvents.bits.PilotFault = YES; break; case AC_AC_LEAKAGE: ShmStatusCodeData->AlarmCode.AlarmEvents.bits.RcdTrip = YES; break; case AC_DC_LEAKAGE: ShmStatusCodeData->AlarmCode.AlarmEvents.bits.RcdTrip = YES; break; case AC_SYSTEM_SELFTEST_FAULT: ShmStatusCodeData->AlarmCode.AlarmEvents.bits.McuSelftestFail = YES; break; case AC_HANDSHAKE_TIMEOUT: break; //case AC_EMC_STOP: ShmStatusCodeData->AlarmCode.AlarmEvents.bits.EmergencyStopTrip = YES; break; case AC_RELAY_WELDING: ShmStatusCodeData->FaultCode.FaultEvents.bits.AcOutputRelayWelding = YES; break; case AC_GF_MODULE_FAULT: ShmStatusCodeData->FaultCode.FaultEvents.bits.RcdSelfTestFail = YES; break; case AC_SHUTTER_FAULT: break; case AC_LOCKER_FAULT: ShmStatusCodeData->FaultCode.FaultEvents.bits.AcConnectorLockFail = YES; break; case AC_POWER_DROP: ShmStatusCodeData->AlarmCode.AlarmEvents.bits.SystemL1InputDrop = YES; break; case AC_CIRCUIT_SHORT: ShmStatusCodeData->AlarmCode.AlarmEvents.bits.CircuitShort = YES; break; case AC_ROTARY_SWITCH_FAULT: break; case AC_RELAY_DRIVE_FAULT: ShmStatusCodeData->FaultCode.FaultEvents.bits.AcOutputRelayDrivingFault = YES; break; } } else { switch(_alarm_code[count]) { case AC_OVP: ShmStatusCodeData->AlarmCode.AlarmEvents.bits.AcSystemInputOVP = NO; break; case AC_UVP: ShmStatusCodeData->AlarmCode.AlarmEvents.bits.AcSystemInputUVP = NO; break; case AC_OCP: ShmStatusCodeData->AlarmCode.AlarmEvents.bits.SystemAcOutputOCP = NO; break; case AC_OTP: ShmStatusCodeData->AlarmCode.AlarmEvents.bits.SystemAmbientOTP = NO; break; case AC_GMI_FAULT: ShmStatusCodeData->AlarmCode.AlarmEvents.bits.AcGroundfaultFail = NO; break; case AC_CP_ERROR: ShmStatusCodeData->InfoCode.InfoEvents.bits.PilotFault = NO; break; case AC_AC_LEAKAGE: ShmStatusCodeData->AlarmCode.AlarmEvents.bits.RcdTrip = NO; break; case AC_DC_LEAKAGE: ShmStatusCodeData->AlarmCode.AlarmEvents.bits.RcdTrip = NO; break; case AC_SYSTEM_SELFTEST_FAULT: ShmStatusCodeData->AlarmCode.AlarmEvents.bits.McuSelftestFail = NO; break; case AC_HANDSHAKE_TIMEOUT: break; //case AC_EMC_STOP: ShmStatusCodeData->AlarmCode.AlarmEvents.bits.EmergencyStopTrip = NO; break; case AC_RELAY_WELDING: ShmStatusCodeData->FaultCode.FaultEvents.bits.AcOutputRelayWelding = NO; break; case AC_GF_MODULE_FAULT: ShmStatusCodeData->FaultCode.FaultEvents.bits.RcdSelfTestFail = NO; break; case AC_SHUTTER_FAULT: break; case AC_LOCKER_FAULT: ShmStatusCodeData->FaultCode.FaultEvents.bits.AcConnectorLockFail = NO; break; case AC_POWER_DROP: ShmStatusCodeData->AlarmCode.AlarmEvents.bits.SystemL1InputDrop = NO; break; case AC_CIRCUIT_SHORT: ShmStatusCodeData->AlarmCode.AlarmEvents.bits.CircuitShort = NO; break; case AC_ROTARY_SWITCH_FAULT: break; case AC_RELAY_DRIVE_FAULT: ShmStatusCodeData->FaultCode.FaultEvents.bits.AcOutputRelayDrivingFault = NO; break; } } } ac_chargingInfo[0]->IsErrorOccur = isErr; } bool IsNoneMatchLedColor() { bool result = false; if (cur_led_color.Connect_1_Red != led_color.Connect_1_Red || cur_led_color.Connect_1_Green != led_color.Connect_1_Green || cur_led_color.Connect_1_Blue != led_color.Connect_1_Blue || cur_led_color.Connect_2_Red != led_color.Connect_2_Red || cur_led_color.Connect_2_Green != led_color.Connect_2_Green || cur_led_color.Connect_2_Blue != led_color.Connect_2_Blue) { result = true; } return result; } void SetLedColor(struct ChargingInfoData *chargingData_1, struct ChargingInfoData *chargingData_2) { byte _colorBuf = COLOR_MAX_LV * LED_INTENSITY_BRIGHTEST; if (ShmSysConfigAndInfo->SysConfig.LedInfo.Intensity == _LED_INTENSITY_DARKEST) _colorBuf = COLOR_MAX_LV * LED_INTENSITY_DARKEST; else if (ShmSysConfigAndInfo->SysConfig.LedInfo.Intensity == _LED_INTENSITY_MEDIUM) _colorBuf = COLOR_MAX_LV * LED_INTENSITY_MEDIUM; if (ShmSysConfigAndInfo->SysInfo.IsAlternatvieConf) { if ((chargingData_1->SystemStatus == S_BOOTING || chargingData_1->SystemStatus == S_IDLE || chargingData_1->SystemStatus == S_RESERVATION) && (chargingData_2->SystemStatus == S_BOOTING || chargingData_2->SystemStatus == S_IDLE || chargingData_2->SystemStatus == S_RESERVATION)) { led_color.Connect_1_Green = _colorBuf; led_color.Connect_1_Blue = COLOR_MIN_LV; led_color.Connect_1_Red = COLOR_MIN_LV; led_color.Connect_2_Green = _colorBuf; led_color.Connect_2_Blue = COLOR_MIN_LV; led_color.Connect_2_Red = COLOR_MIN_LV; } else if ((chargingData_1->SystemStatus >= S_AUTHORIZING && chargingData_1->SystemStatus <= S_COMPLETE) || (chargingData_1->SystemStatus >= S_CCS_PRECHARGE_ST0 && chargingData_1->SystemStatus <= S_CCS_PRECHARGE_ST1) || (chargingData_2->SystemStatus >= S_AUTHORIZING && chargingData_2->SystemStatus <= S_COMPLETE) || (chargingData_2->SystemStatus >= S_CCS_PRECHARGE_ST0 && chargingData_2->SystemStatus <= S_CCS_PRECHARGE_ST1)) { led_color.Connect_1_Green = COLOR_MIN_LV; led_color.Connect_1_Blue = _colorBuf; led_color.Connect_1_Red = COLOR_MIN_LV; led_color.Connect_2_Green = COLOR_MIN_LV; led_color.Connect_2_Blue = _colorBuf; led_color.Connect_2_Red = COLOR_MIN_LV; } } else { if (chargingData_1->SystemStatus == S_BOOTING || chargingData_1->SystemStatus == S_IDLE || chargingData_1->SystemStatus == S_RESERVATION) { led_color.Connect_1_Green = _colorBuf; led_color.Connect_1_Blue = COLOR_MIN_LV; led_color.Connect_1_Red = COLOR_MIN_LV; } else if ((chargingData_1->SystemStatus >= S_AUTHORIZING && chargingData_1->SystemStatus <= S_COMPLETE) || (chargingData_1->SystemStatus >= S_CCS_PRECHARGE_ST0 && chargingData_1->SystemStatus <= S_CCS_PRECHARGE_ST1)) { led_color.Connect_1_Green = COLOR_MIN_LV; led_color.Connect_1_Blue = _colorBuf; led_color.Connect_1_Red = COLOR_MIN_LV; } // -------------------------------------------------------------------------- if (chargingData_2->SystemStatus == S_BOOTING || chargingData_2->SystemStatus == S_IDLE || chargingData_2->SystemStatus == S_RESERVATION) { led_color.Connect_2_Green = _colorBuf; led_color.Connect_2_Blue = COLOR_MIN_LV; led_color.Connect_2_Red = COLOR_MIN_LV; } else if ((chargingData_2->SystemStatus >= S_AUTHORIZING && chargingData_2->SystemStatus <= S_COMPLETE) || (chargingData_2->SystemStatus >= S_CCS_PRECHARGE_ST0 && chargingData_2->SystemStatus <= S_CCS_PRECHARGE_ST1)) { led_color.Connect_2_Green = COLOR_MIN_LV; led_color.Connect_2_Blue = _colorBuf; led_color.Connect_2_Red = COLOR_MIN_LV; } } if (ShmSysConfigAndInfo->SysWarningInfo.Level == 2) { led_color.Connect_1_Green = COLOR_MIN_LV; led_color.Connect_1_Blue = COLOR_MIN_LV; led_color.Connect_1_Red = _colorBuf; led_color.Connect_2_Green = COLOR_MIN_LV; led_color.Connect_2_Blue = COLOR_MIN_LV; led_color.Connect_2_Red = _colorBuf; } if (_checkLedChanged > 0) { if (Config_Led_Color(Uart5Fd, Addr.Led, &led_color) == PASS) { _checkLedChanged--; cur_led_color.Connect_1_Red = led_color.Connect_1_Red; cur_led_color.Connect_1_Green = led_color.Connect_1_Green; cur_led_color.Connect_1_Blue = led_color.Connect_1_Blue; cur_led_color.Connect_2_Red = led_color.Connect_2_Red; cur_led_color.Connect_2_Green = led_color.Connect_2_Green; cur_led_color.Connect_2_Blue = led_color.Connect_2_Blue; } } else if (IsNoneMatchLedColor()) _checkLedChanged = 3; } //========================================== // Init all share memory //========================================== int InitShareMemory() { int result = PASS; int MeterSMId; if ((MeterSMId = shmget(ShmSysConfigAndInfoKey, sizeof(struct SysConfigAndInfo), 0777)) < 0) { #ifdef SystemLogMessage DEBUG_ERROR("shmget ShmSysConfigAndInfo NG\n"); #endif result = FAIL; } else if ((ShmSysConfigAndInfo = shmat(MeterSMId, NULL, 0)) == (void *) -1) { #ifdef SystemLogMessage DEBUG_ERROR("[shmat ShmSysConfigAndInfo NG\n"); #endif result = FAIL; } if ((MeterSMId = shmget(ShmStatusCodeKey, sizeof(struct StatusCodeData), 0777)) < 0) { #ifdef SystemLogMessage DEBUG_ERROR("shmget ShmStatusCodeData NG\n"); #endif result = FAIL; } else if ((ShmStatusCodeData = shmat(MeterSMId, NULL, 0)) == (void *) -1) { #ifdef SystemLogMessage DEBUG_ERROR("shmat ShmStatusCodeData NG\n"); #endif result = FAIL; } if ((MeterSMId = shmget(ShmFanBdKey, sizeof(struct FanModuleData), 0777)) < 0) { #ifdef SystemLogMessage DEBUG_ERROR("shmget ShmFanModuleData NG\n"); #endif result = FAIL; } else if ((ShmFanModuleData = shmat(MeterSMId, NULL, 0)) == (void *) -1) { #ifdef SystemLogMessage DEBUG_ERROR("shmat ShmFanModuleData NG\n"); #endif result = FAIL; } memset(ShmFanModuleData,0,sizeof(struct FanModuleData)); if ((MeterSMId = shmget(ShmRelayBdKey, sizeof(struct RelayModuleData), 0777)) < 0) { #ifdef SystemLogMessage DEBUG_ERROR("shmget ShmRelayModuleData NG\n"); #endif result = FAIL; } else if ((ShmRelayModuleData = shmat(MeterSMId, NULL, 0)) == (void *) -1) { #ifdef SystemLogMessage DEBUG_ERROR("shmat ShmRelayModuleData NG\n"); #endif result = FAIL; } memset(ShmRelayModuleData,0,sizeof(struct RelayModuleData)); if ((MeterSMId = shmget(ShmLedBdKey, sizeof(struct LedModuleData), 0777)) < 0) { #ifdef SystemLogMessage DEBUG_ERROR("shmget ShmLedModuleData NG\n"); #endif result = FAIL; } else if ((ShmLedModuleData = shmat(MeterSMId, NULL, 0)) == (void *) -1) { #ifdef SystemLogMessage DEBUG_ERROR("shmat ShmLedModuleData NG\n"); #endif result = FAIL; } memset(ShmLedModuleData,0,sizeof(struct LedModuleData)); if ((MeterSMId = shmget(ShmPsuKey, sizeof(struct PsuData), 0777)) < 0) { #ifdef SystemLogMessage DEBUG_ERROR("shmget ShmPsuData NG \n"); #endif result = FAIL; } else if ((ShmPsuData = shmat(MeterSMId, NULL, 0)) == (void *) -1) { #ifdef SystemLogMessage DEBUG_ERROR("shmat ShmPsuData NG \n"); #endif result = FAIL; } if ((MeterSMId = shmget(ShmOcppModuleKey, sizeof(struct OCPP16Data), 0777)) < 0) { #ifdef SystemLogMessage DEBUG_ERROR("shmat ShmOCPP16Data NG \n"); #endif result = FAIL; } else if ((ShmOCPP16Data = shmat(MeterSMId, NULL, 0)) == (void *) -1) { #ifdef SystemLogMessage DEBUG_ERROR("shmat ShmOCPP16Data NG \n"); #endif result = FAIL; } return result; } int InitComPort() { int fd; struct termios tios; fd = open(relayRs485PortName, O_RDWR); if(fd <= 0) { #ifdef SystemLogMessage DEBUG_ERROR("Module_InternalComm. InitComPort NG\n"); #endif if(ShmStatusCodeData!=NULL) { ShmStatusCodeData->AlarmCode.AlarmEvents.bits.CsuInitFailed=1; } sleep(5); return -1; } ioctl (fd, TCGETS, &tios); tios.c_cflag = B115200 | CS8 | CLOCAL | CREAD; tios.c_lflag = 0; tios.c_iflag = 0; tios.c_oflag = 0; tios.c_cc[VMIN]=0; tios.c_cc[VTIME]=(byte)0; // timeout 0.5 second tios.c_lflag=0; tcflush(fd, TCIFLUSH); ioctl (fd, TCSETS, &tios); return fd; } //================================================ // Main process //================================================ bool FindChargingInfoData(byte target, struct ChargingInfoData **chargingData) { for (byte index = 0; index < CHAdeMO_QUANTITY; index++) { if (ShmSysConfigAndInfo->SysInfo.ChademoChargingData[index].Index == target) { chargingData[target] = &ShmSysConfigAndInfo->SysInfo.ChademoChargingData[index]; return true; } } for (byte index = 0; index < CCS_QUANTITY; index++) { if (ShmSysConfigAndInfo->SysInfo.CcsChargingData[index].Index == target) { chargingData[target] = &ShmSysConfigAndInfo->SysInfo.CcsChargingData[index]; return true; } } for (byte index = 0; index < GB_QUANTITY; index++) { if (ShmSysConfigAndInfo->SysInfo.GbChargingData[index].Index == target) { chargingData[target] = &ShmSysConfigAndInfo->SysInfo.GbChargingData[index]; return true; } } return false; } bool FindAcChargingInfoData(byte target, struct ChargingInfoData **acChargingData) { if (target < AC_QUANTITY) { acChargingData[target] = &ShmSysConfigAndInfo->SysInfo.AcChargingData[target]; return true; } return false; } void Initialization() { bool isPass = false; for (byte index = 0; index < ARRAY_SIZE(outputRelay.relay_event.relay_status); index++) { outputRelay.relay_event.relay_status[index] = 0x00; } while(!isPass) { isPass = true; for (byte _index = 0; _index < gunCount; _index++) { if (!FindChargingInfoData(_index, &_chargingData[0])) { DEBUG_ERROR("InternalComm : FindChargingInfoData false \n"); isPass = false; break; } } sleep(1); } isPass = false; if (acgunCount > 0) { while(!isPass) { isPass = true; for (byte _index = 0; _index < acgunCount; _index++) { if (!FindAcChargingInfoData(_index, &ac_chargingInfo[0])) { DEBUG_ERROR("EvComm : FindAcChargingInfoData false \n"); isPass = false; break; } } sleep(1); } } } bool IsNoneMatchRelayStatus() { bool result = false; if ((regRelay.relay_event.bits.AC_Contactor != outputRelay.relay_event.bits.AC_Contactor) || (regRelay.relay_event.bits.CCS_Precharge != outputRelay.relay_event.bits.CCS_Precharge) || (regRelay.relay_event.bits.Gun1_P != outputRelay.relay_event.bits.Gun1_P) || (regRelay.relay_event.bits.Gun1_N != outputRelay.relay_event.bits.Gun1_N) || (regRelay.relay_event.bits.Gun2_P != outputRelay.relay_event.bits.Gun2_P) || (regRelay.relay_event.bits.Gun2_N != outputRelay.relay_event.bits.Gun2_N) || (regRelay.relay_event.bits.Gun1_Parallel_P != outputRelay.relay_event.bits.Gun1_Parallel_P) || (regRelay.relay_event.bits.Gun1_Parallel_N != outputRelay.relay_event.bits.Gun1_Parallel_N)) { if (regRelay.relay_event.bits.AC_Contactor != outputRelay.relay_event.bits.AC_Contactor) PRINTF_FUNC("AC Contact Relay none match. \n"); if (regRelay.relay_event.bits.CCS_Precharge != outputRelay.relay_event.bits.CCS_Precharge) PRINTF_FUNC("CCS Precharge Relay none match. \n"); if (regRelay.relay_event.bits.Gun1_P != outputRelay.relay_event.bits.Gun1_P) PRINTF_FUNC("SMR1:D+ Relay none match. \n"); if (regRelay.relay_event.bits.Gun1_N != outputRelay.relay_event.bits.Gun1_N) PRINTF_FUNC("SMR1:D- Relay none match. \n"); if (regRelay.relay_event.bits.Gun2_P != outputRelay.relay_event.bits.Gun2_P) PRINTF_FUNC("SMR2:D+ Relay none match. \n"); if (regRelay.relay_event.bits.Gun2_N != outputRelay.relay_event.bits.Gun2_N) PRINTF_FUNC("SMR2:D- Relay none match. \n"); if (regRelay.relay_event.bits.Gun1_Parallel_P != outputRelay.relay_event.bits.Gun1_Parallel_P) PRINTF_FUNC("Parallel:D+ Relay none match. \n"); if (regRelay.relay_event.bits.Gun1_Parallel_N != outputRelay.relay_event.bits.Gun1_Parallel_N) PRINTF_FUNC("Parallel:D- Relay none match. \n"); result = true; } return result; } void MatchRelayStatus() { // 因為 AC Contactor 沒有 Feedback,所以暫時先這樣處理 //regRelay.relay_event.bits.AC_Contactor = outputRelay.relay_event.bits.AC_Contactor; ShmSysConfigAndInfo->SysInfo.AcContactorStatus = regRelay.relay_event.bits.AC_Contactor = outputRelay.relay_event.bits.AC_Contactor; regRelay.relay_event.bits.CCS_Precharge = outputRelay.relay_event.bits.CCS_Precharge; regRelay.relay_event.bits.Gun1_P = outputRelay.relay_event.bits.Gun1_P; regRelay.relay_event.bits.Gun1_N = outputRelay.relay_event.bits.Gun1_N; regRelay.relay_event.bits.Gun2_P = outputRelay.relay_event.bits.Gun2_P; regRelay.relay_event.bits.Gun2_N = outputRelay.relay_event.bits.Gun2_N; regRelay.relay_event.bits.Gun1_Parallel_P = outputRelay.relay_event.bits.Gun1_Parallel_P; regRelay.relay_event.bits.Gun1_Parallel_N = outputRelay.relay_event.bits.Gun1_Parallel_N; } void CheckRelayStatusByADC() { if (ShmRelayModuleData->Gun1FuseOutputVolt > 0 && ShmRelayModuleData->Gun1RelayOutputVolt > 0 && (ShmRelayModuleData->Gun1FuseOutputVolt == ShmRelayModuleData->Gun1RelayOutputVolt)) { // Relay 前後電壓一致 _chargingData[0]->RelayK1K2Status = 0x01; } else _chargingData[0]->RelayK1K2Status = 0x00; if (ShmRelayModuleData->Gun2FuseOutputVolt > 0 && ShmRelayModuleData->Gun2RelayOutputVolt > 0 && (ShmRelayModuleData->Gun2FuseOutputVolt == ShmRelayModuleData->Gun2RelayOutputVolt)) { // Relay 前後電壓一致 _chargingData[1]->RelayK1K2Status = 0x01; } else _chargingData[1]->RelayK1K2Status = 0x00; } void SetGfdConfig(byte index, byte resister) { gfd_config.index = index; gfd_config.state = resister; //PRINTF_FUNC("************************GFD Vol = %d, GFD Res = %d \n", gfd_config.reqVol, gfd_config.resister); if (Config_Gfd_Value(Uart5Fd, Addr.Relay, &gfd_config) == PASS) { // PRINTF_FUNC("Set reqVol = %f, resister = %d \n", // gfd_config.reqVol, // gfd_config.resister); } } void CableCheckDetected(byte index) { // Cable Check // 當火線上的電壓 = 車端要求的電壓電流 // _chargingData[targetGun]->EvBatterytargetVoltage // 才可以開始偵測 1s // Warning : Rgfd <= 150 歐/V 假設電壓為 500V 則~ Rgfd <= 75000 歐 // Pre-Warning : 150 歐/V < Rgfd <= 500 歐/V 假設電壓為 500V 則 75000 歐 < Rgfd <= 250000 // SO Normal : Rgfd > 500 歐/V 假設電壓為 500 V 則 Rgfd > 250000 歐 if ((_chargingData[index]->Type >= _Type_Chademo && _chargingData[index]->Type <= _Type_GB) || (_chargingData[index]->Type == 0x09 && ShmSysConfigAndInfo->SysConfig.AlwaysGfdFlag)) { if ((_chargingData[index]->SystemStatus >= S_PREPARING_FOR_EVSE && _chargingData[index]->SystemStatus <= S_TERMINATING) || (_chargingData[index]->SystemStatus >= S_CCS_PRECHARGE_ST0 && _chargingData[index]->SystemStatus <= S_CCS_PRECHARGE_ST1)) { if (_chargingData[index]->SystemStatus == S_PREPARING_FOR_EVSE && _chargingData[index]->RelayWeldingCheck == YES) { SetGfdConfig(index, GFD_CABLECHK); } else if (_chargingData[index]->SystemStatus >= S_CCS_PRECHARGE_ST0 && _chargingData[index]->SystemStatus <= S_CCS_PRECHARGE_ST1) { SetGfdConfig(index, GFD_PRECHARGE); } else if (_chargingData[index]->SystemStatus >= S_CHARGING && _chargingData[index]->SystemStatus <= S_TERMINATING) { if (_chargingData[index]->Type == _Type_GB || _chargingData[index]->Type == _Type_Chademo) SetGfdConfig(index, GFD_IDLE); else SetGfdConfig(index, GFD_CHARGING); } } else if(_chargingData[index]->SystemStatus == S_COMPLETE || _chargingData[index]->SystemStatus == S_PREPARNING || _chargingData[index]->SystemStatus == S_IDLE) { SetGfdConfig(index, GFD_IDLE); } } } void CheckOutputPowerOverCarReq(byte index) { float fireV = _chargingData[index]->FireChargingVoltage; float carV = _chargingData[index]->EvBatterytargetVoltage * 10; if ((_chargingData[index]->EvBatterytargetVoltage * 10) > 1500 && (_chargingData[index]->Type == _Type_Chademo || _chargingData[index]->Type == _Type_CCS_2 || _chargingData[index]->Type == _Type_GB)) { if (fireV >= (carV + (carV * 0.1))) { PRINTF_FUNC("[Module_InternalComm]CheckOutputPowerOverCarReq NG : fire = %f, battery = %f \n", _chargingData[index]->FireChargingVoltage, (_chargingData[index]->EvBatterytargetVoltage * 10)); DEBUG_ERROR("[Module_InternalComm]CheckOutputPowerOverCarReq NG : fire = %f, battery = %f \n", _chargingData[index]->FireChargingVoltage, (_chargingData[index]->EvBatterytargetVoltage * 10)); _chargingData[index]->StopChargeFlag = YES; } } } void CheckOutputVolNoneMatchFire(byte index) { if ((_chargingData[index]->EvBatterytargetVoltage * 10) > 1500 && (_chargingData[index]->Type == _Type_Chademo || _chargingData[index]->Type == _Type_CCS_2 || _chargingData[index]->Type == _Type_GB)) { if (((_chargingData[index]->PresentChargingVoltage * 10) < _chargingData[index]->FireChargingVoltage - 300) || ((_chargingData[index]->PresentChargingVoltage * 10) > _chargingData[index]->FireChargingVoltage + 300)) { if (!_isOutputNoneMatch[index]) { _isOutputNoneMatch[index] = YES; gettimeofday(&_checkOutputNoneMatchTimer[index], NULL); } else { if ((GetTimeoutValue(_checkOutputNoneMatchTimer[index]) / 1000) >= 5000) { PRINTF_FUNC("[Module_InternalComm]CheckOutputVolNoneMatchFire NG (%d) : pre = %f, fire = %f \n", index, (_chargingData[index]->PresentChargingVoltage * 10), _chargingData[index]->FireChargingVoltage); DEBUG_ERROR("[Module_InternalComm]CheckOutputVolNoneMatchFire NG (%d): pre = %f, fire = %f \n", index, (_chargingData[index]->PresentChargingVoltage * 10), _chargingData[index]->FireChargingVoltage); _chargingData[index]->StopChargeFlag = YES; } } } else _isOutputNoneMatch[index] = NO; } } void CheckRelayWeldingStatus(byte index) { if (!_isRelayWelding[index]) { if ((_chargingData[index]->PresentChargingVoltage * 10) >= VOUT_MIN_VOLTAGE * 10) { gettimeofday(&_checkRelayWeldingTimer[index], NULL); _isRelayWelding[index] = YES; } } else { if ((GetTimeoutValue(_checkRelayWeldingTimer[index]) / 1000) >= 1000) { _chargingData[index]->RelayWeldingCheck = YES; return; } if (_chargingData[index]->FireChargingVoltage >= VOUT_MIN_VOLTAGE) { if (_chargingData[index]->Type == _Type_Chademo) ShmStatusCodeData->FaultCode.FaultEvents.bits.ChademoOutputRelayWelding = YES; else if (_chargingData[index]->Type == _Type_GB) ShmStatusCodeData->FaultCode.FaultEvents.bits.GbOutputRelayWelding = YES; else if (_chargingData[index]->Type == _Type_CCS_2) ShmStatusCodeData->FaultCode.FaultEvents.bits.CcsOutputRelayWelding = YES; PRINTF_FUNC("CheckRelayWeldingStatus : fail \n"); _chargingData[index]->StopChargeFlag = YES; } } } void GetPsuTempForFanSpeed() { char temp = 0; for (byte index = 0; index < ShmPsuData->GroupCount; index++) { for (byte count = 0; count < ShmPsuData->PsuGroup[index].GroupPresentPsuQuantity; count++) { if (temp < ShmPsuData->PsuGroup[index].PsuModule[count].ExletTemp) temp = ShmPsuData->PsuGroup[index].PsuModule[count].ExletTemp; } } ShmSysConfigAndInfo->SysInfo.SystemAmbientTemp = temp; if (ShmSysConfigAndInfo->SysConfig.SwitchDebugFlag == NO) { if (ShmFanModuleData->TestFanSpeed == NORMAL_FAN_SPEED) { if (temp >= ENV_TEMP_MAX) ShmFanModuleData->TestFanSpeed = MAX_FAN_SPEED; } else if (ShmFanModuleData->TestFanSpeed == MAX_FAN_SPEED) { if (temp <= ENV_TEMP_MIN) ShmFanModuleData->TestFanSpeed = NORMAL_FAN_SPEED; } else ShmFanModuleData->TestFanSpeed = NORMAL_FAN_SPEED; } } void GetFanSpeedByFunction() { if (ShmSysConfigAndInfo->SysConfig.SwitchDebugFlag == YES) return; // 風控修改 : // ******************************************************* // // // 當前PSU輸出總 KW PSU Temp // 30 x -------------------- x ---------- + 14 x (PSU Temp - 45) // 當前樁最大功率 KW 45 // // ******************************************************* // // 當前樁最大功率 KW : ShmPsuData->SystemAvailablePower unsigned int _maxPower = ShmPsuData->SystemAvailablePower; // 當前PSU輸出總 KW & PSU Temp : unsigned char temp = 0; float power = 0; for (byte index = 0; index < ShmPsuData->GroupCount; index++) { for (byte count = 0; count < ShmPsuData->PsuGroup[index].GroupPresentPsuQuantity; count++) { if (temp < ShmPsuData->PsuGroup[index].PsuModule[count].ExletTemp) temp = ShmPsuData->PsuGroup[index].PsuModule[count].ExletTemp; } power += (_chargingData[index]->PresentChargingPower * 10); } double _pw_rate = 0; if (_maxPower > 0) _pw_rate = power / (double)_maxPower; double _temp_rate = 0; if (temp > 0) _temp_rate = (double)temp / 45; unsigned char _temp_diff = 0; if (temp > 45) _temp_diff = temp - 45; ShmFanModuleData->TestFanSpeed = ((30 * _pw_rate * _temp_rate + 14 * _temp_diff) / 100) * MAX_FAN_SPEED; if (ShmFanModuleData->TestFanSpeed > MAX_FAN_SPEED) ShmFanModuleData->TestFanSpeed = MAX_FAN_SPEED; if (ShmFanModuleData->TestFanSpeed < 0) ShmFanModuleData->TestFanSpeed = 0; // // printf("power = %f \n", power); // printf("_maxPower = %d \n", _maxPower); // printf("temp = %d \n", temp); // // printf("_pw_rate = %f \n", _pw_rate); // printf("_temp_rate = %f \n", _temp_rate); // printf("_temp_diff = %d \n", _temp_diff); // printf("fan rate = %f \n", (30 * _pw_rate * _temp_rate + 14 * _temp_diff)); // printf("ShmFanModuleData->TestFanSpeed = %d \n", ShmFanModuleData->TestFanSpeed); } void GetAcStatus() { if (Query_AC_Status(Uart5Fd, Addr.AcPlug, &acStatus) == PASS) { ShmSysConfigAndInfo->SysConfig.AcRatingCurrent = acStatus.MaxCurrent; if(ShmSysConfigAndInfo->SysConfig.AcMaxChargingCurrent == 0) ShmSysConfigAndInfo->SysConfig.AcMaxChargingCurrent = ShmSysConfigAndInfo->SysConfig.AcRatingCurrent; ac_chargingInfo[0]->ConnectorPlugIn = acStatus.CpStatus; // printf("CpStatus = %d \n", acStatus.CpStatus); // printf("CurLimit = %d \n", acStatus.CurLimit); // printf("PilotVol_P = %d \n", acStatus.PilotVol_P); // printf("PilotVol_N = %d \n", acStatus.PilotVol_N); // printf("LockStatus = %d \n", acStatus.LockStatus); // printf("RelayStatus = %d \n", acStatus.RelayStatus); // printf("ShutterStatus = %d \n", acStatus.ShutterStatus); // printf("MeterStatus = %d \n", acStatus.MeterStatus); // printf("PpStatus = %d \n", acStatus.PpStatus); // printf("MaxCurrent = %d \n", acStatus.MaxCurrent); // printf("RotateSwitchStatus = %d \n", acStatus.RelayStatus); // printf("============================== \n"); // // ac_chargingInfo[0]->SystemStatus = acStatus.CpStatus; } } void GetAcAlarmCode() { if (Query_AC_Alarm_Code(Uart5Fd, Addr.AcPlug, &acAlarmCode) == PASS) { CheckAlarmOccur(); } } unsigned char GetChargingEnergy() { return Query_Charging_Energy(Uart5Fd, Addr.AcPlug, &acChargingEnergy); } unsigned char GetChargingCurrent() { return Query_Charging_Current(Uart5Fd, Addr.AcPlug, &acChargingCurrent); } void ChangeLedStatus() { if (ac_chargingInfo[0]->SystemStatus == S_IDLE) ledStatus.ActionMode = 1; else if (ac_chargingInfo[0]->SystemStatus == S_PREPARNING) ledStatus.ActionMode = 3; else if (ac_chargingInfo[0]->SystemStatus == S_CHARGING) ledStatus.ActionMode = 4; Config_LED_Status(Uart5Fd, Addr.AcPlug, &ledStatus); } void SetLegacyReq(byte _switch) { Config_Legacy_Req(Uart5Fd, Addr.AcPlug, _switch); } void SetCpDuty(byte _value) { Config_Ac_Duty(Uart5Fd, Addr.AcPlug, _value); } void ChangeToCsuMode() { ac_chargingInfo[0]->IsModeChagned = Config_CSU_Mode(Uart5Fd, Addr.AcPlug); // if (ac_chargingInfo[0]->IsModeChagned == PASS) // { // Config_Reset_MCU(Uart5Fd, Addr.AcPlug); // } } void ChangeStartOrStopDateTime(byte isStart) { char cmdBuf[32]; struct timeb csuTime; struct tm *tmCSU; ftime(&csuTime); tmCSU = localtime(&csuTime.time); sprintf(cmdBuf, "%04d-%02d-%02d %02d:%02d:%02d", tmCSU->tm_year + 1900, tmCSU->tm_mon + 1, tmCSU->tm_mday, tmCSU->tm_hour, tmCSU->tm_min, tmCSU->tm_sec); if (isStart) strcpy((char *)ac_chargingInfo[0]->StartDateTime, cmdBuf); else strcpy((char *)ac_chargingInfo[0]->StopDateTime, cmdBuf); } void OcppStartTransation(byte gunIndex) { if(strcmp((char *)ac_chargingInfo[0]->StartUserId, "") == EQUAL) strcpy((char *)ShmOCPP16Data->StartTransaction[gunIndex].IdTag, (char *)ShmOCPP16Data->StartTransaction[gunIndex].IdTag); else strcpy((char *)ShmOCPP16Data->StartTransaction[gunIndex].IdTag, (char *)ac_chargingInfo[0]->StartUserId); PRINTF_FUNC("AC IdTag = %s \n", ShmOCPP16Data->StartTransaction[gunIndex].IdTag); ShmOCPP16Data->CpMsg.bits[gunIndex].StartTransactionReq = YES; } void OcppStopTransation(byte gunIndex) { if(strcmp((char *)ac_chargingInfo[0]->StartUserId, "") == EQUAL) strcpy((char *)ShmOCPP16Data->StopTransaction[gunIndex].IdTag, (char *)ShmOCPP16Data->StopTransaction[gunIndex].IdTag); else strcpy((char *)ShmOCPP16Data->StopTransaction[gunIndex].IdTag, (char *)ac_chargingInfo[0]->StartUserId); PRINTF_FUNC("AC IdTag = %s \n", ShmOCPP16Data->StopTransaction[gunIndex].IdTag); ShmOCPP16Data->CpMsg.bits[gunIndex].StopTransactionReq = YES; } bool OcppRemoteStop(byte gunIndex) { bool result = ShmOCPP16Data->CsMsg.bits[gunIndex].RemoteStopTransactionReq; if (ShmOCPP16Data->CsMsg.bits[gunIndex].RemoteStopTransactionReq == YES) { strcpy((char *)ShmOCPP16Data->StopTransaction[gunIndex].StopReason, "Remote"); ShmOCPP16Data->CsMsg.bits[gunIndex].RemoteStopTransactionReq = NO; } return result; } unsigned char isModeChange() { unsigned char result = NO; if(ac_chargingInfo[0]->SystemStatus != ac_chargingInfo[0]->PreviousSystemStatus) { result = YES; ac_chargingInfo[0]->PreviousSystemStatus = ac_chargingInfo[0]->SystemStatus; } return result; } void AcChargeTypeProcess() { if (acgunCount > 0) { //ac_chargingInfo[0]->SelfTest_Comp = YES; //ac_chargingInfo[0]->IsModeChagned = PASS; //--------------------------------------------- if (ac_chargingInfo[0]->SelfTest_Comp == NO) { ac_chargingInfo[0]->IsModeChagned = NO; GetFwVersion_AC(); GetAcModelName(); } else if (ac_chargingInfo[0]->SelfTest_Comp == YES) { if (ac_chargingInfo[0]->IsModeChagned != PASS) { ChangeToCsuMode(); return; } GetAcStatus(); GetAcAlarmCode(); byte _status = S_NONE; if (ac_chargingInfo[0]->SystemStatus == S_IDLE && ac_chargingInfo[0]->IsErrorOccur) { _status = S_ALARM; } else if (acStatus.CpStatus == AC_SYS_A || ac_chargingInfo[0]->IsErrorOccur) { if (ac_chargingInfo[0]->SystemStatus == S_CHARGING) _status = S_TERMINATING; else if (ac_chargingInfo[0]->SystemStatus >= S_TERMINATING) { if (GetTimeoutValue(_ac_charging_comp) >= 10000000 && acStatus.CpStatus == AC_SYS_A) _status = S_IDLE; } else _status = S_IDLE; } else if (ac_chargingInfo[0]->SystemStatus >= S_PREPARNING && ac_chargingInfo[0]->SystemStatus < S_CHARGING) { if (acStatus.CpStatus == AC_SYS_C && acStatus.RelayStatus == YES) _status = S_CHARGING; else if (GetTimeoutValue(_ac_preparing) >= 30000000) _status = S_IDLE; } else if ((acStatus.CpStatus == AC_SYS_B || ac_chargingInfo[0]->ConnectorPlugIn == AC_SYS_B) && ac_chargingInfo[0]->IsAvailable && !ac_chargingInfo[0]->IsErrorOccur && (ShmSysConfigAndInfo->SysInfo.WaitForPlugit == YES || ShmSysConfigAndInfo->SysConfig.AuthorisationMode == AUTH_MODE_DISABLE)) { if (ac_chargingInfo[0]->RemoteStartFlag == YES) { PRINTF_FUNC("** AC Remote \n"); ac_chargingInfo[0]->RemoteStartFlag = NO; strcpy((char *)ac_chargingInfo[0]->StartUserId, ""); ShmSysConfigAndInfo->SysInfo.WaitForPlugit = NO; _status = S_PREPARNING; } else if (ShmSysConfigAndInfo->SysInfo.OrderCharging == NO_DEFINE) { PRINTF_FUNC("** UserId = %s \n", ShmSysConfigAndInfo->SysConfig.UserId); strcpy((char *)ac_chargingInfo[0]->StartUserId, (char *)ShmSysConfigAndInfo->SysConfig.UserId); PRINTF_FUNC("** CardNumber = %s \n", ac_chargingInfo[0]->StartUserId); strcpy((char *)ShmSysConfigAndInfo->SysConfig.UserId, ""); ShmSysConfigAndInfo->SysInfo.WaitForPlugit = NO; _status = S_PREPARNING; } } else if (ac_chargingInfo[0]->SystemStatus == S_CHARGING) { if (OcppRemoteStop(1)) _status = S_TERMINATING; } //printf("_status = %d \n", _status); if (_status != S_NONE && ac_chargingInfo[0]->SystemStatus != _status) { ac_chargingInfo[0]->SystemStatus = _status; } // 設定限制最大充電電流 >= 6 ~ <= 32 switch(ac_chargingInfo[0]->SystemStatus) { case S_IDLE: case S_ALARM: { if (isModeChange()) { ac_chargingInfo[0]->PresentChargedEnergy = 0.0; ac_chargingInfo[0]->PresentChargingVoltage = 0; ac_chargingInfo[0]->ChargingFee = 0.0; strcpy((char *)ac_chargingInfo[0]->StartDateTime, ""); strcpy((char *)ac_chargingInfo[0]->StopDateTime, ""); _beforeChargingTotalEnergy = 0.0; } ChangeLedStatus(); } break; case S_PREPARNING: { if (isModeChange()) { ShmSysConfigAndInfo->SysInfo.SystemPage = _LCM_NONE; ShmSysConfigAndInfo->SysInfo.CurGunSelectedByAc = DEFAULT_AC_INDEX; if (ShmSysConfigAndInfo->SysInfo.OrderCharging != NO_DEFINE) ShmSysConfigAndInfo->SysInfo.OrderCharging = NO_DEFINE; gettimeofday(&_ac_preparing, NULL); } if (GetChargingEnergy() == PASS) { //ac_chargingInfo[0]->PresentChargedEnergy = acChargingEnergy.Energy / 100; _beforeChargingTotalEnergy = acChargingEnergy.Energy; } SetLegacyReq(YES); ChangeLedStatus(); } break; case S_CHARGING: { if (isModeChange()) { ftime(&_ac_startChargingTime); OcppStartTransation(1); ChangeStartOrStopDateTime(YES); ShmSysConfigAndInfo->SysInfo.CurGunSelectedByAc = DEFAULT_AC_INDEX; } if (GetChargingEnergy() == PASS) { if ((acChargingEnergy.Energy - _beforeChargingTotalEnergy) > 0) { ac_chargingInfo[0]->PresentChargedEnergy += (acChargingEnergy.Energy - _beforeChargingTotalEnergy) / 100; if (ShmSysConfigAndInfo->SysConfig.BillingData.isBilling) { ac_chargingInfo[0]->ChargingFee += ac_chargingInfo[0]->PresentChargedEnergy * ShmSysConfigAndInfo->SysConfig.BillingData.Cur_fee; } } _beforeChargingTotalEnergy = acChargingEnergy.Energy; } if (GetChargingCurrent() == PASS) ac_chargingInfo[0]->PresentChargingPower = (((float)(AC_DEFAULT_VOL * acChargingCurrent.OuputCurrentL1) / 10) / 1000); ftime(&_ac_endChargingTime); ac_chargingInfo[0]->PresentChargedDuration = DiffTimeb(_ac_startChargingTime, _ac_endChargingTime); ac_chargingInfo[0]->PresentChargingVoltage = AC_DEFAULT_VOL; ac_chargingInfo[0]->PresentChargingCurrent = ((float)acChargingCurrent.OuputCurrentL1 / 10); // 用以判斷是否有在輸出 ac_chargingInfo[0]->IsCharging = acStatus.RelayStatus; SetCpDuty(ShmSysConfigAndInfo->SysConfig.AcMaxChargingCurrent); ChangeLedStatus(); } break; case S_TERMINATING: { if (isModeChange()) { ChangeStartOrStopDateTime(NO); gettimeofday(&_ac_charging_comp, NULL); } SetLegacyReq(NO); if (acStatus.RelayStatus == NO) ac_chargingInfo[0]->SystemStatus = S_COMPLETE; } break; case S_COMPLETE: { if (isModeChange()) { gettimeofday(&_ac_charging_comp, NULL); ftime(&_ac_endChargingTime); if (strcmp((char *)ac_chargingInfo[0]->StartDateTime, "") != EQUAL) { // AC 固定為第2把槍 OcppStopTransation(1); } ChangeStartOrStopDateTime(NO); ac_chargingInfo[0]->PresentChargedDuration = DiffTimeb(_ac_startChargingTime, _ac_endChargingTime); } } break; } } } } int main(void) { if(InitShareMemory() == FAIL) { #ifdef SystemLogMessage DEBUG_ERROR("InitShareMemory NG\n"); #endif if(ShmStatusCodeData!=NULL) { ShmStatusCodeData->AlarmCode.AlarmEvents.bits.FailToCreateShareMemory=1; } sleep(5); return 0; } gunCount = ShmSysConfigAndInfo->SysConfig.TotalConnectorCount; acgunCount = ShmSysConfigAndInfo->SysConfig.AcConnectorCount; // Open Uart5 for RB Uart5Fd = InitComPort(); Initialization(); sleep(1); if(Uart5Fd < 0) { PRINTF_FUNC("(Internal) open port error. \n"); return 0; } outputRelay.relay_event.bits.AC_Contactor = 0x00; outputRelay.relay_event.bits.CCS_Precharge = 0x00; outputRelay.relay_event.bits.Gun1_Parallel_P = 0x00; outputRelay.relay_event.bits.Gun1_Parallel_N = 0x00; outputRelay.relay_event.bits.Gun1_P = 0x00; outputRelay.relay_event.bits.Gun1_N = 0x00; outputRelay.relay_event.bits.Gun2_N = 0x00; outputRelay.relay_event.bits.Gun2_P = 0x00; if(Config_Relay_Output(Uart5Fd, Addr.Relay, &outputRelay) != PASS) PRINTF_FUNC("Config_Relay_Output fail \n"); cur_led_color.Connect_1_Red = COLOR_MIN_LV; cur_led_color.Connect_1_Green = COLOR_MIN_LV; cur_led_color.Connect_1_Blue = COLOR_MIN_LV; cur_led_color.Connect_2_Red = COLOR_MIN_LV; cur_led_color.Connect_2_Green = COLOR_MIN_LV; cur_led_color.Connect_2_Blue = COLOR_MIN_LV; for(;;) { bool isCharging = false; // 程序開始之前~ 必須先確定 FW 版本與硬體版本,確認後!!~ 該模組才算是真正的 Initial Comp. if (ShmRelayModuleData->SelfTest_Comp == NO) { GetFwAndHwVersion_Relay(); SetRtcData_Relay(); sleep(1); } if (ShmFanModuleData->SelfTest_Comp == NO) { GetFwAndHwVersion_Fan(); SetModelName_Fan(); SetRtcData_Fan(); sleep(1); gettimeofday(&_priority_time, NULL); } // 自檢階段處理,自檢階段如果讀不到版號則代表該系統沒有掛燈板 if (ShmLedModuleData->SelfTest_Comp == NO) { // 自檢階段 if (ShmSysConfigAndInfo->SysInfo.SelfTestSeq <= _STEST_PSU_CAP) { GetFwAndHwVersion_Led(); sleep(1); gettimeofday(&_led_priority_time, NULL); } else { // 自檢階段沒有問到版號 if (ShmStatusCodeData->AlarmCode.AlarmEvents.bits.LedboardStestFail == NO) ShmStatusCodeData->AlarmCode.AlarmEvents.bits.LedboardStestFail = YES; } } AcChargeTypeProcess(); if (ShmRelayModuleData->SelfTest_Comp == YES) { // ==============優先權最高 10 ms ============== // 輸出電壓 GetPersentOutputVol(); // 三相輸入電壓 GetPresentInputVol(); // 讀取當前 AC relay 狀態 regRelay.relay_event.bits.AC_Contactor = ShmSysConfigAndInfo->SysInfo.AcContactorStatus; //GetRelayOutputStatus(); for (int i = 0; i < gunCount; i++) { // Cable check (Set) CableCheckDetected(i); // check k1 k2 relay 狀態 CheckK1K2RelayOutput(i); // 依據當前各槍的狀態選擇 搭上/放開 Relay SetK1K2RelayStatus(i); if (ShmSysConfigAndInfo->SysConfig.PhaseLossPolicy == YES) CheckPhaseLossStatus(i); CheckAcInputOvpStatus(i); if (_chargingData[i]->SystemStatus == S_IDLE) { _chargingData[i]->RelayWeldingCheck = NO; _isRelayWelding[i] = NO; } if (_chargingData[i]->SystemStatus == S_BOOTING || (_chargingData[i]->SystemStatus >= S_REASSIGN_CHECK && _chargingData[i]->SystemStatus <= S_COMPLETE) || (_chargingData[i]->SystemStatus >= S_CCS_PRECHARGE_ST0 && _chargingData[i]->SystemStatus <= S_CCS_PRECHARGE_ST1) || ShmSysConfigAndInfo->SysInfo.WaitForPlugit == YES || (ShmSysConfigAndInfo->SysInfo.PageIndex >= _LCM_AUTHORIZING && ShmSysConfigAndInfo->SysInfo.PageIndex <= _LCM_WAIT_FOR_PLUG)) { _chargingData[i]->IsReadyToCharging = YES; isCharging = true; // 限定只有在槍類別為 GBT 的時候才做 relay welding 的判斷 if (_chargingData[i]->Type == _Type_GB) { if (_chargingData[i]->SystemStatus >= S_PREPARING_FOR_EVSE && _chargingData[i]->RelayWeldingCheck == NO) CheckRelayWeldingStatus(i); } else _chargingData[i]->RelayWeldingCheck = YES; if (_chargingData[i]->SystemStatus == S_CHARGING) { CheckOutputPowerOverCarReq(i); CheckOutputVolNoneMatchFire(i); } else _isOutputNoneMatch[i] = NO; } else _chargingData[i]->IsReadyToCharging = NO; } // Cable check (Get) GetGfdAdc(); // 橋接 relay SetParalleRelayStatus(); // 搭上 AC Contactor if (isCharging || (ShmPsuData->Work_Step >= _TEST_MODE && ShmPsuData->Work_Step <= _TEST_MODE)) { isStopChargingCount = false; outputRelay.relay_event.bits.AC_Contactor = YES; } else { if (!isStopChargingCount) { gettimeofday(&_close_ac_contactor, NULL); isStopChargingCount = true; } else { if ((outputRelay.relay_event.bits.AC_Contactor == YES && GetTimeoutValue(_close_ac_contactor) / 1000 >= (TEN_MINUTES * 1000))) outputRelay.relay_event.bits.AC_Contactor = NO; } } if (ShmPsuData->Work_Step >= _TEST_MODE && ShmPsuData->Work_Step <= _TEST_MODE) outputRelay.relay_event.bits.Gun1_N = outputRelay.relay_event.bits.Gun1_P = YES; // 搭上/鬆開 Relay if(IsNoneMatchRelayStatus()) { if (Config_Relay_Output(Uart5Fd, Addr.Relay, &outputRelay)) { regRelay.relay_event.bits.CCS_Precharge = outputRelay.relay_event.bits.CCS_Precharge; regRelay.relay_event.bits.Gun1_P = outputRelay.relay_event.bits.Gun1_P; regRelay.relay_event.bits.Gun1_N = outputRelay.relay_event.bits.Gun1_N; regRelay.relay_event.bits.Gun2_P = outputRelay.relay_event.bits.Gun2_P; regRelay.relay_event.bits.Gun2_N = outputRelay.relay_event.bits.Gun2_N; regRelay.relay_event.bits.Gun1_Parallel_P = outputRelay.relay_event.bits.Gun1_Parallel_P; regRelay.relay_event.bits.Gun1_Parallel_N = outputRelay.relay_event.bits.Gun1_Parallel_N; PRINTF_FUNC("Match Relay, AC = %x, g1_p = %x, g1_n = %x, g2_p = %x, g2_n = %x, pre = %x, bri_p = %x, bri_n = %x \n", regRelay.relay_event.bits.AC_Contactor, regRelay.relay_event.bits.Gun1_P, regRelay.relay_event.bits.Gun1_N, regRelay.relay_event.bits.Gun2_P, regRelay.relay_event.bits.Gun2_N, regRelay.relay_event.bits.CCS_Precharge, regRelay.relay_event.bits.Gun1_Parallel_P, regRelay.relay_event.bits.Gun1_Parallel_N); } } } if (ShmFanModuleData->SelfTest_Comp == YES) { if (GetTimeoutValue(_priority_time) / 1000 >= 1000) { //GetPsuTempForFanSpeed(); GetFanSpeedByFunction(); GetFanSpeed(); ShmSysConfigAndInfo->SysInfo.SystemFanRotaSpeed = _setFanSpeed; gettimeofday(&_priority_time, NULL); ShmFanModuleData->SetFan1Speed = ShmFanModuleData->TestFanSpeed; ShmFanModuleData->SetFan2Speed = ShmFanModuleData->TestFanSpeed; ShmFanModuleData->SetFan3Speed = ShmFanModuleData->TestFanSpeed; ShmFanModuleData->SetFan4Speed = ShmFanModuleData->TestFanSpeed; //PRINTF_FUNC("set fan = %d \n", ShmFanModuleData->SetFan1Speed); SetFanModuleSpeed(); } } if (ShmLedModuleData->SelfTest_Comp == YES) { if (GetTimeoutValue(_led_priority_time) / 1000 >= 1000) { if(gunCount == 1) { SetLedColor(_chargingData[0], _chargingData[0]); } else if (gunCount == 2) { SetLedColor(_chargingData[0], _chargingData[1]); } gettimeofday(&_led_priority_time, NULL); } } usleep(10000); } return FAIL; }