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

Last change on this file since 26 was 26, checked in by f.jahn, 3 months ago
  • Bug in ADC Kalibrierung (STM32 ADC Strom) behoben
  • DMA Buffer für ADC 1 und ADC wird vor Überschreibung während bearbeitung geschützt, indem Datenübertragung nur einmalig erfolgt und erst nach Auswertung wieder gestartet wird
  • RS485Modbus: Timeout Zeit wird für Baudraten >19200 korrekt berechnet
  • Hardware ID geändert
  • Separates Register für "Batterie Empty detection mode" auf Adresse 92 angelegt
File size: 8.5 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;
29// --- LOKALE FUNKTIONS PROTOTYPEN ----------------------------------------------
30int getSocAhRated(void);
31int getSocAhAuto(void);
32
33//int64_t mAs_AutoMode;
34
35
36void AH_COUNTER_Init(void)
37{
38 sys_data.s.values.mAs_AutoMode = (int32_t)-sys_data.s.parameter.cellCapacity * 3600;;
39}
40
41
42// --- LOKALE FUNKTIONEN - bitte hier dokumentieren -----------------------------
43int getSocAhRated(void)
44{
45 int64_t cellCapacitySeconds = (int64_t)sys_data.s.parameter.cellCapacity * 60 * 60; // Umrechnung mAh zu mAs
46 return (100000 * sys_data.s.values.mAsCounter) / cellCapacitySeconds;
47}
48
49
50int getSocAhAuto(void)
51{
52
53 const int64_t _100mPercent = 100000LL;
54
55
56 int64_t mAh_AutoMode = sys_data.s.values.mAh_AutoMode < 0 ? -sys_data.s.values.mAh_AutoMode : 0;
57 int64_t tmp = 0LL;
58 if (sys_data.s.values.detectedCapacity <= 0)
59 {
60 tmp = _100mPercent - (mAh_AutoMode * _100mPercent) / (int64_t)sys_data.s.parameter.cellCapacity;
61 }
62 else
63 {
64 tmp = _100mPercent - (mAh_AutoMode * _100mPercent) / (int64_t)sys_data.s.values.detectedCapacity;
65 }
66
67 if (tmp > _100mPercent) tmp = _100mPercent;
68 else if (tmp <= 0) tmp = 0LL;
69 return tmp;
70 }
71
72
73// --- GLOBALE FUNKTIONEN - bitte in Header dokumentieren------------------------
74
75void AH_COUNTER_Exec(void)
76{
77 double iBatDivIbatNenn = 0;
78 double current = 0;
79 double peukert = 0;
80 double calcPow = 0;
81 double cef = 0;
82 double soc = 0;
83 int64_t maxCurrentForBatteryFullDetection = 0;
84 static int16_t batteryFullCounter = 0;
85 static uint64_t totalDischarge = 0;
86 static uint64_t totalCharge = 0;
87
88 int64_t cellCapacitySeconds = (int64_t)sys_data.s.parameter.cellCapacity * 60 * 60; // Umrechnung mAh zu mAs
89
90
91 if (totalDischarge == 0) totalDischarge = sys_data.s.values.dischargeTotalAh * 3600000;
92 if (totalCharge == 0) totalCharge = sys_data.s.values.chargeTotalAh * 3600000;
93
94
95
96 // bei Strom größer 0 -> Ladestrom CEF rechnen
97 if(sys_data.s.values.batteryCurrent >= 0)
98 {
99 //99 --> 99% --> 0.99
100 cef = sys_data.s.parameter.cef / 100.0;
101 sys_data.s.values.batteryCurrentCorrected = sys_data.s.values.batteryCurrent * cef;
102 }
103 else
104 { // bei Strom kleiner 0 peukert rechnen
105 //int32_t ratedCurrent = sys_data.s.parameter.cellRatedCurrent * 1000;
106 int32_t ratedCurrent = sys_data.s.parameter.cellCapacity / sys_data.s.parameter.cellRatedDischargeTime;
107
108 if (sys_data.s.values.batteryCurrent < -ratedCurrent) //ACHTUNG mit Minus das vorzeichen gedreht!
109 {
110 current = sys_data.s.values.batteryCurrent;
111 iBatDivIbatNenn = current / ratedCurrent;
112 iBatDivIbatNenn = -iBatDivIbatNenn;
113 peukert = (sys_data.s.parameter.peukert / 100.0);
114 calcPow = pow(iBatDivIbatNenn , peukert - 1.0);
115 sys_data.s.values.batteryCurrentCorrected = (current * calcPow);
116 }
117 else sys_data.s.values.batteryCurrentCorrected = sys_data.s.values.batteryCurrent;
118 }
119
120 sys_data.s.values.batteryCurrentCorrected -= (int32_t)sys_data.s.parameter.extraDischargeStrom_mA;
121
122 // Counting negative current
123 if (sys_data.s.values.batteryCurrent < 0)
124 {
125 totalDischarge += -sys_data.s.values.batteryCurrent;
126 sys_data.s.values.dischargeTotalAh = totalDischarge / 3600000; //Umrechnung von mAs auf Ah
127
128
129 sys_data.s.values.fullCyclesCnt = (uint16_t) ((sys_data.s.values.dischargeTotalAh * 1000) / sys_data.s.parameter.cellCapacity);
130 }
131 else
132 {
133 totalCharge += sys_data.s.values.batteryCurrent;
134 sys_data.s.values.chargeTotalAh = totalCharge / 3600000; //Umrechnung von mAs auf Ah
135 }
136
137
138
139 // Aufsummieren
140 sys_data.s.values.mAsCounter += sys_data.s.values.batteryCurrentCorrected;
141 sys_data.s.values.mAs_AutoMode += (int64_t)sys_data.s.values.batteryCurrentCorrected;
142 sys_data.s.values.mAh_AutoMode = sys_data.s.values.mAs_AutoMode / 3600LL;
143
144 // Begrenzen, Batterie darf nicht über 100% gehen
145 if (sys_data.s.values.mAsCounter > cellCapacitySeconds) sys_data.s.values.mAsCounter = cellCapacitySeconds;
146
147 if (sys_data.s.values.mAs_AutoMode > 0)
148 {
149 sys_data.s.values.mAs_AutoMode = 0;
150 }
151
152 //Prüfe Battery Voll Bedinungen
153 maxCurrentForBatteryFullDetection = sys_data.s.parameter.cellCapacity * sys_data.s.parameter.iBatFull / 100.0;
154
155 if (sys_data.s.values.batteryVoltage > sys_data.s.parameter.uBatFull && sys_data.s.values.batteryCurrent < maxCurrentForBatteryFullDetection)
156 {
157 batteryFullCounter++;
158 }
159 else
160 {
161 batteryFullCounter = 0;
162 }
163
164 if (batteryFullCounter > sys_data.s.parameter.tBatFull)
165 {
166 sys_data.s.values.mAsCounter = cellCapacitySeconds;
167 sys_data.s.values.mAs_AutoMode = 0;
168 // Here we can set Wh to max
169 WH_COUNTER_SetToMax();
170
171 //und wir starten eine neue Battery Kapazitäts und Energiemessung
172 startMeasurement = 1;
173 }
174
175 sys_data.s.values.mAhCounter = sys_data.s.values.mAsCounter / 3600LL;
176
177 static uint16_t cnt;
178 if (sys_data.s.parameter.batteryEmptyDetectionMode == 0)
179 {
180 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
181 {
182 cnt++;
183 if ((cnt >= 10) && (startMeasurement == 1)) // 5 Sekunden fest
184 {
185 cnt = 10; //sys_data.s.parameter.tBatFull;
186
187 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
188 {
189 // This line is not so important anymore, because we do not allow mAh_AutoMode to be greater than zero
190 sys_data.s.values.detectedCapacity = sys_data.s.values.mAh_AutoMode >= 0 ? sys_data.s.values.mAh_AutoMode : -sys_data.s.values.mAh_AutoMode;
191 WH_COUNTER_SetDetectedEnergy();
192 startMeasurement = 0;
193 }
194 sys_data.s.values.lastTimeVbatEmpty = 0U;
195 }
196 }
197 else
198 {
199 cnt = 0;
200 }
201 }
202 else
203 {
204 // Neuer Modus. Spannungsmessung wird ignoriert. Erkannt wird Batt Leer mit LVP Signal von LiPro
205 // OVP darf nicht ausgehen, sonst handelt es sich um ein Temperaturabschaltung oder ein andere Fehler
206 // 1000mV als Schwelle um sicher vor rauschen um den Nullpunkt zu seinzu sein
207 if ((sys_data.s.values.ovp_sense > 1000) && (sys_data.s.values.lvp_sense < 1000))
208 {
209 cnt++;
210 if ((cnt >= 10) && (startMeasurement == 1)) // 5 Sekunden fest
211 {
212 cnt = 10; //sys_data.s.parameter.tBatFull;
213
214 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
215 {
216 // This line is not so important anymore, because we do not allow mAh_AutoMode to be greater than zero
217 sys_data.s.values.detectedCapacity = sys_data.s.values.mAh_AutoMode >= 0 ? sys_data.s.values.mAh_AutoMode : -sys_data.s.values.mAh_AutoMode;
218 WH_COUNTER_SetDetectedEnergy();
219 startMeasurement = 0;
220 }
221 sys_data.s.values.lastTimeVbatEmpty = 0U;
222 }
223 }
224 else
225 {
226 cnt = 0;
227 }
228 }
229
230
231 switch (sys_data.s.parameter.socCalcMode)
232 {
233 case SOC_CALC_MODE_AH_RATED: sys_data.s.values.soc = getSocAhRated(); break;
234 case SOC_CALC_MODE_AH_AUTO: sys_data.s.values.soc = getSocAhAuto(); break;
235 case SOC_CALC_MODE_WH_RATED: sys_data.s.values.soc = WH_COUNTER_GetSoCManual(); break;
236 case SOC_CALC_MODE_WH_AUTO: sys_data.s.values.soc = WH_COUNTER_GetSoCAuto(); break;
237 case SOC_CALC_MODE_WH_AUTO_TEMP: sys_data.s.values.soc = WH_COUNTER_GetSoCAutoTemp(); break;
238 default: sys_data.s.values.soc = 0;
239 }
240}
Note: See TracBrowser for help on using the repository browser.