A Discrete-Event Network Simulator
API
Loading...
Searching...
No Matches
generic-battery-model.cc
Go to the documentation of this file.
1/*
2 * Copyright (c) 2010 Andrea Sacco: Li-Ion battery
3 * Copyright (c) 2023 Tokushima University, Japan:
4 * NiMh,NiCd,LeaAcid batteries and preset and multicell extensions.
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 as
8 * published by the Free Software Foundation;
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 *
19 * Author: Andrea Sacco <andrea.sacco85@gmail.com>
20 * Alberto Gallegos Ramonet <alramonet@is.tokushima-u.ac.jp>
21 */
22
24
25#include <ns3/assert.h>
26#include <ns3/double.h>
27#include <ns3/log.h>
28#include <ns3/simulator.h>
29#include <ns3/trace-source-accessor.h>
30
31#include <cmath>
32
33namespace ns3
34{
35
36NS_LOG_COMPONENT_DEFINE("GenericBatteryModel");
37
38NS_OBJECT_ENSURE_REGISTERED(GenericBatteryModel);
39
40TypeId
42{
43 static TypeId tid =
44 TypeId("ns3::GenericBatteryModel")
46 .SetGroupName("Energy")
47 .AddConstructor<GenericBatteryModel>()
48 .AddAttribute("LowBatteryThreshold",
49 "Low battery threshold for generic battery model.",
50 DoubleValue(0.10), // 0.10 as a fraction of the initial energy
52 MakeDoubleChecker<double>())
53 .AddAttribute("FullVoltage",
54 "(Q_full) The voltage of the cell when fully charged (V).",
55 DoubleValue(4.18),
57 MakeDoubleChecker<double>())
58 .AddAttribute("MaxCapacity",
59 "(Q) The maximum capacity of the cell (Ah).",
60 DoubleValue(2.45),
62 MakeDoubleChecker<double>())
63 .AddAttribute("NominalVoltage",
64 "(V_nom) Nominal voltage of the cell (V).",
65 DoubleValue(3.59),
67 MakeDoubleChecker<double>())
68 .AddAttribute("NominalCapacity",
69 "(Q_nom) Cell capacity at the end of the nominal zone (Ah)",
70 DoubleValue(1.3),
72 MakeDoubleChecker<double>())
73 .AddAttribute("ExponentialVoltage",
74 "(V_exp) Cell voltage at the end of the exponential zone (V).",
75 DoubleValue(3.75),
77 MakeDoubleChecker<double>())
78 .AddAttribute("ExponentialCapacity",
79 "(Q_exp) Cell Capacity at the end of the exponential zone (Ah).",
80 DoubleValue(0.39),
82 MakeDoubleChecker<double>())
83 .AddAttribute("InternalResistance",
84 "(R) Internal resistance of the cell (Ohms)",
85 DoubleValue(0.083),
87 MakeDoubleChecker<double>())
88 .AddAttribute("TypicalDischargeCurrent",
89 "Typical discharge current used in manufacters datasheets (A)",
90 DoubleValue(2.33),
92 MakeDoubleChecker<double>())
93 .AddAttribute("CutoffVoltage",
94 "The voltage where the battery is considered depleted (V).",
95 DoubleValue(3.3),
97 MakeDoubleChecker<double>())
98 .AddAttribute("PeriodicEnergyUpdateInterval",
99 "Time between two consecutive periodic energy updates.",
100 TimeValue(Seconds(1.0)),
104 .AddAttribute("BatteryType",
105 "Indicates the battery type used by the model",
107 MakeEnumAccessor<GenericBatteryType>(&GenericBatteryModel::m_batteryType),
109 "LION_LIPO",
110 NIMH_NICD,
111 "NIMH_NICD",
112 LEADACID,
113 "LEADACID"))
114 .AddTraceSource("RemainingEnergy",
115 "Remaining energy of generic battery",
117 "ns3::TracedValueCallback::Double");
118 return tid;
119}
120
122 : m_drainedCapacity(0),
123 m_currentFiltered(0),
124 m_entn(0),
125 m_expZone(0),
126 m_lastUpdateTime(Seconds(0.0))
127{
128 NS_LOG_FUNCTION(this);
129}
130
132{
133 NS_LOG_FUNCTION(this);
134}
135
136double
138{
139 double initialEnergy = m_qMax * m_vFull * 3600;
140 return initialEnergy;
141}
142
143double
145{
146 return m_supplyVoltageV;
147}
148
149void
151{
152 NS_LOG_FUNCTION(this << interval);
153 m_energyUpdateInterval = interval;
154}
155
156void
158{
159 NS_ASSERT(drainedCapacity >= 0 && drainedCapacity < m_qMax);
160 m_drainedCapacity = drainedCapacity;
161}
162
163double
165{
166 return m_drainedCapacity;
167}
168
169double
171{
172 double soc = 100 * (1 - m_drainedCapacity / m_qMax);
173 return soc;
174}
175
176Time
178{
179 NS_LOG_FUNCTION(this);
181}
182
183double
185{
186 NS_LOG_FUNCTION(this);
188 return m_remainingEnergyJ;
189}
190
191double
193{
194 NS_LOG_FUNCTION(this);
195 return GetStateOfCharge();
196}
197
198void
200{
201 NS_LOG_FUNCTION(this);
202
203 // do not update if simulation has finished
205 {
206 return;
207 }
208
210
212
214
216 {
217 // check if battery is depleted
219 }
220 else if (m_supplyVoltageV >= m_vFull)
221 {
222 // check if battery has reached full charge
224 // TODO: Should battery charging be stopped if full voltage is reached?
225 // or should it be allowed to continue charging (overcharge)?
226 }
227
230}
231
232void
234{
235 NS_LOG_FUNCTION(this);
236}
237
238void
240{
241 NS_LOG_FUNCTION(this);
243}
244
245void
247{
248 NS_LOG_FUNCTION(this);
249 // notify DeviceEnergyModel objects, all "usable" energy has been depleted
250 // (cutoff voltage was reached)
252}
253
254void
256{
257 NS_LOG_FUNCTION(this);
258 // notify DeviceEnergyModel objects, the battery has reached its full energy potential.
259 // (full voltage was reached)
261}
262
263void
265{
266 NS_LOG_FUNCTION(this);
267
268 double totalCurrentA = CalculateTotalCurrent();
269
271
273
274 // Calculate i* (current step response)
275 Time batteryResponseConstant = Seconds(30);
276
277 double responseTime = (Simulator::Now() / batteryResponseConstant).GetDouble();
278 m_currentFiltered = totalCurrentA * (1 - 1 / (std::exp(responseTime)));
279 // TODO: the time in the responseTime should be a time taken since the last *battery current*
280 // change, in the testing the battery current is only changed at the beginning of the
281 // simulation therefore, the simulation time can be used. However this must be changed to
282 // a time counter to allow this value to reset in the middle of the simulation when the
283 // battery current changes.
284
285 m_drainedCapacity += (totalCurrentA * m_energyUpdateLapseTime).GetHours();
286
287 if (totalCurrentA < 0)
288 {
289 // Charge current (Considered as "Negative" i)
290 m_supplyVoltageV = GetChargeVoltage(totalCurrentA);
291 }
292 else
293 {
294 // Discharge current (Considered as "Positive" i)
295 m_supplyVoltageV = GetVoltage(totalCurrentA);
296 }
297}
298
299double
301{
302 // integral of i over time drained capacity in Ah
303 double it = m_drainedCapacity;
304
305 // empirical factors
306 double A = m_vFull - m_vExp;
307 double B = 3 / m_qExp;
308
309 // voltage constant
311
312 // voltage of exponential zone when battery is fully charged
313 double expZoneFull = A * std::exp(-B * m_qNom);
314
315 // Obtain the voltage|resistance polarization constant
316 double K = (E0 - m_vNom - (m_internalResistance * m_typicalCurrent) + expZoneFull) /
318
319 double V = 0;
320 double polResistance = 0;
321 double polVoltage = 0;
322
324 { // For LiOn & LiPo batteries
325
326 // Calculate exponential zone voltage
327 m_expZone = A * std::exp(-B * it);
328
329 polResistance = K * m_qMax / (it + 0.1 * m_qMax);
330 polVoltage = K * m_qMax / (m_qMax - it);
331 V = E0 - (m_internalResistance * i) - (polResistance * m_currentFiltered) -
332 (polVoltage * it) + m_expZone;
333 }
334 else
335 {
336 // Calculate exponential zone voltage
337
338 if (m_expZone == 0)
339 {
340 m_expZone = A * std::exp(-B * it);
341 }
342 double entnPrime = m_entn;
343 double expZonePrime = m_expZone;
344 m_entn = B * std::abs(i) * (-expZonePrime + A);
345 m_expZone = expZonePrime + (m_energyUpdateLapseTime * entnPrime).GetHours();
346
348 { // For NiMH and NiCd batteries
349 polResistance = K * m_qMax / (std::abs(it) + 0.1 * m_qMax);
350 }
351 else if (m_batteryType == LEADACID)
352 { // For Lead acid batteries
353 polResistance = K * m_qMax / (it + 0.1 * m_qMax);
354 }
355
356 polVoltage = K * m_qMax / (m_qMax - it);
357
358 V = E0 - (m_internalResistance * i) - (polResistance * m_currentFiltered) -
359 (polVoltage * it) + m_expZone;
360 }
361
362 // Energy in Joules = RemainingCapacity * Voltage * Seconds in an Hour
363 m_remainingEnergyJ = (m_qMax - it) * V * 3600;
364
365 NS_LOG_DEBUG("* CHARGE *| " << Simulator::Now().As(Time::S) << "| i " << i << " | it " << it
366 << "| E0 " << E0 << " | polRes " << polResistance << " | polVol "
367 << polVoltage << "| B " << B << " | ExpZone " << m_expZone
368 << " | A " << A << "| K " << K << "| i* " << m_currentFiltered
369 << " | V " << V << " | rmnEnergy " << m_remainingEnergyJ
370 << "J | SoC " << GetStateOfCharge() << "% ");
371
372 return V;
373}
374
375double
377{
378 NS_LOG_FUNCTION(this << i);
379
380 // integral of i in dt, drained capacity in Ah
381 double it = m_drainedCapacity;
382
383 // empirical factors
384 double A = m_vFull - m_vExp;
385
386 double B = 3 / m_qExp;
387
388 // constant voltage
390
391 // voltage of exponential zone when battery is fully charged
392 double expZoneFull = A * std::exp(-B * m_qNom);
393
394 // Obtain the voltage|resistance polarization constant
395 double K = (E0 - m_vNom - (m_internalResistance * m_typicalCurrent) + expZoneFull) /
397
398 double V = 0;
399 double polResistance = K * (m_qMax / (m_qMax - it));
400 double polVoltage = polResistance;
401
402 // Calculate exponential zone voltage according to the battery type
404 {
405 m_expZone = A * exp(-B * it);
406 }
407 else
408 {
410 if (m_expZone == 0)
411 {
412 m_expZone = A * exp(-B * it);
413 }
414
415 double entnPrime = m_entn;
416 double expZonePrime = m_expZone;
417
418 m_entn = B * std::abs(i) * (-expZonePrime);
419 m_expZone = expZonePrime + (m_energyUpdateLapseTime * entnPrime).GetHours();
420 }
421
422 V = E0 - (m_internalResistance * i) - (polResistance * m_currentFiltered) - (polVoltage * it) +
423 m_expZone;
424
425 // EnergyJ = RemainingCapacity * Voltage * Seconds in an Hour
426 m_remainingEnergyJ = (m_qMax - it) * V * 3600;
427
428 NS_LOG_DEBUG("* DISCHARGE *| " << Simulator::Now().As(Time::S) << "| i " << i << " | it " << it
429 << " | A " << A << " | B " << B << " | ExpZone " << m_expZone
430 << " | V " << V << " | rmnEnergy " << m_remainingEnergyJ
431 << "J | SoC " << GetStateOfCharge() << "% "
432 << "\n"
433 << " | K " << K << " | E0 " << E0);
434
435 return V;
436}
437
438} // namespace ns3
This class can be used to hold variables of floating point type such as 'double' or 'float'.
Definition: double.h:42
Introspection did not find any typical Config paths.
Definition: energy-source.h:87
double CalculateTotalCurrent()
void NotifyEnergyRecharged()
This function notifies all DeviceEnergyModel of energy recharged event.
void BreakDeviceEnergyModelRefCycle()
This function is called to break reference cycle between EnergySource and DeviceEnergyModel.
void NotifyEnergyDrained()
This function notifies all DeviceEnergyModel of energy depletion event.
Hold variables of type enum.
Definition: enum.h:62
void Cancel()
This method is syntactic sugar for the ns3::Simulator::Cancel method.
Definition: event-id.cc:55
A generic battery model for Li-Ion, NiCd, NiMh and Lead acid batteries.
double m_entn
The previous value of the exponential zone in NiMh,NiCd and LeadAcid.
double m_expZone
Voltage value of the exponential zone.
void BatteryChargedEvent()
Handles the battery reaching its full voltage.
double GetEnergyFraction() override
Implements GetEnergyFraction.
Time m_lastUpdateTime
Last update time.
double m_lowBatteryTh
Low battery threshold, as a fraction of the initial energy.
double m_typicalCurrent
Typical discharge current used to fit the curves.
double GetStateOfCharge() const
Calculates an estimate of the State of Charge (SoC).
double GetDrainedCapacity() const
Obtain the amount of drained capacity from the battery based on the integral of the current over time...
Time m_energyUpdateInterval
Energy update interval.
void UpdateEnergySource() override
Implements UpdateEnergySource.
double m_currentFiltered
The step response (a.k.a.
double m_qMax
The maximum capacity of the battery, in Ah.
void CalculateRemainingEnergy()
Calculates remaining energy.
double GetVoltage(double current)
Get the battery voltage in function of the discharge current.
void DoInitialize() override
Initialize() implementation.
double m_vExp
Battery voltage at the end of the exponential zone, in Volts.
TracedValue< double > m_remainingEnergyJ
Remaining energy, in Joules.
double GetSupplyVoltage() const override
Implements GetSupplyVoltage.
double m_vNom
Nominal voltage of the battery, in Volts.
EventId m_energyUpdateEvent
Energy update event.
double GetChargeVoltage(double current)
Obtain the battery voltage as a result of a charge current.
double GetRemainingEnergy() override
Implements GetRemainingEnergy.
double m_internalResistance
Internal resistance of the battery, in Ohms.
void SetEnergyUpdateInterval(Time interval)
This function sets the interval between each energy update.
void DoDispose() override
All child's implementation must call BreakDeviceEnergyModelRefCycle to ensure reference cycles to Dev...
GenericBatteryType m_batteryType
Indicates the battery type used by the model.
double m_qNom
Battery capacity at the end of the nominal zone, in Ah.
static TypeId GetTypeId()
Get the type ID.
double m_vFull
Initial voltage of the battery, in Volts.
double m_drainedCapacity
Capacity drained from the battery, in Ah.
Time m_energyUpdateLapseTime
The lapse of time between the last battery energy update and the current time.
double m_cutoffVoltage
The threshold voltage where the battery is considered depleted.
void SetDrainedCapacity(double drainedCapacity)
This function is used to change the initial capacity in the battery.
double m_qExp
Capacity value at the end of the exponential zone, in Ah.
void BatteryDepletedEvent()
Handles the battery reaching its cutoff voltage.
double GetInitialEnergy() const override
Implements GetInitialEnergy.
double m_supplyVoltageV
Actual voltage of the battery.
static EventId Schedule(const Time &delay, FUNC f, Ts &&... args)
Schedule an event to expire after delay.
Definition: simulator.h:571
static bool IsFinished()
Check if the simulation should finish.
Definition: simulator.cc:171
static Time Now()
Return the current simulation virtual time.
Definition: simulator.cc:208
Simulation virtual time values and global simulation resolution.
Definition: nstime.h:105
double GetSeconds() const
Get an approximation of the time stored in this instance in the indicated unit.
Definition: nstime.h:403
@ S
second
Definition: nstime.h:116
AttributeValue implementation for Time.
Definition: nstime.h:1406
a unique identifier for an interface.
Definition: type-id.h:59
TypeId SetParent(TypeId tid)
Set the parent TypeId.
Definition: type-id.cc:932
#define NS_ASSERT(condition)
At runtime, in debugging builds, if this condition is not true, the program prints the source file,...
Definition: assert.h:66
Ptr< const AttributeAccessor > MakeDoubleAccessor(T1 a1)
Definition: double.h:43
Ptr< const AttributeChecker > MakeTimeChecker()
Helper to make an unbounded Time checker.
Definition: nstime.h:1427
Ptr< const AttributeAccessor > MakeTimeAccessor(T1 a1)
Definition: nstime.h:1407
@ NIMH_NICD
Nickel-metal hydride and Nickel cadmium batteries.
@ LION_LIPO
Lithium-ion and Lithium-polymer batteries.
@ LEADACID
Lead Acid Batteries.
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
Definition: log.h:202
#define NS_LOG_DEBUG(msg)
Use NS_LOG to output a message of level LOG_DEBUG.
Definition: log.h:268
#define NS_LOG_FUNCTION(parameters)
If log level LOG_FUNCTION is enabled, this macro will output all input parameters separated by ",...
#define NS_OBJECT_ENSURE_REGISTERED(type)
Register an Object subclass with the TypeId system.
Definition: object-base.h:46
Time Seconds(double value)
Construct a Time in the indicated unit.
Definition: nstime.h:1319
Ptr< const TraceSourceAccessor > MakeTraceSourceAccessor(T a)
Create a TraceSourceAccessor which will control access to the underlying trace source.
Every class exported by the ns3 library is enclosed in the ns3 namespace.
Ptr< const AttributeChecker > MakeEnumChecker(T v, std::string n, Ts... args)
Make an EnumChecker pre-configured with a set of allowed values by name.
Definition: enum.h:189