BMS_Set_Error_States.c 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447
  1. /*
  2. * BMS_Set_Error_States.c
  3. *
  4. * Created on: Nov 8, 2016
  5. * Author: le8041
  6. */
  7. #include "BMS_Master.h"
  8. /*
  9. * @brief check if Battery is charged or discharged
  10. * return true if discharged false if charged
  11. */
  12. uint32_t BMS_set_Error_check_if_stable_discharge(MASTER_CAN0_STRUCT_t* s) {
  13. // stable when mean value is bigger than -150mA
  14. uint8_t i;
  15. int16_t Current=0;
  16. for(i=0;i<UI_CURRENT_FIFO_SIZE;i++) {
  17. Current=Current + s->UI_Board.IbattFiFo[i] ;
  18. }
  19. Current = (Current*10) /UI_CURRENT_FIFO_SIZE ;
  20. if(Current > -150) {
  21. // stable discharge
  22. return TRUE;
  23. }
  24. //stable discharge
  25. return FALSE;
  26. }
  27. /*
  28. * @brief ceck if battery is charged stable over given amount of samples
  29. */
  30. uint32_t BMS_set_Error_check_if_stable_charge(MASTER_CAN0_STRUCT_t* s) {
  31. // stable when all values of FiFo are greater than -150
  32. uint8_t i;
  33. for(i=0;i<UI_CURRENT_FIFO_SIZE;i++) {
  34. if(s->UI_Board.IbattFiFo[i] *10 > -150) {
  35. // no stable charge
  36. return FALSE;
  37. }
  38. }
  39. //stable charge
  40. return TRUE;
  41. }
  42. /*
  43. * @brief check voltage levels Umin1 Umin2 Umin3 and set Error states accordingly
  44. * return True if everything is of return false if error occured
  45. */
  46. uint32_t BMS_Set_Error_check_Voltage_level_min(MASTER_CAN0_STRUCT_t* s){
  47. uint16_t Umin;
  48. float PvPwrAvailable;
  49. Umin=s->minCellVoltage;
  50. PvPwrAvailable=s->inverter.rxStruct.expectedInputPower;
  51. if(Umin < BMS_SOC_UMIN_3 ) {
  52. // Voltage level below Umin3
  53. // Kill Relays
  54. s->relayState.HS_closed=FALSE;
  55. s->relayState.LS_closed=FALSE;
  56. s->relayState.PRECHARGE_closed=FALSE;
  57. SwitchRelais( LS_RELAIS, 0);
  58. SwitchRelais( PRE_CHARGE_RELAIS, 0);
  59. SwitchRelais( HS_RELAIS, 0);
  60. // set Error state 3 - should be alse set directly after test of Slave Voltage in Salve
  61. ErrorStackPushMasterError(s,BMS_ERROR_STACK_MASTER_UMIN_3,BMS_ERROR_CLASS_3);
  62. return FALSE;
  63. }
  64. else if(Umin < BMS_SOC_UMIN_2 && BMS_set_Error_check_if_stable_discharge(s) && !ErrorStackCheckifUmin2ErrorRecoveryPending(s) ) {
  65. // Voltage level below Umin2 and Battery is discharged
  66. // Kill Relays
  67. SwitchRelais( LS_RELAIS, 0);
  68. SwitchRelais( PRE_CHARGE_RELAIS, 0);
  69. SwitchRelais( HS_RELAIS, 0);
  70. s->relayState.HS_closed=FALSE;
  71. s->relayState.LS_closed=FALSE;
  72. s->relayState.PRECHARGE_closed=FALSE;
  73. // set Error state 2
  74. ErrorStackPushMasterError(s,BMS_ERROR_STACK_MASTER_UMIN_2,BMS_ERROR_CLASS_2);
  75. return FALSE;
  76. }
  77. else if(Umin < BMS_SOC_UMIN_1 && BMS_set_Error_check_if_stable_discharge(s) && !ErrorStackCheckifUmin1ErrorRecoveryPending(s) ) {
  78. // Voltage Level below Umin1 and battery is discharged
  79. // Kill Relays
  80. SwitchRelais( LS_RELAIS, 0);
  81. SwitchRelais( PRE_CHARGE_RELAIS, 0);
  82. SwitchRelais( HS_RELAIS, 0);
  83. s->relayState.HS_closed=FALSE;
  84. s->relayState.LS_closed=FALSE;
  85. s->relayState.PRECHARGE_closed=FALSE;
  86. // set Error state 1
  87. ErrorStackPushMasterError(s,BMS_ERROR_STACK_MASTER_UMIN_1,BMS_ERROR_CLASS_1);
  88. return FALSE;
  89. }
  90. else {
  91. // everything is ok
  92. return TRUE;
  93. }
  94. }
  95. /*
  96. * @brief check max voltage level
  97. */
  98. uint32_t BMS_Set_Error_check_Voltage_level_max(MASTER_CAN0_STRUCT_t* s) {
  99. uint16_t Umax=s->maxCellVoltage;
  100. if(Umax > BMS_SOC_UMAX_3) {
  101. // set Error State 1
  102. // Kill Relays
  103. SwitchRelais( LS_RELAIS, 0);
  104. SwitchRelais( PRE_CHARGE_RELAIS, 0);
  105. SwitchRelais( HS_RELAIS, 0);
  106. s->relayState.HS_closed=FALSE;
  107. s->relayState.LS_closed=FALSE;
  108. s->relayState.PRECHARGE_closed=FALSE;
  109. // set Error state 2
  110. ErrorStackPushMasterError(s,BMS_ERROR_STACK_MASTER_UMAX_3,BMS_ERROR_CLASS_3);
  111. return FALSE;
  112. }
  113. else if(Umax > BMS_SOC_UMAX_2) {
  114. // set Error State 1
  115. // Kill Relays
  116. SwitchRelais( LS_RELAIS, 0);
  117. SwitchRelais( PRE_CHARGE_RELAIS, 0);
  118. SwitchRelais( HS_RELAIS, 0);
  119. s->relayState.HS_closed=FALSE;
  120. s->relayState.LS_closed=FALSE;
  121. s->relayState.PRECHARGE_closed=FALSE;
  122. // set Error state 2
  123. ErrorStackPushMasterError(s,BMS_ERROR_STACK_MASTER_UMAX_2,BMS_ERROR_CLASS_1);
  124. return FALSE;
  125. }
  126. else if(Umax > BMS_SOC_UMAX_1 ) {
  127. // set Error State 0 not implemented yet
  128. // TODO return TRUE; everything is ok
  129. return TRUE;
  130. }
  131. else {
  132. // everything is ok
  133. return TRUE;
  134. }
  135. }
  136. /*
  137. * @brief check if system exceeds maximum System Voltage in case customer plays around with the system
  138. */
  139. uint32_t BMS_Set_Error_check_System_voltage_level_max(MASTER_CAN0_STRUCT_t* s) {
  140. uint32_t Uges=s->systemVoltage;
  141. if(Uges >BMS_ERROR_THRESHOLD_UMAX_SYSTEM) {
  142. // Kill Relays
  143. SwitchRelais( LS_RELAIS, 0);
  144. SwitchRelais( PRE_CHARGE_RELAIS, 0);
  145. SwitchRelais( HS_RELAIS, 0);
  146. s->relayState.HS_closed=FALSE;
  147. s->relayState.LS_closed=FALSE;
  148. s->relayState.PRECHARGE_closed=FALSE;
  149. // set Error state 3
  150. ErrorStackPushMasterError(s,BMS_ERROR_STACK_MASTER_UMAX_SYSTEM,BMS_ERROR_CLASS_3);
  151. return FALSE;
  152. }
  153. else {
  154. //everything is ok
  155. return TRUE;
  156. }
  157. }
  158. /*
  159. *@brief do linear interpolation
  160. */
  161. float BMS_Set_Error_linear_interpolate(float x1,float x2,float x,float y1,float y2) {
  162. // solve linear eq y1= m*x1 + b
  163. // y2= m*x2 + b
  164. float m = (y2-y1)/(float)(x2-x1);
  165. float b = y1 - m*(float)(x1);
  166. //
  167. return m*(float)(x) + b;
  168. }
  169. /*
  170. *
  171. */
  172. float BMS_Set_Error_generate_Fcn(float* x_values,float* y_values,uint8_t NrOfPoints, float x) {
  173. uint8_t i;
  174. if(x < x_values[0]) {
  175. // value is to the left of the described area => return left most value
  176. return y_values[0];
  177. }
  178. else if( x> x_values[NrOfPoints -1] ) {
  179. // value is to the right of the described area => return right most value
  180. return y_values[NrOfPoints -1];
  181. }
  182. // find left x_value to x
  183. for(i=0;i< NrOfPoints; i++) {
  184. if(x_values[i] <= x && x_values[i+1] >= x ) {
  185. // x is between x_value[i] and x_value[i+1]
  186. return BMS_Set_Error_linear_interpolate(x_values[i],x_values[i+1],x,y_values[i],y_values[i+1]);
  187. }
  188. }
  189. }
  190. uint32_t BMS_Set_Error_Check_derating(MASTER_CAN0_STRUCT_t* s) {
  191. float Current = (float)(s->UI_Board.Ibatt*10);
  192. float minTemp = (float)s->minCellTemp;
  193. float maxTemp = (float)s->maxCellTemp;
  194. float SoC = s->SoC_estimator.SoC_percentage_smooth_FiFo[5];
  195. float capacity = 26.0 ; // capacity 26.0 Ah
  196. float temp_discharge_x[4]={0,25,40,55};
  197. float temp_discharge_y[4]={0.3,1.1,1.1,0};
  198. float temp_charge_x[5]={-5,0,25,40,50};
  199. float temp_charge_y[5]={0.3,0.6,1.1,1.1,0};
  200. float SoC_charge_x[5]={0,0.8,0.95,0.999,1};
  201. float SoC_charge_y[5]={25,25,2.5,2.5,0};
  202. float SoC_discharge_x[5]={0,0.001,0.05,0.2,1};
  203. float SoC_discharge_y[5]={0,2.5,2.5,25,25};
  204. s->currentLimits.I_max_charge_temp_max = BMS_Set_Error_generate_Fcn(temp_charge_x,temp_charge_y,5,maxTemp)*25*1000;
  205. s->currentLimits.I_max_charge_temp_min = BMS_Set_Error_generate_Fcn(temp_charge_x,temp_charge_y,5,minTemp)*25*1000;
  206. s->currentLimits.I_max_charge_SoC = BMS_Set_Error_generate_Fcn(SoC_charge_x,SoC_charge_y,5,SoC)*1000 *1.1 ;
  207. s->currentLimits.I_max_discharge_temp_max = BMS_Set_Error_generate_Fcn(temp_discharge_x,temp_discharge_y,4,maxTemp)*25*1000;
  208. s->currentLimits.I_max_discharge_temp_min = BMS_Set_Error_generate_Fcn(temp_discharge_x,temp_discharge_y,4,minTemp)*25*1000;
  209. s->currentLimits.I_max_discharge_SoC = BMS_Set_Error_generate_Fcn(SoC_discharge_x,SoC_discharge_y,5,SoC)*1000 *1.1 ;
  210. if(Current < -100) {
  211. // Battery is charged
  212. // check temperature derating at tmin
  213. // check if low temperature is violated
  214. if((-1)*Current > s->currentLimits.I_max_charge_temp_min) {
  215. // current to high
  216. ErrorStackPushMasterError(s,BMS_ERROR_STACK_MASTER_I_MAX_CHARGE_OP,BMS_ERROR_CLASS_1);
  217. // Kill Relays
  218. SwitchRelais( LS_RELAIS, 0);
  219. SwitchRelais( PRE_CHARGE_RELAIS, 0);
  220. SwitchRelais( HS_RELAIS, 0);
  221. s->relayState.HS_closed=FALSE;
  222. s->relayState.LS_closed=FALSE;
  223. s->relayState.PRECHARGE_closed=FALSE;
  224. return FALSE;
  225. }
  226. // check temperature derating at tmax
  227. // check if low temperature is violated
  228. else if((-1)*Current > s->currentLimits.I_max_charge_temp_max ) {
  229. // current too high
  230. ErrorStackPushMasterError(s,BMS_ERROR_STACK_MASTER_I_MAX_CHARGE_OP,BMS_ERROR_CLASS_1);
  231. // Kill Relays
  232. SwitchRelais( LS_RELAIS, 0);
  233. SwitchRelais( PRE_CHARGE_RELAIS, 0);
  234. SwitchRelais( HS_RELAIS, 0);
  235. s->relayState.HS_closed=FALSE;
  236. s->relayState.LS_closed=FALSE;
  237. s->relayState.PRECHARGE_closed=FALSE;
  238. return FALSE;
  239. }
  240. // check SoC derating // normal derating curve + 10%
  241. else if((-1)*Current > s->currentLimits.I_max_charge_SoC) {
  242. // current too high
  243. ErrorStackPushMasterError(s,BMS_ERROR_STACK_MASTER_I_MAX_CHARGE_OP,BMS_ERROR_CLASS_1);
  244. // Kill Relays
  245. SwitchRelais( LS_RELAIS, 0);
  246. SwitchRelais( PRE_CHARGE_RELAIS, 0);
  247. SwitchRelais( HS_RELAIS, 0);
  248. s->relayState.HS_closed=FALSE;
  249. s->relayState.LS_closed=FALSE;
  250. s->relayState.PRECHARGE_closed=FALSE;
  251. return FALSE;
  252. }
  253. else {
  254. // derating is ok
  255. return TRUE;
  256. }
  257. }
  258. else if(Current > 100) {
  259. // Battery is discharged
  260. // check temperature derating at tmin
  261. // check if low temperature is violated
  262. if(Current > s->currentLimits.I_max_discharge_temp_min ) {
  263. // current to high
  264. ErrorStackPushMasterError(s,BMS_ERROR_STACK_MASTER_I_MAX_DISCHARGE_OP,BMS_ERROR_CLASS_1);
  265. // Kill Relays
  266. SwitchRelais( LS_RELAIS, 0);
  267. SwitchRelais( PRE_CHARGE_RELAIS, 0);
  268. SwitchRelais( HS_RELAIS, 0);
  269. s->relayState.HS_closed=FALSE;
  270. s->relayState.LS_closed=FALSE;
  271. s->relayState.PRECHARGE_closed=FALSE;
  272. return FALSE;
  273. }
  274. // check temperature derating at tmax
  275. // check if low temperature is violated
  276. else if(Current > s->currentLimits.I_max_discharge_temp_max ) {
  277. // current too high
  278. ErrorStackPushMasterError(s,BMS_ERROR_STACK_MASTER_I_MAX_DISCHARGE_OP,BMS_ERROR_CLASS_1);
  279. // Kill Relays
  280. SwitchRelais( LS_RELAIS, 0);
  281. SwitchRelais( PRE_CHARGE_RELAIS, 0);
  282. SwitchRelais( HS_RELAIS, 0);
  283. s->relayState.HS_closed=FALSE;
  284. s->relayState.LS_closed=FALSE;
  285. s->relayState.PRECHARGE_closed=FALSE;
  286. return FALSE;
  287. }
  288. // check SoC derating // normal derating curve + 10%
  289. else if(Current > s->currentLimits.I_max_discharge_SoC) {
  290. // current too high
  291. ErrorStackPushMasterError(s,BMS_ERROR_STACK_MASTER_I_MAX_DISCHARGE_OP,BMS_ERROR_CLASS_1);
  292. // Kill Relays
  293. SwitchRelais( LS_RELAIS, 0);
  294. SwitchRelais( PRE_CHARGE_RELAIS, 0);
  295. SwitchRelais( HS_RELAIS, 0);
  296. s->relayState.HS_closed=FALSE;
  297. s->relayState.LS_closed=FALSE;
  298. s->relayState.PRECHARGE_closed=FALSE;
  299. return FALSE;
  300. }
  301. else {
  302. // derating is ok
  303. return TRUE;
  304. }
  305. }
  306. else {
  307. // nothing happens
  308. return TRUE;
  309. }
  310. return TRUE;
  311. }
  312. uint32_t BMS_Set_Error_CAN1_Timeout(MASTER_CAN0_STRUCT_t* s) {
  313. // CAN 1 Timeout Has occured
  314. ErrorStackPushMasterError(s,BMS_ERROR_STACK_MASTER_EXTERN_CAN_ERROR,BMS_ERROR_CLASS_1);
  315. // Kill Relays
  316. SwitchRelais( LS_RELAIS, 0);
  317. SwitchRelais( PRE_CHARGE_RELAIS, 0);
  318. SwitchRelais( HS_RELAIS, 0);
  319. s->relayState.HS_closed=FALSE;
  320. s->relayState.LS_closed=FALSE;
  321. s->relayState.PRECHARGE_closed=FALSE;
  322. return TRUE;
  323. }
  324. /*
  325. * @brief check if current mesured by UI is consitent wit current measured by Inverter
  326. */
  327. uint32_t BMS_Set_Error_Check_current_consitency(MASTER_CAN0_STRUCT_t* s) {
  328. uint8_t i=0;
  329. float I_av_ui =0 ;
  330. float I_av_inverter =0;
  331. for(i=0; i<UI_CURRENT_FIFO_SIZE;i++) {
  332. I_av_ui = I_av_ui + (float)(s->UI_Board.IbattFiFo[i]);
  333. }
  334. I_av_ui = I_av_ui *10; // convert to mA
  335. I_av_ui = I_av_ui /UI_CURRENT_FIFO_SIZE ; // calc mean
  336. for(i=0;i<UI_CURRENT_FIFO_SIZE;i++ ) {
  337. I_av_inverter = I_av_inverter + s->UI_Board.Ibatt_Inverter_FIFO[i];
  338. }
  339. I_av_inverter = I_av_inverter *1000 /UI_CURRENT_FIFO_SIZE ; // convert to mA and calc mean
  340. // compare
  341. s->UiInverterInconsistency = bms_SoC_get_norm(I_av_inverter) - bms_SoC_get_norm(I_av_ui) ;
  342. if( s->UiInverterInconsistency > BMS_MAX_CURRENT_INCONSITENCY_MA || s->UiInverterInconsistency <( (-1) * BMS_MAX_CURRENT_INCONSITENCY_MA) ) {
  343. // error has occured
  344. ErrorStackPushUiError(s,BMS_ERROR_STACK_UI_CURRENT_INCONSIST,BMS_ERROR_CLASS_1);
  345. // Kill Relays
  346. SwitchRelais( LS_RELAIS, 0);
  347. SwitchRelais( PRE_CHARGE_RELAIS, 0);
  348. SwitchRelais( HS_RELAIS, 0);
  349. s->relayState.HS_closed=FALSE;
  350. s->relayState.LS_closed=FALSE;
  351. s->relayState.PRECHARGE_closed=FALSE;
  352. return TRUE;
  353. }
  354. return TRUE;
  355. }
  356. /*
  357. * @brief check if Voltage measured by UI and by Summation of Slaves are equal
  358. */
  359. uint32_t BMS_Set_Error_Check_voltage_inconsitency(MASTER_CAN0_STRUCT_t* s) {
  360. uint8_t i=0;
  361. uint32_t addedCellVoltage_mean=0;
  362. uint32_t UI_Board_voltage_mean=0;
  363. for(i=0;i<UI_VOLTAGE_FIFO_SIZE;i++) {
  364. addedCellVoltage_mean = addedCellVoltage_mean + s->UI_Board.SystemVoltageFiFo[i];
  365. UI_Board_voltage_mean = UI_Board_voltage_mean + s->UI_Board.UbattFiFo[i];
  366. }
  367. addedCellVoltage_mean = addedCellVoltage_mean /UI_VOLTAGE_FIFO_SIZE ; // voltage in mV
  368. UI_Board_voltage_mean = UI_Board_voltage_mean *100 / UI_VOLTAGE_FIFO_SIZE ;
  369. s->UiSlaveInconsistency = bms_SoC_get_norm((float)addedCellVoltage_mean - (float)UI_Board_voltage_mean) ;
  370. // if voltage error is bigger than threshold and All relais are closed kill relays
  371. if((s->UiSlaveInconsistency > (float)addedCellVoltage_mean * 0.05 && s->RunMode.onCounter > UI_VOLTAGE_FIFO_SIZE* CAN0_MAX_NR_OF_SLAVES) &&
  372. (s->relayState.HS_closed==TRUE && s->relayState.LS_closed==TRUE && s->relayState.PRECHARGE_closed==TRUE) ){
  373. ErrorStackPushUiError(s,BMS_ERROR_STACK_UI_VOLTAGE_INCONSIST,BMS_ERROR_CLASS_1);
  374. // Kill Relays
  375. SwitchRelais( LS_RELAIS, 0);
  376. SwitchRelais( PRE_CHARGE_RELAIS, 0);
  377. SwitchRelais( HS_RELAIS, 0);
  378. s->relayState.HS_closed=FALSE;
  379. s->relayState.LS_closed=FALSE;
  380. s->relayState.PRECHARGE_closed=FALSE;
  381. s->RunMode.onCounter=0;
  382. return TRUE;
  383. }
  384. return TRUE;
  385. }