No BSD License  

image thumbnail

Simplified Waveform Programming for the Agilent 33250A

by

 

17 Sep 2008 (Updated )

Simplifies arbitrary waveform generation on the 33250A through GPIB control

GPIBSend(GPIBObj, command)
%% 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;

Contact us