/** ****************************************************************************** * @file remain_distance.c * @author Damon * @version V1.5 * @date 20190105 * @brief 电池剩余续航里程统计 ****************************************************************************** * @attention *本功能模块输出计算结果为,剩余续航里程RemainDis.remainDistance * ****************************************************************************** */ #include "remain_distance.h" #include "battery_info.h" #include "eeprom_24c02.h" /*电流积分,最小值,单位mA*/ #define CURRENT_MIN 130 /*电流积分周期*/ #define Q_ADD_TIME_MS 5 extern const MC_AvgPower_Struct_t MC_AvgPower_Default; //续航计算相关参数 Remain_Dis_t RemainDis = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0xFFFF, 0, 0, FALSE, 0}; //电池信息 Battery_Info_t Battery_Info; /****************************************************************************** * @Function: void RD_getQRemainRecord( void ) * @Discrible: 读取电池剩余电量 * @Param: * @Return: * @Others: 此函数在系统上电时调用一次,读取电池剩余电量 已添加到RD_RemainDis_init(void),无需单独调用 ****************************************************************************** * @Recode date version author modify * ------------------------------------------------------------------ * 20190815 V1.3 Damon modify * *******************************************************************************/ static void RD_getQRemainRecord(uint16_t Volgate) { uint16_t BusVoltage; uint16_t i; uint16_t num,batteryTotalQ,batteryRemainQ; //获取母线初始电压 BusVoltage = Volgate; //查表读取电池电量 num = sizeof(battery_VoltageQuantity) / 4; batteryTotalQ = battery_VoltageQuantity[num-1][1]; batteryRemainQ = batteryTotalQ; for(i=0; i 2000) { RemainDis.BMS_Com_DelayTimeCnt = HAL_GetTick(); RemainDis.IsBMS_ComOK_Flag = FALSE; } /*电流大于最小阈值,累加一次电量*/ if((RemainDis.I_motor > CURRENT_MIN) && (RemainDis.IsBMS_ComOK_Flag == FALSE) ) { RemainDis.Q_add += RemainDis.I_motor * RemainDis.acc_period;//mA * ms } /*助力档位切换后*/ if( RemainDis.flag_helpModeChange == 1 ) { RemainDis.flag_helpModeChange = 0; /*清空一级缓冲区数据*/ for(i=0;i= WHEEL_COUNT_REFRESH_VALUE) { WheelTurnCntOld = WheelTurnCnt; /*消耗电量信息来自电池*/ if(RemainDis.IsBMS_ComOK_Flag == TRUE ) { //更新电池剩余容量 Battery_Info.Q_remain_real = RemainCap; //更新电池剩余电量 Battery_Info.SOC = SOC; if(Battery_Info.Q_remain_real_last != 0) { Q_add_tmp = (int16_t)(Battery_Info.Q_remain_real_last - Battery_Info.Q_remain_real); /*充电状态,或由母线电流切换到电量信息计算时,此值会出现负数*/ Q_add_tmp = (Q_add_tmp > 0) ? Q_add_tmp : 0; /*判断电池是否满充*/ if( ( Q_add_tmp == 0 ) && ( Battery_Info.SOC == 100 ) ) { /*当电池满充时,发出的电量信息会是标称值, 在Battery.SOC==100时不会随电量消耗尔减小*/ /*置标志位,不计算更新*/ flagBatteryFull = 1; } /*切换到母线电流积分计算后,使用最新的剩余电量数据*/ Battery_Info.Q_remain_record = Battery_Info.Q_remain_real; Battery_Info.Q_discharged = 0; RemainDis.Q_add = 0; } } else/*消耗的电量信息来自母线电流,进行积分累计计算*/ { /*单位mA*h*/ Q_add_tmp = RemainDis.Q_add / ( 3600 * 1000 ); if(Q_add_tmp > 0) { RemainDis.Q_add = RemainDis.Q_add % ( 3600 * 1000 );//保留余数,下次累加 } /*累计总的消耗电量*/ Battery_Info.Q_discharged += Q_add_tmp ; //mA*h /*更新电池剩余电量*/ Battery_Info.Q_remain_real = Battery_Info.Q_remain_record - Battery_Info.Q_discharged ; } /*电量信息来自电池的计算,需要用到此数据*/ Battery_Info.Q_remain_real_last = Battery_Info.Q_remain_real; /*电池非满充状态*/ if( flagBatteryFull == 0 ) { /*将一定轮圈数消耗的电量,写入FIFO,FIFO中的数据滑动求平均值*/ Q_sum -= Q_FIFO[Q_Index]; Q_sum += Q_add_tmp; Q_FIFO[Q_Index++] = Q_add_tmp; } if(Q_Index>=Q_FIFO_LENGTH) { Q_Index = 0; Q_fifo_full_falg = 1; /*250圈,动态功耗刷新一次,置一次eeprom保存标志*/ RemainDis.flag_saveInfo = 1; } /* wheelCount x WHEEL_LENGTH(cm) ------------------------------- (km) wheelCount=(Q_FIFO_LENGTH * WHEEL_COUNT_REFRESH_VALUE) 1000 x 100 Q_sum(mA*h) x 1000 x 100 ------------------------------- (mA*h/km) wheelCount x WHEEL_LENGTH */ if( Q_sum > 0 ) { /*缓存满后,求平均值*/ if(Q_fifo_full_falg==1) { RemainDis.Power_per_km = (Q_sum * 1000 * 100 ) / ( Q_FIFO_LENGTH * WHEEL_COUNT_REFRESH_VALUE * RemainDis.wheelLength ); } else { /*缓存数据未满,以当前有效数据个数求平均值*/ RemainDis.Power_per_km = (Q_sum * 1000 * 100 ) / ( Q_Index * WHEEL_COUNT_REFRESH_VALUE * RemainDis.wheelLength ); } } else { RemainDis.Power_per_km = 0; } /*电量缓存Q_FIFO计满一次,滑动滤波求平均值*/ if(Q_Index==0) { ptmp = RemainDis.Power_per_km; PowerPerKmFltSum += ((ptmp << 8) - PowerPerKmFltSum) / P_FIFO_LENGTH; RemainDis.Power_per_km_average = (uint16_t)(PowerPerKmFltSum >> 8); } /*计算剩余续航里程*/ if(RemainDis.Power_per_km_average > 0) { RemainDis.remainDistance = Battery_Info.Q_remain_real / RemainDis.Power_per_km_result;//单位km } else { RemainDis.remainDistance = 0xFFFF;//码表显示---km } } } } /****************************************************************************** * @Function: void RD_saveAndUpdateInfo(uint8_t uwHelpMode) * @Discrible: 保存功耗数据到EEPROM * @Param: * @Return: * @Others: 每一公里,保存一次数据到eeprom;助力档位切换时,刷新计算的功耗数据。此函数在主循环中调用 ****************************************************************************** * @Recode date version author modify * ------------------------------------------------------------------ * 20190105 V1.4 Damon modify * *******************************************************************************/ void RD_SaveAndUpdateInfo(MC_GearSt_Struct_t GearSt, MC_AssistRunMode_Struct_t MC_AssistRunMode) { static MC_GearSt_Struct_t MC_GearSt_Old = MC_GearSt_OFF; static MC_AssistRunMode_Struct_t MC_AssistRunMode_Old = MC_AssistRunMode_INVALID; static uint16_t usPowerPerKmAverageLast =0; static uint16_t powerDefaultCurrentMode=0; int16_t sPercent; int32_t ltmp; if( ( (GearSt & 0x0F) != 0 ) && ( MC_AssistRunMode != MC_AssistRunMode_INVALID )) { RemainDis.start = 1; /*保存当前助力档位的数据到eeprom*/ if( RemainDis.flag_saveInfo == 1 ) { RemainDis.flag_saveInfo = 0; /*平均功耗值有更新时,执行保存数据相关操作*/ if( RemainDis.Power_per_km_average != usPowerPerKmAverageLast ) { if(RemainDis.Power_per_km_average != 0) { /*计算平均功耗,增减量的百分比,放大100倍*/ ltmp = (int32_t)(RemainDis.Power_per_km_average - powerDefaultCurrentMode) * 100; sPercent = ltmp / powerDefaultCurrentMode; /*各档位关联*/ /*不低于默认值30%*/ if( sPercent >= -30 ) { /*更新平均功耗*/ RemainDis.Power_per_km_result = powerDefaultCurrentMode * ( 100 + sPercent ) / 100; /*计算各档位增减后的值*/ ltmp = MC_AvgPower_Default.GearSt_ECO; MC_AvgPower.GearSt_ECO = ltmp * ( 100 + sPercent ) / 100; ltmp = MC_AvgPower_Default.GearSt_NORM; MC_AvgPower.GearSt_NORM = ltmp * ( 100 + sPercent ) / 100; ltmp = MC_AvgPower_Default.GearSt_SPORT; MC_AvgPower.GearSt_SPORT = ltmp * ( 100 + sPercent ) / 100; ltmp = MC_AvgPower_Default.GearSt_TURBO; MC_AvgPower.GearSt_TURBO = ltmp * ( 100 + sPercent ) / 100; ltmp = MC_AvgPower_Default.GearSt_5; MC_AvgPower.GearSt_5 = ltmp * ( 100 + sPercent ) / 100; ltmp = MC_AvgPower_Default.GearSt_SMART; MC_AvgPower.GearSt_SMART = ltmp * ( 100 + sPercent ) / 100; ltmp = MC_AvgPower_Default.GearSt_SMART_T; MC_AvgPower.GearSt_SMART_T = ltmp * ( 100 + sPercent ) / 100; /*保存所有档位的更新数据*/ SaveParamToEEprom_24C02(&I2C_Handle_EEPROM, EEPROM_24C02_ADDR_AVG_POWER, sizeof(MC_AvgPower_Struct_t), (uint8_t*)&MC_AvgPower.GearSt_ECO); } } /*备份平均功耗值*/ usPowerPerKmAverageLast = RemainDis.Power_per_km_average; } } /*助力档位切换后,根据当前档位更新功耗数据*/ if((GearSt != MC_GearSt_Old) || (MC_AssistRunMode != MC_AssistRunMode_Old)) { switch(GearSt) { case MC_GearSt_Torque_ECO: RemainDis.Power_per_km_average = MC_AvgPower.GearSt_ECO; powerDefaultCurrentMode = MC_AvgPower_Default.GearSt_ECO; break; case MC_GearSt_Torque_NORM: RemainDis.Power_per_km_average = MC_AvgPower.GearSt_NORM; powerDefaultCurrentMode = MC_AvgPower_Default.GearSt_NORM; break; case MC_GearSt_Torque_SPORT: RemainDis.Power_per_km_average = MC_AvgPower.GearSt_SPORT; powerDefaultCurrentMode = MC_AvgPower_Default.GearSt_SPORT; break; case MC_GearSt_Torque_TURBO: RemainDis.Power_per_km_average = MC_AvgPower.GearSt_TURBO; powerDefaultCurrentMode = MC_AvgPower_Default.GearSt_TURBO; break; case MC_GearSt_Torque_5: RemainDis.Power_per_km_average = MC_AvgPower.GearSt_5; powerDefaultCurrentMode = MC_AvgPower_Default.GearSt_5; break; case MC_GearSt_SMART: RemainDis.Power_per_km_average = MC_AvgPower.GearSt_SMART; powerDefaultCurrentMode = MC_AvgPower_Default.GearSt_SMART; break; case MC_GearSt_SMART_T: RemainDis.Power_per_km_average = MC_AvgPower.GearSt_SMART_T; powerDefaultCurrentMode = MC_AvgPower_Default.GearSt_SMART_T; break; default: RemainDis.Power_per_km_average = 0; powerDefaultCurrentMode = 0; break; } /*备份平均功耗值*/ usPowerPerKmAverageLast = RemainDis.Power_per_km_average; RemainDis.Power_per_km_result = RemainDis.Power_per_km_average; /*计算剩余续航里程*/ if(RemainDis.Power_per_km_average > 0) { RemainDis.remainDistance = Battery_Info.Q_remain_real / RemainDis.Power_per_km_result;//单位km } else { RemainDis.remainDistance = 0xFFFF;//码表界面显示:---km } /*置标志位,在后续计算中,刷新相关数据*/ RemainDis.flag_helpModeChange = 1; } } else { RemainDis.start = 0; RemainDis.Power_per_km_average = 0; RemainDis.Power_per_km_result = 0; RemainDis.remainDistance = 0xFFFF;//码表界面显示:---km } /*备份助力档位*/ MC_GearSt_Old = GearSt; MC_AssistRunMode_Old = MC_AssistRunMode; } //运行周期200ms uint8_t Battery_SocCal(uint16_t Voltage_mV) { static uint16_t TimeDelayCnt = 0; static uint32_t FiltSum = 0; static uint8_t FiltCnt = 0; static uint8_t Result = 0, Result_Pre=0; static TrueOrFalse_Flag_Struct_t InitFlag = FALSE; uint16_t i; uint16_t TableNum; uint32_t batteryTotalQ, batteryRemainQ; uint16_t Vol_Avg = 0; TableNum = sizeof(battery_VoltageQuantity) / 4; batteryTotalQ = battery_VoltageQuantity[TableNum - 1][1]; batteryRemainQ = batteryTotalQ; TimeDelayCnt++; //初始化电压上升较慢,开机时动态效果 if(TimeDelayCnt <= 10) return 0; else if(TimeDelayCnt <= 15) return 10; else if(TimeDelayCnt <= 20) return 25; else if(TimeDelayCnt <= 25) return 45; else if(TimeDelayCnt <= 30) return 65; else if(TimeDelayCnt <= 35) return 85; else { if(InitFlag == FALSE)//等待约5s后,计算一次初始值 { InitFlag = TRUE; for(i=0; i= 25) { Vol_Avg = FiltSum / 25; FiltSum = 0; FiltCnt = 0; //查表计算SOC for(i=0; i Result_Pre)//电量上升时,突变较小,取上次计算值 { if((Result < (Result_Pre + 30)) && (Result < 90)) { Result = Result_Pre; } } } } return Result; } }