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

Last change on this file since 26 was 26, checked in by f.jahn, 7 weeks 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: 6.6 KB
Line 
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 "stm32g4xx_hal.h"
12#include "sysdata.h"
13#include "wh_counter.h"
14
15//static int64_t mWs_AutoMode;
16
17void WH_COUNTER_CalcSoH(void);
18
19
20void 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
35void 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  // Counting Total Power
81  if (sys_data.s.values.batteryPower < 0)
82  {
83          totalDischarge += -sys_data.s.values.batteryPower;
84          sys_data.s.values.dischargeTotalWh = totalDischarge / 3600000; //Umrechnung von mWs auf Wh   
85  }
86  else
87  {
88          totalCharge += sys_data.s.values.batteryPower;
89          sys_data.s.values.chargeTotalWh = totalCharge / 3600000; //Umrechnung von mWs auf Wh
90  }
91}
92
93//------------------------------------------------------------------------------
94
95void WH_COUNTER_SetDetectedEnergy(void) {
96  sys_data.s.values.detectedEnergy = sys_data.s.values.mWh_AutoMode >= 0 ? sys_data.s.values.mWh_AutoMode : -sys_data.s.values.mWh_AutoMode;
97  WH_COUNTER_CalcSoH();
98}
99
100//------------------------------------------------------------------------------
101
102/*!
103 *      \brief  Returns Soc in m%
104 *
105 *      \return SoC value in m%
106 */
107
108int32_t WH_COUNTER_GetSoCManual(void) {
109  int64_t E_mWh = sys_data.s.parameter.battEnergy;
110  int64_t battEnergy_mWs = E_mWh * 3600LL;
111
112  int64_t SoC = 0LL;
113  if (battEnergy_mWs != 0LL)
114    SoC = (100000LL * sys_data.s.values.mWsCounter) / battEnergy_mWs;
115  else
116    SoC = 0LL;
117
118  return (int32_t)SoC;
119}
120
121//------------------------------------------------------------------------------
122
123/*!
124 *      \brief  Returns Soc in m%
125 *
126 *      \return SoC value in m%
127 */
128
129int32_t WH_COUNTER_GetSoCAuto(void) {
130  // int64_t E_mWh = sys_data.s.parameter.cellEnergy;
131  // int64_t cellEnergy_mWs = E_mWh * 3600LL;
132  const int64_t _100mPercent = 100000LL;
133
134  int64_t mWh_AutoMode = sys_data.s.values.mWh_AutoMode < 0 ? -sys_data.s.values.mWh_AutoMode : 0;
135  int64_t SoC = 0LL;
136  if (sys_data.s.values.detectedEnergy <= 0)
137  {
138    SoC = _100mPercent - (_100mPercent * mWh_AutoMode) / (int64_t)sys_data.s.parameter.battEnergy;
139  }
140  else
141  {
142    SoC = _100mPercent - (_100mPercent * mWh_AutoMode) / (int64_t)sys_data.s.values.detectedEnergy;
143  }
144
145  if (SoC > _100mPercent)
146    SoC = _100mPercent;
147  else if (SoC <= 0LL)
148    SoC = 0LL;
149
150  return (int32_t)SoC;
151}
152
153int32_t WH_COUNTER_GetSoCAutoTemp(void) {
154  // int64_t E_mWh = sys_data.s.parameter.cellEnergy;
155  // int64_t cellEnergy_mWs = E_mWh * 3600LL;
156  const int64_t _100mPercent = 100000LL;
157  int32_t SoC = 0LL;
158
159  // Verbleibene mAh
160  int64_t rmAh;
161  if (sys_data.s.values.detectedEnergy <= 0)
162  {
163    rmAh = sys_data.s.parameter.cellCapacity - (-sys_data.s.values.mAh_AutoMode); // 40000
164  }
165  else {
166    rmAh = sys_data.s.values.detectedCapacity - (-sys_data.s.values.mAh_AutoMode); // 40000
167  }
168
169
170  // verbleibene Energie
171  // dazu zunächst den Mittelwert der noch verbleibenden Spannung vom aktuellen Zeitpunkt bis zur Abschaltung ermittelndazu
172  int64_t avgVoltage = (sys_data.s.values.batteryVoltage + sys_data.s.values.uBatEmptyTempComp) / 2;
173
174  //Jetzt mit der verbleibene Kapazität die verbleibene Energie unter den aktuellen Bedingungen ermitteln (Spannung bei akt. Temp)
175  int64_t rP = (rmAh * avgVoltage) / 1000LL;
176
177
178  if (sys_data.s.values.detectedEnergy > 0)
179  {
180    SoC = (_100mPercent * rP) / sys_data.s.values.detectedEnergy;
181  }
182  else {
183    SoC = (_100mPercent * rP) / sys_data.s.parameter.battEnergy;
184  }
185
186
187  if (SoC > _100mPercent)
188    SoC = _100mPercent;
189  else if (SoC <= 0LL)
190    SoC = 0LL;
191
192  return SoC;
193}
194
195//------------------------------------------------------------------------------
196
197void WH_COUNTER_SetToMax(void) {
198  int64_t E_mWh = sys_data.s.parameter.battEnergy;
199  int64_t battEnergy_mWs = E_mWh * 3600LL;
200
201  sys_data.s.values.mWsCounter = battEnergy_mWs;
202
203  sys_data.s.values.mWs_AutoMode = 0LL;
204  sys_data.s.values.mWh_AutoMode = 0;
205
206  sys_data.s.values.lastTimeVbatFull = 0U;
207}
208
209//------------------------------------------------------------------------------
210
211void WH_COUNTER_CalcSoH(void)
212{
213        const int64_t _promille = 1000LL;
214
215        if (sys_data.s.values.detectedCapacity < 0) sys_data.s.values.SoH = -1; // SoH was not yet calculated
216        else
217        {
218                uint32_t detectedCapacity_mAh = sys_data.s.values.detectedCapacity;
219
220                if (detectedCapacity_mAh >= sys_data.s.parameter.cellCapacity) sys_data.s.values.SoH = (int32_t)_promille;
221                else
222                {
223                        if (sys_data.s.parameter.cellCapacity == 0U)
224                                sys_data.s.values.SoH = -1;
225                        else
226                                sys_data.s.values.SoH = (int32_t)((_promille * (int64_t)detectedCapacity_mAh) / (int64_t)sys_data.s.parameter.cellCapacity);
227                }
228        }
229}
Note: See TracBrowser for help on using the repository browser.