RelayBoard.c 56 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353
  1. #include <stdio.h> /*標準輸入輸出定義*/
  2. #include <stdlib.h> /*標準函數庫定義*/
  3. #include <string.h>
  4. #include <stdint.h>
  5. #include <time.h>
  6. #include <unistd.h>
  7. #include <sys/time.h>
  8. #include <sys/timeb.h>
  9. #include "../ShareMemory/shmMem.h"
  10. #include "../Config.h"
  11. #include "../Log/log.h"
  12. #include "Module_InternalComm.h"
  13. #include "internalComm.h"
  14. //------------------------------------------------------------------------------
  15. static struct SysConfigData *pSysConfig = NULL;
  16. static struct SysInfoData *pSysInfo = NULL;
  17. static struct AlarmCodeData *pAlarmCode = NULL;
  18. static struct RelayModuleData *ShmRelayModuleData = NULL;
  19. static struct PsuData *ShmPsuData = NULL;
  20. static struct PrimaryMcuData *ShmPrimaryMcuData = NULL;
  21. static DcCommonInfo *ShmDcCommonData = NULL;
  22. static Relay outputRelay = {0};
  23. static Relay regRelay = {0};
  24. static int Uart5Fd = 0;
  25. //static bool _isRelayWelding[CHAdeMO_QUANTITY + CCS_QUANTITY + GB_QUANTITY];
  26. //static struct timeval _checkRelayWeldingTimer[CHAdeMO_QUANTITY + CCS_QUANTITY + GB_QUANTITY];
  27. //static bool _isOutputNoneMatch[CHAdeMO_QUANTITY + CCS_QUANTITY + GB_QUANTITY];
  28. //static struct timeval _checkOutputNoneMatchTimer[CHAdeMO_QUANTITY + CCS_QUANTITY + GB_QUANTITY];
  29. static bool _isOvpChkTimeFlag[CHAdeMO_QUANTITY + CCS_QUANTITY + GB_QUANTITY]; //DS60-120 add
  30. static struct timeval _checkOutputVolProtectTimer[CHAdeMO_QUANTITY + CCS_QUANTITY + GB_QUANTITY]; //DS60-120 add
  31. static struct timeval _close_ac_contactor;
  32. //------------------------------------------------------------------------------
  33. static void RunForceStopProcess(void)
  34. {
  35. static bool isCriticalStop = NO;
  36. static struct timeval _psuCriticalStop;
  37. uint32_t _timebuf;
  38. if (isCriticalStop == NO) {
  39. isCriticalStop = YES;
  40. gettimeofday(&_psuCriticalStop, NULL);
  41. } else {
  42. _timebuf = GetTimeoutValue(_psuCriticalStop);
  43. if (_timebuf < 0) {
  44. gettimeofday(&_psuCriticalStop, NULL);
  45. } else {
  46. if (_timebuf / 1000 >= (FORCE_STOP_TIME * 1000)) {
  47. isCriticalStop = NO;
  48. pAlarmCode->AlarmEvents.bits.PsuFailureAlarm = NORMAL;
  49. }
  50. }
  51. }
  52. }
  53. static void StopCheckRelayInfo(uint8_t _chkIndex)
  54. {
  55. if (ShmDcCommonData->CheckRelayStatus[_chkIndex] != STOP) {
  56. ShmDcCommonData->CheckRelayStatus[_chkIndex] = STOP;
  57. }
  58. }
  59. static void StartCheckRelayInfo(uint8_t _chkIndex, uint8_t toState)
  60. {
  61. // SMR1 *2 + SMR2 * 2 + Parallel * 2
  62. static time_t lastCheckRelayStateTimer[6] = {0};
  63. time_t nowTime = {0};
  64. //uint8_t *pCheckRelayState = (uint8_t *)ShmDcCommonData->CheckRelayStatus[_chkIndex];
  65. if (ShmDcCommonData->CheckRelayStatus[_chkIndex] == STOP) {
  66. time(&lastCheckRelayStateTimer[_chkIndex]);
  67. ShmDcCommonData->CheckRelayStatus[_chkIndex] = START;
  68. } else {
  69. time(&nowTime);
  70. if (nowTime - lastCheckRelayStateTimer[_chkIndex] >= 1) {
  71. //log_info("relay welding or driving fault = %d \n", _chkIndex);
  72. if (toState == 1) {
  73. ShmDcCommonData->CheckRelayStatus[_chkIndex] = RELAY_STATUS_ERROR_DRIVING;
  74. } else {
  75. ShmDcCommonData->CheckRelayStatus[_chkIndex] = RELAY_STATUS_ERROR_WELDING;
  76. }
  77. lastCheckRelayStateTimer[_chkIndex] = nowTime;
  78. }
  79. }
  80. }
  81. static uint8_t getCommTargetID(uint8_t index)
  82. {
  83. uint8_t targetID = 0;
  84. struct ChargingInfoData *pDcChargingInfo = (struct ChargingInfoData *)GetDcChargingInfoData(index);
  85. if (pSysConfig->TotalConnectorCount == 1) {
  86. if (strncmp((char *)&pSysConfig->ModelName[7], "0", 1) != 0) {
  87. targetID = 0x01;
  88. } else if (strncmp((char *)&pSysConfig->ModelName[9], "0", 1) != 0) {
  89. targetID = 0x02;
  90. }
  91. } else {
  92. targetID = pDcChargingInfo->Evboard_id;
  93. }
  94. return targetID;
  95. }
  96. static void MatchRelayStatus(void)
  97. {
  98. // 因為 AC Contactor 沒有 Feedback,所以暫時先這樣處理
  99. //regRelay.relay_event.bits.AC_Contactor = outputRelay.relay_event.bits.AC_Contactor;
  100. //pSysInfo->AcContactorStatus =
  101. // regRelay.relay_event.bits.AC_Contactor =
  102. // outputRelay.relay_event.bits.AC_Contactor;
  103. regRelay.relay_event.bits.CCS_Precharge = outputRelay.relay_event.bits.CCS_Precharge;
  104. regRelay.relay_event.bits.Gun1_P = outputRelay.relay_event.bits.Gun1_P;
  105. regRelay.relay_event.bits.Gun1_N = outputRelay.relay_event.bits.Gun1_N;
  106. regRelay.relay_event.bits.Gun2_P = outputRelay.relay_event.bits.Gun2_P;
  107. regRelay.relay_event.bits.Gun2_N = outputRelay.relay_event.bits.Gun2_N;
  108. regRelay.relay_event.bits.Gun1_Parallel_P = outputRelay.relay_event.bits.Gun1_Parallel_P;
  109. regRelay.relay_event.bits.Gun1_Parallel_N = outputRelay.relay_event.bits.Gun1_Parallel_N;
  110. }
  111. static bool IsNoneMatchRelayStatus(void)
  112. {
  113. bool result = false;
  114. if (
  115. #if !defined DD360 && !defined DD360Audi && !defined DD360ComBox
  116. (regRelay.relay_event.bits.AC_Contactor != outputRelay.relay_event.bits.AC_Contactor) ||
  117. (regRelay.relay_event.bits.CCS_Precharge != outputRelay.relay_event.bits.CCS_Precharge) ||
  118. #endif //!defined DD360 && !defined DD360Audi
  119. (regRelay.relay_event.bits.Gun1_P != outputRelay.relay_event.bits.Gun1_P) ||
  120. (regRelay.relay_event.bits.Gun1_N != outputRelay.relay_event.bits.Gun1_N) ||
  121. (regRelay.relay_event.bits.Gun2_P != outputRelay.relay_event.bits.Gun2_P) ||
  122. (regRelay.relay_event.bits.Gun2_N != outputRelay.relay_event.bits.Gun2_N)
  123. #if !defined DD360 && !defined DD360Audi && !defined DD360ComBox
  124. ||
  125. (regRelay.relay_event.bits.Gun1_Parallel_P != outputRelay.relay_event.bits.Gun1_Parallel_P) ||
  126. (regRelay.relay_event.bits.Gun1_Parallel_N != outputRelay.relay_event.bits.Gun1_Parallel_N)
  127. #endif //!defined DD360 && !defined DD360Audi
  128. ) {
  129. result = true;
  130. }
  131. #if !defined DD360 && !defined DD360Audi && !defined DD360ComBox
  132. if (regRelay.relay_event.bits.AC_Contactor != outputRelay.relay_event.bits.AC_Contactor) {
  133. log_info("AC Contact Relay none match. \n");
  134. }
  135. if (regRelay.relay_event.bits.CCS_Precharge != outputRelay.relay_event.bits.CCS_Precharge) {
  136. log_info("CCS Precharge Relay none match. \n");
  137. }
  138. #endif //
  139. if (regRelay.relay_event.bits.Gun1_P != outputRelay.relay_event.bits.Gun1_P) {
  140. //log_info("SMR1:D+ Relay none match. \n");
  141. StartCheckRelayInfo(RELAY_SMR1_P_STATUS, outputRelay.relay_event.bits.Gun1_P);
  142. } else {
  143. StopCheckRelayInfo(RELAY_SMR1_P_STATUS);
  144. }
  145. if (regRelay.relay_event.bits.Gun1_N != outputRelay.relay_event.bits.Gun1_N) {
  146. //log_info("SMR1:D- Relay none match. \n");
  147. StartCheckRelayInfo(RELAY_SMR1_N_STATUS, outputRelay.relay_event.bits.Gun1_N);
  148. } else {
  149. StopCheckRelayInfo(RELAY_SMR1_N_STATUS);
  150. }
  151. if (regRelay.relay_event.bits.Gun2_P != outputRelay.relay_event.bits.Gun2_P) {
  152. //log_info("SMR2:D+ Relay none match. \n");
  153. StartCheckRelayInfo(RELAY_SMR2_P_STATUS, outputRelay.relay_event.bits.Gun2_P);
  154. } else {
  155. StopCheckRelayInfo(RELAY_SMR2_P_STATUS);
  156. }
  157. if (regRelay.relay_event.bits.Gun2_N != outputRelay.relay_event.bits.Gun2_N) {
  158. //log_info("SMR2:D- Relay none match. \n");
  159. StartCheckRelayInfo(RELAY_SMR2_N_STATUS, outputRelay.relay_event.bits.Gun2_N);
  160. } else {
  161. StopCheckRelayInfo(RELAY_SMR2_N_STATUS);
  162. }
  163. #if !defined DD360 && !defined DD360Audi && !defined DD360ComBox
  164. if (regRelay.relay_event.bits.Gun1_Parallel_P != outputRelay.relay_event.bits.Gun1_Parallel_P) {
  165. //log_info("Parallel:D+ Relay none match. \n");
  166. StartCheckRelayInfo(RELAY_PARA_P_STATUS, outputRelay.relay_event.bits.Gun1_Parallel_P);
  167. } else {
  168. StopCheckRelayInfo(RELAY_PARA_P_STATUS);
  169. }
  170. if (regRelay.relay_event.bits.Gun1_Parallel_N != outputRelay.relay_event.bits.Gun1_Parallel_N) {
  171. //log_info("Parallel:D- Relay none match. \n");
  172. StartCheckRelayInfo(RELAY_PARA_N_STATUS, outputRelay.relay_event.bits.Gun1_Parallel_N);
  173. } else {
  174. StopCheckRelayInfo(RELAY_PARA_N_STATUS);
  175. }
  176. #endif //
  177. return result;
  178. }
  179. static void SetParalleRelayStatus(void)
  180. {
  181. #if defined DD360 || defined DD360Audi || defined DD360ComBox
  182. return;
  183. #endif //!defined DD360 || !defined DD360Audi || !defined DD360ComBox
  184. struct ChargingInfoData *pDcChargingInfo0 = (struct ChargingInfoData *)GetDcChargingInfoData(0);
  185. struct ChargingInfoData *pDcChargingInfo1 = (struct ChargingInfoData *)GetDcChargingInfoData(1);
  186. // 之後雙槍單模機種,橋接都會上
  187. if (pSysConfig->TotalConnectorCount >= 2) {
  188. if (pDcChargingInfo0->SystemStatus == S_BOOTING || pDcChargingInfo1->SystemStatus == S_BOOTING ||
  189. (pDcChargingInfo0->SystemStatus == S_IDLE && pDcChargingInfo1->SystemStatus == S_IDLE)) {
  190. // 初始化~ 不搭橋接
  191. if (regRelay.relay_event.bits.Gun1_Parallel_P == YES) {
  192. outputRelay.relay_event.bits.Gun1_Parallel_P = NO;
  193. } else if (regRelay.relay_event.bits.Gun1_Parallel_N == YES) {
  194. outputRelay.relay_event.bits.Gun1_Parallel_N = NO;
  195. }
  196. } else {
  197. if (pDcChargingInfo0->IsReadyToCharging == YES ||
  198. pDcChargingInfo1->IsReadyToCharging == YES) {
  199. // ************需考慮在切換中 - 切開 relay 與搭回 relay 的時機點************
  200. if (pSysInfo->MainChargingMode == _MAIN_CHARGING_MODE_MAX) {
  201. if (pSysInfo->ReAssignedFlag < _REASSIGNED_RELAY_M_TO_A) {
  202. // 最大充 - 搭上橋接
  203. if (regRelay.relay_event.bits.Gun1_Parallel_N == NO) {
  204. outputRelay.relay_event.bits.Gun1_Parallel_N = YES;
  205. } else if (regRelay.relay_event.bits.Gun1_Parallel_P == NO) {
  206. outputRelay.relay_event.bits.Gun1_Parallel_P = YES;
  207. }
  208. } else {
  209. // 平均充 - 不搭
  210. if (regRelay.relay_event.bits.Gun1_Parallel_P == YES) {
  211. outputRelay.relay_event.bits.Gun1_Parallel_P = NO;
  212. } else if (regRelay.relay_event.bits.Gun1_Parallel_N == YES) {
  213. outputRelay.relay_event.bits.Gun1_Parallel_N = NO;
  214. }
  215. }
  216. } else if (pSysInfo->MainChargingMode == _MAIN_CHARGING_MODE_AVER) {
  217. if (pSysInfo->ReAssignedFlag < _REASSIGNED_RELAY_A_TO_M) {
  218. // 平均充 - 不搭
  219. if (regRelay.relay_event.bits.Gun1_Parallel_P == YES) {
  220. outputRelay.relay_event.bits.Gun1_Parallel_P = NO;
  221. } else if (regRelay.relay_event.bits.Gun1_Parallel_N == YES) {
  222. outputRelay.relay_event.bits.Gun1_Parallel_N = NO;
  223. }
  224. } else {
  225. // 最大充 - 搭上橋接
  226. if (regRelay.relay_event.bits.Gun1_Parallel_N == NO) {
  227. outputRelay.relay_event.bits.Gun1_Parallel_N = YES;
  228. } else if (regRelay.relay_event.bits.Gun1_Parallel_P == NO) {
  229. outputRelay.relay_event.bits.Gun1_Parallel_P = YES;
  230. }
  231. }
  232. }
  233. }
  234. }
  235. }
  236. }
  237. static void GetGfdAdc(void)
  238. {
  239. int gunIndex = 0;
  240. uint8_t targetID = 0;
  241. struct ChargingInfoData *pDcChargingInfo = NULL;
  242. Gfd gfd_adc = {0};
  243. // define : 每 0.2 ~ 1 秒一次
  244. // occur : <= 75k 歐姆 @ 150 - 750 Vdc
  245. // warning : >= 100 歐姆 && <= 500 歐姆 @ 150-750 Vdc
  246. if (Query_Gfd_Adc(Uart5Fd, ADDR_RELAY, &gfd_adc) == PASS) {
  247. for (gunIndex = 0; gunIndex < pSysConfig->TotalConnectorCount; gunIndex++) {
  248. pDcChargingInfo = (struct ChargingInfoData *)GetDcChargingInfoData(gunIndex);
  249. if (pDcChargingInfo->Type == 0x09 &&
  250. !pSysConfig->AlwaysGfdFlag
  251. ) {
  252. if ((pDcChargingInfo->PresentChargingVoltage * 10) >= VOUT_MIN_VOLTAGE) {
  253. pDcChargingInfo->GroundFaultStatus = GFD_PASS;
  254. }
  255. continue;
  256. }
  257. targetID = getCommTargetID(gunIndex);
  258. if (targetID == 0x01) {
  259. //if (gfd_adc.result_conn1 == GFD_WARNING) {
  260. // gfd_adc.result_conn1 = GFD_PASS;
  261. //}
  262. pDcChargingInfo->GroundFaultStatus = gfd_adc.result_conn1;
  263. //log_info("GFD ******** Result = %d, Step = %d, R = %d, Vol = %d \n",
  264. // pDcChargingInfo->GroundFaultStatus,
  265. // gfd_adc.rb_step_1,
  266. // gfd_adc.Resister_conn1,
  267. // gfd_adc.voltage_conn1);
  268. if (pDcChargingInfo->GroundFaultStatus == GFD_FAIL) {
  269. log_info("GFD Fail. index = %d, Step = %d, R = %d, Vol = %d \n",
  270. gunIndex,
  271. gfd_adc.rb_step_1,
  272. gfd_adc.Resister_conn1,
  273. gfd_adc.voltage_conn1);
  274. } else if (pDcChargingInfo->GroundFaultStatus == GFD_PASS ||
  275. pDcChargingInfo->GroundFaultStatus == GFD_WARNING
  276. ) {
  277. if (pDcChargingInfo->GroundFaultStatus == GFD_WARNING) {
  278. log_info("GFD Warning. index = %d, Result = %d, R = %d, Vol = %d \n",
  279. gunIndex,
  280. pDcChargingInfo->GroundFaultStatus,
  281. gfd_adc.Resister_conn1,
  282. gfd_adc.voltage_conn1);
  283. }
  284. }
  285. } else if (targetID == 0x02) {
  286. //if (gfd_adc.result_conn2 == GFD_WARNING) {
  287. // gfd_adc.result_conn2 = GFD_PASS;
  288. //}
  289. pDcChargingInfo->GroundFaultStatus = gfd_adc.result_conn2;
  290. if (pDcChargingInfo->GroundFaultStatus == GFD_FAIL) {
  291. log_info("GFD Fail. index = %d, Step = %d, R = %d, Vol = %d \n",
  292. gunIndex,
  293. gfd_adc.rb_step_2,
  294. gfd_adc.Resister_conn2,
  295. gfd_adc.voltage_conn2);
  296. } else if (pDcChargingInfo->GroundFaultStatus == GFD_PASS ||
  297. pDcChargingInfo->GroundFaultStatus == GFD_WARNING
  298. ) {
  299. if (pDcChargingInfo->GroundFaultStatus == GFD_WARNING) {
  300. log_info("GFD Warning. index = %d, Result = %d, R = %d, Vol = %d \n",
  301. gunIndex,
  302. pDcChargingInfo->GroundFaultStatus,
  303. gfd_adc.Resister_conn1,
  304. gfd_adc.voltage_conn1);
  305. }
  306. }
  307. }
  308. }
  309. }
  310. }
  311. void CheckOutputPowerOverCarReq(uint8_t index)
  312. {
  313. struct ChargingInfoData *pDcChargingInfo = (struct ChargingInfoData *)GetDcChargingInfoData(index);
  314. float fireV = pDcChargingInfo->FireChargingVoltage;
  315. float carV = pDcChargingInfo->EvBatteryMaxVoltage * 10;
  316. if ((pDcChargingInfo->EvBatterytargetVoltage * 10) > 1500 &&
  317. (pDcChargingInfo->Type == _Type_Chademo ||
  318. pDcChargingInfo->Type == _Type_CCS_2 ||
  319. pDcChargingInfo->Type == _Type_GB)) {
  320. if (fireV >= (carV + (carV * 0.02))) {
  321. if (!_isOvpChkTimeFlag[index]) {
  322. if ((pDcChargingInfo->PresentChargingVoltage * 10) >= VOUT_MIN_VOLTAGE * 10) {
  323. gettimeofday(&_checkOutputVolProtectTimer[index], NULL);
  324. _isOvpChkTimeFlag[index] = YES;
  325. }
  326. } else {
  327. log_info("[Module_InternalComm]CheckOutputPowerOverCarReq NG : fire = %f, battery = %f \n",
  328. pDcChargingInfo->FireChargingVoltage, (pDcChargingInfo->EvBatterytargetVoltage * 10));
  329. log_error("[Module_InternalComm]CheckOutputPowerOverCarReq NG : fire = %f, battery = %f \n",
  330. pDcChargingInfo->FireChargingVoltage, (pDcChargingInfo->EvBatterytargetVoltage * 10));
  331. if ((GetTimeoutValue(_checkOutputVolProtectTimer[index]) / 1000) >= OUTPUT_VOL_CHK_TIME) {
  332. if (pDcChargingInfo->Type == _Type_Chademo) {
  333. pAlarmCode->AlarmEvents.bits.SystemChademoOutputOVP = YES;
  334. } else if (pDcChargingInfo->Type == _Type_CCS_2) {
  335. pAlarmCode->AlarmEvents.bits.SystemCcsOutputOVP = YES;
  336. } else if (pDcChargingInfo->Type == _Type_GB) {
  337. pAlarmCode->AlarmEvents.bits.SystemGbOutputOVP = YES;
  338. }
  339. pDcChargingInfo->StopChargeFlag = YES;
  340. }
  341. }
  342. } else {
  343. if (_isOvpChkTimeFlag[index] == YES) {
  344. _isOvpChkTimeFlag[index] = NO;
  345. }
  346. }
  347. }
  348. }
  349. void ResetDetAlarmStatus(uint8_t gun)
  350. {
  351. struct ChargingInfoData *pDcChargingInfo = (struct ChargingInfoData *)GetDcChargingInfoData(gun);
  352. if (pDcChargingInfo->Type == _Type_Chademo) {
  353. if (pAlarmCode->AlarmEvents.bits.SystemChademoOutputOVP == YES) {
  354. pAlarmCode->AlarmEvents.bits.SystemChademoOutputOVP = NO;
  355. }
  356. } else if (pDcChargingInfo->Type == _Type_GB) {
  357. if (pAlarmCode->AlarmEvents.bits.SystemGbOutputOVP == YES) {
  358. pAlarmCode->AlarmEvents.bits.SystemGbOutputOVP = NO;
  359. }
  360. } else if (pDcChargingInfo->Type == _Type_CCS_2) {
  361. if (pAlarmCode->AlarmEvents.bits.SystemCcsOutputOVP == YES) {
  362. pAlarmCode->AlarmEvents.bits.SystemCcsOutputOVP = NO;
  363. }
  364. }
  365. }
  366. void CheckAcInputOvpStatus(uint8_t index)
  367. {
  368. struct ChargingInfoData *pDcChargingInfo = (struct ChargingInfoData *)GetDcChargingInfoData(index);
  369. if (pAlarmCode->AlarmEvents.bits.SystemL1InputOVP == YES ||
  370. pAlarmCode->AlarmEvents.bits.SystemL2InputOVP == YES ||
  371. pAlarmCode->AlarmEvents.bits.SystemL3InputOVP == YES) {
  372. // if ((pDcChargingInfo->SystemStatus >= S_PREPARNING && pDcChargingInfo->SystemStatus <= S_CHARGING) ||
  373. // (pDcChargingInfo->SystemStatus >= S_CCS_PRECHARGE_ST0 && pDcChargingInfo->SystemStatus <= S_CCS_PRECHARGE_ST1))
  374. // {
  375. // if (pSysInfo->ChargerType == _CHARGER_TYPE_IEC)
  376. // {
  377. // if (_psuInputVolR > VIN_MAX_VOLTAGE_IEC ||
  378. // _psuInputVolS > VIN_MAX_VOLTAGE_IEC ||
  379. // _psuInputVolT > VIN_MAX_VOLTAGE_IEC)
  380. // {
  381. // log_info("IEC _psuInputVolR = %f, _psuInputVolS = %f, _psuInputVolT = %f \n",
  382. // _psuInputVolR, _psuInputVolS, _psuInputVolT);
  383. // pDcChargingInfo->StopChargeFlag = YES;
  384. // }
  385. //
  386. // }
  387. // else if (pSysInfo->ChargerType == _CHARGER_TYPE_UL)
  388. // {
  389. // if (_psuInputVolR > VIN_MAX_VOLTAGE_UL ||
  390. // _psuInputVolS > VIN_MAX_VOLTAGE_UL ||
  391. // _psuInputVolT > VIN_MAX_VOLTAGE_UL)
  392. // {
  393. // log_info("UL _psuInputVolR = %f, _psuInputVolS = %f, _psuInputVolT = %f \n",
  394. // _psuInputVolR, _psuInputVolS, _psuInputVolT);
  395. // pDcChargingInfo->StopChargeFlag = YES;
  396. // }
  397. // }
  398. // }
  399. // else
  400. //log_info("CheckAcInputOvpStatus\r\n");
  401. pDcChargingInfo->StopChargeFlag = YES;
  402. }
  403. }
  404. //void CheckOutputVolNoneMatchFire(uint8_t index)
  405. //{
  406. // struct ChargingInfoData *pDcChargingInfo = (struct ChargingInfoData *)GetDcChargingInfoData(index);
  407. //
  408. // if ((pDcChargingInfo->EvBatterytargetVoltage * 10) > 1500 &&
  409. // (pDcChargingInfo->Type == _Type_Chademo ||
  410. // pDcChargingInfo->Type == _Type_CCS_2 ||
  411. // pDcChargingInfo->Type == _Type_GB)) {
  412. // if (((pDcChargingInfo->PresentChargingVoltage * 10) < pDcChargingInfo->FireChargingVoltage - 300) ||
  413. // ((pDcChargingInfo->PresentChargingVoltage * 10) > pDcChargingInfo->FireChargingVoltage + 300)) {
  414. // if (!_isOutputNoneMatch[index]) {
  415. // _isOutputNoneMatch[index] = YES;
  416. // gettimeofday(&_checkOutputNoneMatchTimer[index], NULL);
  417. // } else {
  418. // if ((GetTimeoutValue(_checkOutputNoneMatchTimer[index]) / 1000) >= 5000) {
  419. // /*log_info("[Module_InternalComm]CheckOutputVolNoneMatchFire NG (%d) : pre = %f, fire = %f \n",
  420. // index, (pDcChargingInfo->PresentChargingVoltage * 10), pDcChargingInfo->FireChargingVoltage);
  421. // log_error("[Module_InternalComm]CheckOutputVolNoneMatchFire NG (%d): pre = %f, fire = %f \n",
  422. // index, (pDcChargingInfo->PresentChargingVoltage * 10), pDcChargingInfo->FireChargingVoltage);
  423. // pDcChargingInfo->StopChargeFlag = YES;*/
  424. // }
  425. // }
  426. // } else {
  427. // _isOutputNoneMatch[index] = NO;
  428. // }
  429. // }
  430. //}
  431. void CheckPhaseLossStatus(uint8_t index)
  432. {
  433. struct ChargingInfoData *pDcChargingInfo = (struct ChargingInfoData *)GetDcChargingInfoData(index);
  434. if (pAlarmCode->AlarmEvents.bits.SystemL1InputUVP == YES ||
  435. pAlarmCode->AlarmEvents.bits.SystemL2InputUVP == YES ||
  436. pAlarmCode->AlarmEvents.bits.SystemL3InputUVP == YES) {
  437. //log_info("CheckPhaseLossStatus\r\n");
  438. pDcChargingInfo->StopChargeFlag = YES;
  439. }
  440. }
  441. void SetK1K2RelayStatus(uint8_t index)
  442. {
  443. uint8_t targetID = 0;
  444. PreChargingState *pRegPreChargingState = NULL;
  445. PreChargingState *pOutputPreChargingState = NULL;
  446. GunPNState *pRegGunPNState = NULL;
  447. GunPNState *pOutputGunPNState = NULL;
  448. struct ChargingInfoData *pDcChargingInfo = (struct ChargingInfoData *)GetDcChargingInfoData(index);
  449. if (ShmPsuData->Work_Step >= _TEST_MODE && ShmPsuData->Work_Step <= _TEST_MODE) {
  450. if (regRelay.relay_event.bits.Gun1_N == NO) {
  451. outputRelay.relay_event.bits.Gun1_N = YES;
  452. } else if (regRelay.relay_event.bits.Gun1_P == NO) {
  453. outputRelay.relay_event.bits.Gun1_P = YES;
  454. }
  455. return;
  456. }
  457. targetID = getCommTargetID(index);
  458. pRegPreChargingState = (PreChargingState *)&regRelay.relay_event.relay_status[0];
  459. pOutputPreChargingState = (PreChargingState *)&outputRelay.relay_event.relay_status[0];
  460. if (targetID == 0x01) {
  461. pRegGunPNState = (GunPNState *)&regRelay.relay_event.relay_status[1];
  462. pOutputGunPNState = (GunPNState *)&outputRelay.relay_event.relay_status[1];
  463. } else if (targetID == 0x02) {
  464. pRegGunPNState = (GunPNState *)&regRelay.relay_event.relay_status[2];
  465. pOutputGunPNState = (GunPNState *)&outputRelay.relay_event.relay_status[2];
  466. }
  467. switch (pDcChargingInfo->SystemStatus) {
  468. case S_BOOTING:
  469. case S_IDLE:
  470. case S_AUTHORIZING:
  471. case S_REASSIGN_CHECK:
  472. case S_REASSIGN:
  473. case S_PREPARNING:
  474. case S_PREPARING_FOR_EV:
  475. if (pRegGunPNState->GunP == YES) {
  476. pOutputGunPNState->GunP = NO;
  477. } else if (pRegGunPNState->GunN == YES) {
  478. pOutputGunPNState->GunN = NO;
  479. }
  480. if (targetID == 0x02 && pDcChargingInfo->Type == _Type_CCS_2) {
  481. if (pRegPreChargingState->CcsPrecharge == YES) {
  482. pOutputPreChargingState->CcsPrecharge = NO;
  483. }
  484. }
  485. break;
  486. case S_PREPARING_FOR_EVSE:
  487. case S_CHARGING:
  488. //if (pDcChargingInfo->RelayWeldingCheck != YES) {
  489. // break;
  490. //}
  491. if (pRegGunPNState->GunN == NO) {
  492. pOutputGunPNState->GunN = YES;
  493. } else if (pRegGunPNState->GunP == NO) {
  494. pOutputGunPNState->GunP = YES;
  495. }
  496. break;
  497. case S_TERMINATING:
  498. case S_COMPLETE:
  499. case S_ALARM:
  500. if ((pDcChargingInfo->PresentChargingCurrent * 10) <= SEFETY_SWITCH_RELAY_CUR) {
  501. if (pRegGunPNState->GunP == YES) {
  502. pOutputGunPNState->GunP = NO;
  503. } else if (pRegGunPNState->GunN == YES) {
  504. pOutputGunPNState->GunN = NO;
  505. }
  506. }
  507. break;
  508. case S_CCS_PRECHARGE_ST0:
  509. #if defined DD360 || defined DD360Audi || defined DD360ComBox
  510. break;
  511. #endif //defined DD360 || defined DD360Audi || defined DD360ComBox
  512. //if (pDcChargingInfo->Type == _Type_CCS_2 && targetID == 0x02) {
  513. // if (pRegPreChargingState->CcsPrecharge == NO) {
  514. // pOutputPreChargingState->CcsPrecharge = YES;
  515. // } else if (pRegPreChargingState->CcsPrecharge == YES) {
  516. // pRegGunPNState->GunP = NO;
  517. // }
  518. //}
  519. break;
  520. case S_CCS_PRECHARGE_ST1:
  521. #if defined DD360 || defined DD360Audi || defined DD360ComBox
  522. break;
  523. #endif //defined DD360 || defined DD360Audi || defined DD360ComBox
  524. //if (pDcChargingInfo->Type == _Type_CCS_2 && targetID == 0x02) {
  525. // if (pRegGunPNState->GunP == NO) {
  526. // pOutputGunPNState->GunP = YES;
  527. // } else if (pRegGunPNState->GunP == YES) {
  528. // pOutputPreChargingState->CcsPrecharge = NO;
  529. // }
  530. //}
  531. break;
  532. }
  533. }
  534. // 確認 K1 K2 relay 的狀態
  535. void CheckK1K2RelayOutput(uint8_t index)
  536. {
  537. uint8_t targetID = 0;
  538. struct ChargingInfoData *pDcChargingInfo = (struct ChargingInfoData *)GetDcChargingInfoData(index);
  539. targetID = getCommTargetID(index);
  540. switch (targetID) {
  541. case 0x01:
  542. if (regRelay.relay_event.bits.Gun1_N == YES && regRelay.relay_event.bits.Gun1_P == YES) {
  543. pDcChargingInfo->RelayK1K2Status = YES;
  544. } else {
  545. pDcChargingInfo->RelayK1K2Status = NO;
  546. }
  547. if (pDcChargingInfo->Type == _Type_CCS_2) {
  548. #if !defined DD360 && !defined DD360Audi && !defined DD360ComBox
  549. if (regRelay.relay_event.bits.Gun1_N == YES && regRelay.relay_event.bits.CCS_Precharge == YES) {
  550. pDcChargingInfo->RelayKPK2Status = YES;
  551. } else {
  552. pDcChargingInfo->RelayKPK2Status = NO;
  553. }
  554. #else
  555. if (pDcChargingInfo->SystemStatus == S_CCS_PRECHARGE_ST0) {
  556. pDcChargingInfo->RelayKPK2Status = YES;
  557. } else {
  558. pDcChargingInfo->RelayKPK2Status = NO;
  559. }
  560. #endif //!defined DD360 && !defined DD360Audi
  561. }
  562. break;
  563. case 0x02:
  564. if (regRelay.relay_event.bits.Gun2_N == YES &&
  565. regRelay.relay_event.bits.Gun2_P == YES) {
  566. pDcChargingInfo->RelayK1K2Status = YES;
  567. } else {
  568. pDcChargingInfo->RelayK1K2Status = NO;
  569. }
  570. if (pDcChargingInfo->Type == _Type_CCS_2) {
  571. #if !defined DD360 && !defined DD360Audi && !defined DD360ComBox
  572. if (regRelay.relay_event.bits.Gun2_N == YES &&
  573. regRelay.relay_event.bits.CCS_Precharge == YES) {
  574. pDcChargingInfo->RelayKPK2Status = YES;
  575. } else {
  576. pDcChargingInfo->RelayKPK2Status = NO;
  577. }
  578. #else
  579. if (pDcChargingInfo->SystemStatus == S_CCS_PRECHARGE_ST0) {
  580. pDcChargingInfo->RelayKPK2Status = YES;
  581. } else {
  582. pDcChargingInfo->RelayKPK2Status = NO;
  583. }
  584. #endif //!defined DD360 && !defined DD360Audi
  585. }
  586. break;
  587. }
  588. #if !defined DD360 && !defined DD360Audi && !defined DD360ComBox
  589. //DS60-120 add
  590. if (pSysInfo->BridgeRelayStatus == YES) {
  591. if (regRelay.relay_event.bits.Gun1_Parallel_N == NO &&
  592. regRelay.relay_event.bits.Gun1_Parallel_P == NO) {
  593. pSysInfo->BridgeRelayStatus = NO;
  594. }
  595. } else if (pSysInfo->BridgeRelayStatus == NO) {
  596. if (regRelay.relay_event.bits.Gun1_Parallel_N == YES &&
  597. regRelay.relay_event.bits.Gun1_Parallel_P == YES) {
  598. pSysInfo->BridgeRelayStatus = YES;
  599. }
  600. }
  601. #else
  602. pSysInfo->BridgeRelayStatus = YES;
  603. #endif //!defined DD360 && !defined DD360Audi
  604. }
  605. void SetGfdConfig(uint8_t index, uint8_t resister)
  606. {
  607. Gfd_config gfd_config = {
  608. .index = index,
  609. .state = resister,
  610. };
  611. //log_info("************************GFD Vol = %d, GFD Res = %d \n", gfd_config.reqVol, gfd_config.resister);
  612. if (Config_Gfd_Value(Uart5Fd, ADDR_RELAY, &gfd_config) == PASS) {
  613. // log_info("Set reqVol = %f, resister = %d \n",
  614. // gfd_config.reqVol,
  615. // gfd_config.resister);
  616. }
  617. }
  618. void CableCheckDetected(uint8_t index)
  619. {
  620. uint8_t targetID = 0;
  621. struct ChargingInfoData *pDcChargingInfo = (struct ChargingInfoData *)GetDcChargingInfoData(index);
  622. // Cable Check
  623. // 當火線上的電壓 = 車端要求的電壓電流
  624. // _chargingData[targetGun]->EvBatterytargetVoltage
  625. // 才可以開始偵測 1s
  626. // Warning : Rgfd <= 150 歐/V 假設電壓為 500V 則~ Rgfd <= 75000 歐
  627. // Pre-Warning : 150 歐/V < Rgfd <= 500 歐/V 假設電壓為 500V 則 75000 歐 < Rgfd <= 250000
  628. // SO Normal : Rgfd > 500 歐/V 假設電壓為 500 V 則 Rgfd > 250000 歐
  629. if (pSysConfig->TotalConnectorCount == 1) {
  630. if (strncmp((char *)&pSysConfig->ModelName[7], "0", 1) != 0) {
  631. targetID = 0;
  632. } else if (strncmp((char *)&pSysConfig->ModelName[9], "0", 1) != 0) {
  633. targetID = 1;
  634. }
  635. } else {
  636. targetID = index;
  637. }
  638. if ((pDcChargingInfo->Type >= _Type_Chademo &&
  639. pDcChargingInfo->Type <= _Type_GB) ||
  640. (pDcChargingInfo->Type == 0x09 &&
  641. pSysConfig->AlwaysGfdFlag)
  642. ) {
  643. if ((pDcChargingInfo->SystemStatus >= S_PREPARING_FOR_EVSE &&
  644. pDcChargingInfo->SystemStatus <= S_TERMINATING) ||
  645. (pDcChargingInfo->SystemStatus >= S_CCS_PRECHARGE_ST0 &&
  646. pDcChargingInfo->SystemStatus <= S_CCS_PRECHARGE_ST1)
  647. ) {
  648. //if ((pDcChargingInfo->SystemStatus == S_PREPARING_FOR_EVSE) &&
  649. // (pDcChargingInfo->RelayWeldingCheck == YES)
  650. // ) {
  651. if (pDcChargingInfo->SystemStatus == S_PREPARING_FOR_EVSE) {
  652. SetGfdConfig(targetID, GFD_CABLECHK);
  653. } else if ((pDcChargingInfo->SystemStatus >= S_CCS_PRECHARGE_ST0) &&
  654. (pDcChargingInfo->SystemStatus <= S_CCS_PRECHARGE_ST1)
  655. ) {
  656. SetGfdConfig(targetID, GFD_PRECHARGE);
  657. } else if ((pDcChargingInfo->SystemStatus >= S_CHARGING) &&
  658. (pDcChargingInfo->SystemStatus <= S_TERMINATING)
  659. ) {
  660. if ((pDcChargingInfo->Type == _Type_GB) ||
  661. (pDcChargingInfo->Type == _Type_Chademo)
  662. ) {
  663. SetGfdConfig(targetID, GFD_IDLE);
  664. } else {
  665. SetGfdConfig(targetID, GFD_CHARGING);
  666. }
  667. }
  668. } else if (pDcChargingInfo->SystemStatus == S_COMPLETE ||
  669. pDcChargingInfo->SystemStatus == S_PREPARNING ||
  670. pDcChargingInfo->SystemStatus == S_IDLE) {
  671. SetGfdConfig(targetID, GFD_IDLE);
  672. }
  673. }
  674. }
  675. // 讀取 Relay 狀態
  676. void GetRelayOutputStatus(void)
  677. {
  678. if (Query_Relay_Output(Uart5Fd, ADDR_RELAY, &regRelay) == PASS) {
  679. #if !defined DD360 && !defined DD360Audi && !defined DD360ComBox
  680. regRelay.relay_event.bits.AC_Contactor = pSysInfo->AcContactorStatus;
  681. #endif //!defined DD360 && !defined DD360Audi
  682. }
  683. }
  684. // AC 三相輸入電壓
  685. void GetPresentInputVol(void)
  686. {
  687. static uint8_t _threePhaseOvp[3] = {0, 0, 0}; //DS60-120 add
  688. static uint8_t _threePhaseUvp[3] = {0, 0, 0}; //DS60-120 add
  689. PresentInputVoltage inputVoltage = {0};
  690. if (Query_Present_InputVoltage(Uart5Fd, ADDR_RELAY, &inputVoltage) == PASS) {
  691. // resolution : 0.1
  692. pSysInfo->InputVoltageR = ShmRelayModuleData->InputL1Volt = inputVoltage.L1N_L12;
  693. pSysInfo->InputVoltageS = ShmRelayModuleData->InputL2Volt = inputVoltage.L2N_L23;
  694. pSysInfo->InputVoltageT = ShmRelayModuleData->InputL3Volt = inputVoltage.L3N_L31;
  695. //********************************************************************************************************//
  696. // Vin (UVP)
  697. if (pSysInfo->ChargerType == _CHARGER_TYPE_IEC) {
  698. if (pAlarmCode->AlarmEvents.bits.SystemL1InputUVP == NO) {
  699. if (inputVoltage.L1N_L12 < VIN_MIN_VOLTAGE_IEC) {
  700. log_info("In Uvp L1N_L12 = %f \n", inputVoltage.L1N_L12);
  701. if (_threePhaseUvp[0] >= OVP_UVP_CHK_COUNT) {
  702. pAlarmCode->AlarmEvents.bits.SystemL1InputUVP = YES;
  703. } else {
  704. _threePhaseUvp[0] += 1;
  705. }
  706. }
  707. } else {
  708. if (inputVoltage.L1N_L12 > VIN_MIN_REV_VOLTAGE_IEC) {
  709. pAlarmCode->AlarmEvents.bits.SystemL1InputUVP = NO;
  710. _threePhaseUvp[0] = 0;
  711. }
  712. }
  713. if (pAlarmCode->AlarmEvents.bits.SystemL2InputUVP == NO) {
  714. if (inputVoltage.L2N_L23 < VIN_MIN_VOLTAGE_IEC) {
  715. log_info("In Uvp L2N_L23 = %f \n", inputVoltage.L2N_L23);
  716. if (_threePhaseUvp[1] >= OVP_UVP_CHK_COUNT) {
  717. pAlarmCode->AlarmEvents.bits.SystemL2InputUVP = YES;
  718. } else {
  719. _threePhaseUvp[1] += 1;
  720. }
  721. }
  722. } else {
  723. if (inputVoltage.L2N_L23 > VIN_MIN_REV_VOLTAGE_IEC) {
  724. pAlarmCode->AlarmEvents.bits.SystemL2InputUVP = NO;
  725. _threePhaseUvp[1] = 0;
  726. }
  727. }
  728. if (pAlarmCode->AlarmEvents.bits.SystemL3InputUVP == NO) {
  729. if (inputVoltage.L3N_L31 < VIN_MIN_VOLTAGE_IEC) {
  730. log_info("In Uvp L3N_L31 = %f \n", inputVoltage.L3N_L31);
  731. if (_threePhaseUvp[2] >= OVP_UVP_CHK_COUNT) {
  732. pAlarmCode->AlarmEvents.bits.SystemL3InputUVP = YES;
  733. } else {
  734. _threePhaseUvp[2] += 1;
  735. }
  736. }
  737. } else {
  738. if (inputVoltage.L3N_L31 > VIN_MIN_REV_VOLTAGE_IEC) {
  739. pAlarmCode->AlarmEvents.bits.SystemL3InputUVP = NO;
  740. _threePhaseUvp[2] = 0;
  741. }
  742. }
  743. } else if (pSysInfo->ChargerType == _CHARGER_TYPE_UL) {
  744. if (pAlarmCode->AlarmEvents.bits.SystemL1InputUVP == NO) {
  745. if (inputVoltage.L1N_L12 < VIN_MIN_VOLTAGE_UL) {
  746. log_info("In Uvp L1N_L12 = %f \n", inputVoltage.L1N_L12);
  747. if (_threePhaseUvp[0] >= OVP_UVP_CHK_COUNT) {
  748. pAlarmCode->AlarmEvents.bits.SystemL1InputUVP = YES;
  749. } else {
  750. _threePhaseUvp[0] += 1;
  751. }
  752. }
  753. } else {
  754. if (inputVoltage.L1N_L12 > VIN_MIN_REV_VOLTAGE_UL) {
  755. pAlarmCode->AlarmEvents.bits.SystemL1InputUVP = NO;
  756. _threePhaseUvp[0] = 0;
  757. }
  758. }
  759. if (pAlarmCode->AlarmEvents.bits.SystemL2InputUVP == NO) {
  760. if (inputVoltage.L2N_L23 < VIN_MIN_VOLTAGE_UL) {
  761. log_info("In Uvp L2N_L23 = %f \n", inputVoltage.L2N_L23);
  762. if (_threePhaseUvp[1] >= OVP_UVP_CHK_COUNT) {
  763. pAlarmCode->AlarmEvents.bits.SystemL2InputUVP = YES;
  764. } else {
  765. _threePhaseUvp[1] += 1;
  766. }
  767. }
  768. } else {
  769. if (inputVoltage.L2N_L23 > VIN_MIN_REV_VOLTAGE_UL) {
  770. pAlarmCode->AlarmEvents.bits.SystemL2InputUVP = NO;
  771. _threePhaseUvp[1] = 0;
  772. }
  773. }
  774. if (pAlarmCode->AlarmEvents.bits.SystemL3InputUVP == NO) {
  775. if (inputVoltage.L3N_L31 < VIN_MIN_VOLTAGE_UL) {
  776. log_info("In Uvp L3N_L31 = %f \n", inputVoltage.L3N_L31);
  777. if (_threePhaseUvp[2] >= OVP_UVP_CHK_COUNT) {
  778. pAlarmCode->AlarmEvents.bits.SystemL3InputUVP = YES;
  779. } else {
  780. _threePhaseUvp[2] += 1;
  781. }
  782. }
  783. } else {
  784. if (inputVoltage.L3N_L31 > VIN_MIN_REV_VOLTAGE_UL) {
  785. pAlarmCode->AlarmEvents.bits.SystemL3InputUVP = NO;
  786. _threePhaseUvp[2] = 0;
  787. }
  788. }
  789. }
  790. //********************************************************************************************************//
  791. // Vin (OVP)
  792. if (pSysInfo->ChargerType == _CHARGER_TYPE_IEC) {
  793. if (pAlarmCode->AlarmEvents.bits.SystemL1InputOVP == NO) {
  794. if (inputVoltage.L1N_L12 > VIN_MAX_VOLTAGE_IEC) {
  795. log_info("In Ovp L1N_L12 = %f \n", inputVoltage.L1N_L12);
  796. if (_threePhaseOvp[0] >= OVP_UVP_CHK_COUNT) {
  797. pAlarmCode->AlarmEvents.bits.SystemL1InputOVP = YES;
  798. } else {
  799. _threePhaseOvp[0] += 1;
  800. }
  801. }
  802. } else {
  803. if (inputVoltage.L1N_L12 < VIN_MAX_REV_VOLTAGE_IEC) {
  804. pAlarmCode->AlarmEvents.bits.SystemL1InputOVP = NO;
  805. _threePhaseOvp[0] = 0;
  806. }
  807. }
  808. if (pAlarmCode->AlarmEvents.bits.SystemL2InputOVP == NO) {
  809. if (inputVoltage.L2N_L23 > VIN_MAX_VOLTAGE_IEC) {
  810. log_info("In Ovp L2N_L23 = %f \n", inputVoltage.L2N_L23);
  811. if (_threePhaseOvp[1] >= OVP_UVP_CHK_COUNT) {
  812. pAlarmCode->AlarmEvents.bits.SystemL2InputOVP = YES;
  813. } else {
  814. _threePhaseOvp[1] += 1;
  815. }
  816. }
  817. } else {
  818. if (inputVoltage.L2N_L23 < VIN_MAX_REV_VOLTAGE_IEC) {
  819. pAlarmCode->AlarmEvents.bits.SystemL2InputOVP = NO;
  820. _threePhaseOvp[1] = 0;
  821. }
  822. }
  823. if (pAlarmCode->AlarmEvents.bits.SystemL3InputOVP == NO) {
  824. if (inputVoltage.L3N_L31 > VIN_MAX_VOLTAGE_IEC) {
  825. log_info("In Ovp L3N_L31 = %f \n", inputVoltage.L3N_L31);
  826. if (_threePhaseOvp[2] >= OVP_UVP_CHK_COUNT) {
  827. pAlarmCode->AlarmEvents.bits.SystemL3InputOVP = YES;
  828. } else {
  829. _threePhaseOvp[2] += 1;
  830. }
  831. }
  832. } else {
  833. if (inputVoltage.L3N_L31 < VIN_MAX_REV_VOLTAGE_IEC) {
  834. pAlarmCode->AlarmEvents.bits.SystemL3InputOVP = NO;
  835. _threePhaseOvp[2] = 0;
  836. }
  837. }
  838. } else if (pSysInfo->ChargerType == _CHARGER_TYPE_UL) {
  839. if (pAlarmCode->AlarmEvents.bits.SystemL1InputOVP == NO) {
  840. if (inputVoltage.L1N_L12 > VIN_MAX_VOLTAGE_UL) {
  841. log_info("In Ovp L1N_L12 = %f \n", inputVoltage.L1N_L12);
  842. if (_threePhaseOvp[0] >= OVP_UVP_CHK_COUNT) {
  843. pAlarmCode->AlarmEvents.bits.SystemL1InputOVP = YES;
  844. } else {
  845. _threePhaseOvp[0] += 0;
  846. }
  847. }
  848. } else {
  849. if (inputVoltage.L1N_L12 < VIN_MAX_REV_VOLTAGE_UL) {
  850. pAlarmCode->AlarmEvents.bits.SystemL1InputOVP = NO;
  851. _threePhaseOvp[0] = 0;
  852. }
  853. }
  854. if (pAlarmCode->AlarmEvents.bits.SystemL2InputOVP == NO) {
  855. if (inputVoltage.L2N_L23 > VIN_MAX_VOLTAGE_UL) {
  856. log_info("In Ovp L2N_L23 = %f \n", inputVoltage.L2N_L23);
  857. if (_threePhaseOvp[1] >= OVP_UVP_CHK_COUNT) {
  858. pAlarmCode->AlarmEvents.bits.SystemL2InputOVP = YES;
  859. } else {
  860. _threePhaseOvp[1] += 0;
  861. }
  862. }
  863. } else {
  864. if (inputVoltage.L2N_L23 < VIN_MAX_REV_VOLTAGE_UL) {
  865. pAlarmCode->AlarmEvents.bits.SystemL2InputOVP = NO;
  866. _threePhaseOvp[1] = 0;
  867. }
  868. }
  869. if (pAlarmCode->AlarmEvents.bits.SystemL2InputOVP == NO) {
  870. if (inputVoltage.L3N_L31 > VIN_MAX_VOLTAGE_UL) {
  871. log_info("In Ovp L3N_L31 = %f \n", inputVoltage.L3N_L31);
  872. if (_threePhaseOvp[2] >= OVP_UVP_CHK_COUNT) {
  873. pAlarmCode->AlarmEvents.bits.SystemL3InputOVP = YES;
  874. } else {
  875. _threePhaseOvp[2] += 1;
  876. }
  877. }
  878. } else {
  879. if (inputVoltage.L3N_L31 < VIN_MAX_REV_VOLTAGE_UL) {
  880. pAlarmCode->AlarmEvents.bits.SystemL3InputOVP = NO;
  881. _threePhaseOvp[2] = 0;
  882. }
  883. }
  884. }
  885. }
  886. }
  887. // 左右槍的 Relay 前後的輸出電壓
  888. void GetPersentOutputVol(void)
  889. {
  890. uint8_t index = 0;
  891. uint8_t targetID = 0;
  892. struct ChargingInfoData *pDcChargingInfo = NULL;
  893. PresentOutputVoltage outputVoltage = {0};
  894. if (Query_Present_OutputVoltage(Uart5Fd, ADDR_RELAY, &outputVoltage) != PASS) {
  895. return;
  896. }
  897. //log_info("Conn1 fuse 1 = %f \n", outputVoltage.behindFuse_Voltage_C1);
  898. //log_info("Conn1 relay 1 = %f \n", outputVoltage.behindRelay_Voltage_C1);
  899. //log_info("Conn2 fuse 2 = %f \n", outputVoltage.behindFuse_Voltage_C2);
  900. //log_info("Conn2 relay 2 = %f \n", outputVoltage.behindRelay_Voltage_C2);
  901. //log_info("outputVoltage.behindFuse_Voltage_C1 = %f \n", outputVoltage.behindFuse_Voltage_C1);
  902. //log_info("outputVoltage.behindFuse_Voltage_C2 = %f \n", outputVoltage.behindFuse_Voltage_C2);
  903. ShmRelayModuleData->Gun1FuseOutputVolt = outputVoltage.behindFuse_Voltage_C1;
  904. ShmRelayModuleData->Gun1RelayOutputVolt = outputVoltage.behindRelay_Voltage_C1;
  905. ShmRelayModuleData->Gun2FuseOutputVolt = outputVoltage.behindFuse_Voltage_C2;
  906. ShmRelayModuleData->Gun2RelayOutputVolt = outputVoltage.behindRelay_Voltage_C2;
  907. for (index = 0; index < pSysConfig->TotalConnectorCount; index++) {
  908. pDcChargingInfo = (struct ChargingInfoData *)GetDcChargingInfoData(index);
  909. targetID = getCommTargetID(index);
  910. switch (targetID) {
  911. case 0x01:
  912. #if defined DD360 || defined DD360Audi || defined DD360ComBox
  913. pDcChargingInfo->FireChargingVoltage = ShmRelayModuleData->Gun1RelayOutputVolt;
  914. pDcChargingInfo->PresentChargingCurrent = ShmRelayModuleData->Gun1FuseOutputVolt / 10;
  915. pDcChargingInfo->PresentChargingVoltage = pDcChargingInfo->FireChargingVoltage / 10;
  916. pDcChargingInfo->FuseChargingVoltage = pDcChargingInfo->FireChargingVoltage;
  917. break;
  918. #endif //defined DD360 || defined DD360Audi || defined DD360ComBox
  919. pDcChargingInfo->FireChargingVoltage = ShmRelayModuleData->Gun1RelayOutputVolt;
  920. pDcChargingInfo->FuseChargingVoltage = ShmRelayModuleData->Gun1FuseOutputVolt;
  921. break;
  922. case 0x02:
  923. #if defined DD360 || defined DD360Audi || defined DD360ComBox
  924. pDcChargingInfo->FireChargingVoltage = ShmRelayModuleData->Gun2RelayOutputVolt;
  925. pDcChargingInfo->PresentChargingCurrent = ShmRelayModuleData->Gun2FuseOutputVolt / 10;
  926. pDcChargingInfo->PresentChargingVoltage = pDcChargingInfo->FireChargingVoltage / 10;
  927. pDcChargingInfo->FuseChargingVoltage = pDcChargingInfo->FireChargingVoltage;
  928. break;
  929. #endif //defined DD360 || defined DD360Audi || defined DD360ComBox
  930. pDcChargingInfo->FireChargingVoltage = ShmRelayModuleData->Gun2RelayOutputVolt;
  931. pDcChargingInfo->FuseChargingVoltage = ShmRelayModuleData->Gun2FuseOutputVolt;
  932. break;
  933. }
  934. //unsigned short Ovp = 0;
  935. //unsigned short Ocp = 0;
  936. //Ovp = MIN [VOUT_MAX_VOLTAGE, EV_BATTERY_VOLTAGE] // 最大輸出電壓與電池電壓最大值
  937. //Ocp = MIN [IOUT_MAX_CURRENT, EV_CURRENT_REQ] // 最大輸出電流與需求電流最小值
  938. //if (pDcChargingInfo->Type == _Type_Chademo) {
  939. // //Ovp = MaxValue(pDcChargingInfo->MaximumChargingVoltage, pDcChargingInfo->EvBatteryMaxVoltage);
  940. // //Ocp = MaxValue(pDcChargingInfo->PresentChargingCurrent, ShmCHAdeMOData->ev[pDcChargingInfo->type_index].ChargingCurrentRequest);
  941. //} else if (pDcChargingInfo->Type == _Type_CCS_2) {
  942. //}
  943. }
  944. }
  945. void SetRtcData_Relay(void)
  946. {
  947. struct timeb csuTime;
  948. struct tm *tmCSU;
  949. Rtc rtc = {0};
  950. ftime(&csuTime);
  951. tmCSU = localtime(&csuTime.time);
  952. // log_info("Time : %04d-%02d-%02d %02d:%02d:%02d \n", tmCSU->tm_year + 1900,
  953. // tmCSU->tm_mon + 1, tmCSU->tm_mday, tmCSU->tm_hour, tmCSU->tm_min,
  954. // tmCSU->tm_sec);
  955. rtc.RtcData[0] = '0' + (tmCSU->tm_year + 1900) / 1000 % 10;
  956. rtc.RtcData[1] = '0' + (tmCSU->tm_year + 1900) / 100 % 10;
  957. rtc.RtcData[2] = '0' + (tmCSU->tm_year + 1900) / 10 % 10;
  958. rtc.RtcData[3] = '0' + (tmCSU->tm_year + 1900) / 1 % 10;
  959. rtc.RtcData[4] = '0' + (tmCSU->tm_mon + 1) / 10 % 10;
  960. rtc.RtcData[5] = '0' + (tmCSU->tm_mon + 1) / 1 % 10;
  961. rtc.RtcData[6] = '0' + (tmCSU->tm_mday) / 10 % 10;
  962. rtc.RtcData[7] = '0' + (tmCSU->tm_mday) / 1 % 10;
  963. rtc.RtcData[8] = '0' + (tmCSU->tm_hour) / 10 % 10;
  964. rtc.RtcData[9] = '0' + (tmCSU->tm_hour) / 1 % 10;
  965. rtc.RtcData[10] = '0' + (tmCSU->tm_min) / 10 % 10;
  966. rtc.RtcData[11] = '0' + (tmCSU->tm_min) / 1 % 10;
  967. rtc.RtcData[12] = '0' + (tmCSU->tm_sec) / 10 % 10;
  968. rtc.RtcData[13] = '0' + (tmCSU->tm_sec) / 1 % 10;
  969. if (Config_Rtc_Data(Uart5Fd, ADDR_RELAY, &rtc) == PASS) {
  970. //log_info("SetRtc (RB) sucessfully. \n");
  971. }
  972. }
  973. void SetModelName_Relay(void)
  974. {
  975. if (Config_Model_Name(Uart5Fd, ADDR_RELAY, pSysConfig->ModelName) == PASS) {
  976. //log_info("Set Model name (RB) PASS = %s \n", pSysConfig->ModelName);
  977. }
  978. }
  979. void GetFwAndHwVersion_Relay(void)
  980. {
  981. Ver ver = {0};
  982. if (Query_FW_Ver(Uart5Fd, ADDR_RELAY, &ver) == PASS) {
  983. // RelayModuleData
  984. strcpy((char *)ShmRelayModuleData->version, ver.Version_FW);
  985. // SystemInfo
  986. strcpy((char *)pSysInfo->RelayModuleFwRev, ver.Version_FW);
  987. //log_info("GetFwAndHwVersion_Relay s1 = %s \n", ver.Version_FW);
  988. }
  989. if (Query_HW_Ver(Uart5Fd, ADDR_RELAY, &ver) == PASS) {
  990. // SystemInfo
  991. strcpy((char *)pSysInfo->RelayModuleHwRev, ver.Version_FW);
  992. //log_info("GetFwAndHwVersion_Relay s2 = %s \n", ver.Version_HW);
  993. }
  994. }
  995. static void outputRelayInit(int fd)
  996. {
  997. memset((uint8_t *)&outputRelay, 0, sizeof(Relay));
  998. if (Config_Relay_Output(fd, ADDR_RELAY, &outputRelay) != PASS) {
  999. log_info("Config_Relay_Output fail \n");
  1000. }
  1001. }
  1002. void RelayBoardTask(int uartFD)
  1003. {
  1004. pid_t pid = fork();
  1005. if (pid == 0) {
  1006. bool isCharging = false;
  1007. bool isStopChargingCount = false;
  1008. uint8_t i = 0;
  1009. int isContinue = 1;
  1010. struct ChargingInfoData *pDcChargingInfo = NULL;
  1011. //share memory mapping
  1012. pSysConfig = (struct SysConfigData *)GetShmSysConfigData();
  1013. pSysInfo = (struct SysInfoData *)GetShmSysInfoData();
  1014. pAlarmCode = (struct AlarmCodeData *)GetShmAlarmCodeData();
  1015. ShmRelayModuleData = (struct RelayModuleData *)GetShmRelayModuleData();
  1016. ShmPsuData = (struct PsuData *)GetShmPsuData();
  1017. ShmDcCommonData = (DcCommonInfo *)GetShmDcCommonData();
  1018. ShmPrimaryMcuData = (struct PrimaryMcuData *)GetShmPrimaryMcuData();
  1019. Uart5Fd = uartFD;
  1020. //relay init
  1021. outputRelayInit(uartFD);
  1022. while (isContinue) {
  1023. // 程序開始之前~ 必須先確定 FW 版本與硬體版本,確認後!!~ 該模組才算是真正的 Initial Comp.
  1024. if (ShmRelayModuleData->SelfTest_Comp == NO) {
  1025. GetFwAndHwVersion_Relay();
  1026. SetModelName_Relay(); //DS60-120 add
  1027. SetRtcData_Relay();
  1028. sleep(1);
  1029. continue;
  1030. }
  1031. // ==============優先權最高 10 ms ==============
  1032. // 輸出電壓
  1033. GetPersentOutputVol();
  1034. #if !defined DD360 && !defined DD360Audi && !defined DD360ComBox
  1035. // 三相輸入電壓
  1036. GetPresentInputVol();
  1037. #endif //!defined DD360 && !defined DD360Audi
  1038. // 讀取當前 AC relay 狀態
  1039. regRelay.relay_event.bits.AC_Contactor = pSysInfo->AcContactorStatus;
  1040. GetRelayOutputStatus();
  1041. for (i = 0; i < pSysConfig->TotalConnectorCount; i++) {
  1042. pDcChargingInfo = (struct ChargingInfoData *)GetDcChargingInfoData(i);
  1043. // Cable check (Set)
  1044. CableCheckDetected(i);
  1045. // check k1 k2 relay 狀態
  1046. CheckK1K2RelayOutput(i);
  1047. // 依據當前各槍的狀態選擇 搭上/放開 Relay
  1048. SetK1K2RelayStatus(i);
  1049. #if !defined DD360 && !defined DD360Audi && !defined DD360ComBox
  1050. if (pSysConfig->PhaseLossPolicy == YES) {
  1051. CheckPhaseLossStatus(i);
  1052. }
  1053. CheckAcInputOvpStatus(i);
  1054. #endif //!defined DD360 && !defined DD360Audi
  1055. if (pDcChargingInfo->SystemStatus == S_IDLE ||
  1056. pDcChargingInfo->SystemStatus == S_RESERVATION ||
  1057. pDcChargingInfo->SystemStatus == S_MAINTAIN) {
  1058. //pDcChargingInfo->RelayWeldingCheck = NO;
  1059. //_isRelayWelding[i] = NO;
  1060. _isOvpChkTimeFlag[i] = NO;
  1061. //ResetDetAlarmStatus(i); //DS60-120 add
  1062. }
  1063. if (pDcChargingInfo->SystemStatus == S_BOOTING ||
  1064. (pDcChargingInfo->SystemStatus >= S_REASSIGN_CHECK &&
  1065. pDcChargingInfo->SystemStatus <= S_COMPLETE) ||
  1066. (pDcChargingInfo->SystemStatus >= S_CCS_PRECHARGE_ST0 &&
  1067. pDcChargingInfo->SystemStatus <= S_CCS_PRECHARGE_ST1) ||
  1068. pSysInfo->WaitForPlugit == YES ||
  1069. (pSysInfo->PageIndex >= _LCM_AUTHORIZING &&
  1070. pSysInfo->PageIndex <= _LCM_WAIT_FOR_PLUG)
  1071. ) {
  1072. pDcChargingInfo->IsReadyToCharging = YES;
  1073. isCharging = true;
  1074. // 限定只有在槍類別為 GBT 的時候才做 relay welding 的判斷
  1075. //if (pDcChargingInfo->Type == _Type_GB) {
  1076. // if (pDcChargingInfo->SystemStatus >= S_PREPARING_FOR_EVSE &&
  1077. // pDcChargingInfo->RelayWeldingCheck == NO) {
  1078. // CheckRelayWeldingStatus(i);
  1079. // }
  1080. //} else {
  1081. //pDcChargingInfo->RelayWeldingCheck = YES;
  1082. //}
  1083. if (pDcChargingInfo->SystemStatus == S_CHARGING) {
  1084. CheckOutputPowerOverCarReq(i);
  1085. //CheckOutputVolNoneMatchFire(i);
  1086. }
  1087. /*else {
  1088. _isOutputNoneMatch[i] = NO;
  1089. }*/
  1090. } else {
  1091. pDcChargingInfo->IsReadyToCharging = NO;
  1092. }
  1093. }
  1094. // Cable check (Get)
  1095. GetGfdAdc();
  1096. // 橋接 relay
  1097. SetParalleRelayStatus();
  1098. // 搭上 AC Contactor
  1099. //if (isCharging) {
  1100. // outputRelay.relay_event.bits.AC_Contactor = YES;
  1101. //} else {
  1102. // outputRelay.relay_event.bits.AC_Contactor = NO;
  1103. //}
  1104. if (isCharging ||
  1105. (ShmPsuData->Work_Step >= _TEST_MODE &&
  1106. ShmPsuData->Work_Step <= _TEST_MODE)) {
  1107. isStopChargingCount = false;
  1108. outputRelay.relay_event.bits.AC_Contactor = YES;
  1109. } else {
  1110. if (!isStopChargingCount) {
  1111. gettimeofday(&_close_ac_contactor, NULL);
  1112. isStopChargingCount = true;
  1113. } else {
  1114. if ((outputRelay.relay_event.bits.AC_Contactor == YES &&
  1115. GetTimeoutValue(_close_ac_contactor) / 1000 >= (TEN_MINUTES * 1000))) {
  1116. outputRelay.relay_event.bits.AC_Contactor = NO;
  1117. }
  1118. }
  1119. }
  1120. if (ShmPrimaryMcuData->InputDet.bits.EmergencyButton == ABNORMAL) {
  1121. outputRelay.relay_event.bits.AC_Contactor = NO;
  1122. }
  1123. if (pAlarmCode->AlarmEvents.bits.PsuFailureAlarm == ABNORMAL) {
  1124. RunForceStopProcess();
  1125. outputRelay.relay_event.bits.AC_Contactor = NO;
  1126. }
  1127. if (ShmPsuData->Work_Step >= _TEST_MODE && ShmPsuData->Work_Step <= _TEST_MODE) {
  1128. outputRelay.relay_event.bits.Gun1_N = outputRelay.relay_event.bits.Gun1_P = YES;
  1129. }
  1130. // 搭上/鬆開 Relay
  1131. if (IsNoneMatchRelayStatus()) {
  1132. if (Config_Relay_Output(Uart5Fd, ADDR_RELAY, &outputRelay)) {
  1133. //regRelay.relay_event.bits.AC_Contactor = pSysInfo->AcContactorStatus;
  1134. //regRelay.relay_event.bits.CCS_Precharge = outputRelay.relay_event.bits.CCS_Precharge;
  1135. //regRelay.relay_event.bits.Gun1_P = outputRelay.relay_event.bits.Gun1_P;
  1136. //regRelay.relay_event.bits.Gun1_N = outputRelay.relay_event.bits.Gun1_N;
  1137. //regRelay.relay_event.bits.Gun2_P = outputRelay.relay_event.bits.Gun2_P;
  1138. //regRelay.relay_event.bits.Gun2_N = outputRelay.relay_event.bits.Gun2_N;
  1139. //regRelay.relay_event.bits.Gun1_Parallel_P = outputRelay.relay_event.bits.Gun1_Parallel_P;
  1140. //regRelay.relay_event.bits.Gun1_Parallel_N = outputRelay.relay_event.bits.Gun1_Parallel_N;
  1141. //MatchRelayStatus();
  1142. //log_info("Match Relay, AC = %x, g1_p = %x, g1_n = %x, g2_p = %x, g2_n = %x, pre = %x, bri_p = %x, bri_n = %x \n",
  1143. // regRelay.relay_event.bits.AC_Contactor,
  1144. // regRelay.relay_event.bits.Gun1_P,
  1145. // regRelay.relay_event.bits.Gun1_N,
  1146. // regRelay.relay_event.bits.Gun2_P,
  1147. // regRelay.relay_event.bits.Gun2_N,
  1148. // regRelay.relay_event.bits.CCS_Precharge,
  1149. // regRelay.relay_event.bits.Gun1_Parallel_P,
  1150. // regRelay.relay_event.bits.Gun1_Parallel_N);
  1151. }
  1152. } /*else {
  1153. log_info("======== Relay Status Start========\n");
  1154. if (regRelay.relay_event.bits.AC_Contactor == YES) {
  1155. log_info("AC Power : ON \n");
  1156. } else {
  1157. log_info("AC Power : OFF \n");
  1158. }
  1159. if (regRelay.relay_event.bits.Gun1_P == YES) {
  1160. log_info("Conn1(+) : ON \n");
  1161. } else {
  1162. log_info("Conn1(+) : OFF \n");
  1163. }
  1164. if (regRelay.relay_event.bits.Gun1_N == YES) {
  1165. log_info("Conn1(-) : ON \n");
  1166. } else {
  1167. log_info("Conn1(-) : OFF \n");
  1168. }
  1169. if (regRelay.relay_event.bits.Gun2_P == YES) {
  1170. log_info("Conn2(+) : ON \n");
  1171. } else {
  1172. log_info("Conn2(+) : OFF \n");
  1173. }
  1174. if (regRelay.relay_event.bits.Gun2_N == YES) {
  1175. log_info("Conn2(-) : ON \n");
  1176. } else {
  1177. log_info("Conn2(-) : OFF \n");
  1178. }
  1179. if (regRelay.relay_event.bits.CCS_Precharge == YES) {
  1180. log_info("Precharge : ON \n");
  1181. } else {
  1182. log_info("Precharge : OFF \n");
  1183. }
  1184. if (regRelay.relay_event.bits.Gun1_Parallel_P == YES) {
  1185. log_info("Parallel(+) : ON \n");
  1186. } else {
  1187. log_info("Parallel(+) : OFF \n");
  1188. }
  1189. if (regRelay.relay_event.bits.Gun1_Parallel_N == YES) {
  1190. log_info("Parallel(-) : ON \n");
  1191. } else {
  1192. log_info("Parallel(-) : OFF \n");
  1193. }
  1194. log_info("======== Relay Status End========\n");
  1195. }*/
  1196. }
  1197. usleep(100000);
  1198. }
  1199. }