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') """ A separate module has been create for the 1547.1 Standard """ lib_1547 = p1547.module_1547(ts=ts, aif='VV') ts.log_debug("1547.1 Library configured for %s" % lib_1547.get_test_name()) # result params result_params = lib_1547.get_rslt_param_plot() ''' a) Connect the EUT according to the instructions and specifications provided by the manufacturer. ''' # initialize HIL environment, if necessary chil = hil.hil_init(ts) if chil is not None: chil.config() # pv simulator is initialized with test parameters and enabled pv = pvsim.pvsim_init(ts) if pv is not None: pv.power_set(p_rated) pv.power_on() # Turn on DC so the EUT can be initialized # DAS soft channels # TODO : add to library 1547 das_points = { 'sc': ('Q_TARGET', 'Q_TARGET_MIN', 'Q_TARGET_MAX', 'Q_MEAS', 'V_TARGET', 'V_MEAS', 'event') } # initialize data acquisition system daq = das.das_init(ts, sc_points=das_points['sc']) 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. ''' eut = der.der_init(ts) if eut is not None: eut.config() ts.log_debug(eut.measurements()) eut.volt_var(params={'Ena': False}) eut.volt_watt(params={'Ena': False}) eut.fixed_pf(params={'Ena': False}) 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, 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, e: ts.log_error('Could not set VRT Stay Connected Low curve. %s' % e)
def test_run(): result = script.RESULT_FAIL daq = None grid = None pv = None eut = None chil = None result_summary = None dataset_filename = None v_nom = None try: settings_test = ts.param_value('iop.settings_test') monitoring_test = ts.param_value('iop.monitoring_test') v_nom = float(ts.param_value('eut.v_nom')) MSA_V = 0.01 * v_nom va_max = float(ts.param_value('eut.s_rated')) va_crg_max = va_max MSA_Q = 0.05 * float(ts.param_value('eut.s_rated')) MSA_P = 0.05 * float(ts.param_value('eut.s_rated')) MSA_F = 0.01 f_nom = float(ts.param_value('eut.f_nom')) phases = ts.param_value('eut.phases') p_rated = float(ts.param_value('eut.p_rated')) w_max = p_rated p_min = p_rated w_crg_max = p_rated var_rated = float(ts.param_value('eut.var_rated')) var_max = float(ts.param_value('eut.var_rated')) # initialize DER configuration eut = der.der_init(ts) eut.config() das_points = {'sc': ('event')} daq = das.das_init(ts, sc_points=das_points['sc']) # initialize HIL environment, if necessary chil = hil.hil_init(ts) if chil is not None: chil.config() # pv simulator is initialized with test parameters and enabled pv = pvsim.pvsim_init(ts) if pv is not None: pv.power_set(p_rated) pv.power_on() # Turn on DC so the EUT can be initialized # grid simulator is initialized with test parameters and enabled grid = gridsim.gridsim_init( ts) # Turn on AC so the EUT can be initialized if grid is not None: grid.voltage(v_nom) lib_1547 = p1547.module_1547(ts=ts, aif='Interoperability Tests') ts.log_debug("1547.1 Library configured for %s" % lib_1547.get_test_name()) ''' 6.4 Nameplate data test a) Read from the DER each nameplate data item listed in Table 28 in IEEE Std 1547-2018. b) Compare each value received to the expected values from the manufacturer-provided expected values. Table 28 - Nameplate information ________________________________________________________________________________________________________________ Parameter Description ________________________________________________________________________________________________________________ 1. Active power rating at unity power factor Active power rating in watts at unity power factor (nameplate active power rating) 2. Active power rating at specified over-excited Active power rating in watts at specified over-excited power factor power factor 3. Specified over-excited power factor Over-excited power factor as described in 5.2 4. Active power rating at specified under-excited Active power rating in watts at specified under-excited power factor power factor 5. Specified under-excited power factor Under-excited power factor as described in 5.2 6. Apparent power maximum rating Maximum apparent power rating in voltamperes 7. Normal operating performance category Indication of reactive power and voltage/power control capability. (Category A/B as described in 1.4) 8. Abnormal operating performance category Indication of voltage and frequency ride-through capability Category I, II, or III, as described in 1.4 9. Reactive power injected maximum rating Maximum injected reactive power rating in vars 10. Reactive power absorbed maximum rating Maximum absorbed reactive power rating in vars 11. Active power charge maximum rating Maximum active power charge rating in watts 12. Apparent power charge maximum rating Maximum apparent power charge rating in voltamperes. May differ from the apparent power maximum rating 13. AC voltage nominal rating Nominal AC voltage rating in RMS volts 14. AC voltage maximum rating Maximum AC voltage rating in RMS volts 15. AC voltage minimum rating Minimum AC voltage rating in RMS volts 16. Supported control mode functions Indication of support for each control mode function 17. Reactive susceptance that remains connected to Reactive susceptance that remains connected to the Area the Area EPS in the cease to energize and trip EPS in the cease to energize and trip state state 18. Manufacturer Manufacturer 19. Model Model 20. Serial number Serial number 21. Version Version ''' ts.log('---') der_info = eut.info() nameplate = eut.nameplate() ts.log('DER Nameplate Information:') if nameplate is not None: ts.log( ' Active power rating at unity power factor (nameplate active power rating) [WRtg]: %s' % nameplate.get('WRtg')) ts.log( ' Active power rating at specified over-excited power factor: %s' % 'Unknown') ts.log(' Specified over-excited power factor [PFRtgQ1]: %s' % nameplate.get('PFRtgQ1')) ts.log(' Specified under-excited power factor [PFRtgQ2]: %s' % nameplate.get('PFRtgQ2')) ts.log(' Apparent power maximum rating: %s' % nameplate.get('VARtg')) ts.log(' Normal operating performance category: %s' % 'Unknown') ts.log(' Abnormal operating performance category: %s' % 'Unknown') ts.log(' Reactive power injected maximum rating [VArRtgQ1]: %s' % nameplate.get('VArRtgQ1')) ts.log(' Reactive power absorbed maximum rating [VArRtgQ4]: %s' % nameplate.get('VArRtgQ4')) ts.log(' Apparent power charge maximum rating: %s' % nameplate.get('MaxChrRte')) ts.log(' AC voltage nominal rating: %s' % 'Unknown') ts.log(' AC voltage maximum rating: %s' % 'Unknown') ts.log(' AC voltage minimum rating: %s' % 'Unknown') if der_info is not None: ts.log(' Supported control mode functions: %s' % der_info.get('Options')) else: ts.log_warning('DER info not supported') if nameplate is not None: ts.log( ' Reactive susceptance that remains connected to the Area EPS in the cease to ' 'energize and trip state: %s' % 'Unknown') else: ts.log_warning('DER nameplate not supported') if der_info is not None: ts.log(' Manufacturer: %s' % (der_info.get('Manufacturer'))) ts.log(' Model: %s' % (der_info.get('Model'))) ts.log(' Serial Number: %s' % (der_info.get('SerialNumber'))) ts.log(' Version: %s' % (der_info.get('Version'))) else: ts.log_warning('DER info not supported') if settings_test: ''' 6.5 Basic settings information test a) Read from the DER each parameter identified in Table 42. b) For each, verify that the value reported matches the behavior of the DER measured though independent test equipment separate from the DER interface. c) Adjust values as identified in Table 42. d) Repeat steps a) and b) for the new values. e) Adjust parameters back to the initial values and verify that the value reported matches the initial values. Table 42 - Basic settings test levels ____________________________________________________________________________________________________________ Parameter Adjustment required Additional test instructions ____________________________________________________________________________________________________________ Active Power Maximum Set to 80% of Initial Value Apparent Power Maximum Set to 80% of Initial Value Reactive Power Injected Maximum Set to 80% of Initial Value Reactive Power Absorbed Maximum Set to 80% of Initial Value Active Power Charge Maximum Set to 80% of Initial Value This test applies only to DER that include energy storage. Apparent Power Charge Maximum Set to 80% of Initial Value This test applies only to DER that include energy storage. AC Current Maximum Set to 80% of Initial Value Control Mode Functions Not applicable Stated Energy Storage Capacity Set to 80% of Initial Value This test applies only to DER that include energy storage. Mode Enable Interval Set to 5 s, set to 300 s ''' # Special considerations for CHIL ASGC/Typhoon startup if chil is not None: inv_power = eut.measurements().get('W') timeout = 120. if inv_power <= p_rated * 0.85: pv.irradiance_set( 995) # Perturb the pv slightly to start the inverter ts.sleep(3) eut.connect(params={'Conn': True}) while inv_power <= p_rated * 0.85 and timeout >= 0: ts.log( 'Inverter power is at %0.1f. Waiting up to %s more seconds or until EUT starts...' % (inv_power, timeout)) ts.sleep(1) timeout -= 1 inv_power = eut.measurements().get('W') if timeout == 0: result = script.RESULT_FAIL raise der.DERError('Inverter did not start.') ts.log('Waiting for EUT to ramp up') ts.sleep(8) # ts.log_debug('DAS data_read(): %s' % daq.data_read()) settings = eut.settings() if settings is not None: # Active Power Maximum ts.log(' Active Power Maximum [WMax]: %s' % (settings.get('WMax'))) ts.log(' Setting WMax to %f.' % (0.8 * w_max)) eut.settings(params={'WMax': 0.8 * w_max}) ts.sleep(2) power = lib_1547.get_measurement_total( data=daq.data_capture_read(), type_meas='P', log=True) ts.log(' Power was recorded to be: %f.' % power) ts.log(' Returning WMax to %f.' % w_max) eut.settings(params={'WMax': w_max}) # Apparent Power Maximum ts.log(' Apparent Power Maximum [VAMax]: %s' % (settings.get('VAMax'))) ts.log(' Setting VAMax to %f.' % (0.8 * va_max)) eut.settings(params={'VAMax': 0.8 * va_max}) ts.sleep(2) va = lib_1547.get_measurement_total( data=daq.data_capture_read(), type_meas='VA', log=True) ts.log(' Apparent Power was recorded to be: %f.' % va) ts.log(' Returning VAMax to %f.' % va_max) eut.settings(params={'VAMax': va_max}) # Reactive Power Injected Maximum # TODO check on sign convention here ts.log(' Reactive Power Injected Maximum [VArMaxQ1]: %s' % (settings.get('VArMaxQ1'))) ts.log(' Setting VArMaxQ1 to %f.' % (0.8 * var_max)) eut.settings(params={'VArMaxQ1': 0.8 * var_max}) eut.reactive_power(params={ 'Ena': True, 'VArPct_Mod': 'VArMax', 'VArMaxPct': 100 }) ts.sleep(2) q = lib_1547.get_measurement_total( data=daq.data_capture_read(), type_meas='Q', log=True) ts.log(' Reactive Power Injected was recorded to be: %f.' % q) ts.log(' Returning VArMaxQ1 to %f.' % var_max) eut.settings(params={'VArMaxQ1': var_max}) eut.reactive_power(params={'Ena': False}) # Reactive Power Absorbed Maximum ts.log(' Reactive Power Absorbed Maximum [VArMaxQ4]: %s' % (settings.get('VArMaxQ4'))) ts.log(' Setting VArMaxQ4 to %f.' % (0.8 * var_max)) eut.settings(params={'VArMaxQ4': 0.8 * var_max}) eut.reactive_power(params={ 'Ena': True, 'VArPct_Mod': 'VArMax', 'VArMaxPct': -100 }) ts.sleep(2) q = lib_1547.get_measurement_total( data=daq.data_capture_read(), type_meas='Q', log=True) ts.log(' Reactive Power Absorbed was recorded to be: %f.' % q) ts.log(' Returning VArMaxQ4 to %f.' % var_max) eut.settings(params={'VArMaxQ4': var_max}) eut.reactive_power(params={'Ena': False}) # AC Current Maximum ts.log(' Apparent Power Maximum [VAMax]: %s' % (settings.get('VAMax'))) ts.log(' Setting VAMax to %f.' % (0.8 * va_max)) eut.settings(params={'VAMax': 0.8 * va_max}) ts.sleep(2) va = lib_1547.get_measurement_total( data=daq.data_capture_read(), type_meas='VA', log=True) ts.log(' Apparent Power was recorded to be: %f.' % va) ts.log(' Returning VAMax to %f.' % va_max) eut.settings(params={'VAMax': va_max}) # Mode Enable Interval # TODO add this assessment {'ModeInterval': [5, 300]} else: ts.log_warning('DER settings not supported') storage = eut.storage() if storage is not None: # Active Power Charge Maximum ts.log(' Active Power Charge Maximum [WChaMax]: %s' % (storage.get('WChaMax'))) ts.log(' Setting WChaMax to %f.' % (0.8 * w_crg_max)) eut.storage(params={'WChaMax': 0.8 * w_crg_max}) ts.log(' Setting InWRte to %f %% of max charging rate.' % 100.) # Percent of max charging rate. eut.storage(params={'InWRte': 100.}) ts.sleep(2) power = lib_1547.get_measurement_total( data=daq.data_capture_read(), type_meas='P', log=True) ts.log(' Apparent Power was recorded to be: %f.' % power) ts.log(' Returning WChaMax to %f.' % w_crg_max) eut.storage(params={'WChaMax': w_crg_max}) eut.storage(params={'InWRte': 0.}) # Apparent Power Charge Maximum ts.log(' Apparent Power Charge Maximum [VAChaMax]: %s' % (storage.get('VAChaMax'))) ts.log(' Setting WChaMax to %f.' % (0.8 * va_crg_max)) eut.storage(params={'VAChaMax': 0.8 * va_crg_max}) ts.log(' Setting InWRte to %f %% of max charging rate.' % 100.) # Percent of max charging rate. eut.storage(params={'InWRte': 100.}) ts.sleep(2) power = lib_1547.get_measurement_total( data=daq.data_capture_read(), type_meas='VA', log=True) ts.log(' Apparent Power was recorded to be: %f.' % power) ts.log(' Returning VAChaMax to %f.' % va_crg_max) eut.storage(params={'VAChaMax': va_crg_max}) eut.storage(params={'InWRte': 0.}) # Stated Energy Storage Capacity # StorAval = State of charge (ChaState) minus storage reserve (MinRsvPct) times capacity rating (AhrRtg) # TODO add this assessment else: ts.log_warning('DER storage not supported') if monitoring_test: ''' 6.6 Monitoring information test a) Set the operating conditions of the DER to the values specified in the "Operating Point A" column in Table 43. b) Wait not less than 30 s, then read from the DER each monitoring information, and verify that the reported values match the operating conditions as identified. c) Change the operating conditions of the DER as specified in the "Operating Point B" column 16 in Table 43. d) Repeat step b). ''' # Monitoring information parameter: Active Power # Operating Point A: 0 to 10% of DER "active power rating at unity power factor" # Operating Point B: 90 to 100% of DER "active power rating at unity power factor" # Pass/Fail Criteria: Reported values match test operating conditions within the accuracy requirements # specified in Table 3 in IEEE Std 1547-2018. (+/- 5% Srated) m = eut.measurements() if m is not None: ts.log(' Active Power reported from the EUT is: %s W' % (m.get('W'))) for setpoint in [5, 100]: eut.limit_max_power(params={ 'Ena': True, 'WMaxPct': setpoint }) # curtial to 5% of power inaccurate_measurement = True while inaccurate_measurement: power_pct = 100 * (eut.measurements().get('W') / w_max) ts.log(' EUT power is currently %f%% Prated' % power_pct) if setpoint - 5. <= power_pct <= setpoint + 5.: # +/- 5% Srated ts.log( 'EUT has recorded power +/- 5%% Srated, as required by IEEE 1547-2018.' ) ts.log('Returning EUT to rated power.') inaccurate_measurement = False ts.sleep(1) eut.limit_max_power(params={'Ena': False}) else: ts.log_warning('DER measurements not supported') ts.log('---') # Monitoring information parameter: Reactive Power # Operating Point A: 90 to 100% of DER "reactive power injected maximum rating" # Operating Point B: 90 to 100% of DER "reactive power absorbed maximum rating" # Pass/Fail Criteria: Reported values match test operating conditions within the accuracy requirements # specified in Table 3 in IEEE Std 1547-2018. (+/- 5% Srated) m = eut.measurements() if m is not None: ts.log(' Reactive Power reported from the EUT is: %f VAr' % (m.get('VAr'))) for setpoint in [5, 100]: eut.reactive_power(params={ 'Ena': True, 'VArPct_Mod': 'VArMax', 'VArMaxPct': 100 }) inaccurate_measurement = True while inaccurate_measurement: q_pct = 100 * (eut.measurements().get('VAr') / var_max) ts.log( ' EUT reactive power is currently %f%% Qrated' % q_pct) if setpoint - 5. <= q_pct <= setpoint + 5.: # +/- 5% Srated ts.log( 'EUT has recorded reactive power +/- 5%% Srated, as required by IEEE 1547-2018.' ) ts.log('Returning EUT to rated power.') inaccurate_measurement = False ts.sleep(1) eut.reactive_power(params={'Ena': False}) else: ts.log_warning('DER measurements not supported') ts.log('---') # Monitoring information parameter: Voltage # Operating Point A: At or below 0.90x(AC voltage nominal rating) # Operating Point B: At or above 1.08x(AC voltage nominal rating) # Pass/Fail Criteria: Reported values match test operating conditions within the accuracy requirements # specified in Table 3 in IEEE Std 1547-2018. (+/-1% Vnom) for setpoint in [90, 108]: grid.voltage(setpoint) inaccurate_measurement = True while inaccurate_measurement: voltages = [] if self.phases == 'Single phase': voltages.append(eut.measurements()['PhVphA']) elif self.phases == 'Split phase': voltages.append(eut.measurements()['PhVphA']) voltages.append(eut.measurements()['PhVphB']) elif self.phases == 'Three phase': voltages.append(eut.measurements()['PhVphB'] / v_nom) voltages.append(eut.measurements()['PhVphB'] / v_nom) voltages.append(eut.measurements()['PhVphC'] / v_nom) # TODO: also check phase to phase voltages voltages.append(eut.measurements()['PPVphAB'] / (v_nom * math.sqrt(3))) voltages.append(eut.measurements()['PPVphBC'] / (v_nom * math.sqrt(3))) voltages.append(eut.measurements()['PPVphCA'] / (v_nom * math.sqrt(3))) ts.log(' EUT voltages are currently %s pu' % voltages) pass_criteria = [] for voltage in voltages: if setpoint / 100. - 0.01 <= voltage <= setpoint / 100. + 0.01: # +/- 1% Vnom pass_criteria.append(True) else: pass_criteria.append(True) if all(pass_criteria): ts.log( 'EUT has recorded voltage +/- 1%% Vnom, as required by IEEE 1547-2018.' ) ts.log('Returning EUT to rated power.') inaccurate_measurement = False ts.sleep(1) grid.voltage(v_nom) # Monitoring information parameter: Frequency # Operating Point A: At or below 57.2Hz # Operating Point B: At or above 61.6Hz # Pass/Fail Criteria: Reported values match test operating conditions within the accuracy requirements # specified in Table 3 in IEEE Std 1547-2018. (10 mHz) # Monitoring information parameter: Operational State # Operating Point A: On # Operating Point B: Off # Pass/Fail Criteria: Reported Operational State matches the device present condition for on and off states. # Monitoring information parameter: Connection Status # Operating Point A: Connected: Enable Permit and AC conditions have been met to enter service as specified # in Table 39 of IEEE Std 1547-2018 # Operating Point B: Disconnected: Permit service is disabled # Pass/Fail Criteria: Reported Connection Status matches the device present connection condition. status = eut.controls_status() if status is not None: ts.log(' Is Fixed_W enabled?: %s' % (status.get('Fixed_W'))) ts.log(' Is Fixed_Var enabled?: %s' % (status.get('Fixed_Var'))) ts.log(' Is Fixed_PF enabled?: %s' % (status.get('Fixed_PF'))) ts.log(' Is Volt_Var enabled?: %s' % (status.get('Volt_Var'))) ts.log(' Is Freq_Watt_Param enabled?: %s' % (status.get('Freq_Watt_Param'))) ts.log(' Is Freq_Watt_Curve enabled?: %s' % (status.get('Freq_Watt_Curve'))) ts.log(' Is Dyn_Reactive_Power enabled?: %s' % (status.get('Dyn_Reactive_Power'))) ts.log(' Is LVRT enabled?: %s' % (status.get('LVRT'))) ts.log(' Is HVRT enabled?: %s' % (status.get('HVRT'))) ts.log(' Is Watt_PF enabled?: %s' % (status.get('Watt_PF'))) ts.log(' Is Volt_Watt enabled?: %s' % (status.get('Volt_Watt'))) ts.log(' Is Scheduled enabled?: %s' % (status.get('Scheduled'))) ts.log(' Is LFRT enabled?: %s' % (status.get('LFRT'))) ts.log(' Is HFRT enabled?: %s' % (status.get('HFRT'))) ts.log('---') status = eut.conn_status() ts.log(' Is PV_Connected?: %s' % (status.get('PV_Connected'))) ts.log(' Is PV_Available?: %s' % (status.get('PV_Available'))) ts.log(' Is PV_Operating?: %s' % (status.get('PV_Operating'))) ts.log(' Is PV_Test?: %s' % (status.get('PV_Test'))) ts.log(' Is Storage_Connected?: %s' % (status.get('Storage_Connected'))) ts.log(' Is Storage_Available?: %s' % (status.get('Storage_Available'))) ts.log(' Is Storage_Operating?: %s' % (status.get('Storage_Operating'))) ts.log(' Is Storage_Test?: %s' % (status.get('Storage_Test'))) ts.log(' Is EPC_Connected?: %s' % (status.get('EPC_Connected'))) ts.log('---') # Monitoring information parameter: Alarm Status # Operating Point A: Has alarms set # Operating Point B: No alarms set # Pass/Fail Criteria: Reported Alarm Status matches the device present alarm condition for alarm and no # alarm conditions. The DER manufacturer shall specify at least one way an alarm condition which is # supported in the protocol being tested can be set and cleared. return script.RESULT_COMPLETE except script.ScriptFail, e: reason = str(e) if reason: ts.log_error(reason)
def volt_var_mode_imbalanced_grid(imbalance_resp, vv_curves, vv_response_time): result = script.RESULT_FAIL daq = None v_nom = None p_rated = None grid = None pv = None eut = None chil = None result_summary = None dataset_filename = None try: #cat = ts.param_value('eut.cat') #cat2 = ts.param_value('eut.cat2') #sink_power = ts.param_value('eut.sink_power') p_rated = ts.param_value('eut.p_rated') #p_rated_prime = ts.param_value('eut.p_rated_prime') var_rated = ts.param_value('eut.var_rated') s_rated = ts.param_value('eut.s_rated') #absorb_enable = ts.param_value('eut.abs_enabled') # DC voltages v_in_nom = ts.param_value('eut.v_in_nom') #v_min_in = ts.param_value('eut.v_in_min') #v_max_in = ts.param_value('eut.v_in_max') # AC voltages v_nom = ts.param_value('eut.v_nom') v_min = ts.param_value('eut.v_low') v_max = ts.param_value('eut.v_high') p_min = ts.param_value('eut.p_min') p_min_prime = ts.param_value('eut.p_min_prime') phases = ts.param_value('eut.phases') pf_response_time = ts.param_value('vv.test_imbalanced_t_r') # Pass/fail accuracies pf_msa = ts.param_value('eut.pf_msa') # According to Table 3-Minimum requirements for manufacturers stated measured and calculated accuracy MSA_Q = 0.05 * s_rated MSA_P = 0.05 * s_rated MSA_V = 0.01 * v_nom imbalance_fix = ts.param_value('vv.imbalance_fix') """ A separate module has been create for the 1547.1 Standard """ lib_1547 = p1547.module_1547(ts=ts, aif='VV', imbalance_angle_fix=imbalance_fix) ts.log_debug('1547.1 Library configured for %s' % lib_1547.get_test_name()) # Get the rslt parameters for plot result_params = lib_1547.get_rslt_param_plot() ''' a) Connect the EUT according to the instructions and specifications provided by the manufacturer. ''' # initialize HIL environment, if necessary chil = hil.hil_init(ts) if chil is not None: chil.config() # grid simulator is initialized with test parameters and enabled grid = gridsim.gridsim_init( ts) # 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) pv.power_set(p_rated) pv.power_on() # Turn on DC so the EUT can be initialized # DAS soft channels # TODO : add to library 1547 das_points = { 'sc': ('Q_TARGET', 'Q_TARGET_MIN', 'Q_TARGET_MAX', 'Q_MEAS', 'V_TARGET', 'V_MEAS', 'event') } # initialize data acquisition system daq = das.das_init(ts, sc_points=das_points['sc']) if daq is not None: daq.sc['Q_TARGET'] = 100 daq.sc['Q_TARGET_MIN'] = 100 daq.sc['Q_TARGET_MAX'] = 100 daq.sc['V_TARGET'] = v_nom daq.sc['event'] = 'None' ts.log('DAS device: %s' % daq.info()) ''' b) Set all voltage trip parameters to the widest range of adjustability. Disable all reactive/active power control functions. ''' ''' 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(lib_1547.get_rslt_sum_col_name()) ''' d) Adjust the EUT's available active power to Prated. For an EUT with an input voltage range, set the input voltage to Vin_nom. ''' if pv is not None: pv.iv_curve_config(pmp=p_rated, vmp=v_in_nom) pv.irradiance_set(1000.) ''' h) Once steady state is reached, begin the adjustment of phase voltages. ''' """ Test start """ for imbalance_response in imbalance_resp: for vv_curve in vv_curves: ''' e) Set EUT volt-watt parameters to the values specified by Characteristic 1. All other function be turned off. ''' v_pairs = lib_1547.get_params(curve=vv_curve) # it is assumed the EUT is on eut = der.der_init(ts) if eut is not None: vv_curve_params = { 'v': [ v_pairs['V1'] * (100 / v_nom), v_pairs['V2'] * (100 / v_nom), v_pairs['V3'] * (100 / v_nom), v_pairs['V4'] * (100 / v_nom) ], 'q': [ v_pairs['Q1'] * (100 / var_rated), v_pairs['Q2'] * (100 / var_rated), v_pairs['Q3'] * (100 / var_rated), v_pairs['Q4'] * (100 / var_rated) ], 'DeptRef': 'Q_MAX_PCT' } ts.log_debug('Sending VV points: %s' % vv_curve_params) eut.volt_var(params={ 'Ena': True, 'curve': vv_curve_params }) # ASK @Jay about this loop. Necessary here ? Could go inside your driver... for i in range(10): if not eut.volt_var()['Ena']: ts.log_error( 'EUT VV Enable register not set to True. Trying again...' ) eut.volt_var(params={'Ena': True}) ts.sleep(1) else: break # 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. ''' if eut is not None: ts.log_debug('Initial EUT VV settings are %s' % eut.volt_var()) ts.log_debug('curve points: %s' % v_pairs) ''' g) Wait for steady state to be reached. Every time a parameter is stepped or ramped, measure and record the time domain current and voltage response for at least 4 times the maximum expected response time after the stimulus, and measure or derive, active power, apparent power, reactive power, and power factor. ''' """ Test start """ step = 'Step G' daq.sc['event'] = step daq.data_sample() ts.log('Wait for steady state to be reached') ts.sleep(4 * vv_response_time[vv_curve]) ts.log(imbalance_resp) ts.log('Starting imbalance test with VV mode at %s' % (imbalance_response)) if imbalance_fix == "Yes": dataset_filename = 'VV_IMB_%s_FIX' % (imbalance_response) else: dataset_filename = 'VV_IMB_%s' % (imbalance_response) ts.log('------------{}------------'.format(dataset_filename)) # Start the data acquisition systems daq.data_capture(True) ''' h) For multiphase units, step the AC test source voltage to Case A from Table 24. ''' if grid is not None: step = 'Step H' ts.log( 'Voltage step: setting Grid simulator to case A (IEEE 1547.1-Table 24)(%s)' % step) q_initial = lib_1547.get_initial(daq=daq, step=step) lib_1547.set_grid_asymmetric(grid=grid, case='case_a') q_v_analysis = lib_1547.criteria( daq=daq, tr=vv_response_time[vv_curve], step=step, initial_value=q_initial, curve=vv_curve) result_summary.write( lib_1547.write_rslt_sum(analysis=q_v_analysis, step=step, filename=dataset_filename)) ''' w) For multiphase units, step the AC test source voltage to VN. ''' if grid is not None: # STD_CHANGE : This step is not following order step = 'Step W' ts.log( 'Voltage step: setting Grid simulator voltage to %s (%s)' % (v_nom, step)) q_initial = lib_1547.get_initial(daq=daq, step=step) grid.voltage(v_nom) q_v_analysis = lib_1547.criteria( daq=daq, tr=vv_response_time[vv_curve], step=step, initial_value=q_initial, curve=vv_curve, target=v_nom) result_summary.write( lib_1547.write_rslt_sum(analysis=q_v_analysis, step=step, filename=dataset_filename)) """ i) For multiphase units, step the AC test source voltage to Case B from Table 24. """ if grid is not None: step = 'Step I' ts.log( 'Voltage step: setting Grid simulator to case B (IEEE 1547.1-Table 24)(%s)' % step) q_initial = lib_1547.get_initial(daq=daq, step=step) lib_1547.set_grid_asymmetric(grid=grid, case='case_b') q_v_analysis = lib_1547.criteria( daq=daq, tr=vv_response_time[vv_curve], step=step, initial_value=q_initial, curve=vv_curve) result_summary.write( lib_1547.write_rslt_sum(analysis=q_v_analysis, step=step, filename=dataset_filename)) """ j) For multiphase units, step the AC test source voltage to VN """ if grid is not None: ts.log( 'Voltage step: setting Grid simulator voltage to %s (%s)' % (v_nom, step)) step = 'Step J' q_initial = lib_1547.get_initial(daq=daq, step=step) grid.voltage(v_nom) q_v_analysis = lib_1547.criteria( daq=daq, tr=vv_response_time[vv_curve], step=step, initial_value=q_initial, curve=vv_curve, target=v_nom) result_summary.write( lib_1547.write_rslt_sum(analysis=q_v_analysis, step=step, filename=dataset_filename)) 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, e: reason = str(e) if reason: ts.log_error(reason)
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") """ A separate module has been create for the 1547.1 Standard """ lib_1547 = p1547.module_1547(ts=ts, aif='FW') ts.log_debug("1547.1 Library configured for %s" % lib_1547.get_test_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 = lib_1547.get_sc_points() # initialize data acquisition system daq = das.das_init(ts, sc_points=das_points['sc']) 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) ''' 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) 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 = lib_1547.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(lib_1547.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 #'MaxLimW': round(p_rated / 2.0, 2) * -1 }) 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) "" "" "" ''' for fw_curve in fw_curves: ts.log('Starting test with characteristic curve %s' % (fw_curve)) fw_param = lib_1547.get_params(curve=fw_curve) a_f = lib_1547.MRA_F * 1.5 lib_1547.set_step_label(starting_label='G') f_steps_dic[mode] = collections.OrderedDict() if mode == 'Above': # 1547.1 (5.15.2.2): f_steps_dic[mode][lib_1547.get_step_label()] = ( f_nom + fw_param['dbf']) + a_f f_steps_dic[mode][lib_1547.get_step_label()] = ( f_nom + fw_param['dbf']) - a_f f_steps_dic[mode][lib_1547.get_step_label()] = ( f_nom + fw_param['dbf']) + a_f f_steps_dic[mode][lib_1547.get_step_label( )] = fw_param['f_small'] + f_nom + fw_param['dbf'] # STD_CHANGE : step k) should consider the accuracy f_steps_dic[mode][lib_1547.get_step_label()] = f_max - a_f f_steps_dic[mode][lib_1547.get_step_label( )] = f_max - fw_param['f_small'] f_steps_dic[mode][lib_1547.get_step_label()] = ( f_nom + fw_param['dbf']) + a_f f_steps_dic[mode][lib_1547.get_step_label()] = ( f_nom + fw_param['dbf']) - a_f f_steps_dic[mode][lib_1547.get_step_label()] = f_nom for step, frequency in f_steps_dic[mode].iteritems(): f_steps_dic[mode].update( {step: np.around(frequency, 3)}) if frequency > f_max: ts.log( "{0} frequency step (value : {1}) changed to fH (f_max)" .format(step, frequency)) f_steps_dic[mode].update({step: f_max}) elif mode == 'Below': # 1547.1 (5.15.3.2): f_steps_dic[mode][lib_1547.get_step_label()] = ( f_nom + fw_param['dbf']) - a_f f_steps_dic[mode][lib_1547.get_step_label()] = ( f_nom - fw_param['dbf']) - a_f f_steps_dic[mode][lib_1547.get_step_label( )] = f_nom - fw_param['f_small'] - fw_param['dbf'] # STD_CHANGE : step j) should consider the accuracy f_steps_dic[mode][lib_1547.get_step_label()] = f_min + a_f f_steps_dic[mode][lib_1547.get_step_label( )] = f_min + fw_param['f_small'] f_steps_dic[mode][lib_1547.get_step_label()] = ( f_nom - fw_param['dbf']) - a_f f_steps_dic[mode][lib_1547.get_step_label()] = ( f_nom - fw_param['dbf']) + a_f f_steps_dic[mode][lib_1547.get_step_label()] = f_nom for step, frequency in f_steps_dic[mode].iteritems(): f_steps_dic[mode].update( {step: np.around(frequency, 3)}) if frequency < f_min: ts.log( "{0} frequency step (value : {1}) changed to fL (f_min)" .format(step, frequency)) f_steps_dic[mode].update({step: f_min}) ''' p) Repeat test steps b) through o) with the EUT power set at 20% and 66% of rated power. ''' for power in pwr_lvls: 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) 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(4 * fw_param['tr']) daq.data_capture(True) for step_label, f_step in f_steps_dic[mode].iteritems(): p_initial = lib_1547.get_initial_value(daq=daq, step=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) lib_1547.process_data( daq=daq, tr=fw_param['tr'], step=step_label, initial_value=p_initial, x_target=step_dict, #y_target=None, #automatically calculated in p1547 curve=fw_curve, pwr_lvl=power, result_summary=result_summary, filename=dataset_filename) 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, e: reason = str(e) if reason: ts.log_error(reason)
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') 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') p_min_prime = ts.param_value('eut.p_min_prime') phases = ts.param_value('eut.phases') # RT test parameters lf_ena = ts.param_value('frt.lf_ena') hf_ena = ts.param_value('frt.hf_ena') freq_response_time = ts.param_value('frt.response_time') n_iter = ts.param_value('frt.n_iter') pwr_lvl = ts.param_value('frt.pwr_value') # Pass/fail accuracies pf_msa = ts.param_value('eut.pf_msa') # EUI Absorb capabilities absorb = {} absorb['ena'] = ts.param_value('eut_cpf.sink_power') absorb['p_rated_prime'] = ts.param_value('eut_cpf.p_rated_prime') absorb['p_min_prime'] = ts.param_value('eut_cpf.p_min_prime') # Functions to be enabled for test mode = [] steps_dict = {} if lf_ena == 'Enabled': mode.append(LF) lf_value = ts.param_value('frt.lf_value') if not(isinstance(lf_value, float) or isinstance(lf_value, int)): #TODO if not numeric value inputed pass elif not (f_min <= lf_value <= 57.0): #TODO raise error if not between f_min and 57.0 raise ValueError steps_dict[LF] = {'location': f'C:/', 'value': lf_value} if hf_ena == 'Enabled': mode.append(HF) hf_value = ts.param_value('frt.hf_value') if not(isinstance(hf_value, float) or isinstance(hf_value, int)): #TODO if not numeric value inputed pass elif not 61.7 <= hf_value <= f_max: #TODO raise error if not between 63.0 and f_max raise ValueError steps_dict[HF] = {'location': f'C:/', 'value': hf_value} if not (isinstance(freq_response_time, float) or isinstance(freq_response_time, int)): # TODO if not numeric value inputed pass elif 299 > freq_response_time: # TODO timedelay must be over 299 sec raise ValueError time_step = {'location': f'C:....', 'value': freq_response_time } """ A separate module has been create for the 1547.1 Standard """ lib_1547 = p1547.module_1547(ts=ts, aif='FW', absorb=absorb) ts.log_debug("1547.1 Library configured for %s" % lib_1547.get_test_name()) # result params result_params = lib_1547.get_rslt_param_plot() ts.log(result_params) # initialize HIL environment, if necessary phil = hil.hil_init(ts) if phil is not None: phil.config() # grid simulator is initialized with test parameters and enabled grid = gridsim.gridsim_init(ts) # 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 = lib_1547.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()) """ """ a) Connect the EUT according to the instructions and specifications provided by the manufacturer. """ # it is assumed the EUT is on eut = der.der_init(ts) if eut is not None: eut.config() eut.deactivate_all_fct() # 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(lib_1547.get_rslt_sum_col_name()) """ c) Set the frequency droop function and droop values to make the active power change with respect to frequency as small as possible. """ if eut is not None: default_curve = 1 fw_settings = lib_1547.get_params(aif=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'] } eut.freq_watt(fw_curve_params) ts.log_debug('Sending FW points: %s' % fw_curve_params) """ d) Set or verify that all frequency trip settings are set to not influence the outcome of the test. """ ts.log_debug('If not done already, set L/HVRT and trip parameters to the widest range of adjustability.') ts.log_debug(f'{mode}') #TODO Isolated Source mode?? for current_mode in mode: ts.log_debug(f'Initializing {current_mode}') # TODO FIND A WAY TO SET ROCOF """ e) Operate the ac test source at nominal frequency ± 0.1 Hz. """ if grid is not None: grid.voltage(v_nom) ts.log(f'Setting Grid simulator voltage to {v_nom}') grid.freq(f_nom) ts.log(f'Setting Grid simulator frequency to {f_nom}') for i in range(1, n_iter+1): ts.log_debug('Starting mode = %s and %s' % (current_mode, current_mode == VV)) daq.data_capture(True) dataset_filename = f'FRT_{current_mode}_{i}' ts.log('------------{}------------'.format(dataset_filename)) #step_label = lib_1547.set_step_label(starting_label='F') #step = lib_1547.get_step_label() """ f) Operate EUT at any convenient power level between 90% and 100% of EUT rating and at any convenient power factor. Record the output current of the EUT at the nominal frequency condition. """ if pv is not None: pv.iv_curve_config(pmp=p_rated, vmp=v_nom_in) pv.irradiance_set(1000.) pv.power_set(round(pwr_lvl*p_rated)) """ ***For High Frequency RT test mode*** g) Adjust the source frequency from PN to PU where fU is greater than or equal to 61.8 Hz. The source shall be held at this frequency for period th, which shall be not less than 299 s. """ # Set values for steps freq_step_location = steps_dict[current_mode]['location'] freq_step_value = steps_dict[current_mode]['value'] ts.log(f'Frequency step: setting Grid simulator frequency to {freq_step_value}Hz') ts.log(f'At frequency step location: {freq_step_location}') # Set timestep time_step_location = time_step['location'] time_step_value = time_step['value'] ts.log(f'Time setting: setting Grid simulator time setting to {time_step_value}sec') ts.log(f'At time step location: {time_step_location}') if phil is not None: #Send commands to HIL phil.set_params((freq_step_location, freq_step_value)) phil.set_params((time_step_location, time_step_value)) #TODO HIL SECTION TO BE COMPLETED ts.log('Stop time set to %s' % phil.set_stop_time(stop_time)) if compilation == 'Yes': ts.log(" Model ID: {}".format(phil.compile_model().get("modelId"))) if stop_sim == 'Yes': ts.log(" {}".format(phil.stop_simulation())) if load == 'Yes': ts.log(" {}".format(phil.load_model_on_hil())) if execute == 'Yes': ts.log(" {}".format(phil.start_simulation())) sim_time = phil.get_time() while (stop_time - sim_time) > 1.0: # final sleep will get to stop_time. sim_time = phil.get_time() ts.log('Sim Time: %s. Waiting another %s sec before saving data.' % ( sim_time, stop_time - sim_time)) ts.sleep(1) """ h) Decrease the frequency of the ac test source to the nominal frequency ± 0.1 Hz. """ if grid is not None: grid.freq(f_nom) ts.log(f'Frequency step: setting Grid simulator frequency to {f_nom}') """ i) Repeat steps f) and g) twice for a total of three tests. """ """ j) During all frequency transitions in steps f) through h), the ROCOF shall be greater than or equal to the ROCOF limit in Table 21 of IEEE Std 1547-2018 and shall be within the demonstrated ROCOF capability of the EUT. """ 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.freq_watt(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 watt_var_mode(wv_curves, wv_response_time): result = script.RESULT_FAIL daq = None v_nom = None grid = None pv = None eut = None chil = None result_summary = None dataset_filename = None try: cat = ts.param_value('eut.cat') cat2 = ts.param_value('eut.cat2') sink_power = ts.param_value('eut.sink_power') p_rated = ts.param_value('eut.p_rated') p_rated_prime = ts.param_value('eut.p_rated_prime') var_rated = ts.param_value('eut.var_rated') s_rated = ts.param_value('eut.s_rated') # DC voltages v_in_nom = ts.param_value('eut.v_in_nom') #v_min_in = ts.param_value('eut.v_in_min') #v_max_in = ts.param_value('eut.v_in_max') # AC voltages v_nom = ts.param_value('eut.v_nom') v_low = ts.param_value('eut.v_low') v_high = ts.param_value('eut.v_high') p_min = ts.param_value('eut.p_min') p_min_prime = ts.param_value('eut.p_min_prime') phases = ts.param_value('eut.phases') # EUI Absorb capabilities absorb = {} absorb['ena'] = ts.param_value('eut_cpf.sink_power') """ A separate module has been create for the 1547.1 Standard """ lib_1547 = p1547.module_1547(ts=ts, aif='WV', absorb=absorb) ts.log_debug("1547.1 Library configured for %s" % lib_1547.get_test_name()) # result params result_params = lib_1547.get_rslt_param_plot() ''' a) Connect the EUT according to the instructions and specifications provided by the manufacturer. ''' # initialize HIL environment, if necessary chil = hil.hil_init(ts) if chil is not None: chil.config() # DAS soft channels das_points = lib_1547.get_sc_points() # initialize data acquisition system daq = das.das_init(ts, sc_points=das_points['sc']) daq.sc['P_TARGET'] = p_min 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()) # 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 if callable(getattr(daq, "set_dc_measurement", None) ): # for DAQs that don't natively have dc measurements daq.set_dc_measurement( pv) # send pv obj to daq to get dc measurements ts.sleep(0.5) eut = der.der_init(ts) if eut is not None: eut.config() ts.log_debug(eut.measurements()) # Special considerations for CHIL ASGC/Typhoon startup if chil is not None: if chil.hil_info()['mode'] == 'Typhoon': inv_power = eut.measurements().get('W') timeout = 120. if inv_power <= p_rated * 0.85: pv.irradiance_set( 995) # Perturb the pv slightly to start the inverter ts.sleep(3) eut.connect(params={'Conn': True}) while inv_power <= p_rated * 0.85 and timeout >= 0: ts.log( 'Inverter power is at %0.1f. Waiting up to %s more seconds or until EUT starts...' % (inv_power, timeout)) ts.sleep(1) timeout -= 1 inv_power = eut.measurements().get('W') if timeout == 0: result = script.RESULT_FAIL raise der.DERError('Inverter did not start.') ts.log('Waiting for EUT to ramp up') ts.sleep(8) ts.log_debug('DAS data_read(): %s' % daq.data_read()) ''' b) Set all AC test source parameters to the nominal operating voltage and frequency. ''' grid = gridsim.gridsim_init( ts) # Turn on AC so the EUT can be initialized if grid is not None: # for HIL-based gridsim objects, link the chil parameters to voltage/frequency simulink parameters if callable(getattr(grid, "gridsim_info", None)): if grid.gridsim_info()['mode'] == 'Opal': grid.config(hil_object=chil) 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(lib_1547.get_rslt_sum_col_name()) ''' c) Set all EUT parameters to the rated active power conditions for the EUT. ''' if pv is not None: pv.iv_curve_config(pmp=p_rated, vmp=v_in_nom) pv.irradiance_set(1000.) ts.log('Waiting for EUT to power up. Sleeping 30 sec.') ts.sleep(30) ''' d) Set all voltage trip parameters to default settings. ''' try: eut.vrt_stay_connected_high( params={ 'Ena': True, 'ActCrv': 0, 'Tms1': 3000, 'V1': v_high, 'Tms2': 0.16, 'V2': v_high }) except Exception, 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, e: ts.log_error('Could not set VRT Stay Connected Low curve. %s' % e)
def volt_watt_mode_imbalanced_grid(imbalance_resp, vw_curves, vw_response_time): result = script.RESULT_FAIL daq = None p_rated = None grid = None pv = None eut = None chil = None result_summary = None try: cat = ts.param_value('eut.cat') cat2 = ts.param_value('eut.cat2') p_rated = ts.param_value('eut.p_rated') s_rated = ts.param_value('eut.s_rated') # DC voltages v_in_nom = ts.param_value('eut.v_in_nom') # AC voltages v_nom = ts.param_value('eut.v_nom') v_min = ts.param_value('eut.v_low') v_max = ts.param_value('eut.v_high') p_min = ts.param_value('eut.p_min') phases = ts.param_value('eut.phases') imbalance_fix = ts.param_value('vw.imbalance_fix') # EUI Absorb capabilities absorb = {} absorb['ena'] = ts.param_value('eut_vw.sink_power') absorb['p_rated_prime'] = ts.param_value('eut_vw.p_rated_prime') absorb['p_min_prime'] = ts.param_value('eut_vw.p_min_prime') ''' A separate module has been create for the 1547.1 Standard ''' lib_1547 = p1547.module_1547(ts=ts, aif='VW', imbalance_angle_fix=imbalance_fix) ts.log_debug('1547.1 Library configured for %s' % lib_1547.get_test_name()) # Get the rslt parameters for plot result_params = lib_1547.get_rslt_param_plot() ''' a) Connect the EUT according to the instructions and specifications provided by the manufacturer. ''' # initialize HIL environment, if necessary chil = hil.hil_init(ts) if chil is not None: chil.config() # grid simulator is initialized with test parameters and enabled grid = gridsim.gridsim_init( ts) # 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 # TODO : add to library 1547 das_points = { 'sc': ('P_TARGET', 'P_TARGET_MIN', 'P_TARGET_MAX', 'P_MEAS', 'V_TARGET', 'V_MEAS', 'event') } # initialize data acquisition system daq = das.das_init(ts, sc_points=das_points['sc']) if daq is not None: daq.sc['P_TARGET'] = 100 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. ''' eut = der.der_init(ts) if eut is not None: eut.config() 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, 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, e: ts.log_error('Could not set VRT Stay Connected Low curve. %s' % e)
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) """ A separate module has been create for the 1547.1 Standard """ lib_1547 = p1547.module_1547(ts=ts, aif='PRI', absorb=absorb) ts.log_debug("1547.1 Library configured for %s" % lib_1547.get_test_name()) # result params result_params = lib_1547.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 = lib_1547.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(lib_1547.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 = lib_1547.get_params(aif=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 = lib_1547.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 and %s' % (current_mode,current_mode == VV)) 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 = lib_1547.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 = lib_1547.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)) #Todo : Start measuring Voltage and """ 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_dict = [{'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}] ''' target_dict = lib_1547.get_params(aif=PRI) ts.log('Target_dict: %s' % (target_dict)) target_dict_updated = {} i = 0 for step in steps_dict: step_label = 'Step_%i_%s' % (i+1, current_mode) step['V'] *= v_nom #v_step = step['V'] * v_nom #f_step = step['F'] target_dict_updated['Q'] = target_dict[i][current_mode] target_dict_updated['P'] = target_dict[i]['P'] ts.log('Voltage step: setting Grid simulator voltage to %s (%s)' % (step['V'], step_label)) ts.log('Frequency step: setting Grid simulator frequency to %s (%s)' % (step['F'], step_label)) ts.log('Ptarget: %s (%s)' % (target_dict_updated['P'], step_label)) ts.log('Qtarget: %s (%s)' % (target_dict_updated['Q'], step_label)) initial_values = lib_1547.get_initial_value(daq=daq, step=step_label) if grid is not None: grid.freq(step['F']) grid.voltage(step['V']) ts.log_debug('step: %s' % step) ts.log_debug('type: %s' % type(step)) ts.log_debug('current mode %s' % current_mode) lib_1547.process_data( daq=daq, tr=pri_response_time, step=step_label, initial_value=initial_values, x_target=step, y_target=target_dict_updated, #x_target=[v_step, f_step], #y_target=[p_target, q_target], result_summary=result_summary, filename=dataset_filename, aif=current_mode ) ts.sleep(2 * pri_response_time) i += 1 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, e: reason = str(e) if reason: ts.log_error(reason)
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') # 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') pf_response_time = ts.param_value('cpf.pf_response_time') # 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') """ A separate module has been create for the 1547.1 Standard """ lib_1547 = p1547.module_1547(ts=ts, aif='CPF', absorb=absorb) ts.log_debug("1547.1 Library configured for %s" % lib_1547.get_test_name()) # result params result_params = lib_1547.get_rslt_param_plot() # get target power factors pf_targets = {} if ts.param_value('cpf.pf_min_inj') == 'Enabled': pf_targets['cpf_min_ind'] = float( ts.param_value('cpf.pf_min_inj_value')) if ts.param_value('cpf.pf_mid_inj') == 'Enabled': pf_targets['cpf_mid_ind'] = float( ts.param_value('cpf.pf_mid_inj_value')) if ts.param_value('cpf.pf_min_ab') == 'Enabled': pf_targets['cpf_min_cap'] = float( ts.param_value('cpf.pf_min_ab_value')) if ts.param_value('cpf.pf_mid_ab') == 'Enabled': pf_targets['cpf_mid_cap'] = float( ts.param_value('cpf.pf_mid_ab_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') raise """ 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) # 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 = lib_1547.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'] = 120 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(lib_1547.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.iteritems(): ts.log('Starting test %s at v_in = %s' % (v_in_label, v_in)) a_v = lib_1547.MRA_V * 1.5 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 pf_test_name, pf_target in pf_targets.iteritems(): if grid is not None: grid.voltage(v_nom) #Setting up step label lib_1547.set_step_label(starting_label='F') ts.log('Starting data capture for pf = %s' % pf_target) if imbalance_fix == "Yes": dataset_filename = ('{0}_{1}_FIX'.format( v_in_label.upper(), pf_test_name.upper())) else: dataset_filename = ('{0}_{1}'.format( v_in_label.upper(), pf_test_name.upper())) ts.log('------------{}------------'.format(dataset_filename)) # Start the data acquisition systems daq.data_capture(True) daq.sc['PF_TARGET'] = pf_target if eut is not None: parameters = {'Ena': True, 'PF': pf_target} ts.log('PF set: %s' % parameters) eut.fixed_pf(params=parameters) pf_setting = eut.fixed_pf() ts.log('PF setting read: %s' % pf_setting) """ f) Wait for steady state to be reached. Every time a parameter is stepped or ramped, measure and record the time domain current and voltage response for at least 4 times the maximum expected response time after the stimulus, and measure or derive, active power, apparent power, reactive power, and power factor. """ step = lib_1547.get_step_label() daq.sc['event'] = step 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 Pmin. """ if pv is not None: step = lib_1547.get_step_label() ts.log( 'Power step: setting PV simulator power to %s (%s)' % (p_min, step)) initial_values = lib_1547.get_initial_value(daq=daq, step=step) step_dict = {'V': v_nom, 'P': p_min, 'PF': pf_target} pv.power_set(step_dict['P']) lib_1547.process_data( daq=daq, tr=pf_response_time, step=step, #curve=vw_curve, pwr_lvl=1.0, x_target=step_dict, initial_value=initial_values, result_summary=result_summary, filename=dataset_filename) """ h) Step the EUT's available active power to Prated. """ if pv is not None: step = lib_1547.get_step_label() ts.log( 'Power step: setting PV simulator power to %s (%s)' % (p_rated, step)) initial_values = lib_1547.get_initial_value(daq=daq, step=step) step_dict = {'V': v_nom, 'P': p_rated, 'PF': pf_target} pv.power_set(step_dict['P']) lib_1547.process_data( daq=daq, tr=pf_response_time, step=step, #curve=vw_curve, pwr_lvl=1.0, x_target=step_dict, initial_value=initial_values, result_summary=result_summary, filename=dataset_filename) if grid is not None: # i) Step the AC test source voltage to (VL + av) step = lib_1547.get_step_label() ts.log( 'Voltage step: setting Grid simulator voltage to %s (%s)' % ((v_min + a_v), step)) #q_initial = lib_1547.get_initial(daq=daq,step=step) initial_values = lib_1547.get_initial_value(daq=daq, step=step) step_dict = { 'V': v_min + a_v, 'P': p_rated, 'PF': pf_target } grid.voltage(step_dict['V']) lib_1547.process_data(daq=daq, tr=pf_response_time, step=step, pwr_lvl=1.0, x_target=step_dict, initial_value=initial_values, result_summary=result_summary, filename=dataset_filename) # j) Step the AC test source voltage to (VH - av) step = lib_1547.get_step_label() ts.log( 'Voltage step: setting Grid simulator voltage to %s (%s)' % ((v_max - a_v), step)) initial_values = lib_1547.get_initial_value(daq=daq, step=step) step_dict = { 'V': v_min - a_v, 'P': p_rated, 'PF': pf_target } grid.voltage(step_dict['V']) lib_1547.process_data( daq=daq, tr=pf_response_time, step=step, #curve=vw_curve, pwr_lvl=1.0, x_target=step_dict, initial_value=initial_values, result_summary=result_summary, filename=dataset_filename) # k) Step the AC test source voltage to (VL + av) step = lib_1547.get_step_label() ts.log( 'Voltage step: setting Grid simulator voltage to %s (%s)' % (v_nom, step)) #q_initial = lib_1547.get_initial(daq=daq,step=step) initial_values = lib_1547.get_initial_value(daq=daq, step=step) step_dict = { 'V': v_min + a_v, 'P': p_rated, 'PF': pf_target } grid.voltage(step_dict['V']) lib_1547.process_data( daq=daq, tr=pf_response_time, step=step, #curve=vw_curve, pwr_lvl=1.0, x_target=step_dict, initial_value=initial_values, result_summary=result_summary, filename=dataset_filename) if grid is not None and phases is 'Three phase': """ l) For multiphase units, step the AC test source voltage to Vnom. """ step = lib_1547.get_step_label() ts.log( 'Voltage step: setting Grid simulator voltage to %s (%s)' % (v_nom, step)) initial_values = lib_1547.get_initial_value(daq=daq, step=step) step_dict = {'V': v_nom, 'P': p_rated, 'PF': pf_target} grid.voltage(step_dict['V']) lib_1547.process_data(daq=daq, tr=pf_response_time, step=step, pwr_lvl=1.0, x_target=step_dict, initial_value=initial_values, result_summary=result_summary, filename=dataset_filename) if grid is not None and phases is 'Three phase': """ m) For multiphase units, step the AC test source voltage to Case A from Table 24. """ step = lib_1547.get_step_label() ts.log( 'Voltage step: setting Grid simulator voltage to %s (%s)' % (v_nom, step)) initial_values = lib_1547.get_initial_value(daq=daq, step=step) step_dict = { 'V': v_nom * (1.07 + 0.91 + 0.91) / 3, 'P': p_rated, 'PF': pf_target } lib_1547.set_grid_asymmetric(grid=grid, case='case_a') #grid.voltage(step_dict['V']) lib_1547.process_data(daq=daq, tr=pf_response_time, step=step, pwr_lvl=1.0, x_target=step_dict, initial_value=initial_values, result_summary=result_summary, filename=dataset_filename) """ n) For multiphase units, step the AC test source voltage to VN. """ if grid is not None and phases is 'Three phase': step = lib_1547.get_step_label() ts.log( 'Voltage step: setting Grid simulator voltage to %s (%s)' % (v_nom, step)) initial_values = lib_1547.get_initial_value(daq=daq, step=step) step_dict = {'V': v_nom, 'P': p_rated, 'PF': pf_target} grid.voltage(step_dict['V']) lib_1547.process_data(daq=daq, tr=pf_response_time, step=step, pwr_lvl=1.0, x_target=step_dict, initial_value=initial_values, result_summary=result_summary, filename=dataset_filename) ''' o) For multiphase units, step the AC test source voltage to Case B from Table 24. ''' if grid is not None and phases is 'Three phase': step = lib_1547.get_step_label() ts.log( 'Voltage step: setting Grid simulator to case B (IEEE 1547.1-Table 24)(%s)' % step) initial_values = lib_1547.get_initial_value(daq=daq, step=step) # TODO READJUST WITH INVERTER CALCULATION WITH IMBALANCED GRID step_dict = { 'V': v_nom * (0.91 + 1.07 + 1.07) / 3, 'P': p_rated, 'PF': pf_target } lib_1547.set_grid_asymmetric(grid=grid, case='case_b') lib_1547.process_data(daq=daq, tr=pf_response_time, step=step, pwr_lvl=1.0, x_target=step_dict, initial_value=initial_values, result_summary=result_summary, filename=dataset_filename) """ p) For multiphase units, step the AC test source voltage to Vnom. """ if grid is not None and phases is 'Three phase': step = lib_1547.get_step_label() ts.log( 'Voltage step: setting Grid simulator voltage to %s (%s)' % (v_nom, step)) initial_values = lib_1547.get_initial_value(daq=daq, step=step) step_dict = {'V': v_nom, 'P': p_rated, 'PF': pf_target} grid.voltage(step_dict['V']) lib_1547.process_data(daq=daq, tr=pf_response_time, step=step, pwr_lvl=1.0, x_target=step_dict, initial_value=initial_values, result_summary=result_summary, filename=dataset_filename) """ q) Disable constant power factor mode. Power factor should return to unity. """ if eut is not None: #parameters = {'Ena': False, 'PF': 1.0} #ts.log('PF set: %s' % parameters) #eut.fixed_pf(params=parameters) step = lib_1547.get_step_label() pf_setting = eut.fixed_pf() ts.log('PF setting read: %s' % pf_setting) daq.sc['event'] = 'Step %s' % step daq.data_sample() ts.sleep(2 * pf_response_time) daq.sc['event'] = 'T_settling_done' daq.data_sample() """ r) 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, e: reason = str(e) if reason: ts.log_error(reason)
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') """ A separate module has been create for the 1547.1 Standard """ lib_1547 = p1547.module_1547(ts=ts, aif='VW', absorb=absorb) ts.log_debug("1547.1 Library configured for %s" % lib_1547.get_test_name()) # result params result_params = lib_1547.get_rslt_param_plot() ''' a) Connect the EUT according to the instructions and specifications provided by the manufacturer. ''' # initialize HIL environment, if necessary chil = hil.hil_init(ts) if chil is not None: chil.config() # pv simulator is initialized with test parameters and enabled pv = pvsim.pvsim_init(ts) 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 #das_points = {'sc': ('P_TARGET', 'P_TARGET_MIN', 'P_TARGET_MAX', 'P_MEAS', 'V_TARGET','V_MEAS','event')} das_points = lib_1547.get_sc_points() # initialize data acquisition system daq = das.das_init(ts, sc_points=das_points['sc']) 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. ''' eut = der.der_init(ts) 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, 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, e: ts.log_error('Could not set VRT Stay Connected Low curve. %s' % e)
def test_run(): result = script.RESULT_FAIL grid = None pv = p_rated = None daq = None eut = None rs = None chil = None result_summary = None step = None q_initial = None dataset_filename = None fw_curves = [] fw_response_time = [0, 0, 0] filename = None result_params = None try: cat = ts.param_value('eut.cat') cat2 = ts.param_value('eut.cat2') sink_power = ts.param_value('eut.sink_power') p_rated = ts.param_value('eut.p_rated') p_rated_prime = ts.param_value('eut.p_rated_prime') s_rated = ts.param_value('eut.s_rated') # DC voltages v_nom_in = ts.param_value('eut.v_in_nom') v_min_in = ts.param_value('eut.v_in_min') v_max_in = ts.param_value('eut.v_in_max') # AC voltages v_nom = ts.param_value('eut.v_nom') v_min = ts.param_value('eut.v_low') v_max = ts.param_value('eut.v_high') p_min = ts.param_value('eut.p_min') phases = ts.param_value('eut.phases') # EUI Absorb capabilities absorb = {} absorb['ena'] = ts.param_value('eut_vw.sink_power') absorb['p_rated_prime'] = ts.param_value('eut_vw.p_rated_prime') absorb['p_min_prime'] = ts.param_value('eut_vw.p_min_prime') # AC voltages f_nom = ts.param_value('eut.f_nom') f_min = ts.param_value('eut.f_min') f_max = ts.param_value('eut.f_max') p_min = ts.param_value('eut.p_min') phases = ts.param_value('eut.phases') # EUI FW parameters absorb_enable = ts.param_value('eut_fw.sink_power') p_rated_prime = ts.param_value('eut_fw.p_rated_prime') p_min_prime = ts.param_value('eut_fw.p_min_prime') p_small = ts.param_value('eut_fw.p_small') if ts.param_value('fw.test_1') == 'Enabled': fw_curves.append(1) fw_response_time[1] = float(ts.param_value('fw.test_1_tr')) if ts.param_value('fw.test_2') == 'Enabled': fw_curves.append(2) fw_response_time[2] = float(ts.param_value('fw.test_2_tr')) # VW parameters absorb = {} absorb['ena'] = ts.param_value('eut_vw.sink_power') """ A separate module has been create for the 1547.1 Standard """ lib_1547 = p1547.module_1547(ts=ts, aif='LAP', absorb=absorb) ts.log_debug("1547.1 Library configured for %s" % lib_1547.get_test_name()) # result params result_params = lib_1547.get_rslt_param_plot() # Set Test parameter act_pwrs = ts.param_value('lap.act_pwr') # List of power level for tests ts.log_debug('%s' % (act_pwrs)) if act_pwrs == '0%': act_pwrs_limits = [0.0] elif act_pwrs == '33%': act_pwrs_limits = [0.33] elif act_pwrs == '66%': act_pwrs_limits = [0.66] else: act_pwrs_limits = [0.66, 0.33, 0.0] # 5.13.2 Procedure asks for three repetitions n_iters = range(1, int(ts.param_value('lap.iter')) + 1) # Take the highest value for the steady state wait time tr_min = min(ts.param_value('fw.test_1_tr'), ts.param_value('vw.test_1_tr')) tr_vw = ts.param_value('vw.test_1_tr') """ a) - Connect the EUT according to the instructions and specifications provided by the manufacturer. - Apply the default settings from IEEE std 1547 for voltage-active power mode (Minimum setting of table 10 of IEEE 1547) - Apply the default settings from frequency droop response in IEE std 1547 for abnormal operating perfomance category of the DER - Enable voltage active power mode """ # initialize HIL environment, if necessary chil = hil.hil_init(ts) if chil is not None: chil.config() # grid simulator is initialized with test parameters and enabled grid = gridsim.gridsim_init(ts, support_interfaces={ 'hil': chil }) # Turn on AC so the EUT can be initialized if grid is not None: grid.voltage(v_nom) # pv simulator is initialized with test parameters and enabled pv = pvsim.pvsim_init(ts) if pv is not None: pv.power_set(p_rated) pv.power_on() # Turn on DC so the EUT can be initialized # DAS soft channels das_points = lib_1547.get_sc_points() ts.log(das_points) # initialize data acquisition daq = das.das_init(ts, sc_points=das_points['sc'], support_interfaces={ 'pvsim': pv, 'hil': chil }) if daq is not None: ts.log('DAS device: %s' % daq.info()) eut = der.der_init(ts) if eut is not None: eut.config() # Enable volt/watt curve and configure default settings eut.volt_watt( params={ 'Ena': True, 'curve': { 'ActPt': 2, 'v': [106, 110], 'w': [100, 0], 'DeptRef': 'W_MAX_PCT', 'RmpPtTms': 10, 'RmpDecTmm': 0, 'RmpIncTmm': 0 } }) eut.freq_watt(params={ 'Ena': True, 'curve': 1, 'dbf': 0.036, 'kof': 0.05, 'RspTms': 5 }) try: eut.vrt_stay_connected_high( params={ 'Ena': True, 'ActCrv': 0, 'Tms1': 3000, 'V1': v_max, 'Tms2': 0.16, 'V2': v_max }) except Exception, e: ts.log_error( 'Could not set VRT Stay Connected High curve. %s' % e) try: eut.frt_stay_connected_high( params={ 'Ena': True, 'ActCrv': 0, 'Tms1': 3000, 'Hz1': f_max, 'Tms2': 160, 'Hz2': f_max }) except Exception, e: ts.log_error( 'Could not set FRT Stay Connected High curve. %s' % e) try: eut.vrt_stay_connected_low( params={ 'Ena': True, 'ActCrv': 0, 'Tms1': 3000, 'V1': v_min, 'Tms2': 0.16, 'V2': v_min }) except Exception, e: ts.log_error('Could not set VRT Stay Connected Low curve. %s' % e)
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 result_params = None try: cat = ts.param_value('eut.cat') cat2 = ts.param_value('eut.cat2') sink_power = ts.param_value('eut.sink_power') p_rated = ts.param_value('eut.p_rated') p_rated_prime = ts.param_value('eut.p_rated_prime') s_rated = ts.param_value('eut.s_rated') 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') response_time = ts.param_value('crp.response_time') # 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') """ A separate module has been create for the 1547.1 Standard """ lib_1547 = p1547.module_1547(ts=ts, aif='CRP', absorb=absorb) ts.log_debug("1547.1 Library configured for %s" % lib_1547.get_test_name()) # result params result_params = lib_1547.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')) ts.log('Evaluating the following Reactive Power Targets: %s' % q_targets) 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: raise 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 start_up = 60 ts.log('Waiting for EUT to power up. Sleeping %s sec.' % start_up) ts.sleep(start_up) das_points = lib_1547.get_sc_points() # DAS soft channels # 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'] = None daq.sc['P_MEAS'] = None daq.sc['Q_MEAS'] = None daq.sc['Q_TARGET_MIN'] = None daq.sc['Q_TARGET_MAX'] = None daq.sc['PF_TARGET'] = None 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.volt_var(params={'Ena': False}) # disable volt/var curve eut.watt_var(params={'Ena': False}) eut.volt_watt(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: if chil.hil_info()['mode'] == 'Typhoon': inv_power = eut.measurements().get('W') timeout = 120. if inv_power <= p_rated * 0.85: pv.irradiance_set( 995) # Perturb the pv slightly to start the inverter ts.sleep(3) eut.connect(params={'Conn': True}) while inv_power <= p_rated * 0.85 and timeout >= 0: ts.log( 'Inverter power is at %0.1f. Waiting up to %s more seconds or until EUT starts...' % (inv_power, timeout)) ts.sleep(1) timeout -= 1 inv_power = eut.measurements().get('W') if timeout == 0: result = script.RESULT_FAIL raise der.DERError('Inverter did not start.') ts.log('Waiting for EUT to ramp up') ts.sleep(8) """ 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(lib_1547.get_rslt_sum_col_name()) """ v) Steps d) through s) may be repeated to test additional protocols methods. (Rerun script in those cases) u) For an EUT with an input voltage range, repeat steps d) through t) for Vin_min and Vin_max """ # For PV systems, this requires that Vmpp = Vin_nom and Pmpp = Prated. for v_in_label, v_in in v_in_targets.iteritems(): ts.log('Starting test %s at v_in = %s' % (v_in_label, v_in)) a_v = lib_1547.MRA_V * 1.5 if pv is not None: pv.iv_curve_config(pmp=p_rated, vmp=v_in) pv.irradiance_set(1000.) ts.sleep(60.) # Give EUT time to track new I-V Curve """ t) Repeat steps d) through s) for additional reactive power settings: Qmax,ab, 0.5Qmax,inj, 0.5Qmax,ab. d) Adjust the EUT's active power to Prated. For an EUT with an input voltage range, set the input voltage to Vin_nom. (previously completed) e) Enable constant power factor mode and set the EUT power factor to PFmin,inj. """ for q_test_name, q_target in q_targets.iteritems(): dataset_filename = '%s_v=%0.1f' % (q_test_name, v_in) ts.log('------------{}------------'.format(dataset_filename)) q_target *= var_rated ts.log('Starting data capture for fixed Q relative = %s' % q_target) daq.data_capture(True) # Start the data acquisition systems daq.sc['Q_TARGET'] = q_target if eut is not None: parameters = { 'Ena': True, 'VArPct_Mod': 1, # 1 = WMax percentage 'VArWMaxPct': (100. * q_target) / var_rated } ts.log('Parameters set: %s' % parameters) eut.reactive_power(params=parameters) """ f) Verify Constant Var mode is reported as active and that the reactive power setting is reported as Qmax,inj. """ ts.log('Waiting 15 seconds before reading back parameters') ts.sleep(15) vars_setting = eut.reactive_power() ts.log('fixed vars setting read: %s' % vars_setting) """ g) Step the EUT's active power to 20% of Prated or Pmin, whichever is less. h) Step the EUT's active power to 5% of Prated or Pmin, whichever is less. i) Step the EUT's available active power to Prated. j) Step the AC test source voltage to (VL + av). k) Step the AC test source voltage to (VH - av). l) Step the AC test source voltage to (VL + av). m) For multiphase units, step the AC test source voltage to VN. n) For multiphase units, step the AC test source voltage to Case A from Table 24. o) For multiphase units, step the AC test source voltage to VN. p) For multiphase units, step the AC test source voltage to Case B from Table 24. q) For multiphase units, step the AC test source voltage to VN. """ lib_1547.set_step_label(starting_label='G') crp_dict = collections.OrderedDict() crp_dict[lib_1547.get_step_label()] = { 'p_pv': min(0.2 * p_rated, p_min) } # G crp_dict[lib_1547.get_step_label()] = { 'p_pv': min(0.05 * p_rated, p_min) } # H crp_dict[lib_1547.get_step_label()] = {'p_pv': p_rated} # I crp_dict[lib_1547.get_step_label()] = {'V': v_min + a_v} # J crp_dict[lib_1547.get_step_label()] = {'V': v_max - a_v} # K crp_dict[lib_1547.get_step_label()] = {'V': v_min + a_v} # L crp_dict[lib_1547.get_step_label()] = {'V': v_nom} # M if imbalance_fix == "Yes": crp_dict[lib_1547.get_step_label()] = { 'V': [v_nom * 1.07, v_nom * 0.91, v_nom * 0.91] } # N crp_dict[lib_1547.get_step_label()] = {'V': v_nom} # O crp_dict[lib_1547.get_step_label()] = { 'V': [v_nom * 0.91, v_nom * 1.07, v_nom * 1.07] } # P crp_dict[lib_1547.get_step_label()] = {'V': v_nom} # Q for step_label, step_change in crp_dict.iteritems(): daq.data_sample() initial_values = lib_1547.get_initial_value( daq=daq, step=step_label) if pv is not None and step_change.get('p_pv') is not None: pwr_lvl = step_change.get('p_pv') ts.log( 'Power step: setting PV simulator power to %s (%s)' % (pwr_lvl, step)) pv.power_set(pwr_lvl) if grid is not None and step_change.get('V') is not None: volt = step_change.get('V') ts.log( 'Voltage step: setting grid simulator voltage to %s (%s)' % (volt, step)) grid.voltage(volt) lib_1547.process_data(daq=daq, tr=response_time, step=step_label, pwr_lvl=1.0, y_target=q_target, initial_value=initial_values, result_summary=result_summary, filename=dataset_filename, number_of_tr=1) """ r) Disable constant reactive power mode. Reactive power should return to zero. s) Verify all reactive/active power control functions are disabled. """ if eut is not None: ts.log('Reactive Power disabled. Readback: %s' % eut.reactive_power(params={'Ena': False})) step_label = lib_1547.get_step_label() ts.log( 'Waiting %s seconds to get the next Tr data for analysis...' % response_time) ts.sleep(response_time) daq.data_sample() # sample new data data = daq.data_capture_read( ) # Return dataset created from last data capture q_meas = lib_1547.get_measurement_total(data=data, type_meas='Q', log=False) daq.sc['Q_MEAS'] = q_meas daq.sc['Q_TARGET'] = 0.0 daq.sc['EVENT'] = "{0}_TR_1".format(step_label) daq.sc[ 'Q_TARGET_MIN'] = daq.sc['Q_TARGET'] - 1.5 * lib_1547.MRA_Q daq.sc[ 'Q_TARGET_MAX'] = daq.sc['Q_TARGET'] + 1.5 * lib_1547.MRA_Q if daq.sc['Q_TARGET_MIN'] <= daq.sc['Q_MEAS'] <= daq.sc[ 'Q_TARGET_MAX']: daq.sc['90%_BY_TR=1'] = 'Pass' else: daq.sc['90%_BY_TR=1'] = 'Fail' ts.log_debug( 'Disabled CRP: q_min [%s] <= q_meas [%s] <= q_max [%s] = %s' % (daq.sc['Q_TARGET_MIN'], daq.sc['Q_MEAS'], daq.sc['Q_TARGET_MAX'], daq.sc['90%_BY_TR=1'])) daq.data_sample() # 90%_BY_TR=1, V_MEAS, V_TARGET, P_MEAS, P_TARGET, Q_MEAS, Q_TARGET, Q_TARGET_MIN, # Q_TARGET_MAX, PF_MEAS, STEP, FILENAME row_data = [] row_data.append(str(daq.sc['90%_BY_TR=1'])) row_data.append( str( lib_1547.get_measurement_total(data=data, type_meas='V', log=False))) row_data.append('None') row_data.append( str( lib_1547.get_measurement_total(data=data, type_meas='P', log=False))) row_data.append('None') row_data.append(str(daq.sc['Q_MEAS'])) row_data.append(str(daq.sc['Q_TARGET'])) row_data.append(str(daq.sc['Q_TARGET_MIN'])) row_data.append(str(daq.sc['Q_TARGET_MAX'])) row_data.append( str( lib_1547.get_measurement_total(data=data, type_meas='PF', log=False))) row_data.append(str(step_label)) row_data.append(str(dataset_filename)) row_data_str = ','.join(row_data) + '\n' result_summary.write(row_data_str) 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, e: reason = str(e) if reason: ts.log_error(reason)