""" Provide basic class to operate scope Created by Eugeniy E. Mikhailov 2021/11/29 """ import pyvisa import scpi import re import numpy as np class Scope(scpi.SCPIinstr): """ Do not instantiate directly, use rm = pyvisa.ResourceManager() Scope(rm.open_resource('TCPIP::192.168.0.2::INSTR')) """ def __init__(self, resource): super().__init__(resource) class SDS1104x(Scope): def __init__(self, resource): super().__init__(resource) self.resource.read_termination='\n' self.maxRequiredPoints = 1000; # desired number of points per channel, can return twice more def mean(self, chNum): # get mean on a specific channel calculated by scope # PAVA stands for PArameter VAlue qstr = f'C{chNum}:PAVA? MEAN' rstr = self.query(qstr); # reply is in the form 'C1:PAVA MEAN,3.00E-02V' spltStr = re.split(',', rstr) rstr = spltStr[1] spltStr = re.split('V', rstr) rstr = spltStr[0] return( float(rstr) ) def getAvailableNumberOfPoints(self, chNum): if chNum != 1 and chNum != 3: # for whatever reason 'SAMPLE_NUM' fails for channel 2 and 4 chNum = 1 qstr = f'SAMPLE_NUM? C{chNum}' rstr = self.query(qstr) # reply is in the form 'SANU 7.00E+01pts' spltStr = re.split(' ', rstr) spltStr = re.split('pts', spltStr[1]) rstr = spltStr[0] return( int(float(rstr)) ) def getSampleRate(self): rstr = self.query('SAMPLE_RATE?'); # expected reply is like 'SARA 1.00E+09Sa/s' spltStr = re.split(' ', rstr) spltStr = re.split('Sa/s', spltStr[1]) rstr = spltStr[0] return( int(float(rstr)) ) def getRawWaveform(self, chNum, availableNpnts=None, sampleRate=None, maxRequiredPoints=None): if availableNpnts == None: availableNpnts = self.getAvailableNumberOfPoints(chNum) if sampleRate == None: sampleRate = self.getSampleRate() if maxRequiredPoints == None: maxRequiredPoints = self.maxRequiredPoints if availableNpnts <= maxRequiredPoints*2: Npnts = availableNpnts sparsing = 1 cstr = f'WAVEFORM_SETUP NP,0,FP,0,SP,{sparsing}' self.write(cstr) else: sparsing = int(np.floor(availableNpnts/maxRequiredPoints)) Npnts = int(np.floor(availableNpnts/sparsing)) cstr = f'WAVEFORM_SETUP SP,{sparsing},NP,{Npnts},FP,0' # Note: it is not enough to provide sparsing (SP), # number of points (NP) needed to be calculated properly too! # From the manual # WAVEFORM_SETUP SP,,NP,,FP, # SP Sparse point. It defines the interval between data points. # For example: # SP = 0 sends all data points. # SP = 1 sends all data points. # SP = 4 sends every 4th data point # NP — Number of points. It indicates how many points should be transmitted. # For example: # NP = 0 sends all data points. # NP = 50 sends a maximum of 50 data points. # FP — First point. It specifies the address of the first data point to be sent. # For example: # FP = 0 corresponds to the first data point. # FP = 1 corresponds to the second data point qstr = f'C{chNum}:WAVEFORM? DAT2' wfRaw=self.query_binary_values(qstr, datatype='b', header_fmt='ieee', container=np.array) # expected full reply: 'C1:WF DAT2,#9000000140.........' return(wfRaw) def getChanVoltsPerDiv(self, chNum): qstr = f'C{chNum}:VDIV?' rstr = self.query(qstr) # expected reply to query: 'C1:VDIV 1.04E+00V' res = re.split(' ', rstr) res = re.split('V', res[1]) VoltsPerDiv = float(res[0]) return(VoltsPerDiv) def getChanOffset(self, chNum): qstr = f'C{chNum}:OFST?' rstr = self.query(qstr) # expected reply to query: 'C1:OFST -1.27E+00V' res = re.split(' ', rstr) res = re.split('V', res[1]) VoltageOffset = float(res[0]) return(VoltageOffset) def getWaveform(self, chNum, availableNpnts=None, sampleRate=None, maxRequiredPoints=None): wfRaw = self.getRawWaveform(chNum, availableNpnts=availableNpnts, sampleRate=sampleRate, maxRequiredPoints=maxRequiredPoints) vertDivOnScreen = 10 VoltageOffset = self.getChanOffset(chNum) VoltsPerDiv = self.getChanVoltsPerDiv(chNum) return( wfRaw * VoltsPerDiv * vertDivOnScreen/250 -VoltageOffset ) if __name__ == '__main__': print("testing") rm = pyvisa.ResourceManager() print(rm.list_resources()) instr=rm.open_resource('TCPIP::192.168.0.61::INSTR') scope = SDS1104x(instr) print(scope.idn) print(scope.mean(1)) print(scope.getAvailableNumberOfPoints(1)) print(scope.getSampleRate()) print(scope.getChanVoltsPerDiv(1)) print(scope.getChanOffset(1)) wf = scope.getWaveform(1)