Module_PsuComm.c 30 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938
  1. #include "Module_PsuComm.h"
  2. #define Debug
  3. #define ARRAY_SIZE(A) (sizeof(A) / sizeof(A[0]))
  4. #define PASS 1
  5. #define FAIL -1
  6. #define YES 1
  7. #define NO 0
  8. #define SELF_TEST 0
  9. struct SysConfigAndInfo *ShmSysConfigAndInfo;
  10. struct StatusCodeData *ShmStatusCodeData;
  11. struct PsuData *ShmPsuData;
  12. void trim(char *s);
  13. int mystrcmp(char *p1,char *p2);
  14. void substr(char *dest, const char* src, unsigned int start, unsigned int cnt);
  15. void split(char **arr, char *str, const char *del);
  16. bool libInitialize = false;
  17. byte gun_count = CHAdeMO_QUANTITY + CCS_QUANTITY + GB_QUANTITY;
  18. byte getAvailableCapOffset = 5;
  19. float carReqVol = 0;
  20. float carReqCur = 0;
  21. float evseOutVol = 0;
  22. float evseOutCur = 0;
  23. int cmdDelayTime = 30000;
  24. int StoreLogMsg(const char *fmt, ...);
  25. #define DEBUG_INFO(format, args...) StoreLogMsg("[%s:%d][%s][Info] "format, __FILE__, __LINE__, __FUNCTION__, ##args)
  26. #define DEBUG_WARN(format, args...) StoreLogMsg("[%s:%d][%s][Warn] "format, __FILE__, __LINE__, __FUNCTION__, ##args)
  27. #define DEBUG_ERROR(format, args...) StoreLogMsg("[%s:%d][%s][Error] "format, __FILE__, __LINE__, __FUNCTION__, ##args)
  28. unsigned long GetTimeoutValue(struct timeval _sour_time);
  29. unsigned long GetTimeoutValue(struct timeval _sour_time)
  30. {
  31. struct timeval _end_time;
  32. gettimeofday(&_end_time, NULL);
  33. return 1000000 * (_end_time.tv_sec - _sour_time.tv_sec) + _end_time.tv_usec - _sour_time.tv_usec;
  34. }
  35. int StoreLogMsg(const char *fmt, ...)
  36. {
  37. char Buf[4096+256];
  38. char buffer[4096];
  39. time_t CurrentTime;
  40. struct tm *tm;
  41. va_list args;
  42. va_start(args, fmt);
  43. int rc = vsnprintf(buffer, sizeof(buffer), fmt, args);
  44. va_end(args);
  45. memset(Buf,0,sizeof(Buf));
  46. CurrentTime = time(NULL);
  47. tm=localtime(&CurrentTime);
  48. sprintf(Buf,"echo \"%04d-%02d-%02d %02d:%02d:%02d - %s\" >> /Storage/SystemLog/[%04d.%02d]SystemLog",
  49. tm->tm_year+1900,tm->tm_mon+1,tm->tm_mday,tm->tm_hour,tm->tm_min,tm->tm_sec,
  50. buffer,
  51. tm->tm_year+1900,tm->tm_mon+1);
  52. system(Buf);
  53. return rc;
  54. }
  55. int DiffTimeb(struct timeb ST, struct timeb ET)
  56. {
  57. //return milli-second
  58. unsigned int StartTime,StopTime;
  59. StartTime=(unsigned int)ST.time;
  60. StopTime=(unsigned int)ET.time;
  61. return (StopTime-StartTime)*1000+ET.millitm-ST.millitm;
  62. }
  63. //=================================
  64. // Common routine
  65. //=================================
  66. char* getTimeString(void)
  67. {
  68. char *result=malloc(21);
  69. time_t timep;
  70. struct tm *p;
  71. time(&timep);
  72. p=gmtime(&timep);
  73. sprintf(result, "[%04d-%02d-%02d %02d:%02d:%02d]", (1900+p->tm_year), (1+p->tm_mon), p->tm_mday, p->tm_hour, p->tm_hour, p->tm_sec);
  74. return result;
  75. }
  76. void trim(char *s)
  77. {
  78. int i=0, j, k, l=0;
  79. while((s[i]==' ')||(s[i]=='\t')||(s[i]=='\n'))
  80. i++;
  81. j = strlen(s)-1;
  82. while((s[j]==' ')||(s[j]=='\t')||(s[j]=='\n'))
  83. j--;
  84. if(i==0 && j==strlen(s)-1) { }
  85. else if(i==0) s[j+1] = '\0';
  86. else {
  87. for(k=i; k<=j; k++) s[l++] = s[k];
  88. s[l] = '\0';
  89. }
  90. }
  91. int mystrcmp(char *p1,char *p2)
  92. {
  93. while(*p1==*p2)
  94. {
  95. if(*p1=='\0' || *p2=='\0')
  96. break;
  97. p1++;
  98. p2++;
  99. }
  100. if(*p1=='\0' && *p2=='\0')
  101. return(PASS);
  102. else
  103. return(FAIL);
  104. }
  105. void substr(char *dest, const char* src, unsigned int start, unsigned int cnt)
  106. {
  107. strncpy(dest, src + start, cnt);
  108. dest[cnt] = 0;
  109. }
  110. void split(char **arr, char *str, const char *del)
  111. {
  112. char *s = strtok(str, del);
  113. while(s != NULL)
  114. {
  115. *arr++ = s;
  116. s = strtok(NULL, del);
  117. }
  118. }
  119. //=================================
  120. // Save data to share memory Function
  121. //=================================
  122. bool FindChargingInfoData(byte target, struct ChargingInfoData **chargingData)
  123. {
  124. for (byte index = 0; index < CHAdeMO_QUANTITY; index++)
  125. {
  126. if (ShmSysConfigAndInfo->SysInfo.ChademoChargingData[index].Index == target)
  127. {
  128. chargingData[target] = &ShmSysConfigAndInfo->SysInfo.ChademoChargingData[index];
  129. return true;
  130. }
  131. }
  132. for (byte index = 0; index < CCS_QUANTITY; index++)
  133. {
  134. if (ShmSysConfigAndInfo->SysInfo.CcsChargingData[index].Index == target)
  135. {
  136. chargingData[target] = &ShmSysConfigAndInfo->SysInfo.CcsChargingData[index];
  137. return true;
  138. }
  139. }
  140. for (byte index = 0; index < GB_QUANTITY; index++)
  141. {
  142. if (ShmSysConfigAndInfo->SysInfo.GbChargingData[index].Index == target)
  143. {
  144. chargingData[target] = &ShmSysConfigAndInfo->SysInfo.GbChargingData[index];
  145. return true;
  146. }
  147. }
  148. return false;
  149. }
  150. void GetPsuRequestCallback(byte phy_id, char *serial_number)
  151. {
  152. if (ShmSysConfigAndInfo->SysInfo.AcContactorStatus == NO)
  153. return;
  154. //printf("++++++++++++++++++++phy_id = %d \n", phy_id);
  155. // ********************** 每次送電後,需判斷要把所有的模塊分配到哪個 Group **********************
  156. byte group = 0;
  157. if(ShmSysConfigAndInfo->SysInfo.BootingStatus == BOOTTING || gun_count == 1)
  158. {
  159. // 初始化狀態,則直接先分配到同個群
  160. group = 0;
  161. }
  162. else
  163. {
  164. group = ShmSysConfigAndInfo->SysInfo.CurGunSelected;
  165. }
  166. bool isNewPsu = true;
  167. for (byte index = 0; index < ShmPsuData->PsuGroup[group].GroupPresentPsuQuantity; index++)
  168. {
  169. if (ShmPsuData->PsuGroup[group].PsuModule[index].PhysicalID == phy_id &&
  170. strncmp((char *)ShmPsuData->PsuGroup[group].PsuModule[index].SerialNumber, serial_number, 7) == 0)
  171. {
  172. isNewPsu = false;
  173. }
  174. }
  175. if (isNewPsu)
  176. {
  177. ShmPsuData->SystemPresentPsuQuantity++;
  178. printf("get psu********Membar = %d, group = %d \n", ShmPsuData->SystemPresentPsuQuantity, group);
  179. if (ShmPsuData->Work_Step >= _TEST_LINE_STEP && ShmPsuData->Work_Step <= _TEST_COMPLETE)
  180. {
  181. // 已經進入火線上的驗證動作
  182. ShmPsuData->NeedBackTest = YES;
  183. }
  184. else if (ShmPsuData->Work_Step == _WORK_CHARGING)
  185. {
  186. // 一旦進入火線,分配一個不會用到的給該模塊
  187. group++;
  188. }
  189. ShmPsuData->PsuGroup[group].PsuModule[ShmPsuData->PsuGroup[group].GroupPresentPsuQuantity].Address = ShmPsuData->SystemPresentPsuQuantity;
  190. ShmPsuData->PsuGroup[group].PsuModule[ShmPsuData->PsuGroup[group].GroupPresentPsuQuantity].PhysicalID = phy_id;
  191. ShmPsuData->PsuGroup[group].PsuModule[ShmPsuData->PsuGroup[group].GroupPresentPsuQuantity].AssignID = (group >> 6) + ShmPsuData->SystemPresentPsuQuantity;
  192. strcpy((char *)ShmPsuData->PsuGroup[group].PsuModule[ShmPsuData->PsuGroup[group].GroupPresentPsuQuantity].SerialNumber, serial_number);
  193. ShmPsuData->PsuGroup[group].GroupPresentPsuQuantity++;
  194. //PsuAddressAssignment(phy_id, serial_number, ShmPsuData->SystemPresentPsuQuantity, group);
  195. PsuAddressAssignment(phy_id, group);
  196. if (ShmPsuData->Work_Step != _WORK_CHARGING)
  197. {
  198. ShmPsuData->GroupCount = group + 1;
  199. }
  200. }
  201. }
  202. void SaveStatusCallback(byte group, byte address, char cri_temp1, int alarm)
  203. {
  204. //EVSE
  205. //for (byte groupIndex = 0; groupIndex < ShmPsuData->GroupCount; groupIndex++)
  206. //{
  207. for (byte index = 0; index < ShmPsuData->PsuGroup[group].GroupPresentPsuQuantity; index++)
  208. {
  209. if (ShmPsuData->PsuGroup[group].PsuModule[index].PhysicalID == address)
  210. {
  211. ShmPsuData->PsuGroup[group].PsuModule[index].CriticalTemp1 = cri_temp1;
  212. //ShmPsuData->PsuGroup[group].PsuModule[index].INFYPWR_Alarm.AlarmCode = alarm;
  213. break;
  214. }
  215. }
  216. //printf ("psu alarm = %08x \n", alarm);
  217. //}
  218. }
  219. //模組三向輸入電壓
  220. void SavePresentInputVoltageCallback(byte address, unsigned short vol1, unsigned short vol2, unsigned short vol3)
  221. {
  222. bool isSearch = false;
  223. //EVSE
  224. //search group
  225. for (byte groupIndex = 0; groupIndex < ShmPsuData->GroupCount; groupIndex++)
  226. {
  227. for (byte index = 0; index < ShmPsuData->PsuGroup[groupIndex].GroupPresentPsuQuantity; index++)
  228. {
  229. //search id
  230. if (ShmPsuData->PsuGroup[groupIndex].PsuModule[index].PhysicalID == address)
  231. {
  232. //update module msg
  233. ShmPsuData->PsuGroup[groupIndex].PsuModule[index].InputVoltageL1 = vol1;
  234. ShmPsuData->PsuGroup[groupIndex].PsuModule[index].InputVoltageL2 = vol2;
  235. ShmPsuData->PsuGroup[groupIndex].PsuModule[index].InputVoltageL3 = vol3;
  236. isSearch = true;
  237. break;
  238. }
  239. }
  240. if(isSearch) break;
  241. }
  242. }
  243. // 模塊輸出的電壓電流
  244. void SavePresentOutputCallback(byte address, unsigned short out_vol, unsigned short out_cur)
  245. {
  246. unsigned short outputVol = 0;
  247. unsigned short outputCur = 0;
  248. unsigned short group = 0;
  249. bool isChange = false;
  250. // PSU
  251. for (byte groupIndex = 0; groupIndex < ShmPsuData->GroupCount; groupIndex++)
  252. {
  253. for (int index = 0; index < ShmPsuData->PsuGroup[groupIndex].GroupPresentPsuQuantity; index++)
  254. {
  255. if (ShmPsuData->PsuGroup[groupIndex].PsuModule[index].PhysicalID == address)
  256. {
  257. ShmPsuData->PsuGroup[groupIndex].PsuModule[index].PresentOutputVoltage = out_vol;
  258. ShmPsuData->PsuGroup[groupIndex].PsuModule[index].PresentOutputCurrent = out_cur;
  259. for (int loop = 0; loop < ShmPsuData->PsuGroup[groupIndex].GroupPresentPsuQuantity; loop++)
  260. {
  261. //update voltage
  262. if (ShmPsuData->PsuGroup[groupIndex].PsuModule[loop].PresentOutputVoltage > outputVol)
  263. {
  264. outputVol = ShmPsuData->PsuGroup[groupIndex].PsuModule[loop].PresentOutputVoltage;
  265. }
  266. //update total current
  267. outputCur += ShmPsuData->PsuGroup[groupIndex].PsuModule[index].PresentOutputCurrent;
  268. group = groupIndex;
  269. isChange = true;
  270. }
  271. }
  272. /*
  273. if (ShmPsuData->PsuGroup[group].PsuModule[index].PresentOutputVoltage > outputVol)
  274. outputVol = ShmPsuData->PsuGroup[group].PsuModule[index].PresentOutputVoltage;
  275. outputCur += ShmPsuData->PsuGroup[group].PsuModule[index].PresentOutputCurrent;
  276. */
  277. }
  278. }
  279. if (isChange)
  280. {
  281. // PSU Group
  282. // 電壓
  283. ShmPsuData->PsuGroup[group].GroupPresentOutputVoltage = outputVol;
  284. // 電流
  285. ShmPsuData->PsuGroup[group].GroupPresentOutputCurrent = outputCur;
  286. //EVSE - 槍端的輸出電壓
  287. chargingInfo[group]->PresentChargingVoltage = ShmPsuData->PsuGroup[group].GroupPresentOutputVoltage;
  288. //EVSE - 槍端的輸出電流
  289. chargingInfo[group]->PresentChargingCurrent = ShmPsuData->PsuGroup[group].GroupPresentOutputCurrent;
  290. }
  291. //printf("GroupPresentOutputVoltage = %d \n", ShmPsuData->PsuGroup[group].GroupPresentOutputVoltage);
  292. //printf("GroupPresentOutputCurrent = %d \n", ShmPsuData->PsuGroup[group].GroupPresentOutputCurrent);
  293. }
  294. //PSU able_power = KW (單位 0.1) exp. 300 = 30kw
  295. //PSU able_cur = A (單位 0.1) exp. 400 = 40A
  296. void SaveAvailableCapCallback(byte address, unsigned short maxv,unsigned short minv, unsigned short able_cur, unsigned short able_power)
  297. {
  298. unsigned int power = 0;
  299. unsigned int current = 0;
  300. unsigned int group = 0;
  301. bool isChange = false;
  302. //bool sameGroup = false;
  303. //search group
  304. for (byte groupIndex = 0; groupIndex < ShmPsuData->GroupCount; groupIndex++)
  305. {
  306. for (int index = 0; index < ShmPsuData->PsuGroup[groupIndex].GroupPresentPsuQuantity; index++)
  307. {
  308. //search group-id
  309. if (ShmPsuData->PsuGroup[groupIndex].PsuModule[index].PhysicalID == address)
  310. {
  311. //先更新該模組資訊
  312. ShmPsuData->PsuGroup[groupIndex].PsuModule[index].AvailablePower = able_power;
  313. ShmPsuData->PsuGroup[groupIndex].PsuModule[index].AvailableCurrent = able_cur;
  314. //該對應的模組群重新計算總合
  315. for (int loop = 0; loop < ShmPsuData->PsuGroup[groupIndex].GroupPresentPsuQuantity; loop++)
  316. {
  317. power += ShmPsuData->PsuGroup[groupIndex].PsuModule[loop].AvailablePower;
  318. current += ShmPsuData->PsuGroup[groupIndex].PsuModule[loop].AvailableCurrent;
  319. group = groupIndex;
  320. isChange = true;
  321. }
  322. /*
  323. if (ShmSysConfigAndInfo->SysInfo.ReAssignedFlag == YES)
  324. {
  325. for (int index = 0; index < ShmPsuData->SystemPresentPsuQuantity; index++)
  326. {
  327. if (recordPsuData[index]._phy_addr == ShmPsuData->PsuGroup[group].PsuModule[index].PhysicalID)
  328. {
  329. if (recordPsuData[index]._fire_index == group)
  330. {
  331. sameGroup = true;
  332. }
  333. break;
  334. }
  335. }
  336. }
  337. else
  338. sameGroup = true;
  339. if(sameGroup)
  340. {
  341. ShmPsuData->PsuGroup[group].PsuModule[index].AvailablePower = able_power;
  342. ShmPsuData->PsuGroup[group].PsuModule[index].AvailableCurrent = able_cur;
  343. isChange = true;
  344. }
  345. */
  346. }
  347. /*
  348. if(sameGroup)
  349. {
  350. power += ShmPsuData->PsuGroup[group].PsuModule[index].AvailablePower;
  351. current += ShmPsuData->PsuGroup[group].PsuModule[index].AvailableCurrent;
  352. }
  353. */
  354. }
  355. }
  356. if (isChange)
  357. {
  358. // PSU Group
  359. // Available Power
  360. ShmPsuData->PsuGroup[group].GroupAvailablePower = power;
  361. // Available Current
  362. ShmPsuData->PsuGroup[group].GroupAvailableCurrent = current;
  363. //EVSE
  364. if (ShmSysConfigAndInfo->SysInfo.ReAssignedFlag == NO)
  365. {
  366. if (ShmPsuData->PsuGroup[group].GroupAvailablePower < chargingInfo[group]->AvailableChargingPower)
  367. {
  368. printf("Power derating old = %f, new = %d ***************************************************************** \n",
  369. chargingInfo[group]->AvailableChargingPower,
  370. ShmPsuData->PsuGroup[group].GroupAvailablePower);
  371. }
  372. }
  373. chargingInfo[group]->MaximumChargingVoltage = maxv;
  374. chargingInfo[group]->AvailableChargingCurrent = ShmPsuData->PsuGroup[group].GroupAvailableCurrent;
  375. chargingInfo[group]->AvailableChargingPower = ShmPsuData->PsuGroup[group].GroupAvailablePower;
  376. }
  377. //printf("GetAvb:%d maxV= %d, minV = %d, mixA =%d pwr =%d\n", address, maxv, minv, able_cur, able_power);
  378. }
  379. void SaveHardwareVersion(byte group, byte address, int hw_ver)
  380. {
  381. //EVSE
  382. for (byte index = 0; index < ShmPsuData->PsuGroup[group].GroupPresentPsuQuantity; index++)
  383. {
  384. if (ShmPsuData->PsuGroup[group].PsuModule[index].Address == address)
  385. {
  386. ShmPsuData->PsuGroup[group].PsuModule[index].FwVersion[0] = (hw_ver >> 24) & 0xFF;
  387. ShmPsuData->PsuGroup[group].PsuModule[index].FwVersion[1] = (hw_ver >> 16) & 0xFF;
  388. ShmPsuData->PsuGroup[group].PsuModule[index].FwVersion[2] = (hw_ver >> 8) & 0xFF;
  389. ShmPsuData->PsuGroup[group].PsuModule[index].FwVersion[3] = hw_ver & 0xFF;
  390. break;
  391. }
  392. }
  393. }
  394. void GetOutputPowerSwitchStatusCallback(byte address, unsigned char value)
  395. {
  396. for (byte groupIndex = 0; groupIndex < ShmPsuData->GroupCount; groupIndex++)
  397. {
  398. for (byte index = 0; index < ShmPsuData->PsuGroup[groupIndex].GroupPresentPsuQuantity; index++)
  399. {
  400. if (ShmPsuData->PsuGroup[groupIndex].PsuModule[index].PhysicalID == address)
  401. {
  402. //printf("PowerSwitch = %d, group = %d, address = %d \n", value, group, address);
  403. if(value){
  404. ShmPsuData->PsuGroup[groupIndex].PsuModule[index].OutputPowerSwitch = 0x00;
  405. }else{
  406. ShmPsuData->PsuGroup[groupIndex].PsuModule[index].OutputPowerSwitch = 0x01;
  407. }
  408. break;
  409. }
  410. }
  411. }
  412. }
  413. //==========================================
  414. // Init all share memory
  415. //==========================================
  416. int InitShareMemory()
  417. {
  418. int result = PASS;
  419. int MeterSMId;
  420. //creat ShmSysConfigAndInfo
  421. if ((MeterSMId = shmget(ShmSysConfigAndInfoKey, sizeof(struct SysConfigAndInfo), 0777)) < 0)
  422. {
  423. #ifdef SystemLogMessage
  424. DEBUG_ERROR("shmget ShmSysConfigAndInfo NG %d \n");
  425. #endif
  426. result = FAIL;
  427. }
  428. else if ((ShmSysConfigAndInfo = shmat(MeterSMId, NULL, 0)) == (void *) -1)
  429. {
  430. #ifdef SystemLogMessage
  431. DEBUG_ERROR("shmat ShmSysConfigAndInfo NG \n");
  432. #endif
  433. result = FAIL;
  434. }
  435. else
  436. {}
  437. //creat ShmStatusCodeData
  438. if ((MeterSMId = shmget(ShmStatusCodeKey, sizeof(struct StatusCodeData), 0777)) < 0)
  439. {
  440. #ifdef SystemLogMessage
  441. DEBUG_ERROR("shmget ShmStatusCodeData NG \n");
  442. #endif
  443. result = FAIL;
  444. }
  445. else if ((ShmStatusCodeData = shmat(MeterSMId, NULL, 0)) == (void *) -1)
  446. {
  447. #ifdef SystemLogMessage
  448. DEBUG_ERROR("shmat ShmStatusCodeData NG \n");
  449. #endif
  450. result = FAIL;
  451. }
  452. else
  453. {}
  454. //creat ShmPsuData
  455. if ((MeterSMId = shmget(ShmPsuKey, sizeof(struct PsuData), 0777)) < 0)
  456. {
  457. #ifdef SystemLogMessage
  458. DEBUG_ERROR("shmget ShmPsuData NG \n");
  459. #endif
  460. result = FAIL;
  461. }
  462. else if ((ShmPsuData = shmat(MeterSMId, NULL, 0)) == (void *) -1)
  463. {
  464. #ifdef SystemLogMessage
  465. DEBUG_ERROR("shmat ShmPsuData NG \n");
  466. #endif
  467. result = FAIL;
  468. }
  469. memset(ShmPsuData,0,sizeof(struct PsuData));
  470. return result;
  471. }
  472. //================================================
  473. // Main process
  474. //================================================
  475. void InitialPsuData()
  476. {
  477. ShmPsuData->SystemPresentPsuQuantity = 0;
  478. for (byte _groupCount = 0; _groupCount < ARRAY_SIZE(ShmPsuData->PsuGroup); _groupCount++)
  479. {
  480. ShmPsuData->PsuGroup[_groupCount].GroupPresentPsuQuantity = 0;
  481. ShmPsuData->PsuGroup[_groupCount].GroupAvailablePower = 0;
  482. ShmPsuData->PsuGroup[_groupCount].GroupAvailableCurrent = 0;
  483. }
  484. ShmPsuData->Work_Step = 0xff;
  485. }
  486. void Initialization()
  487. {
  488. bool isPass = false;
  489. while(!isPass)
  490. {
  491. isPass = true;
  492. for (byte _index = 0; _index < _gunCount; _index++)
  493. {
  494. if (!FindChargingInfoData(_index, &chargingInfo[0]))
  495. {
  496. DEBUG_ERROR("EvComm (main) : FindChargingInfoData false \n");
  497. isPass = false;
  498. break;
  499. }
  500. }
  501. }
  502. }
  503. int main(void)
  504. {
  505. printf("Psu Task boot .... \n");
  506. if(InitShareMemory() == FAIL)
  507. {
  508. #ifdef SystemLogMessage
  509. DEBUG_ERROR("InitShareMemory NG\n");
  510. #endif
  511. if(ShmStatusCodeData != NULL)
  512. {
  513. ShmStatusCodeData->AlarmCode.AlarmEvents.bits.FailToCreateShareMemory = 1;
  514. }
  515. sleep(5);
  516. return 0;
  517. }
  518. printf("InitShareMemory OK\n");
  519. // register callback function
  520. GetPsuAddressReq(&GetPsuRequestCallback);
  521. RefreshStatus(&SaveStatusCallback);
  522. RefreshInputVol(&SavePresentInputVoltageCallback);
  523. RefreshGetOutput(&SavePresentOutputCallback);
  524. RefreshAvailableCap(&SaveAvailableCapCallback);
  525. RefreshOutputPowerSwitch(&GetOutputPowerSwitchStatusCallback);
  526. // initial object
  527. InitialPsuData();
  528. Initialization();
  529. libInitialize = InitialCommunication();
  530. //main loop
  531. while (libInitialize)
  532. {
  533. // 斷電狀態
  534. if (ShmSysConfigAndInfo->SysInfo.AcContactorStatus == NO)
  535. {
  536. //一但 AC Off PSU 斷電全部的 PSU Group ID 會全部清 0
  537. InitialPsuData();
  538. sleep(1);
  539. ShmPsuData->Work_Step = ASSIGN_START;
  540. continue;
  541. }
  542. // update psu fw req
  543. // if(psu update req ?)
  544. // {
  545. //
  546. // continue;
  547. // }
  548. // 自檢失敗
  549. if (ShmPsuData->Work_Step == _NO_WORKING)
  550. {
  551. DEBUG_ERROR("== PSU == self test fail. \n");
  552. printf("== PSU == self test fail. \n");
  553. sleep(5);
  554. }
  555. switch(ShmPsuData->Work_Step)
  556. {
  557. case ASSIGN_START:
  558. {
  559. printf("== PSU == ASSIGN_COMP \n");
  560. gettimeofday(&_id_assign_time, NULL);
  561. ShmPsuData->Work_Step = ASSIGN_COMP;
  562. }
  563. break;
  564. case ASSIGN_COMP:
  565. {
  566. // 等待十秒 (英飛源開機須等待約10讓模組互相通訊
  567. if (GetTimeoutValue(_id_assign_time) >= 10000000)
  568. {
  569. //發送取得目前全部模組數量
  570. RequestModuleTotalMumbert();
  571. usleep(cmdDelayTime);
  572. if (ShmPsuData->SystemPresentPsuQuantity)
  573. {
  574. printf("== PSU == ENABLE_POW \n");
  575. ShmPsuData->Work_Step = ENABLE_POW;
  576. }
  577. }
  578. }
  579. break;
  580. case ENABLE_POW:
  581. {
  582. if (ShmSysConfigAndInfo->SysInfo.BootingStatus == BOOTTING)
  583. {
  584. // 電樁在 Booting 的狀態 - 自檢
  585. printf("== PSU == _TEST_LINE_STEP \n");
  586. ShmPsuData->Work_Step = _TEST_LINE_STEP;
  587. }
  588. else
  589. {
  590. printf("== PSU == _WORK_CHARGING \n");
  591. ShmPsuData->Work_Step = _WORK_CHARGING;
  592. gettimeofday(&_workModePriority_time, NULL);
  593. }
  594. }
  595. break;
  596. case _TEST_LINE_STEP:
  597. {
  598. printf("cur total psu count = %d \n", ShmPsuData->SystemPresentPsuQuantity);
  599. if (ShmPsuData->PsuGroup[0].GroupPresentPsuQuantity <= 0)
  600. {
  601. sleep(1);
  602. continue;
  603. }
  604. #if (SELF_TEST)
  605. // 對整個 Group 保持通訊
  606. bool isFind = false;
  607. while(ShmPsuData->Work_Step != _NO_WORKING &&
  608. _curCheckPsuIndexForFireLine < ShmPsuData->PsuGroup[0].GroupPresentPsuQuantity)
  609. {
  610. GetStatus(SET_GROUP_CMD, 0);
  611. usleep(cmdDelayTime);
  612. GetAvailableCap(SET_GROUP_CMD, 0, 0);
  613. usleep(cmdDelayTime);
  614. //如果在開機自我測試中又加入新的模組就全部重做自我測試
  615. if (ShmPsuData->NeedBackTest == YES)
  616. {
  617. ShmPsuData->NeedBackTest = NO;
  618. _curCheckPsuIndexForFireLine = 0x00;
  619. }
  620. if (isFind)
  621. {
  622. GetPresentOutput(SET_MODULE_CMD, ShmPsuData->PsuGroup[0].PsuModule[_curCheckPsuIndexForFireLine].PhysicalID);
  623. usleep(cmdDelayTime);
  624. //printf("isFind ****** \n");
  625. //printf("stop vor = %d \n", ShmPsuData->PsuGroup[0].PsuModule[_curCheckPsuIndexForFireLine].PresentOutputVoltage);
  626. if (ShmPsuData->PsuGroup[0].PsuModule[_curCheckPsuIndexForFireLine].PresentOutputVoltage <= 200)
  627. {
  628. // 檢查下一個
  629. _curCheckPsuIndexForFireLine++;
  630. isFind = false;
  631. }
  632. //英飛源無法設定 v = 0
  633. //程序放在此
  634. //1.前一個模組會被關閉
  635. //2.++後的新的模組也會先被先關閉 1 次
  636. SetPresentOutput(SET_MODULE_CMD, ShmPsuData->PsuGroup[0].PsuModule[_curCheckPsuIndexForFireLine].PhysicalID,
  637. ZERO_VOL, ZERO_CUR, chargingInfo[0]->AvailableChargingCurrent);
  638. usleep(cmdDelayTime);
  639. EnableOutputPower(SET_MODULE_CMD ,ShmPsuData->PsuGroup[0].PsuModule[_curCheckPsuIndexForFireLine].PhysicalID , SWITCH_OFF);
  640. usleep(cmdDelayTime);
  641. EnableGreenLedFlash(SET_MODULE_CMD ,ShmPsuData->PsuGroup[0].PsuModule[_curCheckPsuIndexForFireLine].PhysicalID , SWITCH_OFF);
  642. usleep(cmdDelayTime);
  643. }
  644. else
  645. {
  646. printf("AvailableCurrent[%d] = %d \n",_curCheckPsuIndexForFireLine, ShmPsuData->PsuGroup[0].PsuModule[_curCheckPsuIndexForFireLine].AvailableCurrent);
  647. if (ShmPsuData->PsuGroup[0].PsuModule[_curCheckPsuIndexForFireLine].AvailableCurrent > 0)
  648. {
  649. if (ShmPsuData->PsuGroup[0].PsuModule[_curCheckPsuIndexForFireLine].PresentOutputVoltage == 0)
  650. {
  651. //printf("set output vol = %d, cur = %d \n", SELF_TEST_VOL, SELF_TEST_CUR);
  652. SetPresentOutput(SET_MODULE_CMD, ShmPsuData->PsuGroup[0].PsuModule[_curCheckPsuIndexForFireLine].PhysicalID,
  653. SELF_TEST_VOL, SELF_TEST_CUR, chargingInfo[0]->AvailableChargingCurrent);
  654. usleep(cmdDelayTime);
  655. EnableOutputPower(SET_MODULE_CMD ,ShmPsuData->PsuGroup[0].PsuModule[_curCheckPsuIndexForFireLine].PhysicalID , SWITCH_ON);
  656. usleep(cmdDelayTime);
  657. EnableGreenLedFlash(SET_MODULE_CMD ,ShmPsuData->PsuGroup[0].PsuModule[_curCheckPsuIndexForFireLine].PhysicalID , SWITCH_ON);
  658. usleep(cmdDelayTime);
  659. }
  660. if(!isCheckOutputTimeStart)
  661. {
  662. gettimeofday(&_chk_output_time, NULL);
  663. isCheckOutputTimeStart = true;
  664. }
  665. else
  666. {
  667. // 如果五秒內火線上都沒有偵測到電壓,則代表異常
  668. if (GetTimeoutValue(_chk_output_time) >= 20000000)
  669. {
  670. // 自檢失敗
  671. printf("self test timeout \n");
  672. EnableOutputPower(SET_GROUP_CMD, 0, SWITCH_OFF);
  673. usleep(cmdDelayTime);
  674. EnableGreenLedFlash(SET_MODULE_CMD, 0, SWITCH_OFF);
  675. usleep(cmdDelayTime);
  676. ShmPsuData->Work_Step = _NO_WORKING;
  677. continue;
  678. }
  679. }
  680. for (byte gunIndex = 0; gunIndex < _gunCount; gunIndex ++)
  681. {
  682. GetPresentOutput(SET_MODULE_CMD, ShmPsuData->PsuGroup[0].PsuModule[_curCheckPsuIndexForFireLine].PhysicalID);
  683. usleep(cmdDelayTime);
  684. printf("Cur psu[%d] output voltage = %d \n",_curCheckPsuIndexForFireLine, ShmPsuData->PsuGroup[0].PsuModule[_curCheckPsuIndexForFireLine].PresentOutputVoltage);
  685. printf("Fire[%d] voltage = %f \n", gunIndex, chargingInfo[gunIndex]->FuseChargingVoltage);
  686. // 該模組的輸出電壓與火線上的電壓一致
  687. if (chargingInfo[gunIndex]->FuseChargingVoltage >= 1500 &&
  688. ((chargingInfo[gunIndex]->FuseChargingVoltage >= ShmPsuData->PsuGroup[0].PsuModule[_curCheckPsuIndexForFireLine].PresentOutputVoltage - 300) &&
  689. (chargingInfo[gunIndex]->FuseChargingVoltage <= ShmPsuData->PsuGroup[0].PsuModule[_curCheckPsuIndexForFireLine].PresentOutputVoltage + 300)))
  690. {
  691. printf("Cur psu output voltage2 = %d \n", ShmPsuData->PsuGroup[0].PsuModule[_curCheckPsuIndexForFireLine].PresentOutputVoltage);
  692. // 找到火線上的電壓了,這邊紀錄火線是紀錄屬於哪一把槍的火線
  693. if (_curCheckPsuIndexForFireLine < ShmPsuData->PsuGroup[0].GroupPresentPsuQuantity)
  694. {
  695. // 紀錄當前 PSU 是哪個火線上的
  696. recordPsuData[_curCheckPsuIndexForFireLine]._fire_index = gunIndex;
  697. recordPsuData[_curCheckPsuIndexForFireLine]._phy_addr = ShmPsuData->PsuGroup[0].PsuModule[_curCheckPsuIndexForFireLine].PhysicalID;
  698. strcpy(recordPsuData[_curCheckPsuIndexForFireLine]._serial_num, (char *)ShmPsuData->PsuGroup[0].PsuModule[_curCheckPsuIndexForFireLine].SerialNumber);
  699. printf("Find Fire Line Number end~~~~~~~~~~~~~~~ = %d \n", gunIndex);
  700. usleep(300000);
  701. isCheckOutputTimeStart = false;
  702. isFind = true;
  703. break;
  704. }
  705. }
  706. }
  707. }
  708. }
  709. usleep(100000);
  710. }
  711. if (ShmPsuData->Work_Step != _NO_WORKING)
  712. {
  713. printf("== PSU == TEST_POWER_STEP \n");
  714. ShmPsuData->Work_Step = _TEST_POWER_STEP;
  715. }
  716. EnableOutputPower(SET_GROUP_CMD, 0, SWITCH_OFF);
  717. usleep(cmdDelayTime);
  718. EnableGreenLedFlash(SET_MODULE_CMD, 0, SWITCH_OFF);
  719. usleep(cmdDelayTime);
  720. #else
  721. ShmPsuData->Work_Step = _TEST_POWER_STEP;
  722. #endif
  723. }
  724. break;
  725. case _TEST_POWER_STEP:
  726. {
  727. if(!_chkTotalCapStart)
  728. {
  729. _chkTotalCapStart = true;
  730. gettimeofday(&_chk_cap_time, NULL);
  731. }
  732. for (byte groupIndex = 0; groupIndex < ShmPsuData->GroupCount; groupIndex++)
  733. {
  734. GetStatus(SET_GROUP_CMD, groupIndex);
  735. usleep(cmdDelayTime);
  736. GetAvailableCap(SET_GROUP_CMD, groupIndex, 0);
  737. usleep(cmdDelayTime);
  738. }
  739. if (GetTimeoutValue(_chk_cap_time) >= 2000000)
  740. {
  741. printf("AvailableChargingCurrent = %f, AvailableChargingPower = %f \n",
  742. chargingInfo[0]->AvailableChargingCurrent, chargingInfo[0]->AvailableChargingPower);
  743. for (byte index = 0; index < ShmPsuData->PsuGroup[0].GroupPresentPsuQuantity; index++)
  744. {
  745. printf("index = %d, fire index = %d, phy addr = %d \n",
  746. index, recordPsuData[index]._fire_index, recordPsuData[index]._phy_addr);
  747. }
  748. printf("== PSU == TEST_COMPLETE \n");
  749. ShmPsuData->Work_Step = _TEST_COMPLETE;
  750. }
  751. }
  752. break;
  753. case _TEST_COMPLETE:
  754. {
  755. sleep(1);
  756. }
  757. break;
  758. case _WORK_CHARGING:
  759. {
  760. int time = GetTimeoutValue(_workModePriority_time) / 1000;
  761. //printf("GroupCount = %d \n", ShmPsuData->GroupCount);
  762. //printf("cur total psu count = %d \n", ShmPsuData->SystemPresentPsuQuantity);
  763. for (byte groupIndex = 0; groupIndex < ShmPsuData->GroupCount; groupIndex++)
  764. {
  765. if (time > 1000)
  766. {
  767. GetStatus(SET_GROUP_CMD, groupIndex);
  768. usleep(cmdDelayTime);
  769. GetAvailableCap(SET_GROUP_CMD, groupIndex, 0);
  770. usleep(cmdDelayTime);
  771. gettimeofday(&_workModePriority_time, NULL);
  772. }
  773. GetPresentOutput(SET_GROUP_CMD, groupIndex);
  774. if (carReqVol != chargingInfo[groupIndex]->EvBatterytargetVoltage)
  775. {
  776. carReqVol = chargingInfo[groupIndex]->EvBatterytargetVoltage;
  777. DEBUG_INFO("ev need vol = %f \n", chargingInfo[groupIndex]->EvBatterytargetVoltage);
  778. }
  779. if (carReqCur != chargingInfo[groupIndex]->EvBatterytargetCurrent)
  780. {
  781. carReqCur = chargingInfo[groupIndex]->EvBatterytargetCurrent;
  782. DEBUG_INFO("ev need cur = %f \n", chargingInfo[groupIndex]->EvBatterytargetCurrent);
  783. }
  784. if (evseOutVol != chargingInfo[groupIndex]->FireChargingVoltage)
  785. {
  786. evseOutVol = chargingInfo[groupIndex]->FireChargingVoltage;
  787. printf("evse output vol = %f \n", chargingInfo[groupIndex]->FireChargingVoltage);
  788. }
  789. if (evseOutCur != chargingInfo[groupIndex]->PresentChargingCurrent)
  790. {
  791. evseOutCur = chargingInfo[groupIndex]->PresentChargingCurrent;
  792. printf("evse output cur = %f \n", chargingInfo[groupIndex]->PresentChargingCurrent);
  793. }
  794. // 針對各槍當前狀態,傳送需要回傳的資料指令
  795. if (((chargingInfo[groupIndex]->SystemStatus >= S_PREPARING_FOR_EVSE && chargingInfo[groupIndex]->SystemStatus <= S_CHARGING) && chargingInfo[groupIndex]->RelayK1K2Status) ||
  796. (chargingInfo[groupIndex]->SystemStatus >= S_CCS_PRECHARGE_ST0 && chargingInfo[groupIndex]->SystemStatus <= S_CCS_PRECHARGE_ST1))
  797. {
  798. if (ShmPsuData->PsuGroup[groupIndex].GroupAvailableCurrent > 0)
  799. {
  800. // 該充電槍的目標電壓與目標電流
  801. SetPresentOutput(SET_GROUP_CMD, groupIndex,
  802. chargingInfo[groupIndex]->EvBatterytargetVoltage,
  803. chargingInfo[groupIndex]->EvBatterytargetCurrent,
  804. chargingInfo[groupIndex]->AvailableChargingCurrent);
  805. usleep(cmdDelayTime);
  806. }
  807. if (chargingInfo[groupIndex]->EvBatterytargetVoltage == 0)
  808. {
  809. EnableOutputPower(SET_GROUP_CMD, groupIndex, SWITCH_OFF);
  810. usleep(cmdDelayTime);
  811. EnableGreenLedFlash(SET_GROUP_CMD , groupIndex , SWITCH_OFF);
  812. usleep(cmdDelayTime);
  813. }
  814. else
  815. {
  816. EnableOutputPower(SET_GROUP_CMD, groupIndex, SWITCH_ON);
  817. usleep(cmdDelayTime);
  818. EnableGreenLedFlash(SET_GROUP_CMD , groupIndex, SWITCH_ON);
  819. usleep(cmdDelayTime);
  820. }
  821. }
  822. else if (chargingInfo[groupIndex]->SystemStatus >= S_TERMINATING &&
  823. chargingInfo[groupIndex]->SystemStatus <= S_COMPLETE)
  824. {
  825. SetPresentOutput(SET_GROUP_CMD, groupIndex, ZERO_VOL, ZERO_CUR, chargingInfo[groupIndex]->AvailableChargingCurrent);
  826. usleep(cmdDelayTime);
  827. EnableGreenLedFlash(SET_GROUP_CMD , groupIndex , SWITCH_OFF);
  828. usleep(cmdDelayTime);
  829. EnableOutputPower(SET_GROUP_CMD, groupIndex, SWITCH_OFF);
  830. usleep(cmdDelayTime);
  831. }
  832. }
  833. break;
  834. }
  835. }
  836. usleep(45000);
  837. }
  838. return FAIL;
  839. }