classdef ScopeKeysight %NAME Summary of this class goes here % Detailed explanation goes here properties(Access=public) model scope_model fadc scope_fadc channel autoScale extRef removeDC interpolate recordLen IPaddress waitUntilClick end methods (Access=public) function obj = ScopeKeysight(options) %NAME Construct an instance of this class % Detailed explanation goes here arguments options.model scope_model = scope_model.DSAZ634A; options.fadc scope_fadc = scope_fadc.GSa_160; options.channel logical = [0,0,0,0]; options.autoScale logical = 0; options.extRef logical = 1; options.removeDC logical = 1; options.interpolate logical = 0; options.recordLen double = 1000000; options.IPaddress options.waitUntilClick = 0; end % fn = fieldnames(options); for n = 1:numel(fn) try obj.(fn{n}) = options.(fn{n}); end end switch obj.model case scope_model.DSAZ634A case scope_model.UXR1102A end end function recordedSignals = read(obj,options) arguments obj options.channel logical = obj.channel options.waitUntilClick = obj.waitUntilClick; end %%%%%%%%%%%%%%%%%%%%%%%% %%% CONNECT TO SCOPE %%% %%%%%%%%%%%%%%%%%%%%%%%% if isempty(obj.IPaddress) switch obj.model case scope_model.DSAZ634A v=visadev('TCPIP0::keysight.tf.uni-kiel.de::inst0::INSTR');% TCPIP0::127.0.0.1::inst0::INSTR case scope_model.UXR1102A v=visadev('TCPIP0::testscope.tf.uni-kiel.de::inst0::INSTR');% TCPIP0::127.0.0.1::inst0::INSTR case scope_model.UXR1104B v=visadev('TCPIP0::134.245.243.239::inst0::INSTR'); end else try ressourceName=['TCPIP0::',char(obj.IPaddress),'::inst0::INSTR']; v=visadev(ressourceName); catch error(['Could not connect to instrument using VISA. Check VISA ressourcename -> ', ressourceName]); end end debug = 1; if debug disp(['Connected to Instrument: ',char(v.Vendor),' ',char(v.Model),' SerNo:',char(v.SerialNumber)]); end % Check if Scope is ready to go opdone = 0; acqdone = 0; procdone = 1; while ~opdone || ~acqdone || ~procdone opdone = sscanf(obj.writeReceiveCheck(v,'*opc?'), '%f'); acqdone = sscanf(obj.writeReceiveCheck(v,'ader?'), '%f'); %procdone = sscanf(obj.writeReceiveCheck(v,'pder?'), '%f'); pause(0.005); end armed = sscanf(obj.writeReceiveCheck(v,'aer?'), '%f'); scope_state = strtrim(obj.writeReceiveCheck(v,'RSTate?')); % Set sample rate / activate real edge if obj.fadc == scope_fadc.GSa_160 obj.writeNcheck(v,':ACQuire:REDGe 1'); if length(obj.channel)>1 if obj.channel(2) == 1 error("CH 2 is invalid for Real Edge configuration. ONLY use channel 1 and 3 as shown on scope! Simply use [1,0,1,0] as channel config to record 1 and 3.") end elseif length(obj.channel)>3 if obj.channel(2) == 1 || obj.channel(4) == 1 error("CH 2 is invalid for Real Edge configuration. ONLY use channel 1 and 3 as shown on scope! Simply use [1,0,1,0] as channel config to record 1 and 3.") end end else obj.writeNcheck(v,':ACQuire:REDGe 0'); obj.writeNcheck(v,sprintf(':ACQuire:SRATe %u',double(obj.fadc).*1e9)); end % for n = find(obj.channel == 1) obj.writeNcheck(v,sprintf(':CHANnel%u:DISPlay ON',n));% display captured data trace end set(v,'Timeout',150); if obj.autoScale obj.writeNcheck(v,':AUTOscale'); for n = 1:4 range = str2double(obj.writeReceiveCheck(v,sprintf(':CHANnel%u:RANGe?',n))); %use this to finetune autoscaling - VERY helpful % higher value leads to higher scaling fintunefactor = 1.4; % within [1,...,2] obj.writeNcheck(v,sprintf(':CHANnel%u:RANGe %.3f',n,range/fintunefactor)); end else %obj.writeNcheck(v,':SINGLE'); end % After Autoscale, let the user adjust the scope scaling... % "options.waitUntilClick" was a shit name but now this is it :-) if options.waitUntilClick % Create a dialog box with the desired text d = dialog('Name', 'Scale Scope then press continue', 'Position', [300, 300, 300, 180]); % Add a text label with the instruction uicontrol('Parent', d, ... 'Style', 'text', ... 'Position', [20, 100, 260, 40], ... 'String', 'Please adjust scope scaling now, then press continue', ... 'HorizontalAlignment', 'center'); % Add a button to close the dialog and resume execution uicontrol('Parent', d, ... 'Style', 'pushbutton', ... 'Position', [100, 40, 100, 40], ... 'String', 'Continue', ... 'Callback', 'uiresume(gcbf); delete(gcbf)'); % Pause execution until the dialog box is closed uiwait(d); end if obj.extRef switch obj.model case scope_model.DSAZ634A obj.writeNcheck(v,':TIMebase:REFClock HFR'); case scope_model.UXR1102A || scope_model.UXR1104B obj.writeNcheck(v,':TIMebase:REFClock 1'); end REFclock = strtrim(obj.writeReceiveCheck(v,':TIMebase:REFClock?')); if ~strcmp(REFclock,'HFR') obj.writeNcheck(v,':TIMebase:REFClock ON'); REFclock = strtrim(obj.writeReceiveCheck(v,':TIMebase:REFClock?')); assert(~(strcmp(REFclock,'OFF') || strcmp(REFclock,'0')),'No Refclock found: Using internal') end else obj.writeNcheck(v,':TIMebase:REFClock 0'); end if obj.interpolate obj.writeNcheck(v,'ACQ:INTerpolate INT16'); obj.writeNcheck(v,sprintf(':ACQuire:POINts %u',obj.recordLen+100)); else obj.writeNcheck(v,sprintf(':ACQuire:POINts %u',obj.recordLen+100)); obj.writeNcheck(v,'ACQ:INTerpolate OFF'); end obj.writeNcheck(v,':SYSTem:HEADer OFF'); % turn off system headers obj.writeNcheck(v,':WAVEFORM:FORMAT WORD');% set the data format type to WORD obj.writeNcheck(v,':WAVEFORM:BYTeorder LSBFirst');% Setup transfer of LSB first obj.writeNcheck(v,':WAVEFORM:STReaming off');% Turn off waveform streaming for n = find(obj.channel == 1) obj.writeNcheck(v,sprintf(':CHANnel%u:DISPlay ON',n));% display captured data trace end %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%% Acquire Data from Scope %%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% obj.writeNcheck(v,':DIGitize'); recordedSignals = cell(size(obj.channel)); for n = find(obj.channel == 1) % record recordedSignals{n} = obj.readChannel(v,n); % cut "safety samples" that were added at the end recordedSignals{n} = recordedSignals{n}(1:obj.recordLen); if obj.removeDC recordedSignals{n} = recordedSignals{n}-mean(recordedSignals{n}); end obj.writeNcheck(v,sprintf(':CHANnel%u:DISPlay ON',n)); end % fill all other channels with nothing for n = find(obj.channel == 0) recordedSignals{n} = []; end obj.writeNcheck(v,sprintf(':%s',scope_state)); obj.writeNcheck(v,'*OPC?'); opdone = 0; acqdone = 0; procdone = 0; while ~opdone || ~acqdone || ~procdone opdone = sscanf(obj.writeReceiveCheck(v,'*opc?'), '%f'); acqdone = sscanf(obj.writeReceiveCheck(v,'ader?'), '%f'); procdone = sscanf(obj.writeReceiveCheck(v,'pder?'), '%f'); pause(0.005); end % arrange to Electrcalsinal class as output %% for ch = 1:numel(obj.channel) recordedSignals{ch} = Electricalsignal(recordedSignals{ch},"fs",obj.fadc.getValue);%fs is a enum and requires get function end end end methods (Access=private) function captured_signal = readChannel(obj, v, aCH) Format = 'word'; if strcmpi(Format,'word') nBytes = 2; blockReadType = 'int16'; elseif strcmpi(Format,'byte') nBytes = 1; blockReadType = 'int8'; else error('Param.Format not recognized'); end maxBlockSize = pow2(20); obj.writeNcheck(v,sprintf(':WAVeform:SOURce CHANnel%u',aCH)); % read x origin:WAVeform:SOURce xOrg = str2double(obj.writeReceiveCheck(v,':wav:xor?'));% read x origin xInc = str2double(obj.writeReceiveCheck(v,':wav:xinc?'));% read x increment => 1/fadc xRef = str2double(obj.writeReceiveCheck(v,':wav:xref?')); yOrg = str2double(obj.writeReceiveCheck(v,':wav:yor?'));% read y origin yInc = str2double(obj.writeReceiveCheck(v,':wav:yInc?'));% read y increment yRef = str2double(obj.writeReceiveCheck(v,':wav:yref?')); points = str2double(obj.writeReceiveCheck(v,':wav:points?')); % timerperiod = max(10,1e-6*points*nBytes); % set(v,'TimerPeriod',timerperiod); timeout = min([max(10,1e-6*points*nBytes) 1000]); set(v,'Timeout',timeout); blockSize = min(pow2(ceil(log2(points))),maxBlockSize); set(v,'InputBufferSize',nBytes*blockSize); blockCount = int8(ceil(max(1,points/blockSize))); for block = 0:blockCount - 1 startPoint = double(block) * blockSize + 1; endPoint = min((double(block + 1)) * blockSize,points); pointsRead = endPoint - startPoint + 1; obj.writeNcheck(v, sprintf(':wav:data? %d,%d', startPoint, pointsRead)); %Wfm.data(startPoint:endPoint,1) = binblockread(v,blockReadType); %old Matlab data(startPoint:endPoint,1) = readbinblock(v,blockReadType); Junk = fread(v,1,'schar'); %#ok Read out end of file character. end %scale the signal back to volt captured_signal = data*yInc+yOrg; end function writeNcheck(~,visaobj,command) % 1) send command to intstument % 2) check if everything is okay writeline(visaobj,char(command)); % writeline(visaobj,':syst:err?'); % err_aw=readline(visaobj); % assert(strfind(err_aw,"No error"),['AWG System Error? after command: ', char(command)]) end function [aw]=writeReceiveCheck(~,visaobj,command) % 1) send command to intstument % 2) receive answer from instrument % 3) check i f everything is okay writeline(visaobj,char(command)); aw = readline(visaobj); % writeline(visaobj,':syst:err?'); % err_aw=readline(visaobj); % assert(strfind(err_aw,"No error"),['AWG System Error? after command: ', char(command)]) end end end