Module_SmartBox.c 53 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520
  1. /*
  2. * Module_SmartBox.c
  3. *
  4. * Created on: 2022年5月3日
  5. * Author: 7564
  6. */
  7. #include "Module_SmartBox.h"
  8. struct SysConfigAndInfo *ShmSysConfigAndInfo;
  9. struct StatusCodeData *ShmStatusCodeData;
  10. struct PsuData *ShmPsuData;
  11. struct DcCommonInformation *ShmDcCommonData;
  12. struct SmartBoxData *ShmSmartBoxData;
  13. struct ChargingInfoData *chargingInfo[CHAdeMO_QUANTITY + CCS_QUANTITY + GB_QUANTITY];
  14. byte ConnectorUsingSeq[CHAdeMO_QUANTITY + CCS_QUANTITY + GB_QUANTITY][4] =
  15. {{0, 2, 3, 1}, {1, 3, 2, 0}};
  16. struct timespec _log_time;
  17. #define DEBUG_INFO(format, args...) StoreLogMsg("[%s:%d][%s][Info] "format, __FILE__, __LINE__, __FUNCTION__, ##args)
  18. #define DEBUG_WARN(format, args...) StoreLogMsg("[%s:%d][%s][Warn] "format, __FILE__, __LINE__, __FUNCTION__, ##args)
  19. #define DEBUG_ERROR(format, args...) StoreLogMsg("[%s:%d][%s][Error] "format, __FILE__, __LINE__, __FUNCTION__, ##args)
  20. int StoreLogMsg(const char *fmt, ...)
  21. {
  22. char Buf[4096+256];
  23. char buffer[4096];
  24. va_list args;
  25. struct timeb SeqEndTime;
  26. struct tm *tm;
  27. va_start(args, fmt);
  28. int rc = vsnprintf(buffer, sizeof(buffer), fmt, args);
  29. va_end(args);
  30. memset(Buf,0,sizeof(Buf));
  31. ftime(&SeqEndTime);
  32. SeqEndTime.time = time(NULL);
  33. tm=localtime(&SeqEndTime.time);
  34. if (ShmSysConfigAndInfo->SysConfig.SwitchDebugFlag == YES)
  35. {
  36. sprintf(Buf,"%02d:%02d:%02d:%03d - %s",
  37. tm->tm_hour,tm->tm_min,tm->tm_sec,SeqEndTime.millitm, buffer);
  38. printf("%s \n", Buf);
  39. }
  40. else
  41. {
  42. sprintf(Buf,"echo \"%04d-%02d-%02d %02d:%02d:%02d:%03d - %s\" >> /Storage/SystemLog/[%04d.%02d]SystemLog_%s_Log",
  43. tm->tm_year+1900,tm->tm_mon+1,tm->tm_mday,tm->tm_hour,tm->tm_min,tm->tm_sec,SeqEndTime.millitm,
  44. buffer,
  45. tm->tm_year+1900,tm->tm_mon+1,
  46. ShmSysConfigAndInfo->SysConfig.SerialNumber);
  47. system(Buf);
  48. }
  49. return rc;
  50. }
  51. void PRINTF_FUNC(char *string, ...)
  52. {
  53. va_list args;
  54. char buffer[4096];
  55. va_start(args, string);
  56. vsnprintf(buffer, sizeof(buffer), string, args);
  57. va_end(args);
  58. DEBUG_INFO("%s ", buffer);
  59. }
  60. //==========================================
  61. // Init all share memory
  62. //==========================================
  63. int InitShareMemory()
  64. {
  65. int result = PASS;
  66. int MeterSMId;
  67. //creat ShmSysConfigAndInfo
  68. if ((MeterSMId = shmget(ShmSysConfigAndInfoKey, sizeof(struct SysConfigAndInfo), 0777)) < 0)
  69. {
  70. #ifdef SystemLogMessage
  71. DEBUG_ERROR("shmget ShmSysConfigAndInfoKey NG %d \n");
  72. #endif
  73. result = FAIL;
  74. }
  75. else if ((ShmSysConfigAndInfo = shmat(MeterSMId, NULL, 0)) == (void *) -1)
  76. {
  77. #ifdef SystemLogMessage
  78. DEBUG_ERROR("shmat ShmSysConfigAndInfo NG \n");
  79. #endif
  80. result = FAIL;
  81. }
  82. //creat ShmStatusCodeData
  83. if ((MeterSMId = shmget(ShmStatusCodeKey, sizeof(struct StatusCodeData), 0777)) < 0)
  84. {
  85. #ifdef SystemLogMessage
  86. DEBUG_ERROR("shmget ShmStatusCodeKey NG \n");
  87. #endif
  88. result = FAIL;
  89. }
  90. else if ((ShmStatusCodeData = shmat(MeterSMId, NULL, 0)) == (void *) -1)
  91. {
  92. #ifdef SystemLogMessage
  93. DEBUG_ERROR("shmat ShmStatusCodeData NG \n");
  94. #endif
  95. result = FAIL;
  96. }
  97. //creat ShmPsuData
  98. if ((MeterSMId = shmget(ShmPsuKey, sizeof(struct PsuData), 0777)) < 0)
  99. {
  100. #ifdef SystemLogMessage
  101. DEBUG_ERROR("shmget ShmPsuKey NG \n");
  102. #endif
  103. result = FAIL;
  104. }
  105. else if ((ShmPsuData = shmat(MeterSMId, NULL, 0)) == (void *) -1)
  106. {
  107. #ifdef SystemLogMessage
  108. DEBUG_ERROR("shmat ShmPsuData NG \n");
  109. #endif
  110. result = FAIL;
  111. }
  112. if ((MeterSMId = shmget(ShmCommonKey, sizeof(struct DcCommonInformation), IPC_CREAT | 0777)) < 0)
  113. {
  114. #ifdef SystemLogMessage
  115. DEBUG_ERROR("shmget ShmCommonKey NG \n");
  116. #endif
  117. result = FAIL;
  118. }
  119. else if ((ShmDcCommonData = shmat(MeterSMId, NULL, 0)) == (void *) -1)
  120. {
  121. #ifdef SystemLogMessage
  122. DEBUG_ERROR("shmat ShmDcCommonData NG \n");
  123. #endif
  124. result = FAIL;
  125. }
  126. if ((MeterSMId = shmget ( ShmSmartBoxKey, sizeof(struct SmartBoxData), IPC_CREAT | 0777 )) < 0)
  127. {
  128. #ifdef SystemLogMessage
  129. DEBUG_ERROR("shmat ShmSmartBoxKey NG \n");
  130. #endif
  131. return FAIL;
  132. }
  133. else if ((ShmSmartBoxData = shmat ( MeterSMId, NULL, 0 )) == (void *) - 1)
  134. {
  135. #ifdef SystemLogMessage
  136. DEBUG_ERROR("shmat ShmSmartBoxData NG \n");
  137. #endif
  138. return FAIL;
  139. }
  140. return result;
  141. }
  142. //==========================================
  143. // Public Function
  144. //==========================================
  145. bool FindChargingInfoData(byte target, struct ChargingInfoData **chargingData)
  146. {
  147. for (byte index = 0; index < CHAdeMO_QUANTITY; index++)
  148. {
  149. if (ShmSysConfigAndInfo->SysInfo.ChademoChargingData[index].Index == target)
  150. {
  151. chargingData[target] = &ShmSysConfigAndInfo->SysInfo.ChademoChargingData[index];
  152. return true;
  153. }
  154. }
  155. for (byte index = 0; index < CCS_QUANTITY; index++)
  156. {
  157. if (ShmSysConfigAndInfo->SysInfo.CcsChargingData[index].Index == target)
  158. {
  159. chargingData[target] = &ShmSysConfigAndInfo->SysInfo.CcsChargingData[index];
  160. return true;
  161. }
  162. }
  163. for (byte index = 0; index < GB_QUANTITY; index++)
  164. {
  165. if (ShmSysConfigAndInfo->SysInfo.GbChargingData[index].Index == target)
  166. {
  167. chargingData[target] = &ShmSysConfigAndInfo->SysInfo.GbChargingData[index];
  168. return true;
  169. }
  170. }
  171. return false;
  172. }
  173. void Initialization()
  174. {
  175. bool isPass = false;
  176. while(!isPass)
  177. {
  178. isPass = true;
  179. for (byte _index = 0; _index < ShmSysConfigAndInfo->SysConfig.TotalConnectorCount; _index++)
  180. {
  181. if (!FindChargingInfoData(_index, &chargingInfo[0]))
  182. {
  183. DEBUG_ERROR("SmartBox (main) : FindChargingInfoData false \n");
  184. isPass = false;
  185. break;
  186. }
  187. }
  188. sleep(1);
  189. }
  190. for (byte _index = 0; _index < ShmSysConfigAndInfo->SysConfig.TotalConnectorCount; _index++)
  191. {
  192. ShmSmartBoxData->Dynamic4Fetch[_index].ShareGroup = NONE_GROUP_CAN_SELECTED;
  193. ShmSmartBoxData->Dynamic4Fetch[_index].TargetRelay = NONE_RELAY_SELECTED;
  194. ShmSmartBoxData->Dynamic4Fetch[_index].FetchLoopStep = _PSU_DYNAMIC_FETCH_STEP_NONE;
  195. ShmSmartBoxData->Dynamic4Release[_index].ReleaseGroup = NONE_GROUP_CAN_SELECTED;
  196. ShmSmartBoxData->Dynamic4Release[_index].TargetRelay = NONE_RELAY_SELECTED;
  197. ShmSmartBoxData->Dynamic4Release[_index].ReleaseLoopStep = _PSU_DYNAMIC_RELEASE_STEP_NONE;
  198. ShmSmartBoxData->ConnectorUsingGroupCount[_index] = 0;
  199. }
  200. }
  201. void PrintfLog()
  202. {
  203. if (ShmPsuData->Work_Step != _WORK_CHARGING)
  204. {
  205. PRINTF_FUNC ( "****************************************************************** \n" );
  206. PRINTF_FUNC ( "SystemPresentPsuQuantity = %d \n", ShmPsuData->SystemPresentPsuQuantity);
  207. PRINTF_FUNC ( "SystemAvailableCurrent = %d (A) \n", ShmPsuData->SystemAvailableCurrent / 10);
  208. PRINTF_FUNC ( "SystemAvailablePower = %d (kw) \n", ShmPsuData->SystemAvailablePower / 10);
  209. PRINTF_FUNC ( "GroupCount = %d \n", ShmPsuData->GroupCount );
  210. for (int _count = 0; _count < ARRAY_SIZE(ConnectorUsingSeq[0]); _count ++)
  211. {
  212. PRINTF_FUNC ( "----------------------------------------------------------------- \n" );
  213. PRINTF_FUNC ( "Group Index = %d, UsingTarget for Gun-%d \n", _count, ShmPsuData->PsuGroup[_count].UsingTarget);
  214. PRINTF_FUNC ( "GroupPresentPsuQuantity = %d \n", ShmPsuData->PsuGroup[_count].GroupPresentPsuQuantity );
  215. PRINTF_FUNC ( "GroupTargetOutputVoltage = %d (V) \n", ShmPsuData->PsuGroup[_count].GroupTargetOutputVoltage / 10);
  216. PRINTF_FUNC ( "GroupTargetOutputCurrent = %d (A) \n", ShmPsuData->PsuGroup[_count].GroupTargetOutputCurrent / 10);
  217. PRINTF_FUNC ( "GroupAvailableCurrent = %d (A) \n", ShmPsuData->PsuGroup[_count].GroupAvailableCurrent / 10);
  218. PRINTF_FUNC ( "GroupAvailablePower = %d (kw) \n", ShmPsuData->PsuGroup[_count].GroupAvailablePower / 10);
  219. PRINTF_FUNC ( "GroupMaxVoltage = %d (V) \n", ShmPsuData->PsuGroup[_count].GroupMaxVoltage / 10);
  220. PRINTF_FUNC ( "GroupPresentOutputVoltage = %.1f (V) \n", (double)ShmPsuData->PsuGroup[_count].GroupPresentOutputVoltage / 10);
  221. PRINTF_FUNC ( "GroupPresentOutputCurrent = %.1f (A) \n", (double)ShmPsuData->PsuGroup[_count].GroupPresentOutputCurrent / 10);
  222. PRINTF_FUNC ( "GroupPresentOutputPower = %d \n", ShmPsuData->PsuGroup[_count].GroupPresentOutputPower );
  223. PRINTF_FUNC ( "TotalRatingPower = %f \n", (double)ShmPsuData->PsuGroup[_count].TotalRatingPower);
  224. PRINTF_FUNC ( "TotalIAvailableCurrent = %f \n", (double)ShmPsuData->PsuGroup[_count].TotalIAvailableCurrent / 10);
  225. }
  226. }
  227. else
  228. {
  229. for (byte conn = 0; conn < ShmSysConfigAndInfo->SysConfig.TotalConnectorCount; conn++)
  230. {
  231. byte totalUsingGpCount = 0;
  232. byte totalQuantity = 0;
  233. unsigned short _targetVol = 0 , _targetCur = 0;
  234. unsigned short _avaCur = 0 , _avaPow = 0;
  235. unsigned short _outputVol = 0 , _outputCur = 0;
  236. unsigned short _ratingPow = 0;
  237. for (byte gp = 0; gp < ShmSmartBoxData->ConnectorUsingGroupCount[conn]; gp++)
  238. {
  239. if (ShmPsuData->PsuGroup[ConnectorUsingSeq[conn][gp]].UsingTarget == GUN_LEFT)
  240. {
  241. totalUsingGpCount++;
  242. byte tarGp = ConnectorUsingSeq[conn][gp];
  243. totalQuantity += ShmPsuData->PsuGroup[tarGp].GroupPresentPsuQuantity;
  244. _targetVol = ShmPsuData->PsuGroup[tarGp].GroupTargetOutputVoltage / 10;
  245. _targetCur += ShmPsuData->PsuGroup[tarGp].GroupTargetOutputCurrent / 10;
  246. _avaCur += ShmPsuData->PsuGroup[tarGp].GroupAvailableCurrent / 10;
  247. _avaPow += ShmPsuData->PsuGroup[tarGp].GroupAvailablePower / 10;
  248. _outputVol = (double)ShmPsuData->PsuGroup[tarGp].GroupPresentOutputVoltage / 10;
  249. _outputCur = (double)ShmPsuData->PsuGroup[tarGp].GroupPresentOutputCurrent / 10;
  250. _ratingPow += ShmPsuData->PsuGroup[tarGp].TotalRatingPower;
  251. }
  252. }
  253. if (totalUsingGpCount > 0)
  254. {
  255. PRINTF_FUNC ( "----------------------------------------------------------------- \n" );
  256. PRINTF_FUNC ( "Group Index = %d, totalUsingGpCount = %d \n", conn, totalUsingGpCount);
  257. PRINTF_FUNC ( "totalQuantity = %d \n", totalQuantity);
  258. PRINTF_FUNC ( "_targetVol = %d (V), _targetCur = %d (A) \n", _targetVol, _targetCur);
  259. PRINTF_FUNC ( "_avaCur = %d (A), _avaPow = %d (kw) \n", _avaCur, _avaPow);
  260. PRINTF_FUNC ( "_outputVol = %d (V), _outputCur = %d (A) \n", _outputVol, _outputCur);
  261. PRINTF_FUNC ( "_ratingPow = %d \n", _ratingPow);
  262. }
  263. for (byte gp = 0; gp < ShmSmartBoxData->ConnectorUsingGroupCount[conn]; gp++)
  264. {
  265. if (ShmPsuData->PsuGroup[ConnectorUsingSeq[conn][gp]].UsingTarget == GUN_RIGHT)
  266. {
  267. totalUsingGpCount++;
  268. byte tarGp = ConnectorUsingSeq[conn][gp];
  269. totalQuantity += ShmPsuData->PsuGroup [tarGp].GroupPresentPsuQuantity;
  270. _targetVol = ShmPsuData->PsuGroup [tarGp].GroupTargetOutputVoltage / 10;
  271. _targetCur += ShmPsuData->PsuGroup [tarGp].GroupTargetOutputCurrent / 10;
  272. _avaCur += ShmPsuData->PsuGroup [tarGp].GroupAvailableCurrent / 10;
  273. _avaPow += ShmPsuData->PsuGroup [tarGp].GroupAvailablePower / 10;
  274. _outputVol = (double) ShmPsuData->PsuGroup [tarGp].GroupPresentOutputVoltage / 10;
  275. _outputCur = (double) ShmPsuData->PsuGroup [tarGp].GroupPresentOutputCurrent / 10;
  276. _ratingPow += ShmPsuData->PsuGroup [tarGp].TotalRatingPower;
  277. }
  278. }
  279. if (totalUsingGpCount > 0)
  280. {
  281. PRINTF_FUNC ( "----------------------------------------------------------------- \n" );
  282. PRINTF_FUNC ( "Group Index = %d, totalUsingGpCount = %d \n", conn, totalUsingGpCount);
  283. PRINTF_FUNC ( "totalQuantity = %d \n", totalQuantity);
  284. PRINTF_FUNC ( "_targetVol = %d (V), _targetCur = %d (A) \n", _targetVol, _targetCur);
  285. PRINTF_FUNC ( "_avaCur = %d (A), _avaPow = %d (kw) \n", _avaCur, _avaPow);
  286. PRINTF_FUNC ( "_outputVol = %d (V), _outputCur = %d (A) \n", _outputVol, _outputCur);
  287. PRINTF_FUNC ( "_ratingPow = %d \n", _ratingPow);
  288. }
  289. }
  290. }
  291. }
  292. void GetSystemMaxVoltage()
  293. {
  294. if (ShmSysConfigAndInfo->SysInfo.BootingStatus == BOOTTING)
  295. {
  296. int _sysVol = 0;
  297. for (byte group = 0; group < ShmPsuData->GroupCount; group++)
  298. {
  299. if (ShmPsuData->PsuGroup[group].GroupMaxVoltage > _sysVol)
  300. _sysVol = ShmPsuData->PsuGroup[group].GroupMaxVoltage;
  301. }
  302. for (byte gun_index = 0; gun_index < ShmSysConfigAndInfo->SysConfig.TotalConnectorCount; gun_index++)
  303. {
  304. if (chargingInfo[gun_index]->MaximumChargingVoltage != _sysVol)
  305. {
  306. chargingInfo[gun_index]->MaximumChargingVoltage = _sysVol;
  307. }
  308. }
  309. }
  310. }
  311. void GetTimespecFunc(struct timespec *time)
  312. {
  313. clock_gettime(CLOCK_MONOTONIC, time);
  314. }
  315. long int GetTimeoutValue(struct timespec *startTime)
  316. {
  317. struct timespec endTime;
  318. clock_gettime(CLOCK_MONOTONIC, &endTime);
  319. return 1000 * (endTime.tv_sec - startTime->tv_sec) + (endTime.tv_nsec - startTime->tv_nsec) / 1000000;
  320. }
  321. //==========================================
  322. // Relay Processing
  323. //==========================================
  324. void SmartRelayCheck()
  325. {
  326. /*
  327. ---------------------------------------
  328. G_0 -----------(R1)----------------> Gun - 0
  329. | -> R3
  330. G_2 --------|
  331. | -> R4
  332. G_3 --------|
  333. | -> R5
  334. G_1 -----------(R2)----------------> Gun - 1
  335. ---------------------------------------
  336. R3 ON 時機 : G_2 屬於 Gun-0 輸出、G_0屬於 Gun - 1 輸出
  337. R4 ON 時機 : G_3 屬於 Gun-0 輸出、G_2屬於 Gun - 1 輸出
  338. R5 ON 時機 : G_3 屬於 Gun-1 輸出、G_1屬於 Gun - 0 輸出
  339. -------------------------
  340. 掃描PSU四個群及兩輸出的ShareGroup內的值各屬於哪個輸出
  341. */
  342. byte _buff[3] = {0};
  343. for (byte group = 0; group < ShmPsuData->GroupCount; group++)
  344. {
  345. switch(group)
  346. {
  347. case _PSU_GROUP_INDEX_0:
  348. {
  349. if (ShmPsuData->PsuGroup[group].UsingTarget == GUN_RIGHT)
  350. {
  351. // 如果是標準品
  352. if(ShmDcCommonData->systemType == _SYSTEM_TYPE_STANDARD)
  353. {
  354. _buff[_RELAY_SWITCH_NAME_R4] = 0x01;
  355. _buff[_RELAY_SWITCH_NAME_R5] = 0x01;
  356. }
  357. else
  358. {
  359. // R3 ON
  360. _buff[_RELAY_SWITCH_NAME_R3] = 0x01;
  361. }
  362. }
  363. }
  364. break;
  365. case _PSU_GROUP_INDEX_2:
  366. {
  367. if (ShmPsuData->PsuGroup[group].UsingTarget == GUN_LEFT)
  368. {
  369. // R3 ON
  370. _buff[_RELAY_SWITCH_NAME_R3] = 0x01;
  371. }
  372. if (ShmPsuData->PsuGroup[group].UsingTarget == GUN_RIGHT)
  373. {
  374. // R4 ON
  375. _buff[_RELAY_SWITCH_NAME_R4] = 0x01;
  376. }
  377. }
  378. break;
  379. case _PSU_GROUP_INDEX_3:
  380. {
  381. if (ShmPsuData->PsuGroup[group].UsingTarget == GUN_LEFT)
  382. {
  383. // R4 ON
  384. _buff[_RELAY_SWITCH_NAME_R4] = 0x01;
  385. }
  386. if (ShmPsuData->PsuGroup[group].UsingTarget == GUN_RIGHT)
  387. {
  388. // R5 ON
  389. _buff[_RELAY_SWITCH_NAME_R5] = 0x01;
  390. }
  391. }
  392. break;
  393. case _PSU_GROUP_INDEX_1:
  394. {
  395. if (ShmPsuData->PsuGroup[group].UsingTarget == GUN_LEFT)
  396. {
  397. // 如果是標準品
  398. if(ShmDcCommonData->systemType == _SYSTEM_TYPE_STANDARD)
  399. {
  400. _buff[_RELAY_SWITCH_NAME_R4] = 0x01;
  401. _buff[_RELAY_SWITCH_NAME_R5] = 0x01;
  402. }
  403. else
  404. {
  405. // R5 ON
  406. _buff[_RELAY_SWITCH_NAME_R5] = 0x01;
  407. }
  408. }
  409. }
  410. break;
  411. }
  412. }
  413. for (byte _Conn = 0; _Conn < ShmSysConfigAndInfo->SysConfig.TotalConnectorCount; _Conn++)
  414. {
  415. if (ShmSmartBoxData->Dynamic4Fetch[_Conn].FetchLoopStep >= _PSU_DYNAMIC_FETCH_STEP_RELAY)
  416. {
  417. byte targetGroup = ShmSmartBoxData->Dynamic4Fetch[_Conn].ShareGroup;
  418. switch(targetGroup)
  419. {
  420. case _PSU_GROUP_INDEX_0:
  421. {
  422. if (ShmPsuData->PsuGroup[targetGroup].UsingTarget == GUN_RIGHT)
  423. {
  424. // 如果是標準品
  425. if(ShmDcCommonData->systemType == _SYSTEM_TYPE_STANDARD)
  426. {
  427. _buff[_RELAY_SWITCH_NAME_R4] = 0x01;
  428. _buff[_RELAY_SWITCH_NAME_R5] = 0x01;
  429. ShmSmartBoxData->Dynamic4Fetch[_Conn].TargetRelay = _RELAY_SWITCH_NAME_R4;
  430. }
  431. else
  432. {
  433. // R3 ON -- P
  434. _buff[_RELAY_SWITCH_NAME_R3] = 0x01;
  435. ShmSmartBoxData->Dynamic4Fetch[_Conn].TargetRelay = _RELAY_SWITCH_NAME_R3;
  436. }
  437. }
  438. }
  439. break;
  440. case _PSU_GROUP_INDEX_2:
  441. {
  442. if (ShmPsuData->PsuGroup[targetGroup].UsingTarget == GUN_LEFT)
  443. {
  444. // R3 ON -- P
  445. _buff[_RELAY_SWITCH_NAME_R3] = 0x01;
  446. ShmSmartBoxData->Dynamic4Fetch[_Conn].TargetRelay = _RELAY_SWITCH_NAME_R3;
  447. }
  448. if (ShmPsuData->PsuGroup[targetGroup].UsingTarget == GUN_RIGHT)
  449. {
  450. // R4 ON -- P
  451. _buff[_RELAY_SWITCH_NAME_R4] = 0x01;
  452. ShmSmartBoxData->Dynamic4Fetch[_Conn].TargetRelay = _RELAY_SWITCH_NAME_R4;
  453. }
  454. }
  455. break;
  456. case _PSU_GROUP_INDEX_3:
  457. {
  458. if (ShmPsuData->PsuGroup[targetGroup].UsingTarget == GUN_LEFT)
  459. {
  460. // R4 ON -- P
  461. _buff[_RELAY_SWITCH_NAME_R4] = 0x01;
  462. ShmSmartBoxData->Dynamic4Fetch[_Conn].TargetRelay = _RELAY_SWITCH_NAME_R4;
  463. }
  464. if (ShmPsuData->PsuGroup[targetGroup].UsingTarget == GUN_RIGHT)
  465. {
  466. // R5 ON -- P
  467. _buff[_RELAY_SWITCH_NAME_R5] = 0x01;
  468. ShmSmartBoxData->Dynamic4Fetch[_Conn].TargetRelay = _RELAY_SWITCH_NAME_R5;
  469. }
  470. }
  471. break;
  472. case _PSU_GROUP_INDEX_1:
  473. {
  474. if (ShmPsuData->PsuGroup[targetGroup].UsingTarget == GUN_LEFT)
  475. {
  476. // 如果是標準品
  477. if(ShmDcCommonData->systemType == _SYSTEM_TYPE_STANDARD)
  478. {
  479. _buff[_RELAY_SWITCH_NAME_R4] = 0x01;
  480. _buff[_RELAY_SWITCH_NAME_R5] = 0x01;
  481. ShmSmartBoxData->Dynamic4Fetch[_Conn].TargetRelay = _RELAY_SWITCH_NAME_R4;
  482. }
  483. else
  484. {
  485. // R5 ON -- P
  486. _buff[_RELAY_SWITCH_NAME_R5] = 0x01;
  487. ShmSmartBoxData->Dynamic4Fetch[_Conn].TargetRelay = _RELAY_SWITCH_NAME_R5;
  488. }
  489. }
  490. }
  491. break;
  492. }
  493. }
  494. if (ShmSmartBoxData->Dynamic4Release[_Conn].ReleaseLoopStep >= _PSU_DYNAMIC_RELEASE_STEP_RELAYOFF)
  495. {
  496. byte targetGroup = ShmSmartBoxData->Dynamic4Release[_Conn].ReleaseGroup;
  497. switch(targetGroup)
  498. {
  499. case _PSU_GROUP_INDEX_0:
  500. {
  501. if (ShmPsuData->PsuGroup[targetGroup].UsingTarget == GUN_RIGHT)
  502. {
  503. // R3 OFF
  504. _buff[_RELAY_SWITCH_NAME_R3] = 0x00;
  505. ShmSmartBoxData->Dynamic4Release[_Conn].TargetRelay = _RELAY_SWITCH_NAME_R3;
  506. // 如果是標準品
  507. if(ShmDcCommonData->systemType == _SYSTEM_TYPE_STANDARD)
  508. {
  509. _buff[_RELAY_SWITCH_NAME_R4] = 0x00;
  510. _buff[_RELAY_SWITCH_NAME_R5] = 0x00;
  511. ShmSmartBoxData->Dynamic4Release[_Conn].TargetRelay = _RELAY_SWITCH_NAME_R4;
  512. }
  513. }
  514. }
  515. break;
  516. case _PSU_GROUP_INDEX_2:
  517. {
  518. if (ShmPsuData->PsuGroup[targetGroup].UsingTarget == GUN_LEFT)
  519. {
  520. // R3 OFF
  521. _buff[_RELAY_SWITCH_NAME_R3] = 0x00;
  522. ShmSmartBoxData->Dynamic4Release[_Conn].TargetRelay = _RELAY_SWITCH_NAME_R3;
  523. }
  524. if (ShmPsuData->PsuGroup[targetGroup].UsingTarget == GUN_RIGHT)
  525. {
  526. // R5 OFF
  527. _buff[_RELAY_SWITCH_NAME_R4] = 0x00;
  528. ShmSmartBoxData->Dynamic4Release[_Conn].TargetRelay = _RELAY_SWITCH_NAME_R4;
  529. }
  530. }
  531. break;
  532. case _PSU_GROUP_INDEX_3:
  533. {
  534. if (ShmPsuData->PsuGroup[targetGroup].UsingTarget == GUN_LEFT)
  535. {
  536. // R4 OFF
  537. _buff[_RELAY_SWITCH_NAME_R4] = 0x00;
  538. ShmSmartBoxData->Dynamic4Release[_Conn].TargetRelay = _RELAY_SWITCH_NAME_R4;
  539. }
  540. if (ShmPsuData->PsuGroup[targetGroup].UsingTarget == GUN_RIGHT)
  541. {
  542. // R5 OFF
  543. _buff[_RELAY_SWITCH_NAME_R5] = 0x00;
  544. ShmSmartBoxData->Dynamic4Release[_Conn].TargetRelay = _RELAY_SWITCH_NAME_R5;
  545. }
  546. }
  547. break;
  548. case _PSU_GROUP_INDEX_1:
  549. {
  550. if (ShmPsuData->PsuGroup[targetGroup].UsingTarget == GUN_LEFT)
  551. {
  552. // 如果是標準品
  553. if(ShmDcCommonData->systemType == _SYSTEM_TYPE_STANDARD)
  554. {
  555. _buff[_RELAY_SWITCH_NAME_R4] = 0x00;
  556. _buff[_RELAY_SWITCH_NAME_R5] = 0x00;
  557. ShmSmartBoxData->Dynamic4Release[_Conn].TargetRelay = _RELAY_SWITCH_NAME_R4;
  558. }
  559. else
  560. {
  561. // R4 OFF
  562. _buff[_RELAY_SWITCH_NAME_R5] = 0x00;
  563. ShmSmartBoxData->Dynamic4Release[_Conn].TargetRelay = _RELAY_SWITCH_NAME_R5;
  564. }
  565. }
  566. }
  567. break;
  568. }
  569. }
  570. }
  571. memcpy(ShmSmartBoxData->ParallelRelayStatus, _buff, sizeof(_buff));
  572. }
  573. //==========================================
  574. // Sub Processing
  575. //==========================================
  576. void Assign2ConnectorProcessing(byte _targetConn)
  577. {
  578. // 根據現在該槍拿到的群數量, 依順去設定群的使用目標為左 /右槍
  579. // 一旦設定該模塊目標為左 /右槍後,AssignedPwr2Connector function 會將該模塊的資訊給對應的左/右槍
  580. for (byte aGp = 0; aGp < ShmSmartBoxData->ConnectorUsingGroupCount[_targetConn]; aGp++)
  581. {
  582. if (ShmPsuData->PsuGroup[ConnectorUsingSeq[_targetConn][aGp]].IsUsing == YES)
  583. {
  584. ShmPsuData->PsuGroup[ConnectorUsingSeq[_targetConn][aGp]].UsingTarget = _targetConn;
  585. }
  586. }
  587. }
  588. // 將_group該群的模塊配給_targetConn槍號
  589. void AddGroup2Connector(byte _targetConn, byte _group)
  590. {
  591. ShmPsuData->PsuGroup[_group].IsUsing = YES;
  592. if ((ShmSysConfigAndInfo->SysInfo.IsAlternatvieConf == YES && _targetConn == GUN_RIGHT) ||
  593. (ShmDcCommonData->systemType == _SYSTEM_TYPE_STANDARD && ShmSmartBoxData->ConnectorUsingGroupCount[_targetConn] > 0))
  594. ShmSmartBoxData->ConnectorUsingGroupCount[_targetConn] = 4;
  595. else
  596. ShmSmartBoxData->ConnectorUsingGroupCount[_targetConn]++;
  597. // 對應到相對群
  598. Assign2ConnectorProcessing(_targetConn);
  599. }
  600. // 將targetGp該群的模塊從_targetConn槍號移除
  601. bool ReleaseConnectorProcessing(byte _targetConn, byte targetGp)
  602. {
  603. bool result = false;
  604. if (ShmPsuData->PsuGroup[targetGp].PwSwitchStatus == _PSU_POWER_STATUS_OFF)
  605. {
  606. result = true;
  607. ShmPsuData->PsuGroup[targetGp].UsingTarget = GUN_CHECK;
  608. ShmPsuData->PsuGroup[targetGp].IsUsing = NO;
  609. ShmSmartBoxData->ConnectorUsingGroupCount[_targetConn]--;
  610. }
  611. return result;
  612. }
  613. //==========================================
  614. // Fetch fork
  615. //==========================================
  616. void InitializeDynamicFetch(byte _targetConn)
  617. {
  618. ShmSmartBoxData->Dynamic4Fetch[_targetConn].ShareGroup = NONE_GROUP_CAN_SELECTED;
  619. ShmSmartBoxData->Dynamic4Fetch[_targetConn].TargetRelay = NONE_RELAY_SELECTED;
  620. ShmSmartBoxData->Dynamic4Fetch[_targetConn].ShareTargetCurrent = 0;
  621. ShmSmartBoxData->SmartChk[_targetConn].IsFetchStart = NO;
  622. }
  623. void FetchLoopProcessing(byte _targetConn)
  624. {
  625. byte targetGroup = ShmSmartBoxData->Dynamic4Fetch[_targetConn].ShareGroup;
  626. if (targetGroup == NONE_GROUP_CAN_SELECTED &&
  627. ShmSmartBoxData->Dynamic4Fetch[_targetConn].FetchLoopStep >= _PSU_DYNAMIC_FETCH_STEP_TG_VOL)
  628. {
  629. ShmSmartBoxData->Dynamic4Fetch[_targetConn].FetchLoopStep = _PSU_DYNAMIC_FETCH_STEP_FINISH;
  630. }
  631. // 用 target vol 比較好還是用當前火線電壓 ? 可以試試看~
  632. float EvVoltage = chargingInfo[_targetConn]->EvBatterytargetVoltage * 10;
  633. switch(ShmSmartBoxData->Dynamic4Fetch[_targetConn].FetchLoopStep)
  634. {
  635. case _PSU_DYNAMIC_FETCH_STEP_NONE:
  636. case _PSU_DYNAMIC_FETCH_STEP_WAIT:{ } break;
  637. case _PSU_DYNAMIC_FETCH_STEP_TG_VOL:
  638. {
  639. // 該群升壓
  640. if (ShmPsuData->PsuGroup[targetGroup].GroupPresentOutputVoltage != 0)
  641. {
  642. PRINTF_FUNC("EV_ReqVoltage = %f, targetGroup = %d, Group_CurVoltage = %d \n",
  643. EvVoltage, targetGroup, ShmPsuData->PsuGroup[targetGroup].GroupPresentOutputVoltage);
  644. }
  645. if (EvVoltage <= PSU_MIN_VOL)
  646. {
  647. PRINTF_FUNC("***** FETCH_STEP_ABORT ***** (Gun - %d) \n", _targetConn);
  648. ShmSmartBoxData->Dynamic4Fetch[_targetConn].FetchLoopStep = _PSU_DYNAMIC_FETCH_STEP_ABORT;
  649. }
  650. else if (ShmPsuData->PsuGroup[targetGroup].GroupPresentOutputVoltage >= EvVoltage - PSU_TG_VOL_GAP)
  651. {
  652. PRINTF_FUNC("***** FETCH_STEP_RELAY ***** (Gun - %d) \n", _targetConn);
  653. ShmPsuData->PsuGroup[targetGroup].UsingTarget = _targetConn;
  654. ShmSmartBoxData->Dynamic4Fetch[_targetConn].FetchLoopStep = _PSU_DYNAMIC_FETCH_STEP_RELAY;
  655. }
  656. }
  657. break;
  658. case _PSU_DYNAMIC_FETCH_STEP_RELAY:
  659. {
  660. // 搭上對應的 Relay
  661. if (ShmSmartBoxData->Dynamic4Fetch[_targetConn].TargetRelay < ARRAY_SIZE(ShmSmartBoxData->ParallelRelayStatus))
  662. {
  663. if (ShmSmartBoxData->ParallelRelayStatus[ShmSmartBoxData->Dynamic4Fetch[_targetConn].TargetRelay] == YES)
  664. {
  665. if (ShmSmartBoxData->RcbParallelStatus[ShmSmartBoxData->Dynamic4Fetch[_targetConn].TargetRelay] == YES)
  666. {
  667. PRINTF_FUNC("***** FETCH_STEP_CUR_SHARE ***** (Gun - %d) \n", _targetConn);
  668. ShmSmartBoxData->Dynamic4Fetch[_targetConn].FetchLoopStep = _PSU_DYNAMIC_FETCH_STEP_CUR_SHARE;
  669. }
  670. }
  671. }
  672. }
  673. break;
  674. case _PSU_DYNAMIC_FETCH_STEP_CUR_SHARE:
  675. {
  676. // 均流 : 目標電流 = 當前電流 / (原本輸出群個數 + share group 個數)
  677. PRINTF_FUNC("GroupPresent = %d (0.1A), ShareTarget = %d (0.1A), CurrentPresent = %.1f \n",
  678. ShmPsuData->PsuGroup[targetGroup].GroupPresentOutputCurrent,
  679. ShmSmartBoxData->Dynamic4Fetch[_targetConn].ShareTargetCurrent,
  680. chargingInfo[_targetConn]->PresentChargingCurrent);
  681. if ((ShmPsuData->PsuGroup[targetGroup].GroupPresentOutputCurrent >= ShmSmartBoxData->Dynamic4Fetch[_targetConn].ShareTargetCurrent - PSU_TG_CUR_GAP &&
  682. ShmPsuData->PsuGroup[targetGroup].GroupPresentOutputCurrent <= ShmSmartBoxData->Dynamic4Fetch[_targetConn].ShareTargetCurrent + PSU_TG_CUR_GAP) ||
  683. chargingInfo[_targetConn]->PresentChargingCurrent <= PSU_MIN_CUR)
  684. {
  685. PRINTF_FUNC("***** FETCH_STEP_WATI_FINISH ***** (Gun - %d) \n", _targetConn);
  686. ShmSmartBoxData->Dynamic4Fetch[_targetConn].FetchLoopStep = _PSU_DYNAMIC_FETCH_STEP_WATI_FINISH;
  687. }
  688. }
  689. break;
  690. case _PSU_DYNAMIC_FETCH_STEP_WATI_FINISH:
  691. {
  692. AddGroup2Connector(_targetConn, targetGroup);
  693. GetTimespecFunc(&ShmSmartBoxData->SmartChk[_targetConn].FetchLoopTime);
  694. PRINTF_FUNC("***** FETCH_STEP_FINISH ***** (Gun - %d) \n", _targetConn);
  695. ShmSmartBoxData->Dynamic4Fetch[_targetConn].ShareGroup = NONE_GROUP_CAN_SELECTED;
  696. ShmSmartBoxData->Dynamic4Fetch[_targetConn].FetchLoopStep = _PSU_DYNAMIC_FETCH_STEP_FINISH;
  697. }
  698. break;
  699. case _PSU_DYNAMIC_FETCH_STEP_FINISH:
  700. {
  701. // 完成
  702. int _t = GetTimeoutValue(&ShmSmartBoxData->SmartChk[_targetConn].FetchLoopTime);
  703. if (_t >= FETCH_FINISH_WAIT_TIME)
  704. {
  705. InitializeDynamicFetch(_targetConn);
  706. PRINTF_FUNC("***** FETCH_STEP_NONE ***** (Gun - %d) \n", _targetConn);
  707. ShmSmartBoxData->Dynamic4Fetch[_targetConn].FetchLoopStep = _PSU_DYNAMIC_FETCH_STEP_NONE;
  708. }
  709. }
  710. break;
  711. case _PSU_DYNAMIC_FETCH_STEP_ABORT:
  712. {
  713. // 中斷
  714. if (ShmPsuData->PsuGroup[targetGroup].IsUsing)
  715. {
  716. ShmPsuData->PsuGroup[targetGroup].IsUsing = NO;
  717. ShmPsuData->PsuGroup[targetGroup].UsingTarget = GUN_CHECK;
  718. }
  719. GetTimespecFunc(&ShmSmartBoxData->SmartChk[_targetConn].FetchLoopTime);
  720. ShmSmartBoxData->Dynamic4Fetch[_targetConn].FetchLoopStep = _PSU_DYNAMIC_FETCH_STEP_FINISH;
  721. }
  722. break;
  723. }
  724. }
  725. byte CheckRemainPwrByConIndex(byte _targetConn)
  726. {
  727. byte result = NONE_GROUP_CAN_SELECTED;
  728. // 該槍已經使用的群數量
  729. byte usingCount = ShmSmartBoxData->ConnectorUsingGroupCount[_targetConn];
  730. for (byte Gp = usingCount; Gp < ARRAY_SIZE(ConnectorUsingSeq[_targetConn]); Gp++)
  731. {
  732. // 判斷是否有該槍下一個可用群的狀態
  733. if (ShmPsuData->PsuGroup[ConnectorUsingSeq[_targetConn][Gp]].IsUsing == NO &&
  734. ShmPsuData->PsuGroup[ConnectorUsingSeq[_targetConn][Gp]].GroupPresentPsuQuantity > 0)
  735. {
  736. result = ConnectorUsingSeq[_targetConn][Gp];
  737. break;
  738. }
  739. }
  740. return result;
  741. }
  742. void Chk2StopFetchStep(byte _targetConn)
  743. {
  744. // 開始流程後,就讓流程走完吧~
  745. if (ShmSmartBoxData->Dynamic4Fetch[_targetConn].FetchLoopStep > _PSU_DYNAMIC_FETCH_STEP_NONE &&
  746. ShmSmartBoxData->Dynamic4Fetch[_targetConn].FetchLoopStep < _PSU_DYNAMIC_FETCH_STEP_TG_VOL)
  747. {
  748. PRINTF_FUNC("***** FETCH_STEP_ABORT ***** (Gun - %d) \n", _targetConn);
  749. ShmSmartBoxData->Dynamic4Fetch[_targetConn].FetchLoopStep = _PSU_DYNAMIC_FETCH_STEP_ABORT;
  750. }
  751. }
  752. bool GetCanFetchResult(byte gun_index)
  753. {
  754. // 如果當前輸出接近實際可提供的能量 (距離 <= CAP_GAP_FETCH <3KW>)
  755. // 不取 EvBatterytargetVoltage 原因是小板會將該值做不同的處理方式
  756. float needPower = chargingInfo[gun_index]->PresentChargingVoltage *
  757. chargingInfo[gun_index]->EvBatterytargetCurrent / 100;
  758. ShmSmartBoxData->ConnectorStatus[gun_index].NeedToFetch =
  759. (needPower > 0 && needPower >= chargingInfo[gun_index]->RealRatingPower - CAP_GAP_FETCH) ? true : false;
  760. if (!ShmSmartBoxData->ConnectorStatus[gun_index].NeedToFetch)
  761. {
  762. // 考慮每顆模塊最大輸出電流為 100A
  763. ShmSmartBoxData->ConnectorStatus[gun_index].NeedToFetch = (chargingInfo[gun_index]->EvBatterytargetCurrent >=
  764. chargingInfo[gun_index]->AvailableChargingCurrent - LIMIT_PWR_MODULE_GAP) ? true : false;
  765. }
  766. return ShmSmartBoxData->ConnectorStatus[gun_index].NeedToFetch;
  767. }
  768. void FetchFork()
  769. {
  770. pid_t fetchPid;
  771. fetchPid = fork();
  772. if(fetchPid > 0)
  773. {
  774. bool isPass = false;
  775. struct ChargingInfoData *_chargingData[CHAdeMO_QUANTITY + CCS_QUANTITY + GB_QUANTITY];
  776. while(!isPass)
  777. {
  778. isPass = true;
  779. for (byte _index = 0; _index < ShmSysConfigAndInfo->SysConfig.TotalConnectorCount; _index++)
  780. {
  781. if (!FindChargingInfoData(_index, &_chargingData[0]))
  782. {
  783. DEBUG_ERROR("Smartbox (FetchFork) : FindChargingInfoData false \n");
  784. isPass = false;
  785. break;
  786. }
  787. }
  788. sleep(1);
  789. }
  790. while(1)
  791. {
  792. for (byte gun_index = 0; gun_index < ShmSysConfigAndInfo->SysConfig.TotalConnectorCount; gun_index++)
  793. {
  794. if (chargingInfo[gun_index]->SystemStatus == SYS_MODE_IDLE ||
  795. chargingInfo[gun_index]->SystemStatus == SYS_MODE_RESERVATION ||
  796. chargingInfo[gun_index]->SystemStatus == SYS_MODE_MAINTAIN ||
  797. chargingInfo[gun_index]->SystemStatus == SYS_MODE_FAULT)
  798. {
  799. ShmSmartBoxData->ConnectorStatus[gun_index].NeedToFetch = NO;
  800. if (ShmSmartBoxData->ConnectorStatus[gun_index].ConnectorStaus != _CONNECTOR_STATUS_NONE)
  801. ShmSmartBoxData->ConnectorStatus[gun_index].ConnectorStaus = _CONNECTOR_STATUS_NONE;
  802. }
  803. // 對充電邏輯來說,充電槍只提需求
  804. else if (chargingInfo[gun_index]->SystemStatus >= SYS_MODE_MODE_REASSIGN_CHECK &&
  805. chargingInfo[gun_index]->SystemStatus <= SYS_MODE_REASSIGN)
  806. {
  807. // 判斷該群是否被使用中
  808. if (ShmPsuData->PsuGroup[gun_index].IsUsing)
  809. {
  810. // 如果使用中 : 等待把這顆模塊切出
  811. ShmSmartBoxData->ConnectorStatus[gun_index].ConnectorStaus = _CONNECTOR_STATUS_WAIT;
  812. }
  813. else
  814. {
  815. // 直接同意該群後輸出
  816. InitializeDynamicFetch(gun_index);
  817. ShmSmartBoxData->ConnectorStatus[gun_index].ConnectorStaus = _CONNECTOR_STATUS_USING;
  818. }
  819. }
  820. else if (chargingInfo[gun_index]->SystemStatus == SYS_MODE_PREPARING)
  821. {
  822. // 這個階段只會拿到屬於該槍的模塊群
  823. if (ShmDcCommonData->systemType == _SYSTEM_TYPE_SIMPLE)
  824. {
  825. // 壁掛 : 強制使用第零群
  826. AddGroup2Connector(gun_index, _PSU_GROUP_INDEX_0);
  827. }
  828. else
  829. {
  830. if (!ShmPsuData->PsuGroup[gun_index].IsUsing)
  831. {
  832. // 第一個 : Gun index
  833. // 第二個 : Psu Group index
  834. AddGroup2Connector(gun_index, gun_index);
  835. }
  836. }
  837. }
  838. else if (chargingInfo[gun_index]->SystemStatus == SYS_MODE_CHARGING)
  839. {
  840. // 判斷是否可以及需要提供多餘群輸出
  841. byte chkRemainGp = NONE_GROUP_CAN_SELECTED;
  842. if (ShmSmartBoxData->Dynamic4Fetch[gun_index].ShareGroup == NONE_GROUP_CAN_SELECTED)
  843. chkRemainGp = CheckRemainPwrByConIndex(gun_index);
  844. else
  845. chkRemainGp = ShmSmartBoxData->Dynamic4Fetch[gun_index].ShareGroup;
  846. ShmSmartBoxData->ConnectorStatus[gun_index].NeedToFetch = GetCanFetchResult(gun_index);
  847. if (ShmDcCommonData->systemType != _SYSTEM_TYPE_SIMPLE &&
  848. ShmSmartBoxData->Dynamic4Release[gun_index].ReleaseLoopStep == _PSU_DYNAMIC_RELEASE_STEP_NONE &&
  849. ((ShmSmartBoxData->ConnectorStatus[gun_index].NeedToFetch &&
  850. chkRemainGp != NONE_GROUP_CAN_SELECTED &&
  851. ShmSmartBoxData->Dynamic4Fetch[gun_index].FetchLoopStep <= _PSU_DYNAMIC_FETCH_STEP_WAIT) ||
  852. ShmDcCommonData->smartFetchRun[gun_index])
  853. )
  854. {
  855. if (!ShmSmartBoxData->SmartChk[gun_index].IsFetchStart)
  856. {
  857. // 判斷是否可以及需要提供多餘群輸出
  858. PRINTF_FUNC("Fetch Target = %d, Target Group = %d \n", gun_index, chkRemainGp);
  859. // 鎖定目標群,動態分配開始
  860. // 該群模塊即被鎖定, 預防另外一群也進入相同邏輯,預防搶同一個群的情形
  861. ShmPsuData->PsuGroup[chkRemainGp].IsUsing = YES;
  862. ShmSmartBoxData->Dynamic4Fetch[gun_index].ShareGroup = chkRemainGp;
  863. PRINTF_FUNC("***** FETCH_STEP_WAIT ***** (Gun - %d) \n", gun_index);
  864. ShmSmartBoxData->Dynamic4Fetch[gun_index].FetchLoopStep = _PSU_DYNAMIC_FETCH_STEP_WAIT;
  865. // 倒數進入動態分配邏輯 - Fetch loop
  866. ShmSmartBoxData->SmartChk [gun_index].IsFetchStart = YES;
  867. // 條件成立, 倒數 FETCH_SMART_CHK_TIME <5s>
  868. GetTimespecFunc(&ShmSmartBoxData->SmartChk[gun_index].FetchLoopTime);
  869. }
  870. else
  871. {
  872. if (ShmSmartBoxData->Dynamic4Fetch[gun_index].FetchLoopStep == _PSU_DYNAMIC_FETCH_STEP_WAIT)
  873. {
  874. int _t = GetTimeoutValue(&ShmSmartBoxData->SmartChk[gun_index].FetchLoopTime);
  875. if (_t >= FETCH_SMART_CHK_TIME)
  876. {
  877. PRINTF_FUNC("***** FETCH_STEP_TG_VOL ***** (Gun - %d) \n", gun_index);
  878. ShmSmartBoxData->Dynamic4Fetch[gun_index].FetchLoopStep = _PSU_DYNAMIC_FETCH_STEP_TG_VOL;
  879. ShmDcCommonData->smartFetchRun[gun_index] = NO;
  880. }
  881. }
  882. }
  883. }
  884. else
  885. {
  886. // 動態分配條件中斷
  887. Chk2StopFetchStep(gun_index);
  888. }
  889. }
  890. FetchLoopProcessing(gun_index);
  891. }
  892. usleep(50000);
  893. }
  894. }
  895. }
  896. //==========================================
  897. // Release fork
  898. //==========================================
  899. void InitializeDynamicRelease(byte _targetConn)
  900. {
  901. ShmSmartBoxData->Dynamic4Release[_targetConn].ReleaseGroup = NONE_GROUP_CAN_SELECTED;
  902. ShmSmartBoxData->Dynamic4Release[_targetConn].TargetRelay = NONE_RELAY_SELECTED;
  903. ShmSmartBoxData->Dynamic4Release[_targetConn].LimitCurCap = 0;
  904. ShmSmartBoxData->Dynamic4Release[_targetConn].LimitPwrCap = 0;
  905. ShmSmartBoxData->Dynamic4Release[_targetConn].LimitCur = 0;
  906. ShmSmartBoxData->Dynamic4Release[_targetConn].LimitPwr = 0;
  907. ShmSmartBoxData->Dynamic4Release[_targetConn].AutoRelease = NO;
  908. ShmSmartBoxData->Dynamic4Release[_targetConn].ReleaseLoopStep = _PSU_DYNAMIC_FETCH_STEP_FINISH;
  909. }
  910. byte CheckReleasePwrByConIndex(byte _targetConn)
  911. {
  912. byte result = NONE_GROUP_CAN_SELECTED;
  913. // 該槍已經使用的群數量
  914. byte usingCount = ShmSmartBoxData->ConnectorUsingGroupCount[_targetConn];
  915. // 不可把最後一個也拿來釋放
  916. if (usingCount - 1 > 0)
  917. result = ConnectorUsingSeq[_targetConn][usingCount - 1];
  918. return result;
  919. }
  920. void ReleaseLoopProcessing(byte _targetConn)
  921. {
  922. byte targetGroup = ShmSmartBoxData->Dynamic4Release[_targetConn].ReleaseGroup;
  923. switch(ShmSmartBoxData->Dynamic4Release[_targetConn].ReleaseLoopStep)
  924. {
  925. case _PSU_DYNAMIC_RELEASE_STEP_NONE:
  926. case _PSU_DYNAMIC_RELEASE_STEP_WAIT: {} break;
  927. case _PSU_DYNAMIC_RELEASE_STEP_LIMIT:
  928. {
  929. // 應該要通知可輸出的能量與電流
  930. // if the current and power limits are below their capacity
  931. // if (ShmSmartBoxData->Dynamic4Release[_targetConn].LimitPwr <= ShmSmartBoxData->Dynamic4Release[_targetConn].LimitPwrCap ||
  932. // chargingInfo[_targetConn]->PresentChargingCurrent * 10 <= PSU_LIMIT_CUR)
  933. if (ShmSmartBoxData->Dynamic4Release[_targetConn].LimitPwr <= ShmSmartBoxData->Dynamic4Release[_targetConn].LimitPwrCap)
  934. {
  935. PRINTF_FUNC("***** RELEASE_STEP_CUR_SHARE ***** (Gun - %d) \n", _targetConn);
  936. ShmSmartBoxData->Dynamic4Release[_targetConn].ReleaseLoopStep = _PSU_DYNAMIC_RELEASE_STEP_CUR_SHARE;
  937. }
  938. }
  939. break;
  940. case _PSU_DYNAMIC_RELEASE_STEP_CUR_SHARE:
  941. {
  942. PRINTF_FUNC("targetGroup = %d, GroupPresentOutputCurrent = %.1f \n",
  943. targetGroup,
  944. ShmPsuData->PsuGroup[targetGroup].GroupPresentOutputCurrent);
  945. // if the output current is below their capacity for 5s
  946. int _t = GetTimeoutValue(&ShmSmartBoxData->SmartChk[_targetConn].ReleaseLoopTime);
  947. if (ShmPsuData->PsuGroup[targetGroup].GroupPresentOutputCurrent <= RELEASE_STEP_CUR_SHARE &&
  948. _t >= WAIT_FOR_LIMIT_STABLE)
  949. {
  950. PRINTF_FUNC("***** RELEASE_STEP_RELAYOFF ***** (Gun - %d) \n", _targetConn);
  951. ShmSmartBoxData->Dynamic4Release[_targetConn].ReleaseLoopStep = _PSU_DYNAMIC_RELEASE_STEP_RELAYOFF;
  952. }
  953. }
  954. break;
  955. case _PSU_DYNAMIC_RELEASE_STEP_RELAYOFF:
  956. {
  957. // 釋放對應的 Relay
  958. PRINTF_FUNC("TargetRelay (%d), targetGroup = %d, ParallelRelayStatus = (%d), RcbParallelStatus = (%d) \n",
  959. ShmSmartBoxData->Dynamic4Release[_targetConn].TargetRelay, targetGroup,
  960. ShmSmartBoxData->ParallelRelayStatus[ShmSmartBoxData->Dynamic4Release[_targetConn].TargetRelay],
  961. ShmSmartBoxData->RcbParallelStatus[ShmSmartBoxData->Dynamic4Release[_targetConn].TargetRelay]);
  962. if (ShmSmartBoxData->Dynamic4Release[_targetConn].TargetRelay < ARRAY_SIZE(ShmSmartBoxData->ParallelRelayStatus))
  963. {
  964. if (ShmSmartBoxData->ParallelRelayStatus[ShmSmartBoxData->Dynamic4Release[_targetConn].TargetRelay] == NO)
  965. {
  966. if (ShmSmartBoxData->RcbParallelStatus[ShmSmartBoxData->Dynamic4Release[_targetConn].TargetRelay] == NO)
  967. {
  968. PRINTF_FUNC("***** RELEASE_STEP_WATI_FINISH ***** (Gun - %d) \n", _targetConn);
  969. ShmSmartBoxData->Dynamic4Release[_targetConn].ReleaseLoopStep = _PSU_DYNAMIC_RELEASE_STEP_WAIT_FINISH;
  970. }
  971. }
  972. }
  973. }
  974. break;
  975. case _PSU_DYNAMIC_RELEASE_STEP_WAIT_FINISH:
  976. {
  977. if(ReleaseConnectorProcessing(_targetConn, targetGroup))
  978. {
  979. GetTimespecFunc ( & ShmSmartBoxData->SmartChk [_targetConn].ReleaseLoopTime );
  980. PRINTF_FUNC("***** RELEASE_STEP_FINISH ***** (Gun - %d) \n", _targetConn);
  981. InitializeDynamicRelease(_targetConn);
  982. ShmSmartBoxData->Dynamic4Release[_targetConn].ReleaseLoopStep = _PSU_DYNAMIC_RELEASE_STEP_FINISH;
  983. }
  984. }
  985. break;
  986. case _PSU_DYNAMIC_RELEASE_STEP_FINISH:
  987. {
  988. // 完成
  989. int _t = GetTimeoutValue(&ShmSmartBoxData->SmartChk[_targetConn].ReleaseLoopTime);
  990. if (_t >= RELEASE_FINISH_WAIT_TIME)
  991. {
  992. PRINTF_FUNC("***** RELEASE_STEP_NONE ***** (Gun - %d) \n", _targetConn);
  993. ShmSmartBoxData->SmartChk[_targetConn].IsReleaseStart = NO;
  994. ShmSmartBoxData->Dynamic4Release[_targetConn].ReleaseLoopStep = _PSU_DYNAMIC_RELEASE_STEP_NONE;
  995. }
  996. }
  997. break;
  998. case _PSU_DYNAMIC_RELEASE_STEP_ABORT:
  999. {
  1000. GetTimespecFunc(& ShmSmartBoxData->SmartChk [_targetConn].ReleaseLoopTime);
  1001. PRINTF_FUNC("***** RELEASE_STEP_FINISH ***** (Gun - %d) \n", _targetConn);
  1002. InitializeDynamicRelease(_targetConn);
  1003. ShmSmartBoxData->Dynamic4Release[_targetConn].ReleaseLoopStep = _PSU_DYNAMIC_RELEASE_STEP_FINISH;
  1004. }
  1005. break;
  1006. }
  1007. }
  1008. void Chk2StopReleaseStep(byte _targetConn)
  1009. {
  1010. // 開始流程後,就讓流程走完吧~
  1011. if (ShmSmartBoxData->Dynamic4Release [_targetConn].ReleaseGroup > _PSU_DYNAMIC_RELEASE_STEP_NONE &&
  1012. ShmSmartBoxData->Dynamic4Release [_targetConn].ReleaseGroup < _PSU_DYNAMIC_RELEASE_STEP_LIMIT)
  1013. {
  1014. PRINTF_FUNC ( "***** RELEASE_STEP_ABORT ***** (Gun - %d) \n", _targetConn );
  1015. //ShmSmartBoxData->Dynamic4Release [_targetConn].ReleaseGroup = _PSU_DYNAMIC_RELEASE_STEP_ABORT;
  1016. }
  1017. else
  1018. ShmSmartBoxData->SmartChk[_targetConn].IsReleaseStart = NO;
  1019. }
  1020. bool GetCanReleaseResult(byte gun_index, byte releaseGp)
  1021. {
  1022. bool result = false;
  1023. unsigned short releasePwr = ShmPsuData->PsuGroup[releaseGp].TotalRatingPower * 10;
  1024. float needPower = chargingInfo[gun_index]->PresentChargingVoltage *
  1025. chargingInfo[gun_index]->EvBatterytargetCurrent / 100;
  1026. result = (chargingInfo[gun_index]->RealRatingPower > 0 && releasePwr > 0 &&
  1027. needPower < chargingInfo[gun_index]->RealRatingPower - releasePwr - CAP_GAP_RELEASE) ? true : false;
  1028. if (result)
  1029. {
  1030. // afterReleaseMdCur 每個模塊最大 100A : 1A
  1031. float afterReleaseMdCur = chargingInfo[gun_index]->AvailableChargingCurrent -
  1032. ShmPsuData->PsuGroup[releaseGp].GroupAvailableCurrent;
  1033. result = (chargingInfo[gun_index]->EvBatterytargetCurrent >= afterReleaseMdCur - LIMIT_PWR_MODULE_GAP) ? false : true;
  1034. }
  1035. return result;
  1036. }
  1037. void ReleaseFork()
  1038. {
  1039. pid_t releasePid;
  1040. releasePid = fork();
  1041. if(releasePid > 0)
  1042. {
  1043. bool isPass = false;
  1044. struct ChargingInfoData *_chargingData[CHAdeMO_QUANTITY + CCS_QUANTITY + GB_QUANTITY];
  1045. while(!isPass)
  1046. {
  1047. isPass = true;
  1048. for (byte _index = 0; _index < ShmSysConfigAndInfo->SysConfig.TotalConnectorCount; _index++)
  1049. {
  1050. if (!FindChargingInfoData(_index, &_chargingData[0]))
  1051. {
  1052. DEBUG_ERROR("Smartbox (ReleaseFork) : FindChargingInfoData false \n");
  1053. isPass = false;
  1054. break;
  1055. }
  1056. }
  1057. sleep(1);
  1058. }
  1059. while(1)
  1060. {
  1061. for (byte gun_index = 0; gun_index < ShmSysConfigAndInfo->SysConfig.TotalConnectorCount; gun_index++)
  1062. {
  1063. if (chargingInfo[gun_index]->SystemStatus == SYS_MODE_CHARGING)
  1064. {
  1065. // 釋出多餘群 : 要判斷所要釋出群所能提供的最大能量 RealRatingPower
  1066. // 先找到是否有下一個要釋出的群
  1067. byte releaseGp = CheckReleasePwrByConIndex(gun_index);
  1068. if (releaseGp != NONE_GROUP_CAN_SELECTED)
  1069. {
  1070. bool canRelease = GetCanReleaseResult(gun_index, releaseGp);
  1071. if (chargingInfo[gun_index]->Type != _Type_Test &&
  1072. ShmSmartBoxData->Dynamic4Fetch[gun_index].FetchLoopStep == _PSU_DYNAMIC_FETCH_STEP_NONE &&
  1073. (ShmSmartBoxData->AnotherConnectorStatus[gun_index].ConnectorStaus == _CONNECTOR_STATUS_WAIT ||
  1074. (ShmSmartBoxData->AnotherConnectorStatus[gun_index].NeedToFetch &&
  1075. SMART_MODE && chargingInfo[gun_index]->_TakePsuGpCount > ShmDcCommonData->halfGroupCount) ||
  1076. canRelease ||
  1077. ShmDcCommonData->smartReleaseRun[gun_index])
  1078. )
  1079. {
  1080. //PRINTF_FUNC("RealRatingPower = %d \n", chargingInfo[gun_index]->RealRatingPower);
  1081. //PRINTF_FUNC("releasePwr = %d, needPower = %f \n", releasePwr, needPower);
  1082. if (ShmSmartBoxData->Dynamic4Release[gun_index].ReleaseLoopStep == _PSU_DYNAMIC_RELEASE_STEP_NONE)
  1083. {
  1084. if (!ShmSmartBoxData->SmartChk[gun_index].IsReleaseStart)
  1085. {
  1086. PRINTF_FUNC("***** Entry release chk (Gun_%d).. ***** \n", gun_index);
  1087. ShmSmartBoxData->SmartChk[gun_index].IsReleaseStart = YES;
  1088. ShmSmartBoxData->Dynamic4Release[gun_index].CheckOutPwrIsStable = chargingInfo[gun_index]->PresentChargingPower;
  1089. GetTimespecFunc(&ShmSmartBoxData->SmartChk[gun_index].ReleaseLoopTime);
  1090. }
  1091. else
  1092. {
  1093. int _delayt = GetTimeoutValue(&ShmSmartBoxData->SmartChk[gun_index].ReleaseLoopTime);
  1094. // 每五秒看一次輸出能量是否穩定, 穩定則進入分配
  1095. if (_delayt >= RELEASE_STABLE_CHK_TIME)
  1096. {
  1097. if (chargingInfo[gun_index]->PresentChargingPower >
  1098. ShmSmartBoxData->Dynamic4Release[gun_index].CheckOutPwrIsStable + STABLE_CAP_GAP)
  1099. {
  1100. ShmSmartBoxData->Dynamic4Release[gun_index].CheckOutPwrIsStable = chargingInfo[gun_index]->PresentChargingPower;
  1101. GetTimespecFunc(&ShmSmartBoxData->SmartChk[gun_index].ReleaseLoopTime);
  1102. }
  1103. else
  1104. {
  1105. // 進入穩定
  1106. PRINTF_FUNC("***** RELEASE_STEP_WAIT ***** \n");
  1107. ShmSmartBoxData->Dynamic4Release[gun_index].ReleaseLoopStep = _PSU_DYNAMIC_RELEASE_STEP_WAIT;
  1108. GetTimespecFunc(&ShmSmartBoxData->SmartChk[gun_index].ReleaseLoopTime);
  1109. }
  1110. }
  1111. }
  1112. }
  1113. else if (ShmSmartBoxData->Dynamic4Release[gun_index].ReleaseLoopStep == _PSU_DYNAMIC_RELEASE_STEP_WAIT)
  1114. {
  1115. int _delayt = GetTimeoutValue(&ShmSmartBoxData->SmartChk[gun_index].ReleaseLoopTime);
  1116. // 每五秒看一次輸出能量是否穩定, 穩定則進入分配
  1117. if (_delayt >= RELEASE_SMART_CHK_TIME)
  1118. {
  1119. PRINTF_FUNC("***** RELEASE_STEP_LIMIT ***** \n");
  1120. ShmSmartBoxData->Dynamic4Release[gun_index].ReleaseGroup = releaseGp;
  1121. ShmSmartBoxData->Dynamic4Release[gun_index].ReleaseLoopStep = _PSU_DYNAMIC_RELEASE_STEP_LIMIT;
  1122. ShmDcCommonData->smartReleaseRun[gun_index] = NO;
  1123. }
  1124. }
  1125. }
  1126. else
  1127. {
  1128. // 動態分配條件中斷
  1129. Chk2StopReleaseStep(gun_index);
  1130. }
  1131. }
  1132. }
  1133. else if (chargingInfo[gun_index]->SystemStatus == SYS_MODE_IDLE ||
  1134. chargingInfo[gun_index]->SystemStatus == SYS_MODE_FAULT ||
  1135. chargingInfo[gun_index]->SystemStatus == SYS_MODE_RESERVATION ||
  1136. (chargingInfo[gun_index]->SystemStatus >= SYS_MODE_TERMINATING &&
  1137. chargingInfo[gun_index]->SystemStatus <= SYS_MODE_ALARM))
  1138. {
  1139. if (ShmSmartBoxData->ConnectorStatus[gun_index].ConnectorStaus == _CONNECTOR_STATUS_NONE)
  1140. {
  1141. byte totoalUsingGpCount = ShmSmartBoxData->ConnectorUsingGroupCount[gun_index];
  1142. for (byte _gp = 0; _gp < totoalUsingGpCount; _gp++)
  1143. {
  1144. PRINTF_FUNC("ConnectorUsingSeq[%d][%d] = %d \n", gun_index, _gp, ConnectorUsingSeq[gun_index][_gp]);
  1145. ReleaseConnectorProcessing(gun_index, ConnectorUsingSeq[gun_index][_gp]);
  1146. }
  1147. if (ShmSmartBoxData->Dynamic4Fetch[gun_index].ShareGroup != NONE_GROUP_CAN_SELECTED &&
  1148. ShmSmartBoxData->Dynamic4Fetch[gun_index].FetchLoopStep < _PSU_DYNAMIC_FETCH_STEP_FINISH)
  1149. ShmSmartBoxData->Dynamic4Fetch[gun_index].FetchLoopStep = _PSU_DYNAMIC_FETCH_STEP_ABORT;
  1150. ShmSmartBoxData->Dynamic4Release[gun_index].ReleaseLoopStep = _PSU_DYNAMIC_RELEASE_STEP_NONE;
  1151. }
  1152. if (ShmSmartBoxData->ConnectorStatus[gun_index].NeedToFetch)
  1153. ShmSmartBoxData->ConnectorStatus[gun_index].NeedToFetch = NO;
  1154. }
  1155. ReleaseLoopProcessing(gun_index);
  1156. }
  1157. usleep(50000);
  1158. }
  1159. }
  1160. }
  1161. //==========================================
  1162. // Main Function
  1163. //==========================================
  1164. void TakeAnotherGunStatus(byte target)
  1165. {
  1166. byte another = 0;
  1167. if (target == 0)
  1168. another = 1;
  1169. ShmSmartBoxData->AnotherConnectorStatus[another].ConnectorStaus = ShmSmartBoxData->ConnectorStatus[target].ConnectorStaus;
  1170. ShmSmartBoxData->AnotherConnectorStatus[another].NeedToFetch = ShmSmartBoxData->ConnectorStatus[target].NeedToFetch;
  1171. }
  1172. void AssignedPwr2Connector()
  1173. {
  1174. for(byte _gun = 0; _gun < ShmSysConfigAndInfo->SysConfig.TotalConnectorCount; _gun++)
  1175. {
  1176. byte usingGroupCount = 0;
  1177. float availablePwr = 0, availableCur = 0, iAvailableCur = 0, totalPsuCount = 0, kwAvailablePwr = 0;
  1178. float outputVol = 0, outputCur = 0;
  1179. float limitCur = 0, limitPwr = 0, remainCur = 0;
  1180. for (byte group = 0; group < ShmPsuData->GroupCount; group++)
  1181. {
  1182. if (ShmPsuData->PsuGroup[group].UsingTarget == _gun)
  1183. {
  1184. usingGroupCount++;
  1185. if (group != ShmSmartBoxData->Dynamic4Fetch[_gun].ShareGroup &&
  1186. (group != ShmSmartBoxData->Dynamic4Release[_gun].ReleaseGroup ||
  1187. ShmSmartBoxData->Dynamic4Release[_gun].ReleaseLoopStep <= _PSU_DYNAMIC_RELEASE_STEP_WAIT_FINISH))
  1188. {
  1189. availablePwr += ShmPsuData->PsuGroup[group].GroupAvailablePower;
  1190. availableCur += ShmPsuData->PsuGroup[group].GroupAvailableCurrent;
  1191. iAvailableCur += ShmPsuData->PsuGroup[group].TotalIAvailableCurrent;
  1192. totalPsuCount += ShmPsuData->PsuGroup[group].GroupPresentPsuQuantity;
  1193. if (ShmPsuData->PsuGroup[group].TotalRatingPower <= 15 ||
  1194. ShmPsuData->PsuGroup[group].TotalRatingPower > 30)
  1195. kwAvailablePwr += (ShmPsuData->PsuGroup[group].GroupAvailablePower) / 10;
  1196. else
  1197. kwAvailablePwr += ShmPsuData->PsuGroup[group].TotalRatingPower;
  1198. }
  1199. // Release Loop 用 : 實際上~ 電流會飄 ....
  1200. // 這段, 只取還要留住的模塊輸出電流與能量就好
  1201. if (group != ShmSmartBoxData->Dynamic4Release[_gun].ReleaseGroup &&
  1202. ShmSmartBoxData->Dynamic4Release[_gun].ReleaseLoopStep == _PSU_DYNAMIC_RELEASE_STEP_LIMIT)
  1203. {
  1204. limitCur += ShmPsuData->PsuGroup[group].GroupTargetOutputCurrent;
  1205. remainCur += ShmPsuData->PsuGroup[group].TotalIAvailableCurrent;
  1206. limitPwr += ShmPsuData->PsuGroup[group].TotalRatingPower;
  1207. }
  1208. outputCur += ShmPsuData->PsuGroup[group].GroupPresentOutputCurrent;
  1209. if (outputVol < ShmPsuData->PsuGroup[group].GroupPresentOutputVoltage ||
  1210. outputVol == 0)
  1211. outputVol = ShmPsuData->PsuGroup[group].GroupPresentOutputVoltage;
  1212. }
  1213. }
  1214. chargingInfo[_gun]->AvailableChargingPower = availablePwr;
  1215. chargingInfo[_gun]->AvailableChargingCurrent = availableCur;
  1216. chargingInfo[_gun]->DeratingChargingCurrent = iAvailableCur;
  1217. chargingInfo[_gun]->_TotalPsuCount = totalPsuCount;
  1218. chargingInfo[_gun]->PresentChargingVoltage = outputVol / 10;
  1219. // 在低於最大 1KW 輸出時~ 讓我們偷雞一下~
  1220. if (chargingInfo[_gun]->SystemStatus == SYS_MODE_CHARGING)
  1221. {
  1222. if (chargingInfo[_gun]->RealMaxPower <= 10 && outputCur < (chargingInfo[_gun]->RealMaxCurrent * 0.9))
  1223. outputCur = (chargingInfo[_gun]->RealMaxCurrent * 0.9);
  1224. }
  1225. chargingInfo[_gun]->PresentChargingCurrent = outputCur / 10;
  1226. chargingInfo[_gun]->RealRatingPower = kwAvailablePwr * 10;
  1227. chargingInfo[_gun]->_TakePsuGpCount = usingGroupCount;
  1228. // 雙槍需要記得另外一把槍的狀態
  1229. if (ShmSysConfigAndInfo->SysConfig.TotalConnectorCount > 1)
  1230. TakeAnotherGunStatus(_gun);
  1231. // 取 Release group 的最大電流
  1232. if (ShmSmartBoxData->Dynamic4Release[_gun].ReleaseLoopStep == _PSU_DYNAMIC_RELEASE_STEP_LIMIT &&
  1233. ShmSmartBoxData->Dynamic4Release[_gun].LimitPwrCap == 0)
  1234. {
  1235. // limitCur : 下給剩餘群的需求電流
  1236. //ShmSmartBoxData->Dynamic4Release[_gun].LimitCurCap = limitCur;
  1237. // Release 均流想法(總結) : 如果是抽載不足的自然釋放~ 應該都會跑均流方式
  1238. // 狀況一 : 群1 : 30A,群2 : 30A 共 60A 輸出,且實際上群1 可提供的電流為 75A (400V 輸出)
  1239. // 狀況二 : 群1 : 75A,群2 : 75A 共 150A 輸出,且實際上群1 可提供的電流為 75A (400V 輸出)
  1240. // 狀況三 : 群1 : 70A,群2 : 70A 共 140A 輸出,且實際上群1 可提供的電流為 75A (400V 輸出)
  1241. // ---------------------------------------------
  1242. // 狀況一 : 60A <= 群1可提供的 75A : 均流
  1243. // 狀況一 : 150A > 群1可提供的 75A : 直接切斷
  1244. // 狀況一 : 140A > 群1可提供的 75A : 直接切斷
  1245. if (chargingInfo[_gun]->PresentChargingCurrent <= remainCur)
  1246. {
  1247. PRINTF_FUNC("PresentChargingCurrent = %f, remainCur = %f \n", chargingInfo[_gun]->PresentChargingCurrent, remainCur / 10);
  1248. limitCur = chargingInfo[_gun]->PresentChargingCurrent * 10;
  1249. ShmSmartBoxData->Dynamic4Release[_gun].AutoRelease = YES;
  1250. }
  1251. else
  1252. PRINTF_FUNC("limitCur = %f \n", limitCur);
  1253. ShmSmartBoxData->Dynamic4Release[_gun].LimitCurCap = limitCur;
  1254. ShmSmartBoxData->Dynamic4Release[_gun].LimitPwrCap = limitPwr * 10;
  1255. }
  1256. }
  1257. }
  1258. void CollectGroupInformation(byte group)
  1259. {
  1260. int _groupPower = 0 , _groupCurrent = 0 , _groupMaxVoltage = 0;
  1261. int Iavail = 0, Pavail = 0;
  1262. unsigned short _outputVolBuf = 0, _outputCurBuf = 0;
  1263. for (byte index = 0; index < ShmPsuData->PsuGroup[group].GroupPresentPsuQuantity; index ++)
  1264. {
  1265. // Cap
  1266. _groupCurrent += ShmPsuData->PsuGroup[group].PsuModule[index].AvailableCurrent;
  1267. _groupPower += ShmPsuData->PsuGroup[group].PsuModule[index].AvailablePower;
  1268. if (ShmPsuData->PsuGroup[group].PsuModule[index].PresentMaxOutputVoltage > _groupMaxVoltage)
  1269. _groupMaxVoltage = ShmPsuData->PsuGroup[group].PsuModule[index].PresentMaxOutputVoltage;
  1270. // Iavailable
  1271. Iavail += ShmPsuData->PsuGroup[group].PsuModule[index].IAvailableCurrent;
  1272. Pavail += ShmPsuData->PsuGroup[group].PsuModule[index].KwAvailablePower;
  1273. // output
  1274. _outputCurBuf += ShmPsuData->PsuGroup[group].PsuModule[index].PresentOutputCurrent;
  1275. if (_outputVolBuf == 0 ||
  1276. (ShmPsuData->PsuGroup[group].PsuModule[index].PresentOutputVoltage > PSU_MIN_VOL &&
  1277. _outputVolBuf < ShmPsuData->PsuGroup[group].PsuModule[index].PresentOutputVoltage))
  1278. {
  1279. _outputVolBuf = ShmPsuData->PsuGroup[group].PsuModule[index].PresentOutputVoltage;
  1280. }
  1281. }
  1282. ShmPsuData->PsuGroup[group].GroupMaxVoltage = _groupMaxVoltage;
  1283. ShmPsuData->PsuGroup[group].GroupAvailableCurrent = _groupCurrent;
  1284. ShmPsuData->PsuGroup[group].GroupAvailablePower = _groupPower;
  1285. ShmPsuData->PsuGroup[group].TotalIAvailableCurrent = Iavail;
  1286. ShmPsuData->PsuGroup[group].TotalRatingPower = Pavail;
  1287. ShmPsuData->PsuGroup[group].GroupPresentOutputVoltage = _outputVolBuf;
  1288. ShmPsuData->PsuGroup[group].GroupPresentOutputCurrent = _outputCurBuf;
  1289. }
  1290. void CollectPsuInformation()
  1291. {
  1292. int _sysPwr = 0, _sysCur = 0, _sysVol = 0;
  1293. for (byte group = 0; group < ShmPsuData->GroupCount; group++)
  1294. {
  1295. // 取群資訊
  1296. CollectGroupInformation(group);
  1297. // 整理系統資訊
  1298. _sysPwr += ShmPsuData->PsuGroup[group].GroupAvailablePower;
  1299. _sysCur += ShmPsuData->PsuGroup[group].GroupAvailableCurrent;
  1300. if (ShmPsuData->PsuGroup[group].GroupMaxVoltage > _sysVol)
  1301. _sysVol = ShmPsuData->PsuGroup[group].GroupMaxVoltage;
  1302. }
  1303. // 系統,電壓,電流,能量
  1304. ShmPsuData->SystemAvailableCurrent = _sysCur;
  1305. ShmPsuData->SystemAvailablePower = _sysPwr;
  1306. GetSystemMaxVoltage();
  1307. }
  1308. //==========================================
  1309. // Main Loop
  1310. //==========================================
  1311. int main(void)
  1312. {
  1313. if(InitShareMemory() == FAIL)
  1314. {
  1315. #ifdef SystemLogMessage
  1316. DEBUG_ERROR("InitShareMemory NG\n");
  1317. #endif
  1318. if(ShmStatusCodeData != NULL)
  1319. {
  1320. ShmStatusCodeData->AlarmCode.AlarmEvents.bits.FailToCreateShareMemory = 1;
  1321. }
  1322. sleep(5);
  1323. return 0;
  1324. }
  1325. Initialization();
  1326. // 對充電槍操作 : 將模塊切出來與補上剩餘的模塊功率
  1327. FetchFork();
  1328. ReleaseFork();
  1329. GetTimespecFunc(&_log_time);
  1330. while(1)
  1331. {
  1332. if (ShmPsuData->Work_Step >= GET_SYS_CAP)
  1333. {
  1334. // 收集來自 PSU 的資訊
  1335. CollectPsuInformation();
  1336. // 將群資訊分配到對應的使用中充電槍
  1337. AssignedPwr2Connector();
  1338. int time = GetTimeoutValue(&_log_time);
  1339. if (time < 0)
  1340. GetTimespecFunc(&_log_time);
  1341. // 低 Priority 的指令
  1342. if (time > 5000)
  1343. {
  1344. //PrintfLog();
  1345. GetTimespecFunc(&_log_time);
  1346. }
  1347. }
  1348. if (ShmDcCommonData->systemType != _SYSTEM_TYPE_SIMPLE &&
  1349. ShmPsuData->Work_Step == _WORK_CHARGING)
  1350. {
  1351. // 橋接控制
  1352. SmartRelayCheck();
  1353. }
  1354. usleep(50000);
  1355. }
  1356. return -1;
  1357. }