EEVblog Electronics Community Forum

Products => Test Equipment => Topic started by: FunJumper on November 03, 2020, 05:36:22 am

Title: SDS5054X MATLAB VISA Acquisition
Post by: FunJumper on November 03, 2020, 05:36:22 am

SDS5054X MATLAB VISA Acquisition

Hello.

I had a bit of difficulty following the Python example in the SDS5054X  PG01-11A Programming Guide for an implementation of an acquisition of scope memory into PC using MATLAB abd VISA. The guide was dificult to interpret around the Waveform Preamble, and so I used commands, and saw that tis is an approach in PG01-E02B. Further, all the other sections of the SDS5054X  PG01-11A Programming Guide seem to force a save of the data to a USB memory connected to the SDS5054X. I wanted to get the data into the PC using MATLAB.

Follow the NI VISA instructions in SDS5054X  PG01-11A Programming Guide. Or, as it workrd for me since I had the MATLA Instrument Control App, it used a VISA installed with MATLAB.

Connect a signal such as the probe compensation to channel one, and run the script. It should capture your signal, and save/plot it in MATLAB. I created a complex waveform in MALAB and played it out the PC headset jack and used channel 1 to connect to it. See captured and plotted waveform, if I can place an image in EEVBOL Forum.

I hope this is useful for someone.

Thanks.
FunJumper


Script:

%% SDS5054X_try_05 Test Script for Communicating/Controlling SDS5054X.
%
%   Main Steps:   
%       1. Instrument Connection
%       2. Instrument Configuration and Control
%       3. Disconnect and Clean Up
%
%   To SDS5054X_try_05 Test Script, type the name of the file,
%   SDS5054X_try_05, at the MATLAB command prompt.
%
%   The file, SDS5054X_try_05.m must be on your MATLAB PATH. For additional information
%   on setting your MATLAB PATH, type 'help addpath' at the MATLAB command
%   prompt.
%
%   Example:
%       SDS5054X_try_05;

%% Instrument Connection
% Find a VISA-USB object.
obj1 = instrfind('Type', 'visa-usb', 'RsrcName', 'USB0::0xF4EC::0xEE38::SDS5XCBC4R0031::0::INSTR', 'Tag', '');
% Create the VISA-USB object if it does not exist
% otherwise use the object that was found.
if isempty(obj1)
    obj1 = visa('KEYSIGHT', 'USB0::0xF4EC::0xEE38::SDS5XCBC4R0031::0::INSTR');
else
    fclose(obj1);
    obj1 = obj1(1);
end
% Configure instrument object, obj1, to 60000 Input and 512 Output Buffer Size
% 60000 is the largest input I can without generating an error. This allows the
% most data to be transfered from SDS5x to PC at one time.
set(obj1, 'InputBufferSize', 60000);
set(obj1, 'OutputBufferSize', 512);
% Connect to instrument object, obj1.
fopen(obj1);

%% Instrument Configuration and Control
% Communicating with instrument object, obj1.
%       NOTE!: Connect Chan1 to Probe Cal Port for 1kHz 3.3Vpp square wave,
%       or to some external test signal.
% Query the identification number of the SDS5x
SDS5xID = query(obj1, '*IDN?');
% Reset the SDS5x to factory startup
fprintf(obj1, '*RST');
pause(1)

%%% Note some pauses are needed so scope can keep up. Pausing until
% receiving a response would be better. Pause as you need to to make your
% scripte work. %%%

% Disable all input channels
fprintf(obj1, 'CHAN1:SWIT OFF');
fprintf(obj1, 'CHAN2:SWIT OFF');
fprintf(obj1, 'CHAN3:SWIT OFF');
fprintf(obj1, 'CHAN4:SWIT OFF');
pause(1)

% Setup Channel 1
fprintf(obj1, 'CHAN1:BWL 20M');
fprintf(obj1, 'CHAN1:COUP DC');
fprintf(obj1, 'CHAN1:OFFS 0.0E+0');
fprintf(obj1, 'CHAN1:SCAL 0.25E+0');
pause(1)

% Timebase Setup
fprintf(obj1, 'TIM:DEL 0.0E+0');
fprintf(obj1, 'TIM:SCAL 1.0E-2');
pause(1)

% Acquisition Setup
%

% Waveform Setup
fprintf(obj1, 'WAV:SOUR C1');
pause(1)

% Acquire Raw Waveform
fprintf(obj1, 'CHAN1:SWIT ON');
pause(1)

% Trigger Setup
fprintf(obj1, 'TRIG:EDGE:SOUR C1');
fprintf(obj1, 'TRIG:TYPE EDGE');
fprintf(obj1, 'TRIG:EDGE:LEV 1.0E+00');
fprintf(obj1, 'TRIG:RUN'); % Run/Stop to freeze waveform acquired into scope memory
pause(1)
fprintf(obj1, 'TRIG:STOP'); % Can eliminate stopt to continue to trigger on waveform
pause(1)

% Waveform Generator
%fprintf(obj1, 'C1:BSWV WVTP,SQUARE');
%fprintf(obj1, 'C1:BSWV WVTP,RAMP');
%fprintf(obj1, 'C1:BSWV FRQ,5000');
%fprintf(obj1, 'C1:BSWV AMP,3');
%fprintf(obj1, 'C1:BSWV DUTY,30');
%query(obj1, 'C1:BSWV?')
%fprintf(obj1, 'C1:OUTP ON');

% Clear Data  (Probably not needed to clear data.)
clear dataV dataVn dataV_no_head dataVn_no_head read_len scope_mem_len read_steps
clear steps read_start visa_string volt_no_head

% Send Data
read_len = 50000;  % This is the length of data that will be read from the scope, for each loop read. Nice round number, 50000 of 60000 max.
fprintf(obj1, 'WAV:DATA?'); % 1st read from scope. Next reads in for loop. Tell scope to transfer 50000 samples from first sample
pause(0.1)
dataVn = fread(obj1, read_len, 'int8'); % Read the 50000 samples.
pause(0.1)
dataV = [dataVn]; % start a voltage collection vector
dataVn_no_head = dataVn(17:end); % Strip off the header bytes.
dataV_no_head = [dataVn_no_head]; % % start a no head voltage collection vector
%scope_mem_len = str2num(char(dataVn(8:16)'))
scope_mem_len = str2num(query(obj1, 'ACQ:POIN?')); % Get the number of sample the scope acquired
read_steps = ceil(scope_mem_len/read_len); % Fine the number of loop iterations

for steps = 1:(read_steps - 1) % Iterate through all 50000 chunks of data
read_start = read_len*steps + 1; % adjust a new starting point to read a 50000 chunk
visa_string = "WAV:STAR " + read_start % create a visa string for the start point
fprintf(obj1, visa_string); % set the start point for the 50000 chunk
pause(0.1)
query(obj1, 'WAV:STAR?'); % See if the starting point is right
pause(0.1)
fprintf(obj1, 'WAV:DATA?'); % looped read from scope. Tell scope to transfer 50000 samples from new start point at each loop
pause(0.1)
dataVn = fread(obj1, read_len, 'int8'); % Read the 50000 samples.
pause(0.1)
dataV = [dataV; dataVn]; % Concatenate the voltage vector
dataVn_no_head = dataVn(17:end); % strip the headers off the voltage vectors at each loop
dataV_no_head = [dataV_no_head; dataVn_no_head]; % concatenate the no header voltage vector
end

% This deviates from the PG01-E11A Programming guide in that it does not
% use the waveform preamble. It uses commands like CHAN1:SCAL?,
% CHAN1:OFFS?, etc

% Calculate Voltage Waveform
% Read Data
%dataV = fread(obj1, 50000, 'int8'); % 60000 can not be bigger that Input Buffer
%volt_no_head = dataV(17:end-2); % Clear out the 17 header and the last two end file symbols
volt_no_head = dataV_no_head; % change of varialble. (not needed)
% NOTE: the header may not repear on a second read further into scope
% memory, and th end file symols may not occur untilt the end of scope
% memory, not at end of individual read!!! Need to look into this.
vdiv = query(obj1, 'CHAN1:SCAL?'); % Dummy to rid result of chracter header for all following.
vdiv = str2num(query(obj1, 'CHAN1:SCAL?')); % See Step3 formula P591 PG01-E11A
voffset = str2num(query(obj1, 'CHAN1:OFFS?')); % See Step3 formula P591 PG01-E11A
code_per_div = 30; % Constant for SDS5x
voltV = volt_no_head*vdiv/code_per_div - voffset; % voffset is in scope display
% voffset is in scope display, It should not be in final waveform.
% - voffset in formula compensates for this.

% This deviates from the PG01-E11A Programming guide in that it does not
% use the waveform preamble. It uses commands like TIM:SCAL?,
% TIM:DEL?, etc

% Calculate Time Vector
% NOTE: Formula for time in Step4 P592 PG01-E11A needs *index*interval to
% be replaced by + index*interval
timebase = str2num(query(obj1, 'TIM:SCAL?')); % See P246-P247 PG01-E02B and Step4 formula P592 PG01-E11A
delay = str2num(query(obj1, 'TIM:DEL?')); % See Step4 formula P592 PG01-E11A
% query(obj1, 'ACQ:SRAT?')
samplerate = str2num(query(obj1, 'ACQ:SRAT?'));  % See P247 PG01-E02B and Step4 formula P592 PG01-E11A
interval = (1/samplerate); % See P247 PG01-E02B and Step4 formula P592 PG01-E11A
ggrid = 10; % Constant for SDS5x
index = [0:1:size(voltV)-1]; % See Step4 formula P592 PG01-E11A
timeS = -delay - (timebase*ggrid/2) + index*interval; % See Step4 formula P592 PG01-E11A

% Plot Waveform
plot(timeS, voltV)

%% Disconnect and Clean Up
% The following properly disposes open instrument objects when SDS5054X_try_00.m executed
% as part of a function or script.

% Disconnect all objects.
fclose(obj1);
% Clean up all objects.
delete(obj1);
clear obj1;


[attachimg=1]