def log_conn_state(inv, data=None): try: connected = inverter.get_conn_state(inv) power = inverter.get_power(inv, data) ts.log('Current connection state is %s - power output = %0.3f W' % (inverter.conn_state_str(connected), power)) except Exception, e: ts.log('Error logging connect state: %s' % str(e)) raise
def log_conn_state(inv, data=None): try: connected = inverter.get_conn_state(inv) power = inverter.get_power(inv, data) pf = inverter.get_power_factor(inv, data) ts.log('Current connection state is %s. Power output = %0.3f W. power factor %0.3f.' % (inverter.conn_state_str(connected), power, pf)) except Exception, e: ts.log_error('Error logging connect state: %s' % str(e)) raise
def test_run(): result = script.RESULT_FAIL das = None wfmtrigger = None gsim = None pv = None inv = None filename = None disable = None try: ifc_type = ts.param_value('comm.ifc_type') ifc_name = ts.param_value('comm.ifc_name') if ifc_type == client.MAPPED: ifc_name = ts.param_value('comm.map_name') baudrate = ts.param_value('comm.baudrate') parity = ts.param_value('comm.parity') ipaddr = ts.param_value('comm.ipaddr') ipport = ts.param_value('comm.ipport') slave_id = ts.param_value('comm.slave_id') time_window = ts.param_value('vrt.settings.time_window') timeout_period = ts.param_value('vrt.settings.timeout_period') ramp_time = ts.param_value('vrt.settings.ramp_time') h_n_points = ts.param_value('vrt.settings.h_n_points') h_curve_num = ts.param_value('vrt.settings.h_curve_num') h_time = ts.param_value('vrt.h_curve.h_time') h_volt = ts.param_value('vrt.h_curve.h_volt') l_n_points = ts.param_value('vrt.settings.l_n_points') l_curve_num = ts.param_value('vrt.settings.l_curve_num') l_time = ts.param_value('vrt.l_curve.l_time') l_volt = ts.param_value('vrt.l_curve.l_volt') ride_through = ts.param_value('vrt.settings.ride_through') hc_n_points = ts.param_value('vrt.settings.hc_n_points') hc_curve_num = ts.param_value('vrt.settings.hc_curve_num') hc_time = ts.param_value('vrt.hc_curve.hc_time') hc_volt = ts.param_value('vrt.hc_curve.hc_volt') lc_n_points = ts.param_value('vrt.settings.lc_n_points') lc_curve_num = ts.param_value('vrt.settings.lc_curve_num') lc_time = ts.param_value('vrt.lc_curve.lc_time') lc_volt = ts.param_value('vrt.lc_curve.lc_volt') time_msa = ts.param_value('invt.time_msa') test_point_offset = ts.param_value('invt.test_point_offset') vrt_period = ts.param_value('invt.VRT_period') pretest_delay = ts.param_value('invt.pretest_delay') failure_count = ts.param_value('invt.failure_count') verification_delay = ts.param_value('invt.verification_delay') posttest_delay = ts.param_value('invt.posttest_delay') disable = ts.param_value('invt.disable') # initialize data acquisition system das, wfmtrigger, wfmtrigger_params = das_init() # initialize pv simulation pv = pvsim.pvsim_init(ts) pv.power_on() # initialize grid simulation gsim = gridsim.gridsim_init(ts) #Inverter scan after grid and PV simulation setup so that Modbus registers can be read. ts.log('Scanning inverter') inv = client.SunSpecClientDevice(ifc_type, slave_id=slave_id, name=ifc_name, baudrate=baudrate, parity=parity, ipaddr=ipaddr, ipport=ipport) ### Find test points ### # determine the test points for the HVRT tests (ends near nominal) h_v_test_points = [h_volt[h_volt['index_start']]+test_point_offset] h_v_test_points.append(h_volt[h_volt['index_start']]-test_point_offset) for x in range(h_volt['index_start']+1, h_volt['index_count']): h_v_test_points.append(h_volt[x]+test_point_offset) h_v_test_points.append(h_volt[x]-test_point_offset) h_v_test_points.append(h_volt[h_volt['index_count']]+test_point_offset) h_v_test_points.append(h_volt[h_volt['index_count']]-test_point_offset) #ts.log_debug(h_v_test_points) # determine the test points for the LVRT tests (starts near nominal) l_v_test_points = [l_volt[l_volt['index_count']]+test_point_offset] l_v_test_points.append(l_volt[l_volt['index_count']]-test_point_offset) for x in range(l_volt['index_count']-1, l_volt['index_start'], -1): l_v_test_points.append(l_volt[x]+test_point_offset) l_v_test_points.append(l_volt[x]-test_point_offset) l_v_test_points.append(l_volt[l_volt['index_start']]+test_point_offset) l_v_test_points.append(l_volt[l_volt['index_start']]-test_point_offset) #ts.log_debug(l_v_test_points) v_test_points = h_v_test_points + l_v_test_points list(set(v_test_points)) # remove duplicate points # ts.log_debug(v_test_points) if ride_through == 'Yes': # determine the test points for the HVRTC tests (ends near nominal) hc_v_test_points = [hc_volt[hc_volt['index_start']]+test_point_offset] hc_v_test_points.append(hc_volt[hc_volt['index_start']]-test_point_offset) for x in range(hc_volt['index_start']+1, hc_volt['index_count']): hc_v_test_points.append(hc_volt[x]+test_point_offset) hc_v_test_points.append(hc_volt[x]-test_point_offset) hc_v_test_points.append(hc_volt[hc_volt['index_count']]+test_point_offset) hc_v_test_points.append(hc_volt[hc_volt['index_count']]-test_point_offset) #ts.log_debug(hc_v_test_points) # determine the test points for the LVRTC tests (starts near nominal) lc_v_test_points = [lc_volt[lc_volt['index_count']]+test_point_offset] lc_v_test_points.append(lc_volt[lc_volt['index_count']]-test_point_offset) for x in range(lc_volt['index_count']-1, lc_volt['index_start'], -1): lc_v_test_points.append(lc_volt[x]+test_point_offset) lc_v_test_points.append(lc_volt[x]-test_point_offset) lc_v_test_points.append(lc_volt[lc_volt['index_start']]+test_point_offset) lc_v_test_points.append(lc_volt[lc_volt['index_start']]-test_point_offset) #ts.log_debug(lc_v_test_points) v_test_points = v_test_points + hc_v_test_points + lc_v_test_points v_test_points = list(set(v_test_points)) # remove duplicate points v_test_points.sort() # remove negative test points for x in range(len(v_test_points)-1, 0, -1): if v_test_points[x] < 0: del v_test_points[x] ts.log('Voltage Test points are %s' % v_test_points) ######## Begin Test ######## #if pretest_delay > 0: # ts.log('Waiting for pre-test delay of %d seconds' % pretest_delay) # ts.sleep(pretest_delay) # note: timing parameters are not tested currently by this script - would need to wrap the assignment into loop # below to determine response times and timeout periods ts.log('Writing the VRT curves to the EUT') ''' inverter.set_vrt_trip_high(inv, h_time=h_time, h_volt=h_volt, h_n_points=h_n_points, h_curve_num=h_curve_num, time_window=time_window, timeout_period=timeout_period, ramp_time=ramp_time, enable=1, wfmtrigger=wfmtrigger) inverter.set_vrt_trip_high(inv, l_time=l_time, l_volt=l_volt, l_n_points=l_n_points, l_curve_num=l_curve_num, time_window=time_window, timeout_period=timeout_period, ramp_time=ramp_time, enable=1, wfmtrigger=wfmtrigger) if ride_through == 'Yes': inverter.set_vrt_stay_connected_high(inv, hc_time=hc_time, hc_volt=hc_volt, hc_n_points=hc_n_points, hc_curve_num=hc_curve_num, time_window=time_window, timeout_period=timeout_period, ramp_time=ramp_time, enable=1, wfmtrigger=wfmtrigger) inverter.set_vrt_stay_connected_low(inv, lc_time=lc_time, lc_volt=lc_volt, lc_n_points=lc_n_points, lc_curve_num=lc_curve_num, time_window=time_window, timeout_period=timeout_period, ramp_time=ramp_time, enable=1, wfmtrigger=wfmtrigger) ''' failures = 0 # failure counter for i in xrange(0, len(v_test_points)): # determine the expected behavior c_time, d_time = predict_vrt_response_time(v_test_points[i], ride_through, h_time=h_time, h_volt=h_volt, h_n_points=h_n_points, l_time=l_time, l_volt=l_volt, l_n_points=l_n_points, hc_time=hc_time, hc_volt=hc_volt, hc_n_points=hc_n_points, lc_time=lc_time, lc_volt=lc_volt, lc_n_points=lc_n_points) ts.log('Test %i, test voltage = %0.3f %%Vref. Expected Ride-Through Time = %0.3f sec. ' 'Expected Trip Time = %0.3f sec.' % (i+1, v_test_points[i], c_time, d_time)) if d_time == 0.: # test doesn't have a trip boundary. Set d_time to max time plus verification time max_time = max(l_time, lc_time, h_time, hc_time) ts.log_debug('max_time: %s, max(max_time): %s' % (max_time, max(max_time))) d_time = max_time + verification_delay ### Make sure the EUT is on and operating if inverter.get_conn_state(inv) and inverter.get_power_norm(inv) < 0.05: ts.log_warning('EUT not operating! Checking grid simulator operations.') # if the inverter is off it's probably because the grid simulator is misconfigured. if gsim: gsim.profile_stop() #abort the profile ts.log('grid nominal voltage: %s' % gsim.v_nom()) gsim.voltage(gsim.v_nom()) # return simulator to nominal voltage ts.log('Waiting up to %d seconds for EUT to begin power export.' % (verification_delay+pretest_delay)) if verify_initial_conn_state(inv, state=inverter.CONN_CONNECT, time_period=verification_delay+pretest_delay, das=das) is False: ts.log_error('Inverter unable to be set to connected state.') raise script.ScriptFail() ### Arm the data acquisition system for waveform capture if das is not None: das_time = inverter.get_time(das=das) while das_time == inverter.get_time(das=das): ts.log('Monitoring the data stream to ensure the das is prepared for a waveform capture. ' 'DAS time: %s' % inverter.get_time(das=das)) ts.sleep(1) ts.log('Configuring the data capture for the following channels: %s' % wfmtrigger_params.get('trigacqchannels')) ts.log('Configuring the %s waveform trigger for %s = %0.3f' % (wfmtrigger_params.get('trigcondition'), wfmtrigger_params.get('trigchannel'), float(wfmtrigger_params.get('trigval')))) # ts.log_debug('wfmtrigger_params = %s' % wfmtrigger_params) wfmtrigger.trigger(wfmtrigger_params=wfmtrigger_params) ts.log('Data acquisition preparing for waveform capture. Waiting for pre-test delay of %d seconds' % pretest_delay) starttime = time.time() while pretest_delay >= (time.time()-starttime): totaltime = time.time()-starttime ts.log('Waiting %0.3f more seconds.' % (pretest_delay-totaltime)) ts.sleep(1.0 - totaltime % 1) else: # there is no data acquisition system ts.log_warning('No data acquisition system configured.') if ts.confirm('Please configure the trigger to capture the ride-through and enable it.') is False: raise script.ScriptFail('Aborted VRT!') if v_test_points[i] < 100.: vrt_test_voltage = v_test_points[i]+test_point_offset else: vrt_test_voltage = v_test_points[i]-test_point_offset ### Execute the voltage change if gsim is not None: ### create transient event in grid simulator if d_time == 0 and c_time == 0: # near nominal test_duration = max(h_time, l_time, lc_time, hc_time) # be sure to catch end of transient with at least a 3 cycle window wfmtrigger_params['posttrig'] = test_duration + max(verification_delay, 0.0166*3) else: test_duration = max(c_time, d_time) # be sure to catch end of transient with at least a 3 cycle window wfmtrigger_params['posttrig'] = test_duration + max(verification_delay, 0.0166*3) ts.log('The post trigger time has been adjusted to %s for this ride through test to capture ' 'the EUT dynamics' % wfmtrigger_params.get('posttrig')) # Use the profile so the timing for the event is accurate and there is a trigger from the simulator gsim.profile_load(profile_name='Transient_Step', v_step=vrt_test_voltage, f_step=100, t_step=test_duration) ts.log('Profile is loaded in simulator. Running the grid simulator profile.') gsim.profile_start() else: ts.log('Must set the grid simulator voltage to the ride-through voltage.') if ts.confirm('Set the grid simulator to the test voltage: %0.3f %%Vref.' % vrt_test_voltage) is False: raise script.ScriptFail('Aborted VRT!') ### Wait for DAS to capture transient event start_time = time.time() elapsed_time = 0. while elapsed_time <= wfmtrigger_params['posttrig']: ts.log('Waiting for waveform capture to complete. Total time remaining %0.3f seconds' % (wfmtrigger_params['posttrig']-elapsed_time)) ts.sleep(0.93) elapsed_time = time.time() - start_time ### Screen waveform data and save in the results file if das is not None: ts.log('Waiting post test delay of %0.2f seconds before processing the data file.' % posttest_delay) ts.sleep(posttest_delay) # get data from waveform saved on the hard drive # (this function could use a little help to make it more robust...) wfmname = wfmtrigger.getfilename() ts.log('Analyzing waveform data in file "%s".' % wfmname) if ts.param_value('wfm.trigchannel').count(',') == 3: wfmtime, ac_voltage, ac_current = wfmtrigger.read_file(wfmname) # calculate the time the EUT rode through the voltage event # ride_through_time == 0 means no trip/ceassation ride_through_time = calc_ride_through_duration(wfmtime, ac_current, ac_voltage=ac_voltage) else: # if there are more than 3 channels being collected, assume the first 4 the following: wfmtime, ac_voltage, ac_current, grid_trig = wfmtrigger.read_file(wfmname) # calculate the time the EUT rode through the voltage event # ride_through_time == 0 means no trip/ceassation ride_through_time = calc_ride_through_duration(wfmtime, ac_current, grid_trig=grid_trig) if ride_through_time == 0: ts.log('The EUT did not trip or momentarily cease to energize.') else: ts.log('The ride-through duration was %0.3f.' % ride_through_time) if ride_through_time - time_msa < c_time: ts.log_warning('The ride-through duration of %0.3f minus the manufacturers stated ' 'accuracy of %0.3f is less ' 'than the ride-through time of %0.3f.' % (ride_through_time, time_msa, c_time)) failures += 1 ts.log_warning('The number of failures is %i.' % failures) elif ride_through_time + time_msa > d_time: ts.log_warning('The ride-through duration of %0.3f plus the manufacturers stated ' 'accuracy of %0.3f is more ' 'than the must disconnect time of %0.3f.' % (ride_through_time, time_msa, c_time)) failures += 1 ts.log_warning('The number of failures is %i.' % failures) # save file to results results_dir = os.path.dirname(__file__)[:-7] + 'Results' + os.path.sep ts.log('Moving waveform "%s" to results folder: %s.' % (wfmname, results_dir)) wfmtrigger.move_file_to_results(wfmname=wfmname, results_dir=results_dir, delete_original='No') else: ts.log('Ride-through test complete. Please analyze the data to assign pass/fail result.') if failures >= failure_count: raise script.ScriptFail() ts.log('Waiting the post-test duration %i.' % posttest_delay) ts.sleep(posttest_delay) result = script.RESULT_PASS except script.ScriptFail, e: reason = str(e) if reason: ts.log_error(reason)
def test_run(): result = script.RESULT_FAIL data = None trigger = None inv = None pv = None disable = None try: # UL 1741 Test Protocol # a. Connect the EUT according to the Requirements in Sec. 11.2.4 and specifications provided by the # manufacturer. Set the EUT to maximum power factor. # b. Set all AC source parameters to the nominal operating conditions for the EUT. # c. Set the input power level to provide Ilow from the EUT. Note: for units that do not adjust output # current as a function of their input such as units with energy storage or multimode products the output # power is to be commanded. # d. Turn on the EUT. Allow the EUT to reach steady state, e.g., maximum power point. # e. Set the EUT ramp rate parameters according to Test 1 in Table SA 11.1. # f. Begin recording the time domain response of the EUT AC voltage and current, and DC voltage and current. # g. Increase the available input power to provide Irated from the EUT according to the step function # described in SA 11. # h. Stop recording the time domain response after the ramp duration plus a manufacturer-specified dwell # time. Ramp duration is defined by 100/RRnorm_up as appropriate for the test settings. # i. Repeat steps c-h two times for a total of 3 repetitions. # j. Repeat steps c-i for Tests 2-3 in Table SA 11.1. # EUT communication parameters ifc_type = ts.param_value('comm.ifc_type') ifc_name = ts.param_value('comm.ifc_name') if ifc_type == client.MAPPED: ifc_name = ts.param_value('comm.map_name') baudrate = ts.param_value('comm.baudrate') parity = ts.param_value('comm.parity') ipaddr = ts.param_value('comm.ipaddr') ipport = ts.param_value('comm.ipport') slave_id = ts.param_value('comm.slave_id') # RR parameters RRnorm_up_min = ts.param_value('rr.RRnorm_up_min') RRnorm_up_max = ts.param_value('rr.RRnorm_up_max') Ilow = ts.param_value('rr.Ilow') Irated = ts.param_value('rr.Irated') MSARR = ts.param_value('rr.MSARR') t_dwell = ts.param_value('rr.t_dwell') # Script timing and pass/fail criteria pretest_delay = ts.param_value('invt.pretest_delay') verification_delay = ts.param_value('invt.verification_delay') posttest_delay = ts.param_value('invt.posttest_delay') power_threshold = ts.param_value('invt.power_threshold') disable = ts.param_value('invt.disable') # initialize data acquisition system daq = das.das_init(ts) data = daq.data_init() trigger = daq.trigger_init() # Step b. Set all AC source parameters to the nominal operating conditions for the EUT. # Initialize pv simulation - This is before step (a) because PV power may be required for communications to EUT pv = pvsim.pvsim_init(ts) pv.power_on() # Communication is established between the Utility Management System Simulator and EUT ts.log('Scanning EUT') try: inv = client.SunSpecClientDevice(ifc_type, slave_id=slave_id, name=ifc_name, baudrate=baudrate, parity=parity, ipaddr=ipaddr, ipport=ipport) except Exception, e: raise script.ScriptFail('Error: %s' % e) # Step a. Connect the EUT according to the Requirements in Sec. 11.2.4 and specifications provided by the # manufacturer. Set the EUT to maximum power factor. # It is assumed that the Grid Simulator (if used) is connected to the EUT and operating properly inverter.set_power_factor(inv, power_factor=1., enable=0) # UL 1741 Step j. Repeat steps c-i for Tests 2-3 in Table SA 11.1. for ramp in [RRnorm_up_min, (RRnorm_up_min + RRnorm_up_max)/2, RRnorm_up_max]: for i in xrange(3): # UL 1741 Step i. Repeat steps c-h two times for a total of 3 repetitions. ts.log('Running test number %d with ramp rate %0.3f %%Irated/sec.' % (i+1, ramp)) # Step c. Set the input power level to provide Ilow from the EUT. Note: for units that do not adjust # output current as a function of their input such as units with energy storage or multimode # products the output power is to be commanded. pv.irradiance_set(irradiance=Ilow*10) # Step d. Turn on the EUT. Allow the EUT to reach steady state, e.g., maximum power point. if pretest_delay > 0: ts.log('Waiting for pre-test delay of %d seconds' % pretest_delay) ts.sleep(pretest_delay) # Verify EUT is in correct state before running the test. if inverter.get_conn_state(inv) is False: ts.log('Inverter not in correct state, setting state to connected.') inverter.set_conn_state(inv, state=1) if verify_conn_state_change(inv, orig_state=0, verification_delay=verification_delay, threshold=power_threshold, data=data) is False: raise script.ScriptFail() # Step e. Set the EUT ramp rate parameters according to Test 1 in Table SA 11.1. try: inv.settings.read() if inv.settings.WGra is not None: inv.settings.WGra = ramp else: ts.log_error('Unable to change ramp rate in the EUT.') except Exception, e: ts.log_error('Error changing ramp rate in the EUT: %s' % str(e)) # Step g. Increase the available input power to provide Irated from the EUT according to the step # function described in SA 11. pv.irradiance_set(irradiance=1000) start_time = time.time() # Step h. Stop recording the time domain response after the ramp duration plus a # manufacturer-specified dwell time. data_update_rate = 1 # Hz check_duration = (Irated-Ilow)/ramp test_duration = t_dwell + check_duration duration = 0 while duration < test_duration+verification_delay: duration = time.time()-start_time ts.log_debug('duration = %0.2f, check duration = %0.2f' % (duration, check_duration)) if duration <= check_duration: # only check the ramp response during the check_duration ramp_in_bounds = verify_ramp(inv, ramp=ramp, t_since_step=duration, Ilow=Ilow, Irated=Irated, MSARR=MSARR, data=data) if ramp_in_bounds is False: ts.log_error('Ramp response was not within limits') # raise script.ScriptFail() else: # The EUT shall reach at least 95% of Irated at the end of the dwell time. ts.log('EUT completed ramping. Waiting for dwell time to check current output. ' 'Remaining time: %0.3f' % (test_duration - duration)) if duration >= test_duration: current_pct = inverter.get_power_norm(inv=inv, das=data)*100 ts.log_error('EUT current is %0.3f%%' % current_pct) if current_pct < 95: ts.log_error('EUT did not reach at least 95% of Irated at the end of the dwell time.') raise script.ScriptFail() break time.sleep(1/data_update_rate) # todo: should improve the loop timing if posttest_delay > 0: ts.log('Waiting for post-test delay of %d seconds' % posttest_delay) ts.sleep(posttest_delay)
def test_run(): result = script.RESULT_FAIL das = None trigger = None inv = None pv = None disable = None try: # UL 1741 Test Protocol # SA 11.3.2 The soft-start test shall be carried out as follows: # a) Connect the EUT according to the instructions and specifications provided by the manufacturer. # b) Set all AC source parameters to the nominal operating conditions for the EUT. # c) Set the input source power level to provide Irated from the EUT. Note: for units that do not # adjust output current as a function of their input such as units with energy storage or multimode products # the output power is to be commanded. # d) Turn on the EUT. Set the EUT ramp rate parameters according to Test 1 in Table SA 11.2. # e) Adjust the AC voltage or frequency outside the near nominal range for a period exceeding setting the # AC voltage to zero for longer than the must-trip duration. # f) Begin recording the time domain response of the EUT AC voltage and current, and DC voltage and current. # g) Adjust the AC source to the rated nominal operating conditions for the EUT. The EUT shall not # commence exporting output current until nominal conditions have been achieved. # h) Stop recording the time domain response after at least the reconnect time of the inverter # (e.g. 30 sec. to 5 minutes), plus ramp duration plus a manufacturer-specified dwell time as shown in SA 11. # Ramp duration is defined by 100/RRss as appropriate. # i) Repeat steps e-h for a total of 3 repetitions. # j) Repeat steps d-i for Tests 2-3 in Table 11.2. # EUT communication parameters ifc_type = ts.param_value('comm.ifc_type') ifc_name = ts.param_value('comm.ifc_name') if ifc_type == client.MAPPED: ifc_name = ts.param_value('comm.map_name') baudrate = ts.param_value('comm.baudrate') parity = ts.param_value('comm.parity') ipaddr = ts.param_value('comm.ipaddr') ipport = ts.param_value('comm.ipport') slave_id = ts.param_value('comm.slave_id') # RR parameters RRss_min = ts.param_value('ss.RRss_min') RRss_max = ts.param_value('ss.RRss_max') #Ilow = ts.param_value('ss.Ilow') Irated = 100. MSARR = ts.param_value('ss.MSARR') t_dwell = ts.param_value('ss.t_dwell') # Script timing and pass/fail criteria pretest_delay = ts.param_value('invt.pretest_delay') verification_delay = ts.param_value('invt.verification_delay') posttest_delay = ts.param_value('invt.posttest_delay') power_threshold = ts.param_value('invt.power_threshold') disable = ts.param_value('invt.disable') # Data acquisition and triggering methods datamethod = ts.param_value('datatrig.dsm_method') trigmethod = ts.param_value('datatrig.trigger_method') # Step f. Begin recording the time domain response of the EUT AC voltage and current, and DC voltage and current. # Step h. Stop recording the time domain response after at least the reconnect time of the inverter # (e.g. 30 sec. to 5 minutes), plus ramp duration plus a manufacturer-specified dwell time as shown in # SA 11. Ramp duration is defined by 100/RRss as appropriate. if datamethod == 'Sandia LabView DSM': import sandia_dsm as dsm das = dsm.Data() computer = ts.param_value('datatrig.das_comp') if computer == '10 node': node = ts.param_value('datatrig.node') # Setup trigger if available if trigmethod == 'Create Local File for Sandia LabView DSM': import sandia_dsm as dsm trigger = dsm.Trigger() trigger.off() # Step b. Set all AC source parameters to the nominal operating conditions for the EUT. # Initialize pv simulation - This is before step (a) because PV power may be required for communications to EUT pv = pvsim.pvsim_init(ts) pv.power_on() grid = gridsim.gridsim_init(ts) # Communication is established between the Utility Management System Simulator and EUT ts.log('Scanning EUT') try: inv = client.SunSpecClientDevice(ifc_type, slave_id=slave_id, name=ifc_name, baudrate=baudrate, parity=parity, ipaddr=ipaddr, ipport=ipport) except Exception, e: raise script.ScriptFail('Error: %s' % e) # Step a. Connect the EUT according to the instructions and specifications provided by the manufacturer. # It is assumed that the Grid Simulator (if used) is connected to the EUT and operating properly inverter.set_power_factor(inv, power_factor=1., enable=0) # Step c. Set the input source power level to provide Irated from the EUT. Note: for units that do not # adjust output current as a function of their input such as units with energy storage or multimode # products the output power is to be commanded. pv.irradiance_set(irradiance=1000) # UL 1741 Step j. Repeat steps d-i for Tests 2-3 in Table 11.2. for ramp in [RRss_min, (RRss_min + RRss_max)/2, RRss_max]: # Step d. Turn on the EUT. Set the EUT ramp rate parameters according to Test 1 in Table SA 11.2. if pretest_delay > 0: ts.log('Waiting for pre-test delay of %d seconds' % pretest_delay) ts.sleep(pretest_delay) # Verify EUT is in correct state before running the test. if inverter.get_conn_state(inv) is False: ts.log('Inverter not in correct state, setting state to connected.') inverter.set_conn_state(inv, state=1) if verify_conn_state_change(inv, orig_state=0, verification_delay=verification_delay, threshold=power_threshold, das=das) is False: raise script.ScriptFail() ''' Revise when SS ramp rate exists in a SunSpec Model try: inv.settings.read() if inv.settings.SSWGra is not None: inv.settings.SSWGra = ramp else: ts.log_error('Unable to change ss ramp rate in the EUT.') except Exception, e: ts.log_error('Error changing ss ramp rate in the EUT: %s' % str(e)) ''' for i in xrange(3): # UL 1741 Step i. Repeat steps e-h two times for a total of 3 repetitions. ts.log('Running test number %d with ramp rate %0.3f %%Irated/sec.' % (i+1, ramp)) # e) Adjust the AC voltage or frequency outside the near nominal range for a period exceeding # setting the AC voltage to zero for longer than the must-trip duration. grid.voltage(0) time.sleep(1) # g) Adjust the AC source to the rated nominal operating conditions for the EUT. The EUT shall not # commence exporting output current until nominal conditions have been achieved. grid.voltage(grid.v_nom()) start_time = time.time() # Determine reconnection time t_reconnection = 0 while inverter.get_conn_state(inv) is False: t_reconnection = time.time()-start_time # Reconnection time updates until the inverter reconnects time.sleep(0.1) data_update_rate = 1 # Hz ... parameterize sometime... check_duration = 100./ramp test_duration = t_dwell + check_duration duration = 0 while duration < test_duration+verification_delay: duration = time.time()-start_time-t_reconnection if duration <= check_duration: # only check the ramp response during the check_duration ramp_in_bounds = verify_ramp(inv, ramp=ramp, t_since_start=duration, Irated=Irated, MSARR=MSARR, das=das) if ramp_in_bounds is False: ts.log_error('Ramp response was not within limits') # raise script.ScriptFail() else: # The EUT shall reach at least 95% of Irated at the end of the dwell time. ts.log('EUT completed ramping. Waiting for dwell time to check current output. ' 'Remaining time: %0.3f' % (test_duration - duration)) if duration >= test_duration: current_pct = inverter.get_power_norm(inv=inv, das=das)*100 ts.log_error('EUT current is %0.3f%%' % current_pct) if current_pct < 95: ts.log_error('EUT did not reach at least 95% of Irated at the end of the dwell time.') raise script.ScriptFail() break time.sleep(1/data_update_rate) # todo: improve the loop timing if posttest_delay > 0: ts.log('Waiting for post-test delay of %d seconds' % posttest_delay) ts.sleep(posttest_delay) result = script.RESULT_PASS