%% Agilent33250A.m
% Program to generate a waveform on the Agilent 33250A, and display it on the Agilent DSO81304B scope
% The user programming requirements for waveform generation are greatly simplified
%% Create a GPIB object for each device.
MaxOutputBufferSize = 2^17;
arb1 = instrfind('Type', 'gpib', 'BoardIndex', 0, 'PrimaryAddress', 9, 'Tag', '');
dso1 = instrfind('Type', 'gpib', 'BoardIndex', 0, 'PrimaryAddress', 7, 'Tag', '');
% Create the GPIB object if it does not exist; otherwise use the object that was found.
if isempty(arb1)
arb1 = gpib('ni', 0, 9);
else
fclose(arb1);
arb1 = arb1(1);
end;
if isempty(dso1)
dso1 = gpib('ni', 0, 7);
else
fclose(dso1);
dso1 = dso1(1);
end;
% Open the instrument objects
fclose(arb1);
arb1.OutputBufferSize = MaxOutputBufferSize;
fopen(arb1);
fopen(dso1);
set([arb1, dso1],'Timeout', 10);
arb1.UserData = 'arb1';
dso1.UserData = 'dso1';
%% Items used to build an arb waveform
% NumLevels scalar how many points in the waveform, as if entered from the front panel
% VoltLevels vector of length NumLevels voltage levels, as if entered from the front panel
% TimeWidths vector of length NumLevels duration for each level (in seconds)
% NormLevels vector of length NumLevels normalized levels of the voltages, scaled to the internal 1.0 to -1.0 range of the arb
% num vector of length NumLevels when times are converted to fractions, the numerators
% den vector of length NumLevels when times are converted to fractions, the denominators
% LCM scalar the least common multiple of all the denominators
% nnum vector of length NumLevels the numerators normalized to LCM as the denominator;
% the number of points for each level that must be remotely programmed
% rat native MATLAB function converts a floating point number into a fraction (i.e. 5.2 = 26/5, 1.66 = 5/3, 1 = 1/1, 3.375 = 27/8)
% vectors of the numerators and of the denominators are returned
% lcm native MATLAB function returns the least common multiple of two integers
%% Enter voltage and time parameters for waveform as if from the front panel
% Enter the voltage at each level
VoltLevels = [0 53 75 0 -75 -53 0]*1E-3;
% TimeWidths is the array that contains the duration for each level
% All elements MUST be greater than zero
% TimeExp is exponent to multipy each time by to get actual time in seconds
TimeExp = 1E-6;
TimeWidths = [1 1 2 2 0.5 2.5 1]*TimeExp;
% IMPORTANT: VoltLevels and TimeWidths MUST have the same number of elements
%% Step 1: From user input above, do calculations and check for errors
Vmax = max(VoltLevels);
Vmin = min(VoltLevels);
Voff = (Vmax + Vmin)/2.0;
m = (1.0 - -1.0)/(Vmax - Vmin);
b = -Voff*m;
NormLevels = VoltLevels*m + b;
period = sum(TimeWidths);
freq = 1/period;
NumLevels = length(VoltLevels);
if length(VoltLevels) ~= length(TimeWidths)
error('VoltLevels and TimeWidths must contain the same number of elements.');
end;
if min(TimeWidths) <= 0
error('Some time widths are zero or negative- not allowed.');
end;
if max(abs(VoltLevels)) > 10
error('Voltage levels must be between -10 and 10 volts');
end;
%% Step 2: Get number of points for each level in waveform
% Represent each time as a fraction (i.e. 5.2 = 26/5, 1.66 = 5/3, 1.5 = 3/2, 1 = 1/1, 3.375 = 27/8)
% Create a vector of the numerators and of the denominators
% Find the least common multiple (LCM) of the denominators
% Re-write equivalent fractions with the LCM as denominator
% Numerators of the new fractions are the # points for each level
[num den] = rat(TimeWidths/TimeExp, 0.01); % remove the time exponent temporarily; get fractions accurate to 1%
LCM = den(1);
for ii = 2:NumLevels
LCM = lcm(LCM, den(ii));
end;
nnum = num.*(LCM./den);
TotalPoints = sum(nnum);
%% Step 3: Build a string containing all the numbers for the DATA VOLATILE command
DataString = '';
for level = 1:NumLevels
NormLevelStr = sprintf('%6.4f', NormLevels(level));
for point = 1:nnum(level)
DataString = [DataString ', ' NormLevelStr];
end;
end;
if 2*length(DataString) >= MaxOutputBufferSize
error('Data string (%d bytes) is too big for OutputBufferSize (%d bytes)', 2*length(DataString), MaxOutputBufferSize);
end;
%% Send SCPI commands to the 33250A to output the waveform
GPIBSend(arb1, 'OUTPUT OFF');
GPIBSend(arb1, '*CLS');
GPIBSend(arb1, '*RST');
GPIBSend(arb1, '*OPC');
GPIBSend(arb1, '*ESE 61');
GPIBSend(arb1, ['VOLT:HIGH ' num2str(Vmax, '%8.5G')]);
GPIBSend(arb1, ['VOLT:LOW ' num2str(Vmin, '%8.5G')]);
GPIBSend(arb1, ['VOLT:OFFS ' num2str(Voff, '%8.5G')]);
GPIBSend(arb1, ['FREQ ' num2str(freq, '%8.5G')]);
arb1.timeout = TotalPoints/200.0;
GPIBSend(arb1, ['DATA VOLATILE' DataString]);
arb1.timeout = 10;
GPIBSend(arb1, 'DATA:COPY RAMP3');
GPIBSend(arb1, 'BURST:MODE TRIG');
GPIBSend(arb1, 'BURST:NCYC 1');
GPIBSend(arb1, 'TRIG:SOUR BUS');
GPIBSend(arb1, 'TRIG:SLOP POS');
GPIBSend(arb1, 'BURST:STAT ON');
GPIBSend(arb1, 'FUNC:USER RAMP3');
GPIBSend(arb1, 'FUNC USER');
GPIBSend(arb1, 'OUTPUT:TRIG ON');
GPIBSend(arb1, 'OUTPUT ON');
NumberOfPoints = int16(str2num(query(arb1, 'DATA:ATTR:POIN?')))
%% Send SCPI commands to the DSO81304B to set up the scope
GPIBSend(dso1, '*CLS');
GPIBSend(dso1, '*RST');
GPIBSend(dso1, '*OPC');
GPIBSend(arb1, '*ESE 61');
GPIBSend(dso1, ':CHAN1:DISP ON');
GPIBSend(dso1, ':CHAN2:DISP OFF');
GPIBSend(dso1, ':CHAN3:DISP OFF');
GPIBSend(dso1, ':CHAN4:DISP OFF');
GPIBSend(dso1, ':CHAN1:UNIT VOLT');
GPIBSend(dso1, ':CHAN1:OFFS 0');
GPIBSend(dso1, ':CHAN1:SCAL 20E-3');
GPIBSend(dso1, ':TIM:SCAL 1E-6');
GPIBSend(dso1, ':TIM:POS 5.066E-6');
GPIBSend(dso1, ':TIM:REF CENTER');
GPIBSend(dso1, ':ACQ:SRAT 1E9');
GPIBSend(dso1, ':ACQ:POIN AUTO');
GPIBSend(dso1, ':TRIG:MODE EDGE');
GPIBSend(dso1, ':TRIG:LEV CHAN4, 1.0');
GPIBSend(dso1, ':TRIG:EDGE:SLOP POS');
GPIBSend(dso1, ':TRIG:EDGE:SOUR CHAN4');
GPIBSend(dso1, ':TRIG:SWE TRIG');
%% Trigger arb; capture waveform, save waveform to disk, and check measurements on scope
GPIBSend(arb1, '*TRG');
GPIBSend(arb1, '*WAI');
GPIBSend(dso1, ':DISK:SAVE:WAVEFORM CHANNEL1,"C:\SCOPE\DATA\ANYFILENAME",BIN,OFF');
Vamp = query(dso1, ':MEAS:VAMP? CHAN1')
area = query(dso1, ':MEAS:AREA? DISP, CHAN1')
rate = query(dso1, ':MEAS:DAT? CHAN1')
pwid = query(dso1, ':MEAS:PWID? CHAN1')
nwid = query(dso1, ':MEAS:NWID? CHAN1')
rise = query(dso1, ':MEAS:RIS? CHAN1')
slew = query(dso1, ':MEAS:SLEW? CHAN1')
vbas = query(dso1, ':MEAS:VBAS? CHAN1')
vtop = query(dso1, ':MEAS:VTOP? CHAN1')
vt00 = query(dso1, ':MEAS:VTIM? 0.0E-6, CHAN1')
vt01 = query(dso1, ':MEAS:VTIM? 0.1E-6, CHAN1')
vt02 = query(dso1, ':MEAS:VTIM? 0.2E-6, CHAN1')
vt03 = query(dso1, ':MEAS:VTIM? 0.3E-6, CHAN1')
vt04 = query(dso1, ':MEAS:VTIM? 0.4E-6, CHAN1')
vt05 = query(dso1, ':MEAS:VTIM? 0.5E-6, CHAN1')
%% Close and delete instrument objects.
fclose(arb1);
fclose(dso1);
delete(arb1);
delete(dso1);
%% Make sure to copy and paste this code into a new m file called GPIBSend.m
function GPIBSend(GPIBObj, command)
%
% Send a GPIB command, then
% * list all error messages generated by instrument, if any
% * check bit for operation complete
% * if timeout or errors, stop execution
%
fprintf(GPIBObj, '*OPC');
fprintf(GPIBObj, command);
% Check arb stuff
if strcmp(GPIBObj.UserData, 'arb1')
ESR = uint16(str2num(query(GPIBObj, '*ESR?')));
% Bit values to check
BitValues = [4 8 16 32];
BitNames = {'Query Error', 'Device Error', 'Execution Error', 'Command Error'};
% Was there an error?
if bitand(ESR, sum(BitValues))
% Error: yes
DispNum = min(length(command), 40);
Message = ['In GPIBSend, command ''' command(1:DispNum) ''' to ' GPIBObj.UserData ' had an error.']
ESR
for ii = 1:length(BitValues)
if bitand(BitValues(ii), ESR)
ErrorType = char(BitNames(ii))
end;
end;
ErrorString = query(GPIBObj, 'SYST:ERROR?');
while isempty(findstr(ErrorString, 'No error'))
ErrorString
ErrorString = query(GPIBObj, 'SYST:ERROR?');
end;
OCNames = {'No', 'Yes'};
OperationComplete = char(OCNames(bitand(1, ESR) + 1))
error(' ');
else
% Error: no
scratch = query(GPIBObj, '*OPC?');
end;
end;
% Check dso stuff
if strcmp(GPIBObj.UserData, 'dso1')
ESR = uint16(str2num(query(GPIBObj, '*ESR?')));
% Bit values to check
BitValues = [4 8 16 32];
BitNames = {'Query Error', 'Device Error', 'Execution Error', 'Command Error'};
% Was there an error?
if bitand(ESR, sum(BitValues))
% Error: yes
DispNum = min(length(command), 40);
Message = ['In GPIBSend, command ''' command(1:DispNum) ''' to ' GPIBObj.UserData ' had an error.']
ESR
for ii = 1:length(BitValues)
if bitand(BitValues(ii), ESR)
ErrorType = char(BitNames(ii))
end;
end;
ErrorString = query(GPIBObj, 'SYST:ERROR?');
while isempty(findstr(ErrorString, 'No error'))
ErrorString
ErrorString = query(GPIBObj, 'SYST:ERROR?');
end;
OCNames = {'No', 'Yes'};
OperationComplete = char(OCNames(bitand(1, ESR) + 1))
error(' ');
else
% Error: no
scratch = query(GPIBObj, '*OPC?');
end;
end;