From 3f80bf2be3c2c744e7be5358c66d220490e6adb9 Mon Sep 17 00:00:00 2001 From: Ilario Gelmetti Date: Fri, 21 Jul 2017 14:18:21 +0200 Subject: [PATCH 1/2] Scan in forward and reverse directions, invert order each time --- mppTracker.py | 74 ++++++++++++++++++++++++++++++++++++--------------- 1 file changed, 53 insertions(+), 21 deletions(-) diff --git a/mppTracker.py b/mppTracker.py index 9b79b23..a0138ec 100755 --- a/mppTracker.py +++ b/mppTracker.py @@ -338,6 +338,7 @@ def weAreDone(sm): # for curve exploration dAngleMax = 25 #[degrees] (plus and minus) +previousScanStartDirection = -1 while True: exploring = 0 @@ -354,7 +355,9 @@ def weAreDone(sm): if t_run > args.t_total: weAreDone(sm) toc = time.time() - tic - + myPrint("Stabilized power at Mpp:", file=sys.stderr, flush=True) + myPrint(i*v*1000,"mW @",v,"V", file=sys.stderr, flush=True) + myPrint("Exploring for new Mpp...", file=sys.stderr, flush=True) exploring = 1 i_explore = numpy.array(i) @@ -363,10 +366,45 @@ def weAreDone(sm): dAngle = 0 angleMpp = numpy.rad2deg(numpy.arctan(i/v*Voc/Isc)) v_set = Vmpp - switched = False - myPrint("Walking up in voltage...", file=sys.stderr, flush=True) - while dAngle < dAngleMax: - v_set = v_set + dV + scanDirection = previousScanStartDirection = previousScanStartDirection * -1 + myPrint("Walking {direction} in voltage for starting scan...".format(direction="up" if scanDirection == 1 else "down"), file=sys.stderr, flush=True) + while -dAngleMax < dAngle < dAngleMax: + v_set = v_set + dV * scanDirection + sm.write(':source:voltage {0:0.4f}'.format(v_set)) + [v, i, tx, status] = sm.query_ascii_values('READ?') + i = i*polarity + t_run = tx-t0 + myPrint('{:1d},{:.4e},{:.4e},{:.4e}'.format(exploring,t_run,v,i), flush=True) + if t_run > args.t_total: + weAreDone(sm) + dAngle = numpy.rad2deg(numpy.arctan(i/v*Voc/Isc)) - angleMpp + myPrint("{limit} exploration voltage limit reached.".format(limit="Upper" if scanDirection == 1 else "Lower"), file=sys.stderr, flush=True) + scanDirection = scanDirection * -1 + myPrint("Scanning walking {direction} in voltage...".format(direction="up" if scanDirection == 1 else "down"), file=sys.stderr, flush=True) + while -dAngleMax < dAngle < dAngleMax: + v_set = v_set + dV * scanDirection + sm.write(':source:voltage {0:0.4f}'.format(v_set)) + [v, i, tx, status] = sm.query_ascii_values('READ?') + i = i*polarity + t_run = tx-t0 + myPrint('{:1d},{:.4e},{:.4e},{:.4e}'.format(exploring,t_run,v,i), flush=True) + if t_run > args.t_total: + weAreDone(sm) + i_explore = numpy.append(i_explore, i) + v_explore = numpy.append(v_explore, v) + dAngle = numpy.rad2deg(numpy.arctan(i/v*Voc/Isc)) - angleMpp + # find the powers for the values we just explored + p_explore = v_explore*i_explore + maxIndexFirstScan = numpy.argmax(p_explore) + VmppFirstScan = v_explore[maxIndex] + myPrint("{limit} exploration voltage limit reached.".format(limit="Upper" if scanDirection == 1 else "Lower"), file=sys.stderr, flush=True) + myPrint("Voltage for Mpp in {direction} scan found at {:.4e} V".format(VmppFirstScan, limit="forward" if scanDirection == 1 else "reverse"), file=sys.stderr, flush=True) + i_explore = numpy.array(i) + v_explore = numpy.array(v) + scanDirection = scanDirection * -1 + myPrint("Scanning walking {direction} in voltage...".format(direction="up" if scanDirection == 1 else "down"), file=sys.stderr, flush=True) + while -dAngleMax < dAngle < dAngleMax: + v_set = v_set + dV * scanDirection sm.write(':source:voltage {0:0.4f}'.format(v_set)) [v, i, tx, status] = sm.query_ascii_values('READ?') i = i*polarity @@ -377,27 +415,21 @@ def weAreDone(sm): i_explore = numpy.append(i_explore, i) v_explore = numpy.append(v_explore, v) dAngle = numpy.rad2deg(numpy.arctan(i/v*Voc/Isc)) - angleMpp - if (dAngle < -dAngleMax) and not switched: - myPrint("Upper exploration voltage limit reached.", file=sys.stderr, flush=True) - myPrint("Walking down in voltage...", file=sys.stderr, flush=True) - switched = True - dV = dV * -1 # switch our voltage walking direction (only once) - - myPrint("Lower exploration voltage limit reached.", file=sys.stderr, flush=True) - # find the powers for the values we just explored p_explore = v_explore*i_explore - maxIndex = numpy.argmax(p_explore) - Vmpp = v_explore[maxIndex] + maxIndexSecondScan = numpy.argmax(p_explore) + VmppSecondScan = v_explore[maxIndex] + myPrint("{limit} exploration voltage limit reached.".format(limit="Upper" if scanDirection == 1 else "Lower"), file=sys.stderr, flush=True) + myPrint("Voltage for Mpp in {direction} scan found at {:.4e} V".format(VmppSecondScan, limit="forward" if scanDirection == 1 else "reverse"), file=sys.stderr, flush=True) - myPrint("New Mpp found:", file=sys.stderr, flush=True) - myPrint(p_explore[maxIndex]*1000,"mW @",Vmpp,"V", file=sys.stderr, flush=True) + Vmpp = (VmppFirstScan + VmppSecondScan) / 2 + myPrint("New Mpp found at {:.4e} V:".format(Vmpp), file=sys.stderr, flush=True) # now let's walk back to our new Vmpp - dV = dV * -1 - v_set = v_set + dV + scanDirection = scanDirection * -1 + v_set = v_set + dV * scanDirection myPrint("Walking back to Mpp...", file=sys.stderr, flush=True) - while v_set < Vmpp: + while not Vmpp - dV <= v_set <= Vmpp + dV: sm.write(':source:voltage {0:0.4f}'.format(v_set)) [v, i, tx, status] = sm.query_ascii_values('READ?') i = i*polarity @@ -405,7 +437,7 @@ def weAreDone(sm): myPrint('{:1d},{:.4e},{:.4e},{:.4e}'.format(exploring,t_run,v,i), flush=True) if t_run > args.t_total: weAreDone(sm) - v_set = v_set + dV + v_set = v_set + dV * scanDirection sm.write(':source:voltage {0:0.4f}'.format(Vmpp)) myPrint("Mpp reached.", file=sys.stderr, flush=True) From 102f188ddbc15a787fe3586960895c457b7b73d5 Mon Sep 17 00:00:00 2001 From: Ilario Gelmetti Date: Mon, 24 Jul 2017 14:46:49 +0200 Subject: [PATCH 2/2] Fixes --- mppTracker.py | 26 +++++++++++++++++++------- 1 file changed, 19 insertions(+), 7 deletions(-) diff --git a/mppTracker.py b/mppTracker.py index a0138ec..ed239ad 100755 --- a/mppTracker.py +++ b/mppTracker.py @@ -337,7 +337,9 @@ def weAreDone(sm): # setup complete. the real mppTracker begins here # for curve exploration -dAngleMax = 25 #[degrees] (plus and minus) +dAngleMax = dAngleMaxLimit = 25 #[degrees] (plus and minus) +dAngleMinLimit = 3 +scannedPointsMinLimit = 5 previousScanStartDirection = -1 while True: @@ -380,8 +382,9 @@ def weAreDone(sm): dAngle = numpy.rad2deg(numpy.arctan(i/v*Voc/Isc)) - angleMpp myPrint("{limit} exploration voltage limit reached.".format(limit="Upper" if scanDirection == 1 else "Lower"), file=sys.stderr, flush=True) scanDirection = scanDirection * -1 + scannedPoints = 0 myPrint("Scanning walking {direction} in voltage...".format(direction="up" if scanDirection == 1 else "down"), file=sys.stderr, flush=True) - while -dAngleMax < dAngle < dAngleMax: + while scannedPoints < scannedPointsMinLimit or -dAngleMax < dAngle < dAngleMax: v_set = v_set + dV * scanDirection sm.write(':source:voltage {0:0.4f}'.format(v_set)) [v, i, tx, status] = sm.query_ascii_values('READ?') @@ -393,17 +396,21 @@ def weAreDone(sm): i_explore = numpy.append(i_explore, i) v_explore = numpy.append(v_explore, v) dAngle = numpy.rad2deg(numpy.arctan(i/v*Voc/Isc)) - angleMpp + scannedPoints += 1 # find the powers for the values we just explored p_explore = v_explore*i_explore maxIndexFirstScan = numpy.argmax(p_explore) - VmppFirstScan = v_explore[maxIndex] + VmppFirstScan = v_explore[maxIndexFirstScan] + ImppFirstScan = i_explore[maxIndexFirstScan] + angleMppFirstScan = numpy.rad2deg(numpy.arctan(ImppFirstScan/VmppFirstScan*Voc/Isc)) myPrint("{limit} exploration voltage limit reached.".format(limit="Upper" if scanDirection == 1 else "Lower"), file=sys.stderr, flush=True) - myPrint("Voltage for Mpp in {direction} scan found at {:.4e} V".format(VmppFirstScan, limit="forward" if scanDirection == 1 else "reverse"), file=sys.stderr, flush=True) + myPrint("Voltage for Mpp in {direction} scan found at {:.4e} V".format(VmppFirstScan, direction="forward" if scanDirection == 1 else "reverse"), file=sys.stderr, flush=True) i_explore = numpy.array(i) v_explore = numpy.array(v) + scannedPoints = 0 scanDirection = scanDirection * -1 myPrint("Scanning walking {direction} in voltage...".format(direction="up" if scanDirection == 1 else "down"), file=sys.stderr, flush=True) - while -dAngleMax < dAngle < dAngleMax: + while scannedPoints < scannedPointsMinLimit or -dAngleMax < dAngle < dAngleMax: v_set = v_set + dV * scanDirection sm.write(':source:voltage {0:0.4f}'.format(v_set)) [v, i, tx, status] = sm.query_ascii_values('READ?') @@ -415,16 +422,21 @@ def weAreDone(sm): i_explore = numpy.append(i_explore, i) v_explore = numpy.append(v_explore, v) dAngle = numpy.rad2deg(numpy.arctan(i/v*Voc/Isc)) - angleMpp + scannedPoints += 1 # find the powers for the values we just explored p_explore = v_explore*i_explore maxIndexSecondScan = numpy.argmax(p_explore) - VmppSecondScan = v_explore[maxIndex] + VmppSecondScan = v_explore[maxIndexSecondScan] + ImppSecondScan = i_explore[maxIndexSecondScan] + angleMppSecondScan = numpy.rad2deg(numpy.arctan(ImppSecondScan/VmppSecondScan*Voc/Isc)) myPrint("{limit} exploration voltage limit reached.".format(limit="Upper" if scanDirection == 1 else "Lower"), file=sys.stderr, flush=True) - myPrint("Voltage for Mpp in {direction} scan found at {:.4e} V".format(VmppSecondScan, limit="forward" if scanDirection == 1 else "reverse"), file=sys.stderr, flush=True) + myPrint("Voltage for Mpp in {direction} scan found at {:.4e} V".format(VmppSecondScan, direction="forward" if scanDirection == 1 else "reverse"), file=sys.stderr, flush=True) Vmpp = (VmppFirstScan + VmppSecondScan) / 2 myPrint("New Mpp found at {:.4e} V:".format(Vmpp), file=sys.stderr, flush=True) + mppAngleVariation = max(abs(angleMpp - angleMppFirstScan), abs(angleMpp - angleMppSecondScan)) + dAngleMax = min(mppAngleVariation + dAngleMinLimit, dAngleMaxLimit) # now let's walk back to our new Vmpp scanDirection = scanDirection * -1 v_set = v_set + dV * scanDirection