Electrical Power System For The CubeSTAR Nanosatellite
Electrical Power System For The CubeSTAR Nanosatellite
Electrical Power System For The CubeSTAR Nanosatellite
for the
CubeSTAR Nanosatellite
by
MARTIN OREDSSON
Department of Physics
THESIS
for the degree of
MASTER OF SCIENCE
III
IV
Acknowledgments
Mom and Dad, you deserve your own page, but this will have to do: thank you
for your unconditional love, support, and endless supply of Swedish coffee—
they are the fundamental components of this work.
Tore Andrè Bekkeng also deserves a special mention for being a guiding star
throughout the phases of this work. Anything from LATEX, proofreading,
Matlab to PCB design, you’ve always had the answers and the kindness to
share them. I must also acknowledge the Plasma Group and especially Espen
Trondsen who have given me a the best possible conditions to do my thesis
work. This has included unlimited access to their electronics lab and Espen’s
practical wisdom—what a privilege! My friend and fellow student Manual
Lains has also been helpful in absorbing my bad jokes with minimum fuss.
V
VI
Contents
1 Introduction 1
VII
2.4.5 Efficiency . . . . . . . . . . . . . . . . . . . . . . . . . 20
3.1 Objectives . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 29
VIII
3.5.1 Chemistry Specific Properties . . . . . . . . . . . . . . 42
3.6.3 Redundancy . . . . . . . . . . . . . . . . . . . . . . . . 51
4 System Design 55
IX
4.5.1 A Note on Small-signal Loop Response . . . . . . . . . 70
5 PCB Realization 83
5.3.1 Decoupling . . . . . . . . . . . . . . . . . . . . . . . . 95
X
6 Test Results 109
7 Conclusions 127
Bibliography 131
XI
B Triple Junction Solar Cell SPICE Model 141
XII
F C Code for ATXmega128A1 187
XIII
XIV
List of Figures
XV
2.13 Solar incident angle: Kelly cosine vs Cosine law . . . . . . . . 23
XVI
4.2 Solar array configuration . . . . . . . . . . . . . . . . . . . . . 57
XVII
5.4 Four layer PCB stackup . . . . . . . . . . . . . . . . . . . . . 86
XVIII
6.3 Test: Dark current measurement in 3◦ C. . . . . . . . . . . . . 111
6.7 Test: Angular response of two series connect UTJ solar cells. . 114
6.8 Solar simulator IV curve on which the MPPT testing was done.115
6.9 Test: The effect of dutycycle on current, voltage and power. . 116
6.18 Setup for the -17 degree LiFePO4 discharge test. . . . . . . . . 124
XIX
A.2 Solar simulator IV and PV curves . . . . . . . . . . . . . . . . 136
B.1 SPICE circuit used to generate the plots in this section. . . . . 144
XX
E.7 BotElec Layer . . . . . . . . . . . . . . . . . . . . . . . . . . . 184
XXI
XXII
List of Tables
XXIII
XXIV
Chapter 1
Introduction
By using a single switching regulator with a digital control loop, the max-
imum amount of solar power can be converted to electrical energy. At the
same time, the system controls charging of the energy storage cells that are
vital during the solar eclipse periods. Thus, a low parts-count and efficient
system is made possible.
This thesis is a part of the CubeSTAR student satellite project at the Uni-
versity of Oslo (UiO). The project is a part of the Norwegian student satel-
lite program (ANSAT) which is mainly funded by the government agency
Norwegian Space Centre (NSC). The ANSAT program itself is run by the
Norwegian Center for Space-related Education (NAROM) which is based at
Andøya Rocket Range (ARR). The scientific mission of CubeSTAR is to
demonstrate a new concept of measuring the electron density in the iono-
1
Figure 1.1: The CubeSTAR satellite has dimensions 20cm × 10 cm × 10cm
and are covered by solar cells on four sides. The four probes for measuring
electron density can be seen on the right side of the structure, while the
communication antennas are shown to the left.
spheric plasma, with a new multi-probe system that promises greater spatial
resolution than its predecessors. But in addition to that, the CubeSTAR
mission has an educational component which is to provide a platform where
students from several disciplines can work together towards a common goal
of launching their work into space.
2
cm × 10cm) and ”3U” (30cm × 10cm × 10cm) structures have been built
and launched. The CubeSTAR satellite is built after the 2U specification.
CubeSTAR
satellite
Figure 1.2: The Electrical Power System (EPS) is one of the five CubeSTAR
subsystems.
The satellite naturally divides itself into subsystems, which form the basis
for separate work groups where each group works on a single subsystem.
These range from Attitude Control (ADCS) to stabilize the satellite, com-
munication link (COMM), on-board data handling (OBDH), electrical power
system (EPS) and the scientific payload as mentioned. Communication with
the satellite is made possible by ground stations at UiO and ARS/Andøya
among others.
The goals of this work have been to provide answers to the following ques-
tions:
• How much energy is available to the satellite and how can this energy
be utilized most efficiently?
• How should the energy be stored on-board?
• How is the electrical energy distributed to the other subsystems?
• How can the answers to the above questions be implemented on a
printed circuit board that is within the physical constraints of the 2U
formfactor?
3
In addition, to gap part of the bridge of discontinuity that often plagues
Cubesat projects, an attempt has been made to generate and present in-
formation in such a way that it could be picked up by the next wave of
students.
The explanatory approach taken here is to follow the flow of energy through
the system, from the Sun, through the regulation system and via the batter-
ies, before ending up at the subsystems.
In Chapter 2, the Sun’s role as the ultimate energy source is briefly described,
before moving on to the semiconductor devices that convert solar energy to
electrical energy on most of CubeSTAR’s surface; the solar cells. Having
gotten the energy aboard, Chapter 3 describes the EPS itself: the maximum
power point tracking, the Lithium Iron Phosphate batteries, and system
reliability are keywords here.
The testing that have been done on various parts of the system is presented
in Chapter 6, while Chapter 7 concludes the thesis with a few words on what
this all means and how it can be used by future CubeSTAR worker bees.
4
Chapter 2
The CubeSTAR satellite will harvest energy from the Sun through the use
of solar cells. This chapter deals with the theoretical background for the
conversion from solar- to electrical energy in the context of the chosen triple-
junction solar cells.
To evaluate the amount of available solar energy for a spacecraft, the spectral
irradiance of the Sun at the Earth’s mean distance, or one astronomical unit
(1AU), is often used. Referring to the lack of attenuation in the vacuum
conditions above the Earth’s atmosphere, this spectrum is known as the Air
Mass Zero spectrum, or AM0 for short.
5
5780K Black Body
2 Extraterrestrial Spectrum (AM0)
Spectral Irradiance (Wm−2nm−1)
1.5
0.5
0
0 500 1000 1500 2000 2500
Wavelength (nm)
Figure 2.1: While the terrestrial solar spectrum suffers from absorption
of various wavelengths in the atmosphere, the conditions in space closely
matches those of a black body radiator.
hc
E= (2.1)
λ
6
1240 · eV nm
Emax ≈ ≈ 4 eV
300 nm
An incoming solar energy of 1366 watts per square meter would not be of
much use without a way to convert it to electrical energy. This job is typically
done with solar cells. Although the photovoltaic effect was first recognized
by French physicist A. E. Becquerel in the year 1839, it wasn’t until 1883
that the first solar cell was built by Charles Fritts. His new invention was
capable of transforming 1% of the incoming solar energy to electrical energy.
Fast forward 130 years, and luckily, CubeSTAR is mounted with solar cells
that convert solar energy to electrical energy with an efficiency of around
28%. The chosen cells for CubeSTAR are Spectrolab’s Ultra Triple Junction
(UTJ) solar cells, shown in Figure 2.2. For easy reference the most important
parameters from the UTJ datasheet are re-hashed in Table 2.1. The meaning
and significance of these parameters are explained in Section 2.4.
The cells are delivered in an assembly of solar cell, interconnects and cov-
erglass, known as a CIC, and are approximately 160 microns thick with an
area[3] of 26.62 cm2 . The rear side is mounted with a silicon bypass diode
that sits anti-parallel relative to the solar cell’s anode-to-cathode direction.
The role of the bypass diode is to prevent a partially shadowed or damaged
individual CIC in a series string from being forced into reverse bias.
When sunlight hits these solar cells, one of three things happens:
7
Table 2.1: Key parameters from the UTJ datasheet, AM0, 28◦
Parameter Value Description
Jsc 17.05 mA/cm2 Short-circuit current density
Jmp 16.30 mA/cm2 Current density at the MPP
Voc 2.665 V Open-circuit voltage
Vmp 2.350 V Voltage at the MPP
Cff 0.84 Fill factor
η 28.3% Efficiency
jsc 5 µA/cm2 /◦ C Temperature coefficient for Jsc
2 ◦
jmp 1 µA/cm / C Temperature coefficient for Jmp
voc -5.9 mV/◦ C Temperature coefficient for Voc
◦
vmp -6.5 mV/ C Temperature coefficient for Vmp
8
Figure 2.2: Front and rear sides of a CIC from Spectrolab showing the cath-
ode interconnects (A,B,C), the anode (D) of the monolithic bypass diode,
the parallel electrodes (E) that terminate at the cathodes, the cell’s anode
(G), and the integral monolithic bypass diode (F) which protects the cell in
the case of reverse bias.
There are two bands of special interest to us. The valence band which is
the highest occupied band, and the conduction band which is the lowest
unoccupied band. The energy gap, Eg , between these two bands is known
as the material’s band gap. Suffice for our discussion, it is a measure of the
amount of energy required to free an outer shell electron from its orbit around
the nucleus to a free (conducting) state.
9
Electron
Conduction Band
Energy gap = Eg
Ph
ot
on Valence Band
Figure 2.3: The photon energy must be greater or equal to the bandgap in
order to free an electron from the valence band and make it a mobile charge
carrier.
Eg
VD ≈ − 0.4V
q
where we have divided by the elementary charge q in order to get the right
units. Table 2.2 lists the band gap energies[9, 20] of a few well-known semi-
conductor materials2 .
Triple junction solar cells are, simply put, constructed by stacking three
2
At a temperature of T = 300K
10
different semiconductor materials on top of each other. If a photon has
insufficient energy to knock loose an electron in a layer, it will simply pass
through to the next layer. In the cells from Spectrolab, the top GaInP2 layer
is transparent to all but the most energetic photons in the ultraviolet and
visible part of the spectrum. The second GaAs layer absorbs near-infrared
Ge Eg1
Figure 2.4: The collective ability of triple junction solar cells to absorb light of
different wavelengths is the main reason for their superior efficiency compared
to conventional solar cells.
light while the bottom Ge layer absorbs all the lower photon energies in the
infrared that are above 0.67 eV. By combining semiconductor materials with
different bandgap energies this way, higher conversion efficiencies are possible
due to the stack’s collective ability to match the solar spectrum.
When a layer does absorb photons, the solar energy excites electrons into the
material’s conduction band where it is free to sign up to do work as electrical
current. How this photo-generated current and voltage behaves electronically
is the topic for the next section.
To understand the electronic behavior of the triple junction solar cells, the
equivalent3 circuit in Figure 2.5 is used. Although the use of three diodes
3
The monolithic bypass diode is not included, as it does not affect normal operation.
11
give a better feel for the higher output voltage of triple junction cells, its use
here is more illustrative than practical, as it unnecessarily clutters the equa-
tions without the benefit of increased information output from the model.
Therefore in the following the diode string will be treated as a single diode.
All plots in this section were created with the SPICE model from Appendix
B. Although the model ignores more exotic effects such as the parallel non-
ohmic current paths caused by recombination (which requires a second par-
allel diode in the model), it was constructed in such a way as to match the
output characteristics of Spectrolab’s cells as closely as possible.
RS
VD
+
ID ISH I
DGaInP2
ISC
DGe
Figure 2.5: An equivalent circuit of a triple junction solar cell. The mono-
lithic bypass diode (not shown) has its anode connected to the negative
terminal and its cathode to VD .
With the simplifications made, the cell acts as a constant current source
shunted by a diode. The internal resistance to the current flow, represented
by a lumped resistor RS , is primarily caused by the resistivity of the semicon-
ductor material, but also from the metal grid and contacts on the cell. The
other (shunt) resistor RSH represents the leakage current across the junction,
and for a high-quality cell we have that RSH >> RS .
12
2.4.1 Short-Circuit Current
From Kirchoff’s Current Law it’s clear that the output current I from the
cell is
· µ ¶ ¸
qVD
ID = I0 exp −1
nkB T
µ ¶
Eg
I0 ∝ A · exp − (2.2)
kB T
· µ ¶ ¸
qVD VD
I = Isc − I0 exp −1 − (2.3)
nkB T RSH
where the ground leakage current represented by the last term is negligible
compared to Isc and ID .
If the output is shorted, the output voltage is trivially zero, which means
that the short-circuit current is the same quantity as the photo-generated
current, and thus a measure of the irradiance level, as shown in Figure 2.7.
13
I(Vbias)
500mA
400mA Isc
300mA
200mA
100mA
Voc
0mA
0.0V 0.5V 1.0V 1.5V 2.0V 2.5V 3.0V
--- D:\_Work_dir\LTSpice_wrk\Closing In\UTJ_sim.cir ---
The cell’s open-circuit output voltage VOC is the voltage, VD , across the
current source less the small drop over RS , or
VD = VOC + IRS
· µ ¶ ¸
qVoc Voc
Ioc = Isc − I0 exp −1 − =0
nkT RSH
14
I(Vbias)
500mA
1366 W/m^2
400mA
1000 W/m^2
300mA
200mA
500 W/m^2
100mA
1 W/m^2
0mA
0.0V 0.4V 0.8V 1.2V 1.6V 2.0V 2.4V 2.8V
--- D:\_Work_dir\LTSpice_wrk\Closing In\UTJ_sim.cir ---
Figure 2.7: The effect of varying irradiance levels on the I-V curve.
µ ¶ µ ¶
Isc Isc
Voc = VT · ln 1 + ≈ VT · ln (2.4)
I0 I0
which shows that the net effect is that Voc increases linearly with increasing
temperature. In Figure 2.8, parameters within the SPICE model was ad-
justed to match the negative temperature coefficient from the datasheet, and
as such, the curves represent the theoretical response to varying temperature.
Equation 2.4 also explains why the change in open-circuit voltage was so small
relative to the change in Isc under the varying irradiance conditions in Figure
2.7; Voc depends logarithmically on the Isc /I0 ratio which in turn depends
linearly on the irradiance, as we saw earlier. Replacing the current with the
current density expression above will also reveal that Voc is independent of
the cell area.
15
I(Vbias)
500mA
400mA 78°C
28°C
300mA - 22°C
- 74 °C
200mA
100mA
0mA
0.0V 0.5V 1.0V 1.5V 2.0V 2.5V 3.0V 3.5V
--- D:\_Work_dir\LTSpice_wrk\Closing In\UTJ_sim.cir ---
Every point on the I-V curve has a power associated with it, given by
· µ µ ¶ ¶¸
V
P = V I = V IL − I0 exp −1 (2.6)
VT
The maximum power point (MPP) of a solar cell is the operating point on
the I-V curve where the product of the delivered output current, IL , and the
voltage across the cell, V, is at its maximum. We shall call this point
16
I(Vbias)*V(31)
1.25W
1.00W
Pmax
0.75W
0.50W
0.25W
0.00W
I(Vbias)
500mA
MPP
400mA Imp
300mA
200mA
100mA
Vmp
0mA
0.0V 0.3V 0.6V 0.9V 1.2V 1.5V 1.8V 2.1V 2.4V 2.7V 3.0V
--- D:\_Work_dir\LTSpice_wrk\Closing In\UTJ_sim.cir ---
Figure 2.9: Every point on the I-V (bottom) curve has a corresponding point
on the P-V (top) curve. To extract maximum power from the cell, it must
be operated at the MPP.
and take it to be the point where the maximum power is generated, as can
be seen in Figure 2.9.
Plugging the pair of Vmp and Imp into Equation 2.3 we find that the current
at the MPP is,
· µ ¶ ¸
Vmp
Imp = IL − I0 exp −1 (2.7)
VT
From Figure 2.9 it is clear that the power derivative with respect to voltage
must be zero at the MPP (where V = Vmp and I = Imp ), so
17
· µ ¶ ¸ µ ¶
dP Vmp Vmp Vmp
= IL − I0 exp −1 − I0 · exp
dV VT VT VT
µ ¶
Vmp Vmp
= Imp − I0 · exp =0 (2.8)
VT VT
Using the result from Equation 2.8 together with Equation 2.4 we find that
the voltage at the MPP is
µ ¶
Imp VT Vmp
Vmp = exp
I0 VT
h ³ ´ i
IL VT − I0 VT · exp VVmp T
− 1
= ³ ´
Vmp
I0 · exp VT
IL VT VT
= ³ ´+ ³ ´ − VT
Vmp Vmp
I0 · exp VT exp VT
µ ¶µ ¶
Vmp IL
= VT · exp − + 1 − VT (2.9)
VT I0
We’ll let the power-discussion rest for now, and run through the rest of
the datasheet parameters, before picking up the power again in Section 3.4,
where the focus will be on how to actually maximize the output power and
do something useful with it.
18
2.4.4 Fill Factor
We will now define the fill factor (FF) as the ratio between the actual power
output Pmax , and the product of open-circuit voltage Voc and short-circuit
current Isc .
Vmp Imp
FF = (2.11)
Voc Isc
The fill factor is a measure of a cell’s energy conversion efficiency, and as seen
from Figures 2.10 and 2.11, the ratio is strongly dependent on the shunt- and
series resistance in the cell.
I(Vbias)
500mA
Ω
0.001Ω
400mA Ω
0.5Ω
Ω
1Ω
Ω
2Ω
300mA
200mA
100mA
0mA
0.0V 0.3V 0.6V 0.9V 1.2V 1.5V 1.8V 2.1V 2.4V 2.7V 3.0V
--- D:\_Work_dir\LTSpice_wrk\Closing In\UTJ_sim.cir ---
Figure 2.10: The effects of an increasing series resistance (RS ). High quality
cells have low series resistance.
19
I(Vbias)
500mA
Ω
1000Ω
Ω
50Ω
400mA
Ω
25Ω
Ω
15Ω
300mA
200mA
100mA
0mA
0.0V 0.3V 0.6V 0.9V 1.2V 1.5V 1.8V 2.1V 2.4V 2.7V 3.0V
--- D:\_Work_dir\LTSpice_wrk\Closing In\UTJ_sim.cir ---
Figure 2.11: The effects of a decreasing shunt resistance (RSH ). High quality
cells have high shunt resistance.
2.4.5 Efficiency
where G = 1366 W/m2 is the solar constant and A = 26.6 cm2 is the area of
a single UTJ cell from Spectrolab. Note that the cell efficiency is referenced
to AM0 conditions
20
2.4.6 Loading the Solar Cell
In Figure 2.12, another type of load line can be seen; a constant power load.
Among the type of loads that are characterized by such a load line, is the
switching regulator4 , which aims to regulate its output at a steady voltage
regardless of variations in input voltage or load current draw.
Figure 2.12: Constant power load lines (P1 and P2 ) intersect the IV curve
in two places. Only B2 is stable, and this is where the system naturally
operates. Figure reproduced from [19].
If the power is P = V I and the operating point moves away from this point,
4
For example, if the solar cell voltage increases, the control loop of the regulator would
reduce its dutycycle, which in turn would reduce the input current of the regulator. There-
for, an increase in the input voltage (i.e., solar cell output voltage) results into a current
decrease, and vice versa, making the switching regulator look like a constant power load
to the solar cell.
21
to
∆P = ∆V I + ∆IV (2.14)
At the maximum power point, ∆P should necessarily be zero and lie on a lo-
cally flat neighborhood, so the relationship in the limit between the dynamic
and static impedance at the maximum power point, can be stated as
∆V V
=− (2.15)
∆I I
When the solar cell is operated away from Pmax , it has been shown in [10]
that only point B2 in Figure 2.12 is stable and any perturbation from it
will generate a restoring power in the direction of Voc to take the operation
back to B2 . In other words, electrically stable operation of the solar array is
characterized by
· ¸ · ¸
dP dP
> (2.16)
dV load dV source
A fundamental parameter in all solar array analysis is the angle (η) between
the solar panel normal vector (N b ) and the spacecraft-Sun vector (S).
b In
general, the cosine of the angle between the two vectors is given by the the
sum of their direction cosines. Thus, by using elementary vector identities the
angle for any combination of panel normal and Sun vector can be calculated
with
Nb • Sb = ~nx~sx + ~ny~sy + ~nz ~sz = cos η (2.17)
22
This is an important result, because the amount of solar generated current
from a cell is proportional to the cosine of the angle between the two vectors—
or, at least up until a certain point. Beyond 50◦ , increased reflection causes
the angular response to deviate from the cosine law, and the actual response
is more accurately expressed by what is known as the Kelly cosine:
where θ is the angle between the Sun vector and the solar panel normal.
Cos θ
Kelly cosine
1
0.8
Normalized Current
0.6
0.4
0.2
0
0 10 20 30 40 50 60 70 80 90
Incident angle (θ in degrees)
Figure 2.13: Output current from a solar cell is proportional to the cosine of
the incident angle—up to about 50◦ at which point the Kelly cosine is more
accurate. No current is produced at angles > 85◦ .
As seen in Figure 2.13, the actual electrical output drops off slightly steeper
than what the cosine function predicts, and no current is produced at angles
greater than 85◦ . However, the deviation is not large enough to outweigh the
benefits of simpler calculations, so the Kelly cosine is therefore rejected here
in favor of the cosine function.
23
I = A · K · cos η (2.18)
where A is the area in m2 , K is the solar constant (1367 W/m2 ), and η is the
angle between the surface normal and Sun vector. With Equation 2.18 and
Figure 1.1 in mind, four different cases will be considered where an attempt
is made to illuminate how the spacecraft’s position will affect the effective
area A · cos η and thus the power output from the cells.
This case is trivial since if one of the two sides without mounted solar cells
have their normal vector aligned with the Sun vector, the effective solar cell
covered area is zero and no power is produced.
Amin = 0
If the normal vector of a surface with four mounted solar cells is aligned with
the Sun vector the effective area is
The maximum possible effective area is when two sides with mounted cells
simultaneously face the Sun such that their individual projected area in the
direction of the Sun equals the cosine of the angle. The total area is
24
Amax = 2 × 4 × 26.6cm2 × cos 45 = 150.6cm2
By letting the Sun vector lie along one of the axis, the projected area in
each dimension is sufficiently expressed by the spherical coordinates for the
normal vector:
Nx = sin β cos α
Ny = sin β sin α
Nz = cos β
Negative values of the cosine function are discarded since a surface is only
illuminated for angles between 0◦ and 90◦ . The total projected area in the
direction of the Sun, Atot , is found by integrating the contributions from each
face over the 90◦ rotation about two axis, or
π π
Z2 Z2
Atot = (A1 sin β · cos α + A2 sin β · sin α + A3 cos β) dβ · dα
0 0
where A1,2,3 represent the areas of each of the three sides that at any given
time can face the Sun.
In terms of actual solar cell area, the solar panel configuration from Figure X
means one of the three areas will be zero. This fact is taken into account by
letting the empty face be represented by A1,2,3 in succession and averaging
the result over the three trials. But that is equivalent to replacing each
25
X
Figure 2.14: Solar panel normal vector and geometry used to estimate the
output power for a free tumbling spacecraft.
individual side’s area with the average area (i.e., two thirds of the area of
one side) of the three exposed sides, or
2
A = A1,2,3 = 4 cells × 26.6 cm2 × = 70.9 cm2 = 0.00709 m2
3
π π
Z2 Z2
π
Atot = A · (sin β · sin α + sin β · cos α + cos β) dβ · dα = A · (2 + )
2
0 0
To get a feel for the angular response of Atot /A, the a Matlab script was used
to sum5 up the contributions and average them over the summation limits.
It should be noted however, that Figure 2.15 does not illustrate the actual
angular response of the spacecraft, but rather that of the equivalent scenario
with scaled average sized solar cells on all sides.
5
The integrals were approximated with sums.
26
90
80
70
60
Angle β (degrees)
50
40
30
20
10
0
0 10 20 30 40 50 60 70 80 90
Angle α (degrees)
Figure 2.15: Angular response when all sides are covered by imaginary aver-
aged sized solar cells.
The averaged projected area Aavg in the direction of the Sun is then found
by dividing Atot with the integration limits, or
π π
Z2 Z2
1 1 Atot
= · dβ · dα ⇒ Aavg = (2.21)
Aavg Atot π 2 /4
0 0
Thus, the numerical average projected area in the direction of the Sun for a
free tumbling spacecraft is
2 + π2 8 + 2π
Aavg = A · 2
= 0.0071 m2 · = 0.01026 m2 (2.22)
π /4 π2
27
Finally then, the estimated average input power during the sunlit portion of
the orbit is
The four cases considered in this section are summarized in Table 2.3.
Table 2.3: Effective area and produced power under various spacecraft posi-
tions.
Case Area Power
1: Minimum area 0 0W
2: One side only 106.5 cm2 4.08 W
2
3: Maximum area 150.6 cm 5.76 W
2
4: Average area 102.6 cm 3.93 W
28
Chapter 3
3.1 Objectives
The main objective of the electrical power system (EPS) is to provide the
other subsystems with a reliable and continuous power source. Typical build-
ing blocks of such a system consists of a solar array, energy storage batteries
and power processing electronics, which perform:
Having already dealt with the solar array in Chapter 2, the main focus here
will be on the second and third points, while the fourth task will be simplified
by choosing batteries with an operating voltage that lies in the range of what
many of the subsystems are expected to operate within. Thus, in the current
setup, a de-centralized distribution scheme is used.
29
Electrical Power Subsystem
Power
Power Energy Power
Regulation &
Source Storage Distribution
Control
Electrical power systems used for spacecrafts in LEO can broadly be divided
into two types; the Direct Energy Transfer (DET) approach and the Peak
Power Transfer (PPT) approach. All other configurations are variations,
derivations or combinations of these two basic types.
Since they both have common building blocks in the form of solar arrays
and power distribution units, the distinction between DET and PPT lies in
how the power processing electronics conditions the solar array and storage
batteries. While a PPT system aims to extract the maximum power from the
solar array and hence dissipate very little power internally, a DET system
employs a shunt regulator to dissipate any excessive power.
30
3.2.1 Direct Energy Transfer (DET)
In the DET approach, the power from the solar array is directly transferred
to the loads (via the distribution unit). To regulate the bus voltage at a
predetermined level, a shunt regulator dissipates any excessive power as heat
within the system which may require large heatsinks.
TO
POWER LOADS
SOLAR
DISTRIBUTION
ARRAY
UNIT
SHUNT CHARGE
REGULATOR REGULATOR
STORAGE
BATTERIES
Figure 3.2: The solar array is connected directly to the distribution unit in
a DET system. A regulated DET system is achieved by replacing the diode
with a discharge regulator.
In the PPT approach, a regulator is placed in series between the solar array
and the loads. By taking control of the operating point on the solar array’s
I-V curve, the regulator tries to operate the solar array in such a way as to
maximize the power output from it. This increases efficiency and simulta-
neously side-steps the potential thermal dissipation problems seen in DET
31
systems. Such a regulator is often called a Maximum Power Point Tracking
(MPPT) regulator, and it is used to both charge the batteries and supply
the loads with power.
TO
PEAK POWER POWER
SOLAR LOADS
TRACKING DISTRIBUTION
ARRAY
REGULATOR UNIT
STORAGE
BATTERIES
Figure 3.3: A maximum power point tracking regulator, controlling the out-
put of the solar array, can be used to supply power to the loads and for
battery charging at the same time.
When the batteries are fully charged, the tracker electronically moves the
operating point away (towards the open-circuit condition) from the maximum
power point, and in the process it leaves the energy from the sun as heat in
the solar array itself, instead of converting it to electrical energy. Since a
large portion of the incoming solar energy already is left as heat in the 28%
efficient panels during normal operation, an additional few percent does not
pose a thermal problem as far as the solar array is concerned. Contrast this
to the DET systems, where the excessive energy is dissipated inside of the
spacecraft, which may give rise to some of the thermal problems discussed in
Section 3.6.4. Yet another benefit with the PPT system is that the battery is
connected directly to the loads. This maximizes efficiency during the eclipse,
which is when we need it.
Before looking closer at how such a PPT system works, some of the orbit
constraints will be introduced. By introducing them here, they will serve to
back up the decision to choose a PPT system over a DET system, and also
provide the backdrop for the energy storage discussion that follows i Section
3.5.
32
3.3 Orbital Considerations
Since the final orbit details for CubeSTAR are presently undefined, the orbit
considered here will be a typical Low Earth Orbit (LEO) Cubesat orbit,
with an altitude of 600 km and an inclination of 98◦ . To simplify further,
only the ”minimum Sun” case (i.e., maximum eclipse), where the Sun-Earth
vector lies in the orbit plane, will be considered here. For all but the Sun
synchronous low earth orbits, the Sun will lie in the orbit plane twice a year,
allowing us to calculate the orbital parameters based on a simple argument
from geometry. The minimum Sun case also returns valuable information
about the energy storage requirements, as it defines the minimum battery
capacity needed.
33
s
(RE + A)3
T ' 2π ' 1.6585 · 10−4 × (RE + A)3/2 = 96.7 min (3.1)
µ
where µ = 3.986005 × 1014 m3 /s2 = 14.3496 × 108 km3 /min2 is the standard
gravitational parameter1 of a celestial body, RE = 6378.137 km is Earth’s
radius, A= 600 km is the orbit altitude for circular orbits. The sum of RE +A
is the orbit semimajor axis in km.
Equipped with the orbital period, we can find the eclipse period for the
minimum Sun case from the simple geometry in Figure 3.5. Since the final
orbit of CubeSTAR is unknown as of today, only the maximum eclipse (or
minimum Sun) case will be considered here. For all but the Sun synchronous
low earth orbits, the sun will lie in the orbit plane twice a year. This situation
is illustrated in Figure 3.5 and is valid for circular orbits.
Figure 3.5: Geometry used to calculate the eclipse and sunlit periods for the
”minimum sun” case when the sun is in the orbital plane.
When the Sun is in the orbital plane, the rays are parallel and the tangential
terminal ray forms a right triangle where the hypotenuse is equal to the sum
of Earth’s radius and the spacecraft altitude. One of the legs is equal to RE
as shown, and the angle is then
1
It’s the product of Earth’s mass and gravitational constant.
34
µ ¶ µ ¶
RE 6378km
α = arccos = arccos = 24◦ (3.2)
RE + A 6378km + 600km
180 + 2α
Fraction of time in sunlight = = 63.3 %
360
and
180 − 2α
Fraction of time in eclipse = = 36.6 %
360
For an orbital period of 96.7 minutes, the sunlit and eclipse fractions are thus
61.2 minutes and 35.4 minutes respectively.
As discussed in Section 2.4, the solar array generates most power when oper-
ated under cold conditions. It is clear then from the approximate2 expected
orbital temperatures shown in Figure 3.6 that the solar array will produce
most energy upon leaving the eclipse, with the temperature profile rising
sharply before leveling out as the sunlight heats the panels. Only the PPT
regulator is able to adjust to this temperature variation.
Assuming the temperature profile in Figure 3.6 is representable for our mis-
sion, it reveals one of the main weaknesses of the DET system approach. The
moment the spacecraft leaves the eclipse, the battery voltage (and thus the
main bus) will be at its lowest level, while the cold array could potentially
generate its highest power level—if it hadn’t been clamped by the battery.
Thus, with DET, the moment the EPS needs to produce the most power is
the moment it in practice can produce the least relative to its potential. In
fact, its in the dual case, when the array is at its warmest (and thus VM P
2
The shape of this curve depends on panel-specific factors such as absorption coefficients
(absorbtivity/emissivity), panel thickness, rigidity, etc.)
35
Figure 3.6: Solar array worst-case orbital temperature profile for a satellite
in a sun-synchronous low-earth orbit (LEO) at an altitude of 700km.
moves towards the battery voltage) and the battery is nearly fully charged
at the end of the orbit, that the DET maximizes solar array performance.
36
3.4 Maximum Power Point Tracking
A maximum power point tracker can be separated into two blocks; a control
block and a power block. The power block, which is discussed in Section 4.3,
is typically a switching DC-DC converter that steps the solar array voltage up
or down (or both) in accordance to the bus voltage, while the control block,
which can be implemented either in hardware[21] or software, measures the
solar array parameters and sets the new operating point.
MPPT Regulator
Pmax
Solar Array Power Loads
V A
Control
Figure 3.7: A maximum power point tracking regulator sits in series with the
solar array, and tries to find the optimal operating point on the array based
on the output/input current, voltage and/or a combination of the two.
Also considered was the Incremental Conductance method, but its added
complexity and slower conversion time (with a large power loss as a result[11])
made it a less attractive option than the P&O, and it will not be dealt with
here.
37
3.4.1 Constant Voltage Method
The Constant Voltage (CV) method regulates the solar array terminal voltage
and matches it to a fixed reference voltage, which is the assumed MPP of the
solar array. The method is simple; just measure the array voltage, compare
it to a constant reference, and use the difference (or, error) to drive a power
conditioner. While this method requires very little computation, and thus
finds the approximated MPP very quickly, it suffers from low accuracy due to
the ignored temperature-dependent variations in the solar cell’s open-circuit
voltage. In fact, the ”constant” voltage method, in this context, is inherently
flawed, as it is based on a false assumption that the array voltage is constant.
A possible solution to this problem is to use a look-up table (based on the
temperature vs voltage plot in Figure 2.8) in tandem with panel temperature
measurements, and adding this temperature offset to the VOC measurements.
VM P P = k × VOC (3.3)
The Perturbation and Observation (P&O) Method is perhaps the most com-
monly used MPPT method due to its ease of implementation. The tracker
operates by periodically incrementing or decrementing (perturbing) the solar
array voltage and measuring (observing) the change in array power. If the
change results in an increase in the array output power, the tracker will re-
peat its last action. In the opposite case, if the result is a decrease, then the
next perturbation will be in the opposite direction. This situation is illus-
trated with the flow diagram in Figure 3.8, where P, V and I is the power,
38
voltage and current, while D represents the dutycycle control parameter.
39
Measure
V(k), I(k)
Calculate
P(k) = V(k)I(k)
Yes
P(k) – P(k-1) = 0
No
Yes No Yes No
V(k) > V(k-1) V(k) > V(k-1)
Return
40
3.5 Energy Storage with Lithium Iron Phos-
phate Battery
Energy storage batteries provide the power source for peak-power demands
and the eclipse periods. The capacity of a battery is the total number of
ampere-hours that can be withdrawn from a fully charged cell. The product
of ampere·second is the amount of electric charge transported in one second
by a steady current of one ampere, so the ampere-hour, or Ah, is equal to
3600 coulombs.
64.95 ± 0.20
10.00
18.20 ± 0.20
The chosen batteries in this system are rechargeable 1.1 Ah Lithium Iron
Phosphate (LiFePO4 ) cells from A123 Systems Inc. Based on the calculated
orbital eclipse period in Section 3.3, they undergo about 15 charge-discharge
cycles per day—or about 5000 cycles a year.
41
Figure 3.10: A123 Systems LiFePO4 DOD vs Cycles. Picture is copied from
A123 Systems Inc own website, and has been edited/emphesized.
42
Instead of dwelling too much on chemistry, the interesting properties of the
LiFePO4 cells are summarized in Table 3.1.
Since about one third of the orbit time is in darkness, some of the energy
generated by the solar panels must be diverted to battery charging.
Nighttime Energy
Daytime Energy Loss Margin
(Battery recharge)
Figure 3.11: Distribution of the total energy from the solar panels.
43
is the sum of the energy needed to charge the battery and the energy to
daytime loads, expressed as
Esa = En + Ed (3.4)
where Esa is the required solar panel energy, En and Ed are the energies
consumed during night and day, including margins. But energy is the product
of power and time, so Equation 3.4 can be written as
Psa Td = Pn Tn + Pd Td (3.5)
where Psa is the average output from the solar array during the sunlit portion
of the orbit, Pn and Pd are the average load power consumption during night
and day, Tn and Td are the eclipse and day periods in hours.
If we use the average solar panel output from Table 2.3 and the sunlit and
eclipse fractions from Section 3.3 (Td = 1 and Tn = 0.6), and assume a
constant lossless power consumption Pnd(ideal) throughout the orbit, i.e. Pn
= Pd = Pnd(ideal) , then we can solve Equation 3.5 for the average power
available to the subsystems throughout the orbit:
Before we can take the system losses into account, it’s normal to group the
losses into three fractions[8]: Xa−l is the power transfer efficiency from the
solar array to daytime loads; Xa−b is the power transfer efficiency from solar
array to battery; Xb−l is the power transfer efficiency from the battery to the
nighttime loads.
Pn Tn Pd
Psa = + (3.6)
Xa−l Xb−l Td Xa−l
Equation 3.6 should be used with the maximum time-averaged electrical loads
44
(including margins) and Psa is then the minimum required power required
from the solar array.
We can then take some imaginary losses into consideration by assuming Xa−l
= 80%, Xa−b = 85% and Xb−l = 95%. The average power available to the
subsystems including loss is
Raising the solar array to loads and battery efficiency to 90% would yield an
available power of 2.15W.
It follows then that the battery energy capacity is the average nighttime
power multiplied by the maximum eclipse time divided by the transmission
efficiency from battery to loads:
P n Tn
Eb = (3.8)
Xb−l
But Eb is usually not equal to the actual battery capacity. Only a small
percentage of the total battery capacity is removed at each discharge and the
battery is never allowed to discharge completely. The percentage removed,
or depth of discharge (DOD) during a discharge is
Eb
DOD = (3.9)
Eb(tot)
Pn Tn
Eb(tot) = (3.10)
Xb−l DOD
45
Dividing through by V = P/I we’re left with the ampere-hour product on
the right hand side, which we recognize as the capacity of a battery. The
battery capacity requirement in Ampere·hours is thus
Eb(tot) P n Tn
C= = (3.11)
Vbat Vbat Xb−l DOD
where Vbat in volt is the average battery discharge voltage, Pn in watts is the
nighttime power required (including margins) and Tn is the eclipse period in
hours.
With a 3.25V discharge voltage and 10% DOD the required capacity is
2.44 × 0.6
C= = 4.7Ah (3.12)
3.25 × 0.95 × 0.1
One of the most appealing characteristics of the LiFePO4 cell for our pur-
poses is its flat discharge voltage of around 3.25V. This suites our chosen
unregulated power bus well. In fact, it’s the main reason the unregulated
bus was chosen in the first place. Thus there is no need to connect the bat-
teries in series to raise the battery pack voltage. However, by connecting four
1.1Ah cells in parallel, their collective capacity is increased to 4.4 Ah, which
is about the level we need, based on the calculations in Section 3.5.2.
46
The Electronics Lab and Mechanical Workshop at the Department of Physics
(UiO) are working together on the physical design of the battery pack. An
early engineering model that was made, is shown in Figure 3.12, where the
pack is mounted to form the center of gravity in the structure.
The pack contains two redundant 4.4 Ah batteries. There are potential issues
regarding equalization of the cells, but these should be minor, and should not
affect the design of the charging system. Only single-cell testing3 has been
done up to this point and thus the battery pack will not be discussed further,
on the assumption that the pack’s behavior will not differ much from that of
a single cell.
47
low internal resistance—and high short-circuit current—of the LiFePO4 cells,
this type of failure would probably end the mission in spectacular fashion. To
prevent this, fuses, circuit breakers or thermal switches could be used, and
the surface of the battery terminals should be insulated to avoid accidental
contact with other conductors inside the structure[17].
Similar to conventional lithium-based batteries, our chosen cell has two main
charging phases; constant current (CC) and constant voltage (CV), as shown
in 3.13. Both phases are explained below in the context of the implemented
charging system.
V,I
Voltage
3.6V
Y-Axis
C
ur
re
nt
Time
Time
CC X-Axis CV
Figure 3.13: All lithium based rechargeable batteries are charged with a
”constant current - constant voltage” regime as shown. The battery is said
to be fully charged when the current drops below a certain threshold.
48
assuring that the charge current does not exceed the maximum allowed by the
manufacturer—the last point being of little importance due to the inherent
current limitations of the solar array and the recommended maximum charge
current of 1.5 A. This process continues until the battery’s terminal voltage
reaches a preset value of 3.6V, as per the cell’s datasheet.
When the battery bus reaches a preset value of 3.6 V, the battery charge
regulator moves away from the MPP toward the open circuit voltage, reduc-
ing current flow to the battery, and regulates the bus at a constant voltage
of 3.6V. The reduction in charge current, which drops exponentially, is nec-
essary in order to maintain the bus at a steady 3.6V during this phase of the
charging.
Ichg
Constant Voltage Battery
Source
ESR
DC
Vbat
Vc
Figure 3.14: Equivalent circuit during the constant voltage charging phase.
The battery is said to be fully charged when Vbat = 3.6V and Ichg < C/10,
with C being the charge current. Or, as A123 Systems suggest; the battery
is fully charged after 45 min of CV, although this assumes a 1.5A charge
current.
49
3.6 System Reliability
The EPS has a special responsibility as the power supplier to all the other
subsystems; a system failure here would end the mission. An inevitable fact
of operating a power-system, or any electronics, in space, is that no repair
is possible once the system is launched. This means that special attention
must be paid to failure tolerance of components and the system’s reliability.
Which raises the question; what is a significant loss? The answer is mission-
specific and the suggestion in [18] of 10% of the total power capability, is,
although being a nobel goal, probably not a realistic one, seen from a Cubesat
perspective. What the final failure tolerance amounts to will be more clear
when moving closer to the final system revisions, but even in the earliest
stages of development, the general approach to failure tolerance must be that
it is built into the system itself, and not be added as a post-hoc ”feature”.
50
(e.g., an overcurrent condition) can invoke fault responses in the main on-
board computer that contain preprogrammed instructions such as going into
a ”safe-mode”, or similar. Such responses are currently outside the scope of
the EPS, and should be implemented in the main on-board computer.
3.6.3 Redundancy
All non-ideal components dissipate power in the form of heat which is trans-
ported away from the component by one of the three fundamental modes
of heat transfer; conduction, convection or radiation. The big elephant in
the room here is the lack of air convection due to the vacuum conditions in
space. Although usually taken for granted, the principal means of cooling
PCB mounted components in terrestrial electronics is by air convection. For
the terrestrial case, the junction temperature tj can be modeled as in Figure
3.15, with
51
where P is the power to dissipate and RΘj−c is the equivalent junction-to-case
resistance while RΘc−c,s,r are the case-to-environment equivalent resistances
representing convection (c), conduction (s) and radiation (r).
Terrestrial Environment
Convection
t j
Radiation P
R
θJ-C
Component
R R R
Conduction
θC-C θC-S θC-R
Space Environment
t j
Radiation P
R
θJ-C
Component
R R
Conduction
θC-S θC-R
Figure 3.15: The three different means for a component to get rid of heat
energy: convection, conduction and radiation. The situation can be modeled
with an equivalent circuit as shown (right).
Considering how the thermal resistance associated with air convection can be
between a fifth and a tenth of the radiation and conduction resistances[18],
a component operating at 40◦ C in a terrestrial environment can experience
52
a case temperature exceeding 200◦ C in vacuum! Because of this, special
attention must be paid to junction temperatures and expected dissipation
when selecting components.
53
54
Chapter 4
System Design
Two redundant regulators each serve two opposite faced sides and aim to
either optimize the charge current into the batteries, or regulate the bus
voltage, depending on the system state. The regulation mode is determined
by the battery voltage. As long as the battery is below 3.6V, the regulator
aims to maximize the power output from the solar panels. This is equivalent
to maximizing the charging current, since the battery voltage is constant be-
tween the two discrete points in time where the regulator makes its decision.
When (or if) the battery reaches 3.6V, the regulation mode changes to a
constant voltage mode where a PID regulator regulates the battery voltage
at 3.6V, thus moving the operating point of the solar cells away from the
MPP.
A de-centralized post regulation scheme has been chosen for the subsystems.
The reasoning behind this can be summed up by the discharge plots of the
LiFePO4 cells in Chapter 6. Boasting an almost flat discharge curve, the idea
is that this voltage will be stable enough for some of the subsystems, and
if not, it is up to each individual subsystem to step up or down the voltage
as necessary. However, the subsystems will not be connected directly to the
battery bus, but will be routed through an overcurrent protection switch that
will shut down any ill-behaving systems.
55
Subsystem
example 1
Power
Regulation and Control Overcurrent 3V
Power Source LDO
protection/
Solar Panels Step-down monitoring
A
North+South DC/DC Subsystem
A Switch
V example 2
4V – 6V Control 3V – 3.6V 3V – 3.6V
A Switch
V
Solar Panels Step-down A Switch
A T
East+West DC/DC Battery
Battery
V Packs (2) Subsystem
Packs
example 3
Control
Storage Cells 5V
DC-DC
Legend:
V Voltage monitor A Current monitor T Temperature monitor
Figure 4.1: Two redundant regulators each service two opposite faced sides
and aim to either optimize the charge current into the batteries, or regu-
late the bus voltage, depending on the system state. De-centralized post
regulation has been chosen for the subsystems.
In the following sections, each of the blocks in Figure 4.1 will be explained
(except the other subsystems).
Since only one of two opposite facing side can face the Sun at any time,
they share a single regulator as shown in Figure 4.2. Two and two cells
are connected in series, raising the voltage to around 5 V. With four cells
on each side, two such series strings are connected in parallel, similar to the
configuration of the US Air Force built PSIREX picosatellite[13]. This boosts
the current to a maximum of around 900mA, but the orbital average will be
well below this as the photo-generated current falls off with the cosine to
the incident angle as described in Section 2.5. Each side is protected with
a diode to prevent the shaded side from loading down the sunlit and power
producing side. Low drop Schottky diodes are used here to minimize the Vf I
loss over the diode.
56
4V – 6V
N side S side
Imax ≈
900 mA
REGULATOR
UNIT N
1 OF 2
Satellite
W Top View E
3V – 3.6V S
Figure 4.2: Two opposite facing sides are connected in series via protec-
tion diodes to prevent the shaded side to load down the sunlit and power
producing side.
Two buck converters are used to step down the solar panel voltages to a lower
battery voltage. They are electrically identical, so the following description
applies to both converters.
If we forget about the synchronous rectifier (SR) for now, the basic idea is
to apply a pulse-width modulated (PWM) signal to the high-side switch and
average the resulting square wave with a large LC filter.
The relation between the dutycycle and output voltage can be understood by
looking at the average voltage at the switch (SW) node in isolation. As with
any waveform, the average is found by integrating the peak input voltage
seen at the SW node over a switching period Tsw , or
57
SW node
V V
4V – 6V 2.7V – 3.6V
A
Charge
+ + Pump Battery
+ + Pack
MOSFET
Driver [1 of 2]
Side Side T
”N” ”S”
PWM SR switch
A A ATXmega Sensors
Microcontroller (V, A, T)
TWI
(I2C)
Figure 4.3: Overview over the implemented buck converter. To drive the N-
type high-side mosfet, a simple charge pump is used in tandem with a driver
that is fed by a PWM signal from a microcontroller.
ZTsw
1 Ton
VSW (avg) = Vin dt = Vin (4.1)
Tsw Tsw
0
where the total cycle time Tsw = Ton + Tof f can be replaced by the switch
on time Ton in the integral limit, since Vin is zero during the switch off-time
Tof f . If the open/close frequency is fixed, we can define the dutycycle D as
the ratio of on-time to total time, or
Ton Ton
D= = (4.2)
Ton + Tof f Tsw
and thus D is necessarily a number between 0 and 1. For an (ideal) buck, also
known as a step-down converter, the output voltage is directly proportional
to the dutycycle through
58
which is to say that the output on a buck is always lower than the input.
Vout
V in
0 D
0 1
Figure 4.4: In contrast to other converter topologies the buck converter has
a linear relationship between dutycycle and output voltage.
However, chopping the input voltage on and off produces a square wave
output output with a high harmonic content, and is not very useful as far as
providing power to the typical load is concerned. To remedy this, a lowpass
LC filter is used to remove the higher harmonics and thus averages the square
waveform from the switch. But the introduction of the inductor leads to a
new challenge; the voltage across an inductor is related to the rate of change
of current by
dIL (t)
VL (t) = L · (4.4)
dt
and by abruptly turning off the input, i.e. a large di/dt, the voltage at SW
will quickly be driven down in an attempt by the inductor to maintain the
previous current. This reversal of the inductor voltage polarity is known as
an inductive kickback. By adding a diode at the switch node, the voltage at
the SW node is clamped a diode drop below ground during the off state and
the inductor now has a path through which it can maintain current flow. We
have a buck converter.
59
High-side L
FET +
Vin
+
D C Load
L
+
High-side
Vin FET
+
D C Load
Figure 4.5: Energy is stored in the inductor during the ON state (top) as
the current through it ramps up. During the OFF state (bottom) the free-
wheeling diode provides a current as the inductor releases its energy into the
load.
Unfortunately, adding the free-wheeling diode comes with a prize. From the
loss calculations in [16] it’s clear that the diode’s conduction loss (I · Vf )
represents by far the biggest loss in the converter. Even with the use of a
Schottky diode with low forward drop, as the one used here, the low output
voltage of the converter means that the loss in the diode remains relatively
large even with the most efficient diodes. A common work-around for low
voltage converters is to add a second mosfet that acts as a synchronous
rectifier, and basically takes over the duties of the free-wheeling diode[16].
60
Figure 4.6: SW node voltage. The turning on of the low resistance SR
channel is delayed by a small time known as ”deadtime”, during which the
diode conducts. Evidence of the falling inductor current can be seen by the
slightly positive voltage gradient while the diode/SR conducts. The snubber
is discussed in Section 5.3.3
As shown in Figure 4.6, even though the diode has lost some of its prominent
status, it still has a role to play at the beginning and end of each OFF state.
By adding the SR and driving it with an inverted PWM signal with respect
to the high-side, we now risk that both switches are on simultaneously. This
would short the input through the switches to ground, and must be avoided.
And it can—by adding a certain amount of deadtime between the switching
of the two mosfets, we ensure the necessary leeway needed for safe operation.
This is shown in Figure 4.7.
The inductor voltage during the on period is the difference between the input
and output voltage of the converter and is given by
61
Figure 4.7: Oscilloscope screendump showing the gate drive signals on the
two mosfets. A software adjustable amount of deadtime is inserted to prevent
shoot-through.
where the last approximation neglects the relatively small time-varying ripple
voltage. Equipped with this knowledge we can easily find the inductor current
via Equation 4.4. A simple re-arrangement reveals how the inductor current
changes with an essentially constant slope m1 :
The situation during the off period, when the inductor voltage VL (t) =
−Vout , is analogous to the on period, and thus the slope m2 is given by
62
VL(t)
Vin - Vout
Area = λ1
VL(avg)= 0
Area = λ2
- Vout t
IL(t)
Ipeak
Slope = m1
∆IL IL(avg)
Slope = m2
Ivalley
t
DTsw
Tsw
Figure 4.8: Ideal output inductor voltage (top) and current (bottom) wave-
forms during a switching cycle, illustrating the principle of inductor volt-
second balance where λ1 = λ2 during steady-state conditions.
63
dIL (t) VL (t) Vout
m2 = = =−
dt L L
From Figure 4.8 the change in inductor current, or the output ripple current
amplitude, is given by
µ ¶
Vin − Vout
∆IL = DTsw (4.6)
L
Vin − Vout
L= DTsw (4.7)
∆IL
A couple of key points can be made regarding inductor selection at this stage:
64
L = 100 µH (4.8)
The role of the output capacitance is to minimize voltage overshoot and ripple
at the output. Real capacitors have a certain amount of parasitic equivalent
series resistance (ESR) and inductance (ESL). The latter can be ignored
at frequencies below around 500 kHz[12], but the ESR has a real effect,
and thus the output ripple (noise) is mainly determined by the total output
capacitance and the total ESR. The relationship between output capacitance
C and total peak-to-peak ripple voltage ∆V is given in [5] as
∆IL Tsw
∆V = (4.9)
8C
µ ¶2
∆V π2 f0
= (1 − D) (4.10)
Vout 2 Fsw
√
where f0 = 1/2π LC is the LC cutoff frequency, Fsw is the switching fre-
quency and D the dutycycle. Since we already have decided on the output
inductor value, we can solve Equation 4.10 for a maximum desired ripple
voltage of, say, ∆V = Vout · 3%. Doing so reveals the converter needs output
capacitance of2
Cout = 59 µF (4.11)
µ ¶
Vin − Vout
∆VESR = ∆IL · RESR = DTsw RESR (4.12)
L
2
Considering how a large battery will load down the output line, the value is probably
not critical—but we’ll go by the book for now.
65
The chosen solid tantalum capacitors are low-ESR types, and by putting
two or three in parallel the resistance is further reduced. Their collective
equivalent resistance is only around 40 mΩ, and solving Equation 4.12 for
Vin = 5.5V, Vout = 3V, Tsw = 1/127500 kHz and L = 100 µH, reveals a
noise contribution from the ESR of only 5 mV.
The digital control block is the brain, ears and eyes of the circuit and ulti-
mately sets the dutycycle on the buck converter depending on the sampled
sensor inputs. In this section the control scheme is described, and also an
example of the ADC interfacing process is given.
66
4.4.1 System State Machine
The main system control loop is implemented as a finite state machine (FSM)
that runs on a microcontroller. Currently there are three possible system
states, including two different regulation modes:
Figure 4.9: Main system loop state machine and transitions. The system
will at any time be in one of the four states depending on the conditions of
events.
MPPT State:
This is the main regulation mode and the implementation of the Perturb
& Observe algorithm described in Section 3.4.2. By tracking the MPP of
the solar panel, battery charge current is maximized. Seen from a battery
perspective, this mode takes care of the Constant Current (CC) charging
phase of the battery.
PID State
This is the secondary regulation mode which regulates the battery voltage
at 3.6V (or any voltage desired) with a discrete PID controller that can be
found in Appendix C. It takes care of the Constant Voltage (CV) phase of
charging, where the end-of-charge criterion is currently set at an arbitrary
minimum current. Hysteresis is built into the system to avoid oscillation
between the PID and MPPT state.
67
DISC state
This state disconnects the solar panels from the battery bus, and leaves the
system in a battery-discharge only condition. There isn’t any magic going on
here; the state simply discontinues PWM generation and activates internal
pull-downs on the microcontroller PWM port, leaving both the high-side and
SR switch in an open state. There should be an option to put the EPS system
in a low power mode in this state or as a separate state, but that has not
been implemented yet.
1. Power ON
2. Vbat >= Vbat(M AX) : Leave constant current mode and regulate battery
voltage.
3. Vbat < (Vbat(M AX) - hysteresis): Battery is below its float voltage, go
back to constant current mode.
4. An error flag is set or the charge current Ibat < Ibat(REF ) has dropped
to 10% (or any limit desired) of the max charge current and thus the
battery is per definition fully charged.
The error flags can be set to trigger on parameters such as battery over-
temperature, low solar panel voltage, or any other test that is implemented.
While the digital control algorithm has two regulation modes, the system has
four operating modes: MPPT charging, PID charging, MPPT discharging,
and battery only discharging.
68
is a stiff voltage source and represents the discharging battery. The battery
provides an appropriate amount of current to compensate for the discrepancy
between source line 1 and the load line, and thus only one equilibrium point
exists.
Current
Current
Source line 1
Load line
Figure 4.10: MPPT charge (left) and discharge (right) mode. When the load
is heavier than the solar panels can handle alone, the battery sources the
difference by discharging. When the load draw is less than what the solar
panels can handle, what is left goes to battery charging.
During the MPPT charging mode the battery acts as a varying voltage cur-
rent sink, and any extra power from the solar array will flow into the battery
to compensate for the discrepancy between source line 1 and the load line,
as shown to the left in Figure 4.10.
The change from MPPT charge to MPPT discharge mode does not cause
any stability problem since the converter always tracks the MPP of the solar
array[14]—the MPPT control algorithm doesn’t care if the battery is charging
or discharging. This is also in agreement with the tests that have been done
in Chapter 6.
During the last operating mode, when the battery is charged with constant
voltage, the battery is a constant power load line at any instant, as seen from
the solar array[14]. Since we’re moving off the MPP in this mode the solar
array voltage is floating, and will settle at the only stable operating point
towards the open-circuit condition, as discussed in Section 2.4.6. Thus, in
this operation mode, the solar array voltage will vary with load demand.
69
Current
P1 P2 > P1
Unstable
Stable
Voltage
Figure 4.11: During the PID (constant voltage) mode, the battery, as seen
from the solar array, is a constant power load line at any instant while the
solar array voltage is unregulated and floating. Only one stable equilibrium
point exists however, which is that towards the open-circuit voltage.
When the load increases to the point where the two operating points become
one, the system switches to MPPT mode.
Apart from deriving the transfer function for the output LC filter, no attempt
has been made to determine the cross-over frequency, open-loop gain and
phase margin for the system.
The analog control loop equivalent of this system has a well-documented set
of equations that can be used to determine the three mentioned criterions for
a stable system. However, for the digital control loop with multiple modes,
the situation is not as clear. It can be said, though, that the effective lag of
the digital-control loop is the combination of two effects: processing delay
and update interval. The former includes the analog-to-digital conversion
time and the MPPT/PID control-algorithm calculations, and the latter is
the dutycycle update interval of the respective regulation states.
70
4.6 Sensor to ADC - Analog Interface Design
The sensors and ADC are the previously mentioned eyes and ears of the
circuit, and deserve a little extra attention due to their importance. Four
measurement points, shown as circles in Figure 4.3, are currently sampled
and used in the control scheme. They are:
In order to utilize the entire dynamic range of the ADC, the sensor output
voltage span and the ADC input voltage span must be matched[4]. This is
in general a two-step process involving level-shifting and amplification with
op-amps as the prime candidate for the job.
Vin(min)
V out(min)
Amplification Level
Shifting
B
Figure 4.12: Transducer interface design (TID) block diagram.
In the first stage in Figure 4.12, the sensor’s output voltage is scaled (ampli-
fied) by a constant K, mapping the output range of the sensor to the input
range of the ADC. Once this is done the signal is shifted by a bias B, com-
pleting the interface circuit. The general equations for this process are linear
and can be stated as,
4
A dummy termistor located on the PCB is used here for now.
71
Vout(max) = K × Vin(max) + B (4.13)
Vout(min) = K × Vin(min) + B
where Vin(max) and Vin(min) represents the maximum and minimum output
voltages from the input transducer corresponding to the max/min physical
variables that the sensor measures. Similarly, Vout(max) and Vout(min) represent
the inherent voltage range of the ADC. Since we will be using the multiplexed
ATXmega ADC for all the sensed signals in the system, the output voltages
needed for all the interfaces will be the same. They are given by the maximum
allowed voltage reference which is given in the ATXmega datasheet as
The ADC is setup with differential sampling with the negative input grounded
so
Vout(min) = 0V (4.15)
We’ll apply this to the battery voltage sensor as an example, and let the rest
be, as it is just a matter of rinse and repeat for the other sensor inputs.
72
−B
K=
2.7V
−B
2V = 3.7V × +B
2.7V
and thus
K = 2
B = −5.4V
which can then used to calculate the resistor values in the op-amp circuit.
Referring to sheet 8 in the schematics (in Appendix), the resistor values can
be found from
µ ¶ µ ¶
R810 + R808 R810
VOU T = · VIN − VREF
R808 R808
73
4.7.1 Slave Reaction to Address Packet
The slave Address/Stop Interrupt Flag is set when a start condition suc-
ceeded by a valid address packet is detected. When this happens, the SCL
line is forced low, giving the slave time to respond or handle any data as
needed.
Case 3: Collision.
When the slave is unable to send a positive or negative acknowledgment,
the Collision Flag is set. This disables the data and (negative) acknowledge
output from the slave logic, and also releases the clock hold. A start or
repeated start condition will be accepted.
74
4.7.2 Receiving Data
75
Initialize
TWI Slave
No START
condition
Yes
ADR + RW
No Correct
ADR
Yes
Yes Write
Error
CTRLB
NACK
No
Write
CTRLB Legend:
ACK
In hardware
In software
Write
DATA
Tx
76
4.8 Powering the Microcontroller
The EPS reliance on the microcontroller for most of its tasks, raises a critical
question: How does the EPS provide power for itself?
There are two possible power sources available to the microcontroller; the
solar cells (VSA ) and/or the battery (VBAT ). The problem of choosing one
over the other can be traced back to a desire to operate the EPS continuously
throughout the orbit, and the need to be able to recover from a flat5 battery.
Since the solar array does not provide power during the eclipse, and the
microcontroller cannot run from a flat battery, the two requirements means
that neither the solar panels nor the battery can sustain system power on
their own.
VSA
VSA PG VµC
> 3.2V 1 VSA* Microcontroller
< 3.2V 0 VBAT
VµC
VBAT
3V LDO
Regulator VSA*
PG
Figure 4.14: Scheme for powering the system for the duration of an orbit.
A low dropout voltage regulator6 is used to step down the solar array voltage
to a usable VSA ∗ = 3.0V. As long as the LDO input is higher than about
3.2V, the regulator output will be stable at VSA ∗ = 3.0V and the PG signal,
being active high, keeps the PMOS turned off. If the array voltage drops
5
Defined here as below 2.7V where the uC no longer guarantees its current operating
clock frequency.
6
TPS76630 from Texas Instruments
77
below 3.2V, the active high Power Good signal pulls the gate of the p-type
MOSFET7 to ground—well below the threshold voltage (VGS(th) = −1.5V )
required to turn the FET on—at which point the MCU power is taken from
the battery.
Since the battery voltage range is within the rated input voltage range of
the microcontroller, the battery voltage is used directly without further reg-
ulation. This keeps the loss during the eclipse sleep-mode to the negligible
conduction loss in the MOSFET, while the LDO provides a stable power
source for the MCU during the period it matters the most.
A potential drawback with this approach is the switching back and forth in
the case of a free tumbling satellite. Testing should be done to evaluate this
effect, and a solution where the LDO’s active low enable signal is used to only
use the solar array power in the case of battery failure, should be considered.
The PG signal could also trigger an interrupt that disconnects the solar
array from the bus, and forces the microcontroller into a low-power sleep
state where it would stay for the duration of the battery-only power mode.
This idea has not yet been implemented though.
7
FDN306P from Fairchild Semiconductor
78
4.9 Fault Protection and Monitoring Unit
Each subsystem that is connected to the power bus via the backpanel, is
buffered from the main bus by a autonomous fault protection unit that also
monitors the subsystem’s current consumption.
TPS2556/57
2.5V – 6.5V 0.1 uF VOUT
IN OUT
RFAULT IN OUT
100 kΩ
RILIM CLOAD
ILIM
Fault Signal FAULT
Control Signal EN GND
Power Pad
99038V
IOS(max) = (4.17)
RLIM 0.947
where the current is given in units of amperes if RLIM is given in units of kΩ.
The ENABLE signal controls the device supply current and is compatible with
TTL and CMOS levels, allowing for a microcontroller to manually turn in-
dividual subsystems ON or OFF as necessary. The device also has a built-in
79
RS IS
VIN+
Up To 60V 3 4
VIN+ VIN–
Load
5kΩ 5kΩ
V+
5
OUT
VO = ISRSRL/5kΩ
GND 1
2
RL
undervoltage lockout with hysteresis (35mV) which disables the switch until
the input voltage reaches the turn-on threshold (2.35V).
A 25mΩ sense resistor was chosen in this prototype, which, together with the
2A upper limit set by TPS2556, and a maximum ATxmega ADC voltage of
2V, means that we need RL to be
Vo · 5kΩ 2V · 5kΩ
RL = = = 200kΩ
RS · IS 25mΩ · 2A
80
Fault Protection Unit
From To
Power Bus Rsense TPS2556 Subsystem
INA
FAULT
138
Manual
Current Fault Shutdown
Monitoring Detection (optional)
81
82
Chapter 5
PCB Realization
A total of three printed circuit boards (PCBs) were designed and realized.
Only the next two paragraphs will be devoted to the two first prototypes,
before moving on to the main focus of this section: the PCB realization of
the system described in Chapter 4. All work with the PCBs, from net list
to schematics through wiring board design and finally post-processing, was
done on the computer assisted design (CAD) suite Zuken Cadstar v12.1.
Figure 5.1: The first prototype was a two-layer PCB with a stand-alone buck
converter with a driver and some supporting electronics.
83
The first prototype, shown in Figure 5.1 was realized on a two-layer board
which basically consisted of a synchronous buck converter, a driver circuit,
snubber network, a current sensor and some testpoints. The PWM signal
was generated on a STK600/ATXmega development board from Atmel. This
setup met the wall around the time work on the control algorithm began and
the need arose to sample the various signals.
Figure 5.2: The second prototype was a four-layer PCB with on-board digital
control, sampling and LEDS and switches for debugging, in addition to the
buck converter on the right side of the board.
84
Figure 5.3: The third and last prototype is a four-layer PCB created with the
CubeSTAR module. It contains two redundant regulation blocks with JTAG
programmable digital parts, RS232 driver for debugging, I2 C interface, and
connectors for the solar panels and backpanel/battery connector.
The two available templates are the module and the backpanel templates.
However, neither the templates nor the design rules contained within them
are set in stone, and evolve—at the mercy of ELAB—with the student’s
designs and needs. Their current status is shown in Figure 5.5. Using the
module template means staying within the physical size of 80x75 mm with a
maximum building height of 25 mm. The backpanel template is only shown
85
here for the sake of completion, and will not be discussed further.
The board itself is a standard FR4 type, where the dielectric between the
copper planes is typically a woven fiberglass cloth that is reinforced with a
flame resistant1 epoxy resin.
SIGNAL 18 µm
GROUND PLANE 35 µm
1.6 mm
POWER PLANE 35 µm
SIGNAL 18 µm
Figure 5.4: Four layer PCB stackup showing the inter-plane plated through-
hole vias connections (not to scale).
Total board thickness is 1.6 mm with 18 µm (0.5 Oz) Cu foils for the signal
layers, and 35 µm (1 Oz) foils for the Ground and Power layers. Wherever
possible, 0603 SMD components were chosen for the passives, and plated-
through hole vias with dimensions 1.0/0.5 mm for inter-plane connections.
Where space was tight the via size was reduced to 0.6/0.3 mm, with the two
numbers representing via pad and hole diameter, respectively.
1
Flame Resistant, hence the abbreviation: FR4
86
Figure 5.5: The current status of the CubeSTAR module (top) and back-
panel (bottom) templates. Both were created and are maintained by the
Electronics Laboratory (ELAB) at UiO
87
5.2 Electromagnetic Compatibility
This section deals with some of the sources of EMC problems and what has
been done to minimize their effect in the PCB design and layout.
Being far from the ideal straight lines known from the schematics, real life
conductors always have a certain amount of resistive and reactive behavior.
Since these conductors inter-connect every part of the circuit, a quick look
at how they (mis-)behave may be a good idea. The geometry used in this
section is shown in Figure 5.6, where the distance d also will be used to
represent the height of a trace above a ground plane.
88
L
A
W H
d
Resistance
The trace resistance in Ohms per meter for a material with a given resistivity
ρ in nΩ·m is
ρ
Resistance (Ω/m) =
W ·H
where W and H are the trace width and height in units of meters, as illus-
trated in Figure 5.6. For example, a 5 cm long copper (ρ = 16.8 nΩ·m) trace,
with W = 1.0 mm and H = 18 µm, has a resistance of 47 mΩ. Resistance
versus trace width is illustrated in Figure 5.7.
Inductance
· ¸
5.98 · d
Inductance (nH/cm) = 1.996 × ln
0.8W + H
where W is the trace width and H is the trace thickness at a distance d above
the ground plane. Any units can be used for d, W, and H, as long as they are
consistent. For example, a 5 cm long trace with a cross section of 0.25 mm
x 18 µm, running 0.5 mm above its return ground plane, has an inductance
of roughly 25 nH. The effect of trace width on inductance is illustrated in
Figure 5.8.
89
2
10
Resistance per length (mΩ/cm)
0
10
0 0.2 0.4 0.6 0.8 1 1.2 1.4 1.6 1.8 2
Trace width (mm)
Figure 5.7: The resistance per length versus trace width for the two sheet
thicknesses used on the printed circuit board.
Capacitance
A
Capacitance = ²0 ²r
d
In fact, for frequencies below 500 MHz, the simplest way to improve the EMC
performance of a four-layer board is to place the signal layers as closely as
possible to the current-return planes, thus minimizing the current loop areas
at the expense of this small and insignificant inter-plane capacitance[25]. This
was not, however, implemented on the current prototype where equidistant
90
6.5
Loop Inductance per length (nH/cm)
6
18 µm copper sheet (0.5 oz)
36 µm copper sheet (1 oz)
5.5
4.5
3.5
0.1 0.15 0.2 0.25 0.3 0.35 0.4 0.45 0.5 0.55
Trace width (mm)
Figure 5.8: Loop inductance versus trace width for rectangular PCB traces
located 0.5 mm above a ground plane for the two different sheet thicknesses
used in the PCB.
Two things are immediately clear with that definition. First of all; noise
wins. There’s simply no way a real-life signal will look like the simulated
ideal signal. But there’s still hope; by reducing the undesirable effect or
interference of noise until the noise magnitude is at an acceptable level,
the problem is solved. Second, whether or not a signal is classified as noise
depends on where it is. A desired signal in one part of the system can become
noise if coupled to another part of the system.
91
The noise path is often illustrated as shown in Figure 5.9.
NOISE COUPLING
RECEPTOR
SOURCE CHANNEL
Figure 5.9: Typical noise path. All three blocks must be successfully identi-
fied to analyze a noise problem.
The source of noise can be grouped into three categories: 1) intrinsic noise
such as thermal and shot noise; 2) man-made noise such as digital electronics
and switching; 3) noise from natural disturbances such as sunspot activity
and lightning. Some of the techniques used to here to reduce noise are generic
and can be used on all kinds of noise, only noise reduction of the the second
category has been actively pursued here.
The coupling channel may be either a solid conductor which is run through a
noisy environment, or by means of electric and magnetic field coupling, while
the receptor in Figure 5.9 is the affected system.
A lot can be said about electrical currents, but one thing is universally true;
it can only flow in loops. Michael Faraday discovered that when the magnetic
flux enclosed by a loop of wire changes with time, a current is produced in
that loop, indicating that an electromotive force (emf) is induced around
the loop[22]. This wonderful result can be stated mathematically in what is
know as Faraday’s Law:
I Z
d
E · dl = − B · dS (5.1)
C dt S
where S is the surface bounded by the closed path C while E and B are
the electric and magnetic field vectors. The minus sign on the right-hand
92
side of Equation 5.1 ensures that Lenz’s Law is satisfied: the sense of the
induced emf is such that any current it produces tends to oppose the change
in the magnetic flux producing it. Solving Faraday’s Law for a given situa-
tion reveals that the induced emf is proportional to 1) loop area, 2) current
strength, and 3) frequency.
From a PCB perspective, the above result means that if the current drawn by
a device must take a long de-tour around the board before returning to the
device’s Vcc pin, a large current loop will be created which will be susceptible
to electromagnetic noise from surrounding sources, or, as in the case of high
current loops, create noise itself. Of the listed three, only loop area is usually
under the designer’s control at the production stage of development, and by
keeping it as small as possible, the risk of noise problems can be greatly
reduced.
By adding a separate ground plane as in Figure 5.4, the loop area is reduced to
the area traced by distance between the signal and ground planes in addition
to the track length. But ”ground” is not a magic black hole where current
disappears. The impedance of any conductor is complex and can be written
as
Zg = Rg + jωLg (5.2)
From Equation 5.2 it is clear how the ohmic resistance Rg dominates the
total impedance at low frequencies ω, while the inductance Lg dominates at
higher frequencies. Also, any conductor carrying a current will, per Ohm’s
Law, have an voltage drop associated with it. This is true also for ground
planes. The voltage drop (noise), which may cause interference in the ground
system, is given by
Vg = Ig Zg (5.3)
93
return current moves the focus more towards the actual path taken by the
ground current.
We then have two options if we want to minimize the ground noise voltage;
minimize Zg or decrease Ig by forcing the ground current through a different
path. The two different scenarios in Figure 5.10 illustrates how frequency
affects the current return path.
A A
Vsrc Vsrc
Path of least Path of least
resistance inductance
B B
Figure 5.10: The path taken by the return current in the ground plane is
dependent on frequency. At higher frequencies the return current seeks the
path of least inductance, which is traced out by the path that minimizes the
loop area.
In the low-frequency case, the current takes the path of least resistance, which
is the direct path from A to B in the ground plane. In the high-frequency
case, the current takes the path of least inductance (or loop area) which is the
return path in the ground plane directly under the signal trace. The distinc-
tion between low- and high frequency is typically a few hundred kilohertz[25],
and from the above discussion we can conclude that high-frequency signals
in fact behave as desired as far as reducing loop areas is concerned—that is,
as long as we don’t interrupt the signal path. On the other hand, the low-
frequency signals can create large and undesired current loops with improper
layout.
94
5.3 PCB Layout Noise Reduction Techniques
Noise and EMI issues with switch-mode DC-DC converters are often a result
of bad board layout and component placement[2]. Cutting corners here may
cause errant switching, excessive voltage ringing and even circuit latch-up.
So, not only does the layout dictate the EMC performance; getting it right
can be crucial to get correct functionality. Some of the techniques that were
used to tame the circuit are discussed below.
5.3.1 Decoupling
dI
VL = L ·
dt
it is clear the current spike will produce a corresponding voltage spike across
the trace inductances—an unwanted voltage which, per the definition in Sec-
tion 5.2.2, is regarded as noise on the line.
The exact capacitance value is not critical, but it can be calculated by con-
sidering the transient current demand in relation to the acceptable power rail
95
Rp Lp Lp1 Lp2
Rg Lg Lg1 Lg2
voltage droop. For example, if a chip sinks 10ns × 50mA current pulses and
the acceptable voltage droop is 0.2V, then
dV IC · ∆t
IC = C · ⇒ Cmin = = 2.5 nF
dt ∆V
Currents up to 1A, averaging around half that value, enter the board during
the constant current battery charge stage. Therefore, the current loop areas
for the on- and off states must be identified and minimized. This is shown
in Figure 5.12, where the the low-side mosfet supplies the load with current
while the high-side switch is off.
The loop created by the input capacitors and the two series MOSFETs is
kept as small as possible. By doing so, any noise generated by the pulsating
96
Figure 5.12: A cutout from the PCB illustrating some of the measures taken
to minimize circuit noise. The situation shows the high current loops while
charging the battery.
97
current in the input capacitors ESR and ESL is minimized, giving the high
side MOSFET the full input voltage to work from.
The loop formed by the low-side MOSFET, the inductor and output capacitor
is also minimized, as this helps reduce ringing on the switch (SW) node where
the power switches and output inductor meet.
Since the digital part of the PCB is separated with ”slots” in the ground
plane, it becomes paramount not to cross the gaps. In Figure 5.13 a portion
of the traces on the bottom signal layer can be seen. By forcing the traces on
the bottom layer directly above their ground return current path, the loop
areas are kept to a minimum.
Figure 5.13: The ground plane is separated into digital and analog sections.
By not crossing the gaps, the return current is forced to return underneath
the signal traces thus minimizing the loop areas.
98
tank formed by the (lumped) parasitic capacitance Cp and inductance Lp at
the node, as shown in Figure 5.14. The main culprits and cause of ringing
are the drain-to-source capacitance of the SR switch, package inductance in
the high-side switch and PCB traces and any capacitance seen looking into
the output inductor.
SW Lout
VIN node
High side
switch Lp Snubber
Csnub
Cp SR
switch
Rsnub
1
f0 = p (5.4)
2π Lp · Cp
The snubber’s basic function is to absorb energy from the node’s parasitic
reactances, which in turn means a reduction in voltage- and current spikes,
noise, and power dissipation in the SR switch. The energy is not saved,
however—dissipation is merely shifted from the SR switch to the snubber
resistor, thus providing less stressful operating conditions for the switch. It’s
also worth noting that, for a given switching frequency fsw , the dissipated
energy in the snubber network
1
Psnub = · Csnub Vin2 · fsw (5.5)
2
99
is independent of the snubber resistor value. In fact, the only influence
available over power dissipation at this point is the choice of Csnub , so care
must be taken when choosing its value.
The snubber capacitor is charged to Vin when the high-side switch turns on,
and discharged through Rsnub when the same switch turns off. This does not
mean the resistor can be chosen arbitrarily large however. One important
design constraint is that the chosen resistor value should be such that the
snubber RC time constant times three [6], is less than the minimum on-time
or maximum off-time of the power switches, i.e.
where T is the switching period and Dmin is the minimum dutycycle. This
allows the snubber capacitor to fully charge and discharge during each portion
of the switching period.
From an EMI/RFI perspective, the energy that flows back and forth be-
tween the Cp ’s electric field and Lp ’s magnetic field does not generally pose a
problem[16]. However, the nature of low-voltage converters require the use of
low gate threshold MOSFETs which are susceptible to parasitic turn-on if the
ringing dv/dt becomes large. Also, the low cost and ease of implementation
is in clear favor of using a RC network.
Parasitic Turn-on
The nature of low-voltage converters require the use of low gate threshold
MOSFETs. A large dV /dt on the switch node represents a potential failure
mode as these spikes may be capacitively coupled from the drain to the gate,
and thus inadvertently turning on the SR during its off state. This can be
understood by considering how a rising voltage on the switch node causes
currents to flow in the parasitic capacitances and inductances in Figure 5.15.
As Figure 5.16 shows, a rise on the SW voltage also raises the SR drain
voltage. This rate of change in voltage is related to the current flowing into
Cdg and Cds by
100
SR switch
L_pcb Ld
SW_node Drain
1nH 250pH
Cdg
PULSE(0 6 0 10ns 10ns 4us 8us)
330pF
V_in Driver
Lg
Gate
GS Cds
2nH 1240pF
Rg
8 Cgs
3310pF
Ls
350pH
.tran 10us
Source
--- D:\_temp_working_dir\SPICE\MOSFET_parasitic_equivalent_cir.asc ---
dv(t)
i(t) = C · (5.7)
dt
where Cgs should be added to Cdg in order to represent the total branch
capacitance, C, as seen from the drain node. This capacitance is three times
greater than that of Cds , so most of the current will be geared towards charg-
ing the the gate capacitance. The current into Cdg must either be shunted
to ground through the driver, or go into Cgs . The latter option causes the
voltage on Cgs to rise, and if left unattended this voltage rise may above the
gate threshold voltage and momentarily turn on the MOSFET. As mentioned
in Section 4.3, a scenario where both switches are turned on simultaneously
would short the input (i.e. the solar panels) to ground, and must be avoided
at all costs. A SPICE simulation model is presented in [16] which can be
used to predict this event a priori.
For this simulation the MOSFET used was IRF7456 (i.e., a different MOS-
FET from the one used to calculate the snubber network), but the model is
generic and can be used for any similar situation. The manufacturers nor-
mally characterize their MOSFETs indirectly in their datasheets by CISS ,
101
CRSS and COSS . Being functions of VDS their values are estimated from
plots in the datasheet at the maximum voltage that occurs across the device.
The maximum voltage seen at the SW node is
The parasitic inductances used are estimations from [16] where the typical
SO-8 package leads each contribute around 2 nH of inductance. With four
source leads, three drain leads and one gate lead, in addition to a small pcb
trace inductance, the model in Figure 5.15 was used to produce the plot in
Figure 5.16.
V(gs)
540mV
450mV
360mV
270mV
180mV
90mV
0mV
-90mV
-180mV
-270mV
-360mV
-450mV
-540mV
0µs 1µs 2µs 3µs 4µs 5µs 6µs 7µs 8µs 9µs
--- D:\_temp_working_dir\SPICE\MOSFET_parasitic_equivalent_cir.raw ---
Figure 5.16: The SPICE simulation shows that the dv/dt bump has an
amplitude of around 450 mV.
102
Simulation shows that shoot-through should not pose a problem under the
given conditions. The spike—peaking at around 0.450 V—is below IRF7456’s
gate threshold voltage Vth = 0.6V. This is comparable to the real-life situ-
ation shown in Figure 5.17 which was captured before the snubber was im-
plemented. The dv/dt bump can clearly be seen when the high side switch
closes. In fact, due to the short duration of the voltage spike, a threshold
crossing would probably not be a problem anyway due to the MOSFET’s
inherent turn-on delay.
Figure 5.17: Capacitive coupling of large dv/dt ringing on the SW node may
cause the SR gate voltage to rise above its threshold voltage while it is in
the ”off” state.
To counter the parasitic turn on effect, the following measures are taken:
103
3. keep the impedance from gate to source of the SR as low as possible
4. close attention to drive circuit layout: wide short track for low impedance,
GND track (plane) directly beneath it for low inductance and mini-
mized loop area in the circuit
The third point must be weighed up against the need to minimize the ex-
cessive inductive energy buildup by limiting the switching time on the main
switch. This is done by adding some resistance between the driver and the
gate, keeping in mind that this increases switching loss.
In Figure 5.19, a 4.7nF cap has been added across the SR switch, and the
frequency is now around 7.5MHz. Since the resonant frequency of an LC
circuit is inversely proportional to the square root of the LC product, we can
conclude from this that the node’s parasitic capacitance is a third of 4.7nF,
or
Cp ≈ 1500pF (5.8)
which is in agreement with the MOSFET’s given datasheet2 value for output
capacitance.
2
The mosfet used in this setup was Si4864DY from Vishay
104
Figure 5.18: Without the snubber, the switch-node (bottom curve) rings
with a period of T = 65 ns. The top curve is the high-side switch.
1
Lp = (T22 − T12 ) ·
4π 2 · Ctest
But with the prior knowledge of Cp as we now have, we can simply solve
Equation 5.4 for Lp .
105
Figure 5.19: By adding a lone 4.7nF capacitor (Rsnub = 0) across the SR
switch, the ringing period is increased to T = 130 ns.
1 1
Lp = 2
≈ ≈ 75nH (5.9)
(2π · f0 ) · Cp (2π · 15MHz)2 · 1500pF
The final step is to choose the snubber resistor such that it equals the char-
acteristic impedance of the resonant tank, allowing for damping near Q = 1.
1
Q= p =1
Rsnub Lp /Cp
or
s r
Lp 75nH
Rsnub = = = 7.1Ω (5.10)
Cp 1.5nF
106
Figure 5.20: By placing a RC snubber across the SR switch, very little ringing
is left on the switch-node waveform when the high-side switch (top curve)
closes.
The resistor value was rounded up to the nearest standard value and the
effect of the implemented snubber can be seen in Figure 5.20, where very
little ringing is left on the waveform.
107
108
Chapter 6
Test Results
All of the tests related to system performance were done on the second pro-
totype PCB.
This test was done to measure the dark current of the solar cells, which is
the second term of the output current from Equation 2.3, repeated here for
convenience:
· µ ¶ ¸
qVD VD
I = Isc − I0 exp −1 −
nkB T RSH
The procedure used here involved covering the solar cells to eliminate light-
generated current and then using a power supply to force electrical current
through the cell from the positive contact to the negative. The current and
voltage was measured as the power supply voltage was increased from zero
to a predetermined limit. The limit was set to a maximum current of 20mA,
to avoid damaging the cells. The voltage across the cell was measured along
with the drop over the resistor.
109
Two series UTJ cells
R
I=0
Vbias
Figure 6.1: Test setup of the two series connected cells in complete darkness.
A lab supply was varied and the voltage across the diode was measured. The
voltage across the resistor (R = 100 Ω) was used to calculate the current.
The resulting direction for current flow is opposite to that of the photo-
generated current (i.e. we’re in the fourth quadrant of the IV plot), but
the electrical configuration still means that the cell’s p-n junction is forward
biased as during normal operation. The test was repeated three times in
different temperatures: 23 ◦ C, 3 ◦ C and -20 ◦ C. Two series connected cells
were used.
y(x) = a exp(x / b)
−5 a = −4.41e−007
b = 0.29091
Current (mA)
R = 0.99354 (lin)
−10
Experimental: −20°C
Non−linear regression fit
−15
−20
0 1 2 3 4 5 6
Forward Bias Voltage (V)
110
0
y(x) = a exp(x / b)
a = −1.4328e−006
−5 b = 0.29137
R = 0.99909 (lin)
Current (mA)
Experimental: 3°C
−10
Non−linear regression fit
−15
−20
0 1 2 3 4 5 6
Forward Bias Voltage (V)
−2 y(x) = a exp(x / b)
a = −4.3707e−006
−4
b = 0.29365
−6 R = 0.99803 (lin)
Current (mA)
−8
Experimental: 23°C
−10 Non−linear regression fit
−12
−14
−16
−18
−20
0 1 2 3 4 5 6
Forward Bias Voltage (V)
111
Regression Analysis
The plot in Figure 6.5 was made by plotting the non-linear fits returned from
the Matlab extension package Ezfit.
−50
−100
Current (mA)
−150
23 °C
−200
−250
3 °C
−300
°
−20 C
−350
−400
−450
0 1 2 3 4 5 6
Forward Bias Voltage (V)
Finally, in Figure 6.6 a comparison was made between the extrapolated values
from the dark current measurements and the total output characteristics of
two series connected cells. The latter values were taken from the datasheet
which states temperature coefficient of -5.9 mV/◦ C.
112
Two Series UTJ Cells−−−Open−circuit Voltage vs Temperature
6.5
°
Datasheet temperature coefficent: −5.9 mV/ C per cell
Extrapolated results from Dark Current experiment
Linear fit: − 7.0 mV/°C per cell
Open−circuit Voltage (V)
5.5
4.5
4
−40 −20 0 20 40 60 80 100 120
Temperature (celcius)
113
6.2 UTJ Solar Cell Angular Response
This test was done to determine the angular response of two series connected
solar cells (see Section 2.5). The cells were mounted on a flat plastic assemble.
The location was the roof of the Chemistry building at UiO , 17th December
2009 at noon. Temperature was -7◦ C.
Measured values
1 Cosine Function
0.8
Normalized Current
0.6
0.4
0.2
0
0 20 40 60 80 100
Angle (degrees)
Figure 6.7: Angular response of two series connect UTJ solar cells.
Contrary to the theoretical prediction (i.e. the Kelly cosine) the experiment
showed a slight positive deviation from the cosine function. However, the
experiment was plagued by reflections from various directions, which has not
been controlled for.
114
6.3 Open Loop Dutycycle Stepping
In this test the solar simulator circuit was setup with an open-circuit voltage
of around 5.3V, and a short-circuit current of 0.67A, as shown in Figure 6.8.
The feedback loop on the prototype PCB was opened (in software) and the
dutycycle was manually stepped with switch buttons on the PCB, resulting
in the output in Figure 6.9. The dutycycle in the plots are 8-bit register
values that can be converted to percent of full dutycycle by multiplying by
255 and dividing by 100.
0.7
0.6
0.5
Current, I
0.4
0.3
0.2
0.1
0
0 1 2 3 4 5 6
Voltage, V
Figure 6.8: Solar simulator IV curve on which the MPPT testing was done.
It can be seen that, for this combination of open-circuit voltage and short-
circuit current, there exists an optimal ratio of input and output voltage
(i.e., the dutycycle) that results in the maximum output power from the
solar panel.
115
0.6
Charge Current, A
0.5
0.4
0.3
0.2
0.1
0
170 180 190 200 210 220 230 240 250
5.5
Solar cell voltage, V
4.5
4
170 180 190 200 210 220 230 240 250 260
2.5
Power, W
1.5
0.5
0
170 180 190 200 210 220 230 240 250 260
Dutycycle
Figure 6.9: The effect of dutycycle on current, voltage and power when the
solar simulator was set up with the I-V curve in Figure 6.8.
116
6.4 P&O Characteristic Oscillation
This test was done to illustrate the oscillating characteristic of the Perturb
and Observe MPPT algorithm. By holding down a press button on the
prototype board, the dutycycle was held at a low value. When the button
was released the system resumed normal operation and seeked out the MPP
as shown in Figure 6.10. Per definition the algorithm will oscillate around
the MPP.
225
220
215
210
205
Dutycycle
200
195
190
185
180
175
170
0 20 40 60 80 100 120 140 160 180
Time (s)
Figure 6.10: The control algorithm seeks out the maximum power point and
the characteristically oscillates around the MPP.
In this test the open-circuit voltage of the Solar Simulator circuit was varied
during the charging of a battery. This was done to simulate varying orbital
temperature and to evaluate the algorithm’s ability to track different power
117
levels. The ”temperature” was varied by adjusting trimpot B on the solar
simulator circuit. The solar simulator circuit output voltage and inductor
current was sampled and the product used as the y-axis value.
As can be seen in Figure 6.11, the response of the MPPT to abrupt changes
in Vmp results in undershooting. However, sudden changes (i.e. the time it
takes to turn a trimpot a couple of turns) in temperature are not expected
in orbit, except for perhaps the exit from eclipse where the system is thrown
back into action.
4
Simulated temperature
Solar Panel Output Power (W)
change
Simulated temperature
2 change
0
20 26 32 39
Time (min)
A single LiFePO4 cell that had been discharged to 2.9V with a 6 Ω resistor in
room temperature was used in this test. It was charged as shown in Figure
6.12, where the MPPT state takes care of the Constant Current phase while
the PID state takes care of the Constant Voltage phase.
The storage cell was then immediately discharged again with the 6 Ω resistor
118
to 3.24V this time. The PID float voltage was set to 3.6V and recharg-
ing resumed. The full charge-discharge-charge cycle with two different float
voltages (set in software) can be seen in Figure 6.13
In the first charging the float voltage was set to 3.47V and in the second
charging the float voltage was set to 3.62V. A note on the battery voltage
curve: the sampling time of one sample per 5 seconds does not catch the
spikes that can be seen on a scope. The spikes (not shown) have a duration
of about 10ns and an amplitude of around 400mV and occur on every rising
SW node flank, i.e., the noise frequency is—not surprisingly— equal to the
switching frequency. It’s unclear yet whether or not these spikes present a
problem, and no attempt has been made to remove them. However it is
possible that part of this effect could be traced back to a poorly damped
snubber network on the prototype during this test. Another source of uncer-
tainty here is the ground strap of the scope probe; earlier tests with different
ground strap lengths showed doubling and even tripled effect of overshoot
ringing due to the added ground strap inductance.
3.5 900
Battery Voltage
3.3 600
Battery Voltage (V)
Charge Current
PID State
MPPT State
3.1 300
DISC
State
2.9 0
0 13.6 27.2 40.7 54.3 67.9 81.4 95
Time (minutes)
119
The complete charge-discharge-charge cycle can be seen in Figure 6.13.
Figure 6.13: The first charge cycle was done with a float voltage (adjustable
in software) of 3.47V and the second charge cycle with 3.62V.
120
Circuit breaker
Solar Simulator
Regulator Variable
Circuit
dummy
load
Battery
Figure 6.15: MPPT mode. The battery voltage when a secondary load draws
current while the battery is charging. The three periods of dummy load draw
were done with increasing load; the first two are examples of MPPT charge
mode, and the third is MPPT discharge mode where the dummy load draws
more current than the solar array can supply.
121
Figure 6.16: PID mode. Similar dummy draws as in MPPT mode were done.
The two first that were within the solar array capability did not affect the
3.6V regulated battery voltage. The third attempt with a draw larger than
what the panels could handle, resulted in the battery discharging.
122
6.8 Over-discharge Abuse Tolerance
In this test the battery was discharged to 0.9V—well below the recommended
discharge cutoff at 2.0V. There was no sign of the battery struggling, other
than the quickly falling terminal voltage. Once the discharge was stopped the
battery was left with floating terminals. The next charge cycle was performed
Figure 6.17: Over-discharging the LiFePO4 cell to 0.9V. When the load is
removed, the battery voltage approaches 2.7V.
123
6.9 LiFePO4 Discharge in -17◦C
In this test a single LiFePO4 cell was charged to 3.6V in room temperature
and then discharged through a 10 Ω resistor in a kitchen freezer holding a
temperature of -17◦ C.
Figure 6.18: Setup for the -17 degree LiFePO4 discharge test.
The cell was then recharged again in room temperature to test if any per-
manent damage was done. The room temperature discharge curves before
and after the cold case were nearly identical and are therefor represented by
a single curve. Both the shape and level of the ”cold” discharge curve was
affected.
124
3.5
LiFePO4 discharged in room temperature
3.4
3.3
3.2
Voltage (V)
3.1
3
°
LiFePO discharged in −17 C
2.9 4
2.8
2.7
2.6
2.5
0 17 33 50 67 83 100 117 133 150
Time (min)
1
The battery is a 1100 mAh VARTA Easypack, which was tested in the early stages of
development.
125
4.2
4
1100 mAh Lithium Polymer (Varta EasyPack)
3.8
3.6
Voltage (V)
3.4
3.2
2.8
2.6
126
Chapter 7
Conclusions
This thesis has described an electrical power system prototype that is de-
signed to supply a free-trumbling CubeSTAR satellite with a continuous
orbital average power of around 2W, based on an assumed EPS efficiency of
around 80%. A single regulator has been shown to be sufficient to track the
maximum power point of the solar panels and charge the battery.
By implementing the control loop in software, the control system can evolve
with the CubeSTAR project as the need for new functionality arises. For
example, to speed up the digital control processing, a current-only measuring
scheme may be used for the maximum power point tracker[24].
The tests show that by using the proposed 4.4 Ah battery pack and a shal-
low depth of discharge, an unregulated 3.0V system should be within reach.
However, the test also show that the LiFePO4 cells react poorly to cold tem-
perature, and a reliable battery heater should be considered. The NASA
report found in [17] states an optimum temperature between 20 and 40◦ C for
most lithium ion batteries, and this is probably a good guideline for lithium
iron phosphate cells too.
The flat discharge curve of the LiFePO4 cells are promising, as is their ap-
parent abuse tolerance. But with no flight-history (as far as I know) and
without the proven record in space that for example Lithium ion polymer
has, the question remains: can these batteries fly? Vacuum testing should
be a minimum requirement before launching Lithium Iron Phosphate into
127
space.
The system fits comfortably within the specified module PCB area. Apart
from decoupling and a serial driver for debugging, only the top side was used.
A consequence of trying to save precious PCB real-estate on this prototype,
each side’s protection diode must be placed external from this prototype
together with the joint that connects two opposite faced solar panels.
128
Bibliography
129
[12] Abraham I. Pressman, Keith Billings, and Taylor Morey. Switching
Power Supply Design, Third Edition. McGraw Hill, New York, 2009.
[13] Edward J. Simburger, Daniel Rumsey, David Hinkley, Simon Liu, and
Peter Carian. Distributed Power System for Microsatellites.
[16] Brian Lynch and Kurt Hesse. Under the Hood of Low-Voltage DC/DC
Converters. Technical report, 2003.
[19] Mukund R. Patel. Spacecraft Power Systems. CRC Press, Boca Raton,
2005.
[20] Paul R. Sharps. Growth and Development of GaInAs for Use in High-
efficiency Solar Cells. Research Triangle Institute, Annual Subcontravt
Report, page 10, 1992.
130
[24] V. Salas, E. Olias, A. Lazaro, and A. Barrado. New Algorithm using
only One Variable Measurement Applied to a Maximum Power Point
Tracker. Solar Energy Materials & Solar Cells, 87:675–684, 2004.
131
132
Appendix A
A.1 Motivation
While xenon-lamp based solar simulators are available, their cost, size and
heat make them impractical for the purposes described above. To overcome
these issues, a power supply was built that simulates the behavior of a single
side’s panel (i.e., two parallel strings of two cells in series).
133
I-V curve1 for a single cell is shown in Figure A.1. Due to the negligible
difference between the characteristic I-V curve of the circuit’s chosen silicon
diode (IN4148) and that of the Ge-GaAs-InP based solar cell, the only re-
maining parameters of interest are the short-circuit current and open-circuit
voltage (i.e., we know the shape but need curve’s end points).
and with an open-circuit voltage of 2.665V coupled with the fact that the
curve is of exponential nature, we have the information needed to replicate
the behavior in the simulator circuit.
1
The plot is from Spectrolab’s datasheet, to be found here:
http://www.spectrolab.com/solarcells.htm
134
Figure A.1: I-V characteristics for a single 28.3% Ultra Triple Junction (UTJ)
solar cell.
It’s assumed that all four solar cells that make up the four panels on each
face are exposed to the same insolation and temperature. The series-parallel
135
panel configuration means that the short-circuit current and open-circuit
voltage from Table A.1 both can be multiplied by two. By choosing a 50Ω
trimpot for Rb and a 2kΩ trimpot in series with a 3.3kΩ resistor for Ra , the
circuit can be used to simulate the entire range of expected insolation and
the temperature-dependent voltage range from about 4V to 6V.
In the SPICE plot in Figure A.2, Rb = 36Ω and Ra = 4.3kΩ were arbitrarily
chosen with the resulting I-V and P-V curves shown.
1 4
Current (A)
Power (W)
0.5 2
0 0
0 1 2 3 4 5 6
Voltage (V)
136
Constant Current/Reference Generator Power Supply
9V 9V 5V
U1
-5V
5V V3 V1 V2
R6 UA741
220k R5 -5V
9 5 -5
REF_out
100 D1
1N4148
Dummy Load
R1 R3 Rb
OUT_pos
I_Load
100 1 {RB} 0.5
Rsh_1 Rsh_2
1 0.1
.step param RB 0.01 50 5 OUT_neg
OUT_neg
.dc I_Load 0 2000mA 1mA
137
Output Amplifier
Temperature Correction
9V
R12 9V
R11 U3
820k Q1
220k FZT849
5V
UA741
-5V
REF_out R10 9V
220k Ra R2
U2 R13
R9 OUT_pos
9V 3.3k 1
UA741 1k C1
3.9k R7
220k R8 -5V 0.1µF
D2 220k
1N4148 .step param RA 1k 2k 200 OUT_neg
The SPICE circuit in Figure A.3 was realized on a two-layer PCB, illustrated
in Figure A.4 and Figure A.5. Some minor rework (not shown) was needed
before the circuit worked as intended, and a heatsink was also added to
prevent the transistor from overheating.
ELAB-2010
SOLAR CELL SIMULATOR V3.3
CN1 C5
C2 Martin Oredsson
X2 07/07/2010
C6 C4
TP1 X3
C7
D2 R6
R8
R10 TP7
R4
X5
C8
R5 TP2
R9
Q1 R7
TP6
X4 R1
R2
TP3
R11 X1
D1
C3
P1 R3
C1
R13 P4
1
R14
R12
CN3 TP4
TP5
TopElec
TopSilk
BotElec
BotSilk
Figure A.4: Two layer circuit layout. Note: the ground connection for the
shunt resistor R12 should be re-routed with a shorter track.
138
Figure A.5: The finished mounted PCB with a 8-pin male output connector
from ERNI.
A.5 Results
A 50Ω potentiometer was used as a varying load to generate the I-V curves
in Figure A.6. These curves correspond well to the SPICE simulation and
the I-V curve from the UTJ datasheet, enabling us to use this circuit as the
power source while working with the EPS system.
139
0.7
0.6
0.5
Current (A)
0.3
0.2
0.1
0
0 1 2 3 4 5 6
Voltage (V)
0.9
0.8
0.7
0.6
Current (A)
0.5
0.4
0.3
0.2
140
Appendix B
The first two lines of the program defines a subcircuit named utj using the
.subckt keyword, with nodes 100, 101, and 102:
The listed parameters are cell area, diode saturation currents j0x for each
junction semiconductor material, short-circuit current density jsc, series re-
1
This approach also leaves the door open to later include input parameters such as sun
irradiance, temperature variations and load effects.
141
sistance rs, and shunt resistance rsh. All are loaded with dummy values at
this stage which are replaced by real values once the circuit is excited.
Gxxx n+ n- value={expression}
Jsc A
Isc = G (B.1)
1000
In the next six lines, the three pn-junctions of the solar cell are represented by
diode definitions and their models. The general form of the diode definition
in SPICE is
but we only need the saturation current here, and if we take the Germanium
junction as an example, the code becomes
142
DGe 103 104 Ge
.model Ge D(IS={j0a*area})
In the next section, we’ll throw the subcircuit into an excitation circuit and
create some plots.
The subcircuit in Figure B.1 is excited with two voltage sources; Vbias and
Virrad, where the latter represents the irradiance.
The characteristic I-V curve is then easily obtained by sweeping the bias
source over the operating range of the cell while Virrad source is set to
1366 W/m2 . Comparing the curve against Spectrolab’s own datasheet plot
in Figure A.1, the saturation current within the subcircuit can be adjusted
until a satisfactory match is obtained.
143
Figure B.1: SPICE circuit used to generate the plots in this section.
By parameterizing the value of our irradiance source with the following lines
we can plot four I-V curves for four different values of insolation to illustrate
the current-irradiance relationship.
Although there are other factors that come into play regarding the temper-
ature dependence of the solar cell, one of the dominant factors, and one
which we have at arms length in our model, is the saturation current I0 . By
parameterizing it with
and combining the result with the fact that Spectolab’s UTJ cells have a
negative temperature coefficient of -5.9 mV/◦ C, the information can be pre-
sented graphically as in Figure 2.8.
144
1 . i n c l u d e UTJ subckt . l i b
2 X1 0 31 32 u t j params : a r e a =26.62 r s ={RS} r s h =300
3 + j s c =17.05 j 0 a =9.5 e −20 j 0 b=1e −16 j 0 c =1e −14
4 Vbias 31 0 dc 0
5 V i r r a d 32 0 dc 1366
6 RS = 50 e−3
7 ∗ . param RS=0.001
8 ∗ . s t e p param RS l i s t 0 . 0 0 0 1 0 . 0 0 1 0 . 0 1 0 . 1 1
9 . p l o t dc i ( v b i a s )
10 . dc v b i a s 0 3 0 . 0 1
11 . probe
12 . end
Listing B.2: Exciting the sub-circuit.
145
146
Appendix C
A PID controller[1] is used to stabilize the voltage during the constant voltage
charging phase1 . By measuring the process value (battery voltage) and com-
paring this value to the reference (the preset battery float voltage), the error
can be calculated and used to determine the new process input. This input
will then try to adjust the measured process back to the desired setpoint.
147
stationary error. A high valued P term results in a large change in the output
for a given change in the error, and/but setting the it too large will result
in a unstable system. Setting it low results in a less responsive/sensitive
controller, which might be unable to react quickly enough to variations in
the input.
The Integral term adds the sum of the previous errors to the system control
input, and as such is proportional to both the magnitude and duration of the
error. By summing up the error over time and multiplying with the integral
gain Ki , the I-term returns the scaled accumulated offset that should have
been corrected previously.
Zt
Iout = Ki e(τ ) dt (C.2)
0
By adding the I term to the P term, the stationary error from the P only
case, is removed. However, since the I term is also responding to accumulated
errors from the past, overshooting the setpoint is a typical side-effect. These
issues should be dealt with by tuning the loop with one of the plethora of
tuning methods available.
148
C.3 Derivative Term
The derivative term deals with the rate of change of the process error, and is
calculated by determining the slope of the error over time. This rate is then
multiplied by the derivative gain Kd :
de(t)
Dout = Kd (C.3)
dt
The end effect of the D term is to slow down the rate of change of the
controller output, which might be used to counter the overshoot effect from
the I term.
C.4 Implementation
The three terms are then added together and returned as the controller out-
put u(t)
Zt
de(t)
u(t) = Kp · e(t) + Ki e(τ ) dt + Kd (C.4)
dt
0
y0 e u Buck y
PID Regulator
-
Figure C.1: When the system is in the CV state the PID regulator controls
the buck converter dutycycle.
149
In the digital world, integrals become sums and derivatives become slopes,
so
Ztk k
X
e(τ ) dτ → e(ti )∆t (C.6)
0 i=1
Td d/dt
e u
Kp
Ti
Kp T Kp Td
where Ki = Ti
and Kd = T
A plethora of methods exists in the literature, but with limited time to invest
in the interesting topic of PID tuning, the PID regulator was tuned by trial
150
and error until a satisfactory result was achieved. The P, I, and D terms are
in any case readily available and easy to change in the PID.h header file.
151
152
Appendix D
This appendix provides a quick breakdown of the TWI bus and the neces-
sary background information for the described telemetry implementation in
Section 4.7.
Atmel’s I2 C compatible TWI bus operates at 100 kbp/s and consists of two
active lines; Serial Data (SDA) and Serial Clock (SCL). Both are bidirectional
open-collector lines that require pull-up resistors. Any device connected to
the TWI bus has a unique address and acts as either a master or slave, with
the former being the initiator of data a transaction.
On a idle bus, both SDA and SCL are high. To initiate a transaction, a
device must first pull SDA low before pulling SCL low, as in Figure D.1.
This is called a START condition (S). By initiating a transaction with the
start condition, a device automatically becomes the master, and all other
connected devices are considered slaves until a STOP condition (P) is issued.
153
The stop condition, being the start condition’s dual, is initiated by first
releasing the SCL line, followed by the release of the SDA line.
Further, a master can prevent other masters from starting their own transac-
tions by sending a new start condition before stopping the current one. This
is known as a REPEATED START, and can be used by the master to address
another slave without first generating a stop condition.
SDA SDA
SCL SCL
S P
START STOP
CONDITION CONDITION
SU00362
Figure6.D.1:START
Figure Start and
and stop
STOP conditions.
conditions
D.3 Address
After the start condition, the next seven bits contain the ADDRESS (A) of the
slave followed by a R/W bit which specifies the direction of the transaction.
When a slave recognizes its address it will ACKnowledge by pulling SDA low
in the next clock cycle. Meanwhile, all other slaves should keep the TWI
lines released (hence the need for pull-ups), and wait for the next START–
ADDRESS–R/W sequence.
154
MSB LSB
R/W
SLAVE ADDRESS
DATA OUTPUT BY
TRANSMITTER
DATA OUTPUT
BY RECEIVER
START
CONDITION
CLOCK PULSE FOR ACKNOWLEDGMENT
In the bottom part of Figure D.4, the read/write bit is low, indicating a
master write transaction. The data transfer will proceed once the slave has
acknowledged its address, and the transaction will be on-going for a arbitrary
number of DATA packets as long as no stop condition is initiated.
The master read transaction, shown in the top part of Figure D.4, is initiated
by setting the read/write bit high. When the slave acknowledges the address,
the master can start receiving data from the slave. Again, there is no inher-
ent limitation to the number of data packets that can be transferred—the
transaction is terminated when the masters sends a NACK followed by a stop
condition.
A third transfer modus is possible by combining the write and read transac-
tions into a combined transaction. By sending a REPEATED START–ADDRESS–
R/W, the master can at any time change the direction of the data transfer
within a transaction.
155
ÎÎ
ÎÎ
ÎÎÎÎÎÎÎ
S
ÎÎ
ÎÎÎÎÎ ÎÎ
ÎÎ ÎÎ ÎÎÎÎÎÎ
ÎÎ
SLAVE ADDRESS
1
DATA TRANSFERRED
ÎÎ
ÎÎÎÎÎÎÎÎÎÎ ÎÎÎ ÎÎ
(READ) (n BYTES + ACKNOWLEDGE)
ÎÎ
ÎÎÎÎÎ
ÎÎÎÎÎ
S
ÎÎÎÎÎ ÎÎÎ
ÎÎÎÎÎÎÎÎ ÎÎÎÎ
SLAVE ADDRESS R/W A DATA A DATA A/A P
ÎÎÎ
ÎÎÎÎÎÎÎ ÎÎ
ÎÎÎÎÎ
ÎÎ ÎÎ
DATA TRANSFERRED
ÎÎ
‘0’ (WRITE) (n BYTES + ACKNOWLEDGE)
ÎÎÎ
ÎÎÎÎÎ
ÎÎÎÎ ÎÎ
ÎÎÎÎÎ
ÎÎ
FROM MASTER TO SLAVE
ÎÎ
ÎÎÎÎÎ
ÎÎ ÎÎ ÎÎ
ÎÎ
Although the clock is always controlled by the master, any device on the bus
ÎÎ
ÎÎÎÎÎ
ÎÎ ÎÎ ÎÎ
ÎÎ
can hold the clock low at any time, thus providing a slave a way to hold back
a transaction in case it needs more time to process data. When this happens,
the master cannot continue clocking, and the slave is said to perform clock
stretching.
ÎÎÎ
ÎÎÎÎÎ
ÎÎÎ ÎÎ
ÎÎÎÎÎ
ÎÎ ÎÎ
ÎÎÎÎÎ
ÎÎ ÎÎ
ÎÎÎÎÎ
ÎÎ ÎÎ
ÎÎ
156
Appendix E
Production Files
The following sections contain the parts list, schematics and Gerber files that
were created with the computer assisted software suite Zuken Cadstar V12.1.
157
E.1 Parts List
158
partslist.rep
--------------------------------------------------------------------------------
Parts List
CADSTAR Design Editor Version 12.1
Design: C:\_workdir\Cadstar_wrk\V1.5\V1.5d\EPS_Prototype_v1.5d.scm
Design Title:
EPS CubeSTAR Prototype
Date: 16. september 2010
Time: 12:11
--------------------------------------------------------------------------------
Part Name/Number Description Qty. Comps.
---------------- ----------- ---- ------
X-XX-XXX-XX ATMEL AVR MICROCONTROLLER 2 U701
U1701
X-XX-XXX-XX BURR BROWN CURRENT SHUNT MONIT 2 X501
X1501
E-65-759-63 10% 16V 0603 X7R 49 C303
C403
C501-502
C601
C701-713
C801-802
C804-805
C901-905
C1303
C1403
C1501-1502
C1603
C1701-1713
C1802-1805
E-65-758-49 10% 50V 0603 X7R 2 C803
C1801
E-65-757-81 10% 50V 0603 X7R 2 C307
C1307
RS-248-007 ERNI 1.27mm SRC SINGLE ROW MIN 2 CN201-202
E-43-714-31 13X2 TYCO PINROW ANGELED 1 CN203
E-43-704-33 5X2 SCOTT ELEC. PINROW 2 CN701
CN1701
F1713895 SMD SCHOTTKY DIODE 20V/2A 2 D401
D1401
F-9550780 SMD VERY LOW DROP SCHOTTKY DIO 2 D301
D1301
F1635948 WURTH CHOKE, SMD, 100UH 2 L301
L1301
E-58-830-04 KOA SMD-W COIL 2 L601
L1601
F-1422325 MOSFET DRIVER, DUAL, 1.5A 2 X402
X1402
F-XX-XXX-XX +/-5% 0402 LQG15H-series 2 L602
L1602
F-1663786 MICROPOWER OPAMP 6 X801-803
X1801-1803
F-1197392 CHARGE PUMP VOLTAGE DOUBLER 2 X401
X1401
RS-661-6468 LDO, 3.0V 2 X601
X1601
E-60-440-02 RESISTOR KOA 0603 1% 0.1W 8 R304
R803
R811-812
Page 1
159
partslist.rep
R1304
R1805
R1808
R1811
F-1703806 CURRENT SENSE RESISTOR 1206 1% 2 R301
R1301
E-60-452-64 RESISTOR KOA 0603 1% 0.1W 4 R801-802
R1807
R1809
E-60-450-25 RESISTOR KOA 0603 1% 0.1W 6 R601
R703
R804
R1601
R1703
R1803
E-60-445-80 RESISTOR KOA 0603 1% 0.1W 2 R602
R1602
E-60-448-46 RESISTOR KOA 0603 1% 0.1W 4 R701-702
R1701-1702
E-60-451-08 RESISTOR KOA 0603 1% 0.1W 2 R807
R1812
E-60-451-24 RESISTOR KOA 0603 1% 0.1W 2 R806
R1804
E-60-451-40 RESISTOR KOA 0603 1% 0.1W 2 R809
R1806
E-60-451-57 RESISTOR KOA 0603 1% 0.1W 2 R808
R1801
E-60-454-05 RESISTOR KOA 0603 1% 0.1W 2 R501
R1501
E-60-451-73 RESISTOR KOA 0603 1% 0.1W 2 R805
R1810
E-60-438-71 RESISTOR KOA 0603 1% 0.1W 4 R302-303
R1302-1303
E-60-452-56 RESISTOR KOA 0603 1% 0.1W 2 R810
R1802
F-1053844 VOLT REF, 2.048V, 0.5%. uPOW 2 D601
D1601
E-73-217-48 DUAL RS-232 TX/RX 3.0V - 5.5V 1 IC901
E-35-790-18 ALPS-SMD PUSH BUTTON 2 SW701
SW1701
F-1658504 SOLID TANTAL CAP 4 C401-402
C1401-1402
F-1754123 TANTAL ELECTROLYTIC CAP 10 C302
C305-306
C603-604
C1302
C1305-1306
C1602
C1604
F-1754003 SOLID TANTAL CAP 4 C301
C304
C1301
C1304
E-67-732-46 TANTAL ELECTROLYTIC CAP 4 C404
C602
C1404
C1601
E-67-736-34 TANTAL ELECTROLYTIC CAP 2 C605
C1605
F1471047 P-CHANNEL MOSFET 12V/2.6A 0.5W 2 M601
M1601
F-9102639 N-CHANNEL MOSFET 20V 4 Q301-302
Q1301-1302
--------------------------------------------------------------------------------
End of report
--------------------------------------------------------------------------------
Page 1
160
E.2 Schematics
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
E.3 Gerber Files
177
Layer 1: TopSilk Layer
This layer contains all visible text on the top side of the finished PCB, in-
cluding text for component names, connectors and testpoints.
Figure E.1: TopSilk layer includes component names, outlines and other
visible text.
178
Layer 2: TopStop Layer
This layer defines the solder resist mask, giving the finished PCB its charac-
teristic green color. The solder mask greatly simplifies the soldering process
because it treats solder paste during reflow much in the same way that oil
treats water. Thus by having a solder resist between pads, the risk for solder
”bridges” (a short circuit) between component pins is greatly reduced. The
pads on this layer are oversized by 8 mils to provide a buffer zone around the
pad.
179
Layer 3: TopPaste Layer
This layer defines the mask for the soldering stencil, if such a stencil is used.
The stencil is a aluminium sheet with openings where the pads are. Once
in place the solder may be applied and once the stencil is removed, only the
pads are left covered with solder. The pads on this layer should be undersized
by 10% to avoid smearing.
Figure E.3: TopPaste layer defines the openings in the soldering paste stencil.
180
Layer 4: TopElec Layer
This is the top copper layer, and it carries most of the signal traces on the
board. Among these are the high-current input from the solar cells, the
switch node, and the mosfet drive signals which are all routed uninterrupted
on this layer.
Figure E.4: TopElec layer is the first copper layer and defines the copper
tracks and pads on the layer.
181
Layer 5: Ground Layer
The second, and arguably the most important, copper layer—mistakes made
here are punished hard by mother nature. The ground plane is separated
into areas for analog and digital to avoid the issues discussed in Section 5.3
Figure E.5: Ground layer is the second copper layer. It is segregated into
analog, digital and battery parts.
182
Layer 6: Power Layer
The third copper layer is the power plane, which is split into solar array
power, digital power and battery power areas. The latter is the battery
”bus” from which the remaining satellite subsystems are powered.
Figure E.6: Power layer is the third copper layer. It is split into power
”islands” for two opposite solar array side, digital, and battery.
183
Layer 7: BotElec Layer
The fourth and last copper layer is the bottom signal layer. It is mainly used
for decoupling and routing digital traces. It also holds the RS-232 driver
used for debugging.
Figure E.7: BotElec layer is the fourth and last copper layer and defines the
copper tracks and pads on the layer.
184
Layer 8: BotStop Layer
This is the solder resist mask for the bottom layer, see TopStop.
Figure E.8: BotStop layer defines the solder resist mask for the bottom layer.
185
Layer 9: Drill File
The NC (numeric control) drill file was created with Exellon’s control codes,
and defines the drill holes on the board. The dimensions of vias, testpoints,
and any other through holes are defined here.
Figure E.9: Drill layer is not really a layer, but in any case, it defines the
drill holes for all the plated vias and testpoints used.
186
Appendix F
187
30 // Setup printf () for debugging purposes .
31 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
32 FILE mystdout = F DEV_SE TUP_ST REAM ( uart_putchar ,
33 NULL ,
34 _FDEV_SETUP_WRITE ) ;
35
36 int main ( void )
37 {
38 // Connect the standard output
39 // to the address of mystdout
40 stdout = & mystdout ;
41
42 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
43 // Setup the GPIO ports for their respective duties
.
44 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
45 // PWM output on PORTC
46 PORTC . DIRSET = 0 xFF ;
47 // Switches input on PORTF
48 PORTF . DIRSET = 0 x00 ;
49
50 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
51 // Initialize System Peripherals
52 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
53 // Sets the system - and peripheral clocks .
54 CLK_init () ;
55
56 // Enable high - level interrupts
57 P M I C _ S e t V e c t o r L o c a t i o n T o A p p l i c a t i o n () ;
58 PMIC . CTRL |= PMIC_HILVLEN_bm | PMIC_LOLVLEN_bm ;
59
60 // Enable interrupts globally
61 sei () ;
62
63 // Enables and starts PWM on PORTC [0:1].
64 PWM_Start () ;
65 // Sets up the serial comm . link used for debugging
.
66 USART_init () ;
67 // Initialize the adc converter channels .
68 ADC_init () ;
69 // Initialize PID regulator
70 pid_Init ( K_P * SCALING_FACTOR ,
71 K_I * SCALING_FACTOR ,
72 K_D * SCALING_FACTOR ,
73 & pidData ) ;
74
75 // Initialize TWI slave
76 T W I _ S l a v e I n i t i al i z e D r i v e r ( & twiSlave ,
188
77 & TWID ,
78 T W ID_S lave Proc essDa ta ) ;
79 TWI_SlaveInitializeModule ( & twiSlave ,
80 SLAVE_ADDRESS ,
81 T W I _S LA VE_ IN TL VL _HI _g c )
;
82
83 typedef struct {
84 unsigned char NextState ;
85 unsigned char Error ;
86 } No rmalP ar am et er s_ t ;
87
88 Nor ma lP ar amet er s_t NormalParameters ;
89 unsigned char CurrentState = ST_MPPT ;
90 uint16_t SAvoltage , SAcurrent , BatVoltage ;
91 char i = 0;
92
93 unsigned char NormalMode ( unsigned char inp )
94 {
95 unsigned char NextState ;
96 SAvoltage = So l a rArr ay N SVolt age () ;
97 SAcurrent = So l a rArr ay N SCurr ent () ;
98 BatVoltage = BatteryVoltage () ;
99
100 switch ( CurrentState ) {
101
102 case ST_MPPT :
103 MPPT ( SAcurrent , SAvoltage ) ;
104 NextState = ST_MPPT ;
105 if ( BattData . Voltage >= BAT_VOLTAGE_MAX )
{
106 NextState = ST_CVOLTAGE ;
107 NormalParameters . NextState =
NextState ;
108
109 } else if ( BattData . Voltage <
BAT_VOLTAGE_MAX ) {
110 NextState = ST_MPPT ;
111 NormalParameters . NextState =
NextState ;
112 }
113 break ;
114
115 case ST_CVOLTAGE :
116 ST_CVoltage () ;
117 if ( BattData . Voltage <=
118 ( BAT_VOLTAGE_MAX -
BAT_VOLTAGE_HYST ) ) {
119 NextState = ST_MPPT ;
189
120 NormalParameters . NextState =
NextState ;
121 } else {
122 NextState = ST_CVOLTAGE ;
123 NormalParameters . NextState =
NextState ;
124 }
125 break ;
126
127 case ST_DISCONNECT :
128 ST_Disconnect () ;
129 if ( BattData . Voltage <=
130 ( BAT_VOLTAGE_MAX -
BAT_VOLTAGE_HYST ) ) {
131 PWM_Start () ;
132 NextState = ST_MPPT ;
133 NormalParameters . NextState =
NextState ;
134 } else {
135 NextState = ST_DISCONNECT ;
136 NormalParameters . NextState =
NextState ;
137 }
138 break ;
139
140 case ST_POWERSAVE :
141 break ;
142
143 case ST_SOFTSTART :
144 break ;
145
146 default :
147 break ;
148 }
149 return ( NextState ) ;
150 }
151
152 while (1) {
153 CurrentState = NormalMode (1) ;
154
155 // Usart Debugging info
156 i ++;
157 if ( i ==50)
158 {
159 printf ( " % d % u % u % u % u \ n " ,
160 NormalParameters . NextState ,
161 SolarPanelNS . Current ,
162 SAvoltage ,
163 BattData . Voltage ,
190
164 DutyCycle ) ;
165 i = 0;
166 }
167 }
168
169 SetDutyCycle (185) ;
170 return 1;
171 }
172
173 void UpdateTWI ( void ) {
174 for ( uint8_t i = 0; i <8; i ++) {
175 twiSlave . sendData [ i ] = GetTelemetry ( i ) ;
176 }
177 }
178
179 void T W I D _ S la v e P r o c e s s D a t a ( void )
180 {
181 uint8_t bufIndex = twiSlave . bytesReceived ;
182 twiSlave . sendData [ bufIndex ] =
183 (~ twiSlave . receivedData [ bufIndex ]) ;
184 }
185
186 /* TWI slave Address or Stop Interrupt vector .
187 *
188 * TWID Slave Interrupt vector .
189 */
190 ISR ( TWID_TWIS_vect )
191 {
192 UpdateTWI () ;
193 T W I _ S l a v e I n t e r r u p t H a n d l e r (& twiSlave ) ;
194 }
195
196 /* Timer / Counter Overflow Channel A Interrupt vector .
197 *
198 * Updates the dutycycle buffer once per period .
199 */
200 ISR ( TCC0_OVF_vect )
201 {
202 TCC0 . CCABUF = DutyCycle ;
203 }
204
205 /* Timer / Counter Compare or Capture Channel A
206 * Interrupt vector offset .
207 * Used by the PID regulator to set the update flag .
208 */
209 ISR ( TCC1_CCA_vect )
210 {
211 static uint16_t i = 0;
212 if ( i < TIME_INTERVAL )
191
213 i ++;
214 else {
215 gFlags . pidTimer = TRUE ;
216 i = 0;
217 }
218 }
219
220 /* Move interrupt vector table to application area .
221 *
222 * This function moves the interrupt vector table
223 * to application area . The function writes the
224 * correct signature to the Configuration Change
225 * Protection register before writing the CTRL
226 * register . Interrupts are automatically ignored
227 * during the change enable period .
228 */
229 void P M I C _ S e t V e c t o r L o c a t i o n T o A p p l i c a t i o n ( void )
230 {
231 uint8_t temp = PMIC . CTRL & ~ PMIC_IVSEL_bm ;
232 CCP = CCP_IOREG_gc ;
233 PMIC . CTRL = temp ;
234 }
235
236 uint16_t S ol a r Ar r a yN S Vo lt a ge ( void )
237 {
238 uint16_t SAVoltage = ReadADC (& ADCA . CH1 , offset_ch1 ,
5) ;
239 SolarPanelNS . Voltage = SAVoltage ;
240 return ( SAVoltage ) ;
241 }
242
243 uint16_t S ol a r Ar r a yN S Cu rr e nt ( void )
244 {
245 uint16_t SACurrent = ReadADC (& ADCA . CH0 , offset_ch0 ,
5) ;
246 if ( SACurrent < 0)
247 SACurrent = 0;
248 if ( SACurrent > 60000)
249 SACurrent = 0;
250 SolarPanelNS . Current = SACurrent ;
251 return ( SACurrent ) ;
252 }
192
4 // Minimum solar panel current below which the panels
are disconnected .
5 # define S O L A R P A N E L _ C U R R E N T _M I N 0
6 // Minimum solar panel voltage
7 # define S O L A R P A N E L _ V O L T A G E _M I N 0
8 # define TELEMETRY_BYTES 4
9 # define T WIS_ST ATUS_R EADY 0
10
11
12 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
13 // State machine states
14 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
15 // Initialization state
16 # define ST_INIT (10)
17 // Start - up state
18 # define ST_START (20)
19 // Prequalification state for over - discharged batteries
20 # define ST_PREQUAL (30)
21 // Prequalification control state
22 # define ST_PREQUAL_CTRL (40)
23 // Maximum power point tracking state
24 # define ST_MPPT (50)
25 // Maximum power point tracking control state
26 # define ST_MPPT_CTRL (60)
27 // Constant voltage state with PID regulation
28 # define ST_CVOLTAGE (70)
29 // Constant voltage control state
30 # define ST_CVOLTAGE_CTRL (80)
31 // Sleep state
32 # define ST_SLEEP (90)
33 // Disconnect state
34 # define ST_DISCONNECT (100)
35 // Discharge state ( same as disconnect ?)
36 # define ST_DISCHARGE (110)
37 // Error state that deals with any error that may arise
38 # define ST_ERROR (120)
39
40
41 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
42 // Solar Panels struct declarations
43 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
44 /* Holds status and various data for the solar panels .
45 *
46 * These data are updated by sensors ( TODO )
47 */
48 typedef struct
49 {
50 uint16_t Voltage ;
51 uint16_t Current ;
193
52 uint16_t Temperature ;
53 uint16_t CutoffVoltage ;
54 } SolarPanels_t ;
55
56
57 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
58 // Flags for status information
59 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
60 /* Holds flags .
61 *
62 * These data are updated by
63 */
64 typedef struct {
65 uint8_t pidTimer :1;
66 uint8_t pwmTimer :1;
67 } gFlags_t ;
68
69 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
70 // Global variables
71 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
72 extern unsigned char CurrentState ;
73 extern int8_t offset_ch0 , offset_ch1 ,
74 offset_ch2 , offset_ch3 ;
75 extern gFlags_t gFlags ;
76 extern SolarPanels_t SolarPanelNS ;
77
78 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
79 // Function prototypes
80 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
81 int main ( void ) ;
82 void P M I C _ S e t V e c t o r L o c a t i o n T o A p p l i c a t i o n ( void ) ;
83 uint16_t S ol a r Ar r a yN S Cu rr e nt ( void ) ;
84 uint16_t S ol a r Ar r a yN S Vo lt a ge ( void ) ;
85 void UpdateTWI ( void ) ;
86
87 # endif // MAIN_H
194
11 * the number of averaged samples as argument ,
12 * and starts a conversion on the given channel .
13 * An average over [ samples ] samples is then
14 * calculated before the conversion
15 * is terminated and the answer is returned .
16 */
17 uint16_t ReadADC ( ADC_CH_t * adc_ch ,
18 uint8_t offset ,
19 uint8_t samples ) {
20
21 uint32_t dummy = 0;
22 uint16_t result = 0;
23
24 for ( uint8_t i = 0; i < samples ; i ++) {
25 AD C _ C h _ C o n v e r s i o n _ S t a r t ( adc_ch ) ;
26 do {
27 } while (! A D C _ C h _ C o n v e r s i o n _ C o m p l e t e ( adc_ch ) ) ;
28 if ( i != 0) {
29 dummy += ( uint32_t ) A D C _ R e s u l t C h _ G e t W o r d _ S i g n e d (
adc_ch , offset ) ;
30 }
31 }
32 result = ( uint16_t ) ( dummy /( samples -1) ) ;
33 return result ;
34 }
35
36 /* Helper function for the ReadADC function .
37 *
38 * Clears Interrupt flag by setting IF high , stores
39 * contents of the channels RES into answer before
40 * returning the answer .
41 */
42 int16_t A D C _ R e s u l t C h _ G e t W o r d _ S i g n e d ( ADC_CH_t * adc_ch ,
int8_t signedOffset )
43 {
44 int16_t answer ;
45
46 // Clear interrupt flag
47 adc_ch - > INTFLAGS = ADC_CH_CHIF_bm ;
48
49 // Return result register contents
50 answer = adc_ch - > RES - signedOffset ;
51 return answer ;
52 }
53
54
55 /* Calculates the offset on a given ADC channel .
56 *
57 * This function does one or several measurements to
195
58 * determine the offset of the ADC . The ADC must be
59 * configured and enabled before this function is run .
60 * It only returns the low byte of the 12 - bit
61 * conversion , because the offset should never
62 * be more than + -8 LSB off .
63 *
64 */
65 int8_t A DC _ O f f s e t _ G et _S i g ne d ( ADC_t * adc , ADC_CH_t * ch ,
bool oversampling )
66 {
67 if ( oversampling )
68 {
69 int16_t offset =0;
70 for ( int i =0; i <4; i ++)
71 {
72 A D C _ C h _ C o n v e r si o n _ S ta r t ( ch ) ;
73
74 do {
75 } while (! A D C _ C h _ C o n v e r s i o n _ C o m p l e t e ( ch ) ) ;
76
77 // Returns ch . RES and adds it to offset
78 offset += A D C _ R e s u l t C h _ G e t W o r d _ S i g n e d ( ch , 0 x00 ) ;
79 }
80 // Takes the average offset value and throws the
excess high - order bits
81 return (( int8_t ) ( offset /4) ) ;
82 }
83 else // ** Do one conversion to find offset :
84 {
85 int8_t offset =0;
86
87 // Starts a conversion on channel " ch "
88 A D C _ C h _ C o n v e r si o n _ S ta r t ( ch ) ;
89
90 do {
91 } while (! A D C _ C h _ C o n v e r s i o n _ C o m p l e t e ( ch ) ) ;
92 offset = ( uint8_t ) A D C _ R e s u l t C h _ G e t W o r d _ S i g n e d ( ch ,
0 x00 ) ;
93
94 return offset ;
95 }
96 }
97
98 /* Initializes the system ADC .
99 *
100 * Sets up the ADc , and so on . RTFM .
101 *
102 */
103 void ADC_init ( void )
196
104 {
105 PORTA . DIRSET = 0 x00 ;
106
107 // Clear RESOLUTION and CONVMODE Mode
108 // Set 8 bit ADC resolution
109 // Enable signed conversion mode
110 ADCA . CTRLB =
111 (( ADCA . CTRLB & ~( ADC_RESOLUTION_gm |
ADC_CONMODE_bm ) )
112 | A D C _R ES O L U T I O N _ 1 2 B I T_ g c
113 | ( A DC _ C on v M od e _ Si g n ed ? ADC_CONMODE_bm : 0) ) ;
114
115 // Clear PRESCALER bits
116 // Set ADC_clk to Peripheral_clk /256
117 ADCA . PRESCALER =
118 ( ADCA . PRESCALER & ~( ADC_PRESCALER_gm ) )
119 | ADC_PRESCALER_DIV64_gc ;
120
121 // Clear REFSEL bits
122 // Set Reference to Internal Vcc /1.6
123 ADCA . REFCTRL =
124 ( ADCA . REFCTRL & ~( ADC_REFSEL_gm ) )
125 | A DC _ R EF S E L_ A R EF A _ gc ;
126
127 // Clear Ch0 Input Mode and Gain factor
128 // Enable single - ended or differential input signal
129 // Set input amplification to 1 x
130 ADCA . CH0 . CTRL =
131 ( ADCA . CH0 . CTRL & ~( ADC_ C H_IN PUTMODE_gm
132 | ADC _CH_GA INFAC _gm ) )
133 | A D C _ C H _ I N P U T M O D E _ D I F F _ gc
134 | AD C_CH_GAIN_1X _gc ;
135
136 // Clear Ch1 Input Mode and Gain factor
137 // Enable single - ended or differential input signal
138 // Set input amplification to 1 x
139 ADCA . CH1 . CTRL =
140 ( ADCA . CH1 . CTRL & ~( ADC_ C H_IN PUTMODE_gm
141 | ADC _CH_GA INFAC _gm ) )
142 | A D C _ C H _ I N P U T M O D E _ D I F F _ gc
143 | AD C_CH_GAIN_1X _gc ;
144
145 // Clear Ch1 Input Mode and Gain factor
146 // Enable single - ended or differential input signal
147 // Set input amplification to 1 x
148 ADCA . CH2 . CTRL =
149 ( ADCA . CH2 . CTRL & ~( ADC_ C H_IN PUTMODE_gm |
ADC_ CH_GAI NFAC_g m ) )
150 | A D C _ C H _ I N P U T M O D E _ D I F F _ gc
197
151 | A DC_CH_ GAIN_1 X_gc ;
152
153 // Clear Ch1 Input Mode and Gain factor
154 // Enable single - ended or differential input signal
155 // Set input amplification to 1 x
156 ADCA . CH3 . CTRL =
157 ( ADCA . CH3 . CTRL & ~( ADC_CH_INPUTMODE_gm |
ADC _CH_GA INFAC_gm ) )
158 | A D C_ C H _ I N P U T M O D E _ DI F F _ g c
159 | A DC_CH_ GAIN_1 X_gc ;
160
161 // Set ADC4 pin as both positive and negative analog
input
162 ADCA . CH0 . MUXCTRL =
163 ( uint8_t ) A D C_C H _MU X POS_ PIN4 _gc
164 | A D C _ C H _ M U X N E G _ P I N4 _g c ;
165
166 // Set ADC5 pin as both positive and negative analog
input
167 ADCA . CH1 . MUXCTRL =
168 ( uint8_t ) A D C_C H _MU X POS_ PIN5 _gc
169 | A D C _ C H _ M U X N E G _ P I N5 _g c ;
170
171 // Set ADC6 pin as both positive and negative analog
input
172 ADCA . CH2 . MUXCTRL =
173 ( uint8_t ) A D C_C H _MU X POS_ PIN6 _gc
174 | A D C _ C H _ M U X N E G _ P I N6 _g c ;
175
176 // Set ADC7 pin as both positive and negative analog
input
177 ADCA . CH3 . MUXCTRL =
178 ( uint8_t ) A D C_C H _MU X POS_ PIN7 _gc
179 | A D C _ C H _ M U X N E G _ P I N7 _g c ;
180
181 ADCA . CALL = R ea d C al ibrat i onByte (
182 offsetof ( NVM_PROD_SIGNATURES_t , ADCACAL0 ) ) ;
183 ADCA . CALH = R ea d C al ibrat i onByte (
184 offsetof ( NVM_PROD_SIGNATURES_t , ADCACAL1 ) ) ;
185
186 // Enable the ADC .
187 ADC_Enable (& ADCA ) ;
188
189 // Wait until common mode voltage is stable .
190 ADC_Wait_8MHz (& ADCA ) ;
191
192 // Returns the offset between the two differential
inputs .
193 offset_ch0 =
198
194 A DC _O f f s e t _ G e t _ S i gn e d (& ADCA , & ADCA . CH0 , true ) ;
195 offset_ch1 =
196 A DC _O f f s e t _ G e t _ S i gn e d (& ADCA , & ADCA . CH1 , true ) ;
197 offset_ch2 =
198 A DC _O f f s e t _ G e t _ S i gn e d (& ADCA , & ADCA . CH2 , true ) ;
199 offset_ch3 =
200 A DC _O f f s e t _ G e t _ S i gn e d (& ADCA , & ADCA . CH3 , true ) ;
201
202 // Disable the ADC
203 ADCA . CTRLA = ADCA . CTRLA & (~ ADC_ENABLE_bm ) ;
204
205 // Set ADC5 pin as positive analog input .
206 // Set ADC4 pin as negative analog input .
207 ADCA . CH0 . MUXCTRL =
208 ( uint8_t ) A D C _ C H _ M UX P O S_P I N4_ gc
209 | A D C _ CH _ M U X N E G _ P I N 2_ gc ;
210 ADCA . CH1 . MUXCTRL =
211 ( uint8_t ) A D C _ C H _ M UX P O S_P I N5_ gc
212 | A D C _ CH _ M U X N E G _ P I N 2_ gc ;
213 ADCA . CH2 . MUXCTRL =
214 ( uint8_t ) A D C _ C H _ M UX P O S_P I N6_ gc
215 | A D C _ CH _ M U X N E G _ P I N 2_ gc ;
216 ADCA . CH3 . MUXCTRL =
217 ( uint8_t ) A D C _ C H _ M UX P O S_P I N7_ gc
218 | A D C _ CH _ M U X N E G _ P I N 2_ gc ;
219
220 // Clear the SWEEP bits .
221 // Set channel 0 as active channel for sweep .
222 ADCA . EVCTRL = ( ADCA . EVCTRL & ~( ADC_SWEEP_gm ) )
223 | ADC _SWEEP _0123 _gc ;
224
225 // Enable the ADC .
226 ADC_Enable (& ADCA ) ;
227
228 // Wait until common mode voltage is stable .
229 ADC_Wait_8MHz (& ADCA ) ;
230
231 // Enable free running mode .
232 ADCA . CTRLB |= ADC_FREERUN_bm ;
233
234 }
235
236
237 /* Function : ADC_Wait_8Mhz ()
238 *
239 * 1) Store current PRESCALER Value
240 * 2) Set new PRESCALER value to Sys_clk /4
241 * 3) Delay 4 cycles
242 * 4) Restore old PRESCALER value
199
243 * 5) Return
244 *
245 * NOTE : Default clk is 2 MHz and therefore
246 * below the maximum frequency to use this
247 * function .
248 *
249 */
250 void ADC_Wait_8MHz ( ADC_t * adc )
251 {
252 /* Store old prescaler value . */
253 uint8_t prescaler_val = adc - > PRESCALER ;
254
255 /* Set prescaler value to minimum value . */
256 adc - > PRESCALER = ADC _P RE S C AL ER _DIV4 _gc ;
257
258 /* Wait 4* CO MM ON _MODE _C YC LE S for common mode to
settle . */
259 _delay_us (4* CO MM ON_MODE_CYCLES ) ;
260
261 /* Set prescaler to old value */
262 adc - > PRESCALER = prescaler_val ;
263 }
264
265 /* Reads the calibration bytes from factory .
266 *
267 * Bla bla bla .
268 */
269 uint8_t Rea d C al i b ra tio nB y te ( uint8_t index )
270 {
271 uint8_t result ;
272
273 /* Load the NVM Command register
274 * to read the calibration row .
275 */
276 NVM_CMD = N V M _ C M D _ R E A D _ C A L I B_ R O W _ g c ;
277 result = pgm_read_byte ( index ) ;
278
279 /* Clean up NVM Command register . */
280 NVM_CMD = N V M _ C M D _ NO _ O P E RA T I O N_ g c ;
281 return ( result ) ;
282 }
200
6 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
7 // Definitions for the Analog - to - Digital peripheral .
8 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
9 // Signed conversion mode flag .
10 # define ADC _ Con v M o de _ S ig n e d true
11 // Unsigned conversion mode flag .
12 # define A D C _ C o n vM o d e _ U n s i g n ed false
13 // Number of common mode cycles .
14 # define COMM ON _M ODE _C YC LE S 16
15 // Enable selected ADC .
16 # define ADC_Enable ( _adc ) (( _adc ) -> CTRLA |=
ADC_ENABLE_bm )
17 // Disable selected ADC .
18 # define ADC_Disable ( _adc ) (( _adc ) -> CTRLA = ( _adc ) ->
CTRLA & (~ ADC_ENABLE_bm ) )
19 // Starts a single conversion on a channel .
20 # define A D C _ C h _C o n v e r s i o n _S t a r t ( _adc_ch ) (( _adc_ch ) ->
CTRL |= ADC_CH_START_bm )
21 // True or false flag which sets upon conversion
complete on a given channel .
22 # define A D C _ C h _ C o n v e r s i o n _ C o m p l e t e ( _adc_ch ) \
23 ((( _adc_ch ) -> INTFLAGS & ADC_CH_CHIF_bm ) != 0 x00 )
24 // Selects the analog input pins on a channel . See
ADC_CH_MUXPOS / NEG_enum types .
25 # define A D C _ C h _ I n p u t M u x _ C o nf i g ( _adc_ch , _posInput ,
_negInput ) \
26 (( _adc_ch ) -> MUXCTRL = ( uint8_t ) ( _posInput |
_negInput ) )
27
28
29 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
30 // Global variables
31 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
32 extern int8_t offset_ch0 , offset_ch1 , offset_ch2 ,
offset_ch3 ;
33 int8_t offset_ch0 , offset_ch1 , offset_ch2 , offset_ch3 ;
34
35 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
36 // Function prototypes
37 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
38 uint16_t ReadADC ( ADC_CH_t * adc_ch , uint8_t offset ,
uint8_t samples ) ;
39 int16_t A D C _ R e s u l t C h _ G e t W o r d _ S i g n e d ( ADC_CH_t * adc_ch
, int8_t signedOffset ) ;
40 int8_t A DC _ O f f s e t _ G e t _ S i gn ed ( ADC_t * adc , ADC_CH_t *
ch , bool oversampling ) ;
41 void ADC_init ( void ) ;
42 void ADC_Wait_8MHz ( ADC_t * adc ) ;
43 uint8_t R ead C al i b ra t i on B y te ( uint8_t index ) ;
201
44
45 # endif // ADC_H
202
44 uint8_t clkCtrl =
45 ( CLK . CTRL & ~ CLK_SCLKSEL_gm )
46 | C LK _ SC L K S E L _ R C 3 2 M_g c ;
47 CCPWrite (& CLK . CTRL , clkCtrl ) ;
48 clkCtrl = ( CLK . CTRL & CLK _ SCL KSE L_RC32M_gc ) ;
49
50 }
51
52 /* CCP write helper function written in assembly .
53 *
54 * This function is written in assembly because
55 * of the time critical operation of writing to
56 * the registers .
57 *
58 * address : A pointer to the address to write to .
59 * value : The value to put in to the register .
60 */
61 void CCPWrite ( volatile uint8_t * address , uint8_t value
)
62 {
63 # ifdef __ICCAVR__
64
65 // Store global interrupt setting in scratch
66 // register and disable interrupts .
67 asm ( " in R1 , 0 x3F \ n "
68 " cli "
69 );
70
71 // Move destination address pointer
72 // to Z pointer registers .
73 asm ( " movw r30 , r16 " ) ;
74 # ifdef RAMPZ
75 asm ( " ldi R16 , 0 \ n "
76 " out 0 x3B , R16 "
77 );
78
79 # endif
80 asm ( " ldi r16 , 0 xD8 \ n "
81 " out 0 x34 , r16 \ n "
82 # if ( __MEMORY_MODEL__ == 1)
83 " st Z , r17 \ n " ) ;
84 # elif ( __MEMORY_MODEL__ == 2)
85 " st Z , r18 \ n " ) ;
86 # else /* ( __MEMORY_MODEL__ == 3) || ( __MEMORY_MODEL__
== 5) */
87 " st Z , r19 \ n " ) ;
88 # endif /* __MEMORY_MODEL__ */
89
203
90 // Restore global interrupt setting from scratch
register .
91 asm ( " out 0 x3F , R1 " ) ;
92
93 # elif defined __GNUC__
94 A V R _ E N T E R _ C R I T IC A L _ R E G I O N ( ) ;
95 volatile uint8_t * tmpAddr = address ;
96 # ifdef RAMPZ
97 RAMPZ = 0;
98 # endif
99 asm volatile (
100 " movw r30 , %0 " "\n\t"
101 " ldi r16 , %2 " "\n\t"
102 " out %3 , r16 " "\n\t"
103 " st Z , %1 " "\n\t"
104 :
105 : " r " ( tmpAddr ) , " r " ( value ) , " M " ( CCP_IOREG_gc
) , " i " (& CCP )
106 : " r16 " , " r30 " , " r31 "
107 );
108
109 A V R _ L E A V E _ C R I T IC A L _ R E G I O N ( ) ;
110 # endif
111 }
204
21 # endif // CLOCK_H
205
44 }
45
46 if ((! BattData . Low ) ) {
47 success = TRUE ;
48 } else {
49 BattData . Low = FALSE ; // ( This is just a
technicality ..)
50 success = FALSE ;
51 }
52
53 return ( success ) ; // when is it false ...? eh ?
54 }
55
56 uint16_t BatteryVoltage ( void )
57 {
58 uint16_t BatVoltage = ReadADC (& ADCA . CH2 , offset_ch2 ,
5) ;
59 BattData . Voltage = BatVoltage ;
60 return ( BatVoltage ) ;
61 }
62
63 uint16_t BatteryTemp ( void )
64 {
65 uint16_t BatTemperature = ReadADC (& ADCA . CH3 ,
offset_ch3 , 5) ;
66 BattData . Temperature = BatTemperature ;
67 return ( BatTemperature ) ;
68 }
206
19 // Battery fully charged . ( TRUE / FALSE )
20 unsigned char Charged : 1;
21 // Battery low voltage . ( TRUE / FALSE )
22 unsigned char Low : 1;
23 // Battery temperature , in centigrade .
24 uint16_t Temperature ;
25 uint16_t Voltage ;
26 // Capacity , in mAh .
27 unsigned int Capacity ;
28 // Charge current , in mA .
29 unsigned int MaxCurrent ;
30 // Charge cut - off time , in minutes .
31 unsigned int MaxTime ;
32 // Cut - off current , in mA .
33 unsigned int MinCurrent ;
34 } Batteries_t ;
35
36 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
37 // Global variable ( s )
38 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
39 extern Batteries_t BattData ;
40
41 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
42 // Function prototypes
43 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
44 unsigned char BatteryCheck ( void ) ;
45 unsigned char B a t t e r y S t a t usR e fre sh ( void ) ;
46 uint16_t BatteryVoltage ( void ) ;
47 uint16_t BatteryTemp ( void ) ;
48
49 # endif // BATTERY_H
207
15 InputValue = pid_Controller ( RefValue ,
MeasuredValue , & pidData ) ;
16
17 Set_Input ( InputValue ) ;
18 gFlags . pidTimer = FALSE ;
19 }
20 _delay_ms (1) ;
21 }
22
23 void ST_Disconnect ( void ) {
24 PWM_Stop () ;
25 }
208
18 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
19 /* Track the maximum power point on the solar panel .
20 *
21 * This function tracks the maximum power point ( MPP )
22 * on the solar panel according to the Perturb and
23 * Observe Method . TODO : A flag is set when the
battery
24 * has reached its maximum voltage level , and a new
25 * state is returned to the main loop .
26 */
27 unsigned char MPPT ( uint16_t current , uint16_t voltage )
{
28 uint32_t Power = ( uint32_t ) voltage * ( uint32_t )
current ;
29 // check for old = new case here
30 if ( Power > OldPower ) {
31 if ( voltage > OldVoltage ) {
32 P W M_ D e c r e m e n t Du ty C yc le (1) ;
33 } else if ( voltage < OldVoltage ) {
34 P W M_ I n c r e m e n t Du ty C yc le (1) ;
35 }
36 } else if ( Power < OldPower ) {
37 if ( voltage > OldVoltage ) {
38 P W M_ I n c r e m e n t Du ty C yc le (1) ;
39 } else if ( voltage < OldVoltage ) {
40 P W M_ D e c r e m e n t Du ty C yc le (1) ;
41 }
42 }
43 OldPower = Power ;
44 OldVoltage = voltage ;
45
46 _delay_ms (1) ; // debugging
47 return (1) ; // ChargeParameters . NextState ) ;
48 }
209
13 // Function prototypes
14 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
15 unsigned char MPPT ( uint16_t current , uint16_t voltage ) ;
16 # endif
210
41 * the PID . Takes as input : desired ( setPoint ) value ,
42 * the measured ( processValue ) value and PID status (
pid_st ) .
43 */
44 int16_t pid_Controller ( int16_t setPoint ,
45 int16_t processValue ,
46 pidData_t * pid_st )
47 {
48 int16_t error , p_term , d_term ;
49 int32_t i_term , ret , temp ;
50
51 error = setPoint - processValue ;
52
53 // Calculate Pterm and limit error overflow
54 if ( error > pid_st - > maxError ) {
55 p_term = MAX_INT ;
56 } else if ( error < - pid_st - > maxError ) {
57 p_term = - MAX_INT ;
58 } else {
59 p_term = pid_st - > P_Factor * error ;
60 }
61
62 // Calculate Iterm and limit integral runaway
63 temp = pid_st - > sumError + error ;
64 if ( temp > pid_st - > maxSumError ) {
65 i_term = MAX_I_TERM ;
66 pid_st - > sumError = pid_st - > maxSumError ;
67 } else if ( temp < - pid_st - > maxSumError ) {
68 i_term = - MAX_I_TERM ;
69 pid_st - > sumError = - pid_st - > maxSumError ;
70 } else {
71 pid_st - > sumError = temp ;
72 i_term = pid_st - > I_Factor * pid_st - > sumError ;
73 }
74
75 // Calculate Dterm
76 d_term = pid_st - >
77 D_Factor * ( pid_st - > lastProcessValue -
processValue ) ;
78 pid_st - > lastProcessValue = processValue ;
79
80 ret = ( p_term + i_term + d_term ) / SCALING_FACTOR ;
81 if ( ret > MAX_INT ) {
82 ret = MAX_INT ;
83 } else if ( ret < - MAX_INT ) {
84 ret = - MAX_INT ;
85 }
86 return (( int16_t ) ret ) ;
87 }
211
88
89 /*
90 * Resets the integrator
91 */
92 void p i d _R e s e t _ I n t e gra t or ( pidData_t * pid_st )
93 {
94 pid_st - > sumError = 0;
95 }
96
97 int16_t GetReference ( void )
98 {
99 // Returns CELL_VOLTAGE_MAX .
100 return CELL_VOLTAGE_MAX ;
101 }
102
103 int16_t GetMeasurement ( void )
104 {
105 return ( BatteryVoltage () ) ;
106 // return ( ReadADC (& ADCA . CH2 , offset_ch2 , 11) ) ;
107 }
108
109 /* Sets the PID output as input to the system .
110 *
111 * This function takes the output value from
112 * the PID controller and level shifts it into
113 * a positive range , normalizes the output
114 * before setting the the new dutycycle .
115 */
116 void Set_Input ( int16_t inputValue )
117 {
118 uint8_t NewDutyCycle ;
119 // Level shift the PID output value to a positive
range .
120 shift ed _i np ut Va lu e = inputValue + abs ( PID_ERROR_MIN
);
121 // Normalize input range .
122 no r m a l i z e d _ i n p u tV a l ue = (( shifted_inputValue /
PI D _ S H I F T E D _E RR OR _M AX ) ) ;
123 // Calculate the new dutycycle
124 NewDutyCycle = DUTYCYCLE_MIN + (
DU T Y C Y C L E _ V AL ID _R AN GE * n ormal ized _inp utVal ue ) ;
125 // Set the new dutycycle
126 SetDutyCycle ( NewDutyCycle ) ;
127 }
128
129 void TC1_init ( void )
130 {
131 /* Set the clock source to
132 Clk_per /1024 = 8 MHz /1024 = 7812 ,5 Hz
212
133 = 1 / 7812 ,5 s = 128 us clock tick
134 */
135 TCC1 . CTRLA =
136 ( TCC1 . CTRLA & ~ TC1_CLKSEL_gm )
137 | TC_ CLKSEL _DIV8 _gc ; // 64 _gc ;
138
139 /* Set the Timer Waveform Generation Mode
140 * to normal , i . e . no waveform , and enable
141 * CC on channel A .
142 */
143 TCC1 . CTRLB = ( TCC1 . CTRLB & ~ TC1_WGMODE_gm )
144 | T C _ WG MO DE _ NORMAL_gc
145 | TC1_CCAEN_bm ;
146
147 /* Enable interrupts on CC channel A
148 * with HI priority
149 */
150 TCC1 . INTCTRLB = ( uint8_t ) TC_CCAINTLVL_HI_gc ;
151
152 /* Set the period for Timer1 */
153 TCC1 . PER = 0 x0FF0 ;
154
155 /*
156 * 16 bit Compare or Capture register .
157 * CCxH + CCxL = CCA . The reg is updated from
158 * CCaBUF . If CNT equals CCA ( or CCx ) ,
159 * the comparator signals a match that sets
160 * the CC channel ’s flag at the next timer
161 * clock cycle and the event and optional
162 * interrupt is generated .
163 */
164 TCC1 . CCA = 0 x0FF0 ;
165 }
213
13 ( PID_ERROR_MAX + abs ( PID_ERROR_MIN ) )
14 # define P I D _ S H I F T E D _ E RRO R _MI N
15 ( PID_ERROR_MIN + abs ( PID_ERROR_MIN ) )
16
17 // Maximum values used to avoid sign / overflow problems
18 # define MAX_INT INT16_MAX
19 # define MAX_LONG INT32_MAX
20 # define MAX_I_TERM ( MAX_LONG / 2)
21
22 // Boolean values
23 # define FALSE 0
24 # define TRUE 1
25
26 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
27 // Definitions for the PID gains which
28 // should be modified after tuning .
29 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
30 // Proportional gain
31 # define K_P 0.35
32 // Integral gain
33 # define K_I 0.26
34 // Derivative gain
35 # define K_D 0.005
36
37 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
38 // Definition for the desired PID sample
39 // time interval . For a n - bit counter :
40 // TIME_INTERVAL = ( desired interval
41 // [ sec ]) * ( frequency [ Hz ]) / (2^ n -1)
42 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
43 // ! PID sampling time interval
44 # define TIME_INTERVAL 20
45
46 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
47 // Definition for the scaling factor
48 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
49 // ! Scaling factor .
50 # define SCALING_FACTOR 128
51
52 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
53 // PID Status declarations
54 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
55 /* Holds the setpoints and data used by
56 * the PID control algorithm .
57 */
58 typedef struct {
59 int16_t lastProcessValue ;
60 int32_t sumError ;
61 int16_t P_Factor ;
214
62 int16_t I_Factor ;
63 int16_t D_Factor ;
64 int16_t maxError ;
65 int32_t maxSumError ;
66 } pidData_t ;
67
68 extern pidData_t pidData ;
69 // struct PID_DATA pidData ;
70 // pidData_t pidData ; ??
71 /*
72 struct PID_DATA {
73 int16_t lastProcessValue ;
74 int32_t sumError ;
75 int16_t P_Factor ;
76 int16_t I_Factor ;
77 int16_t D_Factor ;
78 int16_t maxError ;
79 int32_t maxSumError ;
80 };
81 typedef struct PID_DATA pidData_t ; */
82
83
84 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
85 // Function prototypes
86 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
87 // Returns the reference voltage
88 // ( in ADC counts ) for the PID algorithm .
89 int16_t GetReference ( void ) ;
90 // Returns the battery voltage from
91 // ADC channel 2.
92 int16_t GetMeasurement ( void ) ;
93 // Sets the dutycycle to the new input .
94 void Set_Input ( int16_t inputValue ) ;
95 // Initialize the the PID routine .
96 void pid_Init ( int16_t p_factor ,
97 int16_t i_factor ,
98 int16_t d_factor ,
99 pidData_t * pid ) ;
100 // The actual PID algorithm . Returns the
101 // new inputvalue for the converter .
102 int16_t pid_Controller ( int16_t setPoint ,
103 int16_t processValue ,
104 pidData_t * pid ) ;
105 // Resets the integrator to avoid integral run - away .
106 void p i d _ R e s e t_ I n t e g r a t o r ( pidData_t * pid_st ) ;
107 // Timer / Counter for PID
108 void TC1_init ( void ) ;
109
110 # endif
215
Listing F.15: pwm.c
1 # include < avr / io .h >
2 # include < stdio .h >
3 # include " pwm . h "
4
5 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
6 // Starts the PWM output to the high - and
7 // low side switches .
8 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
9 /* Starts PWM output with
10 * dead - time insertion on PORTC .
11 */
12 void PWM_Start ( void )
13 {
14 // Enable output on PC0 .
15 PORTC . DIRSET = ( PIN0_bm | PIN1_bm ) ;
16 // Set 16 bit period .
17 TCC0 . PER = ( PWM_period & HiResMask ) ;
18 // Enable Single Slope PWM and Enable Compare
Capture Channel A ( CCA ) .
19 TCC0 . CTRLB = ( TCC0 . CTRLB & ~ TC0_WGMODE_gm ) |
TC_WGMODE_SS_gc | TC0_CCAEN_bm ;
20 // Selects starts a clock source . Must use DIV1 if Hi
- Res enabled .
21 TCC0 . CTRLA = ( TCC0 . CTRLA & ~ TC0_CLKSEL_gm ) |
TC _CLKSE L_DIV1 _gc ;
22
23 // Enable interrupts on CC channel A with HI priority
.
24 TCC0 . INTCTRLA = ( uint8_t ) TC_CCAINTLVL_LO_gc ;
25
26 // Enable Dead - Time Generator for CCA and mirror Low -
side signal on PC1 .
27 AWEXC . CTRL |= AWEX_DTICCAEN_bm ;
28 // Enables Output Override on pin 0 and 1.
29 AWEXC . OUTOVEN = ( PIN0_bm | PIN1_bm ) ;
30 // Writes number of peripheral clock cycles of Dead
- Time to Both Sides .
31 // AWEXC . DTBOTH = 2;
32 // Sets number of peripheral clock cycles of Dead -
Time to Low side .
33 AWEXC . DTLS = 3;
34 // Writes number of peripheral clock cycles of Dead -
Time to High Sides .
35 AWEXC . DTHS = 3;
36 // Enable High Resolution on Timer / Counter 0.
37 HIRESC . CTRL |= HIRES_HREN_TC0_gc ;
38 // Set default dutycycle . TCC0 . CCABUF =
DU TYCYCL E_DEFAULT ;
216
39 DutyCycle = SetDutyCycle ( DUTYCYCLE_DEFAULT ) ;
40 TCC0 . CCABUF = DutyCycle ;
41 }
42
43 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
44 // Stops the PWM output to the
45 // high - and low side switches .
46 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
47 /* ! Stops PWM output , and activates the internal
48 * pull - downs on the NMOS gates , leaving the the
49 * switches in an open state .
50 */
51 void PWM_Stop ( void )
52 {
53 // Turn off Timer / Counter ( no clock selected )
54 TCC0 . CTRLA = ( TCC0 . CTRLA & ~ TC0_CLKSEL_gm ) |
TC_CLKSEL_OFF_gc ;
55 // Set waveform generation to normal mode ,
56 // i .e , NO waveform generation .
57 TCC0 . CTRLB = 0;
58 // Turn off Advanced Waveform Generation module .
59 AWEXC . CTRL = 0;
60 // Turn off Hi Resolution module .
61 HIRESC . CTRL = 0;
62 // Set port C to input .
63 PORTC . DIR = 0;
64 // Enable Totempole w / pull - down on PIN0
65 PORTC . PIN0CTRL = P O R T _ OP C _PU LLD O WN_gc ;
66 // Enable Totempole w / pull - down on PIN1
67 PORTC . PIN1CTRL = P O R T _ OP C _PU LLD O WN_gc ;
68
69 // SetErrorFlag ( PWM_STOPPED ) ;
70 }
71
72 /* Decrements the PWM duty cycle , if not already at min
.
73 *
74 * TRUE Success , duty cycle could be incremented .
75 * FALSE Failure , duty cycle already at maximum .
76 */
77 unsigned char PW M _ D e c r e m e n t D ut yC y cl e ( uint8_t StepSize ) {
78 if ( DutyCycle > DUTYCYCLE_MIN ) {
79 DutyCycle -= StepSize ;
80 return ( TRUE ) ;
81 } else {
82 return ( FALSE ) ;
83 }
84 }
85
217
86 /* Increments the PWM duty cycle , if not already at
max .
87 *
88 * TRUE Success , duty cycle could be incremented .
89 * FALSE Failure , duty cycle already at maximum .
90 */
91 unsigned char P W M _ I n c re m e n tD u t yC ycl e ( uint8_t StepSize ) {
92 if ( DutyCycle < DUTYCYCLE_MAX ) {
93 DutyCycle += StepSize ;
94 return ( TRUE ) ;
95 } else {
96 return ( FALSE ) ;
97 }
98 }
99
100 /* Sets the PWM dutycycle within the defined
101 * MAX and MIN values .
102 *
103 * TRUE Success , duty cycle could be incremented .
104 * FALSE Failure , duty cycle already at maximum .
105 */
106 uint8_t SetDutyCycle ( uint8_t NewDutyCycle ) {
107 // Check if new dutycycle is ok
108 // before setting the new value .
109 if ( NewDutyCycle > DUTYCYCLE_MAX ) {
110 DutyCycle = DUTYCYCLE_MAX ;
111 // OutOfBounds = TRUE ;
112 } else if ( NewDutyCycle < DUTYCYCLE_MIN ) {
113 DutyCycle = DUTYCYCLE_MIN ;
114 } else DutyCycle = NewDutyCycle ;
115
116 // Return the dutycycle value
117 return ( DutyCycle ) ;
118 }
218
13 # define DUTYCYCLE_MAX 236
14 // Minimum PWM dutycycle .
15 # define DUTYCYCLE_MIN 180
16 // Valid range of the PWM dutycycle based
17 // on min / max limits .
18 # define D U T Y C Y C LE _ V A L I D _ R A N GE
19 ( DUTYCYCLE_MAX - DUTYCYCLE_MIN )
20 // A " safe " default PWM dutycycle for debugging etc .
21 # define D UTYCYC LE_DEF AULT 210
22
23 # define TRUE 1
24 # define FALSE 0
25
26 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
27 // Global variables
28 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
29 extern uint16_t DutyCycle ;
30
31 uint16_t DutyCycle ;
32 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
33 // Function prototypes
34 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
35 void PWM_Start ( void ) ;
36 void PWM_Stop ( void ) ;
37 unsigned char PW M _ D e c r e m e n t D ut yC y cl e
38 ( uint8_t StepSize ) ;
39 unsigned char PW M _ I n c r e m e n t D ut yC y cl e
40 ( uint8_t StepSize ) ;
41 uint8_t SetDutyCycle
42 ( uint8_t NewDutyCycle ) ;
43
44 # endif // PWM_H
219
14 * This gives a baud rate of 9600 ( or 38600) with a
f_per = 8 Mhz ,
15 * as per the equations on p . 238 in the datasheet .
16 */
17 USARTC0 . BAUDCTRLB = ( USARTC0 . BAUDCTRLB & (~
USART_BSCALE_gm | ~ USART_BSEL_gm ) ) ;
18 USARTC0 . BAUDCTRLA = 51;
19 // Disable interrupts
20 USARTC0 . CTRLA = ( U SA RT _ R XCI NT LV L_ OFF _g c |
U S A R T _ T X C I N T LV L_ O FF _g c ) ;
21 // Asynchronous mode , No parity , 8 bit , 1 Stop bit (
default , i . e . USART_SBMODE_bm not set )
22 USARTC0 . CTRLC = ( U S A R T _ C M O D E _ A S Y N C H R O N O U S _ g c |
U S A R T _ P M O D E _ D IS A B L E D_ g c | USART_CHSIZE_8BIT_gc ) ;
23 // Enable transmitter
24 USARTC0 . CTRLB = USART_TXEN_bm ;
25 }
26
27 /* Macro for writing to the USART on PORTC .
28 *
29 * This macro is used for debugging purposes only .
30 */
31 int uart_putchar ( char c , FILE * stream )
32 {
33 if ( c == ’\ n ’)
34 uart_putchar ( ’\ r ’ , stream ) ;
35
36 while (!( USARTC0 . STATUS & USART_DREIF_bm ) ) ;
37
38 USARTC0 . DATA = c ;
39 return 0;
40 }
220
2 # include < stdio .h >
3 # include < util / delay .h >
4 # include " battery . h "
5 # include " main . h "
6 # include " twi_slave . h "
7
8 /* Initalizes TWI slave driver structure .
9 *
10 * Initialize the instance of the TWI Slave
11 * and set the appropriate values .
12 *
13 * twi :
14 * The TWI_Slave_t struct instance .
15 * module :
16 * Pointer to the TWI module .
17 * p r oce s sDa t aFu n c ti o n :
18 * Pointer to the function that
19 * handles incoming data .
20 */
21 void T W I _ S l a v e I n i t i a l i z e D r i v e r (
22 TWI_Slave_t * twi ,
23 TWI_t * module ,
24 void (* p ro ce ssDat a Function ) ( void ) )
25 {
26 twi - > interface = module ;
27 twi - > Process_Data = proc e ss Da ta Function ;
28 twi - > bytesReceived = 0;
29 twi - > bytesSent = 0;
30 twi - > status = TW IS_STA TUS_READY ;
31 twi - > result = T WI S _RESU LT_UNKNOWN ;
32 twi - > abort = false ;
33 }
34
35
36 /* Initialize the TWI module .
37 *
38 * Enables interrupts on address recognition
39 * and data available . Remember to enable interrupts
40 * globally from the main application .
41 *
42 * twi :
43 * The TWI_Slave_t struct instance .
44 * address :
45 * Slave address for this module .
46 * intLevel :
47 * Interrupt level for the TWI slave ISR .
48 */
49 void T W I _ S l a v e I n i t i a l i z e M o d u l e (
50 TWI_Slave_t * twi ,
221
51 uint8_t address ,
52 TWI_SLAVE_INTLVL_t
intLevel )
53 {
54 twi - > interface - > SLAVE . CTRLA = intLevel |
55 TWI_SLAVE_DIEN_bm |
56 TWI_SLAVE_APIEN_bm |
57 TWI_SLAVE_ENABLE_bm ;
58
59 twi - > interface - > MASTER . CTRLA &= 0;
60 twi - > interface - > SLAVE . ADDR = ( address < <1) ;
61 }
62
63
64 /* Common TWI slave interrupt service routine .
65 *
66 * Handles all TWI transactions and responses to
67 * address match , data reception , data transmission ,
68 * bus error and data collision .
69 *
70 * twi :
71 * The TWI_Slave_t struct instance .
72 */
73 void T W I _ S l a v e I n t e r r u p t H a n d l e r ( TWI_Slave_t * twi )
74 {
75 uint8_t currentStatus = twi - > interface - > SLAVE . STATUS ;
76
77 /* If bus error . */
78 if ( currentStatus & T WI_S L AVE_BUSERR_bm ) {
79 twi - > bytesReceived = 0;
80 twi - > bytesSent = 0;
81 twi - > result = T W I S_ RE SU LT _BU S_ER ROR ;
82 twi - > status = T WIS_STATUS_READY ;
83 }
84
85 /* If transmit collision . */
86 else if ( currentStatus & TWI_SLAVE_COLL_bm ) {
87 twi - > bytesReceived = 0;
88 twi - > bytesSent = 0;
89 twi - > result = T W I S _ R E S U L T _ T R A N S M I T _ C O L L I S I O N ;
90 twi - > status = T WIS_STATUS_READY ;
91 }
92
93 /* If address match . */
94 else if (( currentStatus & T WI_SLAVE_APIF_bm ) &&
95 ( currentStatus & TWI_SLAVE_AP_bm ) ) {
96 T W I _ S l a v e A d d r e s s M a t c h H a n d l e r ( twi ) ;
97 }
98
222
99 /* If stop ( only enabled through slave read
transaction ) . */
100 else if ( currentStatus & TW I_SLAV E_APIF_bm ) {
101 T W I _ S l a v eS t o p H a n d l e r ( twi ) ;
102 }
103
104 /* If data interrupt . */
105 else if ( currentStatus & TWI_SLAVE_DIF_bm ) {
106 T W I _ S l a v eD a t a H a n d l e r ( twi ) ;
107 }
108
109 /* If unexpected state . */
110 else {
111 TWI_SlaveTransactionFinished (
112 twi , TWIS_RESULT_FAIL ) ;
113 }
114 }
115
116 /* TWI address match interrupt handler .
117 *
118 * Prepares TWI module for transaction when
119 * an address match occurs .
120 *
121 * twi :
122 * The TWI_Slave_t struct instance .
123 */
124 void T W I _ S l a v e A d d r e s s M a t c h H a n d l e r ( TWI_Slave_t * twi )
125 {
126 /* If application signalling need to abort ( error
occurred ) . */
127 if ( twi - > abort ) {
128 twi - > interface - > SLAVE . CTRLB =
129 TWI_SLAVE_CMD_COMPTRANS_gc ;
130 TWI_SlaveTransactionFinished (
131 twi , TW I S_ RESUL T_ABORTED ) ;
132 twi - > abort = false ;
133 } else {
134 twi - > status = TWIS_STATUS_BUSY ;
135 twi - > result = T WI S _ RESU LT _ UNKNO WN ;
136
137 /* Disable stop interrupt . */
138 uint8_t currentCtrlA =
139 twi - > interface - > SLAVE . CTRLA ;
140 twi - > interface - > SLAVE . CTRLA =
141 currentCtrlA & ~ TWI_SLAVE_PIEN_bm ;
142
143 twi - > bytesReceived = 0;
144 twi - > bytesSent = 0;
145
223
146 /* Send ACK , wait for data interrupt . */
147 twi - > interface - > SLAVE . CTRLB =
148 TWI_SLAVE_CMD_RESPONSE_gc ;
149 }
150 }
151
152
153 /* TWI stop condition interrupt handler .
154 *
155 * twi :
156 * The TWI_Slave_t struct instance .
157 */
158 void T W I _S l a v e S t o p H and l er ( TWI_Slave_t * twi )
159 {
160 /* Disable stop interrupt . */
161 uint8_t currentCtrlA =
162 twi - > interface - > SLAVE . CTRLA ;
163 twi - > interface - > SLAVE . CTRLA =
164 currentCtrlA & ~ TWI_SLAVE_PIEN_bm ;
165
166 /* Clear APIF , according to flowchart don ’t ACK or
NACK */
167 uint8_t currentStatus =
168 twi - > interface - > SLAVE . STATUS ;
169 twi - > interface - > SLAVE . STATUS =
170 currentStatus | TWI_SLAVE_APIF_bm ;
171
172 T W I _ S l a v e T r a n s a c t i o n F i n i s h e d ( twi , TWIS_RESULT_OK ) ;
173 }
174
175 /* TWI data interrupt handler .
176 *
177 * Calls the appropriate slave read or write handler .
178 *
179 * twi :
180 * The TWI_Slave_t struct instance .
181 */
182 void T W I _S l a v e D a t a H and l er ( TWI_Slave_t * twi )
183 {
184 if ( twi - > interface - > SLAVE . STATUS & TWI_SLAVE_DIR_bm )
{
185 TW I _ S l a v e W r i t e H an d l er ( twi ) ;
186 } else {
187 TW I _ S l a v e R e a d H a nd ler ( twi ) ;
188 }
189 }
190
191 /* TWI slave read interrupt handler .
192 *
224
193 * Handles TWI slave read transactions and responses .
194 *
195 * twi :
196 * The TWI_Slave_t struct instance .
197 */
198 void T W I _ S l a v eR e a d H a n d l e r ( TWI_Slave_t * twi )
199 {
200 /* Enable stop interrupt . */
201 uint8_t currentCtrlA = twi - > interface - > SLAVE . CTRLA ;
202 twi - > interface - > SLAVE . CTRLA =
203 currentCtrlA | TWI_SLAVE_PIEN_bm ;
204
205 /* If free space in buffer . */
206 if ( twi - > bytesReceived < T W IS _ R E C E I V E _B U F F ER _ S I ZE ) {
207 /* Fetch data */
208 uint8_t data = twi - > interface - > SLAVE . DATA ;
209 twi - > receivedData [ twi - > bytesReceived ] = data ;
210
211 /* Process data . */
212 twi - > Process_Data () ;
213
214 twi - > bytesReceived ++;
215
216 /* If application signalling need to abort ( error
occurred ) ,
217 * complete transaction and wait for next START .
Otherwise
218 * send ACK and wait for data interrupt .
219 */
220 if ( twi - > abort ) {
221 twi - > interface - > SLAVE . CTRLB =
222 TWI_SLAVE_CMD_COMPTRANS_gc ;
223 TWI_SlaveTransactionFinished (
224 twi , T W I S_ RESUL T _A BO RTED ) ;
225 twi - > abort = false ;
226 } else {
227 twi - > interface - > SLAVE . CTRLB =
228 TWI_SLAVE_CMD_RESPONSE_gc ;
229 }
230 }
231 /* If buffer overflow , send NACK and wait for next
START . Set
232 * result buffer overflow .
233 */
234 else {
235 twi - > interface - > SLAVE . CTRLB =
236 TW I _S L A VE _ACK A CT_bm
237 | TWI_SLAVE_CMD_COMPTRANS_gc ;
238 TWI_SlaveTransactionFinished (
225
239 twi , T W I S _ R E S U L T _ B U F F E R _ O V E R F L O W ) ;
240 }
241 }
242
243
244 /* TWI slave write interrupt handler .
245 *
246 * Handles TWI slave write transactions and responses .
247 *
248 * twi :
249 * The TWI_Slave_t struct instance .
250 */
251 void T W I_ S l a v e W r i t e H an d l er ( TWI_Slave_t * twi )
252 {
253 /* If NACK , slave write transaction finished . */
254 if (( twi - > bytesSent > 0) && ( twi - > interface - > SLAVE .
STATUS &
255 TWI_SLAVE_RXACK_bm ) ) {
256 twi - > interface - > SLAVE . CTRLB =
TWI_SLAVE_CMD_COMPTRANS_gc ;
257 T W I _ S l a v e T r a n s a c t i o n F i n i s h e d ( twi , TWIS_RESULT_OK ) ;
258 }
259 /* If ACK , master expects more data . */
260 else {
261 if ( twi - > bytesSent < T W I S_ SEND _BUFF ER_S IZE ) {
262 uint8_t data = twi - > sendData [ twi - > bytesSent ];
263 twi - > interface - > SLAVE . DATA = data ;
264 twi - > bytesSent ++;
265
266 /* Send data , wait for data interrupt . */
267 twi - > interface - > SLAVE . CTRLB =
TWI_SLAVE_CMD_RESPONSE_gc ;
268 }
269 /* If buffer overflow . */
270 else {
271 twi - > interface - > SLAVE . CTRLB =
TWI_SLAVE_CMD_COMPTRANS_gc ;
272 T W I _ S l a v e T r a n s a c t i o n F i n i s h e d ( twi ,
TWIS_RESULT_BUFFER_OVERFLOW );
273 }
274 }
275 }
276
277 /* TWI transaction finished function .
278 *
279 * Prepares module for new transaction .
280 *
281 * twi :
282 * The TWI_Slave_t struct instance .
226
283 * result :
284 * The result of the transaction .
285 */
286 void T W I _ S l a v e T r a n s a c t i o n F i n i s h e d (
287 TWI_Slave_t * twi , uint8_t result )
288 {
289 twi - > result = result ;
290 twi - > status = TW IS_STA TUS_R EADY ;
291 }
292
293 /* Telemetry - grabbing function .
294 *
295 * Prepares and fetches sensor - data
296 * for transmission via TWI .
297 *
298 * OBS ! Perhaps this method should read the
299 * struct members of each sensor , in order to
300 * reduce the process time spent in the ISR .
301 *
302 * data :
303 * The high - or low byte of a sensor .
304 * info :
305 * The return value converted to mV .
306 */
307 uint8_t GetTelemetry ( char data ) {
308 uint16_t BV_temp , BT_temp , SAV_temp , SAC_temp ;
309 uint8_t info ;
310
311 switch ( data ) {
312 case 0: // B AT _ V OL T AGE_ HI_BY T E :
313 BV_temp =
314 ( BatteryVoltage () ) * ADC_TO_MILLIVOLTS ;
315 info = (( BV_temp ) >> 8) ;
316 break ;
317
318 case 1: // B AT _ V OL T AGE_ LO_BY T E :
319 info =
320 ( BatteryVoltage () ) * ADC_TO_MILLIVOLTS ;
321 break ;
322
323 case 2: // BAT_TEMP_HI_BYTE :
324 BT_temp =
325 ( BatteryTemp () ) * ADC_TO_MILLIVOLTS ;
326 info = (( BT_temp ) >> 8) ;
327 break ;
328
329 case 3: // BAT_TEMP_LO_BYTE :
330 info =
331 ( BatteryTemp () ) * ADC_TO_MILLIVOLTS ;
227
332 break ;
333
334 case 4: // SA _V OL TA GE _HI_BYTE :
335 SAV_temp =
336 ( So la rA rrayN SVoltage () ) *
ADC_ TO_MILLIVOLTS ;
337 info = (( SAV_temp ) >> 8) ;
338 break ;
339
340 case 5: // SA _V OL TA GE _LO_BYTE :
341 info =
342 ( So la rA rrayN SVoltage () ) *
ADC_ TO_MILLIVOLTS ;
343 break ;
344
345 case 6: // SA _C UR RE NT _HI_BYTE :
346 SAC_temp =
347 ( So la rA rrayN SCurrent () ) *
ADC_ TO_MILLIVOLTS ;
348 info = (( SAC_temp ) >> 8) ;
349 break ;
350
351 case 7: // SA _C UR RE NT _LO_BYTE :
352 info =
353 ( So la rA rrayN SCurrent () ) *
ADC_ TO_MILLIVOLTS ;
354 break ;
355
356 default :
357 info = 0;
358 break ;
359 }
360 return ( info ) ;
361 }
228
13
14 /* Transaction status defines . */
15 # define T WIS_ST ATUS_R EADY 0
16 # define TWIS_STATUS_BUSY 1
17
18 # define A DC_TO_ MILLIV OLTS 1.820
19
20 # define BAT _ VOL T A G E_ H I _B Y T E 0 x80
21 # define BAT _ VOL T A G E_ L O _B Y T E 0 x40
22 # define BAT_TEMP_HI_BYTE 0 x20
23 # define BAT_TEMP_LO_BYTE 0 x10
24 # define SA_V OL TA GE_ HI _B YT E 0 x08
25 # define SA_V OL TA GE_ LO _B YT E 0 x04
26 # define SA_C UR RE NT_ HI _B YT E 0 x02
27 # define SA_C UR RE NT_ LO _B YT E 0 x01
28
29 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
30 // TWI struct / enum declarations
31 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
32 /* Transaction result enumeration */
33 typedef enum TWIS_RESULT_enum {
34 TWI S _RE S ULT _ UN K N O WN = (0 x00 < <0) ,
35 TWIS_RESULT_OK = (0 x01 < <0) ,
36 TWIS_RESULT_BUFFER_OVERFLOW = (0 x02 < <0) ,
37 T W I S _ R E S U L T _ T R A N S M I T _ C O L L I S I O N = (0 x03 < <0) ,
38 TW I S_ R E S U L T _B U S _ E R R O R = (0 x04 < <0) ,
39 TWIS_RESULT_FAIL = (0 x05 < <0) ,
40 TWI S _RE S ULT _ AB O R T ED = (0 x06 < <0) ,
41 } TWIS_RESULT_t ;
42
43 typedef struct TWI_Slave {
44 // Pointer to what interface to use
45 TWI_t * interface ;
46 // Pointer to process data function
47 void (* Process_Data ) ( void ) ;
48 // Read data
49 register8_t receivedData [ T WI S _ R E C E I V E_ B U F FE R _ S IZ E ];
50 // Data to write
51 register8_t sendData [ T W IS _ S END _ BUFFE R_SI ZE ];
52 // Number of bytes received
53 register8_t bytesReceived ;
54 // Number of bytes sent
55 register8_t bytesSent ;
56 // Status of transaction
57 register8_t status ;
58 // Result of transaction
59 register8_t result ;
60 // Strobe to abort
61 bool abort ;
229
62 } TWI_Slave_t ;
63
64 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
65 // Function prototypes
66 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
67 void T W I _ S l a v e I n i t i a l i z e D r i v e r (
68 TWI_Slave_t * twi ,
69 TWI_t * module ,
70 void (* pr o cessDataFunction ) ( void ) ) ;
71
72 void T W I _ S l a v e I n i t i a l i z e M o d u l e (
73 TWI_Slave_t * twi ,
74 uint8_t address ,
75 TWI _S LAVE_ IN TLVL_t intLevel ) ;
76
77 void T W I _ S l a v e I n t e r r u p t H a n d l e r ( TWI_Slave_t * twi ) ;
78 void T W I _ S l a v e A d d r e s s M a t c h H a n d l e r ( TWI_Slave_t * twi ) ;
79 void T W I _S l a v e S t o p H and l er ( TWI_Slave_t * twi ) ;
80 void T W I _S l a v e D a t a H and l er ( TWI_Slave_t * twi ) ;
81 void T W I _S l a v e R e a d H and l er ( TWI_Slave_t * twi ) ;
82 void T W I_ S l a v e W r i t e H an d l er ( TWI_Slave_t * twi ) ;
83 void TWI_SlaveTransactionFinished (
84 TWI_Slave_t * twi , uint8_t result ) ;
85 void T W ID _ S l a v e P r o c e ss D a ta ( void ) ;
86 uint8_t GetTelemetry ( char data ) ;
87
88 # endif /* TWI_DRIVER_H */
230