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 * SPDX-License-Identifier: GPL-2.0-only
7 *
8 * Author: Andrea Sacco <andrea.sacco85@gmail.com>
9 * Alberto Gallegos Ramonet <alramonet@is.tokushima-u.ac.jp>
10 */
11
13
14#include <ns3/assert.h>
15#include <ns3/double.h>
16#include <ns3/log.h>
17#include <ns3/simulator.h>
18#include <ns3/trace-source-accessor.h>
19
20#include <cmath>
21
22namespace ns3
23{
24namespace energy
25{
26
27NS_LOG_COMPONENT_DEFINE("GenericBatteryModel");
28NS_OBJECT_ENSURE_REGISTERED(GenericBatteryModel);
29
30TypeId
32{
33 static TypeId tid =
34 TypeId("ns3::energy::GenericBatteryModel")
35 .AddDeprecatedName("ns3::GenericBatteryModel")
37 .SetGroupName("Energy")
38 .AddConstructor<GenericBatteryModel>()
39 .AddAttribute("LowBatteryThreshold",
40 "Low battery threshold for generic battery model.",
41 DoubleValue(0.10), // 0.10 as a fraction of the initial energy
44 .AddAttribute("FullVoltage",
45 "(Q_full) The voltage of the cell when fully charged (V).",
46 DoubleValue(4.18),
49 .AddAttribute("MaxCapacity",
50 "(Q) The maximum capacity of the cell (Ah).",
51 DoubleValue(2.45),
54 .AddAttribute("NominalVoltage",
55 "(V_nom) Nominal voltage of the cell (V).",
56 DoubleValue(3.59),
59 .AddAttribute("NominalCapacity",
60 "(Q_nom) Cell capacity at the end of the nominal zone (Ah)",
61 DoubleValue(1.3),
64 .AddAttribute("ExponentialVoltage",
65 "(V_exp) Cell voltage at the end of the exponential zone (V).",
66 DoubleValue(3.75),
69 .AddAttribute("ExponentialCapacity",
70 "(Q_exp) Cell Capacity at the end of the exponential zone (Ah).",
71 DoubleValue(0.39),
74 .AddAttribute("InternalResistance",
75 "(R) Internal resistance of the cell (Ohms)",
76 DoubleValue(0.083),
79 .AddAttribute("TypicalDischargeCurrent",
80 "Typical discharge current used in manufacturers datasheets (A)",
81 DoubleValue(2.33),
84 .AddAttribute("CutoffVoltage",
85 "The voltage where the battery is considered depleted (V).",
86 DoubleValue(3.3),
89 .AddAttribute("PeriodicEnergyUpdateInterval",
90 "Time between two consecutive periodic energy updates.",
91 TimeValue(Seconds(1.0)),
95 .AddAttribute("BatteryType",
96 "Indicates the battery type used by the model",
100 "LION_LIPO",
101 NIMH_NICD,
102 "NIMH_NICD",
103 LEADACID,
104 "LEADACID"))
105 .AddTraceSource("RemainingEnergy",
106 "Remaining energy of generic battery",
108 "ns3::TracedValueCallback::Double");
109 return tid;
110}
111
113 : m_drainedCapacity(0),
114 m_currentFiltered(0),
115 m_entn(0),
116 m_expZone(0),
117 m_lastUpdateTime(Seconds(0.0))
118{
119 NS_LOG_FUNCTION(this);
120}
121
126
127double
129{
130 double initialEnergy = m_qMax * m_vFull * 3600;
131 return initialEnergy;
132}
133
134double
139
140void
142{
143 NS_LOG_FUNCTION(this << interval);
144 m_energyUpdateInterval = interval;
145}
146
147void
149{
150 NS_ASSERT(drainedCapacity >= 0 && drainedCapacity < m_qMax);
151 m_drainedCapacity = drainedCapacity;
152}
153
154double
159
160double
162{
163 double soc = 100 * (1 - m_drainedCapacity / m_qMax);
164 return soc;
165}
166
167Time
173
174double
181
182double
188
189void
191{
192 NS_LOG_FUNCTION(this);
193
194 // do not update if simulation has finished
196 {
197 return;
198 }
199
201
203
205
207 {
208 // check if battery is depleted
210 }
211 else if (m_supplyVoltageV >= m_vFull)
212 {
213 // check if battery has reached full charge
215 // TODO: Should battery charging be stopped if full voltage is reached?
216 // or should it be allowed to continue charging (overcharge)?
217 }
218
221}
222
223void
228
229void
235
236void
238{
239 NS_LOG_FUNCTION(this);
240 // notify DeviceEnergyModel objects, all "usable" energy has been depleted
241 // (cutoff voltage was reached)
243}
244
245void
247{
248 NS_LOG_FUNCTION(this);
249 // notify DeviceEnergyModel objects, the battery has reached its full energy potential.
250 // (full voltage was reached)
252}
253
254void
256{
257 NS_LOG_FUNCTION(this);
258
259 double totalCurrentA = CalculateTotalCurrent();
260
262
264
265 // Calculate i* (current step response)
266 Time batteryResponseConstant = Seconds(30);
267
268 double responseTime = (Simulator::Now() / batteryResponseConstant).GetDouble();
269 m_currentFiltered = totalCurrentA * (1 - 1 / (std::exp(responseTime)));
270 // TODO: the time in the responseTime should be a time taken since the last *battery current*
271 // change, in the testing the battery current is only changed at the beginning of the
272 // simulation therefore, the simulation time can be used. However this must be changed to
273 // a time counter to allow this value to reset in the middle of the simulation when the
274 // battery current changes.
275
276 m_drainedCapacity += (totalCurrentA * m_energyUpdateLapseTime).GetHours();
277
278 if (totalCurrentA < 0)
279 {
280 // Charge current (Considered as "Negative" i)
281 m_supplyVoltageV = GetChargeVoltage(totalCurrentA);
282 }
283 else
284 {
285 // Discharge current (Considered as "Positive" i)
286 m_supplyVoltageV = GetVoltage(totalCurrentA);
287 }
288}
289
290double
292{
293 // integral of i over time drained capacity in Ah
294 double it = m_drainedCapacity;
295
296 // empirical factors
297 double A = m_vFull - m_vExp;
298 double B = 3 / m_qExp;
299
300 // voltage constant
302
303 // voltage of exponential zone when battery is fully charged
304 double expZoneFull = A * std::exp(-B * m_qNom);
305
306 // Obtain the voltage|resistance polarization constant
307 double K = (E0 - m_vNom - (m_internalResistance * m_typicalCurrent) + expZoneFull) /
309
310 double V = 0;
311 double polResistance = 0;
312 double polVoltage = 0;
313
315 { // For LiOn & LiPo batteries
316
317 // Calculate exponential zone voltage
318 m_expZone = A * std::exp(-B * it);
319
320 polResistance = K * m_qMax / (it + 0.1 * m_qMax);
321 polVoltage = K * m_qMax / (m_qMax - it);
322 V = E0 - (m_internalResistance * i) - (polResistance * m_currentFiltered) -
323 (polVoltage * it) + m_expZone;
324 }
325 else
326 {
327 // Calculate exponential zone voltage
328
329 if (m_expZone == 0)
330 {
331 m_expZone = A * std::exp(-B * it);
332 }
333 double entnPrime = m_entn;
334 double expZonePrime = m_expZone;
335 m_entn = B * std::abs(i) * (-expZonePrime + A);
336 m_expZone = expZonePrime + (m_energyUpdateLapseTime * entnPrime).GetHours();
337
339 { // For NiMH and NiCd batteries
340 polResistance = K * m_qMax / (std::abs(it) + 0.1 * m_qMax);
341 }
342 else if (m_batteryType == LEADACID)
343 { // For Lead acid batteries
344 polResistance = K * m_qMax / (it + 0.1 * m_qMax);
345 }
346
347 polVoltage = K * m_qMax / (m_qMax - it);
348
349 V = E0 - (m_internalResistance * i) - (polResistance * m_currentFiltered) -
350 (polVoltage * it) + m_expZone;
351 }
352
353 // Energy in Joules = RemainingCapacity * Voltage * Seconds in an Hour
354 m_remainingEnergyJ = (m_qMax - it) * V * 3600;
355
356 NS_LOG_DEBUG("* CHARGE *| " << Simulator::Now().As(Time::S) << "| i " << i << " | it " << it
357 << "| E0 " << E0 << " | polRes " << polResistance << " | polVol "
358 << polVoltage << "| B " << B << " | ExpZone " << m_expZone
359 << " | A " << A << "| K " << K << "| i* " << m_currentFiltered
360 << " | V " << V << " | rmnEnergy " << m_remainingEnergyJ
361 << "J | SoC " << GetStateOfCharge() << "% ");
362
363 return V;
364}
365
366double
368{
369 NS_LOG_FUNCTION(this << i);
370
371 // integral of i in dt, drained capacity in Ah
372 double it = m_drainedCapacity;
373
374 // empirical factors
375 double A = m_vFull - m_vExp;
376
377 double B = 3 / m_qExp;
378
379 // constant voltage
381
382 // voltage of exponential zone when battery is fully charged
383 double expZoneFull = A * std::exp(-B * m_qNom);
384
385 // Obtain the voltage|resistance polarization constant
386 double K = (E0 - m_vNom - (m_internalResistance * m_typicalCurrent) + expZoneFull) /
388
389 double V = 0;
390 double polResistance = K * (m_qMax / (m_qMax - it));
391 double polVoltage = polResistance;
392
393 // Calculate exponential zone voltage according to the battery type
395 {
396 m_expZone = A * exp(-B * it);
397 }
398 else
399 {
401 if (m_expZone == 0)
402 {
403 m_expZone = A * exp(-B * it);
404 }
405
406 double entnPrime = m_entn;
407 double expZonePrime = m_expZone;
408
409 m_entn = B * std::abs(i) * (-expZonePrime);
410 m_expZone = expZonePrime + (m_energyUpdateLapseTime * entnPrime).GetHours();
411 }
412
413 V = E0 - (m_internalResistance * i) - (polResistance * m_currentFiltered) - (polVoltage * it) +
414 m_expZone;
415
416 // EnergyJ = RemainingCapacity * Voltage * Seconds in an Hour
417 m_remainingEnergyJ = (m_qMax - it) * V * 3600;
418
419 NS_LOG_DEBUG("* DISCHARGE *| " << Simulator::Now().As(Time::S) << "| i " << i << " | it " << it
420 << " | A " << A << " | B " << B << " | ExpZone " << m_expZone
421 << " | V " << V << " | rmnEnergy " << m_remainingEnergyJ
422 << "J | SoC " << GetStateOfCharge() << "% "
423 << "\n"
424 << " | K " << K << " | E0 " << E0);
425
426 return V;
427}
428
429} // namespace energy
430} // namespace ns3
This class can be used to hold variables of floating point type such as 'double' or 'float'.
Definition double.h:31
Hold variables of type enum.
Definition enum.h:52
void Cancel()
This method is syntactic sugar for the ns3::Simulator::Cancel method.
Definition event-id.cc:44
static EventId Schedule(const Time &delay, FUNC f, Ts &&... args)
Schedule an event to expire after delay.
Definition simulator.h:560
static bool IsFinished()
Check if the simulation should finish.
Definition simulator.cc:160
static Time Now()
Return the current simulation virtual time.
Definition simulator.cc:197
Simulation virtual time values and global simulation resolution.
Definition nstime.h:94
double GetSeconds() const
Get an approximation of the time stored in this instance in the indicated unit.
Definition nstime.h:392
@ S
second
Definition nstime.h:105
a unique identifier for an interface.
Definition type-id.h:48
TypeId AddDeprecatedName(const std::string &name)
Add an deprecated name for a TypeId.
Definition type-id.cc:862
TypeId SetParent(TypeId tid)
Set the parent TypeId.
Definition type-id.cc:1001
Energy source base class.
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.
void NotifyEnergyRecharged()
This function notifies all DeviceEnergyModel of energy recharged event.
A generic battery model for Li-Ion, NiCd, NiMh and Lead acid batteries.
void DoDispose() override
All child's implementation must call BreakDeviceEnergyModelRefCycle to ensure reference cycles to Dev...
double m_expZone
Voltage value of the exponential zone.
double m_cutoffVoltage
The threshold voltage where the battery is considered depleted.
double GetChargeVoltage(double current)
Obtain the battery voltage as a result of a charge current.
static TypeId GetTypeId()
Get the type ID.
void BatteryChargedEvent()
Handles the battery reaching its full voltage.
double GetEnergyFraction() override
Implements GetEnergyFraction.
EventId m_energyUpdateEvent
Energy update event.
double m_lowBatteryTh
Low battery threshold, as a fraction of the initial energy.
double m_currentFiltered
The step response (a.k.a.
Time m_energyUpdateLapseTime
The lapse of time between the last battery energy update and the current time.
double m_qMax
The maximum capacity of the battery, in Ah.
double m_supplyVoltageV
Actual voltage of the battery.
double m_qNom
Battery capacity at the end of the nominal zone, in Ah.
double m_drainedCapacity
Capacity drained from the battery, in Ah.
double m_vFull
Initial voltage of the battery, in Volts.
double m_entn
The previous value of the exponential zone in NiMh,NiCd and LeadAcid.
double m_qExp
Capacity value at the end of the exponential zone, in Ah.
void SetDrainedCapacity(double drainedCapacity)
This function is used to change the initial capacity in the battery.
double GetSupplyVoltage() const override
Implements GetSupplyVoltage.
TracedValue< double > m_remainingEnergyJ
Remaining energy, in Joules.
double GetRemainingEnergy() override
Implements GetRemainingEnergy.
void BatteryDepletedEvent()
Handles the battery reaching its cutoff voltage.
double GetVoltage(double current)
Get the battery voltage in function of the discharge current.
double m_typicalCurrent
Typical discharge current used to fit the curves.
GenericBatteryType m_batteryType
Indicates the battery type used by the model.
void DoInitialize() override
Initialize() implementation.
double GetStateOfCharge() const
Calculates an estimate of the State of Charge (SoC).
double GetInitialEnergy() const override
Implements GetInitialEnergy.
double m_vNom
Nominal voltage of the battery, in Volts.
double GetDrainedCapacity() const
Obtain the amount of drained capacity from the battery based on the integral of the current over time...
void CalculateRemainingEnergy()
Calculates remaining energy.
void UpdateEnergySource() override
Implements UpdateEnergySource.
double m_vExp
Battery voltage at the end of the exponential zone, in Volts.
void SetEnergyUpdateInterval(Time interval)
This function sets the interval between each energy update.
double m_internalResistance
Internal resistance of the battery, in Ohms.
Time m_energyUpdateInterval
Energy update interval.
#define NS_ASSERT(condition)
At runtime, in debugging builds, if this condition is not true, the program prints the source file,...
Definition assert.h:55
@ LEADACID
Lead Acid Batteries.
@ NIMH_NICD
Nickel-metal hydride and Nickel cadmium batteries.
@ LION_LIPO
Lithium-ion and Lithium-polymer batteries.
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
Definition log.h:191
#define NS_LOG_DEBUG(msg)
Use NS_LOG to output a message of level LOG_DEBUG.
Definition log.h:257
#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:35
Time Seconds(double value)
Construct a Time in the indicated unit.
Definition nstime.h:1308
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 AttributeAccessor > MakeTimeAccessor(T1 a1)
Definition nstime.h:1396
Ptr< const AttributeChecker > MakeDoubleChecker()
Definition double.h:82
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:179
Ptr< const AttributeAccessor > MakeDoubleAccessor(T1 a1)
Definition double.h:32
Ptr< const AttributeAccessor > MakeEnumAccessor(T1 a1)
Definition enum.h:221
Ptr< const AttributeChecker > MakeTimeChecker()
Helper to make an unbounded Time checker.
Definition nstime.h:1416