def test_run():

    result = script.RESULT_FAIL
    daq = None

    try:
        # initialize data acquisition system
        ts.log('result_id = %s' % (ts.result_id()))
        ts.log('result_dir = %s' % (ts.result_dir()))

        grid = gridsim.gridsim_init(ts)
        pv = pvsim.pvsim_init(ts)
        daq = das.das_init(ts)

        pv.irradiance_set(ts.param_value('profile.irr_start'))
        # pv.profile_load(ts.param_value('profile.profile_name'))
        # pv.profile_start()
        pv.power_on()

        ts.log('Running capture 2')
        daq.data_capture_start()
        ts.sleep(8)
        daq.data_capture_stop()
        ds = daq.data_capture_dataset()
        ds.to_csv(ts.result_file('capture_2.csv'))

        result = script.RESULT_COMPLETE

    except script.ScriptFail, e:
        reason = str(e)
        if reason:
            ts.log_error(reason)
def test_run():

    result = script.RESULT_FAIL
    daq = None

    try:
        # initialize data acquisition system
        ts.log('result_id = %s' % (ts.result_id()))
        ts.log('result_dir = %s' % (ts.result_dir()))

        grid = gridsim.gridsim_init(ts)
        pv = pvsim.pvsim_init(ts)
        daq = das.das_init(ts)

        pv.irradiance_set(ts.param_value('profile.irr_start'))
        # pv.profile_load(ts.param_value('profile.profile_name'))
        # pv.profile_start()
        pv.power_on()

        ts.log('Running capture 2')
        daq.data_capture_start()
        ts.sleep(8)
        daq.data_capture_stop()
        ds = daq.data_capture_dataset()
        ds.to_csv(ts.result_file('capture_2.csv'))

        result = script.RESULT_COMPLETE

    except script.ScriptFail, e:
        reason = str(e)
        if reason:
            ts.log_error(reason)
Esempio n. 3
0
def test_run():

    result = script.RESULT_PASS

    # initialize pv simulation
    pv = pvsim.pvsim_init(ts)
    pv.irradiance_set(ts.param_value('profile.irr_start'))
    pv.profile_load(ts.param_value('profile.profile_name'))
    pv.power_on()

    if ts.param_value('profile.run_profile') == 'Yes':
        pv.profile_start()

    return result
Esempio n. 4
0
def test_run():

    result = script.RESULT_FAIL
    data = None
    trigger = None
    inv = None
    pv = None
    disable = None

    try:
        ifc_type = ts.param_value('comm.ifc_type')
        ifc_name = ts.param_value('comm.ifc_name')
        if ifc_type == client.MAPPED:
            ifc_name = ts.param_value('comm.map_name')
        baudrate = ts.param_value('comm.baudrate')
        parity = ts.param_value('comm.parity')
        ipaddr = ts.param_value('comm.ipaddr')
        ipport = ts.param_value('comm.ipport')
        slave_id = ts.param_value('comm.slave_id')

        power_limit_pct = ts.param_value('inv2.power_limit_pct')
        ramp_time = ts.param_value('inv2.ramp_time')  # slope defined by % nameplate power/sec
        time_window = ts.param_value('inv2.time_window')
        timeout_period = ts.param_value('inv2.timeout_period')

        pretest_delay = ts.param_value('invt.pretest_delay')
        power_limit_pct_buffer = ts.param_value('invt.power_limit_pct_buffer')
        screening_period = ts.param_value('invt.screening_period')
        setpoint_failure_count = ts.param_value('invt.setpoint_failure_count')
        verification_delay = ts.param_value('invt.verification_delay')
        posttest_delay = ts.param_value('invt.posttest_delay')
        disable = ts.param_value('invt.disable')

        # initialize data acquisition system
        daq = das.das_init(ts)
        data = daq.data_init()
        trigger = daq.trigger_init()

        # initialize pv simulation
        pv = pvsim.pvsim_init(ts)
        pv.irradiance_set(ts.param_value('profile.irr_start'))
        pv.profile_load(ts.param_value('profile.profile_name'))
        pv.power_on()

        # Sandia Test Protocol: Communication is established between the Utility Management System Simulator
        # and EUT
        ts.log('Scanning EUT')
        try:
            inv = client.SunSpecClientDevice(ifc_type, slave_id=slave_id, name=ifc_name, baudrate=baudrate,
                                             parity=parity, ipaddr=ipaddr, ipport=ipport)
        except Exception, e:
            raise script.ScriptFail('Error: %s' % (e))

        if pretest_delay > 0:
            ts.log('Waiting for pre-test delay of %d seconds' % pretest_delay)
            ts.sleep(pretest_delay)

        # Make sure the EUT is on and operating
        ts.log('Verifying EUT is in connected state. Waiting up to %d seconds for EUT to begin power export.'
               % (verification_delay+pretest_delay))
        if verify_initial_conn_state(inv, state=inverter.CONN_CONNECT,
                                     time_period=verification_delay+pretest_delay, data=data) is False:
                ts.log_error('Inverter unable to be set to connected state.')
                raise script.ScriptFail()

        # Sandia Test Protocol Step 1: Request status of EUT
        # Sandia Test Protocol Step 2: UMS receives response from EUT
        try:
            inv.settings.read()
            power_max = int(inv.settings.WMax)
            ts.log('Inverter maximum power = %d W' % (power_max))
        except Exception, e:
            raise('Unable to get WMax setting: %s' % str(e))
Esempio n. 5
0
def test_run():

    result = script.RESULT_FAIL
    data = None
    trigger = None
    inv = None
    pv = None
    disable = None

    try:
        # EUT communication parameters
        ifc_type = ts.param_value('comm.ifc_type')
        ifc_name = ts.param_value('comm.ifc_name')
        if ifc_type == client.MAPPED:
            ifc_name = ts.param_value('comm.map_name')
        baudrate = ts.param_value('comm.baudrate')
        parity = ts.param_value('comm.parity')
        ipaddr = ts.param_value('comm.ipaddr')
        ipport = ts.param_value('comm.ipport')
        slave_id = ts.param_value('comm.slave_id')

        # INV1 parameters
        operation = ts.param_value('inv1.operation')
        time_window = ts.param_value('inv1.time_window')
        timeout_period = ts.param_value('inv1.timeout_period')

        # Script timing and pass/fail criteria
        pretest_delay = ts.param_value('invt.pretest_delay')
        verification_delay = ts.param_value('invt.verification_delay')
        posttest_delay = ts.param_value('invt.posttest_delay')
        power_threshold = ts.param_value('invt.power_threshold')
        disable = ts.param_value('invt.disable')

        # initialize data acquisition system
        daq = das.das_init(ts)
        data = daq.data_init()
        trigger = daq.trigger_init()

        # initialize pv simulation
        pv = pvsim.pvsim_init(ts)
        pv.power_on()

        # It is assumed that the PV and Grid Simulators (if used) are connected to the EUT and operating properly
        # prior to running this test script.
        if pretest_delay > 0:
            ts.log('Waiting for pre-test delay of %d seconds' % pretest_delay)
            ts.sleep(pretest_delay)

        # Sandia Test Protocol: Communication is established between the Utility Management System Simulator and EUT
        ts.log('Scanning EUT')
        try:
            inv = client.SunSpecClientDevice(ifc_type, slave_id=slave_id, name=ifc_name, baudrate=baudrate,
                                             parity=parity, ipaddr=ipaddr, ipport=ipport)
        except Exception, e:
            raise script.ScriptFail('Error: %s' % e)

        # Define operation states (connected/disconnected)
        # Default state is required for timeout_periods because the EUT will return to that mode of operation
        default_state = inverter.CONN_CONNECT
        if operation == 'Connect':
            orig_state = inverter.CONN_DISCONNECT
            state = inverter.CONN_CONNECT
        elif operation == 'Disconnect':
            orig_state = inverter.CONN_CONNECT
            state = inverter.CONN_DISCONNECT
        else:
            ts.log('Unknown operation requested: %s' % operation)
            raise script.ScriptFail()

        # Sandia Test Protocol Step 1: Request Status of EUT.
        # Sandia Test Protocol Step 2: UMS receives response to the DS93 command.
        # Verify EUT is in correct state before running the test.
        if inverter.verify_conn_state(inv, orig_state, threshold=power_threshold, das=data) is False:
            # todo: update inverter module with das changed to data
            ts.log('Inverter not in correct state, setting state to: %s' %
                   (inverter.conn_state_str(orig_state)))
            # EUT put into state where INV1 can be verified
            inverter.set_conn_state(inv, orig_state)
            if verify_conn_state_change(inv, orig_state, verification_delay=verification_delay,
                                        threshold=power_threshold, data=data) is False:
                raise script.ScriptFail()

        # Sandia Test Protocol Step 3: Inverter output is measured and logged.
        log_conn_state(inv, data=data)

        # Sandia Test Protocol Step 4: UMS issues the INV1 command.
        ts.log('Executing %s' % operation)
        inverter.set_conn_state(inv, state, time_window=time_window, timeout_period=timeout_period, trigger=trigger)

        # Sandia Test Protocol Step 5: Verify the INV1 command was successfully executed.
        if verify_conn_state_change(inv, state, time_window=time_window, verification_delay=verification_delay,
                                    threshold=power_threshold, data=data) is False:
            raise script.ScriptFail()

        # Verify revert (timeout) to default state if timeout period specified
        if timeout_period > 0:

             if verify_conn_state_change(inv, default_state, timeout_period=timeout_period,
                                         verification_delay=verification_delay,
                                         threshold=power_threshold, data=data) is False:
                raise script.ScriptFail()

        if posttest_delay > 0:
             ts.log('Waiting for post-test delay of %d seconds' % posttest_delay)
             ts.sleep(posttest_delay)

        result = script.RESULT_PASS
Esempio n. 6
0
def test_run():

    result = script.RESULT_FAIL
    daq = None
    pv = None
    grid = None

    try:
        # read test parameters
        tests_param = ts.param_value('general.tests')

        s_rated = ts.param_value('ratings.s_rated')
        p_rated = ts.param_value('ratings.p_rated')
        v_dc_min = ts.param_value('ratings.v_dc_min')  ##
        v_dc_max = ts.param_value('ratings.v_dc_max')  ##
        v_nom = ts.param_value('ratings.v_nom')
        v_min = ts.param_value('ratings.v_min')
        v_max = ts.param_value('ratings.v_max')
        #v_msa = ts.param_value('ratings.v_msa')
        var_msa = ts.param_value('ratings.var_msa')
        var_ramp_max = ts.param_value('ratings.var_ramp_max')
        q_max_cap = ts.param_value('ratings.q_max_cap')
        q_max_ind = ts.param_value('ratings.q_max_ind')
        k_var_max = ts.param_value('ratings.k_var_max')
        deadband_min = ts.param_value('ratings.deadband_min')
        deadband_max = ts.param_value('ratings.deadband_max')
        t_settling = ts.param_value('ratings.t_settling')
        power_priority = ts.param_value('ratings.power_priority')

        p_min_pct = ts.param_value('srd.p_min_pct')
        p_max_pct = ts.param_value('srd.p_max_pct')
        k_var_min_srd = ts.param_value('srd.k_var_min')
        try:
            k_var_min = float(k_var_min_srd)
        except ValueError:
            k_var_min = None
        segment_point_count = ts.param_value('srd.segment_point_count')

        # set power priorities to be tested
        if power_priority == 'Both':
            power_priorities = ['Active', 'Reactive']
        else:
            power_priorities = [power_priority]

        # default power range
        p_min = p_rated * .2
        p_max = p_rated

        # use values from SRD, if supplied
        if p_min_pct is not None:
            p_min = p_rated * (p_min_pct / 100.)
        if p_max is not None:
            p_max = p_rated * (p_max_pct / 100.)
        p_avg = (p_min + p_max) / 2

        q_min_cap = q_max_cap / 4
        q_min_ind = q_max_ind / 4
        v_dev = min(v_nom - v_min, v_max - v_nom)
        # calculate k_var_min if not suppied in the SRD
        if k_var_min is None:
            k_var_min = (q_max_cap / 4) / (v_dev - deadband_max / 2)
        k_var_avg = (k_var_min + k_var_max) / 2
        deadband_avg = (deadband_min + deadband_max) / 2

        # list of active tests
        active_tests = test_labels[tests_param]

        # create test curves based on input parameters
        tests = [0] * 4
        '''
        The script only sets points 1-4 in the EUT, however they use v[0] and v[5] for testing purposes to define
        n points on the line segment to verify the reactive power
        '''
        # Test 1 - Characteristic 1 "Most Aggressive" Curve
        q = [0] * 5
        q[1] = q_max_cap  # Q1
        q[2] = 0
        q[3] = 0
        q[4] = q_max_ind
        v = [0] * 6
        v[2] = v_nom - deadband_min / 2
        v[1] = v[2] - abs(q[1]) / k_var_max
        v[0] = v_min
        v[3] = v_nom + deadband_min / 2
        v[4] = v[3] + abs(q[4]) / k_var_max
        v[5] = v_max

        tests[1] = [list(v), list(q)]

        # Test 2 - Characteristic 2 "Average" Curve
        q = [0] * 5
        q[1] = q_max_cap * .5
        q[2] = 0
        q[3] = 0
        q[4] = q_max_ind * .5
        v = [0] * 6
        v[2] = v_nom - deadband_avg / 2
        v[1] = v[2] - abs(q[1]) / k_var_avg
        v[0] = v_min
        v[3] = v_nom + deadband_avg / 2
        v[4] = v[3] + abs(q[4]) / k_var_avg
        v[5] = v_max
        tests[2] = [list(v), list(q)]

        # Test 3 - Characteristic 3 "Least Aggressive" Curve
        q = [0] * 5
        q[1] = q_min_cap
        q[2] = 0
        q[3] = 0
        q[4] = q_min_ind
        v = [0] * 6
        v[0] = v_min
        v[2] = v_nom - deadband_min / 2
        v[3] = v_nom + deadband_min / 2
        if k_var_min == 0:
            v[1] = 0.99 * v[2]
            v[4] = 1.01 * v[3]
        else:
            v[1] = v[2] - abs(q[1]) / k_var_min
            v[4] = v[3] + abs(q[4]) / k_var_min
        v[5] = v_max
        tests[3] = [list(v), list(q)]

        ts.log('tests = %s' % (tests))

        # list of tuples each containing (power level as % of max, # of test at power level)
        power_levels = [(1, 3), ((p_min / p_max), 3), (.66, 5)]
        '''
        1) Connect the EUT and measurement equipment according to the requirements in Sections 4 and 5 of
        IEEE Std 1547.1-2005 and specifications provided by the manufacturer.
        '''
        '''
        2) Set all AC source parameters to the nominal operating conditions for the EUT. Frequency is set at nominal
        and held at nominal throughout this test. Set the EUT power to Pmax.
        '''
        # grid simulator is initialized with test parameters and enabled
        grid = gridsim.gridsim_init(ts)

        # pv simulator is initialized with test parameters and enabled
        pv = pvsim.pvsim_init(ts)
        pv.power_set(p_max)
        pv.power_on()

        # initialize data acquisition
        daq = das.das_init(ts)
        '''
        3) Turn on the EUT. Set all L/HVRT parameters to the widest range of adjustability possible with the
        VV Q(V) enabled. The EUT's range of disconnect settings may depend on which function(s) are enabled.
        '''
        # it is assumed the EUT is on
        eut = der.der_init(ts)
        eut.config()

        for priority in power_priorities:
            '''
            4) If the EUT has the ability to set 'Active Power Priority' or 'Reactive Power Priority', select Priority
            being evaluated.
            '''
            '''
            5) Set the EUT to provide reactive power according to the Q(V) characteristic defined in Test 1 in
            Table SA13.1.
            '''
            for test in active_tests:
                ts.log('Starting test - %s' % (test_labels[test]))

                # create voltage settings along all segments of the curve
                v = tests[test][0]
                q = tests[test][1]
                voltage_points = voltage_sample_points(v, segment_point_count)
                ts.log('Voltage test points = %s' % (voltage_points))

                # set dependent reference type
                if priority == 'Active':
                    dept_ref = 'VAR_AVAL_PCT'
                elif priority == 'Reactive':
                    dept_ref = 'VAR_MAX_PCT'
                else:
                    raise script.ScriptFail(
                        'Unknown power priority setting: %s')

                # set volt/var curve
                eut.volt_var_curve(
                    1,
                    params={
                        # convert curve points to percentages and set DER parameters
                        'v': [
                            v[1] / v_nom * 100.0, v[2] / v_nom * 100.0,
                            v[3] / v_nom * 100.0, v[4] / v_nom * 100.0
                        ],
                        'var': [
                            q[1] / q_max_cap * 100.0, q[2] / q_max_cap * 100.0,
                            q[3] / q_max_cap * 100.0, q[4] / q_max_cap * 100.0
                        ],
                        'Dept_Ref':
                        dept_ref
                    })
                # enable volt/var curve
                eut.volt_var(params={'Ena': True, 'ActCrv': 1})

                for level in power_levels:
                    power = level[0]
                    # set input power level
                    ts.log(
                        '    Setting the input power of the PV simulator to %0.2f'
                        % (p_max * power))
                    pv.power_set(p_max * power)

                    count = level[1]
                    for i in xrange(1, count + 1):
                        '''
                        6) Set the EPS voltage to a value greater than V4 for a duration of not less than the settling
                        time.
                        '''
                        '''
                        7) Begin recording the time domain response of the EUT AC voltage and current, and DC voltage
                        and current. Step down the simulated EPS voltage (the rise/fall time of simulated EPS voltage
                        shall be < 1 cyc or < 1% of settling time) until at least three points are recorded in each
                        line segment of the characteristic curve or the EUT trips from the LVRT must trip requirements.
                        Continue recording the time domain response for at least twice the settling time after each
                        voltage step.
                        '''
                        '''
                        8) Set all AC source parameters to the nominal operating conditions for the EUT. Frequency is
                        set at nominal and held at nominal throughout this test. Set the EUT power to Pmax then repeat
                        Repeat Step (7), except raising, instead of dropping, the simulated EPS voltage (the rise/fall
                        time of simulated EPS voltage shall be < 1 cyc or < 1% of settling time) until at least three
                        points are recorded in each line segment of the characteristic curve or the EUT trips from HVRT
                        must trip requirements.
                        '''

                        # test voltage high to low
                        # start capture
                        test_str = 'VV_high_%s_%s_%s' % (str(test), str(power),
                                                         str(i))
                        ts.log(
                            'Starting data capture for test %s, testing voltage high to low, with %s, '
                            'Power = %s%%, and sweep = %s' %
                            (test_str, test_labels[test], power * 100., i))
                        daq.data_capture(True)

                        for v in reversed(voltage_points):
                            ts.log(
                                '        Setting the grid voltage to %0.2f and waiting %0.1f seconds.'
                                % (v, t_settling))
                            grid.voltage(v)
                            ts.sleep(t_settling)

                        # stop capture and save
                        daq.data_capture(False)
                        ds = daq.data_capture_dataset()
                        ds.to_csv(ts.result_file('%s.csv') % (test_str))
                        ts.log('Saving data capture')

                        # test voltage low to high
                        # start capture
                        test_str = 'VV_low_%s_%s_%s' % (str(test), str(power),
                                                        str(i))
                        ts.log(
                            'Starting data capture for test %s, testing voltage low to high, with %s, '
                            'Power = %s%%, and sweep = %s' %
                            (test_str, test_labels[test], power * 100., i))
                        daq.data_capture(True)

                        for v in voltage_points:
                            ts.log(
                                '        Setting the grid voltage to %0.2f and waiting %0.1f seconds.'
                                % (v, t_settling))
                            grid.voltage(v)
                            ts.sleep(t_settling)

                        # stop capture and save
                        daq.data_capture(False)
                        ds = daq.data_capture_dataset()
                        ds.to_csv(ts.result_file('%s.csv') % (test_str))
                        ts.log('Saving data capture')
                        '''
                        9) Repeat test Steps (6) - (8) at power levels of 20 and 66%; as described by the following:
                           a) For the 20% test, the EUT output power set to 20% of its Prated nominal rating
                           b) For the 66% test the test input source is to be adjusted to limit the EUT output power to
                           a value between 50% and 95% of rated output power.
                           c) The 66% power level, as defined in (b), shall be repeated for a total of five sweeps of
                           the Q(V) curve to validate consistency.
                        '''
                '''
                10) Repeat steps (6) - (9) for the remaining tests in Table SA13.1. Other than stated in (9) (c), the
                required number of sweeps for each of these repetitions is three. In the case of EUT without adjustable
                (V, Q) points, this step may be eliminated.
                '''
            '''
            11) If the EUT has the ability to set 'Active Power Priority' and 'Reactive Power Priority', select the
            other Priority, return the simulated EPS voltage to nominal, and repeat steps (5) - (10).
            '''

        result = script.RESULT_COMPLETE

    except script.ScriptFail, e:
        reason = str(e)
        if reason:
            ts.log_error(reason)
Esempio n. 7
0
def test_run():

    result = script.RESULT_FAIL
    data = None
    trigger = None
    grid = None
    pv = None
    inv = None
    freq = {}
    W = {}
    disable = None

    try:
        ifc_type = ts.param_value('comm.ifc_type')
        ifc_name = ts.param_value('comm.ifc_name')
        if ifc_type == client.MAPPED:
            ifc_name = ts.param_value('comm.map_name')
        baudrate = ts.param_value('comm.baudrate')
        parity = ts.param_value('comm.parity')
        ipaddr = ts.param_value('comm.ipaddr')
        ipport = ts.param_value('comm.ipport')
        slave_id = ts.param_value('comm.slave_id')

        freq_ref = ts.param_value(
            'fw.settings.freq_ref')  # is there a sunspec parameter for this?

        fw_mode = ts.param_value('fw.settings.fw_mode')
        #fw_mode == 'FW21 (FW parameters)':
        WGra = ts.param_value('fw.settings.WGra')
        HzStr = ts.param_value('fw.settings.HzStr')
        HzStop = ts.param_value('fw.settings.HzStop')
        HysEna = ts.param_value('fw.settings.HysEna')
        HzStopWGra = ts.param_value('fw.settings.HzStopWGra')

        #'FW22 (pointwise FW)'
        time_window = ts.param_value('fw.settings.time_window')
        timeout_period = ts.param_value('fw.settings.timeout_period')
        ramp_time = ts.param_value('fw.settings.ramp_time')
        recovery_ramp_rate = ts.param_value('fw.settings.recovery_ramp_rate')
        curve_num = ts.param_value('fw.settings.curve_num')
        n_points = ts.param_value('fw.settings.n_points')
        freq = ts.param_value('fw.curve.freq')
        W = ts.param_value('fw.curve.W')

        pretest_delay = ts.param_value('invt.pretest_delay')
        power_range = ts.param_value('invt.power_range')
        setpoint_failure_count = ts.param_value('invt.setpoint_failure_count')
        setpoint_period = ts.param_value('invt.setpoint_period')
        verification_delay = ts.param_value('invt.verification_delay')
        posttest_delay = ts.param_value('invt.posttest_delay')
        disable = ts.param_value('invt.disable')

        # initialize data acquisition system
        daq = das.das_init(ts)
        data = daq.data_init()
        trigger = daq.trigger_init()

        # initialize pv simulation
        pv = pvsim.pvsim_init(ts)
        pv.power_on()

        # initialize grid simulation
        grid = gridsim.gridsim_init(ts)
        grid.profile_load(ts.param_value('profile.profile_name'))

        # Sandia Test Protocol: Communication is established between the Utility Management System Simulator and EUT
        # EUT scan after grid and PV simulation setup so that Modbus registers can be read.
        ts.log('Scanning inverter')
        inv = client.SunSpecClientDevice(ifc_type,
                                         slave_id=slave_id,
                                         name=ifc_name,
                                         baudrate=baudrate,
                                         parity=parity,
                                         ipaddr=ipaddr,
                                         ipport=ipport)

        # Make sure the EUT is on and operating
        ts.log(
            'Verifying EUT is in connected state. Waiting up to %d seconds for EUT to begin power export.'
            % (verification_delay + pretest_delay))
        if verify_initial_conn_state(
                inv,
                state=inverter.CONN_CONNECT,
                time_period=verification_delay + pretest_delay,
                das=data) is False:
            ts.log_error('Inverter unable to be set to connected state.')
            raise script.ScriptFail()

        ######## Begin Test ########
        if pretest_delay > 0:
            ts.log('Waiting for pre-test delay of %d seconds' % pretest_delay)
            ts.sleep(pretest_delay)

        # Request status and display power
        freq_original = inverter.get_freq(inv, das=data)
        power_original = inverter.get_power(inv, das=data)
        ts.log('Current grid frequency is %.3f Hz and EUT power is %.3f W' %
               (freq_original, power_original))

        ### todo: open the ride-through settings at this point to ensure the EUT doesn't trip during freq profile.

        # ts.log_debug('%s, %s, %s, %s, %s' % (WGra, HzStr, HzStop, HysEna, HzStopWGra))

        if HzStopWGra == 0:
            ts.log_warning(
                'Setting HzStopWGra to 10000 because of the limits of the EUT. This is the fastest available option.'
            )

        inverter.set_freq_watt(inv,
                               fw_mode=fw_mode,
                               freq=freq,
                               W=W,
                               n_points=n_points,
                               curve_num=curve_num,
                               timeout_period=timeout_period,
                               ramp_time=ramp_time,
                               recovery_ramp_rate=recovery_ramp_rate,
                               time_window=time_window,
                               WGra=WGra,
                               HzStr=HzStr,
                               HzStop=HzStop,
                               HysEna=HysEna,
                               HzStopWGra=HzStopWGra,
                               enable=1,
                               trigger=trigger)

        # Run the grid simulator profile immediately after setting the freq-watt functions and triggering
        if grid is not None:
            ts.log('Running frequency profile.')
            grid.profile_start()

        # power_pass_fail_band only determines the point on the curve. It does not account for hysteresis.
        pow_targ, pow_upper, pow_lower = power_pass_fail_band(
            inv,
            fw_mode=fw_mode,
            freq=freq,
            W=W,
            n_points=n_points,
            power_range=power_range,
            WGra=WGra,
            HzStr=HzStr,
            freq_ref=freq_ref,
            das=das)

        ts.log(
            'Target power: %.3f. Pass limits for screening: upper = %.3f  lower = %.3f'
            % (pow_targ, pow_upper, pow_lower))

        # Log FW parameters and calculate test_duration
        test_duration = setpoint_period + verification_delay
        ts.log(
            'Waiting up to %d seconds for power change with a verification period of %d seconds.'
            % (ramp_time + time_window, verification_delay))

        ts.log_debug('dc_voltage = %0.3f' % data.dc_voltage)
        ts.log_debug('dc_current = %0.3f' % data.dc_current)
        ts.log_debug('ac_voltage = %0.3f' % data.ac_voltage)
        ts.log_debug('ac_current = %0.3f' % data.ac_current)
        ts.log_debug('dc_watts = %0.3f' % data.dc_watts)
        ts.log_debug('Power = %0.3f' % data.ac_watts)
        ts.log_debug('ac_freq = %0.3f' % data.ac_freq)
        ts.log_debug('trigger = %0.3f' % data.trigger)

        start_time = time.time()
        elapsed_time = 0

        # Initialize consecutive failure count to not script fail on transient behavior
        failures = 0
        revert_complete = False

        in_hysteresis = False  # flag for when the FW is in hysteresis
        inv.nameplate.read()
        max_W = float(inv.nameplate.WRtg)

        if time_window != 0:
            window_complete = False
        else:
            window_complete = True
        time_window_execution = time_window

        while elapsed_time <= test_duration:
            ts.sleep(0.93)
            elapsed_time = time.time() - start_time

            power_pct = (inverter.get_power(inv, das=data) / max_W) * 100.

            #determine if function is in hysteresis
            if fw_mode == 'FW21 (FW parameters)' and HysEna == 'Yes':
                freq_new = inverter.get_freq(inv, das=data)

                if freq_new < freq_original and freq_original > HzStr:
                    if not in_hysteresis:
                        in_hysteresis = True
                        hys_power = power_pct
                        ts.log(
                            'Entered the Hysteresis band with power limit = %0.3f%%'
                            % hys_power)
                    else:
                        ts.log(
                            'Still in the Hysteresis band with power limited to %0.3f%%'
                            % hys_power)
                elif in_hysteresis and freq_new < HzStop:
                    in_hysteresis = False  # No longer in hysteresis band
                    ts.log(
                        'Exited hysteresis band. Returning to FW curve power at HzStopWGra = %0.3f %%nameplate/min'
                        % HzStopWGra)

                freq_original = freq_new

            if window_complete is True and revert_complete is False:
                if in_hysteresis is False:
                    # pow_targ, pow_upper, pow_lower are in percentages of nameplate power
                    pow_targ, pow_upper, pow_lower = power_pass_fail_band(
                        inv,
                        fw_mode=fw_mode,
                        freq=freq,
                        W=W,
                        n_points=n_points,
                        power_range=power_range,
                        WGra=WGra,
                        HzStr=HzStr,
                        freq_ref=freq_ref,
                        das=data)
                else:  # in hysteresis band
                    pow_targ = hys_power
                    pow_upper = pow_targ + power_range  # units of % nameplate watts
                    pow_lower = pow_targ - power_range  # units of % nameplate watts
            else:
                # Before the time window executes and after timeout period, the upper and lower pass/fail bounds for EUT
                # use the default power state of 100% Wmax
                pow_targ = 100.
                pow_upper = pow_targ + power_range  # units of % nameplate watts
                pow_lower = pow_targ - power_range  # units of % nameplate watts

            ts.log(
                'W Target = %.3f [%.3f to %.3f], W = %.3f (Error = %0.3f%%), Time: %0.3f seconds.'
                % (pow_targ, pow_lower, pow_upper, power_pct,
                   (power_pct - pow_targ), elapsed_time))

            if revert_complete is False:  #if testing FW21, timing parameters are all 0, so they don't affect results

                # Check when the EUT is in range for the first time
                if window_complete is False and \
                        inverter.get_active_control_status(inv, inverter.STACTCTL_FREQ_WATT_PARAM):
                    window_complete = True
                    time_window_execution = elapsed_time
                    ts.log(
                        'Randomization window occurred at %0.3f seconds, current power %.3f.'
                        % (time_window_execution, power_pct))

                # Check for timeout period (reversion)
                if window_complete and timeout_period != 0:

                    if not inverter.get_active_control_status(
                            inv, inverter.STACTCTL_FREQ_WATT_PARAM):  #reverted
                        revert_complete = True
                        ts.log(
                            'Reversion occurred at timeout period = %0.3f seconds, current power %.3f.'
                            % (elapsed_time, power_pct))

                    # Did timeout_period fail?  If so, end the test here.
                    # Note: there's a final timeout_period check outside the while loop.
                    elif elapsed_time >= timeout_period + min(
                            time_window,
                            time_window_execution) + verification_delay:
                        ts.log_error(
                            'Inverter did not revert after %0.3f seconds.' %
                            elapsed_time)
                        raise script.ScriptFail()

                # if power out of range
                if power_pct < pow_lower or power_pct > pow_upper:
                    ts.log_debug(
                        'Power %0.3f, Pow Lower = %0.3f, Pow Upper = %0.3f.' %
                        (power_pct, pow_lower, pow_upper))
                    # There are three acceptable sources of noncompliance. If the randomization window hasn't occurred,
                    # the reversion (timeout) occurred, or it is ramping to the target vars
                    if window_complete is False:  #time window
                        ts.log(
                            'Randomization window still in effect after %0.3f seconds.'
                            % (time.time() - start_time))
                    elif elapsed_time > min(time_window,
                                            time_window_execution) + ramp_time:
                        # Noncompliance is not from time period, time window, or ramp rate
                        # Count this as a failure
                        failures += 1
                        if failures >= setpoint_failure_count:
                            ts.log_error(
                                'Inverter exceeded var setpoint + buffer after %0.3f seconds. '
                                'Fail count = %d.' % (elapsed_time, failures))
                            raise script.ScriptFail()
                        else:
                            ts.log_warning(
                                'Inverter exceeded var setpoint + buffer after %0.3f seconds. '
                                'Fail count = %d.' % (elapsed_time, failures))
                    else:
                        ts.log_warning(
                            'EUT has not reached the target reactive power because it is ramping.'
                        )
                else:
                    failures = 0

        # Additional timeout check to determine if the timeout_period occurred during the test. This is necessary
        # in cases where the verification_delay is not set sufficiently long.
        if timeout_period != 0 and inverter.get_active_control_status(
                inv, inverter.STACTCTL_VOLT_VAR):
            ts.log_error(
                'Inverter did not revert by the end of the test duration. Elapsed time = %0.3f seconds.  '
                'Increase the verification period if the timeout period is greater than the elapsed time.'
                % (elapsed_time))
            raise script.ScriptFail()

        if posttest_delay > 0:
            ts.log('Waiting for post-test delay of %d seconds' %
                   posttest_delay)
            ts.sleep(posttest_delay)

        result = script.RESULT_PASS

    except script.ScriptFail, e:
        reason = str(e)
        if reason:
            ts.log_error(reason)
Esempio n. 8
0
def test_run():

    result = script.RESULT_FAIL
    das = None
    wfmtrigger = None
    gsim = None
    pv = None
    inv = None
    filename = None
    disable = None

    try:
        ifc_type = ts.param_value('comm.ifc_type')
        ifc_name = ts.param_value('comm.ifc_name')
        if ifc_type == client.MAPPED:
            ifc_name = ts.param_value('comm.map_name')
        baudrate = ts.param_value('comm.baudrate')
        parity = ts.param_value('comm.parity')
        ipaddr = ts.param_value('comm.ipaddr')
        ipport = ts.param_value('comm.ipport')
        slave_id = ts.param_value('comm.slave_id')

        time_window = ts.param_value('vrt.settings.time_window')
        timeout_period = ts.param_value('vrt.settings.timeout_period')
        ramp_time = ts.param_value('vrt.settings.ramp_time')

        h_n_points = ts.param_value('vrt.settings.h_n_points')
        h_curve_num = ts.param_value('vrt.settings.h_curve_num')
        h_time = ts.param_value('vrt.h_curve.h_time')
        h_volt = ts.param_value('vrt.h_curve.h_volt')

        l_n_points = ts.param_value('vrt.settings.l_n_points')
        l_curve_num = ts.param_value('vrt.settings.l_curve_num')
        l_time = ts.param_value('vrt.l_curve.l_time')
        l_volt = ts.param_value('vrt.l_curve.l_volt')

        ride_through = ts.param_value('vrt.settings.ride_through')

        hc_n_points = ts.param_value('vrt.settings.hc_n_points')
        hc_curve_num = ts.param_value('vrt.settings.hc_curve_num')
        hc_time = ts.param_value('vrt.hc_curve.hc_time')
        hc_volt = ts.param_value('vrt.hc_curve.hc_volt')

        lc_n_points = ts.param_value('vrt.settings.lc_n_points')
        lc_curve_num = ts.param_value('vrt.settings.lc_curve_num')
        lc_time = ts.param_value('vrt.lc_curve.lc_time')
        lc_volt = ts.param_value('vrt.lc_curve.lc_volt')

        time_msa = ts.param_value('invt.time_msa')
        test_point_offset = ts.param_value('invt.test_point_offset')
        vrt_period = ts.param_value('invt.VRT_period')
        pretest_delay = ts.param_value('invt.pretest_delay')
        failure_count = ts.param_value('invt.failure_count')
        verification_delay = ts.param_value('invt.verification_delay')
        posttest_delay = ts.param_value('invt.posttest_delay')
        disable = ts.param_value('invt.disable')

        # initialize data acquisition system
        das, wfmtrigger, wfmtrigger_params = das_init()

        # initialize pv simulation
        pv = pvsim.pvsim_init(ts)
        pv.power_on()

        # initialize grid simulation
        gsim = gridsim.gridsim_init(ts)

        #Inverter scan after grid and PV simulation setup so that Modbus registers can be read.
        ts.log('Scanning inverter')
        inv = client.SunSpecClientDevice(ifc_type, slave_id=slave_id, name=ifc_name, baudrate=baudrate, parity=parity,
                                         ipaddr=ipaddr, ipport=ipport)

        ### Find test points ###
        # determine the test points for the HVRT tests (ends near nominal)
        h_v_test_points = [h_volt[h_volt['index_start']]+test_point_offset]
        h_v_test_points.append(h_volt[h_volt['index_start']]-test_point_offset)
        for x in range(h_volt['index_start']+1, h_volt['index_count']):
            h_v_test_points.append(h_volt[x]+test_point_offset)
            h_v_test_points.append(h_volt[x]-test_point_offset)
        h_v_test_points.append(h_volt[h_volt['index_count']]+test_point_offset)
        h_v_test_points.append(h_volt[h_volt['index_count']]-test_point_offset)
        #ts.log_debug(h_v_test_points)

        # determine the test points for the LVRT tests (starts near nominal)
        l_v_test_points = [l_volt[l_volt['index_count']]+test_point_offset]
        l_v_test_points.append(l_volt[l_volt['index_count']]-test_point_offset)
        for x in range(l_volt['index_count']-1, l_volt['index_start'], -1):
            l_v_test_points.append(l_volt[x]+test_point_offset)
            l_v_test_points.append(l_volt[x]-test_point_offset)
        l_v_test_points.append(l_volt[l_volt['index_start']]+test_point_offset)
        l_v_test_points.append(l_volt[l_volt['index_start']]-test_point_offset)
        #ts.log_debug(l_v_test_points)

        v_test_points = h_v_test_points + l_v_test_points
        list(set(v_test_points))  # remove duplicate points
        # ts.log_debug(v_test_points)

        if ride_through == 'Yes':

            # determine the test points for the HVRTC tests (ends near nominal)
            hc_v_test_points = [hc_volt[hc_volt['index_start']]+test_point_offset]
            hc_v_test_points.append(hc_volt[hc_volt['index_start']]-test_point_offset)
            for x in range(hc_volt['index_start']+1, hc_volt['index_count']):
                hc_v_test_points.append(hc_volt[x]+test_point_offset)
                hc_v_test_points.append(hc_volt[x]-test_point_offset)
            hc_v_test_points.append(hc_volt[hc_volt['index_count']]+test_point_offset)
            hc_v_test_points.append(hc_volt[hc_volt['index_count']]-test_point_offset)
            #ts.log_debug(hc_v_test_points)

            # determine the test points for the LVRTC tests (starts near nominal)
            lc_v_test_points = [lc_volt[lc_volt['index_count']]+test_point_offset]
            lc_v_test_points.append(lc_volt[lc_volt['index_count']]-test_point_offset)
            for x in range(lc_volt['index_count']-1, lc_volt['index_start'], -1):
                lc_v_test_points.append(lc_volt[x]+test_point_offset)
                lc_v_test_points.append(lc_volt[x]-test_point_offset)
            lc_v_test_points.append(lc_volt[lc_volt['index_start']]+test_point_offset)
            lc_v_test_points.append(lc_volt[lc_volt['index_start']]-test_point_offset)
            #ts.log_debug(lc_v_test_points)

            v_test_points = v_test_points + hc_v_test_points + lc_v_test_points

        v_test_points = list(set(v_test_points))  # remove duplicate points
        v_test_points.sort()

        # remove negative test points
        for x in range(len(v_test_points)-1, 0, -1):
            if v_test_points[x] < 0:
                del v_test_points[x]
        ts.log('Voltage Test points are %s' % v_test_points)

        ######## Begin Test ########
        #if pretest_delay > 0:
        #    ts.log('Waiting for pre-test delay of %d seconds' % pretest_delay)
        #    ts.sleep(pretest_delay)

        # note: timing parameters are not tested currently by this script - would need to wrap the assignment into loop
        # below to determine response times and timeout periods

        ts.log('Writing the VRT curves to the EUT')
        '''
        inverter.set_vrt_trip_high(inv, h_time=h_time, h_volt=h_volt, h_n_points=h_n_points, h_curve_num=h_curve_num,
                         time_window=time_window, timeout_period=timeout_period, ramp_time=ramp_time,
                         enable=1, wfmtrigger=wfmtrigger)

        inverter.set_vrt_trip_high(inv, l_time=l_time, l_volt=l_volt, l_n_points=l_n_points, l_curve_num=l_curve_num,
                         time_window=time_window, timeout_period=timeout_period, ramp_time=ramp_time,
                         enable=1, wfmtrigger=wfmtrigger)

        if ride_through == 'Yes':
            inverter.set_vrt_stay_connected_high(inv, hc_time=hc_time, hc_volt=hc_volt, hc_n_points=hc_n_points,
                                                 hc_curve_num=hc_curve_num, time_window=time_window,
                                                 timeout_period=timeout_period, ramp_time=ramp_time,
                                                 enable=1, wfmtrigger=wfmtrigger)

            inverter.set_vrt_stay_connected_low(inv, lc_time=lc_time, lc_volt=lc_volt, lc_n_points=lc_n_points,
                                                 lc_curve_num=lc_curve_num, time_window=time_window,
                                                 timeout_period=timeout_period, ramp_time=ramp_time,
                                                 enable=1, wfmtrigger=wfmtrigger)
        '''

        failures = 0  # failure counter
        for i in xrange(0, len(v_test_points)):
            # determine the expected behavior
            c_time, d_time = predict_vrt_response_time(v_test_points[i], ride_through,
                                                       h_time=h_time, h_volt=h_volt, h_n_points=h_n_points,
                                                       l_time=l_time, l_volt=l_volt, l_n_points=l_n_points,
                                                       hc_time=hc_time, hc_volt=hc_volt, hc_n_points=hc_n_points,
                                                       lc_time=lc_time, lc_volt=lc_volt, lc_n_points=lc_n_points)

            ts.log('Test %i, test voltage = %0.3f %%Vref. Expected Ride-Through Time = %0.3f sec. '
                   'Expected Trip Time = %0.3f sec.' % (i+1, v_test_points[i], c_time, d_time))

            if d_time == 0.:  # test doesn't have a trip boundary. Set d_time to max time plus verification time
                max_time = max(l_time, lc_time, h_time, hc_time)
                ts.log_debug('max_time: %s, max(max_time): %s' % (max_time, max(max_time)))
                d_time = max_time + verification_delay

            ### Make sure the EUT is on and operating
            if inverter.get_conn_state(inv) and inverter.get_power_norm(inv) < 0.05:
                ts.log_warning('EUT not operating! Checking grid simulator operations.')

                # if the inverter is off it's probably because the grid simulator is misconfigured.
                if gsim:
                    gsim.profile_stop()  #abort the profile
                    ts.log('grid nominal voltage: %s' % gsim.v_nom())
                    gsim.voltage(gsim.v_nom())  # return simulator to nominal voltage

                ts.log('Waiting up to %d seconds for EUT to begin power export.' % (verification_delay+pretest_delay))
                if verify_initial_conn_state(inv, state=inverter.CONN_CONNECT,
                                             time_period=verification_delay+pretest_delay, das=das) is False:
                        ts.log_error('Inverter unable to be set to connected state.')
                        raise script.ScriptFail()

            ### Arm the data acquisition system for waveform capture
            if das is not None:
                das_time = inverter.get_time(das=das)
                while das_time == inverter.get_time(das=das):
                    ts.log('Monitoring the data stream to ensure the das is prepared for a waveform capture. '
                           'DAS time: %s' % inverter.get_time(das=das))
                    ts.sleep(1)

                ts.log('Configuring the data capture for the following channels: %s' %
                       wfmtrigger_params.get('trigacqchannels'))
                ts.log('Configuring the %s waveform trigger for %s = %0.3f' %
                       (wfmtrigger_params.get('trigcondition'), wfmtrigger_params.get('trigchannel'),
                        float(wfmtrigger_params.get('trigval'))))
                # ts.log_debug('wfmtrigger_params = %s' % wfmtrigger_params)
                wfmtrigger.trigger(wfmtrigger_params=wfmtrigger_params)

                ts.log('Data acquisition preparing for waveform capture. Waiting for pre-test delay of %d seconds'
                       % pretest_delay)
                starttime = time.time()
                while pretest_delay >= (time.time()-starttime):
                    totaltime = time.time()-starttime
                    ts.log('Waiting %0.3f more seconds.' % (pretest_delay-totaltime))
                    ts.sleep(1.0 - totaltime % 1)

            else:  # there is no data acquisition system
                ts.log_warning('No data acquisition system configured.')
                if ts.confirm('Please configure the trigger to capture the ride-through and enable it.') is False:
                    raise script.ScriptFail('Aborted VRT!')

            if v_test_points[i] < 100.:
                vrt_test_voltage = v_test_points[i]+test_point_offset
            else:
                vrt_test_voltage = v_test_points[i]-test_point_offset

            ### Execute the voltage change
            if gsim is not None:
                ### create transient event in grid simulator
                if d_time == 0 and c_time == 0:  # near nominal
                    test_duration = max(h_time, l_time, lc_time, hc_time)
                    # be sure to catch end of transient with at least a 3 cycle window
                    wfmtrigger_params['posttrig'] = test_duration + max(verification_delay, 0.0166*3)
                else:
                    test_duration = max(c_time, d_time)
                    # be sure to catch end of transient with at least a 3 cycle window
                    wfmtrigger_params['posttrig'] = test_duration + max(verification_delay, 0.0166*3)
                ts.log('The post trigger time has been adjusted to %s for this ride through test to capture '
                       'the EUT dynamics' % wfmtrigger_params.get('posttrig'))

                # Use the profile so the timing for the event is accurate and there is a trigger from the simulator
                gsim.profile_load(profile_name='Transient_Step', v_step=vrt_test_voltage, f_step=100,
                                  t_step=test_duration)
                ts.log('Profile is loaded in simulator. Running the grid simulator profile.')
                gsim.profile_start()
            else:
                ts.log('Must set the grid simulator voltage to the ride-through voltage.')
                if ts.confirm('Set the grid simulator to the test voltage: %0.3f %%Vref.' %
                              vrt_test_voltage) is False:
                    raise script.ScriptFail('Aborted VRT!')

            ### Wait for DAS to capture transient event
            start_time = time.time()
            elapsed_time = 0.
            while elapsed_time <= wfmtrigger_params['posttrig']:
                ts.log('Waiting for waveform capture to complete. Total time remaining %0.3f seconds' %
                       (wfmtrigger_params['posttrig']-elapsed_time))
                ts.sleep(0.93)
                elapsed_time = time.time() - start_time

            ### Screen waveform data and save in the results file
            if das is not None:

                ts.log('Waiting post test delay of %0.2f seconds before processing the data file.' % posttest_delay)
                ts.sleep(posttest_delay)

                # get data from waveform saved on the hard drive
                # (this function could use a little help to make it more robust...)
                wfmname = wfmtrigger.getfilename()
                ts.log('Analyzing waveform data in file "%s".' % wfmname)

                if ts.param_value('wfm.trigchannel').count(',') == 3:
                    wfmtime, ac_voltage, ac_current = wfmtrigger.read_file(wfmname)

                    # calculate the time the EUT rode through the voltage event
                    # ride_through_time == 0 means no trip/ceassation
                    ride_through_time = calc_ride_through_duration(wfmtime, ac_current, ac_voltage=ac_voltage)

                else:  # if there are more than 3 channels being collected, assume the first 4 the following:
                    wfmtime, ac_voltage, ac_current, grid_trig = wfmtrigger.read_file(wfmname)

                    # calculate the time the EUT rode through the voltage event
                    # ride_through_time == 0 means no trip/ceassation
                    ride_through_time = calc_ride_through_duration(wfmtime, ac_current, grid_trig=grid_trig)

                if ride_through_time == 0:
                    ts.log('The EUT did not trip or momentarily cease to energize.')
                else:
                    ts.log('The ride-through duration was %0.3f.' % ride_through_time)

                if ride_through_time - time_msa < c_time:
                    ts.log_warning('The ride-through duration of %0.3f minus the manufacturers stated '
                                   'accuracy of %0.3f is less '
                                   'than the ride-through time of %0.3f.' % (ride_through_time, time_msa, c_time))
                    failures += 1
                    ts.log_warning('The number of failures is %i.' % failures)
                elif ride_through_time + time_msa > d_time:
                    ts.log_warning('The ride-through duration of %0.3f plus the manufacturers stated '
                                   'accuracy of %0.3f is more '
                                   'than the must disconnect time of %0.3f.' % (ride_through_time, time_msa, c_time))
                    failures += 1
                    ts.log_warning('The number of failures is %i.' % failures)

                # save file to results
                results_dir = os.path.dirname(__file__)[:-7] + 'Results' + os.path.sep
                ts.log('Moving waveform "%s" to results folder: %s.' % (wfmname, results_dir))
                wfmtrigger.move_file_to_results(wfmname=wfmname, results_dir=results_dir, delete_original='No')

            else:
                ts.log('Ride-through test complete. Please analyze the data to assign pass/fail result.')

            if failures >= failure_count:
                raise script.ScriptFail()

        ts.log('Waiting the post-test duration %i.' % posttest_delay)
        ts.sleep(posttest_delay)

        result = script.RESULT_PASS

    except script.ScriptFail, e:
        reason = str(e)
        if reason:
            ts.log_error(reason)
Esempio n. 9
0
def test_run():

    result = script.RESULT_FAIL
    data = None
    trigger = None
    grid = None
    pv = None
    inv = None
    freq = {}
    W = {}
    disable = None

    try:
        ifc_type = ts.param_value('comm.ifc_type')
        ifc_name = ts.param_value('comm.ifc_name')
        if ifc_type == client.MAPPED:
            ifc_name = ts.param_value('comm.map_name')
        baudrate = ts.param_value('comm.baudrate')
        parity = ts.param_value('comm.parity')
        ipaddr = ts.param_value('comm.ipaddr')
        ipport = ts.param_value('comm.ipport')
        slave_id = ts.param_value('comm.slave_id')

        freq_ref = ts.param_value('fw.settings.freq_ref')  # is there a sunspec parameter for this?

        fw_mode = ts.param_value('fw.settings.fw_mode')
        #fw_mode == 'FW21 (FW parameters)':
        WGra = ts.param_value('fw.settings.WGra')
        HzStr = ts.param_value('fw.settings.HzStr')
        HzStop = ts.param_value('fw.settings.HzStop')
        HysEna = ts.param_value('fw.settings.HysEna')
        HzStopWGra = ts.param_value('fw.settings.HzStopWGra')

        #'FW22 (pointwise FW)'
        time_window = ts.param_value('fw.settings.time_window')
        timeout_period = ts.param_value('fw.settings.timeout_period')
        ramp_time = ts.param_value('fw.settings.ramp_time')
        recovery_ramp_rate = ts.param_value('fw.settings.recovery_ramp_rate')
        curve_num = ts.param_value('fw.settings.curve_num')
        n_points = ts.param_value('fw.settings.n_points')
        freq = ts.param_value('fw.curve.freq')
        W = ts.param_value('fw.curve.W')

        pretest_delay = ts.param_value('invt.pretest_delay')
        power_range = ts.param_value('invt.power_range')
        setpoint_failure_count = ts.param_value('invt.setpoint_failure_count')
        setpoint_period = ts.param_value('invt.setpoint_period')
        verification_delay = ts.param_value('invt.verification_delay')
        posttest_delay = ts.param_value('invt.posttest_delay')
        disable = ts.param_value('invt.disable')

        # initialize data acquisition system
        daq = das.das_init(ts)
        data = daq.data_init()
        trigger = daq.trigger_init()

        # initialize pv simulation
        pv = pvsim.pvsim_init(ts)
        pv.power_on()

        # initialize grid simulation
        grid = gridsim.gridsim_init(ts)
        grid.profile_load(ts.param_value('profile.profile_name'))

        # Sandia Test Protocol: Communication is established between the Utility Management System Simulator and EUT
        # EUT scan after grid and PV simulation setup so that Modbus registers can be read.
        ts.log('Scanning inverter')
        inv = client.SunSpecClientDevice(ifc_type, slave_id=slave_id, name=ifc_name, baudrate=baudrate, parity=parity,
                                         ipaddr=ipaddr, ipport=ipport)

        # Make sure the EUT is on and operating
        ts.log('Verifying EUT is in connected state. Waiting up to %d seconds for EUT to begin power export.'
               % (verification_delay+pretest_delay))
        if verify_initial_conn_state(inv, state=inverter.CONN_CONNECT,
                                     time_period=verification_delay+pretest_delay, das=data) is False:
                ts.log_error('Inverter unable to be set to connected state.')
                raise script.ScriptFail()

        ######## Begin Test ########
        if pretest_delay > 0:
            ts.log('Waiting for pre-test delay of %d seconds' % pretest_delay)
            ts.sleep(pretest_delay)

        # Request status and display power
        freq_original = inverter.get_freq(inv, das=data)
        power_original = inverter.get_power(inv, das=data)
        ts.log('Current grid frequency is %.3f Hz and EUT power is %.3f W' % (freq_original, power_original))

        ### todo: open the ride-through settings at this point to ensure the EUT doesn't trip during freq profile.

        # ts.log_debug('%s, %s, %s, %s, %s' % (WGra, HzStr, HzStop, HysEna, HzStopWGra))

        if HzStopWGra == 0:
            ts.log_warning('Setting HzStopWGra to 10000 because of the limits of the EUT. This is the fastest available option.')

        inverter.set_freq_watt(inv, fw_mode=fw_mode, freq=freq, W=W, n_points=n_points, curve_num=curve_num,
                               timeout_period=timeout_period, ramp_time=ramp_time,
                               recovery_ramp_rate=recovery_ramp_rate,
                               time_window=time_window, WGra=WGra, HzStr=HzStr, HzStop=HzStop, HysEna=HysEna,
                               HzStopWGra=HzStopWGra, enable=1, trigger=trigger)

        # Run the grid simulator profile immediately after setting the freq-watt functions and triggering
        if grid is not None:
            ts.log('Running frequency profile.')
            grid.profile_start()

        # power_pass_fail_band only determines the point on the curve. It does not account for hysteresis.
        pow_targ, pow_upper, pow_lower = power_pass_fail_band(inv, fw_mode=fw_mode, freq=freq, W=W, n_points=n_points,
                                                              power_range=power_range, WGra=WGra,
                                                              HzStr=HzStr, freq_ref=freq_ref, das=das)

        ts.log('Target power: %.3f. Pass limits for screening: upper = %.3f  lower = %.3f' %
               (pow_targ, pow_upper, pow_lower))

        # Log FW parameters and calculate test_duration
        test_duration = setpoint_period + verification_delay
        ts.log('Waiting up to %d seconds for power change with a verification period of %d seconds.' %
               (ramp_time + time_window, verification_delay))

        ts.log_debug('dc_voltage = %0.3f' % data.dc_voltage)
        ts.log_debug('dc_current = %0.3f' % data.dc_current)
        ts.log_debug('ac_voltage = %0.3f' % data.ac_voltage)
        ts.log_debug('ac_current = %0.3f' % data.ac_current)
        ts.log_debug('dc_watts = %0.3f' % data.dc_watts)
        ts.log_debug('Power = %0.3f' % data.ac_watts)
        ts.log_debug('ac_freq = %0.3f' % data.ac_freq)
        ts.log_debug('trigger = %0.3f' % data.trigger)

        start_time = time.time()
        elapsed_time = 0

        # Initialize consecutive failure count to not script fail on transient behavior
        failures = 0
        revert_complete = False

        in_hysteresis = False  # flag for when the FW is in hysteresis
        inv.nameplate.read()
        max_W = float(inv.nameplate.WRtg)

        if time_window != 0:
            window_complete = False
        else:
            window_complete = True
        time_window_execution = time_window

        while elapsed_time <= test_duration:
            ts.sleep(0.93)
            elapsed_time = time.time()-start_time

            power_pct = (inverter.get_power(inv, das=data) / max_W) * 100.

            #determine if function is in hysteresis
            if fw_mode == 'FW21 (FW parameters)' and HysEna == 'Yes':
                freq_new = inverter.get_freq(inv, das=data)

                if freq_new < freq_original and freq_original > HzStr:
                    if not in_hysteresis:
                        in_hysteresis = True
                        hys_power = power_pct
                        ts.log('Entered the Hysteresis band with power limit = %0.3f%%' % hys_power)
                    else:
                        ts.log('Still in the Hysteresis band with power limited to %0.3f%%' % hys_power)
                elif in_hysteresis and freq_new < HzStop:
                    in_hysteresis = False  # No longer in hysteresis band
                    ts.log('Exited hysteresis band. Returning to FW curve power at HzStopWGra = %0.3f %%nameplate/min'
                           % HzStopWGra)

                freq_original = freq_new

            if window_complete is True and revert_complete is False:
                if in_hysteresis is False:
                    # pow_targ, pow_upper, pow_lower are in percentages of nameplate power
                    pow_targ, pow_upper, pow_lower = power_pass_fail_band(inv, fw_mode=fw_mode, freq=freq, W=W,
                                                                          n_points=n_points, power_range=power_range,
                                                                          WGra=WGra, HzStr=HzStr,
                                                                          freq_ref=freq_ref, das=data)
                else:  # in hysteresis band
                    pow_targ = hys_power
                    pow_upper = pow_targ + power_range  # units of % nameplate watts
                    pow_lower = pow_targ - power_range  # units of % nameplate watts
            else:
                # Before the time window executes and after timeout period, the upper and lower pass/fail bounds for EUT
                # use the default power state of 100% Wmax
                pow_targ = 100.
                pow_upper = pow_targ + power_range  # units of % nameplate watts
                pow_lower = pow_targ - power_range  # units of % nameplate watts

            ts.log('W Target = %.3f [%.3f to %.3f], W = %.3f (Error = %0.3f%%), Time: %0.3f seconds.' %
                   (pow_targ, pow_lower, pow_upper, power_pct, (power_pct - pow_targ), elapsed_time))

            if revert_complete is False:  #if testing FW21, timing parameters are all 0, so they don't affect results

                # Check when the EUT is in range for the first time
                if window_complete is False and \
                        inverter.get_active_control_status(inv, inverter.STACTCTL_FREQ_WATT_PARAM):
                    window_complete = True
                    time_window_execution = elapsed_time
                    ts.log('Randomization window occurred at %0.3f seconds, current power %.3f.' %
                           (time_window_execution, power_pct))

                # Check for timeout period (reversion)
                if window_complete and timeout_period != 0:

                    if not inverter.get_active_control_status(inv, inverter.STACTCTL_FREQ_WATT_PARAM): #reverted
                        revert_complete = True
                        ts.log('Reversion occurred at timeout period = %0.3f seconds, current power %.3f.'
                               % (elapsed_time, power_pct))

                    # Did timeout_period fail?  If so, end the test here.
                    # Note: there's a final timeout_period check outside the while loop.
                    elif elapsed_time >= timeout_period+min(time_window,time_window_execution)+verification_delay:
                        ts.log_error('Inverter did not revert after %0.3f seconds.' % elapsed_time)
                        raise script.ScriptFail()

                # if power out of range
                if power_pct < pow_lower or power_pct > pow_upper:
                    ts.log_debug('Power %0.3f, Pow Lower = %0.3f, Pow Upper = %0.3f.' % (power_pct, pow_lower, pow_upper))
                    # There are three acceptable sources of noncompliance. If the randomization window hasn't occurred,
                    # the reversion (timeout) occurred, or it is ramping to the target vars
                    if window_complete is False: #time window
                        ts.log('Randomization window still in effect after %0.3f seconds.' % (time.time()-start_time))
                    elif elapsed_time > min(time_window,time_window_execution)+ramp_time:
                        # Noncompliance is not from time period, time window, or ramp rate
                        # Count this as a failure
                        failures += 1
                        if failures >= setpoint_failure_count:
                            ts.log_error('Inverter exceeded var setpoint + buffer after %0.3f seconds. '
                                         'Fail count = %d.' % (elapsed_time,failures))
                            raise script.ScriptFail()
                        else:
                            ts.log_warning('Inverter exceeded var setpoint + buffer after %0.3f seconds. '
                                           'Fail count = %d.' % (elapsed_time,failures))
                    else:
                        ts.log_warning('EUT has not reached the target reactive power because it is ramping.')
                else:
                    failures = 0

        # Additional timeout check to determine if the timeout_period occurred during the test. This is necessary
        # in cases where the verification_delay is not set sufficiently long.
        if timeout_period != 0 and inverter.get_active_control_status(inv, inverter.STACTCTL_VOLT_VAR):
            ts.log_error('Inverter did not revert by the end of the test duration. Elapsed time = %0.3f seconds.  '
                         'Increase the verification period if the timeout period is greater than the elapsed time.'
                         % (elapsed_time))
            raise script.ScriptFail()

        if posttest_delay > 0:
            ts.log('Waiting for post-test delay of %d seconds' % posttest_delay)
            ts.sleep(posttest_delay)

        result = script.RESULT_PASS

    except script.ScriptFail, e:
        reason = str(e)
        if reason:
            ts.log_error(reason)
Esempio n. 10
0
def test_run():

    result = script.RESULT_FAIL
    data = None
    trigger = None
    inv = None
    pv = None
    disable = None

    try:

        # UL 1741 Test Protocol
        # a.	Connect the EUT according to the Requirements in Sec. 11.2.4 and specifications provided by the
        #       manufacturer. Set the EUT to maximum power factor.

        # b.	Set all AC source parameters to the nominal operating conditions for the EUT.

        # c.	Set the input power level to provide Ilow from the EUT. Note: for units that do not adjust output
        #       current as a function of their input such as units with energy storage or multimode products the output
        #       power is to be commanded.

        # d.	Turn on the EUT.  Allow the EUT to reach steady state, e.g., maximum power point.

        # e.	Set the EUT ramp rate parameters according to Test 1 in Table SA 11.1.

        # f.	Begin recording the time domain response of the EUT AC voltage and current, and DC voltage and current.

        # g.	Increase the available input power to provide Irated from the EUT according to the step function
        #       described in SA 11.

        # h.	Stop recording the time domain response after the ramp duration plus a manufacturer-specified dwell
        #       time. Ramp duration is defined by 100/RRnorm_up as appropriate for the test settings.

        # i.	Repeat steps c-h two times for a total of 3 repetitions.

        # j.	Repeat steps c-i for Tests 2-3 in Table SA 11.1.

        # EUT communication parameters
        ifc_type = ts.param_value('comm.ifc_type')
        ifc_name = ts.param_value('comm.ifc_name')
        if ifc_type == client.MAPPED:
            ifc_name = ts.param_value('comm.map_name')
        baudrate = ts.param_value('comm.baudrate')
        parity = ts.param_value('comm.parity')
        ipaddr = ts.param_value('comm.ipaddr')
        ipport = ts.param_value('comm.ipport')
        slave_id = ts.param_value('comm.slave_id')

        # RR parameters
        RRnorm_up_min = ts.param_value('rr.RRnorm_up_min')
        RRnorm_up_max = ts.param_value('rr.RRnorm_up_max')
        Ilow = ts.param_value('rr.Ilow')
        Irated = ts.param_value('rr.Irated')
        MSARR = ts.param_value('rr.MSARR')
        t_dwell = ts.param_value('rr.t_dwell')

        # Script timing and pass/fail criteria
        pretest_delay = ts.param_value('invt.pretest_delay')
        verification_delay = ts.param_value('invt.verification_delay')
        posttest_delay = ts.param_value('invt.posttest_delay')
        power_threshold = ts.param_value('invt.power_threshold')
        disable = ts.param_value('invt.disable')

        # initialize data acquisition system
        daq = das.das_init(ts)
        data = daq.data_init()
        trigger = daq.trigger_init()

        # Step b.	Set all AC source parameters to the nominal operating conditions for the EUT.
        # Initialize pv simulation - This is before step (a) because PV power may be required for communications to EUT
        pv = pvsim.pvsim_init(ts)
        pv.power_on()

        # Communication is established between the Utility Management System Simulator and EUT
        ts.log('Scanning EUT')
        try:
            inv = client.SunSpecClientDevice(ifc_type, slave_id=slave_id, name=ifc_name, baudrate=baudrate,
                                             parity=parity, ipaddr=ipaddr, ipport=ipport)
        except Exception, e:
            raise script.ScriptFail('Error: %s' % e)

        # Step a.	Connect the EUT according to the Requirements in Sec. 11.2.4 and specifications provided by the
        #       manufacturer. Set the EUT to maximum power factor.
        # It is assumed that the  Grid Simulator (if used) is connected to the EUT and operating properly
        inverter.set_power_factor(inv, power_factor=1., enable=0)

        # UL 1741 Step j.	Repeat steps c-i for Tests 2-3 in Table SA 11.1.
        for ramp in [RRnorm_up_min, (RRnorm_up_min + RRnorm_up_max)/2, RRnorm_up_max]:

            for i in xrange(3):  # UL 1741 Step i. Repeat steps c-h two times for a total of 3 repetitions.

                ts.log('Running test number %d with ramp rate %0.3f %%Irated/sec.' %
                       (i+1, ramp))

                # Step c. Set the input power level to provide Ilow from the EUT. Note: for units that do not adjust
                #       output current as a function of their input such as units with energy storage or multimode
                #       products the output power is to be commanded.
                pv.irradiance_set(irradiance=Ilow*10)

                # Step d.	Turn on the EUT.  Allow the EUT to reach steady state, e.g., maximum power point.
                if pretest_delay > 0:
                    ts.log('Waiting for pre-test delay of %d seconds' % pretest_delay)
                    ts.sleep(pretest_delay)

                # Verify EUT is in correct state before running the test.
                if inverter.get_conn_state(inv) is False:
                    ts.log('Inverter not in correct state, setting state to connected.')
                    inverter.set_conn_state(inv, state=1)
                    if verify_conn_state_change(inv, orig_state=0, verification_delay=verification_delay,
                                                threshold=power_threshold, data=data) is False:
                        raise script.ScriptFail()

                # Step e.	Set the EUT ramp rate parameters according to Test 1 in Table SA 11.1.
                try:
                    inv.settings.read()
                    if inv.settings.WGra is not None:
                        inv.settings.WGra = ramp
                    else:
                        ts.log_error('Unable to change ramp rate in the EUT.')
                except Exception, e:
                    ts.log_error('Error changing ramp rate in the EUT: %s' % str(e))

                # Step g.	Increase the available input power to provide Irated from the EUT according to the step
                #           function described in SA 11.
                pv.irradiance_set(irradiance=1000)
                start_time = time.time()

                # Step h.	Stop recording the time domain response after the ramp duration plus a
                #           manufacturer-specified dwell time.
                data_update_rate = 1  # Hz
                check_duration = (Irated-Ilow)/ramp
                test_duration = t_dwell + check_duration
                duration = 0
                while duration < test_duration+verification_delay:
                    duration = time.time()-start_time
                    ts.log_debug('duration = %0.2f, check duration = %0.2f' % (duration, check_duration))
                    if duration <= check_duration:  # only check the ramp response during the check_duration
                        ramp_in_bounds = verify_ramp(inv, ramp=ramp, t_since_step=duration, Ilow=Ilow,
                                                     Irated=Irated, MSARR=MSARR, data=data)
                        if ramp_in_bounds is False:
                            ts.log_error('Ramp response was not within limits')
                            # raise script.ScriptFail()
                    else:  # The EUT shall reach at least 95% of Irated at the end of the dwell time.
                        ts.log('EUT completed ramping. Waiting for dwell time to check current output. '
                               'Remaining time: %0.3f' % (test_duration - duration))
                        if duration >= test_duration:
                            current_pct = inverter.get_power_norm(inv=inv, das=data)*100
                            ts.log_error('EUT current is %0.3f%%' % current_pct)
                            if current_pct < 95:
                                ts.log_error('EUT did not reach at least 95% of Irated at the end of the dwell time.')
                                raise script.ScriptFail()
                            break
                    time.sleep(1/data_update_rate)  # todo: should improve the loop timing

                if posttest_delay > 0:
                    ts.log('Waiting for post-test delay of %d seconds' % posttest_delay)
                    ts.sleep(posttest_delay)
Esempio n. 11
0
def test_run():

    result = script.RESULT_FAIL
    das = None
    trigger = None
    inv = None
    pv = None
    disable = None

    try:

        # UL 1741 Test Protocol
        # SA 11.3.2 The soft-start test shall be carried out as follows:

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

        # b)	Set all AC source parameters to the nominal operating conditions for the EUT.

        # c)	Set the input  source power level to provide  Irated from the EUT. Note: for units that do not
        # adjust output current as a function of their input such as units with energy storage or multimode products
        # the output power is to be commanded.

        # d)	Turn on the EUT.  Set the EUT ramp rate parameters according to Test 1 in Table SA 11.2.

        # e)	Adjust the AC voltage or frequency outside the near nominal range for a period exceeding setting the
        # AC voltage to zero for longer than the must-trip duration.

        # f)	Begin recording the time domain response of the EUT AC voltage and current, and DC voltage and current.

        # g)	Adjust the AC source to the rated nominal operating conditions for the EUT. The EUT shall not
        # commence exporting output current until nominal conditions have been achieved.

        # h)	Stop recording the time domain response after at least the reconnect time of the inverter
        # (e.g. 30 sec. to 5 minutes), plus ramp duration plus a manufacturer-specified dwell time as shown in SA 11.
        # Ramp duration is defined by 100/RRss as appropriate.

        # i)	Repeat steps e-h for a total of 3 repetitions.

        # j)	Repeat steps d-i for Tests 2-3 in Table 11.2.


        # EUT communication parameters
        ifc_type = ts.param_value('comm.ifc_type')
        ifc_name = ts.param_value('comm.ifc_name')
        if ifc_type == client.MAPPED:
            ifc_name = ts.param_value('comm.map_name')
        baudrate = ts.param_value('comm.baudrate')
        parity = ts.param_value('comm.parity')
        ipaddr = ts.param_value('comm.ipaddr')
        ipport = ts.param_value('comm.ipport')
        slave_id = ts.param_value('comm.slave_id')

        # RR parameters
        RRss_min = ts.param_value('ss.RRss_min')
        RRss_max = ts.param_value('ss.RRss_max')
        #Ilow = ts.param_value('ss.Ilow')
        Irated = 100.
        MSARR = ts.param_value('ss.MSARR')
        t_dwell = ts.param_value('ss.t_dwell')

        # Script timing and pass/fail criteria
        pretest_delay = ts.param_value('invt.pretest_delay')
        verification_delay = ts.param_value('invt.verification_delay')
        posttest_delay = ts.param_value('invt.posttest_delay')
        power_threshold = ts.param_value('invt.power_threshold')
        disable = ts.param_value('invt.disable')

        # Data acquisition and triggering methods
        datamethod = ts.param_value('datatrig.dsm_method')
        trigmethod = ts.param_value('datatrig.trigger_method')

        # Step f. Begin recording the time domain response of the EUT AC voltage and current, and DC voltage and current.

        # Step h. Stop recording the time domain response after at least the reconnect time of the inverter
        #         (e.g. 30 sec. to 5 minutes), plus ramp duration plus a manufacturer-specified dwell time as shown in
        #         SA 11. Ramp duration is defined by 100/RRss as appropriate.

        if datamethod == 'Sandia LabView DSM':
            import sandia_dsm as dsm
            das = dsm.Data()
            computer = ts.param_value('datatrig.das_comp')
            if computer == '10 node':
                node = ts.param_value('datatrig.node')

        # Setup trigger if available
        if trigmethod == 'Create Local File for Sandia LabView DSM':
            import sandia_dsm as dsm
            trigger = dsm.Trigger()
            trigger.off()

        # Step b.	Set all AC source parameters to the nominal operating conditions for the EUT.
        # Initialize pv simulation - This is before step (a) because PV power may be required for communications to EUT
        pv = pvsim.pvsim_init(ts)
        pv.power_on()

        grid = gridsim.gridsim_init(ts)

        # Communication is established between the Utility Management System Simulator and EUT
        ts.log('Scanning EUT')
        try:
            inv = client.SunSpecClientDevice(ifc_type, slave_id=slave_id, name=ifc_name, baudrate=baudrate,
                                             parity=parity, ipaddr=ipaddr, ipport=ipport)
        except Exception, e:
            raise script.ScriptFail('Error: %s' % e)

        # Step a.	Connect the EUT according to the instructions and specifications provided by the manufacturer.
        # It is assumed that the  Grid Simulator (if used) is connected to the EUT and operating properly
        inverter.set_power_factor(inv, power_factor=1., enable=0)

        # Step c. Set the input  source power level to provide Irated from the EUT. Note: for units that do not
        # adjust output current as a function of their input such as units with energy storage or multimode
        # products the output power is to be commanded.
        pv.irradiance_set(irradiance=1000)

        # UL 1741 Step j.	Repeat steps d-i for Tests 2-3 in Table 11.2.
        for ramp in [RRss_min, (RRss_min + RRss_max)/2, RRss_max]:

            # Step d.	Turn on the EUT. Set the EUT ramp rate parameters according to Test 1 in Table SA 11.2.
            if pretest_delay > 0:
                ts.log('Waiting for pre-test delay of %d seconds' % pretest_delay)
                ts.sleep(pretest_delay)

            # Verify EUT is in correct state before running the test.
            if inverter.get_conn_state(inv) is False:
                ts.log('Inverter not in correct state, setting state to connected.')
                inverter.set_conn_state(inv, state=1)
                if verify_conn_state_change(inv, orig_state=0, verification_delay=verification_delay,
                                            threshold=power_threshold, das=das) is False:
                    raise script.ScriptFail()

            ''' Revise when SS ramp rate exists in a SunSpec Model
            try:
                inv.settings.read()
                if inv.settings.SSWGra is not None:
                    inv.settings.SSWGra = ramp
                else:
                    ts.log_error('Unable to change ss ramp rate in the EUT.')
            except Exception, e:
                ts.log_error('Error changing ss ramp rate in the EUT: %s' % str(e))
            '''

            for i in xrange(3):  # UL 1741 Step i. Repeat steps e-h two times for a total of 3 repetitions.

                ts.log('Running test number %d with ramp rate %0.3f %%Irated/sec.' % (i+1, ramp))

                # e)	Adjust the AC voltage or frequency outside the near nominal range for a period exceeding
                # setting the AC voltage to zero for longer than the must-trip duration.
                grid.voltage(0)
                time.sleep(1)

                # g)	Adjust the AC source to the rated nominal operating conditions for the EUT. The EUT shall not
                # commence exporting output current until nominal conditions have been achieved.
                grid.voltage(grid.v_nom())
                start_time = time.time()

                # Determine reconnection time
                t_reconnection = 0
                while inverter.get_conn_state(inv) is False:
                    t_reconnection = time.time()-start_time  # Reconnection time updates until the inverter reconnects
                    time.sleep(0.1)

                data_update_rate = 1  # Hz ... parameterize sometime...
                check_duration = 100./ramp
                test_duration = t_dwell + check_duration
                duration = 0
                while duration < test_duration+verification_delay:
                    duration = time.time()-start_time-t_reconnection
                    if duration <= check_duration:  # only check the ramp response during the check_duration
                        ramp_in_bounds = verify_ramp(inv, ramp=ramp, t_since_start=duration, Irated=Irated, MSARR=MSARR,
                                                     das=das)
                        if ramp_in_bounds is False:
                            ts.log_error('Ramp response was not within limits')
                            # raise script.ScriptFail()
                    else:  # The EUT shall reach at least 95% of Irated at the end of the dwell time.
                        ts.log('EUT completed ramping. Waiting for dwell time to check current output. '
                               'Remaining time: %0.3f' % (test_duration - duration))
                        if duration >= test_duration:
                            current_pct = inverter.get_power_norm(inv=inv, das=das)*100
                            ts.log_error('EUT current is %0.3f%%' % current_pct)
                            if current_pct < 95:
                                ts.log_error('EUT did not reach at least 95% of Irated at the end of the dwell time.')
                                raise script.ScriptFail()
                            break
                    time.sleep(1/data_update_rate)  # todo: improve the loop timing

                if posttest_delay > 0:
                    ts.log('Waiting for post-test delay of %d seconds' % posttest_delay)
                    ts.sleep(posttest_delay)

        result = script.RESULT_PASS
Esempio n. 12
0
def test_run():

    result = script.RESULT_FAIL
    data = None
    trigger = None
    inv = None
    pv = None
    disable = None

    try:
        ifc_type = ts.param_value('comm.ifc_type')
        ifc_name = ts.param_value('comm.ifc_name')
        if ifc_type == client.MAPPED:
            ifc_name = ts.param_value('comm.map_name')
        baudrate = ts.param_value('comm.baudrate')
        parity = ts.param_value('comm.parity')
        ipaddr = ts.param_value('comm.ipaddr')
        ipport = ts.param_value('comm.ipport')
        slave_id = ts.param_value('comm.slave_id')

        power_factor = ts.param_value('inv3.power_factor')
        msa_vac = ts.param_value('inv3.MSA_Vac')
        msa_vdc = ts.param_value('inv3.MSA_Vdc')
        p_low = ts.param_value('inv3.p_low')
        p_high = ts.param_value('inv3.p_high')
        v_low = ts.param_value('inv3.v_low')
        v_high = ts.param_value('inv3.v_high')
        pf_acc = ts.param_value('inv3.pf_acc')
        pf_settling_time = ts.param_value('inv3.pf_settling_time')
        dc_nom = ts.param_value('inv3.dc_nom')

        pretest_delay = ts.param_value('invt.pretest_delay')
        power_factor_range = ts.param_value('invt.power_factor_range')
        setpoint_failure_count = ts.param_value('invt.setpoint_failure_count')
        verification_delay = ts.param_value('invt.verification_delay')
        posttest_delay = ts.param_value('invt.posttest_delay')
        disable = ts.param_value('invt.disable')

        # initialize data acquisition system
        daq = das.das_init(ts)
        data = daq.data_init()
        trigger = daq.trigger_init()

        # Initialize pv simulation - Part of UL 1741 Step 1
        pv = pvsim.pvsim_init(ts)
        pv.power_on()

        # Communication is established between the Utility Management System Simulator and EUT
        ts.log('Scanning EUT')
        try:
            inv = client.SunSpecClientDevice(ifc_type, slave_id=slave_id, name=ifc_name, baudrate=baudrate,
                                             parity=parity, ipaddr=ipaddr, ipport=ipport)
        except Exception, e:
            raise script.ScriptFail('Error: %s' % (e))

        # Make sure the EUT is on and operating
        ts.log('Verifying EUT is in connected state. Waiting up to %d seconds for EUT to begin power export.'
               % (verification_delay+pretest_delay))
        if verify_initial_conn_state(inv, state=inverter.CONN_CONNECT,
                                     time_period=verification_delay+pretest_delay, data=data) is False:
                ts.log_error('Inverter unable to be set to connected state.')
                raise script.ScriptFail()

        # Get parameters
        try:
            # This test follows the IEEE Std-1459-2000 reactive power sign convention, in which a leading, capacitive,
            # overexcited power factor is positive and a lagging, inductive, underexcited power factor is negative.

            #  get min/max PF settings
            inv.nameplate.read()
            min_ind_PF = float(inv.nameplate.PFRtgQ1) # negative
            min_cap_PF = float(inv.nameplate.PFRtgQ4) # positive

            inv.controls.read()
            inv.settings.read()
            inv.inverter.read()
            OutPFSet_Ena = inv.controls.OutPFSet_Ena
            ts.log('Power factor is %0.3f.' % float(inv.inverter.PF))
            if OutPFSet_Ena:
                ts.log('Power factor mode is enabled.')
            else:
                ts.log('Power factor mode is not enabled.')

            ts.log('********Parameters of the EUT*************')
            S_rated = float(inv.nameplate.VARtg)
            ts.log('Apparent Power Rating (VA) - S_rated: %.3f.' % S_rated)
            ts.log('EUT Input Power Rating (W) - P_rated: %.3f.' % float(inv.nameplate.WRtg))
            ts.log('DC Voltage range with function enabled (V) - [V_low, V_high]: [%.1f, %.1f].' % (v_low, v_high))
            ts.log('Nominal DC Voltage (V): %.3f.' % dc_nom)
            ts.log('Nominal AC Voltage (V): %.3f.' % float(inv.settings.VRef))
            ts.log('AC Voltage Range with function enabled (V): %.3f to %.3f' %
                   (float(inv.settings.VMin),float(inv.settings.VMax)))
            ts.log('AC Voltage Accuracy (V) - MSA_Vac: %.3f.' % msa_vac)
            ts.log('DC Voltage Accuracy (V) - MSA_Vdc: %.3f.' % msa_vdc)
            ts.log('Active power range of function (%%nameplate) - [P_low, P_high]: [%.1f, %.1f].' % (p_low, p_high))
            ts.log('Power Factor Accuracy: %.3f.' % pf_acc)
            ts.log('Power Factor Settling Time: %.3f.' % pf_settling_time)
            ts.log('Minimum inductive (underexcited) power factor - PF_min,ind: %.3f.' % min_cap_PF)
            ts.log('Minimum capacitive (overexcited) power factor - PF_min,cap: %.3f.' % min_ind_PF)
            ts.log('*******************************************')
            mid_cap_PF = (-1. - min_cap_PF)/2.
            mid_ind_PF = (1. - min_ind_PF)/2.
            ts.log('Power factor target for the test - PF: %.3f.' % power_factor)
            ts.log('PF_mid,cap = half the EUT capacitive range: %.3f.' % mid_cap_PF)
            ts.log('PF_mid,ind = half the EUT inductive range: %.3f.' % mid_ind_PF)
            ts.log('P_limit, the maximum output power (W): %.3f.' % float(inv.settings.WMax))
            ts.log('Q_rated, the reactive power rating of the EUT (VAr): %.3f.' % float(inv.settings.VArMaxQ1))
            p_x = math.fabs(power_factor)*100
            ts.log('P_X, the maximum input power which an "Active Power Priority" mode maintains the PF '
                   'command (%%nameplate): %.3f.' % p_x)
            ts.log('*******************************************')

        except Exception, e:
            raise script.ScriptFail('Unable to get PF limits or other data from EUT: %s' % str(e))
Esempio n. 13
0
def test_run():

    result = script.RESULT_FAIL
    data = None
    trigger = None
    grid = None
    pv = None
    inv = None
    volt = {}
    var = {}
    disable = None

    try:
        ifc_type = ts.param_value('comm.ifc_type')
        ifc_name = ts.param_value('comm.ifc_name')
        if ifc_type == client.MAPPED:
            ifc_name = ts.param_value('comm.map_name')
        baudrate = ts.param_value('comm.baudrate')
        parity = ts.param_value('comm.parity')
        ipaddr = ts.param_value('comm.ipaddr')
        ipport = ts.param_value('comm.ipport')
        slave_id = ts.param_value('comm.slave_id')

        vv_mode = ts.param_value('vv.settings.vv_mode')
        if vv_mode == 'VV11 (watt priority)':
            deptRef = inverter.VOLTVAR_WMAX
        elif vv_mode == 'VV12 (var priority)':
            deptRef = inverter.VOLTVAR_VARMAX
        elif vv_mode == 'VV13 (fixed var)':
            deptRef = inverter.VOLTVAR_VARAVAL
            fixedVar = ts.param_value('vv.settings.fixedVar')
            var[1] = fixedVar # Not very clean - will pull 'points' info out later for pass/fail bounds
            fixedVarRef = ts.param_value('vv.settings.fixedVarRef')
            if fixedVarRef == '%VarAval':
                volt[1] = 1 # Not very clean - will pull 'points' info out later for pass/fail bounds
            elif fixedVarRef ==  '%WMax':
                volt[1] = 2 # Not very clean - will pull 'points' info out later for pass/fail bounds
            else: #fixedVarRef == '%VarMax'
                volt[1] = 3 # Not very clean - will pull 'points' info out later for pass/fail bounds
        else:
            deptRef = 4

        time_window = ts.param_value('vv.settings.time_window')
        timeout_period = ts.param_value('vv.settings.timeout_period')
        ramp_time = ts.param_value('vv.settings.ramp_time')

        if vv_mode == 'VV11 (watt priority)' or vv_mode == 'VV12 (var priority)':
            n_points = ts.param_value('vv.settings.n_points')
            curve_num = ts.param_value('vv.settings.curve_num')
            volt = ts.param_value('vv.curve.volt')
            var = ts.param_value('vv.curve.var')

        var_range = ts.param_value('invt.var_range')
        setpoint_period = ts.param_value('invt.setpoint_period')
        pretest_delay = ts.param_value('invt.pretest_delay')
        setpoint_failure_count = ts.param_value('invt.setpoint_failure_count')
        verification_delay = ts.param_value('invt.verification_delay')
        posttest_delay = ts.param_value('invt.posttest_delay')
        disable = ts.param_value('invt.disable')

        # initialize data acquisition system
        daq = das.das_init(ts)
        data = daq.data_init()
        trigger = daq.trigger_init()

        # initialize pv simulation
        pv = pvsim.pvsim_init(ts)
        pv.power_on()

        # initialize grid simulation
        grid = gridsim.gridsim_init(ts)
        profile_name = ts.param_value('profile.profile_name')
        grid.profile_load(profile_name)

        #Inverter scan after grid and PV simulation setup so that Modbus registers can be read.
        ts.log('Scanning inverter')
        inv = client.SunSpecClientDevice(ifc_type, slave_id=slave_id, name=ifc_name, baudrate=baudrate, parity=parity,
                                         ipaddr=ipaddr, ipport=ipport)

        # Make sure the EUT is on and operating
        ts.log('Verifying EUT is in connected state. Waiting up to %d seconds for EUT to begin power export.'
               % (verification_delay+pretest_delay))
        if verify_initial_conn_state(inv, state=inverter.CONN_CONNECT,
                                     time_period=verification_delay+pretest_delay, data=data) is False:
                ts.log_error('Inverter unable to be set to connected state.')
                raise script.ScriptFail()

        ######## Begin Test ########
        if pretest_delay > 0:
            ts.log('Waiting for pre-test delay of %d seconds' % pretest_delay)
            ts.sleep(pretest_delay)

        # Request status from EUT and display vars
        var_original = inverter.get_var(inv, das=data)
        ts.log('Current reactive power is %.3f VAr' % var_original)

        #ts.log_debug('SET volt and var are: %s, %s' % (volt, var))
        #inv.volt_var.read()
        #ts.log_debug('inv.volt_var.ActCrv = %d' % inv.volt_var.ActCrv)
        inverter.set_volt_var(inv, volt=volt, var=var, n_points=n_points, time_window=time_window,
                              timeout_period=timeout_period, ramp_time=ramp_time,
                              curve_num=curve_num, deptRef=deptRef, enable=1, trigger=trigger)

        # Run the grid simulator profile immediately after setting the volt-var functions and triggering
        if grid is not None:
            ts.log('Running voltage profile.')
            grid.profile_start()

        inv.nameplate.read()
        VarAval = inv.nameplate.VArRtgQ1
        WAval = inv.nameplate.WRtg

        varTarg, var_upper, var_lower = var_pass_fail_band(inv, volt=volt, var=var, n_points=n_points,
                                                           var_range=var_range, deptRef=deptRef, data=data)

        ts.log('Target vars: %.3f. Pass limits for screening: lower = %.3f  upper = %.3f' %
               (varTarg, var_lower, var_upper))

        # Log VV parameters and calculate test_duration
        test_duration = setpoint_period + verification_delay
        ts.log('Waiting up to %d seconds for power change with a verification period of %d seconds.' %
               (ramp_time + time_window , verification_delay))

        start_time = time.time()
        elapsed_time = 0

        # Initialize consecutive failure count to not script fail on transient behavior
        failures = 0
        revert_complete = False

        if time_window != 0:
            window_complete = False
        else:
            window_complete = True
        time_window_execution = time_window

        while elapsed_time <= test_duration:
            ts.sleep(0.93)
            elapsed_time = time.time()-start_time

            current_vars = inverter.get_var(inv, das=data)
            if window_complete == True and revert_complete == False:
                varTarg, var_upper, var_lower = var_pass_fail_band(inv, volt=volt, var=var, n_points=n_points,
                                                               var_range=var_range, deptRef=deptRef, data=data)
            else:
                # Before the time window executes and after timeout period, the upper and lower pass/fail bounds for EUT
                # use the default volt-var state of 0 vars
                varTarg = 0
                inv.nameplate.read()
                var_upper = var_range/100.*float(inv.nameplate.VArRtgQ1) #var_range is %max_Var
                var_lower = -(var_range/100.*float(inv.nameplate.VArRtgQ1)) #var_range is %max_Var

            # Cheat a little since var is unsigned from data (and inverter?)
            if varTarg < 0 and current_vars > 0:
                current_vars = -current_vars

            ts.log('Var Target = %.3f [%.3f to %.3f], Vars = %.3f (Total Error = %.3f%%), Time: %0.3f seconds.' %
                   (varTarg, var_lower, var_upper, current_vars, (current_vars - varTarg)/VarAval*100.0, elapsed_time))

            if not revert_complete:

                # Check when the EUT is in range for the first time
                if window_complete == False and inverter.get_active_control_status(inv, inverter.STACTCTL_VOLT_VAR):
                    window_complete = True
                    time_window_execution = elapsed_time
                    ts.log('Randomization window occurred at %0.3f seconds, current vars %.3f.' %
                           (time_window_execution, current_vars))

                # Check for timeout period (reversion)
                if window_complete and timeout_period != 0:

                    #ts.log_debug('Volt-Var mode is: %d' %
                    #             inverter.get_active_control_status(inv, inverter.STACTCTL_VOLT_VAR))
                    #ts.log_debug('Is revert complete? %s' % revert_complete)

                    #### Update this section with the following line when firmware is updated
                    #if not inverter.get_active_control_status(inv, inverter.STACTCTL_VOLT_VAR): #reverted
                    if elapsed_time > timeout_period: #To be changed at a later date
                        revert_complete = True
                        ts.log('Reversion occurred at timeout period = %0.3f seconds, current vars %.3f.'
                                % (elapsed_time, current_vars))

                    # Did timeout_period fail?  If so, end the test here.
                    # Note: there's a final timeout_period check outside the while loop.
                    elif elapsed_time >= timeout_period+min(time_window,time_window_execution)+verification_delay:
                        ts.log_error('Inverter did not revert after %0.3f seconds.' % (elapsed_time))
                        raise script.ScriptFail()

                # if vars out of range
                if current_vars < var_lower or current_vars > var_upper:
                    # There are three acceptable sources of noncompliance. If the randomization window hasn't occurred,
                    # the reversion (timeout) occurred, or it is ramping to the target vars
                    if window_complete == False: #time window
                        ts.log('Randomization window still in effect after %0.3f seconds.' % (time.time()-start_time))
                    elif elapsed_time > min(time_window,time_window_execution)+ramp_time:
                        # Noncompliance is not from time period, time window, or ramp rate
                        # Count this as a failure
                        failures += 1
                        if failures >= setpoint_failure_count:
                            ts.log_error('Inverter exceeded var setpoint + buffer after %0.3f seconds. '
                                         'Fail count = %d.' % (elapsed_time,failures))
                            raise script.ScriptFail()
                        else:
                            ts.log_warning('Inverter exceeded var setpoint + buffer after %0.3f seconds. '
                                           'Fail count = %d.' % (elapsed_time,failures))
                    else:
                        ts.log_warning('EUT has not reached the target reactive power because it is ramping.')
                else:
                    failures = 0

        # Additional timeout check to determine if the timeout_period occurred during the test. This is necessary
        # in cases where the verification_delay is not set sufficiently long.
        if timeout_period != 0 and inverter.get_active_control_status(inv, inverter.STACTCTL_VOLT_VAR):
            ts.log_error('Inverter did not revert by the end of the test duration. Elapsed time = %0.3f seconds.  '
                         'Increase the verification period if the timeout period is greater than the elapsed time.'
                         % (elapsed_time))
            raise script.ScriptFail()

        if posttest_delay > 0:
            ts.log('Waiting for post-test delay of %d seconds' % posttest_delay)
            ts.sleep(posttest_delay)

        result = script.RESULT_PASS

    except script.ScriptFail, e:
        reason = str(e)
        if reason:
            ts.log_error(reason)
Esempio n. 14
0
def test_run():

    result = script.RESULT_FAIL
    data = None
    trigger = None
    inv = None
    pv = None
    disable = None

    try:
        ifc_type = ts.param_value('comm.ifc_type')
        ifc_name = ts.param_value('comm.ifc_name')
        if ifc_type == client.MAPPED:
            ifc_name = ts.param_value('comm.map_name')
        baudrate = ts.param_value('comm.baudrate')
        parity = ts.param_value('comm.parity')
        ipaddr = ts.param_value('comm.ipaddr')
        ipport = ts.param_value('comm.ipport')
        slave_id = ts.param_value('comm.slave_id')

        power_factor = ts.param_value('inv3.power_factor')
        ramp_time = ts.param_value('inv3.ramp_time')  # time to ramp
        time_window = ts.param_value('inv3.time_window')
        timeout_period = ts.param_value('inv3.timeout_period')

        pretest_delay = ts.param_value('invt.pretest_delay')
        power_factor_range = ts.param_value('invt.power_factor_range')
        setpoint_failure_count = ts.param_value('invt.setpoint_failure_count')
        setpoint_period = ts.param_value('invt.setpoint_period')
        verification_delay = ts.param_value('invt.verification_delay')
        posttest_delay = ts.param_value('invt.posttest_delay')
        disable = ts.param_value('invt.disable')

        # initialize data acquisition system
        daq = das.das_init(ts)
        data = daq.data_init()
        trigger = daq.trigger_init()

        # initialize pv simulation
        pv = pvsim.pvsim_init(ts)
        pv.irradiance_set(ts.param_value('profile.irr_start'))
        pv.profile_load(ts.param_value('profile.profile_name'))
        pv.power_on()

        # Sandia Test Protocol: Communication is established between the Utility Management System Simulator and EUT
        ts.log('Scanning EUT')
        try:
            # Sandia Test Protocol Step 1: Request status of EUT
            # Sandia Test Protocol Step 2: UMS receives response from EUT
            inv = client.SunSpecClientDevice(ifc_type,
                                             slave_id=slave_id,
                                             name=ifc_name,
                                             baudrate=baudrate,
                                             parity=parity,
                                             ipaddr=ipaddr,
                                             ipport=ipport)
        except Exception, e:
            raise script.ScriptFail('Error: %s' % (e))

        if pretest_delay > 0:
            ts.log('Waiting for pre-test delay of %d seconds' % pretest_delay)
            ts.sleep(pretest_delay)

        # Make sure the EUT is on and operating
        ts.log(
            'Verifying EUT is in connected state. Waiting up to %d seconds for EUT to begin power export.'
            % (verification_delay + pretest_delay))
        if verify_initial_conn_state(
                inv,
                state=inverter.CONN_CONNECT,
                time_period=verification_delay + pretest_delay,
                data=data) is False:
            ts.log_error('Inverter unable to be set to connected state.')
            raise script.ScriptFail()

        # Get parameters
        try:
            inv.nameplate.read()
            # get min/max PF settings
            min_PF = float(inv.nameplate.PFRtgQ1)
            max_PF = float(inv.nameplate.PFRtgQ4)
            ts.log('Power factor range for this device is %.3f to %.3f' %
                   (min_PF, max_PF))

            # Sandia Test Protocol Step 3: EUT output power factor is measured and logged
            # Get INV3 settings and report these.

            # Get PF from EUT
            pf = inverter.get_power_factor(inv, das=data)
            ts.log('Power factor is %f.' % pf)
        except Exception, e:
            raise script.ScriptFail(
                'Unable to get PF limits or PF from EUT: %s' % str(e))
Esempio n. 15
0
def test_run():

    result = script.RESULT_FAIL
    data = None
    trigger = None
    inv = None
    pv = None
    disable = None

    try:
        ifc_type = ts.param_value('comm.ifc_type')
        ifc_name = ts.param_value('comm.ifc_name')
        if ifc_type == client.MAPPED:
            ifc_name = ts.param_value('comm.map_name')
        baudrate = ts.param_value('comm.baudrate')
        parity = ts.param_value('comm.parity')
        ipaddr = ts.param_value('comm.ipaddr')
        ipport = ts.param_value('comm.ipport')
        slave_id = ts.param_value('comm.slave_id')

        power_limit_pct = ts.param_value('inv2.power_limit_pct')
        ramp_time = ts.param_value(
            'inv2.ramp_time')  # slope defined by % nameplate power/sec
        time_window = ts.param_value('inv2.time_window')
        timeout_period = ts.param_value('inv2.timeout_period')

        pretest_delay = ts.param_value('invt.pretest_delay')
        power_limit_pct_buffer = ts.param_value('invt.power_limit_pct_buffer')
        screening_period = ts.param_value('invt.screening_period')
        setpoint_failure_count = ts.param_value('invt.setpoint_failure_count')
        verification_delay = ts.param_value('invt.verification_delay')
        posttest_delay = ts.param_value('invt.posttest_delay')
        disable = ts.param_value('invt.disable')

        # initialize data acquisition system
        daq = das.das_init(ts)
        data = daq.data_init()
        trigger = daq.trigger_init()

        # initialize pv simulation
        pv = pvsim.pvsim_init(ts)
        pv.irradiance_set(ts.param_value('profile.irr_start'))
        pv.profile_load(ts.param_value('profile.profile_name'))
        pv.power_on()

        # Sandia Test Protocol: Communication is established between the Utility Management System Simulator
        # and EUT
        ts.log('Scanning EUT')
        try:
            inv = client.SunSpecClientDevice(ifc_type,
                                             slave_id=slave_id,
                                             name=ifc_name,
                                             baudrate=baudrate,
                                             parity=parity,
                                             ipaddr=ipaddr,
                                             ipport=ipport)
        except Exception, e:
            raise script.ScriptFail('Error: %s' % (e))

        if pretest_delay > 0:
            ts.log('Waiting for pre-test delay of %d seconds' % pretest_delay)
            ts.sleep(pretest_delay)

        # Make sure the EUT is on and operating
        ts.log(
            'Verifying EUT is in connected state. Waiting up to %d seconds for EUT to begin power export.'
            % (verification_delay + pretest_delay))
        if verify_initial_conn_state(
                inv,
                state=inverter.CONN_CONNECT,
                time_period=verification_delay + pretest_delay,
                data=data) is False:
            ts.log_error('Inverter unable to be set to connected state.')
            raise script.ScriptFail()

        # Sandia Test Protocol Step 1: Request status of EUT
        # Sandia Test Protocol Step 2: UMS receives response from EUT
        try:
            inv.settings.read()
            power_max = int(inv.settings.WMax)
            ts.log('Inverter maximum power = %d W' % (power_max))
        except Exception, e:
            raise ('Unable to get WMax setting: %s' % str(e))
Esempio n. 16
0
def test_run():

    result = script.RESULT_FAIL
    daq = None

    try:

        p_rated = ts.param_value('ratings.p_rated')
        pf_min_ind = ts.param_value('ratings.pf_min_ind')
        pf_min_cap = ts.param_value('ratings.pf_min_cap')
        pf_settling_time = ts.param_value('ratings.pf_settling_time')
        pf_target = ts.param_value('ratings.pf_target')

        p_low = p_rated * .2
        pf_mid_ind = (1 + pf_min_ind) / 2
        pf_mid_cap = (-1 + pf_min_cap) / 2

        pf_target_value = {
            'PF_min_ind': pf_min_ind,
            'PF_mid_ind': pf_mid_ind,
            'PF_min_cap': pf_min_cap,
            'PF_mid_cap': pf_mid_cap
        }
        '''
        2) Set all AC source parameters to the normal operating conditions for the EUT. 
        '''
        # grid simulator is initialized with test parameters and enabled
        grid = gridsim.gridsim_init(ts)

        # pv simulator is initialized with test parameters and enabled
        pv = pvsim.pvsim_init(ts)
        pv.power_set(p_low)
        pv.power_on()

        # initialize data acquisition
        daq = das.das_init(ts)
        '''
        3) Turn on the EUT. It is permitted to set all L/HVRT limits and abnormal voltage trip parameters to the
        widest range of adjustability possible with the SPF enabled in order not to cross the must trip
        magnitude threshold during the test.
        '''
        # it is assumed the EUT is on
        eut = der.der_init(ts)
        eut.config()
        '''
        4) Select 'Fixed Power Factor' operational mode.
        '''
        # fixed power factor mode is enabled in test

        # table SA 12.1 - SPF test parameters
        if pf_target == 'All':
            pf_table = [pf_min_ind, pf_mid_ind, pf_min_cap, pf_mid_cap]
        else:
            pf_table = [pf_target_value.get(pf_target)]

        for pf in pf_table:
            for power_level in [1, .2, .5]:
                '''
                5) Set the input source to produce Prated for the EUT.
                '''
                pv.power_set(p_rated * power_level)
                ts.log('*** Setting power level to %s W (rated power * %s)' %
                       ((p_rated * power_level), power_level))

                for count in range(1, 4):
                    ts.log('Starting pass %s' % (count))
                    '''
                    6) Set the EUT power factor to unity. Measure the AC source voltage and EUT current to measure the
                    displacement
                    '''
                    #ts.log('Fixed PF settings: %s' % eut.fixed_pf())
                    eut.fixed_pf(params={'Ena': True, 'PF': 1.0})
                    ts.log('Starting data capture for pf = %s' % (1.0))
                    daq.data_capture(True)
                    ts.sleep(pf_settling_time * 3)
                    daq.data_capture(False)
                    ds = daq.data_capture_dataset()
                    ds.to_csv(
                        ts.result_file('PF_1_%s_%s.csv') %
                        (str(power_level), str(count)))
                    ts.log('Saving data capture')
                    '''
                    7) Set the EUT power factor to the value in Test 1 of Table SA12.1. Measure the AC source voltage
                    and EUT current to measure the displacement power factor and record all data.
                    '''
                    eut.fixed_pf(params={'Ena': True, 'PF': pf})
                    ts.log('Starting data capture for pf = %s' % (pf))
                    daq.data_capture(True)
                    ts.sleep(pf_settling_time * 3)
                    daq.data_capture(False)
                    ds = daq.data_capture_dataset()
                    ds.to_csv(
                        ts.result_file('PF_%s_%s_%s.csv') %
                        (str(pf), str(power_level), str(count)))
                    '''
                    8) Repeat steps (6) - (8) for two additional times for a total of three repetitions.
                    '''
                '''
                9) Repeat steps (5) - (7) at two additional power levels. One power level shall be a Pmin or 20% of
                Prated and the second at any power level between 33% and 66% of Prated.
                '''
            '''
            10) Repeat Steps (6) - (9) for Tests 2 - 5 in Table SA12.1
            '''
        '''
        11) In the case of bi-directional inverters, repeat Steps (6) - (10) for the active power flow direction
        '''

        result = script.RESULT_COMPLETE

    except script.ScriptFail, e:
        reason = str(e)
        if reason:
            ts.log_error(reason)
Esempio n. 17
0
def test_run():

    result = script.RESULT_FAIL
    daq = None

    try:

        p_rated = ts.param_value('ratings.p_rated')
        pf_min_ind = ts.param_value('ratings.pf_min_ind')
        pf_min_cap = ts.param_value('ratings.pf_min_cap')
        pf_settling_time = ts.param_value('ratings.pf_settling_time')
        pf_target = ts.param_value('ratings.pf_target')

        p_low = p_rated * .2
        pf_mid_ind = (1 + pf_min_ind)/2
        pf_mid_cap = (-1 + pf_min_cap)/2

        pf_target_value = {'PF_min_ind': pf_min_ind, 'PF_mid_ind': pf_mid_ind,
                           'PF_min_cap': pf_min_cap, 'PF_mid_cap': pf_mid_cap}


        '''
        2) Set all AC source parameters to the normal operating conditions for the EUT. 
        '''
        # grid simulator is initialized with test parameters and enabled
        grid = gridsim.gridsim_init(ts)

        # pv simulator is initialized with test parameters and enabled
        pv = pvsim.pvsim_init(ts)
        pv.power_set(p_low)
        pv.power_on()

        # initialize data acquisition
        daq = das.das_init(ts)

        '''
        3) Turn on the EUT. It is permitted to set all L/HVRT limits and abnormal voltage trip parameters to the
        widest range of adjustability possible with the SPF enabled in order not to cross the must trip
        magnitude threshold during the test.
        '''
        # it is assumed the EUT is on
        eut = der.der_init(ts)
        eut.config()

        '''
        4) Select 'Fixed Power Factor' operational mode.
        '''
        # fixed power factor mode is enabled in test

        # table SA 12.1 - SPF test parameters
        if pf_target == 'All':
            pf_table = [pf_min_ind, pf_mid_ind, pf_min_cap, pf_mid_cap]
        else:
            pf_table = [pf_target_value.get(pf_target)]

        for pf in pf_table:
            for power_level in [1, .2, .5]:
                '''
                5) Set the input source to produce Prated for the EUT.
                '''
                pv.power_set(p_rated * power_level)
                ts.log('*** Setting power level to %s W (rated power * %s)' % ((p_rated * power_level), power_level))

                for count in range(1, 4):
                    ts.log('Starting pass %s' % (count))
                    '''
                    6) Set the EUT power factor to unity. Measure the AC source voltage and EUT current to measure the
                    displacement
                    '''
                    #ts.log('Fixed PF settings: %s' % eut.fixed_pf())
                    eut.fixed_pf(params={'Ena': True, 'PF': 1.0})
                    ts.log('Starting data capture for pf = %s' % (1.0))
                    daq.data_capture(True)
                    ts.sleep(pf_settling_time * 3)
                    daq.data_capture(False)
                    ds = daq.data_capture_dataset()
                    ds.to_csv(ts.result_file('PF_1_%s_%s.csv') % (str(power_level), str(count)))
                    ts.log('Saving data capture')

                    '''
                    7) Set the EUT power factor to the value in Test 1 of Table SA12.1. Measure the AC source voltage
                    and EUT current to measure the displacement power factor and record all data.
                    '''
                    eut.fixed_pf(params={'Ena': True, 'PF': pf})
                    ts.log('Starting data capture for pf = %s' % (pf))
                    daq.data_capture(True)
                    ts.sleep(pf_settling_time * 3)
                    daq.data_capture(False)
                    ds = daq.data_capture_dataset()
                    ds.to_csv(ts.result_file('PF_%s_%s_%s.csv') % (str(pf), str(power_level), str(count)))

                    '''
                    8) Repeat steps (6) - (8) for two additional times for a total of three repetitions.
                    '''
                '''
                9) Repeat steps (5) - (7) at two additional power levels. One power level shall be a Pmin or 20% of
                Prated and the second at any power level between 33% and 66% of Prated.
                '''
            '''
            10) Repeat Steps (6) - (9) for Tests 2 - 5 in Table SA12.1
            '''

        '''
        11) In the case of bi-directional inverters, repeat Steps (6) - (10) for the active power flow direction
        '''

        result = script.RESULT_COMPLETE

    except script.ScriptFail, e:
        reason = str(e)
        if reason:
            ts.log_error(reason)
Esempio n. 18
0
def test_run():

    result = script.RESULT_FAIL
    data = None
    trigger = None
    grid = None
    pv = None
    inv = None
    volt = {}
    var = {}
    disable = None

    try:
        ifc_type = ts.param_value('comm.ifc_type')
        ifc_name = ts.param_value('comm.ifc_name')
        if ifc_type == client.MAPPED:
            ifc_name = ts.param_value('comm.map_name')
        baudrate = ts.param_value('comm.baudrate')
        parity = ts.param_value('comm.parity')
        ipaddr = ts.param_value('comm.ipaddr')
        ipport = ts.param_value('comm.ipport')
        slave_id = ts.param_value('comm.slave_id')

        var_ramp_rate = ts.param_value('vv.settings.var_ramp_rate')  # time to ramp
        msa_var = ts.param_value('vv.settings.MSA_VAr')
        v_low = ts.param_value('vv.settings.v_low')
        v_high = ts.param_value('vv.settings.v_high')
        k_varmax = ts.param_value('vv.settings.k_varmax')
        v_deadband_min = ts.param_value('vv.settings.v_deadband_min')
        v_deadband_max = ts.param_value('vv.settings.v_deadband_max')
        manualcurve = ts.param_value('vv.settings.manualcurve')
        settling_time = ts.param_value('vv.settings.settling_time')

        vv_mode = ts.param_value('vv.settings.vv_mode')
        if vv_mode == 'VV11 (watt priority)':
            deptRef = inverter.VOLTVAR_WMAX
        elif vv_mode == 'VV12 (var priority)':
            deptRef = inverter.VOLTVAR_VARMAX
        elif vv_mode == 'VV13 (fixed var)':
            deptRef = inverter.VOLTVAR_VARAVAL
            fixedVar = ts.param_value('vv.settings.fixedVar')
            var[1] = fixedVar # Not very clean - will pull 'points' info out later for pass/fail bounds
            fixedVarRef = ts.param_value('vv.settings.fixedVarRef')
            if fixedVarRef == '%VarAval':
                volt[1] = 1 # Not very clean - will pull 'points' info out later for pass/fail bounds
            elif fixedVarRef ==  '%WMax':
                volt[1] = 2 # Not very clean - will pull 'points' info out later for pass/fail bounds
            else: #fixedVarRef == '%VarMax'
                volt[1] = 3 # Not very clean - will pull 'points' info out later for pass/fail bounds
        else:
            deptRef = 4

        if vv_mode == 'VV11 (watt priority)' or vv_mode == 'VV12 (var priority)':
            curve_num = ts.param_value('vv.settings.curve_num')
            volt = ts.param_value('vv.curve.volt')
            var = ts.param_value('vv.curve.var')
            if manualcurve is 'Manual':
                n_points = ts.param_value('vv.settings.n_points')
            else:
                n_points = 4

        var_range = ts.param_value('invt.var_range')
        pretest_delay = ts.param_value('invt.pretest_delay')
        verification_delay = ts.param_value('invt.verification_delay')
        posttest_delay = ts.param_value('invt.posttest_delay')
        voltage_tests_per_line = ts.param_value('invt.voltage_tests_per_line')
        test_on_vv_points = ts.param_value('invt.test_on_vv_points')
        disable = ts.param_value('invt.disable')

        ''' UL 1741 requirements from the Feb 2015 Draft
        1. Connect the EUT according to the Requirements in Sec. 4.3.1 and specifications provided by the manufacturer.
        2. Set all AC source parameters to the nominal operating conditions for the EUT. Frequency is set at nominal
        and held at nominal throughout this test. Set the input power to the value to Prated.
        3. Turn on the EUT.  Set all R21-1-L/HVRT parameters to the widest range of adjustability possible with the
        R21-1-VV11 enabled.
        4. If the EUT has the ability to set "Real Power Priority" or "Reactive Power Priority", select
        "Reactive Power Priority".
        5. Set the EUT to provide reactive power according to the Q(V) characteristic defined in Test 1 in Table 10.
        6. Begin recording the time domain response of the EUT AC voltage and current, and DC voltage and current.
        Step down the AC voltage until at least three points  are recorded in each line segment of the characteristic
        curve or the EUT trips from the LVRT must trip requirements.  Continue recording the time domain response for
        at least twice the settling time after each voltage step.
        7. Repeat Step 6, raising the AC voltage until at least three points  are recorded in each line segment of the
        characteristic curve or the EUT trips from HVRT must trip requirements.
        8. Repeat steps 6 - 7 four more times, for a total of five sweeps  of the Q(V) curve.
        9. Repeat test steps 5 - 8 at power levels 20% and 60% of Prated by reducing the DC voltage of the Input
        Source.
        10. Repeat steps 6 - 9 for the remaining tests in Table 10.
        '''

        # initialize data acquisition system
        daq = das.das_init(ts)
        data = daq.data_init()
        trigger = daq.trigger_init()

        # initialize pv simulation
        pv = pvsim.pvsim_init(ts)
        pv.power_on()

        # UL 1741 SA Step 2: Set all AC source parameters to the nominal operating conditions for the EUT
        # initialize grid simulation
        grid = gridsim.gridsim_init(ts)
        if grid:
            gridsim_v_nom = grid.v_nom()

        #Put inverter scan after grid and PV simulation setup so that Modbus registers can be read.
        ts.log('Scanning inverter')
        inv = client.SunSpecClientDevice(ifc_type, slave_id=slave_id, name=ifc_name, baudrate=baudrate, parity=parity,
                                         ipaddr=ipaddr, ipport=ipport)

        # Make sure the EUT is on and operating
        ts.log('Verifying EUT is in connected state. Waiting up to %d seconds for EUT to begin power export.'
               % (verification_delay+pretest_delay))
        if verify_initial_conn_state(inv, state=inverter.CONN_CONNECT,
                                     time_period=verification_delay+pretest_delay, data=data) is False:
                ts.log_error('Inverter unable to be set to connected state.')
                raise script.ScriptFail()

        # Get parameters
        try:
            inv.nameplate.read()
            inv.controls.read()
            inv.settings.read()
        except Exception, e:
            raise script.ScriptFail('Unable to get parameters from EUT: %s' % str(e))

        ts.log('********Parameters of the EUT*************')
        S_rated = float(inv.nameplate.VARtg)
        ts.log('Apparent Power Rating (VA) - S_rated: %.3f.' % S_rated)
        ts.log('EUT Input Power Rating (W) - P_rated: %.3f.' % float(inv.nameplate.WRtg))
        ts.log('DC Voltage range with function enabled (V) - [V_low, V_high]: [%.1f, %.1f].' % (v_low, v_high))
        v_nom = float(inv.settings.VRef)
        ts.log('Nominal AC Voltage (V): %.3f.' % v_nom)
        v_min = float(inv.settings.VMin)
        v_max = float(inv.settings.VMax)
        ts.log('AC Voltage Range with function enabled (V): %.3f to %.3f' % (v_min,v_max))
        ts.log('VAr Accuracy (VAr) - MSA_VAr: %.3f.' % msa_var)
        ts.log('Max reactive power ramp rate (VAr/s): %.3f.' % var_ramp_rate)
        Q_max_cap = float(inv.settings.VArMaxQ1)
        Q_max_ind = float(inv.settings.VArMaxQ4) # negative
        ts.log('Minimum inductive (underexcited) reactive power - Q_max,ind: %.3f.' % Q_max_ind) # negative
        ts.log('Minimum capacitive (overexcited) reactive power - Q_max,cap: %.3f.' % Q_max_cap)
        ts.log('Maximum slope (VAr/V), K_varmax: %.3f.' % k_varmax)
        ts.log('Deadband range (V): [%.1f, %.1f].' % (v_deadband_min, v_deadband_max))
        ts.log('*******************************************')
        Q_min_cap = Q_max_cap/4.
        Q_min_ind = Q_max_ind/4. #negative
        #v_avg = (v_min + v_max)/2.
        v_min_dev = min(v_nom - v_min, v_max - v_nom)
        v_deadband_avg = (v_deadband_min + v_deadband_max)/2.
        k_varmin = Q_min_cap/(v_min_dev - v_deadband_max/2.)
        k_varavg = (k_varmin + k_varmax)/2.
        ts.log('Q_mid,cap = half the EUT capacitive VAr range: %.3f.' % Q_min_cap)
        ts.log('Q_mid,ind = half the EUT inductive VAr range: %.3f.' % Q_min_ind)
        #ts.log('V_avg = halfway point for the operating ac voltage of the function: %.3f.' % v_avg)
        ts.log('K_varavg: %.3f.' % k_varavg)
        ts.log('K_varmin: %.3f.' % k_varmin)
        ts.log('Average voltage deadband: %.3f.' % v_deadband_avg)

        ts.log('********Required Test Points for UL 1741*************')
        volt, var = volt_var_set(v_nom=240., volt=volt, var=var, v_deadband_max=v_deadband_max,
                                 v_deadband_avg=v_deadband_avg, v_deadband_min=v_deadband_min, Q_max_cap=Q_max_cap,
                                 Q_max_ind=Q_max_ind, k_varmax=k_varmax, k_varavg=k_varavg,
                                 k_varmin=k_varmin, manualcurve=manualcurve)

        ######## Begin Test ########
        # UL 1741 SA Step 3: if applicable set LVRT/HVRT settings here.

        # Request status from EUT and display vars
        var_original = inverter.get_var(inv, das=data)
        ts.log('Current reactive power is %.3f VAr' % var_original)

        # UL 1741 SA Step 4 (using deptRef) and Step 5 (setting the Q(V) characteristic curve)
        inverter.set_volt_var(inv, volt=volt, var=var, n_points=n_points,
                              curve_num=curve_num, deptRef=deptRef, enable=1)

        #voltage_pct_test_points = np.linspace(0., 100., voltage_tests_per_line)
        #ts.log('test_on_vv_points == Yes: %s' % voltage_pct_test_points)
        #voltage_pct_test_points = np.linspace(0., 100., voltage_tests_per_line+2)
        #voltage_pct_test_points = voltage_pct_test_points[1:-1]
        #ts.log('test_on_vv_points == No: %s' % voltage_pct_test_points)

        if test_on_vv_points == 'Yes':
            # the test points are on the (V,Q) points
            voltage_pct_test_points = np.linspace(0., 100., voltage_tests_per_line)
            ts.log('Test points will at %s %% of the volt-var curve segments.' % voltage_pct_test_points)
        else:
            # the test points are not on the (V,Q) points
            voltage_pct_test_points = np.linspace(0., 100., voltage_tests_per_line+2)
            voltage_pct_test_points = voltage_pct_test_points[1:-1]
            ts.log('Test points will at %s %% of the volt-var curve segments.' % voltage_pct_test_points)

        lines_to_test = volt['index_count']+1 # There are 1 more line than there are (V,Q) points

        for irradiance in [1000, 200, 600]:
            ts.log('DC power level is %.3f %% nameplate, so the simulator power level is set to %.1f W/m^2' %
                   (irradiance/10., irradiance))
            pv.irradiance_set(irradiance=irradiance)

            for repeats in xrange(1,6): # UL 1741 Step 8: Repeat the test 5 times
                ts.log('    Running volt-var sweep number %d.' % (repeats))

                if pretest_delay > 0:
                    ts.log('    Waiting for pre-test delay of %d seconds' % pretest_delay)
                    ts.sleep(pretest_delay)

                for j in xrange(lines_to_test):
                    for i in voltage_pct_test_points:
                        ts.log('    Testing the reactive power on curve segment %d at %d%% down the line segment.'
                               % (j+1,i))
                        voltage_pct = grid_voltage_get(inv, volt=volt, var=var, v_nom=v_nom,
                                                       line_to_test=j+1, voltage_pct_test_point=i)

                        # Set grid simulator voltage immediately prior to triggering
                        if grid is not None:
                            ts.log('        Setting ac voltage percentage = %.2f.%%. Simulator voltage = %.2f' %
                                   (voltage_pct,(voltage_pct/100.)*gridsim_v_nom))

                            grid_sim_voltage = (voltage_pct/100.)*gridsim_v_nom
                            gridsim_v_max = grid.v_max()
                            if grid_sim_voltage > gridsim_v_max:
                                grid.voltage(voltage=gridsim_v_max)
                                ts.log_warning('The grid simulator voltage is set to the simulator equipment limit.')
                            else:
                                grid.voltage(voltage=grid_sim_voltage)
                        else:
                            ts.confirm('Set ac voltage percentage to %.2f.%% with grid simulator voltage = %.2f' %
                                   (voltage_pct,(voltage_pct/100.)*gridsim_v_nom))

                        if trigger:
                            trigger.on()
                        start_time = time.time()

                        inv.nameplate.read()
                        VarAval = inv.nameplate.VArRtgQ1

                        varTarg, var_upper, var_lower = var_pass_fail_band(inv, volt=volt, var=var, n_points=n_points,
                                                                        var_range=var_range, deptRef=deptRef, das=das)
                        ts.log('        Target vars: %.3f. Pass limits for screening: lower = %.3f  upper = %.3f' %
                               (varTarg, var_lower, var_upper))

                        ts.log('        Waiting settling time of %.3f' % (settling_time))
                        time.sleep(settling_time-0.25) # computer specific time correction

                        current_vars = inverter.get_var(inv, das=data)

                        # Cheat a little since var is unsigned from das (and inverter?)
                        if varTarg < 0 and current_vars > 0:
                            current_vars = -current_vars

                        elapsed_time = time.time()-start_time
                        ts.log('        Var Target = %.3f [%.3f to %.3f], Vars = %.3f (Total Error = %.3f%%), '
                               'Time: %0.3f seconds.' %
                               (varTarg, var_lower, var_upper, current_vars, (current_vars - varTarg)/VarAval*100.0,
                                elapsed_time))

                        # if vars out of range
                        if current_vars < var_lower or current_vars > var_upper:
                            ts.log('        Acceptable reactive power levels were not reacted after the settling time.')
                            raise script.ScriptFail()
                        else:
                            # Criteria
                            # For each voltage step, the EUT reactive power measurement should remain within the
                            # manufacturers stated accuracy of the Q(V) value except when the voltage is changing.
                            # The EUT shall obtain the Q(V) characteristic within its stated accuracy within the
                            # stated settling time.
                            ts.log('        Reactive power level was within the bounds after the settling time.')
                        if trigger:
                            trigger.off()
                            if posttest_delay > 0:
                                ts.log('        Waiting for post-test delay of %d seconds' % posttest_delay)
                                ts.sleep(posttest_delay)

        result = script.RESULT_PASS
Esempio n. 19
0
def test_run():

    result = script.RESULT_FAIL
    daq = None
    pv = None
    grid = None

    try:
        # read test parameters
        tests_param = ts.param_value('general.tests')

        s_rated = ts.param_value('ratings.s_rated')
        p_rated = ts.param_value('ratings.p_rated')
        v_dc_min = ts.param_value('ratings.v_dc_min')  ##
        v_dc_max = ts.param_value('ratings.v_dc_max')  ##
        v_nom = ts.param_value('ratings.v_nom')
        v_min = ts.param_value('ratings.v_min')
        v_max = ts.param_value('ratings.v_max')
        #v_msa = ts.param_value('ratings.v_msa')
        var_msa = ts.param_value('ratings.var_msa')
        var_ramp_max = ts.param_value('ratings.var_ramp_max')
        q_max_cap = ts.param_value('ratings.q_max_cap')
        q_max_ind = ts.param_value('ratings.q_max_ind')
        k_var_max = ts.param_value('ratings.k_var_max')
        deadband_min = ts.param_value('ratings.deadband_min')
        deadband_max = ts.param_value('ratings.deadband_max')
        t_settling = ts.param_value('ratings.t_settling')
        power_priority = ts.param_value('ratings.power_priority')

        p_min_pct = ts.param_value('srd.p_min_pct')
        p_max_pct = ts.param_value('srd.p_max_pct')
        k_var_min_srd = ts.param_value('srd.k_var_min')
        try:
            k_var_min = float(k_var_min_srd)
        except ValueError:
            k_var_min = None
        segment_point_count = ts.param_value('srd.segment_point_count')

        # set power priorities to be tested
        if power_priority == 'Both':
            power_priorities = ['Active', 'Reactive']
        else:
            power_priorities = [power_priority]

        # default power range
        p_min = p_rated * .2
        p_max = p_rated

        # use values from SRD, if supplied
        if p_min_pct is not None:
            p_min = p_rated * (p_min_pct/100.)
        if p_max is not None:
            p_max = p_rated * (p_max_pct/100.)
        p_avg = (p_min + p_max)/2

        q_min_cap = q_max_cap/4
        q_min_ind = q_max_ind/4
        v_dev = min(v_nom - v_min, v_max - v_nom)
        # calculate k_var_min if not suppied in the SRD
        if k_var_min is None:
            k_var_min = (q_max_cap/4)/(v_dev - deadband_max/2)
        k_var_avg = (k_var_min + k_var_max)/2
        deadband_avg = (deadband_min + deadband_max)/2

        # list of active tests
        active_tests = test_labels[tests_param]

        # create test curves based on input parameters
        tests = [0] * 4

        '''
        The script only sets points 1-4 in the EUT, however they use v[0] and v[5] for testing purposes to define
        n points on the line segment to verify the reactive power
        '''
        # Test 1 - Characteristic 1 "Most Aggressive" Curve
        q = [0] * 5
        q[1] =q_max_cap    # Q1
        q[2] = 0
        q[3] = 0
        q[4] = q_max_ind
        v = [0] * 6
        v[2] = v_nom - deadband_min/2
        v[1] = v[2] - abs(q[1])/k_var_max
        v[0] = v_min
        v[3] = v_nom + deadband_min/2
        v[4] = v[3] + abs(q[4])/k_var_max
        v[5] = v_max

        tests[1] = [list(v), list(q)]

        # Test 2 - Characteristic 2 "Average" Curve
        q = [0] * 5
        q[1] = q_max_cap * .5
        q[2] = 0
        q[3] = 0
        q[4] = q_max_ind * .5
        v = [0] * 6
        v[2] = v_nom - deadband_avg/2
        v[1] = v[2] - abs(q[1])/k_var_avg
        v[0] = v_min
        v[3] = v_nom + deadband_avg/2
        v[4] = v[3] + abs(q[4])/k_var_avg
        v[5] = v_max
        tests[2] = [list(v), list(q)]

        # Test 3 - Characteristic 3 "Least Aggressive" Curve
        q = [0] * 5
        q[1] = q_min_cap
        q[2] = 0
        q[3] = 0
        q[4] = q_min_ind
        v = [0] * 6
        v[0] = v_min
        v[2] = v_nom - deadband_min/2
        v[3] = v_nom + deadband_min/2
        if k_var_min == 0:
            v[1] = 0.99*v[2]
            v[4] = 1.01*v[3]
        else:
            v[1] = v[2] - abs(q[1])/k_var_min
            v[4] = v[3] + abs(q[4])/k_var_min
        v[5] = v_max
        tests[3] = [list(v), list(q)]

        ts.log('tests = %s' % (tests))

        # list of tuples each containing (power level as % of max, # of test at power level)
        power_levels = [(1, 3), ((p_min/p_max), 3), (.66, 5)]

        '''
        1) Connect the EUT and measurement equipment according to the requirements in Sections 4 and 5 of
        IEEE Std 1547.1-2005 and specifications provided by the manufacturer.
        '''
        '''
        2) Set all AC source parameters to the nominal operating conditions for the EUT. Frequency is set at nominal
        and held at nominal throughout this test. Set the EUT power to Pmax.
        '''
        # grid simulator is initialized with test parameters and enabled
        grid = gridsim.gridsim_init(ts)

        # pv simulator is initialized with test parameters and enabled
        pv = pvsim.pvsim_init(ts)
        pv.power_set(p_max)
        pv.power_on()

        # initialize data acquisition
        daq = das.das_init(ts)

        '''
        3) Turn on the EUT. Set all L/HVRT parameters to the widest range of adjustability possible with the
        VV Q(V) enabled. The EUT's range of disconnect settings may depend on which function(s) are enabled.
        '''
        # it is assumed the EUT is on
        eut = der.der_init(ts)
        eut.config()

        for priority in power_priorities:
            '''
            4) If the EUT has the ability to set 'Active Power Priority' or 'Reactive Power Priority', select Priority
            being evaluated.
            '''
            '''
            5) Set the EUT to provide reactive power according to the Q(V) characteristic defined in Test 1 in
            Table SA13.1.
            '''
            for test in active_tests:
                ts.log('Starting test - %s' % (test_labels[test]))

                # create voltage settings along all segments of the curve
                v = tests[test][0]
                q = tests[test][1]
                voltage_points = voltage_sample_points(v, segment_point_count)
                ts.log('Voltage test points = %s' % (voltage_points))

                # set dependent reference type
                if priority == 'Active':
                    dept_ref = 'VAR_AVAL_PCT'
                elif priority == 'Reactive':
                    dept_ref = 'VAR_MAX_PCT'
                else:
                    raise script.ScriptFail('Unknown power priority setting: %s')

                # set volt/var curve
                eut.volt_var_curve(1, params={
                    # convert curve points to percentages and set DER parameters
                    'v': [v[1]/v_nom*100.0, v[2]/v_nom*100.0, v[3]/v_nom*100.0, v[4]/v_nom*100.0],
                    'var': [q[1]/q_max_cap*100.0, q[2]/q_max_cap*100.0, q[3]/q_max_cap*100.0, q[4]/q_max_cap*100.0],
                    'Dept_Ref': dept_ref
                })
                # enable volt/var curve
                eut.volt_var(params={
                    'Ena': True,
                    'ActCrv': 1
                })

                for level in power_levels:
                    power = level[0]
                    # set input power level
                    ts.log('    Setting the input power of the PV simulator to %0.2f' % (p_max * power))
                    pv.power_set(p_max * power)

                    count = level[1]
                    for i in xrange(1, count + 1):
                        '''
                        6) Set the EPS voltage to a value greater than V4 for a duration of not less than the settling
                        time.
                        '''
                        '''
                        7) Begin recording the time domain response of the EUT AC voltage and current, and DC voltage
                        and current. Step down the simulated EPS voltage (the rise/fall time of simulated EPS voltage
                        shall be < 1 cyc or < 1% of settling time) until at least three points are recorded in each
                        line segment of the characteristic curve or the EUT trips from the LVRT must trip requirements.
                        Continue recording the time domain response for at least twice the settling time after each
                        voltage step.
                        '''
                        '''
                        8) Set all AC source parameters to the nominal operating conditions for the EUT. Frequency is
                        set at nominal and held at nominal throughout this test. Set the EUT power to Pmax then repeat
                        Repeat Step (7), except raising, instead of dropping, the simulated EPS voltage (the rise/fall
                        time of simulated EPS voltage shall be < 1 cyc or < 1% of settling time) until at least three
                        points are recorded in each line segment of the characteristic curve or the EUT trips from HVRT
                        must trip requirements.
                        '''

                        # test voltage high to low
                        # start capture
                        test_str = 'VV_high_%s_%s_%s' % (str(test), str(power), str(i))
                        ts.log('Starting data capture for test %s, testing voltage high to low, with %s, '
                               'Power = %s%%, and sweep = %s' % (test_str, test_labels[test], power*100., i))
                        daq.data_capture(True)

                        for v in reversed(voltage_points):
                            ts.log('        Setting the grid voltage to %0.2f and waiting %0.1f seconds.' %
                                   (v, t_settling))
                            grid.voltage(v)
                            ts.sleep(t_settling)

                        # stop capture and save
                        daq.data_capture(False)
                        ds = daq.data_capture_dataset()
                        ds.to_csv(ts.result_file('%s.csv') % (test_str))
                        ts.log('Saving data capture')

                        # test voltage low to high
                        # start capture
                        test_str = 'VV_low_%s_%s_%s' % (str(test), str(power), str(i))
                        ts.log('Starting data capture for test %s, testing voltage low to high, with %s, '
                               'Power = %s%%, and sweep = %s' % (test_str, test_labels[test], power*100., i))
                        daq.data_capture(True)

                        for v in voltage_points:
                            ts.log('        Setting the grid voltage to %0.2f and waiting %0.1f seconds.' %
                                   (v, t_settling))
                            grid.voltage(v)
                            ts.sleep(t_settling)

                        # stop capture and save
                        daq.data_capture(False)
                        ds = daq.data_capture_dataset()
                        ds.to_csv(ts.result_file('%s.csv') % (test_str))
                        ts.log('Saving data capture')

                        '''
                        9) Repeat test Steps (6) - (8) at power levels of 20 and 66%; as described by the following:
                           a) For the 20% test, the EUT output power set to 20% of its Prated nominal rating
                           b) For the 66% test the test input source is to be adjusted to limit the EUT output power to
                           a value between 50% and 95% of rated output power.
                           c) The 66% power level, as defined in (b), shall be repeated for a total of five sweeps of
                           the Q(V) curve to validate consistency.
                        '''
                '''
                10) Repeat steps (6) - (9) for the remaining tests in Table SA13.1. Other than stated in (9) (c), the
                required number of sweeps for each of these repetitions is three. In the case of EUT without adjustable
                (V, Q) points, this step may be eliminated.
                '''
            '''
            11) If the EUT has the ability to set 'Active Power Priority' and 'Reactive Power Priority', select the
            other Priority, return the simulated EPS voltage to nominal, and repeat steps (5) - (10).
            '''

        result = script.RESULT_COMPLETE

    except script.ScriptFail, e:
        reason = str(e)
        if reason:
            ts.log_error(reason)
Esempio n. 20
0
def test_run():

    result = script.RESULT_FAIL
    data = None
    trigger = None
    grid = None
    pv = None
    inv = None
    volt = {}
    var = {}
    disable = None

    try:
        ifc_type = ts.param_value('comm.ifc_type')
        ifc_name = ts.param_value('comm.ifc_name')
        if ifc_type == client.MAPPED:
            ifc_name = ts.param_value('comm.map_name')
        baudrate = ts.param_value('comm.baudrate')
        parity = ts.param_value('comm.parity')
        ipaddr = ts.param_value('comm.ipaddr')
        ipport = ts.param_value('comm.ipport')
        slave_id = ts.param_value('comm.slave_id')

        var_ramp_rate = ts.param_value(
            'vv.settings.var_ramp_rate')  # time to ramp
        msa_var = ts.param_value('vv.settings.MSA_VAr')
        v_low = ts.param_value('vv.settings.v_low')
        v_high = ts.param_value('vv.settings.v_high')
        k_varmax = ts.param_value('vv.settings.k_varmax')
        v_deadband_min = ts.param_value('vv.settings.v_deadband_min')
        v_deadband_max = ts.param_value('vv.settings.v_deadband_max')
        manualcurve = ts.param_value('vv.settings.manualcurve')
        settling_time = ts.param_value('vv.settings.settling_time')

        vv_mode = ts.param_value('vv.settings.vv_mode')
        if vv_mode == 'VV11 (watt priority)':
            deptRef = inverter.VOLTVAR_WMAX
        elif vv_mode == 'VV12 (var priority)':
            deptRef = inverter.VOLTVAR_VARMAX
        elif vv_mode == 'VV13 (fixed var)':
            deptRef = inverter.VOLTVAR_VARAVAL
            fixedVar = ts.param_value('vv.settings.fixedVar')
            var[1] = fixedVar  # Not very clean - will pull 'points' info out later for pass/fail bounds
            fixedVarRef = ts.param_value('vv.settings.fixedVarRef')
            if fixedVarRef == '%VarAval':
                volt[
                    1] = 1  # Not very clean - will pull 'points' info out later for pass/fail bounds
            elif fixedVarRef == '%WMax':
                volt[
                    1] = 2  # Not very clean - will pull 'points' info out later for pass/fail bounds
            else:  #fixedVarRef == '%VarMax'
                volt[
                    1] = 3  # Not very clean - will pull 'points' info out later for pass/fail bounds
        else:
            deptRef = 4

        if vv_mode == 'VV11 (watt priority)' or vv_mode == 'VV12 (var priority)':
            curve_num = ts.param_value('vv.settings.curve_num')
            volt = ts.param_value('vv.curve.volt')
            var = ts.param_value('vv.curve.var')
            if manualcurve is 'Manual':
                n_points = ts.param_value('vv.settings.n_points')
            else:
                n_points = 4

        var_range = ts.param_value('invt.var_range')
        pretest_delay = ts.param_value('invt.pretest_delay')
        verification_delay = ts.param_value('invt.verification_delay')
        posttest_delay = ts.param_value('invt.posttest_delay')
        voltage_tests_per_line = ts.param_value('invt.voltage_tests_per_line')
        test_on_vv_points = ts.param_value('invt.test_on_vv_points')
        disable = ts.param_value('invt.disable')
        ''' UL 1741 requirements from the Feb 2015 Draft
        1. Connect the EUT according to the Requirements in Sec. 4.3.1 and specifications provided by the manufacturer.
        2. Set all AC source parameters to the nominal operating conditions for the EUT. Frequency is set at nominal
        and held at nominal throughout this test. Set the input power to the value to Prated.
        3. Turn on the EUT.  Set all R21-1-L/HVRT parameters to the widest range of adjustability possible with the
        R21-1-VV11 enabled.
        4. If the EUT has the ability to set "Real Power Priority" or "Reactive Power Priority", select
        "Reactive Power Priority".
        5. Set the EUT to provide reactive power according to the Q(V) characteristic defined in Test 1 in Table 10.
        6. Begin recording the time domain response of the EUT AC voltage and current, and DC voltage and current.
        Step down the AC voltage until at least three points  are recorded in each line segment of the characteristic
        curve or the EUT trips from the LVRT must trip requirements.  Continue recording the time domain response for
        at least twice the settling time after each voltage step.
        7. Repeat Step 6, raising the AC voltage until at least three points  are recorded in each line segment of the
        characteristic curve or the EUT trips from HVRT must trip requirements.
        8. Repeat steps 6 - 7 four more times, for a total of five sweeps  of the Q(V) curve.
        9. Repeat test steps 5 - 8 at power levels 20% and 60% of Prated by reducing the DC voltage of the Input
        Source.
        10. Repeat steps 6 - 9 for the remaining tests in Table 10.
        '''

        # initialize data acquisition system
        daq = das.das_init(ts)
        data = daq.data_init()
        trigger = daq.trigger_init()

        # initialize pv simulation
        pv = pvsim.pvsim_init(ts)
        pv.power_on()

        # UL 1741 SA Step 2: Set all AC source parameters to the nominal operating conditions for the EUT
        # initialize grid simulation
        grid = gridsim.gridsim_init(ts)
        if grid:
            gridsim_v_nom = grid.v_nom()

        #Put inverter scan after grid and PV simulation setup so that Modbus registers can be read.
        ts.log('Scanning inverter')
        inv = client.SunSpecClientDevice(ifc_type,
                                         slave_id=slave_id,
                                         name=ifc_name,
                                         baudrate=baudrate,
                                         parity=parity,
                                         ipaddr=ipaddr,
                                         ipport=ipport)

        # Make sure the EUT is on and operating
        ts.log(
            'Verifying EUT is in connected state. Waiting up to %d seconds for EUT to begin power export.'
            % (verification_delay + pretest_delay))
        if verify_initial_conn_state(
                inv,
                state=inverter.CONN_CONNECT,
                time_period=verification_delay + pretest_delay,
                data=data) is False:
            ts.log_error('Inverter unable to be set to connected state.')
            raise script.ScriptFail()

        # Get parameters
        try:
            inv.nameplate.read()
            inv.controls.read()
            inv.settings.read()
        except Exception, e:
            raise script.ScriptFail('Unable to get parameters from EUT: %s' %
                                    str(e))

        ts.log('********Parameters of the EUT*************')
        S_rated = float(inv.nameplate.VARtg)
        ts.log('Apparent Power Rating (VA) - S_rated: %.3f.' % S_rated)
        ts.log('EUT Input Power Rating (W) - P_rated: %.3f.' %
               float(inv.nameplate.WRtg))
        ts.log(
            'DC Voltage range with function enabled (V) - [V_low, V_high]: [%.1f, %.1f].'
            % (v_low, v_high))
        v_nom = float(inv.settings.VRef)
        ts.log('Nominal AC Voltage (V): %.3f.' % v_nom)
        v_min = float(inv.settings.VMin)
        v_max = float(inv.settings.VMax)
        ts.log('AC Voltage Range with function enabled (V): %.3f to %.3f' %
               (v_min, v_max))
        ts.log('VAr Accuracy (VAr) - MSA_VAr: %.3f.' % msa_var)
        ts.log('Max reactive power ramp rate (VAr/s): %.3f.' % var_ramp_rate)
        Q_max_cap = float(inv.settings.VArMaxQ1)
        Q_max_ind = float(inv.settings.VArMaxQ4)  # negative
        ts.log(
            'Minimum inductive (underexcited) reactive power - Q_max,ind: %.3f.'
            % Q_max_ind)  # negative
        ts.log(
            'Minimum capacitive (overexcited) reactive power - Q_max,cap: %.3f.'
            % Q_max_cap)
        ts.log('Maximum slope (VAr/V), K_varmax: %.3f.' % k_varmax)
        ts.log('Deadband range (V): [%.1f, %.1f].' %
               (v_deadband_min, v_deadband_max))
        ts.log('*******************************************')
        Q_min_cap = Q_max_cap / 4.
        Q_min_ind = Q_max_ind / 4.  #negative
        #v_avg = (v_min + v_max)/2.
        v_min_dev = min(v_nom - v_min, v_max - v_nom)
        v_deadband_avg = (v_deadband_min + v_deadband_max) / 2.
        k_varmin = Q_min_cap / (v_min_dev - v_deadband_max / 2.)
        k_varavg = (k_varmin + k_varmax) / 2.
        ts.log('Q_mid,cap = half the EUT capacitive VAr range: %.3f.' %
               Q_min_cap)
        ts.log('Q_mid,ind = half the EUT inductive VAr range: %.3f.' %
               Q_min_ind)
        #ts.log('V_avg = halfway point for the operating ac voltage of the function: %.3f.' % v_avg)
        ts.log('K_varavg: %.3f.' % k_varavg)
        ts.log('K_varmin: %.3f.' % k_varmin)
        ts.log('Average voltage deadband: %.3f.' % v_deadband_avg)

        ts.log('********Required Test Points for UL 1741*************')
        volt, var = volt_var_set(v_nom=240.,
                                 volt=volt,
                                 var=var,
                                 v_deadband_max=v_deadband_max,
                                 v_deadband_avg=v_deadband_avg,
                                 v_deadband_min=v_deadband_min,
                                 Q_max_cap=Q_max_cap,
                                 Q_max_ind=Q_max_ind,
                                 k_varmax=k_varmax,
                                 k_varavg=k_varavg,
                                 k_varmin=k_varmin,
                                 manualcurve=manualcurve)

        ######## Begin Test ########
        # UL 1741 SA Step 3: if applicable set LVRT/HVRT settings here.

        # Request status from EUT and display vars
        var_original = inverter.get_var(inv, das=data)
        ts.log('Current reactive power is %.3f VAr' % var_original)

        # UL 1741 SA Step 4 (using deptRef) and Step 5 (setting the Q(V) characteristic curve)
        inverter.set_volt_var(inv,
                              volt=volt,
                              var=var,
                              n_points=n_points,
                              curve_num=curve_num,
                              deptRef=deptRef,
                              enable=1)

        #voltage_pct_test_points = np.linspace(0., 100., voltage_tests_per_line)
        #ts.log('test_on_vv_points == Yes: %s' % voltage_pct_test_points)
        #voltage_pct_test_points = np.linspace(0., 100., voltage_tests_per_line+2)
        #voltage_pct_test_points = voltage_pct_test_points[1:-1]
        #ts.log('test_on_vv_points == No: %s' % voltage_pct_test_points)

        if test_on_vv_points == 'Yes':
            # the test points are on the (V,Q) points
            voltage_pct_test_points = np.linspace(0., 100.,
                                                  voltage_tests_per_line)
            ts.log(
                'Test points will at %s %% of the volt-var curve segments.' %
                voltage_pct_test_points)
        else:
            # the test points are not on the (V,Q) points
            voltage_pct_test_points = np.linspace(0., 100.,
                                                  voltage_tests_per_line + 2)
            voltage_pct_test_points = voltage_pct_test_points[1:-1]
            ts.log(
                'Test points will at %s %% of the volt-var curve segments.' %
                voltage_pct_test_points)

        lines_to_test = volt[
            'index_count'] + 1  # There are 1 more line than there are (V,Q) points

        for irradiance in [1000, 200, 600]:
            ts.log(
                'DC power level is %.3f %% nameplate, so the simulator power level is set to %.1f W/m^2'
                % (irradiance / 10., irradiance))
            pv.irradiance_set(irradiance=irradiance)

            for repeats in xrange(
                    1, 6):  # UL 1741 Step 8: Repeat the test 5 times
                ts.log('    Running volt-var sweep number %d.' % (repeats))

                if pretest_delay > 0:
                    ts.log('    Waiting for pre-test delay of %d seconds' %
                           pretest_delay)
                    ts.sleep(pretest_delay)

                for j in xrange(lines_to_test):
                    for i in voltage_pct_test_points:
                        ts.log(
                            '    Testing the reactive power on curve segment %d at %d%% down the line segment.'
                            % (j + 1, i))
                        voltage_pct = grid_voltage_get(
                            inv,
                            volt=volt,
                            var=var,
                            v_nom=v_nom,
                            line_to_test=j + 1,
                            voltage_pct_test_point=i)

                        # Set grid simulator voltage immediately prior to triggering
                        if grid is not None:
                            ts.log(
                                '        Setting ac voltage percentage = %.2f.%%. Simulator voltage = %.2f'
                                % (voltage_pct,
                                   (voltage_pct / 100.) * gridsim_v_nom))

                            grid_sim_voltage = (voltage_pct /
                                                100.) * gridsim_v_nom
                            gridsim_v_max = grid.v_max()
                            if grid_sim_voltage > gridsim_v_max:
                                grid.voltage(voltage=gridsim_v_max)
                                ts.log_warning(
                                    'The grid simulator voltage is set to the simulator equipment limit.'
                                )
                            else:
                                grid.voltage(voltage=grid_sim_voltage)
                        else:
                            ts.confirm(
                                'Set ac voltage percentage to %.2f.%% with grid simulator voltage = %.2f'
                                % (voltage_pct,
                                   (voltage_pct / 100.) * gridsim_v_nom))

                        if trigger:
                            trigger.on()
                        start_time = time.time()

                        inv.nameplate.read()
                        VarAval = inv.nameplate.VArRtgQ1

                        varTarg, var_upper, var_lower = var_pass_fail_band(
                            inv,
                            volt=volt,
                            var=var,
                            n_points=n_points,
                            var_range=var_range,
                            deptRef=deptRef,
                            das=das)
                        ts.log(
                            '        Target vars: %.3f. Pass limits for screening: lower = %.3f  upper = %.3f'
                            % (varTarg, var_lower, var_upper))

                        ts.log('        Waiting settling time of %.3f' %
                               (settling_time))
                        time.sleep(settling_time -
                                   0.25)  # computer specific time correction

                        current_vars = inverter.get_var(inv, das=data)

                        # Cheat a little since var is unsigned from das (and inverter?)
                        if varTarg < 0 and current_vars > 0:
                            current_vars = -current_vars

                        elapsed_time = time.time() - start_time
                        ts.log(
                            '        Var Target = %.3f [%.3f to %.3f], Vars = %.3f (Total Error = %.3f%%), '
                            'Time: %0.3f seconds.' %
                            (varTarg, var_lower, var_upper, current_vars,
                             (current_vars - varTarg) / VarAval * 100.0,
                             elapsed_time))

                        # if vars out of range
                        if current_vars < var_lower or current_vars > var_upper:
                            ts.log(
                                '        Acceptable reactive power levels were not reacted after the settling time.'
                            )
                            raise script.ScriptFail()
                        else:
                            # Criteria
                            # For each voltage step, the EUT reactive power measurement should remain within the
                            # manufacturers stated accuracy of the Q(V) value except when the voltage is changing.
                            # The EUT shall obtain the Q(V) characteristic within its stated accuracy within the
                            # stated settling time.
                            ts.log(
                                '        Reactive power level was within the bounds after the settling time.'
                            )
                        if trigger:
                            trigger.off()
                            if posttest_delay > 0:
                                ts.log(
                                    '        Waiting for post-test delay of %d seconds'
                                    % posttest_delay)
                                ts.sleep(posttest_delay)

        result = script.RESULT_PASS