Files
CuboBmsFirmware/firmware/Core/Src/modStateOfCharge.c
2023-04-06 21:23:19 +03:00

228 lines
8.8 KiB
C
Raw Permalink Blame History

/*
Copyright 2017 - 2018 Danny Bokma danny@diebie.nl
Copyright 2019 - 2020 Kevin Dionne kevin.dionne@ennoid.me
This file is part of the DieBieMS/ENNOID-BMS firmware.
The DieBieMS/ENNOID-BMS firmware is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
The DieBieMS/ENNOID-BMS firmware is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "modStateOfCharge.h"
#include "main.h"
modStateOfChargeStructTypeDef modStateOfChargeGeneralStateOfCharge;
modPowerElectronicsPackStateTypedef *modStateOfChargePackStatehandle;
modConfigGeneralConfigStructTypedef *modStateOfChargeGeneralConfigHandle;
uint32_t modStateOfChargeLargeCoulombTick;
uint32_t modStateOfChargeStoreSoCTick;
bool modStateOfChargePowerDownSavedFlag = false;
modStateOfChargeStructTypeDef* modStateOfChargeInit(modPowerElectronicsPackStateTypedef *packState, modConfigGeneralConfigStructTypedef *generalConfigPointer){
modStateOfChargePackStatehandle = packState;
modStateOfChargeGeneralConfigHandle = generalConfigPointer;
driverSWStorageManagerStateOfChargeStructSize = (sizeof(modStateOfChargeStructTypeDef)/sizeof(uint16_t)); // Calculate the space needed for the config struct in EEPROM
modStateOfChargeLargeCoulombTick = HAL_GetTick();
modStateOfChargeStoreSoCTick = HAL_GetTick();
return &modStateOfChargeGeneralStateOfCharge;
};
float real_capacity = 0;
float previous_capacity = 0;
float previous_SoC = 0;
//static float current_SoC = 0;
float soc_diff = 0;
float capacity_diff = 0;
uint8_t SoC_Save_Flag = 0;
void modStateOfChargeProcess(void){
// Calculate accumulated energy
uint32_t dt = HAL_GetTick() - modStateOfChargeLargeCoulombTick;
static float lastsaved_remainingCapacityAh = 0;
modStateOfChargeStructTypeDef lastGeneralStateOfCharge;
/*
* <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
* <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
* <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
*
* <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> = <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>, <20><><EFBFBD><EFBFBD><EFBFBD>
* <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD> <20><> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
*
* soc = <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> / <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> * 100
*
* <20> - <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><> 1% (<28><>)
* b - <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><> 5% (<28><>) ( x amp - 5%
* y amp - 100%; y = 100x/5
*
* <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> = ( 100 * <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD> ) / <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
*
* 100 * 2 /1 = 200
*
* *
* <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> 1%, <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> 1,4<><34><EFBFBD>
* <20><> = (100 * 1.4) / 1 = 140 <20><><EFBFBD>
*
* <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> 1%, <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> 2,8<><38><EFBFBD>
* (100 * 2,8) /1 = 280 <20><><EFBFBD>
*
* <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> 2%, <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> 1,4
* (100 * 1.4) /2 70 <20><><EFBFBD>
*
*
*
* soh
*
* <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> 150, <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> 1,5, <20><><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> 99%
*
*
* <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20> (<28><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD>) <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
*
* soh = <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
*
* soc =
*
*
*/
lastGeneralStateOfCharge = modStateOfChargeGeneralStateOfCharge;
modStateOfChargeLargeCoulombTick = HAL_GetTick();
// calc in Ahmps how much we put or take
modStateOfChargeGeneralStateOfCharge.remainingCapacityAh += dt*modStateOfChargePackStatehandle->packCurrent/(3600*1000);// (miliseconds * amps)/(3600*1000) accumulatedCharge in AmpHour.
// Cap the max stored energy to the configured battery capacity.
// if we put more than battery is, set maximum
if(modStateOfChargeGeneralStateOfCharge.remainingCapacityAh > modStateOfChargeGeneralConfigHandle->batteryCapacity)
modStateOfChargeGeneralStateOfCharge.remainingCapacityAh = modStateOfChargeGeneralConfigHandle->batteryCapacity;
// if we take more than battery, set zero
if(modStateOfChargeGeneralStateOfCharge.remainingCapacityAh < 0.0f)
modStateOfChargeGeneralStateOfCharge.remainingCapacityAh = 0.0f;
// Calculate state of charge
// calc percent of we put/take to battery capacity
modStateOfChargeGeneralStateOfCharge.generalStateOfCharge =
modStateOfChargeGeneralStateOfCharge.remainingCapacityAh / modStateOfChargeGeneralConfigHandle->batteryCapacity * 100.0f;
if(SoC_Save_Flag == 0) {
previous_SoC = modStateOfChargeGeneralStateOfCharge.generalStateOfCharge;
previous_capacity = modStateOfChargeGeneralStateOfCharge.remainingCapacityAh;
SoC_Save_Flag = 1;
}
if(previous_SoC - modStateOfChargeGeneralStateOfCharge.generalStateOfCharge > 1) {
soc_diff = previous_SoC - modStateOfChargeGeneralStateOfCharge.generalStateOfCharge;
//
if(soc_diff == 0) soc_diff = 1;
capacity_diff = previous_capacity - modStateOfChargeGeneralStateOfCharge.remainingCapacityAh;
real_capacity = (100 * capacity_diff) / soc_diff;
export_real_capacity = real_capacity;
previous_SoC = modStateOfChargeGeneralStateOfCharge.generalStateOfCharge;
previous_capacity = modStateOfChargeGeneralStateOfCharge.remainingCapacityAh;
//SoC_Save_Flag = 0;
} //else if (previous_SoC - modStateOfChargeGeneralStateOfCharge.generalStateOfCharge < -1) {
// SoC_Save_Flag = 0;
//}
// if we have more than 100% it is 100%
if(modStateOfChargeGeneralStateOfCharge.generalStateOfCharge >= 100.0f)
modStateOfChargeGeneralStateOfCharge.generalStateOfCharge = 100.0f;
// save soc and amps
modStateOfChargePackStatehandle->SoC = modStateOfChargeGeneralStateOfCharge.generalStateOfCharge;
modStateOfChargePackStatehandle->SoCCapacityAh = modStateOfChargeGeneralStateOfCharge.remainingCapacityAh;
// Store SoC every 'stateOfChargeStoreInterval'
modStateOfChargeGeneralConfigHandle->stateOfChargeStoreInterval = 10000;
if(modDelayTick1ms(&modStateOfChargeStoreSoCTick,modStateOfChargeGeneralConfigHandle->stateOfChargeStoreInterval) &&
(lastsaved_remainingCapacityAh != modStateOfChargeGeneralStateOfCharge.remainingCapacityAh)) {
lastsaved_remainingCapacityAh = modStateOfChargeGeneralStateOfCharge.remainingCapacityAh;
modStateOfChargeStoreStateOfCharge();
}
};
bool modStateOfChargeStoreAndLoadDefaultStateOfCharge(void){
bool returnVal = false;
if(driverSWStorageManagerStateOfChargeEmpty){
// TODO: SoC manager is empy -> Determin SoC from voltage when voltages are available.
modStateOfChargeStructTypeDef defaultStateOfCharge;
defaultStateOfCharge.generalStateOfCharge = 100.0f;
defaultStateOfCharge.generalStateOfHealth = 100.0f;
defaultStateOfCharge.remainingCapacityAh = modStateOfChargeGeneralConfigHandle->batteryCapacity;
defaultStateOfCharge.remainingCapacityWh = 0.0f;
driverSWStorageManagerStateOfChargeEmpty = false;
driverSWStorageManagerStoreStruct(&defaultStateOfCharge,STORAGE_STATEOFCHARGE);
// TODO_EEPROM
}
modStateOfChargeStructTypeDef tempStateOfCharge;
driverSWStorageManagerGetStruct(&tempStateOfCharge,STORAGE_STATEOFCHARGE);
modStateOfChargeLoadStateOfCharge();
return returnVal;
};
bool modStateOfChargeStoreStateOfCharge(void){
HAL_GPIO_TogglePin(HL2_GPIO_Port, HL2_Pin);
return driverSWStorageManagerStoreStruct(&modStateOfChargeGeneralStateOfCharge,STORAGE_STATEOFCHARGE);
};
bool modStateOfChargeLoadStateOfCharge(void){
return driverSWStorageManagerGetStruct(&modStateOfChargeGeneralStateOfCharge,STORAGE_STATEOFCHARGE);
};
bool modStateOfChargePowerDownSave(void) {
// if(!modStateOfChargePowerDownSavedFlag) {
// modStateOfChargePowerDownSavedFlag = true;
// modStateOfChargeStoreStateOfCharge();
// // TODO_EEPROM
// return true;
// }else
// return false;
};
void modStateOfChargeVoltageEvent(modStateOfChargeVoltageEventTypeDef eventType) {
switch(eventType) {
case EVENT_EMPTY:
break;
case EVENT_FULL:
modStateOfChargeGeneralStateOfCharge.remainingCapacityAh = modStateOfChargeGeneralConfigHandle->batteryCapacity;
break;
default:
break;
}
};