1 | /*! |
---|
2 | * \file wh_counter.c |
---|
3 | * \author ECS, Zhambolat Kazharov |
---|
4 | * \brief |
---|
5 | * |
---|
6 | */ |
---|
7 | |
---|
8 | #include <math.h> |
---|
9 | #include <stdint.h> |
---|
10 | |
---|
11 | #include "stm32g0xx_hal.h" |
---|
12 | #include "sysdata.h" |
---|
13 | #include "wh_counter.h" |
---|
14 | |
---|
15 | //static int64_t mWs_AutoMode; |
---|
16 | |
---|
17 | void WH_COUNTER_CalcSoH(void); |
---|
18 | |
---|
19 | |
---|
20 | void WH_COUNTER_Init(void) |
---|
21 | { |
---|
22 | sys_data.s.values.mWs_AutoMode = (int32_t)-sys_data.s.parameter.battEnergy * 3600;; |
---|
23 | } |
---|
24 | |
---|
25 | |
---|
26 | //------------------------------------------------------------------------------ |
---|
27 | |
---|
28 | /*! |
---|
29 | * \brief Calculates Wh periodically (1s) |
---|
30 | * |
---|
31 | * Must be called every second |
---|
32 | * |
---|
33 | */ |
---|
34 | |
---|
35 | void WH_COUNTER_Exec(void) { |
---|
36 | |
---|
37 | static uint64_t totalDischarge = 0; |
---|
38 | static uint64_t totalCharge = 0; |
---|
39 | |
---|
40 | if (totalDischarge == 0) totalDischarge = sys_data.s.values.dischargeTotalWh * 3600000; |
---|
41 | if (totalCharge == 0) totalCharge = sys_data.s.values.chargeTotalWh * 3600000; |
---|
42 | |
---|
43 | //------------ separater CEF ----------- |
---|
44 | // bei Strom größer 0 -> Ladestrom CEF rechnen |
---|
45 | if (sys_data.s.values.batteryCurrent >= 0) { |
---|
46 | // 99 --> 99% --> 0.99 |
---|
47 | int32_t cefW = sys_data.s.parameter.cefW; |
---|
48 | sys_data.s.values.correctedStromForChargeWhCnt = (sys_data.s.values.batteryCurrent * cefW) / 100; |
---|
49 | sys_data.s.values.correctedStromForChargeWhCnt -= sys_data.s.parameter.extraDischargeStrom_mA; |
---|
50 | } else { |
---|
51 | sys_data.s.values.correctedStromForChargeWhCnt = sys_data.s.values.batteryCurrentCorrected; |
---|
52 | } |
---|
53 | |
---|
54 | // mW = (mA * mV) / 1000 |
---|
55 | int64_t i_mA = sys_data.s.values.correctedStromForChargeWhCnt; |
---|
56 | int64_t v_mV = sys_data.s.values.batteryVoltage; |
---|
57 | int64_t p_mW = (i_mA * v_mV) / 1000LL; |
---|
58 | |
---|
59 | int64_t E_mWh = (int64_t)sys_data.s.parameter.battEnergy; |
---|
60 | int64_t battEnergy_mWs = E_mWh * 3600LL; // Umrechnung mWh zu mWs |
---|
61 | |
---|
62 | // Aufsummieren |
---|
63 | sys_data.s.values.mWsCounter += p_mW; // Energy value for both positive and negative currents |
---|
64 | sys_data.s.values.mWs_AutoMode += p_mW; |
---|
65 | |
---|
66 | |
---|
67 | // Begrenzen, Batterie darf nicht über 100% gehen |
---|
68 | if (sys_data.s.values.mWsCounter > battEnergy_mWs) { |
---|
69 | sys_data.s.values.mWsCounter = battEnergy_mWs; |
---|
70 | } |
---|
71 | |
---|
72 | // Autmode Zähler, zählen von 0 Rückwärts und sollen nicht über 0 steigen |
---|
73 | if (sys_data.s.values.mWs_AutoMode > 0) { |
---|
74 | sys_data.s.values.mWs_AutoMode = 0; |
---|
75 | } |
---|
76 | |
---|
77 | sys_data.s.values.mWh_AutoMode = sys_data.s.values.mWs_AutoMode / 3600LL; |
---|
78 | sys_data.s.values.mWhCounter = sys_data.s.values.mWsCounter / 3600LL; |
---|
79 | |
---|
80 | |
---|
81 | |
---|
82 | |
---|
83 | // Counting Total Power |
---|
84 | if (sys_data.s.values.batteryPower < 0) |
---|
85 | { |
---|
86 | totalDischarge += -sys_data.s.values.batteryPower; |
---|
87 | sys_data.s.values.dischargeTotalWh = totalDischarge / 3600000; //Umrechnung von mWs auf Wh |
---|
88 | |
---|
89 | |
---|
90 | sys_data.s.values.fullCyclesCnt = (uint16_t) ((sys_data.s.values.dischargeTotalAh * 1000) / sys_data.s.parameter.cellCapacity); |
---|
91 | } |
---|
92 | else |
---|
93 | { |
---|
94 | totalCharge += sys_data.s.values.batteryPower; |
---|
95 | sys_data.s.values.chargeTotalWh = totalCharge / 3600000; //Umrechnung von mWs auf Wh |
---|
96 | } |
---|
97 | |
---|
98 | |
---|
99 | |
---|
100 | } |
---|
101 | |
---|
102 | //------------------------------------------------------------------------------ |
---|
103 | |
---|
104 | void WH_COUNTER_SetDetectedEnergy(void) { |
---|
105 | sys_data.s.values.detectedEnergy = sys_data.s.values.mWh_AutoMode >= 0 ? sys_data.s.values.mWh_AutoMode : -sys_data.s.values.mWh_AutoMode; |
---|
106 | WH_COUNTER_CalcSoH(); |
---|
107 | } |
---|
108 | |
---|
109 | //------------------------------------------------------------------------------ |
---|
110 | |
---|
111 | /*! |
---|
112 | * \brief Returns Soc in m% |
---|
113 | * |
---|
114 | * \return SoC value in m% |
---|
115 | */ |
---|
116 | |
---|
117 | int32_t WH_COUNTER_GetSoCManual(void) { |
---|
118 | int64_t E_mWh = sys_data.s.parameter.battEnergy; |
---|
119 | int64_t battEnergy_mWs = E_mWh * 3600LL; |
---|
120 | |
---|
121 | int64_t SoC = 0LL; |
---|
122 | if (battEnergy_mWs != 0LL) |
---|
123 | SoC = (100000LL * sys_data.s.values.mWsCounter) / battEnergy_mWs; |
---|
124 | else |
---|
125 | SoC = 0LL; |
---|
126 | |
---|
127 | return (int32_t)SoC; |
---|
128 | } |
---|
129 | |
---|
130 | //------------------------------------------------------------------------------ |
---|
131 | |
---|
132 | /*! |
---|
133 | * \brief Returns Soc in m% |
---|
134 | * |
---|
135 | * \return SoC value in m% |
---|
136 | */ |
---|
137 | |
---|
138 | int32_t WH_COUNTER_GetSoCAuto(void) { |
---|
139 | // int64_t E_mWh = sys_data.s.parameter.cellEnergy; |
---|
140 | // int64_t cellEnergy_mWs = E_mWh * 3600LL; |
---|
141 | const int64_t _100mPercent = 100000LL; |
---|
142 | |
---|
143 | int64_t mWh_AutoMode = sys_data.s.values.mWh_AutoMode < 0 ? -sys_data.s.values.mWh_AutoMode : 0; |
---|
144 | int64_t SoC = 0LL; |
---|
145 | if (sys_data.s.values.detectedEnergy <= 0) |
---|
146 | { |
---|
147 | SoC = _100mPercent - (_100mPercent * mWh_AutoMode) / (int64_t)sys_data.s.parameter.battEnergy; |
---|
148 | } |
---|
149 | else |
---|
150 | { |
---|
151 | SoC = _100mPercent - (_100mPercent * mWh_AutoMode) / (int64_t)sys_data.s.values.detectedEnergy; |
---|
152 | } |
---|
153 | |
---|
154 | if (SoC > _100mPercent) |
---|
155 | SoC = _100mPercent; |
---|
156 | else if (SoC <= 0LL) |
---|
157 | SoC = 0LL; |
---|
158 | |
---|
159 | return (int32_t)SoC; |
---|
160 | } |
---|
161 | |
---|
162 | int32_t WH_COUNTER_GetSoCAutoTemp(void) { |
---|
163 | // int64_t E_mWh = sys_data.s.parameter.cellEnergy; |
---|
164 | // int64_t cellEnergy_mWs = E_mWh * 3600LL; |
---|
165 | const int64_t _100mPercent = 100000LL; |
---|
166 | int32_t SoC = 0LL; |
---|
167 | |
---|
168 | // Verbleibene mAh |
---|
169 | int64_t rmAh; |
---|
170 | if (sys_data.s.values.detectedEnergy <= 0) |
---|
171 | { |
---|
172 | rmAh = sys_data.s.parameter.cellCapacity - (-sys_data.s.values.mAh_AutoMode); // 40000 |
---|
173 | } |
---|
174 | else { |
---|
175 | rmAh = sys_data.s.values.detectedCapacity - (-sys_data.s.values.mAh_AutoMode); // 40000 |
---|
176 | } |
---|
177 | |
---|
178 | |
---|
179 | // verbleibene Energie |
---|
180 | // dazu zunächst den Mittelwert der noch verbleibenden Spannung vom aktuellen Zeitpunkt bis zur Abschaltung ermittelndazu |
---|
181 | int64_t avgVoltage = (sys_data.s.values.batteryVoltage + sys_data.s.values.uBatEmptyTempComp) / 2; |
---|
182 | |
---|
183 | //Jetzt mit der verbleibene Kapazität die verbleibene Energie unter den aktuellen Bedingungen ermitteln (Spannung bei akt. Temp) |
---|
184 | int64_t rP = (rmAh * avgVoltage) / 1000LL; |
---|
185 | |
---|
186 | |
---|
187 | if (sys_data.s.values.detectedEnergy > 0) |
---|
188 | { |
---|
189 | SoC = (_100mPercent * rP) / sys_data.s.values.detectedEnergy; |
---|
190 | } |
---|
191 | else { |
---|
192 | SoC = (_100mPercent * rP) / sys_data.s.parameter.battEnergy; |
---|
193 | } |
---|
194 | |
---|
195 | |
---|
196 | if (SoC > _100mPercent) |
---|
197 | SoC = _100mPercent; |
---|
198 | else if (SoC <= 0LL) |
---|
199 | SoC = 0LL; |
---|
200 | |
---|
201 | return SoC; |
---|
202 | } |
---|
203 | |
---|
204 | //------------------------------------------------------------------------------ |
---|
205 | |
---|
206 | void WH_COUNTER_SetToMax(void) { |
---|
207 | int64_t E_mWh = sys_data.s.parameter.battEnergy; |
---|
208 | int64_t battEnergy_mWs = E_mWh * 3600LL; |
---|
209 | |
---|
210 | sys_data.s.values.mWsCounter = battEnergy_mWs; |
---|
211 | |
---|
212 | sys_data.s.values.mWs_AutoMode = 0LL; |
---|
213 | sys_data.s.values.mWh_AutoMode = 0; |
---|
214 | |
---|
215 | sys_data.s.values.lastTimeVbatFull = 0U; |
---|
216 | } |
---|
217 | |
---|
218 | //------------------------------------------------------------------------------ |
---|
219 | |
---|
220 | void WH_COUNTER_CalcSoH(void) |
---|
221 | { |
---|
222 | const int64_t _promille = 1000LL; |
---|
223 | |
---|
224 | if (sys_data.s.values.detectedCapacity < 0) sys_data.s.values.SoH = -1; // SoH was not yet calculated |
---|
225 | else |
---|
226 | { |
---|
227 | uint32_t detectedCapacity_mAh = sys_data.s.values.detectedCapacity; |
---|
228 | |
---|
229 | if (detectedCapacity_mAh >= sys_data.s.parameter.cellCapacity) sys_data.s.values.SoH = (int32_t)_promille; |
---|
230 | else |
---|
231 | { |
---|
232 | if (sys_data.s.parameter.cellCapacity == 0U) |
---|
233 | sys_data.s.values.SoH = -1; |
---|
234 | else |
---|
235 | sys_data.s.values.SoH = (int32_t)((_promille * (int64_t)detectedCapacity_mAh) / (int64_t)sys_data.s.parameter.cellCapacity); |
---|
236 | } |
---|
237 | } |
---|
238 | } |
---|