#include "Module_PsuComm.h" #define ARRAY_SIZE(A) (sizeof(A) / sizeof(A[0])) #define PASS 1 #define FAIL -1 #define YES 1 #define NO 0 #define NORMAL 0 #define ABNORMAL 1 #define SHARE_CURRENT_GAP 40 #define RELEASE_CUR_GAP 40 #define PSU_DEFAULT_ADDR 255 #define PSU_MIN_VOL 1500 #define EQUAL 0 #define CMD_DELAY_TIME 25000 #define PSU_MIN_OUTPUT_CUR 0.4 // 1A // 安全在停止充電程序中斷開 Relay 的電流 #define SEFETY_SWITCH_RELAY_CUR 50 #define PSU_GONE_RESET 30 #define PSU_NONE 0 struct SysConfigAndInfo *ShmSysConfigAndInfo; struct StatusCodeData *ShmStatusCodeData; struct PsuData *ShmPsuData; struct DcCommonInformation *ShmDcCommonData; struct SmartBoxData *ShmSmartBoxData; bool libInitialize = false; byte getAvailableCapOffset = 5; byte deratingKeepCount = 0; byte step3KeepCount = 0; byte psuCmdSeq = _PSU_CMD_STATUS; float chargingOutputLogInfo[2][4]; byte ConnectorUsingSeq[CHAdeMO_QUANTITY + CCS_QUANTITY + GB_QUANTITY][4] = {{0, 2, 3, 1}, {1, 3, 2, 0}}; void PRINTF_FUNC(char *string, ...); int StoreLogMsg(const char *fmt, ...); #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 GetTimeoutValue(struct timespec *startTime); long int GetTimeoutMValue(struct timespec *startTime) { struct timespec endTime; clock_gettime(CLOCK_MONOTONIC, &endTime); return 1000 * (endTime.tv_sec - startTime->tv_sec) + (endTime.tv_nsec - startTime->tv_nsec) / 1000000; } void GetTimespecMFunc(struct timespec *time) { clock_gettime(CLOCK_MONOTONIC, time); } int GetTimeoutValue(struct timespec *startTime) { struct timespec endTime; clock_gettime(CLOCK_MONOTONIC_COARSE, &endTime); return endTime.tv_sec - startTime->tv_sec; } void GetTimespecFunc(struct timespec *time) { clock_gettime(CLOCK_MONOTONIC_COARSE, time); } 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_%s_Log", 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, ShmSysConfigAndInfo->SysConfig.SerialNumber); system(Buf); } return rc; } 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 ", buffer); } //================================= // Common routine //================================= bool FindTargetGpAndAddr(byte sourceAddr, byte *gp, byte *psuIndex) { bool result = false; for (byte _gp = 0; _gp < ShmPsuData->GroupCount; _gp++) { for (byte _psu = 0; _psu < ShmPsuData->PsuGroup[_gp].GroupPresentPsuQuantity; _psu++) { if (ShmPsuData->PsuGroup[_gp].PsuModule[_psu].Address == sourceAddr) { *gp = _gp; *psuIndex = _psu; result = true; return result; } } } PRINTF_FUNC("Can't find Psu index : %d \n", sourceAddr); return result; } //================================= // Save data to share memory Function //================================= 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; } //================================= // Alarm code mapping to share memory Function //================================= // 檢查 Byte 中某個 Bit 的值 // _byte : 欲改變的 byte // _bit : 該 byte 的第幾個 bit int mask_table[] = { 0x00000001, 0x00000002, 0x00000004, 0x00000008, 0x00000010, 0x00000020, 0x00000040, 0x00000080, 0x00000100, 0x00000200, 0x00000400, 0x00000800, 0x00001000, 0x00002000, 0x00004000, 0x00008000, 0x00010000, 0x00020000, 0x00040000, 0x00080000, 0x00100000, 0x00200000, 0x00400000, 0x00800000, 0x01000000, 0x02000000, 0x04000000, 0x08000000, 0x10000000, 0x20000000, 0x40000000, 0x80000000 }; // INFY POWER #define NONE_DEFINE_1 0 #define NONE_DEFINE_2 1 #define FUSE_BURN_OUT 2 #define PFC_DC_COMM_FAIL 3 #define NONE_DEFINE_3 4 #define NONE_DEFINE_4 5 #define UNBALANCE_POSI_NEGA_BUS_VOL 6 #define BUS_OVER_VOL 7 #define BUS_ABNORMAL_VOL 8 #define PHASE_OVP 9 #define ID_REPETITION 10 #define BUS_UVP 11 #define PHASE_LOSE 12 #define NONE_DEFINE_5 13 #define PHASE_UVP 14 #define NONE_DEFINE_6 15 #define CAN_COMM_FAULT 16 #define DC_DC_UNEVEN_CUR_SHARING 17 #define NONE_DEFINE_7 18 #define PFC_POW_OFF 19 #define NONE_DEFINE_8 20 #define FULL_SPEED_OF_FAN 21 #define DC_DC_POW_OFF 22 #define MODULE_UNDER_POW_LIMIT 23 #define TEMP_POW_LIMIT 24 #define AC_POW_LIMIT 25 #define DC_DC_EEPROM_FAULT 26 #define FAN_FAULT 27 #define DC_DC_SHORT_CIRCUIT 28 #define PFC_EEPROM_FAULT 29 #define DC_DC_OTP 30 #define DC_DC_OVP 31 // UU POWER #define AC_SITE_OVP 0 #define AC_SITE_UVP 1 #define AC_OVP_SHUTDOWN 2 #define PSU_INTERNAL_OVP 3 #define PFC_INTERNAL_UVP 4 #define PFC_INTERNAL_UNBALANCE 5 #define DC_OUTPUT_OVP 6 #define DC_OVP_SHUTDOWN 7 #define DC_OUTPUT_UVP 8 #define FAN_DONT_WORK 9 #define UU_NONE_DEFINE_1 10 #define UU_FAN_FAULT 11 #define ENV_OTP 12 #define ENV_UTP 13 #define PFC_OTP 14 #define OUTPUT_RELAY_BROKEN 15 #define DC_OTP 16 #define UU_NONE_DEFINE_2 17 #define UU_PFC_DC_COMM_FAIL 18 #define UU_NONE_DEFINE_3 19 #define PFC_BROKEN 20 #define DC_TO_DC_BROKEN 21 #define UU_NONE_DEFINE_4 22 #define UU_NONE_DEFINE_5 23 #define UU_NONE_DEFINE_6 24 #define DC_TO_DC_DONT_WORK 25 #define UU_NONE_DEFINE_7 26 #define UU_NONE_DEFINE_8 27 #define DC_OUTPUT_VOLTAGE_UNBALANCE 28 #define UU_ID_REPETITION 29 #define NONE_DEFINE_9 30 #define ABNORMAL_DISCHARGE_CIRCUIT 31 unsigned char DetectBitValue(int _value, unsigned char _bit) { return ( _value & mask_table[_bit] ) != 0x00; } bool AbnormalStopAnalysis(byte gun_index, int errCode) { bool isErr = false; for(byte count = 0; count < sizeof(mask_table)/sizeof(mask_table[0]); count++) { byte value = DetectBitValue(errCode, count); if (value == 1) { switch(count) { case NONE_DEFINE_1 : {} break; case NONE_DEFINE_2 : {} break; case FUSE_BURN_OUT : { isErr = true; if(ShmStatusCodeData->AlarmCode.AlarmEvents.bits.PsuFuseBurnOut == NO) { PRINTF_FUNC("PSU AbnormalStop : FUSE_BURN_OUT \n"); ShmStatusCodeData->AlarmCode.AlarmEvents.bits.PsuFuseBurnOut = YES; } } break; case PFC_DC_COMM_FAIL : { isErr = true; if(ShmStatusCodeData->AlarmCode.AlarmEvents.bits.PsuPfcAndDcdcCommFault == NO) { PRINTF_FUNC ( "PSU AbnormalStop : PFC_DC_COMM_FAIL \n" ); ShmStatusCodeData->AlarmCode.AlarmEvents.bits.PsuPfcAndDcdcCommFault = YES; } } break; case NONE_DEFINE_3 : {} break; case NONE_DEFINE_4 : {} break; case UNBALANCE_POSI_NEGA_BUS_VOL : { isErr = true; if(ShmStatusCodeData->AlarmCode.AlarmEvents.bits.PsuBusVoltageUnbalance == NO) { PRINTF_FUNC ( "PSU AbnormalStop : UNBALANCE_POSI_NEGA_BUS_VOL \n" ); ShmStatusCodeData->AlarmCode.AlarmEvents.bits.PsuBusVoltageUnbalance = YES; } } break; case BUS_OVER_VOL : { isErr = true; if(ShmStatusCodeData->AlarmCode.AlarmEvents.bits.PsuBusOverVoltage == NO) { PRINTF_FUNC ( "PSU AbnormalStop : BUS_OVER_VOL \n" ); ShmStatusCodeData->AlarmCode.AlarmEvents.bits.PsuBusOverVoltage = YES; } } break; case BUS_ABNORMAL_VOL : { isErr = true; if(ShmStatusCodeData->AlarmCode.AlarmEvents.bits.PsuBusVoltageAbnormal == NO) { PRINTF_FUNC ( "PSU AbnormalStop : BUS_ABNORMAL_VOL \n" ); ShmStatusCodeData->AlarmCode.AlarmEvents.bits.PsuBusVoltageAbnormal = YES; } } break; case PHASE_OVP : { isErr = true; if(ShmStatusCodeData->AlarmCode.AlarmEvents.bits.PsuPhaseOvp == NO) { PRINTF_FUNC ( "PSU AbnormalStop : PHASE_OVP \n" ); ShmStatusCodeData->AlarmCode.AlarmEvents.bits.PsuPhaseOvp = YES; } } break; case ID_REPETITION : { isErr = true; if(ShmStatusCodeData->AlarmCode.AlarmEvents.bits.PsuIdRepeat == NO) { PRINTF_FUNC ( "PSU AbnormalStop : ID_REPETITION \n" ); ShmStatusCodeData->AlarmCode.AlarmEvents.bits.PsuIdRepeat = YES; } } break; case BUS_UVP : { isErr = true; if(ShmStatusCodeData->AlarmCode.AlarmEvents.bits.PsuBusUnderVoltage == NO) { PRINTF_FUNC ( "PSU AbnormalStop : BUS_UVP \n" ); ShmStatusCodeData->AlarmCode.AlarmEvents.bits.PsuBusUnderVoltage = YES; } } break; case PHASE_LOSE : { isErr = true; if(ShmStatusCodeData->AlarmCode.AlarmEvents.bits.PsuInputPhaseLoss == NO) { PRINTF_FUNC ( "PSU AbnormalStop : PHASE_LOSE \n" ); ShmStatusCodeData->AlarmCode.AlarmEvents.bits.PsuInputPhaseLoss = YES; } } break; case NONE_DEFINE_5 : {} break; case PHASE_UVP : { isErr = true; if(ShmStatusCodeData->AlarmCode.AlarmEvents.bits.DcInputUVP == NO) { PRINTF_FUNC ( "PSU AbnormalStop : PHASE_UVP \n" ); ShmStatusCodeData->AlarmCode.AlarmEvents.bits.DcInputUVP = YES; } } break; case NONE_DEFINE_6 : {} break; case CAN_COMM_FAULT : { isErr = true; if(ShmStatusCodeData->AlarmCode.AlarmEvents.bits.PsuCanCommFault == NO) { PRINTF_FUNC ( "PSU AbnormalStop : CAN_COMM_FAULT \n" ); ShmStatusCodeData->AlarmCode.AlarmEvents.bits.PsuCanCommFault = YES; } } break; case DC_DC_UNEVEN_CUR_SHARING : { isErr = true; if(ShmStatusCodeData->AlarmCode.AlarmEvents.bits.PsuSevereUnevenCurrent == NO) { PRINTF_FUNC ( "PSU AbnormalStop : DC_DC_UNEVEN_CUR_SHARING \n" ); ShmStatusCodeData->AlarmCode.AlarmEvents.bits.PsuSevereUnevenCurrent = YES; } } break; case NONE_DEFINE_7 : {} break; case PFC_POW_OFF : { //if(ShmStatusCodeData->AlarmCode.AlarmEvents.bits.PsuPfcPowOff == NO) { //PRINTF_FUNC ( "PSU AbnormalStop : PFC_POW_OFF \n" ); //ShmStatusCodeData->AlarmCode.AlarmEvents.bits.PsuPfcPowOff = YES; } } break; case NONE_DEFINE_8 : {} break; case FULL_SPEED_OF_FAN : { isErr = true; if(ShmStatusCodeData->AlarmCode.AlarmEvents.bits.PsuFanFullSpeed == NO) { PRINTF_FUNC ( "PSU AbnormalStop : FULL_SPEED_OF_FAN \n" ); ShmStatusCodeData->AlarmCode.AlarmEvents.bits.PsuFanFullSpeed = YES; } } break; case DC_DC_POW_OFF : { //if(ShmStatusCodeData->AlarmCode.AlarmEvents.bits.PsuDcDcPowOff == NO) { //PRINTF_FUNC ( "PSU AbnormalStop : DC_DC_POW_OFF \n" ); //ShmStatusCodeData->AlarmCode.AlarmEvents.bits.PsuDcDcPowOff = YES; } } break; case MODULE_UNDER_POW_LIMIT : { isErr = true; if(ShmStatusCodeData->AlarmCode.AlarmEvents.bits.PsuPowerLimitedState == NO) { PRINTF_FUNC("PSU AbnormalStop : MODULE_UNDER_POW_LIMIT \n"); ShmStatusCodeData->AlarmCode.AlarmEvents.bits.PsuPowerLimitedState = YES; } } break; case TEMP_POW_LIMIT : { isErr = true; if(ShmStatusCodeData->AlarmCode.AlarmEvents.bits.PsuTemperaturePowerLimit == NO) { PRINTF_FUNC ( "PSU AbnormalStop : TEMP_POW_LIMIT \n" ); ShmStatusCodeData->AlarmCode.AlarmEvents.bits.PsuTemperaturePowerLimit = YES; } } break; case AC_POW_LIMIT : { isErr = true; if(ShmStatusCodeData->AlarmCode.AlarmEvents.bits.PsuAcPowerLimit == NO) { PRINTF_FUNC ( "PSU AbnormalStop : AC_POW_LIMIT \n" ); ShmStatusCodeData->AlarmCode.AlarmEvents.bits.PsuAcPowerLimit = YES; } } break; case DC_DC_EEPROM_FAULT : { isErr = true; if(ShmStatusCodeData->AlarmCode.AlarmEvents.bits.PsuDcdcEepromFault == NO) { PRINTF_FUNC ( "PSU AbnormalStop : DC_DC_EEPROM_FAULT \n" ); ShmStatusCodeData->AlarmCode.AlarmEvents.bits.PsuDcdcEepromFault = YES; } } break; case FAN_FAULT : { isErr = true; if(ShmStatusCodeData->AlarmCode.AlarmEvents.bits.PsuFanFailureAlarm == NO) { PRINTF_FUNC ( "PSU AbnormalStop : FAN_FAULT \n" ); ShmStatusCodeData->AlarmCode.AlarmEvents.bits.PsuFanFailureAlarm = YES; } } break; case DC_DC_SHORT_CIRCUIT : { isErr = true; if(ShmStatusCodeData->AlarmCode.AlarmEvents.bits.PsuOutputShortCircuit == NO) { PRINTF_FUNC ( "PSU AbnormalStop : DC_DC_SHORT_CIRCUIT \n" ); ShmStatusCodeData->AlarmCode.AlarmEvents.bits.PsuOutputShortCircuit = YES; } } break; case PFC_EEPROM_FAULT : { isErr = true; if(ShmStatusCodeData->AlarmCode.AlarmEvents.bits.PsuPfcEepromFault == NO) { PRINTF_FUNC ( "PSU AbnormalStop : PFC_EEPROM_FAULT \n" ); ShmStatusCodeData->AlarmCode.AlarmEvents.bits.PsuPfcEepromFault = YES; } } break; case DC_DC_OTP : { isErr = true; if(ShmStatusCodeData->AlarmCode.AlarmEvents.bits.PsuDcDcOtp == NO) { PRINTF_FUNC ( "PSU AbnormalStop : DC_DC_OTP \n" ); ShmStatusCodeData->AlarmCode.AlarmEvents.bits.PsuDcDcOtp = YES; } } break; case DC_DC_OVP : { isErr = true; if(ShmStatusCodeData->AlarmCode.AlarmEvents.bits.PsuDcDcOvp == NO) { PRINTF_FUNC ( "PSU AbnormalStop : DC_DC_OVP \n" ); ShmStatusCodeData->AlarmCode.AlarmEvents.bits.PsuDcDcOvp = YES; } } break; } } } return isErr; } bool AbnormalStopAnalysis_UU(byte gun_index, int errCode) { bool isErr = false; for(byte count = 0; count < sizeof(mask_table)/sizeof(mask_table[0]); count++) { byte value = DetectBitValue(errCode, count); if (value == 1) { switch(count) { case AC_SITE_OVP : { isErr = true; if(ShmStatusCodeData->AlarmCode.AlarmEvents.bits.PsuBusOverVoltage == NO) { PRINTF_FUNC ( "PSU AbnormalStop : AC_SITE_OVP \n" ); ShmStatusCodeData->AlarmCode.AlarmEvents.bits.PsuBusOverVoltage = YES; } } break; case AC_SITE_UVP : { isErr = true; if(ShmStatusCodeData->AlarmCode.AlarmEvents.bits.PsuBusVoltageAbnormal == NO) { PRINTF_FUNC ( "PSU AbnormalStop : AC_SITE_UVP \n" ); ShmStatusCodeData->AlarmCode.AlarmEvents.bits.PsuBusVoltageAbnormal = YES; } } break; case AC_OVP_SHUTDOWN : { isErr = true; if(ShmStatusCodeData->AlarmCode.AlarmEvents.bits.PsuAcPowerLimit == NO) { PRINTF_FUNC ( "PSU AbnormalStop : AC_OVP_SHUTDOWN \n" ); ShmStatusCodeData->AlarmCode.AlarmEvents.bits.PsuAcPowerLimit = YES; } } break; case PSU_INTERNAL_OVP : { isErr = true; if(ShmStatusCodeData->AlarmCode.AlarmEvents.bits.PsuFuseBurnOut == NO) { PRINTF_FUNC("PSU AbnormalStop : PSU_INTERNAL_OVP \n"); ShmStatusCodeData->AlarmCode.AlarmEvents.bits.PsuFuseBurnOut = YES; } } break; case PFC_INTERNAL_UVP : { isErr = true; if(ShmStatusCodeData->AlarmCode.AlarmEvents.bits.PsuBusUnderVoltage == NO) { PRINTF_FUNC ( "PSU AbnormalStop : PFC_INTERNAL_UVP \n" ); ShmStatusCodeData->AlarmCode.AlarmEvents.bits.PsuBusUnderVoltage = YES; } } break; case PFC_INTERNAL_UNBALANCE : { isErr = true; if(ShmStatusCodeData->AlarmCode.AlarmEvents.bits.PsuSevereUnevenCurrent == NO) { PRINTF_FUNC ( "PSU AbnormalStop : PFC_INTERNAL_UNBALANCE \n" ); ShmStatusCodeData->AlarmCode.AlarmEvents.bits.PsuSevereUnevenCurrent = YES; } } break; case DC_OUTPUT_OVP : { isErr = true; if(ShmStatusCodeData->AlarmCode.AlarmEvents.bits.PsuDcDcOvp == NO) { PRINTF_FUNC ( "PSU AbnormalStop : DC_OUTPUT_OVP \n" ); ShmStatusCodeData->AlarmCode.AlarmEvents.bits.PsuDcDcOvp = YES; } } break; case DC_OVP_SHUTDOWN : { isErr = true; if(ShmStatusCodeData->AlarmCode.AlarmEvents.bits.PsuPowerLimitedState == NO) { PRINTF_FUNC("PSU AbnormalStop : DC_OVP_SHUTDOWN \n"); ShmStatusCodeData->AlarmCode.AlarmEvents.bits.PsuPowerLimitedState = YES; } } break; case DC_OUTPUT_UVP : { isErr = true; if(ShmStatusCodeData->AlarmCode.AlarmEvents.bits.PsuPhaseOvp == NO) { PRINTF_FUNC ( "PSU AbnormalStop : DC_OUTPUT_UVP \n" ); ShmStatusCodeData->AlarmCode.AlarmEvents.bits.PsuPhaseOvp = YES; } } break; case FAN_DONT_WORK : { isErr = true; if(ShmStatusCodeData->AlarmCode.AlarmEvents.bits.PsuFanFullSpeed == NO) { PRINTF_FUNC ( "PSU AbnormalStop : FAN_DONT_WORK \n" ); ShmStatusCodeData->AlarmCode.AlarmEvents.bits.PsuFanFullSpeed = YES; } } break; case UU_NONE_DEFINE_1 : {} break; case UU_FAN_FAULT : { // if(ShmStatusCodeData->AlarmCode.AlarmEvents.bits.PsuFanFailureAlarm == NO) // { // PRINTF_FUNC ( "PSU AbnormalStop : UU_FAN_FAULT \n" ); // ShmStatusCodeData->AlarmCode.AlarmEvents.bits.PsuFanFailureAlarm = YES; // } } break; case ENV_OTP : { isErr = true; if(ShmStatusCodeData->AlarmCode.AlarmEvents.bits.PsuTemperaturePowerLimit == NO) { PRINTF_FUNC ( "PSU AbnormalStop : ENV_OTP \n" ); ShmStatusCodeData->AlarmCode.AlarmEvents.bits.PsuTemperaturePowerLimit = YES; } } break; case ENV_UTP : { isErr = true; if(ShmStatusCodeData->AlarmCode.AlarmEvents.bits.PsuDcDcOtp == NO) { PRINTF_FUNC ( "PSU AbnormalStop : ENV_UTP \n" ); ShmStatusCodeData->AlarmCode.AlarmEvents.bits.PsuDcDcOtp = YES; } } break; case PFC_OTP : { isErr = true; if(ShmStatusCodeData->AlarmCode.AlarmEvents.bits.PsuTemperaturePowerLimit == NO) { PRINTF_FUNC ( "PSU AbnormalStop : ENV_OTP \n" ); ShmStatusCodeData->AlarmCode.AlarmEvents.bits.PsuTemperaturePowerLimit = YES; } } break; case OUTPUT_RELAY_BROKEN : { isErr = true; if(ShmStatusCodeData->AlarmCode.AlarmEvents.bits.PsuTemperaturePowerLimit == NO) { PRINTF_FUNC ( "PSU AbnormalStop : OUTPUT_RELAY_BROKEN \n" ); ShmStatusCodeData->AlarmCode.AlarmEvents.bits.PsuTemperaturePowerLimit = YES; } } break; case DC_OTP : { isErr = true; if(ShmStatusCodeData->AlarmCode.AlarmEvents.bits.PsuTemperaturePowerLimit == NO) { PRINTF_FUNC ( "PSU AbnormalStop : DC_OTP \n" ); ShmStatusCodeData->AlarmCode.AlarmEvents.bits.PsuTemperaturePowerLimit = YES; } } break; case UU_NONE_DEFINE_2 : {} break; case UU_PFC_DC_COMM_FAIL : { isErr = true; if(ShmStatusCodeData->AlarmCode.AlarmEvents.bits.PsuPfcAndDcdcCommFault == NO) { PRINTF_FUNC ( "PSU AbnormalStop : UU_PFC_DC_COMM_FAIL \n" ); ShmStatusCodeData->AlarmCode.AlarmEvents.bits.PsuPfcAndDcdcCommFault = YES; } } break; case UU_NONE_DEFINE_3 : {} break; case PFC_BROKEN : { isErr = true; if(ShmStatusCodeData->AlarmCode.AlarmEvents.bits.PsuPfcEepromFault == NO) { PRINTF_FUNC ( "PSU AbnormalStop : PFC_BROKEN \n" ); ShmStatusCodeData->AlarmCode.AlarmEvents.bits.PsuPfcEepromFault = YES; } } break; case DC_TO_DC_BROKEN : { isErr = true; if(ShmStatusCodeData->AlarmCode.AlarmEvents.bits.PsuDcdcEepromFault == NO) { PRINTF_FUNC ( "PSU AbnormalStop : DC_DC_EEPROM_FAULT \n" ); ShmStatusCodeData->AlarmCode.AlarmEvents.bits.PsuDcdcEepromFault = YES; } } break; case UU_NONE_DEFINE_4 : {} break; case UU_NONE_DEFINE_5 : {} break; case UU_NONE_DEFINE_6 : {} break; case DC_TO_DC_DONT_WORK : { // isErr = true; // if(ShmStatusCodeData->AlarmCode.AlarmEvents.bits.PsuInputPhaseLoss == NO) // { // PRINTF_FUNC ( "PSU AbnormalStop : DC_TO_DC_DONT_WORK \n" ); // ShmStatusCodeData->AlarmCode.AlarmEvents.bits.PsuInputPhaseLoss = YES; // } } break; case UU_NONE_DEFINE_7 : {} break; case UU_NONE_DEFINE_8 : {} break; case DC_OUTPUT_VOLTAGE_UNBALANCE : { isErr = true; if(ShmStatusCodeData->AlarmCode.AlarmEvents.bits.PsuBusVoltageUnbalance == NO) { PRINTF_FUNC ( "PSU AbnormalStop : DC_OUTPUT_VOLTAGE_UNBALANCE \n" ); ShmStatusCodeData->AlarmCode.AlarmEvents.bits.PsuBusVoltageUnbalance = YES; } } break; case UU_ID_REPETITION : { isErr = true; if(ShmStatusCodeData->AlarmCode.AlarmEvents.bits.PsuIdRepeat == NO) { PRINTF_FUNC ( "PSU AbnormalStop : UU_ID_REPETITION \n" ); ShmStatusCodeData->AlarmCode.AlarmEvents.bits.PsuIdRepeat = YES; } } break; case NONE_DEFINE_9 : {} break; case ABNORMAL_DISCHARGE_CIRCUIT : { isErr = true; if(ShmStatusCodeData->AlarmCode.AlarmEvents.bits.PsuOutputShortCircuit == NO) { PRINTF_FUNC ( "PSU AbnormalStop : ABNORMAL_DISCHARGE_CIRCUIT \n" ); ShmStatusCodeData->AlarmCode.AlarmEvents.bits.PsuOutputShortCircuit = YES; } } break; } } } return isErr; } bool IsVoltageStable(byte _index) { bool result = true; float sample = ShmDcCommonData->_outputVoltageSapmle[_index][0]; if (ShmPsuData->PsuGroup[_index].GroupPresentOutputVoltage >= 1500) { for(byte i = 1; i < VOLTAGE_SAMPLE_COUNT; i++) { if (sample <= ShmDcCommonData->_outputVoltageSapmle[_index][i] - 300 || sample >= ShmDcCommonData->_outputVoltageSapmle[_index][i] + 300) { result = false; } } //if (result) { // printf("V[0] => %f \n", ShmDcCommonData->_outputVoltageSapmle[_index][0]); // printf("V[1] => %f \n", ShmDcCommonData->_outputVoltageSapmle[_index][1]); // printf("V[2] => %f \n", ShmDcCommonData->_outputVoltageSapmle[_index][2]); // printf("V[3] => %f \n", ShmDcCommonData->_outputVoltageSapmle[_index][3]); // printf("V[4] => %f \n", ShmDcCommonData->_outputVoltageSapmle[_index][4]); } } else result = false; return result; } //================================= // Callback Function //================================= void ChkUuPwrErrOccur(unsigned address, unsigned char err1, unsigned char err2, unsigned char err3, unsigned char err4) { if (ShmPsuData->Work_Step < GET_SYS_CAP) return; byte group = 0, psuIndex = 0; FindTargetGpAndAddr(address, &group, &psuIndex); int alarm = err4 | (err3 << 8) | (err2 << 16) | (err1 << 24); if (AbnormalStopAnalysis_UU (group, alarm)) { ShmPsuData->PsuGroup[group].PsuModule[psuIndex].AlarmCode = YES; // if (!ShmPsuData->PsuGroup [group].GroupErrorFlag.bits.PsuFailure) // { // ShmPsuData->PsuGroup [group].GroupErrorFlag.bits.PsuFailure = YES; // ShmPsuData->PsuStopChargeFlag = YES; // ShmDcCommonData->_isPsuErrorOccur = YES; // PRINTF_FUNC ( "Group_%d - Index_%d, PSU Error Occurred. \n", group, psuIndex ); // } } else ShmPsuData->PsuGroup[group].PsuModule[psuIndex].AlarmCode = NO; } void GetStatusCallback(byte group, byte SN, byte temp, int alarm, byte type, unsigned char err1, unsigned char err2, unsigned char err3, unsigned char err4) { if (ShmDcCommonData->_psuProtocol != type) ShmDcCommonData->_psuProtocol = type; if (type == _PSU_PROTOCOL_UU) { ShmDcCommonData->psuKeepCommunication = ShmDcCommonData->acContactSwitch; int _timebuf = GetTimeoutValue ( & ShmDcCommonData->_psuComm_time ); if (_timebuf > 1 || _timebuf < 0) { GetTimespecFunc ( & ShmDcCommonData->_psuComm_time ); } if (ShmPsuData->Work_Step == _WORK_CHARGING) { ChkUuPwrErrOccur(SN, err1, err2, err3, err4); } } bool isFind = false; bool isComp = false; byte totalPsuQuantity = 0; if (group >= 4) return; for (byte _group = 0; _group < ShmPsuData->GroupCount; _group++) { totalPsuQuantity += ShmPsuData->PsuGroup[_group].GroupPresentPsuQuantity; } // if (type == _PSU_PROTOCOL_UU) // { // for (byte psuIndex = 0; psuIndex < ShmPsuData->PsuGroup [group].GroupPresentPsuQuantity; psuIndex ++) // { // if (ShmPsuData->PsuGroup [group].PsuModule [psuIndex].Address == PSU_DEFAULT_ADDR) // { // ShmPsuData->PsuGroup [group].PsuModule [psuIndex].Address = SN; // return; // } // } // // if (totalPsuQuantity == ShmPsuData->SystemPresentPsuQuantity && // ShmPsuData->Work_Step < GET_SYS_CAP) // isComp = true; // } // else if (totalPsuQuantity != ShmPsuData->SystemPresentPsuQuantity && // ShmPsuData->SystemPresentPsuQuantity > 0) if (totalPsuQuantity != ShmPsuData->SystemPresentPsuQuantity && ShmPsuData->SystemPresentPsuQuantity > 0) { for (byte psuIndex = 0; psuIndex < ShmPsuData->PsuGroup[group].GroupPresentPsuQuantity; psuIndex++) { if (ShmPsuData->PsuGroup[group].PsuModule[psuIndex].Address == SN) { isFind = true; break; } } if(!isFind) { PRINTF_FUNC("ADD Group = %d, GroupPresentPsuQuantity = %d Psu Count = %d \n", group, ShmPsuData->PsuGroup[group].GroupPresentPsuQuantity, SN); ShmPsuData->PsuGroup[group].PsuModule[ShmPsuData->PsuGroup[group].GroupPresentPsuQuantity].Address = SN; ShmPsuData->PsuGroup[group].GroupPresentPsuQuantity++; } totalPsuQuantity = 0; for (byte _group = 0; _group < ShmPsuData->GroupCount; _group++) { totalPsuQuantity += ShmPsuData->PsuGroup[_group].GroupPresentPsuQuantity; } PRINTF_FUNC("totalPsuQuantity = %d \n", totalPsuQuantity); if (totalPsuQuantity == ShmPsuData->SystemPresentPsuQuantity) isComp = true; } if (isComp) { PRINTF_FUNC ("**************************************************************************** \n" ); for (int _count = 0; _count < ShmPsuData->GroupCount; _count ++) { PRINTF_FUNC ( "Group = %d, Psu Count = %d \n", _count, ShmPsuData->PsuGroup [_count].GroupPresentPsuQuantity); for (int _Pcount = 0; _Pcount < ShmPsuData->PsuGroup [_count].GroupPresentPsuQuantity; _Pcount++) { PRINTF_FUNC ( "Address = %d \n", ShmPsuData->PsuGroup[_count].PsuModule[_Pcount].Address); } } PRINTF_FUNC ("**************************************************************************** \n" ); } } void GetModuleCountCallback(byte group, byte count) { if (group == SYSTEM_CMD) { ShmPsuData->SystemPresentPsuQuantity = count; } else { // if (ShmDcCommonData->_psuProtocol == _PSU_PROTOCOL_UU) // ShmPsuData->PsuGroup[group].GroupPresentPsuQuantity = count; } } void GetAvailableCapCallback(byte address, short maxVol, short minVol, short maxCur, short totalPow) { if (ShmPsuData->Work_Step < GET_SYS_CAP) return; byte group = 0, psuIndex = 0; FindTargetGpAndAddr(address, &group, &psuIndex); ShmPsuData->PsuGroup[group].PsuModule[psuIndex].AvailablePower = totalPow; ShmPsuData->PsuGroup[group].PsuModule[psuIndex].AvailableCurrent = maxCur; ShmPsuData->PsuGroup[group].PsuModule[psuIndex].PresentMaxOutputVoltage = maxVol; } void GetFwCallback(byte address, short dcSwVer, short pfcSwVer, short hwVer, byte type) { if (ShmPsuData->Work_Step < GET_SYS_CAP) return; byte group = 0, psuIndex = 0; FindTargetGpAndAddr(address, &group, &psuIndex); sprintf((char *)ShmPsuData->PsuVersion[address].FwPrimaryVersion, "DC %d.%02d", (dcSwVer & 0xFF00) >> 8, dcSwVer & 0xFF); sprintf((char *)ShmPsuData->PsuVersion[address].FwSecondVersion, "PFC %d.%02d", (pfcSwVer & 0xFF00) >> 8, pfcSwVer & 0xFF); sprintf((char *)ShmPsuData->PsuGroup[group].PsuModule[psuIndex].FwVersion, "DC %d.%02d : PFC %d.%02d", (dcSwVer & 0xFF00) >> 8, dcSwVer & 0xFF, (pfcSwVer & 0xFF00) >> 8, pfcSwVer & 0xFF); } void GetInputVoltageCallback(byte address, unsigned short vol1, unsigned short vol2, unsigned short vol3) { if (ShmPsuData->Work_Step < GET_SYS_CAP) return; byte group = 0, psuIndex = 0; FindTargetGpAndAddr(address, &group, &psuIndex); ShmPsuData->PsuGroup[group].PsuModule[psuIndex].InputVoltageL1 = vol1; ShmPsuData->PsuGroup[group].PsuModule[psuIndex].InputVoltageL2 = vol2; ShmPsuData->PsuGroup[group].PsuModule[psuIndex].InputVoltageL3 = vol3; // PRINTF_FUNC("***Input*** address = %d, R = %d, S = %d, T = %d, gp = %d \n", // address, vol1, vol2, vol3, group); } void GetPresentOutputCallback(byte group, unsigned short outVol, unsigned short outCur) { } void GetMisCallback(byte address, unsigned int value, byte type) { if (ShmPsuData->Work_Step < GET_SYS_CAP) return; byte group = 0, psuIndex = 0; FindTargetGpAndAddr(address, &group, &psuIndex); if (type == 1) { ShmPsuData->PsuGroup[group].PsuModule[psuIndex].FanSpeed_1 = value; ShmPsuData->PsuGroup[group].PsuModule[psuIndex].FanSpeed_2 = value; ShmPsuData->PsuGroup[group].PsuModule[psuIndex].FanSpeed_3 = value; ShmPsuData->PsuGroup[group].PsuModule[psuIndex].FanSpeed_4 = value; } else if (type == 2) { ShmPsuData->PsuGroup[group].PsuModule[psuIndex].ExletTemp = value; } else if (type == 3) { printf("PFC - group = %d, index = %d, value = %d \n", group, address, value); } } void GetIavailableCallback(byte address, unsigned short Iavail, unsigned short Vext) { if (ShmPsuData->Work_Step < GET_SYS_CAP || Iavail > 1000) return; byte group = 0, psuIndex = 0; FindTargetGpAndAddr(address, &group, &psuIndex); // if (group == 2) // { // printf("V1 = %f \n", ShmDcCommonData->_outputVoltageSapmle[group][0]); // printf("V2 = %f \n", ShmDcCommonData->_outputVoltageSapmle[group][1]); // printf("V3 = %f \n", ShmDcCommonData->_outputVoltageSapmle[group][2]); // printf("V4 = %f \n", ShmDcCommonData->_outputVoltageSapmle[group][3]); // printf("V5 = %f \n", ShmDcCommonData->_outputVoltageSapmle[group][4]); // } if (IsVoltageStable(group)) { ShmPsuData->PsuGroup[group].PsuModule[psuIndex].IAvailableCurrent = Iavail; ShmPsuData->PsuGroup[group].PsuModule[psuIndex].KwAvailablePower = ShmPsuData->PsuGroup[group].PsuModule[psuIndex].PresentOutputVoltage * ShmPsuData->PsuGroup[group].PsuModule[psuIndex].IAvailableCurrent / 100 / 1000; } } void GetPresentOutputFCallback(byte group, float outVol, float outCur, byte type) { if (ShmPsuData->Work_Step < GET_SYS_CAP || type == _PSU_PROTOCOL_INFY) return; for(byte count = 0; count < ShmPsuData->PsuGroup[group].GroupPresentPsuQuantity; count++) { ShmPsuData->PsuGroup[group].PsuModule[count].PresentOutputVoltage = (unsigned short)(outVol); ShmPsuData->PsuGroup[group].PsuModule[count].PresentOutputCurrent = (unsigned short)(outCur / ShmPsuData->PsuGroup[group].GroupPresentPsuQuantity); } } //========================================== // 特規用指令 //========================================== void GetOutputAndTempCallback(byte address, unsigned short outputVol_s, unsigned short outputCur_s, unsigned short outputPower, unsigned char Temperature, byte type) { if (ShmPsuData->Work_Step != _WORK_CHARGING) return; byte group = 0, psuIndex = 0; FindTargetGpAndAddr(address, &group, &psuIndex); //PRINTF_FUNC("GetOutputAndTempCallback = *address = %d, group = %d, psuIndex = %d \n", address, group, psuIndex); //printf("group = %d, addr = %d \n", group, addr); ShmPsuData->PsuGroup[group].PsuModule[psuIndex].CriticalTemp1 = Temperature; ShmPsuData->PsuGroup[group].PsuModule[psuIndex].CriticalTemp2 = Temperature; ShmPsuData->PsuGroup[group].PsuModule[psuIndex].CriticalTemp3 = Temperature; // ShmPsuData->PsuGroup[group].PsuModule[psuIndex].ExletTemp = Temperature; if (type == _PSU_PROTOCOL_UU) return; // isinf : -1 = 負無窮,1 = 正無窮,0 = 其他 ShmPsuData->PsuGroup[group].PsuModule[psuIndex].PresentOutputVoltage = (unsigned short)(outputVol_s); ShmPsuData->PsuGroup[group].PsuModule[psuIndex].PresentOutputCurrent = (unsigned short)(outputCur_s); } void GetModuleStatusCallback(byte address, unsigned char isErr, unsigned char status, unsigned char err1, unsigned char err2, unsigned char err3, unsigned char err4) { ShmDcCommonData->psuKeepCommunication = ShmDcCommonData->acContactSwitch; int _timebuf = GetTimeoutValue(&ShmDcCommonData->_psuComm_time); if (_timebuf > 1 || _timebuf < 0) { GetTimespecFunc(&ShmDcCommonData->_psuComm_time); } if (ShmPsuData->Work_Step != _WORK_CHARGING) return; byte group = 0, psuIndex = 0; FindTargetGpAndAddr(address, &group, &psuIndex); //PRINTF_FUNC("GetModuleStatusCallback = *address = %d, group = %d, psuIndex = %d \n", address, group, psuIndex); int alarm = err1 | (err2 << 8) | (err3 << 16) | (err4 << 24); if(AbnormalStopAnalysis(group, alarm)) { ShmPsuData->PsuGroup[group].PsuModule[psuIndex].AlarmCode = YES; // if (!ShmPsuData->PsuGroup[group].GroupErrorFlag.bits.PsuFailure) // { // ShmPsuData->PsuGroup[group].GroupErrorFlag.bits.PsuFailure = YES; // ShmPsuData->PsuStopChargeFlag = YES; // ShmDcCommonData->_isPsuErrorOccur = YES; // PRINTF_FUNC("Group_%d - Index_%d, PSU Error Occurred. \n", group, psuIndex); // } } else ShmPsuData->PsuGroup[group].PsuModule[psuIndex].AlarmCode = NO; } void GetModuleInputCallback(byte address, unsigned short inputR, unsigned short inputS, unsigned short inputT) { if (ShmPsuData->Work_Step != _WORK_CHARGING) return; byte group = 0, psuIndex = 0; FindTargetGpAndAddr(address, &group, &psuIndex); //PRINTF_FUNC("*address = %d, group = %d, psuIndex = %d \n", address, group, psuIndex); ShmPsuData->PsuGroup[group].PsuModule[psuIndex].InputVoltageL1 = inputR; ShmPsuData->PsuGroup[group].PsuModule[psuIndex].InputVoltageL2 = inputS; ShmPsuData->PsuGroup[group].PsuModule[psuIndex].InputVoltageL3 = inputT; //PRINTF_FUNC("***Input*** address = %d, R = %d, S = %d, T = %d \n", // address, inputR, inputS, inputT); } //========================================== // Init all share memory //========================================== int InitShareMemory() { int result = PASS; int MeterSMId; //creat ShmSysConfigAndInfo if ((MeterSMId = shmget(ShmSysConfigAndInfoKey, sizeof(struct SysConfigAndInfo), 0777)) < 0) { #ifdef SystemLogMessage DEBUG_ERROR("shmget ShmSysConfigAndInfo NG %d \n"); #endif result = FAIL; } else if ((ShmSysConfigAndInfo = shmat(MeterSMId, NULL, 0)) == (void *) -1) { #ifdef SystemLogMessage DEBUG_ERROR("shmat ShmSysConfigAndInfo NG \n"); #endif result = FAIL; } //creat ShmStatusCodeData 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; } //creat ShmPsuData 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 ( ShmSmartBoxKey, sizeof(struct SmartBoxData), IPC_CREAT | 0777 )) < 0) { #ifdef SystemLogMessage DEBUG_ERROR("shmat ShmSmartBoxKey NG \n"); #endif return FAIL; } else if ((ShmSmartBoxData = shmat ( MeterSMId, NULL, 0 )) == (void *) - 1) { #ifdef SystemLogMessage DEBUG_ERROR("shmat ShmSmartBoxData NG \n"); #endif return FAIL; } if ((MeterSMId = shmget(ShmCommonKey, sizeof(struct DcCommonInformation), IPC_CREAT | 0777)) < 0) { #ifdef SystemLogMessage DEBUG_ERROR("shmget ShmCommonKey NG \n"); #endif result = FAIL; } else if ((ShmDcCommonData = shmat(MeterSMId, NULL, 0)) == (void *) -1) { #ifdef SystemLogMessage DEBUG_ERROR("shmat ShmCommonKey NG \n"); #endif result = FAIL; } return result; } //================================================ // Log function //================================================ void OutputChargingLogFuncion(byte groupIndex) { // 列印時機 : 需求改變時 if (chargingOutputLogInfo[groupIndex][_CHARGING_LOG_NEED_VOL] != chargingInfo[groupIndex]->EvBatterytargetVoltage * 10) { chargingOutputLogInfo[groupIndex][_CHARGING_LOG_NEED_VOL] = chargingInfo[groupIndex]->EvBatterytargetVoltage * 10; chargingOutputLogInfo[groupIndex][_CHARGING_LOG_OUTPUT_VOL] = chargingInfo[groupIndex]->FireChargingVoltage; PRINTF_FUNC("Conn %d, EV Req Voltage : %.1f (V), EVSE Output Voltage = %.1f (V) \n", groupIndex, chargingOutputLogInfo[groupIndex][_CHARGING_LOG_NEED_VOL] / 10, chargingOutputLogInfo[groupIndex][_CHARGING_LOG_OUTPUT_VOL] / 10); } if (chargingOutputLogInfo[groupIndex][_CHARGING_LOG_NEED_CUR] != chargingInfo[groupIndex]->EvBatterytargetCurrent * 10) { chargingOutputLogInfo[groupIndex][_CHARGING_LOG_NEED_CUR] = chargingInfo[groupIndex]->EvBatterytargetCurrent * 10; chargingOutputLogInfo[groupIndex][_CHARGING_LOG_OUTPUT_CUR] = chargingInfo[groupIndex]->PresentChargingCurrent; PRINTF_FUNC("Conn %d, EV Req Current : %.1f (A), EVSE Output Current = %.1f (A) \n", groupIndex, chargingOutputLogInfo[groupIndex][_CHARGING_LOG_NEED_CUR] / 10, chargingOutputLogInfo[groupIndex][_CHARGING_LOG_OUTPUT_CUR]); } } //================================================ // Main process //================================================ void ClearPsuAlarmCode() { ShmStatusCodeData->AlarmCode.AlarmEvents.bits.PsuFuseBurnOut = NO; ShmStatusCodeData->AlarmCode.AlarmEvents.bits.PsuPfcAndDcdcCommFault = NO; ShmStatusCodeData->AlarmCode.AlarmEvents.bits.PsuBusVoltageUnbalance = NO; ShmStatusCodeData->AlarmCode.AlarmEvents.bits.PsuBusOverVoltage = NO; ShmStatusCodeData->AlarmCode.AlarmEvents.bits.PsuBusVoltageAbnormal = NO; ShmStatusCodeData->AlarmCode.AlarmEvents.bits.PsuPhaseOvp = NO; ShmStatusCodeData->AlarmCode.AlarmEvents.bits.PsuIdRepeat = NO; ShmStatusCodeData->AlarmCode.AlarmEvents.bits.PsuBusUnderVoltage = NO; ShmStatusCodeData->AlarmCode.AlarmEvents.bits.PsuInputPhaseLoss = NO; ShmStatusCodeData->AlarmCode.AlarmEvents.bits.DcInputUVP = NO; ShmStatusCodeData->AlarmCode.AlarmEvents.bits.PsuCanCommFault = NO; ShmStatusCodeData->AlarmCode.AlarmEvents.bits.PsuSevereUnevenCurrent = NO; ShmStatusCodeData->AlarmCode.AlarmEvents.bits.PsuFfcSideShutDown = NO; ShmStatusCodeData->AlarmCode.AlarmEvents.bits.PsuFanFullSpeed = NO; ShmStatusCodeData->AlarmCode.AlarmEvents.bits.PsuDcSideShutDown = NO; ShmStatusCodeData->AlarmCode.AlarmEvents.bits.PsuPowerLimitedState = NO; ShmStatusCodeData->AlarmCode.AlarmEvents.bits.PsuTemperaturePowerLimit = NO; ShmStatusCodeData->AlarmCode.AlarmEvents.bits.PsuAcPowerLimit = NO; ShmStatusCodeData->AlarmCode.AlarmEvents.bits.PsuDcdcEepromFault = NO; ShmStatusCodeData->AlarmCode.AlarmEvents.bits.PsuFanFailureAlarm = NO; ShmStatusCodeData->AlarmCode.AlarmEvents.bits.PsuOutputShortCircuit = NO; ShmStatusCodeData->AlarmCode.AlarmEvents.bits.PsuPfcEepromFault = NO; ShmStatusCodeData->AlarmCode.AlarmEvents.bits.PsuDcDcOtp = NO; ShmStatusCodeData->AlarmCode.AlarmEvents.bits.PsuDcDcOvp = NO; } void Check2ClearPsuError() { for (byte group = 0; group < ShmPsuData->GroupCount; group++) { for (byte psuIndex = 0; psuIndex < ShmPsuData->PsuGroup[group].GroupPresentPsuQuantity; psuIndex++) { if (ShmPsuData->PsuGroup[group].PsuModule[psuIndex].AlarmCode != NO) { return; } } } ClearPsuAlarmCode(); } void FindGunInfo() { bool isPass = false; while ( ! isPass) { isPass = true; for (byte _index = 0; _index < _gunCountRecord; _index ++) { if ( ! FindChargingInfoData ( _index, & chargingInfo [0] )) { DEBUG_ERROR( "Module_PsuComm : FindChargingInfoData false \n" ); isPass = false; break; } } sleep ( 1 ); } } void InitialPsuData() { if (ShmSysConfigAndInfo->SysInfo.IsAlternatvieConf == YES) ShmPsuData->GroupCount = 1; else ShmPsuData->GroupCount = ARRAY_SIZE(ShmPsuData->PsuGroup); ShmPsuData->SystemAvailableCurrent = 0; ShmPsuData->SystemAvailablePower = 0; ShmPsuData->SystemPresentPsuQuantity = 0; for (byte _groupCount = 0; _groupCount < ShmPsuData->GroupCount; _groupCount++) { ShmPsuData->PsuGroup[_groupCount].GroupAvailablePower = 0; ShmPsuData->PsuGroup[_groupCount].GroupAvailableCurrent = 0; ShmPsuData->PsuGroup[_groupCount].GroupRealOutputPower = 0; ShmPsuData->PsuGroup[_groupCount].GroupErrorFlag.bits.PsuFailure = NO; ShmPsuData->PsuGroup[_groupCount].UsingTarget = GUN_CHECK; for (byte _psuCount = 0; _psuCount < MAX_PSU_QUANTITY; _psuCount++) ShmPsuData->PsuGroup[_groupCount].PsuModule[_psuCount].Address = PSU_DEFAULT_ADDR; } for(byte _gunCount = 0; _gunCount < _gunCountRecord; _gunCount++) { chargingInfo[_gunCount]->PresentChargingVoltage = 0; chargingInfo[_gunCount]->PresentChargingCurrent = 0; _releaseWait_chk[_gunCount] = false; } ShmPsuData->PsuStopChargeFlag = NO; ShmDcCommonData->_isPsuErrorOccur = NO; _delayToGetCap = 0; } void Await() { usleep(CMD_DELAY_TIME); } bool ClosePsuPower(byte targetConn, int target) { bool isStop = true; if (target == SYSTEM_CMD) { for (byte groupIndex = 0; groupIndex < _gunCountRecord; groupIndex++) { if((chargingInfo[groupIndex]->PresentChargingCurrent * 10) > SEFETY_SWITCH_RELAY_CUR) { isStop = false; } } if (isStop) { SwitchPower(SYSTEM_CMD, PSU_POWER_OFF); } else { PresentOutputVol(SYSTEM_CMD, 0, 0, ShmPsuData->SystemPresentPsuQuantity); } } else if(ShmPsuData->PsuGroup[target].GroupPresentOutputCurrent > SEFETY_SWITCH_RELAY_CUR) { //PRINTF_FUNC ("target = %d, %d \n", target, ShmPsuData->PsuGroup[target].GroupPresentOutputCurrent); isStop = false; PresentOutputVol(target, 0, 0, ShmPsuData->PsuGroup[target].GroupPresentPsuQuantity); Await(); } else { //PRINTF_FUNC ("close = %d \n", target); SwitchPower(target, PSU_POWER_OFF); FlashLed(target, PSU_FLASH_NORMAL); } return isStop; } void SwitchOffPowerCheck(byte groupIndex) { _maxChargingStatus = _CHARGING_GUN_STATUS_STOP; for (byte index = 0; index < _gunCountRecord; index++) { // 判斷另一把槍的狀態 if (index != groupIndex) { if ((chargingInfo[index]->SystemStatus >= SYS_MODE_PREPARE_FOR_EV && chargingInfo[index]->SystemStatus <= SYS_MODE_CHARGING) || (chargingInfo[index]->SystemStatus >= SYS_MODE_CCS_PRECHARGE_STEP0 && chargingInfo[index]->SystemStatus <= SYS_MODE_CCS_PRECHARGE_STEP1)) _maxChargingStatus = _CHARGING_GUN_STATUS_CHARGING; else _maxChargingStatus = _CHARGING_GUN_STATUS_STOP; } } } byte GetPollingCmd() { if (psuCmdSeq == _PSU_CMD_CAP) { psuCmdSeq = _PSU_CMD_IAVAILABLE; } else if (psuCmdSeq == _PSU_CMD_IAVAILABLE) { psuCmdSeq = _PSU_CMD_OUTPUT_V; } else if (psuCmdSeq == _PSU_CMD_OUTPUT_V) { psuCmdSeq = _PSU_CMD_STATUS; } else if (psuCmdSeq == _PSU_CMD_STATUS) { if (_delay2GetPsuTemp <= 0) psuCmdSeq = _PSU_CMD_TEMP; else psuCmdSeq = _PSU_CMD_CAP; } else psuCmdSeq = _PSU_CMD_CAP; return psuCmdSeq; } void PsuPowerON(byte targetPsuGroup) { // 電流 : 除上使用的模塊總數得到每一個模塊應該輸出的電流值再乘上該輸出群的模塊數量 PresentOutputVol(targetPsuGroup, ShmPsuData->PsuGroup[targetPsuGroup].GroupTargetOutputVoltage, ShmPsuData->PsuGroup[targetPsuGroup].GroupTargetOutputCurrent, ShmPsuData->PsuGroup[targetPsuGroup].GroupPresentPsuQuantity); if (ShmPsuData->PsuGroup[targetPsuGroup].PwSwitchStatus == _PSU_POWER_STATUS_OFF) { ShmPsuData->PsuGroup[targetPsuGroup].PwSwitchStatus = _PSU_POWER_STATUS_ON; SwitchPower(targetPsuGroup, PSU_POWER_ON); FlashLed(targetPsuGroup, PSU_FLASH_ON); } } byte PsuPowerOFF(byte targetConn, byte targetPsuGroup) { if (ShmPsuData->PsuGroup[targetPsuGroup].PwSwitchStatus == _PSU_POWER_STATUS_ON) { // 判斷輸出是否還在 if (ClosePsuPower(targetConn, targetPsuGroup)) ShmPsuData->PsuGroup[targetPsuGroup].PwSwitchStatus = _PSU_POWER_STATUS_OFF; } return ShmPsuData->PsuGroup[targetPsuGroup].PwSwitchStatus; } void PsuOutputCurrentLimtit(byte targetGroup, unsigned short *cur) { //LWADD_MIN_POWER unsigned short Psu_Min_OutputCur = (ShmPsuData->PsuGroup[targetGroup].GroupPresentPsuQuantity * PSU_MIN_OUTPUT_CUR) * 10; if (*cur < Psu_Min_OutputCur) *cur = Psu_Min_OutputCur; } 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; } PRINTF_FUNC("InitShareMemory OK\n"); // register callback function RefreshStatus(&GetStatusCallback); RefreshModuleCount(&GetModuleCountCallback); RefreshAvailableCap(&GetAvailableCapCallback); RefreshFwVersion(&GetFwCallback); RefreshInputVol(&GetInputVoltageCallback); RefreshGetOutput(&GetPresentOutputCallback); RefreshMisInfo(&GetMisCallback); RefreshIavailable(&GetIavailableCallback); RefreshGetOutputF(&GetPresentOutputFCallback); // GetPresentOutputCallback & GetStatusCallback AutoMode_RefreshOutputAndTemp(&GetOutputAndTempCallback); // GetStatusCallback AutoMode_RefreshModuleStatus(&GetModuleStatusCallback); // GetInputVoltageCallback AutoMode_RefreshModuleInput(&GetModuleInputCallback); sleep(2); _gunCountRecord = ShmSysConfigAndInfo->SysConfig.TotalConnectorCount; // initial object FindGunInfo(); InitialPsuData(); GetTimespecFunc(&ShmDcCommonData->_psuComm_time); libInitialize = InitialCommunication(); byte isInitialComp = NO; if (ShmSysConfigAndInfo->SysInfo.IsAlternatvieConf == YES) { PRINTF_FUNC("Alter native mode. \n"); } //main loop while (libInitialize) { // 斷電狀態 if (ShmSysConfigAndInfo->SysInfo.AcContactorStatus == NO) { //一但 AC Off PSU 斷電全部的 PSU Group ID 會全部清 0 if (!isInitialComp) { ShmPsuData->Work_Step = INITIAL_START; psuCmdSeq = _PSU_CMD_STATUS; sleep(2); InitialPsuData(); isInitialComp = YES; } ShmDcCommonData->psuKeepCommunication = ShmDcCommonData->acContactSwitch; sleep(1); continue; } else { if (isInitialComp) GetTimespecFunc(&ShmDcCommonData->_psuComm_time); isInitialComp = NO; } // 自檢失敗 if (ShmPsuData->Work_Step == _NO_WORKING) { PRINTF_FUNC("== PSU == self test fail. \n"); sleep(5); } else if (ShmDcCommonData->rebootCount < 1) { int _time = GetTimeoutValue(&ShmDcCommonData->_psuComm_time); if (_time < 0) GetTimespecFunc(&ShmDcCommonData->_psuComm_time); if (_time > PSU_GONE_RESET) { if (ShmStatusCodeData->AlarmCode.AlarmEvents.bits.PsuComminicationErrWithCSU == NORMAL) { ShmStatusCodeData->AlarmCode.AlarmEvents.bits.PsuComminicationErrWithCSU = ABNORMAL; ShmDcCommonData->rebootCount = 1; PRINTF_FUNC("Psu is gone, reset one time. \n"); } } } switch(ShmPsuData->Work_Step) { case INITIAL_START: { PRINTF_FUNC("== PSU == INITIAL_START \n"); GetTimespecMFunc(&_cmdSubPsuPriority_time); sleep(5); ClosePsuPower(PSU_NONE, SYSTEM_CMD); SetWalkInConfig(SYSTEM_CMD, NO, 0); FlashLed(SYSTEM_CMD, PSU_FLASH_NORMAL); for (byte index = 0; index < ShmPsuData->GroupCount; index++) { ShmPsuData->PsuGroup[index].GroupPresentPsuQuantity = 0; isStartOutputSwitch[index] = false; } ShmPsuData->Work_Step = GET_PSU_COUNT; } break; case GET_PSU_COUNT: { int time = GetTimeoutMValue(&_cmdSubPsuPriority_time); byte moduleCount = 0; if (time < 0) GetTimespecMFunc(&_cmdSubPsuPriority_time); // 發送取得目前全部模組數量 GetModuleCount(SYSTEM_CMD); if (time > 500) { if (psuCmdSeq == _PSU_CMD_STATUS) { // 取得狀態 : 支援模塊不須按照順序功能 for (byte index = 0; index < ShmPsuData->GroupCount; index++) { GetStatus(index, LIB_IN_USE); } Await(); } else if (psuCmdSeq == _PSU_CMD_GETCOUNT) { // 分別取各群模組數量 for (byte index = 0; index < ShmPsuData->GroupCount; index++) { // 總和各群模組數量 moduleCount += ShmPsuData->PsuGroup[index].GroupPresentPsuQuantity; // 取各群模組數量 GetModuleCount(index); } if(_delayToGetCap == 0 && moduleCount == ShmPsuData->SystemPresentPsuQuantity && moduleCount > 0) { PRINTF_FUNC("== PSU == Connector Count = %d, moduleCount = %d, sysCount = %d\n", _gunCountRecord, moduleCount, ShmPsuData->SystemPresentPsuQuantity); } // 判斷系統數量與各群數量一致 if(moduleCount == ShmPsuData->SystemPresentPsuQuantity && moduleCount > 0) { // 電樁在 Booting 的狀態 - 自檢 PRINTF_FUNC ( "== PSU == GET_SYS_CAP \n" ); ShmPsuData->Work_Step = GET_SYS_CAP; } } if (psuCmdSeq == _PSU_CMD_STATUS) psuCmdSeq = _PSU_CMD_GETCOUNT; else psuCmdSeq = _PSU_CMD_STATUS; GetTimespecMFunc(&_cmdSubPsuPriority_time); } } break; case GET_SYS_CAP: { int time = GetTimeoutMValue(&_cmdSubPsuPriority_time); if (time < 0) GetTimespecMFunc(&_cmdSubPsuPriority_time); if (time > 200) { bool isFinish = true; for(byte group = 0; group < ShmPsuData->GroupCount; group++) { if (isFinish) { for (byte psuCount = 0; psuCount < ShmPsuData->PsuGroup[group].GroupPresentPsuQuantity; psuCount++) { if (strcmp((char *)ShmPsuData->PsuGroup[group].PsuModule[psuCount].FwVersion, "") == EQUAL || ShmPsuData->SystemAvailablePower <= 0 || ShmPsuData->SystemAvailableCurrent <= 0) { isFinish = false; break; } } } } if (!isFinish) { for (byte index = 0; index < ShmPsuData->GroupCount; index++) { if (psuCmdSeq == _PSU_CMD_STATUS) { // 取得狀態 : 支援模塊不須按照順序功能 GetStatus(index, LIB_IN_USE); } else if (psuCmdSeq == _PSU_CMD_CAP) { // 取系統總輸出能力 GetModuleCap(index); } else if (psuCmdSeq == _PSU_CMD_VERSION) { // 取版號 GetModuleVer(index); } } Await(); if (psuCmdSeq == _PSU_CMD_STATUS) psuCmdSeq = _PSU_CMD_CAP; else if (psuCmdSeq == _PSU_CMD_CAP) psuCmdSeq = _PSU_CMD_VERSION; else psuCmdSeq = _PSU_CMD_STATUS; } else { // 判斷系統輸出額定功率與電流 PRINTF_FUNC("SystemAvailableCurrent = %d (A), SystemAvailablePower = %d (KW) \n", ShmPsuData->SystemAvailableCurrent / 10, ShmPsuData->SystemAvailablePower / 10); if (ShmSysConfigAndInfo->SysInfo.BootingStatus == BOOTTING) { PRINTF_FUNC ( "== PSU == BOOTING_COMPLETE \n" ); ShmPsuData->Work_Step = BOOTING_COMPLETE; } else { PRINTF_FUNC ( "== PSU == _WORK_CHARGING \n" ); ShmPsuData->Work_Step = _WORK_CHARGING; } } GetTimespecMFunc(&_cmdSubPsuPriority_time); GetTimespecMFunc(&_log_time); GetTimespecMFunc(&_smooth_time); } } break; case BOOTING_COMPLETE: { bool isSelfTestPass = true; for (byte groupIndex = 0; groupIndex < _gunCountRecord; groupIndex++) { if (chargingInfo[groupIndex]->SystemStatus == SYS_MODE_BOOTING) { isSelfTestPass = false; } } if (isSelfTestPass) ShmPsuData->Work_Step = _WORK_CHARGING; sleep(1); } break; case _WORK_CHARGING: { int time = GetTimeoutMValue(&_cmdSubPsuPriority_time); int logTime = GetTimeoutMValue(&_log_time); int smoothTime = GetTimeoutMValue(&_smooth_time); if (time < 0) GetTimespecMFunc(&_cmdSubPsuPriority_time); // 低 Priority 的指令 if (time > 1500) { GetTimespecMFunc(&_cmdSubPsuPriority_time); Check2ClearPsuError(); if (_delay2GetPsuTemp > 0) _delay2GetPsuTemp--; } for (byte groupIndex = 0; groupIndex < ShmPsuData->GroupCount; groupIndex++) { if (psuCmdSeq == _PSU_CMD_STATUS) { // 取得狀態 GetStatus(groupIndex, LIB_IN_USE); } else if (psuCmdSeq == _PSU_CMD_CAP) { // 取系統總輸出能力 GetModuleCap(groupIndex); } else if (psuCmdSeq == _PSU_CMD_IAVAILABLE) { GetModuleIavailable ( groupIndex ); } else if (psuCmdSeq == _PSU_CMD_OUTPUT_V) { // 取各群輸出電壓電流 (UU) GetModuleOutputF(groupIndex); } else if (psuCmdSeq == _PSU_CMD_TEMP) { // 取得模塊溫度 GetDcTemperature(groupIndex); _delay2GetPsuTemp = 10; // 15s } } Await(); psuCmdSeq = GetPollingCmd(); for (byte gunIndex = 0; gunIndex < _gunCountRecord; gunIndex++) { // 針對各槍當前狀態,傳送需要回傳的資料指令 if (((chargingInfo[gunIndex]->SystemStatus >= SYS_MODE_PREPARE_FOR_EVSE && chargingInfo[gunIndex]->SystemStatus <= SYS_MODE_CHARGING) && chargingInfo[gunIndex]->RelayK1K2Status) || (chargingInfo[gunIndex]->SystemStatus >= SYS_MODE_PREPARE_FOR_EVSE && chargingInfo[gunIndex]->SystemStatus <= SYS_MODE_CHARGING && chargingInfo[gunIndex]->Type == _Type_GB) || (chargingInfo[gunIndex]->SystemStatus >= SYS_MODE_CCS_PRECHARGE_STEP0 && chargingInfo[gunIndex]->SystemStatus <= SYS_MODE_CCS_PRECHARGE_STEP1)) { OutputChargingLogFuncion(gunIndex); // 該槍該群是否為使用中 if (ShmPsuData->PsuGroup[gunIndex].PwSwitchStatus == _PSU_POWER_STATUS_OFF && ShmSmartBoxData->ConnectorStatus[gunIndex].ConnectorStaus != _CONNECTOR_STATUS_USING) { // 切出該模塊 } else { unsigned short _shareOutputCur_buf = 0; // Fetch Group if (ShmSmartBoxData->Dynamic4Fetch[gunIndex].ShareGroup < ShmPsuData->GroupCount) { byte _shareGroup = ShmSmartBoxData->Dynamic4Fetch[gunIndex].ShareGroup; byte totalPsuCount = chargingInfo[gunIndex]->_TotalPsuCount; if (ShmSmartBoxData->Dynamic4Fetch[gunIndex].FetchLoopStep >= _PSU_DYNAMIC_FETCH_STEP_TG_VOL && ShmSmartBoxData->Dynamic4Fetch[gunIndex].FetchLoopStep <= _PSU_DYNAMIC_FETCH_STEP_WATI_FINISH) { // 升壓 ShmPsuData->PsuGroup[_shareGroup].GroupTargetOutputVoltage = chargingInfo[gunIndex]->EvBatterytargetVoltage * 10; if (ShmSmartBoxData->Dynamic4Fetch[gunIndex].FetchLoopStep >= _PSU_DYNAMIC_FETCH_STEP_CUR_SHARE) { // 均流 totalPsuCount += ShmPsuData->PsuGroup[_shareGroup].GroupPresentPsuQuantity; // 目標電流 ShmSmartBoxData->Dynamic4Fetch[gunIndex].ShareTargetCurrent = (chargingInfo[gunIndex]->PresentChargingCurrent / totalPsuCount * ShmPsuData->PsuGroup[_shareGroup].GroupPresentPsuQuantity) * 10; if (ShmPsuData->PsuGroup [_shareGroup].GroupPresentOutputCurrent + SHARE_CURRENT_GAP <= ShmSmartBoxData->Dynamic4Fetch[gunIndex].ShareTargetCurrent) _shareOutputCur_buf = ShmPsuData->PsuGroup[_shareGroup].GroupPresentOutputCurrent + SHARE_CURRENT_GAP; else _shareOutputCur_buf = ShmSmartBoxData->Dynamic4Fetch[gunIndex].ShareTargetCurrent; } PsuOutputCurrentLimtit(_shareGroup, &_shareOutputCur_buf); ShmPsuData->PsuGroup [_shareGroup].GroupTargetOutputCurrent = _shareOutputCur_buf; if (logTime >= LOG_TIME) { PRINTF_FUNC("_shareGroup = %d, ShareTargetCurrent = %d, GroupPresentOutputCurrent = %d, GroupTargetOutputCurrent = %d \n", _shareGroup, ShmSmartBoxData->Dynamic4Fetch[gunIndex].ShareTargetCurrent, ShmPsuData->PsuGroup[_shareGroup].GroupPresentOutputCurrent, ShmPsuData->PsuGroup [_shareGroup].GroupTargetOutputCurrent); } if (ShmPsuData->PsuGroup [_shareGroup].GroupTargetOutputVoltage <= PSU_MIN_VOL) { PsuPowerOFF ( gunIndex, _shareGroup ); } else { PsuPowerON ( _shareGroup ); } } } // Release Group unsigned short _releasePsuCount_buf = 0; unsigned short _releaseTargetCur = 0; if (ShmSmartBoxData->Dynamic4Release[gunIndex].ReleaseGroup < ShmPsuData->GroupCount) { byte _releaseGroup = ShmSmartBoxData->Dynamic4Release[gunIndex].ReleaseGroup; if (ShmSmartBoxData->Dynamic4Release[gunIndex].ReleaseLoopStep >= _PSU_DYNAMIC_RELEASE_STEP_CUR_SHARE && ShmSmartBoxData->Dynamic4Release[gunIndex].ReleaseLoopStep <= _PSU_DYNAMIC_RELEASE_STEP_WAIT_FINISH) { unsigned short _releaseTargetVol = chargingInfo[gunIndex]->EvBatterytargetVoltage * 10; _releasePsuCount_buf = ShmPsuData->PsuGroup[_releaseGroup].GroupPresentPsuQuantity; // 扣掉預計要輸出的電流, 餘下的才是該模塊輸出的電流 // if (logTime >= 1000) // { // PRINTF_FUNC ("Req = %.1f, LimitCur = %.1f, _releasePsuCount_buf = %d \n", // chargingInfo[gunIndex]->EvBatterytargetCurrent * 10, // ShmSmartBoxData->Dynamic4Release[gunIndex].LimitCur, // _releasePsuCount_buf); // } if (ShmSmartBoxData->Dynamic4Release[gunIndex].AutoRelease) { _releaseTargetCur = ShmPsuData->PsuGroup[_releaseGroup].GroupTargetOutputCurrent; if (smoothTime >= SMOOTH_TIME) { if (ShmPsuData->PsuGroup[_releaseGroup].GroupTargetOutputCurrent - RELEASE_CUR_GAP < PSU_MIN_OUTPUT_CUR * 10) _releaseTargetCur = PSU_MIN_OUTPUT_CUR * 10 * ShmPsuData->PsuGroup[_releaseGroup].GroupPresentPsuQuantity; else _releaseTargetCur = ShmPsuData->PsuGroup[_releaseGroup].GroupTargetOutputCurrent - RELEASE_CUR_GAP; } // if (ShmSmartBoxData->Dynamic4Release [gunIndex].ReleaseLoopStep == _PSU_DYNAMIC_RELEASE_STEP_CUR_SHARE) // { // ShmPsuData->PsuGroup [_releaseGroup].GroupTargetOutputVoltage = _releaseTargetVol; // PsuOutputCurrentLimtit ( _releaseGroup, // & _releaseTargetCur ); // ShmPsuData->PsuGroup [_releaseGroup].GroupTargetOutputCurrent = _releaseTargetCur; // // PsuPowerON ( _releaseGroup ); // } // else if (ShmSmartBoxData->Dynamic4Release [gunIndex].ReleaseLoopStep == _PSU_DYNAMIC_RELEASE_STEP_WAIT_FINISH) // { // PsuPowerOFF ( gunIndex, _releaseGroup ); // } } else { if ((chargingInfo[gunIndex]->EvBatterytargetCurrent * 10) - ShmSmartBoxData->Dynamic4Release[gunIndex].LimitCur - PSU_CUR_GAP < PSU_MIN_OUTPUT_CUR * 10) _releaseTargetCur = PSU_MIN_OUTPUT_CUR * 10 * ShmPsuData->PsuGroup[_releaseGroup].GroupPresentPsuQuantity; else _releaseTargetCur = (chargingInfo[gunIndex]->EvBatterytargetCurrent * 10) - ShmSmartBoxData->Dynamic4Release[gunIndex].LimitCur - PSU_CUR_GAP; // // if (ShmSmartBoxData->Dynamic4Release[gunIndex].ReleaseLoopStep == _PSU_DYNAMIC_RELEASE_STEP_CUR_SHARE) // { // ShmPsuData->PsuGroup[_releaseGroup].GroupTargetOutputVoltage = _releaseTargetVol; // PsuOutputCurrentLimtit(_releaseGroup, &_releaseTargetCur); // ShmPsuData->PsuGroup[_releaseGroup].GroupTargetOutputCurrent = _releaseTargetCur; // // PsuPowerON(_releaseGroup); // } // else if (ShmSmartBoxData->Dynamic4Release[gunIndex].ReleaseLoopStep == _PSU_DYNAMIC_RELEASE_STEP_WAIT_FINISH) // { // PsuPowerOFF(gunIndex, _releaseGroup); // } } if (ShmSmartBoxData->Dynamic4Release[gunIndex].ReleaseLoopStep == _PSU_DYNAMIC_RELEASE_STEP_CUR_SHARE) { int _releaseTime = 0; if (!_releaseWait_chk[gunIndex]) { _releaseWait_chk[gunIndex] = true; GetTimespecMFunc(&_releaseWait_time[gunIndex]); } else { _releaseTime = GetTimeoutMValue(&_releaseWait_time[gunIndex]); if (_releaseTime >= WAIT_LIMIT_TIME) _releaseTargetCur = PSU_MIN_OUTPUT_CUR * 10 * ShmPsuData->PsuGroup[_releaseGroup].GroupPresentPsuQuantity; } ShmPsuData->PsuGroup[_releaseGroup].GroupTargetOutputVoltage = _releaseTargetVol; PsuOutputCurrentLimtit(_releaseGroup, &_releaseTargetCur); ShmPsuData->PsuGroup[_releaseGroup].GroupTargetOutputCurrent = _releaseTargetCur; PsuPowerON(_releaseGroup); } else if (ShmSmartBoxData->Dynamic4Release[gunIndex].ReleaseLoopStep == _PSU_DYNAMIC_RELEASE_STEP_WAIT_FINISH) { PsuPowerOFF(gunIndex, _releaseGroup); _releaseWait_chk[gunIndex] = false; } } } // 對群下發輸出指令 float sumCurrent = 0; for (int _psuGpIndex = ShmSmartBoxData->ConnectorUsingGroupCount[gunIndex] - 1; _psuGpIndex >= 0; _psuGpIndex--) { byte _targetGroup = ConnectorUsingSeq[gunIndex][_psuGpIndex]; byte psuTotalCount = chargingInfo[gunIndex]->_TotalPsuCount - _releasePsuCount_buf; if (ShmPsuData->PsuGroup[_targetGroup].GroupPresentPsuQuantity <= 0) continue; unsigned short _targetOutputVol_buf = chargingInfo[gunIndex]->EvBatterytargetVoltage * 10; float _evTargetCur = chargingInfo[gunIndex]->EvBatterytargetCurrent; if (_evTargetCur - (_shareOutputCur_buf / 10) <= 0) _evTargetCur = 0; else _evTargetCur -= (_shareOutputCur_buf / 10); if (_releasePsuCount_buf != 0) { if (ShmSmartBoxData->Dynamic4Release[gunIndex].ReleaseGroup == _targetGroup) continue; else { if (ShmSmartBoxData->Dynamic4Release[gunIndex].AutoRelease) { _evTargetCur = chargingInfo[gunIndex]->EvBatterytargetCurrent - _releaseTargetCur / 10; } else _evTargetCur = ShmSmartBoxData->Dynamic4Release[gunIndex].LimitCur / 10; } } unsigned short _targetOutputCur_buf = 0; // 最後一群輸出為總輸出 - 已經輸出的電流 if (_psuGpIndex == 0) { if (_evTargetCur - sumCurrent > 0) _targetOutputCur_buf = (_evTargetCur - sumCurrent) * 10; else { // 輸出電流邏輯 : 該群需要分攤輸出的電流 = 總需求電流 / 總模塊個數 * 該群模塊個數 _targetOutputCur_buf = (_evTargetCur / psuTotalCount * ShmPsuData->PsuGroup[_targetGroup].GroupPresentPsuQuantity) * 10; } } else { // 輸出電流邏輯 : 該群需要分攤輸出的電流 = 總需求電流 / 總模塊個數 * 該群模塊個數 _targetOutputCur_buf = (_evTargetCur / psuTotalCount * ShmPsuData->PsuGroup[_targetGroup].GroupPresentPsuQuantity) * 10; sumCurrent += _targetOutputCur_buf; } // 經度 0.1 // if (logTime >= LOG_TIME) // { // PRINTF_FUNC("psuTotalCount = %d, _evTargetCur = %.1f, sumCurrent = %.1f \n", // psuTotalCount, // _evTargetCur, // sumCurrent); // // PRINTF_FUNC("_targetGroup = %d, _targetOutputVol_buf = %d (0.1), _targetOutputCur_buf = %d (0.1)\n", // _targetGroup, // _targetOutputVol_buf, // _targetOutputCur_buf); // } ShmPsuData->PsuGroup[_targetGroup].GroupTargetOutputVoltage = _targetOutputVol_buf; PsuOutputCurrentLimtit(_targetGroup, &_targetOutputCur_buf); ShmPsuData->PsuGroup[_targetGroup].GroupTargetOutputCurrent = _targetOutputCur_buf; if (ShmPsuData->PsuGroup[_targetGroup].GroupTargetOutputVoltage <= PSU_MIN_VOL) PsuPowerOFF(gunIndex, _targetGroup); else PsuPowerON(_targetGroup); } } } else if (chargingInfo[gunIndex]->SystemStatus >= SYS_MODE_TERMINATING && chargingInfo[gunIndex]->SystemStatus <= SYS_MODE_ALARM) { // 對群下發輸出指令 bool isAllStop = true; for (byte _psuGpIndex = 0; _psuGpIndex < ShmSmartBoxData->ConnectorUsingGroupCount[gunIndex]; _psuGpIndex++) { if (PsuPowerOFF(gunIndex, ConnectorUsingSeq[gunIndex][_psuGpIndex]) == _PSU_POWER_STATUS_ON) { if (isAllStop) isAllStop = false; } } if (ShmSmartBoxData->Dynamic4Fetch[gunIndex].ShareGroup < ShmPsuData->GroupCount) { PsuPowerOFF(gunIndex, ShmSmartBoxData->Dynamic4Fetch[gunIndex].ShareGroup); } if (isAllStop) ShmSmartBoxData->ConnectorStatus[gunIndex].ConnectorStaus = _CONNECTOR_STATUS_NONE; } } if (logTime > LOG_TIME) GetTimespecMFunc(&_log_time); if (smoothTime > SMOOTH_TIME) GetTimespecMFunc(&_smooth_time); } break; } usleep(20000); } return FAIL; }