def open(self): ''' Open connection with 5 retries. ''' if self.mbSession is not None: return if self.address is None: raise RuntimeError("Attempting to open connection to unknown address.") if self.resMan is None: self.resMan = pyvisa.ResourceManager() try: self.mbSession = self.resMan.open_resource(self.address) self.mbSession.write_termination = self.termination if not self.tempSess: logger.debug('Opened %s', self.address) except pyvisa.VisaIOError as err: logger.warning('There was a problem opening the VISA %s... Error code: %s', self.address, err.error_code) if self._open_retries < OPEN_RETRIES: self._open_retries += 1 time.sleep(0.5 * self._open_retries) logger.warning('Trying again... (try = %s/%s)', self._open_retries, OPEN_RETRIES) self.open() else: logger.error(err) raise else: if self._open_retries != 0: logger.warning('Found it!') self._open_retries = 0
def amplAndOffs(self, amplOffs=None): ''' Amplitude and offset setting/getting Only uses the data-bar because the other one is broken Args: amplOffs (tuple(float)): new amplitude and offset in volts If either is None, returns but does not set Returns: (tuple(float)): amplitude and offset, read from hardware if specified as None ''' if amplOffs is None: amplOffs = (None, None) if np.isscalar(amplOffs): raise ValueError('amplOffs must be a tuple. ' + 'You can specify one element as None if you don\'t want to set it') amplitude, offset = amplOffs amplitude = np.clip(amplitude, *self.amplitudeRange) if amplitude is not None: self.setConfigParam('AMP', '{} V'.format(amplitude)) try: ampl = float(self.getConfigParam('AMP').split(' ')[0]) except VisaIOError: logger.error('unable to get the amplitude') ampl = None if offset is not None: self.setConfigParam('OFS', '{} V'.format(offset)) try: offs = float(self.getConfigParam('OFS').split(' ')[0]) except VisaIOError: logger.error('unable to get the offset') offs = None return (ampl, offs)
def connect(self): ''' Connects to the socket and leaves the connection open. If already connected, does nothing. Returns: socket object. ''' if self._socket is None: s = socket.socket(socket.AF_INET, socket.SOCK_STREAM, socket.IPPROTO_TCP) try: logger.debug("Attempting new connection (timeout = %s)", str(self.timeout)) init_time = time.time() s.settimeout(self.timeout) s.connect((self.ip_address, self.port)) except socket.error: # avoiding shutdown to prevent sending any data to remote socket # https://stackoverflow.com/questions/13109899/does-socket-become-unusable-after-connect-fails # s.shutdown(socket.SHUT_WR) s.close() del s logger.error('Cannot connect to resource.') raise else: final_time = time.time() elapsed_time_ms = 1e3 * (final_time - init_time) logger.debug("Connected. Time elapsed: %s msec", '{:.2f}'.format(elapsed_time_ms)) self._socket = s return self._socket else: return self._socket
def __transferData(self, chan): ''' Returns the raw data pulled from the scope as time (seconds) and voltage (Volts) Args: chan (int): one channel at a time Returns: :mod:`data.Waveform`: a time, voltage paired signal Todo: Make this binary transfer to go even faster ''' chStr = 'CH' + str(chan) self.setConfigParam('DATA:ENCDG', 'ASCII') self.setConfigParam('DATA:SOURCE', chStr) self.open() try: voltRaw = self.mbSession.query_ascii_values('CURV?') except pyvisa.VisaIOError as err: logger.error('Problem during query_ascii_values(\'CURV?\')') try: self.close() except pyvisa.VisaIOError: logger.error('Failed to close! %s', self.address) raise err self.close() return voltRaw
def close(self): if self.mbSession is None: return try: self.mbSession.close() except pyvisa.VisaIOError: logger.error('There was a problem closing the VISA %s', self.address) raise self.mbSession = None if not self.tempSess: logger.debug('Closed %s', self.address)
def instrID(self): """Overloads the super function because the OSA does not respond to *IDN? Instead sends a simple command and waits for a confirmed return """ try: self.write('SPSWPMSK?') except socket.error: logger.error('OSA communication test failed. Sent: \'SPSWPMSK?\'') raise else: return 'Apex AP2440A'
def write(self, writeStr): try: self.open() try: self.mbSession.write(writeStr) except Exception: logger.error('Problem writing to %s', self.address) raise logger.debug('%s - W - %s', self.address, writeStr) finally: if self.tempSess: self.close()
def __getFullHardwareConfig(self, subgroup=''): ''' Get everything that is returned by the SET? query Args: subgroup (str): default '' means everything Returns: TekConfig: structured configuration object ''' self.initHardware() logger.info('Querying SET? response of %s', self.instrID()) try: resp = self.query('SET?') return TekConfig.fromSETresponse(resp, subgroup=subgroup) except VisaIOError as err: # SET timed out. You are done. logger.error( '%s timed out on \'SET?\'. \ Try resetting with \'*RST\'.', self.instrID()) raise err
def query(self, queryStr, withTimeout=None): retStr = None try: self.open() logger.debug('%s - Q - %s', self.address, queryStr) toutOrig = self.timeout try: if withTimeout is not None: self.timeout = withTimeout retStr = self.mbSession.query(queryStr) if withTimeout is not None: self.timeout = toutOrig except Exception: logger.error('Problem querying to %s', self.address) # self.close() raise retStr = retStr.rstrip() logger.debug('Query Read - %s', retStr) finally: if self.tempSess: self.close() return retStr
def _getHardwareConfig(self, cStrList): ''' Queries all or a subgroup of commands using the state of the 'live' config. This does not return, but it puts it in the config['live'] attribute Args: cStrList (list or str): list of command strings. Can also be a scalar string ''' self.initHardware() if type(cStrList) is not list and type(cStrList) is str: cStrList = [cStrList] for cStr in cStrList: if cStr[-1] == '&': # handle the sibling subdir token cStr = cStr[:-2] try: ret = self.query(cStr + '?') except VisaIOError: logger.error( 'Problematic parameter was %s.\n' 'Likely it does not exist in this instrument command structure.', cStr) raise logger.debug('Queried %s, got %s', cStr, ret) if self.header: val = ret.split(' ')[-1] else: val = ret # Type detection try: val = float(val) except ValueError: pass else: if val == floor(val): val = int(val) self.config['live'].set(cStr, val)