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

Last change on this file since 27 was 27, checked in by f.jahn, 7 weeks ago

Fixing project before CubeMX regeneration.

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