-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathSolarCell.m
More file actions
195 lines (167 loc) · 6.01 KB
/
SolarCell.m
File metadata and controls
195 lines (167 loc) · 6.01 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
%% SolarCell Class
% Defines a single solar cell
% Stores IV characteristics of cell in a vector called viVector
%
% Cell is initialized by cell = SolarCell.CreateCell(id)
classdef SolarCell < handle
properties
id uint32 % Unique for each cell on car
name = "" % Identifies SolarCell as base object
parentId = 0 % ID of module cell belongs to
eta = [] % Ideality factor
Is = [] % Reverse-bias saturation current
R = [] % Series resistance
IoptMax = [] % Optical current in full light
T = [] % Cell temperature
theta = [] % Pitch angle (0 when flat)
phi= [] % Roll angle (0 when flat)
viVector % VI vector for storing IV curve
fullyDefined = 0 % All parameters have a value
end
methods
% Check if cell is fully defined every time parameter is set
function set.eta(obj, eta)
obj.eta = eta;
obj.CheckFullyDefined;
end
function set.Is(obj, Is)
obj.Is = Is;
obj.CheckFullyDefined;
end
function set.R(obj, R)
obj.R = R;
obj.CheckFullyDefined;
end
function set.T(obj, T)
obj.T = T;
obj.CheckFullyDefined;
end
function set.IoptMax(obj, IoptMax)
obj.IoptMax = IoptMax;
obj.CheckFullyDefined;
end
function set.theta(obj, theta)
obj.theta = theta;
obj.CheckFullyDefined;
end
function set.phi(obj, phi)
obj.phi = phi;
obj.CheckFullyDefined;
end
% Generates VI Vector based on light intensity, sun zenith, and
% sun azimuth
function GenerateCurve(obj, li, zen, azm)
if obj.fullyDefined
% Compute effective light intensity based on sun angles
sunVector = [sind(zen)*cosd(azm) sind(zen)*sind(azm) cosd(zen)];
sunVectorUnit = sunVector / norm(sunVector);
cellNormal = [-sind(obj.theta) sind(obj.phi) cosd(obj.theta)];
cellNormalUnit = cellNormal / norm(cellNormal);
cosIncidence = dot(sunVectorUnit, cellNormalUnit);
effLi = li * cosIncidence;
% Compute effective optical current based on effective
% light intensity
IoptEff = obj.IoptMax * effLi;
% Generate VI vector
Id = linspace(-1, 10, 11001); % Current points for horizontal axis
multiplier = obj.eta * (obj.T / 11586);
log_term = log(((IoptEff - Id) / obj.Is) + 1);
series_r_drop = Id * obj.R;
obj.viVector = multiplier * log_term - series_r_drop;
% Handle undefined logs
obj.viVector = obj.viVector ./ (imag(log_term) == 0);
obj.viVector = real(obj.viVector);
else
error('Cell must by fully defined');
end
end
% Returns cell current given voltage
function I = GetCurrent(obj, V)
if obj.fullyDefined
[~, idx] = min(abs(obj.viVector - V));
I = obj.IdxtoI(idx);
else
error('Cell must be fully defined');
end
end
% Returns cell voltage given current
function V = GetVoltage(obj, I)
if obj.fullyDefined
idx = obj.ItoIdx(I);
V = obj.viVector(idx);
else
error('Cell must be fully defined');
end
end
% Returns open-circuit voltage
function Voc = GetVoc(obj)
if obj.fullyDefined
Voc = obj.GetVoltage(0);
else
error('Cell must be fully defined');
end
end
% Returns short-circuit current
function Isc = GetIsc(obj)
if obj.fullyDefined
Isc = obj.GetCurrent(0);
else
error('Cell must be fully defined');
end
end
% Returns power given voltage
function P = GetPowerV(obj, V)
if obj.fullyDefined
P = V .* obj.GetCurrent(V);
P = P .* ~(isinf(P));
else
error('Cell must be fully defined');
end
end
% Returns power given current
function P = GetPowerI(obj, I)
if obj.fullyDefined
P = I .* obj.GetVoltage(I);
P = P .* ~(isinf(P));
else
error('Cell must be fully defined');
end
end
% Returns electrical parameters at the maximum power point
function [Vmpp, Impp, Pmpp] = GetMPP(obj)
if obj.fullyDefined
Impp = fminbnd(@(I)obj.GetPowerI(I) * (-1), 0, obj.IoptMax);
Vmpp = obj.GetVoltage(Impp);
Pmpp = Impp * Vmpp;
else
error('Cell must be fully defined');
end
end
end
methods (Access = private)
% Sees if all parameters are populated and sets fullyDefined
function CheckFullyDefined(obj)
if ~isempty(obj.eta) && ~isempty(obj.Is) && ~isempty(obj.IoptMax) &&...
~isempty(obj.T) && ~isempty(obj.theta) && ~isempty(obj.phi)
obj.fullyDefined = 1;
else
obj.fullyDefined = 0;
end
end
end
methods (Static)
% Object constructor function
function obj = CreateCell(id)
obj = SolarCell;
obj.id = id;
end
% Convert current (A) to index
function idx = ItoIdx(I)
idx = floor((I + 1) * 1000 + 1);
end
% Convert index to current (A)
function I = IdxtoI(idx)
I = (idx - 1) / 1000 - 1;
end
end
end