BMS——SOC、SOH算法梳理

时间:2025-03-10 19:42:17
void BmsSoc_gauging(void) { U32 soc_temp;//循环容量16位*100后会溢出 uint16 CellVoltage; int32 Coulomb,k = 100,CoulombAve; SoftSoc.AccCounter = 0; Coulomb = (gAccCoulomb*10)/SOC_SAMPLE_TIME;//提取积分值,扩大了10倍(mAh) CoulombAve = Coulomb/10; gAccCoulomb = 0; if(battery.BatSta == BatteryCharging) { Coulomb = (Coulomb*SOC_CHG_EFF)/1000;//根据充电效率计算充电累加 SoftSoc.CoulombK = 100;//积分器增益系数 } else { k = CalcTempDsgCoff();//计算温度放电系数 SoftSoc.CoulombK = k*CalcDsgRate(AbsInt32(Coulomb))/100;//计算放电倍率 Coulomb = Coulomb*SoftSoc.CoulombK/100; } Coulomb = Coulomb/20; //单位换算回0.1mAh if((-Coulomb) >= (int32)SoftSoc.RemainCap) { SoftSoc.RemainCap = 0; } else { SoftSoc.RemainCap += Coulomb; //循环次数由放电容量计算 if(Coulomb < 0) { SoftSoc.TotalDsgCap += Coulomb;// 计算放电总循环容量,用于计算循环次数 } if(SoftSoc.TotalDsgCap < 0) { if((AbsInt32(SoftSoc.TotalDsgCap)/100) >= ((U32)gsThrSoc.CycleCapacity*80/100)) { SoftSoc.TotalDsgCap = 0; gsThrSoc.CycleCount ++; BmsEvent.CycleCount = gsThrSoc.CycleCount;//更新循环次数,更新循环容量 BmsEvent.Record = 1; //允许记录 BmsSoc_GetSoh(); //更新SOH gsThrSoc.CycleCapacity = BmsSoc_GetCycleCap(100);//更新循环容量 //保存循环容量和循环次数 VirtualEEP_Write(EEP_dCycleCount, (uint8_t *)&gsThrSoc.CycleCount, 2,0); VirtualEEP_Write(EEP_CycleCapacity,(uint8_t *)&gsThrSoc.CycleCapacity,2,1);//1——立即写 } } } soc_temp = gsThrSoc.CycleCapacity;//用U32不会溢出 if(SoftSoc.RemainCap >= soc_temp * 100) { soc_temp = gsThrSoc.CycleCapacity; SoftSoc.RemainCap = soc_temp * 100; } SoftSoc.Soc = SoftSoc.RemainCap/gsThrSoc.CycleCapacity;//更新SOC //------------------------------------------------------------------ //极限电压强制计算,优先级最高 if(battery.BatSta == BatteryCharging) { CellVoltage = SoftSoc.CellVmaxAcc/SOC_SAMPLE_TIME; if(CellVoltage >= (gsThrSoc.VoltageCap[10]))//满电100%电压 { if(AbsInt32(CoulombAve) < CHG_END_COULOMB)//电流小于充电截止电流 { SoftSoc.Soc = 100; soc_temp = gsThrSoc.CycleCapacity; SoftSoc.RemainCap = soc_temp * 100; SoftSoc.SocStatus.B_bit.BATFull = 1;//容量学习标志 } } SoftSoc.ChargeCap += Coulomb;//累加本次充电容量 } else { CellVoltage = SoftSoc.CellVminAcc/SOC_SAMPLE_TIME; } //------------------------------------------------------------------ //充电保护置100操作 if(SoftSoc.SocStatus.B_bit.EN_OVP100 == 0) { if(SoftSoc.Soc < 90) SoftSoc.SocStatus.B_bit.EN_OVP100 = 1; } else { if((gBatStatus.B_bit.CELL_OV == TRUE)||(gBatStatus.B_bit.PACK_OV == 1))//发生充电保护时强制置100% { SoftSoc.Soc = 100; soc_temp = gsThrSoc.CycleCapacity; SoftSoc.RemainCap = soc_temp * 100; SoftSoc.SocStatus.B_bit.BATFull = 1; SoftSoc.SocStatus.B_bit.EN_OVP100 = 0; } } //************************************容量学习功能*******************************************************// if(SoftSoc.Soc < 100) { SoftSoc.SocStatus.B_bit.BATFull = 0; } if((SoftSoc.SocStatus.B_bit.EN_CALIB)&&(SoftSoc.SocStatus.B_bit.BATFull)) { if(SoftSoc.Soc == 100) //判断是否满电 { SoftSoc.SocStatus.B_bit.EN_CALIB = 0; //学习到的容量值要在电池设计容量的(60%,120%)之间; soc_temp = gsThrSoc.DesignCapacity*120; if(SoftSoc.ChargeCap > soc_temp) { SoftSoc.ChargeCap = soc_temp; } else { //计算电池老化系数 soc_temp = BmsSoc_GetCycleCap(100); //计算理论循环容量 SoftSoc.AgingCoeff = (SoftSoc.ChargeCap/soc_temp) - 2;// 容量学习保留2%——充电效率用的100% gsThrSoc.CycleCapacity = BmsSoc_GetCycleCap(SoftSoc.AgingCoeff); //更新循环容量 soc_temp = gsThrSoc.CycleCapacity; SoftSoc.RemainCap = soc_temp * 100; //更新剩余容量 } } } //---------------------------------------------------------------------- if((gBatStatus.B_bit.CELL_OV == TRUE)||(gBatStatus.B_bit.PACK_OV == 1)) //发生充电保护时强制置100% { SoftSoc.Soc = 100; soc_temp = gsThrSoc.CycleCapacity; SoftSoc.RemainCap = soc_temp * 100; } if((CellVoltage < gsThrSoc.DsgEndVol)||(gBatStatus.B_bit.CELL_UV == TRUE)) //截止电压 { SoftSoc.Soc = 0; SoftSoc.RemainCap = 0; if(Ext_TempMin > SOC_TMP_ENABLE) { SoftSoc.SocStatus.B_bit.EN_CALIB = 1; //允许校准容量 } } } //计算电量 void BmsSoc_Calculate(void) { uint16_t SocTmp = 0; int32_t AccTemp; if(++SoftSoc.PowOnDelay>10) //等待电压稳定 { SoftSoc.PowOnDelay = 10; } else {return;} SoftSoc.CellVmaxAcc += Info.CellVmax; SoftSoc.CellVminAcc += Info.CellVmin; if(++SoftSoc.AccCounter >= SOC_SAMPLE_TIME) { BmsSoc_gauging(); //到达一个积分周期 SoftSoc.CellVmaxAcc = 0; SoftSoc.CellVminAcc = 0; } AccTemp = gAccCoulomb; //------------------------------------------------------------------------- AccTemp = AccTemp*SoftSoc.CoulombK;//积分器增益系数 AccTemp = AccTemp/(SOC_S_TIME*100); SoftSoc.RmCapTmp = SoftSoc.RemainCap + AccTemp; if(SoftSoc.RmCapTmp < 0)//剩余容量缓存 { SoftSoc.RmCapTmp = 0; } if(SoftSoc.RmCapTmp > ((U32)((U32)gsThrSoc.CycleCapacity * 100))) { SoftSoc.RmCapTmp = (U32)((U32)gsThrSoc.CycleCapacity * 100); } //**************通讯SOCOUT显示值计算********************************// SocTmp = SoftSoc.RmCapTmp/gsThrSoc.CycleCapacity; //更新SOC if(SocTmp<=99) //改善用户体验 { SoftSoc.SocOut = SocTmp + 1; } else if(SocTmp >= 100) { SoftSoc.SocOut = 100; } if(SoftSoc.RemainCap == 0) SoftSoc.SocOut = 0; //******************强制清零点、置百点、****************************// if((gBatStatus.B_bit.CELL_OV == TRUE)||(gBatStatus.B_bit.PACK_OV == 1)) //发生充电保护时强制置100% { SoftSoc.SocOut = 100; SoftSoc.RemainCap = (U32)((U32)gsThrSoc.CycleCapacity * 100); } if(gBatStatus.B_bit.CELL_UV == TRUE) //截止电压 { SoftSoc.SocOut = 0; SoftSoc.RemainCap = 0; } //***************************************************************// }