source: trunk/fw_g473rct/SES/src/ah_counter.c@ 28

Last change on this file since 28 was 28, checked in by f.jahn, 3 months ago
File size: 9.0 KB
Line 
1
2 /******************************************************************************
3*
4* @file ah_counter.c
5* @author ECS, Falko Jahn
6* @version V1.0.0
7* @date 2020-05-01
8* @brief
9*
10******************************************************************************/
11
12// --- INCLUDES -----------------------------------------------------------------
13#include "main.h"
14#include "math.h"
15#include "sysdata.h"
16#include "ah_counter.h"
17#include "wh_counter.h"
18#include "eeprom.h"
19// --- EXTERNE VARIABLEN --------------------------------------------------------
20
21// --- LOKALE DEFINES - bitte hier dokumentieren --------------------------------
22
23// --- LOKALE TYPE DEFS - bitte hier dokumentieren-------------------------------
24
25// --- DEFINITIONEN GLOBALER VARIABLEN - Bitte in Header dokumentieren ----------
26
27// --- LOKALE VARIABLEN - bitte hier dokumentieren ------------------------------
28int startMeasurement = 0;
29int startMeasurementCEF = 0;
30// --- LOKALE FUNKTIONS PROTOTYPEN ----------------------------------------------
31int getSocAhRated(void);
32int getSocAhAuto(void);
33
34//int64_t mAs_AutoMode;
35
36
37void AH_COUNTER_Init(void)
38{
39 sys_data.s.values.mAs_AutoMode = (int32_t)-sys_data.s.parameter.cellCapacity * 3600;;
40}
41
42void AH_COUNTER_SetDetectedAh(void)
43{
44 sys_data.s.values.detectedCapacity = sys_data.s.values.mAh_AutoMode >= 0 ? sys_data.s.values.mAh_AutoMode : -sys_data.s.values.mAh_AutoMode;
45}
46
47// --- LOKALE FUNKTIONEN - bitte hier dokumentieren -----------------------------
48int getSocAhRated(void)
49{
50 int64_t cellCapacitySeconds = (int64_t)sys_data.s.parameter.cellCapacity * 60 * 60; // Umrechnung mAh zu mAs
51 return (100000 * sys_data.s.values.mAsCounter) / cellCapacitySeconds;
52}
53
54
55int getSocAhAuto(void)
56{
57
58 const int64_t _100mPercent = 100000LL;
59
60
61 int64_t mAh_AutoMode = sys_data.s.values.mAh_AutoMode < 0 ? -sys_data.s.values.mAh_AutoMode : 0;
62 int64_t tmp = 0LL;
63 if (sys_data.s.values.detectedCapacity <= 0)
64 {
65 tmp = _100mPercent - (mAh_AutoMode * _100mPercent) / (int64_t)sys_data.s.parameter.cellCapacity;
66 }
67 else
68 {
69 tmp = _100mPercent - (mAh_AutoMode * _100mPercent) / (int64_t)sys_data.s.values.detectedCapacity;
70 }
71
72 if (tmp > _100mPercent) tmp = _100mPercent;
73 else if (tmp <= 0) tmp = 0LL;
74 return tmp;
75 }
76
77
78// --- GLOBALE FUNKTIONEN - bitte in Header dokumentieren------------------------
79
80void AH_COUNTER_Exec(void)
81{
82 double iBatDivIbatNenn = 0;
83 double current = 0;
84 double peukert = 0;
85 double calcPow = 0;
86 double cef = 0;
87 double soc = 0;
88 int64_t maxCurrentForBatteryFullDetection = 0;
89 static int16_t batteryFullCounter = 0;
90 static uint64_t totalDischarge = 0;
91 static uint64_t totalCharge = 0;
92
93 int64_t cellCapacitySeconds = (int64_t)sys_data.s.parameter.cellCapacity * 60 * 60; // Umrechnung mAh zu mAs
94
95
96 if (totalDischarge == 0) totalDischarge = sys_data.s.values.dischargeTotalAh * 3600000;
97 if (totalCharge == 0) totalCharge = sys_data.s.values.chargeTotalAh * 3600000;
98
99
100 int32_t realStrom = (int32_t) sys_data.s.values.batteryCurrent - sys_data.s.parameter.extraDischargeStrom_mA;
101
102 // bei Strom größer 0 -> Ladestrom CEF rechnen
103 if (realStrom >= 0)
104 {
105 //99 --> 99% --> 0.99
106 if (sys_data.s.values.calculatedCEFAh <= 0)
107 {
108 cef = sys_data.s.parameter.cef / 100.0;
109 }
110 else
111 {
112 cef = sys_data.s.values.calculatedCEFAh / 1000.0;
113 }
114 sys_data.s.values.batteryCurrentCorrected = realStrom * cef;
115 }
116 else // if (realStrom < 0)
117 { // bei Strom kleiner 0 peukert rechnen
118 //int32_t ratedCurrent = sys_data.s.parameter.cellRatedCurrent * 1000;
119 int32_t ratedCurrent = sys_data.s.parameter.cellCapacity / sys_data.s.parameter.cellRatedDischargeTime;
120
121
122 if (realStrom < -ratedCurrent) //ACHTUNG mit Minus das vorzeichen gedreht!
123 {
124 current = realStrom;
125 iBatDivIbatNenn = current / ratedCurrent;
126 iBatDivIbatNenn = -iBatDivIbatNenn;
127 peukert = (sys_data.s.parameter.peukert / 100.0);
128 calcPow = pow(iBatDivIbatNenn , peukert - 1.0);
129 sys_data.s.values.batteryCurrentCorrected = (current * calcPow);
130 }
131 else sys_data.s.values.batteryCurrentCorrected = realStrom;
132 }
133
134
135 // Counting negative current
136 if (sys_data.s.values.batteryCurrent < 0)
137 {
138 totalDischarge += -realStrom;
139 sys_data.s.values.dischargeTotalAh = totalDischarge / 3600000; //Umrechnung von mAs auf Ah
140
141 sys_data.s.values.fullCyclesCnt = (uint16_t) ((sys_data.s.values.dischargeTotalAh * 1000) / sys_data.s.parameter.cellCapacity);
142 }
143 else
144 {
145 totalCharge += realStrom;
146 sys_data.s.values.chargeTotalAh = totalCharge / 3600000; //Umrechnung von mAs auf Ah
147 }
148
149
150 // Aufsummieren
151 sys_data.s.values.mAsCounter += sys_data.s.values.batteryCurrentCorrected;
152 sys_data.s.values.mAs_AutoMode += sys_data.s.values.batteryCurrentCorrected;
153 sys_data.s.values.mAh_AutoMode = sys_data.s.values.mAs_AutoMode / 3600LL;
154 sys_data.s.values.ahCounterCEF_AutoMode += sys_data.s.values.batteryCurrentCorrected;
155 sys_data.s.values.whCounterCEF_AutoMode += sys_data.s.values.batteryCurrentCorrected * sys_data.s.values.batteryVoltage;
156
157 // Begrenzen, Batterie darf nicht über 100% gehen
158 if (sys_data.s.values.mAsCounter > cellCapacitySeconds) sys_data.s.values.mAsCounter = cellCapacitySeconds;
159
160 if (sys_data.s.values.mAs_AutoMode > 0)
161 {
162 sys_data.s.values.mAs_AutoMode = 0;
163 }
164
165 //Prüfe Battery Voll Bedinungen
166 maxCurrentForBatteryFullDetection = sys_data.s.parameter.cellCapacity * sys_data.s.parameter.iBatFull / 100.0;
167
168 if (sys_data.s.values.batteryVoltage > sys_data.s.parameter.uBatFull && sys_data.s.values.batteryCurrent < maxCurrentForBatteryFullDetection)
169 {
170 batteryFullCounter++;
171 }
172 else
173 {
174 batteryFullCounter = 0;
175 }
176
177 if (batteryFullCounter > sys_data.s.parameter.tBatFull)
178 {
179 sys_data.s.values.mAsCounter = cellCapacitySeconds;
180 sys_data.s.values.mAs_AutoMode = 0;
181 // Here we can set Wh to max
182 WH_COUNTER_SetToMax();
183
184 //und wir starten eine neue Battery Kapazitäts und Energiemessung
185 startMeasurement = 1;
186
187 if (startMeasurementCEF == 1)
188 {
189 startMeasurementCEF=0;
190 sys_data.s.values.calculatedCEFAh = 1000 * (sys_data.s.values.detectedCapacity * 3600) / sys_data.s.values.ahCounterCEF_AutoMode ;
191 sys_data.s.values.calculatedCEFWh = 1000 * (sys_data.s.values.detectedEnergy * 3600) / sys_data.s.values.whCounterCEF_AutoMode;
192 }
193 }
194
195 sys_data.s.values.mAhCounter = sys_data.s.values.mAsCounter / 3600LL;
196
197 // --- BATTERY LEER ERKENNUNG
198 static uint16_t cnt;
199 if (sys_data.s.parameter.batteryEmptyDetectionMode == 0)
200 {
201 if (sys_data.s.values.batteryVoltage < sys_data.s.values.uBatEmptyTempComp && sys_data.s.values.batteryVoltage > 1000) // Verhindert das beim abziehen der Sense ein Batt Empty erkannt wird
202 {
203 cnt++;
204 if ((cnt >= 10) && (startMeasurement == 1)) // 5 Sekunden fest
205 {
206 cnt = 10; //sys_data.s.parameter.tBatFull;
207
208 if ((sys_data.s.values.lastTimeVbatFull >= 3600U) && (sys_data.s.values.lastTimeVbatFull <= 200U * 3600U)) // This line prevents from very high discharge-currents to be used to estimate battery capacity
209 {
210
211 AH_COUNTER_SetDetectedAh();
212 WH_COUNTER_SetDetectedEnergy();
213 sys_data.s.values.ahCounterCEF_AutoMode = 0;
214 sys_data.s.values.whCounterCEF_AutoMode = 0;
215 startMeasurement = 0;
216 }
217 sys_data.s.values.lastTimeVbatEmpty = 0U;
218 }
219 }
220 else
221 {
222 cnt = 0;
223 }
224 }
225 else
226 {
227 // Neuer Modus. Spannungsmessung wird ignoriert. Erkannt wird Batt Leer mit LVP Signal von LiPro
228 // OVP darf nicht ausgehen, sonst handelt es sich um ein Temperaturabschaltung oder ein andere Fehler
229 // 1000mV als Schwelle um sicher vor rauschen um den Nullpunkt zu seinzu sein
230 if ((sys_data.s.values.ovp_sense > 1000) && (sys_data.s.values.lvp_sense < 1000))
231 {
232 cnt++;
233 if ((cnt >= 10) && (startMeasurement == 1)) // 5 Sekunden fest
234 {
235 cnt = 10; //sys_data.s.parameter.tBatFull;
236
237 if ((sys_data.s.values.lastTimeVbatFull >= 3600U) && (sys_data.s.values.lastTimeVbatFull <= 240U * 3600U)) // This line prevents from very high discharge-currents to be used to estimate battery capacity
238 {
239
240 AH_COUNTER_SetDetectedAh();
241 WH_COUNTER_SetDetectedEnergy();
242 startMeasurement = 0;
243 startMeasurementCEF = 1;
244 }
245 sys_data.s.values.lastTimeVbatEmpty = 0U;
246 }
247 }
248 else
249 {
250 cnt = 0;
251 }
252 }
253
254
255 switch (sys_data.s.parameter.socCalcMode)
256 {
257 case SOC_CALC_MODE_AH_RATED: sys_data.s.values.soc = getSocAhRated(); break;
258 case SOC_CALC_MODE_AH_AUTO: sys_data.s.values.soc = getSocAhAuto(); break;
259 case SOC_CALC_MODE_WH_RATED: sys_data.s.values.soc = WH_COUNTER_GetSoCManual(); break;
260 case SOC_CALC_MODE_WH_AUTO: sys_data.s.values.soc = WH_COUNTER_GetSoCAuto(); break;
261 case SOC_CALC_MODE_WH_AUTO_TEMP: sys_data.s.values.soc = WH_COUNTER_GetSoCAutoTemp(); break;
262 default: sys_data.s.values.soc = 0;
263 }
264}
Note: See TracBrowser for help on using the repository browser.