def query_serial(self, cmd_str): resp = '' more_data = True self.cmd_serial(cmd_str) while more_data: try: count = self.conn.inWaiting() if count < 1: count = 1 data = self.conn.read(count) if len(data) > 0: for d in data: resp += d if d == '\n': more_data = False break else: raise gridsim.GridSimError('Timeout waiting for response') except gridsim.GridSimError: raise except Exception, e: raise gridsim.GridSimError( 'Timeout waiting for response - More data problem')
def cmd_serial(self, cmd_str): self.cmd_str = cmd_str try: if self.conn is None: raise gridsim.GridSimError('Communications port not open') self.conn.flushInput() self.conn.write(cmd_str) except Exception, e: raise gridsim.GridSimError(str(e))
def cmd(self, cmd_str): self.cmd_str = cmd_str try: self.dev.cmd(cmd_str) resp = self.dev.query('SYSTem:ERRor?\n') #\r if len(resp) > 0: if resp[0] != '0': raise gridsim.GridSimError(resp + ' ' + self.cmd_str) except Exception, e: raise gridsim.GridSimError(str(e))
def write_visa(self, cmd_str): """ Performs a SCPI write command with the given cmd_str :param cmd_str: the SCPI command which must be a valid command """ try: if self.conn is None: raise gridsim.GridSimError('VISA GPIB connection not open') num_written_bytes = self.conn.write(cmd_str) return num_written_bytes except Exception, e: raise gridsim.GridSimError(str(e))
def query_visa(self, cmd_str): """ Performs a SCPI query with the given cmd_str and returns the reply of the device :param cmd_str: the SCPI command which must be a valid command :return: the answer from the SPS """ try: if self.conn is None: raise gridsim.GridSimError('VISA GPIB connection not open') return self.conn.query(cmd_str) except Exception, e: raise gridsim.GridSimError(str(e))
def _write(self, cmd_str): """ Performs a SCPI write command with the given cmd_str :param cmd_str: the SCPI command which must be a valid command """ try: if self.conn is None: raise gridsim.GridSimError('GPIB connection not open') num_written_bytes = self.conn.write(cmd_str) # TODO: check num_written_bytes to see if writing succeeded return num_written_bytes except Exception, e: raise gridsim.GridSimError(str(e))
def open(self): """ Open the communications resources associated with the grid simulator. """ try: if self.comm == 'Serial': self.conn = serial.Serial(port=self.serial_port, baudrate=self.baudrate, bytesize=8, stopbits=1, xonxoff=0, timeout=self.timeout, writeTimeout=self.write_timeout) elif self.comm == 'GPIB': raise NotImplementedError( 'The driver for plain GPIB is not implemented yet. ' + 'Please use VISA which supports also GPIB devices') elif self.comm == 'VISA': try: # sys.path.append(os.path.normpath(self.visa_path)) import visa self.rm = visa.ResourceManager() self.conn = self.rm.open_resource(self.visa_device) # the default pyvisa write termination is '\r\n' which does not work with the SPS self.conn.write_termination = '\n' self.ts.sleep(1) except Exception, e: raise gridsim.GridSimError( 'Cannot open VISA connection to %s\n\t%s' % (self.visa_device, str(e))) else:
def regen(self, state=None): """ Set the state of the regen mode if provided. Valid states are: REGEN_ON, REGEN_OFF. If none is provided, obtains the state of the regen mode. """ if state == gridsim.REGEN_ON: self.cmd('REGenerate:STATe ON\n') self.query('*esr?\n') self.cmd('INST:COUP ALL\n') self.query('*esr?\n') self.cmd('INST:COUP none;:inst:nsel 1;\n') elif state == gridsim.REGEN_OFF: self.cmd('REGenerate:STATe OFF\n') self.query('*esr?\n') self.cmd('INST:COUP ALL\n') self.query('*esr?\n') self.cmd('INST:COUP none;:inst:nsel 1;\n') elif state is None: current_state = self.query('REGenerate:STATe?\n') if current_state is '1': state = 'on' else: state = 'off' else: raise gridsim.GridSimError('Unknown regen state: %s', state) return state
def relay(self, state=None): """ Set the state of the relay if provided. Valid states are: RELAY_OPEN, RELAY_CLOSED. If none is provided, obtains the state of the relay. """ if state is not None: if state == gridsim.RELAY_OPEN: self.cmd('abort;:outp off\n') elif state == gridsim.RELAY_CLOSED: self.cmd('abort;:outp on\n') else: raise gridsim.GridSimError('Invalid relay state. State = "%s"', state) else: relay = self.query(':AC:STAT:READ?\n').strip() #self.ts.log(relay) #if relay == '0': if relay == ':AC:STAT:READ 0': state = gridsim.RELAY_OPEN #elif relay == '1': elif relay == ':AC:STAT:READ 1': state = gridsim.RELAY_CLOSED else: state = gridsim.RELAY_UNKNOWN return state
def open(self): """ Open the communications resources associated with the grid simulator. """ self.ts.log('Gridsim Open') try: if self.comm == 'GPIB': raise NotImplementedError('The driver for plain GPIB is not implemented yet. ' + 'Please use VISA which supports also GPIB devices') elif self.comm == 'VISA': try: # sys.path.append(os.path.normpath(self.visa_path)) import visa self.rm = visa.ResourceManager() self.conn = self.rm.open_resource(self.visa_device) self.ts.log('Gridsim Visa config') # TODO : Add the connection for AWG430 # the default pyvisa write termination is '\r\n' work with the ELGAR704 (p.3-2 Manual Addendum) #self.conn.write_termination = '\r\n' self.ts.sleep(1) except Exception, e: raise gridsim.GridSimError('Cannot open VISA connection to %s\n\t%s' % (self.visa_device,str(e))) else:
def relay(self, state=None): """ Set the state of the relay if provided. If none is provided, obtains the state of the relay. :param state: valid states are: RELAY_OPEN, RELAY_CLOSED """ if state is not None: if state == gridsim.RELAY_OPEN: self._write('AMP:Output 0') self.ts.log('Opened Relay') elif state == gridsim.RELAY_CLOSED: self._write('AMP:Output 1') self.ts.log('Closed Relay') else: raise gridsim.GridSimError('Invalid relay state: %s' % state) else: state = int(self._query('AMP:Output?')) if state == 0: state = gridsim.RELAY_OPEN elif state == 1: state = gridsim.RELAY_CLOSED else: state = gridsim.RELAY_UNKNOWN return state
def config(self): """ Perform any configuration for the simulation based on the previously provided parameters. """ if self.ts.confirm('Configure grid simulator to following settings:\n' ' \nVoltage = %s\nMax voltage = %s\nMax current = %s\nFrequency = %s' % (self.v_nom, self.v_max, self.i_max, self.freq_param)) is False: raise gridsim.GridSimError('Aborted grid simulation')
def open(self): """ Open the communications resources associated with the device. """ try: self.dev.open() except Exception, e: raise gridsim.GridSimError('Cannot open VISA connection to %s' % (self.visa_device))
def open(self): """ Open the communications resources associated with the grid simulator. """ try: self.conn = serial.Serial(port=self.serial_port, baudrate=self.baudrate, bytesize=8, stopbits=1, xonxoff=0, timeout=self.timeout, writeTimeout=self.write_timeout) time.sleep(2) except Exception, e: raise gridsim.GridSimError(str(e))
def aberration(self, freq=None, voltage=None, cycles=None): # keep frequency between 50 and 70 Hz even though the maximum are 45 and 1000 Hz if freq is not none and voltage is not none and cycles: self.cmd('ABBR W {}, V {}, F {}'.format(cycles, voltage, freq)) else: raise gridsim.GridSimError( 'Invalid parameters for aberration function') return 0
def profile_start(self): """ Start the loaded profile. """ if self.profile is not None: self.ts.log('Starting profile: %s' % self.profile_name) prev_v = self.voltage()[0] prev_f = self.freq() for entry in self.profile: if not self._numeric_equal(prev_v, entry.v, self.eps): if not self._numeric_equal(prev_f, entry.f, self.eps): # change in voltage and frequency self.ts.log( '\tChange voltage from %0.1fV to %0.1fV and frequency from %0.1fHz to %0.1fHz in %0.2fs' % (prev_v, entry.v, prev_f, entry.f, entry.t)) self.amplitude_frequency_ramp( amplitude_end_value=entry.v, end_frequency=entry.f, ramp_time=entry.t, phases=entry.ph, amplitude_start_value=prev_v, start_frequency=prev_f) else: # change in voltage self.ts.log( '\tChange voltage from %0.1fV to %0.1fV in %0.2fs' % (prev_v, entry.v, entry.t)) self.amplitude_ramp(end_value=entry.v, ramp_time=entry.t, phases=entry.ph, start_value=prev_v) elif not self._numeric_equal(prev_f, entry.f, self.eps): # change in frequency self.ts.log( '\tChange frequency from %0.1fHz to %0.1fHz in %0.2fs' % (prev_f, entry.f, entry.t)) self.frequency_ramp(end_frequency=entry.f, ramp_time=entry.t, start_frequency=prev_f) else: # wait, because no change in voltage or frequency self.ts.log('\tWait %0.2fs' % entry.t) self.ts.sleep(entry.t) prev_v = entry.v prev_f = entry.f self.ts.log('Finished profile') else: raise gridsim.GridSimError( 'You have to load a profile before starting it')
def regen(self, state=None): """ Set the state of the regen mode if provided. Valid states are: REGEN_ON, REGEN_OFF. If none is provided, obtains the state of the regen mode. :param state: :return: """ if state == gridsim.REGEN_ON: # do nothing, because regen mode is always on pass elif state == gridsim.REGEN_OFF: raise gridsim.GridSimError( 'Cannot disable the regen mode. It is always ON for the SPS gridsim' ) elif state is None: state = gridsim.REGEN_ON # Regeneration is always on for SPS else: raise gridsim.GridSimError('Unknown regen state: %s', state) return state
def current_max(self, current=None): """ Set the value for max current if provided. If none provided, obtains the value for max current. """ if current is not None: if self.ts.confirm('Set grid simulator maximum current to %s' % (current)) is False: raise gridsim.GridSimError('Aborted grid simulation') else: current = self.i_max return current
def cmd_tcp(self, cmd_str): try: if self.conn is None: self.ts.log('ipaddr = %s ipport = %s' % (self.ipaddr, self.ipport)) self.conn = socket.socket(socket.AF_INET, socket.SOCK_STREAM) self.conn.settimeout(self.timeout) self.conn.connect((self.ipaddr, self.ipport)) # print 'cmd> %s' % (cmd_str) self.conn.send(cmd_str) except Exception, e: raise gridsim.GridSimError(str(e))
def voltage_max(self, voltage=None): """ Set the value for max voltage if provided. If none provided, obtains the value for max voltage. """ if voltage is not None: self.v_max = voltage[0] if self.ts.confirm('Set grid simulator maximum voltage to %s' % (voltage)) is False: raise gridsim.GridSimError('Aborted grid simulation') else: voltage = (self.v_max, self.v_max, self.v_max) return voltage
def __init__(self, ts, group_name): self.buffer_size = 1024 self.conn = None gridsim.GridSim.__init__(self, ts, group_name) self.v_nom_param = self._param_value('v_nom') self.v_max_param = self._param_value('v_max') self.i_max_param = self._param_value('i_max') self.freq_param = self._param_value('freq') self.comm = self._param_value('comm') self.serial_port = self._param_value('serial_port') self.ipaddr = self._param_value('ip_addr') self.ipport = self._param_value('ip_port') self.gpib_bus_address = self._param_value('gpib_bus_address') self.gpib_board = self._param_value('gpib_board') self.visa_device = self._param_value('visa_device') self.baudrate = 115200 self.timeout = 5 self.write_timeout = 2 self.cmd_str = '' self._cmd = None self._query = None self.profile_name = ts.param_value('profile.profile_name') if self.comm == 'Serial': self.open() # open communications self._cmd = self.cmd_serial self._query = self.query_serial elif self.comm == 'TCP/IP': self._cmd = self.cmd_tcp self._query = self.query_tcp elif self.comm == 'GPIB': raise NotImplementedError('GPIB is not implemented yet.') elif self.comm == 'VISA': try: # sys.path.append(os.path.normpath(self.visa_path)) import visa self.rm = visa.ResourceManager() self.conn = self.rm.open_resource(self.visa_device) # the default pyvisa write termination is '\r\n' which does not work with the SPS self.conn.write_termination = '\n' self.ts.sleep(1) self._cmd = self.cmd_visa self._query = self.query_visa except Exception, e: raise gridsim.GridSimError( 'Cannot open VISA connection to %s\n\t%s' % (self.visa_device, str(e)))
def relay(self, state=None): """ Set the state of the relay if provided. Valid states are: RELAY_OPEN, RELAY_CLOSED. If none is provided, obtains the state of the relay. """ if state is not None: self.relay_state = state if self.ts.confirm('Set grid simulator relay to %s' % (state)) is False: raise gridsim.GridSimError('Aborted grid simulation') else: state = self.relay_state return state
def voltage_max(self, voltage=None): """ Set the value for max voltage if provided. If none provided, obtains the value for max voltage. :param voltage: :return: """ if voltage is not None: voltage = float(max( voltage)) # voltage is a triplet but SPS only takes one value if voltage <= 0: raise gridsim.GridSimError( 'Maximum Voltage must be greater than 0V') # get range values range_values = str(self._query('conf:amp:range?')).split(',') for i, rg in enumerate(range_values): value = float(rg[:-1]) if voltage == value: self._write('amp:range %i' % i) return self._create_3tuple(voltage) # if code reaches this, the set value is not within the supported ranges raise gridsim.GridSimError( 'Invalid maximum voltage. SPS does not support %sV as maximum Voltage (Range)' % str(voltage)) else: # return 270 # get range act_range = int(self._query('amp:range?')) # get range values range_values = str(self._query('conf:amp:range?')).split(',') return self._create_3tuple(float(range_values[act_range - 1][:-1]))
def voltage_max(self, voltage=None): """ Set the value for max voltage if provided. If none provided, obtains the value for max voltage. """ if voltage is not None: voltage = max(voltage) # voltage is a triplet but Ametek only takes one value if voltage == 150 or voltage == 300 or voltage == 600: self.cmd('volt:rang %0.0f\n' % voltage) else: raise gridsim.GridSimError('Invalid Max Voltage %s, must be 150, 300 or 600 V.' % str(voltage)) v1 = self.query('inst:coup none;:inst:nsel 1;:volt:ac? max\n') v2 = self.query('inst:nsel 2;:volt:ac? max\n') v3 = self.query('inst:nsel 3;:volt:ac? max\n') return float(v1[:-1]), float(v2[:-1]), float(v3[:-1])
def __init__(self, ts, group_name): self.buffer_size = 1024 self.conn = None gridsim.GridSim.__init__(self, ts, group_name) self.phases_param = self._param_value('phases') self.v_nom_param = float(self._param_value('v_nom')) self.v_max_param = self._param_value('v_max') self.i_max_param = self._param_value('i_max') self.freq_param = self._param_value('freq') self.comm = self._param_value('comm') self.serial_port = self._param_value('serial_port') self.ipaddr = self._param_value('ip_addr') self.ipport = self._param_value('ip_port') self.baudrate = 115200 self.timeout = 5 self.write_timeout = 2 self.cmd_str = '' self._cmd = None self._query = None self.profile_name = ts.param_value('profile.profile_name') if self.comm == 'Serial': self.open() # open communications self._cmd = self.cmd_serial self._query = self.query_serial elif self.comm == 'TCP/IP': self._cmd = self.cmd_tcp self._query = self.query_tcp self.cmd('*CLS\n') # self.cmd('*RST\n') # Reset the entire system self.profile_stop() if self.auto_config == 'Enabled': ts.log('Configuring the Grid Simulator.') self.config() state = self.relay() if state != gridsim.RELAY_CLOSED: if self.ts.confirm( 'Would you like to close the grid simulator relay and ENERGIZE the system?' ) is False: raise gridsim.GridSimError('Aborted grid simulation') else: self.ts.log('Turning on grid simulator.') self.relay(state=gridsim.RELAY_CLOSED)
def distortion(self, state=None): """ This command listed in paragraphs are used to program an 8% distortion """ # if state is not None: if state == 'ON': self.cmd('DIST0') elif state == gridsim.RELAY_CLOSED: self.cmd('DISTO1') else: raise gridsim.GridSimError('Invalid relay state. State = "%s"', state) self.ts.log_warning( 'This equipment does not have a regenerative mode.') state == gridsim.REGEN_OFF return state
def __init__(self, ts): self.rm = None # Resource Manager for VISA self.conn = None # Connection to instrument for VISA-GPIB self.dt_min = 0.02 # minimal delta t for amplitude pulses to avoid to fast amplitude changes self.ProfileEntry = namedtuple('ProfileEntry', 't v f ph') self.execution_time = 0.02 self.eps = 0.01 gridsim.GridSim.__init__(self, ts) self.auto_config = ts.param_value('gridsim.auto_config') self.v_nom_param = ts.param_value('gridsim.sps.v_nom') self.v_max_param = ts.param_value('gridsim.sps.v_max') self.i_max_param = ts.param_value('gridsim.sps.i_max') self.freq_param = ts.param_value('gridsim.sps.freq') self.profile_name = ts.param_value('gridsim.sps.profile_name') self.comm = ts.param_value('gridsim.sps.comm') self.serial_port = ts.param_value('gridsim.sps.serial_port') self.gpib_bus_address = ts.param_value('gridsim.sps.gpib_bus_address') self.gpib_board = ts.param_value('gridsim.sps.gpib_board') self.visa_device = ts.param_value('gridsim.sps.visa_device') self.visa_path = ts.param_value('gridsim.sps.visa_path') self.open() # open communications, not the relay self.profile_stop() if self.auto_config == 'Enabled': ts.log('Configuring the Grid Simulator.') self.config() # sets the output voltage to v_nom state = self.relay() if state != gridsim.RELAY_CLOSED: if self.ts.confirm( 'Would you like to close the grid simulator relay and ENERGIZE the system?' ) is False: raise gridsim.GridSimError('Aborted grid simulation') else: self.ts.log('Turning on grid simulator.') self.relay(state=gridsim.RELAY_CLOSED) if self.profile_name is not None and self.profile_name != 'Manual': self.profile_load(self.v_nom_param, self.freq_param, self.profile_name)
def current_max(self, current=None): """ Set the value for max current if provided. If none provided, obtains the value for max voltage. """ if current is not None: current = max(current) # current is a triplet but Elgar only takes one value # TODO : Check if it matches with ELGAR 704 if current == 10 : self.cmd('CURLS %0.0f' % current) else: raise gridsim.GridSimError('Invalid Max Voltage %s V, must be 132 V.' % str(current)) i1 = self.query('TST IA') i2 = self.query('TST IB') i3 = self.query('TST IC') return float(i1[:-1]), float(i2[:-1]), float(i3[:-1])
def query_tcp(self, cmd_str): resp = '' more_data = True self._cmd(cmd_str) while more_data: try: data = self.conn.recv(self.buffer_size) if len(data) > 0: for d in data: resp += d if d == '\n': #\r more_data = False break except Exception, e: raise gridsim.GridSimError('Timeout waiting for response')
def config_phase_angles(self,pang =None): if self.phases_param == 1: self.ts.log_debug('Configuring system for single phase.') # phase 1 always 'preconfigured' at 0 phase angle self.cmd('PANGA 0') # self.form(1) - UNSUPPORTED elif self.phases_param == 2: # set the phase angles for split phase self.ts.log_debug('Configuring system for split phase on Phases A & B.') self.cmd('PANGB 180.0') # self.form(2) - UNSUPPORTED elif self.phases_param == 3: # set the phase angles for the 3 phases self.ts.log_debug('Configuring system for three phase.') self.cmd('PANGB 120.0') self.cmd('PANGB 240.0') # self.form(3) - UNNECESSARY BECAUSE IT IS THE DEFAULT else: raise gridsim.GridSimError('Unsupported phase parameter: %s' % (self.phases_param))