source: trunk/firmware/Src/ah_counter.c @ 6

Last change on this file since 6 was 6, checked in by f.jahn, 3 months ago
File size: 7.2 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 lowVoltageCnt;
178  if (sys_data.s.values.batteryVoltage < sys_data.s.values.uBatEmptyTempComp && sys_data.s.values.batteryVoltage > 1000)
179  {
180          lowVoltageCnt++;
181          if ((lowVoltageCnt >= 10) && (startMeasurement == 1)) // 5 Sekunden fest
182          {
183                  lowVoltageCnt = 10; //sys_data.s.parameter.tBatFull;
184
185                  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
186                  {
187                          // This line is not so important anymore, because we do not allow mAh_AutoMode to be greater than zero
188                          sys_data.s.values.detectedCapacity = sys_data.s.values.mAh_AutoMode >= 0 ? sys_data.s.values.mAh_AutoMode : -sys_data.s.values.mAh_AutoMode;
189                          WH_COUNTER_SetDetectedEnergy();
190                          startMeasurement = 0;
191                          EEPROM_storeConfig(&sys_data, 0);     // Saving detected values
192                  }
193                  sys_data.s.values.lastTimeVbatEmpty = 0U;
194          }
195  }
196  else lowVoltageCnt = 0;
197
198
199
200  switch (sys_data.s.parameter.socCalcMode)
201  {
202          case SOC_CALC_MODE_AH_RATED:          sys_data.s.values.soc = getSocAhRated();                          break;
203          case SOC_CALC_MODE_AH_AUTO:           sys_data.s.values.soc = getSocAhAuto();                           break;
204          case SOC_CALC_MODE_WH_RATED:          sys_data.s.values.soc = WH_COUNTER_GetSoCManual();        break;
205          case SOC_CALC_MODE_WH_AUTO:           sys_data.s.values.soc = WH_COUNTER_GetSoCAuto();          break;
206          case SOC_CALC_MODE_WH_AUTO_TEMP:      sys_data.s.values.soc = WH_COUNTER_GetSoCAutoTemp();  break;
207          default: sys_data.s.values.soc = 0;
208  }
209}
Note: See TracBrowser for help on using the repository browser.