コード例 #1
0
ファイル: VV.py プロジェクト: jayatsandia/svp_1547.1
def volt_var_mode_imbalanced_grid(imbalance_resp, vv_curves, vv_response_time):

    result = script.RESULT_FAIL
    daq = None
    v_nom = None
    p_rated = None
    grid = None
    pv = None
    eut = None
    chil = None
    result_summary = None
    dataset_filename = None

    try:
        #cat = ts.param_value('eut.cat')
        #cat2 = ts.param_value('eut.cat2')
        #sink_power = ts.param_value('eut.sink_power')
        p_rated = ts.param_value('eut.p_rated')
        #p_rated_prime = ts.param_value('eut.p_rated_prime')
        var_rated = ts.param_value('eut.var_rated')
        s_rated = ts.param_value('eut.s_rated')

        #absorb_enable = ts.param_value('eut.abs_enabled')

        # DC voltages
        v_in_nom = ts.param_value('eut.v_in_nom')
        #v_min_in = ts.param_value('eut.v_in_min')
        #v_max_in = ts.param_value('eut.v_in_max')

        # AC voltages
        v_nom = ts.param_value('eut.v_nom')
        v_min = ts.param_value('eut.v_low')
        v_max = ts.param_value('eut.v_high')
        p_min = ts.param_value('eut.p_min')
        p_min_prime = ts.param_value('eut.p_min_prime')
        phases = ts.param_value('eut.phases')
        pf_response_time = ts.param_value('vv.test_1_t_r')

        imbalance_fix = ts.param_value('vv.imbalance_fix')

        """
        A separate module has been create for the 1547.1 Standard
        """
        ActiveFunction = p1547.ActiveFunction(ts=ts,
                                              script_name='Volt-Var',
                                              functions=[VV],
                                              criteria_mode=[True, True, True])
        ActiveFunction.set_imbalance_config(imbalance_angle_fix=imbalance_fix)
        ts.log_debug('1547.1 Library configured for %s' % ActiveFunction.get_script_name())

        # Get the rslt parameters for plot
        result_params = ActiveFunction.get_rslt_param_plot()

        '''
        a) Connect the EUT according to the instructions and specifications provided by the manufacturer.
        '''
        # initialize HIL environment, if necessary
        chil = hil.hil_init(ts)
        if chil is not None:
            chil.config()

        # grid simulator is initialized with test parameters and enabled
        grid = gridsim.gridsim_init(ts, support_interfaces={'hil': chil})  # Turn on AC so the EUT can be initialized
        if grid is not None:
            grid.voltage(v_nom)

        # pv simulator is initialized with test parameters and enabled
        pv = pvsim.pvsim_init(ts, support_interfaces={'hil': chil}) 
        if pv is not None:
            pv.power_set(p_rated)
            pv.power_on()  # Turn on DC so the EUT can be initialized

        # DAS soft channels
        das_points = ActiveFunction.get_sc_points()

        # initialize data acquisition system
        daq = das.das_init(ts, sc_points=das_points['sc'], support_interfaces={'hil': chil}) 
        if daq is not None:
            daq.sc['Q_TARGET'] = 100
            daq.sc['Q_TARGET_MIN'] = 100
            daq.sc['Q_TARGET_MAX'] = 100
            daq.sc['V_TARGET'] = v_nom
            daq.sc['event'] = 'None'
            ts.log('DAS device: %s' % daq.info())

        '''
        b) Set all voltage trip parameters to the widest range of adjustability. Disable all reactive/active power
        control functions.
        '''
        # it is assumed the EUT is on
        eut = der.der_init(ts, support_interfaces={'hil': chil}) 
        if eut is not None:
            eut.config()
            ts.log_debug('If not done already, set L/HVRT and trip parameters to the widest range of adjustability.')

        '''
        c) Set all AC test source parameters to the nominal operating voltage and frequency.
        '''
        if grid is not None:
            grid.voltage(v_nom)

        # open result summary file
        result_summary_filename = 'result_summary.csv'
        result_summary = open(ts.result_file_path(result_summary_filename), 'a+')
        ts.result_file(result_summary_filename)

        result_summary.write(ActiveFunction.get_rslt_sum_col_name())

        '''
         d) Adjust the EUT's available active power to Prated. For an EUT with an input voltage range, set the input
        voltage to Vin_nom.
        '''
        if pv is not None:
            pv.iv_curve_config(pmp=p_rated, vmp=v_in_nom)
            pv.irradiance_set(1000.)

        '''
        h) Once steady state is reached, begin the adjustment of phase voltages.
        '''

        """
        Test start
        """
        ts.log_debug(f'imbalance_resp={imbalance_resp}')
        for imbalance_response in imbalance_resp:

            #Default 2 time responses cycles
            #ActiveFunction.reset_time_settings(tr=pf_response_time)

            for vv_curve in vv_curves:

                '''
                 e) Set EUT volt-watt parameters to the values specified by Characteristic 1. All other function be turned off.
                 '''
                ts.log('Starting test with characteristic curve %s' % (vv_curve))
                ActiveFunction.reset_curve(vv_curve)
                ActiveFunction.reset_time_settings(tr=vv_response_time[vv_curve], number_tr=2)
                v_pairs = ActiveFunction.get_params(function=VV, curve=vv_curve)
                ts.log_debug('v_pairs:%s' % v_pairs)
                #Setting up step label
                ActiveFunction.set_step_label(starting_label='G')


                # it is assumed the EUT is on
                if eut is not None:
                    vv_curve_params = {
                            'v': [(v_pairs['V1'] / v_nom) , (v_pairs['V2'] / v_nom) ,
                                  (v_pairs['V3'] / v_nom), (v_pairs['V4'] / v_nom) ],
                            'var': [(v_pairs['Q1'] / s_rated), (v_pairs['Q2'] / s_rated) ,
                                    (v_pairs['Q3'] / s_rated) , (v_pairs['Q4'] / s_rated)],
                            'vref': 1.0,
                            'RmpPtTms': vv_response_time[vv_curve]}
                    ts.log_debug('Sending VV points: %s' % vv_curve_params)
                    eut.volt_var(params={'Ena': True, 'curve': vv_curve_params})

                '''
                f) Verify volt-var mode is reported as active and that the correct characteristic is reported.
                '''
                if eut is not None:
                    ts.log_debug('Initial EUT VV settings are %s' % eut.volt_var())
                ts.log_debug('curve points:  %s' % v_pairs)
                if chil is not None:                        
                    ts.log('Start simulation of CHIL')  
                    chil.start_simulation()
                '''
                g) Wait for steady state to be reached.
    
                Every time a parameter is stepped or ramped, measure and record the time domain current and voltage
                response for at least 4 times the maximum expected response time after the stimulus, and measure or
                derive, active power, apparent power, reactive power, and power factor.
                '''

                step = ActiveFunction.get_step_label()

                daq.sc['event'] = step
                daq.data_sample()
                ts.log('Wait for steady state to be reached')
                ts.sleep(2 * vv_response_time[vv_curve])
                ts.log(imbalance_resp)

                ts.log('Starting imbalance test with VV mode at %s' % (imbalance_response))

                ActiveFunction.set_imbalance_config(imbalance_angle_fix=imbalance_fix)
                #ts.log_debug(f'{imbalance_response}')
                dataset_filename = f'VV_IMB_{imbalance_fix}_{imbalance_response}'

                ActiveFunction.reset_filename(filename=dataset_filename)
                ts.log('------------{}------------'.format(dataset_filename))
                # Start the data acquisition systems
                daq.data_capture(True)

                '''
                h) For multiphase units, step the AC test source voltage to Case A from Table 24.
                '''
                if grid is not None:
                    step_label = ActiveFunction.get_step_label()
                    ts.log('Voltage step: setting Grid simulator to case A (IEEE 1547.1-Table 24)(%s)' % step)
                    ActiveFunction.start(daq=daq, step_label=step_label)
                    v_target = ActiveFunction.set_grid_asymmetric(grid=grid, case='case_a', imbalance_resp=imbalance_response)
                    ts.log_debug(f'v_target={v_target}')
                    step_dict = {'V': v_target}
                    ActiveFunction.record_timeresponse(daq=daq)
                    ActiveFunction.evaluate_criterias(daq=daq, step_dict=step_dict)
                    result_summary.write(ActiveFunction.write_rslt_sum())

                '''
                i) For multiphase units, step the AC test source voltage to VN.
                '''
                if grid is not None:
                    step_label = ActiveFunction.get_step_label()
                    v_target = v_nom
                    ActiveFunction.start(daq=daq, step_label=step_label)
                    ts.log('Voltage step: setting Grid simulator voltage to %s (%s)' % (v_nom, step))
                    grid.voltage(v_target)
                    step_dict = {'V': v_target}
                    ActiveFunction.record_timeresponse(daq=daq)
                    ActiveFunction.evaluate_criterias(daq=daq, step_dict=step_dict)
                    result_summary.write(ActiveFunction.write_rslt_sum())

                """
                j) For multiphase units, step the AC test source voltage to Case B from Table 24.
                """
                if grid is not None:
                    step_label = ActiveFunction.get_step_label()
                    ActiveFunction.start(daq=daq, step_label=step_label)
                    ts.log('Voltage step: setting Grid simulator to case B (IEEE 1547.1-Table 24)(%s)' % step)
                    v_target = ActiveFunction.set_grid_asymmetric(grid=grid, case='case_b', imbalance_resp=imbalance_response)
                    step_dict = {'V': v_target}
                    ActiveFunction.record_timeresponse(daq=daq)
                    ActiveFunction.evaluate_criterias(daq=daq, step_dict=step_dict)
                    result_summary.write(ActiveFunction.write_rslt_sum())

                """
                k) For multiphase units, step the AC test source voltage to VN
                """
                if grid is not None:
                    step_label = ActiveFunction.get_step_label()
                    v_target = v_nom
                    ActiveFunction.start(daq=daq, step_label=step_label)
                    ts.log('Voltage step: setting Grid simulator voltage to %s (%s)' % (v_nom, step))
                    grid.voltage(v_nom)
                    step_dict = {'V': v_target}
                    ActiveFunction.record_timeresponse(daq=daq)
                    ActiveFunction.evaluate_criterias(daq=daq, step_dict=step_dict)
                    result_summary.write(ActiveFunction.write_rslt_sum())

                ts.log('Sampling complete')
                dataset_filename = dataset_filename + ".csv"
                daq.data_capture(False)
                ds = daq.data_capture_dataset()
                ts.log('Saving file: %s' % dataset_filename)
                ds.to_csv(ts.result_file_path(dataset_filename))
                result_params['plot.title'] = dataset_filename.split('.csv')[0]
                ts.result_file(dataset_filename, params=result_params)
                result = script.RESULT_COMPLETE

    except script.ScriptFail as e:
        reason = str(e)
        if reason:
            ts.log_error(reason)


    except Exception as e:

        if dataset_filename is not None:
            dataset_filename = dataset_filename + ".csv"
            daq.data_capture(False)
            ds = daq.data_capture_dataset()
            ts.log('Saving file: %s' % dataset_filename)
            ds.to_csv(ts.result_file_path(dataset_filename))
            result_params['plot.title'] = dataset_filename.split('.csv')[0]
            ts.result_file(dataset_filename, params=result_params)

        raise

    finally:
        if daq is not None:
            daq.close()
        if pv is not None:
            if p_rated is not None:
                pv.power_set(p_rated)
            pv.close()
        if grid is not None:
            if v_nom is not None:
                grid.voltage(v_nom)
            grid.close()
        if chil is not None:
            chil.close()
        if eut is not None:
            #eut.volt_var(params={'Ena': False})
            #eut.volt_watt(params={'Ena': False})
            eut.close()
        if result_summary is not None:
            result_summary.close()

    return result
コード例 #2
0
ファイル: VV.py プロジェクト: jayatsandia/svp_1547.1
def volt_vars_mode(vv_curves, vv_response_time, pwr_lvls, v_ref_value):

    result = script.RESULT_FAIL
    daq = None
    v_nom = None
    grid = None
    pv = None
    eut = None
    chil = None
    result_summary = None
    dataset_filename = None

    try:
        cat = ts.param_value('eut.cat')
        cat2 = ts.param_value('eut.cat2')
        sink_power = ts.param_value('eut.sink_power')
        p_rated = ts.param_value('eut.p_rated')
        p_rated_prime = ts.param_value('eut.p_rated_prime')
        var_rated = ts.param_value('eut.var_rated')
        s_rated = ts.param_value('eut.s_rated')

        #absorb_enable = ts.param_value('eut.abs_enabled')
        # DC voltages
        v_in_nom = ts.param_value('eut.v_in_nom')
        #v_min_in = ts.param_value('eut.v_in_min')
        #v_max_in = ts.param_value('eut.v_in_max')

        # AC voltages
        v_nom = ts.param_value('eut.v_nom')
        v_low = ts.param_value('eut.v_low')
        v_high = ts.param_value('eut.v_high')
        p_min = ts.param_value('eut.p_min')
        p_min_prime = ts.param_value('eut.p_min_prime')
        phases = ts.param_value('eut.phases')

        """
        Version validation
        """
        p1547.VersionValidation(script_version=ts.info.version)

        """
        A separate module has been create for the 1547.1 Standard
        """
        ActiveFunction = p1547.ActiveFunction(ts=ts,
                                              functions=[VV],
                                              script_name='Volt-Var',
                                              criteria_mode=[True, True, True])
        ts.log_debug("1547.1 Library configured for %s" % ActiveFunction.get_script_name())

        # result params
        result_params = ActiveFunction.get_rslt_param_plot()
        ts.log_debug(result_params)

        '''
        a) Connect the EUT according to the instructions and specifications provided by the manufacturer.
        '''
        ts.log_debug(15*"*"+"HIL initialization"+15*"*")

        # initialize HIL environment, if necessary
        chil = hil.hil_init(ts)
        if chil is not None:
            chil.config()
        ts.log_debug(15*"*"+"PVSIM initialization"+15*"*")
        # pv simulator is initialized with test parameters and enabled
        pv = pvsim.pvsim_init(ts, support_interfaces={'hil': chil}) 
        if pv is not None:
            pv.power_set(p_rated)
            pv.power_on()  # Turn on DC so the EUT can be initialized
            #daq.set_dc_measurement(pv)  # send pv obj to daq to get dc measurements
            ts.sleep(0.5)

        # DAS soft channels
        ts.log_debug(15*"*"+"DAS initialization"+15*"*")

        #das_points = {'sc': ('Q_TARGET', 'Q_TARGET_MIN', 'Q_TARGET_MAX', 'Q_MEAS', 'V_TARGET', 'V_MEAS', 'event')}
        das_points = ActiveFunction.get_sc_points()
        # initialize data acquisition system
        daq = das.das_init(ts, sc_points=das_points['sc'], support_interfaces={'hil': chil}) 

        daq.sc['V_TARGET'] = v_nom
        daq.sc['Q_TARGET'] = 100
        daq.sc['Q_TARGET_MIN'] = 100
        daq.sc['Q_TARGET_MAX'] = 100
        daq.sc['event'] = 'None'

        ts.log('DAS device: %s' % daq.info())

        '''
        b) Set all voltage trip parameters to the widest range of adjustability.  Disable all reactive/active power
        control functions.
        '''
        ts.log_debug(15*"*"+"EUT initialization"+15*"*")

        eut = der.der_init(ts, support_interfaces={'hil': chil}) 
        if eut is not None:
            eut.config()
            ts.log_debug(eut.measurements())

            #Deactivating all functions on EUT
            #eut.deactivate_all_fct()

            ts.log_debug('Voltage trip parameters set to the widest range: v_min: {0} V, '
                         'v_max: {1} V'.format(v_low, v_high))
            try:
                eut.vrt_stay_connected_high(params={'Ena': True, 'ActCrv': 0, 'Tms1': 3000,
                                                    'V1': v_high, 'Tms2': 0.16, 'V2': v_high})
            except Exception as e:
                ts.log_error('Could not set VRT Stay Connected High curve. %s' % e)
            try:
                eut.vrt_stay_connected_low(params={'Ena': True, 'ActCrv': 0, 'Tms1': 3000,
                                                   'V1': v_low, 'Tms2': 0.16, 'V2': v_low})
            except Exception as e:
                ts.log_error('Could not set VRT Stay Connected Low curve. %s' % e)
        else:
            ts.log_debug('Set L/HVRT and trip parameters set to the widest range of adjustability possible.')

        # # Special considerations for CHIL ASGC/Typhoon startup
        if chil is not None:
            if eut is not None:
                if eut.measurements() is not None:
                    inv_power = eut.measurements().get('W')
                    timeout = 120.
                    if inv_power <= p_rated * 0.85:
                        pv.irradiance_set(995)  # Perturb the pv slightly to start the inverter
                        ts.sleep(3)
                        eut.connect(params={'Conn': True})
                    while inv_power <= p_rated * 0.85 and timeout >= 0:
                        ts.log('Inverter power is at %0.1f. Waiting up to %s more seconds or until EUT starts...' %
                            (inv_power, timeout))
                        ts.sleep(1)
                        timeout -= 1
                        inv_power = eut.measurements().get('W')
                        if timeout == 0:
                            result = script.RESULT_FAIL
                            raise der.DERError('Inverter did not start.')
                    ts.log('Waiting for EUT to ramp up')
                    ts.sleep(8)
                    ts.log_debug('DAS data_read(): %s' % daq.data_read())

        '''
        c) Set all AC test source parameters to the nominal operating voltage and frequency.
        '''
        ts.log_debug(15*"*"+"GRIDSIM initialization"+15*"*")

        grid = gridsim.gridsim_init(ts,support_interfaces={'hil': chil})  # Turn on AC so the EUT can be initialized
        if grid is not None:
            grid.voltage(v_nom)
            if chil is not None:  # If using HIL, give the grid simulator the hil object
                grid.config()

        # open result summary file
        result_summary_filename = 'result_summary.csv'
        result_summary = open(ts.result_file_path(result_summary_filename), 'a+')
        ts.result_file(result_summary_filename)
        result_summary.write(ActiveFunction.get_rslt_sum_col_name())

        '''
        d) Adjust the EUT's available active power to Prated. For an EUT with an input voltage range, set the input
        voltage to Vin_nom. The EUT may limit active power throughout the test to meet reactive power requirements.
        For an EUT with an input voltage range.
        '''

        if pv is not None:
            pv.iv_curve_config(pmp=p_rated, vmp=v_in_nom)
            pv.irradiance_set(1000.)

        '''
        gg) Repeat steps g) through dd) for characteristics 2 and 3.
        '''
        for vv_curve in vv_curves:
            ts.log('Starting test with characteristic curve %s' % (vv_curve))
            ActiveFunction.reset_curve(vv_curve)
            ActiveFunction.reset_time_settings(tr=vv_response_time[vv_curve], number_tr=2)
            v_pairs = ActiveFunction.get_params(function=VV, curve=vv_curve)
            #ts.log_debug('v_pairs:%s' % v_pairs)

            '''
            ff) Repeat test steps d) through ee) at EUT power set at 20% and 66% of rated power.
            '''
            for power in pwr_lvls:
                ActiveFunction.reset_pwr(power)

                if pv is not None:
                    pv_power_setting = (p_rated * power)
                    pv.iv_curve_config(pmp=pv_power_setting, vmp=v_in_nom)
                    pv.irradiance_set(1000.)

                # Special considerations for CHIL ASGC/Typhoon startup #
                # Why does it need to appear twice, shouldn't this be at the driver level
                if chil is not None:
                    if eut is not None:
                        if  eut.measurements() is not None:
                            inv_power = eut.measurements().get('W')
                            timeout = 120.
                            if inv_power <= pv_power_setting * 0.85:
                                pv.irradiance_set(995)  # Perturb the pv slightly to start the inverter
                                ts.sleep(3)
                                eut.connect(params={'Conn': True})
                            while inv_power <= pv_power_setting * 0.85 and timeout >= 0:
                                ts.log('Inverter power is at %0.1f. Waiting up to %s more seconds or until EUT starts...' %
                                    (inv_power, timeout))
                                ts.sleep(1)
                                timeout -= 1
                                inv_power = eut.measurements().get('W')
                                if timeout == 0:
                                    result = script.RESULT_FAIL
                                    raise der.DERError('Inverter did not start.')
                            ts.log('Waiting for EUT to ramp up')
                            ts.sleep(8)
                    



                '''
                ee) Repeat test steps e) through dd) with Vref set to 1.05*VN and 0.95*VN, respectively.
                '''
                for v_ref in v_ref_value:
                    ts.log('Setting v_ref at %s %% of v_nom' % (int(v_ref * 100)))

                    #Setting grid to vnom before test
                    if grid is not None:
                        grid.voltage(v_nom)

                    if eut is not None:
                        '''
                        e) Set EUT volt-var parameters to the values specified by Characteristic 1.
                        All other function should be turned off. Turn off the autonomously adjusting reference voltage.
                        '''
                        # Activate volt-var function with following parameters
                        # SunSpec convention is to use percentages for V and Q points.
                        vv_curve_params = {
                            'v': [(v_pairs['V1'] / v_nom) , (v_pairs['V2'] / v_nom) ,
                                  (v_pairs['V3'] / v_nom), (v_pairs['V4'] / v_nom) ],
                            'var': [(v_pairs['Q1'] / s_rated), (v_pairs['Q2'] / s_rated) ,
                                    (v_pairs['Q3'] / s_rated) , (v_pairs['Q4'] / s_rated)],
                            'vref': v_ref,
                            'RmpPtTms': vv_response_time[vv_curve]
                        }
                        ts.log_debug('Sending VV points: %s' % vv_curve_params)
                        eut.volt_var(params={'Ena': True, 'ACTCRV': vv_curve, 'curve': vv_curve_params})
                        # TODO autonomous vref adjustment to be included
                        # eut.autonomous_vref_adjustment(params={'Ena': False})
                        '''
                        f) Verify volt-var mode is reported as active and that the correct characteristic is reported.
                        '''
                        ts.log_debug('Initial EUT VV settings are %s' % eut.volt_var())
                    if chil is not None:                        
                        ts.log('Start simulation of CHIL')  
                        chil.start_simulation()
                    v_steps_dict = ActiveFunction.create_vv_dict_steps(v_ref=v_ref)

                    dataset_filename = 'VV_%s_PWR_%d_vref_%d' % (vv_curve, power * 100, v_ref*100)
                    ActiveFunction.reset_filename(filename=dataset_filename)
                    #ts.log('------------{}------------'.format(dataset_filename))
                    # Start the data acquisition systems
                    daq.data_capture(True)

                    for step_label, v_step in v_steps_dict.items():

                        ts.log('Voltage step: setting Grid simulator voltage to %s (%s)' % (v_step, step_label))

                        ActiveFunction.start(daq=daq, step_label=step_label)
                        step_dict = {'V': v_step}

                        if grid is not None:
                            grid.voltage(step_dict['V'])

                        ActiveFunction.record_timeresponse(daq=daq)
                        ActiveFunction.evaluate_criterias(daq=daq, step_dict=step_dict)
                        result_summary.write(ActiveFunction.write_rslt_sum())

                    ts.log('Sampling complete')
                    dataset_filename = dataset_filename + ".csv"
                    daq.data_capture(False)
                    ds = daq.data_capture_dataset()
                    ts.log('Saving file: %s' % dataset_filename)
                    ds.to_csv(ts.result_file_path(dataset_filename))
                    result_params['plot.title'] = dataset_filename.split('.csv')[0]
                    ts.result_file(dataset_filename, params=result_params)
                    result = script.RESULT_COMPLETE



    except script.ScriptFail as e:
        reason = str(e)
        if reason:
            ts.log_error(reason)

    except Exception as e:
        if dataset_filename is not None:
            dataset_filename = dataset_filename + ".csv"
            daq.data_capture(False)
            ds = daq.data_capture_dataset()
            ts.log('Saving file: %s' % dataset_filename)
            ds.to_csv(ts.result_file_path(dataset_filename))
            result_params['plot.title'] = dataset_filename.split('.csv')[0]
            ts.result_file(dataset_filename, params=result_params)
        ts.log_error('Test script exception: %s' % traceback.format_exc())

    finally:
        if daq is not None:
            daq.close()
        if pv is not None:
            pv.close()
        if grid is not None:
            if v_nom is not None:
                grid.voltage(v_nom)
            grid.close()
        if chil is not None:
            chil.close()
        if eut is not None:
            #eut.volt_var(params={'Ena': False})
            eut.close()
        if result_summary is not None:
            result_summary.close()


    return result
コード例 #3
0
def test_run():
    result = script.RESULT_FAIL
    grid = None
    pv = p_rated = None
    daq = None
    eut = None
    rs = None
    phil = None
    result_summary = None
    step = None
    q_initial = None
    dataset_filename = None

    try:
        sink_power = ts.param_value('eut.sink_power')
        p_rated = ts.param_value('eut.p_rated')
        p_rated_prime = ts.param_value('eut.p_rated_prime')
        s_rated = ts.param_value('eut.s_rated')
        var_rated = ts.param_value('eut.var_rated')

        # DC voltages
        v_nom_in_enabled = ts.param_value('cpf.v_in_nom')
        v_min_in_enabled = ts.param_value('cpf.v_in_min')
        v_max_in_enabled = ts.param_value('cpf.v_in_max')

        v_nom_in = ts.param_value('eut.v_in_nom')
        v_min_in = ts.param_value('eut_cpf.v_in_min')
        v_max_in = ts.param_value('eut_cpf.v_in_max')

        # AC voltages
        v_nom = ts.param_value('eut.v_nom')
        v_min = ts.param_value('eut.v_low')
        v_max = ts.param_value('eut.v_high')
        f_nom = ts.param_value('eut.f_nom')
        p_min = ts.param_value('eut.p_min')
        p_min_prime = ts.param_value('eut.p_min_prime')
        phases = ts.param_value('eut.phases')

        # Pass/fail accuracies
        pf_msa = ts.param_value('eut.pf_msa')

        # EUI Absorb capabilities
        absorb = {}
        absorb['ena'] = ts.param_value('eut_cpf.sink_power')
        absorb['p_rated_prime'] = ts.param_value('eut_cpf.p_rated_prime')
        absorb['p_min_prime'] = ts.param_value('eut_cpf.p_min_prime')

        # initialize HIL environment, if necessary
        ts.log_debug(15 * "*" + "HIL initialization" + 15 * "*")

        phil = hil.hil_init(ts)
        if phil is not None:
            # return self.ts.param_value(self.group_name + '.' + GROUP_NAME + '.' + name)
            open_proj = phil._param_value('hil_config_open')
            compilation = phil._param_value('hil_config_compile')
            stop_sim = phil._param_value('hil_config_stop_sim')
            load = phil._param_value('hil_config_load')
            execute = phil._param_value('hil_config_execute')
            model_name = phil._param_value('hil_config_model_name')
            phil.config()
        ''' RTLab OpWriteFile Math using worst case scenario of 160 seconds, 14 signals and Ts = 40e-6
        Duration of acquisition in number of points: Npoints = (Tend-Tstart)/(Ts*dec) = (350)/(0.000040*25) = 1350e3
        
        Acquisition frame duration: Tframe = Nbss * Ts * dec = 1000*0.000040*250 = 10 sec
        
        Number of buffers to be acquired: Nbuffers = Npoints / Nbss = (Tend - Tstart) / Tframe = 16
        
        Minimum file size: MinSize= Nbuffers x SizeBuf = [(Tend - Tstart) / Ts ] * (Nsig+1) * 8 * Nbss 
            = (160/40e-6)*(14+1)*8*1000 = 4.8e11
        
        SizeBuf = 1/Nbuffers * {[(Tend - Tstart) / Ts ]*(Nsig+1)*8*Nbss} = [(160/0.000040)*(14+1)*8*1e3]/16 = 30e9
        Size of one buffer in bytes (SizeBuf) = (Nsig+1) * 8 * Nbss (Minimum) = (14+1)*8*1000 = 120e3
        '''
        """
        Configure settings in 1547.1 Standard module for the Frequency Ride Through Tests
        """
        pwr = float(ts.param_value('frt.high_pwr_value'))
        repetitions = ts.param_value('frt.repetitions')
        if ts.param_value('frt.wav_ena') == "Yes":
            wav_ena = True
        else:
            wav_ena = False
        if ts.param_value('frt.data_ena') == "Yes":
            data_ena = True
        else:
            data_ena = False

        FreqRideThrough = p1547.FrequencyRideThrough(
            ts=ts, support_interfaces={"hil": phil})
        # result params
        # result_params = lib_1547.get_rslt_param_plot()
        # ts.log(result_params

        # grid simulator is initialized with test parameters and enabled
        ts.log_debug(15 * "*" + "Gridsim initialization" + 15 * "*")
        grid = gridsim.gridsim_init(ts, support_interfaces={
            "hil": phil
        })  # Turn on AC so the EUT can be initialized
        if grid is not None:
            grid.voltage(v_nom)
        # Set the grid simulator rocof to 3Hz/s
        grid.rocof(FreqRideThrough.get_rocof_dic())
        # pv simulator is initialized with test parameters and enabled
        ts.log_debug(15 * "*" + "PVsim initialization" + 15 * "*")
        pv = pvsim.pvsim_init(ts)
        if pv is not None:
            pv.power_set(p_rated)
            pv.power_on()  # Turn on DC so the EUT can be initialized

        # initialize data acquisition
        ts.log_debug(15 * "*" + "DAS initialization" + 15 * "*")
        daq = das.das_init(ts, support_interfaces={"hil": phil, "pvsim": pv})
        daq.waveform_config({
            "mat_file_name":
            "WAV.mat",
            "wfm_channels":
            FreqRideThrough.get_wfm_file_header()
        })

        if daq is not None:
            daq.sc['F_MEAS'] = 100

        # open result summary file
        result_summary_filename = 'result_summary.csv'
        result_summary = open(ts.result_file_path(result_summary_filename),
                              'a+')
        ts.result_file(result_summary_filename)
        result_summary.write('Test Name, Waveform File, RMS File\n')
        """
        Set the frequency droop function and droop values to make the active power change with respect to
        frequency as small as possible.
        """
        # Wait to establish communications with the EUT after AC and DC power are provided
        eut = der.der_init(ts, support_interfaces={"hil": phil})
        if eut is not None:
            eut.config()

        # Default curve is characteristic curve 1
        fw_curve = 1
        ActiveFunction = p1547.ActiveFunction(ts=ts,
                                              script_name='Freq-Watt',
                                              functions=[FW],
                                              criteria_mode=[True, True, True])
        fw_param = ActiveFunction.get_params(function=FW, curve=fw_curve)
        ts.log_debug('fw_param:%s' % fw_param)

        if eut is not None:
            params = {
                'Ena': True,
                'curve': fw_curve,
                'dbf': fw_param['dbf'],
                'kof': fw_param['kof'],
                'RspTms': fw_param['tr']
            }
            settings = eut.freq_watt(params)
            ts.log_debug('Initial EUT FW settings are %s' % settings)
        """
        Set or verify that all frequency trip settings are set to not influence the outcome of the test.
        """
        # ts.log_debug('HFRT and trip parameters from EUT : {}'.format(eut.frt_stay_connected_high()))
        # ts.log_debug('LFRT and trip parameters from EUT : {}'.format(eut.frt_stay_connected_low()))
        """
        Operate the ac test source at nominal frequency ± 0.1 Hz.
        """
        # Configured in PHIL on startup

        # Initial loop for all mode that will be executed
        modes = FreqRideThrough.get_modes()  # Options: LFRT, HFRT
        ts.log(f"FRT modes tested : '{modes}'")
        for current_mode in modes:
            for repetition in range(1, repetitions + 1):
                dataset_filename = f'{current_mode}_{round(pwr*100)}PCT_{repetition}'
                ts.log_debug(15 * "*" + f"Starting {dataset_filename}" +
                             15 * "*")
                if data_ena:
                    daq.data_capture(True)
                """
                Setting up available power to appropriate power level 
                """
                if pv is not None:
                    ts.log_debug(f'Setting power level to {pwr}')
                    pv.iv_curve_config(pmp=p_rated, vmp=v_nom_in)
                    pv.irradiance_set(1000.)
                    pv.power_set(p_rated * pwr)
                """
                Initiating voltage sequence for FRT
                """
                frt_test_sequences = FreqRideThrough.set_test_conditions(
                    current_mode)
                ts.log_debug(frt_test_sequences)
                frt_stop_time = FreqRideThrough.get_frt_stop_time(
                    frt_test_sequences)
                if phil is not None:
                    # This adds 5 seconds of nominal behavior for EUT normal shutdown. This 5 sec is not recorded.
                    frt_stop_time = frt_stop_time + 5
                    ts.log('Stop time set to %s' %
                           phil.set_stop_time(frt_stop_time))

                    # The driver should take care of this by selecting "Yes" to "Load the model to target?"
                    phil.load_model_on_hil()
                    # You need to first load the model, then configure the parameters
                    # Now that we have all the test_sequences its time to sent them to the model.
                    FreqRideThrough.set_frt_model_parameters(
                        frt_test_sequences)

                    # The driver parameter "Execute the model on target?" should be set to "No"
                    phil.start_simulation()
                    ts.sleep(0.5)
                    sim_time = phil.get_time()
                    while (frt_stop_time - sim_time
                           ) > 1.0:  # final sleep will get to stop_time.
                        sim_time = phil.get_time()
                        ts.log(
                            'Sim Time: %0.3f.  Waiting another %0.3f sec before saving data.'
                            % (sim_time, frt_stop_time - sim_time))
                        ts.sleep(5)

                    rms_dataset_filename = "No File"
                    wave_start_filename = "No File"
                    if data_ena:
                        rms_dataset_filename = dataset_filename + "_RMS.csv"
                        daq.data_capture(False)

                        # complete data capture
                        ts.log(
                            'Waiting for Opal to save the waveform data: {}'.
                            format(dataset_filename))
                        ts.sleep(10)
                    if wav_ena:
                        # Convert and save the .mat file
                        ts.log('Processing waveform dataset(s)')
                        wave_start_filename = dataset_filename + "_WAV.csv"

                        ds = daq.waveform_capture_dataset(
                        )  # returns list of databases of waveforms (overloaded)
                        ts.log(f'Number of waveforms to save {len(ds)}')
                        if len(ds) > 0:
                            ds[0].to_csv(
                                ts.result_file_path(wave_start_filename))
                            ts.result_file(wave_start_filename)

                    if data_ena:
                        ds = daq.data_capture_dataset()
                        ts.log('Saving file: %s' % rms_dataset_filename)
                        ds.to_csv(ts.result_file_path(rms_dataset_filename))
                        ds.remove_none_row(
                            ts.result_file_path(rms_dataset_filename), "TIME")
                        result_params = {
                            'plot.title':
                            rms_dataset_filename.split('.csv')[0],
                            'plot.x.title': 'Time (sec)',
                            'plot.x.points': 'TIME',
                            'plot.y.points': 'AC_VRMS_1, AC_VRMS_2, AC_VRMS_3',
                            'plot.y.title': 'Voltage (V)',
                            'plot.y2.points':
                            'AC_IRMS_1, AC_IRMS_2, AC_IRMS_3',
                            'plot.y2.title': 'Current (A)',
                        }
                        ts.result_file(rms_dataset_filename,
                                       params=result_params)
                    result_summary.write(
                        '%s, %s, %s,\n' %
                        (dataset_filename, wave_start_filename,
                         rms_dataset_filename))

                    phil.stop_simulation()

        result = script.RESULT_COMPLETE

    except script.ScriptFail as e:
        reason = str(e)
        if reason:
            ts.log_error(reason)

    except Exception as e:
        ts.log_error((e, traceback.format_exc()))

        ts.log_error('Test script exception: %s' % traceback.format_exc())

    finally:
        if grid is not None:
            grid.close()
        if pv is not None:
            if p_rated is not None:
                pv.power_set(p_rated)
            pv.close()
        if daq is not None:
            daq.close()
        if eut is not None:
            # eut.fixed_pf(params={'Ena': False, 'PF': 1.0})
            eut.close()
        if rs is not None:
            rs.close()
        if phil is not None:
            if phil.model_state() == 'Model Running':
                phil.stop_simulation()
            phil.close()

        if result_summary is not None:
            result_summary.close()

        # create result workbook
        excelfile = ts.config_name() + '.xlsx'
        rslt.result_workbook(excelfile, ts.results_dir(), ts.result_dir())
        ts.result_file(excelfile)

    return result
コード例 #4
0
ファイル: VRT.py プロジェクト: jayatsandia/svp_1547.1
def test_run():
    result = script.RESULT_FAIL
    grid = None
    pv = p_rated = None
    daq = None
    eut = None
    rs = None
    phil = None
    result_summary = None
    step = None
    q_initial = None
    dataset_filename = None

    try:
        sink_power = ts.param_value('eut.sink_power')
        p_rated = ts.param_value('eut.p_rated')
        p_rated_prime = ts.param_value('eut.p_rated_prime')
        s_rated = ts.param_value('eut.s_rated')
        var_rated = ts.param_value('eut.var_rated')

        # DC voltages
        v_nom_in_enabled = ts.param_value('cpf.v_in_nom')
        v_min_in_enabled = ts.param_value('cpf.v_in_min')
        v_max_in_enabled = ts.param_value('cpf.v_in_max')

        v_nom_in = ts.param_value('eut.v_in_nom')
        v_min_in = ts.param_value('eut_cpf.v_in_min')
        v_max_in = ts.param_value('eut_cpf.v_in_max')

        # AC voltages
        v_nom = ts.param_value('eut.v_nom')
        v_min = ts.param_value('eut.v_low')
        v_max = ts.param_value('eut.v_high')
        f_nom = ts.param_value('eut.f_nom')
        p_min = ts.param_value('eut.p_min')
        p_min_prime = ts.param_value('eut.p_min_prime')
        phases = ts.param_value('eut.phases')

        low_pwr_ena = ts.param_value('vrt.low_pwr_ena')
        high_pwr_ena = ts.param_value('vrt.high_pwr_ena')
        low_pwr_value = ts.param_value('vrt.low_pwr_value')
        high_pwr_value = ts.param_value('vrt.high_pwr_value')

        # Pass/fail accuracies
        pf_msa = ts.param_value('eut.pf_msa')

        # EUI Absorb capabilities
        absorb = {}
        absorb['ena'] = ts.param_value('eut_cpf.sink_power')
        absorb['p_rated_prime'] = ts.param_value('eut_cpf.p_rated_prime')
        absorb['p_min_prime'] = ts.param_value('eut_cpf.p_min_prime')

        # Following parameters are collected in p1547.VoltageRideThrough.set_vrt_params in init:
        # vrt.lv_ena, vrt.hv_ena, vrt.consecutive_ena, vrt.cat, vrt.range_steps
        consecutive_ena = ts.param_value('vrt.consecutive_ena')
        if consecutive_ena == "Enabled":
            consecutive_label = "CE"
        else:
            consecutive_label = "CD"

        phase_comb_list = []

        if ts.param_value('vrt.one_phase_mode') == "Enabled":
            phase_comb_list.append([ts.param_value('vrt.one_phase_value')])
        
        if ts.param_value('vrt.two_phase_mode') == "Enabled":
            phase_comb_list.append([ts.param_value('vrt.two_phase_value_1'),ts.param_value('vrt.two_phase_value_2')])

        if ts.param_value('vrt.three_phase_mode') == "Enabled":
            phase_comb_list.append(['A', 'B', 'C'])

        # Functions to be enabled for test
        mode = []
        pwr_lvl = []
        steps_dict = {}
        timestep_dict = {}
        sequence_dict = {}
        parameters = []

        # initialize HIL environment, if necessary
        ts.log_debug(15 * "*" + "HIL initialization" + 15 * "*")

        phil = hil.hil_init(ts)
        if phil is not None:
            # return self.ts.param_value(self.group_name + '.' + GROUP_NAME + '.' + name)
            open_proj = phil._param_value('hil_config_open')
            compilation = phil._param_value('hil_config_compile')
            stop_sim = phil._param_value('hil_config_stop_sim')
            load = phil._param_value('hil_config_load')
            execute = phil._param_value('hil_config_execute')
            model_name = phil._param_value('hil_config_model_name')
            phil.config()

        ''' RTLab OpWriteFile Math using worst case scenario of 160 seconds, 14 signals and Ts = 40e-6
        Duration of acquisition in number of points: Npoints = (Tend-Tstart)/(Ts*dec) = (350)/(0.000040*25) = 1350e3
        
        Acquisition frame duration: Tframe = Nbss * Ts * dec = 1000*0.000040*250 = 10 sec
        
        Number of buffers to be acquired: Nbuffers = Npoints / Nbss = (Tend - Tstart) / Tframe = 16
        
        Minimum file size: MinSize= Nbuffers x SizeBuf = [(Tend - Tstart) / Ts ] * (Nsig+1) * 8 * Nbss 
            = (160/40e-6)*(14+1)*8*1000 = 4.8e11
        
        SizeBuf = 1/Nbuffers * {[(Tend - Tstart) / Ts ]*(Nsig+1)*8*Nbss} = [(160/0.000040)*(14+1)*8*1e3]/16 = 30e9
        Size of one buffer in bytes (SizeBuf) = (Nsig+1) * 8 * Nbss (Minimum) = (14+1)*8*1000 = 120e3
        '''

        if low_pwr_ena == 'Enabled':
            pwr_lvl.append(low_pwr_value)
        else:
            ts.log_debug('No low power chosen')
        if high_pwr_ena == 'Enabled':
            pwr_lvl.append(high_pwr_value)
        else:
            ts.log_debug('No high power chosen')
        if high_pwr_ena == 'Disabled' and low_pwr_ena == 'Disabled':
            ts.log_error('No power tests included in VRT test!')

        if ts.param_value('vrt.wav_ena') == "Yes" :
            wav_ena = True
        else :
            wav_ena = False
        if ts.param_value('vrt.data_ena') == "Yes" :
            data_ena = True
        else :
            data_ena = False
        """
        Configure settings in 1547.1 Standard module for the Voltage Ride Through Tests
        """
        VoltRideThrough = p1547.VoltageRideThrough(ts=ts, support_interfaces={"hil": phil})
        # result params
        # result_params = lib_1547.get_rslt_param_plot()
        # ts.log(result_params

        # grid simulator is initialized with test parameters and enabled
        ts.log_debug(15 * "*" + "Gridsim initialization" + 15 * "*")
        grid = gridsim.gridsim_init(ts, support_interfaces={"hil": phil})  # Turn on AC so the EUT can be initialized
        if grid is not None:
            grid.voltage(v_nom)  

        # pv simulator is initialized with test parameters and enabled
        ts.log_debug(15 * "*" + "PVsim initialization" + 15 * "*")
        pv = pvsim.pvsim_init(ts)
        if pv is not None:
            pv.power_set(p_rated)
            pv.power_on()  # Turn on DC so the EUT can be initialized

        # initialize data acquisition
        ts.log_debug(15 * "*" + "DAS initialization" + 15 * "*")
        daq = das.das_init(ts, support_interfaces={"hil": phil, "pvsim": pv})
        daq.waveform_config({"mat_file_name":"Data.mat",
                            "wfm_channels": VoltRideThrough.get_wfm_file_header()})

        if daq is not None:
            daq.sc['V_MEAS'] = 100
            """
            daq.sc['P_MEAS'] = 100
            daq.sc['Q_MEAS'] = 100
            daq.sc['Q_TARGET_MIN'] = 100
            daq.sc['Q_TARGET_MAX'] = 100
            daq.sc['PF_TARGET'] = 1
            daq.sc['event'] = 'None'
            ts.log('DAS device: %s' % daq.info())
            """

        """
        This test doesn't have specific procedure steps. 
        """

        # open result summary file
        result_summary_filename = 'result_summary.csv'
        result_summary = open(ts.result_file_path(result_summary_filename), 'a+')
        ts.result_file(result_summary_filename)
        result_summary.write('Test Name, Waveform File, RMS File\n')

        """
        During the LVRT test, the settings for magnitude and duration of undervoltage tripping functions shall be
        disabled or set so as not to influence the outcome of the test. 
        
        If the EUT provides a voltage-active power control mode, that mode shall be disabled. 
        
        Connect the EUT according to the instructions and specifications provided by the manufacturer.
        """
        # Wait to establish communications with the EUT after AC and DC power are provided
        eut = der.der_init(ts, support_interfaces={'hil': phil}) 

        # start = time.time()
        # comm_wait_time = max(0.0, startup_time - 60.)
        # while time.time()-start < comm_wait_time - 1:
        #     ts.sleep(1)
        #     ts.log('Waiting another %0.2f seconds until communicating with EUT' %
        #            (comm_wait_time - (time.time()-start)))

        if eut is not None:
            eut.config()
            
        # if eut is not None:
        #     eut.deactivate_all_fct()

    

        # Initial loop for all mode that will be executed
        modes = VoltRideThrough.get_modes()  # Options: LV_CAT_2, HV_CAT_2, LV_CAT_3, HV_CAT_3
        ts.log(f"VRT modes tested : '{modes}'")
        ts.log(f"VRT power level tested : '{pwr_lvl}'")
        ts.log(f"VRT phase combination tested : '{phase_comb_list}'")
        for current_mode in modes:
            # Configuring waveform timing blocks with offset in seconds
            # daq.waveform_config(vrt_lib_1547.get_waveform_config(current_mode,offset=5))
            """
            The ride-through tests shall be performed at two output power levels, high and low, and at any convenient
            power factor greater than 0.90. The output power levels shall be measured prior to the disturbance, i.e., in
            test condition A. High-power tests shall be performed at any active power level greater than 90% of the
            EUT nameplate active power rating at nominal voltage. ... Low-power tests shall be performed at any 
            convenient power level between 25% to 50% of EUT nameplate  apparent power rating at nominal voltage.
            """
            for pwr in pwr_lvl:  
                for phase in phase_comb_list :  
             
                    phase_combination_label = "PH" + ''.join(phase)

                    dataset_filename = f'{current_mode}_{round(pwr*100)}PCT_{phase_combination_label}_{consecutive_label}'
                    ts.log_debug(15 * "*" + f"Starting {dataset_filename}" + 15 * "*")
                    if data_ena:
                        daq.data_capture(True)

                    """
                    Setting up available power to appropriate power level 
                    """
                    if pv is not None:
                        ts.log_debug(f'Setting power level to {pwr}')
                        pv.iv_curve_config(pmp=p_rated, vmp=v_nom_in)
                        pv.irradiance_set(1000.)
                        pv.power_set(p_rated * pwr)
                        
                    """
                    Initiating voltage sequence for VRT
                    """
                    vrt_test_sequences = VoltRideThrough.set_test_conditions(current_mode)
                    VoltRideThrough.set_phase_combination(phase)
                    vrt_stop_time = VoltRideThrough.get_vrt_stop_time(vrt_test_sequences)
                    if phil is not None:
                        # Set model parameters
                        #phil.set_parameters(vrt_parameters)
                        # This adds 5 seconds of nominal behavior for EUT normal shutdown. This 5 sec is not recorded.
                        vrt_stop_time = vrt_stop_time + 5
                        ts.log('Stop time set to %s' % phil.set_stop_time(vrt_stop_time))
                        # The driver should take care of this by selecting "Yes" to "Load the model to target?"
                        ts.sleep(2.0)
                        phil.load_model_on_hil()
                        # You need to first load the model, then configure the parameters
                        # Now that we have all the test_sequences its time to sent them to the model.
                        VoltRideThrough.set_vrt_model_parameters(vrt_test_sequences)
                                        
                        """
                        The voltage-reactive power control mode of the EUT shall be set to the default settings specified in Table 8
                        of IEEE Std 1547-2018 for the applicable performance category, and enabled.
                        """
                        # Default curve is characteristic curve 1
                        vv_curve = 1
                        ActiveFunction = p1547.ActiveFunction(ts=ts,
                                                            script_name='Volt-Var',
                                                            functions=[VV],
                                                            criteria_mode=[True, True, True])
                        # Don't need to be set to imbalance mode
                        #ActiveFunction.set_imbalance_config(imbalance_angle_fix="std")
                        #ActiveFunction.reset_curve(vv_curve)
                        #ActiveFunction.reset_time_settings(tr=10, number_tr=2)
                        v_pairs = ActiveFunction.get_params(function=VV, curve=vv_curve)
                        ts.log_debug('v_pairs:%s' % v_pairs)
                        if eut is not None:
                            # Set to: V = {92, 98, 102, 108}, Var = {44, 0 , 0 , -44}
                            vv_curve_params = {'v': [round(v_pairs['V1']/v_nom,2),
                                                    round(v_pairs['V2']/v_nom,2),
                                                    round(v_pairs['V3']/v_nom,2),
                                                    round(v_pairs['V4']/v_nom,2)],
                                            'var': [round(v_pairs['Q1']/p_rated,2),
                                                    round(v_pairs['Q2']/p_rated,2),
                                                    round(v_pairs['Q3']/p_rated,2),
                                                    round(v_pairs['Q4']/p_rated,2)],
                                            'vref': 1.0,
                                            'RmpPtTms': 1.0}
                            ts.log_debug('Setting VV points: %s' % vv_curve_params)
                            eut.volt_var(params={'Ena': True, 'ACTCRV': vv_curve, 'curve': vv_curve_params})
                            ts.log_debug('Initial EUT VV settings are %s' % eut.volt_var())

                        # The driver parameter "Execute the model on target?" should be set to "No"
                        phil.start_simulation() 
                        ts.sleep(0.5)
                        sim_time = phil.get_time()
                        while (vrt_stop_time - sim_time) > 1.0:  # final sleep will get to stop_time.
                            sim_time = phil.get_time()
                            ts.log('Sim Time: %0.3f.  Waiting another %0.3f sec before saving data.' % (
                                sim_time, vrt_stop_time - sim_time))
                            ts.sleep(5)

                    
                        rms_dataset_filename = "No File"   
                        wave_start_filename = "No File"        
                        if data_ena:
                            rms_dataset_filename = dataset_filename + "_RMS.csv"
                            daq.data_capture(False)

                            # complete data capture
                            ts.log('Waiting for Opal to save the waveform data: {}'.format(dataset_filename))
                            ts.sleep(10)
                        if wav_ena:
                            # Convert and save the .mat file 
                            ts.log('Processing waveform dataset(s)')
                            wave_start_filename = dataset_filename + "_WAV.csv"

                            ds = daq.waveform_capture_dataset()  # returns list of databases of waveforms (overloaded)
                            ts.log(f'Number of waveforms to save {len(ds)}')
                            if len(ds) > 0:
                                ds[0].to_csv(ts.result_file_path(wave_start_filename))
                                ts.result_file(wave_start_filename)

                        if data_ena:
                            ds = daq.data_capture_dataset()
                            ts.log('Saving file: %s' % rms_dataset_filename)
                            ds.to_csv(ts.result_file_path(rms_dataset_filename))
                            ds.remove_none_row(ts.result_file_path(rms_dataset_filename), "TIME")
                            result_params = {
                                'plot.title': rms_dataset_filename.split('.csv')[0],
                                'plot.x.title': 'Time (sec)',
                                'plot.x.points': 'TIME',
                                'plot.y.points': 'AC_VRMS_1, AC_VRMS_2, AC_VRMS_3',
                                'plot.y.title': 'Voltage (V)',
                                'plot.y2.points': 'AC_IRMS_1, AC_IRMS_2, AC_IRMS_3',
                                'plot.y2.title': 'Current (A)',
                            }
                            ts.result_file(rms_dataset_filename, params=result_params)
                        result_summary.write('%s, %s, %s,\n' % (dataset_filename, wave_start_filename,
                                                                rms_dataset_filename))

                        phil.stop_simulation()

                  

        result = script.RESULT_COMPLETE

    except script.ScriptFail as e:
        reason = str(e)
        if reason:
            ts.log_error(reason)

    except Exception as e:
        ts.log_error((e, traceback.format_exc()))

        ts.log_error('Test script exception: %s' % traceback.format_exc())

    finally:
        if grid is not None:
            grid.close()
        if pv is not None:
            if p_rated is not None:
                pv.power_set(p_rated)
            pv.close()
        if daq is not None:
            daq.close()
        if eut is not None:
            # eut.fixed_pf(params={'Ena': False, 'PF': 1.0})
            eut.close()
        if rs is not None:
            rs.close()
        if phil is not None:
            if phil.model_state() == 'Model Running':
                phil.stop_simulation()
            phil.close()

        if result_summary is not None:
            result_summary.close()

        # create result workbook
        excelfile = ts.config_name() + '.xlsx'
        rslt.result_workbook(excelfile, ts.results_dir(), ts.result_dir())
        ts.result_file(excelfile)

    return result
コード例 #5
0
ファイル: FW.py プロジェクト: jayatsandia/svp_1547.1
def test_run():

    result = script.RESULT_FAIL
    # Variables use in script
    daq = None
    data = None
    grid = None
    pv = None
    eut = None
    chil = None
    result_summary = None
    dataset_filename = None
    fw_curves = []
    fw_response_time = [0, 0, 0]
    f_steps_dic = {}


    try:
        """
        Test Configuration
        """
        # Get all test script parameter
        mode = ts.param_value("fw.mode")
        eut_absorb = ts.param_value("eut_fw.absorb")

        """
        Version validation
        """
        p1547.VersionValidation(script_version=ts.info.version)
        """
        A separate module has been create for the 1547.1 Standard
        """
        ActiveFunction = p1547.ActiveFunction(ts=ts,
                                              functions=[FW],
                                              script_name='Frequency-Watt',
                                              criteria_mode=[True, True, True])
        ts.log_debug("1547.1 Library configured for %s" % ActiveFunction.get_script_name())


        if eut_absorb == "Yes":
            absorb_powers = [False, True]
        else:
            absorb_powers = [False]
        p_rated = ts.param_value('eut.p_rated')
        s_rated = ts.param_value('eut.s_rated')
        # DC voltages
        v_nom_in = ts.param_value('eut.v_in_nom')
        irr = ts.param_value('fw.power_lvl')
        if mode == 'Above':
            if irr == 'All':
                pwr_lvls = [1., 0.66, 0.2]
            elif irr == '100%':
                pwr_lvls = [1.]
            elif irr == '66%':
                pwr_lvls = [0.66]
            elif irr == '20%':
                pwr_lvls = [0.2]
        else:
            pwr_lvls = [1.]
        # AC voltages
        f_nom = ts.param_value('eut.f_nom')
        f_min = ts.param_value('eut.f_min')
        f_max = ts.param_value('eut.f_max')
        p_min = ts.param_value('eut.p_min')
        phases = ts.param_value('eut.phases')
        # EUI FW parameters
        absorb_enable = ts.param_value('eut_fw.sink_power')
        p_rated_prime = ts.param_value('eut_fw.p_rated_prime')
        p_min_prime = ts.param_value('eut_fw.p_min_prime')
        p_small = ts.param_value('eut_fw.p_small')

        if ts.param_value('fw.test_1') == 'Enabled':
            fw_curves.append(1)
            fw_response_time[1] = float(ts.param_value('fw.test_1_tr'))
        if ts.param_value('fw.test_2') == 'Enabled':
            fw_curves.append(2)
            fw_response_time[2] = float(ts.param_value('fw.test_2_tr'))

        '''
        a) Connect the EUT according to the instructions and specifications provided by the manufacturer.
        '''
        # initialize HIL environment, if necessary
        chil = hil.hil_init(ts)
        if chil is not None:
            chil.config()

        # DAS soft channels
        # TODO : add to library 1547
        #das_points = {'sc': ('P_TARGET', 'P_TARGET_MIN', 'P_TARGET_MAX', 'P_MEAS', 'F_TARGET', 'F_MEAS', 'event')}
        das_points = ActiveFunction.get_sc_points()
        # initialize data acquisition system
        daq = das.das_init(ts, sc_points=das_points['sc'], support_interfaces={'hil': chil}) 
        if daq is not None:
            daq.sc['P_TARGET'] = 100
            daq.sc['P_TARGET_MIN'] = 100
            daq.sc['P_TARGET_MAX'] = 100
            daq.sc['P_MEAS'] = 100
            daq.sc['F_TARGET'] = f_nom
            daq.sc['P_TARGET'] = p_rated
            daq.sc['event'] = 'None'
            ts.log('DAS device: %s' % daq.info())

        # Configure the EUT communications
        eut = der.der_init(ts, support_interfaces={'hil': chil}) 
        '''
        b) Set all frequency trip parameters to the widest range of adjustability. 
            Disable all reactive/active power control functions.
        '''
        if eut is not None:
            eut.config()
            #eut.deactivate_all_fct(act_fct='FW')
            ts.log_debug(eut.measurements())
            ts.log_debug(
                'L/HFRT and trip parameters set to the widest range : f_min:{0} Hz, f_max:{1} Hz'.format(f_min,
                                                                                                         f_max))
            eut_response = eut.frt_stay_connected_high(
                params={'Ena': True, 'ActCrv': 0, 'Tms1': 3000, 'Hz1': f_max, 'Tms2': 160, 'Hz2': f_max})
            ts.log_debug('HFRT and trip parameters from EUT : {}'.format(eut_response))
            eut_response = eut.frt_stay_connected_low(
                params={'Ena': True, 'ActCrv': 0, 'Tms1': 3000, 'Hz1': f_min, 'Tms2': 160, 'Hz2': f_min})
            ts.log_debug('LFRT and trip parameters from EUT : {}'.format(eut_response))

        else:
            ts.log_debug('Set L/HFRT and trip parameters to the widest range of adjustability possible.')

        '''
        c) Set all AC test source parameters to the nominal operating voltage and frequency 
        '''
        grid = gridsim.gridsim_init(ts, support_interfaces={'hil': chil})  # Turn on AC so the EUT can be initialized
        if grid is not None:
            grid.freq(f_nom)
            if mode == 'Below':
                # 1547.1 :  Frequency is ramped at the ROCOF for the category of the EUT.
                #           In this case the ROCOF is based on table 21 of 1547.2018
                #           (Category III is use because of table B.1 of 1547.2018)
                #           The ROCOF unit : Hz/s
                ts.log('Set Grid simulator ROCOF to 3 Hz/s')
                grid.rocof(3.0)


        # result params
        result_params = ActiveFunction.get_rslt_param_plot()

        # open result summary file
        result_summary_filename = 'result_summary.csv'
        result_summary = open(ts.result_file_path(result_summary_filename), 'a+')
        ts.result_file(result_summary_filename)
        result_summary.write(ActiveFunction.get_rslt_sum_col_name())

        '''
        above_d) Adjust the EUT's available active power to Prated .
        below_d) ""         ""          "". Set the EUT's output power to 50% of P rated .
        '''
        pv = pvsim.pvsim_init(ts)
        if pv is not None:
            pv.iv_curve_config(pmp=p_rated, vmp=v_nom_in)
            pv.irradiance_set(1000.)
        if mode == 'Below':
            if eut is not None:
                ts.log_debug("In Below mode, EUT's output power is set to 50%% of %s (Prated)" % p_rated)
                eut.limit_max_power(params={
                    'MaxLimWEna': True,
                    'MaxLimW_PCT': 50
                })
        """
        Test start
        """
        '''
        above_r) For EUT's that can absorb power, rerun Characteristic 1 allowing the unit to absorb power by
        programing a negative Pmin . 

        below_p) ""                 ""                  "". Set the unit to absorb power at -50% of P rated . 
        '''
        for absorb_power in absorb_powers:
            if absorb_power:
                if eut is not None:
                    if mode == 'Below':
                        ts.log_debug("Config EUT's absorb power at -50%% of P rated")
                        eut.limit_max_power(
                            params={
                            'MaxLimWEna': True,
                            'MaxLimW_PCT': 50
                            }
                        )
                    else:
                        ts.log_debug("Config EUT's absorb power to %s (P\'min)" % p_min_prime)
                        eut.limit_max_power(params={
                            'MaxLimWEna': True,
                            'MaxLimW': p_min_prime
                        })

            '''
              above_q) Repeat steps b) through p) for Characteristic 2. 

              below_o) ""           ""              ""
            '''
            if chil is not None:
                    ts.log('Start simulation of CHIL')
                    chil.start_simulation()
            for fw_curve in fw_curves:
                ts.log('Starting test with characteristic curve %s' % (fw_curve))
                ActiveFunction.reset_curve(curve=fw_curve)
                ActiveFunction.reset_time_settings(tr=fw_response_time[fw_curve])
                fw_param = ActiveFunction.get_params(function=FW, curve=fw_curve)

                f_steps_dict = ActiveFunction.create_fw_dict_steps(mode=mode)
                ts.log_debug(f'f_step={f_steps_dict}')


                '''
                p) Repeat test steps b) through o) with the EUT power set at 20% and 66% of rated power. 
                '''
                for power in pwr_lvls:
                    ActiveFunction.reset_pwr(pwr=power)

                    if pv is not None:
                        pv_power_setting = (p_rated * power)
                        pv.iv_curve_config(pmp=pv_power_setting, vmp=v_nom_in)
                        pv.irradiance_set(1000.)
                    '''
                    e) Set EUT freq-watt parameters to the values specified by Characteristic 1. 
                        All other functions should be turned off. 
                    '''

                    # STD_CHANGE : dbf and kf don't exist but dbof=dbuf and kof=kuf was the point of having two?
                    if eut is not None:
                        params = {
                            'Ena': True,
                            'curve': fw_curve,
                            'dbf': fw_param['dbf'],
                            'kof': fw_param['kof'],
                            'RspTms': fw_param['tr']
                        }
                        ts.log_debug(params)
                        settings = eut.freq_watt(params)
                        '''
                        f) Verify freq-watt mode is reported as active and that 
                            the correct characteristic is reported. 
                        '''
                        ts.log_debug('Initial EUT FW settings are %s' % settings)

                    ts.log_debug('Test parameters :  %s' % fw_param)
                    ts.log('Starting data capture for power = %s' % power)

                    dataset_filename = 'FW_{0}_PWR_{1}_{2}'.format(fw_curve, power, mode)
                    if absorb_power:
                        dataset_filename = 'FW_{0}_PWR_{1}_{2}_ABSORB'.format(fw_curve, power, mode)
                    ActiveFunction.reset_filename(filename=dataset_filename)
                    ts.log('------------{}------------'.format(dataset_filename))

                    '''
                    g) Once steady state is reached, read and record the EUT's 
                    active power, reactive power, voltage,frequency, and current measurements. 
                    '''
                    # STD_CHANGE there should be a wait for steady state to be reached in both mode
                    step = 'Step F'
                    daq.sc['event'] = step
                    daq.data_sample()
                    ts.log('Wait for steady state to be reached')
                    ts.sleep(2 * fw_response_time[fw_curve])
                    daq.data_capture(True)

                    for step_label, f_step in f_steps_dict.items():
                        ActiveFunction.start(daq=daq, step_label=step_label)
                        ts.log('Frequency step: setting Grid simulator frequency to %s (%s)' % (f_step, step_label))
                        step_dict = {'F': f_step}
                        if grid is not None:
                            grid.freq(f_step)
                        ActiveFunction.record_timeresponse(daq=daq)
                        ActiveFunction.evaluate_criterias(daq=daq, step_dict=step_dict)
                        result_summary.write(ActiveFunction.write_rslt_sum())

                    dataset_filename = dataset_filename + ".csv"
                    daq.data_capture(False)
                    ds = daq.data_capture_dataset()
                    ts.log('Saving file: %s' % dataset_filename)
                    ds.to_csv(ts.result_file_path(dataset_filename))
                    result_params['plot.title'] = os.path.splitext(dataset_filename)[0]
                    ts.result_file(dataset_filename, params=result_params)

        result = script.RESULT_COMPLETE

        return result

    except script.ScriptFail as e:
        reason = str(e)
        if reason:
            ts.log_error(reason)

    except Exception as e:
        if dataset_filename is not None:
            dataset_filename = dataset_filename + ".csv"
            daq.data_capture(False)
            ds = daq.data_capture_dataset()
            ts.log('Saving file: %s' % dataset_filename)
            ds.to_csv(ts.result_file_path(dataset_filename))
            result_params['plot.title'] = dataset_filename.split('.csv')[0]
            ts.result_file(dataset_filename, params=result_params)
        ts.log_error('Test script exception: %s' % traceback.format_exc())

    finally:
        if daq is not None:
            daq.close()
        if pv is not None:
            if p_rated is not None:
                pv.power_set(p_rated)
            pv.close()
        if grid is not None:
            if f_nom is not None:
                grid.voltage(f_nom)
            grid.close()
        if chil is not None:
            chil.close()
        if eut is not None:
            #eut.volt_var(params={'Ena': False})
            #eut.volt_watt(params={'Ena': False})
            eut.close()
        if result_summary is not None:
            result_summary.close()

        # create result workbook
        excelfile = ts.config_name() + '.xlsx'
        rslt.result_workbook(excelfile, ts.results_dir(), ts.result_dir())
        ts.result_file(excelfile)

    return result
コード例 #6
0
def watt_var_mode(wv_curves, wv_response_time, pwr_lvls):

    result = script.RESULT_FAIL
    daq = None
    v_nom = None
    grid = None
    pv = None
    eut = None
    chil = None
    result_summary = None
    dataset_filename = None

    try:
        cat = ts.param_value('eut.cat')
        cat2 = ts.param_value('eut.cat2')
        sink_power = ts.param_value('eut.sink_power')
        p_rated = ts.param_value('eut.p_rated')
        p_rated_prime = ts.param_value('eut.p_rated_prime')
        var_rated = ts.param_value('eut.var_rated')
        s_rated = ts.param_value('eut.s_rated')

        # DC voltages
        v_in_nom = ts.param_value('eut.v_in_nom')
        #v_min_in = ts.param_value('eut.v_in_min')
        #v_max_in = ts.param_value('eut.v_in_max')

        # AC voltages
        v_nom = ts.param_value('eut.v_nom')
        v_low = ts.param_value('eut.v_low')
        v_high = ts.param_value('eut.v_high')
        p_min = ts.param_value('eut.p_min')
        p_min_prime = ts.param_value('eut.p_min_prime')
        phases = ts.param_value('eut.phases')

        # EUI Absorb capabilities
        absorb = {}
        absorb['ena'] = ts.param_value('eut_cpf.sink_power')

        """
        A separate module has been create for the 1547.1 Standard
        """
        #lib_1547 = p1547.module_1547(ts=ts, aif='WV', criteria)
        ActiveFunction = p1547.ActiveFunction(ts=ts,
                                              functions=[WV],
                                              script_name='Watt-Var',
                                              criteria_mode=[True, True, True])
        ts.log_debug("1547.1 Library configured for %s" % ActiveFunction.get_script_name())

        # result params
        result_params = ActiveFunction.get_rslt_param_plot()

        '''
        a) Connect the EUT according to the instructions and specifications provided by the manufacturer.
        '''

        # initialize HIL environment, if necessary
        chil = hil.hil_init(ts)
        if chil is not None:
            chil.config()

        # pv simulator is initialized with test parameters and enabled
        pv = pvsim.pvsim_init(ts)
        if pv is not None:
            pv.power_set(p_rated)
            pv.power_on()  # Turn on DC so the EUT can be initialized

        # DAS soft channels
        das_points = ActiveFunction.get_sc_points()

        # initialize data acquisition system
        daq = das.das_init(ts, sc_points=das_points['sc'])

        ts.log_debug(0.05 * ts.param_value('eut.s_rated'))
        daq.sc['P_TARGET'] = v_nom
        daq.sc['Q_TARGET'] = 100
        daq.sc['Q_TARGET_MIN'] = 100
        daq.sc['Q_TARGET_MAX'] = 100
        daq.sc['event'] = 'None'

        ts.log('DAS device: %s' % daq.info())

        '''
        b) Set all voltage trip parameters to the widest range of adjustability.  Disable all reactive/active power
        control functions.
        '''

        eut = der.der_init(ts)
        if eut is not None:
            eut.config()
            ts.log_debug(eut.measurements())

            #Disable all functions on EUT
            eut.deactivate_all_fct()

            ts.log_debug('Voltage trip parameters set to the widest range: v_min: {0} V, '
                         'v_max: {1} V'.format(v_low, v_high))
            try:
                eut.vrt_stay_connected_high(params={'Ena': True, 'ActCrv': 0, 'Tms1': 3000,
                                                    'V1': v_high, 'Tms2': 0.16, 'V2': v_high})
            except Exception as e:
                ts.log_error('Could not set VRT Stay Connected High curve. %s' % e)
            try:
                eut.vrt_stay_connected_low(params={'Ena': True, 'ActCrv': 0, 'Tms1': 3000,
                                                   'V1': v_low, 'Tms2': 0.16, 'V2': v_low})
            except Exception as e:
                ts.log_error('Could not set VRT Stay Connected Low curve. %s' % e)
        else:
            ts.log_debug('Set L/HVRT and trip parameters set to the widest range of adjustability possible.')

        # Special considerations for CHIL ASGC/Typhoon startup
        if chil is not None:
            inv_power = eut.measurements().get('W')
            timeout = 120.
            if inv_power <= p_rated * 0.85:
                pv.irradiance_set(995)  # Perturb the pv slightly to start the inverter
                ts.sleep(3)
                eut.connect(params={'Conn': True})
            while inv_power <= p_rated * 0.85 and timeout >= 0:
                ts.log('Inverter power is at %0.1f. Waiting up to %s more seconds or until EUT starts...' %
                       (inv_power, timeout))
                ts.sleep(1)
                timeout -= 1
                inv_power = eut.measurements().get('W')
                if timeout == 0:
                    result = script.RESULT_FAIL
                    raise der.DERError('Inverter did not start.')
            ts.log('Waiting for EUT to ramp up')
            ts.sleep(8)
            ts.log_debug('DAS data_read(): %s' % daq.data_read())

        '''
        c) Set all AC test source parameters to the nominal operating voltage and frequency.
        '''
        grid = gridsim.gridsim_init(ts, support_interfaces={'hil': chil})  # Turn on AC so the EUT can be initialized
        if grid is not None:
            grid.voltage(v_nom)

        # open result summary file
        result_summary_filename = 'result_summary.csv'
        result_summary = open(ts.result_file_path(result_summary_filename), 'a+')
        ts.result_file(result_summary_filename)
        result_summary.write(ActiveFunction.get_rslt_sum_col_name())

        '''
        d) Adjust the EUT's available active power to Prated. For an EUT with an input voltage range, set the input
        voltage to Vin_nom. The EUT may limit active power throughout the test to meet reactive power requirements.
        For an EUT with an input voltage range.
        '''

        if pv is not None:
            pv.iv_curve_config(pmp=p_rated, vmp=v_in_nom)
            pv.irradiance_set(1000.)

        '''
        dd) Repeat steps e) through dd) for characteristics 2 and 3.
        '''

        #TODO 1.Add absorb option possibility for EUT
        #TODO 2.Add communication with EUT

        for wv_curve in wv_curves:
            ts.log('Starting test with characteristic curve %s' % (wv_curve))
            ActiveFunction.reset_curve(wv_curve)
            ActiveFunction.reset_time_settings(tr=wv_response_time[wv_curve], number_tr=2)
            p_pairs = ActiveFunction.get_params(function=WV, curve=wv_curve)
            '''
            d2) Set EUT volt-var parameters to the values specified by Characteristic 1.
            All other function should be turned off. Turn off the autonomously adjusting reference voltage.
            '''
            if eut is not None:
                # Activate watt-var function with following parameters
                # SunSpec convention is to use percentages for P and Q points.
                wv_curve_params = {'w': [p_pairs['P0']*(100/p_rated),
                                         p_pairs['P1']*(100/p_rated),
                                         p_pairs['P2']*(100/p_rated),
                                         p_pairs['P3']*(100/p_rated)],
                                   'var': [p_pairs['Q0']*(100/var_rated),
                                           p_pairs['Q1']*(100/var_rated),
                                           p_pairs['Q2']*(100/var_rated),
                                           p_pairs['Q3']*(100/var_rated)]}
                ts.log_debug('Sending WV points: %s' % wv_curve_params)
                eut.watt_var(params={'Ena': True, 'curve': wv_curve_params})


                '''
                e) Verify volt-var mode is reported as active and that the correct characteristic is reported.
                '''
                ts.log_debug('Initial EUT VV settings are %s' % eut.watt_var())

            '''
            cc) Repeat test steps d) through cc) at EUT power set at 20% and 66% of rated power.
            '''
            for power in pwr_lvls:
                ActiveFunction.reset_pwr(pwr=power)
                if pv is not None:
                    pv_power_setting = (p_rated * power)
                    pv.iv_curve_config(pmp=pv_power_setting, vmp=v_in_nom)
                    pv.irradiance_set(1000.)

                # Special considerations for CHIL ASGC/Typhoon startup #
                if chil is not None:
                    inv_power = eut.measurements().get('W')
                    timeout = 120.
                    if inv_power <= pv_power_setting * 0.85:
                        pv.irradiance_set(995)  # Perturb the pv slightly to start the inverter
                        ts.sleep(3)
                        eut.connect(params={'Conn': True})
                    while inv_power <= pv_power_setting * 0.85 and timeout >= 0:
                        ts.log('Inverter power is at %0.1f. Waiting up to %s more seconds or until EUT starts...' %
                               (inv_power, timeout))
                        ts.sleep(1)
                        timeout -= 1
                        inv_power = eut.measurements().get('W')
                        if timeout == 0:
                            result = script.RESULT_FAIL
                            raise der.DERError('Inverter did not start.')
                    ts.log('Waiting for EUT to ramp up')
                    ts.sleep(8)

                #Create Watt-Var Dictionary
                p_steps_dict = ActiveFunction.create_wv_dict_steps()

                filename = 'WV_%s_PWR_%d' % (wv_curve, power * 100)
                ActiveFunction.reset_filename(filename=filename)
                ts.log('------------{}------------'.format(dataset_filename))

                # Start the data acquisition systems
                daq.data_capture(True)

                for step_label, p_step in p_steps_dict.items():
                    ts.log('Power step: setting Grid power to %s (W)(%s)' % (p_step, step_label))
                    ActiveFunction.start(daq=daq, step_label=step_label)
                    step_dict = {'V': v_nom, 'P': p_step}
                    if pv is not None:
                        pv.power_set(step_dict['P'])

                    ActiveFunction.record_timeresponse(daq=daq)
                    ActiveFunction.evaluate_criterias(daq=daq, step_dict=step_dict)
                    result_summary.write(ActiveFunction.write_rslt_sum())

                ts.log('Sampling complete')
                dataset_filename = filename + ".csv"
                daq.data_capture(False)
                ds = daq.data_capture_dataset()
                ts.log('Saving file: %s' % dataset_filename)
                ds.to_csv(ts.result_file_path(dataset_filename))
                result_params['plot.title'] = dataset_filename.split('.csv')[0]
                ts.result_file(dataset_filename, params=result_params)
                result = script.RESULT_COMPLETE

    except script.ScriptFail as e:
        reason = str(e)
        if reason:
            ts.log_error(reason)

    except Exception as e:
        if dataset_filename is not None:
            dataset_filename = dataset_filename + ".csv"
            daq.data_capture(False)
            ds = daq.data_capture_dataset()
            ts.log('Saving file: %s' % dataset_filename)
            ds.to_csv(ts.result_file_path(dataset_filename))
            result_params['plot.title'] = dataset_filename.split('.csv')[0]
            ts.result_file(dataset_filename, params=result_params)
        ts.log_error('Test script exception: %s' % traceback.format_exc())

    finally:
        if daq is not None:
            daq.close()
        if pv is not None:
            pv.power_set(p_rated)
            pv.close()
        if grid is not None:
            if v_nom is not None:
                grid.voltage(v_nom)
            grid.close()
        if chil is not None:
            chil.close()
        if eut is not None:
            eut.deactivate_all_fct()
            eut.close()
        if result_summary is not None:
            result_summary.close()

    return result
コード例 #7
0
ファイル: VW.py プロジェクト: jayatsandia/svp_1547.1
def volt_watt_mode(vw_curves, vw_response_time, pwr_lvls):

    result = script.RESULT_FAIL
    daq = None
    data = None
    p_rated = None
    v_nom = None
    grid = None
    pv = None
    eut = None
    chil = None
    result_summary = None
    dataset_filename = None

    try:

        p_rated = ts.param_value('eut.p_rated')
        s_rated = ts.param_value('eut.s_rated')

        # DC voltages
        v_in_nom = ts.param_value('eut.v_in_nom')
        v_min_in = ts.param_value('eut.v_in_min')
        v_max_in = ts.param_value('eut.v_in_max')

        # AC voltages
        v_nom = ts.param_value('eut.v_nom')
        v_min = ts.param_value('eut.v_low')
        v_max = ts.param_value('eut.v_high')
        p_min = ts.param_value('eut.p_min')
        phases = ts.param_value('eut.phases')

        # EUI Absorb capabilities
        absorb = {}
        absorb['ena'] = ts.param_value('eut_vw.sink_power')
        absorb['p_rated_prime'] = ts.param_value('eut_vw.p_rated_prime')
        absorb['p_min_prime'] = ts.param_value('eut_vw.p_min_prime')
        """
        Version validation
        """
        p1547.VersionValidation(script_version=ts.info.version)
        """
        A separate module has been create for the 1547.1 Standard
        """
        ActiveFunction = p1547.ActiveFunction(ts=ts,
                                              functions=[VW],
                                              script_name='Volt-Watt',
                                              criteria_mode=[True, True, True])
        ts.log_debug("1547.1 Library configured for %s" %
                     ActiveFunction.get_script_name())

        # result params
        result_params = ActiveFunction.get_rslt_param_plot()
        '''
        a) Connect the EUT according to the instructions and specifications provided by the manufacturer.
        '''
        ts.log_debug(15 * "*" + "HIL initialization" + 15 * "*")

        # initialize HIL environment, if necessary
        chil = hil.hil_init(ts)
        if chil is not None:
            chil.config()
        ts.log_debug(15 * "*" + "PVSIM initialization" + 15 * "*")

        # pv simulator is initialized with test parameters and enabled
        pv = pvsim.pvsim_init(ts)
        if pv is not None:
            pv.power_set(p_rated)
            pv.power_on()  # Turn on DC so the EUT can be initialized

        ts.log_debug(15 * "*" + "DAS initialization" + 15 * "*")

        # DAS soft channels
        #das_points = {'sc': ('P_TARGET', 'P_TARGET_MIN', 'P_TARGET_MAX', 'P_MEAS', 'V_TARGET','V_MEAS','event')}
        das_points = ActiveFunction.get_sc_points()

        # initialize data acquisition system
        das_points = ActiveFunction.get_sc_points()
        daq = das.das_init(ts,
                           sc_points=das_points['sc'],
                           support_interfaces={'hil': chil})
        if daq is not None:
            daq.sc['P_TARGET'] = p_rated
            daq.sc['P_TARGET_MIN'] = 100
            daq.sc['P_TARGET_MAX'] = 100
            daq.sc['V_TARGET'] = v_nom
            daq.sc['event'] = 'None'
            ts.log('DAS device: %s' % daq.info())
        '''
        b) Set all voltage trip parameters to the widest range of adjustability. Disable all reactive/active power
        control functions.
        '''
        ts.log_debug(15 * "*" + "EUT initialization" + 15 * "*")

        eut = der.der_init(ts, support_interfaces={'hil': chil})
        if eut is not None:
            eut.config()
            #Disable all functions on EUT
            eut.deactivate_all_fct()
            ts.log_debug(eut.measurements())
            ts.log_debug(
                'L/HVRT and trip parameters set to the widest range : v_min: {0} V, v_max: {1} V'
                .format(v_min, v_max))
            try:
                eut.vrt_stay_connected_high(
                    params={
                        'Ena': True,
                        'ActCrv': 0,
                        'Tms1': 3000,
                        'V1': v_max,
                        'Tms2': 0.16,
                        'V2': v_max
                    })
            except Exception as e:
                ts.log_error(
                    'Could not set VRT Stay Connected High curve. %s' % e)
            try:
                eut.vrt_stay_connected_low(
                    params={
                        'Ena': True,
                        'ActCrv': 0,
                        'Tms1': 3000,
                        'V1': v_min,
                        'Tms2': 0.16,
                        'V2': v_min
                    })
            except Exception as e:
                ts.log_error('Could not set VRT Stay Connected Low curve. %s' %
                             e)
        else:
            ts.log_debug(
                'Set L/HVRT and trip parameters set to the widest range of adjustability possible.'
            )
        '''
        c) Set all AC test source parameters to the nominal operating voltage and frequency.
        '''
        ts.log_debug(15 * "*" + "GRIDSIM initialization" + 15 * "*")

        # grid simulator is initialized with test parameters and enabled
        grid = gridsim.gridsim_init(ts, support_interfaces={
            'hil': chil
        })  # Turn on AC so the EUT can be initialized
        if grid is not None:
            grid.voltage(v_nom)

        # open result summary file
        result_summary_filename = 'result_summary.csv'
        result_summary = open(ts.result_file_path(result_summary_filename),
                              'a+')
        ts.result_file(result_summary_filename)
        result_summary.write(ActiveFunction.get_rslt_sum_col_name())
        '''
        v) Test may be repeated for EUT's that can also absorb power using the P' values in the characteristic
        definition.
        '''
        # TODO: add P' tests (Like CPF -> for absorb_power in absorb_powers:)
        '''
        u) Repeat steps d) through u) for characteristics 2 and 3.
        '''
        for vw_curve in vw_curves:
            ts.log('Starting test with characteristic curve %s' % (vw_curve))
            ActiveFunction.reset_curve(vw_curve)
            ActiveFunction.reset_time_settings(tr=vw_response_time[vw_curve],
                                               number_tr=2)
            v_pairs = ActiveFunction.get_params(curve=vw_curve, function=VW)
            '''
            t) Repeat steps d) through t) at EUT power set at 20% and 66% of rated power.
            '''
            for power in pwr_lvls:
                ActiveFunction.reset_pwr(pwr=power)
                '''
                d) Adjust the EUT's available active power to Prated. For an EUT with an input voltage range, set the input
                voltage to Vin_nom. The EUT may limit active power throughout the test to meet reactive power requirements.
                For an EUT with an input voltage range.
                '''
                if pv is not None:
                    pv_power_setting = (p_rated * power)
                    pv.iv_curve_config(pmp=pv_power_setting, vmp=v_in_nom)
                    pv.irradiance_set(1000.)

                # Special considerations for CHIL ASGC/Typhoon startup #
                if chil is not None:
                    if eut is not None:
                        if eut.measurements() is not None:
                            inv_power = eut.measurements().get('W')
                            timeout = 120.
                            if inv_power <= pv_power_setting * 0.85:
                                pv.irradiance_set(
                                    995
                                )  # Perturb the pv slightly to start the inverter
                                ts.sleep(3)
                                eut.connect(params={'Conn': True})
                            while inv_power <= pv_power_setting * 0.85 and timeout >= 0:
                                ts.log(
                                    'Inverter power is at %0.1f. Waiting up to %s more seconds or until EUT starts...'
                                    % (inv_power, timeout))
                                ts.sleep(1)
                                timeout -= 1
                                inv_power = eut.measurements().get('W')
                                if timeout == 0:
                                    result = script.RESULT_FAIL
                                    raise der.DERError(
                                        'Inverter did not start.')
                            ts.log('Waiting for EUT to ramp up')
                            ts.sleep(8)
                '''
                e) Set EUT volt-watt parameters to the values specified by Characteristic 1. All other functions should
                   be turned off.
                '''
                if eut is not None:
                    vw_curve_params = {
                        'v': [v_pairs['V1'] / v_nom, v_pairs['V2'] / v_nom],
                        'w':
                        [v_pairs['P1'] / p_rated, v_pairs['P2'] / p_rated],
                        'DeptRef': 'W_MAX_PCT',
                        "RmpTms": vw_response_time[vw_curve]
                    }

                    vw_params = {
                        'Ena': True,
                        'ActCrv': 1,
                        'curve': vw_curve_params
                    }
                    ts.log_debug('Writing the following params to EUT: %s' %
                                 vw_params)
                    eut.volt_watt(params=vw_params)
                    '''
                    f) Verify volt-watt mode is reported as active and that the correct characteristic is reported.
                    '''
                    ts.log_debug('Initial EUT VW settings are %s' %
                                 eut.volt_watt())
                if chil is not None:
                    ts.log('Start simulation of CHIL')
                    chil.start_simulation()
                '''
                Refer to P1547 Library and IEEE1547.1 standard for steps 
                '''
                v_steps_dict = ActiveFunction.create_vw_dict_steps()

                # Configure the data acquisition system
                ts.log('Starting data capture for power = %s' % power)
                dataset_filename = ('VW_{0}_PWR_{1}'.format(vw_curve, power))
                ActiveFunction.reset_filename(filename=dataset_filename)
                ts.log('------------{}------------'.format(dataset_filename))
                daq.data_capture(True)

                for step_label, v_step in v_steps_dict.items():
                    ts.log(
                        'Voltage step: setting Grid simulator voltage to %s (%s)'
                        % (v_step, step_label))
                    ActiveFunction.start(daq=daq, step_label=step_label)

                    step_dict = {'V': v_step}
                    if grid is not None:
                        grid.voltage(step_dict['V'])

                    ActiveFunction.record_timeresponse(daq=daq)
                    ActiveFunction.evaluate_criterias(daq=daq,
                                                      step_dict=step_dict)
                    result_summary.write(ActiveFunction.write_rslt_sum())

                # create result workbook
                ts.log('Sampling complete')
                dataset_filename = dataset_filename + ".csv"
                daq.data_capture(False)
                ds = daq.data_capture_dataset()
                ts.log('Saving file: %s' % dataset_filename)
                ds.to_csv(ts.result_file_path(dataset_filename))
                result_params['plot.title'] = dataset_filename.split('.csv')[0]
                ts.result_file(dataset_filename, params=result_params)
                result = script.RESULT_COMPLETE

    except script.ScriptFail as e:
        reason = str(e)
        if reason:
            ts.log_error(reason)

    except Exception as e:
        if dataset_filename is not None:
            dataset_filename = dataset_filename + ".csv"
            daq.data_capture(False)
            ds = daq.data_capture_dataset()
            ts.log('Saving file: %s' % dataset_filename)
            ds.to_csv(ts.result_file_path(dataset_filename))
            result_params['plot.title'] = dataset_filename.split('.csv')[0]
            ts.result_file(dataset_filename, params=result_params)
        ts.log_error('Test script exception: %s' % traceback.format_exc())
        raise

    finally:
        if daq is not None:
            daq.close()
        if pv is not None:
            if p_rated is not None:
                pv.power_set(p_rated)
            pv.close()
        if grid is not None:
            if v_nom is not None:
                grid.voltage(v_nom)
            grid.close()
        if chil is not None:
            chil.close()
        if eut is not None:
            eut.close()
        if result_summary is not None:
            result_summary.close()

    return result
コード例 #8
0
ファイル: VW.py プロジェクト: jayatsandia/svp_1547.1
def volt_watt_mode_imbalanced_grid(imbalance_resp, vw_curves,
                                   vw_response_time):

    result = script.RESULT_FAIL
    daq = None
    p_rated = None
    grid = None
    pv = None
    eut = None
    chil = None
    result_summary = None

    try:
        cat = ts.param_value('eut.cat')
        cat2 = ts.param_value('eut.cat2')
        p_rated = ts.param_value('eut.p_rated')
        s_rated = ts.param_value('eut.s_rated')

        # DC voltages
        v_in_nom = ts.param_value('eut.v_in_nom')

        # AC voltages
        v_nom = ts.param_value('eut.v_nom')
        v_min = ts.param_value('eut.v_low')
        v_max = ts.param_value('eut.v_high')
        p_min = ts.param_value('eut.p_min')
        phases = ts.param_value('eut.phases')
        imbalance_fix = ts.param_value('vw.imbalance_fix')

        # EUI Absorb capabilities
        absorb = {}
        absorb['ena'] = ts.param_value('eut_vw.sink_power')
        absorb['p_rated_prime'] = ts.param_value('eut_vw.p_rated_prime')
        absorb['p_min_prime'] = ts.param_value('eut_vw.p_min_prime')
        """
        A separate module has been create for the 1547.1 Standard
        """
        ActiveFunction = p1547.ActiveFunction(ts=ts,
                                              functions=[VW],
                                              script_name='Volt-Watt',
                                              criteria_mode=[True, True, True])
        ts.log_debug('1547.1 Library configured for %s' %
                     ActiveFunction.get_script_name())

        ActiveFunction.set_imbalance_config(imbalance_angle_fix=imbalance_fix)
        ts.log_debug('1547.1 Library configured for %s' %
                     ActiveFunction.get_script_name())
        '''
        a) Connect the EUT according to the instructions and specifications provided by the manufacturer.
        '''
        ts.log_debug(15 * "*" + "HIL initialization" + 15 * "*")

        # initialize HIL environment, if necessary
        chil = hil.hil_init(ts)
        if chil is not None:
            chil.config()
        ts.log_debug(15 * "*" + "GRIDSIM initialization" + 15 * "*")
        # grid simulator is initialized with test parameters and enabled
        grid = gridsim.gridsim_init(ts, support_interfaces={
            'hil': chil
        })  # Turn on AC so the EUT can be initialized
        if grid is not None:
            grid.voltage(v_nom)
        ts.log_debug(15 * "*" + "PVSIM initialization" + 15 * "*")
        # pv simulator is initialized with test parameters and enabled
        pv = pvsim.pvsim_init(ts)
        if pv is not None:
            pv.power_set(p_rated)
            pv.power_on()  # Turn on DC so the EUT can be initialized
        ts.log_debug(15 * "*" + "DAS initialization" + 15 * "*")
        # DAS soft channels
        #das_points = {'sc': ('P_TARGET', 'P_TARGET_MIN', 'P_TARGET_MAX', 'P_MEAS', 'V_TARGET', 'V_MEAS', 'event')}
        das_points = ActiveFunction.get_sc_points()

        # initialize data acquisition system
        daq = das.das_init(ts,
                           sc_points=das_points['sc'],
                           support_interfaces={'hil': chil})

        if daq is not None:
            daq.sc['P_TARGET'] = p_rated
            daq.sc['P_TARGET_MIN'] = 100
            daq.sc['P_TARGET_MAX'] = 100
            daq.sc['V_TARGET'] = v_nom
            daq.sc['event'] = 'None'

        ts.log('DAS device: %s' % daq.info())
        '''
        b) Set all voltage trip parameters to the widest range of adjustability. Disable all reactive/active power
        control functions.
        '''
        ts.log_debug(15 * "*" + "EUT initialization" + 15 * "*")

        eut = der.der_init(ts, support_interfaces={'hil': chil})
        if eut is not None:
            eut.config()
            #Disable all functions on EUT
            #eut.deactivate_all_fct()
            ts.log_debug(eut.measurements())
            ts.log_debug(
                'L/HVRT and trip parameters set to the widest range : v_min: {0} V, v_max: {1} V'
                .format(v_min, v_max))
            try:
                eut.vrt_stay_connected_high(
                    params={
                        'Ena': True,
                        'ActCrv': 0,
                        'Tms1': 3000,
                        'V1': v_max,
                        'Tms2': 0.16,
                        'V2': v_max
                    })
            except Exception as e:
                ts.log_error(
                    'Could not set VRT Stay Connected High curve. %s' % e)
            try:
                eut.vrt_stay_connected_low(
                    params={
                        'Ena': True,
                        'ActCrv': 0,
                        'Tms1': 3000,
                        'V1': v_min,
                        'Tms2': 0.16,
                        'V2': v_min
                    })
            except Exception as e:
                ts.log_error('Could not set VRT Stay Connected Low curve. %s' %
                             e)
        else:
            ts.log_debug(
                'Set L/HVRT and trip parameters set to the widest range of adjustability possible.'
            )

        # Special considerations for CHIL ASGC/Typhoon startup
        if chil is not None:
            if eut is not None:
                inv_power = eut.measurements().get('W')
                timeout = 120.
                if inv_power <= p_rated * 0.85:
                    pv.irradiance_set(
                        995)  # Perturb the pv slightly to start the inverter
                    ts.sleep(3)
                    eut.connect(params={'Conn': True})
                while inv_power <= p_rated * 0.85 and timeout >= 0:
                    ts.log(
                        'Inverter power is at %0.1f. Waiting up to %s more seconds or until EUT starts...'
                        % (inv_power, timeout))
                    ts.sleep(1)
                    timeout -= 1
                    inv_power = eut.measurements().get('W')
                    if timeout == 0:
                        result = script.RESULT_FAIL
                        raise der.DERError('Inverter did not start.')
                ts.log('Waiting for EUT to ramp up')
                ts.sleep(8)
        '''
        c) Set all AC test source parameters to the nominal operating voltage and frequency.
        '''
        if grid is not None:
            grid.voltage(v_nom)

        # open result summary file
        result_summary_filename = 'result_summary.csv'
        result_summary = open(ts.result_file_path(result_summary_filename),
                              'a+')
        ts.result_file(result_summary_filename)
        result_summary.write(ActiveFunction.get_rslt_sum_col_name())
        '''
        d) Adjust the EUT's available active power to Prated. For an EUT with an input voltage range, set the input
        voltage to Vin_nom.
        '''
        if pv is not None:
            pv.iv_curve_config(pmp=p_rated, vmp=v_in_nom)
            pv.irradiance_set(1000.)

        for imbalance_response in imbalance_resp:
            for vw_curve in vw_curves:
                '''
                e) Set EUT volt-watt parameters to the values specified by Characteristic 1. All other function be
                turned off.
                '''
                if eut is not None:
                    #eut.deactivate_all_fct()
                    pass
                ts.log('Starting test with characteristic curve %s' %
                       (vw_curve))
                ActiveFunction.reset_curve(vw_curve)
                ActiveFunction.reset_time_settings(
                    tr=vw_response_time[vw_curve], number_tr=2)
                v_pairs = ActiveFunction.get_params(curve=vw_curve,
                                                    function=VW)

                # it is assumed the EUT is on
                eut = der.der_init(ts)
                if eut is not None:
                    vw_curve_params = {
                        'v': [
                            round(v_pairs['V1'] * (v_nom), 2),
                            round(v_pairs['V2'] * (v_nom), 2)
                        ],
                        'w': [
                            round(v_pairs['P1'] * (p_rated), 2),
                            round(v_pairs['P2'] * (p_rated), 2)
                        ],
                        'DeptRef':
                        'W_MAX_PCT'
                    }
                    vw_params = {
                        'Ena': True,
                        'ActCrv': 1,
                        'curve': vw_curve_params
                    }
                    '''
                    f) Verify volt-watt mode is reported as active and that the correct characteristic is reported
                    '''
                    eut.volt_watt(params=vw_params)
                    ts.log_debug('Initial EUT VW settings are %s' %
                                 eut.volt_watt())
                    ts.log_debug('curve points:  %s' % v_pairs)
                '''
                g) Once steady state is reached, begin the adjustment of phase voltages.
                '''
                """
                Test start
                """
                ActiveFunction.set_step_label('G')
                daq.sc['event'] = ActiveFunction.get_step_label()
                daq.data_sample()
                ts.log('Wait for steady state to be reached')
                ts.sleep(2 * vw_response_time[vw_curve])
                ts.log('Starting imbalance test with VW mode at %s (%s)' %
                       (imbalance_response, imbalance_fix))

                dataset_filename = 'VW_IMB_%s_%s' % (imbalance_response,
                                                     imbalance_fix)
                ts.log('------------{}------------'.format(dataset_filename))
                # Start the data acquisition systems
                daq.data_capture(True)
                '''
                Step h) For multiphase units, step the AC test source voltage to Case A from Table 24
                '''

                if grid is not None:
                    step_label = ActiveFunction.get_step_label()
                    ts.log(
                        'Voltage step: setting Grid simulator to case A (IEEE 1547.1-Table 24)(%s)'
                        % step_label)
                    ActiveFunction.start(daq=daq, step_label=step_label)
                    v_target = ActiveFunction.set_grid_asymmetric(
                        grid=grid, case='case_a')
                    step_dict = {'V': v_target}
                    ActiveFunction.record_timeresponse(daq=daq)
                    ActiveFunction.evaluate_criterias(daq=daq,
                                                      step_dict=step_dict)
                    result_summary.write(ActiveFunction.write_rslt_sum())
                '''
                Step i) For multiphase units, step the AC test source voltage to VN.
                '''
                if grid is not None:
                    step_label = ActiveFunction.get_step_label()
                    ts.log(
                        'Voltage step: setting Grid simulator voltage to %s (%s)'
                        % (v_nom, step_label))
                    ActiveFunction.start(daq=daq, step_label=step_label)
                    v_target = v_nom
                    grid.voltage(v_target)
                    step_dict = {'V': v_target}
                    ActiveFunction.record_timeresponse(daq=daq)
                    ActiveFunction.evaluate_criterias(daq=daq,
                                                      step_dict=step_dict)
                    result_summary.write(ActiveFunction.write_rslt_sum())
                '''
                Step j) For multiphase units, step the AC test source voltage to Case B from Table 24
                '''
                if grid is not None:
                    step_label = ActiveFunction.get_step_label()
                    ts.log(
                        'Voltage step: setting Grid simulator to case B (IEEE 1547.1-Table 24)(%s)'
                        % step_label)
                    ActiveFunction.start(daq=daq, step_label=step_label)
                    v_target = ActiveFunction.set_grid_asymmetric(
                        grid=grid, case='case_b')
                    step_dict = {'V': v_target}
                    ActiveFunction.record_timeresponse(daq=daq)
                    ActiveFunction.evaluate_criterias(daq=daq,
                                                      step_dict=step_dict)
                    result_summary.write(ActiveFunction.write_rslt_sum())
                '''
                Step k) For multiphase units, step the AC test source voltage to VN.
                '''
                if grid is not None:
                    step_label = ActiveFunction.get_step_label()
                    ts.log(
                        'Voltage step: setting Grid simulator voltage to %s (%s)'
                        % (v_nom, step_label))
                    ActiveFunction.start(daq=daq, step_label=step_label)
                    v_target = v_nom
                    grid.voltage(v_target)
                    step_dict = {'V': v_target}
                    ActiveFunction.record_timeresponse(daq=daq)
                    ActiveFunction.evaluate_criterias(daq=daq,
                                                      step_dict=step_dict)
                    result_summary.write(ActiveFunction.write_rslt_sum())

                # Get the rslt parameters for plot
                result_params = ActiveFunction.get_rslt_param_plot()
                ts.log('Sampling complete')
                dataset_filename = dataset_filename + ".csv"
                daq.data_capture(False)
                ds = daq.data_capture_dataset()
                ts.log('Saving file: %s' % dataset_filename)
                ds.to_csv(ts.result_file_path(dataset_filename))
                result_params['plot.title'] = dataset_filename.split('.csv')[0]
                ts.result_file(dataset_filename, params=result_params)
                result = script.RESULT_COMPLETE

    except script.ScriptFail as e:
        reason = str(e)
        if reason:
            ts.log_error(reason)

    finally:
        if daq is not None:
            daq.close()
        if pv is not None:
            if p_rated is not None:
                pv.power_set(p_rated)
            pv.close()
        if grid is not None:
            if v_nom is not None:
                grid.voltage(v_nom)
            grid.close()
        if chil is not None:
            chil.close()
        if eut is not None:
            eut.volt_var(params={'Ena': False})
            eut.volt_watt(params={'Ena': False})
            eut.close()
        if result_summary is not None:
            result_summary.close()

    return result
コード例 #9
0
ファイル: LAP.py プロジェクト: jayatsandia/svp_1547.1
def test_run():

    result = script.RESULT_FAIL
    grid = None
    pv = p_rated = None
    daq = None
    eut = None
    rs = None
    chil = None
    result_summary = None
    step = None
    q_initial = None
    dataset_filename = None
    fw_curves = []
    fw_response_time = [0, 0, 0]
    filename = None
    result_params = None

    try:
        cat = ts.param_value('eut.cat')
        cat2 = ts.param_value('eut.cat2')
        sink_power = ts.param_value('eut.sink_power')
        p_rated = ts.param_value('eut.p_rated')
        p_rated_prime = ts.param_value('eut.p_rated_prime')
        s_rated = ts.param_value('eut.s_rated')

        # DC voltages
        v_nom_in = ts.param_value('eut.v_in_nom')
        v_min_in = ts.param_value('eut.v_in_min')
        v_max_in = ts.param_value('eut.v_in_max')

        # AC voltages
        v_nom = ts.param_value('eut.v_nom')
        v_min = ts.param_value('eut.v_low')
        v_max = ts.param_value('eut.v_high')
        p_min = ts.param_value('eut.p_min')
        phases = ts.param_value('eut.phases')

        # EUI Absorb capabilities
        absorb = {}
        absorb['ena'] = ts.param_value('eut_vw.sink_power')
        absorb['p_rated_prime'] = ts.param_value('eut_vw.p_rated_prime')
        absorb['p_min_prime'] = ts.param_value('eut_vw.p_min_prime')

        # AC voltages
        f_nom = ts.param_value('eut.f_nom')
        f_min = ts.param_value('eut.f_min')
        f_max = ts.param_value('eut.f_max')
        p_min = ts.param_value('eut.p_min')
        phases = ts.param_value('eut.phases')
        # EUI FW parameters
        absorb_enable = ts.param_value('eut_fw.sink_power')
        p_rated_prime = ts.param_value('eut_fw.p_rated_prime')
        p_min_prime = ts.param_value('eut_fw.p_min_prime')
        p_small = ts.param_value('eut_fw.p_small')

        if ts.param_value('fw.test_1') == 'Enabled':
            fw_curves.append(1)
            fw_response_time[1] = float(ts.param_value('fw.test_1_tr'))
        if ts.param_value('fw.test_2') == 'Enabled':
            fw_curves.append(2)
            fw_response_time[2] = float(ts.param_value('fw.test_2_tr'))

        # VW parameters
        absorb = {}
        absorb['ena'] = ts.param_value('eut_vw.sink_power')
        """
        A separate module has been create for the 1547.1 Standard
        """
        ActiveFunction = p1547.ActiveFunction(ts=ts,
                                              functions=[LAP, FW, VW],
                                              script_name='Limit Active Power',
                                              criteria_mode=[True, True, True])
        ts.log_debug("1547.1 Library configured for %s" %
                     ActiveFunction.get_script_name())

        # result params
        result_params = ActiveFunction.get_rslt_param_plot()

        #  Set Test parameter
        act_pwrs = ts.param_value('lap.act_pwr')

        # List of power level for tests
        ts.log_debug('%s' % (act_pwrs))
        if act_pwrs == '0%':
            act_pwrs_limits = [0.0]
        elif act_pwrs == '33%':
            act_pwrs_limits = [0.33]
        elif act_pwrs == '66%':
            act_pwrs_limits = [0.66]
        else:
            act_pwrs_limits = [0.66, 0.33, 0.0]

        # 5.13.2 Procedure asks for three repetitions
        n_iters = list(range(1, int(ts.param_value('lap.iter')) + 1))

        # Take the highest value for the steady state wait time
        tr_min = min(ts.param_value('lap.test_vw_1_tr'),
                     ts.param_value('lap.test_fw_1_tr'))
        tr_vw = ts.param_value('lap.test_vw_1_tr')
        """
        a) - Connect the EUT according to the instructions and specifications provided by the manufacturer.
           - Apply the default settings from IEEE std 1547 for voltage-active power mode 
             (Minimum setting of table 10 of IEEE 1547)
           
           - Apply the default settings from frequency droop response in IEE std 1547 for abnormal operating perfomance
             category of the DER
           - Enable voltage active power mode
        """
        # initialize HIL environment, if necessary
        chil = hil.hil_init(ts)
        if chil is not None:
            chil.config()

        # grid simulator is initialized with test parameters and enabled
        grid = gridsim.gridsim_init(ts, support_interfaces={
            'hil': chil
        })  # Turn on AC so the EUT can be initialized
        if grid is not None:
            grid.voltage(v_nom)

        # pv simulator is initialized with test parameters and enabled
        pv = pvsim.pvsim_init(ts)
        if pv is not None:
            pv.power_set(p_rated)
            pv.power_on()  # Turn on DC so the EUT can be initialized

        # DAS soft channels
        das_points = ActiveFunction.get_sc_points()
        ts.log(das_points)
        # initialize data acquisition
        daq = das.das_init(ts,
                           sc_points=das_points['sc'],
                           support_interfaces={
                               'pvsim': pv,
                               'hil': chil
                           })

        if daq is not None:
            ts.log('DAS device: %s' % daq.info())

        eut = der.der_init(ts, support_interfaces={'hil': chil})
        if eut is not None:
            eut.config()
            # Enable volt/watt curve and configure default settings
            v_pairs = ActiveFunction.get_params(curve=1, function=VW)
            vw_curve_params = {
                'v': (round(v_pairs['V1'] / v_nom,
                            2), round(v_pairs['V2'] / v_nom, 2)),
                'w': (round(v_pairs['P1'] / p_rated,
                            2), round(v_pairs['P2'] / p_rated, 2)),
                'DeptRef':
                'W_MAX_PCT',
                'RmpTms':
                tr_vw
            }
            vw_params = {'Ena': True, 'ActCrv': 1, 'curve': vw_curve_params}
            eut.volt_watt(params=vw_params)
            # Enable freq/watt curve and configure default settings
            fw_curve_params = ActiveFunction.get_params(function=FW, curve=1)
            fw_params = {
                'Ena': True,
                'curve': 1,
                'dbf': fw_curve_params['dbf'],
                'kof': fw_curve_params['kof'],
                'RspTms': fw_curve_params['TR']
            }
            eut.freq_watt(fw_params)
            try:
                eut.vrt_stay_connected_high(
                    params={
                        'Ena': True,
                        'ActCrv': 0,
                        'Tms1': 3000,
                        'V1': v_max,
                        'Tms2': 0.16,
                        'V2': v_max
                    })
            except Exception as e:
                ts.log_error(
                    'Could not set VRT Stay Connected High curve. %s' % e)
            try:
                eut.frt_stay_connected_high(
                    params={
                        'Ena': True,
                        'ActCrv': 0,
                        'Tms1': 3000,
                        'Hz1': f_max,
                        'Tms2': 160,
                        'Hz2': f_max
                    })
            except Exception as e:
                ts.log_error(
                    'Could not set FRT Stay Connected High curve. %s' % e)
            try:
                eut.vrt_stay_connected_low(
                    params={
                        'Ena': True,
                        'ActCrv': 0,
                        'Tms1': 3000,
                        'V1': v_min,
                        'Tms2': 0.16,
                        'V2': v_min
                    })
            except Exception as e:
                ts.log_error('Could not set VRT Stay Connected Low curve. %s' %
                             e)
            try:
                eut.frt_stay_connected_low(
                    params={
                        'Ena': True,
                        'ActCrv': 0,
                        'Tms1': 3000,
                        'Hz1': f_min,
                        'Tms2': 160,
                        'Hz2': f_min
                    })
            except Exception as e:
                ts.log_error('Could not set FRT Stay Connected Low curve. %s' %
                             e)

            ts.log_debug(
                'If not done already, set L/HVRT and trip parameters to the widest range of adjustability.'
            )

        # Special considerations for CHIL ASGC/Typhoon startup #
        if chil is not None:
            if chil.hil_info()['mode'] == 'Typhoon':
                inv_power = eut.measurements().get('W')
                timeout = 120.
                if inv_power <= p_rated * 0.85:
                    pv.irradiance_set(
                        995)  # Perturb the pv slightly to start the inverter
                    ts.sleep(3)
                    eut.connect(params={'Conn': True})
                while inv_power <= p_rated * 0.85 and timeout >= 0:
                    ts.log(
                        'Inverter power is at %0.1f. Waiting up to %s more seconds or until EUT starts...'
                        % (inv_power, timeout))
                    ts.sleep(1)
                    timeout -= 1
                    inv_power = eut.measurements().get('W')
                    if timeout == 0:
                        result = script.RESULT_FAIL
                        raise der.DERError('Inverter did not start.')
                ts.log('Waiting for EUT to ramp up')
                ts.sleep(8)

        # Configure Grid simulator
        if grid is not None:
            grid.voltage(v_nom)

        # open result summary file
        result_summary_filename = 'result_summary.csv'
        result_summary = open(ts.result_file_path(result_summary_filename),
                              'a+')
        ts.result_file(result_summary_filename)
        result_summary.write(ActiveFunction.get_rslt_sum_col_name())
        """
        g) Repeat steps b) through f using active power limits of 33% and zero

        h) Repeat steps b) through g) twice for a total of three repetitions
        """
        if chil is not None:
            ts.log('Start simulation of CHIL')
            chil.start_simulation()

        for n_iter in n_iters:
            for act_pwrs_limit in act_pwrs_limits:
                """
                 b) - Establish nominal operating conditions as specified by the manufacturer at the terminals 
                      of the EUT.
                    - Make available sufficient input power for the EUT to reach its rated active power.
                    - Allow (or command) the EUT to reach steady-state output at its rated active power
                    - Begin recording EUT active power
                 """
                ts.log('Starting test no. %s with active power limit to %s ' %
                       (n_iter, act_pwrs_limit))
                ActiveFunction.reset_pwr(pwr=act_pwrs_limit)
                ActiveFunction.reset_time_settings(tr=tr_min)

                # For PV systems, this requires that Vmpp = Vin_nom and Pmpp = Prated.
                if pv is not None:
                    pv.iv_curve_config(pmp=p_rated, vmp=v_nom_in)
                    pv.irradiance_set(1000.)

                ts.log('EUT Config: setting Active Power Limit to 100%')
                if eut is not None:
                    # limit maximum power
                    eut.limit_max_power(
                        params={
                            'Ena': True,
                            'WMaxPct': 100,
                            'WinTms': 0,
                            'RmpTms': 0,
                            'RvrtTms': 0.0
                        })
                ts.sleep(2 * tr_min)
                daq.data_capture(True)
                filename = ('LAP_{0}_{1}'.format(act_pwrs_limit, n_iter))
                ActiveFunction.reset_filename(filename=filename)
                ts.log('------------{}------------'.format(filename))
                """
                c)  - Apply an active power limit to the EUT of 66% of its rated power.
                    - Wait until the EUT active power reaches a new steady state
                """
                # Setting up step label
                ActiveFunction.set_step_label(starting_label='C')
                step_label = ActiveFunction.get_step_label()
                daq.sc['event'] = step
                ActiveFunction.start(daq=daq, step_label=step_label)
                #initial_values = ActiveFunction.get_initial_value(daq=daq, step=step)
                ts.log('EUT Config: setting Active Power Limit to %s (%s)' %
                       (act_pwrs_limit, step))
                if eut is not None:
                    # limit maximum power
                    eut.limit_max_power(
                        params={
                            'MaxLimWEna': True,
                            'MaxLimW_PCT': act_pwrs_limit * 100,
                            'WinTms': 0,
                            'RmpTms': 0,
                            'RvrtTms': 0.0
                        })
                step_dict = {'V': v_nom, 'F': f_nom, 'P': act_pwrs_limit}
                #target_dict = {'P': act_pwrs_limit}
                ActiveFunction.record_timeresponse(daq=daq)
                ts.log_debug(f'daq={daq}')
                ActiveFunction.evaluate_criterias(daq=daq,
                                                  step_dict=step_dict,
                                                  y_criterias_mod={'P': LAP})
                result_summary.write(ActiveFunction.write_rslt_sum())
                """
                d)  - Reduce the frequency of the AC test to 59 Hz and hold until EUT active power reaches a new steady 
                      state
                    - Return AC test frequency to nominal and Hold until new states reached
                """
                f_steps = [59.0, f_nom]
                step_label = ActiveFunction.get_step_label()
                if grid is not None:
                    for f_step in f_steps:
                        step_ = step_label + "_" + str(f_step)
                        ts.log(
                            'Frequency step: setting Grid simulator frequency to %s (%s)'
                            % (f_step, step_))
                        ActiveFunction.start(daq=daq, step_label=step_)
                        #initial_values = ActiveFunction.get_initial_value(daq=daq,step=step_)
                        grid.freq(f_step)
                        step_dict = {
                            'V': v_nom,
                            'F': f_step,
                            'P': act_pwrs_limit
                        }
                        ActiveFunction.record_timeresponse(daq=daq)
                        ActiveFunction.evaluate_criterias(
                            daq=daq,
                            step_dict=step_dict,
                            y_criterias_mod={'P': FW})
                        result_summary.write(ActiveFunction.write_rslt_sum())
                """
                e)  - Increase the frequency of the AC test to 61 Hz and hold until EUT active power reaches a new steady 
                      state
                    - Return AC test frequency to nominal and Hold until new states reached
                """
                f_steps = [61.0, f_nom]
                step_label = ActiveFunction.get_step_label()
                if grid is not None:
                    for f_step in f_steps:
                        step_ = step_label + "_" + str(f_step)
                        ts.log(
                            'Frequency step: setting Grid simulator frequency to %s (%s)'
                            % (f_step, step_))
                        ActiveFunction.start(daq=daq, step_label=step_)
                        #initial_values = ActiveFunction.get_initial_value(daq=daq,step=step_)
                        grid.freq(f_step)
                        step_dict = {
                            'V': v_nom,
                            'F': f_step,
                            'P': act_pwrs_limit
                        }
                        ActiveFunction.record_timeresponse(daq=daq)
                        ActiveFunction.evaluate_criterias(
                            daq=daq,
                            step_dict=step_dict,
                            y_criterias_mod={'P': FW})
                        result_summary.write(ActiveFunction.write_rslt_sum())
                """
                f)  - Increase the voltage of the AC test to 1.08 times nominal and hold until EUT active power 
                      reaches a new steady state
                    - Return AC test voltage to nominal and Hold until new states reached
                """
                v_steps = [1.08 * v_nom, v_nom]
                step_label = ActiveFunction.get_step_label()
                if grid is not None:
                    for v_step in v_steps:
                        step_ = step_label + "_" + str(v_step)
                        ts.log(
                            'Voltage step: setting Grid simulator voltage to %s (%s)'
                            % (v_step, step_))
                        #initial_values = ActiveFunction.get_initial_value(daq=daq,step=step_)
                        ActiveFunction.start(daq=daq, step_label=step_)
                        grid.voltage(v_step)
                        step_dict = {
                            'V': v_step,
                            'F': f_nom,
                            'P': act_pwrs_limit
                        }
                        ActiveFunction.record_timeresponse(daq=daq)
                        ActiveFunction.evaluate_criterias(
                            daq=daq,
                            step_dict=step_dict,
                            y_criterias_mod={'P': VW})
                        result_summary.write(ActiveFunction.write_rslt_sum())

                ts.log('Sampling complete')
                dataset_filename = filename + ".csv"
                daq.data_capture(False)
                ds = daq.data_capture_dataset()
                ts.log('Saving file: %s' % dataset_filename)
                ds.to_csv(ts.result_file_path(dataset_filename))
                result_params['plot.title'] = dataset_filename.split('.csv')[0]
                ts.result_file(dataset_filename, params=result_params)
                result = script.RESULT_COMPLETE

    except script.ScriptFail as e:
        reason = str(e)
        if reason:
            ts.log_error(reason)

    except Exception as e:
        if dataset_filename is not None:
            dataset_filename = filename + ".csv"
            daq.data_capture(False)
            ds = daq.data_capture_dataset()
            ts.log('Saving file: %s' % dataset_filename)
            ds.to_csv(ts.result_file_path(dataset_filename))
            result_params['plot.title'] = dataset_filename.split('.csv')[0]
            ts.result_file(dataset_filename, params=result_params)
        ts.log_error('Test script exception: %s' % traceback.format_exc())

    finally:
        if grid is not None:
            grid.close()
        if pv is not None:
            if p_rated is not None:
                pv.power_set(p_rated)
            pv.close()
        if daq is not None:
            daq.close()
        if eut is not None:
            #eut.fixed_pf(params={'Ena': False, 'PF': 1.0})
            eut.close()
        if rs is not None:
            rs.close()
        if chil is not None:
            chil.close()

        if result_summary is not None:
            result_summary.close()

        # create result workbook
        excelfile = ts.config_name() + '.xlsx'
        rslt.result_workbook(excelfile, ts.results_dir(), ts.result_dir())
        ts.result_file(excelfile)

    return result
コード例 #10
0
ファイル: CRP.py プロジェクト: BuiMCanmet/svp_1547.1
def test_run():
    result = script.RESULT_FAIL
    grid = None
    pv = p_rated = None
    daq = None
    eut = None
    rs = None
    chil = None
    result_summary = None
    step_label = None
    q_initial = None
    dataset_filename = None

    try:

        cat = ts.param_value('eut.cat')
        cat2 = ts.param_value('eut.cat2')
        sink_power = ts.param_value('eut.sink_power')
        p_rated = ts.param_value('eut.p_rated')
        p_rated_prime = ts.param_value('eut.p_rated_prime')
        s_rated = ts.param_value('eut.s_rated')
        var_rated = ts.param_value('eut.var_rated')

        # DC voltages
        v_nom_in_enabled = ts.param_value('crp.v_in_nom')
        v_min_in_enabled = ts.param_value('crp.v_in_min')
        v_max_in_enabled = ts.param_value('crp.v_in_max')

        v_nom_in = ts.param_value('eut.v_in_nom')
        v_min_in = ts.param_value('eut_crp.v_in_min')
        v_max_in = ts.param_value('eut_crp.v_in_max')

        # AC voltages
        v_nom = ts.param_value('eut.v_nom')
        v_min = ts.param_value('eut.v_low')
        v_max = ts.param_value('eut.v_high')
        p_min = ts.param_value('eut.p_min')
        p_min_prime = ts.param_value('eut.p_min_prime')
        phases = ts.param_value('eut.phases')
        pf_response_time = ts.param_value('crp.pf_response_time')

        # Pass/fail accuracies
        pf_msa = ts.param_value('eut.pf_msa')

        # Imbalance configuration
        imbalance_fix = ts.param_value('crp.imbalance_fix')

        # EUI Absorb capabilities
        absorb = {}
        absorb['ena'] = ts.param_value('eut_crp.sink_power')
        absorb['p_rated_prime'] = ts.param_value('eut_crp.p_rated_prime')
        absorb['p_min_prime'] = ts.param_value('eut_crp.p_min_prime')
        """
        Version validation
        """
        p1547.VersionValidation(script_version=ts.info.version)
        """
        A separate module has been create for the 1547.1 Standard
        """
        ActiveFunction = p1547.ActiveFunction(
            ts=ts,
            functions='CRP',
            script_name='Constant Reactive Power',
            criteria_mode=[True, False, False])
        ActiveFunction.set_imbalance_config(imbalance_angle_fix=imbalance_fix)
        ts.log_debug("1547.1 Library configured for %s" %
                     ActiveFunction.get_script_name())

        # result params
        result_params = ActiveFunction.get_rslt_param_plot()

        #get target q relative value
        q_targets = {}

        if ts.param_value('crp.q_max_abs_enable') == 'Enabled':
            q_targets['crp_q_max_abs'] = float(
                ts.param_value('crp.q_max_abs_value'))
        if ts.param_value('crp.q_max_inj_enable') == 'Enabled':
            q_targets['crp_q_max_inj'] = float(
                ts.param_value('crp.q_max_inj_value'))
        if ts.param_value('crp.half_q_max_abs_enable') == 'Enabled':
            q_targets['crp_half_q_max_abs'] = 0.5 * float(
                ts.param_value('crp.q_max_abs_value'))
        if ts.param_value('crp.half_q_max_inj_enable') == 'Enabled':
            q_targets['crp_half_q_max_inj'] = 0.5 * float(
                ts.param_value('crp.q_max_inj_value'))

        #get q max value
        #q_max_value = ts.param_value('crp.q_max_value')

        v_in_targets = {}

        if v_nom_in_enabled == 'Enabled':
            v_in_targets['v_nom_in'] = v_nom_in
        if v_min_in != v_nom_in and v_min_in_enabled == 'Enabled':
            v_in_targets['v_min_in'] = v_min_in
        if v_max_in != v_nom_in and v_max_in_enabled == 'Enabled':
            v_in_targets['v_max_in'] = v_max_in
        if not v_in_targets:
            ts.log_error('No V_in target specify. Please select a V_IN test')
        """
        a) Connect the EUT according to the instructions and specifications provided by the manufacturer.
        """
        # initialize HIL environment, if necessary
        chil = hil.hil_init(ts)
        if chil is not None:
            chil.config()

        # grid simulator is initialized with test parameters and enabled
        grid = gridsim.gridsim_init(ts, support_interfaces={
            'hil': chil
        })  # Turn on AC so the EUT can be initialized
        if grid is not None:
            grid.voltage(v_nom)

        # pv simulator is initialized with test parameters and enabled
        pv = pvsim.pvsim_init(ts)
        if pv is not None:
            pv.power_set(p_rated)
            pv.power_on()  # Turn on DC so the EUT can be initialized

        # DAS soft channels
        #das_points = {'sc': ('V_MEAS', 'P_MEAS', 'Q_MEAS', 'Q_TARGET_MIN', 'Q_TARGET_MAX', 'PF_TARGET', 'event')}
        das_points = ActiveFunction.get_sc_points()

        # initialize data acquisition
        daq = das.das_init(ts, sc_points=das_points['sc'])

        if daq is not None:
            daq.sc['V_MEAS'] = 100
            daq.sc['P_MEAS'] = 100
            daq.sc['Q_MEAS'] = 100
            daq.sc['Q_TARGET_MIN'] = 100
            daq.sc['Q_TARGET_MAX'] = 100
            daq.sc['PF_TARGET'] = 1
            daq.sc['event'] = 'None'
            ts.log('DAS device: %s' % daq.info())
        """
        b) Set all voltage trip parameters to the widest range of adjustability. Disable all reactive/active power
        control functions.
        """
        # it is assumed the EUT is on
        eut = der.der_init(ts)
        if eut is not None:
            eut.config()
            # disable volt/var curve
            #eut.volt_var(params={'Ena': False})
            ts.log_debug(
                'If not done already, set L/HVRT and trip parameters to the widest range of adjustability.'
            )

        # Special considerations for CHIL ASGC/Typhoon startup #
        if chil is not None:
            inv_power = eut.measurements().get('W')
            timeout = 120.
            if inv_power <= p_rated * 0.85:
                pv.irradiance_set(
                    995)  # Perturb the pv slightly to start the inverter
                ts.sleep(3)
                eut.connect(params={'Conn': True})
            while inv_power <= p_rated * 0.85 and timeout >= 0:
                ts.log(
                    'Inverter power is at %0.1f. Waiting up to %s more seconds or until EUT starts...'
                    % (inv_power, timeout))
                ts.sleep(1)
                timeout -= 1
                inv_power = eut.measurements().get('W')
                if timeout == 0:
                    result = script.RESULT_FAIL
                    raise der.DERError('Inverter did not start.')
            ts.log('Waiting for EUT to ramp up')
            ts.sleep(8)
        """
        c) Set all AC test source parameters to the nominal operating voltage and frequency.
        """
        if grid is not None:
            grid.voltage(v_nom)

        # open result summary file
        result_summary_filename = 'result_summary.csv'
        result_summary = open(ts.result_file_path(result_summary_filename),
                              'a+')
        ts.result_file(result_summary_filename)
        result_summary.write(ActiveFunction.get_rslt_sum_col_name())
        """
        d) Adjust the EUT's available active power to Prated. For an EUT with an input voltage range, set the input
        voltage to Vin_nom. The EUT may limit active power throughout the test to meet reactive power requirements.

        s) For an EUT with an input voltage range, repeat steps d) through o) for Vin_min and Vin_max.
        """
        # TODO: Include step t)
        """
        t) Steps d) through q) may be repeated to test additional communication protocols - Run with another test.
        """

        # For PV systems, this requires that Vmpp = Vin_nom and Pmpp = Prated.
        for v_in_label, v_in in v_in_targets.items():
            ts.log('Starting test %s at v_in = %s' % (v_in_label, v_in))
            a_v = ActiveFunction.MRA['V'] * 1.5
            #Set response time recording
            ActiveFunction.reset_time_settings(tr=pf_response_time)

            if pv is not None:
                pv.iv_curve_config(pmp=p_rated, vmp=v_in)
                pv.irradiance_set(1000.)
            """
            e) Enable constant power factor mode and set the EUT power factor to PFmin,inj.
            r) Repeat steps d) through o) for additional power factor settings: PFmin,ab, PFmid,inj, PFmid,ab.

            Only the user-selected PF setting will be tested.
            """
            for q_test_name, q_target in q_targets.items():

                # Setting up step label
                ActiveFunction.set_step_label(starting_label='F')

                q_target *= var_rated

                ts.log('Starting data capture for fixed Q relative = %s' %
                       q_target)

                if imbalance_fix == "Yes":
                    dataset_filename = ('{0}_{1}_FIX'.format(
                        v_in_label.upper(), q_test_name.upper()))
                else:
                    dataset_filename = ('{0}_{1}'.format(
                        v_in_label.upper(), q_test_name.upper()))
                ts.log('------------{}------------'.format(dataset_filename))
                ActiveFunction.reset_filename(filename=dataset_filename)
                # Start the data acquisition systems
                daq.data_capture(True)

                daq.sc['Q_TARGET'] = q_target

                if eut is not None:
                    parameters = {'Ena': True, 'Q': q_target, 'Wmax': p_rated}
                    ts.log('Parameters set: %s' % parameters)
                    eut.reactive_power(params=parameters)
                    vars_setting = eut.reactive_power(params=parameters)
                    ts.log('fixed vars setting read: %s' % vars_setting)
                """
                f) Verify Constant Var mode is reported as active and that the power factor setting is reported 
                as Qmax,inj.

                """
                step_label = ActiveFunction.get_step_label()
                daq.sc['event'] = step_label
                daq.data_sample()
                ts.log('Wait for steady state to be reached')
                ts.sleep(2 * pf_response_time)
                """
                g) Step the EUT's active power to 20% of Prated or Pmin, whichever is less.
                """
                if pv is not None:
                    step_label = ActiveFunction.get_step_label()
                    ts.log(
                        'Power step: setting PV simulator power to %s (%s)' %
                        (p_min, step_label))
                    ActiveFunction.start(daq=daq, step_label=step_label)
                    if p_rated * 0.2 > p_min:
                        p_target = p_min
                    else:
                        p_target = p_rated * 0.2
                    step_dict = {
                        'V': v_nom,
                        'P': round(p_target, 2),
                        'Q': q_target
                    }
                    pv.power_set(step_dict['P'])
                    ActiveFunction.record_timeresponse(daq=daq)
                    ActiveFunction.evaluate_criterias(daq=daq,
                                                      step_dict=step_dict)
                    result_summary.write(ActiveFunction.write_rslt_sum())
                """
                h) Step the EUT's active power to 5% of Prated or Pmin, whichever is less.
                """
                if pv is not None:
                    step_label = ActiveFunction.get_step_label()
                    ts.log(
                        'Power step: setting PV simulator power to %s (%s)' %
                        (p_min, step_label))
                    ActiveFunction.start(daq=daq, step_label=step_label)
                    if p_rated * 0.05 > p_min:
                        p_target = p_min
                    else:
                        p_target = p_rated * 0.05
                    step_dict = {
                        'V': v_nom,
                        'P': round(p_target, 2),
                        'Q': q_target
                    }
                    pv.power_set(step_dict['P'])
                    ActiveFunction.record_timeresponse(daq=daq)
                    ActiveFunction.evaluate_criterias(daq=daq,
                                                      step_dict=step_dict)
                    result_summary.write(ActiveFunction.write_rslt_sum())
                """
                i) Step the EUT's available active power to Prated.
                """
                if pv is not None:
                    step_label = ActiveFunction.get_step_label()
                    ts.log(
                        'Power step: setting PV simulator power to %s (%s)' %
                        (p_rated, step_label))
                    ActiveFunction.start(daq=daq, step_label=step_label)
                    step_dict = {'V': v_nom, 'P': p_rated, 'Q': q_target}
                    pv.power_set(step_dict['P'])
                    ActiveFunction.record_timeresponse(daq=daq)
                    ActiveFunction.evaluate_criterias(daq=daq,
                                                      step_dict=step_dict)
                    result_summary.write(ActiveFunction.write_rslt_sum())

                if grid is not None:
                    #   J) Step the AC test source voltage to (VL + av)
                    step_label = ActiveFunction.get_step_label()
                    ts.log(
                        'Voltage step: setting Grid simulator voltage to %s (%s)'
                        % ((v_min + a_v), step_label))
                    ActiveFunction.start(daq=daq, step_label=step_label)
                    step_dict = {'V': v_min + a_v, 'P': p_rated, 'Q': q_target}
                    grid.voltage(step_dict['V'])
                    ActiveFunction.record_timeresponse(daq=daq)
                    ActiveFunction.evaluate_criterias(daq=daq,
                                                      step_dict=step_dict)
                    result_summary.write(ActiveFunction.write_rslt_sum())

                    #   k) Step the AC test source voltage to (VH - av)
                    step_label = ActiveFunction.get_step_label()
                    ts.log(
                        'Voltage step: setting Grid simulator voltage to %s (%s)'
                        % ((v_max - a_v), step_label))
                    ActiveFunction.start(daq=daq, step_label=step_label)
                    step_dict = {'V': v_max - a_v, 'P': p_rated, 'Q': q_target}
                    grid.voltage(step_dict['V'])
                    ActiveFunction.record_timeresponse(daq=daq)
                    ActiveFunction.evaluate_criterias(daq=daq,
                                                      step_dict=step_dict)
                    result_summary.write(ActiveFunction.write_rslt_sum())

                    #   l) Step the AC test source voltage to (VL + av)
                    step_label = ActiveFunction.get_step_label()
                    ts.log(
                        'Voltage step: setting Grid simulator voltage to %s (%s)'
                        % ((v_min + a_v), step_label))
                    ActiveFunction.start(daq=daq, step_label=step_label)
                    step_dict = {'V': v_min + a_v, 'P': p_rated, 'Q': q_target}
                    grid.voltage(step_dict['V'])
                    ActiveFunction.record_timeresponse(daq=daq)
                    ActiveFunction.evaluate_criterias(daq=daq,
                                                      step_dict=step_dict)
                    result_summary.write(ActiveFunction.write_rslt_sum())

                    if phases == 'Three phase':
                        #   m) For multiphase units, step the AC test source voltage to VN
                        step_label = ActiveFunction.get_step_label()
                        ts.log(
                            'Voltage step: setting Grid simulator voltage to %s (%s)'
                            % (v_nom, step_label))
                        ActiveFunction.start(daq=daq, step_label=step_label)
                        step_dict = {'V': v_nom, 'P': p_rated, 'Q': q_target}
                        grid.voltage(step_dict['V'])
                        ActiveFunction.record_timeresponse(daq=daq)
                        ActiveFunction.evaluate_criterias(daq=daq,
                                                          step_dict=step_dict)
                        result_summary.write(ActiveFunction.write_rslt_sum())
                    '''
                    n) For multiphase units, step the AC test source voltage to Case A from Table 24.
                    '''

                    if grid is not None and phases == 'Three phase':
                        step_label = ActiveFunction.get_step_label()
                        ts.log(
                            'Voltage step: setting Grid simulator to case A (IEEE 1547.1-Table 24)(%s)'
                            % step_label)
                        ActiveFunction.start(daq=daq, step_label=step_label)
                        v_target = ActiveFunction.set_grid_asymmetric(
                            grid=grid, case='case_a')
                        step_dict = {
                            'V': v_target,
                            'P': p_rated,
                            'Q': q_target
                        }
                        ActiveFunction.record_timeresponse(daq=daq)
                        ActiveFunction.evaluate_criterias(daq=daq,
                                                          step_dict=step_dict)
                        result_summary.write(ActiveFunction.write_rslt_sum())
                    """
                    o) For multiphase units, step the AC test source voltage to VN.
                    """

                    if grid is not None and phases == 'Three phase':
                        step_label = ActiveFunction.get_step_label()
                        ts.log(
                            'Voltage step: setting Grid simulator voltage to %s (%s)'
                            % (v_nom, step_label))
                        ActiveFunction.start(daq=daq, step_label=step_label)
                        step_dict = {'V': v_nom, 'P': p_rated, 'Q': q_target}
                        grid.voltage(step_dict['V'])
                        ActiveFunction.record_timeresponse(daq=daq)
                        ActiveFunction.evaluate_criterias(daq=daq,
                                                          step_dict=step_dict)
                        result_summary.write(ActiveFunction.write_rslt_sum())
                    """
                    p) For multiphase units, step the AC test source voltage to Case B from Table 24.
                    """
                    if grid is not None and phases == 'Three phase':
                        step_label = ActiveFunction.get_step_label()
                        ts.log(
                            'Voltage step: setting Grid simulator to case B (IEEE 1547.1-Table 24)(%s)'
                            % step_label)
                        ActiveFunction.start(daq=daq, step_label=step_label)
                        v_target = ActiveFunction.set_grid_asymmetric(
                            grid=grid, case='case_b')
                        step_dict = {
                            'V': v_target,
                            'P': p_rated,
                            'Q': q_target
                        }
                        ActiveFunction.record_timeresponse(daq=daq)
                        ActiveFunction.evaluate_criterias(daq=daq,
                                                          step_dict=step_dict)
                        result_summary.write(ActiveFunction.write_rslt_sum())
                    """
                    q) For multiphase units, step the AC test source voltage to VN
                    """
                    if grid is not None and phases == 'Three phase':
                        step_label = ActiveFunction.get_step_label()
                        ts.log(
                            'Voltage step: setting Grid simulator voltage to %s (%s)'
                            % (v_nom, step_label))
                        ActiveFunction.start(daq=daq, step_label=step_label)
                        step_dict = {'V': v_nom, 'P': p_rated, 'Q': q_target}
                        grid.voltage(step_dict['V'])
                        ActiveFunction.record_timeresponse(daq=daq)
                        ActiveFunction.evaluate_criterias(daq=daq,
                                                          step_dict=step_dict)
                        result_summary.write(ActiveFunction.write_rslt_sum())
                """
                r) Disable constant power factor mode. Power factor should return to unity.
                """
                if eut is not None:
                    parameters = {'Ena': False}
                    #ts.log('PF set: %s' % parameters)
                    eut.fixed_var(params=parameters)
                    var_setting = eut.fixed_var()
                    ts.log('Reactive Power setting read: %s' % vars_setting)
                    daq.sc['event'] = ActiveFunction.get_step_label()
                    daq.data_sample()
                    ts.sleep(4 * pf_response_time)
                    daq.sc['event'] = 'T_settling_done'
                    daq.data_sample()
                """
                q) Verify all reactive/active power control functions are disabled.
                """
                if eut is not None:
                    ts.log(
                        'Reactive/active power control functions are disabled.'
                    )
                    # TODO Implement ts.prompt functionality?
                    # meas = eut.measurements()
                    # ts.log('EUT PF is now: %s' % (data.get('AC_PF_1')))
                    # ts.log('EUT Power: %s, EUT Reactive Power: %s' % (meas['W'], meas['VAr']))

                ts.log('Sampling complete')
                dataset_filename = dataset_filename + ".csv"
                daq.data_capture(False)
                ds = daq.data_capture_dataset()
                ts.log('Saving file: %s' % dataset_filename)
                ds.to_csv(ts.result_file_path(dataset_filename))
                result_params['plot.title'] = dataset_filename.split('.csv')[0]
                ts.result_file(dataset_filename, params=result_params)
                result = script.RESULT_COMPLETE

    except script.ScriptFail as e:
        reason = str(e)
        if reason:
            ts.log_error(reason)

    except Exception as e:
        if dataset_filename is not None:
            dataset_filename = dataset_filename + ".csv"
            daq.data_capture(False)
            ds = daq.data_capture_dataset()
            ts.log('Saving file: %s' % dataset_filename)
            ds.to_csv(ts.result_file_path(dataset_filename))
            result_params['plot.title'] = dataset_filename.split('.csv')[0]
            ts.result_file(dataset_filename, params=result_params)
        ts.log_error('Test script exception: %s' % traceback.format_exc())

    finally:

        if grid is not None:
            grid.close()
        if pv is not None:
            if p_rated is not None:
                pv.power_set(p_rated)
            pv.close()
        if daq is not None:
            daq.close()
        if eut is not None:
            #eut.reactive_power(params={'Ena': False})
            eut.close()
        if rs is not None:
            rs.close()
        if chil is not None:
            chil.close()

        if result_summary is not None:
            result_summary.close()

        # create result workbook
        excelfile = ts.config_name() + '.xlsx'
        rslt.result_workbook(excelfile, ts.results_dir(), ts.result_dir())
        ts.result_file(excelfile)

    return result
コード例 #11
0
def test_run():

    result = script.RESULT_FAIL
    grid = None
    pv = p_rated = None
    daq = None
    eut = None
    rs = None
    chil = None
    result_summary = None
    step = None
    q_initial = None
    dataset_filename = None


    try:
        cat = ts.param_value('eut.cat')
        cat2 = ts.param_value('eut.cat2')
        sink_power = ts.param_value('eut.sink_power')
        p_rated = ts.param_value('eut.p_rated')
        p_rated_prime = ts.param_value('eut.p_rated_prime')
        s_rated = ts.param_value('eut.s_rated')
        var_rated = ts.param_value('eut.var_rated')

        # DC voltages
        v_nom_in_enabled = ts.param_value('cpf.v_in_nom')
        v_min_in_enabled = ts.param_value('cpf.v_in_min')
        v_max_in_enabled = ts.param_value('cpf.v_in_max')

        v_nom_in = ts.param_value('eut.v_in_nom')
        v_min_in = ts.param_value('eut_cpf.v_in_min')
        v_max_in = ts.param_value('eut_cpf.v_in_max')

        # AC voltages
        v_nom = ts.param_value('eut.v_nom')
        v_min = ts.param_value('eut.v_low')
        v_max = ts.param_value('eut.v_high')
        p_min = ts.param_value('eut.p_min')
        p_min_prime = ts.param_value('eut.p_min_prime')
        phases = ts.param_value('eut.phases')
        pri_response_time = ts.param_value('pri.pri_response_time')

        #Reactive power
        vv_status = ts.param_value('pri.vv_status')
        crp_status = ts.param_value('pri.crp_status')
        cpf_status = ts.param_value('pri.cpf_status')
        wv_status = ts.param_value('pri.wv_status')

        # Pass/fail accuracies
        pf_msa = ts.param_value('eut.pf_msa')

        # Imbalance configuration
        imbalance_fix = ts.param_value('cpf.imbalance_fix')

        # EUI Absorb capabilities
        absorb = {}
        absorb['ena'] = ts.param_value('eut_cpf.sink_power')
        absorb['p_rated_prime'] = ts.param_value('eut_cpf.p_rated_prime')
        absorb['p_min_prime'] = ts.param_value('eut_cpf.p_min_prime')

        #Functions to be enabled for test
        mode = []
        if vv_status == 'Enabled':
            mode.append(VV)
        if crp_status == 'Enabled':
            mode.append(CRP)
        if cpf_status == 'Enabled':
            mode.append(CPF)
        if wv_status == 'Enabled':
            mode.append(WV)
        """
        Version validation
        """
        p1547.VersionValidation(script_version=ts.info.version)
        """
        A separate module has been create for the 1547.1 Standard
        """
        ActiveFunction = p1547.ActiveFunction(ts=ts,
                                              functions=[PRI, VW, FW, VV, CPF, CRP, WV],
                                              script_name='Prioritization',
                                              criteria_mode=[False, False, True])
        ts.log_debug("1547.1 Library configured for %s" % ActiveFunction.get_script_name())

        # result params
        result_params = ActiveFunction.get_rslt_param_plot()
        ts.log(result_params)

        """
        a) Connect the EUT according to the instructions and specifications provided by the manufacturer.
        """
        # initialize HIL environment, if necessary
        chil = hil.hil_init(ts)
        if chil is not None:
            chil.config()

        # grid simulator is initialized with test parameters and enabled
        grid = gridsim.gridsim_init(ts, support_interfaces={'hil': chil})  # Turn on AC so the EUT can be initialized
        if grid is not None:
            grid.voltage(v_nom)

        # pv simulator is initialized with test parameters and enabled
        pv = pvsim.pvsim_init(ts)
        if pv is not None:
            pv.power_set(p_rated)
            pv.power_on()  # Turn on DC so the EUT can be initialized
            ts.sleep(0.5)

        # DAS soft channels
        das_points = ActiveFunction.get_sc_points()

        # initialize data acquisition
        daq = das.das_init(ts, sc_points=das_points['sc'], support_interfaces={'pvsim': pv, 'hil': chil})

        if daq is not None:
            daq.sc['V_MEAS'] = 100
            daq.sc['P_MEAS'] = 100
            daq.sc['Q_MEAS'] = 100
            daq.sc['Q_TARGET_MIN'] = 100
            daq.sc['Q_TARGET_MAX'] = 100
            daq.sc['PF_TARGET'] = 1
            daq.sc['event'] = 'None'
            ts.log('DAS device: %s' % daq.info())

        """
        b) Set all voltage trip parameters to the widest range of adjustability. Disable all reactive/active power
        control functions.
        """
        # it is assumed the EUT is on
        eut = der.der_init(ts)
        if eut is not None:
            eut.config()

            eut.deactivate_all_fct()
            ts.log_debug('If not done already, set L/HVRT and trip parameters to the widest range of adjustability.')

        """
        c) Set all AC test source parameters to the nominal operating voltage and frequency.
        """
        if grid is not None:
            grid.voltage(v_nom)

        # open result summary file
        result_summary_filename = 'result_summary.csv'
        result_summary = open(ts.result_file_path(result_summary_filename), 'a+')
        ts.result_file(result_summary_filename)
        result_summary.write(ActiveFunction.get_rslt_sum_col_name())

        """
        d) Adjust the EUT's available active power to Prated. For an EUT with an input voltage range, set the input
        voltage to Vin_nom. The EUT may limit active power throughout the test to meet reactive power requirements.
        """

        if pv is not None:
            pv.iv_curve_config(pmp=p_rated, vmp=v_nom_in)
            pv.irradiance_set(1000.)

        """
        e) Set EUT frequency-watt and volt-watt parameters to the default values for the EUTs category, and
        enable frequency-watt and volt-watt parameters. For volt-watt, set P2 = 0.2Prated.
        """

        default_curve = 1

        if eut is not None:
            fw_settings = ActiveFunction.get_params(function=FW)
            fw_curve_params = {
                'Ena': True,
                'curve': default_curve,
                'dbf': fw_settings[default_curve]['dbf'],
                'kof': fw_settings[default_curve]['kof'],
                'RspTms': fw_settings[default_curve]['tr']
            }
            ts.log_debug('Sending FW points: %s' % fw_curve_params)
            fw_current_settings = eut.freq_watt(fw_curve_params)

            vw_settings = ActiveFunction.get_params(aif=VW)
            #P2 require 0.2*p_rated value for VW function
            vw_settings['P2'] = 0.2*p_rated
            vw_curve_params = {'v': [int(vw_settings[default_curve]['V1'] * (100. / v_nom)),
                                     int(vw_settings[default_curve]['V2'] * (100. / v_nom))],
                               'w': [int(vw_settings[default_curve]['P1'] * (100. / p_rated)),
                                     int(vw_settings[default_curve]['P2'] * (100. / p_rated))],
                               'DeptRef': 'W_MAX_PCT',
                               'RmpPtTms': 10.0}
            vw_params = {'Ena': True, 'ActCrv': 1, 'curve': vw_curve_params}
            ts.log_debug('Sending VW points: %s' % vw_curve_params)
            eut.volt_watt(params=vw_params)
            #ts.log_debug('Initial EUT VW settings are %s' % eut.volt_watt())
            ts.log_debug('curve points:  %s' % vw_settings)

            """
            h) Set the EUTs active power limit signal to 50% of Prated.
            """
            ts.sleep(4*pri_response_time)

            # limit maximum power
            eut.limit_max_power(params={'Ena': True,
                                        'WMaxPct': 50,
                                        'WinTms': 0,
                                        'RmpTms': 0,
                                        'RvrtTms': 0.0})

        for current_mode in mode:
            ts.log_debug('Starting mode = %s' % current_mode)
            ActiveFunction.reset_curve(curve=default_curve)
            ActiveFunction.reset_time_settings(tr=pri_response_time)
            if current_mode == VV:
                """
                f) Set EUT volt-var parameters to the default values for the EUTs category and enable volt-var
                mode
                """
                if eut is not None:
                    vv_settings = ActiveFunction.get_params(aif=VV)
                    #ts.log_debug('Sending VV points: %s' % vv_settings)
                    vv_curve_params = {'v': [vv_settings[default_curve]['V1'] * (100 / v_nom),
                                             vv_settings[default_curve]['V2'] * (100 / v_nom),
                                             vv_settings[default_curve]['V3'] * (100 / v_nom),
                                             vv_settings[default_curve]['V4'] * (100 / v_nom)],
                                       'q': [vv_settings[default_curve]['Q1'] * (100 / var_rated),
                                             vv_settings[default_curve]['Q2'] * (100 / var_rated),
                                             vv_settings[default_curve]['Q3'] * (100 / var_rated),
                                             vv_settings[default_curve]['Q4'] * (100 / var_rated)],
                                       'DeptRef': 'Q_MAX_PCT',
                                       'RmpPtTms': 10.0}
                    ts.log_debug('Sending VV points: %s' % vv_curve_params)
                    eut.volt_var(params={'Ena': True, 'curve': vv_curve_params})

            elif current_mode == CRP:
                """
                q) Set EUT watt-var parameters to the default values for the EUTs category. Disable the present
                mode of reactive power control and enable watt-var mode. Repeat steps g) through n).
                """
                if eut is not None:
                    parameters = {'Ena': True, 'Q': var_rated, 'Wmax': p_rated}
                    ts.log('Parameters set: %s' % parameters)
                    eut.reactive_power(params=parameters)
                    vars_setting = eut.reactive_power(params=parameters)
                    ts.log('fixed vars setting read: %s' % vars_setting)

            elif current_mode == CPF:
                """
                p) Set the constant power factor function to PFmax,ing. Disable the present mode of reactive power
                control and enable power factor mode. Repeat steps g) through n).
                """
                if eut is not None:
                    parameters = {'Ena': True, 'PF': 0.9}
                    ts.log('PF set: %s' % parameters)

                    pf_setting = eut.fixed_pf(params=parameters)
                    ts.log('PF setting read: %s' % pf_setting)

            elif current_mode == WV:
                """
                q) Set EUT watt-var parameters to the default values for the EUTs category. Disable the present
                mode of reactive power control and enable watt-var mode. Repeat steps g) through n).
                """
                if eut is not None:
                    wv_settings = ActiveFunction.get_params(aif=WV)[default_curve]
                    ts.log('WV setting: %s' % wv_settings)
                    # Activate watt-var function with following parameters
                    # SunSpec convention is to use percentages for P and Q points.
                    wv_curve_params = {'w': [wv_settings['P0'] * (100 / p_rated),
                                             wv_settings['P1'] * (100 / p_rated),
                                             wv_settings['P2'] * (100 / p_rated),
                                             wv_settings['P3'] * (100 / p_rated)],
                                       'var': [wv_settings['Q0'] * (100 / var_rated),
                                               wv_settings['Q1'] * (100 / var_rated),
                                               wv_settings['Q2'] * (100 / var_rated),
                                               wv_settings['Q3'] * (100 / var_rated)]}
                    ts.log_debug('Sending WV points: %s' % wv_curve_params)
                    eut.watt_var(params={'Ena': True, 'curve': wv_curve_params})

            """
            g) Allow the EUT to reach steady state. Measure AC test source voltage and frequency and the EUTs
            active and reactive power production.
            """

            daq.data_capture(True)
            dataset_filename = 'PRI_{}'.format(current_mode)
            ts.log('------------{}------------'.format(dataset_filename))
            ActiveFunction.reset_filename(filename=dataset_filename)

            """
            i) Allow the EUT to reach steady state.
            """
            ts.sleep(2*pri_response_time)
            """
            j) Measure AC test source voltage and frequency, and the EUTs active and reactive power
            production.
            """

            """
            k) Set the AC test source voltage and frequency to the values in step 1 of Table 38 or Table 39,
            depending on the EUTs normal operating performance category.
     
            l) Allow the EUT to reach steady state.
    
            m) Measure AC test source voltage and frequency, and the EUTs active and reactive power
            production.
     
            n) Repeat steps k) through m) for the rest of the steps in Table 38 or Table 39, depending on the
            EUTs normal operating performance category
            """
            """
            steps_dicts = [{'V': 1.00, 'F': 60.00},
                          {'V': 1.09, 'F': 60.00},
                          {'V': 1.09, 'F': 60.33},
                          {'V': 1.09, 'F': 60.00},
                          {'V': 1.09, 'F': 59.36},
                          {'V': 1.00, 'F': 59.36},
                          {'V': 1.00, 'F': 60.00},
                          {'V': 1.00, 'F': 59.36}]
            """
            '''
            target_dict = [{'P': 0.5*p_rated, VV: 0.00*var_rated, CRP: 0.44, CPF: 0.9, WV: 0},
                           {'P': 0.4*p_rated, VV: -0.25*var_rated, CRP: 0.44, CPF: 0.9, WV: 0},
                           {'P': 0.3*p_rated, VV: -0.25*var_rated, CRP: 0.44, CPF: 0.9, WV: 0},
                           {'P': 0.4*p_rated, VV: -0.25*var_rated, CRP: 0.44, CPF: 0.9, WV: 0},
                           {'P': 0.4*p_rated, VV: -0.25*var_rated, CRP: 0.44, CPF: 0.9, WV: 0},
                           {'P': 0.6*p_rated, VV: 0.00*var_rated, CRP: 0.44, CPF: 0.9, WV: 0.05},
                           {'P': 0.5*p_rated, VV: 0.00*var_rated, CRP: 0.44, CPF: 0.9, WV: 0},
                           {'P': 0.7*p_rated, VV: 0.00*var_rated, CRP: 0.44, CPF: 0.9, WV: 0.10}]
            '''
            step_dicts = ActiveFunction.create_pri_dict_steps(function=current_mode)
            ts.log('step_dicts: %s' % (step_dicts))

            i = 0

            for step_dict in step_dicts:
                step_label = 'Step_%i_%s' % (i+1, current_mode)

                ts.log('Voltage step: setting Grid simulator voltage to %s (%s)' % (step_dict['V'], step_label))
                ts.log('Frequency step: setting Grid simulator frequency to %s (%s)' % (step_dict['F'], step_label))
                ts.log('Steps: %s (%s)' % (step_dict, step_label))


                ActiveFunction.start(daq=daq, step_label=step_label)
                if grid is not None:
                    grid.freq(step_dict['F'])
                    grid.voltage(step_dict['V'])

                ts.log_debug('current mode %s' % current_mode)
                ActiveFunction.record_timeresponse(daq=daq)
                ActiveFunction.evaluate_criterias(daq=daq, step_dict=step_dict, y_criterias_mod={'Q': current_mode})
                result_summary.write(ActiveFunction.write_rslt_sum())
                i += 1

            if eut is not None:
                if current_mode == VV:
                    eut.volt_var(params={'Ena': False})
                elif current_mode == CPF:
                    eut.fixed_pf(params={'Ena': False})
                elif current_mode == CRP:
                    eut.reactive_power(params={'Ena': False})
                elif current_mode == WV:
                    eut.watt_var(params={'Ena': False})

            ts.log('Sampling complete')
            dataset_filename = dataset_filename + ".csv"
            daq.data_capture(False)
            ds = daq.data_capture_dataset()
            ts.log('Saving file: %s' % dataset_filename)
            ds.to_csv(ts.result_file_path(dataset_filename))
            result_params['plot.title'] = dataset_filename.split('.csv')[0]
            ts.result_file(dataset_filename, params=result_params)
            result = script.RESULT_COMPLETE

    except script.ScriptFail as e:
        reason = str(e)
        if reason:
            ts.log_error(reason)

    except Exception as e:
        ts.log_error((e, traceback.format_exc()))
        if dataset_filename is not None:
            dataset_filename = dataset_filename + ".csv"
            daq.data_capture(False)
            ds = daq.data_capture_dataset()
            ts.log('Saving file: %s' % dataset_filename)
            ds.to_csv(ts.result_file_path(dataset_filename))
            result_params['plot.title'] = dataset_filename.split('.csv')[0]
            ts.result_file(dataset_filename, params=result_params)
        ts.log_error('Test script exception: %s' % traceback.format_exc())

    finally:
        if grid is not None:
            grid.close()
        if pv is not None:
            if p_rated is not None:
                pv.power_set(p_rated)
            pv.close()
        if daq is not None:
            daq.close()
        if eut is not None:
            # eut.fixed_pf(params={'Ena': False, 'PF': 1.0})
            eut.close()
        if rs is not None:
            rs.close()
        if chil is not None:
            chil.close()

        if result_summary is not None:
            result_summary.close()

        # create result workbook
        excelfile = ts.config_name() + '.xlsx'
        rslt.result_workbook(excelfile, ts.results_dir(), ts.result_dir())
        ts.result_file(excelfile)

    return result