A Discrete-Event Network Simulator
API
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
li-ion-energy-source.cc
1 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2 /*
3  * Copyright (c) 2010 Andrea Sacco
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License version 2 as
7  * published by the Free Software Foundation;
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software
16  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17  *
18  * Author: Andrea Sacco <andrea.sacco85@gmail.com>
19  */
20 
21 #include "li-ion-energy-source.h"
22 #include "ns3/log.h"
23 #include "ns3/assert.h"
24 #include "ns3/double.h"
25 #include "ns3/trace-source-accessor.h"
26 #include "ns3/simulator.h"
27 
28 #include <cmath>
29 
30 NS_LOG_COMPONENT_DEFINE ("LiIonEnergySource");
31 
32 namespace ns3 {
33 
34 NS_OBJECT_ENSURE_REGISTERED (LiIonEnergySource);
35 
36 TypeId
37 LiIonEnergySource::GetTypeId (void)
38 {
39  static TypeId tid = TypeId ("ns3::LiIonEnergySource")
40  .SetParent<EnergySource> ()
41  .AddConstructor<LiIonEnergySource> ()
42  .AddAttribute ("LiIonEnergySourceInitialEnergyJ",
43  "Initial energy stored in basic energy source.",
44  DoubleValue (31752.0), // in Joules
45  MakeDoubleAccessor (&LiIonEnergySource::SetInitialEnergy,
47  MakeDoubleChecker<double> ())
48  .AddAttribute ("InitialCellVoltage",
49  "Initial (maximum) voltage of the cell (fully charged).",
50  DoubleValue (4.05), // in Volts
51  MakeDoubleAccessor (&LiIonEnergySource::SetInitialSupplyVoltage,
53  MakeDoubleChecker<double> ())
54  .AddAttribute ("NominalCellVoltage",
55  "Nominal voltage of the cell.",
56  DoubleValue (3.6), // in Volts
57  MakeDoubleAccessor (&LiIonEnergySource::m_eNom),
58  MakeDoubleChecker<double> ())
59  .AddAttribute ("ExpCellVoltage",
60  "Cell voltage at the end of the exponential zone.",
61  DoubleValue (3.6), // in Volts
62  MakeDoubleAccessor (&LiIonEnergySource::m_eExp),
63  MakeDoubleChecker<double> ())
64  .AddAttribute ("RatedCapacity",
65  "Rated capacity of the cell.",
66  DoubleValue (2.45), // in Ah
67  MakeDoubleAccessor (&LiIonEnergySource::m_qRated),
68  MakeDoubleChecker<double> ())
69  .AddAttribute ("NomCapacity",
70  "Cell capacity at the end of the nominal zone.",
71  DoubleValue (1.1), // in Ah
72  MakeDoubleAccessor (&LiIonEnergySource::m_qNom),
73  MakeDoubleChecker<double> ())
74  .AddAttribute ("ExpCapacity",
75  "Cell Capacity at the end of the exponential zone.",
76  DoubleValue (1.2), // in Ah
77  MakeDoubleAccessor (&LiIonEnergySource::m_qExp),
78  MakeDoubleChecker<double> ())
79  .AddAttribute ("InternalResistance",
80  "Internal resistance of the cell",
81  DoubleValue (0.083), // in Ohms
82  MakeDoubleAccessor (&LiIonEnergySource::m_internalResistance),
83  MakeDoubleChecker<double> ())
84  .AddAttribute ("TypCurrent",
85  "Typical discharge current used to fit the curves",
86  DoubleValue (2.33), // in A
87  MakeDoubleAccessor (&LiIonEnergySource::m_typCurrent),
88  MakeDoubleChecker<double> ())
89  .AddAttribute ("ThresholdVoltage",
90  "Minimum threshold voltage to consider the battery depleted.",
91  DoubleValue (3.3), // in Volts
92  MakeDoubleAccessor (&LiIonEnergySource::m_minVoltTh),
93  MakeDoubleChecker<double> ())
94  .AddAttribute ("PeriodicEnergyUpdateInterval",
95  "Time between two consecutive periodic energy updates.",
96  TimeValue (Seconds (1.0)),
99  MakeTimeChecker ())
100  .AddTraceSource ("RemainingEnergy",
101  "Remaining energy at BasicEnergySource.",
102  MakeTraceSourceAccessor (&LiIonEnergySource::m_remainingEnergyJ))
103  ;
104  return tid;
105 }
106 
107 LiIonEnergySource::LiIonEnergySource ()
108  : m_drainedCapacity (0.0),
109  m_lastUpdateTime (Seconds (0.0))
110 {
111  NS_LOG_FUNCTION (this);
112 }
113 
114 LiIonEnergySource::~LiIonEnergySource ()
115 {
116  NS_LOG_FUNCTION (this);
117 }
118 
119 void
120 LiIonEnergySource::SetInitialEnergy (double initialEnergyJ)
121 {
122  NS_LOG_FUNCTION (this << initialEnergyJ);
123  NS_ASSERT (initialEnergyJ >= 0);
124  m_initialEnergyJ = initialEnergyJ;
125  // set remaining energy to be initial energy
126  m_remainingEnergyJ = m_initialEnergyJ;
127 }
128 
129 double
131 {
132  NS_LOG_FUNCTION (this);
133  return m_initialEnergyJ;
134 }
135 
136 void
138 {
139  NS_LOG_FUNCTION (this << supplyVoltageV);
140  m_eFull = supplyVoltageV;
141  m_supplyVoltageV = supplyVoltageV;
142 }
143 
144 double
146 {
147  NS_LOG_FUNCTION (this);
148  return m_supplyVoltageV;
149 }
150 
151 void
153 {
154  NS_LOG_FUNCTION (this << interval);
155  m_energyUpdateInterval = interval;
156 }
157 
158 Time
160 {
161  NS_LOG_FUNCTION (this);
162  return m_energyUpdateInterval;
163 }
164 
165 double
167 {
168  NS_LOG_FUNCTION (this);
169  // update energy source to get the latest remaining energy.
171  return m_remainingEnergyJ;
172 }
173 
174 double
176 {
177  NS_LOG_FUNCTION (this);
178  // update energy source to get the latest remaining energy.
180  return m_remainingEnergyJ / m_initialEnergyJ;
181 }
182 
183 void
185 {
186  NS_LOG_FUNCTION (this << energyJ);
187  NS_ASSERT (energyJ >= 0);
188  m_remainingEnergyJ -= energyJ;
189 
190  // check if remaining energy is 0
191  if (m_supplyVoltageV <= m_minVoltTh)
192  {
194  }
195 }
196 
197 void
199 {
200  NS_LOG_FUNCTION (this << energyJ);
201  NS_ASSERT (energyJ >= 0);
202  m_remainingEnergyJ += energyJ;
203 }
204 
205 void
207 {
208  NS_LOG_FUNCTION (this);
209  NS_LOG_DEBUG ("LiIonEnergySource:Updating remaining energy at node #" <<
210  GetNode ()->GetId ());
211 
212  // do not update if simulation has finished
213  if (Simulator::IsFinished ())
214  {
215  return;
216  }
217 
218  m_energyUpdateEvent.Cancel ();
219 
221 
222  if (m_remainingEnergyJ <= 0)
223  {
225  return; // stop periodic update
226  }
227 
228  m_lastUpdateTime = Simulator::Now ();
229 
230  m_energyUpdateEvent = Simulator::Schedule (m_energyUpdateInterval,
232  this);
233 }
234 
235 /*
236  * Private functions start here.
237  */
238 void
240 {
241  NS_LOG_FUNCTION (this);
242  UpdateEnergySource (); // start periodic update
243 }
244 
245 void
247 {
248  NS_LOG_FUNCTION (this);
249  // calculate remaining energy at the end of simulation
251  BreakDeviceEnergyModelRefCycle (); // break reference cycle
252 }
253 
254 
255 void
257 {
258  NS_LOG_FUNCTION (this);
259  NS_LOG_DEBUG ("LiIonEnergySource:Energy depleted at node #" <<
260  GetNode ()->GetId ());
261  NotifyEnergyDrained (); // notify DeviceEnergyModel objects
262  m_remainingEnergyJ = 0; // energy never goes below 0
263 }
264 
265 
266 void
268 {
269  NS_LOG_FUNCTION (this);
270  double totalCurrentA = CalculateTotalCurrent ();
271  Time duration = Simulator::Now () - m_lastUpdateTime;
272  NS_ASSERT (duration.GetSeconds () >= 0);
273  // energy = current * voltage * time
274  double energyToDecreaseJ = totalCurrentA * m_supplyVoltageV * duration.GetSeconds ();
275  m_remainingEnergyJ -= energyToDecreaseJ;
276  m_drainedCapacity += (totalCurrentA * duration.GetSeconds () / 3600);
277  // update the supply voltage
278  m_supplyVoltageV = GetVoltage (totalCurrentA);
279  NS_LOG_DEBUG ("LiIonEnergySource:Remaining energy = " << m_remainingEnergyJ);
280 }
281 
282 double
284 {
285  NS_LOG_FUNCTION (this << i);
286 
287  // integral of i in dt, drained capacity in Ah
288  double it = m_drainedCapacity;
289 
290  // empirical factors
291  double A = m_eFull - m_eExp;
292  double B = 3 / m_qExp;
293 
294  // slope of the polarization curve
295  double K = std::abs ( (m_eFull - m_eNom + A * (std::exp (-B * m_qNom) - 1)) * (m_qRated - m_qNom) / m_qNom);
296 
297  // constant voltage
298  double E0 = m_eFull + K + m_internalResistance * m_typCurrent - A;
299 
300  double E = E0 - K * m_qRated / (m_qRated - it) + A * std::exp (-B * it);
301 
302  // cell voltage
303  double V = E - m_internalResistance * i;
304 
305  NS_LOG_DEBUG ("Voltage: " << V << " with E: " << E);
306 
307  return V;
308 }
309 
310 } // namespace ns3
keep track of time unit.
Definition: nstime.h:149
#define NS_LOG_FUNCTION(parameters)
Definition: log.h:311
void SetEnergyUpdateInterval(Time interval)
virtual double GetEnergyFraction(void)
Ptr< Node > GetNode(void) const
#define NS_ASSERT(condition)
Definition: assert.h:64
#define NS_LOG_COMPONENT_DEFINE(name)
Definition: log.h:122
virtual void UpdateEnergySource(void)
static EventId Schedule(Time const &time, MEM mem_ptr, OBJ obj)
Definition: simulator.h:820
virtual double GetInitialEnergy(void) const
double GetVoltage(double current) const
virtual double GetRemainingEnergy(void)
void BreakDeviceEnergyModelRefCycle(void)
double GetSeconds(void) const
Definition: nstime.h:262
void SetInitialSupplyVoltage(double supplyVoltageV)
double CalculateTotalCurrent(void)
Ptr< const TraceSourceAccessor > MakeTraceSourceAccessor(T a)
static Time Now(void)
Definition: simulator.cc:179
void NotifyEnergyDrained(void)
Time Seconds(double seconds)
create ns3::Time instances in units of seconds.
Definition: nstime.h:586
Time GetEnergyUpdateInterval(void) const
#define NS_LOG_DEBUG(msg)
Definition: log.h:255
virtual double GetSupplyVoltage(void) const
void Cancel(void)
Definition: event-id.cc:47
virtual void DecreaseRemainingEnergy(double energyJ)
virtual void IncreaseRemainingEnergy(double energyJ)
void SetInitialEnergy(double initialEnergyJ)
static bool IsFinished(void)
Definition: simulator.cc:150