343 lines
13 KiB
Matlab
343 lines
13 KiB
Matlab
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
|