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

Last change on this file since 28 was 28, checked in by f.jahn, 7 weeks 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.