|
@@ -0,0 +1,1475 @@
|
|
|
+/*
|
|
|
+ * Module_SmartBox.c
|
|
|
+ *
|
|
|
+ * Created on: 2022年5月3日
|
|
|
+ * Author: 7564
|
|
|
+ */
|
|
|
+
|
|
|
+#include "Module_SmartBox.h"
|
|
|
+
|
|
|
+struct SysConfigAndInfo *ShmSysConfigAndInfo;
|
|
|
+struct StatusCodeData *ShmStatusCodeData;
|
|
|
+struct PsuData *ShmPsuData;
|
|
|
+struct DcCommonInformation *ShmDcCommonData;
|
|
|
+struct SmartBoxData *ShmSmartBoxData;
|
|
|
+
|
|
|
+struct ChargingInfoData *chargingInfo[CHAdeMO_QUANTITY + CCS_QUANTITY + GB_QUANTITY];
|
|
|
+byte ConnectorUsingSeq[CHAdeMO_QUANTITY + CCS_QUANTITY + GB_QUANTITY][4] =
|
|
|
+{{0, 2, 3, 1}, {1, 3, 2, 0}};
|
|
|
+
|
|
|
+struct timespec _log_time;
|
|
|
+
|
|
|
+#define DEBUG_INFO(format, args...) StoreLogMsg("[%s:%d][%s][Info] "format, __FILE__, __LINE__, __FUNCTION__, ##args)
|
|
|
+#define DEBUG_WARN(format, args...) StoreLogMsg("[%s:%d][%s][Warn] "format, __FILE__, __LINE__, __FUNCTION__, ##args)
|
|
|
+#define DEBUG_ERROR(format, args...) StoreLogMsg("[%s:%d][%s][Error] "format, __FILE__, __LINE__, __FUNCTION__, ##args)
|
|
|
+
|
|
|
+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);
|
|
|
+}
|
|
|
+//==========================================
|
|
|
+// 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 ShmSysConfigAndInfoKey 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 ShmStatusCodeKey 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 ShmPsuKey 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(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 ShmDcCommonData 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;
|
|
|
+ }
|
|
|
+
|
|
|
+ return result;
|
|
|
+}
|
|
|
+
|
|
|
+//==========================================
|
|
|
+// Public 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;
|
|
|
+}
|
|
|
+
|
|
|
+void Initialization()
|
|
|
+{
|
|
|
+ bool isPass = false;
|
|
|
+ while(!isPass)
|
|
|
+ {
|
|
|
+ isPass = true;
|
|
|
+ for (byte _index = 0; _index < ShmSysConfigAndInfo->SysConfig.TotalConnectorCount; _index++)
|
|
|
+ {
|
|
|
+ if (!FindChargingInfoData(_index, &chargingInfo[0]))
|
|
|
+ {
|
|
|
+ DEBUG_ERROR("SmartBox (main) : FindChargingInfoData false \n");
|
|
|
+ isPass = false;
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ sleep(1);
|
|
|
+ }
|
|
|
+
|
|
|
+ for (byte _index = 0; _index < ShmSysConfigAndInfo->SysConfig.TotalConnectorCount; _index++)
|
|
|
+ {
|
|
|
+ ShmSmartBoxData->Dynamic4Fetch[_index].ShareGroup = NONE_GROUP_CAN_SELECTED;
|
|
|
+ ShmSmartBoxData->Dynamic4Fetch[_index].TargetRelay = NONE_RELAY_SELECTED;
|
|
|
+ ShmSmartBoxData->Dynamic4Fetch[_index].FetchLoopStep = _PSU_DYNAMIC_FETCH_STEP_NONE;
|
|
|
+
|
|
|
+ ShmSmartBoxData->Dynamic4Release[_index].ReleaseGroup = NONE_GROUP_CAN_SELECTED;
|
|
|
+ ShmSmartBoxData->Dynamic4Release[_index].TargetRelay = NONE_RELAY_SELECTED;
|
|
|
+ ShmSmartBoxData->Dynamic4Release[_index].ReleaseLoopStep = _PSU_DYNAMIC_RELEASE_STEP_NONE;
|
|
|
+
|
|
|
+ ShmSmartBoxData->ConnectorUsingGroupCount[_index] = 0;
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+void PrintfLog()
|
|
|
+{
|
|
|
+ if (ShmPsuData->Work_Step != _WORK_CHARGING)
|
|
|
+ {
|
|
|
+ PRINTF_FUNC ( "****************************************************************** \n" );
|
|
|
+ PRINTF_FUNC ( "SystemPresentPsuQuantity = %d \n", ShmPsuData->SystemPresentPsuQuantity);
|
|
|
+ PRINTF_FUNC ( "SystemAvailableCurrent = %d (A) \n", ShmPsuData->SystemAvailableCurrent / 10);
|
|
|
+ PRINTF_FUNC ( "SystemAvailablePower = %d (kw) \n", ShmPsuData->SystemAvailablePower / 10);
|
|
|
+ PRINTF_FUNC ( "GroupCount = %d \n", ShmPsuData->GroupCount );
|
|
|
+
|
|
|
+ for (int _count = 0; _count < ARRAY_SIZE(ConnectorUsingSeq[0]); _count ++)
|
|
|
+ {
|
|
|
+ PRINTF_FUNC ( "----------------------------------------------------------------- \n" );
|
|
|
+ PRINTF_FUNC ( "Group Index = %d, UsingTarget for Gun-%d \n", _count, ShmPsuData->PsuGroup[_count].UsingTarget);
|
|
|
+ PRINTF_FUNC ( "GroupPresentPsuQuantity = %d \n", ShmPsuData->PsuGroup[_count].GroupPresentPsuQuantity );
|
|
|
+ PRINTF_FUNC ( "GroupTargetOutputVoltage = %d (V) \n", ShmPsuData->PsuGroup[_count].GroupTargetOutputVoltage / 10);
|
|
|
+ PRINTF_FUNC ( "GroupTargetOutputCurrent = %d (A) \n", ShmPsuData->PsuGroup[_count].GroupTargetOutputCurrent / 10);
|
|
|
+ PRINTF_FUNC ( "GroupAvailableCurrent = %d (A) \n", ShmPsuData->PsuGroup[_count].GroupAvailableCurrent / 10);
|
|
|
+ PRINTF_FUNC ( "GroupAvailablePower = %d (kw) \n", ShmPsuData->PsuGroup[_count].GroupAvailablePower / 10);
|
|
|
+ PRINTF_FUNC ( "GroupMaxVoltage = %d (V) \n", ShmPsuData->PsuGroup[_count].GroupMaxVoltage / 10);
|
|
|
+ PRINTF_FUNC ( "GroupPresentOutputVoltage = %.1f (V) \n", (double)ShmPsuData->PsuGroup[_count].GroupPresentOutputVoltage / 10);
|
|
|
+ PRINTF_FUNC ( "GroupPresentOutputCurrent = %.1f (A) \n", (double)ShmPsuData->PsuGroup[_count].GroupPresentOutputCurrent / 10);
|
|
|
+ PRINTF_FUNC ( "GroupPresentOutputPower = %d \n", ShmPsuData->PsuGroup[_count].GroupPresentOutputPower );
|
|
|
+ PRINTF_FUNC ( "TotalRatingPower = %f \n", (double)ShmPsuData->PsuGroup[_count].TotalRatingPower);
|
|
|
+ PRINTF_FUNC ( "TotalIAvailableCurrent = %f \n", (double)ShmPsuData->PsuGroup[_count].TotalIAvailableCurrent / 10);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ for (byte conn = 0; conn < ShmSysConfigAndInfo->SysConfig.TotalConnectorCount; conn++)
|
|
|
+ {
|
|
|
+ byte totalUsingGpCount = 0;
|
|
|
+ byte totalQuantity = 0;
|
|
|
+ unsigned short _targetVol = 0 , _targetCur = 0;
|
|
|
+ unsigned short _avaCur = 0 , _avaPow = 0;
|
|
|
+ unsigned short _outputVol = 0 , _outputCur = 0;
|
|
|
+ unsigned short _ratingPow = 0;
|
|
|
+
|
|
|
+ for (byte gp = 0; gp < ShmSmartBoxData->ConnectorUsingGroupCount[conn]; gp++)
|
|
|
+ {
|
|
|
+ if (ShmPsuData->PsuGroup[ConnectorUsingSeq[conn][gp]].UsingTarget == GUN_LEFT)
|
|
|
+ {
|
|
|
+ totalUsingGpCount++;
|
|
|
+ byte tarGp = ConnectorUsingSeq[conn][gp];
|
|
|
+
|
|
|
+ totalQuantity += ShmPsuData->PsuGroup[tarGp].GroupPresentPsuQuantity;
|
|
|
+ _targetVol = ShmPsuData->PsuGroup[tarGp].GroupTargetOutputVoltage / 10;
|
|
|
+ _targetCur += ShmPsuData->PsuGroup[tarGp].GroupTargetOutputCurrent / 10;
|
|
|
+ _avaCur += ShmPsuData->PsuGroup[tarGp].GroupAvailableCurrent / 10;
|
|
|
+ _avaPow += ShmPsuData->PsuGroup[tarGp].GroupAvailablePower / 10;
|
|
|
+ _outputVol = (double)ShmPsuData->PsuGroup[tarGp].GroupPresentOutputVoltage / 10;
|
|
|
+ _outputCur = (double)ShmPsuData->PsuGroup[tarGp].GroupPresentOutputCurrent / 10;
|
|
|
+ _ratingPow += ShmPsuData->PsuGroup[tarGp].TotalRatingPower;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ if (totalUsingGpCount > 0)
|
|
|
+ {
|
|
|
+ PRINTF_FUNC ( "----------------------------------------------------------------- \n" );
|
|
|
+ PRINTF_FUNC ( "Group Index = %d, totalUsingGpCount = %d \n", conn, totalUsingGpCount);
|
|
|
+ PRINTF_FUNC ( "totalQuantity = %d \n", totalQuantity);
|
|
|
+ PRINTF_FUNC ( "_targetVol = %d (V), _targetCur = %d (A) \n", _targetVol, _targetCur);
|
|
|
+ PRINTF_FUNC ( "_avaCur = %d (A), _avaPow = %d (kw) \n", _avaCur, _avaPow);
|
|
|
+ PRINTF_FUNC ( "_outputVol = %d (V), _outputCur = %d (A) \n", _outputVol, _outputCur);
|
|
|
+ PRINTF_FUNC ( "_ratingPow = %d \n", _ratingPow);
|
|
|
+ }
|
|
|
+
|
|
|
+ for (byte gp = 0; gp < ShmSmartBoxData->ConnectorUsingGroupCount[conn]; gp++)
|
|
|
+ {
|
|
|
+ if (ShmPsuData->PsuGroup[ConnectorUsingSeq[conn][gp]].UsingTarget == GUN_RIGHT)
|
|
|
+ {
|
|
|
+ totalUsingGpCount++;
|
|
|
+ byte tarGp = ConnectorUsingSeq[conn][gp];
|
|
|
+
|
|
|
+ totalQuantity += ShmPsuData->PsuGroup [tarGp].GroupPresentPsuQuantity;
|
|
|
+ _targetVol = ShmPsuData->PsuGroup [tarGp].GroupTargetOutputVoltage / 10;
|
|
|
+ _targetCur += ShmPsuData->PsuGroup [tarGp].GroupTargetOutputCurrent / 10;
|
|
|
+ _avaCur += ShmPsuData->PsuGroup [tarGp].GroupAvailableCurrent / 10;
|
|
|
+ _avaPow += ShmPsuData->PsuGroup [tarGp].GroupAvailablePower / 10;
|
|
|
+ _outputVol = (double) ShmPsuData->PsuGroup [tarGp].GroupPresentOutputVoltage / 10;
|
|
|
+ _outputCur = (double) ShmPsuData->PsuGroup [tarGp].GroupPresentOutputCurrent / 10;
|
|
|
+ _ratingPow += ShmPsuData->PsuGroup [tarGp].TotalRatingPower;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ if (totalUsingGpCount > 0)
|
|
|
+ {
|
|
|
+ PRINTF_FUNC ( "----------------------------------------------------------------- \n" );
|
|
|
+ PRINTF_FUNC ( "Group Index = %d, totalUsingGpCount = %d \n", conn, totalUsingGpCount);
|
|
|
+ PRINTF_FUNC ( "totalQuantity = %d \n", totalQuantity);
|
|
|
+ PRINTF_FUNC ( "_targetVol = %d (V), _targetCur = %d (A) \n", _targetVol, _targetCur);
|
|
|
+ PRINTF_FUNC ( "_avaCur = %d (A), _avaPow = %d (kw) \n", _avaCur, _avaPow);
|
|
|
+ PRINTF_FUNC ( "_outputVol = %d (V), _outputCur = %d (A) \n", _outputVol, _outputCur);
|
|
|
+ PRINTF_FUNC ( "_ratingPow = %d \n", _ratingPow);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+void GetSystemMaxVoltage()
|
|
|
+{
|
|
|
+ if (ShmSysConfigAndInfo->SysInfo.BootingStatus == BOOTTING)
|
|
|
+ {
|
|
|
+ int _sysVol = 0;
|
|
|
+
|
|
|
+ for (byte group = 0; group < ShmPsuData->GroupCount; group++)
|
|
|
+ {
|
|
|
+ if (ShmPsuData->PsuGroup[group].GroupMaxVoltage > _sysVol)
|
|
|
+ _sysVol = ShmPsuData->PsuGroup[group].GroupMaxVoltage;
|
|
|
+ }
|
|
|
+
|
|
|
+ for (byte gun_index = 0; gun_index < ShmSysConfigAndInfo->SysConfig.TotalConnectorCount; gun_index++)
|
|
|
+ {
|
|
|
+ if (chargingInfo[gun_index]->MaximumChargingVoltage != _sysVol)
|
|
|
+ {
|
|
|
+ chargingInfo[gun_index]->MaximumChargingVoltage = _sysVol;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+void GetTimespecFunc(struct timespec *time)
|
|
|
+{
|
|
|
+ clock_gettime(CLOCK_MONOTONIC, time);
|
|
|
+}
|
|
|
+
|
|
|
+long int GetTimeoutValue(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;
|
|
|
+}
|
|
|
+
|
|
|
+//==========================================
|
|
|
+// Relay Processing
|
|
|
+//==========================================
|
|
|
+void SmartRelayCheck()
|
|
|
+{
|
|
|
+ /*
|
|
|
+ ---------------------------------------
|
|
|
+ G_0 -----------(R1)----------------> Gun - 0
|
|
|
+ | -> R3
|
|
|
+ G_2 --------|
|
|
|
+ | -> R4
|
|
|
+ G_3 --------|
|
|
|
+ | -> R5
|
|
|
+ G_1 -----------(R2)----------------> Gun - 1
|
|
|
+ ---------------------------------------
|
|
|
+ R3 ON 時機 : G_2 屬於 Gun-0 輸出、G_0屬於 Gun - 1 輸出
|
|
|
+ R4 ON 時機 : G_3 屬於 Gun-0 輸出、G_2屬於 Gun - 1 輸出
|
|
|
+ R5 ON 時機 : G_3 屬於 Gun-1 輸出、G_1屬於 Gun - 0 輸出
|
|
|
+ -------------------------
|
|
|
+ 掃描PSU四個群及兩輸出的ShareGroup內的值各屬於哪個輸出
|
|
|
+ */
|
|
|
+ byte _buff[3] = {0};
|
|
|
+
|
|
|
+ for (byte group = 0; group < ShmPsuData->GroupCount; group++)
|
|
|
+ {
|
|
|
+ switch(group)
|
|
|
+ {
|
|
|
+ case _PSU_GROUP_INDEX_0:
|
|
|
+ {
|
|
|
+ if (ShmPsuData->PsuGroup[group].UsingTarget == GUN_RIGHT)
|
|
|
+ {
|
|
|
+ // 如果是標準品
|
|
|
+ if(ShmDcCommonData->systemType == _SYSTEM_TYPE_STANDARD)
|
|
|
+ {
|
|
|
+ _buff[_RELAY_SWITCH_NAME_R4] = 0x01;
|
|
|
+ _buff[_RELAY_SWITCH_NAME_R5] = 0x01;
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ // R3 ON
|
|
|
+ _buff[_RELAY_SWITCH_NAME_R3] = 0x01;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ break;
|
|
|
+ case _PSU_GROUP_INDEX_2:
|
|
|
+ {
|
|
|
+ if (ShmPsuData->PsuGroup[group].UsingTarget == GUN_LEFT)
|
|
|
+ {
|
|
|
+ // R3 ON
|
|
|
+ _buff[_RELAY_SWITCH_NAME_R3] = 0x01;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (ShmPsuData->PsuGroup[group].UsingTarget == GUN_RIGHT)
|
|
|
+ {
|
|
|
+ // R4 ON
|
|
|
+ _buff[_RELAY_SWITCH_NAME_R4] = 0x01;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ break;
|
|
|
+ case _PSU_GROUP_INDEX_3:
|
|
|
+ {
|
|
|
+ if (ShmPsuData->PsuGroup[group].UsingTarget == GUN_LEFT)
|
|
|
+ {
|
|
|
+ // R4 ON
|
|
|
+ _buff[_RELAY_SWITCH_NAME_R4] = 0x01;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (ShmPsuData->PsuGroup[group].UsingTarget == GUN_RIGHT)
|
|
|
+ {
|
|
|
+ // R5 ON
|
|
|
+ _buff[_RELAY_SWITCH_NAME_R5] = 0x01;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ break;
|
|
|
+ case _PSU_GROUP_INDEX_1:
|
|
|
+ {
|
|
|
+ if (ShmPsuData->PsuGroup[group].UsingTarget == GUN_LEFT)
|
|
|
+ {
|
|
|
+ // 如果是標準品
|
|
|
+ if(ShmDcCommonData->systemType == _SYSTEM_TYPE_STANDARD)
|
|
|
+ {
|
|
|
+ _buff[_RELAY_SWITCH_NAME_R4] = 0x01;
|
|
|
+ _buff[_RELAY_SWITCH_NAME_R5] = 0x01;
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ // R5 ON
|
|
|
+ _buff[_RELAY_SWITCH_NAME_R5] = 0x01;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ for (byte _Conn = 0; _Conn < ShmSysConfigAndInfo->SysConfig.TotalConnectorCount; _Conn++)
|
|
|
+ {
|
|
|
+ if (ShmSmartBoxData->Dynamic4Fetch[_Conn].FetchLoopStep >= _PSU_DYNAMIC_FETCH_STEP_RELAY)
|
|
|
+ {
|
|
|
+ byte targetGroup = ShmSmartBoxData->Dynamic4Fetch[_Conn].ShareGroup;
|
|
|
+
|
|
|
+ switch(targetGroup)
|
|
|
+ {
|
|
|
+ case _PSU_GROUP_INDEX_0:
|
|
|
+ {
|
|
|
+ if (ShmPsuData->PsuGroup[targetGroup].UsingTarget == GUN_RIGHT)
|
|
|
+ {
|
|
|
+ // 如果是標準品
|
|
|
+ if(ShmDcCommonData->systemType == _SYSTEM_TYPE_STANDARD)
|
|
|
+ {
|
|
|
+ _buff[_RELAY_SWITCH_NAME_R4] = 0x01;
|
|
|
+ _buff[_RELAY_SWITCH_NAME_R5] = 0x01;
|
|
|
+ ShmSmartBoxData->Dynamic4Fetch[_Conn].TargetRelay = _RELAY_SWITCH_NAME_R4;
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ // R3 ON -- P
|
|
|
+ _buff[_RELAY_SWITCH_NAME_R3] = 0x01;
|
|
|
+ ShmSmartBoxData->Dynamic4Fetch[_Conn].TargetRelay = _RELAY_SWITCH_NAME_R3;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ break;
|
|
|
+ case _PSU_GROUP_INDEX_2:
|
|
|
+ {
|
|
|
+ if (ShmPsuData->PsuGroup[targetGroup].UsingTarget == GUN_LEFT)
|
|
|
+ {
|
|
|
+ // R3 ON -- P
|
|
|
+ _buff[_RELAY_SWITCH_NAME_R3] = 0x01;
|
|
|
+ ShmSmartBoxData->Dynamic4Fetch[_Conn].TargetRelay = _RELAY_SWITCH_NAME_R3;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (ShmPsuData->PsuGroup[targetGroup].UsingTarget == GUN_RIGHT)
|
|
|
+ {
|
|
|
+ // R4 ON -- P
|
|
|
+ _buff[_RELAY_SWITCH_NAME_R4] = 0x01;
|
|
|
+ ShmSmartBoxData->Dynamic4Fetch[_Conn].TargetRelay = _RELAY_SWITCH_NAME_R4;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ break;
|
|
|
+ case _PSU_GROUP_INDEX_3:
|
|
|
+ {
|
|
|
+ if (ShmPsuData->PsuGroup[targetGroup].UsingTarget == GUN_LEFT)
|
|
|
+ {
|
|
|
+ // R4 ON -- P
|
|
|
+ _buff[_RELAY_SWITCH_NAME_R4] = 0x01;
|
|
|
+ ShmSmartBoxData->Dynamic4Fetch[_Conn].TargetRelay = _RELAY_SWITCH_NAME_R4;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (ShmPsuData->PsuGroup[targetGroup].UsingTarget == GUN_RIGHT)
|
|
|
+ {
|
|
|
+ // R5 ON -- P
|
|
|
+ _buff[_RELAY_SWITCH_NAME_R5] = 0x01;
|
|
|
+ ShmSmartBoxData->Dynamic4Fetch[_Conn].TargetRelay = _RELAY_SWITCH_NAME_R5;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ break;
|
|
|
+ case _PSU_GROUP_INDEX_1:
|
|
|
+ {
|
|
|
+ if (ShmPsuData->PsuGroup[targetGroup].UsingTarget == GUN_LEFT)
|
|
|
+ {
|
|
|
+ // 如果是標準品
|
|
|
+ if(ShmDcCommonData->systemType == _SYSTEM_TYPE_STANDARD)
|
|
|
+ {
|
|
|
+ _buff[_RELAY_SWITCH_NAME_R4] = 0x01;
|
|
|
+ _buff[_RELAY_SWITCH_NAME_R5] = 0x01;
|
|
|
+ ShmSmartBoxData->Dynamic4Fetch[_Conn].TargetRelay = _RELAY_SWITCH_NAME_R4;
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ // R5 ON -- P
|
|
|
+ _buff[_RELAY_SWITCH_NAME_R5] = 0x01;
|
|
|
+ ShmSmartBoxData->Dynamic4Fetch[_Conn].TargetRelay = _RELAY_SWITCH_NAME_R5;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ if (ShmSmartBoxData->Dynamic4Release[_Conn].ReleaseLoopStep >= _PSU_DYNAMIC_RELEASE_STEP_RELAYOFF)
|
|
|
+ {
|
|
|
+ byte targetGroup = ShmSmartBoxData->Dynamic4Release[_Conn].ReleaseGroup;
|
|
|
+
|
|
|
+ switch(targetGroup)
|
|
|
+ {
|
|
|
+ case _PSU_GROUP_INDEX_0:
|
|
|
+ {
|
|
|
+ if (ShmPsuData->PsuGroup[targetGroup].UsingTarget == GUN_RIGHT)
|
|
|
+ {
|
|
|
+ // R3 OFF
|
|
|
+ _buff[_RELAY_SWITCH_NAME_R3] = 0x00;
|
|
|
+ ShmSmartBoxData->Dynamic4Release[_Conn].TargetRelay = _RELAY_SWITCH_NAME_R3;
|
|
|
+
|
|
|
+ // 如果是標準品
|
|
|
+ if(ShmDcCommonData->systemType == _SYSTEM_TYPE_STANDARD)
|
|
|
+ {
|
|
|
+ _buff[_RELAY_SWITCH_NAME_R4] = 0x00;
|
|
|
+ _buff[_RELAY_SWITCH_NAME_R5] = 0x00;
|
|
|
+ ShmSmartBoxData->Dynamic4Release[_Conn].TargetRelay = _RELAY_SWITCH_NAME_R4;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ break;
|
|
|
+ case _PSU_GROUP_INDEX_2:
|
|
|
+ {
|
|
|
+ if (ShmPsuData->PsuGroup[targetGroup].UsingTarget == GUN_LEFT)
|
|
|
+ {
|
|
|
+ // R3 OFF
|
|
|
+ _buff[_RELAY_SWITCH_NAME_R3] = 0x00;
|
|
|
+ ShmSmartBoxData->Dynamic4Release[_Conn].TargetRelay = _RELAY_SWITCH_NAME_R3;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (ShmPsuData->PsuGroup[targetGroup].UsingTarget == GUN_RIGHT)
|
|
|
+ {
|
|
|
+ // R5 OFF
|
|
|
+ _buff[_RELAY_SWITCH_NAME_R4] = 0x00;
|
|
|
+ ShmSmartBoxData->Dynamic4Release[_Conn].TargetRelay = _RELAY_SWITCH_NAME_R4;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ break;
|
|
|
+ case _PSU_GROUP_INDEX_3:
|
|
|
+ {
|
|
|
+ if (ShmPsuData->PsuGroup[targetGroup].UsingTarget == GUN_LEFT)
|
|
|
+ {
|
|
|
+ // R4 OFF
|
|
|
+ _buff[_RELAY_SWITCH_NAME_R4] = 0x00;
|
|
|
+ ShmSmartBoxData->Dynamic4Release[_Conn].TargetRelay = _RELAY_SWITCH_NAME_R4;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (ShmPsuData->PsuGroup[targetGroup].UsingTarget == GUN_RIGHT)
|
|
|
+ {
|
|
|
+ // R5 OFF
|
|
|
+ _buff[_RELAY_SWITCH_NAME_R5] = 0x00;
|
|
|
+ ShmSmartBoxData->Dynamic4Release[_Conn].TargetRelay = _RELAY_SWITCH_NAME_R5;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ break;
|
|
|
+ case _PSU_GROUP_INDEX_1:
|
|
|
+ {
|
|
|
+ if (ShmPsuData->PsuGroup[targetGroup].UsingTarget == GUN_LEFT)
|
|
|
+ {
|
|
|
+ // 如果是標準品
|
|
|
+ if(ShmDcCommonData->systemType == _SYSTEM_TYPE_STANDARD)
|
|
|
+ {
|
|
|
+ _buff[_RELAY_SWITCH_NAME_R4] = 0x00;
|
|
|
+ _buff[_RELAY_SWITCH_NAME_R5] = 0x00;
|
|
|
+ ShmSmartBoxData->Dynamic4Release[_Conn].TargetRelay = _RELAY_SWITCH_NAME_R4;
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ // R4 OFF
|
|
|
+ _buff[_RELAY_SWITCH_NAME_R5] = 0x00;
|
|
|
+ ShmSmartBoxData->Dynamic4Release[_Conn].TargetRelay = _RELAY_SWITCH_NAME_R5;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ memcpy(ShmSmartBoxData->ParallelRelayStatus, _buff, sizeof(_buff));
|
|
|
+}
|
|
|
+
|
|
|
+//==========================================
|
|
|
+// Sub Processing
|
|
|
+//==========================================
|
|
|
+void Assign2ConnectorProcessing(byte _targetConn)
|
|
|
+{
|
|
|
+ // 根據現在該槍拿到的群數量, 依順去設定群的使用目標為左 /右槍
|
|
|
+ // 一旦設定該模塊目標為左 /右槍後,AssignedPwr2Connector function 會將該模塊的資訊給對應的左/右槍
|
|
|
+ for (byte aGp = 0; aGp < ShmSmartBoxData->ConnectorUsingGroupCount[_targetConn]; aGp++)
|
|
|
+ {
|
|
|
+ if (ShmPsuData->PsuGroup[ConnectorUsingSeq[_targetConn][aGp]].IsUsing == YES)
|
|
|
+ {
|
|
|
+ ShmPsuData->PsuGroup[ConnectorUsingSeq[_targetConn][aGp]].UsingTarget = _targetConn;
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+// 將_group該群的模塊配給_targetConn槍號
|
|
|
+void AddGroup2Connector(byte _targetConn, byte _group)
|
|
|
+{
|
|
|
+ ShmPsuData->PsuGroup[_group].IsUsing = YES;
|
|
|
+ if ((ShmSysConfigAndInfo->SysInfo.IsAlternatvieConf == YES && _targetConn == GUN_RIGHT) ||
|
|
|
+ (ShmDcCommonData->systemType == _SYSTEM_TYPE_STANDARD && ShmSmartBoxData->ConnectorUsingGroupCount[_targetConn] > 0))
|
|
|
+ ShmSmartBoxData->ConnectorUsingGroupCount[_targetConn] = 4;
|
|
|
+ else
|
|
|
+ ShmSmartBoxData->ConnectorUsingGroupCount[_targetConn]++;
|
|
|
+ // 對應到相對群
|
|
|
+ Assign2ConnectorProcessing(_targetConn);
|
|
|
+}
|
|
|
+
|
|
|
+// 將targetGp該群的模塊從_targetConn槍號移除
|
|
|
+bool ReleaseConnectorProcessing(byte _targetConn, byte targetGp)
|
|
|
+{
|
|
|
+ bool result = false;
|
|
|
+
|
|
|
+ if (ShmPsuData->PsuGroup[targetGp].PwSwitchStatus == _PSU_POWER_STATUS_OFF)
|
|
|
+ {
|
|
|
+ result = true;
|
|
|
+ ShmPsuData->PsuGroup[targetGp].UsingTarget = GUN_CHECK;
|
|
|
+ ShmPsuData->PsuGroup[targetGp].IsUsing = NO;
|
|
|
+ ShmSmartBoxData->ConnectorUsingGroupCount[_targetConn]--;
|
|
|
+ }
|
|
|
+
|
|
|
+ return result;
|
|
|
+}
|
|
|
+
|
|
|
+//==========================================
|
|
|
+// Fetch fork
|
|
|
+//==========================================
|
|
|
+void InitializeDynamicFetch(byte _targetConn)
|
|
|
+{
|
|
|
+ ShmSmartBoxData->Dynamic4Fetch[_targetConn].ShareGroup = NONE_GROUP_CAN_SELECTED;
|
|
|
+ ShmSmartBoxData->Dynamic4Fetch[_targetConn].TargetRelay = NONE_RELAY_SELECTED;
|
|
|
+ ShmSmartBoxData->Dynamic4Fetch[_targetConn].ShareTargetCurrent = 0;
|
|
|
+ ShmSmartBoxData->SmartChk[_targetConn].IsFetchStart = NO;
|
|
|
+}
|
|
|
+
|
|
|
+void FetchLoopProcessing(byte _targetConn)
|
|
|
+{
|
|
|
+ byte targetGroup = ShmSmartBoxData->Dynamic4Fetch[_targetConn].ShareGroup;
|
|
|
+ if (targetGroup == NONE_GROUP_CAN_SELECTED &&
|
|
|
+ ShmSmartBoxData->Dynamic4Fetch[_targetConn].FetchLoopStep >= _PSU_DYNAMIC_FETCH_STEP_TG_VOL)
|
|
|
+ {
|
|
|
+ ShmSmartBoxData->Dynamic4Fetch[_targetConn].FetchLoopStep = _PSU_DYNAMIC_FETCH_STEP_FINISH;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 用 target vol 比較好還是用當前火線電壓 ? 可以試試看~
|
|
|
+ float EvVoltage = chargingInfo[_targetConn]->EvBatterytargetVoltage * 10;
|
|
|
+
|
|
|
+ switch(ShmSmartBoxData->Dynamic4Fetch[_targetConn].FetchLoopStep)
|
|
|
+ {
|
|
|
+ case _PSU_DYNAMIC_FETCH_STEP_NONE:
|
|
|
+ case _PSU_DYNAMIC_FETCH_STEP_WAIT:{ } break;
|
|
|
+ case _PSU_DYNAMIC_FETCH_STEP_TG_VOL:
|
|
|
+ {
|
|
|
+ // 該群升壓
|
|
|
+ if (ShmPsuData->PsuGroup[targetGroup].GroupPresentOutputVoltage != 0)
|
|
|
+ {
|
|
|
+ PRINTF_FUNC("EV_ReqVoltage = %f, targetGroup = %d, Group_CurVoltage = %d \n",
|
|
|
+ EvVoltage, targetGroup, ShmPsuData->PsuGroup[targetGroup].GroupPresentOutputVoltage);
|
|
|
+ }
|
|
|
+
|
|
|
+ if (EvVoltage <= PSU_MIN_VOL)
|
|
|
+ {
|
|
|
+ PRINTF_FUNC("***** FETCH_STEP_ABORT ***** (Gun - %d) \n", _targetConn);
|
|
|
+ ShmSmartBoxData->Dynamic4Fetch[_targetConn].FetchLoopStep = _PSU_DYNAMIC_FETCH_STEP_ABORT;
|
|
|
+ }
|
|
|
+ else if (ShmPsuData->PsuGroup[targetGroup].GroupPresentOutputVoltage >= EvVoltage - PSU_TG_VOL_GAP)
|
|
|
+ {
|
|
|
+ PRINTF_FUNC("***** FETCH_STEP_RELAY ***** (Gun - %d) \n", _targetConn);
|
|
|
+ ShmPsuData->PsuGroup[targetGroup].UsingTarget = _targetConn;
|
|
|
+ ShmSmartBoxData->Dynamic4Fetch[_targetConn].FetchLoopStep = _PSU_DYNAMIC_FETCH_STEP_RELAY;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ break;
|
|
|
+ case _PSU_DYNAMIC_FETCH_STEP_RELAY:
|
|
|
+ {
|
|
|
+ // 搭上對應的 Relay
|
|
|
+ if (ShmSmartBoxData->Dynamic4Fetch[_targetConn].TargetRelay < ARRAY_SIZE(ShmSmartBoxData->ParallelRelayStatus))
|
|
|
+ {
|
|
|
+ if (ShmSmartBoxData->ParallelRelayStatus[ShmSmartBoxData->Dynamic4Fetch[_targetConn].TargetRelay] == YES)
|
|
|
+ {
|
|
|
+ if (ShmSmartBoxData->RcbParallelStatus[ShmSmartBoxData->Dynamic4Fetch[_targetConn].TargetRelay] == YES)
|
|
|
+ {
|
|
|
+ PRINTF_FUNC("***** FETCH_STEP_CUR_SHARE ***** (Gun - %d) \n", _targetConn);
|
|
|
+ ShmSmartBoxData->Dynamic4Fetch[_targetConn].FetchLoopStep = _PSU_DYNAMIC_FETCH_STEP_CUR_SHARE;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ break;
|
|
|
+ case _PSU_DYNAMIC_FETCH_STEP_CUR_SHARE:
|
|
|
+ {
|
|
|
+ // 均流 : 目標電流 = 當前電流 / (原本輸出群個數 + share group 個數)
|
|
|
+ PRINTF_FUNC("GroupPresent = %d (0.1A), ShareTarget = %d (0.1A), CurrentPresent = %.1f \n",
|
|
|
+ ShmPsuData->PsuGroup[targetGroup].GroupPresentOutputCurrent,
|
|
|
+ ShmSmartBoxData->Dynamic4Fetch[_targetConn].ShareTargetCurrent,
|
|
|
+ chargingInfo[_targetConn]->PresentChargingCurrent);
|
|
|
+
|
|
|
+ if ((ShmPsuData->PsuGroup[targetGroup].GroupPresentOutputCurrent >= ShmSmartBoxData->Dynamic4Fetch[_targetConn].ShareTargetCurrent - PSU_TG_CUR_GAP &&
|
|
|
+ ShmPsuData->PsuGroup[targetGroup].GroupPresentOutputCurrent <= ShmSmartBoxData->Dynamic4Fetch[_targetConn].ShareTargetCurrent + PSU_TG_CUR_GAP) ||
|
|
|
+ chargingInfo[_targetConn]->PresentChargingCurrent <= PSU_MIN_CUR)
|
|
|
+ {
|
|
|
+ PRINTF_FUNC("***** FETCH_STEP_WATI_FINISH ***** (Gun - %d) \n", _targetConn);
|
|
|
+ ShmSmartBoxData->Dynamic4Fetch[_targetConn].FetchLoopStep = _PSU_DYNAMIC_FETCH_STEP_WATI_FINISH;
|
|
|
+ }
|
|
|
+
|
|
|
+ }
|
|
|
+ break;
|
|
|
+ case _PSU_DYNAMIC_FETCH_STEP_WATI_FINISH:
|
|
|
+ {
|
|
|
+ AddGroup2Connector(_targetConn, targetGroup);
|
|
|
+ GetTimespecFunc(&ShmSmartBoxData->SmartChk[_targetConn].FetchLoopTime);
|
|
|
+ PRINTF_FUNC("***** FETCH_STEP_FINISH ***** (Gun - %d) \n", _targetConn);
|
|
|
+ ShmSmartBoxData->Dynamic4Fetch[_targetConn].ShareGroup = NONE_GROUP_CAN_SELECTED;
|
|
|
+ ShmSmartBoxData->Dynamic4Fetch[_targetConn].FetchLoopStep = _PSU_DYNAMIC_FETCH_STEP_FINISH;
|
|
|
+ }
|
|
|
+ break;
|
|
|
+ case _PSU_DYNAMIC_FETCH_STEP_FINISH:
|
|
|
+ {
|
|
|
+ // 完成
|
|
|
+ int _t = GetTimeoutValue(&ShmSmartBoxData->SmartChk[_targetConn].FetchLoopTime);
|
|
|
+
|
|
|
+ if (_t >= FETCH_FINISH_WAIT_TIME)
|
|
|
+ {
|
|
|
+ InitializeDynamicFetch(_targetConn);
|
|
|
+ PRINTF_FUNC("***** FETCH_STEP_NONE ***** (Gun - %d) \n", _targetConn);
|
|
|
+ ShmSmartBoxData->Dynamic4Fetch[_targetConn].FetchLoopStep = _PSU_DYNAMIC_FETCH_STEP_NONE;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ break;
|
|
|
+ case _PSU_DYNAMIC_FETCH_STEP_ABORT:
|
|
|
+ {
|
|
|
+ // 中斷
|
|
|
+ if (ShmPsuData->PsuGroup[targetGroup].IsUsing)
|
|
|
+ {
|
|
|
+ ShmPsuData->PsuGroup[targetGroup].IsUsing = NO;
|
|
|
+ ShmPsuData->PsuGroup[targetGroup].UsingTarget = GUN_CHECK;
|
|
|
+ }
|
|
|
+
|
|
|
+ GetTimespecFunc(&ShmSmartBoxData->SmartChk[_targetConn].FetchLoopTime);
|
|
|
+ ShmSmartBoxData->Dynamic4Fetch[_targetConn].FetchLoopStep = _PSU_DYNAMIC_FETCH_STEP_FINISH;
|
|
|
+ }
|
|
|
+ break;
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+byte CheckRemainPwrByConIndex(byte _targetConn)
|
|
|
+{
|
|
|
+ byte result = NONE_GROUP_CAN_SELECTED;
|
|
|
+
|
|
|
+ // 該槍已經使用的群數量
|
|
|
+ byte usingCount = ShmSmartBoxData->ConnectorUsingGroupCount[_targetConn];
|
|
|
+
|
|
|
+ for (byte Gp = usingCount; Gp < ARRAY_SIZE(ConnectorUsingSeq[_targetConn]); Gp++)
|
|
|
+ {
|
|
|
+ // 判斷是否有該槍下一個可用群的狀態
|
|
|
+ if (ShmPsuData->PsuGroup[ConnectorUsingSeq[_targetConn][Gp]].IsUsing == NO &&
|
|
|
+ ShmPsuData->PsuGroup[ConnectorUsingSeq[_targetConn][Gp]].GroupPresentPsuQuantity > 0)
|
|
|
+ {
|
|
|
+ result = ConnectorUsingSeq[_targetConn][Gp];
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ return result;
|
|
|
+}
|
|
|
+
|
|
|
+void Chk2StopFetchStep(byte _targetConn)
|
|
|
+{
|
|
|
+ // 開始流程後,就讓流程走完吧~
|
|
|
+ if (ShmSmartBoxData->Dynamic4Fetch[_targetConn].FetchLoopStep > _PSU_DYNAMIC_FETCH_STEP_NONE &&
|
|
|
+ ShmSmartBoxData->Dynamic4Fetch[_targetConn].FetchLoopStep < _PSU_DYNAMIC_FETCH_STEP_TG_VOL)
|
|
|
+ {
|
|
|
+ PRINTF_FUNC("***** FETCH_STEP_ABORT ***** (Gun - %d) \n", _targetConn);
|
|
|
+ ShmSmartBoxData->Dynamic4Fetch[_targetConn].FetchLoopStep = _PSU_DYNAMIC_FETCH_STEP_ABORT;
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+void FetchFork()
|
|
|
+{
|
|
|
+ pid_t fetchPid;
|
|
|
+
|
|
|
+ fetchPid = fork();
|
|
|
+
|
|
|
+ if(fetchPid > 0)
|
|
|
+ {
|
|
|
+ bool isPass = false;
|
|
|
+ struct ChargingInfoData *_chargingData[CHAdeMO_QUANTITY + CCS_QUANTITY + GB_QUANTITY];
|
|
|
+
|
|
|
+ while(!isPass)
|
|
|
+ {
|
|
|
+ isPass = true;
|
|
|
+ for (byte _index = 0; _index < ShmSysConfigAndInfo->SysConfig.TotalConnectorCount; _index++)
|
|
|
+ {
|
|
|
+ if (!FindChargingInfoData(_index, &_chargingData[0]))
|
|
|
+ {
|
|
|
+ DEBUG_ERROR("Smartbox (FetchFork) : FindChargingInfoData false \n");
|
|
|
+ isPass = false;
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ sleep(1);
|
|
|
+ }
|
|
|
+
|
|
|
+ while(1)
|
|
|
+ {
|
|
|
+ for (byte gun_index = 0; gun_index < ShmSysConfigAndInfo->SysConfig.TotalConnectorCount; gun_index++)
|
|
|
+ {
|
|
|
+ if (chargingInfo[gun_index]->SystemStatus == SYS_MODE_IDLE ||
|
|
|
+ chargingInfo[gun_index]->SystemStatus == SYS_MODE_RESERVATION ||
|
|
|
+ chargingInfo[gun_index]->SystemStatus == SYS_MODE_MAINTAIN ||
|
|
|
+ chargingInfo[gun_index]->SystemStatus == SYS_MODE_FAULT)
|
|
|
+ {
|
|
|
+ ShmSmartBoxData->ConnectorStatus[gun_index].NeedToFetch = NO;
|
|
|
+
|
|
|
+ if (ShmSmartBoxData->ConnectorStatus[gun_index].ConnectorStaus != _CONNECTOR_STATUS_NONE)
|
|
|
+ ShmSmartBoxData->ConnectorStatus[gun_index].ConnectorStaus = _CONNECTOR_STATUS_NONE;
|
|
|
+ }
|
|
|
+ // 對充電邏輯來說,充電槍只提需求
|
|
|
+ else if (chargingInfo[gun_index]->SystemStatus >= SYS_MODE_MODE_REASSIGN_CHECK &&
|
|
|
+ chargingInfo[gun_index]->SystemStatus <= SYS_MODE_REASSIGN)
|
|
|
+ {
|
|
|
+ // 判斷該群是否被使用中
|
|
|
+ if (ShmPsuData->PsuGroup[gun_index].IsUsing)
|
|
|
+ {
|
|
|
+ // 如果使用中 : 等待把這顆模塊切出
|
|
|
+ ShmSmartBoxData->ConnectorStatus[gun_index].ConnectorStaus = _CONNECTOR_STATUS_WAIT;
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ // 直接同意該群後輸出
|
|
|
+ InitializeDynamicFetch(gun_index);
|
|
|
+ ShmSmartBoxData->ConnectorStatus[gun_index].ConnectorStaus = _CONNECTOR_STATUS_USING;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ else if (chargingInfo[gun_index]->SystemStatus == SYS_MODE_PREPARING)
|
|
|
+ {
|
|
|
+ // 這個階段只會拿到屬於該槍的模塊群
|
|
|
+ if (ShmSysConfigAndInfo->SysInfo.IsAlternatvieConf == YES && gun_index == GUN_RIGHT)
|
|
|
+ {
|
|
|
+ // 壁掛 : 強制使用第零群
|
|
|
+ AddGroup2Connector(gun_index, _PSU_GROUP_INDEX_0);
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ if (!ShmPsuData->PsuGroup[gun_index].IsUsing)
|
|
|
+ {
|
|
|
+ // 第一個 : Gun index
|
|
|
+ // 第二個 : Psu Group index
|
|
|
+ AddGroup2Connector(gun_index, gun_index);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ else if (chargingInfo[gun_index]->SystemStatus == SYS_MODE_CHARGING)
|
|
|
+ {
|
|
|
+ // 如果當前輸出接近實際可提供的能量 (距離 <= CAP_GAP_FETCH <3KW>)
|
|
|
+ // 不取 EvBatterytargetVoltage 原因是小板會將該值做不同的處理方式
|
|
|
+ float needPower = chargingInfo[gun_index]->PresentChargingVoltage *
|
|
|
+ chargingInfo[gun_index]->EvBatterytargetCurrent / 100;
|
|
|
+ // 判斷是否可以及需要提供多餘群輸出
|
|
|
+ byte chkRemainGp = NONE_GROUP_CAN_SELECTED;
|
|
|
+
|
|
|
+ if (ShmSmartBoxData->Dynamic4Fetch[gun_index].ShareGroup == NONE_GROUP_CAN_SELECTED)
|
|
|
+ chkRemainGp = CheckRemainPwrByConIndex(gun_index);
|
|
|
+ else
|
|
|
+ chkRemainGp = ShmSmartBoxData->Dynamic4Fetch[gun_index].ShareGroup;
|
|
|
+
|
|
|
+ ShmSmartBoxData->ConnectorStatus[gun_index].NeedToFetch =
|
|
|
+ (needPower > 0 && needPower >= chargingInfo[gun_index]->RealRatingPower - CAP_GAP_FETCH) ? true : false;
|
|
|
+
|
|
|
+ if (ShmDcCommonData->systemType != _SYSTEM_TYPE_SIMPLE &&
|
|
|
+ ShmSmartBoxData->Dynamic4Release[gun_index].ReleaseLoopStep == _PSU_DYNAMIC_RELEASE_STEP_NONE &&
|
|
|
+ ((ShmSmartBoxData->ConnectorStatus[gun_index].NeedToFetch &&
|
|
|
+ chkRemainGp != NONE_GROUP_CAN_SELECTED &&
|
|
|
+ ShmSmartBoxData->Dynamic4Fetch[gun_index].FetchLoopStep <= _PSU_DYNAMIC_FETCH_STEP_WAIT) ||
|
|
|
+ ShmDcCommonData->smartFetchRun[gun_index])
|
|
|
+ )
|
|
|
+ {
|
|
|
+ if (!ShmSmartBoxData->SmartChk[gun_index].IsFetchStart)
|
|
|
+ {
|
|
|
+ // 判斷是否可以及需要提供多餘群輸出
|
|
|
+ PRINTF_FUNC("Fetch Target = %d, Target Group = %d \n", gun_index, chkRemainGp);
|
|
|
+ // 鎖定目標群,動態分配開始
|
|
|
+ // 該群模塊即被鎖定, 預防另外一群也進入相同邏輯,預防搶同一個群的情形
|
|
|
+ ShmPsuData->PsuGroup[chkRemainGp].IsUsing = YES;
|
|
|
+
|
|
|
+ ShmSmartBoxData->Dynamic4Fetch[gun_index].ShareGroup = chkRemainGp;
|
|
|
+ PRINTF_FUNC("***** FETCH_STEP_WAIT ***** (Gun - %d) \n", gun_index);
|
|
|
+ ShmSmartBoxData->Dynamic4Fetch[gun_index].FetchLoopStep = _PSU_DYNAMIC_FETCH_STEP_WAIT;
|
|
|
+
|
|
|
+ // 倒數進入動態分配邏輯 - Fetch loop
|
|
|
+ ShmSmartBoxData->SmartChk [gun_index].IsFetchStart = YES;
|
|
|
+ // 條件成立, 倒數 FETCH_SMART_CHK_TIME <5s>
|
|
|
+ GetTimespecFunc(&ShmSmartBoxData->SmartChk[gun_index].FetchLoopTime);
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ if (ShmSmartBoxData->Dynamic4Fetch[gun_index].FetchLoopStep == _PSU_DYNAMIC_FETCH_STEP_WAIT)
|
|
|
+ {
|
|
|
+ int _t = GetTimeoutValue(&ShmSmartBoxData->SmartChk[gun_index].FetchLoopTime);
|
|
|
+
|
|
|
+ if (_t >= FETCH_SMART_CHK_TIME)
|
|
|
+ {
|
|
|
+ PRINTF_FUNC("***** FETCH_STEP_TG_VOL ***** (Gun - %d) \n", gun_index);
|
|
|
+ ShmSmartBoxData->Dynamic4Fetch[gun_index].FetchLoopStep = _PSU_DYNAMIC_FETCH_STEP_TG_VOL;
|
|
|
+
|
|
|
+ ShmDcCommonData->smartFetchRun[gun_index] = NO;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ // 動態分配條件中斷
|
|
|
+ Chk2StopFetchStep(gun_index);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ FetchLoopProcessing(gun_index);
|
|
|
+ }
|
|
|
+
|
|
|
+ usleep(200000);
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+//==========================================
|
|
|
+// Release fork
|
|
|
+//==========================================
|
|
|
+void InitializeDynamicRelease(byte _targetConn)
|
|
|
+{
|
|
|
+ ShmSmartBoxData->Dynamic4Release[_targetConn].ReleaseGroup = NONE_GROUP_CAN_SELECTED;
|
|
|
+ ShmSmartBoxData->Dynamic4Release[_targetConn].TargetRelay = NONE_RELAY_SELECTED;
|
|
|
+ ShmSmartBoxData->Dynamic4Release[_targetConn].LimitCurCap = 0;
|
|
|
+ ShmSmartBoxData->Dynamic4Release[_targetConn].LimitPwrCap = 0;
|
|
|
+ ShmSmartBoxData->Dynamic4Release[_targetConn].LimitCur = 0;
|
|
|
+ ShmSmartBoxData->Dynamic4Release[_targetConn].LimitPwr = 0;
|
|
|
+ ShmSmartBoxData->Dynamic4Release[_targetConn].ReleaseLoopStep = _PSU_DYNAMIC_FETCH_STEP_FINISH;
|
|
|
+}
|
|
|
+
|
|
|
+byte CheckReleasePwrByConIndex(byte _targetConn)
|
|
|
+{
|
|
|
+ byte result = NONE_GROUP_CAN_SELECTED;
|
|
|
+
|
|
|
+ // 該槍已經使用的群數量
|
|
|
+ byte usingCount = ShmSmartBoxData->ConnectorUsingGroupCount[_targetConn];
|
|
|
+
|
|
|
+ // 不可把最後一個也拿來釋放
|
|
|
+ if (usingCount - 1 > 0)
|
|
|
+ result = ConnectorUsingSeq[_targetConn][usingCount - 1];
|
|
|
+
|
|
|
+ return result;
|
|
|
+}
|
|
|
+
|
|
|
+void ReleaseLoopProcessing(byte _targetConn)
|
|
|
+{
|
|
|
+ byte targetGroup = ShmSmartBoxData->Dynamic4Release[_targetConn].ReleaseGroup;
|
|
|
+
|
|
|
+ switch(ShmSmartBoxData->Dynamic4Release[_targetConn].ReleaseLoopStep)
|
|
|
+ {
|
|
|
+ case _PSU_DYNAMIC_RELEASE_STEP_NONE:
|
|
|
+ case _PSU_DYNAMIC_RELEASE_STEP_WAIT: {} break;
|
|
|
+ case _PSU_DYNAMIC_RELEASE_STEP_LIMIT:
|
|
|
+ {
|
|
|
+ // 應該要通知可輸出的能量與電流
|
|
|
+// PRINTF_FUNC("_targetConn = %d, LimitCurCap = %.1f, LimitPwrCap = %.1f \n",
|
|
|
+// _targetConn,
|
|
|
+// ShmSmartBoxData->Dynamic4Release[_targetConn].LimitCurCap,
|
|
|
+// ShmSmartBoxData->Dynamic4Release[_targetConn].LimitPwrCap);
|
|
|
+
|
|
|
+ // 通知可輸出的能量與電流
|
|
|
+// PRINTF_FUNC("_targetConn = %d, LimitCur = %.1f, LimitPwr = %.1f \n",
|
|
|
+// _targetConn,
|
|
|
+// ShmSmartBoxData->Dynamic4Release[_targetConn].LimitCur,
|
|
|
+// ShmSmartBoxData->Dynamic4Release[_targetConn].LimitPwr);
|
|
|
+
|
|
|
+ // 需求能量與電流
|
|
|
+// PRINTF_FUNC("_targetConn = %d, Req Power = %.1f (kw), Req Vol. = %.1f, Req Cur. = %.1f, Present Cur = %.1f \n",
|
|
|
+// _targetConn,
|
|
|
+// (chargingInfo[_targetConn]->EvBatterytargetVoltage * chargingInfo[_targetConn]->EvBatterytargetCurrent) / 100,
|
|
|
+// chargingInfo[_targetConn]->EvBatterytargetVoltage,
|
|
|
+// chargingInfo[_targetConn]->EvBatterytargetCurrent,
|
|
|
+// chargingInfo[_targetConn]->PresentChargingCurrent);
|
|
|
+
|
|
|
+ // if the current and power limits are below their capacity
|
|
|
+ if ((ShmSmartBoxData->Dynamic4Release[_targetConn].LimitCur <= ShmSmartBoxData->Dynamic4Release[_targetConn].LimitCurCap &&
|
|
|
+ ShmSmartBoxData->Dynamic4Release[_targetConn].LimitPwr <= ShmSmartBoxData->Dynamic4Release[_targetConn].LimitPwrCap) ||
|
|
|
+ chargingInfo[_targetConn]->PresentChargingCurrent * 10 <= PSU_LIMIT_CUR)
|
|
|
+ {
|
|
|
+ PRINTF_FUNC("***** RELEASE_STEP_PWROFF ***** (Gun - %d) \n", _targetConn);
|
|
|
+ ShmSmartBoxData->Dynamic4Release[_targetConn].ReleaseLoopStep = _PSU_DYNAMIC_RELEASE_STEP_PWROFF;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ break;
|
|
|
+ case _PSU_DYNAMIC_RELEASE_STEP_PWROFF:
|
|
|
+ {
|
|
|
+// PRINTF_FUNC("targetGroup = %d, PresentChargingCurrent = %.1f, LimitCur = %.1f \n",
|
|
|
+// _targetConn,
|
|
|
+// chargingInfo[_targetConn]->PresentChargingCurrent,
|
|
|
+// ShmSmartBoxData->Dynamic4Release[_targetConn].LimitCur / 10);
|
|
|
+
|
|
|
+ // if the output current is below their capacity for 5s
|
|
|
+ int _t = GetTimeoutValue(&ShmSmartBoxData->SmartChk[_targetConn].ReleaseLoopTime);
|
|
|
+
|
|
|
+ if (chargingInfo[_targetConn]->PresentChargingCurrent <=
|
|
|
+ ShmSmartBoxData->Dynamic4Release[_targetConn].LimitCur &&
|
|
|
+ _t >= WAIT_FOR_LIMIT_STABLE)
|
|
|
+ {
|
|
|
+ PRINTF_FUNC("***** RELEASE_STEP_RELAYOFF ***** (Gun - %d) \n", _targetConn);
|
|
|
+ ShmSmartBoxData->Dynamic4Release[_targetConn].ReleaseLoopStep = _PSU_DYNAMIC_RELEASE_STEP_RELAYOFF;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ break;
|
|
|
+ case _PSU_DYNAMIC_RELEASE_STEP_RELAYOFF:
|
|
|
+ {
|
|
|
+ // 釋放對應的 Relay
|
|
|
+ PRINTF_FUNC("TargetRelay (%d), targetGroup = %d, ParallelRelayStatus = (%d), RcbParallelStatus = (%d) \n",
|
|
|
+ ShmSmartBoxData->Dynamic4Release[_targetConn].TargetRelay, targetGroup,
|
|
|
+ ShmSmartBoxData->ParallelRelayStatus[ShmSmartBoxData->Dynamic4Release[_targetConn].TargetRelay],
|
|
|
+ ShmSmartBoxData->RcbParallelStatus[ShmSmartBoxData->Dynamic4Release[_targetConn].TargetRelay]);
|
|
|
+
|
|
|
+ if (ShmSmartBoxData->Dynamic4Release[_targetConn].TargetRelay < ARRAY_SIZE(ShmSmartBoxData->ParallelRelayStatus))
|
|
|
+ {
|
|
|
+ if (ShmSmartBoxData->ParallelRelayStatus[ShmSmartBoxData->Dynamic4Release[_targetConn].TargetRelay] == NO)
|
|
|
+ {
|
|
|
+ if (ShmSmartBoxData->RcbParallelStatus[ShmSmartBoxData->Dynamic4Release[_targetConn].TargetRelay] == NO)
|
|
|
+ {
|
|
|
+ PRINTF_FUNC("***** RELEASE_STEP_WATI_FINISH ***** (Gun - %d) \n", _targetConn);
|
|
|
+ ShmSmartBoxData->Dynamic4Release[_targetConn].ReleaseLoopStep = _PSU_DYNAMIC_RELEASE_STEP_WAIT_FINISH;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ break;
|
|
|
+ case _PSU_DYNAMIC_RELEASE_STEP_WAIT_FINISH:
|
|
|
+ {
|
|
|
+ if(ReleaseConnectorProcessing(_targetConn, targetGroup))
|
|
|
+ {
|
|
|
+ GetTimespecFunc ( & ShmSmartBoxData->SmartChk [_targetConn].ReleaseLoopTime );
|
|
|
+ PRINTF_FUNC("***** RELEASE_STEP_FINISH ***** (Gun - %d) \n", _targetConn);
|
|
|
+ InitializeDynamicRelease(_targetConn);
|
|
|
+ ShmSmartBoxData->Dynamic4Release[_targetConn].ReleaseLoopStep = _PSU_DYNAMIC_RELEASE_STEP_FINISH;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ break;
|
|
|
+ case _PSU_DYNAMIC_RELEASE_STEP_FINISH:
|
|
|
+ {
|
|
|
+ // 完成
|
|
|
+ int _t = GetTimeoutValue(&ShmSmartBoxData->SmartChk[_targetConn].ReleaseLoopTime);
|
|
|
+
|
|
|
+ if (_t >= RELEASE_FINISH_WAIT_TIME)
|
|
|
+ {
|
|
|
+ PRINTF_FUNC("***** RELEASE_STEP_NONE ***** (Gun - %d) \n", _targetConn);
|
|
|
+ ShmSmartBoxData->SmartChk[_targetConn].IsReleaseStart = NO;
|
|
|
+ ShmSmartBoxData->Dynamic4Release[_targetConn].ReleaseLoopStep = _PSU_DYNAMIC_RELEASE_STEP_NONE;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ break;
|
|
|
+ case _PSU_DYNAMIC_RELEASE_STEP_ABORT:
|
|
|
+ {
|
|
|
+ GetTimespecFunc(& ShmSmartBoxData->SmartChk [_targetConn].ReleaseLoopTime);
|
|
|
+ PRINTF_FUNC("***** RELEASE_STEP_FINISH ***** (Gun - %d) \n", _targetConn);
|
|
|
+ InitializeDynamicRelease(_targetConn);
|
|
|
+ ShmSmartBoxData->Dynamic4Release[_targetConn].ReleaseLoopStep = _PSU_DYNAMIC_RELEASE_STEP_FINISH;
|
|
|
+ }
|
|
|
+ break;
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+void Chk2StopReleaseStep(byte _targetConn)
|
|
|
+{
|
|
|
+ // 開始流程後,就讓流程走完吧~
|
|
|
+ if (ShmSmartBoxData->Dynamic4Release [_targetConn].ReleaseGroup > _PSU_DYNAMIC_RELEASE_STEP_NONE &&
|
|
|
+ ShmSmartBoxData->Dynamic4Release [_targetConn].ReleaseGroup < _PSU_DYNAMIC_RELEASE_STEP_LIMIT)
|
|
|
+ {
|
|
|
+ PRINTF_FUNC ( "***** RELEASE_STEP_ABORT ***** (Gun - %d) \n", _targetConn );
|
|
|
+ //ShmSmartBoxData->Dynamic4Release [_targetConn].ReleaseGroup = _PSU_DYNAMIC_RELEASE_STEP_ABORT;
|
|
|
+ }
|
|
|
+ else
|
|
|
+ ShmSmartBoxData->SmartChk[_targetConn].IsReleaseStart = NO;
|
|
|
+}
|
|
|
+
|
|
|
+void ReleaseFork()
|
|
|
+{
|
|
|
+ pid_t releasePid;
|
|
|
+
|
|
|
+ releasePid = fork();
|
|
|
+
|
|
|
+ if(releasePid > 0)
|
|
|
+ {
|
|
|
+ bool isPass = false;
|
|
|
+ struct ChargingInfoData *_chargingData[CHAdeMO_QUANTITY + CCS_QUANTITY + GB_QUANTITY];
|
|
|
+
|
|
|
+ while(!isPass)
|
|
|
+ {
|
|
|
+ isPass = true;
|
|
|
+ for (byte _index = 0; _index < ShmSysConfigAndInfo->SysConfig.TotalConnectorCount; _index++)
|
|
|
+ {
|
|
|
+ if (!FindChargingInfoData(_index, &_chargingData[0]))
|
|
|
+ {
|
|
|
+ DEBUG_ERROR("Smartbox (ReleaseFork) : FindChargingInfoData false \n");
|
|
|
+ isPass = false;
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ sleep(1);
|
|
|
+ }
|
|
|
+
|
|
|
+ while(1)
|
|
|
+ {
|
|
|
+ for (byte gun_index = 0; gun_index < ShmSysConfigAndInfo->SysConfig.TotalConnectorCount; gun_index++)
|
|
|
+ {
|
|
|
+ if (chargingInfo[gun_index]->SystemStatus == SYS_MODE_CHARGING)
|
|
|
+ {
|
|
|
+ // 釋出多餘群 : 要判斷所要釋出群所能提供的最大能量 RealRatingPower
|
|
|
+ // 先找到是否有下一個要釋出的群
|
|
|
+ byte releaseGp = CheckReleasePwrByConIndex(gun_index);
|
|
|
+ if (releaseGp != NONE_GROUP_CAN_SELECTED)
|
|
|
+ {
|
|
|
+ unsigned short releasePwr = ShmPsuData->PsuGroup[releaseGp].TotalRatingPower * 10;
|
|
|
+ float needPower = chargingInfo[gun_index]->PresentChargingVoltage *
|
|
|
+ chargingInfo[gun_index]->EvBatterytargetCurrent / 100;
|
|
|
+
|
|
|
+ if (chargingInfo[gun_index]->Type != _Type_Test &&
|
|
|
+ ShmSmartBoxData->Dynamic4Fetch[gun_index].FetchLoopStep == _PSU_DYNAMIC_FETCH_STEP_NONE &&
|
|
|
+ (ShmSmartBoxData->AnotherConnectorStatus[gun_index].ConnectorStaus == _CONNECTOR_STATUS_WAIT ||
|
|
|
+ (ShmSmartBoxData->AnotherConnectorStatus[gun_index].NeedToFetch &&
|
|
|
+ SMART_MODE && chargingInfo[gun_index]->_TakePsuGpCount > ShmDcCommonData->halfGroupCount) ||
|
|
|
+ (chargingInfo[gun_index]->RealRatingPower > 0 && releasePwr > 0 &&
|
|
|
+ needPower < chargingInfo[gun_index]->RealRatingPower - releasePwr - CAP_GAP_RELEASE) ||
|
|
|
+ ShmDcCommonData->smartReleaseRun[gun_index])
|
|
|
+ )
|
|
|
+ {
|
|
|
+ //PRINTF_FUNC("RealRatingPower = %d \n", chargingInfo[gun_index]->RealRatingPower);
|
|
|
+ //PRINTF_FUNC("releasePwr = %d, needPower = %f \n", releasePwr, needPower);
|
|
|
+
|
|
|
+ if (ShmSmartBoxData->Dynamic4Release[gun_index].ReleaseLoopStep == _PSU_DYNAMIC_RELEASE_STEP_NONE)
|
|
|
+ {
|
|
|
+ if (!ShmSmartBoxData->SmartChk[gun_index].IsReleaseStart)
|
|
|
+ {
|
|
|
+ PRINTF_FUNC("***** Entry release chk (Gun_%d).. ***** \n", gun_index);
|
|
|
+ ShmSmartBoxData->SmartChk[gun_index].IsReleaseStart = YES;
|
|
|
+ ShmSmartBoxData->Dynamic4Release[gun_index].CheckOutPwrIsStable = chargingInfo[gun_index]->PresentChargingPower;
|
|
|
+ GetTimespecFunc(&ShmSmartBoxData->SmartChk[gun_index].ReleaseLoopTime);
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ int _delayt = GetTimeoutValue(&ShmSmartBoxData->SmartChk[gun_index].ReleaseLoopTime);
|
|
|
+
|
|
|
+ // 每五秒看一次輸出能量是否穩定, 穩定則進入分配
|
|
|
+ if (_delayt >= RELEASE_STABLE_CHK_TIME)
|
|
|
+ {
|
|
|
+ if (chargingInfo[gun_index]->PresentChargingPower >
|
|
|
+ ShmSmartBoxData->Dynamic4Release[gun_index].CheckOutPwrIsStable + STABLE_CAP_GAP)
|
|
|
+ {
|
|
|
+ ShmSmartBoxData->Dynamic4Release[gun_index].CheckOutPwrIsStable = chargingInfo[gun_index]->PresentChargingPower;
|
|
|
+ GetTimespecFunc(&ShmSmartBoxData->SmartChk[gun_index].ReleaseLoopTime);
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ // 進入穩定
|
|
|
+ PRINTF_FUNC("***** RELEASE_STEP_WAIT ***** \n");
|
|
|
+ ShmSmartBoxData->Dynamic4Release[gun_index].ReleaseLoopStep = _PSU_DYNAMIC_RELEASE_STEP_WAIT;
|
|
|
+ GetTimespecFunc(&ShmSmartBoxData->SmartChk[gun_index].ReleaseLoopTime);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ else if (ShmSmartBoxData->Dynamic4Release[gun_index].ReleaseLoopStep == _PSU_DYNAMIC_RELEASE_STEP_WAIT)
|
|
|
+ {
|
|
|
+ int _delayt = GetTimeoutValue(&ShmSmartBoxData->SmartChk[gun_index].ReleaseLoopTime);
|
|
|
+
|
|
|
+ // 每五秒看一次輸出能量是否穩定, 穩定則進入分配
|
|
|
+ if (_delayt >= RELEASE_SMART_CHK_TIME)
|
|
|
+ {
|
|
|
+ PRINTF_FUNC("***** RELEASE_STEP_LIMIT ***** \n");
|
|
|
+ ShmSmartBoxData->Dynamic4Release[gun_index].ReleaseGroup = releaseGp;
|
|
|
+ ShmSmartBoxData->Dynamic4Release[gun_index].ReleaseLoopStep = _PSU_DYNAMIC_RELEASE_STEP_LIMIT;
|
|
|
+ ShmDcCommonData->smartReleaseRun[gun_index] = NO;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ // 動態分配條件中斷
|
|
|
+ Chk2StopReleaseStep(gun_index);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ else if (chargingInfo[gun_index]->SystemStatus == SYS_MODE_IDLE ||
|
|
|
+ chargingInfo[gun_index]->SystemStatus == SYS_MODE_FAULT ||
|
|
|
+ chargingInfo[gun_index]->SystemStatus == SYS_MODE_RESERVATION ||
|
|
|
+ (chargingInfo[gun_index]->SystemStatus >= SYS_MODE_TERMINATING &&
|
|
|
+ chargingInfo[gun_index]->SystemStatus <= SYS_MODE_ALARM))
|
|
|
+ {
|
|
|
+ if (ShmSmartBoxData->ConnectorStatus[gun_index].ConnectorStaus == _CONNECTOR_STATUS_NONE)
|
|
|
+ {
|
|
|
+ byte totoalUsingGpCount = ShmSmartBoxData->ConnectorUsingGroupCount[gun_index];
|
|
|
+
|
|
|
+ for (byte _gp = 0; _gp < totoalUsingGpCount; _gp++)
|
|
|
+ {
|
|
|
+ PRINTF_FUNC("ConnectorUsingSeq[%d][%d] = %d \n", gun_index, _gp, ConnectorUsingSeq[gun_index][_gp]);
|
|
|
+ ReleaseConnectorProcessing(gun_index, ConnectorUsingSeq[gun_index][_gp]);
|
|
|
+ }
|
|
|
+
|
|
|
+ if (ShmSmartBoxData->Dynamic4Fetch[gun_index].ShareGroup != NONE_GROUP_CAN_SELECTED &&
|
|
|
+ ShmSmartBoxData->Dynamic4Fetch[gun_index].FetchLoopStep < _PSU_DYNAMIC_FETCH_STEP_FINISH)
|
|
|
+ ShmSmartBoxData->Dynamic4Fetch[gun_index].FetchLoopStep = _PSU_DYNAMIC_FETCH_STEP_ABORT;
|
|
|
+
|
|
|
+ ShmSmartBoxData->Dynamic4Release[gun_index].ReleaseLoopStep = _PSU_DYNAMIC_RELEASE_STEP_NONE;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (ShmSmartBoxData->ConnectorStatus[gun_index].NeedToFetch)
|
|
|
+ ShmSmartBoxData->ConnectorStatus[gun_index].NeedToFetch = NO;
|
|
|
+ }
|
|
|
+
|
|
|
+ ReleaseLoopProcessing(gun_index);
|
|
|
+ }
|
|
|
+
|
|
|
+ usleep(200000);
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+//==========================================
|
|
|
+// Main Function
|
|
|
+//==========================================
|
|
|
+void TakeAnotherGunStatus(byte target)
|
|
|
+{
|
|
|
+ byte another = 0;
|
|
|
+
|
|
|
+ if (target == 0)
|
|
|
+ another = 1;
|
|
|
+
|
|
|
+ ShmSmartBoxData->AnotherConnectorStatus[another].ConnectorStaus = ShmSmartBoxData->ConnectorStatus[target].ConnectorStaus;
|
|
|
+ ShmSmartBoxData->AnotherConnectorStatus[another].NeedToFetch = ShmSmartBoxData->ConnectorStatus[target].NeedToFetch;
|
|
|
+}
|
|
|
+
|
|
|
+void AssignedPwr2Connector()
|
|
|
+{
|
|
|
+ for(byte _gun = 0; _gun < ShmSysConfigAndInfo->SysConfig.TotalConnectorCount; _gun++)
|
|
|
+ {
|
|
|
+ byte usingGroupCount = 0;
|
|
|
+ float availablePwr = 0, availableCur = 0, iAvailableCur = 0, totalPsuCount = 0, kwAvailablePwr = 0;
|
|
|
+ float outputVol = 0, outputCur = 0;
|
|
|
+ float limitCur = 0, limitPwr = 0;
|
|
|
+
|
|
|
+ for (byte group = 0; group < ShmPsuData->GroupCount; group++)
|
|
|
+ {
|
|
|
+ if (ShmPsuData->PsuGroup[group].UsingTarget == _gun)
|
|
|
+ {
|
|
|
+ usingGroupCount++;
|
|
|
+ if (group != ShmSmartBoxData->Dynamic4Fetch[_gun].ShareGroup &&
|
|
|
+ (group != ShmSmartBoxData->Dynamic4Release[_gun].ReleaseGroup ||
|
|
|
+ ShmSmartBoxData->Dynamic4Release[_gun].ReleaseLoopStep <= _PSU_DYNAMIC_RELEASE_STEP_WAIT_FINISH))
|
|
|
+ {
|
|
|
+ availablePwr += ShmPsuData->PsuGroup[group].GroupAvailablePower;
|
|
|
+ availableCur += ShmPsuData->PsuGroup[group].GroupAvailableCurrent;
|
|
|
+ iAvailableCur += ShmPsuData->PsuGroup[group].TotalIAvailableCurrent;
|
|
|
+ totalPsuCount += ShmPsuData->PsuGroup[group].GroupPresentPsuQuantity;
|
|
|
+ if (ShmPsuData->PsuGroup[group].TotalRatingPower <= 15 ||
|
|
|
+ ShmPsuData->PsuGroup[group].TotalRatingPower > 30)
|
|
|
+ kwAvailablePwr += (ShmPsuData->PsuGroup[group].GroupAvailablePower) / 10;
|
|
|
+ else
|
|
|
+ kwAvailablePwr += ShmPsuData->PsuGroup[group].TotalRatingPower;
|
|
|
+ }
|
|
|
+
|
|
|
+ // Release Loop 用 : 實際上~ 電流會飄 ....
|
|
|
+ // 這段, 只取還要留住的模塊輸出電流與能量就好
|
|
|
+ if (group != ShmSmartBoxData->Dynamic4Release[_gun].ReleaseGroup &&
|
|
|
+ ShmSmartBoxData->Dynamic4Release[_gun].ReleaseLoopStep == _PSU_DYNAMIC_RELEASE_STEP_LIMIT)
|
|
|
+ {
|
|
|
+ limitCur += ShmPsuData->PsuGroup[group].GroupTargetOutputCurrent;
|
|
|
+ limitPwr += ShmPsuData->PsuGroup[group].TotalRatingPower;
|
|
|
+ }
|
|
|
+
|
|
|
+ outputCur += ShmPsuData->PsuGroup[group].GroupPresentOutputCurrent;
|
|
|
+
|
|
|
+ if (outputVol < ShmPsuData->PsuGroup[group].GroupPresentOutputVoltage ||
|
|
|
+ outputVol == 0)
|
|
|
+ outputVol = ShmPsuData->PsuGroup[group].GroupPresentOutputVoltage;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ chargingInfo[_gun]->AvailableChargingPower = availablePwr;
|
|
|
+ chargingInfo[_gun]->AvailableChargingCurrent = availableCur;
|
|
|
+ chargingInfo[_gun]->DeratingChargingCurrent = iAvailableCur;
|
|
|
+ chargingInfo[_gun]->_TotalPsuCount = totalPsuCount;
|
|
|
+ chargingInfo[_gun]->PresentChargingVoltage = outputVol / 10;
|
|
|
+ chargingInfo[_gun]->PresentChargingCurrent = outputCur / 10;
|
|
|
+ chargingInfo[_gun]->RealRatingPower = kwAvailablePwr * 10;
|
|
|
+ chargingInfo[_gun]->_TakePsuGpCount = usingGroupCount;
|
|
|
+
|
|
|
+ // 雙槍需要記得另外一把槍的狀態
|
|
|
+ if (ShmSysConfigAndInfo->SysConfig.TotalConnectorCount > 1)
|
|
|
+ TakeAnotherGunStatus(_gun);
|
|
|
+
|
|
|
+ // 取 Release group 的最大電流
|
|
|
+ if (ShmSmartBoxData->Dynamic4Release[_gun].ReleaseLoopStep == _PSU_DYNAMIC_RELEASE_STEP_LIMIT)
|
|
|
+ {
|
|
|
+ ShmSmartBoxData->Dynamic4Release[_gun].LimitCurCap = limitCur;
|
|
|
+ ShmSmartBoxData->Dynamic4Release[_gun].LimitPwrCap = limitPwr * 10;
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+void CollectGroupInformation(byte group)
|
|
|
+{
|
|
|
+ int _groupPower = 0 , _groupCurrent = 0 , _groupMaxVoltage = 0;
|
|
|
+ int Iavail = 0, Pavail = 0;
|
|
|
+ unsigned short _outputVolBuf = 0, _outputCurBuf = 0;
|
|
|
+
|
|
|
+ for (byte index = 0; index < ShmPsuData->PsuGroup[group].GroupPresentPsuQuantity; index ++)
|
|
|
+ {
|
|
|
+ // Cap
|
|
|
+ _groupCurrent += ShmPsuData->PsuGroup[group].PsuModule[index].AvailableCurrent;
|
|
|
+ _groupPower += ShmPsuData->PsuGroup[group].PsuModule[index].AvailablePower;
|
|
|
+
|
|
|
+ if (ShmPsuData->PsuGroup[group].PsuModule[index].PresentMaxOutputVoltage > _groupMaxVoltage)
|
|
|
+ _groupMaxVoltage = ShmPsuData->PsuGroup[group].PsuModule[index].PresentMaxOutputVoltage;
|
|
|
+
|
|
|
+ // Iavailable
|
|
|
+ Iavail += ShmPsuData->PsuGroup[group].PsuModule[index].IAvailableCurrent;
|
|
|
+ Pavail += ShmPsuData->PsuGroup[group].PsuModule[index].KwAvailablePower;
|
|
|
+
|
|
|
+ // output
|
|
|
+ _outputCurBuf += ShmPsuData->PsuGroup[group].PsuModule[index].PresentOutputCurrent;
|
|
|
+
|
|
|
+ if (_outputVolBuf == 0 ||
|
|
|
+ (ShmPsuData->PsuGroup[group].PsuModule[index].PresentOutputVoltage > PSU_MIN_VOL &&
|
|
|
+ _outputVolBuf < ShmPsuData->PsuGroup[group].PsuModule[index].PresentOutputVoltage))
|
|
|
+ {
|
|
|
+ _outputVolBuf = ShmPsuData->PsuGroup[group].PsuModule[index].PresentOutputVoltage;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ ShmPsuData->PsuGroup[group].GroupMaxVoltage = _groupMaxVoltage;
|
|
|
+ ShmPsuData->PsuGroup[group].GroupAvailableCurrent = _groupCurrent;
|
|
|
+ ShmPsuData->PsuGroup[group].GroupAvailablePower = _groupPower;
|
|
|
+
|
|
|
+ ShmPsuData->PsuGroup[group].TotalIAvailableCurrent = Iavail;
|
|
|
+ ShmPsuData->PsuGroup[group].TotalRatingPower = Pavail;
|
|
|
+
|
|
|
+ ShmPsuData->PsuGroup[group].GroupPresentOutputVoltage = _outputVolBuf;
|
|
|
+ ShmPsuData->PsuGroup[group].GroupPresentOutputCurrent = _outputCurBuf;
|
|
|
+}
|
|
|
+
|
|
|
+void CollectPsuInformation()
|
|
|
+{
|
|
|
+ int _sysPwr = 0, _sysCur = 0, _sysVol = 0;
|
|
|
+
|
|
|
+ for (byte group = 0; group < ShmPsuData->GroupCount; group++)
|
|
|
+ {
|
|
|
+ // 取群資訊
|
|
|
+ CollectGroupInformation(group);
|
|
|
+
|
|
|
+ // 整理系統資訊
|
|
|
+ _sysPwr += ShmPsuData->PsuGroup[group].GroupAvailablePower;
|
|
|
+ _sysCur += ShmPsuData->PsuGroup[group].GroupAvailableCurrent;
|
|
|
+
|
|
|
+ if (ShmPsuData->PsuGroup[group].GroupMaxVoltage > _sysVol)
|
|
|
+ _sysVol = ShmPsuData->PsuGroup[group].GroupMaxVoltage;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 系統,電壓,電流,能量
|
|
|
+ ShmPsuData->SystemAvailableCurrent = _sysCur;
|
|
|
+ ShmPsuData->SystemAvailablePower = _sysPwr;
|
|
|
+ GetSystemMaxVoltage();
|
|
|
+}
|
|
|
+
|
|
|
+//==========================================
|
|
|
+// Main Loop
|
|
|
+//==========================================
|
|
|
+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;
|
|
|
+ }
|
|
|
+
|
|
|
+ Initialization();
|
|
|
+
|
|
|
+ // 對充電槍操作 : 將模塊切出來與補上剩餘的模塊功率
|
|
|
+ FetchFork();
|
|
|
+ ReleaseFork();
|
|
|
+
|
|
|
+ GetTimespecFunc(&_log_time);
|
|
|
+ while(1)
|
|
|
+ {
|
|
|
+ if (ShmPsuData->Work_Step >= GET_SYS_CAP)
|
|
|
+ {
|
|
|
+ // 收集來自 PSU 的資訊
|
|
|
+ CollectPsuInformation();
|
|
|
+ // 將群資訊分配到對應的使用中充電槍
|
|
|
+ AssignedPwr2Connector();
|
|
|
+
|
|
|
+ int time = GetTimeoutValue(&_log_time);
|
|
|
+
|
|
|
+ if (time < 0)
|
|
|
+ GetTimespecFunc(&_log_time);
|
|
|
+
|
|
|
+ // 低 Priority 的指令
|
|
|
+ if (time > 5000)
|
|
|
+ {
|
|
|
+ //PrintfLog();
|
|
|
+ GetTimespecFunc(&_log_time);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ if (ShmDcCommonData->systemType != _SYSTEM_TYPE_SIMPLE &&
|
|
|
+ ShmPsuData->Work_Step == _WORK_CHARGING)
|
|
|
+ {
|
|
|
+ // 橋接控制
|
|
|
+ SmartRelayCheck();
|
|
|
+ }
|
|
|
+ usleep(50000);
|
|
|
+ }
|
|
|
+
|
|
|
+ return -1;
|
|
|
+}
|
|
|
+
|