From 1eb3928e429e0fe9fe6f1f8a8a9d9818cd520922 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Mon, 11 Oct 2010 22:46:18 +1100 Subject: [PATCH] new version --- pv_model/pv_model.py | 96 +++++++++++++++++++++++++++++++++++--------- 1 file changed, 78 insertions(+), 18 deletions(-) diff --git a/pv_model/pv_model.py b/pv_model/pv_model.py index 2b814af..27009f2 100755 --- a/pv_model/pv_model.py +++ b/pv_model/pv_model.py @@ -271,12 +271,12 @@ class subpanel: if recursive: for c in self.cells: c._recalc() - # array Voc is sum of cells + # subpanel Voc is sum of cells self.Voc = 0 for c in self.cells: self.Voc += c.V(0) - # array Isc is min of cells + # subpanel Isc is min of cells self.Isc = self.cells[0].I(0) for c in self.cells: if c.I(0) < self.Isc: @@ -339,10 +339,12 @@ class panel: for c in self.subpanels: self.Voc += c.V(0) - # array Isc is min of cells + # panel Isc is max of cells. It is the maximum + # not the minimum due to the effect of the bypass diodes + # on the subpanels self.Isc = self.subpanels[0].I(0) for c in self.subpanels: - if c.I(0) < self.Isc: + if c.I(0) > self.Isc: self.Isc = c.I(0) def V(self, I): @@ -391,13 +393,15 @@ class string: if recursive: for p in self.panels: p._recalc(recursive) - # array Isc is min of cells + # string Isc is max of the panel currents + # it is max, not min, as any underperforming + # panels will go into bypass self.Isc = self.panels[0].I(0) for c in self.panels: - if c.I(0) < self.Isc: + if c.I(0) > self.Isc: self.Isc = c.I(0) - # array Voc is sum of cells + # string Voc is sum of panels self.Voc = 0 for c in self.panels: self.Voc += c.V(0) @@ -463,7 +467,8 @@ class pvarray: @cacheobj def V(self, I): def Ierr(x): - return abs(I - self.I(x)) + ret = abs(I - self.I(x)) + return ret if I < 0: lower = 0 upper = panel_Voc*len(self.strings[0].panels) @@ -474,7 +479,7 @@ class pvarray: lower = 0 upper = panel_Voc*opts.string_length print "aV I=%g lower=%g upper=%g" % (I, lower, upper) - return find_best(Ierr, lower, upper) + return find_best2(Ierr, lower, upper) def P(self, V): if V < inverter_range[0] or V > inverter_range[1]: @@ -638,6 +643,57 @@ def shaded_2mpp(): print("A1=%.2f A2=%.2f MPPP=%.2fW (%d shaded)" % (Pa1, Pa2, Pa1+Pa2, i+1)) +def panel_shading(): + '''plot shading effects on 1 panel''' + p = panel() + maxv = p.Voc + minv = 0 + plotit(p.P, minv, maxv, label='Unshaded', loc='upper left') + + pylab.xlabel('Voltage (V)') + pylab.ylabel('Power (W)') + pylab.title("1 Panel") + + for i in range(0, opts.num_subpanels): + p.subpanels[i].set_irradiance(opts.irradiance * opts.shade_factor) + p._recalc(True) + plotit(p.P, minv, maxv, label='%d shaded' % (i+1), loc='upper left') + pylab.show() + +def panel_shading_IV(): + '''plot shading effects on 1 panel''' + p = panel() + maxv = p.Voc + minv = 0 + plotit(p.I, minv, maxv, label='Unshaded', loc='upper left') + + pylab.xlabel('Voltage (V)') + pylab.ylabel('Current (A)') + pylab.title("1 Panel") + + for i in range(0, opts.num_subpanels): + p.subpanels[i].set_irradiance(opts.irradiance * opts.shade_factor) + p._recalc(True) + plotit(p.I, minv, maxv, label='%d shaded' % (i+1), loc='upper left') + pylab.show() + +def panel_shading_VI(): + '''plot shading effects on 1 panel''' + p = panel() + maxi = p.Isc + mini = 0 + plotit(p.V, mini, maxi, label='Unshaded', loc='upper left') + + pylab.xlabel('Current (A)') + pylab.ylabel('Voltage (V)') + pylab.title("1 Panel") + + for i in range(0, opts.num_subpanels): + p.subpanels[i].set_irradiance(opts.irradiance * opts.shade_factor) + p._recalc(True) + plotit(p.V, mini, maxi, label='%d shaded' % (i+1), loc='upper left') + pylab.show() + def mpp_loss(): '''show loss from not having separate MPPTs per string''' n=opts.string_length @@ -1012,7 +1068,7 @@ def selftest(): if err > tolerance: raise Exception("%s: v1=%f v2=%g" % (tag, v1, v2)) - def check_IV(tag, m, tolerance=1.0): + def check_IV(tag, m, tolerance=10.0): irange = numpy.arange(-m.Isc, m.Isc*2, (3*m.Isc/100)) for i in irange: check('%s: I=%g Isc=%g' % (tag, i, m.Isc), m.I(m.V(i)), i, @@ -1042,7 +1098,7 @@ def selftest(): p2 = c.P(cell_Vmp) check("irradiance", p1, p2/2, tolerance=10) - check("leakage", c.I(c.Voc+1), -1.0/(opts.panel_Roc/cell_scale)) + check("leakage", c.I(c.Voc+1), -1.0/(opts.panel_Roc/cell_scale), tolerance=10) @@ -1052,14 +1108,14 @@ def selftest(): check("Voc", cell_Voc*opts.cells_per_subpanel, s.V(0)) check("Isc", panel_Isc, s.I(0)) check("Vmp", cell_Vmp*opts.cells_per_subpanel, s.V(panel_Imp)) - check("Imp", panel_Imp, s.I(panel_Vmp*opts.cells_per_subpanel)) + check("Imp", panel_Imp, s.I(panel_Vmp/opts.num_subpanels)) check_IV("subpanel IV", s) s2=subpanel() s2.set_irradiance(500) check_IV("subpanel IV 500W/m2", s2, tolerance=2.0) - Vmp = panel_Vmp/opts.cells_per_subpanel + Vmp = panel_Vmp/opts.num_subpanels check("irradiance", s2.P(Vmp), s.P(Vmp)/2, tolerance=10) check("bypass1", s.I(-1.0) - s.Isc, 1.0/subpanel_Rbp) @@ -1073,14 +1129,15 @@ def selftest(): check("Isc", panel_Isc, p.I(0)) check("Vmp", panel_Vmp, p.V(panel_Imp)) check("Imp", panel_Imp, p.I(Vmp)) - check("bypass", p.I(-1.0) - p.Isc, 1.0/subpanel_Rbp) + check("bypass", p.I(-1.0) - p.Isc, 1.0/(subpanel_Rbp*opts.num_subpanels)) check_IV("panel IV", p) p2=subpanel() p2.set_irradiance(500) check_IV("panel IV 500W/m2", p2, tolerance=2.0) - check("irradiance", p2.P(Vmp), p.P(Vmp)/2, tolerance=10) + Vmp = panel_Vmp/opts.num_subpanels + check("irradiance", p2.P(Vmp), p.P(Vmp)/2, tolerance=15) print "Checking string behaviour" s=string(opts.string_length) @@ -1088,7 +1145,7 @@ def selftest(): check("Isc", panel_Isc, s.I(0)) check("Vmp", panel_Vmp*opts.string_length, s.V(panel_Imp)) check("Imp", panel_Imp, s.I(panel_Vmp*opts.string_length)) - check("bypass", s.I(-1.0*opts.string_length) - s.Isc, 1.0/subpanel_Rbp) + check("bypass", s.I(-1.0*opts.string_length) - s.Isc, 1.0/(subpanel_Rbp*opts.num_subpanels)) check_IV("string IV", s, tolerance=5.0) @@ -1106,7 +1163,7 @@ def selftest(): check("Isc", panel_Isc*2, a.I(0)) # check("Vmp", panel_Vmp*opts.string_length, a.V(panel_Imp*2)) check("Imp", panel_Imp*2, a.I(panel_Vmp*opts.string_length)) - check("bypass", a.I(-1.0*opts.string_length) - a.Isc, 2.0/subpanel_Rbp) + check("bypass", a.I(-1.0*opts.string_length) - a.Isc, 2.0/(opts.num_subpanels*subpanel_Rbp)) check_IV("array IV", a, tolerance=2.0) @@ -1137,6 +1194,9 @@ if __name__ == "__main__": "panel_IV_T" : panel_IV_T, "panel_L" : panel_L, "panel_IV_L" : panel_IV_L, + "panel-shading": panel_shading, + "panel-shadingIV": panel_shading_IV, + "panel-shadingVI": panel_shading_VI, "string_P" : string_P, "string_IV" : string_IV, "string_VI" : string_VI, @@ -1174,7 +1234,7 @@ if __name__ == "__main__": parser.add_option("", "--irradiance", dest="irradiance", help="light level (W/m2)",type='float', default=1000) parser.add_option("", "--shade-factor", dest="shade_factor", help="shading factor",type='float', default=0.05) parser.add_option("", "--subpanels", dest="num_subpanels", help="subpanels per panel", - type='int', default=1) + type='int', default=3) parser.add_option("", "--cells-per-subpanel", dest="cells_per_subpanel", help="cells per subpanel", type='int', default=1) parser.add_option("", "--blocking-diodes", dest="blocking_diodes", -- 2.34.1