#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 "IOComm.h" #include "Config.h" #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; int Uart1Fd; char *relayRs485PortName = "/dev/ttyS5"; char* pPortName = "/dev/ttyS3"; char *priPortName = "/dev/ttyS1"; 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; #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}; byte flash = NO; void PRINTF_FUNC(char *string, ...); #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) 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); } } 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; } void SetModelName_Fan() { } // 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) { } } } */ if (Query_Present_OutputVoltage(Uart5Fd, Addr.Relay, &outputVoltage) == PASS) { //ShmRelayModuleData->Gun1FuseOutputVolt = outputVoltage.behindFuse_Voltage_C1; //ShmRelayModuleData->Gun1RelayOutputVolt = outputVoltage.behindRelay_Voltage_C1; //ShmRelayModuleData->Gun2FuseOutputVolt = outputVoltage.behindFuse_Voltage_C2; //ShmRelayModuleData->Gun2RelayOutputVolt = outputVoltage.behindRelay_Voltage_C2; ShmSysConfigAndInfo->ate.targetVoltage_Value = (outputVoltage.behindRelay_Voltage_C2); //usleep(whileLoopTime); /* for (int index = 0; index < gunCount; index++) { if (index == 0) { if (chargingInfo[index]->Evboard_id == 0x01) { chargingInfo[index]->FuseChargingVoltage = ShmRelayModuleData->Gun1FuseOutputVolt; chargingInfo[index]->FireChargingVoltage = ShmRelayModuleData->Gun1RelayOutputVolt; } else if (chargingInfo[index]->Evboard_id == 0x02) { chargingInfo[index]->FuseChargingVoltage = ShmRelayModuleData->Gun2FuseOutputVolt; chargingInfo[index]->FireChargingVoltage = ShmRelayModuleData->Gun2RelayOutputVolt; } } else if (index == 1) { chargingInfo[index]->FuseChargingVoltage = ShmRelayModuleData->Gun2FuseOutputVolt; chargingInfo[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 (chargingInfo[index]->Type == _Type_Chademo) { Ovp = MaxValue(chargingInfo[index]->MaximumChargingVoltage, chargingInfo[index]->EvBatteryMaxVoltage); Ocp = MaxValue(chargingInfo[index]->PresentChargingCurrent, ShmCHAdeMOData->ev[chargingInfo[index]->type_index].ChargingCurrentRequest); if (chargingInfo[index]->FireChargingVoltage >= Ovp) { //ShmStatusCodeData->AlarmCode.AlarmEvents.bits.SystemChademoOutputOVP = 0x01; } if (chargingInfo[index]->PresentChargingCurrent >= Ocp) { //ShmStatusCodeData->AlarmCode.AlarmEvents.bits.SystemChademoOutputOCP = 0x01; } } else if (chargingInfo[index]->Type == _Type_CCS) { } */ //} } sleep(1); } // 風扇速度 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) { 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) { 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) { 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 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) { //TODO } 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; } } } } } } //========================================== // Init all share memory //========================================== int InitShareMemory() { int result = PASS; int MeterSMId; if ((MeterSMId = shmget(ShmSysConfigAndInfoKey, sizeof(struct SysConfigAndInfo), IPC_CREAT | 0777)) < 0) { #ifdef SystemLogMessage printf("Inter shmget ShmSysConfigAndInfo NG\n"); #endif result = FAIL; } else if ((ShmSysConfigAndInfo = shmat(MeterSMId, NULL, 0)) == (void *) -1) { #ifdef SystemLogMessage printf("[shmat ShmSysConfigAndInfo NG\n"); #endif result = FAIL; } if ((MeterSMId = shmget(ShmStatusCodeKey, sizeof(struct StatusCodeData), IPC_CREAT | 0777)) < 0) { #ifdef SystemLogMessage printf("shmget ShmStatusCodeData NG\n"); #endif result = FAIL; } else if ((ShmStatusCodeData = shmat(MeterSMId, NULL, 0)) == (void *) -1) { #ifdef SystemLogMessage printf("shmat ShmStatusCodeData NG\n"); #endif result = FAIL; } if ((MeterSMId = shmget(ShmFanBdKey, sizeof(struct FanModuleData), IPC_CREAT | 0777)) < 0) { #ifdef SystemLogMessage printf("shmget ShmFanModuleData NG\n"); #endif result = FAIL; } else if ((ShmFanModuleData = shmat(MeterSMId, NULL, 0)) == (void *) -1) { #ifdef SystemLogMessage printf("shmat ShmFanModuleData NG\n"); #endif result = FAIL; } memset(ShmFanModuleData,0,sizeof(struct FanModuleData)); if ((MeterSMId = shmget(ShmRelayBdKey, sizeof(struct RelayModuleData), IPC_CREAT | 0777)) < 0) { #ifdef SystemLogMessage printf("shmget ShmRelayModuleData NG\n"); #endif result = FAIL; } else if ((ShmRelayModuleData = shmat(MeterSMId, NULL, 0)) == (void *) -1) { #ifdef SystemLogMessage printf("shmat ShmRelayModuleData NG\n"); #endif result = FAIL; } memset(ShmRelayModuleData,0,sizeof(struct RelayModuleData)); if ((MeterSMId = shmget(ShmLedBdKey, sizeof(struct LedModuleData), IPC_CREAT | 0777)) < 0) { #ifdef SystemLogMessage printf("shmget ShmLedModuleData NG\n"); #endif result = FAIL; } else if ((ShmLedModuleData = shmat(MeterSMId, NULL, 0)) == (void *) -1) { #ifdef SystemLogMessage printf("shmat ShmLedModuleData NG\n"); #endif result = FAIL; } memset(ShmLedModuleData,0,sizeof(struct LedModuleData)); if ((MeterSMId = shmget(ShmPsuKey, sizeof(struct PsuData), IPC_CREAT | 0777)) < 0) { #ifdef SystemLogMessage printf("shmget ShmPsuData NG \n"); #endif result = FAIL; } else if ((ShmPsuData = shmat(MeterSMId, NULL, 0)) == (void *) -1) { #ifdef SystemLogMessage printf("shmat ShmPsuData 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; } bool FindAcChargingInfoData(byte target, struct ChargingInfoData **acChargingData) { if (target < AC_QUANTITY) { acChargingData[target] = &ShmSysConfigAndInfo->SysInfo.AcChargingData[target]; return true; } return false; } void Initialization() { for (byte index = 0; index < ARRAY_SIZE(outputRelay.relay_event.relay_status); index++) { outputRelay.relay_event.relay_status[index] = 0x00; } char *moduleName = "DMYZ30100J01P0"; memcpy(&ShmSysConfigAndInfo->SysConfig.ModelName, moduleName, strlen(moduleName)); //printf("%s \n", ShmSysConfigAndInfo->SysConfig.ModelName); ShmSysConfigAndInfo->SysInfo.CcsChargingData[CCS_QUANTITY].Index = CCS_QUANTITY; ShmSysConfigAndInfo->SysInfo.CcsChargingData[CCS_QUANTITY].slotsIndex = 1; _chargingData[CCS_QUANTITY] = &ShmSysConfigAndInfo->SysInfo.CcsChargingData[CCS_QUANTITY]; _chargingData[CCS_QUANTITY]->SystemStatus = V_IDLE; _chargingData[CCS_QUANTITY]->Type = _Type_CCS; _chargingData[CCS_QUANTITY]->type_index = CCS_QUANTITY; _chargingData[CCS_QUANTITY]->Evboard_id = 0x01; ShmSysConfigAndInfo->ate.ATEStatus = 0; /* 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.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)) { 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_N = outputRelay.relay_event.bits.Gun1_Parallel_N; regRelay.relay_event.bits.Gun1_Parallel_P = outputRelay.relay_event.bits.Gun1_Parallel_P; } // relay 的狀態 void CheckRelayOutput(byte index) { if(ShmSysConfigAndInfo->ate.ATEState == 1){ if (index == 0) { //printf("=====%d\n",chargingInfo[index]->Evboard_id); if (_chargingData[index]->Evboard_id == 0x01) { if (regRelay.relay_event.bits.Gun1_N == YES && regRelay.relay_event.bits.Gun1_P == YES) _chargingData[0]->RelayK1K2Status = YES; else _chargingData[0]->RelayK1K2Status = NO; if (regRelay.relay_event.bits.Gun1_N == YES && regRelay.relay_event.bits.CCS_Precharge == YES) _chargingData[0]->RelayKPK2Status = YES; else _chargingData[0]->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[0]->RelayK1K2Status = YES; else _chargingData[0]->RelayK1K2Status = NO; if (regRelay.relay_event.bits.Gun2_N == YES && regRelay.relay_event.bits.CCS_Precharge == YES) _chargingData[0]->RelayKPK2Status = YES; else _chargingData[0]->RelayKPK2Status = NO; } } else if (index == 1) { if (regRelay.relay_event.bits.Gun2_N == YES && regRelay.relay_event.bits.Gun2_P == YES) _chargingData[1]->RelayK1K2Status = YES; else _chargingData[1]->RelayK1K2Status = NO; if (regRelay.relay_event.bits.Gun2_N == YES && regRelay.relay_event.bits.CCS_Precharge == YES) _chargingData[1]->RelayKPK2Status = YES; else _chargingData[1]->RelayKPK2Status = NO; } }else if(ShmSysConfigAndInfo->ate.ATEState == 2){ if (index == 0) { //printf("=====%d\n",chargingInfo[index]->Evboard_id); if (_chargingData[index]->Evboard_id == 0x01) { if (regRelay.relay_event.bits.Gun1_Parallel_N == YES && regRelay.relay_event.bits.Gun1_Parallel_P == YES) _chargingData[0]->RelayK1K2Status = YES; else _chargingData[0]->RelayK1K2Status = NO; } else if (_chargingData[index]->Evboard_id == 0x02) { if (regRelay.relay_event.bits.Gun1_Parallel_N == YES && regRelay.relay_event.bits.Gun1_Parallel_P == YES) _chargingData[0]->RelayK1K2Status = YES; else _chargingData[0]->RelayK1K2Status = NO; } } else if (index == 1) { if (regRelay.relay_event.bits.Gun2_N == YES && regRelay.relay_event.bits.Gun2_P == YES) _chargingData[1]->RelayK1K2Status = YES; else _chargingData[1]->RelayK1K2Status = NO; if (regRelay.relay_event.bits.Gun2_N == YES && regRelay.relay_event.bits.CCS_Precharge == YES) _chargingData[1]->RelayKPK2Status = YES; else _chargingData[1]->RelayKPK2Status = NO; } }else if(ShmSysConfigAndInfo->ate.ATEState == 3){ } } void SetOutputGpio(byte flash) { Gpio_out gpio; gpio.Button_LED[0] = 0x00; gpio.Button_LED[1] = 0x00; if(ShmSysConfigAndInfo->ate.ATEState == 1){//CCS gpio.System_LED[0] = flash;//CCS2 gpio.System_LED[1] = 0x00;//GB gpio.System_LED[3] = flash;//CCS1 }else if(ShmSysConfigAndInfo->ate.ATEState == 2){//GB gpio.System_LED[0] = 0x00;//CCS2 gpio.System_LED[1] = flash;//GB gpio.System_LED[3] = 0x00;//CCS1 } //gpio.System_LED[0] = flash;//CCS2 //gpio.System_LED[1] = flash;//GB gpio.System_LED[2] = 0x00; //gpio.System_LED[3] = flash;//CCS1 gpio.AC_Connector = 0x00; gpio.AC_Breaker = 0x00; if (Config_Gpio_Output(Uart1Fd, Addr.IoExtend, &gpio) == PASS) { //PRINTF_FUNC("SetOutputGpio sucessfully. %d \n", flash); } else { //PRINTF_FUNC("SetOutputGpio fail. \n"); } } void SetEvContactorRelayStatus(byte index) { // 為安全起見~ 切換該槍 relay 的條件一是 relay 前後電壓須都要小於 10V // 除了做完 CCS 端的 Precharge,因為在做完 Precharge後,車端會直接直接準備拉載,輸出並不會降低 // 另一個是 Complete 狀態,因為火線上的電壓有可能是來自車端電池電壓,導致火線上的電壓並不會降下來 // 於此同時,只要判斷火線上的電流低於 1A 來判斷 Relay 可鬆開 /* if (chargingInfo[index]->SystemStatus != V_ISOLATION && chargingInfo[index]->SystemStatus != S_COMPLETE ) { if (index == 0 && (ShmRelayModuleData->Gun1FuseOutputVolt > 600 || ShmRelayModuleData->Gun1RelayOutputVolt > 600)) { return; } } */ if(ShmSysConfigAndInfo->ate.ATEState == 1){ if(_chargingData[index]->SystemStatus > V_ISOLATION){ //if(_chargingData[index]->SystemStatus > V_VOLTAGEDIFFERENCE){ if(_chargingData[index]->Evboard_id == 0x01) { // 先搭 D- if (outputRelay.relay_event.bits.Gun1_N == 0x00) outputRelay.relay_event.bits.Gun1_N = 0x01; else outputRelay.relay_event.bits.Gun1_P = 0x01; if (outputRelay.relay_event.bits.Gun2_N == 0x00) outputRelay.relay_event.bits.Gun2_N = 0x01; else outputRelay.relay_event.bits.Gun2_P = 0x01; flash = YES; SetOutputGpio(flash); } }else{ if (_chargingData[index]->Evboard_id == 0x01) { // 先釋放 D+ if (outputRelay.relay_event.bits.Gun1_P == 0x01) outputRelay.relay_event.bits.Gun1_P = 0x00; else outputRelay.relay_event.bits.Gun1_N = 0x00; if (outputRelay.relay_event.bits.Gun2_P == 0x01) outputRelay.relay_event.bits.Gun2_P = 0x00; else outputRelay.relay_event.bits.Gun2_N = 0x00; flash = NO; SetOutputGpio(flash); } } }else if(ShmSysConfigAndInfo->ate.ATEState == 2){ if(ShmSysConfigAndInfo->ate.chademo.id0D_req.K1K2Status == 1){ if(_chargingData[index]->Evboard_id == 0x01){ if (outputRelay.relay_event.bits.Gun1_Parallel_N == 0x00) outputRelay.relay_event.bits.Gun1_Parallel_N = 0x01; else outputRelay.relay_event.bits.Gun1_Parallel_P = 0x01; flash = YES; SetOutputGpio(flash); } }else{ if (_chargingData[index]->Evboard_id == 0x01){ if (outputRelay.relay_event.bits.Gun1_Parallel_P == 0x01) outputRelay.relay_event.bits.Gun1_Parallel_P = 0x00; else outputRelay.relay_event.bits.Gun1_Parallel_N = 0x00; flash = NO; SetOutputGpio(flash); } } } } 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) { } 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 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 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 gpio_export(int pin) { char buffer[64]; snprintf(buffer, sizeof(buffer), "echo %d > /sys/class/gpio/export", pin); system(buffer); } void gpio_unexport(int pin) { char buffer[64]; snprintf(buffer, sizeof(buffer), "echo %d > /sys/class/gpio/unexport", pin); system(buffer); } void gpio_set_direction(int pin, unsigned char dir) { /* char buffer[64]; snprintf(buffer, sizeof(buffer), "echo %s > /sys/class/gpio/gpio%d/direction", dir == GPIO_DIR_INPUT ? "in" : "out", pin); system(buffer); */ int fd; char buffer[64]; snprintf(buffer, sizeof(buffer), "/sys/class/gpio/gpio%d/direction", pin); fd = open(buffer, O_WRONLY); if (fd < 0) { gpio_export(pin); fd = open(buffer, O_WRONLY); if(fd < 0) { printf("\r\nFailed to open gpio%d direction for writing!", pin); return; } } write(fd, dir == GPIO_DIR_INPUT ? "in" : "out", dir == GPIO_DIR_INPUT ? 2 : 3); close(fd); } void gpio_write(int pin, unsigned char value) { char buffer[64]; snprintf(buffer, sizeof(buffer), "echo %d > /sys/class/gpio/gpio%d/value", value > 0 ? 1 : 0, pin); system(buffer); } int gpio_read(int pin) { int fd, value = 0; char ch; char buffer[64]; snprintf(buffer, sizeof(buffer), "/sys/class/gpio/gpio%d/value", pin); fd = open(buffer, O_RDONLY); if (fd < 0) { return -1; } if (read(fd, &ch, 4) < 0) { return -1; } value = atoi(&ch); close(fd); return value; } int Init407ComPort() { int fd; struct termios tios; fd = open(priPortName, O_RDWR); if(fd<=0) { #ifdef SystemLogMessage //DEBUG_ERROR("open 407 Communication port NG \n"); #endif 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]=(unsigned char)1; tios.c_lflag=0; tcflush(fd, TCIFLUSH); ioctl (fd, TCSETS, &tios); return fd; } void InitRS485DirectionIO(void) { //LCD_AC_BIAS_EN => GPIO2_25*//*RS-485 for module DE control gpio_set_direction(PIN_AM_DE_1, GPIO_DIR_OUTPUT); gpio_write(PIN_AM_DE_1, 1); //system("echo 89 > /sys/class/gpio/export"); //system("echo \"out\" > /sys/class/gpio/gpio89/direction"); //system("echo 1 > /sys/class/gpio/gpio89/value"); //LCD_HSYNC => GPIO2_23*//*RS-485 for module RE control gpio_set_direction(PIN_AM_RE_1, GPIO_DIR_OUTPUT); gpio_write(PIN_AM_RE_1, 0); //system("echo 87 > /sys/class/gpio/export"); //system("echo \"out\" > /sys/class/gpio/gpio87/direction"); //system("echo 0 > /sys/class/gpio/gpio87/value"); } int main(void) { printf("Module_internal=====Initializing. \n"); if(InitShareMemory() == FAIL) { #ifdef SystemLogMessage printf("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; Uart1Fd = Init407ComPort(); InitRS485DirectionIO(); // Open Uart5 for RB Uart5Fd = InitComPort(); Initialization(); sleep(1); if(Uart5Fd < 0) { PRINTF_FUNC("(Internal) open port error. \n"); return 0; } for (byte index = 0; index < ARRAY_SIZE(outputRelay.relay_event.relay_status); index++) { outputRelay.relay_event.relay_status[index] = 0x00; } memset(®Relay, 0xFF,sizeof(Relay)); 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("Config_Relay_Output fail \n"); } printf("inter %d....................\n" , ShmSysConfigAndInfo->ate.ATEState); for(;;) { GetPersentOutputVol(); CheckRelayOutput(CCS_QUANTITY); //依據當前各槍的狀態選擇 搭上/放開 Relay SetEvContactorRelayStatus(CCS_QUANTITY); // 搭上/鬆開 Relay // 放開 Relay 之前要先確認輸出的電壓電流是否已經降到某個值 if(IsNoneMatchRelayStatus()) { if (Config_Relay_Output(Uart5Fd, Addr.Relay, &outputRelay)) { //printf("Match Relay............................ \n"); MatchRelayStatus(); /* printf("reg relay, AC = %x, g1_p = %x, g1_n = %x, g2_p = %x, g2_n = %x, pn = %x, pp = %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.Gun1_Parallel_N, regRelay.relay_event.bits.Gun1_Parallel_P); */ } } usleep(10000); } return FAIL; }