def volt_vars_mode(vv_curves, vv_response_time, pwr_lvls, v_ref_value): result = script.RESULT_FAIL daq = None v_nom = None grid = None pv = None eut = None chil = None result_summary = None dataset_filename = None try: cat = ts.param_value('eut.cat') cat2 = ts.param_value('eut.cat2') sink_power = ts.param_value('eut.sink_power') p_rated = ts.param_value('eut.p_rated') p_rated_prime = ts.param_value('eut.p_rated_prime') var_rated = ts.param_value('eut.var_rated') s_rated = ts.param_value('eut.s_rated') #absorb_enable = ts.param_value('eut.abs_enabled') # DC voltages v_in_nom = ts.param_value('eut.v_in_nom') #v_min_in = ts.param_value('eut.v_in_min') #v_max_in = ts.param_value('eut.v_in_max') # AC voltages v_nom = ts.param_value('eut.v_nom') v_low = ts.param_value('eut.v_low') v_high = ts.param_value('eut.v_high') p_min = ts.param_value('eut.p_min') p_min_prime = ts.param_value('eut.p_min_prime') phases = ts.param_value('eut.phases') """ Version validation """ p1547.VersionValidation(script_version=ts.info.version) """ A separate module has been create for the 1547.1 Standard """ ActiveFunction = p1547.ActiveFunction(ts=ts, functions=[VV], script_name='Volt-Var', criteria_mode=[True, True, True]) ts.log_debug("1547.1 Library configured for %s" % ActiveFunction.get_script_name()) # result params result_params = ActiveFunction.get_rslt_param_plot() ts.log_debug(result_params) ''' a) Connect the EUT according to the instructions and specifications provided by the manufacturer. ''' ts.log_debug(15*"*"+"HIL initialization"+15*"*") # initialize HIL environment, if necessary chil = hil.hil_init(ts) if chil is not None: chil.config() ts.log_debug(15*"*"+"PVSIM initialization"+15*"*") # pv simulator is initialized with test parameters and enabled pv = pvsim.pvsim_init(ts, support_interfaces={'hil': chil}) if pv is not None: pv.power_set(p_rated) pv.power_on() # Turn on DC so the EUT can be initialized #daq.set_dc_measurement(pv) # send pv obj to daq to get dc measurements ts.sleep(0.5) # DAS soft channels ts.log_debug(15*"*"+"DAS initialization"+15*"*") #das_points = {'sc': ('Q_TARGET', 'Q_TARGET_MIN', 'Q_TARGET_MAX', 'Q_MEAS', 'V_TARGET', 'V_MEAS', 'event')} das_points = ActiveFunction.get_sc_points() # initialize data acquisition system daq = das.das_init(ts, sc_points=das_points['sc'], support_interfaces={'hil': chil}) daq.sc['V_TARGET'] = v_nom daq.sc['Q_TARGET'] = 100 daq.sc['Q_TARGET_MIN'] = 100 daq.sc['Q_TARGET_MAX'] = 100 daq.sc['event'] = 'None' ts.log('DAS device: %s' % daq.info()) ''' b) Set all voltage trip parameters to the widest range of adjustability. Disable all reactive/active power control functions. ''' ts.log_debug(15*"*"+"EUT initialization"+15*"*") eut = der.der_init(ts, support_interfaces={'hil': chil}) if eut is not None: eut.config() ts.log_debug(eut.measurements()) #Deactivating all functions on EUT #eut.deactivate_all_fct() ts.log_debug('Voltage trip parameters set to the widest range: v_min: {0} V, ' 'v_max: {1} V'.format(v_low, v_high)) try: eut.vrt_stay_connected_high(params={'Ena': True, 'ActCrv': 0, 'Tms1': 3000, 'V1': v_high, 'Tms2': 0.16, 'V2': v_high}) except Exception as e: ts.log_error('Could not set VRT Stay Connected High curve. %s' % e) try: eut.vrt_stay_connected_low(params={'Ena': True, 'ActCrv': 0, 'Tms1': 3000, 'V1': v_low, 'Tms2': 0.16, 'V2': v_low}) except Exception as e: ts.log_error('Could not set VRT Stay Connected Low curve. %s' % e) else: ts.log_debug('Set L/HVRT and trip parameters set to the widest range of adjustability possible.') # # Special considerations for CHIL ASGC/Typhoon startup if chil is not None: if eut is not None: if eut.measurements() is not None: inv_power = eut.measurements().get('W') timeout = 120. if inv_power <= p_rated * 0.85: pv.irradiance_set(995) # Perturb the pv slightly to start the inverter ts.sleep(3) eut.connect(params={'Conn': True}) while inv_power <= p_rated * 0.85 and timeout >= 0: ts.log('Inverter power is at %0.1f. Waiting up to %s more seconds or until EUT starts...' % (inv_power, timeout)) ts.sleep(1) timeout -= 1 inv_power = eut.measurements().get('W') if timeout == 0: result = script.RESULT_FAIL raise der.DERError('Inverter did not start.') ts.log('Waiting for EUT to ramp up') ts.sleep(8) ts.log_debug('DAS data_read(): %s' % daq.data_read()) ''' c) Set all AC test source parameters to the nominal operating voltage and frequency. ''' ts.log_debug(15*"*"+"GRIDSIM initialization"+15*"*") grid = gridsim.gridsim_init(ts,support_interfaces={'hil': chil}) # Turn on AC so the EUT can be initialized if grid is not None: grid.voltage(v_nom) if chil is not None: # If using HIL, give the grid simulator the hil object grid.config() # open result summary file result_summary_filename = 'result_summary.csv' result_summary = open(ts.result_file_path(result_summary_filename), 'a+') ts.result_file(result_summary_filename) result_summary.write(ActiveFunction.get_rslt_sum_col_name()) ''' d) Adjust the EUT's available active power to Prated. For an EUT with an input voltage range, set the input voltage to Vin_nom. The EUT may limit active power throughout the test to meet reactive power requirements. For an EUT with an input voltage range. ''' if pv is not None: pv.iv_curve_config(pmp=p_rated, vmp=v_in_nom) pv.irradiance_set(1000.) ''' gg) Repeat steps g) through dd) for characteristics 2 and 3. ''' for vv_curve in vv_curves: ts.log('Starting test with characteristic curve %s' % (vv_curve)) ActiveFunction.reset_curve(vv_curve) ActiveFunction.reset_time_settings(tr=vv_response_time[vv_curve], number_tr=2) v_pairs = ActiveFunction.get_params(function=VV, curve=vv_curve) #ts.log_debug('v_pairs:%s' % v_pairs) ''' ff) Repeat test steps d) through ee) at EUT power set at 20% and 66% of rated power. ''' for power in pwr_lvls: ActiveFunction.reset_pwr(power) if pv is not None: pv_power_setting = (p_rated * power) pv.iv_curve_config(pmp=pv_power_setting, vmp=v_in_nom) pv.irradiance_set(1000.) # Special considerations for CHIL ASGC/Typhoon startup # # Why does it need to appear twice, shouldn't this be at the driver level if chil is not None: if eut is not None: if eut.measurements() is not None: inv_power = eut.measurements().get('W') timeout = 120. if inv_power <= pv_power_setting * 0.85: pv.irradiance_set(995) # Perturb the pv slightly to start the inverter ts.sleep(3) eut.connect(params={'Conn': True}) while inv_power <= pv_power_setting * 0.85 and timeout >= 0: ts.log('Inverter power is at %0.1f. Waiting up to %s more seconds or until EUT starts...' % (inv_power, timeout)) ts.sleep(1) timeout -= 1 inv_power = eut.measurements().get('W') if timeout == 0: result = script.RESULT_FAIL raise der.DERError('Inverter did not start.') ts.log('Waiting for EUT to ramp up') ts.sleep(8) ''' ee) Repeat test steps e) through dd) with Vref set to 1.05*VN and 0.95*VN, respectively. ''' for v_ref in v_ref_value: ts.log('Setting v_ref at %s %% of v_nom' % (int(v_ref * 100))) #Setting grid to vnom before test if grid is not None: grid.voltage(v_nom) if eut is not None: ''' e) Set EUT volt-var parameters to the values specified by Characteristic 1. All other function should be turned off. Turn off the autonomously adjusting reference voltage. ''' # Activate volt-var function with following parameters # SunSpec convention is to use percentages for V and Q points. vv_curve_params = { 'v': [(v_pairs['V1'] / v_nom) , (v_pairs['V2'] / v_nom) , (v_pairs['V3'] / v_nom), (v_pairs['V4'] / v_nom) ], 'var': [(v_pairs['Q1'] / s_rated), (v_pairs['Q2'] / s_rated) , (v_pairs['Q3'] / s_rated) , (v_pairs['Q4'] / s_rated)], 'vref': v_ref, 'RmpPtTms': vv_response_time[vv_curve] } ts.log_debug('Sending VV points: %s' % vv_curve_params) eut.volt_var(params={'Ena': True, 'ACTCRV': vv_curve, 'curve': vv_curve_params}) # TODO autonomous vref adjustment to be included # eut.autonomous_vref_adjustment(params={'Ena': False}) ''' f) Verify volt-var mode is reported as active and that the correct characteristic is reported. ''' ts.log_debug('Initial EUT VV settings are %s' % eut.volt_var()) if chil is not None: ts.log('Start simulation of CHIL') chil.start_simulation() v_steps_dict = ActiveFunction.create_vv_dict_steps(v_ref=v_ref) dataset_filename = 'VV_%s_PWR_%d_vref_%d' % (vv_curve, power * 100, v_ref*100) ActiveFunction.reset_filename(filename=dataset_filename) #ts.log('------------{}------------'.format(dataset_filename)) # Start the data acquisition systems daq.data_capture(True) for step_label, v_step in v_steps_dict.items(): ts.log('Voltage step: setting Grid simulator voltage to %s (%s)' % (v_step, step_label)) ActiveFunction.start(daq=daq, step_label=step_label) step_dict = {'V': v_step} if grid is not None: grid.voltage(step_dict['V']) ActiveFunction.record_timeresponse(daq=daq) ActiveFunction.evaluate_criterias(daq=daq, step_dict=step_dict) result_summary.write(ActiveFunction.write_rslt_sum()) ts.log('Sampling complete') dataset_filename = dataset_filename + ".csv" daq.data_capture(False) ds = daq.data_capture_dataset() ts.log('Saving file: %s' % dataset_filename) ds.to_csv(ts.result_file_path(dataset_filename)) result_params['plot.title'] = dataset_filename.split('.csv')[0] ts.result_file(dataset_filename, params=result_params) result = script.RESULT_COMPLETE except script.ScriptFail as e: reason = str(e) if reason: ts.log_error(reason) except Exception as e: if dataset_filename is not None: dataset_filename = dataset_filename + ".csv" daq.data_capture(False) ds = daq.data_capture_dataset() ts.log('Saving file: %s' % dataset_filename) ds.to_csv(ts.result_file_path(dataset_filename)) result_params['plot.title'] = dataset_filename.split('.csv')[0] ts.result_file(dataset_filename, params=result_params) ts.log_error('Test script exception: %s' % traceback.format_exc()) finally: if daq is not None: daq.close() if pv is not None: pv.close() if grid is not None: if v_nom is not None: grid.voltage(v_nom) grid.close() if chil is not None: chil.close() if eut is not None: #eut.volt_var(params={'Ena': False}) eut.close() if result_summary is not None: result_summary.close() return result
def test_run(): result = script.RESULT_FAIL # Variables use in script daq = None data = None grid = None pv = None eut = None chil = None result_summary = None dataset_filename = None fw_curves = [] fw_response_time = [0, 0, 0] f_steps_dic = {} try: """ Test Configuration """ # Get all test script parameter mode = ts.param_value("fw.mode") eut_absorb = ts.param_value("eut_fw.absorb") """ Version validation """ p1547.VersionValidation(script_version=ts.info.version) """ A separate module has been create for the 1547.1 Standard """ ActiveFunction = p1547.ActiveFunction(ts=ts, functions=[FW], script_name='Frequency-Watt', criteria_mode=[True, True, True]) ts.log_debug("1547.1 Library configured for %s" % ActiveFunction.get_script_name()) if eut_absorb == "Yes": absorb_powers = [False, True] else: absorb_powers = [False] p_rated = ts.param_value('eut.p_rated') s_rated = ts.param_value('eut.s_rated') # DC voltages v_nom_in = ts.param_value('eut.v_in_nom') irr = ts.param_value('fw.power_lvl') if mode == 'Above': if irr == 'All': pwr_lvls = [1., 0.66, 0.2] elif irr == '100%': pwr_lvls = [1.] elif irr == '66%': pwr_lvls = [0.66] elif irr == '20%': pwr_lvls = [0.2] else: pwr_lvls = [1.] # AC voltages f_nom = ts.param_value('eut.f_nom') f_min = ts.param_value('eut.f_min') f_max = ts.param_value('eut.f_max') p_min = ts.param_value('eut.p_min') phases = ts.param_value('eut.phases') # EUI FW parameters absorb_enable = ts.param_value('eut_fw.sink_power') p_rated_prime = ts.param_value('eut_fw.p_rated_prime') p_min_prime = ts.param_value('eut_fw.p_min_prime') p_small = ts.param_value('eut_fw.p_small') if ts.param_value('fw.test_1') == 'Enabled': fw_curves.append(1) fw_response_time[1] = float(ts.param_value('fw.test_1_tr')) if ts.param_value('fw.test_2') == 'Enabled': fw_curves.append(2) fw_response_time[2] = float(ts.param_value('fw.test_2_tr')) ''' a) Connect the EUT according to the instructions and specifications provided by the manufacturer. ''' # initialize HIL environment, if necessary chil = hil.hil_init(ts) if chil is not None: chil.config() # DAS soft channels # TODO : add to library 1547 #das_points = {'sc': ('P_TARGET', 'P_TARGET_MIN', 'P_TARGET_MAX', 'P_MEAS', 'F_TARGET', 'F_MEAS', 'event')} das_points = ActiveFunction.get_sc_points() # initialize data acquisition system daq = das.das_init(ts, sc_points=das_points['sc'], support_interfaces={'hil': chil}) if daq is not None: daq.sc['P_TARGET'] = 100 daq.sc['P_TARGET_MIN'] = 100 daq.sc['P_TARGET_MAX'] = 100 daq.sc['P_MEAS'] = 100 daq.sc['F_TARGET'] = f_nom daq.sc['P_TARGET'] = p_rated daq.sc['event'] = 'None' ts.log('DAS device: %s' % daq.info()) # Configure the EUT communications eut = der.der_init(ts, support_interfaces={'hil': chil}) ''' b) Set all frequency trip parameters to the widest range of adjustability. Disable all reactive/active power control functions. ''' if eut is not None: eut.config() #eut.deactivate_all_fct(act_fct='FW') ts.log_debug(eut.measurements()) ts.log_debug( 'L/HFRT and trip parameters set to the widest range : f_min:{0} Hz, f_max:{1} Hz'.format(f_min, f_max)) eut_response = eut.frt_stay_connected_high( params={'Ena': True, 'ActCrv': 0, 'Tms1': 3000, 'Hz1': f_max, 'Tms2': 160, 'Hz2': f_max}) ts.log_debug('HFRT and trip parameters from EUT : {}'.format(eut_response)) eut_response = eut.frt_stay_connected_low( params={'Ena': True, 'ActCrv': 0, 'Tms1': 3000, 'Hz1': f_min, 'Tms2': 160, 'Hz2': f_min}) ts.log_debug('LFRT and trip parameters from EUT : {}'.format(eut_response)) else: ts.log_debug('Set L/HFRT and trip parameters to the widest range of adjustability possible.') ''' c) Set all AC test source parameters to the nominal operating voltage and frequency ''' grid = gridsim.gridsim_init(ts, support_interfaces={'hil': chil}) # Turn on AC so the EUT can be initialized if grid is not None: grid.freq(f_nom) if mode == 'Below': # 1547.1 : Frequency is ramped at the ROCOF for the category of the EUT. # In this case the ROCOF is based on table 21 of 1547.2018 # (Category III is use because of table B.1 of 1547.2018) # The ROCOF unit : Hz/s ts.log('Set Grid simulator ROCOF to 3 Hz/s') grid.rocof(3.0) # result params result_params = ActiveFunction.get_rslt_param_plot() # open result summary file result_summary_filename = 'result_summary.csv' result_summary = open(ts.result_file_path(result_summary_filename), 'a+') ts.result_file(result_summary_filename) result_summary.write(ActiveFunction.get_rslt_sum_col_name()) ''' above_d) Adjust the EUT's available active power to Prated . below_d) "" "" "". Set the EUT's output power to 50% of P rated . ''' pv = pvsim.pvsim_init(ts) if pv is not None: pv.iv_curve_config(pmp=p_rated, vmp=v_nom_in) pv.irradiance_set(1000.) if mode == 'Below': if eut is not None: ts.log_debug("In Below mode, EUT's output power is set to 50%% of %s (Prated)" % p_rated) eut.limit_max_power(params={ 'MaxLimWEna': True, 'MaxLimW_PCT': 50 }) """ Test start """ ''' above_r) For EUT's that can absorb power, rerun Characteristic 1 allowing the unit to absorb power by programing a negative Pmin . below_p) "" "" "". Set the unit to absorb power at -50% of P rated . ''' for absorb_power in absorb_powers: if absorb_power: if eut is not None: if mode == 'Below': ts.log_debug("Config EUT's absorb power at -50%% of P rated") eut.limit_max_power( params={ 'MaxLimWEna': True, 'MaxLimW_PCT': 50 } ) else: ts.log_debug("Config EUT's absorb power to %s (P\'min)" % p_min_prime) eut.limit_max_power(params={ 'MaxLimWEna': True, 'MaxLimW': p_min_prime }) ''' above_q) Repeat steps b) through p) for Characteristic 2. below_o) "" "" "" ''' if chil is not None: ts.log('Start simulation of CHIL') chil.start_simulation() for fw_curve in fw_curves: ts.log('Starting test with characteristic curve %s' % (fw_curve)) ActiveFunction.reset_curve(curve=fw_curve) ActiveFunction.reset_time_settings(tr=fw_response_time[fw_curve]) fw_param = ActiveFunction.get_params(function=FW, curve=fw_curve) f_steps_dict = ActiveFunction.create_fw_dict_steps(mode=mode) ts.log_debug(f'f_step={f_steps_dict}') ''' p) Repeat test steps b) through o) with the EUT power set at 20% and 66% of rated power. ''' for power in pwr_lvls: ActiveFunction.reset_pwr(pwr=power) if pv is not None: pv_power_setting = (p_rated * power) pv.iv_curve_config(pmp=pv_power_setting, vmp=v_nom_in) pv.irradiance_set(1000.) ''' e) Set EUT freq-watt parameters to the values specified by Characteristic 1. All other functions should be turned off. ''' # STD_CHANGE : dbf and kf don't exist but dbof=dbuf and kof=kuf was the point of having two? if eut is not None: params = { 'Ena': True, 'curve': fw_curve, 'dbf': fw_param['dbf'], 'kof': fw_param['kof'], 'RspTms': fw_param['tr'] } ts.log_debug(params) settings = eut.freq_watt(params) ''' f) Verify freq-watt mode is reported as active and that the correct characteristic is reported. ''' ts.log_debug('Initial EUT FW settings are %s' % settings) ts.log_debug('Test parameters : %s' % fw_param) ts.log('Starting data capture for power = %s' % power) dataset_filename = 'FW_{0}_PWR_{1}_{2}'.format(fw_curve, power, mode) if absorb_power: dataset_filename = 'FW_{0}_PWR_{1}_{2}_ABSORB'.format(fw_curve, power, mode) ActiveFunction.reset_filename(filename=dataset_filename) ts.log('------------{}------------'.format(dataset_filename)) ''' g) Once steady state is reached, read and record the EUT's active power, reactive power, voltage,frequency, and current measurements. ''' # STD_CHANGE there should be a wait for steady state to be reached in both mode step = 'Step F' daq.sc['event'] = step daq.data_sample() ts.log('Wait for steady state to be reached') ts.sleep(2 * fw_response_time[fw_curve]) daq.data_capture(True) for step_label, f_step in f_steps_dict.items(): ActiveFunction.start(daq=daq, step_label=step_label) ts.log('Frequency step: setting Grid simulator frequency to %s (%s)' % (f_step, step_label)) step_dict = {'F': f_step} if grid is not None: grid.freq(f_step) ActiveFunction.record_timeresponse(daq=daq) ActiveFunction.evaluate_criterias(daq=daq, step_dict=step_dict) result_summary.write(ActiveFunction.write_rslt_sum()) dataset_filename = dataset_filename + ".csv" daq.data_capture(False) ds = daq.data_capture_dataset() ts.log('Saving file: %s' % dataset_filename) ds.to_csv(ts.result_file_path(dataset_filename)) result_params['plot.title'] = os.path.splitext(dataset_filename)[0] ts.result_file(dataset_filename, params=result_params) result = script.RESULT_COMPLETE return result except script.ScriptFail as e: reason = str(e) if reason: ts.log_error(reason) except Exception as e: if dataset_filename is not None: dataset_filename = dataset_filename + ".csv" daq.data_capture(False) ds = daq.data_capture_dataset() ts.log('Saving file: %s' % dataset_filename) ds.to_csv(ts.result_file_path(dataset_filename)) result_params['plot.title'] = dataset_filename.split('.csv')[0] ts.result_file(dataset_filename, params=result_params) ts.log_error('Test script exception: %s' % traceback.format_exc()) finally: if daq is not None: daq.close() if pv is not None: if p_rated is not None: pv.power_set(p_rated) pv.close() if grid is not None: if f_nom is not None: grid.voltage(f_nom) grid.close() if chil is not None: chil.close() if eut is not None: #eut.volt_var(params={'Ena': False}) #eut.volt_watt(params={'Ena': False}) eut.close() if result_summary is not None: result_summary.close() # create result workbook excelfile = ts.config_name() + '.xlsx' rslt.result_workbook(excelfile, ts.results_dir(), ts.result_dir()) ts.result_file(excelfile) return result
def test_run(): result = script.RESULT_FAIL grid = None pv = p_rated = None daq = None eut = None rs = None chil = None result_summary = None step_label = None q_initial = None dataset_filename = None try: cat = ts.param_value('eut.cat') cat2 = ts.param_value('eut.cat2') sink_power = ts.param_value('eut.sink_power') p_rated = ts.param_value('eut.p_rated') p_rated_prime = ts.param_value('eut.p_rated_prime') s_rated = ts.param_value('eut.s_rated') var_rated = ts.param_value('eut.var_rated') # DC voltages v_nom_in_enabled = ts.param_value('crp.v_in_nom') v_min_in_enabled = ts.param_value('crp.v_in_min') v_max_in_enabled = ts.param_value('crp.v_in_max') v_nom_in = ts.param_value('eut.v_in_nom') v_min_in = ts.param_value('eut_crp.v_in_min') v_max_in = ts.param_value('eut_crp.v_in_max') # AC voltages v_nom = ts.param_value('eut.v_nom') v_min = ts.param_value('eut.v_low') v_max = ts.param_value('eut.v_high') p_min = ts.param_value('eut.p_min') p_min_prime = ts.param_value('eut.p_min_prime') phases = ts.param_value('eut.phases') pf_response_time = ts.param_value('crp.pf_response_time') # Pass/fail accuracies pf_msa = ts.param_value('eut.pf_msa') # Imbalance configuration imbalance_fix = ts.param_value('crp.imbalance_fix') # EUI Absorb capabilities absorb = {} absorb['ena'] = ts.param_value('eut_crp.sink_power') absorb['p_rated_prime'] = ts.param_value('eut_crp.p_rated_prime') absorb['p_min_prime'] = ts.param_value('eut_crp.p_min_prime') """ Version validation """ p1547.VersionValidation(script_version=ts.info.version) """ A separate module has been create for the 1547.1 Standard """ ActiveFunction = p1547.ActiveFunction( ts=ts, functions='CRP', script_name='Constant Reactive Power', criteria_mode=[True, False, False]) ActiveFunction.set_imbalance_config(imbalance_angle_fix=imbalance_fix) ts.log_debug("1547.1 Library configured for %s" % ActiveFunction.get_script_name()) # result params result_params = ActiveFunction.get_rslt_param_plot() #get target q relative value q_targets = {} if ts.param_value('crp.q_max_abs_enable') == 'Enabled': q_targets['crp_q_max_abs'] = float( ts.param_value('crp.q_max_abs_value')) if ts.param_value('crp.q_max_inj_enable') == 'Enabled': q_targets['crp_q_max_inj'] = float( ts.param_value('crp.q_max_inj_value')) if ts.param_value('crp.half_q_max_abs_enable') == 'Enabled': q_targets['crp_half_q_max_abs'] = 0.5 * float( ts.param_value('crp.q_max_abs_value')) if ts.param_value('crp.half_q_max_inj_enable') == 'Enabled': q_targets['crp_half_q_max_inj'] = 0.5 * float( ts.param_value('crp.q_max_inj_value')) #get q max value #q_max_value = ts.param_value('crp.q_max_value') v_in_targets = {} if v_nom_in_enabled == 'Enabled': v_in_targets['v_nom_in'] = v_nom_in if v_min_in != v_nom_in and v_min_in_enabled == 'Enabled': v_in_targets['v_min_in'] = v_min_in if v_max_in != v_nom_in and v_max_in_enabled == 'Enabled': v_in_targets['v_max_in'] = v_max_in if not v_in_targets: ts.log_error('No V_in target specify. Please select a V_IN test') """ a) Connect the EUT according to the instructions and specifications provided by the manufacturer. """ # initialize HIL environment, if necessary chil = hil.hil_init(ts) if chil is not None: chil.config() # grid simulator is initialized with test parameters and enabled grid = gridsim.gridsim_init(ts, support_interfaces={ 'hil': chil }) # Turn on AC so the EUT can be initialized if grid is not None: grid.voltage(v_nom) # pv simulator is initialized with test parameters and enabled pv = pvsim.pvsim_init(ts) if pv is not None: pv.power_set(p_rated) pv.power_on() # Turn on DC so the EUT can be initialized # DAS soft channels #das_points = {'sc': ('V_MEAS', 'P_MEAS', 'Q_MEAS', 'Q_TARGET_MIN', 'Q_TARGET_MAX', 'PF_TARGET', 'event')} das_points = ActiveFunction.get_sc_points() # initialize data acquisition daq = das.das_init(ts, sc_points=das_points['sc']) if daq is not None: daq.sc['V_MEAS'] = 100 daq.sc['P_MEAS'] = 100 daq.sc['Q_MEAS'] = 100 daq.sc['Q_TARGET_MIN'] = 100 daq.sc['Q_TARGET_MAX'] = 100 daq.sc['PF_TARGET'] = 1 daq.sc['event'] = 'None' ts.log('DAS device: %s' % daq.info()) """ b) Set all voltage trip parameters to the widest range of adjustability. Disable all reactive/active power control functions. """ # it is assumed the EUT is on eut = der.der_init(ts) if eut is not None: eut.config() # disable volt/var curve #eut.volt_var(params={'Ena': False}) ts.log_debug( 'If not done already, set L/HVRT and trip parameters to the widest range of adjustability.' ) # Special considerations for CHIL ASGC/Typhoon startup # if chil is not None: inv_power = eut.measurements().get('W') timeout = 120. if inv_power <= p_rated * 0.85: pv.irradiance_set( 995) # Perturb the pv slightly to start the inverter ts.sleep(3) eut.connect(params={'Conn': True}) while inv_power <= p_rated * 0.85 and timeout >= 0: ts.log( 'Inverter power is at %0.1f. Waiting up to %s more seconds or until EUT starts...' % (inv_power, timeout)) ts.sleep(1) timeout -= 1 inv_power = eut.measurements().get('W') if timeout == 0: result = script.RESULT_FAIL raise der.DERError('Inverter did not start.') ts.log('Waiting for EUT to ramp up') ts.sleep(8) """ c) Set all AC test source parameters to the nominal operating voltage and frequency. """ if grid is not None: grid.voltage(v_nom) # open result summary file result_summary_filename = 'result_summary.csv' result_summary = open(ts.result_file_path(result_summary_filename), 'a+') ts.result_file(result_summary_filename) result_summary.write(ActiveFunction.get_rslt_sum_col_name()) """ d) Adjust the EUT's available active power to Prated. For an EUT with an input voltage range, set the input voltage to Vin_nom. The EUT may limit active power throughout the test to meet reactive power requirements. s) For an EUT with an input voltage range, repeat steps d) through o) for Vin_min and Vin_max. """ # TODO: Include step t) """ t) Steps d) through q) may be repeated to test additional communication protocols - Run with another test. """ # For PV systems, this requires that Vmpp = Vin_nom and Pmpp = Prated. for v_in_label, v_in in v_in_targets.items(): ts.log('Starting test %s at v_in = %s' % (v_in_label, v_in)) a_v = ActiveFunction.MRA['V'] * 1.5 #Set response time recording ActiveFunction.reset_time_settings(tr=pf_response_time) if pv is not None: pv.iv_curve_config(pmp=p_rated, vmp=v_in) pv.irradiance_set(1000.) """ e) Enable constant power factor mode and set the EUT power factor to PFmin,inj. r) Repeat steps d) through o) for additional power factor settings: PFmin,ab, PFmid,inj, PFmid,ab. Only the user-selected PF setting will be tested. """ for q_test_name, q_target in q_targets.items(): # Setting up step label ActiveFunction.set_step_label(starting_label='F') q_target *= var_rated ts.log('Starting data capture for fixed Q relative = %s' % q_target) if imbalance_fix == "Yes": dataset_filename = ('{0}_{1}_FIX'.format( v_in_label.upper(), q_test_name.upper())) else: dataset_filename = ('{0}_{1}'.format( v_in_label.upper(), q_test_name.upper())) ts.log('------------{}------------'.format(dataset_filename)) ActiveFunction.reset_filename(filename=dataset_filename) # Start the data acquisition systems daq.data_capture(True) daq.sc['Q_TARGET'] = q_target if eut is not None: parameters = {'Ena': True, 'Q': q_target, 'Wmax': p_rated} ts.log('Parameters set: %s' % parameters) eut.reactive_power(params=parameters) vars_setting = eut.reactive_power(params=parameters) ts.log('fixed vars setting read: %s' % vars_setting) """ f) Verify Constant Var mode is reported as active and that the power factor setting is reported as Qmax,inj. """ step_label = ActiveFunction.get_step_label() daq.sc['event'] = step_label daq.data_sample() ts.log('Wait for steady state to be reached') ts.sleep(2 * pf_response_time) """ g) Step the EUT's active power to 20% of Prated or Pmin, whichever is less. """ if pv is not None: step_label = ActiveFunction.get_step_label() ts.log( 'Power step: setting PV simulator power to %s (%s)' % (p_min, step_label)) ActiveFunction.start(daq=daq, step_label=step_label) if p_rated * 0.2 > p_min: p_target = p_min else: p_target = p_rated * 0.2 step_dict = { 'V': v_nom, 'P': round(p_target, 2), 'Q': q_target } pv.power_set(step_dict['P']) ActiveFunction.record_timeresponse(daq=daq) ActiveFunction.evaluate_criterias(daq=daq, step_dict=step_dict) result_summary.write(ActiveFunction.write_rslt_sum()) """ h) Step the EUT's active power to 5% of Prated or Pmin, whichever is less. """ if pv is not None: step_label = ActiveFunction.get_step_label() ts.log( 'Power step: setting PV simulator power to %s (%s)' % (p_min, step_label)) ActiveFunction.start(daq=daq, step_label=step_label) if p_rated * 0.05 > p_min: p_target = p_min else: p_target = p_rated * 0.05 step_dict = { 'V': v_nom, 'P': round(p_target, 2), 'Q': q_target } pv.power_set(step_dict['P']) ActiveFunction.record_timeresponse(daq=daq) ActiveFunction.evaluate_criterias(daq=daq, step_dict=step_dict) result_summary.write(ActiveFunction.write_rslt_sum()) """ i) Step the EUT's available active power to Prated. """ if pv is not None: step_label = ActiveFunction.get_step_label() ts.log( 'Power step: setting PV simulator power to %s (%s)' % (p_rated, step_label)) ActiveFunction.start(daq=daq, step_label=step_label) step_dict = {'V': v_nom, 'P': p_rated, 'Q': q_target} pv.power_set(step_dict['P']) ActiveFunction.record_timeresponse(daq=daq) ActiveFunction.evaluate_criterias(daq=daq, step_dict=step_dict) result_summary.write(ActiveFunction.write_rslt_sum()) if grid is not None: # J) Step the AC test source voltage to (VL + av) step_label = ActiveFunction.get_step_label() ts.log( 'Voltage step: setting Grid simulator voltage to %s (%s)' % ((v_min + a_v), step_label)) ActiveFunction.start(daq=daq, step_label=step_label) step_dict = {'V': v_min + a_v, 'P': p_rated, 'Q': q_target} grid.voltage(step_dict['V']) ActiveFunction.record_timeresponse(daq=daq) ActiveFunction.evaluate_criterias(daq=daq, step_dict=step_dict) result_summary.write(ActiveFunction.write_rslt_sum()) # k) Step the AC test source voltage to (VH - av) step_label = ActiveFunction.get_step_label() ts.log( 'Voltage step: setting Grid simulator voltage to %s (%s)' % ((v_max - a_v), step_label)) ActiveFunction.start(daq=daq, step_label=step_label) step_dict = {'V': v_max - a_v, 'P': p_rated, 'Q': q_target} grid.voltage(step_dict['V']) ActiveFunction.record_timeresponse(daq=daq) ActiveFunction.evaluate_criterias(daq=daq, step_dict=step_dict) result_summary.write(ActiveFunction.write_rslt_sum()) # l) Step the AC test source voltage to (VL + av) step_label = ActiveFunction.get_step_label() ts.log( 'Voltage step: setting Grid simulator voltage to %s (%s)' % ((v_min + a_v), step_label)) ActiveFunction.start(daq=daq, step_label=step_label) step_dict = {'V': v_min + a_v, 'P': p_rated, 'Q': q_target} grid.voltage(step_dict['V']) ActiveFunction.record_timeresponse(daq=daq) ActiveFunction.evaluate_criterias(daq=daq, step_dict=step_dict) result_summary.write(ActiveFunction.write_rslt_sum()) if phases == 'Three phase': # m) For multiphase units, step the AC test source voltage to VN step_label = ActiveFunction.get_step_label() ts.log( 'Voltage step: setting Grid simulator voltage to %s (%s)' % (v_nom, step_label)) ActiveFunction.start(daq=daq, step_label=step_label) step_dict = {'V': v_nom, 'P': p_rated, 'Q': q_target} grid.voltage(step_dict['V']) ActiveFunction.record_timeresponse(daq=daq) ActiveFunction.evaluate_criterias(daq=daq, step_dict=step_dict) result_summary.write(ActiveFunction.write_rslt_sum()) ''' n) For multiphase units, step the AC test source voltage to Case A from Table 24. ''' if grid is not None and phases == 'Three phase': step_label = ActiveFunction.get_step_label() ts.log( 'Voltage step: setting Grid simulator to case A (IEEE 1547.1-Table 24)(%s)' % step_label) ActiveFunction.start(daq=daq, step_label=step_label) v_target = ActiveFunction.set_grid_asymmetric( grid=grid, case='case_a') step_dict = { 'V': v_target, 'P': p_rated, 'Q': q_target } ActiveFunction.record_timeresponse(daq=daq) ActiveFunction.evaluate_criterias(daq=daq, step_dict=step_dict) result_summary.write(ActiveFunction.write_rslt_sum()) """ o) For multiphase units, step the AC test source voltage to VN. """ if grid is not None and phases == 'Three phase': step_label = ActiveFunction.get_step_label() ts.log( 'Voltage step: setting Grid simulator voltage to %s (%s)' % (v_nom, step_label)) ActiveFunction.start(daq=daq, step_label=step_label) step_dict = {'V': v_nom, 'P': p_rated, 'Q': q_target} grid.voltage(step_dict['V']) ActiveFunction.record_timeresponse(daq=daq) ActiveFunction.evaluate_criterias(daq=daq, step_dict=step_dict) result_summary.write(ActiveFunction.write_rslt_sum()) """ p) For multiphase units, step the AC test source voltage to Case B from Table 24. """ if grid is not None and phases == 'Three phase': step_label = ActiveFunction.get_step_label() ts.log( 'Voltage step: setting Grid simulator to case B (IEEE 1547.1-Table 24)(%s)' % step_label) ActiveFunction.start(daq=daq, step_label=step_label) v_target = ActiveFunction.set_grid_asymmetric( grid=grid, case='case_b') step_dict = { 'V': v_target, 'P': p_rated, 'Q': q_target } ActiveFunction.record_timeresponse(daq=daq) ActiveFunction.evaluate_criterias(daq=daq, step_dict=step_dict) result_summary.write(ActiveFunction.write_rslt_sum()) """ q) For multiphase units, step the AC test source voltage to VN """ if grid is not None and phases == 'Three phase': step_label = ActiveFunction.get_step_label() ts.log( 'Voltage step: setting Grid simulator voltage to %s (%s)' % (v_nom, step_label)) ActiveFunction.start(daq=daq, step_label=step_label) step_dict = {'V': v_nom, 'P': p_rated, 'Q': q_target} grid.voltage(step_dict['V']) ActiveFunction.record_timeresponse(daq=daq) ActiveFunction.evaluate_criterias(daq=daq, step_dict=step_dict) result_summary.write(ActiveFunction.write_rslt_sum()) """ r) Disable constant power factor mode. Power factor should return to unity. """ if eut is not None: parameters = {'Ena': False} #ts.log('PF set: %s' % parameters) eut.fixed_var(params=parameters) var_setting = eut.fixed_var() ts.log('Reactive Power setting read: %s' % vars_setting) daq.sc['event'] = ActiveFunction.get_step_label() daq.data_sample() ts.sleep(4 * pf_response_time) daq.sc['event'] = 'T_settling_done' daq.data_sample() """ q) Verify all reactive/active power control functions are disabled. """ if eut is not None: ts.log( 'Reactive/active power control functions are disabled.' ) # TODO Implement ts.prompt functionality? # meas = eut.measurements() # ts.log('EUT PF is now: %s' % (data.get('AC_PF_1'))) # ts.log('EUT Power: %s, EUT Reactive Power: %s' % (meas['W'], meas['VAr'])) ts.log('Sampling complete') dataset_filename = dataset_filename + ".csv" daq.data_capture(False) ds = daq.data_capture_dataset() ts.log('Saving file: %s' % dataset_filename) ds.to_csv(ts.result_file_path(dataset_filename)) result_params['plot.title'] = dataset_filename.split('.csv')[0] ts.result_file(dataset_filename, params=result_params) result = script.RESULT_COMPLETE except script.ScriptFail as e: reason = str(e) if reason: ts.log_error(reason) except Exception as e: if dataset_filename is not None: dataset_filename = dataset_filename + ".csv" daq.data_capture(False) ds = daq.data_capture_dataset() ts.log('Saving file: %s' % dataset_filename) ds.to_csv(ts.result_file_path(dataset_filename)) result_params['plot.title'] = dataset_filename.split('.csv')[0] ts.result_file(dataset_filename, params=result_params) ts.log_error('Test script exception: %s' % traceback.format_exc()) finally: if grid is not None: grid.close() if pv is not None: if p_rated is not None: pv.power_set(p_rated) pv.close() if daq is not None: daq.close() if eut is not None: #eut.reactive_power(params={'Ena': False}) eut.close() if rs is not None: rs.close() if chil is not None: chil.close() if result_summary is not None: result_summary.close() # create result workbook excelfile = ts.config_name() + '.xlsx' rslt.result_workbook(excelfile, ts.results_dir(), ts.result_dir()) ts.result_file(excelfile) return result
def volt_watt_mode(vw_curves, vw_response_time, pwr_lvls): result = script.RESULT_FAIL daq = None data = None p_rated = None v_nom = None grid = None pv = None eut = None chil = None result_summary = None dataset_filename = None try: p_rated = ts.param_value('eut.p_rated') s_rated = ts.param_value('eut.s_rated') # DC voltages v_in_nom = ts.param_value('eut.v_in_nom') v_min_in = ts.param_value('eut.v_in_min') v_max_in = ts.param_value('eut.v_in_max') # AC voltages v_nom = ts.param_value('eut.v_nom') v_min = ts.param_value('eut.v_low') v_max = ts.param_value('eut.v_high') p_min = ts.param_value('eut.p_min') phases = ts.param_value('eut.phases') # EUI Absorb capabilities absorb = {} absorb['ena'] = ts.param_value('eut_vw.sink_power') absorb['p_rated_prime'] = ts.param_value('eut_vw.p_rated_prime') absorb['p_min_prime'] = ts.param_value('eut_vw.p_min_prime') """ Version validation """ p1547.VersionValidation(script_version=ts.info.version) """ A separate module has been create for the 1547.1 Standard """ ActiveFunction = p1547.ActiveFunction(ts=ts, functions=[VW], script_name='Volt-Watt', criteria_mode=[True, True, True]) ts.log_debug("1547.1 Library configured for %s" % ActiveFunction.get_script_name()) # result params result_params = ActiveFunction.get_rslt_param_plot() ''' a) Connect the EUT according to the instructions and specifications provided by the manufacturer. ''' ts.log_debug(15 * "*" + "HIL initialization" + 15 * "*") # initialize HIL environment, if necessary chil = hil.hil_init(ts) if chil is not None: chil.config() ts.log_debug(15 * "*" + "PVSIM initialization" + 15 * "*") # pv simulator is initialized with test parameters and enabled pv = pvsim.pvsim_init(ts) if pv is not None: pv.power_set(p_rated) pv.power_on() # Turn on DC so the EUT can be initialized ts.log_debug(15 * "*" + "DAS initialization" + 15 * "*") # DAS soft channels #das_points = {'sc': ('P_TARGET', 'P_TARGET_MIN', 'P_TARGET_MAX', 'P_MEAS', 'V_TARGET','V_MEAS','event')} das_points = ActiveFunction.get_sc_points() # initialize data acquisition system das_points = ActiveFunction.get_sc_points() daq = das.das_init(ts, sc_points=das_points['sc'], support_interfaces={'hil': chil}) if daq is not None: daq.sc['P_TARGET'] = p_rated daq.sc['P_TARGET_MIN'] = 100 daq.sc['P_TARGET_MAX'] = 100 daq.sc['V_TARGET'] = v_nom daq.sc['event'] = 'None' ts.log('DAS device: %s' % daq.info()) ''' b) Set all voltage trip parameters to the widest range of adjustability. Disable all reactive/active power control functions. ''' ts.log_debug(15 * "*" + "EUT initialization" + 15 * "*") eut = der.der_init(ts, support_interfaces={'hil': chil}) if eut is not None: eut.config() #Disable all functions on EUT eut.deactivate_all_fct() ts.log_debug(eut.measurements()) ts.log_debug( 'L/HVRT and trip parameters set to the widest range : v_min: {0} V, v_max: {1} V' .format(v_min, v_max)) try: eut.vrt_stay_connected_high( params={ 'Ena': True, 'ActCrv': 0, 'Tms1': 3000, 'V1': v_max, 'Tms2': 0.16, 'V2': v_max }) except Exception as e: ts.log_error( 'Could not set VRT Stay Connected High curve. %s' % e) try: eut.vrt_stay_connected_low( params={ 'Ena': True, 'ActCrv': 0, 'Tms1': 3000, 'V1': v_min, 'Tms2': 0.16, 'V2': v_min }) except Exception as e: ts.log_error('Could not set VRT Stay Connected Low curve. %s' % e) else: ts.log_debug( 'Set L/HVRT and trip parameters set to the widest range of adjustability possible.' ) ''' c) Set all AC test source parameters to the nominal operating voltage and frequency. ''' ts.log_debug(15 * "*" + "GRIDSIM initialization" + 15 * "*") # grid simulator is initialized with test parameters and enabled grid = gridsim.gridsim_init(ts, support_interfaces={ 'hil': chil }) # Turn on AC so the EUT can be initialized if grid is not None: grid.voltage(v_nom) # open result summary file result_summary_filename = 'result_summary.csv' result_summary = open(ts.result_file_path(result_summary_filename), 'a+') ts.result_file(result_summary_filename) result_summary.write(ActiveFunction.get_rslt_sum_col_name()) ''' v) Test may be repeated for EUT's that can also absorb power using the P' values in the characteristic definition. ''' # TODO: add P' tests (Like CPF -> for absorb_power in absorb_powers:) ''' u) Repeat steps d) through u) for characteristics 2 and 3. ''' for vw_curve in vw_curves: ts.log('Starting test with characteristic curve %s' % (vw_curve)) ActiveFunction.reset_curve(vw_curve) ActiveFunction.reset_time_settings(tr=vw_response_time[vw_curve], number_tr=2) v_pairs = ActiveFunction.get_params(curve=vw_curve, function=VW) ''' t) Repeat steps d) through t) at EUT power set at 20% and 66% of rated power. ''' for power in pwr_lvls: ActiveFunction.reset_pwr(pwr=power) ''' d) Adjust the EUT's available active power to Prated. For an EUT with an input voltage range, set the input voltage to Vin_nom. The EUT may limit active power throughout the test to meet reactive power requirements. For an EUT with an input voltage range. ''' if pv is not None: pv_power_setting = (p_rated * power) pv.iv_curve_config(pmp=pv_power_setting, vmp=v_in_nom) pv.irradiance_set(1000.) # Special considerations for CHIL ASGC/Typhoon startup # if chil is not None: if eut is not None: if eut.measurements() is not None: inv_power = eut.measurements().get('W') timeout = 120. if inv_power <= pv_power_setting * 0.85: pv.irradiance_set( 995 ) # Perturb the pv slightly to start the inverter ts.sleep(3) eut.connect(params={'Conn': True}) while inv_power <= pv_power_setting * 0.85 and timeout >= 0: ts.log( 'Inverter power is at %0.1f. Waiting up to %s more seconds or until EUT starts...' % (inv_power, timeout)) ts.sleep(1) timeout -= 1 inv_power = eut.measurements().get('W') if timeout == 0: result = script.RESULT_FAIL raise der.DERError( 'Inverter did not start.') ts.log('Waiting for EUT to ramp up') ts.sleep(8) ''' e) Set EUT volt-watt parameters to the values specified by Characteristic 1. All other functions should be turned off. ''' if eut is not None: vw_curve_params = { 'v': [v_pairs['V1'] / v_nom, v_pairs['V2'] / v_nom], 'w': [v_pairs['P1'] / p_rated, v_pairs['P2'] / p_rated], 'DeptRef': 'W_MAX_PCT', "RmpTms": vw_response_time[vw_curve] } vw_params = { 'Ena': True, 'ActCrv': 1, 'curve': vw_curve_params } ts.log_debug('Writing the following params to EUT: %s' % vw_params) eut.volt_watt(params=vw_params) ''' f) Verify volt-watt mode is reported as active and that the correct characteristic is reported. ''' ts.log_debug('Initial EUT VW settings are %s' % eut.volt_watt()) if chil is not None: ts.log('Start simulation of CHIL') chil.start_simulation() ''' Refer to P1547 Library and IEEE1547.1 standard for steps ''' v_steps_dict = ActiveFunction.create_vw_dict_steps() # Configure the data acquisition system ts.log('Starting data capture for power = %s' % power) dataset_filename = ('VW_{0}_PWR_{1}'.format(vw_curve, power)) ActiveFunction.reset_filename(filename=dataset_filename) ts.log('------------{}------------'.format(dataset_filename)) daq.data_capture(True) for step_label, v_step in v_steps_dict.items(): ts.log( 'Voltage step: setting Grid simulator voltage to %s (%s)' % (v_step, step_label)) ActiveFunction.start(daq=daq, step_label=step_label) step_dict = {'V': v_step} if grid is not None: grid.voltage(step_dict['V']) ActiveFunction.record_timeresponse(daq=daq) ActiveFunction.evaluate_criterias(daq=daq, step_dict=step_dict) result_summary.write(ActiveFunction.write_rslt_sum()) # create result workbook ts.log('Sampling complete') dataset_filename = dataset_filename + ".csv" daq.data_capture(False) ds = daq.data_capture_dataset() ts.log('Saving file: %s' % dataset_filename) ds.to_csv(ts.result_file_path(dataset_filename)) result_params['plot.title'] = dataset_filename.split('.csv')[0] ts.result_file(dataset_filename, params=result_params) result = script.RESULT_COMPLETE except script.ScriptFail as e: reason = str(e) if reason: ts.log_error(reason) except Exception as e: if dataset_filename is not None: dataset_filename = dataset_filename + ".csv" daq.data_capture(False) ds = daq.data_capture_dataset() ts.log('Saving file: %s' % dataset_filename) ds.to_csv(ts.result_file_path(dataset_filename)) result_params['plot.title'] = dataset_filename.split('.csv')[0] ts.result_file(dataset_filename, params=result_params) ts.log_error('Test script exception: %s' % traceback.format_exc()) raise finally: if daq is not None: daq.close() if pv is not None: if p_rated is not None: pv.power_set(p_rated) pv.close() if grid is not None: if v_nom is not None: grid.voltage(v_nom) grid.close() if chil is not None: chil.close() if eut is not None: eut.close() if result_summary is not None: result_summary.close() return result
def test_run(): result = script.RESULT_FAIL grid = None pv = p_rated = None daq = None eut = None rs = None chil = None result_summary = None step = None q_initial = None dataset_filename = None try: cat = ts.param_value('eut.cat') cat2 = ts.param_value('eut.cat2') sink_power = ts.param_value('eut.sink_power') p_rated = ts.param_value('eut.p_rated') p_rated_prime = ts.param_value('eut.p_rated_prime') s_rated = ts.param_value('eut.s_rated') var_rated = ts.param_value('eut.var_rated') # DC voltages v_nom_in_enabled = ts.param_value('cpf.v_in_nom') v_min_in_enabled = ts.param_value('cpf.v_in_min') v_max_in_enabled = ts.param_value('cpf.v_in_max') v_nom_in = ts.param_value('eut.v_in_nom') v_min_in = ts.param_value('eut_cpf.v_in_min') v_max_in = ts.param_value('eut_cpf.v_in_max') # AC voltages v_nom = ts.param_value('eut.v_nom') v_min = ts.param_value('eut.v_low') v_max = ts.param_value('eut.v_high') p_min = ts.param_value('eut.p_min') p_min_prime = ts.param_value('eut.p_min_prime') phases = ts.param_value('eut.phases') pri_response_time = ts.param_value('pri.pri_response_time') #Reactive power vv_status = ts.param_value('pri.vv_status') crp_status = ts.param_value('pri.crp_status') cpf_status = ts.param_value('pri.cpf_status') wv_status = ts.param_value('pri.wv_status') # Pass/fail accuracies pf_msa = ts.param_value('eut.pf_msa') # Imbalance configuration imbalance_fix = ts.param_value('cpf.imbalance_fix') # EUI Absorb capabilities absorb = {} absorb['ena'] = ts.param_value('eut_cpf.sink_power') absorb['p_rated_prime'] = ts.param_value('eut_cpf.p_rated_prime') absorb['p_min_prime'] = ts.param_value('eut_cpf.p_min_prime') #Functions to be enabled for test mode = [] if vv_status == 'Enabled': mode.append(VV) if crp_status == 'Enabled': mode.append(CRP) if cpf_status == 'Enabled': mode.append(CPF) if wv_status == 'Enabled': mode.append(WV) """ Version validation """ p1547.VersionValidation(script_version=ts.info.version) """ A separate module has been create for the 1547.1 Standard """ ActiveFunction = p1547.ActiveFunction(ts=ts, functions=[PRI, VW, FW, VV, CPF, CRP, WV], script_name='Prioritization', criteria_mode=[False, False, True]) ts.log_debug("1547.1 Library configured for %s" % ActiveFunction.get_script_name()) # result params result_params = ActiveFunction.get_rslt_param_plot() ts.log(result_params) """ a) Connect the EUT according to the instructions and specifications provided by the manufacturer. """ # initialize HIL environment, if necessary chil = hil.hil_init(ts) if chil is not None: chil.config() # grid simulator is initialized with test parameters and enabled grid = gridsim.gridsim_init(ts, support_interfaces={'hil': chil}) # Turn on AC so the EUT can be initialized if grid is not None: grid.voltage(v_nom) # pv simulator is initialized with test parameters and enabled pv = pvsim.pvsim_init(ts) if pv is not None: pv.power_set(p_rated) pv.power_on() # Turn on DC so the EUT can be initialized ts.sleep(0.5) # DAS soft channels das_points = ActiveFunction.get_sc_points() # initialize data acquisition daq = das.das_init(ts, sc_points=das_points['sc'], support_interfaces={'pvsim': pv, 'hil': chil}) if daq is not None: daq.sc['V_MEAS'] = 100 daq.sc['P_MEAS'] = 100 daq.sc['Q_MEAS'] = 100 daq.sc['Q_TARGET_MIN'] = 100 daq.sc['Q_TARGET_MAX'] = 100 daq.sc['PF_TARGET'] = 1 daq.sc['event'] = 'None' ts.log('DAS device: %s' % daq.info()) """ b) Set all voltage trip parameters to the widest range of adjustability. Disable all reactive/active power control functions. """ # it is assumed the EUT is on eut = der.der_init(ts) if eut is not None: eut.config() eut.deactivate_all_fct() ts.log_debug('If not done already, set L/HVRT and trip parameters to the widest range of adjustability.') """ c) Set all AC test source parameters to the nominal operating voltage and frequency. """ if grid is not None: grid.voltage(v_nom) # open result summary file result_summary_filename = 'result_summary.csv' result_summary = open(ts.result_file_path(result_summary_filename), 'a+') ts.result_file(result_summary_filename) result_summary.write(ActiveFunction.get_rslt_sum_col_name()) """ d) Adjust the EUT's available active power to Prated. For an EUT with an input voltage range, set the input voltage to Vin_nom. The EUT may limit active power throughout the test to meet reactive power requirements. """ if pv is not None: pv.iv_curve_config(pmp=p_rated, vmp=v_nom_in) pv.irradiance_set(1000.) """ e) Set EUT frequency-watt and volt-watt parameters to the default values for the EUTs category, and enable frequency-watt and volt-watt parameters. For volt-watt, set P2 = 0.2Prated. """ default_curve = 1 if eut is not None: fw_settings = ActiveFunction.get_params(function=FW) fw_curve_params = { 'Ena': True, 'curve': default_curve, 'dbf': fw_settings[default_curve]['dbf'], 'kof': fw_settings[default_curve]['kof'], 'RspTms': fw_settings[default_curve]['tr'] } ts.log_debug('Sending FW points: %s' % fw_curve_params) fw_current_settings = eut.freq_watt(fw_curve_params) vw_settings = ActiveFunction.get_params(aif=VW) #P2 require 0.2*p_rated value for VW function vw_settings['P2'] = 0.2*p_rated vw_curve_params = {'v': [int(vw_settings[default_curve]['V1'] * (100. / v_nom)), int(vw_settings[default_curve]['V2'] * (100. / v_nom))], 'w': [int(vw_settings[default_curve]['P1'] * (100. / p_rated)), int(vw_settings[default_curve]['P2'] * (100. / p_rated))], 'DeptRef': 'W_MAX_PCT', 'RmpPtTms': 10.0} vw_params = {'Ena': True, 'ActCrv': 1, 'curve': vw_curve_params} ts.log_debug('Sending VW points: %s' % vw_curve_params) eut.volt_watt(params=vw_params) #ts.log_debug('Initial EUT VW settings are %s' % eut.volt_watt()) ts.log_debug('curve points: %s' % vw_settings) """ h) Set the EUTs active power limit signal to 50% of Prated. """ ts.sleep(4*pri_response_time) # limit maximum power eut.limit_max_power(params={'Ena': True, 'WMaxPct': 50, 'WinTms': 0, 'RmpTms': 0, 'RvrtTms': 0.0}) for current_mode in mode: ts.log_debug('Starting mode = %s' % current_mode) ActiveFunction.reset_curve(curve=default_curve) ActiveFunction.reset_time_settings(tr=pri_response_time) if current_mode == VV: """ f) Set EUT volt-var parameters to the default values for the EUTs category and enable volt-var mode """ if eut is not None: vv_settings = ActiveFunction.get_params(aif=VV) #ts.log_debug('Sending VV points: %s' % vv_settings) vv_curve_params = {'v': [vv_settings[default_curve]['V1'] * (100 / v_nom), vv_settings[default_curve]['V2'] * (100 / v_nom), vv_settings[default_curve]['V3'] * (100 / v_nom), vv_settings[default_curve]['V4'] * (100 / v_nom)], 'q': [vv_settings[default_curve]['Q1'] * (100 / var_rated), vv_settings[default_curve]['Q2'] * (100 / var_rated), vv_settings[default_curve]['Q3'] * (100 / var_rated), vv_settings[default_curve]['Q4'] * (100 / var_rated)], 'DeptRef': 'Q_MAX_PCT', 'RmpPtTms': 10.0} ts.log_debug('Sending VV points: %s' % vv_curve_params) eut.volt_var(params={'Ena': True, 'curve': vv_curve_params}) elif current_mode == CRP: """ q) Set EUT watt-var parameters to the default values for the EUTs category. Disable the present mode of reactive power control and enable watt-var mode. Repeat steps g) through n). """ if eut is not None: parameters = {'Ena': True, 'Q': var_rated, 'Wmax': p_rated} ts.log('Parameters set: %s' % parameters) eut.reactive_power(params=parameters) vars_setting = eut.reactive_power(params=parameters) ts.log('fixed vars setting read: %s' % vars_setting) elif current_mode == CPF: """ p) Set the constant power factor function to PFmax,ing. Disable the present mode of reactive power control and enable power factor mode. Repeat steps g) through n). """ if eut is not None: parameters = {'Ena': True, 'PF': 0.9} ts.log('PF set: %s' % parameters) pf_setting = eut.fixed_pf(params=parameters) ts.log('PF setting read: %s' % pf_setting) elif current_mode == WV: """ q) Set EUT watt-var parameters to the default values for the EUTs category. Disable the present mode of reactive power control and enable watt-var mode. Repeat steps g) through n). """ if eut is not None: wv_settings = ActiveFunction.get_params(aif=WV)[default_curve] ts.log('WV setting: %s' % wv_settings) # Activate watt-var function with following parameters # SunSpec convention is to use percentages for P and Q points. wv_curve_params = {'w': [wv_settings['P0'] * (100 / p_rated), wv_settings['P1'] * (100 / p_rated), wv_settings['P2'] * (100 / p_rated), wv_settings['P3'] * (100 / p_rated)], 'var': [wv_settings['Q0'] * (100 / var_rated), wv_settings['Q1'] * (100 / var_rated), wv_settings['Q2'] * (100 / var_rated), wv_settings['Q3'] * (100 / var_rated)]} ts.log_debug('Sending WV points: %s' % wv_curve_params) eut.watt_var(params={'Ena': True, 'curve': wv_curve_params}) """ g) Allow the EUT to reach steady state. Measure AC test source voltage and frequency and the EUTs active and reactive power production. """ daq.data_capture(True) dataset_filename = 'PRI_{}'.format(current_mode) ts.log('------------{}------------'.format(dataset_filename)) ActiveFunction.reset_filename(filename=dataset_filename) """ i) Allow the EUT to reach steady state. """ ts.sleep(2*pri_response_time) """ j) Measure AC test source voltage and frequency, and the EUTs active and reactive power production. """ """ k) Set the AC test source voltage and frequency to the values in step 1 of Table 38 or Table 39, depending on the EUTs normal operating performance category. l) Allow the EUT to reach steady state. m) Measure AC test source voltage and frequency, and the EUTs active and reactive power production. n) Repeat steps k) through m) for the rest of the steps in Table 38 or Table 39, depending on the EUTs normal operating performance category """ """ steps_dicts = [{'V': 1.00, 'F': 60.00}, {'V': 1.09, 'F': 60.00}, {'V': 1.09, 'F': 60.33}, {'V': 1.09, 'F': 60.00}, {'V': 1.09, 'F': 59.36}, {'V': 1.00, 'F': 59.36}, {'V': 1.00, 'F': 60.00}, {'V': 1.00, 'F': 59.36}] """ ''' target_dict = [{'P': 0.5*p_rated, VV: 0.00*var_rated, CRP: 0.44, CPF: 0.9, WV: 0}, {'P': 0.4*p_rated, VV: -0.25*var_rated, CRP: 0.44, CPF: 0.9, WV: 0}, {'P': 0.3*p_rated, VV: -0.25*var_rated, CRP: 0.44, CPF: 0.9, WV: 0}, {'P': 0.4*p_rated, VV: -0.25*var_rated, CRP: 0.44, CPF: 0.9, WV: 0}, {'P': 0.4*p_rated, VV: -0.25*var_rated, CRP: 0.44, CPF: 0.9, WV: 0}, {'P': 0.6*p_rated, VV: 0.00*var_rated, CRP: 0.44, CPF: 0.9, WV: 0.05}, {'P': 0.5*p_rated, VV: 0.00*var_rated, CRP: 0.44, CPF: 0.9, WV: 0}, {'P': 0.7*p_rated, VV: 0.00*var_rated, CRP: 0.44, CPF: 0.9, WV: 0.10}] ''' step_dicts = ActiveFunction.create_pri_dict_steps(function=current_mode) ts.log('step_dicts: %s' % (step_dicts)) i = 0 for step_dict in step_dicts: step_label = 'Step_%i_%s' % (i+1, current_mode) ts.log('Voltage step: setting Grid simulator voltage to %s (%s)' % (step_dict['V'], step_label)) ts.log('Frequency step: setting Grid simulator frequency to %s (%s)' % (step_dict['F'], step_label)) ts.log('Steps: %s (%s)' % (step_dict, step_label)) ActiveFunction.start(daq=daq, step_label=step_label) if grid is not None: grid.freq(step_dict['F']) grid.voltage(step_dict['V']) ts.log_debug('current mode %s' % current_mode) ActiveFunction.record_timeresponse(daq=daq) ActiveFunction.evaluate_criterias(daq=daq, step_dict=step_dict, y_criterias_mod={'Q': current_mode}) result_summary.write(ActiveFunction.write_rslt_sum()) i += 1 if eut is not None: if current_mode == VV: eut.volt_var(params={'Ena': False}) elif current_mode == CPF: eut.fixed_pf(params={'Ena': False}) elif current_mode == CRP: eut.reactive_power(params={'Ena': False}) elif current_mode == WV: eut.watt_var(params={'Ena': False}) ts.log('Sampling complete') dataset_filename = dataset_filename + ".csv" daq.data_capture(False) ds = daq.data_capture_dataset() ts.log('Saving file: %s' % dataset_filename) ds.to_csv(ts.result_file_path(dataset_filename)) result_params['plot.title'] = dataset_filename.split('.csv')[0] ts.result_file(dataset_filename, params=result_params) result = script.RESULT_COMPLETE except script.ScriptFail as e: reason = str(e) if reason: ts.log_error(reason) except Exception as e: ts.log_error((e, traceback.format_exc())) if dataset_filename is not None: dataset_filename = dataset_filename + ".csv" daq.data_capture(False) ds = daq.data_capture_dataset() ts.log('Saving file: %s' % dataset_filename) ds.to_csv(ts.result_file_path(dataset_filename)) result_params['plot.title'] = dataset_filename.split('.csv')[0] ts.result_file(dataset_filename, params=result_params) ts.log_error('Test script exception: %s' % traceback.format_exc()) finally: if grid is not None: grid.close() if pv is not None: if p_rated is not None: pv.power_set(p_rated) pv.close() if daq is not None: daq.close() if eut is not None: # eut.fixed_pf(params={'Ena': False, 'PF': 1.0}) eut.close() if rs is not None: rs.close() if chil is not None: chil.close() if result_summary is not None: result_summary.close() # create result workbook excelfile = ts.config_name() + '.xlsx' rslt.result_workbook(excelfile, ts.results_dir(), ts.result_dir()) ts.result_file(excelfile) return result