/* 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 . */ #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; /* * ������� �������� * ������� �������� * ���� �������� ������� ������� * * �������� = ��������, ����� * �������� ������� ��� �� ���������� �� ������� ������ * * soc = ������ ������� / �������� ������� * 100 * * � - ������� ������� �� ������ ���� ������ �� 1% (��) * b - ������� ������� ������� ������ �� 5% (��) ( x amp - 5% * y amp - 100%; y = 100x/5 * * �������� ������� = ( 100 * �������� ��� ) / ������ � ��������� * * 100 * 2 /1 = 200 * * * * �������� ������ � ��������� 1%, �������� 1,4��� * �� = (100 * 1.4) / 1 = 140 ��� * * �������� ������ � ��������� 1%, �������� 2,8��� * (100 * 2,8) /1 = 280 ��� * * ������ 2%, �������� 1,4 * (100 * 1.4) /2 70 ��� * * * * soh * * �������� ������� 150, ������ 1,5, ��� ���������� 99% * * * ������� ������� ��� ������ � ������� ���������� ������ � (������ ���) ������� ��������� ��� ��������� * * soh = ��������� �������� ������� � �������� * * 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; } };