remain_distance.c 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509
  1. /**
  2. ******************************************************************************
  3. * @file remain_distance.c
  4. * @author Damon
  5. * @version V1.5
  6. * @date 20190105
  7. * @brief 电池剩余续航里程统计
  8. ******************************************************************************
  9. * @attention
  10. *本功能模块输出计算结果为,剩余续航里程RemainDis.remainDistance
  11. *
  12. ******************************************************************************
  13. */
  14. #include "remain_distance.h"
  15. #include "battery_info.h"
  16. #include "eeprom_24c02.h"
  17. /*电流积分,最小值,单位mA*/
  18. #define CURRENT_MIN 130
  19. /*电流积分周期*/
  20. #define Q_ADD_TIME_MS 5
  21. extern const MC_AvgPower_Struct_t MC_AvgPower_Default;
  22. //续航计算相关参数
  23. Remain_Dis_t RemainDis = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0xFFFF, 0, 0, FALSE, 0};
  24. //电池信息
  25. Battery_Info_t Battery_Info;
  26. /******************************************************************************
  27. * @Function: void RD_getQRemainRecord( void )
  28. * @Discrible: 读取电池剩余电量
  29. * @Param:
  30. * @Return:
  31. * @Others: 此函数在系统上电时调用一次,读取电池剩余电量
  32. 已添加到RD_RemainDis_init(void),无需单独调用
  33. ******************************************************************************
  34. * @Recode date version author modify
  35. * ------------------------------------------------------------------
  36. * 20190815 V1.3 Damon modify
  37. *
  38. *******************************************************************************/
  39. static void RD_getQRemainRecord(uint16_t Volgate)
  40. {
  41. uint16_t BusVoltage;
  42. uint16_t i;
  43. uint16_t num,batteryTotalQ,batteryRemainQ;
  44. //获取母线初始电压
  45. BusVoltage = Volgate;
  46. //查表读取电池电量
  47. num = sizeof(battery_VoltageQuantity) / 4;
  48. batteryTotalQ = battery_VoltageQuantity[num-1][1];
  49. batteryRemainQ = batteryTotalQ;
  50. for(i=0; i<num; i++)
  51. {
  52. if(battery_VoltageQuantity[i][0] <= BusVoltage)
  53. {
  54. batteryRemainQ = batteryTotalQ - battery_VoltageQuantity[i][1] ; //A*s
  55. Battery_Info.Q_remain_record = batteryRemainQ * 10 / 36; //mAh
  56. break;
  57. }
  58. else//电池电压低于最小值
  59. {
  60. batteryRemainQ = 0;
  61. }
  62. }
  63. MC_RunInfo.SOC = batteryRemainQ * 100 / batteryTotalQ;
  64. Battery_Info.Q_remain_real = Battery_Info.Q_remain_record;
  65. }
  66. /******************************************************************************
  67. * @Function: void RD_RemainDis_init(void)
  68. * @Discrible: 模块功能初始化
  69. * @Param: uwWheelLength:轮胎周长,BusVoltage:母线电压
  70. * @Return:
  71. * @Others: 此函数在进入主循环前调用,调用后,标志位置位,开启模块的统计功能
  72. ******************************************************************************
  73. * @Recode date version author modify
  74. * ------------------------------------------------------------------
  75. * 20181221 V1.2 Damon modify
  76. *
  77. *******************************************************************************/
  78. void RD_RemainDis_Init(uint16_t uwWheelLength, TrueOrFalse_Flag_Struct_t BMS_COM_OK, uint16_t BusVoltage, uint8_t DesignVol, uint16_t BMS_RC)
  79. {
  80. Battery_Info.Q_discharged = 0;
  81. Battery_Info.Q_remain_real = 0;
  82. Battery_Info.Q_remain_record = BATTERY_TATAL_Q_MAH;
  83. Battery_Info.Q_remain_real_last = 0;
  84. if(BMS_COM_OK == TRUE) //电池通讯正常时,直接获取电池容量
  85. {
  86. Battery_Info.Q_remain_real = BMS_RC;
  87. }
  88. else //电池不含通讯时,根据母线电压估算剩余容量
  89. {
  90. RD_getQRemainRecord(BusVoltage * 36 / DesignVol); //放电曲线是按照36V,针对48V或24V做等效转换
  91. }
  92. RemainDis.start = 0;
  93. RemainDis.I_motor = 0;
  94. RemainDis.acc_period = Q_ADD_TIME_MS;
  95. RemainDis.Q_add = 0;
  96. RemainDis.wheelLength = uwWheelLength;
  97. RemainDis.wheel_Count = 0;
  98. RemainDis.Power_per_km = 0;
  99. RemainDis.Power_per_km_average = 0;
  100. RemainDis.remainDistance = 0xFFFF;//码表显示---km
  101. RemainDis.flag_saveInfo = 0;
  102. RemainDis.flag_helpModeChange = 0;
  103. RemainDis.IsBMS_ComOK_Flag = FALSE;
  104. RemainDis.BMS_Com_DelayTimeCnt = HAL_GetTick();
  105. }
  106. /******************************************************************************
  107. * @Function: void RD_CalculateRemainDis(void)
  108. * @Discrible: 计算电池剩余续航里程
  109. * @Param:
  110. * @Return:
  111. * @Others: 计算平均功耗(中间变量),和剩余续航里程
  112. ******************************************************************************
  113. * @Recode date version author modify
  114. * ------------------------------------------------------------------
  115. * 20181210 V1.4 Damon modify
  116. *
  117. *******************************************************************************/
  118. void RD_CalculateRemainDis(uint32_t WheelTurnCnt, uint16_t RemainCap, uint8_t SOC, uint16_t BusCurrent)
  119. {
  120. /*以下宏定义会影响平均功耗计算结果的变化快慢
  121. WHEEL_COUNT_REFRESH_VALUE 电量统计周期,每10圈统计一次电量
  122. Q_FIFO_LENGTH 动态平均功耗,取平均值的长度。Power_per_km(10圈x25=250圈,即动态功耗是车轮骑行250圈的平均值)
  123. P_FIFO_LENGTH 对Power_per_km求平均值的长度,Power_per_km_average(250圈x10=-2500圈)
  124. 修改宏定义的大小,可以改变Power_per_km_average的更新快慢,最终影响剩余续航里程的更新快慢。
  125. */
  126. /*车轮圈数,最小的电量统计周期*/
  127. #define WHEEL_COUNT_REFRESH_VALUE 10
  128. /*动态平均功耗,缓存长度*/
  129. #define Q_FIFO_LENGTH 25 //25 250圈 约500m
  130. /*平均功耗,缓存长度*/
  131. #define P_FIFO_LENGTH 30 //约15KM
  132. static uint16_t Q_FIFO[Q_FIFO_LENGTH]={0};
  133. static uint16_t Q_Index=0;
  134. static uint32_t Q_sum=0;
  135. static uint8_t Q_fifo_full_falg=0;
  136. static int16_t Q_add_tmp=0;
  137. static int32_t PowerPerKmFltSum=0;
  138. uint8_t i;
  139. uint8_t flagBatteryFull=0;
  140. int32_t ptmp;
  141. static uint32_t RunTimeCnt = 0;
  142. static uint32_t WheelTurnCntOld = 0;
  143. if((HAL_GetTick() - RunTimeCnt) < Q_ADD_TIME_MS)//计算周期为Q_ADD_TIME_MS
  144. {
  145. return;
  146. }
  147. RunTimeCnt = HAL_GetTick();
  148. //更新母线电流值
  149. RemainDis.I_motor = BusCurrent;
  150. //更新计算周期内轮子圈数
  151. RemainDis.wheel_Count = WheelTurnCnt - WheelTurnCntOld;
  152. /*开始计算*/
  153. if(RemainDis.start == 1)
  154. {
  155. /*电池通讯中断超时2s判断*/
  156. if((HAL_GetTick() - RemainDis.BMS_Com_DelayTimeCnt) > 2000)
  157. {
  158. RemainDis.BMS_Com_DelayTimeCnt = HAL_GetTick();
  159. RemainDis.IsBMS_ComOK_Flag = FALSE;
  160. }
  161. /*电流大于最小阈值,累加一次电量*/
  162. if((RemainDis.I_motor > CURRENT_MIN) && (RemainDis.IsBMS_ComOK_Flag == FALSE) )
  163. {
  164. RemainDis.Q_add += RemainDis.I_motor * RemainDis.acc_period;//mA * ms
  165. }
  166. /*助力档位切换后*/
  167. if( RemainDis.flag_helpModeChange == 1 )
  168. {
  169. RemainDis.flag_helpModeChange = 0;
  170. /*清空一级缓冲区数据*/
  171. for(i=0;i<Q_FIFO_LENGTH;i++)
  172. {
  173. Q_FIFO[i] = 0;
  174. }
  175. Q_Index = 0;
  176. Q_sum = 0;
  177. Q_fifo_full_falg=0;
  178. if(RemainDis.Power_per_km_average != 0)
  179. {
  180. /*赋值求平均值的总和*/
  181. PowerPerKmFltSum = RemainDis.Power_per_km_average << 8;
  182. }
  183. }
  184. /*轮圈数大于设定值,计算一次*/
  185. if( RemainDis.wheel_Count >= WHEEL_COUNT_REFRESH_VALUE)
  186. {
  187. WheelTurnCntOld = WheelTurnCnt;
  188. /*消耗电量信息来自电池*/
  189. if(RemainDis.IsBMS_ComOK_Flag == TRUE )
  190. {
  191. //更新电池剩余容量
  192. Battery_Info.Q_remain_real = RemainCap;
  193. //更新电池剩余电量
  194. Battery_Info.SOC = SOC;
  195. if(Battery_Info.Q_remain_real_last != 0)
  196. {
  197. Q_add_tmp = (int16_t)(Battery_Info.Q_remain_real_last - Battery_Info.Q_remain_real);
  198. /*充电状态,或由母线电流切换到电量信息计算时,此值会出现负数*/
  199. Q_add_tmp = (Q_add_tmp > 0) ? Q_add_tmp : 0;
  200. /*判断电池是否满充*/
  201. if( ( Q_add_tmp == 0 ) && ( Battery_Info.SOC == 100 ) )
  202. {
  203. /*当电池满充时,发出的电量信息会是标称值,
  204. 在Battery.SOC==100时不会随电量消耗尔减小*/
  205. /*置标志位,不计算更新*/
  206. flagBatteryFull = 1;
  207. }
  208. /*切换到母线电流积分计算后,使用最新的剩余电量数据*/
  209. Battery_Info.Q_remain_record = Battery_Info.Q_remain_real;
  210. Battery_Info.Q_discharged = 0;
  211. RemainDis.Q_add = 0;
  212. }
  213. }
  214. else/*消耗的电量信息来自母线电流,进行积分累计计算*/
  215. {
  216. /*单位mA*h*/
  217. Q_add_tmp = RemainDis.Q_add / ( 3600 * 1000 );
  218. if(Q_add_tmp > 0)
  219. {
  220. RemainDis.Q_add = RemainDis.Q_add % ( 3600 * 1000 );//保留余数,下次累加
  221. }
  222. /*累计总的消耗电量*/
  223. Battery_Info.Q_discharged += Q_add_tmp ; //mA*h
  224. /*更新电池剩余电量*/
  225. Battery_Info.Q_remain_real = Battery_Info.Q_remain_record - Battery_Info.Q_discharged ;
  226. }
  227. /*电量信息来自电池的计算,需要用到此数据*/
  228. Battery_Info.Q_remain_real_last = Battery_Info.Q_remain_real;
  229. /*电池非满充状态*/
  230. if( flagBatteryFull == 0 )
  231. {
  232. /*将一定轮圈数消耗的电量,写入FIFO,FIFO中的数据滑动求平均值*/
  233. Q_sum -= Q_FIFO[Q_Index];
  234. Q_sum += Q_add_tmp;
  235. Q_FIFO[Q_Index++] = Q_add_tmp;
  236. }
  237. if(Q_Index>=Q_FIFO_LENGTH)
  238. {
  239. Q_Index = 0;
  240. Q_fifo_full_falg = 1;
  241. /*250圈,动态功耗刷新一次,置一次eeprom保存标志*/
  242. RemainDis.flag_saveInfo = 1;
  243. }
  244. /*
  245. wheelCount x WHEEL_LENGTH(cm)
  246. ------------------------------- (km) wheelCount=(Q_FIFO_LENGTH * WHEEL_COUNT_REFRESH_VALUE)
  247. 1000 x 100
  248. Q_sum(mA*h) x 1000 x 100
  249. ------------------------------- (mA*h/km)
  250. wheelCount x WHEEL_LENGTH
  251. */
  252. if( Q_sum > 0 )
  253. {
  254. /*缓存满后,求平均值*/
  255. if(Q_fifo_full_falg==1)
  256. {
  257. RemainDis.Power_per_km = (Q_sum * 1000 * 100 ) / ( Q_FIFO_LENGTH * WHEEL_COUNT_REFRESH_VALUE * RemainDis.wheelLength );
  258. }
  259. else
  260. {
  261. /*缓存数据未满,以当前有效数据个数求平均值*/
  262. RemainDis.Power_per_km = (Q_sum * 1000 * 100 ) / ( Q_Index * WHEEL_COUNT_REFRESH_VALUE * RemainDis.wheelLength );
  263. }
  264. }
  265. else
  266. {
  267. RemainDis.Power_per_km = 0;
  268. }
  269. /*电量缓存Q_FIFO计满一次,滑动滤波求平均值*/
  270. if(Q_Index==0)
  271. {
  272. ptmp = RemainDis.Power_per_km;
  273. PowerPerKmFltSum += ((ptmp << 8) - PowerPerKmFltSum) / P_FIFO_LENGTH;
  274. RemainDis.Power_per_km_average = (uint16_t)(PowerPerKmFltSum >> 8);
  275. }
  276. /*计算剩余续航里程*/
  277. if(RemainDis.Power_per_km_average > 0)
  278. {
  279. RemainDis.remainDistance = Battery_Info.Q_remain_real / RemainDis.Power_per_km_result;//单位km
  280. }
  281. else
  282. {
  283. RemainDis.remainDistance = 0xFFFF;//码表显示---km
  284. }
  285. }
  286. }
  287. }
  288. /******************************************************************************
  289. * @Function: void RD_saveAndUpdateInfo(uint8_t uwHelpMode)
  290. * @Discrible: 保存功耗数据到EEPROM
  291. * @Param:
  292. * @Return:
  293. * @Others: 每一公里,保存一次数据到eeprom;助力档位切换时,刷新计算的功耗数据。此函数在主循环中调用
  294. ******************************************************************************
  295. * @Recode date version author modify
  296. * ------------------------------------------------------------------
  297. * 20190105 V1.4 Damon modify
  298. *
  299. *******************************************************************************/
  300. void RD_SaveAndUpdateInfo(MC_GearSt_Struct_t GearSt, MC_AssistRunMode_Struct_t MC_AssistRunMode)
  301. {
  302. static MC_GearSt_Struct_t MC_GearSt_Old = MC_GearSt_OFF;
  303. static MC_AssistRunMode_Struct_t MC_AssistRunMode_Old = MC_AssistRunMode_INVALID;
  304. static uint16_t usPowerPerKmAverageLast =0;
  305. static uint16_t powerDefaultCurrentMode=0;
  306. int16_t sPercent;
  307. int32_t ltmp;
  308. if( ( (GearSt & 0x0F) != 0 ) && ( MC_AssistRunMode != MC_AssistRunMode_INVALID ))
  309. {
  310. RemainDis.start = 1;
  311. /*保存当前助力档位的数据到eeprom*/
  312. if( RemainDis.flag_saveInfo == 1 )
  313. {
  314. RemainDis.flag_saveInfo = 0;
  315. /*平均功耗值有更新时,执行保存数据相关操作*/
  316. if( RemainDis.Power_per_km_average != usPowerPerKmAverageLast )
  317. {
  318. if(RemainDis.Power_per_km_average != 0)
  319. {
  320. /*计算平均功耗,增减量的百分比,放大100倍*/
  321. ltmp = (int32_t)(RemainDis.Power_per_km_average - powerDefaultCurrentMode) * 100;
  322. sPercent = ltmp / powerDefaultCurrentMode;
  323. /*各档位关联*/
  324. /*不低于默认值30%*/
  325. if( sPercent >= -30 )
  326. {
  327. /*更新平均功耗*/
  328. RemainDis.Power_per_km_result = powerDefaultCurrentMode * ( 100 + sPercent ) / 100;
  329. /*计算各档位增减后的值*/
  330. ltmp = MC_AvgPower_Default.GearSt_ECO;
  331. MC_AvgPower.GearSt_ECO = ltmp * ( 100 + sPercent ) / 100;
  332. ltmp = MC_AvgPower_Default.GearSt_NORM;
  333. MC_AvgPower.GearSt_NORM = ltmp * ( 100 + sPercent ) / 100;
  334. ltmp = MC_AvgPower_Default.GearSt_SPORT;
  335. MC_AvgPower.GearSt_SPORT = ltmp * ( 100 + sPercent ) / 100;
  336. ltmp = MC_AvgPower_Default.GearSt_TURBO;
  337. MC_AvgPower.GearSt_TURBO = ltmp * ( 100 + sPercent ) / 100;
  338. ltmp = MC_AvgPower_Default.GearSt_SMART;
  339. MC_AvgPower.GearSt_SMART = ltmp * ( 100 + sPercent ) / 100;
  340. /*保存所有档位的更新数据*/
  341. SaveParamToEEprom_24C02(&I2C_Handle_EEPROM, EEPROM_24C02_ADDR_AVG_POWER, sizeof(MC_AvgPower_Struct_t), (uint8_t*)&MC_AvgPower.GearSt_ECO);
  342. }
  343. }
  344. /*备份平均功耗值*/
  345. usPowerPerKmAverageLast = RemainDis.Power_per_km_average;
  346. }
  347. }
  348. /*助力档位切换后,根据当前档位更新功耗数据*/
  349. if((GearSt != MC_GearSt_Old) || (MC_AssistRunMode != MC_AssistRunMode_Old))
  350. {
  351. switch(GearSt)
  352. {
  353. case MC_GearSt_Torque_ECO:
  354. RemainDis.Power_per_km_average = MC_AvgPower.GearSt_ECO;
  355. powerDefaultCurrentMode = MC_AvgPower_Default.GearSt_ECO;
  356. break;
  357. case MC_GearSt_Torque_NORM:
  358. RemainDis.Power_per_km_average = MC_AvgPower.GearSt_NORM;
  359. powerDefaultCurrentMode = MC_AvgPower_Default.GearSt_NORM;
  360. break;
  361. case MC_GearSt_Torque_SPORT:
  362. RemainDis.Power_per_km_average = MC_AvgPower.GearSt_SPORT;
  363. powerDefaultCurrentMode = MC_AvgPower_Default.GearSt_SPORT;
  364. break;
  365. case MC_GearSt_Torque_TURBO:
  366. RemainDis.Power_per_km_average = MC_AvgPower.GearSt_TURBO;
  367. powerDefaultCurrentMode = MC_AvgPower_Default.GearSt_TURBO;
  368. break;
  369. case MC_GearSt_SMART:
  370. RemainDis.Power_per_km_average = MC_AvgPower.GearSt_SMART;
  371. powerDefaultCurrentMode = MC_AvgPower_Default.GearSt_SMART;
  372. break;
  373. default:
  374. RemainDis.Power_per_km_average = 0;
  375. powerDefaultCurrentMode = 0;
  376. break;
  377. }
  378. /*备份平均功耗值*/
  379. usPowerPerKmAverageLast = RemainDis.Power_per_km_average;
  380. RemainDis.Power_per_km_result = RemainDis.Power_per_km_average;
  381. /*计算剩余续航里程*/
  382. if(RemainDis.Power_per_km_average > 0)
  383. {
  384. RemainDis.remainDistance = Battery_Info.Q_remain_real / RemainDis.Power_per_km_result;//单位km
  385. }
  386. else
  387. {
  388. RemainDis.remainDistance = 0xFFFF;//码表界面显示:---km
  389. }
  390. /*置标志位,在后续计算中,刷新相关数据*/
  391. RemainDis.flag_helpModeChange = 1;
  392. }
  393. }
  394. else
  395. {
  396. RemainDis.start = 0;
  397. RemainDis.Power_per_km_average = 0;
  398. RemainDis.Power_per_km_result = 0;
  399. RemainDis.remainDistance = 0xFFFF;//码表界面显示:---km
  400. }
  401. /*备份助力档位*/
  402. MC_GearSt_Old = GearSt;
  403. MC_AssistRunMode_Old = MC_AssistRunMode;
  404. }
  405. uint8_t Battery_SocCal(uint16_t Voltage_mV)
  406. {
  407. static uint32_t PeriodTimeCnt = 0;
  408. static uint8_t Result = 0,Result_Pre=0;
  409. uint16_t i;
  410. uint16_t num;
  411. uint32_t batteryTotalQ,batteryRemainQ;
  412. uint16_t Voltage;
  413. Voltage = Voltage_mV / 10;
  414. num = sizeof(battery_VoltageQuantity)/4;
  415. batteryTotalQ = battery_VoltageQuantity[num-1][1];
  416. batteryRemainQ = batteryTotalQ;
  417. Result_Pre = MC_RunInfo.SOC;
  418. Result = Result_Pre;
  419. if((HAL_GetTick() - PeriodTimeCnt) > 2000)//计算周期2s
  420. {
  421. PeriodTimeCnt = HAL_GetTick();
  422. for(i=0;i<num;i++)
  423. {
  424. if(battery_VoltageQuantity[i][0] <= Voltage)
  425. {
  426. batteryRemainQ = batteryTotalQ - battery_VoltageQuantity[i][1] ; //A*s
  427. break;
  428. }
  429. else//电池电压低于最小值
  430. {
  431. batteryRemainQ = 0;
  432. }
  433. }
  434. Result = batteryRemainQ * 100 / batteryTotalQ;
  435. if(Result >= Result_Pre)
  436. {
  437. Result = Result_Pre;
  438. }
  439. }
  440. return Result;
  441. }