kpib
KPIB is a framework for operating laboratory instruments that are connected to a computer by GPIB or serial port connections. KPIB provides a unified interface for communicating with different instruments of the same type from different manufacturers. KPIB requires the MATLAB Instrument Control toolbox for GPIB connections.
RETVAL = KPIB(INSTRUMENT, GPIB, COMMAND, VALUE, CHANNEL, AUX, VERBOSE)
Open the m-file or use "showdemo kpib" for more help.
Contents
- Introduction
- Version Info
- Description
- Input Parameters
- Supported Instruments
- Examples
- GPIB Interface Hardware
- Serial Port Interface
- Code organization
- Template for new instruments:
- Notes for adding new instruments:
- Changlelog
- BEGIN CODE
- Define Constants
- Parse Input
- Begin interpreting commands
- 'version' return kpib version number
- GPIB bus level commands
- 'identify'
- 'clear'
- 'close'
- 'open'
- 'write'
- 'query'
- 'scan'
- Individual Instrument Drivers
- 'None' (no instrument)
- 'Blueoven' Thermotron S1 with 2800-series controller
- 'GreyOven' Testequity 1007S
- 'WAT_981' Temperature controller
- 'HP_3478A' HP multimeter
- 'HP_34401A' HP multimeter
- HP Power Supplies ('HP_POWER')
- 'HP_89410A' HP Vector Signal Analyzer
- 'TEK_TDS' Tektronix oscilloscope
- 'HP_53132A' HP universal counter
- 'HP_33120A' Agilent Function Generator
- 'AG_33250A' Agilent Function Generator
- 'SRS_DS345' Stanford Research Systems function generator
- 'HP_4395A' HP Network and Spectrum Analyzer
- 'HP_34420A' HP nanovoltmeter
- 'KTH_236' Keithley 236/237/238 Source Measure Unit
- 'HP_8753ES' HP S-Parameter Network Analyzer
- 'AO_800' AlphaOmega Instruments 800-series Temperature controller
- 'HP_8560A' HP Spectrum Analyzer 50 Hz - 2.9 GHz
- 'HP_4284A' HP LCR Meter
- 'HP_3499B' Multiplexer
- 'NP_3150' Newport Temperature Controller Model 3150
- 'VH_2701C' Valhalla 2701C voltage calibrator
- 'VH_2701B' Valhalla 2701B voltage calibrator
- 'HP_4195A' HP Network/Spectrum Analyzer
- 'HP_3562A' HP Dynamic Signal Analyzer
- 'KTH_2400' Keithley 2400 Sourcemeter
- 'HP_54600' Hewlett-Packard digital oscilloscope
- 'HP_54800' Hewlett-Packard digital Infiniium oscilloscope
- 'OH_EXP' Ohaus Explorer and Explorer Pro precision balances
- 'CV_TIC304' CryoVac TIC 304-MA Temperature Controller
- 'AG_E5071B' Agilent E5070B/E5071B RF Network Analyzer
- 'SI_9700' Scientific Instruments model 9700 Temperature Controller
- 'FLK_290' Fluke 290 Series Waveform generator
- End of instrument drivers
- function port
- port: serial port instrument
- port: GPIB instrument
- port: GPIB PCI
- port: Special GPIB settings
- port: GPIB serial
- function truncx
- function makeBytes
- function makeDecimal
- function makeCRC
- function watwrite
- function BitToFloat
Introduction
function retval = kpib(instrument, GPIB, command, value, channel, aux, verbose)
%KPIB Kenny-Purpose Interface Bus % RETVAL = KPIB(INSTRUMENT, GPIB, COMMAND, VALUE, CHANNEL, AUX, VERBOSE) % % v4.97 MH May2013 % See list of supported instruments below % % Current Maintainer: % M.A. Hopcroft % mhopeng@gmail.com %
Version Info
versionnum=4.97;
versionstr='kpib.m version 4.97 (May2013)';
Description
KPIB is a framework for operating laboratory instruments that are controlled by GPIB or serial port connections to a computer. KPIB provides a unified interface for communicating with different instruments of the same type from different manufacturers. KPIB was inspired by HPIB, written by Aaron Partridge. KPIB requires the MATLAB Instrument Control toolbox. KPIB is licensed for use under the BSD license supported by the Mathworks File Exchange.
Contributions of new instrument drivers to KPIB are welcome! Many people have contributed individual commands and/or complete instruments. Please see the section below labelled "Code Organization" for information about adding new instruments. Please feel free to contact the Maintainer at the address above with questions, comments, or contributions.
Input Parameters
RETVAL = KPIB(INSTRUMENT, GPIB, COMMAND, VALUE, CHANNEL, AUX, VERBOSE)
- INSTRUMENT (str) Instrument name or bus-level command
- GPIB (num) The GPIB address of the instrument or name of serial port ('COMx' | '/dev/ttyX')
- COMMAND (str) Command to instrument
- VALUE (num or str) Value for command (if applicable)
- CHANNEL (num or str) Channel for command (if applicable)
- AUX (num or str) Additional input parameter (if applicable)
- VERBOSE (0,1,2,3) Controls the amount of status messages printed to the command window:
0 = silent 1 = important messages only 2 = all instrument messages (default) 3 = all instrument messages + debugging messages
Supported Instruments
INSTRUMENT may be one of the following:
'all' All instruments; for init or stop commands. 'none' No instrument; for dummy commands
Temperature Controllers
'BlueOven' 2800 Controller for Thermotron S-1.2 Thermal Chamber (aka "Blue Oven") 'GreyOven' ICS 4809 Modbus interface to Watlow F4 Controller for TestEquity 1007S Thermal Chamber (aka "Grey Oven"). Also'WAT_F4' 'WAT_981' Watlow 981 Temperature controller. 'AO_800' Alpha Omega Instruments Series 800/850 Temperature Controller using Watlow Series 96 controller (Modbus serial comm.) Also 'WAT_96' (RS-232 device, specify port name for GPIB address) 'CV_TIC304' CryoVac TIC 304-MA Temperature Controller 'SI_9700' Scientific Instruments model 9700 Temperature Controller 'NP_3150' Newport Temperature Controller Model 3150
Signal Analyzers
'HP_89410A' HP 89410A Vector Signal Analyzer 'HP_4195A' HP Network/Spectrum Analyzer 'HP_4395A' HP 4395A Network/Spectrum Analyzer 'HP_8753ES' HP 8753ES S-Parameter Network Analyzer 'AG_E5071B' Agilent E5070B/E5071B RF Network Analyzer 'HP_8560A' HP 8560A Spectrum Analyzer 'HP_3562A' HP 3562A Dynamic Signal Analyzer (partial support only)
Oscilloscopes
'TEK_TDS' Tektronix TDS family Oscilloscopes 'HP_54600' Hewlett-Packard 54600-series Oscilloscopes (HP_54602B) 'HP_54800' Hewlett-Packard 548XX Infiniium Oscilloscopes (HP_54845A)
Multimeters
'HP_3478A' Hewlett-Packard 3478A multimeter 'HP_34401A' HP 34401A multimeter 'HP_34420A' HP 34420A 7.5 Digit Nanovoltmeter with RTD measurement
Waveform/Function Generators
'HP_33120A' HP 33120A 15 MHz function generator 'AG_33250A' Agilent 33250A 80 MHz Function generator 'SRS_DS345' Stanford Research Systems DS345 30 MHz function generator 'FLK_290' Fluke 290 series (291, 292, 294) arbitrary waveform generators
Power Supplies
'HP_E3631A' HP E3631A triple output DC power supply 'HP_6614C' HP 6614C single-output 100V/0.5A DC power supply 'HP_E3632A' HP E3632A DC power supply 15/30 V 'HP_E3634A' HP E3634A DC power supply 25/50 V 'HP_E3641A' HP E3641A DC power supply 'HP_E3647A' HP E3647A dual output DC power supply (incl. TDS 340, TDS 540, TDS 744A) 'HP_53132A' HP 53132A 225 MHz Universal Counter 'HP_33120A' HP 33120A 15 MHz function generator 'SRS_DS345' Stanford Research Systems DS345 30 MHz function generator 'HP_E3633A' HP E3633A DC power supply 8/20 V
Other Instruments
'KTH_236' Keithley 236/237/238 Source Measure Unit 'KTH_2400' Keithley 2400 Source-Measure Unit (minimum functionality) 'HP_4284A' HP 4284A LCR Meter 'HP_3499B' Agilent 3499B Multiplexer 'VH_2701C' Valhalla 2701C voltage calibrator 'VH_2701B' Valhalla 2701B voltage calibrator (limited functionality) 'OH_EXP' Ohaus Explorer precision balances (incl. Pro models)
Bus-level commands (typically used for debugging)
'scan' Look for GPIB and serial interfaces and instruments 'identify' Ask an instrument for identifying information 'close' Close a GPIB or serial connection. 'clear' Close all GPIB or serial connections. 'open' Open a GPIB or serial connection. 'write' Send the string VALUE to the instrument at GPIB. 'writeread' Send a string to an instrument and wait for a reply.
Documentation for each instrument is in the code. Use the "Find" command or use the Cell menu in the MATLAB Editor (the "%%" menu) to jump to the code for a specific instrument. If you use the "File/Publish to HTML" menu item, you will get a web page with a link to each instrument.
Typical COMMAND values include:
'init' initialize instrument 'read' read a measurement 'setV' set the output voltage 'on' enable output 'off' disable output 'getdata' download a data trace from scope or analyzer
-------
Examples
Usage: RETVAL = KPIB(INSTRUMENT, GPIB, COMMAND, VALUE, CHANNEL, AUX, VERBOSE)
To read the output (voltage and current) from the HP E3631A Triple Output Power supply with GPIB address 15 and store the reading in the variable called "output", use:
>> output = kpib('HP_E3631A',15,'read');
This command will default to channel 1. The result will be a structure:
output.volt = 5.04 output.curr = 0.24
You might only be interested in the voltage reading. Use:
>> output = kpib('HP_E3631A',15,'read','V');
The result will be a single value:
output = 5.04
(There is usually a small time savings when reading only one value)
To download the 500 data point trace from channel 2 of the Tektronix TDS 540 4-channel oscilloscope with GPIB address 8, see all status messages in the command window, and to store the result in the variable called "data", use:
>> data = kpib('TEK_TDS',8,'getdata',0,2,0,2);
The result will be a structure:
data = x: [500x1 double] y: [500x1 double] units: [1x1 struct] desc: [1x73 char]
It is recommended to organize your code with constants to describe the instruments, so that they can be modified easily. For example:
>> pwrsupply.instr = 'HP_E3647A';
>> pwrsupply.gpib = 15;
>> pwrsupply.channel = 2;
>> powervolt = 3.5;
>> verbose = 1;
>> kpib(pwrsupply.instr,pwrsupply.gpib,'set',powervolt,pwrsupply.channel,0,verbose);
You can also specify instruments as a single structure input. For the example above, you could use:
>> kpib(pwrsupply,'setV',powervolt,0,verbose);
Open the file kpib.m to find details for specific instruments and documentation for adding instruments and modifying the code. Use the Cell menu in the MATLAB Editor (looks like a "%%") to jump to the section for each instrument.
GPIB Interface Hardware
KPIB as provided on File Exchange is configured for a computer using a single National Instruments GPIB interface card ('ni'). For other brands of interface cards and/or multiple cards, you will need to modify the private function PORT, located near the end of this file (approx. 400 lines before the end of the file). To go to this line, search for the string 'GPIBMAN'. See the list of manufacturers supported by MATLAB here: http://www.mathworks.com/products/instrument/supportedio.html KPIB has been tested with GPIB interface hardware from National Instruments and ICS Electronics (both PCI and USB). Note that USB-based GPIB interfaces that use a "GPIB-32.DLL" or similar method act like PCI interfaces as far as MATLAB is concerned (i.e., they use the GPIB command to create the instrument object). Use the KPIB command 'scan' to display a list of available interfaces and instruments. The interface name given by 'scan' is the name which must be entered in KPIB. For example:
>> kpib('scan') kpib.m version 4.84 (Apr2010) kpib/scan: GPIB interface 'ni': >>
Code is also included for USB-GPIB interfaces that use a "virtual serial port", such as the Prologix GPIB-USB Controller 4.2. These interfaces use the SERIAL command to create the instrument object. To use a virtual COM port interface, modify the PORT function by commenting in/out the section relevant to your setup. Also set the the IsUSBPro flag in the "Define Constants" cell (near line 600). Note that this is different than a USB-GPIB interface that uses a .dll-based interface, which is treated like standard GPIB interface hardware.
Serial Port Interface
KPIB includes support for some instruments which use a RS-232 serial port interface. This includes the use of USB-to-serial adaptors if the driver supports a serial port interface. For these instruments, supply the serial port name instead of the GPIB address as an input parameter. On Windows, the serial port is a "COM port"; on Linux or OS X the serial port is a device name (e.g., /dev/ttyUSB1). For example:
>> temp = kpib('AO_800','COM5','read','T');
NOTE: The use of GPIB hardware requires a license for the MATLAB Instrument Control toolbox. The use of serial port connections, including instruments with serial port interfaces and the Prologix GPIB-USB controller, do not require the Instrument Control toolbox.
Code organization
The code is grouped by instrument in IF statement blocks which which evaluate the first input parameter (INSTRUMENT) and then execute the COMMAND parameter if the string is matched. Each instrument group begins with the PORT function, which uses the GPIB or SERIAL commands to open a connection to the instrument, if one does not already exist. The PORT function and other specialized subroutines are at the end of the file. Additional instruments can easily be added by following the format below.
Template for new instruments:
To add a new instrument, use the following template, replacing INSTRUMENT with the name of the instrument (e.e, 'KTH_236'). For certain types of instruments (power supplies, temperature controllers, network analyzers, etc), there are certain commands that should be included. See below.
% % %%%%% begin <NEW INSTRUMENT> % %% '<INSTRUMENT>' Description for Cell title % % Description of instrument and kpib funtionality % % %RETVAL = KPIB('INSTRUMENT', GPIB, 'COMMAND', VALUE, CHANNEL, AUX, VERBOSE) % % Valid commands: % % 'init' Initializes instrument and makes ready for measurement % % 'read' Returns some data or parameter from the instrument % % 'setV' Sets the output voltage % % % if strcmpi(instrument, '<INSTRUMENT>') || strcmpi(instrument, 'all') % baudrate = 0; % buffer size for GPIB (0 for default) or baud rate for serial port instruments % io = port(GPIB, instrument, baudrate, verbose); % if (io ~=0) && (strcmp(get(io,'Status'),'open') ~=0) % % switch command % case 'init' % % %<INSTRUMENT CODE HERE>% % % if verbose >= 1, fprintf(1, 'kpib/%s: Warning: <some warning message>.\n',instrument); end % % if verbose >= 2, fprintf(1, 'kpib/%s: Result of command is <whatever>.\n',instrument); end % % case {'read','getdata'} % %<INSTRUMENT CODE HERE>% % % otherwise % if verbose >= 1, fprintf(1,'kpib/%s: Error, command not supported. ["%s"]\n',instrument,command); end % end % % else % catch incorrect address errors % if verbose >= 1, fprintf(1,'kpib/%s: ERROR: No instrument at GPIB %s\n',instrument,num2str(GPIB)); end % retval=0; % end % validInst = 1; % % end <INSTRUMENT> % % %%%%% end <NEW INSTRUMENT>
Notes for adding new instruments:
Default inputs: all 5 additional input parameters are given default values if the user does not provide them. They are:
command = 'none' value = 0 channel = 0 aux = 0 verbose = 2
Avoid using "nargin" to test for valid inputs; instead, for example:
if isnumeric(channel) && any(channel==[1 2 3 4])
Choosing command names: When adding a new instrument, pick a similar instrument and copy the command syntax. For example, to download a data trace from an analyzer or oscilloscope, name the command 'getdata'. To read a single value from a power supply or multi meter, use 'read'. Maintaining this consistency is a significant part of the value of using kpib. The standard command names are:
'init' Initialize the instrument 'off' Stop instrument action; set output to zero; release controller, etc. also 'stop' 'on' Start instrument action; begin automatic controlling, etc. also 'go' 'getdata' Return the data from the instrument. For instrument with data traces (and screens), "download data from the screen". For other instruments, return the "most important data", e.g., for a counter, return the frequency; for a temperature controller, return the measured temperature. 'read' Return some specific data or parameter specified by VALUE. Default to the same data returned by 'getdata'. 'set' Set the output, controller setpoint, or some other parameter 'setT' specified by VALUE. 'set' is deprecated; better to use 'setV' 'setV' to set a voltage, or 'setT' to specify a temperature, or 'setI' for a current, etc.
Hewlett-Packard/Agilent Power Supplies: Many HP power supplies share a common GPIB command set and kpib syntax ('read','setV','setI', etc). These are grouped together and listed in the constant HP_power, defined at the beginning of the code. If you add a new HP power supply, be sure to add it to the list.
Adding new Network Analyzers: KPIB was originally designed to enable measurement of resonators using network analyzers. In order to maintain compatibility with existing code for resonator measurement (measure_res.m and res_meas.m), the following commands must be included:
Initialize ['init'] Just clear the status registers ("CLS") or similar. Not a full reboot.
Channel Select ['channel'] Set the "active channel" of the instrument >> kpib(tools.analyzer.instr,tools.analyzer.gpib,'channel',ampchannel,0,0,verbose);
Sweep Center Frequency (set/query) ['center'] >> centfreq = kpib(tools.analyzer.instr,tools.analyzer.gpib,'center','query',0,0,verbose);
Sweep Span (set/query) ['span'] >> kpib(tools.analyzer.instr,tools.analyzer.gpib,'span',spanit,0,0,verbose);
Averaging (on/off/number of sweeps) ['averaging','on'] >> kpib(tools.analyzer.instr,tools.analyzer.gpib,'average','on',avenum,0,verbose);
Autoscale the display ['scale','auto'] >> kpib(tools.analyzer.instr,tools.analyzer.gpib,'scale','auto',0,0,verbose);
Marker (on/query) ['marker','query'] >> mark1 = kpib(tools.analyzer.instr,tools.analyzer.gpib,'marker','query',ampchannel,0,verbose);
Marker to peak/max or peak tracking ['mark2peak','peak'] >> kpib(tools.analyzer.instr,tools.analyzer.gpib,'mark2peak','peak',0,0,verbose);
Download a complete data trace ['getdata'] This command should also return the units of the data >> trace1 = kpib(tools.analyzer.instr,tools.analyzer.gpib,'getdata',0,ampchannel,0,verbose);
Sweep Control (initiate a single sweep and wait until it is finished) This is implemented as two commands- one to start the sweep, and one to poll to determine when the sweep has completed. ['sweep','single] and ['complete'] >> kpib(tools.analyzer.instr,tools.analyzer.gpib,'sweep','single',0,0,verbose); >> kpib(tools.analyzer.instr,tools.analyzer.gpib,'complete',0,0,0,verbose);
Wait ['wait'] The 'wait' command instructs the analyzer to complete the current command before executing any further commands. This is the "*WAI" GPIB command, which is only supported by newer instruments, and doesn't usually have much effect, anyway.
For res_meas, the following additional commands are required:
Label ['label'] Prints a short message on the analyzer screen. >> kpib(tools.analyzer,'label','Measuring...',0,0,verbose);
Display Status ['display','dual','?'] Indicates the number of traces currently displayed on the screen. This is used to help res_meas guess the type of data that is being displayed. >> dstate=kpib(tools.analyzer,'display','dual','?',0,verbose);
Many analyzers may not support all of these features. In this case, simply include a dummy command that returns a hard-coded value (e.g., units.x = 'Hz', or retval = 1). See the code for the HP_4195A for a good example of an older analyzer that does not support all of the features listed here. The counter example is the HP_4395A, which supports all of these commands.
Changlelog
(This is the comprehensive changelog)
%MH May2013 % v4.97 remove Acutronic ('ACT_3000') functionality, % per request of ACUTRONIC USA Inc. %MH Nov2012 % v4.96 fixed issues flagged by m-lint % NOTE: fixes to HP_4284A and VH_2701B made but not tested % MH Jan2011 % v4.95 update Acutronic code to latest Acutrol version (67.x) % limit checking for Acutronic inputs (by WS) % MH Dec2010 % v4.94 Acutronic servo status reporting % v4.92 add instrument 'AcuOven' % add instrument 'ACT_3000' % 'writeread' becomes 'query' % update 'close' command % update KTH_236 code for better performance/reliability % MH Jun2010 % v4.9 begin support for HP_3562A % MH May2010 % v4.87 bugfixes for TEK_TDS (data download, label display) % improvements to AG_33250A (CHANNEL warning) % v4.86 add instrument HP_54800 Infiniium Oscilloscope % implemented buffer size specification per instrument % contributions for AG_E5071 from Mehmet Akgul % Small changes to KTH_236 for reliability % v4.84 add instrument AG_33250A Function Generator % add 'noise' to HP_33120A and bugfix % MH Apr2010 % v4.8 add instrument Fluke 294 % add command 'scan' % re-order version number % update GPIB PCI section % MH Feb2010 % v4.72 typo fixes % Temperature read update for GreyOven, AO_800 % MH JAN2010 % v4.70 clean up 4.68a changes, comments % AG_E5071B data download now works with all Channels % MH DEC2009 % v4.68a bugfixes in Cory 484 (mostly HP_4395A) % v4.68 update comments, clean up AO_800 % MH NOV2009 % v4.66 Complete support for AG_E5071 (with help from Damien Wittwer) % MH OCT2009 % v4.64 add 'SI_9700' Scientific Instruments model 9700 Temperature Controller % MH FEB2009 % v4.62 add 'CV_TIC304' CryoVac Temperature Controller % add 'AG_E5071' Network Analyzer (incomplete) % MH SEP2008 % v4.60 format code and comments to use "Cells" (%%) % add new instrument: OH_EXP % MH MAY2008 % v4.59 fix typos in HP_3478A % fix typos in comments % v4.58 add preliminary support for HP_54602B Oscilloscope % fix HP_3478A "temperature" code % clean up "&&" and "||" warnings % MH APR2006 % v4.56 fix KTH_2400 'measure' commands % MH MAR2008 % 4.55 fix 'attenuate' command in HP_4195A % add 'measure' to KTH_2400 % MH FEB2008 % 4.54 bugfixes for Prologix support % 4.53 support for KTH_2400 added (contributed by David Myers) % bugfixes for Prologix USB support, incl. IsUSBPro flag % MH JAN2008 % 4.52 validate port re-write for GPIB/Serial GPIB % minor updates to VH instruments % minor bugfix in TEK_TDS % v4.51 fix USB code in port % more help comments % v4.5 preliminary support for HP_4195A analyzer, % Prologix USB-GPIB interface % fix HP_4395A 'marker to center' command % HKL AUG2007 % v4.48 fix bugs in HP_8753ES averaging on/off routine % fix bugs in HP_8753ES sweep compete check routine % v4.45 fix bugs in HP_8753ES input channel select routine % MH JUN2007 % v4.44 fix bugs in TEK_TDS oscilloscope data handling % HKL JUN2007 % v4.42 add new instruments: NP_3150, VH2701_B, VH2701_C % MH MAY2007 % v4.40 add 'mode' command to 4395A % v4.39 add source frequency set for HP89410 % v4.38 bugfixes for 89410 label, channel % MH MAR2007 % v4.36 change TDS_540 to TEK_TDS (all TDS family programming is same) % add channel select, display query to TEK_TDS % HP_4395A, HP_89410A handle log frequency data correctly % v4.34 error handling for HP_8560A data download % v4.33 error handling for HP_4395A data download % MH FEB2007 % v4.32 misc. Analyzer functionality to support res_meas % v4.31 specify download format for 4395A ('FORM4') % MH JAN2007 % v4.3 HP_53132A Counter code reflects current best practice % Fewer warning messages for HP_89410A % v4.22 SRS DS345 'read' defaults to output voltage amplitude % additional documentation % v4.20 add 'getdata' (same as 'read') to HP_3478A % add V, I specification to KTH_236 'read' command % MH DEC2006 % v4.18 remove duplicate HP_33120A entry, add 'setV' % v4.16 add 'setV' to func. gen., KTH_236 % v4.14 add marker functionality to HP_8560A % v4.12 add wait for complete to HP_89410 autozero % MH NOV2006 % v4.1 add 'config' and 'getdata' to HP_34401A and HP_34420A % v4.04 HP4395A verbosity % v4.02 Two major changes to input syntax: % 1) Structure inputs for tools fully supported % 2) "out-of-place" arguments are no longer supported. % (CHANNEL must always be the channel, etc.) % add HP_89410A average 'finish' % HP_89410A timeout increased to 30 sec % Port shows Timeout, Buffersize % verbose_default % RM 23OCT2006 % v3.971 fixed data structure error in HP_3495A 'units' code % RM 19OCT2006 % v3.97 included new instrument: HP_3499B Multiplexer % MH OCT2006 % v3.982 remove "nargin" (beta) % fix HP_E3631A channel select (use 1,2,3) % fix 8753ES channel select % Add New Instrument: HP_3499B Multiplexer % (contributed by Renata Melamud) % v3.97 fix HP4395A units % v3.96 made all HP power supply code common % v3.94 Fixed 8753ES data download, units % v3.93 Yet more improvements to HP53132A- % 'set' & 'frequency' now work properly % v3.92 Further improvements to HP53132A % Default values for all 7 input parameters % "limited parameter" input cases should be eliminated % Added synchronization (*OPC) to HP89410A % v3.9 Improvements to HP53132A % fixed buffersize bug in PORT related to 'write' % beta implementation of structure inputs % MH SEP2006 % v3.88 bugfixes (m-lint check). % validInstr flag in correct place (incl version!) % use "any" instead of "find" % v3.84 updated port for arbitrary buffer size % v3.82 added 'getdata' to HP 53132A % v3.8 added HP_4284A LCR Meter, HP_3633A Power supply % (contributed by Robert Hennessey) % MH AUG2006 % v3.76 more AO_800 error checking % v3.75 added "high-res temp" to GreyOven % v3.74 changed AO_800 read % v3.72 fault tolerant AO_800 'read' % 'close' closes serial ports as well as GPIB % made all instruments tolerant of GPIB address errors % added openloop detect to AO_800 % v3.6 made port tolerant of GPIB address errors % made 'identify' more robust- can now check to see if an instrument % is present at GPIB without crashing % added HOLD commands to analyzers % MH AUG2006 % v3.52 added HP_E3634A (same as E3632A) % added HP_8560A (preliminary) % v3.45 fixed GreyOven set query % v3.43 fixed marker command for HP_4395A % v3.42 added units to 'getdata' command for analyzers (similar to scopes) % v3.4 added current setting to power supplies - use 'setV' or 'setI' % added current reading to HP3478A % added AO_800 TE controller (RS-232 device) % MH JUL2006 % v3.2 worked on trigger issue with KTH_236 % added start/stop to analyzers % MH JUL2006 % v3.02 incorporated HP_8753ES, made marker commands consistent for all % three analyzers % MH JUL2006 % v2.91 fixed 4395A issues with str/num, units % MH JUN2006 % v2.8 changed blueoven to return scalars % %% % % JTL JUL2004 % v0.9 Jeff Li wrote first version, based on hpib, from AP. Incorporated 89410A. % %% % %#ok<*NBRAK> %#ok<*BDSCA> %#ok<*CTCH> %#ok<*AGROW>
BEGIN CODE
% % verify that the Instrument Control Toolbox is installed if ~isdeployed && isempty(ver('instrument')) %error('kpib: ERROR (fatal): The Instrument Control Toolbox does not appear to be installed.\n\n') if verbose >= 1, fprintf('kpib: WARNING The Instrument Control Toolbox does not appear to be installed.\n\n'); end end
Define Constants
% The IsUSBPro variable indicates whether a Prologix USB controller is % being used. Some instruments (e.g. KTH_2400) require special treatment % from the Prologix. See the function 'port' for more details about the % Prologix and other interface hardware. IsUSBPro = 0; % set 1 or 0 % HP_power is the list of HP Power supplies which have a common syntax % use INSTRUMENT = 'HP_POWER' for generic code HP_power={'HP_POWER','HP_POWERM','HP_6614C','HP_E3631A','HP_E3632A','HP_E3633A','HP_E3634A','HP_E3641A','HP_E3647A'}; % which of these have multiple outputs? % NOTE: some multiple output supplies use numbered output (1,2) and some % use named outputs ("P6V"). Code assumes numbered; adjust in HP_power_M % section as necessary for new instruments. HP_power_M={'HP_POWERM','HP_E3631A','HP_E3647A'}; %
Parse Input
Parse Structure Inputs or Individual Inputs
%RETVAL = KPIB('INSTRUMENT', GPIB, COMMAND, VALUE, CHANNEL, AUX, VERBOSE) % may be interpreted as % RETVAL = KPIB(INSTRUMENT, COMMAND(GPIB), VALUE(COMMAND), AUX(VALUE), VERBOSE(CHANNEL)) % or % RETVAL = KPIB(INSTRUMENT, COMMAND(GPIB), VALUE(COMMAND), CHANNEL(VALUE), AUX(CHANNEL), VERBOSE(AUX)) % depending on whether the first argument is a structure (i.e., tools). If % so, interpret INSTRUMENT as a structure named TOOLS: % tools.instr % tools.gpib % tools.channel (optional) % % Regardless of the input format, all seven parameters are given default % values if they are not provided: % COMMAND = 'none' % VALUE = 0 % CHANNEL = 0 % AUX = 0 % VERBOSE = 2 % verbose_default = 2; % default verbose level (recommend 2) if isstruct(instrument) nf=length(fieldnames(instrument)); if isfield(instrument,'channel') if nargin > 4, verbose = channel; else verbose = verbose_default; end % verbose default channel = instrument.channel; if nargin > 3, aux = value; else aux = 0; end else if nargin > 5, verbose = aux; else verbose = verbose_default; end % verbose default if nargin > 4, aux = channel; else aux = 0; end if nargin > 3, channel = value; else channel = 0; end end if nargin > 2, value = command; else value = 0; end if nargin > 1, command = GPIB; end if isfield(instrument,'gpib') GPIB = instrument.gpib; else error('\nkpib: Input STRUCT error: GPIB address (instrument.gpib) not specified\n'); end if isfield(instrument,'instr') instrument = instrument.instr; else error('\nkpib: STRUCT error: instrument (.instr) not specified\n'); end if verbose >= 3 fprintf(1,'kpib: (STRUCT %d) %s/%s/%s/%s/%s/%s/%s\n',nf,... instrument,num2str(GPIB),num2str(command),num2str(value),num2str(channel),num2str(aux),num2str(verbose)); end else % verbose defaults to level 2 (all messsages) if nargin < 7, verbose = verbose_default; end % verbose default if nargin < 6, aux = 0; end if nargin < 5, channel = 0; end if nargin < 4, value = 0; end if nargin < 3, command = 'none'; end if verbose >= 3 fprintf(1,'kpib: (REGULAR) %s/%s/%s/%s/%s/%s/%s\n',instrument,num2str(GPIB),num2str(command),num2str(value),num2str(channel),num2str(aux),num2str(verbose)); end end % %% %% %% %% %% %% %% %% %% %% %% %% %% %
Begin interpreting commands
The main body of the code begins here. It consists of a series of if statements which check the value of INSTRUMENT and execute the appropriate code block.
% % Flags validInst = 0; % validInst will be set if a valid instrument has been called. %retval=0; % this prevents "output argument not assigned" errors
'version' return kpib version number
if strcmpi(instrument,'version') || strcmpi(instrument,'ver') retval=versionnum; if verbose > 0 fprintf(1,'%s\n',versionstr); end validInst = 1; end
GPIB bus level commands
Low-level commands that apply to any instrument- close, write, etc.
'identify'
Requests the "Identity String" from an instrument using the *IDN command Obviously this only works if the instrument supports *IDN ... Returns 0 if no instrument is present at GPIB (or *IDN? not supported)
if strcmpi(instrument,'identify') || strcmpi(instrument,'identity') || strcmpi(instrument,'*IDN') io = port(GPIB, instrument, 0, verbose); if (io ~=0) && (strcmp(get(io,'Status'),'open') ~=0) fprintf(io,'*IDN?'); retval=fscanf(io,'%s'); if verbose >= 2, fprintf('kpib/identify: %s\n',versionstr); end if verbose >= 1, fprintf('kpib/identify: Instrument at GPIB-%s identifies as:\n %s\n',num2str(GPIB),retval); end validInst = 1; else retval=0; if verbose >= 1, fprintf(1,'kpib/identify: No instrument at GPIB-%s\n',num2str(GPIB)); end kpib('close',GPIB,0,0,0,0,verbose); validInst = 1; end end
'clear'
This function is used in order to clear all of the instrument handles and to close all the connections without having to go and find each individual instrument and close it. Essentially a "close all" command.
if strcmpi(instrument,'clear') if verbose >= 2, fprintf('kpib: Closing and clearing all instrument connections.\n'); end io = instrfind; if verbose >= 2, disp(io); end if ~(isempty(io)) fclose(io); delete(io); clear io; end if verbose >= 2, fprintf('kpib: All instruments (ports) closed.\n'); end validInst = 1; if nargout == 1, retval = 1; end end
'close'
This function is used in order to close individual instruments with a known GPIB address. For many instruments, this returns the instrument to local (front panel) control. Can specify GPIB addresses as an array and all addresses will be closed. Can specify serial ports ('COM1', 'COM2'), but don't mix serial and GPIB.
if strcmpi(instrument,'close') if isnumeric(GPIB) for g=GPIB if verbose >= 2, fprintf('kpib: Closing GPIB-%d.\n',g); end iof = instrfind('Type','gpib','PrimaryAddress',g); if ~isempty(iof) if strcmp(iof.Status,'open') clrdevice(iof); end fclose(iof); delete(iof); clear iof; else if verbose >= 1, fprintf('kpib: No instrument in memory at GPIB-%d.\n',g); end end end elseif isstruct(GPIB) && isfield(GPIB,'gpib') if verbose >= 2, fprintf('kpib: Closing GPIB-%d.\n',GPIB.gpib); end iof = instrfind('Type','gpib','PrimaryAddress',GPIB.gpib); if ~isempty(iof) fclose(iof); delete(iof); clear iof; end elseif strncmpi(GPIB,'COM',3) if verbose >= 2, fprintf('kpib: Closing serial port %s.\n',GPIB); end iof = instrfind('Type','serial'); if ~isempty(iof) clrdevice(iof); fclose(iof); delete(iof); clear iof; end else fprintf('kpib: Error, invalid GPIB address ["%s"].\n',GPIB); end validInst = 1; end
'open'
This function basically calls fopen(). Sort of a ping. Can specify GPIB addresses as an array and all addresses will be opened.
if strcmpi(instrument,'open') if isnumeric(GPIB) if verbose >= 2, fprintf('kpib: Opening GPIB# %d.\n',GPIB); end for g=GPIB %io = instrfind('Type','gpib','PrimaryAddress',g); io = port(g,instrument,value,verbose); % if isempty(io) % io = gpib('ni',0,g); % fopen(io); % % set(io,'EOSMode','read&write') % % set(io,'EOSCharCode','LF') % % EOSmode=get(io,'EOSMode'); % % if verbose >= 3, fprintf('kpib/open: EOSmode: %s\n',EOSmode); end % else % if verbose >= 1, fprintf('kpib: Instrument at GPIB# %d already open.\n',g); end % end end if nargout > 0, retval = io; end else fprintf('kpib: Error, invalid GPIB address ["%s"].\n',GPIB); end validInst = 1; end
'write'
This function is used to write the string COMMAND to a specified address.
if strcmpi(instrument,'write') if verbose >= 2, fprintf('kpib: Writing to GPIB# %d.\n',GPIB); end io = port(GPIB,instrument); fprintf(io,command); validInst = 1; end
'query'
(previously known as 'writeread') This function is used to make queries that return a value. The string COMMAND is written to the GPIB address and whatever is returned is returned. The buffersize can also be set to VALUE. The default buffer size is 1000 bytes. The buffer has to be large enough to contain whatever will be returned.
if any(strcmpi(instrument, {'writeread', 'query'})) if verbose >= 2, fprintf('kpib: Writing "%s" to GPIB# %d and reading response.\n',command,GPIB); end io = port(GPIB,instrument,value,verbose); fprintf(io,command); retval = fscanf(io); validInst = 1; end
'scan'
This function scans the GPIB bus and returns information about the type of GPIB interfaces and connected instruments (uses the INSTRHWINFO function). Use VALUE == 'identify' to ask for the identity string from each instrument that is detected.
if strcmpi(instrument,'scan') if verbose >=2, fprintf(1,'%s\n',versionstr); end gpib_interfaces = instrhwinfo('gpib'); %n = length(gpib_interfaces.InstalledAdaptors); for i=1:length(gpib_interfaces.InstalledAdaptors); fprintf(1,'kpib/scan: GPIB interface ''%s'':\n',gpib_interfaces.InstalledAdaptors{i}); fprintf(1,' Instruments Detected:\n'); boardinfo=instrhwinfo('gpib',gpib_interfaces.InstalledAdaptors{i}); for j=1:length(boardinfo.ObjectConstructorName) fprintf(1,' %s ',boardinfo.ObjectConstructorName{j}); if strcmpi(command,'identify') addr=textscan(boardinfo.ObjectConstructorName{j},'%s %s %n);'); fprintf(1,'%s\n',kpib('identify',addr{3},command,value,channel,aux,0)); else fprintf(1,'\n'); end end end if verbose >= 3, fprintf(1, '%s\n%s\n%s\n%s\n','kpib/scan: Note: if you are having trouble with kpib,',... ' make sure that the correct GPIB interface manufacturer',... ' from the list show here is entered in the kpib code',... ' as the value for the variable "gpib_interface_manufacturer".'); end serial_interfaces = instrhwinfo('serial'); for i=1:length(serial_interfaces.AvailableSerialPorts); fprintf(1,'kpib/scan: Serial interface ''%s''\n\n',serial_interfaces.AvailableSerialPorts{i}); end kpib('clear',0,command,value,channel,aux,verbose); validInst = 1; end % %% %% %% %% %% %% %% %% %% %% %% %% %% %% %% %% %
Individual Instrument Drivers
Each supported instrument is handled by the appropriate IF statement which matches the 'INSTRUMENT' parameter. Documentation for each driver is in the comment field for each section.
'None' (no instrument)
This is a "dummy instrument" so that we can make calls the kpib that have no result 'none' | '[none]' | '(none)'
if any(strcmpi(instrument,{'none','[none]','(none)'})) if verbose >= 2, fprintf(1, 'kpib: Instrument NONE'); end if nargout > 0 if strcmpi(value,'temp') retval = 1776; if verbose >= 2, fprintf(1, ', retval = 1776 (temp).\n'); end else retval = 0; if verbose >= 2, fprintf(1, ', retval = 0.\n'); end end else if verbose >= 2, fprintf('.\n'); end end validInst = 1; end
'Blueoven' Thermotron S1 with 2800-series controller
The BlueOven is a Thermotron S1 thermal chamber with a 2800-series controller.
%RETVAL = KPIB('INSTRUMENT', GPIB, 'COMMAND', VALUE, CHANNEL, AUX, VERBOSE) % Valid oven commands: % 'init' Initializes the oven with a 3 sec command lock out. Locks the % keypad. VALUE determines hard or soft init: % VALUE==0 "hard" reset- forces hardware reset with "I" % Value~=0 "soft" reset- manual, stop, lock commands, does not use "I" % 'set' Sets the temperature setpoint to VALUE in degrees C. Also 'setT'. % Query setpoint with VALUE == 'query' or '?' % 'read' Reads the current temperature and the setpoint temperature. Returns the % oven temperature as read by the controller (change in v2.9) % 'stop' Stops the ovens current program, sets the setpoint to 22 C, and % unlocks the keypad. % 'lock' Locks the keypad. % 'unlock' Unlocks the keypad. % if (strcmpi(instrument, 'BlueOven') || strcmpi(instrument, 'all')) io = port(GPIB, instrument, 0, verbose); if (io ~=0) && (strcmp(get(io,'Status'),'open') ~=0) % default to hard reset %if nargin < 4, value = 0; end switch command case 'init' if verbose >= 1, fprintf('kpib/BlueOven: Initializing Blue Oven at address %.0f\n',GPIB); end % what kind of reset? if value==0 % do a hard reset with "I" command (default) fprintf(io,'I'); % Forces the 2800 to do a hardware reset taking 3 sec. % pause(10); % pause to prevent further communication with blue oven during reset. % fprintf(io,'LKS1'); % Locks the oven keypad. % fclose(io); elseif value~=0 % do a soft reset with manual, stop, lock fprintf(io,'RM'); % set to run manual mode fprintf(io,'S'); % stop any programs fprintf(io,'LKS1'); % lock the keypad end case {'set','setT'} if isnumeric(value) value=round(value); % whole numbers only, please if verbose >= 2, fprintf('kpib/BlueOven: Setting the Blue Oven to %d C\n', value); end fprintf(io,'RM'); % Sets the oven into run manual if value >= 0 fprintf(io,'LTS+%d',value); % Loads temperature set point end if value < 0 fprintf(io,'LTS%d',value); % Loads temperature set point end elseif strcmpi(value,'query') || strcmpi(value,'?') fprintf(io, 'DTS'); %Tells the controller to dump temperature setpoint. retval = fscanf(io, '%f'); %Reads the dumped setpoint. if verbose >= 2, fprintf(1,'kpib/BlueOven: Setpoint: %d C\n',retval); end else if verbose >= 1, fprintf(1,'kpib/BlueOven: "set" command error\n'); end end case {'read','getdata'} if verbose >= 2, fprintf('kpib/BlueOven: Reading the Blue Oven temperature:'); end fprintf(io, 'DTV'); %Tells the controller to dump temperature value. retval = fscanf(io, '%f'); %Reads the dumped temp value. if verbose >= 2, fprintf(1,' %.1f C\n',retval); end case {'stop','off'} if verbose >= 2, fprintf('kpib/BlueOven: Stopping the Blue Oven\n'); end fprintf(io, 'RM'); %Causes controller to go to manual operation. fprintf(io, 'LTS+22'); %Sets the oven temp to 22 C. fprintf(io, 'S'); %Stops the controller from any running condition. fprintf(io, 'LKS0'); %Unlocks the keypad. case 'lock' fprintf(io,'LKS1'); % Locks the oven keypad. if verbose >= 2, fprintf('kpib/BlueOven: Blue Oven keypad locked.\n'); end case 'unlock' fprintf(io,'LKS0'); % Unlocks the oven keypad. if verbose >= 2, fprintf('kpib/BlueOven: Blue Oven keypad unlocked.\n'); end otherwise if verbose >= 1, fprintf('kpib/BlueOven: Error, command not supported. ["%s"]\n',command); end end else % catch incorrect address errors if verbose >= 1, fprintf('kpib/%s: ERROR: No instrument at GPIB %d\n',instrument,GPIB); end retval=0; end validInst = 1; end % end BlueOven
'GreyOven' Testequity 1007S
The Grey Oven has a ICS 4809 GPIB interface which communicates with the Watlow F4 termperature controller. See manual on the web: "TestEquity GPIB Interface Option" and printed manual for both the chamber and the controller. Note that one decimal point is implied for all communication with the Grey Oven/F4.
%RETVAL = KPIB('INSTRUMENT', GPIB, 'COMMAND', VALUE, CHANNEL, AUX, VERBOSE) % Valid oven commands: % 'init' Initializes the oven with a *RST command. Sets the command timeout to % 300 ms, as per example in the manual. Locks the keypad. % 'set' Sets the temperature setpoint to VALUE in degrees C. % Query setpoint with VALUE == 'query' or '?' % 'read' Reads the current oven temperature. Returns the oven temperature % and setpoint as read by the controller (change in v2.9) % Use VALUE=='temp' to read the unfiltered "high-res' % temperature. % 'stop' Stops the oven controller. % 'lock' Locks the keypad (setpoint control only). % 'unlock' Unlocks the keypad. % if any(strcmpi(instrument, {'GreyOven', 'WAT_F4'})) || strcmpi(instrument, 'all') io = port(GPIB, instrument, 0, verbose); if (io ~=0) && (strcmp(get(io,'Status'),'open') ~=0) switch command case 'init' if verbose >= 2, fprintf(1, 'kpib/GreyOven: Initializing Grey Oven at address %.0f\n',GPIB); end % send Reset Command fprintf(io,'*RST'); % set the command timeout to 300 ms fprintf(io,'D300'); % lock the set point fprintf(io,'W1300,1'); case {'set','setT'} if isnumeric(value) % setpoint is register 300. Send temperature with one decimal % point implied. go_set=value*10; fprintf(io,'W300,%0f',go_set); if verbose >= 2, fprintf(1, 'kpib/GreyOven: Setting the Grey Oven to %.1f C\n', value); end elseif strcmp(value,'query') || strcmpi(value,'?') % check to be sure that the result will be given using one % implied decimal point (default) fprintf(io,'R606,1'); decimal_pt=fscanf(io, '%f'); fprintf(io,'R300,1'); set_temp=fscanf(io, '%f'); % divide result by ten if required if decimal_pt == 1 retval = set_temp/10; else retval = set_temp; end else if verbose >= 1, fprintf(1, 'kpib/GreyOven: "set" command error\n'); end end case {'read','getdata'} % check to be sure that the result will be given using one % implied decimal point (default) fprintf(io,'R606,1'); decimal_pt=fscanf(io, '%f'); %if strcmp(value,'temp') if any(strcmpi(value,{'temp','temperature','T'})) %v4.72 % read the "high-res" temperature from register 1707 % it has two decimal places of precision fprintf(io,'R1707,1'); go_temp=fscanf(io, '%f'); retval=go_temp/100; else % read the temperature from register 100 fprintf(io,'R100,1'); go_temp=fscanf(io, '%f'); % divide result by ten if required if decimal_pt == 1 retval = go_temp/10; else retval = go_temp; end end if verbose >= 2, fprintf(1, 'kpib/GreyOven: Grey Oven temperature: %.1f\n',retval); end case {'stop','off'} if verbose >= 2, fprintf(1, 'kpib/GreyOven: Stopping the Grey Oven\n'); end % to stop the F4 controller in manual mode, set the temperature % setpoint to the low limit -1 (F4 manual page 3.1) % NB: this is the low limit in implied-decimal-point ModBus % numbers-1, NOT setpoint-1 in Deg C. fprintf(io,'R602,1'); % read the set point low limit lowlimit=fscanf(io,'%f'); fprintf(io,'W300,%0f',lowlimit-1); % Sets the oven temp to Low Limit -1. % (implied decimal point ModBus numbers) fprintf(io,'W1315,0'); % unlock the control panel. case 'lock' fprintf(io,'W1300,1'); % Locks the oven keypad (setpoint only). if verbose >= 2, fprintf('kpib/GreyOven: Grey Oven keypad locked.\n'); end case 'unlock' fprintf(io,'W1315,0'); % Clears all locks. if verbose >= 2, fprintf('kpib/GreyOven: Grey Oven keypad unlocked.\n'); end otherwise if verbose >= 2, fprintf(1, 'kpib/GreyOven: Error, command not supported. ["%s"]\n',command); end end else % catch incorrect address errors if verbose >= 1, fprintf('kpib/%s: ERROR: No instrument at GPIB %d\n',instrument,GPIB); end retval=0; end validInst = 1; end % end GreyOven
'WAT_981' Temperature controller
The Watlow 981 controller can be used to control a temperature chamber. This code interfaces with the controller over GPIB.
%RETVAL = KPIB('INSTRUMENT', GPIB, 'COMMAND', VALUE, CHANNEL, AUX, VERBOSE) % Valid oven commands: % 'init' Initializes the oven with a *RST command. Sets the command timeout to % 300 ms, as per example in the manual. Locks the keypad. % 'set' Sets the temperature setpoint to VALUE in degrees C. % Query setpoint with VALUE == 'query' or '?' % 'read' Reads the current oven temperature. Returns the oven temperature % and setpoint as read by the controller (change in v2.9) % 'stop' Stops the oven controller. % 'lock' Locks the keypad (setpoint control only). % 'unlock' Unlocks the keypad. % if any(strcmpi(instrument, {'WAT_981'})) || strcmpi(instrument, 'all') baudrate = 0; % buffer size for GPIB (0 for default), baud rate for serial port instruments io = port(GPIB, instrument, baudrate, verbose); if (io ~=0) && (strcmp(get(io,'Status'),'open') ~=0) switch command case 'init' retval=0; % default output fprintf(io, '? MDL'); pause(0.5) mdl = fscanf(io, '%s'); fprintf(io, '? SOFT'); pause(0.5) rev = fscanf(io, '%s'); if verbose >= 2, fprintf(1,'kpib/WAT_981: model %s, software rev %s\n',mdl,rev); end fprintf(io, '? ER'); pause(0.5) rerr1 = fscanf(io, '%i'); if rerr1 ~= 0 if verbose >= 1, fprintf(1,'kpib/WAT_981: WARNING: Input error detected during initialization (%i)\n',rerr1); end else if verbose >= 2, fprintf(1,'kpib/WAT_981: No input errors reported.\n'); end end fprintf(io, '? ER2'); pause(0.5) rerr2 = fscanf(io, '%i'); if rerr2 ~= 0 if verbose >= 1, fprintf(1,'kpib/WAT_981: WARNING: Communication error detected during initialization (%i)\n',rerr2); end else if verbose >= 2, fprintf(1,'kpib/WAT_981: No communication errors reported.\n'); end end if verbose >= 1 && ~rerr1 && ~rerr2 if verbose >= 1, fprintf(1,'kpib/WAT_981: Thermal chamber ready to use.\n'); end end case {'set','setT'} if isnumeric(value) if ~(channel==1 || channel==2) channel=1; % default channel 1 end cmd=sprintf('= SP%d %.1f\n',channel,value); if verbose >= 1, fprintf('kpib/WAT_981: Setting the chamber temperature (ch%d) to %.1f C\n',channel,value); end fprintf(io,cmd); elseif strcmpi(value,'query') || strcmpi(value,'?') fprintf(io, '? SP1'); pause(0.5) % read current setpoint retval = fscanf(io, '%f'); if verbose >= 2, fprintf(1,'kpib/WAT_981: Setpoint: %d C\n',retval); end else if verbose >= 1, fprintf(1,'kpib/WAT_981: "set" command error\n'); end end case {'read','getdata'} if ~(channel==1 || channel==2) channel=1; % default channel 1 end if verbose >= 2, fprintf('kpib/WAT_981: Chamber temperature reading (ch%d):',channel); end cmd=sprintf('? C%d',channel); fprintf(io,cmd); pause(0.5) % query temperature reading retval = fscanf(io, '%f'); %retval = fscanf(io,'%f',1); if verbose >= 2, fprintf(1,' %.1f C\n',retval); end case 'lock' fprintf(io,'= LOC 3'); % Locks the oven keypad (setpoint only). if verbose >= 2, fprintf('kpib/WAT_981: Keypad locked.\n'); end case 'stop' fprintf(io,'? RL1'); % what is low limit? lowlimit=fscanf(io,'%f'); fprintf(io,'= SP1 %.1f',lowlimit-1); fprintf(io,'= LOC 0'); % Clears all locks. if verbose >= 2, fprintf('kpib/WAT_981: Stopped.\n'); end case 'unlock' fprintf(io,'= LOC 0'); % Clears all locks. if verbose >= 2, fprintf('kpib/WAT_981: Keypad unlocked.\n'); end otherwise if verbose >= 1, fprintf(1,'kpib/%s: Error, command not supported. ["%s"]\n',instrument,command); end end else % catch incorrect address errors if verbose >= 1, fprintf(1,'kpib/%s: ERROR: No instrument at GPIB %s\n',instrument,num2str(GPIB)); end retval=0; end validInst = 1; end % %%%%% end <WAT_981>
'HP_3478A' HP multimeter
%RETVAL = KPIB('INSTRUMENT', GPIB, 'COMMAND', VALUE, CHANNEL, AUX, VERBOSE) % Valid Commands: % 'init' Initialize the multimeter. % 'read' Trigger a measurement of type VALUE ('volt'|'ohms'|'curr'|'temp') with % range CHANNEL and return the result % 'read' defaults to voltage measurement for compatibility with code % written to kpib < v2.4. % 'getdata' Same as 'read'. % % Valid ranges for measurement in Volts or DC Amps: % .030,.300,3,30,300 % Valid ranges for measurement in Ohms: % 30,300,3000,30000,300000,3000000,30000000 % If no CHANNEL is supplied for the range then the multimeter is set to % auto. % % % 3478A command strings (manual p59) % Mxx SRQ mask % Zx Autozero on or off (0 | 1) % Nx Display setting: (3 - 5) digits of resolution % Fx Instrument function (1 - 7); % 1 = DC volts, 3 = 2-wire ohms, 5 = DC current % Rx Range(-2 - 7, A). A = autorange % Tx Trigger. 1 = internal trigger if (strcmpi(instrument, 'HP_3478A') || strcmpi(instrument, 'all')) io = port(GPIB, instrument, 0, verbose); if (io ~=0) && (strcmp(get(io,'Status'),'open') ~=0) %fprintf(io, '*RST'); switch command case 'init' fprintf(io,'H0'); case {'read','getdata'} % if VALUE is not specified (volts,ohms,curr,temp), default to volts switch value case {'ohm','ohms','R'} % if a valid range has been specified, use it. CHANNEL is % the measurement range in ohms switch channel case 30 fprintf(io, 'M01Z1N5F3R1T1'); case 300 fprintf(io, 'M01Z1N5F3R2T1'); case 3000 fprintf(io, 'M01Z1N5F3R3T1'); case 30000 fprintf(io, 'M01Z1N5F3R4T1'); case 300000 fprintf(io, 'M01Z1N5F3R5T1'); case 3000000 fprintf(io, 'M01Z1N5F3R6T1'); case 30000000 fprintf(io, 'M01Z1N5F3R7T1'); otherwise if verbose >= 2, fprintf('kpib/HP_3478A: Range Automatically Set by Multimeter\n'); end fprintf(io, 'M01Z1N5F3RAT1'); end % read the value returned retval = fscanf(io,'%f'); if verbose >=2, fprintf(1,'%s %f %s\n','kpib/HP_3478A: Resistance measurement:',retval,'ohms'); end case {'volt','volts','V','temp','temperature','T'} % "temperature" is a special case of reading % voltage from a LM35 sensor. Temperature in C % equals voltage*100 % if a valid range has been specified, use it. % CHANNEL is the measurement range in volts. switch channel case .030 fprintf(io, 'M01Z1N5F1R-2T1'); case .300 fprintf(io, 'M01Z1N5F1R-1T1'); case 3 fprintf(io, 'M01Z1N5F1R0T1'); case 30 fprintf(io, 'M01Z1N5F1R1T1'); case 300 fprintf(io, 'M01Z1N5F1R2T1'); otherwise switch value case {'volt','volts','V'} if verbose >= 2, fprintf('kpib/HP_3478A: Range Automatically Set by Multimeter\n'); end fprintf(io, 'M01Z1N5F1RAT1'); case {'temp','temperature','T'} if verbose >= 2, fprintf('kpib/HP_3478A: Range 3 volts (default for T measurement)\n'); end fprintf(io, 'M01Z1N5F1R0T1'); end end % read the value returned retval = fscanf(io,'%f'); switch value case {'volt','volts','V'} if verbose >= 2, fprintf(1,'%s %g %s\n','kpib/HP_3478A: Voltage measurement:',retval,'volts'); end case {'temp','temperature','T'} retval = retval *100; % return value in deg C if verbose >= 2, fprintf(1,'%s %g %s\n','kpib/HP_3478A: Temperature measurement:',retval,'deg C'); end end % % 'temp' currently refers to the LM35 circuit where % % T (deg C) = volts*100 % % but this could be changed in future to be a % % 4-wire resistance measurement of an RTD % case {'temp','temperature','T'} % % if a valid range has been specified, use it. Otherwise default to 3 volts. % % CHANNEL is the measurement range in volts % switch channel % case .030 % fprintf(io, 'M01Z1N5F1R-2T1'); % case .300 % fprintf(io, 'M01Z1N5F1R-1T1'); % case 3 % fprintf(io, 'M01Z1N5F1R0T1'); % case 30 % fprintf(io, 'M01Z1N5F1R1T1'); % case 300 % fprintf(io, 'M01Z1N5F1R2T1'); % otherwise % if verbose >= 2, fprintf('kpib/HP_3478A: Range 3 volts (default temp)\n'); end % fprintf(io, 'M01Z1N5F1R0T1'); % end % % read the value returned % retval = fscanf(io,'%f'); retval = retval *100; % return value in deg C % if verbose >= 2, fprintf(1,'%s %g %s\n','kpib/HP_3478A: Temperature measurement:',retval,'deg C'); end case {'curr','current','I'} % if a valid range has been specified, use it. CHANNEL is % the measurement range in amps switch channel case .030 fprintf(io, 'M01Z1N5F5R-2T1'); case .300 fprintf(io, 'M01Z1N5F5R-1T1'); case 3 fprintf(io, 'M01Z1N5F5R0T1'); case 30 fprintf(io, 'M01Z1N5F5R1T1'); case 300 fprintf(io, 'M01Z1N5F5R2T1'); otherwise if verbose >= 2, fprintf('kpib/HP_3478A: Range Automatically Set by Multimeter\n'); end fprintf(io, 'M01Z1N5F5RAT1'); end % read the value returned retval = fscanf(io,'%f'); if verbose >= 2, fprintf(1,'%s %g %s\n','kpib/HP_3478A: Current measurement:',retval,'amps'); end otherwise % default to voltage measurement for compatibility with older code % if a valid range has been specified, use it. CHANNEL is % the measurement range in volts switch channel case .030 fprintf(io, 'M01Z1N5F1R-2T1'); case .300 fprintf(io, 'M01Z1N5F1R-1T1'); case 3 fprintf(io, 'M01Z1N5F1R0T1'); case 30 fprintf(io, 'M01Z1N5F1R1T1'); case 300 fprintf(io, 'M01Z1N5F1R2T1'); otherwise if verbose >= 2, fprintf('kpib/HP_3478A: Range Automatically Set by Multimeter\n'); end fprintf(io, 'M01Z1N5F1RAT1'); end % read the value returned retval = fscanf(io,'%f'); if verbose >= 2, fprintf(1,'%s %f %s\n','kpib/HP_3478A: Voltage measurement (default):',retval,'volts'); end end % end ohms/volts/curr (VALUE) switch otherwise if verbose >= 1, fprintf('kpib/HP_3478A: Error, command not supported by the instrument.\n'); end end % end command switch else % catch incorrect address errors if verbose >= 1, fprintf('kpib/%s: ERROR: No instrument at GPIB %d\n',instrument,GPIB); end retval=0; end validInst = 1; end % end HP_3478A
'HP_34401A' HP multimeter
RETVAL = KPIB('INSTRUMENT', GPIB, 'COMMAND', VALUE, CHANNEL, AUX, VERBOSE) Valid instructions: 'read' Trigger a measurement of type VALUE ('volt'|'ohms') with range CHANNEL and resolution AUX and return the result
'config' Configures the multimeter for measurement VALUE ('volt') with range CHANNEL and resolution AUX. Once the instrument has been configured, measurement results can be downloaded from the instrument in quick succession using 'getdata'. Currently, only voltage measurements are supported in kpib, but the principle is applicable to all of the instrument's functions.
'getdata' Return the current measurement result. This is in contrast to the 'read' command, which configures and triggers the measurement before returning the result. As a result, 'getdata' is much faster than 'read' for repeated measurements of the same quantity.
Valid ranges for the resistance measurement in ohms: 100, 1000, 10000, 1000000, 10000000 Valid ranges for voltage measurement in volts: .030,.300,3,30,300
If no VALUE is supplied for the range then the multimeter is set to auto.
Returned values: For command 'read': retval The multimeter measurement, as a %f number
%RETVAL = KPIB('INSTRUMENT', GPIB, 'COMMAND', VALUE, CHANNEL, AUX, VERBOSE) if (strcmpi(instrument, 'HP_34401A') || strcmpi(instrument, 'all')) io = port(GPIB, instrument, 50000*16, verbose); % buffer size for downloading data if (io ~=0) && (strcmp(get(io,'Status'),'open') ~=0) switch command case {'config','configure'} % use config to set up a measurement and 'getdata' to measure switch value case {'volt','volts','V','VDC'} if (any(channel == [0.030 0.300 3 30 300])) if verbose >=2, fprintf(1,'%s %g %s\n','kpib/HP_34401A: Configure for Voltage measurement with range',channel,'volts'); end cmd=sprintf('CONF:VOLT:DC %d,DEF', channel); % if a valid resolution has also been specified, use it if aux >= 1e-8 if verbose >=2, fprintf(1,' %s %g %s\n','and with resolution',aux,'volts'); end cmd=sprintf('CONF:VOLT:DC %d,%d', channel, aux); end % send the resulting command fprintf(io,cmd); else % if the specified range/resolution are not valid, then % autorange if verbose >=2, fprintf(1,'%s\n','kpib/HP_34401A: Configure for autorange Voltage measurement'); end fprintf(io,'CONF:VOLT:DC DEF,DEF'); end otherwise if verbose >= 1, fprintf('kpib/HP_34401A: Error, only "volt" configuration supported.\n'); end end case 'read' switch value case {'ohm','ohms','R'} if any(channel == [100 1000 10000 1000000 10000000]) if verbose >=2, fprintf(1,'%s %d\n','kpib/HP_34401A: Resistance measurement, range:',channel); end cmd = sprintf('MEAS:RES? %d,DEF', channel); % if a valid resolution has been specified, use it if aux >= 0.0001 if verbose >=2, fprintf(1,' %s %g %s\n','with resolution:', aux, 'ohms'); end cmd = sprintf('%s %d%s%d', 'MEAS:RES?', channel, ',', aux); end % send the resulting command fprintf(io, cmd); else % if the specified range/resolution are not valid, then autorange if verbose >=2, fprintf(1,'%s\n','kpib/HP_34401A: Autorange resistance measurement'); end fprintf(io,'MEAS:RES? DEF,DEF'); end % read the value returned retval = fscanf(io,'%f'); if verbose >=2, fprintf(1,'%s %f %s\n','kpib/HP_34401A: Resistance Measurement:',retval,'ohms'); end case {'volt','volts','V','VDC'} % if a valid range has been specified, use it. CHANNEL % is the measurement range in volts if (any(channel == [0.030 0.300 3 30 300])) if verbose >=2, fprintf(1,'%s %g %s\n','kpib/HP_34401A: Voltage measurement with range',channel,'volts'); end cmd=sprintf('MEAS:VOLT:DC? %d,DEF', channel); % if a valid resolution has also been specified, use it if aux >= 1e-8 if verbose >=2, fprintf(1,' %s %g %s\n','and with resolution',aux,'volts'); end cmd=sprintf('MEAS:VOLT:DC? %d,%d', channel, aux); end % send the resulting command fprintf(io,cmd); else % if the specified range/resolution are not valid, then % autorange if verbose >=2, fprintf(1,'%s\n','kpib/HP_34401A: Autorange voltage measurement'); end fprintf(io,'MEAS:VOLT:DC? DEF,DEF'); end % read the value returned retval = fscanf(io,'%f'); if verbose >=2, fprintf(1,'%s %f %s\n','kpib/HP_34401A: Measurement:',retval,'volts'); end case {'curr','current','I','IDC'} % if a valid range has been specified, use it. CHANNEL % is the measurement range in volts if (any(channel == [0.030 0.300 3 30 300])) if verbose >=2, fprintf(1,'%s %g %s\n','kpib/HP_34401A: Current measurement with range',channel,'Amps'); end cmd=sprintf('MEAS:CURR:DC? %d,DEF', channel); %if nargin > 5 % if a valid resolution has also been specified, use it if aux >= 1e-8 if verbose >=2, fprintf(1,' %s %g %s\n','and with resolution',aux,'Amps'); end cmd=sprintf('MEAS:CURR:DC? %d,%d', channel, aux); end %end % send the resulting command fprintf(io,cmd); else % if the specified range/resolution are not valid, then % autorange if verbose >=2, fprintf(1,'%s\n','kpib/HP_34401A: Autorange current measurement'); end fprintf(io,'MEAS:CURR:DC? DEF,DEF'); end % read the value returned retval = fscanf(io,'%f'); if verbose >=2, fprintf(1,'%s %f %s\n','kpib/HP_34401A: Measurement:',retval,'Amps'); end otherwise if verbose >= 1, fprintf('kpib/HP_34401A: Error, must specify measurement: ''ohms'', ''volt'', or ''curr''.\n'); end end % end ohms/volts/current switch case {'getdata'} % get the current measurement result fprintf(io,'READ?'); retval = fscanf(io,'%f'); if verbose >=2, fprintf(1,'kpib/HP_34401A: Measurement: %f\n',retval); end otherwise if verbose >= 1, fprintf('kpib/HP_34401A: Error, command not supported by the instrument. ["%s"]\n',command); end end % end read else % catch incorrect address errors if verbose >= 1, fprintf('kpib/%s: ERROR: No instrument at GPIB %d\n',instrument,GPIB); end retval=0; end validInst = 1; end % end HP_34401A
HP Power Supplies ('HP_POWER')
The GPIB commands are the same for all recent generations of HP power supplies; the only difference is whether or not they have multiple outputs. Note that kpib is doing no limit checking, and different models have different output limits. If your model is not listed here, that means it hasn't been tested, but it probably works if it is reasonably recent (< 10 yrs old). Use INSTRUMENT == 'HP_POWER' to control a generic HP power supply.
%RETVAL = KPIB('INSTRUMENT', GPIB, 'COMMAND', VALUE, CHANNEL, AUX, VERBOSE) % Valid Commands: % 'init' Send the *RST command to reset the instrument and clear registers % 'read' Reads the output levels of the specified Output CHANNEL. % Returns a single value if you specify VALUE ('volt' or 'curr'), % otherwise result is returned as a two-field structure of %f numbers: % retval.volt % retval.curr % 'setV' Sets the output voltage to VALUE in Volts. Also 'set' (deprecated). % 'setI' Sets the output current to VALUE in Amps. % % 'off' Turns off both outputs. % 'on' Turns on both outputs. % if (any(strcmpi(instrument, HP_power)) || strcmpi(instrument, 'all')) io = port(GPIB, instrument, 0, verbose); if (io ~=0) && (strcmp(get(io,'Status'),'open') ~=0) % do we need to select an output channel? if any(strcmpi(instrument, HP_power_M)) % select the Output channel if specified, default to 1 if ~(any(channel == [1 2 3])) channel=1; end if strcmpi(instrument,'HP_E3631A') % use name of channel instead of number switch channel case 1 fprintf(io, 'INST:SEL P6V'); case 2 fprintf(io, 'INST:SEL P25V'); case 3 fprintf(io, 'INST:SEL N25V'); end else fprintf(io, 'INST:SEL OUT%d', channel); % Selects the output end if verbose >= 2, fprintf(1, 'kpib/%s(%d): Output %d ',instrument,GPIB,channel); end end switch command case 'init' fprintf(io,'*RST'); case 'read' switch value % return a single value or both V & I? case {'volt','volts','V','v'} % read the voltage fprintf(io, 'MEAS:VOLT?'); retval = fscanf(io,'%f'); if verbose >= 2, fprintf(1, 'reads %f Volts\n',retval); end case {'curr','I','A','current'} % read the current fprintf(io, 'MEAS:CURR?'); retval = fscanf(io,'%f'); if verbose >= 2, fprintf(1, 'reads %f Amps\n',retval); end otherwise % read the output fprintf(io, 'MEAS:VOLT?'); retval.volt = fscanf(io,'%f'); fprintf(io, 'MEAS:CURR?'); retval.curr = fscanf(io,'%f'); if verbose >= 2, fprintf(1, 'reads %f Volts & %f Amps\n',retval.volt,retval.curr); end end case {'setV','volt','voltage','set'} % set the voltage fprintf(io, 'VOLT %f',value); % Sets voltage. if verbose >= 2, fprintf('Output Voltage set to %g Volts\n',value); end case {'setI','curr','current'} % set the current fprintf(io, 'CURR %f',value); % Sets current. if verbose >= 2, fprintf('Output Current set to %g Amps\n',value); end case 'off' fprintf(io, 'OUTP OFF'); % Disables all outputs. if verbose >= 2, fprintf(1, 'Outputs off.\n'); end case 'on' fprintf(io, 'OUTP ON'); % Enables all outputs. if verbose >= 2, fprintf(1, ' Outputs on.\n'); end otherwise if verbose >= 1, fprintf('Error, command not supported. ["%s"]\n',command); end end else % catch incorrect address errors if verbose >= 1, fprintf('kpib/%s: ERROR: No instrument at GPIB %d\n',instrument,GPIB); end retval=0; end validInst = 1; end % end HP_POWER
'HP_89410A' HP Vector Signal Analyzer
%RETVAL = KPIB('INSTRUMENT', GPIB, 'COMMAND', VALUE, CHANNEL, AUX, VERBOSE) % In general, these commands assume that the analyzer is setup for Network % measurements, for example by recalling the state file "NA_1p2M.sta". % Valid Commands: % 'label' Writes VALUE to the CHANNEL ('right' or 'left') corner % of the Analyzer display. % 'channel' Selects a channel (1-4) on the display. On the instrument, these % are called "traces" (A,B,C,D). The 'channel' command makes the % specified trace active for purposes of the marker, changing % settings, etc. CHANNEL does not refer to the % inputs on the front of the instrument. % 'autozero' Turns automatic autozeroing 'on' or 'off', or performs a % single autozero ('once'). % 'average' VALUE can be: % 'on' turns averaging on % 'off' turns averaging off % 'type' sets type to CHANNEL ('norm','exp','repeat') % 'repeat' enables averaging repeat % 'restart' restarts the averaging % 'finish' waits for averaging to complete % <number> number of measurements to average (default) % 'autoscale' Autoscales the y axis for channel CHANNEL 'on','off' or % 'once'. Default is once on the current channel. Use 'both' % for resonator measurements to autoscale channels 1 & 2. % 'scale' Sets the y scale (units/division) of the display. VALUE is the % scale in the current units, or 'VALUE' = 'autoy' for autoscale % command. % Query with VALUE = 'query', returns y scale in dB/division. % 'auto x' Auto scales x axis 'off' or 'once'. Default is 'once'. % Not often used with Network measurements. % 'mark2peak' Set Marker peak tracking to VALUE 'on' or 'off' for CHANNEL. % Default channel is 1. % 'peaktrack' Same as 'mark2peak'. % 'marker' Sets the x position of the main marker on CHANNEL to VALUE. % Query with VALUE = 'query', returns x & y positions in Hz/dBm. % Also activates some marker functions, for VALUE: % 'center','m2c',marker2center' % makes the current marker position the frequency center % 'peak','searchpeak','marker2peak' % moves the marker to the location of maximum amplitude % 'marker?' (Alternate query form) Returns the markey position for CHANNEL. % Returns x & y values. % 'center' Set the center frequency to VALUE. Units of Hz. % Query with VALUE = 'query', returns center frequency in Hz. % 'span' Set the frequency sweep span VALUE. Units of Hz. % Query with VALUE = 'query', returns span in Hz. % 'start' Set the frequency sweep start VALUE. Units of Hz. % Query with VALUE = 'query', returns span in Hz. % 'stop' Set the frequency sweep stop VALUE. Units of Hz. % Query with VALUE = 'query', returns span in Hz. % 'source' Set the source (stimulus output) signal level. VALUE is the % desired signal level. Units of dBm. % Query with VALUE = 'query', returns a structure with two values: % state = 'on' | 'off' % level = source power in dBm. % 'source?' (Alternate query form) Returns source power in dBm. % 'power' Same as 'source'. % 'autorange' Automatically determine the best input sensitivity. Default % CHANNEL is 1. VALUE can be 'up' or 'up-down'. % 'getdata' Download the current data trace from the analyzer. Data is % returned as a structure with fields x and y for the % specified CHANNEL. If AUX is one of a family of units % {'am','angl','freq','pow','time'}, then the units for the % data will also be returned. Default CHANNEL is 1. If VALUE % is 'x' or 'y', only that data is returned in a single % column array. % 'units' Returns the units for the axis VALUE ('x','y'). For Y units, % you must specify a "family" in AUX: % 'am','angl','freq','pow','time' % See the programming manual under CALC:UNITs for more information. % 'display' Turns trace CHANNEL 'on' or 'off'. Query state with 'query'. % Returns a binary word representing the on/off status of the four % channels (traces) on the display. % 'trace' Same as display. % 'screen' Turns the screen 'on' or 'off'. Query state with 'query'. % 'pause' Pauses measurement. % 'continue' Continues paused measurement. % 'loadstate' Loads state file VALUE from default disk. % 'savestate' Saves current state as state file VALUE to default disk. % 'complete' Enable status byte (SERS) "operation complete" (*OPC) for % the currently executing command, or the following command % if none is currently executing. Use with 'complete?' for % polling of instrument status. % 'complete?' Query status byte (SERS). If bit 0 == 1, operation is % complete. Must use 'complete' *before* command of interest % for polling. Returns a decimal value equal to the binary % byte value. See manual p18,36. % 'event?' Returns the value of the event register. Bit 4 indicates % that an "event" has occurred. % 'precision' Sets the number of digits of precision for the trace data % outputed to the value specified. % 'precision?'Requests the amount of precision set for the trace data. % This returns an integer for the amount of precision. % 'wait' Instructs analyzer to finish its current command before % starting subsequent [overlapping] commands. if (strcmpi(instrument, 'HP_89410A') || strcmpi(instrument, 'all')) % open a GPIB port for the instrument io = port(GPIB, instrument, 24*4097, verbose); % buffer size 24*4097 for downloading data if (io ~=0) && (strcmp(get(io,'Status'),'open') ~=0) % define list of Y unit types (manual p107) yunit_types={'am','angl','freq','pow','time'}; % define list of source unit types (manual p349) srcunit_types={'dBm','dBV','dBVrms','dBVpk','V','Vpk','Vrms','W','Wrms'}; switch command case 'init' % do nothing if verbose >= 2, fprintf(1, 'kpib/HP_89410A: Initialize (nada). Load NA_1p3m.sta manually.\n'); end case 'label' if ~(strcmpi(channel,'left') || strcmpi(channel,'right')) channel = 'left'; end if isequal(channel,'left') fprintf(io, 'DISP:TRAC:LAB:USER "%s"',value); % Writes to the upper left of the display. elseif isequal(channel,'right') fprintf(io, 'DISP:TRAC:INFO "%s"',value); % Writes to the upper right of the display. else fprintf(io, 'DISP:TRAC:LAB:USER "%s"',value); % Default to the upper left of the display. end case 'channel' % activate a channel % note that the 89410 has more display "traces" (4) than % "channels" (2). So this command really does not activate % a channel; it makes a certain trace the active trace on % the display, for purposes of changing the scale or % whatever. In our usual configuration for resonators, trace 1 will be % showing magnitude, and trace 2 phase, both from Channel 2. if isnumeric (value) && any(value == [1 2 3 4]) fprintf(io, 'DISP:WIND%d:ACTIVE ONCE',value); % manual p128 if verbose >= 2, fprintf(1, 'kpib/HP_89410A: Channel %d active.\n',value); end elseif ~isnumeric(value) && (strcmpi(value,'query') || strcmpi(value,'?')) fprintf(io, 'DISP:WIND%d:ACTIVE?',value); retval = fscanf(io); % % returns 1 or 0 else if verbose >= 1, fprintf(1, 'kpib/HP_89410A: Bad VALUE for channel (must be 1-4 or ''query'') ["%s"].\n',num2str(value)); end end case 'autozero' switch value case 'on' fprintf(io, 'CAL:ZERO:AUTO ON'); case 'off' fprintf(io, 'CAL:ZERO:AUTO OFF'); case 'once' fprintf(io, 'CAL:ZERO:AUTO ONCE'); % wait for autozero to complete % Polls Operational Status Register, see manual p19 pause(1); % register does not appear to set immediately?? fprintf(io,'STAT:OPER:COND?'); % are we calibrating now? c1 = fscanf(io,'%f'); c=1; if c1 == 1 if verbose >=2, fprintf(1, 'kpib/HP_89410A: Waiting for Autozero to finish\n'); end else if verbose >=1, fprintf(1, 'kpib/HP_89410A: Warning: Unexpected Operational Status Register value: %i\n',c1); end end while c fprintf(io,'STAT:OPER:COND?'); c = fscanf(io,'%f'); pause(1); end if verbose >=2, fprintf(1, 'kpib/HP_89410A: Autozero complete.\n'); end otherwise if verbose >= 1, fprintf(1, 'kpib/HP_89410A: Autozero: Not a valid VALUE parameter.\n'); end end case 'average' switch value case 'on' fprintf(io, 'AVER ON'); if verbose >=2, fprintf(1, 'kpib/HP_89410A: Measurement Averaging on'); end if isnumeric(aux) && aux > 0 fprintf(io,'AVER:COUN %d',aux); end fprintf(io,'AVER:COUN?'); num = fscanf(io,'%d'); if verbose >= 2, fprintf(1, ', aver. factor: %d\n',num); end case 'off' fprintf(io, 'AVER OFF'); if verbose >=2, fprintf(1, 'kpib/HP_89410A: Measurement Averaging off\n'); end case {'query','?'} fprintf(io, 'AVERAGE?'); retval = fscanf(io,'%f'); case {'num','num?','number','number?','count','count?'} % return the current average count fprintf(io, 'AVER:COUN:INT?'); retval = fscanf(io,'%f'); if verbose >=2, fprintf(1, 'kpib/HP_89410A: Average count: %d\n',retval); end case {'numaverages?'} % return the current average num setting fprintf(io, 'AVER:COUN?'); retval = fscanf(io,'%f'); if verbose >=2, fprintf(1, 'kpib/HP_89410A: Number of measurements to average: %d\n',retval); end case 'type' switch channel case {'norm','rms','normal'} fprintf(io, 'AVER:TYPE RMS;TCON NORM'); if verbose >=2, fprintf(1, 'kpib/HP_89410A: Measurement Averaging rms ("normal")\n'); end case {'exp','rmsexp','exponential'} fprintf(io, 'AVER:TYPE RMS;TCON EXP'); if verbose >=2, fprintf(1, 'kpib/HP_89410A: Measurement Averaging rms exp.\n'); end case {'rmsrep','repeat'} fprintf(io, 'AVER:TYPE RMS;TCON REP'); if verbose >=2, fprintf(1, 'kpib/HP_89410A: Measurement Averaging rms repeat.\n'); end otherwise fprintf(io, 'AVER:TYPE RMS;TCON NORM'); if verbose >=2, fprintf(1, 'kpib/HP_89410A: Default averaging type: rms\n'); end end case 'repeat' fprintf(io, 'AVER:TCON REPEAT'); if verbose >=2, fprintf(1, 'kpib/HP_89410A: Averaging measurements repeat\n'); end case 'restart' fprintf(io, 'ABOR;*WAI'); % note that this does not seem to have exactly the same effect as the front panel key; % the *WAI command seems to be separate somehow if verbose >=2, fprintf(1, 'kpib/HP_89410A: Restarting averaging\n'); end case {'wait','finish','complete'} % is averaging actually on? fprintf(io, 'AVERAGE?'); as = fscanf(io,'%f'); if as == 1 % wait for averaging to complete % Polls Operational Status Register, see manual p19 fprintf(io, 'AVER:COUN?'); % how many averages? ac = fscanf(io,'%f'); pause(1); % averaging register does not appear to set immediately?? fprintf(io,'STAT:OPER:COND?'); % are we averaging now? c1 = fscanf(io,'%f'); c=1; if c1 == 280 if verbose >=2, fprintf(1, 'kpib/HP_89410A: Waiting for Averaging to finish (%d measurements)\n',ac); end elseif c1 ~= 0 if verbose >=1, fprintf(1, 'kpib/HP_89410A: Warning: Unexpected Operational Status Register value: %i\n',c1); end end while c fprintf(io,'STAT:OPER:COND?'); c = fscanf(io,'%f'); pause(1); end fprintf(io, 'AVER:COUN:INT?'); retval = fscanf(io,'%f'); if verbose >=2, fprintf(1, 'kpib/HP_89410A: Averaging complete (%d measurements).\n',retval); end else if verbose >=1, fprintf(1, 'kpib/HP_89410A: Warning: Averaging is off [pause 2 sec].\n'); end retval = 0; pause(2); end otherwise % set the number of measurements to average if isnumeric(value) && value > 0 if value > 0 fprintf(io, 'AVER:COUN %d', value); if verbose >=2, fprintf(1, 'kpib/HP_89410A: Averaging factor set to %d\n',value); end end end end case {'auto y','autoy','autoscale'} % if nargin > 3 switch value case 'on' fprintf(io, 'DISP:TRAC:Y:AUTO ON'); if verbose >=2, fprintf(1, 'kpib/HP_89410A: Autoscale on\n'); end case 'off' fprintf(io, 'DISP:TRAC:Y:AUTO OFF'); if verbose >=2, fprintf(1, 'kpib/HP_89410A: Autoscale off\n'); end % case {'once','single'} % if nargin > 4 % if isnumeric(channel) & any(channel == [1 2 3 4]) % autoscale channel % fprintf(io, 'DISP:WIND%d:TRAC:Y:AUTO ONCE', channel); % if verbose >=2, fprintf(1, 'kpib/HP_89410A: Autoscale Y channel %d\n',channel); end % else % fprintf(io, 'DISP:TRAC:Y:AUTO ONCE'); % if verbose >=2, fprintf(1, 'kpib/HP_89410A: Autoscale Y current channel\n'); end % end % else % fprintf(io, 'DISP:TRAC:Y:AUTO ONCE'); % if verbose >=2, fprintf(1, 'kpib/HP_89410A: Autoscale Y Channel 1 (default channel)\n'); end % end case 'both' % specific to resonators - autoscale channels 1 & 2 fprintf(io, 'DISP:WIND1:TRAC:Y:AUTO ONCE'); fprintf(io, 'DISP:WIND2:TRAC:Y:AUTO ONCE'); if verbose >=2, fprintf(1, 'kpib/HP_89410A: Autoscale once Y channels 1 & 2\n'); end otherwise % autoscale once if isnumeric(channel) && any(channel == [1 2 3 4]) % autoscale channel fprintf(io, 'DISP:WIND%d:TRAC:Y:AUTO ONCE', channel); if verbose >=2, fprintf(1, 'kpib/HP_89410A: Autoscale once Y channel %d\n',channel); end else fprintf(io, 'DISP:TRAC:Y:AUTO ONCE'); if verbose >=2, fprintf(1, 'kpib/HP_89410A: Autoscale once Y current channel\n'); end end end case 'scale' % manual p154 % first, some error checking if ~isnumeric(channel) channel = 1; if verbose >= 2, fprintf('kpib/HP_89410A: Warning: CHANNEL must be numeric 1 - 4. Defaulting to 1.\n'); end elseif channel == 0 channel = 1; if verbose >= 2, fprintf('kpib/HP_89410A: Warning: CHANNEL must be numeric 1 - 4. Defaulting to 1.\n'); end end % now if we just have a value, assume channel 1 % set scale to VALUE dB/div if isnumeric(value) cmd = sprintf('DISP:WIND%d:TRAC:Y:PDIV %d',channel,value); fprintf(io, cmd); if verbose >= 2, fprintf('kpib/HP_89410A: Y Scale on channel %d set to %d/division\n',channel,value); end % but if we have a command, switch on it else switch value case {'auto','AUTO','autoscale','autoy'} cmd = sprintf('DISP:WIND%d:TRAC:Y:AUTO ONCE',channel); fprintf(io, cmd); if verbose >= 2, fprintf('kpib/HP_89410A: Y Autoscale channel %d\n',channel); end case {'query','?','read'} fprintf(io, 'DISP:WIND%d:TRAC:Y:PDIV?',channel); retval = fscanf(io,'%f'); if verbose >= 2, fprintf('kpib/HP_89410A: Y Scale on Channel %d is %d/division\n',channel,retval); end otherwise if verbose >= 1, fprintf('kpib/HP_89410A: VALUE for ''scale'' command not understood.\n'); end end end case 'auto x' switch value case 'off' fprintf(io, 'DISP:TRAC:X:AUTO OFF'); case 'once' fprintf(io, 'DISP:TRAC:X:AUTO ONCE'); otherwise if verbose >= 2, fprintf(1, 'kpib/HP_89410A: Auto Scale X default: Once\n'); end fprintf(io, 'DISP:TRAC:X:AUTO ONCE'); end case {'mark2peak','peaktrack'} if ~(any(channel==[1 2 3 4])) if verbose >= 2, fprintf(1, 'kpib/HP_89410A: Default channel 1 set for mark2peak.\n'); end channel = 1; % Default channel is 1. end switch value case 'on' fprintf(io, 'CALC%d:MARK:MAX:TRAC ON', channel); case 'off' fprintf(io, 'CALC%d:MARK:MAX:TRAC OFF', channel); end case 'marker' % either set or query marker (set is default) if ~isnumeric(channel) if verbose >= 1, fprintf('kpib/HP_89410A: Note: CHANNEL must be numeric 1 - 4. Defaulting to 1.\n'); end channel = 1; elseif channel == 0 channel = 1; end if channel < 1 || channel > 4, channel = 1; end % set the marker position if isnumeric(value) cmd=sprintf('CALC%d:MARK:X %0.0f HZ',channel,value); fprintf(io, cmd); if verbose >= 2, fprintf(1,'%s %d %s %f %s\n','kpib/HP_89410A: Marker on Channel',channel,'set to',value,'Hz'); end % or query the marker position else switch value case {'query','?'} switch aux case {'x','X'} fprintf(io, 'CALC%d:MARK:X?',channel); retval = fscanf(io,'%f'); case {'y','Y'} fprintf(io, 'CALC%d:MARK:Y?',channel); retval = fscanf(io,'%f'); otherwise fprintf(io, 'CALC%d:MARK:X?',channel); retval.x = fscanf(io,'%f'); fprintf(io, 'CALC%d:MARK:Y?',channel); retval.y = fscanf(io,'%f'); if verbose >= 2, fprintf(1, 'kpib/HP_89410A: Marker on Channel %d position is %f/%f\n',channel,retval.x,retval.y); end end case {'center','m2c','mark2center'} fprintf(io, 'CALC%d:MARK:X?',channel); mc = fscanf(io,'%f'); fprintf(io,'FREQ:CENT %.3f',mc); if verbose >= 2, fprintf(1, 'kpib/HP_89410A: Marker to Center at %.3f Hz\n',mc); end case {'peak','searchpeak','mark2peak'} fprintf(io, 'CALC%d:MARK:MAX', channel); otherwise if verbose >= 1, fprintf(1, 'kpib/HP_89410A: Error at ''marker'' command (VALUE incorrect ["%s"]).\n',value); end end end case 'marker?' if ~(any(channel==[1 2 3 4])) if verbose >= 2, fprintf(1, 'kpib/HP_89410A: Default channel 1 marker.\n'); end value = 1; % Default channel is 1. end fprintf(io, 'CALC%d:MARK:X?',value); retval.x = fscanf(io,'%f'); if verbose >= 2, fprintf(1, 'kpib/HP_89410A: Channel %d marker x: %f\n',value,retval.x); end fprintf(io, 'CALC%d:MARK:Y?',value); retval.y = fscanf(io,'%f'); if verbose >= 2, fprintf(1, 'kpib/HP_89410A: Channel %d marker y: %f\n',value,retval.y); end case 'center' % manual p307 % the query returns the center frequency. if isequal(value,'query') || isequal(value,'?') fprintf(io,'FREQ:CENT?'); retval = fscanf(io,'%f'); if verbose >= 2, fprintf(1, 'kpib/HP_89410A: Center at %g\n',retval); end else if verbose >= 2, fprintf(1, 'kpib/HP_89410A: Center set to %g\n',value); end fprintf(io,'FREQ:CENT %.3f',value); end case 'span' if isequal(value,'query') || isequal(value,'?') fprintf(io,'FREQ:SPAN?'); retval = fscanf(io,'%f'); if verbose >= 2, fprintf('kpib/HP_89410A: Span at %g\n',retval); end else if verbose >= 2, fprintf('kpib/HP_89410A: Span set to %g\n',value); end fprintf(io,'FREQ:SPAN %.3f',value); end case 'start' % manual p321 if isequal(value,'query') || isequal(value,'?') fprintf(io,'FREQ:START?'); retval = fscanf(io,'%f'); if verbose >= 2, fprintf(1, 'kpib/HP_89410A: Sweep start at %g\n',retval); end else if verbose >= 2, fprintf(1, 'kpib/HP_89410A: Sweep start set to %g\n',value); end fprintf(io,'FREQ:START %.3f',value); end case 'stop' % manual p324 if isequal(value,'query') || isequal(value,'?') fprintf(io,'FREQ:STOP?'); retval = fscanf(io,'%f'); if verbose >= 2, fprintf(1, 'kpib/HP_89410A: Sweep stop at %g\n',retval); end else if verbose >= 2, fprintf(1, 'kpib/HP_89410A: Sweep stop set to %g\n',value); end fprintf(io,'FREQ:STOP %.3f',value); end case {'source','power'} % manual p349 switch value case 'on' if verbose >= 2, fprintf('kpib/HP_89410A: Source output ON\n'); end fprintf(io,'OUTP ON'); case 'off' if verbose >= 2, fprintf('kpib/HP_89410A: Source output OFF\n'); end fprintf(io,'OUTP OFF'); case {'query','?'} fprintf(io,'OUTPUT:STATE?'); retval.state = fscanf(io,'%d'); if retval.state == 1 retval.state = 'on'; else retval.state = 'off'; end fprintf(io,'SOUR:VOLT:LEV:IMM:AMPL?'); retval.level = fscanf(io,'%f'); if verbose >= 2, fprintf('kpib/HP_89410A: Source %s; output level is set to %d dBm\n',retval.state, retval.level); end case {'func','function'} if any(strcmpi(channel,{'sin','sinusoid','rand','random','noise','pch','chirp'})) fprintf(io,'SOUR:FUNCTION %s',channel); if verbose >= 2, fprintf('kpib/HP_89410A: Source function set to %s\n',channel); end else if verbose >= 1, fprintf('kpib/HP_89410A: Warning: Source function not understood. [%s]\n',num2str(channel)); end end case {'freq','frequency'} %p342 fprintf(io,'SOUR:FREQ %f',channel); if verbose >= 2, fprintf('kpib/HP_89410A: Source frequency %g Hz\n',channel); end case {'offset'} if abs(channel) <= 5 fprintf(io,'SOUR:VOLT:LEV:IMM:OFFSET %fV',channel); if verbose >= 2, fprintf('kpib/HP_89410A: Source DC offset %g V\n',channel); end else if verbose >= 1, fprintf('kpib/HP_89410A: Warning: No change to Offset voltage. Max. offset +/- 5 V\n'); end end otherwise % set source power to the requested value %sp=str2num(value); % check input for allowed values if isnumeric(value)% & (-110 <= value) & (value < 20) if ~any(strcmpi(aux,srcunit_types)) aux='dBm'; end cmd=sprintf('SOUR:VOLT:LEV:IMM:AMPL %d%s',value,aux); fprintf(io,cmd); if verbose >= 2, fprintf('kpib/HP_89410A: Source output level set to %g %s\n',value,aux); end else if verbose >= 1, fprintf('kpib/HP_89410A: Error: Specify source level (VALUE) as numeric.\n'); end end end case {'source?','power?'} fprintf(io,'OUTPUT:STATE?'); retval.state = fscanf(io,'%d'); if retval.state == 1 retval.state = 'on'; else retval.state = 'off'; end fprintf(io,'SOUR:VOLT:LEV:IMM:AMPL?'); retval.level = fscanf(io,'%f'); %retval = str2num(retval.source); if verbose >= 2, fprintf('kpib/HP_89410A: Source %s; output level is set to %g (dBm?)\n',retval.state, retval.level); end case 'autorange' % If channel is invalid, default to channel 1 if ~(isequal(channel,1) || isequal(channel,2)) if verbose >= 2, fprintf('kpib/HP_89410A: Default channel 1 range.\n'); end channel = 1; end % select a autorange direction % did the user specify a value? up or up-down? % default to up if isnumeric(value) if verbose >= 2, fprintf('kpib/HP_89410A: Default autorange up-only.\n'); end value = 'up'; % Default is autorange up. else switch value case {'up','up-only'} fprintf(io,'VOLT%d:RANG:AUTO:DIR UP',channel); case {'updown','up-down','either'} fprintf(io,'VOLT%d:RANG:AUTO:DIR EITHER',channel); otherwise fprintf(io,'VOLT%d:RANG:AUTO:DIR UP',channel); end end % do the autorange fprintf(io,'VOLT%d:RANG:AUTO ONCE',channel); if verbose >= 2, fprintf('kpib/HP_89410A: Autorange %s on channel %d.\n',value,channel); end case 'getdata' % did the user specify a channel? If not, or if channel is invalid, % default to channel 1 if ~(any(channel == [1 2 3 4])) %if ~(isequal(channel,1) | isequal(channel,2) | isequal(channel,3) | isequal(channel,4)) if verbose >= 2, fprintf('kpib/HP_89410A: Default channel 1 data.\n'); end channel = 1; end % did the user specify x or y data? If not, send both switch value case {'x','X'} fprintf(io, 'TRAC:X:DATA? TRAC%d', channel); data = fscanf(io); raw = sscanf([data,','],'%e,'); retval = truncx(raw); if verbose >= 2, fprintf('kpib/HP_89410A: Channel %d X data downloaded.\n',channel); end case {'y','Y'} fprintf(io,'CALC%d:DATA?',channel); data = fscanf(io); retval = sscanf([data,','],'%e,'); if verbose >= 2, fprintf('kpib/HP_89410A: Channel %d Y data downloaded.\n',channel); end otherwise % return both x & y in a structure fprintf(io, 'TRAC:X:DATA? TRAC%d', channel); data = fscanf(io); raw = sscanf([data,','],'%e,'); retval.x = truncx(raw); fprintf(io,'CALC%d:DATA?',channel); data = fscanf(io); retval.y = sscanf([data,','],'%e,'); if verbose >= 2, fprintf('kpib/HP_89410A: Channel %d X & Y data downloaded.\n',channel); end % does the user want units as well? if any(strcmpi(aux,yunit_types)) % get x units fprintf(io, 'TRAC:X:UNIT? TRAC%d', channel); rd = fscanf(io); retval.units.x = rd(2:end-2); % strip the trailing carriage return and quotes % log or linear? fprintf(io, 'DISP:WINDOW%d:TRAC:X:SPACING?', channel); % manual p151 mode = fscanf(io,'%s'); if strcmp(mode,'LOG') retval.units.x = ['log ' retval.units.x]; end if verbose >= 2, fprintf('kpib/HP_89410A: Channel %d X units are %s\n',channel,retval.units.x); end % get y units fprintf(io, 'CALC%d:UNIT:%s?',[channel aux]); rd = fscanf(io); retval.units.y = rd(1:end-1); % strip the trailing carriage return % everything is in capitals if isequal(retval.units.y,'DB'), retval.units.y='dB'; end if isequal(retval.units.y,'DBM'), retval.units.y='dBm'; end if isequal(retval.units.y,'DEG'), retval.units.y='deg'; end if verbose >= 2, fprintf('kpib/HP_89410A: Channel %d Y units are %s\n',channel,retval.units.y); end else % get x units only fprintf(io, 'TRAC:X:UNIT? TRAC%d', channel); rd = fscanf(io); retval.units.x = rd(2:end-2); % strip the trailing carriage return and quotes % log or linear? fprintf(io, 'DISP:WINDOW%d:TRAC:X:SPACING?', channel); % manual p151 mode = fscanf(io,'%s'); if strcmp(mode,'LOG') retval.units.x = ['log ' retval.units.x]; end retval.units.y = ' '; end end case 'units' if ~(any(channel == [1 2 3 4])) if verbose >= 2, fprintf('kpib/HP_89410A: Default channel 1 set for units.\n'); end channel = 1; %Default channel is 1. end switch value case 'x' fprintf(io, 'TRAC:X:UNIT? TRAC%d', channel); retval = fscanf(io); retval = retval(2:end-2); % strip the trailing carriage return and the quotes % log or linear? fprintf(io, 'DISP:WINDOW%d:TRAC:X:SPACING?', channel); % manual p151 mode = fscanf(io,'%s'); if strcmp(mode,'LOG') retval = ['log ' retval]; end if verbose >= 2, fprintf('kpib/HP_89410A: Channel %d X units are %s\n',channel,retval); end case 'y' % Y units have to be specified in terms of their % "family"; see manual p106 if ~(any(strcmpi(aux,yunit_types))) if verbose >= 2, fprintf(1, 'kpib/HP_89410A: Y assumed to be measured for phase angle.\n'); end channel = 'angl'; end fprintf(io, 'CALC%d:UNIT:%s?',[channel aux]); retval = fscanf(io); retval = retval(1:end-1); % strip the trailing carriage return % everything is in capitals if isequal(retval,'DB'), retval='dB'; end if isequal(retval,'DBM'), retval='dBm'; end if isequal(retval,'DEG'), retval='deg'; end if isequal(retval,'RAD'), retval='rad'; end if verbose >= 2, fprintf('kpib/HP_89410A: Channel %d Y units are %s\n',channel,retval); end end case {'display','trace'} % either turn a channel display on/off, or return a binary word % (string) representing the state of the four displays switch value case {'on','ON'} fprintf(io, 'DISP:WIND%d:TRAC ON',channel); if verbose >= 2, fprintf(1, 'kpib/HP_89410A: Trace %d on.\n',channel); end case {'off','OFF'} fprintf(io, 'DISP:WIND%d:TRAC OFF',channel); if verbose >= 2, fprintf(1, 'kpib/HP_89410A: Trace %d off.\n',channel); end case {'query','?'} % returns 1 for on, 0 for off for each channel dstateword=[]; for cd=1:4 fprintf(io, 'DISP:WIND%d:TRAC:STATE?',cd); dstateword(cd)=str2num(fscanf(io)); %#ok<AGROW> if dstateword(cd)==1, dstate='on'; elseif dstateword(cd)==0, dstate='off'; end if verbose >= 2, fprintf(1, 'kpib/HP_89410A: Trace %d is %s.\n',cd,dstate); end retval(cd)=num2str(dstateword(cd)); end end case {'screen'} % turn the screen on and off switch value case{'on','ON',1} fprintf(io, 'DISP:ENABLE ON'); if verbose >= 2, fprintf(1, 'kpib/HP_89410A: Screen on\n'); end case{'off','OFF',0} fprintf(io, 'DISP:ENABLE OFF'); if verbose >= 2, fprintf(1, 'kpib/HP_89410A: Screen off\n'); end case{'query','?'} fprintf(io, 'DISP:ENABLE?'); retval=fscanf(io,'%d'); if verbose >= 2 if retval==1 fprintf(1, 'kpib/HP_89410A: Screen is on\n'); elseif retval==0 fprintf(1, 'kpib/HP_89410A: Screen is off\n'); end end end case 'pause' fprintf(io,'PAUSE'); case 'continue' fprintf(io,'CONTINUE'); case 'loadstate' fprintf(io,'MMEM:LOAD:STAT 1,%s',value); case 'savestate' fprintf(io,'MMEM:STOR:STAT 1,%s',value); case 'complete' if strcmp(value,'single') % for single, use the averaging command for wait kpib(instrument,GPIB,'average','complete',0,0,verbose); else % Enable the Operation Complete bit of the Status Byte. Get % Status Byte with 'complete?' (manual p18) % Note that many commands may trigger the OPC bit. Use % 'wait' (*WAI) to force *currently buffered* commands to % execute in sequence. fprintf(io,'*CLS'); %pause(1) fprintf(io,'*OPC'); % fprintf(io,'*ESR?'); % esr = fscanf(io); if verbose >= 2, fprintf(1, 'kpib/HP_89410A: Begin wait for Operation\n'); end retval = 1; % for compatibility with older code end case 'complete?' % return Status Byte %fprintf(io,'*WAI;*OPC?'); fprintf(io,'*ESR?'); esr = fscanf(io); retval = str2num(esr); if verbose >= 2 if retval > 0 fprintf(1, 'kpib/HP_89410A: Operation complete.\n'); else fprintf(1, 'kpib/HP_89410A: Operation complete.\n'); end end case {'event?'} % For synchronizing with Averaging, the start of averaging % after filling the time record and every new average % count is an "event". % Queries the Device State Event register (manual p366) fprintf(io,'STATUS:DEVICE:EVENT?'); dser = fscanf(io); retval = str2num(dser); %RETVAL of 32 (bit 4) indicates "Event Occurred" if verbose >= 2 if retval > 31 fprintf(1, 'kpib/HP_89410A: Operation complete.\n'); else fprintf(1, 'kpib/HP_89410A: Operation not complete.\n'); end end case 'wait' % Note that *WAI does not really perform sychronization- the code % continues to execute and send new commands to the instrument. % The instrument finishes its current command before % processing any further commands. fprintf(io,'*WAI'); retval = 1; % for compatibility with older code case 'precision' if value > 0 if verbose >= 2, fprintf(1, 'kpib/HP_89410A: Default precision 10.\n'); end value = 10; fprintf(io, 'FORM ASC,%d', value); end case 'precision?' fprintf(io,'FORM?'); retval = fscanf(io,'ASC,%i%i'); case {'abort','restart'} % "pressing Meas Restart" fprintf(io,'ABORT'); %retval = fscanf(io,'ASC,%i%i'); otherwise if verbose >= 1, fprintf('kpib/HP_89410A: Error, command not supported. ["%s"]\n',command); end end % commands else % catch incorrect address errors if verbose >= 1, fprintf('kpib/%s: ERROR: No instrument at GPIB %d\n',instrument,GPIB); end retval=0; end validInst = 1; end % end HP_89410A
'TEK_TDS' Tektronix oscilloscope
%RETVAL = KPIB('INSTRUMENT', GPIB, 'COMMAND', VALUE, CHANNEL, AUX, VERBOSE) % The Tektronix TDS family of oscilloscopes has many different members with % different features, but the essential programming commands appear to be % the same. Only two models have been tested against this code: TDS_540A, TDS_684B. % % In the comments, single value page numbers refer to the pdf available on % the Tektronix website, part no. 063-3002-00. Double-value page numbers % refer to part no. 070-8709-07. % % Valid instructions: % 'read' Returns a measurement of type VALUE from CHANNEL (default 1). % Measurement types are: % 'amplitude' the high value minus the low value. % 'frequency' the frequency of the signal. % 'peak2peak' absolute difference between maximum and minimum % values of the waveform. % 'rms' the root mean square voltage. % 'measure' Same as 'read'. % 'channel' select a channel (1-4) % 'display' either turn a channel display on/off, or VALUE=='query' to % return a binary word representing the state of the 4 % channels. % 'getdata' Downloads the complete waveform from the oscilloscope. % The data is returned in a structure: % retval.x % retval.y % retval.units.x % retval.units.y % if any(strcmpi(instrument, {'TEK_TDS' 'TDS_540'})) || strcmpi(instrument, 'all') io = port(GPIB, instrument, 50000, verbose); % buffer size for downloading data points if (io ~=0) && (strcmp(get(io,'Status'),'open') ~=0) switch command case {'label'} if isempty(value) % makes a big ugly box that covers half the screen, so % remove box is necessary fprintf(io,'MESSAGE:STATE OFF'); else fprintf(io,'MESSAGE:STATE ON'); fprintf(io,'MESSAGE:SHOW "%s"',value); end %pause(3) %fprintf(io,'MESSAGE:STATE OFF'); case {'read','measure'} if any(channel == [1 2 3 4]) if verbose >= 2, fprintf(1, 'kpib/TEK_TDS: Channel %d selected.\n',channel); end fprintf(io,'MEASU:IMM:SOURCE CH%d',channel); else % default to channel 1 if verbose >= 2, fprintf(1, 'kpib/TEK_TDS: Default channel is set to 1.\n'); end channel=1; fprintf(io,'MEASU:IMM:SOURCE CH1'); end switch value case {'amplitude','amp','ampl'} fprintf(io,'MEASU:IMM:TYP AMPL'); fprintf(io,'MEASU:IMM:VAL?'); retval.val = fscanf(io,'%f'); fprintf(io,'MEASU:IMM:UNI?'); retval.units = fscanf(io,'%s'); retval.units = retval.units(2:end-1); % strip quotes if verbose >= 2, fprintf(1, '%s %d %s %g %s\n', 'kpib/TEK_TDS: Channel:',channel,'Amplitude:',retval.val,retval.units); end case {'frequency','freq','f'} fprintf(io,'MEASU:IMM:TYP FREQ'); fprintf(io,'MEASU:IMM:VAL?'); retval.val = fscanf(io,'%f'); fprintf(io,'MEASU:IMM:UNI?'); retval.units = fscanf(io,'%s'); retval.units = retval.units(2:end-1); % strip quotes if verbose >= 2, fprintf(1, '%s %d %s %g %s\n', 'kpib/TEK_TDS: Channel:',channel,'Frequency:',retval.val,retval.units); end case {'peak2peak','p-p','vpp'} fprintf(io,'MEASU:IMM:TYP PK2'); fprintf(io,'MEASU:IMM:VAL?'); retval.val = fscanf(io,'%f'); fprintf(io,'MEASU:IMM:UNI?'); retval.units = fscanf(io,'%s'); retval.units = retval.units(2:end-1); % strip quotes if verbose >= 2, fprintf(1, '%s %d %s %g %s\n', 'kpib/TEK_TDS: Channel:',channel,'Peak2Peak:',retval.val,retval.units); end case {'rms','RMS'} fprintf(io,'MEASU:IMM:TYP RMS'); fprintf(io,'MEASU:IMM:VAL?'); retval.val = fscanf(io,'%f'); fprintf(io,'MEASU:IMM:UNI?'); retval.units = fscanf(io,'%s'); retval.units = retval.units(2:end-1); % strip quotes if verbose >= 2, fprintf(1, '%s %d %s %g %s\n', 'kpib/TEK_TDS: Channel:',channel,'RMS:',retval.val,retval.units); end otherwise if verbose >= 2, fprintf(1, 'kpib/TEK_TDS: No valid measurement type selected.\n'); end end case {'display','trace'} % either turn a channel display on/off, or return a binary word % (string) representing the state of the four displays switch value case {'on','ON'} fprintf(io, 'SELECT:CH%d ON',channel); if verbose >= 2, fprintf(1, 'kpib/TEK_TDS: Channel %d on.\n',channel); end case {'off','OFF'} fprintf(io, 'SELECT:CH%d OFF',channel); if verbose >= 2, fprintf(1, 'kpib/TEK_TDS: Channel %d off.\n',channel); end case {'query','?'} % returns 1 for on, 0 for off for each channel fprintf(io,'SELECT?'); % query the channel state (4 channels) ch = fscanf(io); dstate = sscanf(ch,'%d;%d;%d;%d;',4); for cd=1:4 dstateword(cd) = num2str(dstate(cd)); %#ok<AGROW> if dstate(cd)==1 && verbose >= 2, fprintf(1, 'kpib/TEK_TDS: Channel %d active.\n',cd); end retval=dstateword; end case {'active','active?'} fprintf(io,'SELECT?'); % query the channel state ch = fscanf(io); retval = sscanf(ch(23:end),'CH%d'); otherwise if verbose >= 2, fprintf(1, 'kpib/TEK_TDS: Error: ''display'' VALUE not understood.\n'); end end case {'channel'} % select a channel if any(channel == [1 2 3 4]) fprintf(io,'SELECT:CH%d ON',channel); % select a channel (manual p2-214) if verbose >= 2, fprintf(1, 'kpib/TEK_TDS: Channel %d selected.\n',channel); end end case 'getdata' if ~(any(channel == [1 2 3 4])) if verbose >= 2, fprintf(1, 'kpib/TEK_TDS: Default channel 1 selected.\n'); end channel=1; end if any(channel == [1 2 3 4]) fprintf(io,'SELECT:CH%d ON',channel); % make sure the channel is on, otherwise it hangs fprintf(io,'DAT:SOU CH%d',channel); % Specify which channel to read from. if verbose >= 2, fprintf(1, 'kpib/TEK_TDS: Channel %d selected.\n',channel); end fprintf(io,'DAT:ENC ASCI'); % determine what acquisition mode we are in fprintf(io,'ACQ:MODE?'); mode = fscanf(io); switch mode case {'SAMPLE','ENVELOPE','PEAKDETECT','SAM','ENVE','PEAK'} fprintf(io,'DAT:WID 1'); % 1 8-bit byte per point case {'HIRES','AVERAGE','AVE','HIR'} fprintf(io,'DAT:WID 2'); % 2 8-bit bytes per point end fprintf(io,'DAT:STAR 1'); % Sets the start point of the waveform to the first point of data. fprintf(io,'DAT:STOP 1000000'); % Sets the stop point of data transfer to the record length % by far exceeding any possible record length. fprintf(io,'WFMP:ENC ASC'); % ascii preamble fprintf(io,'WFMP:PT_F Y'); % Specifies the function used to get the correct waveform data. %fprintf(io,'WFMP:PT_OFF 1'); fprintf(io,'WFMP?'); preamble = fscanf(io); preamble = [preamble,';']; % Process the preamble % Preamble has several useful fields (manual p2-207 or p537): % {6} a text description of the waveform % {7} number of data points % {8} data format ('Y' or 'ENV') % {9} X units % {10} X increment % {11} X offset % {12} Y units % {13} Y multiplier % {14} Y offset % {15} Y zero % [BYT_Nr,BIT_Nr,encoding,BN_Fmt,BYT_Order,desc,... % numdatapoints,PT_Fmt,xunits,xincr,xoffset,yunits,ymult,yoffset,yzero]... % =strread(preamble,'%s','delimiter',';') pre=textscan(preamble,'%s','Delimiter',';'); pre=pre{1}; % cell array of cells not necessary if verbose >= 3 fprintf(1, 'kpib/TEK_TDS: Data preamble:\n'); for i=1:length(pre) fprintf(1, 'Field %2d: %s\n',i,pre{i}); end end % Read the data from the oscilloscope fprintf(io,'CURVE?'); data = fscanf(io); yval = sscanf([data,','],'%e,'); if verbose >= 2, fprintf(1, 'kpib/TEK_TDS: Data downloaded.\n'); end %size(yval) % Converts the necessary preamble values from strings into % numbers. numdatapoints = str2num(pre{7}); % The number of data points dformat = pre{8}; % envelope or normal xincr = str2double(pre{10}); % The x increment xoffset = str2double(pre{11}); %#ok<NASGU> % The x offset ("PT_off") % There appears to be a discrepancy in the programming % manual regarding the preamble fields- Field 12 % should be "YUnits", but in several instruments that % have been tested (TDS 684B, TDS 744A), there is an % extra field inserted at position 12 for some reason. % OTOH, some (TDS 540A) seem to be correct. % So, test field 12; if it is txt, consider it to be % units. If it is numeric, assume we are dealing with % the mystery extra field. if isnumeric(str2num(pre{12})) % extra field inserted if verbose >= 3, fprintf(1, 'kpib/TEK_TDS: Extra preamble field 12 found ("%s").\n',pre{12}); end field_offset=1; else if verbose >= 3, fprintf(1, 'kpib/TEK_TDS: Extra preamble field 12 not found.\n'); end field_offset=0; end ymult = str2double(pre{13+field_offset}); % The y multiplier ("YMUlt") yoffset = str2double(pre{14+field_offset}); % The y offset ("Y_OFf") yzero = str2double(pre{15+field_offset}); % The y zero ("YZEro") % get units retval.units.x = pre{9}(2:end-1); % strip quotes if strcmp(retval.units.x,'s'), retval.units.x='sec'; end retval.units.y = pre{12+field_offset}(2:end-1); % strip quotes retval.desc=pre{6}; % numdatapoints = str2num(numdatapoints); % The number of data points % xincr = str2double(xincr); % The x multiplier % xoffset = str2num(xoffset); % The x offset % ymult = str2double(ymult); % The y multiplier % yoffset = str2double(yoffset); % The y offset % yzero = str2double(yzero); % The y zero % Scale the data according the the values in the preamble. % See manual page 2-211 for scaling. Assumes "Y" % data format (preamble field #8) switch dformat case 'Y' retval.x=([0:1:numdatapoints-1]'*xincr); retval.y=((yval-yoffset).*ymult)+yzero; actualdatapoints = length(retval.y); if verbose >= 3, fprintf(1,'kpib/TEK_TDS: data format Y\n'); end case 'ENV' % retval.x=([0:1:numdatapoints-1]'*xincr); % retval.y=((yval-yoffset).*ymult)+yzero; % actualdatapoints = length(retval.y); if verbose >= 1 fprintf(1,'kpib/TEK_TDS: WARNING: data format ENV\n'); fprintf(1,' Not handled by this version of KPIB\n'); fprintf(1,' (use normal, not max/min data)\n'); end end if actualdatapoints~=numdatapoints if verbose >= 1 fprintf(1, 'kpib/TEK_TDS: WARNING: number of data points received from scope appears to be incorrect.\n'); fprintf(1, ' Expected: %d, Received: %d [Using Received]\n',numdatapoints,actualdatapoints); fprintf(1, ' (Try Reset GPIB with ''clear'' or check io.Buffersize)\n'); retval.y=retval.y(1:actualdatapoints); retval.x=retval.x(1:actualdatapoints); end end else if verbose >= 1, fprintf(1, 'kpib/TEK_TDS: Error: channel specified incorrectly.\n'); end retval=0; end otherwise if verbose >= 1, fprintf(1, 'kpib/TEK_TDS: Error, command not supported. ["%s"]\n',command); end retval=0; end else % catch incorrect address errors if verbose >= 1, fprintf('kpib/%s: ERROR: No instrument at GPIB %d\n',instrument,GPIB); end retval=0; end validInst = 1; end % end TEK_TDS
'HP_53132A' HP universal counter
%RETVAL = KPIB('INSTRUMENT', GPIB, 'COMMAND', VALUE, CHANNEL, AUX, VERBOSE) % This driver is focused on frequency measurements. If you want rise time, % phase, etc, then you are SOL. % Valid instructions: % 'init' Initializes the counter with settings designed for fastest % measurement data rate. Use 'frequency' or 'arm' to complete % the initialization for frequency measurement. % 'frequency' Configures the counter for a frequency measurement near % VALUE Hz with AUX resolution (in Hz) on channel CHANNEL. % The expected value should be within 10% of the input % frequency. The resolution should use a mantissa of 1.0 % and be an even power of 10 (i.e., "0.001"). The default % is 4 digits of resolution for all channels. The default % channel is channel 1. % 'channel' Select a channel for frequency measurement. % 'arm' Set the gating conditions: % 'digits' Gate time is adjusted to get AUX digits of % resolution % 'timer' Gate time is AUX seconds % 'auto' Gate time is automatically determined % 'armstart' Measurements begin on AUX ('ext' or 'imm') % external signal or internal (immediate) trigger. % 'set' Same as 'arm'. % Note that the gating is set by 'frequency' (above) for 'digits'. % 'read' Performs the measurement as configured and returns the % frequency value from the counter. Use CHANNEL to % select the counter channel. If CHANNEL is not specified, % the most recently used channel will be read. % 'getdata' Returns the data from the measurement in progress on the % current channel. This is much faster than 'read', which % restarts the measurement every time it is called. % 'run' Puts the counter in "free-run" mode (continuous measurement). % Also 'start'. % 'single' Initiate a single measurement. % 'stop' Stops measurements. Current measurement will be displayed % on counter. Use 'stop' to exit "free-run" mode before % initiating single measurements with 'single'. % % Note: fastest possible operation (returning measurement data) is usually % desired. This can be accomplished by using: % 'init' (to setup the counter) % 'frequency' (specifying expected frequency, resolution, and channel) % (continuous measurements will be started) % 'getdata' (to get the measurement result % (use 'getdata' in subsequent loops) % % Note that 'read','single' will take a single measurement and stop. % Subsequent 'getdata' commands will return the previous frequency reading. % Use 'run' to put the counter into continuous measurement mode % before resuming 'getdata' commands. Use 'channel' to switch channels % without doing measurements. % For 1.3 MHz measurements, 2 Hz data rate is just possible with 'getdata' % in a loop and gate time of 0.5 seconds. % % MH SEP2006 % if (strcmpi(instrument, 'HP_53132A') || strcmpi(instrument, 'all')) io = port(GPIB, instrument, 0, verbose); if (io ~=0) && (strcmp(get(io,'Status'),'open') ~=0) switch command case {'init','INIT'} % initialize for fastest data transfer. See manual p3-35 if verbose >= 1, fprintf(1, 'kpib/HP_53132A: Initializing for fastest measurements:\n'); end fprintf(io,'*RST'); pause(0.5); fprintf(io,'*CLS'); fprintf(io,':HCOPY:CONT OFF'); if verbose >= 1, fprintf(1, 'kpib/HP_53132A: Init: Hard Copy off\n'); end fprintf(io,':CALC:MATH:STATE OFF'); fprintf(io,':CALC2:LIMIT:STATE OFF'); fprintf(io,':CALC3:AVERAGE:STATE OFF'); if verbose >= 1, fprintf(1, 'kpib/HP_53132A: Init: Math off\n'); end fprintf(io,':FORMAT:DATA ASCII'); if verbose >= 1, fprintf(1, 'kpib/HP_53132A: Init: ACSII format data\n'); end fprintf(io,':ROSC:SOURCE INT'); fprintf(io,':ROSC:EXT:CHECK OFF'); if verbose >= 1, fprintf(1, 'kpib/HP_53132A: Init: Using Internal Reference Oscillator\n'); end fprintf(io,':SENSE:EVENT1:LEVEL:AUTO ON'); pause(1); % wait for auto level to pick a level fprintf(io,':SENSE:EVENT1:LEVEL?'); alevel = fscanf(io,'%f'); % what level did it pick? fprintf(io,':SENSE:EVENT1:LEVEL:AUTO OFF'); if verbose >= 1, fprintf(1, 'kpib/HP_53132A: Init: Auto trigger level off. Trigger level at %g V\n',alevel); end fprintf(io,':SENSE:FREQ:ARM:SOURCE IMM'); if verbose >= 1, fprintf(1, 'kpib/HP_53132A: Init: Start Arm is Immediate\n'); end fprintf(io,':INPUT1:IMPEDANCE 1M'); if verbose >= 1, fprintf(1, 'kpib/HP_53132A: Init: Ch. 1 input impedance 1M ohm\n'); end pause(1); % read current frequency (ch. 1), set target frequency for current reading cf = kpib(instrument,GPIB,'read',0,1,aux,verbose); fprintf(io,'CONF:FREQ %d,DEF',value); if verbose >= 1, fprintf(1, 'kpib/HP_53132A: Init: Target frequency set for %d Hz.\n',cf); end % set gate time to 0.5 seconds fprintf(io,'FREQ:ARM:STOP:SOURCE TIM'); fprintf(io,'FREQ:ARM:STOP:TIMER 0.5'); if verbose >= 1, fprintf(1, 'kpib/HP_53132A: Init: Gate Time set to 0.5 seconds.\n'); end %if verbose >= 1, fprintf(1, 'kpib/HP_53132A: Init: Use ''frequency'' to complete configuration.\n'); end case {'config','frequency','freq'} % set the counter for automatic frequency measurements % VALUE is expected frequency in Hz % CHANNEL is channel % AUX is resolution in Hz if channel ~= 0 && value ~= 0 && aux ~= 0 fprintf(io,'CONF:FREQ %d,%d,(@%d)',[value,aux,channel]); fprintf(io,':FREQ:EXPECTED%d %d',[channel,value]); if verbose >= 1 fprintf(1, 'kpib/HP_53132A: Configured for Frequency Measurement:\n at %g Hz, with %g Hz resolution, on Channel %d.\n',... value,aux,channel); end else if verbose >= 1, fprintf(1, 'kpib/HP_53132A: Configured for Frequency Measurement:\n '); end if value == 0 value = 'DEF'; if verbose >= 1, fprintf(1, 'at 10 MHz (default) '); end else if verbose >= 1, fprintf(1, 'at %g Hz ',value); end end if channel == 0 channel = 1; if verbose >= 1, fprintf(1, 'on Channel 1 (default) '); end else if verbose >= 1, fprintf(1, 'on Channel %d ',channel); end end if aux == 0 aux = 'DEF'; if verbose >= 1, fprintf(1, 'with default resolution (default)'); end else if verbose >= 1, fprintf(1, 'at default resolution '); end end cmd=sprintf('CONF:FREQ %s,%s',value,aux); fprintf(io,cmd); if verbose >= 1, fprintf(1, '\n'); end end % start the counter fprintf(io,'INIT:CONT ON'); case {'set','arm'} % set the arming type (aka "gate time") % digits, time, auto switch value case 'digits' fprintf(io,'FREQ:ARM:STOP:SOURCE DIG'); fprintf(io,'FREQ:ARM:STOP:DIGITS %d',aux); if verbose >= 1, fprintf(1, 'kpib/HP_53132A: Frequency measurement gating for %d digits resolution.\n',aux); end case {'time','timer','gatetime'} fprintf(io,'FREQ:ARM:STOP:SOURCE TIM'); fprintf(io,'FREQ:ARM:STOP:TIMER %d',aux); if verbose >= 1, fprintf(1, 'kpib/HP_53132A: Frequency measurement gating for %g seconds per measurement.\n',aux); end case {'armstart'} if isequal(aux,'imm') fprintf(io,'FREQ:ARM:SOURCE IMM'); if verbose >= 1, fprintf(1, 'kpib/HP_53132A: Frequency measurement gating continuously ("immediate").\n'); end elseif isequal(aux,'ext') fprintf(io,'FREQ:ARM:SOURCE EXT'); if verbose >= 1, fprintf(1, 'kpib/HP_53132A: Frequency measurement gating on external signal.\n'); end end case 'auto' fprintf(io,'FREQ:ARM:STOP:SOURCE IMM'); if verbose >= 1, fprintf(1, 'kpib/HP_53132A: Frequency measurement automatic gating.\n'); end otherwise if verbose >= 1, fprintf(1,'kpib/HP_53132A: Set VALUE not understood ("%s")\n',value); end end case {'channel','CHAN'} if any(channel==[1 2 3]) fprintf(io,'FUNC "FREQ %d"',channel); if verbose >= 2, fprintf(1,'kpib/HP_53132A: Select channel %d\n',channel); end else if verbose >= 2, fprintf(1,'kpib/HP_53132A: No channel selected.\n'); end end case 'read' % 'read' will do a frequency measurement. If VALUE is % 'single', the counter will stop taking measurements after it completes the 'read'. % If channel is specified, switch the channel first. Otherwise, % do not change the channel. % See Manual p4-89 for FUNC description. if any(channel==[1 2 3]) fprintf(io,'FUNC "FREQ %d"',channel); if verbose >= 2, fprintf(1,'kpib/HP_53132A: Select channel %d\n',channel); end end fprintf(io,':READ?'); retval = fscanf(io, '%f'); if ~(strcmp(value,'single')==1 || strcmp(value,'one')==1) % start the counter running again unless a single read % is requested fprintf(io,'INIT:CONT ON'); end if verbose >= 2, fprintf(1, '%s %.3f %s\n','kpib/HP_53132A: Frequency:',retval,'Hz'); end case {'single'} % initiate a single measurement. Use 'getdata' to get the % result. fprintf(io,':INIT:IMM'); if verbose >= 2, fprintf(1,'kpib/HP_53132A: Single measurement initiated\n'); end case {'stop','off'} % initiate a single measurement. Use 'getdata' to get the % result. fprintf(io,':INIT:CONT OFF'); if verbose >= 2, fprintf(1,'kpib/HP_53132A: Measurements stopped.\n'); end case {'getdata','fetch'} % 'getdata' will get the data from the current measurement. % Note that if the counter is not currently taking new % measurements (e.g. after a 'read'), then 'getdata' will % return old data. The commands 'frequency', 'read', and % 'run' will initiate continuous measurements. fprintf(io,':FETCH?'); retval = fscanf(io, '%f'); if verbose >= 2, fprintf(1,'kpib/HP_53132A: Frequency %f Hz\n',retval); end case {'run','free','go','start'} % put the counter to "free run" mode, taking measurements % continuously fprintf(io,'INIT:CONT ON'); if verbose >=2, fprintf(1, '%s\n','kpib/HP_53132A: Counter in Continuous Measurement mode.'); end otherwise if verbose >= 1, fprintf('kpib/HP_53132A: Error, command not supported. ["%s"]\n',command); end end else % catch incorrect address errors if verbose >= 1, fprintf('kpib/%s: ERROR: No instrument at GPIB %d\n',instrument,GPIB); end retval=0; end validInst = 1; end % end HP_53132A
'HP_33120A' Agilent Function Generator
%RETVAL = KPIB('INSTRUMENT', GPIB, 'COMMAND', VALUE, CHANNEL, AUX, VERBOSE) % Valid instructions: % % 'sin' / 'square' / 'triangle' / 'ramp' / 'noise' % These commands allow you to specify the complete settings for % an output waveform in one kpib command. The parameters % correspond to settings in the following way: % COMMAND = function ('sin'|'square'|'triangle'|'ramp') % VALUE = frequency (Hz) % CHANNEL = amplitude % AUX = offset (V) or units ('VPP'|'VRMS'|'DBM') (optional) % example: % kpib('HP_33120A',gpib_addr,'sin',5e6,5.5,0,verbose); % 'DC' DC output of VALUE volts % 'dcycle' Duty cycle for DC pulses % 'burst' Use Burst mode. Follow these steps: % 1) Select the desired waveform ('sin','square' etc.) with the % appropriate KPIB command. % 2) Configure burst mode: % COMMAND: 'burst' % VALUE: 'mode' % CHANNEL: select 'immediate', 'external', or 'bus' mode % AUX: number of cycles in each burst (1 - 50000) % 3) Enable burst mode: % COMMAND: 'burst' % VALUE: 'on' % 4) Trigger the burst. For immediate mode, the burst is triggered by the 'on' command. % For 'bus' (software triggering), use % COMMAND: 'burst' % VALUE: 'trigger' % 5) Disable burst mode: % COMMAND: 'burst' % VALUE: 'off' % 'setV' Set the output amplitude, in the current units (Vpp or Vrms) % 'read' Returns the current output amplitude in AUX units ('VPP'|'VRMS'|'DBM') % if (strcmpi(instrument, 'HP_33120A') || strcmpi(instrument, 'all')) io = port(GPIB, instrument, 0, verbose); if (io ~=0) && (strcmp(get(io,'Status'),'open') ~=0) if channel==0 && verbose >=1 fprintf(1, 'kpib/HP_33120A: WARNING: CHANNEL (output amplitude) is 0\n'); end switch command case 'init' fprintf(io,'*CLS'); case {'sin','sine','SIN'} if verbose >= 2, fprintf(1, 'kpib/HP_33120A: Sine wave: %g Hz, %g ',value,channel); end if any(strcmpi(aux,{'VPP','VRMS','DBM'})) cmd=sprintf('APPLY:SIN %d, %d %s',value,channel,upper(aux)); fprintf(io,cmd); if verbose >= 2, fprintf(1, '%s\n',aux); end %fprintf(io,'APPLY:SIN %d, %d, %d',[value,channel,aux]); else fprintf(io,'APPLY:SIN %d, %d, %d',[value,channel,aux]); if verbose >= 2, fprintf(1, 'V, %g V (offset)\n',aux); end end %if verbose >= 2, fprintf(1, 'kpib/HP_33120A: Sine wave: %g Hz %s\n',channel,value,aux); end case {'square','SQU'} if verbose >= 2, fprintf(1, 'kpib/HP_33120A: Square wave: %g Hz, %g ',value,channel); end if any(strcmpi(aux,{'VPP','VRMS','DBM'})) cmd=sprintf('APPLY:SQU %d, %d %s',value,channel,upper(aux)); fprintf(io,cmd); if verbose >= 2, fprintf(1, '%s\n',aux); end else fprintf(io,'APPLY:SQU %d, %d, %d',[value,channel,aux]); if verbose >= 2, fprintf(1, 'V, %g V (offset)\n',aux); end end case {'triangle','TRI'} if verbose >= 2, fprintf(1, 'kpib/HP_33120A: Triangle wave: %g Hz, %g ',value,channel); end if any(strcmpi(aux,{'VPP','VRMS','DBM'})) cmd=sprintf('APPLY:TRI %d, %d %s',value,channel,upper(aux)); fprintf(io,cmd); if verbose >= 2, fprintf(1, '%s\n',aux); end else fprintf(io,'APPLY:TRI %d, %d, %d',[value,channel,aux]); if verbose >= 2, fprintf(1, 'V, %g V (offset)\n',aux); end end case {'ramp','RAMP','saw'} if verbose >= 2, fprintf(1, 'kpib/HP_33120A: Ramp wave: %g Hz, %g ',value,channel); end if any(strcmpi(aux,{'VPP','VRMS','DBM'})) cmd=sprintf('APPLY:RAMP %d, %d %s',value,channel,upper(aux)); fprintf(io,cmd); if verbose >= 2, fprintf(1, '%s\n',aux); end else fprintf(io,'APPLY:RAMP %d, %d, %d',[value,channel,aux]); if verbose >= 2, fprintf(1, 'V, %g V (offset)\n',aux); end end case {'noise','NOISE'} if verbose >= 2, fprintf(1, 'kpib/HP_33120A: Noise: %g Hz, %g ',value,channel); end if any(strcmpi(aux,{'VPP','VRMS','DBM'})) cmd=sprintf('APPLY:NOISE %d, %d %s',value,channel,upper(aux)); fprintf(io,cmd); if verbose >= 2, fprintf(1, '%s\n',aux); end else fprintf(io,'APPLY:NOISE %d, %d, %d',[value,channel,aux]); if verbose >= 2, fprintf(1, 'V, %g V (offset)\n',aux); end end case 'DC' fprintf(io,'APPLY:DC DEF, DEF, %d',value); if verbose >= 2, fprintf(1, 'kpib/HP_33120A: DC voltage: %g V\n',value); end case 'burst' % set burst mode switch value case {'on','ON'} %fprintf(io,'BM:MODE TRIG'); fprintf(io,'BM:STATE ON'); if verbose >= 1, fprintf(1, 'kpib/HP_33120A: Burst mode enabled.\n'); end if verbose >= 2, fprintf(io,'FUNCTION?'); func=fscanf(io); fprintf(1, 'kpib/HP_33120A: Burst mode function: %s.\n',func); end case {'off','OFF'} fprintf(io,'BM:STATE OFF'); if verbose >= 2, fprintf(1, 'kpib/HP_33120A: Burst mode disabled\n'); end case {'mode','type'} switch channel case {'imm','immediate'} fprintf(io,'TRIGGER:SOURCE IMM'); if verbose >= 2, fprintf(1, 'kpib/HP_33120A: Burst mode trigger set to "immediate" (when burst ''on'')\n'); end case {'ext','external'} fprintf(io,'TRIGGER:SOURCE EXT'); if verbose >= 2, fprintf(1, 'kpib/HP_33120A: Burst mode trigger set to "external"\n'); end case {'bus','software','kpib'} fprintf(io,'TRIGGER:SOURCE BUS'); if verbose >= 2, fprintf(1, 'kpib/HP_33120A: Burst mode trigger set to "bus" (use ''burst'',''trigger'')\n'); end otherwise if verbose >= 1, fprintf(1, 'kpib/HP_33120A: Burst mode command (CHANNEL) not undestood.\n'); end end if isnumeric(aux) && aux > 0 fprintf(io,'BM:NCYCLES %d',aux); if verbose >= 2, fprintf(1, 'kpib/HP_33120A: Burst mode set for %d cycles.\n',aux); end else if verbose >= 1, fprintf(1, 'kpib/HP_33120A: Error: use AUX to specify number of cycles per burst (1 - 50e3).\n'); end end case {'trigger','now','start','trig'} fprintf(io,'*TRG'); % initiate a burst case 'phase' if isnumeric(channel) && channel >= 0 fprintf(io,'BM:PHASE %d',channel); if verbose >= 2, fprintf(1, 'kpib/AG_33120A: Burst mode set for %d degrees phase.\n',channel); end end otherwise if isnumeric(value) && value > 0 && value < 50e3 fprintf(io,'BM:NCYCLES %d',value); if verbose >= 2, fprintf(1, 'kpib/HP_33120A: Burst mode set for %d cycles.\n',aux); end end end case {'freq','frequency'} fprintf(io,'FREQ %d',value); if verbose >= 2, fprintf('kpib/HP_33120A: Output frequency set to %g Hz\n',value); end case {'amp','amplitude','setV','volt','VOLT'} % special case for setting output voltage fprintf(io,'VOLT %d',value); % sets the units of the current function (Vpp, Vrms, etc) if verbose >= 2, fprintf('kpib/HP_33120A: Output amplitude set to %g V\n',value); end case {'offset','dclevel'} fprintf(io,'VOLT:OFFSET %d',value); % in volts if verbose >= 2, fprintf('kpib/HP_33120A: Voltage offset (DC level) set to %g V\n',value); end case {'read'} % reading output voltage if any(strcmpi(aux,{'VPP','VRMS','DBM'})) fprintf(io,'VOLT:UNIT %s',aux); else fprintf(io,'VOLT:UNIT?'); aux = fscanf(io,'%s'); if ~strcmp(aux,'VPP') && verbose >=1 fprintf('kpib/HP_33120A: WARNING: units of %s, not Volts p-p. Use AUX to set units.\n',aux); end end fprintf(io,'VOLT?'); % reads the units of the current function (Vpp, Vrms, etc) retval = fscanf(io,'%e'); if verbose >= 2, fprintf('kpib/HP_33120A: Output amplitude reads %g %s\n',retval,aux); end %The duty cycle setting only applies to square waves. case {'dcycle','dutycycle','DCYC'} if isequal(value,'min') fprintf(io,'PULS:DCYC MIN'); elseif isequal(value,'max') fprintf(io,'PULS:DCYC MAX'); else fprintf(io,'PULS:DCYC %d',value); if verbose >= 2, fprintf('kpib/HP_33120A: Duty cycle set to %d%%\n',value); end end otherwise if verbose >= 1, fprintf('kpib/HP_33120A: Error, command not supported. ["%s"]\n',command); end end else % catch incorrect address errors if verbose >= 1, fprintf('kpib/%s: ERROR: No instrument at GPIB %d\n',instrument,GPIB); end retval=0; end validInst = 1; end % end HP_33120A
'AG_33250A' Agilent Function Generator
%RETVAL = KPIB('INSTRUMENT', GPIB, 'COMMAND', VALUE, CHANNEL, AUX, VERBOSE) % Valid instructions: % % 'sin' / 'square' / 'triangle' / 'ramp' / 'noise' % These commands allow you to specify the complete settings for % an output waveform in one kpib command. The parameters % correspond to settings in the following way: % COMMAND = function ('sin'|'square'|'triangle'|'ramp') % VALUE = frequency (Hz) % CHANNEL = amplitude % AUX = offset (V) or units ('VPP'|'VRMS'|'DBM') (optional) % example: % kpib('AG_33250A',gpib_addr,'sin',5e6,5.5,0,verbose); % 'noise' % 'DC' DC output of VALUE volts % 'dcycle' Duty cycle for DC pulses or square waves % 'freq' Set the output frequency to VALUE Hz % 'amp' Set the output amplitude to VALUE in units of AUX ('VPP'|'VRMS'|'DBM') % 'offset' Set the DC offset level. Also 'dclevel'. % 'setV' Same as 'amp'. Default to current units. % 'burst' Use Burst mode. Follow these steps: % 1) Select the desired waveform ('sin','square' etc.) with the % appropriate KPIB command. % 2) Configure burst mode: % COMMAND: 'burst' % VALUE: 'mode' % CHANNEL: select 'immediate', 'external', or 'bus' mode % AUX: number of cycles in each burst (1 - 1e6) % 3) Enable burst mode: % COMMAND: 'burst' % VALUE: 'on' % 4) Trigger the burst. For immediate mode, the burst is triggered by the 'on' command. % For 'bus' (software triggering), use % COMMAND: 'burst' % VALUE: 'trigger' % 5) Disable burst mode: % COMMAND: 'burst' % VALUE: 'off' % 'read' Returns the current output amplitude in AUX units ('VPP'|'VRMS'|'DBM') % 'on'|'off' Enable or disable the output. % if (strcmpi(instrument, 'AG_33250A') || strcmpi(instrument, 'HP_33250A') || strcmpi(instrument, 'all')) io = port(GPIB, instrument, 0, verbose); if (io ~=0) && (strcmp(get(io,'Status'),'open') ~=0) switch command case 'init' fprintf(io,'*CLS'); case {'sin','sine','SIN'} if channel==0 fprintf(1, 'kpib/AG_33250A: WARNING: Output amplitude (CHANNEL) is 0 V. No action performed.\n'); return end if verbose >= 2, fprintf(1, 'kpib/AG_33250A: Sine wave: %g Hz, %g ',value,channel); end if any(strcmpi(aux,{'VPP','VRMS','DBM'})) cmd=sprintf('APPLY:SIN %d, %d %s',value,channel,upper(aux)); fprintf(io,cmd); if verbose >= 2, fprintf(1, '%s\n',aux); end %fprintf(io,'APPLY:SIN %d, %d, %d',[value,channel,aux]); else fprintf(io,'APPLY:SIN %d, %d, %d',[value,channel,aux]); if verbose >= 2, fprintf(1, 'V amp, %g V offset\n',aux); end end %if verbose >= 2, fprintf(1, 'kpib/AG_33250A: Sine wave: %g Hz %s\n',channel,value,aux); end case {'square','SQU'} if channel==0 fprintf(1, 'kpib/AG_33250A: WARNING: Output amplitude (CHANNEL) is 0 V. No action performed.\n'); return end if verbose >= 2, fprintf(1, 'kpib/AG_33250A: Square wave: %g Hz, %g ',value,channel); end if any(strcmpi(aux,{'VPP','VRMS','DBM'})) cmd=sprintf('APPLY:SQU %d, %d %s',value,channel,upper(aux)); fprintf(io,cmd); if verbose >= 2, fprintf(1, '%s\n',aux); end else fprintf(io,'APPLY:SQU %d, %d, %d',[value,channel,aux]); if verbose >= 2, fprintf(1, 'V amp, %g V offset\n',aux); end end case {'triangle','TRI'} if channel==0 fprintf(1, 'kpib/AG_33250A: WARNING: Output amplitude (CHANNEL) is 0 V. No action performed.\n'); return end if verbose >= 2, fprintf(1, 'kpib/AG_33250A: Triangle wave: %g Hz, %g ',value,channel); end if any(strcmpi(aux,{'VPP','VRMS','DBM'})) cmd=sprintf('APPLY:TRI %d, %d %s',value,channel,upper(aux)); fprintf(io,cmd); if verbose >= 2, fprintf(1, '%s\n',aux); end else fprintf(io,'APPLY:TRI %d, %d, %d',[value,channel,aux]); if verbose >= 2, fprintf(1, 'V amp, %g V offset\n',aux); end end case {'ramp','RAMP','saw'} if channel==0 fprintf(1, 'kpib/AG_33250A: WARNING: Output amplitude (CHANNEL) is 0 V. No action performed.\n'); return end if verbose >= 2, fprintf(1, 'kpib/AG_33250A: Ramp wave: %g Hz, %g ',value,channel); end if any(strcmpi(aux,{'VPP','VRMS','DBM'})) cmd=sprintf('APPLY:RAMP %d, %d %s',value,channel,upper(aux)); fprintf(io,cmd); if verbose >= 2, fprintf(1, '%s\n',aux); end else fprintf(io,'APPLY:RAMP %d, %d, %d',[value,channel,aux]); if verbose >= 2, fprintf(1, 'V amp, %g V offset\n',aux); end end case {'noise','NOISE'} if channel==0 fprintf(1, 'kpib/AG_33250A: WARNING: Output amplitude (CHANNEL) is 0 V. No action performed.\n'); return end if verbose >= 2, fprintf(1, 'kpib/AG_33250A: Noise: %g Hz, %g ',value,channel); end if any(strcmpi(aux,{'VPP','VRMS','DBM'})) cmd=sprintf('APPLY:NOISE %d, %d %s',value,channel,upper(aux)); fprintf(io,cmd); if verbose >= 2, fprintf(1, '%s\n',aux); end else fprintf(io,'APPLY:NOISE %d, %d, %d',[value,channel,aux]); if verbose >= 2, fprintf(1, 'V amp, %g V offset\n',aux); end end case 'DC' fprintf(io,'APPLY:DC DEF, DEF, %d',value); if verbose >= 2, fprintf(1, 'kpib/AG_33250A: DC voltage output: %g V\n',value); end case 'burst' % set burst mode switch value case {'on','ON'} fprintf(io,'BURST:MODE TRIG'); fprintf(io,'BURST:STATE ON'); if verbose >= 1, fprintf(1, 'kpib/AG_33250A: Burst mode enabled.\n'); end if verbose >= 2, fprintf(io,'FUNCTION?'); func=fscanf(io); fprintf(1, 'kpib/AG_33250A: Burst mode function: %s.\n',func); end case {'off','OFF'} fprintf(io,'BURST:STATE OFF'); if verbose >= 2, fprintf(1, 'kpib/AG_33250A: Burst mode disabled\n'); end case {'mode','type'} switch channel case {'imm','immediate'} fprintf(io,'TRIGGER:SOURCE IMM'); if verbose >= 2, fprintf(1, 'kpib/AG_33250A: Burst mode trigger set to "immediate" (when burst ''on'')\n'); end case {'ext','external'} fprintf(io,'TRIGGER:SOURCE EXT'); if verbose >= 2, fprintf(1, 'kpib/AG_33250A: Burst mode trigger set to "external"\n'); end case {'bus','software','kpib'} fprintf(io,'TRIGGER:SOURCE BUS'); if verbose >= 2, fprintf(1, 'kpib/AG_33250A: Burst mode trigger set to "bus" (use ''burst'',''trigger'')\n'); end otherwise if verbose >= 1, fprintf(1, 'kpib/AG_33250A: Burst mode command (CHANNEL) not undestood.\n'); end end if isnumeric(aux) && aux > 0 fprintf(io,'BURST:NCYCLES %d',aux); if verbose >= 2, fprintf(1, 'kpib/AG_33250A: Burst mode set for %d cycles.\n',aux); end else if verbose >= 1, fprintf(1, 'kpib/AG_33250A: Error: use AUX to specify number of cycles per burst (1 - 1e6).\n'); end end case {'trigger','now','start','trig'} fprintf(io,'*TRG'); % initiate a burst case 'phase' if isnumeric(channel) && channel >= 0 fprintf(io,'BURST:PHASE %d',channel); if verbose >= 2, fprintf(1, 'kpib/AG_33250A: Burst mode set for %d degrees phase.\n',channel); end end otherwise if isnumeric(value) && value > 0 && value < 50e3 fprintf(io,'BURST:NCYCLES %d',value); if verbose >= 2, fprintf(1, 'kpib/HP_33250A: Burst mode set for %d cycles.\n',aux); end end end case {'freq','frequency'} fprintf(io,'FREQ %d',value); if verbose >= 2, fprintf('kpib/AG_33250A: Output frequency set to %g Hz\n',value); end case {'amp','amplitude','setV','volt','VOLT'} % special case for setting output voltage if any(strcmpi(aux,{'VPP','VRMS','DBM'})), fprintf(io,'VOLT:UNIT %s',aux); end fprintf(io,'VOLT %d',value); % sets the units of the current function (Vpp, Vrms, etc) if verbose >= 2, fprintf('kpib/AG_33250A: Output amplitude set to %g V\n',value); end case {'offset','dclevel'} fprintf(io,'VOLT:OFFSET %d',value); % in volts if verbose >= 2, fprintf('kpib/AG_33250A: Voltage offset (DC level) set to %g V\n',value); end case {'read'} % reading output voltage if any(strcmpi(aux,{'VPP','VRMS','DBM'})) fprintf(io,'VOLT:UNIT %s',aux); else fprintf(io,'VOLT:UNIT?'); aux = fscanf(io,'%s'); if ~strcmp(aux,'VPP') && verbose >=1 fprintf('kpib/AG_33250A: WARNING: units of %s, not Volts p-p. Use AUX to set units.\n',aux); end end fprintf(io,'VOLT?'); % reads the units of the current function (Vpp, Vrms, etc) retval = fscanf(io,'%e'); if verbose >= 2, fprintf('kpib/AG_33250A: Output amplitude reads %g %s\n',retval,aux); end %The duty cycle setting only applies to square waves. case {'dcycle','dutycycle','DCYC'} if isequal(value,'min') fprintf(io,'PULS:DCYC MIN'); elseif isequal(value,'max') fprintf(io,'PULS:DCYC MAX'); else fprintf(io,'PULS:DCYC %d',value); if verbose >= 2, fprintf('kpib/AG_33250A: Duty cycle set to %d%%\n',value); end end case {'off','OFF','stop','STOP'} fprintf(io, 'OUTPUT OFF'); % Disables output on selected channel. if verbose >= 2, fprintf(1, 'kpib/AG_33250A: Output off.\n'); end case {'on','ON','go','GO'} fprintf(io, 'OUTPUT ON'); % Disables output on selected channel. if verbose >= 2, fprintf(1, 'kpib/AG_33250A: Output on.\n'); end otherwise if verbose >= 1, fprintf('kpib/AG_33250A: Error, command not supported. ["%s"]\n',command); end end else % catch incorrect address errors if verbose >= 1, fprintf('kpib/%s: ERROR: No instrument at GPIB %d\n',instrument,GPIB); end retval=0; end validInst = 1; end % end AG_33250A
'SRS_DS345' Stanford Research Systems function generator
%RETVAL = KPIB('INSTRUMENT', GPIB, 'COMMAND', VALUE, CHANNEL, AUX, VERBOSE) % Valid commands: % % 'set' Sets VALUE ('function'|'frequency'|'amplitude'|'offset'|'phase') to CHANNEL. % For 'function', CHANNEL can be: 'sin','square,'triangle','ramp' % For 'frequency', CHANNEL is the output frequency in Hz. % For 'amplitude', CHANNEL can be Volts peak-peak, Volts RMS, or % dBm. You can specify the units with AUX ('vpp'|'rms'|'dbm'). % The default is Vpp. % For 'offset', CHANNEL is the offset in Volts. % For 'phase', CHANNEL is the phase offset in degrees. % % 'sin' / 'square' / 'triangle' / 'ramp' % These are combined forms of 'set', which allow you to specify the % first four parameters of 'set' in one kpib command. The inputs % correspond to settings in the following way: % COMMAND = function ('sin'|'square'|'triangle'|'ramp') % VALUE = frequency (Hz) % CHANNEL = amplitude (Vpp) % AUX = offset (V) % example: kpib('SRS_DS345',gpib_addr,'sin',5e6,5.5,0,verbose); % % 'read' Returns the current value of the parameter VALUE % ('freq'|'amp'|offset'|'phase') % % 'setV' Sets the output amplitude to VALUE in Volts RMS. % if (strcmpi(instrument, 'SRS_DS345') || strcmpi(instrument, 'all')) io = port(GPIB, instrument, 0, verbose); if (io ~=0) && (strcmp(get(io,'Status'),'open') ~=0) switch command case 'set' switch value case 'sin' fprintf(io,'FUNC0'); if verbose >= 2, fprintf(1, 'kpib/SRS_DS345: Function: Sine wave\n'); end case 'square' fprintf(io,'FUNC1'); if verbose >= 2, fprintf(1, 'kpib/SRS_DS345: Function: Square wave\n'); end case 'triangle' fprintf(io,'FUNC2'); if verbose >= 2, fprintf(1, 'kpib/SRS_DS345: Function: Triangle wave\n'); end case 'ramp' fprintf(io,'FUNC3'); if verbose >= 2, fprintf(1, 'kpib/SRS_DS345: Function: Ramp\n'); end case {'frequency', 'freq', 'f'} if isnumeric(channel) fprintf(io,'FREQ %d',channel); if verbose >= 2, fprintf(1, 'kpib/SRS_DS345: Frequency: %g Hz\n',channel); end else if verbose >= 0, fprintf(1, 'kpib/SRS_DS345: Error: Frequency incorrectly specified (must be a number)\n'); end end case {'amplitude', 'ampl', 'amp'} switch aux case {'vpp','VP','Vpp'} fprintf(io,'AMPL %dVP',channel); if verbose >= 2, fprintf(1, 'kpib/SRS_DS345: Amplitude: %.4f Vpp\n',channel); end case {'rms','VR','Vrms','RMS'} fprintf(io,'AMPL %dVR',channel); if verbose >= 2, fprintf(1, 'kpib/SRS_DS345: Amplitude: %.4f Vrms\n',channel); end case {'dBm','DB','Vdbm'} fprintf(io,'AMPL %dDB',channel); if verbose >= 2, fprintf(1, 'kpib/SRS_DS345: Amplitude: %.4f dBm\n',channel); end otherwise % default to Vrms fprintf(io,'AMPL %dVR',channel); if verbose >= 2, fprintf(1, 'kpib/SRS_DS345: Amplitude: %.4f Vrms (default units)\n',channel); end end case {'offset','offs'} if isnumeric(channel) fprintf(io,'OFFS %d',channel); if verbose >= 2, fprintf(1, 'kpib/SRS_DS345: Offset: %d V\n',channel); end else if verbose >= 0, fprintf(1, 'kpib/SRS_DS345: Error: Offset incorrectly specified (must be a number)\n'); end end case {'phase','phse'} if isnumeric(channel) fprintf(io,'PHSE %d',channel); if verbose >= 2, fprintf(1, 'kpib/SRS_DS345: Phase: %d deg\n',channel); end else if verbose >= 0, fprintf(1, 'kpib/SRS_DS345: Error: Phase incorrectly specified (must be a number)\n'); end end otherwise % default to amplitude if isnumeric(channel) fprintf(io,'AMPL %dVP',channel); if verbose >= 2, fprintf(1, 'kpib/SRS_DS345: Amplitude: %.4f Vpp (default units)\n',channel); end else if verbose >= 0, fprintf(1, 'kpib/SRS_DS345: Error: Amplitude incorrectly specified (must be a number)\n'); end end end case {'setV'} % special case for setting output voltage kpib(instrument,GPIB,'set','amplitude',value,'Vrms',verbose); case {'sin','sine'} fprintf(io,'FUNC0'); fprintf(io,'FREQ %d',value); if verbose >= 2, fprintf(1, 'kpib/SRS_DS345: Sine wave: Frequency: %.3f Hz',value); end fprintf(io,'AMPL %dVR',channel); if verbose >= 2, fprintf(1, ', Amplitude: %.4f Vrms',channel); end fprintf(io,'OFFS %d',aux); if verbose >= 2, fprintf(1, ', Offset: %d V',aux); end if verbose >= 2, fprintf(1, '\n'); end case 'square' fprintf(io,'FUNC1'); fprintf(io,'FREQ %d',value); if verbose >= 2, fprintf(1, 'kpib/SRS_DS345: Square wave: Frequency: %.3f Hz',value); end fprintf(io,'AMPL %dVP',channel); if verbose >= 2, fprintf(1, ', Amplitude: %.4f Vpp',channel); end fprintf(io,'OFFS %d',aux); if verbose >= 2, fprintf(1, ', Offset: %d V',aux); end if verbose >= 2, fprintf(1, '\n'); end case 'triangle' fprintf(io,'FUNC2'); fprintf(io,'FREQ %d',value); if verbose >= 2, fprintf(1, 'kpib/SRS_DS345: Triangle wave: Frequency: %.3f Hz',value); end fprintf(io,'AMPL %dVP',channel); if verbose >= 2, fprintf(1, ', Amplitude: %.4f Vpp',channel); end fprintf(io,'OFFS %d',aux); if verbose >= 2, fprintf(1, '\n'); end case 'ramp' fprintf(io,'FUNC3'); fprintf(io,'FREQ %d',value); if verbose >= 2, fprintf(1, 'kpib/SRS_DS345: Ramp wave: Frequency: %.3f Hz',value); end fprintf(io,'AMPL %dVP',channel); if verbose >= 2, fprintf(1, ', Amplitude: %.4f Vpp',channel); end fprintf(io,'OFFS %d',aux); if verbose >= 2, fprintf(1, ', Offset: %d V',aux); end if verbose >= 2, fprintf(1, '\n'); end case {'read','query'} switch value case {'freq','frequency','f'} fprintf(io,'FREQ?'); retval=fscanf(io,'%f'); if verbose >= 2, fprintf(1, 'kpib/SRS_DS345: Frequency set point: %g Hz\n',retval); end case {'ampl','amplitude','a'} switch channel % use CHANNEL to specify units case {'VP','Vpp','p-p'} fprintf(io,'AMPL? VP'); % specify volts peak-to-peak. case {'VR','Vrms','rms'} fprintf(io,'AMPL? VR'); % specify volts rms case {'DB','Vdb','db'} fprintf(io,'AMPL? DB'); % specify volts in decibels otherwise % default to Vpp fprintf(io,'AMPL? VP'); % specify volts peak-to-peak. end retstr=fscanf(io,'%s'); % value is returned as a string with units appended: VP, VR, DB retval.units=retstr(end-1:end); if ~isequal(channel,retval.units) if verbose >= 1, fprintf(1, 'kpib/SRS_DS345: Warning: Amplitude units error (%s/%s)\n',channel,retval.units); end end retval.val=str2num(retstr(1:end-2)); if verbose >= 2, fprintf(1, 'kpib/SRS_DS345: Amplitude set point: %.4f %s\n',retval.val,retval.units); end case {'offs','offset'} fprintf(io,'OFFS?'); % volts retval=fscanf(io,'%f'); if verbose >= 2, fprintf(1, 'kpib/SRS_DS345: Offset set point: %g V\n',retval); end case 'phase' fprintf(io,'PHSE?'); retval=fscanf(io,'%f'); if verbose >= 2, fprintf(1, 'kpib/SRS_DS345: Phase set point: %g deg\n',retval); end otherwise % default to amplitude Vrms fprintf(io,'AMPL? VR'); retval=fscanf(io,'%f'); if verbose >= 2, fprintf(1, 'kpib/SRS_DS345: Output Amplitude (default) set point: %f Vrms\n',retval); end end otherwise if verbose >= 1, fprintf(1, 'kpib/SRS_DS345: Error, command not supported. ["%s"]\n',command); end end else % catch incorrect address errors if verbose >= 1, fprintf('kpib/%s: ERROR: No instrument at GPIB %d\n',instrument,GPIB); end retval=0; end validInst = 1; end % end SRS_DS345
'HP_4395A' HP Network and Spectrum Analyzer
%RETVAL = KPIB('INSTRUMENT', GPIB, 'COMMAND', VALUE, CHANNEL, AUX, VERBOSE) % VALUE is typically the modifier to COMMAND. % Valid Commands: % 'init' Resets the Analyzer. % 'label' Writes 'VALUE' to the display. % 'channel' Makes channel VALUE the active channel. % 'meas' Set the measurement type. % VALUE can be: 'a/r', 'b/r', 'a', 'b', or 'r'. % 'display' Controls what is displayed on the Analyzer screen. % VALUE can be: 'data', 'memory','datamem', or 'dual'. % For 'dual', CHANNEL= 'on' or 'off', 'query', or '?'. % 'format' Set the format of the graph on the Analyzer display: % VALUE= 'linear','log mag','phase','delay','linear mag', etc. % 'scale' Sets the scale of the display. VALUE is the scale in the % current units, or 'VALUE' = 'auto' for autoscale command. % 'ref line' Sets the position of the reference line of the display. % VALUE is the position of the reference line in the current % units. % 'average' Turns averaging on or off, restarts averaging, or returns % the current number of averages taken. % VALUE= 'on','off','restart','query', or a number to set % number of measurements to average. % For 'query', RETVAL returns 0 (off) or the current number of averages (on). % 'mark2peak' Finds the peak and sets the marker, or finds the peak and % sets the peak location to the center of the scan. % VALUE='off','center', or 'peak'. % 'marker' Turns the marker on or off, or returns the current % position of the marker. 'VALUE' = 'on','off', or 'query'. % The position is returned as retval.x, retval.y in current % units. Also 'peak' to move marker to peak, or 'center' to % make marker value the center frequency. % 'center' Set the center frequency to VALUE. Units of Hz. % Query with VALUE = 'query', returns center frequency in Hz. % 'span' Set the frequency span VALUE. Units of Hz. % Query with VALUE = 'query', returns span in Hz. % 'sweep' Sets sweep parameters % 'source' Set the source (stimulus output) signal level. VALUE is the % desired signal level. Units of dBm. % Query with VALUE = 'query', returns source power in dBm. % 'source?' (Alternate query form) Returns source power in dBm. % 'power' Same as 'source'. % 'getdata' Download the current data trace from the analyzer. Data is % returned as two columns, x and y, for the specified % CHANNEL. Current channel if CHANNEL is not set. Returns: % retval.x % retval.y % retval.units.x % retval.units.y % 'units' Returns the units of the data from the analyzer. Must % specify VALUE = 'x' or 'y' axis units. % 'pause' Pauses measurement. % 'continue' Continues paused measurement. % 'complete' Wait for the previous sweep to complete. This command % contains a loop that does not exit until the status byte is % set. Use VALUE=='single' to do a single sweep and return % when the sweep is complete. % 'wait' Wait for the previous command to complete (*WAI) if (strcmpi(instrument, 'HP_4395A') || strcmpi(instrument, 'all')) io = port(GPIB, instrument, 64*4097, verbose); % buffer size 64*4097 if (io ~=0) && (strcmp(get(io,'Status'),'open') ~=0) switch command case 'init' %fprintf(io,'*RST'); fprintf(io,'CLES'); fprintf(io,'*SRE 4;ESNB 1'); % enable the registers; see manual p5-14 case 'label' if length(value) > 53 value=value(1:53); % 53 chars max end fprintf(io,'TITL "%s"',value); case 'channel' switch value case 1 fprintf(io,'CHAN1'); if verbose >=2, fprintf(1, 'kpib/HP_4395A: Channel %d selected.\n',value); end case 2 fprintf(io,'CHAN2'); if verbose >=2, fprintf(1, 'kpib/HP_4395A: Channel %d selected.\n',value); end otherwise % query active channel fprintf(io,'CHAN1?'); ch = fscanf(io); if ch == 1 if verbose >=2, fprintf(1, 'kpib/HP_4395A: Channel 1 active.\n'); end retval = 1; else retval = 2; if verbose >=2, fprintf(1, 'kpib/HP_4395A: Channel 2 active.\n'); end end end case 'meas' switch value case {'a/r','A/R','AR'} fprintf(io,'MEAS AR'); case {'b/r','B/R','BR'} fprintf(io,'MEAS BR'); case {'a','A'} fprintf(io,'MEAS A'); case {'b','B'} fprintf(io,'MEAS B'); case {'r','R'} fprintf(io,'MEAS R'); otherwise if verbose >= 1, fprintf(1, 'kpib/HP_4395A: Error, %s is not a valid input (a/r,b/r,a,b,r).',value); end end case {'display','trace'} switch value case {'data'} fprintf(io,'DISP %s',value); if verbose >= 2, fprintf(1, 'kpib/HP_4395A: Display data only\n'); end case {'memory','mem'} fprintf(io,'DISP MEMO'); if verbose >= 2, fprintf(1, 'kpib/HP_4395A: Display memory only\n'); end case {'both','data&memory','datamem','data+memory'} fprintf(io,'DISP DATM'); if verbose >= 2, fprintf(1, 'kpib/HP_4395A: Display data & memory\n'); end case {'dual'} switch channel case {'on',1} fprintf(io, 'DUAC ON'); if verbose >= 2, fprintf(1, 'kpib/HP_4395A: Dual-channel display on.\n'); end case {'off',0} fprintf(io, 'DUAC OFF'); if verbose >= 2, fprintf(1, 'kpib/HP_4395A: Dual-channel display off.\n'); end case {'query','?'} % returns 1 for dual-channel on, 0 for off fprintf(io, 'DUAC?'); dstatebit=str2num(fscanf(io)); if dstatebit==1, dstate='on'; elseif dstatebit==0, dstate='off'; end retval=dstatebit; if verbose >= 2, fprintf(1, 'kpib/HP_4395A: Dual-channel display is %s\n',dstate); end end case {'query','?'} % returns binary state for channels (emulate 4 channels) fprintf(io, 'DUAC?'); dstateb=str2num(fscanf(io)); % like dstatebits, only different if dstateb==1, dstate='1 1 0 0'; if verbose >= 2, fprintf(1, 'kpib/HP_4395A: Dual-channel display is on\n'); end % NB: fix this- query active channel? % Assume CH 1 until then elseif dstateb==0, dstate=[1 0]; end retval=dstate; % if verbose >= 2, fprintf(1, 'kpib/HP_4395A: Dual-channel display is %s\n',dstate); end end % % dstateword=[]; % for cd=1:4 % fprintf(io, 'DISP:WIND%d:TRAC:STATE?',cd); % dstateword(cd)=str2num(fscanf(io)); % if dstateword(cd)==1, dstate='on'; % elseif dstateword(cd)==0, dstate='off'; % end % if verbose >= 2, fprintf(1, 'kpib/HP_89410A: Trace %d is %s.\n',cd,dstate); end % retval(cd)=num2str(dstateword(cd)); % end % case {'on','ON'} % fprintf(io, 'DUAC ON'); % if verbose >= 2, fprintf(1, 'kpib/HP_4395A: Dual-channel display on.\n'); end % case {'off','OFF'} % fprintf(io, 'DUAC OFF'); % if verbose >= 2, fprintf(1, 'kpib/HP_4395A: Dual-channel display off.\n'); end % case {'query','?'} % returns 1 for dual-channel on, 0 for off % fprintf(io, 'DUAC?'); % dstatebit=str2num(fscanf(io)); % if dstatebit==1, dstate='on'; % elseif dstatebit==0, dstate='off'; % end % retval=dstatebit; % if verbose >= 2, fprintf(1, 'kpib/HP_4395A: Dual-channel display is %s\n',dstate); end % end case 'format' switch value case 'log mag' fprintf(io,'FMT LOGM'); case 'phase' fprintf(io,'FMT PHAS'); case 'delay' fprintf(io,'FMT DELA'); case 'linear mag' fprintf(io,'FMT LINM'); case 'polar' fprintf(io,'FMT POLA'); case 'admit smith' fprintf(io,'FMT ADMIT'); case 'spectrum' fprintf(io,'FMT SPECT'); case 'linear y' fprintf(io,'FMT LINY'); case 'complex' fprintf(io,'FMT COMP'); case 'exp phase' fprintf(io,'FMT EXPP'); case {'query','?'} fprintf(io,'FMT?'); retval=fscanf(io); otherwise fmttype={'swr','real','imag','smith','spec','noise','logy'}; if any(strcmpi(value,fmttype)) %if isequal(value,'swr') || isequal(value,'real') || isequal(value,'imag') || isequal(value,'smith') || isequal(value,'spect') || isequal(value,'noise') || isequal(value,'logy') fprintf(io,'FMT %s',value); else if verbose >= 1, fprintf(1, 'kpib/HP_4395A: Set Analyzer data format to default log magnitude.\n'); end fprintf(io,'FMT LOGM'); end end case {'autoscale','auto','autoy'}; % if nargin > 3 switch value case 'off' % DNE case 'once' if nargin > 4 if channel == 0 % autoscale current channel fprintf(io,'AUTO'); if verbose >=2, fprintf(1, 'kpib/HP_4395A: Autoscale current channel\n'); end else fprintf(io,'CHAN%d',channel); fprintf(io,'AUTO'); if verbose >=2, fprintf(1, 'kpib/HP_4395A: Autoscale channel %d\n',channel); end end else fprintf(io, 'DISP:TRAC:Y:AUTO ONCE'); if verbose >=2, fprintf(1, 'kpib/HP_4395A: Autoscale Y Once Channel 1 (default channel)\n'); end end case 'both' % specific to resonators - autoscale channels 1 & 2 fprintf(io,'CHAN1'); fprintf(io,'AUTO'); fprintf(io,'CHAN2'); fprintf(io,'AUTO'); fprintf(io,'CHAN1'); if verbose >=2, fprintf(1, 'kpib/HP_4395A: Autoscale channels 1 & 2\n'); end otherwise if isnumeric(value) && any(value == [1 2 3 4]) fprintf(io,'CHAN%d',channel); fprintf(io,'AUTO'); if verbose >=2, fprintf(1, 'kpib/HP_4395A: Autoscale channel %d\n',channel); end else fprintf(io,'AUTO'); if verbose >=2, fprintf(1, 'kpib/HP_4395A: Autoscale Y current channel (default)\n'); end end end % % else % fprintf(io, 'DISP:TRAC:Y:AUTO ONCE'); % if verbose >=2, fprintf(1, 'kpib/HP_4395A: Auto Scale Y default: Once\n'); end % end case 'scale' if isnumeric(value) fprintf(io,'SCAL %d',value); if verbose >= 2, fprintf(1, 'kpib/HP_4395A: Scale of current channel set to %d.\n',value); end elseif isequal(value,'auto') || isequal(value,'autoscale') fprintf(io,'AUTO'); if verbose >= 2, fprintf(1, 'kpib/HP_4395A: Autoscale current channel.\n'); end end case {'ref line','ref val','REFL','REFV'} fprintf(io,'REFV %d',value); if verbose >= 2, fprintf(1, 'kpib/HP_4395A: Reference value set to %g dBm.\n',value); end case 'average' switch value case {'on'} fprintf(io,'AVER ON'); if verbose >= 2, fprintf(1, 'kpib/HP_4395A: Measurement Averaging on'); end if isnumeric(channel) && channel > 0 fprintf(io,'AVERFACT %d',channel); if verbose >= 2, fprintf(1, ', aver. factor: %d\n',channel); end else if verbose >= 2, fprintf(1, '\n'); end end case {'off'} fprintf(io,'AVER OFF'); if verbose >= 2, fprintf(1, 'kpib/HP_4395A: Measurement Averaging off\n'); end case {'num','number','count'} % not available for 4395A? Use number of groups if verbose >= 2, fprintf(1, 'kpib/HP_4395A: Warning: Averaging Count not available for 4395A, use number of groups instead.\n'); end case {'restart','Restart'} fprintf(io,'AVERREST'); if verbose >=2, fprintf(1, 'kpib/HP_4395A: Restarting averaging\n'); end case {'query','?'} fprintf(io,'AVER?'); aver = fscanf(io); if aver == 0 retval = 0; if verbose >= 2, fprintf(1, 'kpib/HP_4395A: Averaging is off.'); end else fprintf(io,'AVERFACT?'); retval = fscanf(io); if verbose >= 2, fprintf(1, 'kpib/HP_4395A: Averaging is on; Averaging factor is: %d', retval); end end otherwise % set the number of measurements to average if isnumeric(value) && value > 0 fprintf(io,'AVERFACT %d',value); if verbose >=2, fprintf(1, 'kpib/HP_4395A: Averaging factor set to: %d\n',value); end else if verbose >= 2, fprintf(1, 'kpib/HP_4395A: Warning: Averaging command not understood ("%s")\n',value); end end end % if isequal(value,'on') | isequal(value,'off') % fprintf(io,'AVER %s',value); % if nargin > 4 % fprintf(io,'AVERFACT %d',channel); % % end % elseif isequal('restart') | isequal ('Restart') % fprintf(io,'AVERREST'); % else % fprintf(io,'AVER?'); % aver = fscanf(io); % if aver == 0 % retval = 0; % if verbose >= 2, fprintf(1, 'kpib/HP_4395A: Averaging is off.'); end % else % fprintf(io,'AVERFACT?'); % retval = fscanf(io); % if verbose >= 2, fprintf(1, 'kpib/HP_4395A: Averaging is on; Averaging factor is: %d', retval); end % end % end case {'marker'} % change the channel if specified (default do nothing) if (isnumeric(channel) && channel==(1 | 2)) fprintf(io,'CHAN%d',channel); end switch value case 'on' fprintf(io,'MKR ON'); if verbose >= 2, fprintf(1,'kpib/HP_4395A: Marker ON\n'); end case 'off' fprintf(io,'MKR OFF'); if verbose >= 2, fprintf(1,'kpib/HP_4395A: Marker OFF\n'); end case {'query','?'} % query the marker position fprintf(io,'OUTPMKR?'); mkr = fscanf(io); mkr = str2num(mkr); retval.y = mkr(1); retval.x = mkr(3); if verbose >= 2, fprintf(1,'kpib/HP_4395A: Marker on Channel %d position: %f/%f\n',channel,retval.x,retval.y); end case {'center','m2c','mark2center'} % make the marker position the center freq fprintf(io,'MKRCENT'); if verbose >= 2, fprintf(1,'kpib/HP_4395A: Marker to Center\n'); end case {'peak','searchpeak','mark2peak','max','m2p'} fprintf(io,'SEAM PEAK'); if verbose >= 2, fprintf(1,'%s\n','kpib/HP_4395A: Marker to Peak'); end otherwise if verbose >= 1, fprintf(1, 'kpib/HP_4395A: Error at ''marker'' command (VALUE incorrect ["%s"]).\n',value); end end case {'mark2peak','peaktrack'} switch value case 'off' if verbose >= 2, fprintf(1,'%s\n','kpib/HP_4395A: Marker Search Off'); end fprintf(io,'SEAM OFF'); case 'on' if verbose >= 2, fprintf(1,'%s\n','kpib/HP_4395A: Search Peak; Tracking on'); end fprintf(io,'SEAM PEAK'); fprintf(io,'TRACK ON'); case 'center' if verbose >= 2, fprintf(1,'%s\n','kpib/HP_4395A: Peak to Center'); end fprintf(io,'PEAKCENT'); case 'peak' if verbose >= 2, fprintf(1,'%s\n','kpib/HP_4395A: Marker to Peak'); end fprintf(io,'SEAM PEAK'); otherwise if verbose >= 2, fprintf(1,'%s\n','kpib/HP_4395A: Marker to Peak (default)'); end fprintf(io,'SEAM PEAK'); end case 'sweep' % enable the status registers for synchronization fprintf(io,'CLES'); % clear the status registers fprintf(io,'*SRE 4;ESNB 1'); % enable the registers; see manual p5-14 if isnumeric(value) % set the sweep time fprintf(io,'SWET %d',value); else switch value % set sweep type case {'on','off'} fprintf(io,'SWETAUTO %s',value); case {'linear freq','linfreq'} fprintf(io,'SWPT LINF'); case {'log freq','logf'} fprintf(io,'SWPT LOGF'); case {'list freq','freq list','list'} fprintf(io,'SWPT LIST'); case {'power','power sweep'} fprintf(io,'SWPT POWE'); case {'query','?'} fprintf(io,'SWPT?'); retval=fscanf(io,'%s'); % perform sweep action case {'single'} fprintf(io,'SING'); case {'continuous','cont'} fprintf(io,'CONT'); case {'hold'} fprintf(io,'HOLD'); case {'group','groups','number','N'} if isnumeric(channel) && channel >= 1 && channel <= 999 fprintf(io,'NUMG %d',channel); else if verbose >= 1, fprintf(1, 'kpib/HP_4395A: Sweep Number must be between 1 and 999.\n'); end end case {'setpoints','set'} if isnumeric(channel) && channel >= 2 && channel <= 801 fprintf(io,'POIN %i',channel); if verbose >= 2, fprintf(1, 'kpib/HP_4395A: Number of points set to %i.\n',channel); end else if verbose >= 1, fprintf(1, 'kpib/HP_4395A: Number must be between 2 and 801.\n'); end end otherwise if verbose >= 1, fprintf(1, 'kpib/HP_4395A: Sweep command not supported ["%s"]\n',num2str(value)); end end end % elseif isequal(value,'on') | isequal(value,'off') % fprintf(io,'SWETAUTO %s',value); % elseif isequal(value,'linear freq') % fprintf(io,'SWPT LINF'); % elseif isequal(value,'log freq') % fprintf(io,'SWPT LOGF'); % elseif isequal(value,'list freq') % fprintf(io,'SWPT LIST'); % elseif isequal(value,'power sweep') % fprintf(io,'SWPT POWE'); % % elseif strcmpi(value,'single') % fprintf(io,'SING'); % elseif strcmpi(value,'continuous') % fprintf(io,'CONT'); % elseif strcmpi(value,'hold') % fprintf(io,'HOLD'); % elseif strcmpi(value,'group') % if isnumeric(channel) & channel >= 1 & channel <= 999 % fprintf(io,'NUMG %d',channel); % else % if verbose >= 1, fprintf(1, 'kpib/HP_4395A: Sweep Number must be between 1 and 999.\n'); end % end % % elseif strcmpi(value,'setpoints') % if isnumeric(channel) & channel >= 2 & channel <= 801 % fprintf(io,'POIN %i',channel); % if verbose >= 2, fprintf(1, 'kpib/HP_4395A: Number of points set to %i.\n',channel); end % else % if verbose >= 1, fprintf(1, 'kpib/HP_4395A: Number must be between 2 and 801.\n'); end % end % else % if verbose >= 1, fprintf(1, 'kpib/HP_4395A: Sweep command not supported\n'); end % end case 'center' if isequal(value,'query') || isequal(value,'?') fprintf(io,'CENT?'); retval = fscanf(io,'%f'); if verbose >= 2, fprintf(1, 'kpib/HP_4395A: Center value is %g\n',retval); end else fprintf(io,'CENT %f',value); if verbose >= 2, fprintf(1, 'kpib/HP_4395A: Center set to %g\n',value); end end case 'span' if isequal(value,'query') || isequal(value,'?') fprintf(io,'SPAN?'); retval = fscanf(io,'%f'); if verbose >= 2, fprintf(1, 'kpib/HP_4395A: Span value is %g\n',retval); end else fprintf(io,'SPAN %f',value); if verbose >= 2, fprintf(1, 'kpib/HP_4395A: Span set to %g\n',value); end end case 'start' if isequal(value,'query') || isequal(value,'?') fprintf(io,'STAR?'); retval = fscanf(io,'%f'); if verbose >= 2, fprintf(1, 'kpib/HP_4395A: Start value is %g\n',retval); end else fprintf(io,'STAR %f',value); if verbose >= 2, fprintf(1, 'kpib/HP_4395A: Start set to %g\n',value); end end case 'stop' if isequal(value,'query') || isequal(value,'?') fprintf(io,'STOP?'); retval = fscanf(io,'%f'); if verbose >= 2, fprintf(1, 'kpib/HP_4395A: Stop value is %g\n',retval); end else fprintf(io,'STOP %f',value); if verbose >= 2, fprintf(1, 'kpib/HP_4395A: Stop set to %g\n',value); end end case {'power','source'} if isequal(value,'query') || isequal(value,'?') fprintf(io,'POWE?'); retval = fscanf(io,'%f'); elseif isnumeric(value) && value >= -50 && value <= 15 fprintf(io,'POWE %d',value); if verbose >= 2, fprintf(1, 'kpib/HP_4395A: Source Power set to %d dBm\n',value); end else if verbose >= 2, fprintf(1, 'kpib/HP_4395A: Source Power not set. Power must be between -50 and 15 dBm.\n'); end end case {'power?','source?'} fprintf(io,'POWE?'); retval.level = fscanf(io,'%f'); if verbose >= 2, fprintf(1, 'kpib/HP_4395A: Source Power: %g dBm\n',retval.level); end retval.state='on'; % 4395A source is always on case 'bandwidth' if isnumeric(value) fprintf(io,'BW %d',value); if verbose >= 2, fprintf(1, 'kpib/HP_4395A: Bandwidth set to %d Hz.\n',value); end elseif isequal(value,'auto') if isequal(channel,'on') || isequal(channel,'off') fprintf(io,'BWAUTO %s',channel); if verbose >= 2, fprintf(1, 'kpib/HP_4395A: Bandwidth set to auto.\n'); end end elseif isequal(value,'limit') if isnumeric(channel) fprintf(io,'BWLMT%d',channel); else if verbose >= 2, fprintf(1, 'kpib/HP_4395A: A numeric value must be entered for channel.\n'); end end end case 'trigger' switch value case 'internal' fprintf(io,'TRGS INT'); case 'external' fprintf(io,'TRGS EXT'); case 'GPIB' fprintf(io,'TRGS BUS'); case 'video' fprintf(io,'TRGS VID'); case 'manual' fprintf(io,'TRGS MAN'); case 'ext gate' fprintf(io,'TRGS GAT'); otherwise trgstype={'int','ext','vid','man','gat','bus'}; if any(strcmpi(value,trgstype)) %if isequal(value,'int') | isequal(value,'ext') | isequal(value,'vid') | isequal(value,'man') | isequal(value,'gat') | isequal(value,'bus') fprintf(io,'TRGS %s',value); else if verbose >= 1, fprintf(1, 'kpib/HP_4395A: Not a valid trigger.\n'); end end end case {'mode','type'} % set or get instrument mode % find out what mode the analyzer is in: % Network or Spectrum switch value case {'?','query'} fprintf(io,'NA?'); mode = fscanf(io,'%d'); if mode==1 mode='NA'; if verbose >= 2, fprintf('kpib/HP_4395A: Analyzer in Network mode.\n'); end retval=mode; else fprintf(io,'SA?'); mode = fscanf(io,'%d'); if mode==1 mode='SA'; if verbose >= 2, fprintf('kpib/HP_4395A: Analyzer in Spectrum mode.\n'); end retval=mode; end end case {'NA','network'} fprintf(io,'NA'); if verbose >= 2, fprintf('kpib/HP_4395A: Analyzer set to Network mode.\n'); end case {'SA','spectrum'} fprintf(io,'SA'); if verbose >= 2, fprintf('kpib/HP_4395A: Analyzer set to Spectrum mode.\n'); end otherwise if verbose >= 1, fprintf('kpib/HP_4395A: WARNING: ''mode'' command needs a VALUE parameter (e.g., ''?'').\n'); end retval=-1; end case 'getdata' % Select the channel. For compatibility with old code, the % channel is *not* set if it is not explicitly specified, i.e., % the default is to do nothing, rather than to select a channel. % first, find out what mode the analyzer is in: % Network or Spectrum mode=kpib(instrument,GPIB,'mode','query',channel,aux,verbose); % fprintf(io,'NA?'); % mode = fscanf(io,'%d'); % if mode==1 % mode='NA'; % if verbose >= 2, fprintf('kpib/HP_4395A: Analyzer in Network mode.\n'); end % else % fprintf(io,'SA?'); % mode = fscanf(io,'%d'); % if mode==1 % mode='SA'; % if verbose >= 2, fprintf('kpib/HP_4395A: Analyzer in Spectrum mode.\n'); end % end % end % now, did the user specify a channel or not? if isnumeric(channel) && any(channel == [1 2]) fprintf(io,'CHAN%d',channel); if verbose >= 2, fprintf('kpib/HP_4395A: Channel %d selected for data download.\n',channel); end else if verbose >= 2, fprintf('kpib/HP_4395A: Current channel for data download.\n'); end end % specify the data format as ASCII fprintf(io,'FORM4'); % download the data. The HP4395A only sends the Y values. fprintf(io,'OUTPDTRC?'); % rawdata = fscanf(io) % rawdata = [rawdata ',']; %rawdata = str2num(rawdata) retstr=fscanf(io,'%s'); retstr=[retstr ',']; %size(retstr) retdata=sscanf(retstr,'%f,'); actualnumpoints = size(retdata,1); if verbose >= 2, fprintf('kpib/HP_4395A: Data downloaded.\n'); end % X values are not provided, we have to infer them, so get % data about the frequency sweep fprintf(io,'POIN?'); numdatapoints = fscanf(io); numdatapoints = str2num(numdatapoints); % how many points did you say? if strcmp(mode,'NA') if (ceil(actualnumpoints/2) ~= numdatapoints) if verbose >= 1, fprintf(1, 'kpib/HP_4395A: WARNING: actual number of points downloaded (%d)\n',ceil(actualnumpoints/2)); fprintf(1,' does not equal expected number of points (%d).\n',numdatapoints); end numdatapoints = ceil(actualnumpoints/2); end elseif strcmp(mode,'SA') if (actualnumpoints ~= numdatapoints) if verbose >= 1, fprintf(1, 'kpib/HP_4395A: WARNING: actual number of points downloaded (%d)\n',actualnumpoints); fprintf(1,' does not equal expected number of points (%d).\n',numdatapoints); end numdatapoints = round(actualnumpoints); end end fprintf(io,'CENT?'); center = fscanf(io); center = str2num(center); fprintf(io,'SPAN?'); span = fscanf(io); span = str2num(span); start = center - span/2; data_end = center + span/2; delta = span/(numdatapoints-1); % we have to infer the x values, and we need to know what % type of sweep it is- log or linear? fprintf(io,'SWPT?'); stype=fscanf(io,'%s'); switch stype case {'LINF'} % linear, easy retval.x=([0:1:numdatapoints-1]*delta)'+start; if verbose >= 2, fprintf('kpib/HP_4395A: Frequency Sweep is %s.\n',stype); end retval.units.x = 'Hz'; case {'LOGF'} retval.x=logspace(log10(start),log10(data_end),numdatapoints)'; if verbose >= 2, fprintf('kpib/HP_4395A: Frequency Sweep is %s.\n',stype); end retval.units.x = 'log Hz'; otherwise retval.x=([0:1:numdatapoints-1]*delta)'+start; if verbose >= 2, fprintf('kpib/HP_4395A: WARNING: Freq. Sweep type not understood ["%s"]. Assuming linear.\n',stype); end end % handle Y values switch mode % the returned data is different for different modes case 'NA' % the real data is every other point in the returned array, % so the array has twice as many members as there are data points % (manual p O-10). Vectorize! % Return the data in columns %size(rawdata) %retval.x=([0:1:numdatapoints-1]*delta)'+start; retval.y=retdata([1:2:(numdatapoints)*2]); % determine the Y units % what format is this channel in? fprintf(io,'FMT?'); fmt=fscanf(io); fmt = fmt(1:end-1); % strip the trailing carriage return if strcmpi(fmt, 'LOGM') retval.units.y = 'dB'; elseif strcmpi(fmt, 'LINM') retval.units.y = 'U'; elseif strcmpi(fmt, 'PHAS') fprintf(io,'PHAU?'); rd = fscanf(io); retval.units.y = rd(1:end-1); % strip the trailing carriage return if strcmp(retval.units.y,'DEG')==1, retval.units.y='deg'; end else retval.units.y = '??'; end if verbose >= 2, fprintf('kpib/HP_4395A: Network Analyzer mode Y unit is %s.\n',retval.units.y); end case 'SA' % The spectrum analyzer returns only the data we are % interested in, no extraneous points % Return the data in columns %retval.x=([0:1:numdatapoints-1]*delta)'+start; retval.y=retdata; % determine the Y units fprintf(io,'SAUNIT?'); rd = fscanf(io); retval.units.y = rd(1:end-1); % strip the trailing carriage return if strcmp(retval.units.y,'DBM')==1, retval.units.y='dBm'; end if verbose >= 2, fprintf('kpib/HP_4395A: Spectrum Analyzer mode Y unit is %s.\n',retval.units.y); end end case 'units' if verbose >= 2, fprintf('kpib/HP_4395A: Get Units:\n'); end % now, did the user specify a channel or not? if isnumeric(channel) && any(channel == [1 2]) fprintf(io,'CHAN%d',channel); if verbose >= 2, fprintf('kpib/HP_4395A: Channel %d selected for data download.\n',channel); end else if verbose >= 2, fprintf('kpib/HP_4395A: Current channel for data download.\n'); end end switch value case {'x','X'} % either 'Hz' or 'log Hz' fprintf(io,'SWPT?'); stype=fscanf(io,'%s'); switch stype case {'LINF'} % linear, easy if verbose >= 2, fprintf('kpib/HP_4395A: Frequency Sweep is %s.\n',stype); end retval.units.x = 'Hz'; % X is always in Hz, as far as I know case {'LOGF'} if verbose >= 2, fprintf('kpib/HP_4395A: Frequency Sweep is %s.\n',stype); end retval.units.x = 'log Hz'; % X is always in Hz, as far as I know otherwise if verbose >= 2, fprintf('kpib/HP_4395A: WARNING: Freq. Sweep type not understood ["%s"]. Assuming linear.\n',stype); end retval.units.x = ''; end case {'y','Y'} % In Network Analyzer mode, the units depend on the format. % The units for Y phase could be either deg or rad % In Spectrum Analyzer mode, there is a single command. fprintf(io,'SA?'); mode=fscanf(io,'%d'); if mode==1 fprintf(io,'SAUNIT?'); retval = fscanf(io); retval = retval(1:end-1); % strip the trailing carriage return if strcmp(retval,'DBM')==1, retval='dBm'; end if verbose >= 2, fprintf('kpib/HP_4395A: Spectrum Analyzer mode Y unit is %s.\n',retval); end else % NA mode % what format is this channel in? fprintf(io,'FMT?'); fmt=fscanf(io); fmt = fmt(1:end-1); % strip the trailing carriage return if strcmpi(fmt, 'LOGM') retval = 'dB'; elseif strcmpi(fmt, 'LINM') retval = 'U'; elseif strcmpi(fmt, 'PHAS') fprintf(io,'PHAU?'); retval = fscanf(io); retval = retval(1:end-1); % strip the trailing carriage return if strcmp(retval,'DEG')==1, retval='deg'; end else retval = '??'; end if verbose >= 2, fprintf('kpib/HP_4395A: Network Analyzer mode Y unit is %s.\n',retval); end end otherwise % return both retval.x='Hz'; retval.y=kpib(instrument,GPIB,'units','y',0,0,verbose); end case 'pause' if isequal(value,'query') fprintf(io,'HOLD?'); retval = fscanf(io); else fprintf(io,'HOLD'); if verbose >= 2, fprintf('kpib/HP_4395A: Measurement paused.\n'); end end case {'continue','cont'} % continuous sweeping fprintf(io,'CONT'); if verbose >= 2, fprintf('kpib/HP_4395A: Measurement continue.\n'); end case 'complete' % complete uses the status registers to know when a sweep has % completed. This method only works for SINGLE and GROUP % sweeps, it does not work for continuous sweeps. If you try % to wait for the complete of a sweep in continuous mode, the % program will hang (you will wait forever). % The registers are enabled during the sweep command, above. %fprintf(io,'*SRE 4;ESNB 1'); % enable the registers; see manual p5-14 % can issue a single command for a sweep and complete % if nargin > 3 switch value case {'single','sing','SING'} % % enable the status registers for synchronization % fprintf(io,'CLES'); % clear the status registers % fprintf(io,'*SRE 4;ESNB 1'); % enable the registers; see manual p5-14 % fprintf(io,'SING'); kpib(instrument, GPIB, 'sweep', 'single', channel, aux, verbose); if verbose >= 2, fprintf('kpib/HP_4395A: Single Sweep & Complete\n'); end case {'group','groups','number','N'} kpib(instrument, GPIB, 'sweep', 'group', channel, aux, verbose); if verbose >= 2, fprintf('kpib/HP_4395A: Group Sweep (%d) & Complete\n',channel); end end % end % or just a single command if verbose >= 2, fprintf('kpib/HP_4395A: Waiting for sweep to complete...\n'); end warning off instrument:fscanf:unsuccessfulRead retval=0; while 1 pause(1); fprintf(io,'ESB?'); % check the status byte retval=str2num(fscanf(io,'%+f')); esb=dec2bin(retval); % return binary value represents the status registers if esb(end) == '1' % indicates sweep complete if verbose >= 2, fprintf(1, 'kpib/HP_4395A: Sweep complete.\n'); end break; end if length(esb) > 6 if esb(end-6) == '1' % indicates "Target not found" if verbose >= 2, fprintf(1, 'kpib/HP_4395A: Analyzer reports: "Target not Found".\n'); end end end end % disp('END OF ESB') case 'wait' % The *WAI command is only moderately useful on the 4395A. See % manual p4-4. fprintf(io,'*WAI'); % wait for previous commands to finish before executing new ones. retval = 1; otherwise if verbose >= 1, fprintf('kpib/HP_4395A: Error, command not supported. ["%s"]\n',command); end end else % catch incorrect address errors if verbose >= 1, fprintf('kpib/%s: ERROR: No instrument at GPIB %d\n',instrument,GPIB); end retval=0; end validInst = 1; end % end HP_4395A
'HP_34420A' HP nanovoltmeter
%RETVAL = KPIB('INSTRUMENT', GPIB, 'COMMAND', VALUE, CHANNEL, AUX, VERBOSE) % NOTE: This driver is focused temperature measurements; it assumes an RTD is % connected for a four-wire measurement. Support for other functions is % limited. % Valid instructions: % 'read' Trigger a measurement of type VALUE ('R'|'V'|'T') and return the result. % % 'config' Configures the multimeter for measurement VALUE ('temp') with a % 100-ohm platinum RTD. Once the instrument has been configured, % measurement results can be downloaded from the instrument in quick % succession using 'getdata'. Currently, only RTD measurements are % supported in kpib, but the principle is applicable to all of the % instrument's functions. % % 'getdata' Return the current measurement result. This is in contrast to the % 'read' command, which configures and triggers the measurement before % returning the result. As a result, 'getdata' is much faster than % 'read' for repeated measurements of the same quantity. % % 'sampleN' The instrument will make VALUE measurements (max 1024) and store them in % the instrument's internal memory before returning them. This allows % many measurements to be made quickly, in order to examine a high- % frequency event. % % Returned values: % For command 'read': % retval The temperature in deg C, as a %f number % if (strcmpi(instrument, 'HP_34420A') || strcmpi(instrument, 'all')) io = port(GPIB, instrument, 50000*16, verbose); % buffer size for downloading stored data if (io ~=0) && (strcmp(get(io,'Status'),'open') ~=0) switch command case 'config' switch value case {'temp','T','temperature','RTD'} fprintf(io,'CONF:TEMP FRTD,DEF,1,DEF'); if verbose >=2, fprintf(1,'kpib/HP_34420A: Configured for RTD measurement\n'); end otherwise if verbose >=2, fprintf(1,'kpib/HP_34420A: Error: only RTD (''temp'') supported for rapid measurement\n'); end end case 'read' switch value case {'ohm','ohms','R'} % CHANNEL is the measurement range in ohms %if channel == 100 | channel == 1000 | channel == 10000 | channel == 1000000 | channel == 10000000 if any(channel == [100 1000 10000 1000000 10000000]) if verbose >=2, fprintf(1,'%s %d\n','kpib/HP_34420A: Resistance measurement, range:',channel); end cmd = sprintf('MEAS:RES? %d,DEF', channel); % if a valid resolution has been specified, use it if aux >= 0.0001 if verbose >=2, fprintf(1,' %s %g %s\n','with resolution:', aux, 'ohms'); end cmd = sprintf('%s %d%s%d', 'MEAS:RES?', channel, ',', aux); %fprintf(io,'%s %d%s%d', 'MEAS:RES?', channel, ',', aux); end fprintf(io, cmd); else % if the specified range/resolution are not valid, then autorange if verbose >=2, fprintf(1,'%s\n','kpib/HP_34420A: Autorange resistance measurement'); end fprintf(io,'MEAS:RES? DEF,DEF'); end % read the value returned retval = fscanf(io,'%f'); if verbose >=2, fprintf(1,'%s %g %s\n','kpib/HP_34420A: Resistance Measurement:',retval,'ohms'); end case {'volt','volts','V'} % if a valid range has been specified, use it. CHANNEL % is the measurement range in volts if any(channel == [0.030 0.300 3 30 300]) if verbose >=2, fprintf(1,'%s %g %s\n','kpib/HP_34420A: Voltage measurement with range',channel,'volts'); end cmd = sprintf('MEAS:VOLT:DC? %d,DEF', channel); % if nargin > 5 % if a valid resolution has also been specified, use it if aux >= 0.00001 if verbose >=2, fprintf(1,' %s %g %s\n','and with resolution',aux,'volts'); end cmd=sprintf('MEAS:VOLT:DC? %d,%d', channel, aux); end % end % send the resulting command fprintf(io, cmd); else % if the specified range/resolution are not valid, then % autorange if verbose >=2, fprintf(1,'%s\n','kpib/HP_34420A: Autorange voltage measurement (invalid options specified)'); end fprintf(io,'MEAS:VOLT:DC? DEF,DEF'); end % read the value returned retval = fscanf(io,'%f'); if verbose >=2, fprintf(1,'%s %f %s\n','kpib/HP_34420A: Voltage Measurement:',retval,'volts'); end case {'temp','temperature','T'} fprintf(io,'MEAS:TEMP? FRTD'); retval=fscanf(io,'%f'); if verbose >=2, fprintf(1, '%s %.3f %s\n','kpib/HP_34420A: RTD Temperature:',retval,'C'); end otherwise % default to RTD fprintf(io,'MEAS:TEMP? FRTD'); retval=fscanf(io,'%f'); if verbose >=2, fprintf(1, '%s %.3f %s\n','kpib/HP_34420A: RTD Temperature (default):',retval,'C'); end end case 'sampleN' if value > 1024 if verbose >=1, fprintf(1,'kpib/HP_34420A: Warning: maximum number of readings is 1024.'); end else fprintf(io,'CONF:TEMP FRTD,DEF'); if channel > 0 fprintf(io,'TEMP:NPLC %d',channel); else channel = 0; end % fprintf(io,'*CLS'); % fprintf(io,'*SRE 32'); fprintf(io,'SAMPLE:COUNT %d',value); fprintf(io,'TRIG:SOURCE IMM'); fprintf(io,'INITIATE'); %fprintf(io,'*OPC'); %fprintf(io,'READ?'); %pause(value*channel/300+1); fprintf(io,'FETCH?'); %retval=fscanf(io,'%f,') % The data is returned as a single giant comma-delimited string % for some reason. Append a comma to the end so that we can use % a '%f,' format to read it without any warnings. % retopc=0 % while retopc < 32 % fprintf(io,'*STB?'); retopc=fscanf(io,'%f') % end retstr=fscanf(io,'%s'); retstr=[retstr ',']; retval=sscanf(retstr,'%f,'); fprintf(io,'SAMPLE:COUNT 1'); % reset the sample count fprintf(io,'TEMP:NPLC 10'); % reset NPLC setting end case 'getdata' fprintf(io,'READ?'); retval=fscanf(io,'%f'); if verbose >=2, fprintf(1, 'kpib/HP_34420A: Measurement: %.3f \n',retval); end otherwise if verbose >= 1, fprintf(1, 'kpib/HP_34420A: Error, command not supported. ["%s"]\n',command); end end else % catch incorrect address errors if verbose >= 1, fprintf('kpib/%s: ERROR: No instrument at GPIB %d\n',instrument,GPIB); end retval=0; end validInst = 1; end % end HP_34420A
'KTH_236' Keithley 236/237/238 Source Measure Unit
%RETVAL = KPIB('INSTRUMENT', GPIB, 'COMMAND', VALUE, CHANNEL, AUX, VERBOSE) % This driver focuses on using the Keithley as a precision DC sourcemeter. % Sweep commands are not implemented at this time. % Valid commands: % 'init' Initialize the instrument and select VALUE source mode. It is % strongly recommended that you use the 'init' command when working % with the KTH_236. VALUE ('V' or 'I') sets source mode (optional). % Defaults to voltage source. AUX ('local' | 'remote') sets the % sensing mode. Default is 'local'. % 'mode' Set the source mode to VALUE ('V' | 'I') % 'read' Trigger a measurement and return the result VALUE ('volt' | 'curr'). % If VALUE is not specified, returns %f structure: % retval.volt % retval.curr % 'set' Sets the Voltage or Current (depending on instrument's mode) % output to VALUE. The mode must be already set correctly, % either by the 'init' command or by the 'mode' command. Use 'setV' % or 'setI' to explicitly set the output mode (note this will be % slower than 'set'). Use CHANNEL (0:1:10) to set the output range. % Default is 0 (auto range). Use AUX to set the delay in output % change in ms. Default is 0 ms. % 'on' Enables output. % 'off' Disables output. % % Note: If the KTH_236 "freezes up" during GPIB use, check the Trigger % status on the front panel. If the trigger light is blinking, you may be % set for manual trigger, and nothing will happen until you push the % trigger button. Set the trigger to "IEEE X" (when 'X' is sent on gpib). % See manual p3-59. The wake-up factory default is manual. the 'init' % command sets the trigger correctly. % Also, the KTH_236 seems to have a problem with the 'read' command- it will % freeze up at certain times for no apparent reason. If you can figure out % why, please let me know! MH v3.2 % I updated this code in version 4.92 based on testing with a KTH_238. % Please let me kow if you have a better or worse experience with a 236 or % 237. MH v4.92 % if any(strcmpi(instrument, {'KTH_236','KTH_237','KTH_238'})) || strcmpi(instrument, 'all') io = port(GPIB, instrument, 0, verbose); if (io ~=0) && (strcmp(get(io,'Status'),'open') ~=0) switch command case 'init' if verbose >=2 % get instrument info fprintf(io,'U0X'); % does not work? mdl=fscanf(io,'%s'); fprintf(1,'kpib/%s: Model & firmware: %s\n',instrument,mdl); end %fprintf(io,'Y3X\r'); % set terminator character to LF fprintf(io,'T0,0,0,0X'); %SET TRIGGER TO GPIB (manual p3-59) % set instrument mode switch value case {'voltage','volt','V'} kth_msrc='V'; case {'current','amps','A','I'} kth_msrc='I'; otherwise %fprintf(io,'J0X'); % Reset to factory defaults % default to Voltage source kth_msrc='V'; if verbose >=2, fprintf(1,'kpib/%s: Initialize as Voltage Source (Default)\n',instrument); end end kpib(instrument,GPIB,'mode',kth_msrc,channel,aux,verbose); % standby and zero output kpib(instrument,GPIB,'off',value,channel,aux,verbose); % Local sense is the default setting if strcmpi(aux,'remote') fprintf(io,'O1X'); % set remote sense function ("Oh one") else fprintf(io,'O0X'); % set local sense function ("Oh zero") end % display init message fprintf(io,'D1,KPIB INITIALIZED %sX',kth_msrc); %18 char max pause(2) fprintf(io,'D0X'); case {'mode'} switch value case {'voltage','volt','V'} fprintf(io,'F0,0X'); % Function source voltage and measure current if verbose >=2, fprintf(1,'kpib/%s: Set mode Voltage Source/Current Measure\n',instrument); end case {'current','amps','A','I'} fprintf(io,'F1,0X'); % Function source current and measure voltage if verbose >=2, fprintf(1,'kpib/%s: Set mode Current Source/Voltage Measure\n',instrument); end otherwise if verbose >=1, fprintf(1,'kpib/%s: WARNING ''mode'' VALUE not understood ["%s"]\n',instrument,value); end end case 'read' % Get instrument status string which contains the current readings. % See manual p3-28 fprintf(io,'G5,0,0X'); % "return source and measure as ASCII string with suffix and prefix" kth=fscanf(io,'%s'); if verbose >=3, fprintf(1,'kpib/%s: %s\n',instrument,kth); end % The instrument returns its status as a string that we have to % parse. See manual p3-29. line_pos=find(kth==','); % the string is comma-delimited source=kth(1:line_pos(1)-1); sstate=sscanf(source,'%5s,',1); if length(line_pos) >= 2 measure=kth(line_pos(1)+1:line_pos(2)-1); mstate=sscanf(measure,'%5s,',1); else mstate='XXXXX'; end if sstate(5)=='V' kvolt=sscanf(source,[sstate '%e'],1); if verbose >=2, fprintf(1, 'kpib/%s: Source: %.4f V',instrument,kvolt); end if mstate(5)=='I' kcurr=sscanf(measure,[mstate '%e'],1); if verbose >=2, fprintf(1, ', Measure %.4f I\n',kcurr); end else kcurr=1776; if verbose >=2, fprintf(1, '\n'); end end elseif sstate(5)=='I' kcurr=sscanf(source,[sstate '%e'],1); if verbose >=2, fprintf(1, 'kpib/%s: Source: %.4f I',instrument,kcurr); end if mstate(5)=='V' kvolt=sscanf(measure,[mstate '%e'],1); if verbose >=2, fprintf(1, ', Measure %.4f V\n',kvolt); end else kvolt=1776; if verbose >=2, fprintf(1, '\n'); end end end switch value case {'volt','volts','V','v'} retval=kvolt; case {'curr','current','I','i'} retval=kcurr; otherwise retval.volt=kvolt; retval.curr=kcurr; end % the first character of the status prefix is "N" for normal or "O" for overload if sstate(1) == 'O' if verbose >=1, fprintf(1, 'kpib/%s: Source overload condition reported\n',instrument); end end if mstate(1) == 'O' if verbose >=1, fprintf(1, 'kpib/%s: Measure overload condition reported\n',instrument); end end case {'readV'} kpib(instrument,GPIB,'read','V',channel,aux,verbose); case {'readI'} kpib(instrument,GPIB,'read','I',channel,aux,verbose); case {'set'} if ~isnumeric(channel), channel=0; end % CHANNEL is range setting if ~isnumeric(aux), aux=0; end % AUX is delay value in ms % just set the output, assume user has set the desired mode cmd=sprintf('B%f,%d,%dX',value,channel,aux); if verbose >=3, fprintf(1,'%s\n',cmd); end fprintf(io,cmd); if verbose >=2, fprintf(1,'kpib/%s: Output set to %g\n',instrument,value); end case {'setV'} if ~isnumeric(channel), channel=0; end % CHANNEL is range setting if ~isnumeric(aux), aux=0; end % AUX is delay value in ms % first, explicitly set the mode to current source kpib(instrument,GPIB,'mode','V',channel,aux,verbose); cmd=sprintf('B%f,%d,%dX',value,channel,aux); if verbose >=3, fprintf(1,'%s\n',cmd); end fprintf(io,cmd); if verbose >=2, fprintf(1, 'kpib/%s: Voltage output set to: %g V\n',instrument,value); end case {'setI'} if ~isnumeric(channel), channel=0; end % CHANNEL is range setting if ~isnumeric(aux), aux=0; end % AUX is delay value in ms % first, explicitly set the mode to current source kpib(instrument,GPIB,'mode','I',channel,aux,verbose); cmd=sprintf('B%f,%d,%dX',value,channel,aux); if verbose >=3, fprintf(1,'%s\n',cmd); end fprintf(io,cmd); if verbose >=2, fprintf(1, 'kpib/%s: Current output set to: %f A\n',instrument,value); end case 'on' fprintf(io,'N1X'); if verbose >=2, fprintf(1, '%s\n','kpib/%s: Output enabled',instrument); end case 'off' fprintf(io,'B0,0,0X'); % set output to zero before disabling (manual p3-20) fprintf(io,'N0X'); if verbose >=2, fprintf(1, '%s\n','kpib/%s: Output disabled',instrument); end otherwise if verbose >= 1, fprintf(1, 'kpib/%s: Error, command not supported. ["%s"]\n',instrument,command); end end else % catch incorrect address errors if verbose >= 1, fprintf('kpib/%s: ERROR: No instrument at GPIB %d\n',instrument,GPIB); end retval=0; end validInst = 1; end % end KTH_236
'HP_8753ES' HP S-Parameter Network Analyzer
%RETVAL = KPIB('INSTRUMENT', GPIB, 'COMMAND', VALUE, CHANNEL, AUX, VERBOSE) % Valid Commands: % 'init' Resets the Analyzer. % 'label' Writes 'VALUE' to the display. NOTE: may work intermittently. % 'channel' Makes channel VALUE the active channel. % 'meas' Set the measurement type. % VALUE can be: 'a/r', 'b/r', 'a', 'b', or 'r'. % 'display' Controls what is displayed on the Analyzer screen. % VALUE can be: 'data', 'memory', or 'datamem'. VALUE can also % be 'on' or 'off' to turn on or off dual display mode, or % 'query' for status of dual display mode. % 'format' Set the format of the graph on the Analyzer display: % Linear, log/mag, etc. non-exponentially ('norm'). % Exponentially is the default. % 'scale' Sets the scale of the display. VALUE is the scale in the % current units, or 'VALUE' = 'auto' for autoscale command. % 'ref line' Sets the position of the reference line of the display. % VALUE is the position of the reference line in the current % units. % 'average' Turns averaging on or off, restarts averaging, or returns % the current number of averages taken. % VALUE='on','off','restart', or 'query'. For 'query', RETVAL % returns 0 (off) or the current number of averages (on). % 'mark2peak' Finds the peak and sets the marker, or finds the peak and % sets the peak location to the center of the scan. % VALUE='off','center', or 'peak'. % 'marker' Turns the marker on or off, or returns the current % position of the marker. 'VALUE' = 'on','off', or 'query'. % The position is returned as retval.x, retval.y in current % units. % 'center' Set the center frequency to VALUE. Units of Hz. % Query with VALUE = 'query', returns center frequency in Hz. % 'span' Set the frequency span VALUE. Units of Hz. % Query with VALUE = 'query', returns span in Hz. % 'sweep' Sets sweep parameters % 'source' Set the source (stimulus output) signal level. VALUE is the % desired signal level. Units of dBm. Query with VALUE = % 'query', returns source power in dBm. % 'source?' (Alternate query form) Returns source power in dBm. % 'power' Same as 'source'. % 'getdata' Download the current data trace from the analyzer. Data is % returned as two columns, x and y, for the specified CHANNEL. % Default CHANNEL is not set. If VALUE is 'x' or 'y', only % that data is returned in a single column. % 'units' Returns the units of the data from the analyzer. Must % specify VALUE = 'x' or 'y' axis units. % 'pause' Pauses measurement. 'continue' Continues paused measurement. % 'complete' Wait for the previous sweep to complete. This command % contains a loop that does not exit until the status byte % shows % 'wait' Wait for the previous command to complete (*WAI) if (strcmpi(instrument, 'HP_8753ES') || strcmpi(instrument, 'all')) io = port(GPIB, instrument, 0, verbose); if (io ~=0) && (strcmp(get(io,'Status'),'open') ~=0) switch command case 'init' %ok %fprintf(io,'*RST'); fprintf(io,'CLES'); case {'label','title'} %ok if length(value) > 53 value=value(1:53); % 53 chars max end fprintf(io,'TITL "%s"',value); case 'channel' %ok if channel==0 && any(value==[1 2 3 4]) channel=value; end if any(channel==[1 2 3 4]) fprintf(io,'CHAN%d',channel); if verbose >=2, fprintf(1, 'kpib/HP_8753ES: Channel %d selected.\n',channel); end else if verbose >=2, fprintf(1, 'kpib/HP_8753ES: Warning: Channel select error (must be 1-4).\n'); end end case 'meas' %ok switch value case {'a/r','A/R','AR'} fprintf(io,'AR'); case {'b/r','B/R','BR'} fprintf(io,'BR'); case {'r','R','MEASR'} fprintf(io,'MEASR'); case {'a','A','MEASA'} fprintf(io,'MEASA'); case {'b','B','MEASB'} fprintf(io,'MEASB'); otherwise if verbose >= 1, fprintf(1, 'kpib/HP_8753ES: Error, %s is not a valid input (a/r,b/r,A,B,R).\n',value); end end if verbose >= 2, fprintf(1, 'kpib/HP_8753ES: Measurement set to %s.\n',value); end case {'display','trace'} %ok switch value case {'data'} fprintf(io,'DISPDATA'); if verbose >= 2, fprintf(1, 'kpib/HP_8753ES: Display data only\n'); end case {'memory','mem'} fprintf(io,'DISPMEMO'); if verbose >= 2, fprintf(1, 'kpib/HP_8753ES: Display memory only\n'); end case {'both','data&memory','datamem','data+memory'} fprintf(io,'DISPDATM'); if verbose >= 2, fprintf(1, 'kpib/HP_8753ES: Display data & memory\n'); end case {'dual'} %ok switch channel case {'on',1} fprintf(io, 'DUACON'); if verbose >= 2, fprintf(1, 'kpib/HP_8753ES: Dual-channel display on.\n'); end case {'off',0} fprintf(io, 'DUACOFF'); if verbose >= 2, fprintf(1, 'kpib/HP_8753ES: Dual-channel display off.\n'); end case {'query','?'} % returns 1 for dual-channel on, 0 for off fprintf(io, 'DUAC?'); dstatebit=str2num(fscanf(io)); if dstatebit==1, dstate='on'; elseif dstatebit==0, dstate='off'; end retval=dstatebit; if verbose >= 2, fprintf(1, 'kpib/HP_8753ES: Dual-channel display is %s\n',dstate); end end case {'on',1} fprintf(io,'BLADOFF'); if verbose >= 2, fprintf(1, 'kpib/HP_8753ES: Screen on\n'); end case {'off',0} fprintf(io,'BLADON'); if verbose >= 2, fprintf(1, 'kpib/HP_8753ES: Screen off\n'); end case {'query','?'} % returns binary state for channels (emulate 4 channels) fprintf(io, 'DUAC?'); dstateb=str2num(fscanf(io)); if dstateb==1, dstate='1 1 0 0'; if verbose >= 2, fprintf(1, 'kpib/HP_8753ES: Dual-channel display is on\n'); end % NB: fix this- query active channel? % Assume CH 1 until then elseif dstatebit==0, dstate='1 0 0 0'; if verbose >= 2, fprintf(1, 'kpib/HP_8753ES: Dual-channel display is off (assume CH1)\n'); end % NB: fix this- query active channel? end retval=dstate; % if verbose >= 2, fprintf(1, 'kpib/HP_4395A: Dual-channel display is %s\n',dstate); end end case 'format' %ok switch value case 'log mag' fprintf(io,'LOGM'); case 'phase' fprintf(io,'PHAS'); case 'delay' fprintf(io,'DELA'); case 'linear mag' fprintf(io,'LINM'); case 'polar' fprintf(io,'POLA'); case 'real' fprintf(io,'REAL'); otherwise if verbose >= 1, fprintf(1, 'kpib/HP_8753ES: Set Analyzer data format to default log magnitude.\n'); end fprintf(io,'LOGM'); end case {'autoscale','auto','autoy'}; switch value case 'off' % DNE case 'once' if isnumeric(channel) && any(channel == [1 2 3 4]) fprintf(io,'CHAN%d',channel); fprintf(io,'AUTO'); if verbose >=2, fprintf(1, 'kpib/HP_8753ES: Autoscale channel %d\n',channel); end else fprintf(io,'AUTO'); if verbose >=2, fprintf(1, 'kpib/HP_8753ES: Autoscale current channel\n'); end end case 'both' % specific to resonators - autoscale channels 1 & 2 fprintf(io,'CHAN1'); fprintf(io,'AUTO'); fprintf(io,'CHAN2'); fprintf(io,'AUTO'); fprintf(io,'CHAN1'); if verbose >=2, fprintf(1, 'kpib/HP_8753ES: Autoscale channels 1 & 2\n'); end otherwise if isnumeric(channel) && any(channel == [1 2 3 4]) fprintf(io,'CHAN%d',channel); fprintf(io,'AUTO'); if verbose >=2, fprintf(1, 'kpib/HP_8753ES: Autoscale channel %d\n',channel); end else fprintf(io,'AUTO'); if verbose >=2, fprintf(1, 'kpib/HP_8753ES: Autoscale Y current channel (default)\n'); end end end case 'scale' %ok if isnumeric(value) fprintf(io,'SCAL%d',value); if verbose >= 2, fprintf(1, 'kpib/HP_8753ES: Scale of current channel set to %d/div.\n',value); end else switch value case {'auto','AUTO'} fprintf(io,'AUTO'); if verbose >= 2, fprintf(1, 'kpib/HP_8753ES: Autoscale current channel.\n'); end case {'?','query'} fprintf(io,'SCAL?'); retval = fscanf(io); if verbose >= 2, fprintf(1, 'kpib/HP_8753ES: Scale is %g/division.\n',retval); end case {'ref','refline','ref line'} fprintf(io,'REFV%d',value); if verbose >= 2, fprintf(1, 'kpib/HP_8753ES: Reference value set to %g dBm.\n',value); end end end case 'ref line' %ok fprintf(io,'REFV%d',value); if verbose >= 2, fprintf(1, 'kpib/HP_8753ES: Reference value set to %g dBm.\n',value); end case {'average','averaging'} %ok switch value case {'on',1} fprintf(io,'AVEROON'); if verbose >= 2, fprintf(1, 'kpib/HP_8753ES: Averaging on'); end if isnumeric(channel) && channel > 0 fprintf(io,'AVERFACT%.0f',channel); if verbose >= 2, fprintf(1, ', aver. factor %d.\n',channel); end else if verbose >= 2, fprintf(1,', aver. factor is not specified.\n'); end end case {'off',0}; fprintf(io,'AVEROOFF'); if verbose >= 2, fprintf(1, 'kpib/HP_8753ES: Averaging off.\n'); end case {'num','number','count'} % not available for 8753? Use number of groups if verbose >= 2, fprintf(1, 'kpib/HP_8753ES: Warning: Averaging Count not available for 8753ES, use number of groups instead.\n'); end case{'restart','Restart'} fprintf(io,'AVERREST'); if verbose >= 2, fprintf(1, 'kpib/HP_8753ES: Averaging restarted.\n'); end case {'query','?'} fprintf(io,'AVERO?'); retval = fscanf(io,'%f'); if retval == 0 if verbose >= 2, fprintf(1, 'kpib/HP_8753ES: Averaging is off.\n'); end else fprintf(io,'AVERFACT?'); retval = fscanf(io,'%f'); if verbose >= 2, fprintf(1, 'kpib/HP_8753ES: Averaging is on; Averaging factor is: %g\n', retval); end end otherwise % set the number of measurements to average if isnumeric(value) && value > 0 fprintf(io,'AVERFACT %d',channel); if verbose >=2, fprintf(1, 'kpib/HP_8753ES: Averaging factor set to: %d\n',value); end end end case {'marker'} %ok if isnumeric(channel) && any(channel == [1 2 3 4]) fprintf(io,'MARK%d',channel); if verbose >= 2, fprintf(1, 'kpib/HP_8753ES: Marker channel %d\n',channel); end else channel=1; if verbose >= 2, fprintf(1, 'kpib/HP_8753ES: Marker channel 1 (default)\n'); end end if isnumeric(value) && value > 0 % move marker to that point cmd=sprintf('MARK%d%f',channel,value'); fprintf(io,cmd); if verbose >= 2, fprintf(1, 'kpib/HP_8753ES: Marker channel %d set to %f Hz\n',channel,value); end else switch value case 'on' fprintf(io,'MARK%d',channel); case 'off' fprintf(io,'MARKOFF'); case {'query','?'} % query the marker position fprintf(io,'OUTPMARK'); mkr = fscanf(io); mkr = str2num(mkr); %retval=mkr; retval.y = mkr(1); retval.x = mkr(3); if verbose >= 2, fprintf(1,'kpib/HP_8753ES: Marker position: %f/%f\n',mkr(1),mkr(3)); end case {'center','m2c','mark2center'} % make the marker position the center freq fprintf(io,'SEAMAX'); fprintf(io,'MARKCENT'); if verbose >= 2, fprintf(1,'kpib/HP_8753ES: Peak to Center\n'); end case {'peak','searchpeak','mark2peak','max'} fprintf(io,'SEAMAX'); if verbose >= 2, fprintf(1,'%s\n','kpib/HP_8753ES: Marker to Peak (max)'); end case {'min','valley'} fprintf(io,'SEAMIN'); if verbose >= 2, fprintf(1,'%s\n','kpib/HP_8753ES: Marker to Valley (min)'); end otherwise if verbose >= 1, fprintf(1, 'kpib/HP_8753ES: Error at ''marker'' command (VALUE incorrect ["%s"]).\n',value); end end end case {'mark2peak','m2p','findpeak'} %ok switch value case 'off' if verbose >= 2, fprintf(1,'%s\n','kpib/HP_8753ES: Marker Search Off'); end fprintf(io,'SEAOFF'); case 'center' fprintf(io,'SEAMAX'); fprintf(io,'MARKCENT'); if verbose >= 2, fprintf(1,'kpib/HP_8753ES: Peak to Center\n'); end case {'peak','max'} if verbose >= 2, fprintf(1,'%s\n','kpib/HP_8753ES: Marker to Peak (max)'); end fprintf(io,'SEAMAX'); case 'min' if verbose >= 2, fprintf(1,'%s\n','kpib/HP_8753ES: Marker to minimum'); end fprintf(io,'SEAMIN'); otherwise if verbose >= 2, fprintf(1,'%s\n','kpib/HP_8753ES: Marker to Max (default)'); end fprintf(io,'SEAMAX'); end case 'sweep' %ok fprintf(io,'CLES'); % clear the status registers fprintf(io,'*OPC?'); % to check operation(sweep) complete. % *OPC? + sweep command will return '1' when sweep is % done. complete check is done in 'complete' command if isnumeric(value) && value > 0 % set the sweep time fprintf(io,'SWET%d',value); else switch value case {'auto','AUTO'} fprintf(io,'SWEA'); case {'linear freq'} fprintf(io,'LINFREQ'); case {'list freq'} fprintf(io,'LISFREQ'); case {'log freq'} fprintf(io,'LOGFREQ'); case {'power sweep'} fprintf(io,'POWS'); case {'single','sing','SING'} fprintf(io,'SING'); case {'continuous','cont','CONT'} fprintf(io,'CONT'); case {'hold','HOLD'} fprintf(io,'HOLD'); case {'group','groups','number','N'} if isnumeric(channel) && channel >= 1 && channel <= 999 fprintf(io,'NUMG%d',channel); else if verbose >= 1, fprintf(1, 'kpib/HP_8753ES: Sweep Error: Number or sweeps must be between 1 and 999.\n'); end end case {'points','numpoints','setpoints'} if isnumeric(channel) && channel >= 2 && channel <= 801 fprintf(io,'POIN%i',channel); else if verbose >= 1, fprintf(1, 'kpib/HP_8753ES: Sweep Error: Number of points must be between 2 and 801.\n'); end end otherwise if verbose >= 1, fprintf(1, 'kpib/HP_8753ES: Sweep command not supported ["%s"]\n',value); end end end case 'center' %ok switch value case {'query','?'} fprintf(io,'CENT?'); retval = fscanf(io,'%f'); otherwise fprintf(io,'CENT%f',value); if verbose >= 2, fprintf(1, 'kpib/HP_8753ES: Center set to %f Hz\n',value); end end case 'span' %ok switch value case {'query','?'} fprintf(io,'SPAN?'); retval = fscanf(io,'%f'); otherwise fprintf(io,'SPAN%f',value); if verbose >= 2, fprintf(1, 'kpib/HP_8753ES: Span set to %f Hz\n',value); end end case 'start' %ok switch value case {'query','?'} fprintf(io,'STAR?'); retval = fscanf(io,'%f'); otherwise fprintf(io,'STAR%f',value); if verbose >= 2, fprintf(1, 'kpib/HP_8753ES: Start set to %f Hz\n',value); end end case 'stop' %ok switch value case {'query','?'} fprintf(io,'STOP?'); retval = fscanf(io,'%f'); otherwise fprintf(io,'STOP%f',value); if verbose >= 2, fprintf(1, 'kpib/HP_8753ES: Stop set to %f Hz\n',value); end end case {'power','source'} %ok if isequal(value,'query') fprintf(io,'POWE?'); retval = fscanf(io,'%f'); if verbose >= 2, fprintf(1, 'kpib/HP_8753ES: Source Power is %d dBm\n',retval); end elseif isnumeric(value) && value >= -50 && value <= 15 fprintf(io,'POWE%d',value); if verbose >= 2, fprintf(1, 'kpib/HP_8753ES: Source Power set to %d dBm\n',value); end else if verbose >= 2, fprintf(1, 'kpib/HP_8753ES: Source Power not set. Power must be specified between -50 and 15 dBm.\n'); end end case {'power?','source?'} %ok fprintf(io,'POWE?'); retval.level = fscanf(io,'%f'); if verbose >= 2, fprintf(1, 'kpib/HP_8753ES: Source Power: %g dBm\n',retval.level); end retval.state='on'; % source is always on % case 'bandwidth' % if isnumeric(value) % fprintf(io,'BW %d',value); % elseif isequal(value,'auto') % if isequal(channel,'on') | isequal(channel,'off') % fprintf(io,'BWAUTO %s',channel); % end % elseif isequal(value,'limit') % if isnumeric(channel) % fprintf(io,'BWLMT%d',channel); % else % if verbose >= 2, fprintf(1, 'kpib/HP_8753ES: A numeric value must be entered for channel.\n'); end % end % end % case 'trigger' % switch value % case 'internal' % fprintf(io,'TRGS INT'); % case 'external' % fprintf(io,'TRGS EXT'); % case 'GPIB' % fprintf(io,'TRGS BUS'); % case 'video' % fprintf(io,'TRGS VID'); % case 'manual' % fprintf(io,'TRGS MAN'); % case 'ext gate' % fprintf(io,'TRGS GAT'); % otherwise % if isequal(value,'int') | isequal(value,'ext') | isequal(value,'vid') | isequal(value,'man') | isequal(value,'gat') | isequal(value,'bus') % fprintf(io,'TRGS %s',value); % else % if verbose >= 2, fprintf(1, 'kpib/HP_8753ES: Not a valid trigger.\n'); end % end % end case 'getdata' %ok % Select the channel. For compatibility with old code, the % channel is *not* set if it is not explicitly specified, i.e., % the default is to do nothing, rather than to select a channel. % specify the data format as ASCII fprintf(io,'FORM4'); % now, did the user specify a channel or not? if isnumeric(channel) && any(channel == [1 2 3 4]) fprintf(io,'CHAN%d',channel); if verbose >= 2, fprintf('kpib/HP_8753ES: Channel %d selected for data download.\n',channel); end else if verbose >= 2, fprintf('kpib/HP_8753ES: Current channel for data download.\n'); end end % download the data. The HP_8753ES only sends the Y values. fprintf(io,'POIN?'); numdatapoints = fscanf(io,'%f'); fprintf(io,'OUTPFORM'); %rawdata=fscanf(io,'%e',numdatapoints); for fg=1:numdatapoints rd = fscanf(io); rawdata(fg,:) = str2num(rd); % only column 1 is data end retval.y=rawdata(:,1); % only column 1 is data if verbose >= 2, fprintf('kpib/HP_8753ES: Data downloaded.\n'); end % Now we must infer the X values %numdatapoints = str2num(numdatapoints); fprintf(io,'CENT?'); center = fscanf(io); center = str2num(center); fprintf(io,'SPAN?'); span = fscanf(io); span = str2num(span); start = center - span/2; delta = span/(numdatapoints-1); retval.x=([0:1:numdatapoints-1]*delta)'+start; % get the units retval.units.x = 'Hz'; % X is always in Hz, as far as I know % the units for Y amplitude depend on the Format fprintf(io,'LOGM?'); fmt=fscanf(io,'%d'); if fmt==1 retval.units.y='dB'; else fprintf(io,'LINM?'); fmt=fscanf(io,'%d'); if fmt==1 retval.units.y='U'; else fprintf(io,'PHAS?'); fmt=fscanf(io,'%d'); if fmt==1 retval.units.y='deg'; else retval.units.y='??'; end end end % switch mode % the returned data is different for different modes % case 'NA' % % the real data is every other point in the returned array, % % so the array has twice as many members as there are data points % % (manual p O-10). Vectorize! % % Return the data in columns % retval.x=([0:1:numdatapoints-1]*delta)'+start; % retval.y=rawdata([1:2:numdatapoints*2])'; % % case 'SA' % % The spectrum analyzer returns only the data we are % % interested in, no extraneous points % % Return the data in columns % retval.x=([0:1:numdatapoints-1]*delta)'+start; % retval.y=rawdata'; % end case 'units' %ok % See the manual p1-82 (Table 1-4) for units % query the display format, and then assume the units % now, did the user specify a channel or not? if isnumeric(channel) && any(channel == [1 2 3 4]) fprintf(io,'CHAN%d',channel); if verbose >= 2, fprintf('kpib/HP_8753ES: Channel %d selected for units.\n',channel); end else if verbose >= 2, fprintf('kpib/HP_8753ES: Current channel for units.\n'); end end %if verbose >= 2, fprintf('kpib/HP_8753ES: Get Units:\n'); end switch value case {'x','X'} % the units for X are always Hz, as far as I can tell retval='Hz'; case {'y','Y'} % the units for Y amplitude depend on the Format fprintf(io,'LOGM?'); fmt=fscanf(io,'%d'); if fmt==1 retval='dB'; else fprintf(io,'LINM?'); fmt=fscanf(io,'%d'); if fmt==1 retval='U'; else fprintf(io,'PHAS?'); fmt=fscanf(io,'%d'); if fmt==1 retval='deg'; else retval='??'; end end end otherwise % get both retval.x='Hz'; retval.y=kpib(instrument,GPIB,'units','y',channel,aux,verbose); end case 'pause' %ok if isequal(value,'query') fprintf(io,'HOLD?'); retval = fscanf(io); else fprintf(io,'HOLD'); if verbose >= 2, fprintf('kpib/HP_8753ES: Measurement paused.\n'); end end case {'continue','cont'} % continuous sweeping fprintf(io,'CONT'); if verbose >= 2, fprintf('kpib/HP_8753ES: Measurement continue.\n'); end case 'complete' %ok % complete check return value from io-port after issuing % *OPC? + (sweep command) to know when a sweep has % completed. This method only works for SINGLE and GROUP % sweeps, it does not work for continuous sweeps. If you try % to wait for the complete of a sweep in continuous mode, the % program will hang (you will wait forever). % *OPC? + (sweep command) (i.e. *OPC?; SING) is issued during % the 'sweep' command above. Here, we do fscanf(io,%d) until % '1' is returned. For safety, no GPIB command should be % issued between 'sweep' and 'complete' if verbose >= 2, fprintf('kpib/HP_8753ES: Waiting for sweep to complete...\n'); end warning off instrument:fscanf:unsuccessfulRead % can issue a single command for a sweep and wait for completion % e.g., kpib(tools.analyzer,'complete','single',0,0,verbose); switch value case {'single','sing','SING'} kpib(instrument, GPIB, 'sweep', 'single', channel, aux, verbose); if verbose >= 2, fprintf(1, 'kpib/HP_8753ES: Single Sweep & Complete\n'); end case {'group','groups','number','N'} kpib(instrument, GPIB, 'sweep', 'group', channel, aux, verbose); if verbose >= 2, fprintf('kpib/HP_8753ES: Group Sweep (%d) & Complete\n',channel); end end retval=0; while 1 retval = fscanf(io,'%d'); % read return value after *OPC? is issued in 'sweep' if ~isempty(retval) && retval == 1 % if return value is '1', sweep is completed. if verbose >= 2, fprintf(1,'kpib/HP_8753ES: Sweep complete.\n'); end break; else % if return value is ' ', sweep is not completed. if verbose >= 2, fprintf(1,'kpib/HP_8753ES: Sweep not complete.\n'); end end end case 'wait' % *WAI is not supported by 8753? retval = 1; otherwise if verbose >= 1, fprintf('kpib/HP_8753ES: Error, command not supported. ["%s"]\n',command); end end else % catch incorrect address errors if verbose >= 1, fprintf('kpib/%s: ERROR: No instrument at GPIB %d\n',instrument,GPIB); end retval=0; end validInst = 1; end % end HP_8753ES
'AO_800' AlphaOmega Instruments 800-series Temperature controller
The AO_800 uses a serial port interface. GPIB should be the com port (e.g. 'COM1'). The AO_800 uses a Watlow series 96 controller, so the programming follows the Watlow "Modbus Register" conventions.
%RETVAL = KPIB('INSTRUMENT', GPIB, 'COMMAND', VALUE, CHANNEL, AUX, VERBOSE) % Valid Commands: % 'init' Test the serial connections, make sure controller is set up % for "normal" operation. % 'set','setT' Set the temperature setpoint for automatic temperature % control. Use VALUE = 'query' or '?' to query. % 'manual' Set the controller to manual mode and set the output to % VALUE percent. + = heating, - = cooling. % 'read' Read the current temperature from the feedback sensor. % Returns temperature with two decimal places of precision. % 'on' Set the controller for automatic mode (control temperature). % 'off' Stop controlling temperature (manual mode) and set output % power to zero. % 'readreg' Return the contents of CHANNEL memory registers, starting at % register VALUE. Results are returned as decimal value. For % VERBOSE = 2, results are displayed in hex. % 'writereg' Write a byte (CHANNEL) to register VALUE. % % 'openloop' Enable and disable the "Open Loop Detect" feature. % if strcmpi(instrument, 'AO_800') || strcmpi(instrument, 'WAT_96') || strcmpi(instrument, 'all') % baudrate for serial communications baudrate = 9600; % bps conaddr = 1; % the controller defaults to address 1 % (in theory, you could connect multiple controllers on a serial bus) % Make this flexible in future versions? (MH, v3.4) io = port(GPIB, instrument, baudrate, verbose); try % Wrap the whole thing in try/catch to deal with serial cable noise and errors. % The error rate seems to be on the order of 1/1000 operations. % Its not clear where the real source of the problem lies. See the % Catch block for further discussion. (MH v4.64) switch command case 'init' if verbose >= 2, fprintf(1, 'kpib/AO_800: Initializing AlphaOmega 800 Series Temp. Controller on %s:\n',GPIB); end % loopback command to check wiring message=[conaddr 8 42 42]; crc=makeCRC(message); fwrite(io,[message crc]); confirm = fread(io,6); if confirm' == [message crc] fprintf(1, ' OK Serial port connection to controller is ok\n'); else fprintf(1, ' ERROR: Serial port connection to controller is bad (failed loopback)\n'); end % % enable open loop detect Register % message=[conaddr 6 3 136 0 1]; % crc=makeCRC(message); % response = watwrite(io,[message crc],verbose); % if response == 0 % if verbose >= 1, fprintf(1, ' OK Controller confirms open loop detect enable\n'); end % else % if verbose >= 1, fprintf(1, ' WARNING: Controller does not confirm open loop detect\n'); end % end % disable open loop detect Register message=[conaddr 6 3 136 0 0]; crc=makeCRC(message); response = watwrite(io,[message crc],verbose); if response == 0 if verbose >= 1, fprintf(1, ' OK Controller confirms open loop detect disable\n'); end else if verbose >= 1, fprintf(1, ' WARNING: Controller does not confirm open loop detect\n'); end end % disable the EEPROM message=[conaddr 6 0 24 0 0]; crc=makeCRC(message); response = watwrite(io,[message crc],verbose); if response == 0 if verbose >= 1, fprintf(1, ' OK Controller confirms EEPROM disable\n'); end else if verbose >= 1, fprintf(1, ' WARNING: Controller does not confirm EEPROM disable\n'); end end % check to be sure that the result will be given using one % implied decimal point (default): read register 606 (0x025E) message=[conaddr 3 2 94 0 1]; crc=makeCRC(message); fwrite(io,[message crc]); got_decimal = fread(io,7); % decimal(5) is our answer if got_decimal(5) == 1 if verbose >= 1, fprintf(1, ' OK Controller is using 1 implied decimal point (standard)\n'); end else if verbose >= 1, fprintf(1, ' WARNING: Controller decimal point setting is non-standard.\n'); end if verbose >= 1, fprintf(1, ' (Recommend setting register 606 to 1).\n'); end end % % NB: locking out the setpoint, etc., locks it for remote % % programming as well. % pause(0.1) % % lock out the front panel setpoint % message=[value 6 5 20 0 2]; % crc=makeCRC(message); % fwrite(io,[message crc]); % Personal preference whether 'init' should leave the % controller on or off ... if verbose >= 1, fprintf(1, '\n Initialization sequence complete.\n'); end kpib(instrument,GPIB,'off',value,channel,aux,verbose); if verbose >= 1, fprintf(1, '\n Controller is OFF (manual mode).\n\n'); end % kpib(instrument,GPIB,'on',value,channel,aux,verbose); % if verbose >= 1 % setp=kpib(instrument,GPIB,'set','query',channel,aux,verbose); % fprintf(1, '\n WARNING: Controller is ON, with setpoint %d C.\n',setp); % fprintf(1, ' Verify that TE element is ready for power.\n\n'); % end % % end 'init' case {'on',1,'lock'} % enable the controller for Auto operation (i.e. controlling temperature) % register 301 set to 0 message=[conaddr 6 1 45 0 0]; crc=makeCRC(message); response = watwrite(io,[message crc],verbose); if response == 0 if verbose >= 2, fprintf(1, 'kpib/AO_800: Controller is ON (controlling temperature)\n'); end else if verbose >= 1, fprintf(1, 'kpib/AO_800: WARNING: Controller does not confirm ON\n'); end end case {'off',0,'stop'} % put controller into Manual mode and set output power to 0 % register 301 set to 1 for Manual message=[conaddr 6 1 45 0 1]; crc=makeCRC(message); response = watwrite(io,[message crc],verbose); if response == 0 if verbose >= 2, fprintf(1, 'kpib/AO_800: Controller in Manual mode\n'); end else if verbose >= 1, fprintf(1, 'kpib/AO_800: WARNING: Controller does not confirm Manual Mode\n'); end end % % register 310 set for Manual mode setpoint % % check to be sure that the result will be given using one % % implied decimal point (default): read register 606 (0x025E) % message=[conaddr 3 2 94 0 1]; % crc=makeCRC(message); % fwrite(io,[message crc]); % got_decimal = fread(io,7); % decimal(5) is our answer % pause(0.1) % now set the setpoint to 0 message=[conaddr 6 1 54 0 0]; crc=makeCRC(message); response = watwrite(io,[message crc],verbose); if response == 0 if verbose >= 2, fprintf(1, 'kpib/AO_800: Controller is OFF (output 0%%)\n'); end else if verbose >= 1, fprintf(1, 'kpib/AO_800: WARNING: Controller does not confirm OFF\n'); end end case {'openloop','opld'} % open-loop detect can trip unnecessarily % if you are trying to get to the extreme % low temperature ranges (because it takes % a long time to get there) toggle=0; % flag % if nargin > 3 switch value case {'on'} % enable open loop detect Register message=[conaddr 6 3 136 0 1]; crc=makeCRC(message); response = watwrite(io,[message crc],verbose); if response == 0 if verbose >= 2, fprintf(1, 'kpib/AO_800: Controller confirms open loop detect enable\n'); end else if verbose >= 2, fprintf(1, 'kpib/AO_800: WARNING: Controller does not confirm open loop detect\n'); end end case {'off'} % disable open loop detect Register message=[conaddr 6 3 136 0 0]; crc=makeCRC(message); response = watwrite(io,[message crc],verbose); if response == 0 if verbose >= 2, fprintf(1, 'kpib/AO_800: Controller confirms open loop detect disable\n'); end else if verbose >= 2, fprintf(1, 'kpib/AO_800: WARNING: Controller does not confirm open loop detect\n'); end end otherwise % toggle toggle=1; % set flag end % else % toggle % toggle=1; % end if toggle==1 % you know what to do % read the register to determine the current state message=[conaddr 3 3 136 0 1]; crc=makeCRC(message); fwrite(io,[message crc]); opld = fread(io,7); % decimal(5) is our answer if opld(5)==0 message=[conaddr 6 3 136 0 1]; crc=makeCRC(message); response = watwrite(io,[message crc],verbose); if response == 0 if verbose >= 2, fprintf(1, 'kpib/AO_800: Controller confirms open loop detect enable\n'); end else if verbose >= 2, fprintf(1, 'kpib/AO_800: WARNING: Controller does not confirm open loop detect\n'); end end else message=[conaddr 6 3 136 0 0]; crc=makeCRC(message); response = watwrite(io,[message crc],verbose); if response == 0 if verbose >= 2, fprintf(1, 'kpib/AO_800: Controller confirms open loop detect disable\n'); end else if verbose >= 2, fprintf(1, 'kpib/AO_800: WARNING: Controller does not confirm open loop detect\n'); end end end end case {'set','setT','setpoint'} if isnumeric(value) && value < 125 && value > -55 % setpoint is register 300. Send temperature with one decimal % point implied. go_set=round(value*10); if verbose >= 2, fprintf(1, 'kpib/AO_800: Changing setpoint to %.1f C\n', go_set/10); end % sort out the setpoint values for transmission sp=makeBytes(go_set); message=[conaddr 6 1 44 sp]; crc=makeCRC(message); response = watwrite(io,[message crc],verbose); if response == 0 if verbose >=2, fprintf(1, 'kpib/AO_800: Controller confirms setpoint change to %.1f C\n', go_set/10); end end elseif strcmpi(value,'query') || strcmpi(value,'?') % return setpoint % check decimal register message=[conaddr 3 2 94 0 1]; crc=makeCRC(message); fwrite(io,[message crc]); got_decimal = fread(io,7); % decimal(5) is our answer pause(0.1) % now read setpoint register message=[conaddr 3 1 44 0 1]; crc=makeCRC(message); fwrite(io,[message crc]); pause(0.005) setp = fread(io,7); retval = makeDecimal(setp(4:5)); % divide result by ten if required if got_decimal(5) == 1 retval = retval/10; end if verbose >= 2, fprintf(1, 'kpib/AO_800: Temperature Setpoint is: %.1f C\n',retval); end else if verbose >= 1, fprintf(1, 'kpib/AO_800: "set" command error\n'); end end case {'read','getdata'} % we can read register 100 (Process 1) for the control value % or we can read secret register 1707 for "High Resolution" % temperature value. Hmm. 1707 seems to use 2 decimal places. %if strcmpi(value,'temp') || strcmpi(value,'T') if any(strcmpi(value,{'temp','temperature','T'})) %v4.72 % read the high-res temperature from register 1707 (0x06AB) message=[conaddr 3 06 171 0 1]; highres = 1; else % read the temperature from register 100 (0x0064) message=[conaddr 3 00 100 0 1]; highres = 0; end crc=makeCRC(message); % this try/catch is superseded by the command-wide % try/catch (v3.76) % try fwrite(io,[message crc]); got_temp = fread(io,7); % got_temp(4:5) is our answer retval=makeDecimal(got_temp(4:5)); % divide result by ten if required if highres == 1 retval = retval/100; % 100 for high-res else retval = retval/10; % 10 for normal end if verbose >= 2, fprintf(1, 'kpib/AO_800: Temperature reading: %.2f C\n',retval); end % catch % if verbose >= 0, fprintf(1, 'kpib/AO_800: WARNING: serial port error (read). Retrying:\n'); end % % close the serial port and try again % kpib('close',GPIB,0,0,0,0,verbose); % pause(1); % retval=kpib(instrument,GPIB,command,value,channel,aux,verbose); % end case 'manual' % register 301 set to 1 for Manual message=[conaddr 6 1 45 0 1]; crc=makeCRC(message); response = watwrite(io,[message crc],verbose); if response == 0 if verbose >= 2, fprintf(1, 'kpib/AO_800: Controller in Manual mode\n'); end else if verbose >= 1, fprintf(1, 'kpib/AO_800: WARNING: Controller does not confirm Manual Mode\n'); end end if isnumeric(value) % set the output to VALUE percent go_set=round(value*10); if verbose >= 2, fprintf(1, 'kpib/AO_800: Changing output to %.1f%%\n', go_set/10); end sp=makeBytes(go_set); % now set the setpoint to go_set message=[conaddr 6 1 54 sp]; crc=makeCRC(message); response = watwrite(io,[message crc],verbose); if response == 0 if verbose >= 2, fprintf(1, 'kpib/AO_800: Controller output is %.1f%%\n',value); end else if verbose >= 1, fprintf(1, 'kpib/AO_800: WARNING: Controller does not confirm output\n'); end end else switch value case {'on','go'} kpib(instrument,GPIB,'on',value,channel,aux,verbose); case {'off','stop'} kpib(instrument,GPIB,'off',value,channel,aux,verbose); otherwise %case {'query','?'} retval=kpib(instrument,GPIB,'read',301,channel,aux,verbose); if verbose >= 2 if retval == 1 fprintf(1, 'kpib/AO_800: Controller in manual mode.\n'); elseif retval == 0 fprintf(1, 'kpib/AO_800: Controller in manual mode.\n'); else fprintf(1, 'kpib/AO_800: ERROR: Controller mode not known.\n'); end end end end case 'readreg' % return the contents of an arbitrary register if isnumeric(channel) && channel < 1 && channel > 10 channel=1; % number of 2-byte registers to read if verbose >= 1, fprintf(1,'kpib/readreg: Read one byte (max. 10)\n'); end elseif ~isnumeric(channel) || channel==0 channel=1; end if verbose >= 2, fprintf(1,'kpib/readreg: Read %d bytes starting at %d\n',channel,value); end % code the register value for transmission reg=makeBytes(value); message=[conaddr 3 reg 0 channel]; crc=makeCRC(message); fwrite(io,[message crc]); got_reg = fread(io,5+channel*2); reghex=dec2hex(got_reg(4:4+got_reg(3)-1),2); rhex=[]; for r=1:channel*2 rhex=[rhex reghex(r,:)]; end got_val=got_reg(4:4+got_reg(3)-1); if verbose >= 2 fprintf(1,'kpib/readreg: register bytes (hex):\n'); fprintf(1,' %c%c',rhex); fprintf(1,'\n'); fprintf(1,'kpib/readreg: register bytes (decimal):\n'); fprintf(1,' %d',got_val); fprintf(1,'\n'); end retval=[]; for i=1:2:channel*2 retval=[retval makeDecimal(got_val(i:i+1))]; end case 'writereg' % write CHANNEL to register VALUE if isnumeric(channel) && abs(channel) < 32678 sp=makeBytes(channel); reg=makeBytes(value); message=[conaddr 6 reg sp]; crc=makeCRC(message); response = watwrite(io,[message crc],verbose); if response == 0 && verbose >= 2 fprintf(1, 'kpib/AO_800: Controller confirms write of %d to register %d\n',channel,value); end end otherwise if verbose >= 2, fprintf(1, 'kpib/AO_800: Error, command not supported. ["%s"]\n',command); end end validInst = 1; % Serial communications seem to be prone to errors. This catch block repeats the command. % However, the latest experience suggests that closing the port exacerbates the problem. catch %#ok<CTCH> validInst = 1; % if there is an error, close the port and try again %kpib('close',GPIB,0,0,0,0,verbose); if verbose >= 1, fprintf(1, 'kpib/AO_800: WARNING serial port error at ''%s'' (%s). Retrying...\n',command,datestr(clock)); end pause(1); % flush the serial port? fread(io, io.BytesAvailable) pause(1) if verbose >= 1, fprintf(1,' kpib(%s,%s,%s,%s,%s,%s,%d)\n',instrument,GPIB,command,num2str(value),num2str(channel),num2str(aux),verbose); end % disp(instrument) % disp(GPIB) % disp(command) % disp(value) % disp(channel) % disp(aux) % disp(verbose) if nargout >= 1 retval = kpib(instrument,GPIB,command,value,channel,aux,verbose); elseif nargout == 0 kpib(instrument,GPIB,command,value,channel,aux,verbose); end end % end try/catch end % end AO_800
'HP_8560A' HP Spectrum Analyzer 50 Hz - 2.9 GHz
%RETVAL = KPIB('INSTRUMENT', GPIB, 'COMMAND', VALUE, CHANNEL, AUX, VERBOSE) % VALUE is typically the modifier to COMMAND. % Valid Commands: % 'init' Resets the Analyzer and clears the error list. % 'label' Writes 'VALUE' to the display. 32 char max. % non-exponentially ('norm'). Exponentially is the default. % 'scale' Sets the scale of the display. VALUE is the scale in the % current units, or 'VALUE' = 'auto' for autoscale command. % 'ref line' Sets the position of the reference line of the display. % VALUE is the position of the reference line in the current % units. Also 'reflevel'. % 'average' Turns averaging on or off, restarts averaging, or returns % the current number of averages taken. % VALUE='on','off','restart', or 'query'. CHANNEL= number of % sweeps to average. % For 'query', RETVAL returns 0 (off) or the current number of averages (on). % 'mark2peak' Finds the peak and sets the marker, or finds the peak and % sets the peak location to the center of the scan. % VALUE='off','center', or 'peak'. % 'marker' Turns the marker on or off, sets the marker to position % VALUE (in Hz), or returns the current position of the % marker. 'VALUE' = 'on','off', or 'query'. The position is % returned as retval.x, retval.y in current units. Can also % select a marker function: VALUE = 'center', 'min', 'max'. % 'center' Set the center frequency to VALUE. Units of Hz. % Query with VALUE = 'query', returns center frequency in Hz. % 'span' Set the frequency span VALUE. Units of Hz. % Query with VALUE = 'query', returns span in Hz. % 'start' Set the start of the sweep range to VALUE Hz. % 'stop' Set the end of the sweep range to VALUE Hz. % 'source' Set the source (stimulus output) signal level. VALUE is the % desired signal level. Units of dBm. % Query with VALUE = 'query', returns source power in dBm. % 'source?' (Alternate query form) Returns source power in dBm. % 'power' Same as 'source'. % 'getdata' Download the current data trace from the analyzer. Data is % returned as two columns, x and y, for the specified % CHANNEL. Default CHANNEL is not set. If VALUE is 'x' or 'y', only % that data is returned in a single column. % 'units' Returns the units of the data from the analyzer. Must % specify VALUE = 'x' or 'y' axis units. % 'pause' Pauses measurement. % 'continue' Continues paused measurement. % 'complete' Wait for the previous sweep to complete. This command % contains a loop that does not exit until the status byte shows % 'wait' Wait for the previous command to complete (*WAI) if (strcmpi(instrument, 'HP_8560A') || strcmpi(instrument, 'all')) io = port(GPIB, instrument, 8*601, verbose); % buffer size 8*601 for downloading data if (io ~=0) && (strcmp(get(io,'Status'),'open') ~=0) switch command case 'init' %ok %fprintf(io,'*RST'); %fprintf(io,'CLEAR') clrdevice(io); fprintf(io,'ERR?;'); err=fscanf(io,'%f,'); %#ok<NASGU> %fprintf(io,'*SRE 4;ESNB 1'); % enable the registers; case {'label','title'} %ok if length(value) > 32 % two rows of 16 each allowed value=value(1:32); % 16x2 chars max end fprintf(io,'TITLE@%s@;',value); % % case {'display','trace'} %ok % switch value % case {'data'} % fprintf(io,'DISPDATA',value); % if verbose >= 2, fprintf(1, 'kpib/HP_8753ES: Display data only\n'); end % case {'memory','mem'} % fprintf(io,'DISPMEMO'); % if verbose >= 2, fprintf(1, 'kpib/HP_8753ES: Display memory only\n'); end % case {'both','data&memory','datamem','data+memory'} % fprintf(io,'DISPDATM'); % if verbose >= 2, fprintf(1, 'kpib/HP_8753ES: Display data & memory\n'); end % case {'dual'} %ok % switch channel % case {'on',1} % fprintf(io, 'DUACON'); % if verbose >= 2, fprintf(1, 'kpib/HP_8753ES: Dual-channel display on.\n'); end % case {'off',0} % fprintf(io, 'DUACOFF'); % if verbose >= 2, fprintf(1, 'kpib/HP_8753ES: Dual-channel display off.\n'); end % case {'query','?'} % returns 1 for dual-channel on, 0 for off % fprintf(io, 'DUAC?'); % dstatebit=str2num(fscanf(io)); % if dstatebit==1, dstate='on'; % elseif dstatebit==0, dstate='off'; % end % retval=dstatebit; % if verbose >= 2, fprintf(1, 'kpib/HP_8753ES: Dual-channel display is %s\n',dstate); end % end % case {'on',1} % fprintf(io,'BLADOFF',value); % if verbose >= 2, fprintf(1, 'kpib/HP_8753ES: Screen on\n'); end % case {'off',1} % fprintf(io,'BLADON',value); % if verbose >= 2, fprintf(1, 'kpib/HP_8753ES: Screen off\n'); end % end % % case 'format' % % switch value % case 'log mag' % fprintf(io,'LOGM'); % case 'phase' % fprintf(io,'PHAS'); % case 'delay' % fprintf(io,'DELA'); % case 'linear mag' % fprintf(io,'LINM'); % case 'polar' % fprintf(io,'POLA'); % case 'real' % fprintf(io,'REAL'); % otherwise % if verbose >= 1, fprintf(1, 'kpib/HP_8753ES: Set Analyzer data format to default log magnitude.\n'); end % fprintf(io,'LOGM'); % end % case {'autoscale','auto','autoy'}; % if nargin > 3 % switch value % case 'off' % % DNE % case 'once' % if nargin > 4 % if channel == 0 % autoscale current channel % fprintf(io,'AUTO'); % if verbose >=2, fprintf(1, 'kpib/HP_8753ES: Autoscale current channel\n'); end % else % fprintf(io,'CHAN%d',channel); % fprintf(io,'AUTO'); % if verbose >=2, fprintf(1, 'kpib/HP_8753ES: Autoscale channel %d\n',channel); end % end % else % fprintf(io, 'DISP:TRAC:Y:AUTO ONCE'); % if verbose >=2, fprintf(1, 'kpib/HP_8753ES: Autoscale Y Once Channel 1 (default channel)\n'); end % end % case 'both' % specific to resonators - autoscale channels 1 & 2 % fprintf(io,'CHAN1'); fprintf(io,'AUTO'); % fprintf(io,'CHAN2'); fprintf(io,'AUTO'); % fprintf(io,'CHAN1'); % if verbose >=2, fprintf(1, 'kpib/HP_8753ES: Autoscale channels 1 & 2\n'); end % % otherwise % if isnumeric(value) & value == (1 | 2 | 3 | 4) % fprintf(io,'CHAN%d',channel); % fprintf(io,'AUTO'); % if verbose >=2, fprintf(1, 'kpib/HP_8753ES: Autoscale channel %d\n',channel); end % else % fprintf(io,'AUTO'); % if verbose >=2, fprintf(1, 'kpib/HP_8753ES: Autoscale Y current channel (default)\n'); end % end % end % else % fprintf(io, 'DISP:TRAC:Y:AUTO ONCE'); % if verbose >=2, fprintf(1, 'kpib/HP_8753ES: Auto Scale Y default: Once\n'); end % end case 'scale' %ok if isnumeric(value) fprintf(io,'LG %fDB',value); if verbose >= 2, fprintf(1, 'kpib/HP_8560A: Scale of current channel set to %g dB/div.\n',value); end % elseif isequal(value,'auto') % fprintf(io,'AUTO'); % if verbose >= 2, fprintf(1, 'kpib/HP_8560A: Autoscale current channel.\n'); end end case {'ref line','reflevel'} %ok fprintf(io,'RL %fDBM',value); if verbose >= 2, fprintf(1, 'kpib/HP_8560A: Reference value set to %g dBm.\n',value); end case {'average','averaging'} %ok switch value case {'on'} if verbose >= 2, fprintf(1, 'kpib/HP_8560A: Averaging on'); end if isnumeric(channel) && channel > 0 fprintf(io,'VAVG %f',channel); if verbose >= 2, fprintf(1, ', aver. factor %d.\n',channel); end else fprintf(io,'VAVG ON'); if verbose >= 2, fprintf(1,'.\n'); end end case {'off'}; fprintf(io,'VAVG OFF'); if verbose >= 2, fprintf(1, 'kpib/HP_8560A: Averaging off.\n'); end case {'num','number','count'} if verbose >= 2, fprintf(1, 'kpib/HP_8560A: Warning: Average Count not available on 8560A\n'); end case{'restart','Restart'} fprintf(io,'AVERREST'); case {'query','?'} fprintf(io,'VAVG?'); retval = fscanf(io,'%f'); if verbose >= 2, fprintf(1, 'kpib/HP_8560A: Averaging factor is: %g\n', retval); end otherwise % set the number of measurements to average if isnumeric(value) && value > 0 fprintf(io,'VAVG %F',channel); if verbose >=2, fprintf(1, 'kpib/HP_8560A: Averaging factor set to: %d\n',value); end end end case {'marker'} %ok if isnumeric(value) % move marker to that point cmd=sprintf('MKF %fHZ',value); fprintf(io,cmd); if verbose >= 2, fprintf(1, 'kpib/HP_8560A: Marker set to %f Hz\n',value); end else switch value case 'on' % there is no "marker on", we have to give a frequency fprintf(io,'CF?'); cf=fscanf(io,'%f'); fprintf(io,'MKF %fHZ',cf); if verbose >= 2, fprintf(1, 'kpib/HP_8560A: Marker ON\n'); end case 'off' fprintf(io,'MKOFF'); if verbose >= 2, fprintf(1, 'kpib/HP_8560A: Marker OFF\n'); end case {'query','?'} % query the marker position switch aux case {'x','X'} fprintf(io,'MKF?'); retval = fscanf(io,'%f'); if verbose >= 2, fprintf(1,'kpib/HP_8560A: Marker position: %g Hz\n',retval); end case {'y','Y'} fprintf(io,'MKA?'); retval = fscanf(io,'%f'); if verbose >= 2, fprintf(1,'kpib/HP_8560A: Marker position: %g\n',retval); end otherwise fprintf(io,'MKF?'); retval.x = fscanf(io,'%f'); fprintf(io,'MKA?'); retval.y = fscanf(io,'%f'); if verbose >= 2, fprintf(1,'kpib/HP_8560A: Marker position: %g Hz/%g\n',retval.x,retval.y); end end case {'center','m2c','mark2center'} % make the marker position the center freq fprintf(io,'MKCF'); if verbose >= 2, fprintf(1,'kpib/HP_8560A: Marker to Center\n'); end case {'peak','searchpeak','mark2peak','max'} fprintf(io,'MKPK HI'); if verbose >= 2, fprintf(1,'%s\n','kpib/HP_8560A: Marker to Peak (max)'); end case {'min','valley'} fprintf(io,'MKMIN'); if verbose >= 2, fprintf(1,'%s\n','kpib/HP_8560A: Marker to Valley (min)'); end otherwise if verbose >= 1, fprintf(1, 'kpib/HP_8560A: Error at ''marker'' command (VALUE incorrect ["%s"]).\n',value); end end end case {'mark2peak','m2p','findpeak'} %ok switch value case 'off' fprintf(io,'MKTRACK OFF'); if verbose >= 2, fprintf(1,'%s\n','kpib/HP_8560A: Marker Search Off'); end case 'center' fprintf(io,'MKPK HI;MKCF'); if verbose >= 2, fprintf(1,'%s\n','kpib/HP_8560A: Peak (max) to Center'); end case {'peak','max'} fprintf(io,'MKPK HI;MKTRACK ON'); if verbose >= 2, fprintf(1,'%s\n','kpib/HP_8560A: Marker to Peak (max)'); end % case 'min' % if verbose >= 2, fprintf(1,'%s\n','kpib/HP_8753ES: Marker to minimum'); end % fprintf(io,'SEAMIN'); otherwise fprintf(io,'MKPK HI'); if verbose >= 2, fprintf(1,'%s\n','kpib/HP_8560A: Marker to Max (default)'); end end case {'peaktrack'} %ok switch value case {'on',1} fprintf(io,'MKPK HI;MKTRACK ON'); if verbose >= 2, fprintf(1,'%s\n','kpib/HP_8560A: Marker Peak Tracking ON'); end case {'off',0} fprintf(io,'MKTRACK OFF'); if verbose >= 2, fprintf(1,'%s\n','kpib/HP_8560A: Marker Peak Tracking OFF'); end otherwise if verbose >= 2, fprintf(1,'%s\n','kpib/HP_8560A: ERROR: do you want Peak Tracking on or off?'); end end % % case 'sweep' % % % enable the status registers for synchronization % fprintf(io,'CLES'); % clear the status registers % fprintf(io,'*SRE 4;ESNB 1'); % enable the registers; % % if isnumeric(value) % set the sweep time % fprintf(io,'SWET%d',value); % else % switch value % case {'auto','AUTO'} % fprintf(io,'SWEA'); % case {'linear freq'} % fprintf(io,'LINFREQ'); % case {'list freq'} % fprintf(io,'LISFREQ'); % case {'log freq'} % fprintf(io,'LOGFREQ'); % case {'power sweep'} % fprintf(io,'POWS'); % case {'single','sing','SING'} % fprintf(io,'SING'); % case {'continuous','cont','CONT'} % fprintf(io,'CONT'); % case {'group','groups','number','N'} % if isnumeric(channel) & channel >= 1 & channel <= 999 % fprintf(io,'NUMG%d',channel); % else % if verbose >= 1, fprintf(1, 'kpib/HP_8753ES: Sweep Error: Number or sweeps must be between 1 and 999.\n'); end % end % case {'points','numpoints','setpoints'} % if isnumeric(channel) & channel >= 2 & channel <= 801 % fprintf(io,'POIN%i',channel); % else % if verbose >= 1, fprintf(1, 'kpib/HP_8753ES: Sweep Error: Number of points must be between 2 and 801.\n'); end % end % otherwise % if verbose >= 1, fprintf(1, 'kpib/HP_8753ES: Sweep command not supported ["%s"]\n',value); end % end % end case 'center' %ok switch value case {'query','?'} fprintf(io,'CF?'); retval = fscanf(io,'%f'); otherwise fprintf(io,'CF %fHZ',value); if verbose >= 2, fprintf(1, 'kpib/HP_8560A: Center set to %f Hz\n',value); end end case 'span' %ok switch value case {'query','?'} fprintf(io,'SP?'); retval = fscanf(io,'%f'); otherwise fprintf(io,'SP %fHZ',value); if verbose >= 2, fprintf(1, 'kpib/HP_8560A: Span set to %g Hz\n',value); end end case 'start' %ok switch value case {'query','?'} fprintf(io,'FA?'); retval = fscanf(io,'%f'); otherwise fprintf(io,'FA %fHZ',value); if verbose >= 2, fprintf(1, 'kpib/HP_8560A: Start set to %g Hz\n',value); end end case 'stop' %ok switch value case {'query','?'} fprintf(io,'FB?'); retval = fscanf(io,'%f'); otherwise fprintf(io,'FB %fHZ',value); if verbose >= 2, fprintf(1, 'kpib/HP_8560A: Stop set to %g Hz\n',value); end end case {'power','source'} %ok if isnumeric(value) && value >= -10 && value <= 2.8 fprintf(io,'SRCPWR %fDBM',value); if verbose >= 2, fprintf(1, 'kpib/HP_8560A: Source Power set to %g dBm\n',value); end else switch value case {'query','?'} fprintf(io,'SRCPWR?'); retval = fscanf(io,'%f'); if verbose >= 2, fprintf(1, 'kpib/HP_8560A: Source Power is %d dBm\n',retval); end case {'on','ON'} fprintf(io,'SRCPWR ON'); if verbose >= 2, fprintf(1, 'kpib/HP_8560A: Source Power ON\n'); end case {'off','OFF'} fprintf(io,'SRCPWR OFF'); if verbose >= 2, fprintf(1, 'kpib/HP_8560A: Source Power OFF\n'); end end end case {'power?','source?'} %ok fprintf(io,'SRCPWR?'); retval.level = fscanf(io,'%f'); if verbose >= 2, fprintf(1, 'kpib/HP_8560A: Source Power: %g dBm\n',retval.level); end retval.state='unknown'; % no query for state % case 'bandwidth' % if isnumeric(value) % fprintf(io,'BW %d',value); % elseif isequal(value,'auto') % if isequal(channel,'on') | isequal(channel,'off') % fprintf(io,'BWAUTO %s',channel); % end % elseif isequal(value,'limit') % if isnumeric(channel) % fprintf(io,'BWLMT%d',channel); % else % if verbose >= 2, fprintf(1, 'kpib/HP_8753ES: A numeric value must be entered for channel.\n'); end % end % end % case 'trigger' % switch value % case 'internal' % fprintf(io,'TRGS INT'); % case 'external' % fprintf(io,'TRGS EXT'); % case 'GPIB' % fprintf(io,'TRGS BUS'); % case 'video' % fprintf(io,'TRGS VID'); % case 'manual' % fprintf(io,'TRGS MAN'); % case 'ext gate' % fprintf(io,'TRGS GAT'); % otherwise % if isequal(value,'int') | isequal(value,'ext') | isequal(value,'vid') | isequal(value,'man') | isequal(value,'gat') | isequal(value,'bus') % fprintf(io,'TRGS %s',value); % else % if verbose >= 2, fprintf(1, 'kpib/HP_8753ES: Not a valid trigger.\n'); end % end % end case {'getdata'} % use real numbers (aka "parameters') % Returns comma-delimited string, 601 points % no comma at the end of the string makes format matching % annoying % Y-values only fprintf(io, 'TDF P;TRA?'); ydata = fscanf(io); ydata=[ydata ',']; % add a comma at the end for matching retval.y=sscanf(ydata,'%f,'); numdatapoints = length(retval.y); %retval.y=data if numdatapoints == 0 if verbose >= 1, fprintf('kpib/HP_8560A: ERROR: Data download error (0 points).\n'); end else if verbose >= 2, fprintf('kpib/HP_8560A: Data downloaded (%d points).\n',numdatapoints); end end % Now we must infer the X values %numdatapoints = 601; fprintf(io,'CF?'); center = fscanf(io,'%f'); %center = str2num(center); fprintf(io,'SP?'); span = fscanf(io,'%f'); %span = str2num(span); start = center - span/2; delta = span/(numdatapoints-1); retval.x=([0:1:numdatapoints-1]*delta)'+start; % get the units retval.units.x = 'Hz'; % X is always in Hz, as far as I know % the units for Y amplitude depend on the Format fprintf(io,'AUNITS?'); rd = fscanf(io); retval.units.y = rd(1:end-1); % strip trailing LF if strcmpi(retval.units.y,'DBM') retval.units.y = 'dBm'; end if verbose >= 2, fprintf('kpib/HP_8560A: Y units are %s.\n',retval.units.y); end case 'units' %ok % See the manual p1-82 (Table 1-4) for units % query the display format, and then assume the units switch value case {'x','X'} % the units for X are always Hz retval='Hz'; if verbose >= 2, fprintf('kpib/HP_8560A: X units are %s\n',retval); end case {'y','Y'} fprintf(io,'AUNITS?'); rd = fscanf(io); retval = rd(1:end-1); % strip trailing LF if verbose >= 2, fprintf('kpib/HP_8560A: Y units are %s\n',retval); end otherwise retval.units.x='Hz'; fprintf(io,'AUNITS?'); rd = fscanf(io); retval.units.y = rd(1:end-1); % strip trailing LF if verbose >= 2, fprintf('kpib/HP_8560A: Units are %s/%s\n',retval.units.x,retval.units.y); end end % case 'pause' % % if isequal(value,'query') % fprintf(io,'HOLD?'); % retval = fscanf(io); % else % fprintf(io,'HD'); % if verbose >= 2, fprintf('kpib/HP_8753ES: Measurement paused.\n'); end % end case {'continue','cont'} %ok fprintf(io,'CONTS'); if verbose >= 2, fprintf('kpib/HP_8560A: Measurement continue.\n'); end case 'complete' %ok % the DONE command waits for the previous action to finish % can issue a single command for a sweep and complete % if nargin > 3 switch value case {'single','sing','SING'} if verbose >= 2, fprintf('kpib/HP_8560A: Single Sweep & Complete:\n'); end fprintf(io,'SINGS; TS; DONE?'); if verbose >= 2, fprintf('kpib/HP_8560A: Sweep... '); end stat=0; while ~stat % wait for sweep to complete stat=fread(io); pause(1); end if verbose >= 2, fprintf('Complete\n'); end end % end % or just a single command fprintf(io,'DONE?'); if verbose >= 2, fprintf('kpib/HP_8560A: Waiting for command to complete...'); end stat=0; while ~stat % wait for sweep to complete stat=fread(io); pause(1); end if verbose >= 2, fprintf('Done.\n'); end retval=stat; %warning off instrument:fscanf:unsuccessfulRead % retval=0; while 1 % pause(1); % fprintf(io,'ESB?'); % check the status byte % retval=str2num(fscanf(io,'%+f')); % esb=dec2bin(retval); % return binary value represents the status registers % if esb(end) == '1' % indicates sweep complete % if verbose >= 2, fprintf(1, 'kpib/HP_8753ES: Sweep complete.\n'); end % break; % end % if length(esb) > 6 % if esb(end-6) == '1' % indicates "Target not found" % if verbose >= 2, fprintf(1, 'kpib/HP_8753ES: Analyzer reports: "Target not Found".\n'); end % end % end % end % % % disp('END OF ESB') case 'wait' %ok warning off instrument:fscanf:unsuccessfulRead fprintf(io,'DONE?'); if verbose >= 2, fprintf('kpib/HP_8560A: Waiting for command to complete...'); end stat=fread(io); while ~stat % wait for sweep to complete pause(1); stat=fread(io); end retval=stat; if verbose >= 2, fprintf('Done.\n'); end otherwise if verbose >= 1, fprintf('kpib/HP_8560A: Error, command not supported. ["%s"]\n',command); end end else % catch incorrect address errors if verbose >= 1, fprintf('kpib/%s: ERROR: No instrument at GPIB %d\n',instrument,GPIB); end retval=0; end validInst=1; end % end HP_8560A
'HP_4284A' HP LCR Meter
Contributed by Robert Hennessey
%RETVAL = KPIB('INSTRUMENT', GPIB, 'COMMAND', VALUE, CHANNEL, AUX, VERBOSE) % Valid commands: %'freq' sets the oscillator frequency. the frequncy is 20 Hz to 1 MHz. % Frequencies outside of that range will be clipped. %'volt' sets the oscillator's output voltage. min voltage is 5 mV, max % voltage is 2V (high power mode is off), 20V (high power mode is % on). If needed, turns on high power. %'curr' sets the oscillator's output current. min current is 50uA. max % current is 20mA (high power mode is off) and 200mA (high power % mode is on). Note: max turns ALC off. If needed, turns on high % power. %'ALCON' used to turn the automatic level control on %'ALCOFF' used to turn the automatic level control off %'HPOWON' High power turned off %'HPOWOFF' High power is turned off %'BIASON' Turns the bias on. Note: the bias is turned off when the device % is given *RST. The bias is also turned off when control % settings are loaded from memory %'BIASOFF' Turns the bias off %'VDC' sets the dc bias voltage. Must call BIASON to turn on the bias % voltage. min = 0V max = 2V (high power mode is off) or 40V % (high power mode is on) %'IDC' sets the dc bias current. Must call BIASON to turn on the bias % current. min = 0A max = 100mA (high power mode is on) Note: % Applying IDC will reduce the voltage seen by the DUT (see 9-24 % pg. 366 of the user manual) %'IMP' sets the measurement function. The type of functions are % CPD Sets function to Cp-D LPRP Sets function to Lp-Rp % CPQ Sets function to Cp-Q LSD Sets function to Ls-D % CPG Sets function to Cp-G LSQ Sets function to Ls-Q % CPRP Sets function to Cp-Rp LSRS Sets function to Ls-Rs % CSD Sets function to Cs-D RX Sets function to R-X % CSQ Sets function to Cs-Q ZTD Sets function to Z-theta (deg) % CSRS Sets function to Cs-Rs ZTR Sets function to Z-theta (rad) % LPQ Sets function to Lp-Q GB Sets function to G-B % LPD Sets function to Lp-D YTD Sets function to Y-theta (deg) % LPG Sets function to Lp-G YTR Sets function to Y-theta (rad) %'IMPAUTO' turns on or off the auto range. The auto range should be turned % on for almost all measurements %'TRIG' causes the trigger to execute a measurement or a sweep % meaurement %'INITCONT' If set to on, the idle state is automatically set to wait for % trigger. To start taking measurements, 'TRIG' command needs to % be used after this command. %'FETCH' retrieves the measurement data taken by measurements initiated % by a trigger, and places the data into the output buffer. % Also 'read' or 'getdata'. %'FORMAT' sets the data output formats. value = ASCII or REAL (uses % floating point to represent the data) %'TRIGSOURCE' sets the trigger mode. The bus mode will probably be used % in most instances. values = INT, EXT, BUS, HOLD %'ERROR' Returns the error number and error message. if (strcmpi(instrument, 'HP_4284A') || strcmpi(instrument, 'all')) io = port(GPIB, instrument, 0, verbose); if (io ~=0) && (strcmp(get(io,'Status'),'open') ~=0) switch command case {'f', 'freq', 'frequency'} if(value<20) fprintf(io,'FREQ MIN'); if verbose >= 2 fprintf('kpib/HP_4284A: Frequency clipped to min (20 Hz) \n') end elseif(value>1e6) fprintf(io,'FREQ MAX'); if verbose >= 2 fprintf('kpib/HP_4284A: Frequency clipped to max (1 MHz) \n') end else fprintf(io,'FREQ %f',value); if verbose >= 2 fprintf('kpib/HP_4284A: Frequency set to %f Hz \n',value) end end case {'V', 'volt', 'voltage'} if(value<5e-3) fprintf(io,'VOLT MIN'); if verbose >= 2 fprintf('kpib/HP_4284A: Voltage clipped to min (5 mV) \n') end elseif(value >= 5e-3 && value <=2) fprintf(io,'VOLT %f', value); if verbose >= 2 fprintf('kpib/HP_4284A: Voltage set to %f V \n', value) end elseif(value >2 && value <=20) fprintf(io,'Outp:HPOW ON'); fprintf(io,'VOLT %f', value); if verbose >= 2 fprintf('kpib/HP_4284A: High power turned on \n') fprintf('kpib/HP_4284A: Voltage set to %f V \n', value) end else fprintf(io,'Outp:HPOW ON'); fprintf(io,'VOLT MAX'); if verbose >= 2 fprintf('kpib/HP_4284A: High power turned on \n') fprintf('kpib/HP_4284A: Voltage clipped to Max (20V) \n') end end case{'I','curr','current'} if(value<50e-6) fprintf(io,'CURR MIN'); if verbose >= 2 fprintf('kpib/HP_4284A: Current clipped to min (50 uA) \n') end elseif(value >= 50e-6 && value <=20e-3) fprintf(io,'CURR %f', value); if verbose >= 2 fprintf('kpib/HP_4284A: Current set to %f A \n', value) end elseif(value >20e-3 && value <=200e-3) fprintf(io,'Outp:HPOW ON'); fprintf(io,'CURR %f', value); if verbose >= 2 fprintf('kpib/HP_4284A: High power turned on \n') fprintf('kpib/HP_4284A: Current set to %f A \n', value) end else fprintf(io,'Outp:HPOW ON'); fprintf(io,'CURR MAX'); if verbose >= 2 fprintf('kpib/HP_4284A: High power turned on \n') fprintf('kpib/HP_4284A: Voltage clipped to Max (200 mA) \n') end end case 'ALCON' fprintf(io,'AMPL:ALC ON'); if verbose >= 2 fprintf('kpib/HP_4284A: Automated Level Control turned on \n') end case 'ALCOFF' fprintf(io,'AMPL:ALC OFF'); if verbose >= 2 fprintf('kpib/HP_4284A: Automated Level Control turned off \n') end case 'HPOWON' fprintf(io,'OUTP:HPOW ON'); if verbose >= 2 fprintf('kpib/HP_4284A: High Power turned on \n') end case 'HPOWOFF' fprintf(io,'OUTP:HPOW OFF'); if verbose >= 2 fprintf('kpib/HP_4284A: High Power turned off \n') end case 'BIASON' fprintf(io,'BIAS:STAT ON'); if verbose >= 2 fprintf('kpib/HP_4284A: Bias turned on \n') end case 'BIASOFF' fprintf(io,'BIAS:STAT OFF'); if verbose >= 2 fprintf('kpib/HP_4284A: Bias turned off \n') end case 'VDC' if(value < 0) fprintf(io,'BIAS:VOLT MIN'); if verbose >= 2 fprintf('kpib/HP_4284A: VDC clipped at min (0V) \n') end elseif(value >=0 && value <= 2) fprintf(io,'BIAS:VOLT %f',value); if verbose >= 2 fprintf('kpib/HP_4284A: VDC set at %f V \n', value) end elseif(value >2 && value <= 40) fprintf(io,'Outp:HPOW ON'); fprintf(io,'BIAS:VOLT %f',value); if verbose >= 2 fprintf('kpib/HP_4284A:High Power turned on\n') fprintf('kpib/HP_4284A: VDC set at %f V \n', value) end else fprintf(io,'Outp:HPOW ON'); fprintf(io,'BIAS:VOLT MAX'); if verbose >= 2 fprintf('kpib/HP_4284A:High Power turned on\n') fprintf('kpib/HP_4284A: VDC clipped at max (40 V) \n') end end case 'IDC' fprintf(io,'BIAS:CURR %f', value); if verbose >= 2 fprintf('kpib/HP_4284A: IDC set to %f \n', value) end case 'IMP' SupVals = {'CPD','CPQ','CPG','CPRP','CSD','CSQ','CSRS','LPQ','LPD','LPG','LPRP','LSD','LSQ','LSRS','RX','ZTD','ZTR','GB','YTD','YTR'}; if(isempty(strfind(SupVals,value))) if(verbose >= 2) fprintf('kpib/HP_4284A: Typo in call to IMP. check %s \n', value); end else fprintf(io,'FUNC:IMP %s', value); if(verbose >= 2) fprintf('kpib/HP_4284A: Measurement function is set to %s \n', value); end end case 'IMPAUTO' switch(value) case {'on', 'ON'} fprintf(io,'FUNC:IMP:RANG:AUTO ON'); if(verbose >= 2) fprintf('kpib/HP_4284A: Impedence auto range turned on \n'); end case {'off', 'OFF'} fprintf(io,'FUNC:IMP:RANG:AUTO OFF'); if(verbose >= 2) fprintf('kpib/HP_4284A: Impedence auto range turned off \n'); end otherwise if(verbose >= 1) fprintf('kpib/HP_4284A: Error using impedence auto range. value = on or off \n'); end end case {'trig','TRIG','trigger'} fprintf(io,'TRIG:IMM'); if(verbose >= 2) fprintf('kpib/HP_4284A: Triggered measurement\n'); end case 'INITCONT' switch(value) case{'on', 'ON'} fprintf(io,'INIT:CONT ON'); if(verbose >= 2) fprintf('kpib/HP_4284A: Trigger continuous mode turned on \n'); end case{'OFF', 'off'} fprintf(io,'INIT:CONT OFF'); if(verbose >= 2) fprintf('kpib/HP_4284A: Trigger continuous mode turned off \n'); end otherwise if(verbose >= 1) fprintf('kpib/HP_4284A: Error using trigger continuous mode. value = on or off \n'); end end case {'FETCH','read','getdata'} fprintf(io,'FORM?'); ASCIION = strcmp(fscanf(io,'%s'),'ASC'); fprintf(io,'FETC?'); if(ASCIION) [t1 count]=fscanf(io,'%s'); %#ok<NASGU> %the following code assumes that the output mode is ascii %one data point if(length(t1) < 29 || t1(29)~=',') retval.meas1=str2num(t1(1:12)); retval.meas2=str2num(t1(14:25)); retval.status=str2num(t1(27:28)); retval.binNumb=str2num(t1(29:length(t1))); if(verbose >= 2) fprintf('kpib/HP_4284A: Fetching data \n'); fprintf('kpib/HP_4284A: meas1= '); fprintf('%d ',retval.meas1); fprintf('\nkpib/HP_4284A: meas2= '); fprintf('%d ',retval.meas2); fprintf('\nkpib/HP_4284A: status= '); fprintf('%d ',retval.status); fprintf('\nkpib/HP_4284A: binNumb= '); fprintf('%d ',retval.binNumb); fprintf('\n'); end %more than one data point else conString = str2num(t1); lenConString = length(conString); retval.meas1=conString(1:4:lenConString); retval.meas2=conString(2:4:lenConString); retval.status=conString(3:4:lenConString); retval.InOut=conString(4:4:lenConString); if(verbose >= 2) fprintf('kpib/HP_4284A: Fetching data \n'); fprintf('kpib/HP_4284A: meas1= '); fprintf('%d ',retval.meas1); fprintf('\nkpib/HP_4284A: meas2= '); fprintf('%d ',retval.meas2); fprintf('\nkpib/HP_4284A: status= '); fprintf('%d ',retval.status); fprintf('\nkpib/HP_4284A: InOut= '); fprintf('%d ',retval.InOut); fprintf('\n'); end end else %bit format % These lines were "fixed"but not tested for R2012 % (v4.96) % header=char(fread(io,1,'char')); % NumbHeader=str2num(char(fread(io,1,'char'))); % numberBytes=str2num((char(fread(io,NumbHeader,'char')))'); %header=fread(io,1,'char'); NumbHeader=str2num(fread(io,1,'char')); numberBytes=str2num((fread(io,NumbHeader,'char'))'); % NumbHeader=fread(io,1,'int8') % numberBytes=0; % for i=1:1:NumbHeader % numberBytes=10*numberBytes+fread(io,1,'int8') % end if(numberBytes<=25) % 1 data point %test retval.meas1=BitToFloat(fread(io,8,'char')); retval.meas2=BitToFloat(fread(io,8,'char')); retval.status=fread(io,1,'double'); fread(io,2,'char'); %remove the ending 0 and new line if(verbose >= 2) fprintf('kpib/HP_4284A: Fetching data Float Mode\n'); fprintf('kpib/HP_4284A: meas1= '); fprintf('%d ',retval.meas1); fprintf('\nkpib/HP_4284A: meas2= '); fprintf('%d ',retval.meas2); fprintf('\nkpib/HP_4284A: status= '); fprintf('%d ',retval.status); fprintf('\n'); end elseif(numberBytes>25 && numberBytes<=33) retval.meas1=BitToFloat(fread(io,8,'char')); retval.meas2=BitToFloat(fread(io,8,'char')); retval.status=fread(io,1,'double'); retval.binNumb=fread(io,1,'double'); fread(io,2,'char'); %remove the ending 0 and new line if(verbose >= 2) fprintf('kpib/HP_4284A: Fetching data \n'); fprintf('kpib/HP_4284A: meas1= '); fprintf('%d ',retval.meas1); fprintf('\nkpib/HP_4284A: meas2= '); fprintf('%d ',retval.meas2); fprintf('\nkpib/HP_4284A: status= '); fprintf('%d ',retval.status); fprintf('\nkpib/HP_4284A: binNumb= '); fprintf('%d ',retval.binNumb); fprintf('\n'); end else %more than 1 datapoint. read in one byte at a time. for i=1:1:(numberBytes/24) retval.meas1(i)=BitToFloat(fread(io,8,'char')); retval.meas2(i)=BitToFloat(fread(io,8,'char')); retval.status(i)=fread(io,1,'double'); retval.InOut(i)=fread(io,1,'double'); end if(verbose >= 2) fprintf('kpib/HP_4284A: Fetching data \n'); fprintf('kpib/HP_4284A: meas1= '); fprintf('%d ',retval.meas1); fprintf('\nkpib/HP_4284A: meas2= '); fprintf('%d ',retval.meas2); fprintf('\nkpib/HP_4284A: status= '); fprintf('%d ',retval.status); fprintf('\nkpib/HP_4284A: InOut= '); fprintf('%d ',retval.InOut); fprintf('\n'); end end end case {'format','FORMAT','fmt'} switch(value) case {'ASCII', 'ascii'} fprintf(io,'FORM ASC'); if(verbose>=2) fprintf('kpib/HP_4284A: Output format set to ASCII\n'); end case {'REAL', 'real'} fprintf(io,'FORM REAL'); if(verbose>=2) fprintf('kpib/HP_4284A: Output format set to REAL\n'); end otherwise if(verbose>=1) fprintf('kpib/HP_4284A: Error setting output format. value = ASCII or REAL\n'); end end case 'TRIGSOURCE' switch(value) case {'bus','BUS'} fprintf(io,'TRIG:SOUR BUS'); if(verbose>=2) fprintf('kpib/HP_4284A: Trigger set to bus mode\n'); end case {'EXT','ext'} fprintf(io,'TRIG:SOUR EXT'); if(verbose>=2) fprintf('kpib/HP_4284A: Trigger set to external mode\n'); end case {'int','INT'} fprintf(io,'TRIG:SOUR INT'); if(verbose>=2) fprintf('kpib/HP_4284A: Trigger set to internal mode\n'); end case {'hold','HOLD'} fprintf(io,'TRIG:SOUR HOLD'); if(verbose>=2) fprintf('kpib/HP_4284A: Trigger set to hold mode\n'); end otherwise if(verbose>=1) fprintf('kpib/HP_4284A: Error setting trigger mode\n'); end end case {'error','ERROR'} fprintf(io,'SYST:ERR?'); %pause(1) ind=1; numbChar = fread(io,1,'char'); while(numbChar ~= 44) %44=ascii code for , numbStr(ind)=char(numbChar); ind=ind+1; numbChar = fread(io,1,'char'); end errorNum=str2num(numbStr); %get rid of the first " numbChar = fread(io,1,'char'); %#ok<NASGU> ind=1; numbChar = fread(io,1,'char'); while(numbChar ~= 34) %34 = ascii code for " errStr(ind)=char(numbChar); ind=ind+1; numbChar = fread(io,1,'char'); end fread(io,1,'char'); %remove the end of line character retval=errorNum; %retval=0 if no error has occured if(verbose>=1) fprintf('kpib/HP_4284A: %d, %s\n',errorNum,errStr); end case {'*rst','reset'} fprintf(io,'*RST'); otherwise if verbose >= 1, fprintf(1, 'kpib/HP_4284A: Error, command not supported. ["%s"]\n',command); end % %% end else % catch incorrect address errors if verbose >= 1, fprintf('kpib/%s: ERROR: No instrument at GPIB %s\n',instrument,num2str(GPIB)); end end validInst = 1; end % end HP_4284A
'HP_3499B' Multiplexer
Contributed by Renata Melamud
%RETVAL = KPIB('INSTRUMENT', GPIB, 'COMMAND', VALUE, CHANNEL, AUX, VERBOSE) % % Note: When calling kpib with this instrument, refer below to command % specific meaning of value and channel. % % Valid Commands: % 'init' Sends the *RST command to reset instrument. Clears Errors. % Does a self test to make sure device passes. Returns 0 if % device passes or other errors described p.172 of manual. % 'funcmode' Sets the mode of the MUX for a particular slot (channel) % VALUE = slot # % CHANNEL = mode # % mode #1: 80 channel, 1 wire MUX % mode #2: 40 channel, 2 wire MUX % mode #3: two 20 channel 2 wire MUX % mode #4: 20 channel 4 wire MUX % 'monitor' Turns on the monitor channel functionality on the MUX front display % VALUE = slot # % 'clearerr' Clears any errors % 'close' Close a channel in the specified slot (i.e. close switch) % VALUE = slot # % CHANNEL = channel # or array of channel # % 'open' Open a channel in the specified slot (i.e. open switch) % VALUE = slot # % CHANNEL = channel # or array of channel # % 'reset' Open all channels in the specified slot % VALUE = slot # if (strcmpi(instrument, 'HP_3499B') || strcmpi(instrument, 'AG_3499B') || strcmpi(instrument, 'all')) baudrate = 0; % buffer size for GPIB (0 for default), baud rate for serial port instruments io = port(GPIB, instrument, baudrate, verbose); if (io ~=0) && (strcmp(get(io,'Status'),'open') ~=0) switch command case 'init' fprintf(io, '*RST'); % reset instrument fprintf(io, '*CLS'); % clear any errors fprintf(io, '*TST?'); % self test retval = fscanf(io); % result of self test if str2num(retval) %RETVAL != 0 if failed fprintf(1, 'kpib/%s: MUX did not pass self test (code %s).\n',instrument,str2num(retval)); end if verbose >= 1, fprintf(1, 'kpib/%s: Initialization passed.\n',instrument); end case 'funcmode' fprintf(io, 'ROUT:FUNC %d,%d',[value channel]); switch channel case 1 modetype = '(1) 80 channel, 1 wire MUX'; case 2 modetype = '(2) 40 channel, 2 wire MUX'; case 3 modetype = '(3) two 20 channel 2 wire MUX'; case 4 modetype = '(4) 20 channel 4 wire MUX'; otherwise fprintf(1, 'HP_3499B does not recognize this funcmode (1-4 only)'); return; end if verbose >= 2, fprintf(1, 'kpib/%s: Mode on slot %d is set to %s.\n',instrument, value, modetype); end case 'monitor' if isnumeric(value) fprintf(io, 'DIAG:MON %d', value); if verbose >= 2, fprintf(1, 'kpib/%s: Monitoring is turned on.\n',instrument); end else fprintf(1, 'kpib/%s: Monitoring requires slot #\n',instrument); end case 'clearerr' fprintf(io, '*CLS'); if verbose >= 2, fprintf(1, 'kpib/%s: All errors cleared.\n',instrument); end case 'close' if length(channel)>1 % close multiple channels given in array channel mychannels = sprintf('%d,',value*100+channel); fprintf(io, 'ROUT:CLOS (@%s)', mychannels); if verbose >= 2, fprintf(1, 'kpib/%s: Closing channels (%s).\n',instrument, mychannels); end else % close just one channel fprintf(io, 'ROUT:CLOSE (@%d)', value*100+channel); if verbose >= 2, fprintf(1, 'kpib/%s: Closing channels (%d).\n',instrument, value*100+channel); end end case 'open' if length(channel) >1 % open multiple channels given in array channel mychannels = sprintf('%d,',value*100+channel); fprintf(io, 'ROUT:OPEN (@%s)', mychannels); if verbose >= 2, fprintf(1, 'kpib/%s: Opening channels (%s).\n',instrument, mychannels); end else % close just one channel fprintf(io, 'ROUT:OPEN (@%d)', value*100+channel); if verbose >= 2, fprintf(1, 'kpib/%s: Opening channels (%d).\n',instrument, value*100+channel); end end case 'slotreset' fprintf(io, 'SYST:CPON %d', value); if verbose >= 2, fprintf(1, 'kpib/%s: Open all channels in slot %d.\n',instrument,value); end case 'hardreset' fprintf(io, '*RST'); if verbose >= 2, fprintf(1, 'kpib/%s: Reset instrument %d.\n',instrument,value); end otherwise if verbose >= 1, fprintf(1,'kpib/INSTRUMENT: Error, command not supported. ["%s"]\n',command); end end else % catch incorrect address errors if verbose >= 1, fprintf(1,'kpib/%s: ERROR: No instrument at GPIB %s\n',instrument,num2str(GPIB)); end end validInst = 1; end % End HP_3499B
'NP_3150' Newport Temperature Controller Model 3150
Contributed by Hyungkyu Lee
%RETVAL = KPIB('INSTRUMENT', GPIB, 'COMMAND', VALUE, CHANNEL, AUX, VERBOSE) % % Note: When call to kpib with this instrument, refer below to command % specific meaning of value and channel. % % % 'init' initialize instrument, and display current setting of the % controller % % 'read' read various values. % 'output' : output status( on/off ) % 'sensor' : sensor type (RTD,AD590 etc..) % 'mode' : control mode ( ITE, R and T ) % 'T' : current temperature % 'setT' : set temperature % 'highT' : high temperature limit % 'lowT' : low temperature limit % 'maxI' : maximum current thru TEC % 'gain' : gain for controller % 'tol' : tolerance and time window % 'cond' : condition of TEC % 'fin' : operation completed % % 'set' set various values. % 'output' : output status( on/off ) % 'sensor' : sensor type (RTD,AD590 etc..) % 'mode' : control mode ( ITE, R and T ) % 'T' : current temperature % 'setT' : set temperature % 'highT' : high temperature limit % 'lowT' : low temperature limit % 'maxI' : maximum current thru TEC % 'gain' : gain for controller % 'tol' : tolerance and time window % 'cond' : condition of TEC % % 'on' enable TEC output % % 'off' disable TEC output. Also 'stop'. if (strcmpi(instrument, 'NP_3150') || strcmpi(instrument, 'all')) baudrate = 0; % buffer size for GPIB (0 for default), baud rate for serial port instruments io = port(GPIB, instrument, baudrate, verbose); if (io ~=0) && (strcmp(get(io,'Status'),'open') ~=0) switch command case 'init' %fprintf(io, '*RST'); % reset instrument fprintf(io, '*CLS'); % clear any errors fprintf(io,'*OPC'); fprintf(io, '*TST?'); % self test retval = fscanf(io); % result of self test if str2num(retval) %RETVAL != 0 if failed fprintf(1, 'kpib/%s: Temp. controller did not pass self test (code %s).\n',instrument,retval); end if verbose >= 1, fprintf(1, 'kpib/%s: Initialization passed.\n',instrument); end fprintf(1,'**Controller Status Report:\n'); % get TEC output status kpib('NP_3150',GPIB,'read','output'); % get sensor type kpib('NP_3150',GPIB,'read','sensor'); % get mode(const Temp.,const Ref.,const ITE ) kpib('NP_3150',GPIB,'read','mode'); % get measured temperature kpib('NP_3150',GPIB,'read','T'); % get set temperature kpib('NP_3150',GPIB,'read','setT'); % get high temperature limit kpib('NP_3150',GPIB,'read','highT'); % get lower temperature limit kpib('NP_3150',GPIB,'read','lowT'); % get max. current limit thru TEC kpib('NP_3150',GPIB,'read','maxI'); % get TEC gain kpib('NP_3150',GPIB,'read','gain'); % get TEC gain kpib('NP_3150',GPIB,'read','gain'); % get Tolerance and time kpib('NP_3150',GPIB,'read','tol'); % get TEC condition kpib('NP_3150',GPIB,'read','cond'); % end of 'init' case 'read' switch value case {'output','out','Output','Out'} fprintf(io, 'TEC:OUTput?'); retval = fscanf(io); switch str2num(retval) case 0 output='off'; case 1 output='on'; end retval = output; if verbose >=2, fprintf(1,'kpib/%s: TEC output : %s\n',instrument,retval); end case {'T','t','Temp','temp','Temperature','temperature'} fprintf(io, 'TEC:T?'); retval = str2num(fscanf(io)); if verbose >=2, fprintf(1,'kpib/%s: Current Temperature: %.2d degree C\n',instrument,retval); end case {'setT','setTemp','settemp','setTemperature','settemperature'} fprintf(io,'TEC:SET:T?'); retval = str2num(fscanf(io)); if verbose >=2, fprintf(1, 'kpib/%s: Set Temperature: %.2d degree C\n',instrument,retval); end case {'highT','highLimit','hLimit','highLim'} fprintf(io,'TEC:LIMit:THI?'); retval = str2num(fscanf(io)); if verbose >=2, fprintf(1, 'kpib/%s: Temp. High Limit: %.1d degree C\n',instrument,retval); end case {'lowT','lowLimit','lLimit','lowLim'} fprintf(io,'TEC:LIMit:TLO?'); retval = str2num(fscanf(io)); if verbose >=2, fprintf(1, 'kpib/%s: Temp. Low Limit: %.1d degree C\n',instrument,retval); end case {'maxI','maxCurrent'} fprintf(io,'TEC:LIMit:ITE?'); retval = str2num(fscanf(io)); if verbose >=2, fprintf(1, 'kpib/%s: Max. Current Limit: %.1d ampere\n',instrument,retval); end case {'gain','Gain'} fprintf(io,'TEC:GAIN?'); retval = fscanf(io); if verbose >=2, fprintf(1, 'kpib/%s: Gain For Temp. Controller: %s',instrument,retval); end case{'mode','Mode'} fprintf(io,'TEC:MODE?'); retval = fscanf(io); if verbose >=2, fprintf(1, 'kpib/%s: Temp. Control Mode: %s',instrument,retval); end case {'sensor','Sensor','sens','SNSR','snsr'} fprintf(io,'TEC:SENsor?'); retval = fscanf(io); switch str2num(retval) case 0 sensor='None'; case 1 sensor='Thermistor at 100uA drive'; case 2 sensor='Thermistor at 10uA drive'; case 3 sensor='LM335'; case 4 sensor='AD590'; case 5 sensor='RTD'; otherwise sensor='None'; end retval = sensor; fprintf(1, 'kpib/%s: Temp. Sensor Type: %s\n',instrument,retval); case{'const','constants','constant','Const','Constants','Constant'} fprintf(io,'TEC:CONST?'); retval = fscanf(io); kpib('NP_3150',GPIB,'read','sensor'); fprintf(1, 'kpib/%s: TEC sensor constants: %s\n',instrument,retval); case{'cond','condition','Cond','Condition'} fprintf(io,'TEC:COND?'); retval = str2num(fscanf(io)); fprintf(1,'***** TEC condition report:\n'); if(retval == 0) fprintf(1,'kpib/%s: Everything is O.K. with TEC\n',instrument); end if(bitget(retval,1)==1) fprintf(1,'kpib/%s: TE Current Limit\n',instrument); end if(bitget(retval,2)==1) fprintf(1,'kpib/%s: Voltage Limit Error\n',instrument); end if(bitget(retval,3)==1) fprintf(1,'kpib/%s: R(reference) Limit\n',instrument); end if(bitget(retval,4)==1) fprintf(1,'kpib/%s: High Temperature Limit\n',instrument); end if(bitget(retval,5)==1) fprintf(1,'kpib/%s: Low Temperature Limit\n',instrument); end if(bitget(retval,6)==1) fprintf(1,'kpib/%s: Sensor Shorted\n',instrument); end if(bitget(retval,7)==1) fprintf(1,'kpib/%s: Sensor Shorted\n',instrument); end if(bitget(retval,8)==1) fprintf(1,'kpib/%s: Sensor Open\n',instrument); end if(bitget(retval,9)==1) fprintf(1,'kpib/%s: N/A \n',instrument); end if(bitget(retval,10)==1) fprintf(1,'kpib/%s: Output Out of Tolerance\n',instrument); end if(bitget(retval,11)==1) fprintf(1,'kpib/%s: Output On\n',instrument); end if(bitget(retval,12)==1) fprintf(1,'kpib/%s: Ready for Calibration Data\n',instrument); end if(bitget(retval,13)==1) fprintf(1,'kpib/%s: Calculation Error\n',instrument); end if(bitget(retval,14)==1) fprintf(1,'kpib/%s: TEC Interlock\n',instrument); end if(bitget(retval,15)==1) fprintf(1,'kpib/%s: Software Error\n',instrument); end if(bitget(retval,16)==1) fprintf(1,'kpib/%s: TEC EPROM Checksum Error\n',instrument); end case{'finish','fin','Finish','Fin','opc','OPC'} fprintf(io,'*OPC?'); retval = str2num(fscanf(io)); if(retval == 1) fprintf(1,'kpib/%s: Operation completed \n',instrument); else fprintf(1,'kpib/%s: Operation incomplete \n',instrument); end case{'tol','tolerance','Tol','Tolerance'} fprintf(io,'TEC:TOLerance?'); retval = fscanf(io); fprintf(1,'kpib/%s: Tolerance(degree),Time window(sec) : %s',instrument,retval); otherwise if verbose >= 1, fprintf(1,'kpib/%s: Error, command not supported. ["%s"]\n',instrument,command); end end %end of switch %end of 'read' case 'getdata' retval=kpib(instrument,GPIB,'read','T',channel,aux,verbose); case {'set','setT'} if isnumeric(value) % then set the temperature setpoint to that value % verify the high/low limit fprintf(io,'TEC:LIMit:THI?'); highlim = str2num(fscanf(io)); fprintf(io,'TEC:LIMit:TLO?'); lowlim = str2num(fscanf(io)); if value <= highlim && value >= lowlim fprintf(io,'TEC:T %f',value); if verbose >= 2, fprintf(1,'kpib/%s: Temperature setpoint set to %f C\n',instrument,value); end else if verbose >= 1, fprintf(1,'kpib/%s: WARNING: Temperature setpoint (%f C) outside the limits (%f/%f C)\n',instrument,value,lowlim,highlim); end end else % else set a specific setting of the instrument switch value case {'output','out','Output','Out'} if(isnumeric(channel)) fprintf(io,'TEC:OUTput %d',channel); else switch channel case {'on','On'} fprintf(io,'TEC:OUTput 1'); case {'off','Off'} fprintf(io,'TEC:OUTput 0'); end end kpib('NP_3150',GPIB,'read','output'); case {'t','T','Temp','temp','Temperature','temperature','setT'} kpib('NP_3150',GPIB,'read','T'); fprintf(io,'TEC:T %d',channel); if verbose >= 1 if( channel > kpib('NP_3150',GPIB,'read','highT') ) fprintf(1,'kpib/%s: %d degree C is over high temperature limit\n',instrument,channel); elseif ( channel < kpib('NP_3150',GPIB,'read','lowT')) fprintf(1,'kpib/%s: %d degree C is below lower temperature limit\n',instrument,channel); else fprintf(1,'kpib/%s: temperature is set to %d degree C\n',instrument,channel); end end case {'highT','highLimit','hLimit','highLim'} fprintf(io,'TEC:LIMit:THI %d',channel); kpib('NP_3150',GPIB,'read','highT'); case {'lowT','lowLimit','lLimit','lowLim'} fprintf(io,'TEC:LIMit:TLO %d',channel); kpib('NP_3150',GPIB,'read','lowT'); case {'maxI','maxCurrent','MaxI'} fprintf(io,'TEC:LIMit:ITE %d',channel); kpib('NP_3150',GPIB,'read','maxI'); case {'gain','Gain','G'} %gain : %'0.2S','0.6S','1S','1,'2S','3','5','6S','10S','20S' %'30','50','60S','100','300' if(isnumeric(channel)) fprintf(1,'kpib/%s: Error, gain value should be string. Possible gains are\n',instrument); fprintf(1,'kpib/%s: 0.2S,0.6S,1S,1,2S,3,5,6S,10S,20S,30,50,60S,100 and 300\n',instrument); else fprintf(io,'TEC:GAIN %s',channel); kpib('NP_3150',GPIB,'read','gain'); end case {'sensor','Sensor','sens','SNSR','snsr'} if(isnumeric(channel)) %1:Thermistor 100uA, 2:Thermistor 10uA, 3:LM335, %4:AD590, 5:RTD fprintf(io,'TEC:SENsor %d',channel); kpib('NP_3150',GPIB,'read','Sensor'); else switch channel case {'Th100','T100'} fprintf(io,'TEC:SENsor 1'); kpib('NP_3150',GPIB,'read','Sensor'); case {'Th10','T10'} fprintf(io,'TEC:SENsor 2'); kpib('NP_3150',GPIB,'read','Sensor'); case {'LM335'} fprintf(io,'TEC:SENsor 3'); kpib('NP_3150',GPIB,'read','Sensor'); case {'AD590'} fprintf(io,'TEC:SENsor 4'); kpib('NP_3150',GPIB,'read','Sensor'); case {'RTD'} fprintf(io,'TEC:SENsor 5'); kpib('NP_3150',GPIB,'read','Sensor'); end end case{'mode','Mode'} %mode: 'ITE':constant current mode % 'R' :constant resistance/linear sensor reference mode % 'T' :constant temperature mode fprintf(io,'TEC:MODE:%s',channel); kpib('NP_3150',GPIB,'read','mode'); case{'const','constants','constant','Const','Constants','Constant'} fprintf(io,'TEC:CONST:%s',channel); kpib('NP_3150',GPIB,'read','const'); case{'tol','tolerance','Tol','Tolerance'} fprintf(1,'tolerance in degree C(0.1 to 10.0)\n'); fprintf(1,'time window in seconds (0.001 to 50.000)\n'); fprintf(1,'ex: 0.11,50.0\n'); fprintf(io,'TEC:TOLerance %s',channel); kpib('NP_3150',GPIB,'read','tol'); case{'OPC'} fprintf(io,'*OPC'); fprintf(1,'kpib/%s: Operation Complete command\n',instrument); otherwise if verbose >= 1, fprintf(1,'kpib/%s: Error, command not supported. ["%s/%s"]\n',instrument,command,value); end end % end of switch end % end of 'set' case {'on','On','ON'} kpib('NP_3150',GPIB,'set','out','on'); % end of 'on' case {'off','Off','OFF','stop','STOP'} kpib('NP_3150',GPIB,'set','out','off'); % end of 'off' otherwise if verbose >= 1, fprintf(1,'kpib/%s: Error, command not supported. ["%s"]\n',instrument,command); end end else % catch incorrect address errors if verbose >= 1, fprintf(1,'kpib/%s: ERROR: No instrument at GPIB %s\n',instrument,num2str(GPIB)); end retval=0; end validInst = 1; end % End NP_3150
'VH_2701C' Valhalla 2701C voltage calibrator
Contributed by Jim Salvia
%RETVAL = KPIB('INSTRUMENT', GPIB, 'COMMAND', VALUE, CHANNEL, AUX, VERBOSE) % % Valid Commands: % 'init' Resets the instrument % 'read' Reads the output value. % Returns a value and units ('volts' or 'mamps') % 'setV' Sets the output voltage to VALUE in Volts. Also 'set' % Will bring the device out of standby mode into operate mode! % 'setI' Sets the output current to VALUE in mA. % Will bring the device out of standby mode into operate mode! % 'off' Goes to standby mode (output off) % 'on' Goes to operate mode (output on) % if (strcmpi(instrument, 'VH_2701C') || strcmpi(instrument, 'all')) io = port(GPIB, instrument, 0, verbose); if (io ~=0) && (strcmp(get(io,'Status'),'open') ~=0) % temp_str = fscanf(io,'%c'); switch command case {'init'} fprintf(io, 'S'); fprintf(io, 'L'); % Resets instrument. if verbose >= 2, fprintf(1, 'kpib/VH_2701C: Reset VH_2701C\n'); end case 'read' temp_str = fscanf(io,'%c'); %level,tempchar,opcode] = strread(temp_str,'%f%s%s'); t=textscan(temp_str,'%f%s'); level=t{1}; tempchar=t{2}; tempchar=tempchar{1}; if tempchar(end)=='*' opcode = 'standby'; else opcode = 'operating'; end if verbose >= 2, fprintf(1, 'kpib/VH_2701C '); end switch value % return a single value or both V & I? case {'volt','volts','V','v'} retval = level; if verbose >= 2, fprintf(1, 'reads %f Volts\n',retval); end if ~strcmp(tempchar,'V') if verbose >= 1, fprintf(1, 'kpib/VH_2701C: WARNING Volts requested but mAmps returned!\n'); end end case {'curr','I','A','current'} % read the current retval = level; if verbose >= 2, fprintf(1, 'reads %f Amps\n',retval); end if ~strcmp(tempchar,'mA') if verbose >= 1, fprintf(1, 'kpib/VH_2701C: WARNING mAmps requested but Volts returned!\n'); end end otherwise % return a structure with detailed info retval.value=level; retval.opcode = opcode; switch char(tempchar) % Voltage or current? case {'V'} % read a voltage retval.units = 'Volts'; retval.volts=level; if verbose >= 2, fprintf(1, 'kpib/VH_2701C reads %f Volts\n',retval.value); end case {'mA'} % read a current retval.units = 'mAmps'; retval.curr=level; if verbose >= 2, fprintf(1, 'kpib/VH_2701C reads %f mAmps\n',retval.value); end otherwise if verbose >= 1, fprintf('kpib/VH_2701C Error, returned string not recognized ["%s"]\n',temp_str); end end end case {'setV','volt','voltage','set'} % set the voltage if(value <= 120) fprintf(io, 'VO%f',value); % Sets voltage. if verbose >= 2, fprintf('kpib/VH_2701C Output Voltage set to %g Volts\n',value); end else fprintf(io, 'VO%f',0); % standby if the requested voltage is > 120V if verbose >= 1, fprintf('kpib/VH_2701C Requested voltage = %gV > 120V\nHigh voltage operation via KPIB has been disabled for safety\nOutput set to 0V\n',value); end end case {'setI','curr','current'} % set the current fprintf(io, 'II%f',value); % Sets current. if verbose >= 2, fprintf('kpib/VH_2701C Output Current set to %g mAmps\n',value); end case {'off','standby'} fprintf(io, 'S'); % Standby if verbose >= 2, fprintf(1, 'kpib/VH_2701C in Standby mode.\n'); end case {'on','operate'} fprintf(io, 'V'); % Operate mode. if verbose >= 2, fprintf(1, 'kpib/ VH_2701C in Operate Mode.\n'); end % case {'local'} % iof = instrfind('Type','gpib','PrimaryAddress',GPIB); % if ~isempty(iof) % fclose(iof); % delete(iof); % clear iof; % else % if verbose >= 1, fprintf('kpib: No instrument in memory at GPIB# %d.\n',g); end % end % if verbose >= 2, fprintf(1, ' VH_2701C in Local Mode.\n'); end otherwise if verbose >= 1, fprintf('kpib/Error, command not supported. ["%s"]\n',command); end end else % catch incorrect address errors if verbose >= 1, fprintf('kpib/%s: ERROR: No instrument at GPIB %d\n',instrument,GPIB); end retval=0; end validInst = 1; end % end VH_2701C
'VH_2701B' Valhalla 2701B voltage calibrator
Contributed by Jim Salvia
%RETVAL = KPIB('INSTRUMENT', GPIB, 'COMMAND', VALUE, CHANNEL, AUX, VERBOSE) % % Valid Commands: % 'set' Sets the output voltage to VALUE in Volts. % Will NOT bring the device out of standby mode into operate mode! % The device must be put into operate mode manually % % 'local' Will return the instrument to local control % Note that this returns the intrument's output voltage to that % displayed on the manual knobs on the front panel if (strcmpi(instrument, 'VH_2701B') || strcmpi(instrument, 'all')) io = port(GPIB, instrument, 0, verbose); if (io ~=0) && (strcmp(get(io,'Status'),'open') ~=0) switch command case {'read'} if verbose >=1, fprintf('kpib/VH_2701B: Warning: Read function not operational (DEC2007)\n'), end retval = 1776; case {'setV','volt','voltage','set'} % set the voltage if value < 0 value = abs(value); if verbose >=1, fprintf('kpib/VH_2701B: Warning: Cannout output negative voltages, using absolute value\n'), end end if (value > 120) safeval = 0; if verbose >= 1, fprintf('kpib/VH_2701B Warning: Requested voltage = %gV > 120V\nHigh voltage operation via KPIB has been disabled for safety\n',value); end else safeval = value; end if (safeval < 1000 && safeval >= 100) modvalue = sprintf('%6.0f',safeval/.001); fprintf(io, 'R3V%s',modvalue); % Sets voltage. elseif (safeval < 100 && safeval >= 10) modvalue = sprintf('%6.0f',safeval/.0001); fprintf(io, 'R2V%s',modvalue); % Sets voltage. elseif (safeval < 10 && safeval >= 1) modvalue = sprintf('%6.0f',safeval/.00001); fprintf(io, 'R1V%s',modvalue); % Sets voltage. elseif (safeval < 1) modvalue = sprintf('%6.0f',safeval/.000001); fprintf(io, 'R0V%s',modvalue); % Sets voltage. elseif safeval < 1100 && safeval >= 1000 modvalue = sprintf(':%5.0f',(safeval-1000)/.001); fprintf(io, 'R3V%s',modvalue); % Sets voltage. elseif safeval < 1200 && safeval >= 1100 modvalue = sprintf(';%5.0f',(safeval-1100)/.001); fprintf(io, 'R3V%s',modvalue); % Sets voltage. elseif safeval < 1210 && safeval >= 1200 modvalue = sprintf(';:%4.0f',(safeval-1200)/.001); fprintf(io, 'R3V%s',modvalue); % Sets voltage. else fprintf(io,'V000000'); fprintf('Requested Voltage Out of range %g not in [0V to 1200V]\n',value) value = 0; end if verbose >= 2, fprintf('Output Voltage set to %g Volts\n',safeval); end case {'on'} % does not work with our 2701B? fprintf(io,'V'); % manual p6-9 case {'off'} % does not work with our 2701B? fprintf(io,'S'); % manual p6-9 case {'local'} iof = instrfind('Type','gpib','PrimaryAddress',GPIB); if ~isempty(iof) fclose(iof); delete(iof); clear iof; else if verbose >= 1, fprintf('kpib: No instrument in memory at GPIB# %d.\n',g); end end if verbose >= 2, fprintf(1, ' VH_2701B in Local Mode.\n'); end otherwise if verbose >= 1, fprintf('Error, command not supported. ["%s"]\n',command); end end else % catch incorrect address errors if verbose >= 1, fprintf('kpib/%s: ERROR: No instrument at GPIB %d\n',instrument,GPIB); end retval=0; end validInst = 1; end % end VH_2701B
'HP_4195A' HP Network/Spectrum Analyzer
%RETVAL = KPIB('INSTRUMENT', GPIB, 'COMMAND', VALUE, CHANNEL, AUX, VERBOSE) % VALUE is typically the modifier to COMMAND. % Valid Commands: % 'init' Resets the Analyzer. Returns the decimal value of the status % byte (should be zero for normal condition). % 'label' Writes 'VALUE' to the display. % 'channel' Makes channel VALUE the active channel. NOTE: 'channel' (1|2) % corresponds to the Data Registers A and B. To select the % Test Input Channel, use the parameter 'aux' (1|2). Default is 1. % 'attenuate' Set the imput attenuation to level CHANNEL in dB. % VALUE can be 'T' or 'R' ('test' or 'reference'). % 'display' Controls what is displayed on the Analyzer screen. % VALUE can be any of the four registers: 'a','b','c','d' and % CHANNEL is 'on' or 'off'. % 'format' Set the format of the graph on the Analyzer display: % Linear, log/mag, etc. % non-exponentially ('norm'). Exponentially is the default. % 'scale' Sets the scale of the display. VALUE is the scale in the % current units, or 'VALUE' = 'auto' for autoscale command. % 'ref line' Sets the position of the reference line of the display. % VALUE is the position of the reference line in the current % units. % 'average' Turns averaging on or off, restarts averaging, or returns % the current number of averages taken. % VALUE='on','off','restart', or 'query'. % For 'query', RETVAL returns 0 (off) or the current number of averages (on). % 'mark2peak' Finds the peak and sets the marker, or finds the peak and % sets the peak location to the center of the scan. % VALUE='off','center', or 'peak'. % 'marker' Turns the marker on or off, or returns the current % position of the marker. 'VALUE' = 'on','off', or 'query'. % The position is returned as retval.x, retval.y in current % units. % 'center' Set the center frequency to VALUE. Units of Hz. % Query with VALUE = 'query', returns center frequency in Hz. % 'span' Set the frequency span VALUE. Units of Hz. % Query with VALUE = 'query', returns span in Hz. % 'sweep' Sets sweep parameters % 'source' Set the source (stimulus output) signal level. VALUE is the % desired signal level. Units of dBm. % Query with VALUE = 'query', returns source power in dBm. % 'source?' (Alternate query form) Returns source power in dBm and state (on|off). % 'power' Same as 'source'. % 'bias' The 4195A has a built-in DC source that can be used for % bias. The commands 'setV' and 'read' are supported, so that % the 4195 can pretend to be a power supply (e.g., you can % do: tools.biasset.instr = 'HP_4195A' ) % 'getdata' Download the current data trace from the analyzer. Data is % returned as two columns, x and y, for the specified % CHANNEL. Default CHANNEL is not set. If VALUE is 'x' or 'y', only % that data is returned in a single column. % 'units' Returns the units of the data from the analyzer. Must % specify VALUE = 'x' or 'y' axis units. % 'pause' Pauses measurement. Not supported by 4195A. % 'continue' Continues paused measurement. Not supported by 4195A. % 'complete' Wait for the previous sweep to complete. This command % contains a loop that does not exit until the status byte shows % that the sweep is complete. Use with 'sweep','single' or % 'complete','single'. % 'wait' Wait for the previous command to complete (*WAI) % Not supported by 4195A. if (strcmpi(instrument, 'HP_4195A') || strcmpi(instrument, 'all')) io = port(GPIB, instrument, 18*401, verbose); % buffer size for downloading data if (io ~=0) && (strcmp(get(io,'Status'),'open') ~=0) % 'aux' is the Test Input (aka "Channel") for all commands % ('channel' is the data register A|B, for magnitude|phase traces) if ~isnumeric(aux), T_IN=1; end if aux==0, T_IN=1; end % default to channel 1 if aux==1, T_IN=1; end if aux==2, T_IN=2; end switch command case 'init' %ok %fprintf(io,'*RST'); fprintf(io,'CLS'); fprintf(io,'STB?'); retval=fscanf(io,'%d'); % make sure that input attenuation is 0 kpib(instrument, GPIB, 'attenuate', 'T', 0, aux, verbose); kpib(instrument, GPIB, 'attenuate', 'R', 0, aux, verbose); if verbose >= 2 fprintf(1, 'kpib/HP_4195A: Initialized. Load setup RES1 manually.\n'); end if verbose >= 3 % % The ID string just causes trouble. Don't use it. % fprintf(io,'ID?'); % ID? returns three separate strings % id1 = fscanf(io,'%s'); % id2 = fscanf(io,'%s'); % id3 = fscanf(io,'%s'); % fprintf(1, 'kpib/HP_4195A: %s %s %s\n',id1,id2,id3); fprintf(1,'kpib/HP_4195A: Status byte: %s\n',dec2bin(retval,8)); end case 'label' % manual pE-3 if length(value) > 53 value=value(1:53); % 53 chars max [verify this for 4195A] end cmd = sprintf('%s"%s"','CMT',value); fprintf(io,cmd); case {'channel','CHAN'} % 'channel' is not meaningful for this instrument; include for compatibility % 'channel' (1|2) for kpib means Trace A or B for the Analyzer % Note that some commands have specific channel select, i.e., trace A or B % commands (e.g., 'scale', 'marker') if verbose >= 3 fprintf(1, 'kpib/HP_4195A: Using Test Channel %d. Use AUX parameter to specify Test Input Channel (1|2). Default is 1.', T_IN); end case {'display','trace'} switch value case {'dual'} % for compatibility with res_meas switch channel case {'query','?'} retval = 1; % assume for compatibility % turn on both traces fprintf(io,'DPA1;DPB1'); otherwise % turn on both traces fprintf(io,'DPA1;DPB1'); retval = 0; end case {'a','A'} switch channel case {'on','ON'} fprintf(io,'DPA1'); case {'off','OFF'} fprintf(io,'DPA0'); end case {'b','B'} switch channel case {'on','ON'} fprintf(io,'DPB1'); case {'off','OFF'} fprintf(io,'DPB0'); end case {'c','C'} switch channel case {'on','ON'} fprintf(io,'SPC1'); case {'off','OFF'} fprintf(io,'SPC0'); end case {'d','D'} switch channel case {'on','ON'} fprintf(io,'SPD1'); case {'off','OFF'} fprintf(io,'SPD0'); end end case {'attenuate','ATT','AT','att'} %ok switch value case {'input','T','test'} switch channel case {'query','?'} cmd = sprintf('ATT%d?',T_IN); fprintf(io,cmd); retval = fscanf(io,'%f'); otherwise % round value (0-50, in steps of 10) manual F-4 value=10*round(channel/10); if channel > 50, channel = 50; end if channel < 0, channel = 0; end cmd = sprintf('ATT%d=%d',T_IN,channel); fprintf(io,cmd); if verbose >= 2, fprintf(1, 'kpib/HP_4195A: Input attenuation on Test Input (T%d) set to %d dB\n',T_IN,channel); end end case {'reference','R','ref'} switch channel case {'query','?'} cmd = sprintf('ATR%d?',T_IN); fprintf(io,cmd); retval = fscanf(io,'%f'); otherwise % round value (0-50, in steps of 10) manual F-4 value=10*round(channel/10); if channel > 50, channel = 50; end if channel < 0, channel = 0; end cmd = sprintf('ATR%d=%d',T_IN,channel); fprintf(io,cmd); if verbose >= 2, fprintf(1, 'kpib/HP_4195A: Input attenuation on Reference Input (R%d) set to %d dB\n',T_IN,channel); end end end case 'scale' % select the channel (for the scale command only) switch channel case 1 fprintf(io,'SCL1'); case 2 fprintf(io,'SCL2'); otherwise fprintf(io,'SCL1'); channel = 1; if verbose >= 2, fprintf(1, 'kpib/HP_4195A: Scale: default Channel 1.\n'); end end if isnumeric(value) cmd = sprintf('DIV=%d',value); fprintf(io,cmd); if verbose >= 2, fprintf(1, 'kpib/HP_4195A: Scale set to %g/division.\n',value); end else switch value case {'auto','AUTO'} fprintf(io,'AUTO'); if verbose >= 2, fprintf(1, 'kpib/HP_4195A: Autoscale channel %d.\n',channel); end case {'?','query'} fprintf(io,'DIV?'); retval = fscanf(io,'%f'); if verbose >= 2, fprintf(1, 'kpib/HP_4195A: Scale on channel %d is %g/division.\n',channel,retval); end case {'lin','linear'} fprintf(io,'SCT1'); if verbose >= 2, fprintf(1, 'kpib/HP_4195A: Linear X scale.\n'); end case {'log','logarithmic'} fprintf(io,'SCT2'); if verbose >= 2, fprintf(1, 'kpib/HP_4195A: Logarithmic X scale.\n'); end end end case {'ref line','refline'} if isnumeric(value) cmd = sprintf('REF=%d',value); fprintf(io,cmd); if verbose >= 2, fprintf(1, 'kpib/HP_4195A: Reference value set to %g dB.\n',value); end else switch value case{'?','query'} fprintf(io,'REF?'); retval = fscanf(io,'%f'); end end case {'average','averaging','video'} % Use "video filtering", manual p4-32 retval = 1; switch value case {'on','ON','yes',1} fprintf(io,'VFTR1'); retval = 1; if verbose >= 2, fprintf(1, 'kpib/HP_4195A: Averaging (video filter) enabled\n'); end case {'off','OFF','no',0} fprintf(io,'VFTR0'); retval = 0; if verbose >= 2, fprintf(1, 'kpib/HP_4195A: Averaging (video filter) disabled\n'); end end case 'center' %ok switch value case {'query','?'} fprintf(io,'CENTER?'); retval = fscanf(io,'%f'); otherwise cmd=['CENTER=' num2str(value)]; fprintf(io,cmd); if verbose >= 2, fprintf(1, 'kpib/HP_4195A: Center set to %f Hz\n',value); end end case 'span' %ok switch value case {'query','?'} fprintf(io,'SPAN?'); retval = fscanf(io,'%f'); otherwise cmd=['SPAN=' num2str(value)]; fprintf(io,cmd); if verbose >= 2, fprintf(1, 'kpib/HP_4195A: Span set to %f Hz\n',value); end end case 'start' %ok switch value case {'query','?'} fprintf(io,'START?'); retval = fscanf(io,'%f'); otherwise cmd=['START=' num2str(value)]; fprintf(io,cmd); if verbose >= 2, fprintf(1, 'kpib/HP_4195A: Start set to %f Hz\n',value); end end case 'stop' %ok switch value case {'query','?'} fprintf(io,'STOP?'); retval = fscanf(io,'%f'); otherwise cmd=['STOP=' num2str(value)]; fprintf(io,cmd); if verbose >= 2, fprintf(1, 'kpib/HP_4195A: Stop set to %f Hz\n',value); end end case {'bias','set','setV'} %ok switch value case {'query','?'} fprintf(io,'BIAS?'); retval = fscanf(io,'%f'); otherwise cmd=['BIAS=' num2str(value)]; fprintf(io,cmd); if verbose >= 2, fprintf(1, 'kpib/HP_4195A: Bias voltage set to %f V\n',value); end end case {'bias?','read'} % emulate a power source for bias operation fprintf(io,'BIAS?'); retval = fscanf(io,'%f'); if verbose >= 2, fprintf(1, 'kpib/HP_4195A: Bias voltage set to %f V (''read'')\n',value); end case {'power','source'} %ok switch value % case 'on' % if verbose >= 2, fprintf('kpib/HP_4195A: Warning: Must select channel and value (power in dBm)\n'); end % case 'off' % fprintf(io,'PWR0'); % if verbose >= 2, fprintf('kpib/HP_4195A: Source output OFF\n'); end case {'query','?'} cmd=['OSC' num2str(T_IN) '?']; fprintf(io,cmd); retval = fscanf(io,'%f'); if verbose >= 2, fprintf(1, 'kpib/HP_4195A: Source Amplitude (S%d) is %d dBm\n',T_IN,retval); end otherwise if isnumeric(value) && value >= -50 && value <= 15 cmd = sprintf('OSC%d=%d',T_IN,value); fprintf(io,cmd); if verbose >= 2, fprintf(1, 'kpib/HP_4195A: Source Power (S%d) set to %d dBm\n',T_IN,value); end else if verbose >= 2, fprintf(1, 'kpib/HP_4195A: Source Power not set. Power must be specified between -50 and 15 dBm.\n'); end end end case {'power?','source?'} % alternate query form cmd=['OSC' num2str(T_IN) '?']; fprintf(io,cmd); retval.level = fscanf(io,'%f'); if verbose >= 2, fprintf(1, 'kpib/HP_4195A: Source Power: %g dBm\n',retval.level); end retval.state='on'; % 4195A source is always on case {'marker','mkr'} % select the channel (for the marker command only) switch channel case 1 fprintf(io,'MKCR1'); case 2 fprintf(io,'MKCR2'); otherwise fprintf(io,'MKCR1'); if verbose >= 2, fprintf(1, 'kpib/HP_4195A: Marker: default Channel 1.\n'); end end switch value case 'on' fprintf(io,'MCF1'); if verbose >= 2, fprintf(1, 'kpib/HP_4195A: Marker on.\n'); end case 'off' fprintf(io,'MCF0'); if verbose >= 2, fprintf(1, 'kpib/HP_4195A: Marker off.\n'); end case {'query','?'} fprintf(io,'MKR?'); retval.x = fscanf(io,'%f'); if ~isnumeric(channel) || channel==0, channel=1; end if any(channel==[1 2]) switch channel case 1 trace='A'; case 2 trace='B'; end cmd=['MKR' trace '?']; fprintf(io,cmd); retval.y = fscanf(io,'%f'); if verbose >= 2, fprintf(1, 'kpib/HP_4195A: Marker on Trace %s at %g Hz, %g.\n',trace,retval.x,retval.y); end else if verbose >= 2, fprintf(1, 'kpib/HP_4195A: ''marker'': must specify a valid channel (1,2).\n'); end end case 'line' fprintf(io,'MCF3'); if verbose >= 2, fprintf(1, 'kpib/HP_4195A: Marker in Line mode.\n'); end case {'center','m2c','mark2center'} % make the marker position the center freq fprintf(io,'MKCTR'); if verbose >= 2, fprintf(1,'kpib/HP_4195A: Marker to Center\n'); end case {'peak','searchpeak','mark2peak','max','m2p'} fprintf(io,'MKMX'); if verbose >= 2, fprintf(1,'%s\n','kpib/HP_4195A: Marker to Maximum'); end case {'min','minimum','valley','antipeak'} fprintf(io,'MKMN'); if verbose >= 2, fprintf(1,'%s\n','kpib/HP_4195A: Marker to Minimum'); end case {'stop'} fprintf(io,'MKSP'); if verbose >= 2, fprintf(1,'%s\n','kpib/HP_4195A: Marker to Stop'); end case {'start'} fprintf(io,'MKST'); if verbose >= 2, fprintf(1,'%s\n','kpib/HP_4195A: Marker to Start'); end otherwise if verbose >= 1, fprintf(1, 'kpib/HP_4195A: Error at ''marker'' command (VALUE incorrect ["%s"]).\n',value); end end case {'mark2peak','peaktrack'} % the 4195A does not have some of these explicit commands switch value case 'center' fprintf(io,'MKMX'); % marker to max fprintf(io,'MKCTR'); % marker to center case 'peak' fprintf(io,'MKMX'); end case {'mode','type'} % set or get instrument mode % find out what mode the analyzer is in: % Network or Spectrum switch value case {'?','query'} % Mode query is not supported by 4195A mode = 'NA'; % Assume Network Analyzer retval = mode; if verbose >= 2, fprintf('kpib/HP_4195A: Warning: Analyzer does not support mode query (kpib returns ''NA'').\n'); end % fprintf(io,'FCN1?'); % mode = fscanf(io,'%d'); % if mode==1 % mode='NA'; % if verbose >= 2, fprintf('kpib/HP_4195A: Analyzer in Network mode.\n'); end % retval=mode; % else % fprintf(io,'FCN2?'); % mode = fscanf(io,'%d'); % if mode==1 % mode='SA'; % if verbose >= 2, fprintf('kpib/HP_4195A: Analyzer in Spectrum mode.\n'); end % retval=mode; % end % end case {'NA','network'} fprintf(io,'FNC1'); if verbose >= 2, fprintf('kpib/HP_4195A: Analyzer set to Network mode.\n'); end case {'SA','spectrum'} fprintf(io,'FNC2'); if verbose >= 2, fprintf('kpib/HP_4195A: Analyzer set to Spectrum mode.\n'); end otherwise if verbose >= 1, fprintf('kpib/HP_4195A: WARNING: ''mode'' command needs a VALUE parameter (e.g., ''?'' or ''NA'').\n'); end retval=-1; end case 'getdata' %ok % Select the channel. For compatibility with old code, the % channel is *not* set if it is not explicitly specified, i.e., % the default is to do nothing, rather than to select a channel. % specify the data format as ASCII fprintf(io,'FMT1'); % now, did the user specify a channel or not? if isnumeric(channel) && any(channel == [1 2 3 4]) if verbose >= 2, fprintf('kpib/HP_4195A: Channel [Trace] %d (Test Input %d) selected for data download.\n',channel,T_IN); end switch channel % see manual p F-1 case 1 fprintf(io,'A?'); retval.units.y = 'dB'; % FIX, could be spectrum mode case 2 fprintf(io,'B?'); retval.units.y = 'deg'; % FIX, could be rad case 3 fprintf(io,'C?'); % C and D are saved data retval.units.y = 'dB'; % FIX, could be spectrum mode case 4 fprintf(io,'D?'); % C and D are saved data retval.units.y = 'deg'; % FIX, could be rad end rawdata = fscanf(io); rawdata = [rawdata ',']; % append a comma so that the format matching works right retval.y = sscanf(rawdata,'%e,'); else if verbose >= 2, fprintf('kpib/HP_4195A: Default channel 1 (Input %d) for data download.\n',T_IN); end if verbose >= 3, fprintf('kpib/HP_4195A: Get Y points.\n'); end fprintf(io,'A?'); rawdata = fscanf(io); rawdata = [rawdata ',']; % append a comma so that the format matching works right retval.y = sscanf(rawdata,'%e,'); retval.units.y = 'dB'; % FIX, could be spectrum mode end % double-check the download fprintf(io,'NOP?'); numdatapoints = fscanf(io,'%i'); if (length(retval.y) ~= numdatapoints) if verbose >= 1, fprintf(1, 'kpib/HP_4195A: WARNING: actual number of y points downloaded (%d)\n',length(retval.y)); fprintf(1,' does not equal expected number of points (%d).\n',numdatapoints); end end % get the x data points if verbose >= 3, fprintf('kpib/HP_4195A: Get X points.\n'); end fprintf(io,'X?'); rawdata = fscanf(io); rawdata = [rawdata ',']; % append a comma so that the format matching works right retval.x = sscanf(rawdata,'%e,'); retval.units.x = 'Hz'; % FIX % did we just want some numbers? switch value case {'x','X'} retval=retval.x; case {'y','Y'} retval=retval.y; end % See command SAP for spectrum mode case 'sweep' % enable the status byte for synchronization (manual p6-47) fprintf(io,'CLS'); % clear the status registers if isnumeric(value) % set the sweep time fprintf(io,'ST=%d',value); else switch value % set sweep type case {'freq','frequency'} fprintf(io,'SWP1'); case {'linear sweep','lin','linear'} fprintf(io,'SWT1'); case {'log sweep','log','logarithmic'} fprintf(io,'SWT2'); case {'list freq','freq list','list'} fprintf(io,'SWPT LIST'); case {'power','power sweep','osc','osclevel'} % sweep in dBm pE-17 fprintf(io,'SWP4'); %case {'query','?'} %fprintf(io,'SWPT?'); %retval=fscanf(io,'%s'); % perform sweep action case {'single'} fprintf(io,'SWM2'); fprintf(io,'TRGM1'); fprintf(io,'SWTRG'); case {'continuous','cont'} fprintf(io,'SWM1'); if verbose >= 1, fprintf(1, 'kpib/HP_4195A: WARNING: 4195A does not support continuous sweep?? (p6-22).\n'); end case {'hold'} fprintf(io,'HOLD'); case {'group','groups','number','N'} if verbose >= 3, fprintf(1, 'kpib/HP_4195A: NOTE: 4195A does not support group sweep (avenum fixed at 4).\n'); end % now initiate a single sweep (presumably video filter is on) fprintf(io,'SWM2'); fprintf(io,'TRGM1'); fprintf(io,'SWTRG'); case {'setpoints','set','numpoints'} if isnumeric(channel) && channel >= 2 && channel <= 401 % maximum points is 401 (p4-28) fprintf(io,'NOP=%i',channel); if verbose >= 2, fprintf(1, 'kpib/HP_4195A: Number of sweep points set to %i.\n',channel); end else if verbose >= 1, fprintf(1, 'kpib/HP_4195A: Number of sweep points must be between 2 and 401.\n'); end end case {'restart'} fprintf(io,'SWTRG'); otherwise if verbose >= 1, fprintf(1, 'kpib/HP_4195A: Sweep command not supported ["%s"]\n',num2str(value)); end end end case 'complete' % complete uses the status byte to know when a sweep has % completed. % The registers are enabled during the sweep command, above. % can issue a single command for a sweep and complete % if nargin > 3 switch value case {'single','sing','SING'} kpib(instrument, GPIB, 'sweep', 'single', channel, aux, verbose); if verbose >= 2, fprintf('kpib/HP_4195A: Single Sweep & Complete\n'); end case {'group','groups','number','N'} kpib(instrument, GPIB, 'sweep', 'group', channel, aux, verbose); if verbose >= 2, fprintf('kpib/HP_4195A: Group Sweep (%d) & Complete\n',channel); end end % end % or just a single command if verbose >= 2, fprintf('kpib/HP_4195A: Waiting for sweep to complete...\n'); end warning off instrument:fscanf:unsuccessfulRead retval=0; while 1 pause(1); fprintf(io,'STB?'); % check the status byte retval=fscanf(io,'%d'); esb=dec2bin(retval,8); % return binary value represents the status registers if verbose >= 3, fprintf(1, 'kpib/HP_4195A: Status Byte: %s.\n',esb); end if esb(end-1) == '1' % Bit 2 indicates sweep complete if verbose >= 2, fprintf(1, 'kpib/HP_4195A: Sweep complete.\n'); end break; end if length(esb) > 5 if esb(end-5) == '1' % indicates "Error" fprintf(io,'ERR?'); errno = fscanf(io,'%d'); if verbose >= 2, fprintf(1, 'kpib/HP_4195A: Analyzer reports: "Error Code %d.\n',errno); end end end end case 'units' % FIX -- DEPRECATED switch value case {'x','X'} retval = 'Hz'; case {'y','Y'} retval = 'dB'; otherwise retval.x = 'Hz'; retval.y = 'dB'; end case 'wait' % *WAI is not supported by 4195A retval = 1; if verbose >= 3, fprintf('kpib/%s: WARNING: ''%s'' not supported by %s\n',command,instrument); end case 'continue' % not supported by 4195A retval = 1; if verbose >= 3, fprintf('kpib/%s: WARNING: ''%s'' not supported by %s\n',command,instrument); end case 'pause' % not supported by 4195A retval = 1; if verbose >= 3, fprintf('kpib/%s: WARNING: ''%s'' not supported by %s\n',command,instrument); end otherwise if verbose >= 1, fprintf('Error, command not supported. ["%s"]\n',command); end end else % catch incorrect address errors if verbose >= 1, fprintf('kpib/%s: ERROR: No instrument at GPIB %d\n',instrument,GPIB); end retval=0; end validInst = 1; end % end HP_4195A
'HP_3562A' HP Dynamic Signal Analyzer
%RETVAL = KPIB('INSTRUMENT', GPIB, 'COMMAND', VALUE, CHANNEL, AUX, VERBOSE) % The HP 3562A can perform a number of different signal measurements. The % command set included here is focused on swept sine measurements. % Valid Commands: % 'init' Resets the Analyzer. Returns the decimal value of the status % byte (should be zero for normal condition). % 'label' Writes 'VALUE' to the display. % 'channel' Makes channel VALUE the active channel. NOTE: 'channel' (1|2) % corresponds to the Data Registers A and B. To select the % Test Input Channel, use the parameter 'aux' (1|2). Default is 1. % 'attenuate' Set the imput attenuation to level CHANNEL in dB. % VALUE can be 'T' or 'R' ('test' or 'reference'). % 'display' Controls what is displayed on the Analyzer screen. % VALUE can be any of the four registers: 'a','b','c','d' and % CHANNEL is 'on' or 'off'. % 'format' Set the format of the graph on the Analyzer display: % Linear, log/mag, etc. % non-exponentially ('norm'). Exponentially is the default. % 'scale' Sets the scale of the display. VALUE is the scale in the % current units, or 'VALUE' = 'auto' for autoscale command. % 'ref line' Sets the position of the reference line of the display. % VALUE is the position of the reference line in the current % units. % 'average' Turns averaging on or off, restarts averaging, or returns % the current number of averages taken. % VALUE='on','off','restart', or 'query'. % For 'query', RETVAL returns 0 (off) or the current number of averages (on). % 'mark2peak' Finds the peak and sets the marker, or finds the peak and % sets the peak location to the center of the scan. % VALUE='off','center', or 'peak'. % 'marker' Turns the marker on or off, or returns the current % position of the marker. 'VALUE' = 'on','off', or 'query'. % The position is returned as retval.x, retval.y in current % units. % 'center' Set the center frequency to VALUE. Units of Hz. % Query with VALUE = 'query', returns center frequency in Hz. % 'span' Set the frequency span VALUE. Units of Hz. % Query with VALUE = 'query', returns span in Hz. % 'sweep' Sets sweep parameters % 'source' Set the source (stimulus output) signal level. VALUE is the % desired signal level. Units of dBm. % Query with VALUE = 'query', returns source power in dBm. % 'source?' (Alternate query form) Returns source power in dBm and state (on|off). % 'power' Same as 'source'. % 'bias' The 4195A has a built-in DC source that can be used for % bias. The commands 'setV' and 'read' are supported, so that % the 4195 can pretend to be a power supply (e.g., you can % do: tools.biasset.instr = 'HP_4195A' ) % 'getdata' Download the current data trace from the analyzer. Data is % returned as two columns, x and y, for the specified % CHANNEL. Default CHANNEL is not set. If VALUE is 'x' or 'y', only % that data is returned in a single column. % 'units' Returns the units of the data from the analyzer. Must % specify VALUE = 'x' or 'y' axis units. % 'pause' Pauses measurement. Not supported by 4195A. % 'continue' Continues paused measurement. Not supported by 4195A. % 'complete' Wait for the previous sweep to complete. This command % contains a loop that does not exit until the status byte shows % that the sweep is complete. Use with 'sweep','single' or % 'complete','single'. % 'wait' Wait for the previous command to complete (*WAI) % Not supported by 4195A. if (strcmpi(instrument, 'HP_3562A') || strcmpi(instrument, 'all')) io = port(GPIB, instrument, 18*801, verbose); % buffer size for downloading data if (io ~=0) && (strcmp(get(io,'Status'),'open') ~=0) switch command case 'init' %ok % status byte fprintf(io,'STA?'); retval=fscanf(io,'%d'); fprintf(io,'SSIN'); fprintf(io,'FRQR'); if verbose >= 1 fprintf(1, 'kpib/HP_3562A: Initialized. Swept Sine mode.\n'); end if verbose >= 3 fprintf(1,'kpib/HP_3562A: Status byte: %s\n',dec2bin(retval,8)); end if verbose >= 1 fprintf(1, 'kpib/HP_3562A: Auto calibration off. Performing single calibration. Please wait.\n'); end % turn off the auto calibration fprintf(io,'AUTO 0'); fprintf(io,'RST'); fprintf(io,'SNGL'); case 'label' % manual p6-23 if length(value) > 24 value=value(1:24); % 24 chars max end cmd = sprintf('%s''%s''','DSP',value); fprintf(io,cmd); if verbose >=2, fprintf(1,'kpib/HP_3562A: Message displayed: "%s"\n',value); end case {'channel','CHAN'} % 'channel' is not meaningful for this instrument; include for compatibility % 'channel' (1|2) for kpib means Trace A or B for the Analyzer % Note that some commands have specific channel select, i.e., trace A or B % commands (e.g., 'scale', 'marker') if any(channel==[1 2]) if channel==1, fprintf(io,'A'); chltr='A'; end if channel==2, fprintf(io,'B'); chltr='B'; end if verbose >= 2 fprintf(1, 'kpib/HP_3562A: Select Input Channel %d (trace %s).\n',channel,chltr); end end case {'display','trace'} switch value case {'dual'} % for compatibility with res_meas switch channel case {'query','?'} retval = 1; % assume for compatibility % turn on both traces fprintf(io,'UPLO'); otherwise % turn on both traces fprintf(io,'UPLO'); retval = 0; fprintf(1, 'kpib/HP_3562A: Dual display (Upper/Lower) on.\n'); end end case 'scale' unitval={'V','VRMS','MVRM','DBVR'}; if any(strcmpi(aux,unitval)) aux=upper(aux); else aux='MVRM'; if verbose >= 3, fprintf(1, 'kpib/HP_3562A: Units (AUX) default to mVrms.\n'); end end if isnumeric(value) cmd = sprintf('YSCL%d%s',value,aux); fprintf(io,cmd); if verbose >= 2, fprintf(1, 'kpib/HP_3562A: Scale set to %g %s/division.\n',value,aux); end else switch value case {'auto','AUTO'} fprintf(io,'YASC'); if verbose >= 2, fprintf(1, 'kpib/HP_3562A: Autoscale Y.\n'); end end end case {'ref line','refline','reflevel'} unitval={'V','VRMS','MVRM','DBVR'}; if any(strcmpi(aux,unitval)) aux=upper(aux); else aux='MVRM'; if verbose >= 3, fprintf(1, 'kpib/HP_3562A: Units (AUX) default to mVrms.\n'); end end if isnumeric(value) cmd = sprintf('RFLV%f%s',value,aux); fprintf(io,cmd); if verbose >= 2, fprintf(1, 'kpib/HP_3562A: Reference value set to %g %s.\n',value,aux); end else switch value case{'?','query'} fprintf(io,'RFLV?'); retval = fscanf(io,'%f'); if verbose >= 2, fprintf(1, 'kpib/HP_3562A: Reference value set to %g %s.\n',value,aux); end end end case {'average','averaging','video'} retval = 1; switch value case {'on','ON','yes',1} if isnumeric(channel) && channel > 0 && channel <= 32767 fprintf(io,'NAVG%d',channel); if verbose >= 2, fprintf(1, 'kpib/HP_3562A: Averaging enabled for %d values.\n',channel); end else if verbose >= 1, fprintf(1, 'kpib/HP_3562A: Must specify CHANNEL values to average.\n'); end end retval = 1; case {'off','OFF','no',0} fprintf(io,'NAVG1'); % i.e., one value to average = no averaging retval = 0; if verbose >= 2, fprintf(1, 'kpib/HP_4195A: Averaging (video filter) disabled\n'); end otherwise % set the number of measurements to average if isnumeric(value) && value > 0 fprintf(io,'NAVG%d',value); if verbose >=2, fprintf(1, 'kpib/HP_3562A: Averaging factor set to: %d\n',value); end else if verbose >= 1, fprintf(1, 'kpib/HP_3562A: Warning: Averaging command not understood ("%s")\n',value); end end end case 'center' %ok switch value case {'query','?'} fprintf(io,'CF?'); retval = fscanf(io,'%f'); otherwise cmd = sprintf('CF%fHZ',value); fprintf(io,cmd); if verbose >= 2, fprintf(1, 'kpib/HP_3562A: Center set to %g Hz\n',value); end end case 'span' %ok switch value case {'query','?'} fprintf(io,'FRS?'); retval = fscanf(io,'%e'); otherwise cmd = sprintf('FRS%fHZ',value); fprintf(io,cmd); if verbose >= 2, fprintf(1, 'kpib/HP_3562A: Span set to %g Hz\n',value); end end case 'start' %ok switch value case {'query','?'} fprintf(io,'SF?'); retval = fscanf(io,'%f'); otherwise cmd = sprintf('SF%fHZ',value); fprintf(io,cmd); if verbose >= 2, fprintf(1, 'kpib/HP_3562A: Start set to %g Hz\n',value); end end case 'stop' %ok switch value case {'query','?'} fprintf(io,'SPF?'); retval = fscanf(io,'%f'); otherwise cmd = sprintf('SPF%fHZ',value); fprintf(io,cmd); if verbose >= 2, fprintf(1, 'kpib/HP_3562A: Stop set to %f Hz\n',value); end end case {'power','source'} %ok switch value case 'on' fprintf(io,'SRON1'); if verbose >= 2, fprintf('kpib/HP_3562A: Source output ON.\n'); end case 'off' fprintf(io,'SRON0'); if verbose >= 2, fprintf('kpib/HP_3562A: Source output OFF.\n'); end case {'query','?'} fprintf(io,'SRLV?'); retval = fscanf(io,'%f'); if verbose >= 2, fprintf(1, 'kpib/HP_3562A: Source Amplitude (S%d) is %d dBm\n',T_IN,retval); end case {'offset','DC'} if isnumeric(value) && value >= 0 && value <= 10 fprintf(io,'DCOF%dV',value); if verbose >= 2, fprintf('kpib/HP_3562A: Source output DC offset of %d V.\n',value); end else if verbose >= 1, fprintf('kpib/HP_3562A: Warning: DC offset out of range (0-10 V)\n'); end end otherwise if isnumeric(value) && value >= -50 && value <= 15 if ~isnumeric(aux) && strcmpi(aux,'VRMS') cmd = sprintf('SRLV%fVRMS',value); else % assume user entered power in dBm, convert to Vrms aux='dBm'; value=sqrt((10^(value/10)*0.001)*50); cmd = sprintf('SRLV%fVRMS',value); end fprintf(io,cmd); if verbose >= 2, fprintf(1, 'kpib/HP_3562A: Source Power set to %d %s\n',value,aux); end else if verbose >= 2, fprintf(1, 'kpib/HP_3562A: Source Power not set. Power must be specified between -50 and 15 dBm.\n'); end end end case {'power?','source?'} % alternate query form retval=kpib(instrument,GPIB,'source','query',channel,aux,verbose); case {'marker','mkr'} % select the channel (for the marker command only) switch channel case 1 fprintf(io,'MKCR1'); case 2 fprintf(io,'MKCR2'); otherwise fprintf(io,'MKCR1'); if verbose >= 2, fprintf(1, 'kpib/HP_4195A: Marker: default Channel 1.\n'); end end switch value case 'on' fprintf(io,'MCF1'); if verbose >= 2, fprintf(1, 'kpib/HP_4195A: Marker on.\n'); end case 'off' fprintf(io,'MCF0'); if verbose >= 2, fprintf(1, 'kpib/HP_4195A: Marker off.\n'); end case {'query','?'} fprintf(io,'MKR?'); retval.x = fscanf(io,'%f'); if ~isnumeric(channel) || channel==0, channel=1; end if any(channel==[1 2]) switch channel case 1 trace='A'; case 2 trace='B'; end cmd=['MKR' trace '?']; fprintf(io,cmd); retval.y = fscanf(io,'%f'); if verbose >= 2, fprintf(1, 'kpib/HP_4195A: Marker on Trace %s at %g Hz, %g.\n',trace,retval.x,retval.y); end else if verbose >= 2, fprintf(1, 'kpib/HP_4195A: ''marker'': must specify a valid channel (1,2).\n'); end end case 'line' fprintf(io,'MCF3'); if verbose >= 2, fprintf(1, 'kpib/HP_4195A: Marker in Line mode.\n'); end case {'center','m2c','mark2center'} % make the marker position the center freq fprintf(io,'MKCTR'); if verbose >= 2, fprintf(1,'kpib/HP_4195A: Marker to Center\n'); end case {'peak','searchpeak','mark2peak','max','m2p'} fprintf(io,'MKMX'); if verbose >= 2, fprintf(1,'%s\n','kpib/HP_4195A: Marker to Maximum'); end case {'min','minimum','valley','antipeak'} fprintf(io,'MKMN'); if verbose >= 2, fprintf(1,'%s\n','kpib/HP_4195A: Marker to Minimum'); end case {'stop'} fprintf(io,'MKSP'); if verbose >= 2, fprintf(1,'%s\n','kpib/HP_4195A: Marker to Stop'); end case {'start'} fprintf(io,'MKST'); if verbose >= 2, fprintf(1,'%s\n','kpib/HP_4195A: Marker to Start'); end otherwise if verbose >= 1, fprintf(1, 'kpib/HP_4195A: Error at ''marker'' command (VALUE incorrect ["%s"]).\n',value); end end case {'mark2peak','peaktrack'} % the 4195A does not have some of these explicit commands switch value case 'center' fprintf(io,'MKMX'); % marker to max fprintf(io,'MKCTR'); % marker to center case 'peak' fprintf(io,'MKMX'); end case {'mode','type'} % set or get instrument mode % find out what mode the analyzer is in: % Network or Spectrum switch value case {'?','query'} % Mode query is not supported by 4195A mode = 'NA'; % Assume Network Analyzer retval = mode; if verbose >= 2, fprintf('kpib/HP_4195A: Warning: Analyzer does not support mode query (kpib returns ''NA'').\n'); end % fprintf(io,'FCN1?'); % mode = fscanf(io,'%d'); % if mode==1 % mode='NA'; % if verbose >= 2, fprintf('kpib/HP_4195A: Analyzer in Network mode.\n'); end % retval=mode; % else % fprintf(io,'FCN2?'); % mode = fscanf(io,'%d'); % if mode==1 % mode='SA'; % if verbose >= 2, fprintf('kpib/HP_4195A: Analyzer in Spectrum mode.\n'); end % retval=mode; % end % end case {'NA','network'} fprintf(io,'FNC1'); if verbose >= 2, fprintf('kpib/HP_4195A: Analyzer set to Network mode.\n'); end case {'SA','spectrum'} fprintf(io,'FNC2'); if verbose >= 2, fprintf('kpib/HP_4195A: Analyzer set to Spectrum mode.\n'); end otherwise if verbose >= 1, fprintf('kpib/HP_4195A: WARNING: ''mode'' command needs a VALUE parameter (e.g., ''?'' or ''NA'').\n'); end retval=-1; end case 'getdata' %ok % now, did the user specify a channel or not? if verbose >= 2, fprintf('kpib/HP_3562A: Data download.\n'); end if verbose >= 3, fprintf('kpib/HP_3562A: Get Y points.\n'); end fprintf(io,'DDAN'); % "dump data in ASCII" %rawdata = fscanf(io,'e'); header=fscanf(io,'#I%e',1); %#ok<NASGU> rawdata = fscanf(io,'e'); %rawdata = [rawdata ',']; % append a comma so that the format matching works right %retval.y = sscanf(rawdata,'%e,'); retval.y = rawdata; retval.units.y = 'dB'; % FIX, could be spectrum mode % % double-check the download % fprintf(io,'NOP?'); % numdatapoints = fscanf(io,'%i'); % if (length(retval.y) ~= numdatapoints) % if verbose >= 1, fprintf(1, 'kpib/HP_4195A: WARNING: actual number of y points downloaded (%d)\n',length(retval.y)); % fprintf(1,' does not equal expected number of points (%d).\n',numdatapoints); % end % end % % % get the x data points % if verbose >= 3, fprintf('kpib/HP_4195A: Get X points.\n'); end % fprintf(io,'X?'); % rawdata = fscanf(io); % rawdata = [rawdata ',']; % append a comma so that the format matching works right % retval.x = sscanf(rawdata,'%e,'); % retval.units.x = 'Hz'; % FIX % % % did we just want some numbers? % switch value % case {'x','X'} % retval=retval.x; % case {'y','Y'} % retval=retval.y; % end % See command SAP for spectrum mode case 'sweep' % enable the status byte for synchronization (manual p6-47) fprintf(io,'CLS'); % clear the status registers if isnumeric(value) % set the sweep time fprintf(io,'ST=%d',value); else switch value % set sweep type case {'freq','frequency'} fprintf(io,'SWP1'); case {'linear sweep','lin','linear'} fprintf(io,'SWT1'); case {'log sweep','log','logarithmic'} fprintf(io,'SWT2'); case {'list freq','freq list','list'} fprintf(io,'SWPT LIST'); case {'power','power sweep','osc','osclevel'} % sweep in dBm pE-17 fprintf(io,'SWP4'); %case {'query','?'} %fprintf(io,'SWPT?'); %retval=fscanf(io,'%s'); % perform sweep action case {'single'} fprintf(io,'SWM2'); fprintf(io,'TRGM1'); fprintf(io,'SWTRG'); case {'continuous','cont'} fprintf(io,'SWM1'); if verbose >= 1, fprintf(1, 'kpib/HP_4195A: WARNING: 4195A does not support continuous sweep?? (p6-22).\n'); end case {'hold'} fprintf(io,'HOLD'); case {'group','groups','number','N'} if verbose >= 3, fprintf(1, 'kpib/HP_4195A: NOTE: 4195A does not support group sweep (avenum fixed at 4).\n'); end % now initiate a single sweep (presumably video filter is on) fprintf(io,'SWM2'); fprintf(io,'TRGM1'); fprintf(io,'SWTRG'); case {'setpoints','set','numpoints'} if isnumeric(channel) && channel >= 2 && channel <= 401 % maximum points is 401 (p4-28) fprintf(io,'NOP=%i',channel); if verbose >= 2, fprintf(1, 'kpib/HP_4195A: Number of sweep points set to %i.\n',channel); end else if verbose >= 1, fprintf(1, 'kpib/HP_4195A: Number of sweep points must be between 2 and 401.\n'); end end case {'restart'} fprintf(io,'SWTRG'); otherwise if verbose >= 1, fprintf(1, 'kpib/HP_4195A: Sweep command not supported ["%s"]\n',num2str(value)); end end end case 'complete' % complete uses the status byte to know when a sweep has % completed. % The registers are enabled during the sweep command, above. % can issue a single command for a sweep and complete % if nargin > 3 switch value case {'single','sing','SING'} kpib(instrument, GPIB, 'sweep', 'single', channel, aux, verbose); if verbose >= 2, fprintf('kpib/HP_3562A: Single Sweep & Complete\n'); end case {'group','groups','number','N'} kpib(instrument, GPIB, 'sweep', 'group', channel, aux, verbose); if verbose >= 2, fprintf('kpib/HP_4195A: Group Sweep (%d) & Complete\n',channel); end end % end % or just a single command if verbose >= 2, fprintf('kpib/HP_3562A: Waiting for sweep to complete...\n'); end warning off instrument:fscanf:unsuccessfulRead retval=0; while retval==0 pause(1); fprintf(io,'SMSD?'); % is measurement done? retval=fscanf(io,'%d'); %esb=dec2bin(retval,8); % return binary value represents the status registers if verbose >= 3, fprintf(1, 'kpib/HP_3562A: Measurement Done: %d.\n',retval); end end case 'units' % FIX -- DEPRECATED switch value case {'x','X'} retval = 'Hz'; case {'y','Y'} retval = 'dB'; otherwise retval.x = 'Hz'; retval.y = 'dB'; end case 'wait' % *WAI is not supported by 4195A retval = 1; if verbose >= 3, fprintf('kpib/%s: WARNING: ''%s'' not supported by %s\n',command,instrument); end case 'continue' retval = 1; fprintf(io,'CONT'); if verbose >= 2, fprintf('kpib/HP_3562A: Measurement continued.\n'); end case 'pause' % not supported by 4195A retval = 1; fprintf(io,'PAUS'); if verbose >= 2, fprintf('kpib/HP_3562A: Measurement paused.\n'); end otherwise if verbose >= 1, fprintf('Error, command not supported. ["%s"]\n',command); end end else % catch incorrect address errors if verbose >= 1, fprintf('kpib/%s: ERROR: No instrument at GPIB %d\n',instrument,GPIB); end retval=0; end validInst = 1; end % end HP_4195A
'KTH_2400' Keithley 2400 Sourcemeter
%RETVAL = KPIB('INSTRUMENT', GPIB, 'COMMAND', VALUE, CHANNEL, AUX, VERBOSE) % Contributed by David Myers % This sourcemeter has some special needs. Most seem to be derived from % using the Prologix GPIB controller. Be sure to set the IsUSBPro flag % near the beginning of the file. % % Issue #1 - Quoted from Prologix GPIB-USB Controller Manual % The default setting for the Prologix contoller is to automatically address % instruments to talk after sending a command in order to read their response % (++auto 1). When sending a command which does not require a response, a % Query Unterminated error, -420, is generated in the Keithley 2400. % In essense, the instrument is saying "I have been asked to talk, but I % have nothing to say." While the instrument will continue to operate, the % repeated error messages and buzzing are irksome. This is resolved by setting % the Prologix to NOT automatically address the instrument, only for the KTH_2400 % to talk (++auto 0), and addressing the instrument to talk only after sending a % query command (see the PORT function). % Example: % ++auto 0 - turn off read-after-write and address instrument to listen % Set VOLT 1.0 - Non-query command % *idn? - Query Command % ++ read eoi - read until EOI asserted by instrument % % Issue #2 - % The Prologix controller is using a different EOI for this tool than for % other tools. "CR" rather than "CR/LF", this was solved by adding a line % in the PORT function to change the EOI to CR for the KTH_2400. % % Issue #3 - % The Keithley will not read without setting some value initially, and % turning the output on. For now, the user is directed to call kpib % commands in an order that will not produce this error. % % % Valid Commands: % 'init' Send the *RST command to reset the instrument and clear registers % 'read' Reads the output levels of the specified output ('V' or 'I'). % Returns a single value if you specify VALUE ('volt' or 'curr'), % otherwise result is returned as a two-field structure of %f numbers: % retval.volt % retval.curr % Note that 'read' returns the *setpoint* value, not a measured % value. Other power supplies in kpib (e.g. HP_Exxxx) return a % *measured* value in response to the 'read' command. For % KTH_2400, use 'measure' to return a measurement of the output % values. This behavior may be changed in a future versions. % % 'measure' Performs a measurement of signal at the terminals. VALUE should be % 'V' or 'A' or 'R' % Note that measure ohms ('R') puts the instrument into a mode % that you cannot get out of using the currently implemented % commands. % 'setV' Sets the output voltage to VALUE in Volts. Also 'set' (deprecated). % 'setI' Sets the output current to VALUE in Amps. % % 'off' Disables the source output. % 'on' Enables the source output. % if (any(strcmpi(instrument, 'KTH_2400')) || strcmpi(instrument, 'all')) io = port(GPIB, instrument, 0, verbose); if (io ~=0) && (strcmp(get(io,'Status'),'open') ~=0) switch command case 'init' fprintf(io,'*RST'); % turn the friggin beeper off fprintf(io, ':BEEPER:STATE OFF'); % turn off the "auto-off" function fprintf(io, ':SOURce1:CLEar:AUTO OFF'); case 'function' switch value case {'query','?'} fprintf(io, ':SOURCE:FUNCTION?'); if IsUSBPro, fprintf(io, '++read 13'); end %#ok<UNRCH> retval = fscanf(io,'%s'); if verbose >= 2, fprintf(1, 'kpib/KTH_2400: Source Function is "%s"\n',retval); end case {'V','volt','volts'} fprintf(io, ':SOURCE:FUNCTION VOLT'); fprintf(io, ':SOURCE:VOLT:MODE FIX'); if verbose >= 2, fprintf(1, 'kpib/KTH_2400: Voltage Source selected\n'); end case {'I','amp','amps'} fprintf(io, ':SOURCE:FUNCTION CURR'); fprintf(io, ':SOURCE:VOLT:MODE FIX'); if verbose >= 2, fprintf(1, 'kpib/KTH_2400: Current Source selected\n'); end end case 'read' %assume that instrument output is on and this command is okay switch value % return a single value or both V & I? case {'volt','volts','V','v'} % read the voltage fprintf(io, ':SOURCE:VOLTAGE:IMM:AMPLITUDE?'); if IsUSBPro, fprintf(io, '++read 13'); end %#ok<UNRCH> retval = fscanf(io,'%f'); if verbose >= 2, fprintf(1, 'kpib/KTH_2400: reads %f Volts\n',retval); end case {'curr','I','A','current'} fprintf(io, ':SOURCE:CURRENT:IMM:AMPLITUDE?'); if IsUSBPro, fprintf(io, '++read 13'); end %#ok<UNRCH> retval = fscanf(io,'%f'); if verbose >= 2, fprintf(1, 'kpib/KTH_2400: reads %f Amps\n',retval); end otherwise % read the output fprintf(io, ':SOURCE:VOLTAGE:IMM:AMPLITUDE?'); if IsUSBPro, fprintf(io, '++read 13'); end %#ok<UNRCH> retval.volt = fscanf(io,'%f'); fprintf(io, ':SOURCE:CURRENT:IMM:AMPLITUDE?'); if IsUSBPro, fprintf(io, '++read 13'); end %#ok<UNRCH> retval.curr = fscanf(io,'%f'); if verbose >= 2, fprintf(1, 'kpib/KTH_2400: reads %f Volts && %f Amps\n',retval.volt,retval.curr); end end case {'setV','volt','voltage','set'} % set the voltage fprintf(io, ':SOUR:FUNC VOLT'); fprintf(io, ':SOUR:VOLT:MODE FIX'); fprintf(io, ':SOUR:VOLT:RANGE 200'); %Set to maximum value cmd=sprintf(':SOURCE:VOLT:LEVEL %g',value); fprintf(io,cmd); % Sets voltage. if verbose >= 2, fprintf('kpib/KTH_2400: Output Voltage set to %g Volts\n',value); end case {'setI','curr','current'} % set the current fprintf(io, ':SOURCE:FUNCTION CURR'); fprintf(io, ':SOUR:CURR:MODE FIX'); fprintf(io, ':SOUR:CURR:RANGE 1'); %Set to maximum value cmd=sprintf(':SOURCE:CURR:LEVEL %g',value); fprintf(io,cmd); % Sets voltage if verbose >= 2, fprintf('kpib/KTH_2400: Output Current set to %g Amps\n',value); end case 'off' fprintf(io, ':OUTPUT OFF'); % Disables all outputs. if verbose >= 2, fprintf(1, 'kpib/KTH_2400: Outputs off.\n'); end case 'on' fprintf(io, ':OUTPUT ON'); % Enables all outputs. if verbose >= 2, fprintf(1, 'kpib/KTH_2400: Outputs on.\n'); end case 'measure' % perform a "one-shot" measurement, manual p17-5 % ":MEASURE?" returns 5 values in a comma-delimited string switch value case {'V','volt','volts'} fprintf(io, ':MEASURE:VOLT?'); if IsUSBPro, fprintf(io, '++read 13'); end %#ok<UNRCH> r = fscanf(io,'%s'); rs=str2num(r); retval = rs(1); case {'A','amp','amps','I'} fprintf(io, ':MEASURE:CURR?'); if IsUSBPro, fprintf(io, '++read 13'); end %#ok<UNRCH> r = fscanf(io,'%s'); rs=str2num(r); retval = rs(2); case {'R','ohm','ohms'} fprintf(io, ':MEASURE:RES?'); if IsUSBPro, fprintf(io, '++read 13'); end %#ok<UNRCH> r = fscanf(io,'%s'); rs=str2num(r); retval = rs(3); otherwise % will perform currently selected function fprintf(io, ':MEASURE?'); if IsUSBPro, fprintf(io, '++read 13'); end %#ok<UNRCH> r = fscanf(io,'%s,'); %r=[r ,]; rs=str2num(r); retval.volt=rs(1); retval.curr=rs(2); retval.ohms=rs(3); retval.time=rs(4); retval.status=dec2bin(rs(5)); end otherwise if verbose >= 1, fprintf('kpib/KTH_2400: Error, command not supported. ["%s"]\n',command); end end else % catch incorrect address errors if verbose >= 1, fprintf('kpib/%s: ERROR: No instrument at GPIB %d\n',instrument,GPIB); end retval=0; end validInst = 1; end % end KTH_2400
'HP_54600' Hewlett-Packard digital oscilloscope
%RETVAL = KPIB('INSTRUMENT', GPIB, 'COMMAND', VALUE, CHANNEL, AUX, VERBOSE) % This code should be valid for all members of the HP 54600 family of oscilloscopes, % but later models (i.e., 54622) may have some incompatibilities. This code was % tested only against a 54602B. % Valid instructions: % 'label' Write VALUE on the instrument screen. Shows for 3 seconds. % 'read' Returns a measurement of type VALUE from CHANNEL (default 1). % Measurement types are: % 'amplitude' the high value minus the low value. % 'frequency' the frequency of the signal. % 'peak2peak' absolute difference between maximum and minimum % values of the waveform. % 'rms' the root mean square voltage. % 'measure' Same as 'read'. % 'display' Turn a channel display on/off % 'getdata' Downloads the complete waveform from the oscilloscope. % The data is returned in a structure: % retval.x % retval.y % retval.units.x (always 'sec') % retval.units.y (always 'V') % if strcmpi(instrument, 'HP_54600') || strcmpi(instrument, 'HP_54602B') || strcmpi(instrument, 'all') io = port(GPIB, instrument, 50000, verbose); % buffer size for downloading data if (io ~=0) && (strcmp(get(io,'Status'),'open') ~=0) switch command case {'init','initialize'} %ok if verbose >= 2, fprintf(1, 'kpib/HP_54600: Initialize instrument.\n'); end fprintf(io,':TIMEBASE:MODE NORMAL'); % necessary for data download fprintf(io,':WAVEFORM:FORMAT ASC'); % ASCII format data fprintf(io,':ACQUIRE:TYPE NORMAL'); % as opposed to peak or average case {'label'} %ok fprintf(io,':DISPLAY:TEXT BLANK'); fprintf(io,':DISPLAY:LINE "%s"',value); pause(3) fprintf(io,':DISPLAY:TEXT BLANK'); case {'read','measure'} %ok if any(channel == [1 2 3 4]) if verbose >= 2, fprintf(1, 'kpib/HP_54600: Channel %d selected.\n',channel); end fprintf(io,':MEAS:SOURCE CHAN%d',channel); else % default to channel 1 channel=1; if verbose >= 2, fprintf(1, 'kpib/HP_54600: Default channel is set to %d.\n',channel'); end fprintf(io,':MEAS:SOURCE CHAN%d',channel); end switch value case {'amplitude','amp','ampl','V'} %ok fprintf(io,':MEAS:VAMP?'); retval.val = fscanf(io,'%f'); retval.units='V'; if verbose >= 2, fprintf(1, '%s %d %s %f %s\n', 'kpib/HP_54600: Channel:',channel,'Amplitude:',retval.val,retval.units); end case {'frequency','freq','f'} %ok fprintf(io,':MEAS:FREQ?'); retval.val = fscanf(io,'%f'); retval.units = 'Hz'; if verbose >= 2, fprintf(1, '%s %d %s %f %s\n', 'kpib/HP_54600: Channel:',channel,'Frequency:',retval.val,retval.units); end case {'peak2peak','p-p','vpp'} %ok fprintf(io,':MEAS:VPP?'); retval.val = fscanf(io,'%f'); retval.units='V'; if verbose >= 2, fprintf(1, '%s %d %s %f %s\n', 'kpib/HP_54600: Channel:',channel,'Peak2Peak:',retval.val,retval.units); end case {'rms','RMS'} %ok fprintf(io,':MEAS:VRMS?'); retval.val = fscanf(io,'%f'); retval.units = 'Vrms'; if verbose >= 2, fprintf(1, '%s %d %s %f %s\n', 'kpib/HP_54600: Channel:',channel,'RMS:',retval.val,retval.units); end otherwise if verbose >= 2, fprintf(1, 'kpib/HP_54600: No valid measurement type selected (V,f,vpp,rms).\n'); end end case {'autoscale','auto y'} %ok fprintf(io,'AUTOSCALE'); if verbose >= 2, fprintf(1, 'kpib/HP_54600: Autoscale display.\n'); end case {'display','trace'} % either turn a channel display on/off, or return a binary word % (string) representing the state of the four displays switch value case {'on','ON'} %ok fprintf(io, ':VIEW CHAN%d',channel); if verbose >= 2, fprintf(1, 'kpib/HP_54600: Channel %d on.\n',channel); end case {'off','OFF'} %ok fprintf(io, ':BLANK CHAN%d',channel); if verbose >= 2, fprintf(1, 'kpib/HP_54600: Channel %d off.\n',channel); end case {'query','?'} % HP_54600 does not have a display on/off query for cd=1:4 fprintf(io, ':VIEW CHAN%d',cd); if verbose >= 2, fprintf(1, 'kpib/HP_54600: Display state query: Enable all channels\n'); end fprintf(io, ':VIEW CHAN1'); fprintf(io, ':VIEW CHAN2'); fprintf(io, ':VIEW CHAN3'); fprintf(io, ':VIEW CHAN4'); retval='1111'; % return hardcoded value end % case {'active','active?'} % fprintf(io,'SELECT?'); % query the channel state % ch = fscanf(io); % retval = sscanf(ch(23:end),'CH%d'); otherwise if verbose >= 2, fprintf(1, 'kpib/HP_54600: Error: ''display'' VALUE not understood.\n'); end end case {'channel'} % select a channel if verbose >= 2, fprintf('kpib/HP_54600: Channel Select not supported by instrument\n'); end % if any(channel == [1 2 3 4]) % fprintf(io,'SELECT:CH%d ON',channel); % select a channel (manual p2-214) % if verbose >= 2, fprintf(1, 'kpib/HP_54600: Channel %d selected.\n',channel); end % end case 'getdata' %ok if ~(any(channel == [1 2 3 4])) if verbose >= 2, fprintf(1, 'kpib/HP_54600: Default channel 1 selected.\n'); end channel=1; else if verbose >= 2, fprintf(1, 'kpib/HP_54600: Channel %d selected.\n',channel); end end if ~(isnumeric(aux)) if verbose >= 2, fprintf(1, 'kpib/HP_54600: Default 2000 points.\n'); end aux=2000; elseif aux > 0 if verbose >= 2, fprintf(1, 'kpib/HP_54600: %d data points specified.\n',aux); end else aux=2000; if verbose >= 2, fprintf(1, 'kpib/HP_54600: Default 2000 points.\n'); end end if any(channel == [1 2 3 4]) fprintf(io,':WAVEFORM:SOURCE CHAN%d',channel); % select channel fprintf(io,':WAVEFORM:POINTS %d',aux); % 2000 data points is default if verbose >= 2, fprintf(1, 'kpib/HP_54600: Channel %d, %d points.\n',channel,aux); end fprintf(io,':WAVEFORM:FORMAT ASC'); % ASCII format data fprintf(io,':DIGITIZE CHAN%d',channel); % capture the data pause(2); % to ensure that digitizing completes fprintf(io,':WAVEFORM:PRE?'); % download the preamble preamble = fscanf(io); % preamble is comma-separated numbers preamble = [preamble,',']; % Process the preamble % Preamble has several useful fields (manual p8-18): % (1) FORMAT : int16 0 = ASCII, 1 = BYTE, 2 = WORD % (2) TYPE : int16 0 = AVERAGE, 1 = NORMAL, 2 = PEAK DETECT % (3) POINTS : int32 number of data points transferred % (4) COUNT : int32 1 and is always 1 % (5) XINCREMENT : float32 - time difference between data points % (6) XORIGIN : float64 - always the first data point in memory % (7) XREFERENCE : int32 - specifies the data point associated with x-origin % (8) YINCREMENT : float32 - voltage difference between data points % (9) YORIGIN : float32 - value is the voltage at center screen % (10)YREFERENCE : int16 - specifies data point where y-origin occurs %pre=strread(preamble,'%f','delimiter',','); pre = sscanf(preamble,'%f,'); % preamble is all numeric, easy to parse if verbose >= 3 fprintf(1, 'kpib/HP_54600: Data preamble:\n'); for i=1:length(pre) fprintf(1, 'Field %2d: %f\n',i,pre(i)); end end % Read the data from the oscilloscope fprintf(io,':WAVE:DATA?'); data = fscanf(io); % data will be a long series of characters nc = str2num(data(2)); data=data(nc+3:end); % remove string header "#800008000" % "#" starts the data % next character is remaining % number of characters in string % header % Following value is number of % bytes in data string yval = sscanf([data,','],'%e,'); if verbose >= 2, fprintf(1, 'kpib/HP_54600: Data downloaded.\n'); end actualdatapoints = length(yval); % Converts the necessary preamble values from strings into % numbers. numdatapoints = pre(3); % The number of data points xincr = pre(5); % The x increment xoffset = pre(6); % The x offset (left side of screen) yincr = pre(8); % The y increment yzero = pre(9); % The y offset yoffset = pre(10); % the y value at the origin % scale the data % the y data is integers from the A-D converter. Scale % by the values from the preamble retval.y=((yval-yoffset).*yincr)+yzero; % generate the corresponding x values retval.x=([0:1:numdatapoints-1]'*xincr); retval.x = retval.x + xoffset; % assume units retval.units.x = 'sec'; retval.units.y = 'V'; if actualdatapoints~=numdatapoints if verbose >= 1 fprintf(1, 'kpib/HP_54600: WARNING: number of data points received from scope appears to be incorrect.\n'); fprintf(1, ' Expected: %d, Received: %d [Using Received]\n',numdatapoints,actualdatapoints); fprintf(1, ' (Try Reset GPIB with ''clear'' or check io.Buffersize)\n'); retval.y=retval.y(1:actualdatapoints); retval.x=retval.x(1:actualdatapoints); end end else if verbose >= 1, fprintf(1, 'kpib/HP_54600: Error: channel specified incorrectly.\n'); end retval=0; end otherwise if verbose >= 1, fprintf(1, 'kpib/HP_54600: Error, command not supported. ["%s"]\n',command); end retval=0; end else % catch incorrect address errors if verbose >= 1, fprintf('kpib/%s: ERROR: No instrument at GPIB %d\n',instrument,GPIB); end retval=0; end validInst = 1; end % end HP_54600
'HP_54800' Hewlett-Packard digital Infiniium oscilloscope
%RETVAL = KPIB('INSTRUMENT', GPIB, 'COMMAND', VALUE, CHANNEL, AUX, VERBOSE) % This code should be valid for all members of the HP 548XX family of % Infiniium oscilloscopes, and previous series (545XX, 547XX) should work as well. % This code was tested only against a 54845A. % Valid instructions: % 'label' Write VALUE on the instrument screen. Shows for 3 seconds. % 'read' Returns a measurement of type VALUE from CHANNEL (default 1). % Measurement types are: % 'amplitude' the high value minus the low value. % 'frequency' the frequency of the signal. % 'peak2peak' absolute difference between maximum and minimum % values of the waveform. % 'rms' the root mean square voltage. % 'max' the maximum voltage value % 'min' the minimum voltage value % Returns RETVAL as a structure with fields VAL and UNITS. % 'measure' Same as 'read'. % 'autoscale' Autoscales the display, according to signals on all % channels. % 'display' Turn CHANNEL to VALUE ('on'|'off'). Query channel states % with VALUE ('query'|'?'). % 'getdata' Downloads the complete waveform from the oscilloscope. % The data is returned in a structure: % retval.x % retval.y % retval.units.x % retval.units.y % if strcmpi(instrument, 'HP_54800') || strcmpi(instrument, 'HP_54845A') || strcmpi(instrument, 'all') io = port(GPIB, instrument, 32768*20, verbose); % buffer size for downloading data (# points * 20 bytes) if (io ~=0) && (strcmp(get(io,'Status'),'open') ~=0) switch command case {'init','initialize'} %ok if verbose >= 2, fprintf(1, 'kpib/HP_54800: Initialize instrument.\n'); end fprintf(io,':TIMEBASE:MODE NORMAL'); % necessary for data download fprintf(io,':WAVEFORM:FORMAT ASC'); % ASCII format data fprintf(io,':ACQUIRE:TYPE NORMAL'); % as opposed to peak or average case {'label'} % max 81 chars fprintf(io,':DISPLAY:TEXT BLANK'); fprintf(io,':DISPLAY:STRING "%s"',value); %pause(3) %fprintf(io,':DISPLAY:TEXT BLANK'); case {'read','measure'} %ok if any(channel == [1 2 3 4]) if verbose >= 2, fprintf(1, 'kpib/HP_54800: Channel %d selected.\n',channel); end fprintf(io,':MEAS:SOURCE CHAN%d',channel); else % default to channel 1 channel=1; if verbose >= 2, fprintf(1, 'kpib/HP_54800: Default channel is set to %d.\n',channel'); end fprintf(io,':MEAS:SOURCE CHAN%d',channel); end switch value case {'amplitude','amp','ampl','V'} %ok fprintf(io,':MEAS:VAMP?'); retval.val = fscanf(io,'%f'); retval.units='V'; if verbose >= 2, fprintf(1, '%s %d %s %g %s\n', 'kpib/HP_54800: Channel',channel,'Amplitude:',retval.val,retval.units); end case {'frequency','freq','f'} %ok fprintf(io,':MEAS:FREQ?'); retval.val = fscanf(io,'%f'); retval.units = 'Hz'; if verbose >= 2, fprintf(1, '%s %d %s %g %s\n', 'kpib/HP_54800: Channel',channel,'Frequency:',retval.val,retval.units); end case {'period','P'} %ok fprintf(io,':MEAS:PERIOD?'); retval.val = fscanf(io,'%f'); retval.units = 'sec'; if verbose >= 2, fprintf(1, '%s %d %s %g %s\n', 'kpib/HP_54800: Channel',channel,'Period:',retval.val,retval.units); end case {'peak2peak','p-p','vpp'} %ok fprintf(io,':MEAS:VPP?'); retval.val = fscanf(io,'%f'); retval.units='V'; if verbose >= 2, fprintf(1, '%s %d %s %g %s\n', 'kpib/HP_54800: Channel',channel,'Peak2Peak:',retval.val,retval.units); end case {'rms','RMS'} %ok fprintf(io,':MEAS:VRMS?'); retval.val = fscanf(io,'%f'); retval.units = 'Vrms'; if verbose >= 2, fprintf(1, '%s %d %s %g %s\n', 'kpib/HP_54800: Channel',channel,'RMS:',retval.val,retval.units); end case {'max','MAX'} %ok fprintf(io,':MEAS:VMAX?'); retval.val = fscanf(io,'%f'); retval.units = 'V'; if verbose >= 2, fprintf(1, '%s %d %s %g %s\n', 'kpib/HP_54800: Channel',channel,'Max Voltage:',retval.val,retval.units); end case {'min','MIN'} %ok fprintf(io,':MEAS:VRMS?'); retval.val = fscanf(io,'%f'); retval.units = 'V'; if verbose >= 2, fprintf(1, '%s %d %s %g %s\n', 'kpib/HP_54800: Channel',channel,'Min Voltage:',retval.val,retval.units); end otherwise if verbose >= 2, fprintf(1, 'kpib/HP_54800: No valid measurement type selected (V,f,vpp,rms).\n'); end end case {'autoscale','auto y'} %ok fprintf(io,'AUTOSCALE'); % display is autoscaled to all channels, even if the channels are off if verbose >= 2, fprintf(1, 'kpib/HP_54800: Autoscale display.\n'); end case 'average' switch value case 'on' fprintf(io, ':ACQUIRE:AVERAGE ON'); if verbose >=2, fprintf(1, 'kpib/HP_54800: Measurement Averaging on'); end if isnumeric(aux) && aux > 0 fprintf(io,'ACQUIRE:COUNT %d',aux); end fprintf(io,':ACQUIRE:COUNT?'); num = fscanf(io,'%d'); if verbose >= 2, fprintf(1, ', aver. factor: %d\n',num); end case 'off' fprintf(io, ':ACQUIRE:AVERAGE OFF'); if verbose >=2, fprintf(1, 'kpib/HP_54800: Measurement Averaging off\n'); end case {'query','?'} fprintf(io, ':ACQUIRE:AVERAGE?'); retval = fscanf(io,'%d'); if verbose >=2 fprintf(1, 'kpib/HP_54800: Measurement Averaging '); if retval == 1 fprintf(1, 'on.\n'); else fprintf(1, 'off.\n'); end end case {'numaverages?','count?'} % return the current average num setting fprintf(io, ':ACQUIRE:COUNT?'); retval = fscanf(io,'%f'); if verbose >=2, fprintf(1, 'kpib/HP_54800: Number of measurements to average: %d\n',retval); end end case {'display','trace'} % either turn a channel display on/off, or return a binary word % (string) representing the state of the four displays switch value case {'on','ON'} %ok fprintf(io, ':CHAN%d:DISPLAY ON',channel); if verbose >= 2, fprintf(1, 'kpib/HP_54800: Channel %d on.\n',channel); end case {'off','OFF'} %ok fprintf(io, ':CHAN%d:DISPLAY OFF',channel); if verbose >= 2, fprintf(1, 'kpib/HP_54800: Channel %d off.\n',channel); end case {'query','?'} % HP_54800 queries each channel separately retval=[]; for cd=1:4 fprintf(io, ':CHAN%d:DISPLAY?',cd); dstr=fscanf(io,'%d'); retval=[retval dstr]; end retval=num2str(retval,'%d'); if verbose >= 2, fprintf(1, 'kpib/HP_54800: Display state: %s\n',retval); end otherwise if verbose >= 2, fprintf(1, 'kpib/HP_54800: Error: ''display'' VALUE not understood.\n'); end end case {'channel'} % select a channel if verbose >= 2, fprintf('kpib/HP_54800: Channel Select not supported by instrument (use CHANNEL)\n'); end % if any(channel == [1 2 3 4]) % fprintf(io,'SELECT:CH%d ON',channel); % select a channel % if verbose >= 2, fprintf(1, 'kpib/HP_54800: Channel %d selected.\n',channel); end % end case 'getdata' %ok if ~(any(channel == [1 2 3 4])) if verbose >= 2, fprintf(1, 'kpib/HP_54800: Default channel 1 selected.\n'); end channel=1; else if verbose >= 2, fprintf(1, 'kpib/HP_54800: Channel %d selected.\n',channel); end end if any(channel == [1 2 3 4]) % NOTE: the 54845A has a bug in the ASCII data % transfer- random LF characters are inserted in the % data stream, which causes matlab to terminate the % read early. So, use binary format instead. fprintf(io,':WAVEFORM:FORMAT WORD'); % Word (2-byte) format data fprintf(io,':WAVEFORM:BYTEORDER LSBF'); % Least significant first fprintf(io,':WAVEFORM:SOURCE CHAN%d',channel); % select channel if isnumeric(aux) && aux > 0 if aux > 801, aux = 801; end fprintf(io,':ACQUIRE:POINTS %f',aux); end %fprintf(io,':DIGITIZE CHAN%d',channel); % capture the data %fprintf(io,':DIGITIZE'); % better without CHANNEL ? (p8-7) pause(2); % to ensure that digitizing completes fprintf(io,':WAVEFORM:POINTS?'); % aux=fscanf(io,'%i'); % number of data points if verbose >= 2, fprintf(1, 'kpib/HP_54800: Channel %d, %d data points.\n',channel,aux); end fprintf(io,':WAVEFORM:PRE?'); % download the preamble preamble = fscanf(io); % preamble is comma-separated numbers %disp('(press any key)'); pause % Process the preamble % Preamble has several useful fields (manual p25-36,25-39): % (1) FORMAT : int16 0 = ASCII, 1 = BYTE, 2 = WORD % (2) TYPE : int16 1 = RAW, 2 = AVERAGE % (3) POINTS : int32 number of data points transferred % (4) COUNT : int32 1 and is always 1 % (5) XINCREMENT : float32 - time difference between data points % (6) XORIGIN : float64 - always the first data point in memory % (7) XREFERENCE : int32 - specifies the data point associated with x-origin (0) % (8) YINCREMENT : float32 - voltage difference between data points % (9) YORIGIN : float32 - value is the voltage at center screen % (10)YREFERENCE : int16 - specifies data point where y-origin occurs % ... % (21) X units : int16 0 = Unknown, 1 = Volts, 2 = Seconds, % (22) Y units : 3 = Constant, 4 = Amp, 5 = Decibel %pre=strread(preamble,'%f','delimiter',','); %pre = sscanf(preamble,'%s,'); pre = textscan(preamble,'%s','Delimiter',','); % v4.86 pre=pre{1}; % cell array of cells not necessary %if verbose >= 3, fprintf(1, 'points: %s\n',pre{3}); end if verbose >= 3 fprintf(1, 'kpib/HP_54800: Data preamble:\n'); for i=1:length(pre) fprintf(1, 'Field %2d: %s\n',i,pre{i}); end end %disp('(press any key)'); pause % Converts the necessary preamble values from strings into % numbers. numdatapoints = str2num(pre{3}); % The number of data points xincr = str2num(pre{5}); % The x increment xoffset = str2num(pre{6}); % The x origin (left side of screen) yincr = str2num(pre{8}); % The y increment yzero = str2num(pre{9}); % The y origin yoffset = str2num(pre{10}); % the y value at the origin % Read the data from the oscilloscope fprintf(io,':WAVEFORM:DATA?'); % The binary data starts with "#" (1 byte) and a number NN (1 byte). % N is the number of bytes immediately following which compose a number % in ASCII characters, BN. BN is the number of bytes of data which follow. yd = fread(io,2,'char'); % Get the "#" and the number NN. nn=str2num(char(yd(2))); yd = fread(io,nn,'char'); % Now read NN bytes bn=str2num(char(yd')); % and concatenate these numbers together to get BN if rem(bn,2) && verbose >= 2 fprintf(1, 'kpib/HP_54800: Warning: number of bytes expected is odd (%g).\n',bn); end yval = fread(io,bn/2,'int16'); % and read BN bytes of data, in Word (2-byte) format. if verbose >= 2, fprintf(1, 'kpib/HP_54800: Data downloaded.\n'); end actualdatapoints = length(yval); % scale the data % the binary y data is integers from the A-D converter. Scale % by the values from the preamble retval.y=((yval-yoffset).*yincr)+yzero; % generate the corresponding x values retval.x=([0:1:numdatapoints-1]'*xincr); retval.x = retval.x + xoffset; % other data % voltage offset fprintf(io,'CHANNEL%d:OFFSET?',channel); retval.offset=fscanf(io,'%f'); retval.x_incr=xincr; % units are in preamble switch str2num(pre{21}) case 0 retval.units.x = '?'; case 1 retval.units.x = 'V'; case 2 retval.units.x = 'sec'; case 3 retval.units.x = '[Constant]'; case 4 retval.units.x = 'Amp'; case 5 retval.units.x = 'dB'; otherwise retval.units.x = '??'; if verbose >= 1, fprintf(1, 'kpib/HP_54800: WARNING: X units error\n'); end end switch str2num(pre{22}) case 0 retval.units.y = '?'; case 1 retval.units.y = 'V'; case 2 retval.units.y = 'sec'; case 3 retval.units.y = '[Constant]'; case 4 retval.units.y = 'Amp'; case 5 retval.units.y = 'dB'; otherwise retval.units.y = '??'; if verbose >= 1, fprintf(1, 'kpib/HP_54800: WARNING: Y units error\n'); end end if actualdatapoints~=numdatapoints if verbose >= 1 fprintf(1, 'kpib/HP_54800: WARNING: number of data points received from scope appears to be incorrect.\n'); fprintf(1, ' Expected: %d, Received: %d [Using Received]\n',numdatapoints,actualdatapoints); fprintf(1, ' (Try Reset GPIB with ''clear'' or check io.Buffersize)\n'); retval.y=retval.y(1:actualdatapoints); retval.x=retval.x(1:actualdatapoints); end end % restart the scope (stops during data download) fprintf(io,':CHAN%d:DISPLAY ON',channel); fprintf(io,':RUN'); else if verbose >= 1, fprintf(1, 'kpib/HP_54800: Error: channel specified incorrectly.\n'); end retval=0; end case {'run','RUN','on','ON','go','GO'} fprintf(io,':RUN'); if verbose >= 2, fprintf(1, 'kpib/HP_54800: Scope running\n'); end case {'stop','STOP','off','OFF'} fprintf(io,':STOP'); if verbose >= 2, fprintf(1, 'kpib/HP_54800: Scope stopped\n'); end otherwise if verbose >= 1, fprintf(1, 'kpib/HP_54800: Error, command not supported. ["%s"]\n',command); end retval=0; end else % catch incorrect address errors if verbose >= 1, fprintf('kpib/%s: ERROR: No instrument at GPIB %d\n',instrument,GPIB); end retval=0; end validInst = 1; end % end HP_54800
'OH_EXP' Ohaus Explorer and Explorer Pro precision balances
This code should be valid for all members of the Ohaus Explorer and Explorer Pro family of balances, but some advanced features may not be supported. This code was tested only against a Explorer EOL210. Use a serial port to sonnect to this instrument.
NOTE: The default serial port settings for Explorers are 2400/7/2/1, which is unusual. Make life easy for yourself and use the "RS-232" menu on the balance to change the settings to 2400/8/N/1, which is more normal. You may also have to disable the "Auto-Print" feature.
IMPORTANT: The Explorers have a so-called "RS232" port, but they require a custom serial cable that does not conform to any known standard. Regular serial cables will not work! You must use a DE9 cable with the pinout shown in the manual. In addition, data returned is always terminated with a CRLF (two characters).
%RETVAL = KPIB('INSTRUMENT', GPIB, 'COMMAND', VALUE, CHANNEL, AUX, VERBOSE) % Valid Commands: % 'ID?' Returns instrument ID and firmware revision. % 'read' Returns a measurement in the current mode % (default 'weigh' mode) without units. Also 'print'. % 'measure' Returns a measurement in the current mode in a structure % with units. Also 'weigh'. If the units result has a "?" % after it, then the balance is not stable. Example: % retval.val = 34 % retval.units = 'g' % Use VALUE = 'animal' to start an animal measurement cycle. % 'units' Set the units to VALUE ('mg' | 'g' | 'kg' | 'kt' | 'oz'). % [This is the "mode" of the balance.] % Note the each unit must be "enabled" using the % front-panel Setup menu. If a unit is not enabled, the % 'units' command has no effect. % 'mode' Set balance to mode VALUE ('weigh' | 'percent' | 'parts' | 'animal') % Use CHANNEL for reference value for percent or parts counting. % [This is the "function" of the balance.] % Note the each mode or function must be "enabled" using the % front-panel Setup menu. If a function is not enabled, the % 'mode' command has no effect. % 'zero' Set the current value to zero. Also 'O/T'. This is the % same as pressing the "0/T" button on the front panel. % 'offset' Set the offset weight value (tare weight) to VALUE in grams. % Also 'tare'. % % if (strcmpi(instrument, 'OH_EXP') || strcmpi(instrument, 'all')) baudrate = 2400; % baud rate for serial port instruments io = port(GPIB, instrument, baudrate, verbose); if (io ~=0) && (strcmp(get(io,'Status'),'open') ~=0) switch command case {'ID?','init','version'} fprintf(io,'0A'); % auto-print off fprintf(io,'V'); % display EEPROM version retval = fscanf(io); retval=retval(1:end-2); % strip trailing CRLF fprintf(io,'SN'); % display serial number sn = fscanf(io,'%s'); unitz = kpib(instrument,GPIB,'units','?',0,0,0); func = kpib(instrument,GPIB,'mode','?',0,0,0); if verbose >= 2 fprintf(1, 'kpib/%s: Initialize:\n Balance firmware %s\n',instrument,retval); fprintf(1,' Serial Number: %s.\n',sn); fprintf(1,' Function: %s, Mode (units): "%s".\n',func,unitz); end case {'zero','O/T'} fprintf(io,'T'); if verbose >= 2, fprintf(1, 'kpib/%s: Balance zero value set.\n',instrument); end case {'units'} switch value case {'mg','MG'} fprintf(io,'1M'); if verbose >= 2, fprintf(1, 'kpib/%s: Balance units set to milligrams ("mg").\n',instrument); end case {'g','G'} fprintf(io,'2M'); if verbose >= 2, fprintf(1, 'kpib/%s: Balance units set to grams ("g").\n',instrument); end case {'kg','KG'} fprintf(io,'3M'); if verbose >= 2, fprintf(1, 'kpib/%s: Balance units set to kilograms ("kg").\n',instrument); end case {'kt','KT','carats','Carats','cd','CD'} fprintf(io,'5M'); if verbose >= 2, fprintf(1, 'kpib/%s: Balance units set to carats ("cd").\n',instrument); end case {'oz','OZ','ounces'} fprintf(io,'6M'); if verbose >= 2, fprintf(1, 'kpib/%s: Balance units set to ounces ("oz").\n',instrument); end case {'?','query'} fprintf(io,'?'); retval = fscanf(io,'%s'); if verbose >= 2, fprintf(1, 'kpib/%s: Balance units setting is "%s".\n',instrument,retval); end otherwise if verbose >= 1, fprintf(1, 'kpib/%s: Warning: Balance units command not understood ("%s")\n',instrument,value); end end case {'mode'} switch value case {'weigh','none'} fprintf(io,'0F'); if verbose >= 2, fprintf(1, 'kpib/%s: Balance mode set to normal weighing.\n',instrument); end case {'%','percent'} fprintf(io,'1F'); if channel > 0 cmd = [num2str(channel) '%']; fprintf(io,cmd); if verbose >= 2, fprintf(1, 'kpib/%s: Balance mode set to percent relative to %e grams.\n',instrument,channel); end else if verbose >= 2, fprintf(1, 'kpib/%s: Balance mode set to percent.\n',instrument); end if verbose >= 2, fprintf(1, 'kpib/%s: Warning: reference value not set (use CHANNEL).\n',instrument); end end case {'parts','Parts'} fprintf(io,'2F'); if channel > 0, cmd = [num2str(channel) '#']; fprintf(io,cmd); if verbose >= 2, fprintf(1, 'kpib/%s: Balance mode set to parts count relative to %e grams.\n',instrument,channel); end else if verbose >= 2, fprintf(1, 'kpib/%s: Balance mode set to parts.\n',instrument); end if verbose >= 2, fprintf(1, 'kpib/%s: Warning: reference value not set (use CHANNEL).\n',instrument); end end case {'animal','Animal'} fprintf(io,'3F'); if verbose >= 2, fprintf(1, 'kpib/%s: Balance mode set to Animal Weighing.\n',instrument); end case {'?','query'} fprintf(io,'F'); retval = fscanf(io,'%s'); if strcmp(retval,'None'), retval = 'Normal Weighing ("None")'; end if verbose >= 2, fprintf(1, 'kpib/%s: Balance mode is "%s".\n',instrument,retval); end otherwise if verbose >= 1, fprintf(1, 'kpib/%s: Warning: Balance mode command not understood ("%s")\n',instrument,value); end end case {'read','print','P'} fprintf(io,'P'); ret = fscanf(io); % find out if we have a negative value or not if isnumeric(sscanf(ret,'%f')) retval = sscanf(ret,'%f'); else retval = sscanf(ret,'-%f'); retval=retval*-1; end if verbose >= 2, fprintf(1, 'kpib/%s: Balance reads %f\n',instrument,retval); end case {'measure','weigh','weight'} if ~isnumeric(value) && strcmpi(value,'animal') fprintf(io,'E'); else fprintf(io,'P'); ret = fscanf(io); % find out if we have a negative value or not if isnumeric(sscanf(ret,'%f')) retv = textscan(ret,'%f %s %s'); retval.val = retv{1}; retval.units = [retv{2}{1} retv{3}{1}]; if isempty(retv{2}) && verbose >= 2 fprintf(1, 'kpib/%s: Note: unit printing not enabled.\n',instrument); end else retv = textscan(ret,'%c %f %s %s'); retval.val = retv{2}*-1; retval.units = [retv{3}{1} retv{4}{1}]; if isempty(retv{3}) && verbose >= 2 fprintf(1, 'kpib/%s: Note: unit printing not enabled.\n',instrument); end end end if verbose >= 2, fprintf(1, 'kpib/%s: Balance reads %f %s.\n',instrument,retval.val,retval.units); end case {'offset','tare'} if isnumeric(value) cmd = [num2str(value) 'T']; fprintf(io,cmd); if verbose >= 2, fprintf(1, 'kpib/%s: Balance offset (tare weight) set to %g grams.\n',instrument,value); end else if verbose >= 1, fprintf(1, 'kpib/%s: Warning: Offset weight not valid ("%s")\n',instrument,num2str(value)); end end otherwise if verbose >= 1, fprintf(1,'kpib/%s: Error, command not supported. ["%s"]\n',instrument,command); end end else % catch incorrect address errors if verbose >= 1, fprintf(1,'kpib/%s: ERROR: No instrument at GPIB %s\n',instrument,num2str(GPIB)); end retval=0; end validInst = 1; end % End OH_EXP % %%%%%
'CV_TIC304' CryoVac TIC 304-MA Temperature Controller
The CryoVac TIC 304-MA Temperature Controller is sold with the Karl Suss cryogenic probe station. The stsation must be set for "remote" mode by enabling it on the front panel after startup (press "DIAL 8").
Note that the TIC is intended for use with cryogenic systems, so its default temperature units are in Kelvin. The default for temperature units in KPIB is degrees C. Specify units with the AUX parameter ('C' 'K').
%RETVAL = KPIB('INSTRUMENT', GPIB, 'COMMAND', VALUE, CHANNEL, AUX, VERBOSE) % Valid oven commands: % 'init' Initializes instrument and makes ready for measurement % 'self' Begin instrument self-destruct procedure % if (strcmpi(instrument, 'CV_TIC304') || strcmpi(instrument, 'all')) baudrate = 0; % buffer size for GPIB (0 for default), baud rate for serial port instruments io = port(GPIB, instrument, baudrate, verbose); if (io ~=0) && (strcmp(get(io,'Status'),'open') ~=0) lowlim = 20; % lower limit of input in K highlim = 125; % upper limit of temerpature in K switch command case 'init' if verbose >= 1, fprintf('kpib/%s: Initializing CryoVac at address %.0f\n',instrument,GPIB); end % what kind of reset? try fprintf(io,'?K1'); retval = fscanf(io, '%f'); fprintf(1,'kpib/%s: Controller on. Temperature Setpoint %f K.\n',instrument,retval); catch fprintf(1,'kpib/%s: Controller does not respond. Verify that it is in remote mode.\n',instrument); end case {'set','setT'} % did user specify a channel? if isnumeric(channel) && any(channel==[1 2]) if verbose >= 2, fprintf('kpib/%s: Channel F%d selected\n',instrument, channel); end else channel = 1; if verbose >= 2, fprintf('kpib/%s: Channel F%d (default)\n',instrument, channel); end end command = sprintf('R%d',channel); fprintf(io,command); % set the active channel if isnumeric(value) % proceed if a number was entered % did the user specify temperature units? if strcmpi(aux,'K') if verbose >= 2, fprintf('kpib/%s: Temperature units of degrees %s\n',instrument, aux); end valueC = value - 273; % convert to C else aux = 'C'; % default to degrees celcius if verbose >= 3, fprintf('kpib/%s: Temperature units of degrees %s (default)\n',instrument, aux); end valueC = value; value = value + 273; % convert to K end % check input range (deg K) if value < lowlim value = lowlim; if verbose >= 1, fprintf('kpib/%s: Warning: Temperature setpoint below lower limit (%d K)\n',instrument,lowlim); end end if value > highlim value = highlim; if verbose >= 1, fprintf('kpib/%s: Warning: Temperature setpoint above upper limit (%d K)\n',instrument,highlim); end end % set the temperature setpoint (K) command = sprintf('KS %d',value); fprintf(io,command); % set setpoint for current channel if verbose >= 2, fprintf('kpib/%s: Temperature set to %d C (%d K)\n',instrument,valueC,value); end elseif strcmpi(value,'query') || strcmpi(value,'?') fprintf(io,'?KS'); % query temperature setpoint for current channel retval = fscanf(io, '%f'); % did the user specify temperature units? if strcmpi(aux,'K') if verbose >= 2, fprintf('kpib/%s: Temperature units of degrees %s\n',instrument,aux); end else aux = 'C'; if verbose >= 3, fprintf('kpib/%s: Temperature units of degrees %s\n',instrument,aux); end retval = retval - 273; % convert to C end if verbose >= 2, fprintf(1,'kpib/%s: Setpoint: %d %s\n',instrument,retval,aux); end else if verbose >= 1, fprintf(1,'kpib/%s: "set" command error\n',instrument); end end % set case {'read','getdata'} if isnumeric(channel) && ~any(channel==[1 2]), channel = 1; end % default to channel 1 if verbose >= 2, fprintf('kpib/%s: Reading the F%d temperature:',instrument,channel); end command = sprintf('?K%d',channel); fprintf(io,command); % query temperature retval = fscanf(io, '%f'); % did the user specify temperature units? if strcmpi(aux,'K') if verbose >= 2, fprintf('kpib/%s: Temperature units of degrees %s\n',instrument,aux); end else aux = 'C'; if verbose >= 3, fprintf('kpib/%s: Temperature units of degrees %s\n',instrument,aux); end retval = retval - 293; % convert to C end if verbose >= 2, fprintf(1,' %.1f %s\n',retval,aux); end case 'stop' if verbose >= 2, fprintf('kpib/%s: Stopping the Temperature Controller\n',instrument); end fprintf(io, 'R0'); % "control off'. end else % catch incorrect address errors if verbose >= 1, fprintf(1,'kpib/%s: ERROR: No instrument at GPIB %s\n',instrument,num2str(GPIB)); end retval=0; end validInst = 1; end % %%%%% end 'CV_TIC304' % %%%%%
'AG_E5071B' Agilent E5070B/E5071B RF Network Analyzer
The Agilent E5071B Network Analyzer is a powerful 2-port analyzer. NOTE: Analyzer firmware update A.06.51 or higher is required for averaging-related commands.
With contributions from DAmien Wittwer and Mehmet Akgul
%RETVAL = KPIB('INSTRUMENT', GPIB, 'COMMAND', VALUE, CHANNEL, AUX, VERBOSE) % VALUE is typically the modifier to COMMAND. % Valid Commands: % 'init' Resets the Analyzer. Returns the decimal value of the status % byte (should be zero for normal condition). % 'label' Writes 'VALUE' to the display. No spaces or punctuation. % 'channel' Makes channel VALUE the active channel. NOTE: 'channel' % (1-16) corresponds to Traces on the analyzer screen. See % Note below. To change the Channel, use the parameter 'aux' % (1-16). Default is 1. % 'display' Controls what is displayed on the Analyzer screen. % VALUE can be any of the four registers: 'a','b','c','d' and % CHANNEL is 'on' or 'off'. % 'format' Set the format of the active trac on the Analyzer display: % LogMag, Phase, etc. Use CHANNEL to select the active trace. % non-exponentially ('norm'). Exponentially is the default. % 'scale' Sets the scale of the display. VALUE is the scale in the % current units, or VALUE = 'auto' for autoscale command. % 'ref line' Sets the position of the reference line of the display. % VALUE is the position of the reference line in the current % units. % 'average' Turns averaging on or off, restarts averaging, or returns % the current number of averages taken. % VALUE='on','off','restart', or 'query'. For 'query', RETVAL % returns 0 (off) or the current number of averages (on). % 'mark2peak' Finds the peak and sets the marker, or finds the peak and % sets the peak location to the center of the scan. % VALUE='off','center', or 'peak'. % 'marker' Turns the marker on or off, or returns the current % position of the marker. 'VALUE' = 'on','off', or 'query'. % The position is returned as retval.x, retval.y in current % units. % 'center' Set the center frequency to VALUE. Units of Hz. % Query with VALUE = 'query', returns center frequency in Hz. % 'span' Set the frequency span VALUE. Units of Hz. % Query with VALUE = 'query', returns span in Hz. % 'sweep' Sets sweep parameters. Use VALUE='hold' to stop/start sweeps. % 'source' Set the source (stimulus output) signal level. VALUE is the % desired signal level. Units of dBm. % Query with VALUE = 'query', returns source power in dBm. % 'power' Same as 'source'. % 'getdata' Download the current data trace from the analyzer. Data is % returned as two columns, x and y, for the specified % CHANNEL. Default CHANNEL is not set. If VALUE is 'x' or 'y', % only that data is returned in a single column. % 'units' Returns the units of the data from the analyzer. Must % specify VALUE = 'x' or 'y' axis units. % 'pause' Pauses measurement. % 'continue' Continues paused measurement. % 'complete' Wait for the previous sweep to complete. This command % contains a loop that does not exit until the status byte shows % that the sweep is complete. Use with 'sweep','single' or % 'complete','single'. % 'screenshot' Saves the current screen view to the USB drive (G:) as % VALUE.png. % %NOTE: The E5070B/E5071B uses "Channels" and "Traces". Channels are a % particular group of settings for measurement parameters. Traces are % measurement data that is displayed on the screen. For example, for a % typical resonator measurement, Channel 1 of the analyzer might be % configured for a frequency sweep with 0 dBm stimulus power. Trace 1 of % Channel 1 would show the response amplitude, and Trace 2 of Channel 1 % would show the phase response. % In KPIB, the parameter CHANNELS refers to the Traces on the analyzer % screen, and the analyzer is assumed to be configured as described in the % example above. Use AUX to specify a different Analyzer Channel. % if (strcmpi(instrument, 'AG_E5070B') || strcmpi(instrument, 'AG_E5071B') || strcmpi(instrument, 'all')) io = port(GPIB, instrument, 40*1601, verbose); % buffer size for downloading data points if (io ~=0) && (strcmp(get(io,'Status'),'open') ~=0) switch command case 'init' if isnumeric(aux) && aux==0, aux=1; end %fprintf(io,'*RST'); fprintf(io,'*CLS'); fprintf(io,'*STB?'); retval=fscanf(io,'%d'); % set data transfer type to ascii fprintf(io,':FORM:DATA ASCII'); % set trigger state to Continuous cmd = sprintf(':INIT%d:CONT ON',aux); fprintf(io,cmd); if verbose >= 2 fprintf(1, 'kpib/AG_E5071B: Initialize. Make sure instrument is configured.\n'); end if verbose >= 3 fprintf(1,'kpib/AG_E5071B: Status byte: %s\n',dec2bin(retval,8)); fprintf(io,'*IDN?'); idstring = fscanf(io,'%s'); fprintf(1, 'kpib/AG_E5071B: %s\n',idstring); end case 'label' % manual p477 if length(value) > 254 value=value(1:254); % 254 chars max end % no spaces or punctuation allowed value(isspace(value)) = '_'; value(ismember(value,' ,.:;![]{}')) = []; if channel==0, channel=1; end if ~isnumeric(channel), channel = 1; end %cmd = sprintf(':DISP:WIND%d:TITL ON',channel); fprintf(io,cmd); cmd = sprintf(':DISP:WIND%d:TITL:DATA %s',channel,value); fprintf(io,cmd); case {'channel','CHAN'} % NOTE that "traces" are "channels" for our purposes % so this command sets trace 'channel' (PAR) to active % (manual p424) if isnumeric(aux) && aux==0, aux=1; end if isnumeric(channel) && channel==0 && isnumeric(value), channel=value; end cmd = sprintf(':CALC%d:PAR%d:SELECT',aux,channel); fprintf(io,cmd); if verbose >= 3 fprintf(1, 'kpib/AG_E5071B: Channel %d selected.\n', channel); end case {'display','trace'} %:DISP:WIND1:TRAC1:STAT? :CALC{1-16}:PAR:COUN? if isnumeric(aux) && aux==0, aux=1; end switch value case {'dual'} % for compatibility with res_meas switch channel case {'query','?'} cmd = sprintf(':CALC%d:PAR:COUNT?',aux); fprintf(io,cmd); dcount = fscanf(io,'%d'); % up to 16 possible if verbose >= 3, fprintf(1, 'kpib/AG_E5071B: %d Traces displayed.\n', dcount); end if dcount==2 retval=1; else retval=0; end otherwise % turn on both traces for i=1:2 cmd = sprintf(':DISP:WIND%d:TRACE%d:STAT ON',aux,i); fprintf(io,cmd); end retval = 1; end case {'query','?'} cmd = sprintf(':CALC%d:PAR:COUNT?',aux); fprintf(io,cmd); dcount = fscanf(io,'%d'); % up to 16 possible if verbose >= 2, fprintf(1, 'kpib/AG_E5071B: %d Traces displayed.\n', dcount); end case {'on','ON'} if isnumeric(channel) && channel > 0 cmd = sprintf(':DISP:WIND%d:TRACE%d:STAT ON',aux,channel); fprintf(io,cmd); if verbose >= 2, fprintf(1, 'kpib/AG_E5071B: Trace %d on.\n',channel); end end case {'off','OFF'} if isnumeric(channel) && channel > 0 cmd = sprintf(':DISP:WIND%d:TRACE%d:STAT OFF',aux,channel); fprintf(io,cmd); if verbose >= 2, fprintf(1, 'kpib/AG_E5071B: Trace %d off.\n',channel); end end end case 'format' if isnumeric(aux) && aux==0, aux=1; end if isnumeric(channel) && channel ~= 0 kpib(instrument,GPIB,'channel',0,channel,aux,verbose); elseif channel == 0 channel = 1; end switch value case {'MLOG','logmag','LogMag'} fprintf(io,':CALC%d:FORM MLOG',aux); if verbose >= 2, fprintf(1, 'kpib/AG_E5071B: Format of Channel [Trace] %d set to LogMag.\n',channel); end case {'PHAS','phase','Phase'} fprintf(io,':CALC%d:FORM PHAS',aux); if verbose >= 2, fprintf(1, 'kpib/AG_E5071B: Format of Channel [Trace] %d set to Phase.\n',channel); end case {'REAL','real','Real'} fprintf(io,':CALC%d:FORM REAL',aux); if verbose >= 2, fprintf(1, 'kpib/AG_E5071B: Format of Channel [Trace] %d set to Real.\n',channel); end case {'IMAG','imaginary','Imaginary'} fprintf(io,':CALC%d:FORM REAL',aux); if verbose >= 2, fprintf(1, 'kpib/AG_E5071B: Format of Channel [Trace] %d set to Imaginary.\n',channel); end case {'?','query'} fprintf(io,':CALC%d:FORM?',aux); retval = fscanf(io,'%s'); if verbose >= 2, fprintf(1, 'kpib/AG_E5071B: Format of Channel [Trace] %d is %s.\n',retval); end end case 'scale' if isnumeric(aux) && aux==0, aux=1; end % the "window" or "channel" if channel==0, channel = 1; end % the "trace" if isnumeric(value) cmd = sprintf(':DISP:WIND%d:TRAC%d:Y:PDIV %e',aux,channel,value); fprintf(io,cmd); if verbose >= 2, fprintf(1, 'kpib/AG_E5071B: Scale set to %g/division.\n',value); end else switch value case {'auto','AUTO'} cmd = sprintf(':DISP:WIND%d:TRAC%d:Y:AUTO',aux,channel); fprintf(io,cmd); if verbose >= 2, fprintf(1, 'kpib/AG_E5071B: Autoscale channel %d.\n',channel); end case {'?','query'} cmd = sprintf(':DISP:WIND%d:TRAC%d:Y:PDIV?',aux,channel); fprintf(io,cmd); retval = fscanf(io,'%f'); if verbose >= 2, fprintf(1, 'kpib/AG_E5071B: Scale on channel %d is %g/division.\n',channel,retval); end case {'lin','linear'} fprintf(io,'SCT1'); if verbose >= 2, fprintf(1, 'kpib/HP_4195A: Linear X scale.\n'); end case {'log','logarithmic'} fprintf(io,'SCT2'); if verbose >= 2, fprintf(1, 'kpib/HP_4195A: Logarithmic X scale.\n'); end end end case 'autoscale' kpib(instrument,GPIB,'scale','auto',channel,aux,verbose); case {'ref line','refline'} % manual p483 if isnumeric(aux) && aux==0, aux=1; end % the "window" or "channel" if channel==0, channel = 1; end % the "trace" if isnumeric(value) cmd = sprintf(':DISP:WIND%d:TRACE%d:Y:RLEV %e',aux,channel,value); fprintf(io,cmd); if verbose >= 2, fprintf(1, 'kpib/AG_E5071B: Reference line set to %g dB.\n',value); end else switch value case{'?','query'} cmd = sprintf(':DISP:WIND%d:TRACE%d:Y:RLEV?',aux,channel); fprintf(io,cmd); retval = fscanf(io,'%f'); end end case {'ifbw','bandwidth'} %ok if channel==0, channel=1; end % default to channel 1 (trace 1) switch value case {'query','?'} cmd = sprintf(':SENS%d:BAND?',channel); fprintf(io,cmd); retval = fscanf(io,'%f'); otherwise if isnumeric(value) && value>=10 && value<=100000 cmd = sprintf(':SENS%d:BAND %f',channel,value); fprintf(io,cmd); if verbose >= 2, fprintf(1, 'kpib/HP_5071B: Channel %g IF Bandwidth set to %f Hz\n',channel,value); end else if verbose >= 1, fprintf(1, 'kpib/HP_5071B: Warning: Must enter a IFBW value between 10 and 100000!\n'); end end end case {'average','averaging'} % manual p543 if isnumeric(aux) && aux==0, aux=1; end % the "window" or "channel" switch value case {'on','ON','yes',1} fprintf(io,':SENS%d:AVER ON',aux); fprintf(io,':TRIG:AVER ON'); if verbose >= 2, fprintf(1, 'kpib/AG_E5071B: Sweep Averaging on'); end if isnumeric(channel) && channel > 1 && channel < 1000 cmd = sprintf(':SENS%d:AVER:COUN %d',aux,channel); fprintf(io,cmd); if verbose >= 2, fprintf(1, ', aver. factor: %d\n',channel); end else if verbose >= 2, fprintf(1, '\n'); end end case {'off','OFF','no',0} fprintf(io,':SENS%d:AVER OFF',aux); fprintf(io,':TRIGGER:AVERAGE OFF'); %retval = 0; if verbose >= 2, fprintf(1, 'kpib/AG_E5071B: Averaging disabled\n'); end case {'query','?'} fprintf(io, ':SENS%d:AVER?',aux); retval = fscanf(io,'%f'); case {'num','num?','number','number?','count','count?'} % return the current average count fprintf(io, ':SENS%d:AVER:COUNT?',aux); retval = fscanf(io,'%f'); if verbose >=2, fprintf(1, 'kpib/AG_E5071B: Average count: %d\n',retval); end case {'finish','complete'} kpib(instrument,GPIB,'complete','group',channel,aux,verbose); case {'restart','clear'} fprintf(io,':SENS%d:AVER:CLEAR',aux); otherwise % set the number of measurements to average if isnumeric(value) && value > 0 if value > 0 cmd = sprintf(':SENS%d:AVER:COUNT %d',aux,value); fprintf(io,cmd); if verbose >=2, fprintf(1, 'kpib/AG_E5071B: Averaging factor set to %d\n',value); end end end end case 'center' if channel==0, channel = 1; end % default to channel 1 switch value case {'query','?'} cmd=sprintf(':SENS%d:FREQ:CENTER?',channel); fprintf(io,cmd); retval = fscanf(io,'%f'); otherwise cmd=sprintf(':SENS%d:FREQ:CENTER %f',channel,value); fprintf(io,cmd); if verbose >= 2, fprintf(1, 'kpib/AG_E5071B: Center set to %d Hz\n',value); end end case 'span' if channel==0, channel = 1; end % default to channel 1 switch value case {'query','?'} cmd=sprintf(':SENS%d:FREQ:SPAN?',channel); fprintf(io,cmd); retval = fscanf(io,'%f'); otherwise cmd=sprintf(':SENS%d:FREQ:SPAN %f',channel,value); fprintf(io,cmd); if verbose >= 2, fprintf(1, 'kpib/AG_E5071B: Span set to %d Hz\n',value); end end case 'start' if channel==0, channel = 1; end % default to channel 1 switch value case {'query','?'} cmd=sprintf(':SENS%d:FREQ:START?',channel); fprintf(io,cmd); retval = fscanf(io,'%f'); otherwise cmd=sprintf(':SENS%d:FREQ:START %f',channel,value); fprintf(io,cmd); if verbose >= 2, fprintf(1, 'kpib/AG_E5071B: Start set to %f Hz\n',value); end end case 'stop' if channel==0, channel = 1; end % default to channel 1 switch value case {'query','?'} cmd=sprintf(':SENS%d:FREQ:STOP?',channel); fprintf(io,cmd); retval = fscanf(io,'%f'); otherwise cmd=sprintf(':SENS%d:FREQ:STOP %f',channel,value); fprintf(io,cmd); if verbose >= 2, fprintf(1, 'kpib/AG_E5071B: Stop set to %f Hz\n',value); end end case {'power','source'} %ok if isnumeric(aux) && aux==0, aux=1; end if channel==0, channel = 1; end % default to channel 1 if isnumeric(value) cmd = sprintf(':SOUR%d:POW:PORT%d %d',aux,channel,value); fprintf(io,cmd); if verbose >= 2, fprintf('kpib/AG_E5071B: Source Source Power on Port %d set to %d dBm\n',channel,value); end else switch value case {'query','?'} cmd = sprintf(':SOUR%d:POW:PORT%d?',aux,channel); fprintf(io,cmd); retval = fscanf(io,'%f'); if verbose >= 2, fprintf(1, 'kpib/AG_E5071B: Source Power on Port %d is %d dBm\n',channel,retval); end end end case {'power?','source?'} % alternate query form retval.level=kpib(instrument,GPIB,'source','?',channel,aux,verbose); retval.state = 'on'; case {'marker','mkr'} % select the channel (for the marker command only) if channel == 0, channel = 1; end % default to channel 1 if aux == 0, aux = 1; end % default to marker 1 switch value case 'on' cmd=sprintf(':CALC%d:MARK%d ON',channel,aux); fprintf(io,cmd); if verbose >= 2, fprintf(1, 'kpib/AG_E5071B: Marker %d/%d on.\n',channel,aux); end case 'off' cmd=sprintf(':CALC%d:MARK%d OFF',channel,aux); fprintf(io,cmd); if verbose >= 2, fprintf(1, 'kpib/AG_E5071B: Marker %d/%d off.\n',channel,aux); end case {'query','?'} cmd=sprintf(':CALC%d:MARK%d:X?',channel,aux); fprintf(io,cmd); retval.x = fscanf(io,'%f'); cmd=sprintf(':CALC%d:MARK%d:Y?',channel,aux); fprintf(io,cmd); retval.y = fscanf(io,'%f'); if verbose >= 2, fprintf(1, 'kpib/AG_E5071B: Marker %d on Trace %d at %g Hz, %g.\n',aux,channel,retval.x,retval.y); end case {'center','m2c','mark2center'} % make the marker position the center freq cmd=sprintf(':CALC%d:MARK%d:SET CENT',channel,aux); fprintf(io,cmd); if verbose >= 2, fprintf(1,'kpib/AG_E5071B: Marker to Center\n'); end case {'peak','searchpeak','mark2peak','m2p'} cmd=sprintf(':CALC%d:MARK%d:FUNC:TYPE PEAK',channel,aux); fprintf(io,cmd); if verbose >= 2, fprintf(1,'%s\n','kpib/AG_E5071B: Marker to Peak'); end cmd=sprintf(':CALC%d:MARK%d:FUNC:EXEC',aux,channel); fprintf(io,cmd); % DO the search case {'min','minimum','valley','antipeak'} cmd=sprintf(':CALC%d:MARK%d:FUNC:TYPE MIN',channel,aux); fprintf(io,cmd); if verbose >= 2, fprintf(1,'%s\n','kpib/AG_E5071B: Marker to Minimum'); end cmd=sprintf(':CALC%d:MARK%d:FUNC:EXEC',aux,channel); fprintf(io,cmd); % DO the search case {'max','maximum'} cmd=sprintf(':CALC%d:MARK%d:FUNC:TYPE MAX',channel,aux); fprintf(io,cmd); if verbose >= 2, fprintf(1,'%s\n','kpib/AG_E5071B: Marker to Maximum'); end cmd=sprintf(':CALC%d:MARK%d:FUNC:EXEC',aux,channel); fprintf(io,cmd); % DO the search case {'stop'} cmd=sprintf(':CALC%d:MARK%d:SET STOP',channel,aux); fprintf(io,cmd); if verbose >= 2, fprintf(1,'%s\n','kpib/AG_E5071B: Marker to Stop'); end case {'start'} cmd=sprintf(':CALC%d:MARK%d:SET START',channel,aux); fprintf(io,cmd); if verbose >= 2, fprintf(1,'%s\n','kpib/AG_E5071B: Marker to Start'); end otherwise if verbose >= 1, fprintf(1, 'kpib/AG_E5071B: Error at ''marker'' command (VALUE incorrect ["%s"]).\n',value); end end case {'mark2peak','peaktrack'} if isnumeric(aux) && aux==0, aux=1; end if channel==0, channel = 1; end % default to channel 1 switch value case 'center' kpib(instrument,GPIB,'mark2peak','peak',channel,aux,verbose); centerf = kpib(instrument,GPIB,'marker','?',channel,aux,verbose); kpib(instrument,GPIB,'center',centerf.x,channel,aux,verbose); if verbose >= 2, fprintf(1,'kpib/AG_E5071B: Marker to Center (%d Hz)\n',centerf.x); end case 'peak' % choose between MAX or PEAK - which is best? cmd=sprintf(':CALC%d:MARK1:FUNC:TYPE MAX',aux); fprintf(io,cmd); %cmd=sprintf(':CALC%d:MARK%d:FUNC:TYPE PEAK',aux,channel); fprintf(io,cmd); cmd=sprintf(':CALC%d:MARK%d:FUNC:EXEC',aux,channel); fprintf(io,cmd); % DO the search if verbose >= 2, fprintf(1,'%s\n','kpib/AG_E5071B: Marker to Peak'); end end case {'mode','type'} % :CALC{1-16}:PAR{1-16}:DEFS11 % set or get instrument mode % find out what mode the analyzer is in: % Network or Spectrum retval = 'NA'; if verbose >= 2, fprintf('kpib/AG_E5071B: Warning: Analyzer does not support mode query (kpib returns ''NA'').\n'); end case 'getdata' % Select the channel. For compatibility with old code, the % channel is *not* set if it is not explicitly specified, i.e., % the default is to do nothing, rather than to select a channel. % The E5071 has multiple Traces and Channels. Usually, we % want to download the data from Trace 1 and Trace 2 on % Channel 1. % data format should be ASCII (see 'init') % Normally, we expect to work with Channel 1. if isnumeric(aux) && aux==0, aux=1; end % now, did the user specify a channel or not? if channel==0, channel = 1; end % Select the desired Trace. cmd=sprintf(':CALC%d:PAR%d:SEL',aux,channel); fprintf(io,cmd); if verbose >= 2, fprintf('kpib/AG_E5071B: Channel [Trace] %d selected for data download.\n',channel); end % get Y data if verbose >= 3, fprintf('kpib/AG_E5071B: Get Y points.\n'); end cmd=sprintf(':CALC%d:DATA:FDAT?',aux); fprintf(io,cmd); rawdata = fscanf(io); rawdata = [rawdata ',']; % append a comma so that the format matching works right retval.y = sscanf(rawdata,'%e,'); % % Note: Data probably has two numbers per data point; % discard every other, depending on data format. See manual page 169 % Get Y data units (What kind of data is this?) cmd=sprintf(':CALC%d:FORM?',aux); fprintf(io,cmd); data_format = fscanf(io,'%s'); if verbose >= 3, fprintf('kpib/AG_E5071B: Data format is %s.\n',data_format); end %'MLOG','PHAS','GDEL','MLIN','SWR','REAL','IMAG','UPH'} switch data_format case {'MLOG'} retval.y=retval.y(1:2:end); retval.units.y='dB'; case {'PHAS'} retval.y=retval.y(1:2:end); retval.units.y='deg'; end % double-check the download fprintf(io,':SENS:SWEEP:POINTS?'); numdatapoints = fscanf(io,'%i'); if (length(retval.y) ~= numdatapoints) if verbose >= 1, fprintf(1, 'kpib/AG_E5071B: WARNING: actual number of y points downloaded (%d)\n',length(retval.y)); fprintf(1,' does not equal expected number of points (%d).\n',numdatapoints); end end % get the x data points if verbose >= 3, fprintf('kpib/AG_E5071B: Get X points.\n'); end fprintf(io,':SENS:FREQ:DATA?'); rawdata = fscanf(io); rawdata = [rawdata ',']; % append a comma so that the format matching works right retval.x = sscanf(rawdata,'%e,'); retval.units.x = 'Hz'; % did we just want some numbers? switch value case {'x','X'} retval=retval.x; case {'y','Y'} retval=retval.y; end case 'sweep' if isnumeric(aux) && aux == 0, aux =1; end % enable the status byte for synchronization (manual p286) fprintf(io,'*CLS'); % clear the status registers if isnumeric(value) % set the sweep time cmd = sprintf(':SENS%d:SWEEP:TIME %e',aux,value); fprintf(io,cmd); else switch value % set sweep type manual p696 case {'linear sweep','lin','linear'} cmd = sprintf(':SENS%d:SWEEP:TYPE LIN',aux); fprintf(io,cmd); case {'log sweep','log','logarithmic'} cmd = sprintf(':SENS%d:SWEEP:TYPE LOG',aux); fprintf(io,cmd); case {'segment'} cmd = sprintf(':SENS%d:SWEEP:TYPE SEG',aux); fprintf(io,cmd); case {'power','power sweep','osc','osclevel'} % cmd = sprintf(':SENS%d:SWEEP:TYPE POW',aux); fprintf(io,cmd); case {'query','?'} cmd = sprintf(':SENS%d:SWEEP:TYPE?',aux); fprintf(io,cmd); retval=fscanf(io,'%s'); % perform sweep action case {'single'} fprintf(io,':TRIGGER:SOURCE BUS'); fprintf(io,':TRIGGER:AVERAGE OFF'); %cmd = sprintf(':INIT%d:CONT OFF',aux); fprintf(io,cmd); %cmd=sprintf(':INIT%d',aux); fprintf(io,cmd); % get out of "hold" state, into "wait" state fprintf(io,':TRIGGER:SINGLE'); if verbose >= 2, fprintf(1, 'kpib/AG_E5071B: Begin single sweep.\n'); end case {'continuous','cont'} fprintf(io,':TRIGGER:SOURCE INTERNAL'); cmd = sprintf(':INIT%d:CONT ON',aux); fprintf(io,cmd); if verbose >= 2, fprintf(1, 'kpib/AG_E5071B: Continuous sweep mode on.\n'); end case {'hold'} % toggle hold state on or off fprintf(io,':INIT%d:CONT?',aux); holdstate = fscanf(io,'%d'); if holdstate == 0 cmd = sprintf(':INIT%d:CONT ON',aux); fprintf(io,cmd); if verbose >= 2, fprintf(1, 'kpib/AG_E5071B: Continuous mode ON.\n'); end elseif holdstate == 1 cmd = sprintf(':INIT%d:CONT OFF',aux); fprintf(io,cmd); if verbose >= 2, fprintf(1, 'kpib/AG_E5071B: Continuous mode OFF ("Hold").\n'); end else if verbose >= 1, fprintf(1, 'kpib/AG_E5071B: WARNING: Hold State uncertain.\n'); end end %if verbose >= 2, fprintf(1, 'kpib/AG_E5071B: Continuous sweep mode off ("hold").\n'); end % This command requires analyzer firmware update A.06.51+ % manual p803 case {'group','groups','number','N'} fprintf(io,':TRIG:AVER ON'); %cmd=sprintf(':INIT%d',aux); fprintf(io,cmd); fprintf(io,':TRIG:SING'); % this triggers a single group of measurements if verbose >= 2, fprintf(1, 'kpib/AG_E5071B: Group sweep (averaging) started.\n'); end case {'setpoints','set','numpoints'} if isnumeric(channel) && channel >= 2 && channel <= 1601 % maximum points is 1601 (p693) cmd = sprintf(':SENS%d:SWEEP:POINTS %d',aux,channel); fprintf(io,cmd); if verbose >= 2, fprintf(1, 'kpib/AG_E5071B: Number of sweep points set to %d.\n',channel); end else if verbose >= 1, fprintf(1, 'kpib/AG_E5071B: Number of sweep points must be between 2 and 1601.\n'); end end case {'restart'} fprintf(io,':ABORT'); otherwise if verbose >= 1, fprintf(1, 'kpib/AG_E5071B: Sweep sub-command not supported ["%s"]\n',num2str(value)); end end end case 'complete' % complete uses the status byte to know when a sweep has completed. % The registers are enabled during the sweep command, above. % can issue a single command for a sweep and complete switch value case {'single','sing','SING'} kpib(instrument, GPIB, 'sweep', 'single', channel, aux, verbose); if verbose >= 2, fprintf('kpib/AG_E5071B: Single Sweep & Complete\n'); end case {'group','groups','number','N'} kpib(instrument, GPIB, 'average', 'on', channel, aux, verbose); num=kpib(instrument, GPIB, 'average', 'number?', channel, aux, verbose); %num=fscanf(io,'%d'); kpib(instrument, GPIB, 'sweep', 'group', channel, aux, verbose); if verbose >= 2, fprintf('kpib/AG_E5071B: Group Sweep (%d) & Complete\n',num); end otherwise if verbose >= 2, fprintf('kpib/AG_E5071B: Waiting for command to complete...\n'); end end % set status register when operation completes (manual p288) fprintf(io,'*OPC'); if verbose >= 2, fprintf('kpib/AG_E5071B: Waiting for sweep to complete...\n'); end warning off instrument:fscanf:unsuccessfulRead retval=0; while 1 pause(1); fprintf(io,'*ESR?'); % check the event status register byte (manual p879) retval=fscanf(io,'%d'); esb=dec2bin(retval,8); % return binary value represents the status registers if verbose >= 3, fprintf(1, 'kpib/AG_E5071B: Status Reg. Byte: %s.\n',esb); end if esb(8) == '1' % Bit 1 indicates operation complete if verbose >= 2, fprintf(1, 'kpib/AG_E5071B: Sweep complete.\n'); end break; end end %cmd=sprintf(':INIT%d',aux); fprintf(io,cmd); % get out of "hold" state, into "wait" state case 'screenshot' screenshotfile = strcat('"G:',num2str(value),'.png"'); screenshotcmd = strcat(':MMEMory:STORe:IMAG ',screenshotfile); fprintf(io,screenshotcmd); if verbose >= 2, fprintf(1, 'kpib/AG_E5071B: Screenshot "%s" saved to USB drive.\n',screenshotfile); end case 'units' % DEPRECATED, 'getdata' includes units if verbose >= 2, fprintf(1, 'kpib/AG_E5071B: Note: units are returned with the ''getdata'' command'.\n'); end switch value case {'x','X'} retval = 'Hz'; case {'y','Y'} retval = 'dB'; otherwise retval.x = 'Hz'; retval.y = 'dB'; end case 'wait' % This doesn't usually have much effect fprintf(io,'*WAI'); retval = 1; case 'continue' retval = 1; if verbose >= 3, fprintf('kpib/%s: WARNING: ''%s'' not supported by %s\n',command,instrument); end case 'pause' retval = 1; kpib(instrument,GPIB,'sweep','hold',channel,aux,verbose); otherwise if verbose >= 1, fprintf(1,'kpib/%s: Error, command not supported. ["%s"]\n',instrument,command); end end else % catch incorrect address errors if verbose >= 1, fprintf(1,'kpib/%s: ERROR: No instrument at GPIB %s\n',instrument,num2str(GPIB)); end retval=0; end validInst = 1; end % %%%%% end 'AG_E5071B'
'SI_9700' Scientific Instruments model 9700 Temperature Controller
The SI 9700 temperature controller maintains temperature at a setpoint.
%RETVAL = KPIB('INSTRUMENT', GPIB, 'COMMAND', VALUE, CHANNEL, AUX, VERBOSE) % Valid Commands: % 'init' make sure the controller is ready for operation. % 'set','setT' Set the temperature setpoint for automatic temperature % control. Use VALUE = 'query' or '?' to query. Can specify % temperature units (AUX == 'C' or 'K'), default to 'C'. % 'sensor' Specify which sensor channel (CHANNEL == 'A' or 'B') should % be used for controller input. % 'manual' Set the controller to manual mode and set the output to % VALUE percent. + = heating, - = cooling. % Note that in the documentation, "manual" means "normal PID % control", while "fixed" means "manual control of heater". % Also 'fixed'. % 'read' Read the current temperature from the feedback sensor. % Also 'getdata'. % 'on','go' Set the controller for automatic mode (control temperature). % 'off','stop' Stop controlling temperature (manual mode) and set output % power to zero. % 'status' Return an array with status information for the controller. % (See manual p8-5). % if (strcmpi(instrument, 'SI_9700') || strcmpi(instrument, 'all')) baudrate = 0; % buffer size for GPIB (0 for default), baud rate for serial port instruments io = port(GPIB, instrument, baudrate, verbose); if (io ~=0) && (strcmp(get(io,'Status'),'open') ~=0) lowlim = -100; % lower limit of input in C highlim = 300; % upper limit of temperature in C switch command case 'init' kpib(instrument,GPIB,'stop',value,channel,aux,verbose); retval=kpib(instrument,GPIB,'status',value,channel,aux,2); case {'set','setT'} % did the user specify temperature units? if strcmpi(aux,'K') if verbose >= 2, fprintf('kpib/%s: Temperature units of degrees %s\n',instrument, aux); end valueC = value - 273; % save value in C else aux = 'C'; % default to degrees celcius if verbose >= 3, fprintf('kpib/%s: Temperature units of degrees %s (default)\n',instrument, aux); end valueC = value; value = value + 273; % convert to K end if isnumeric(value) % check input range (deg C) if valueC < lowlim valueC = lowlim; if verbose >= 1, fprintf('kpib/%s: Warning: Temperature setpoint below lower limit (%d K)\n',instrument,lowlim); end end if valueC > highlim valueC = highlim; if verbose >= 1, fprintf('kpib/%s: Warning: Temperature setpoint above upper limit (%d K)\n',instrument,highlim); end end % set the temperature setpoint (K) command = sprintf('SET %.2f',value); fprintf(io,command); % set setpoint for current channel if verbose >= 2, fprintf('kpib/%s: Temperature setpoint set to %.3f C (%.3f K)\n',instrument,valueC,value); end elseif strcmpi(value,'query') || strcmpi(value,'?') fprintf(io,'SET?'); % query temperature setpoint retval = fscanf(io, 'SET %f',1); %retval = sscanf(stringin,'%f') % did the user specify temperature units? if strcmpi(aux,'K') if verbose >= 2, fprintf('kpib/%s: Temperature units of degrees %s\n',instrument,aux); end else aux = 'C'; if verbose >= 3, fprintf('kpib/%s: Temperature units of degrees %s\n',instrument,aux); end retval = retval - 273; % convert to C end if verbose >= 2, fprintf(1,'kpib/%s: Setpoint: %.2f %s\n',instrument,retval,aux); end else if verbose >= 1, fprintf(1,'kpib/%s: "%s" command error\n',instrument,command); end end % set case {'manual','fixed'} if isnumeric(channel) % which channel for sensing? if channel == 1, channelname = 'A'; elseif channel == 2, channelname = 'B'; else channel = 1; channelname = 'A'; % default to channel 1 end elseif strcmpi(channel,'A') channel = 1; channelname = 'A'; elseif strcmpi(channel,'B') channel = 2; channelname = 'B'; else channel = 1; channelname = 'A'; % default to channel 1 end if isnumeric(value) && value <= 100 && value >= 0 fprintf(io,'MODE 5'); % fixed output (percentage) command = sprintf('FIXD %d,%f',channel,value); fprintf(io,command); if verbose >= 2, fprintf('kpib/%s: Fixed heater output at %f %% :',instrument,value,channelname); end else if verbose >= 1, fprintf(1,'kpib/%s: "%s" command error, check VALUE\n',instrument,command); end end case {'sensor','channel'} if isnumeric(channel) % which channel? if channel == 1, channelname = 'A'; elseif channel == 2, channelname = 'B'; else channel = 1; channelname = 'A'; % default to channel 1 end elseif strcmpi(channel,'A') channel = 1; channelname = 'A'; elseif strcmpi(channel,'B') channel = 2; channelname = 'B'; else channel = 1; channelname = 'A'; % default to channel 1 end if strcmpi(value,'query') || strcmpi(value,'?') fprintf(io,'CSEN?'); sensechan = fscanf(io,'CSEN %d',1); if verbose >= 2 fprintf(1, 'kpib:/%s: Sensor using ',instrument); if sensechan == 1, fprintf(1, 'Channel A (1)\n'); elseif sensechan == 2, fprintf(1, 'Channel B (2)\n'); else fprintf(1, 'Channel XX (error)\n'); end end elseif strcmpi(value,'A') fprintf(io,'CSEN 1'); if verbose >= 2, fprintf('kpib/%s: Using sensor Channel A\n',instrument); end elseif strcmpi(value,'B') fprintf(io,'CSEN 2'); if verbose >= 2, fprintf('kpib/%s: Using sensor Channel B\n',instrument); end else command = sprintf('CSEN %d',channel); fprintf(io,command); if verbose >= 2, fprintf('kpib/%s: Using sensor Channel %s\n',instrument,channelname); end end case {'read','getdata'} if isnumeric(channel) % which channel? if channel == 1, channelname = 'A'; elseif channel == 2, channelname = 'B'; else channel = 1; channelname = 'A'; % default to channel 1 end elseif strcmpi(channel,'A') channel = 1; channelname = 'A'; elseif strcmpi(channel,'B') channel = 2; channelname = 'B'; else channel = 1; channelname = 'A'; % default to channel 1 end if verbose >= 2, fprintf('kpib/%s: Channel %s temperature:',instrument,channelname); end command = sprintf('T%s?',channelname); fprintf(io,command); % query temperature if channel == 1, retval = fscanf(io, 'TA %f',1); end if channel == 2, retval = fscanf(io, 'TB %f',1); end % did the user specify temperature units? if strcmpi(aux,'K') if verbose >= 3, fprintf('(%s: Temperature units of degrees %s) ',instrument,aux); end else aux = 'C'; if verbose >= 3, fprintf('(%s: Temperature units of degrees %s) ',instrument,aux); end retval = retval - 273; % convert to C end if verbose >= 2, fprintf(1,' %.3f %s\n',retval,aux); end case {'stop','off','STOP','OFF'} fprintf(io,'MODE 1'); % stop controlling if verbose >= 2, fprintf('(kpib:/%s: Controller STOP\n',instrument); end case {'go','on'} fprintf(io,'MODE 2'); % start controlling fprintf(io,'SET?'); % query temperature setpoint for current channel retval = fscanf(io, 'SET %f',1); fprintf(io,'CSEN?'); % which channel? sensechan = fscanf(io,'CSEN %d',1); if verbose >= 2 fprintf(1, 'kpib:/%s: Controller ON (Setpoint %.1f C, ',instrument,retval); if sensechan == 1, fprintf(1, 'Channel A)\n'); elseif sensechan == 2, fprintf(1, 'Channel B)\n'); else fprintf(1, 'Channel XX)\n'); end end case {'status'} fprintf(io,'STA?'); retvalstring = fscanf(io, '%s'); if verbose >= 3, disp(retvalstring); end retval=sscanf(retvalstring,'STA%f,%f,%d,%d,%d,%d,%d'); if verbose >= 2, fprintf('kpib/%s:\n', instrument); fprintf(' Setpoint: %f K\n',retval(1)); fprintf(' Heater Output: %f %%\n',retval(2)); fprintf(' Operating Mode: %d, ',retval(3)); switch retval(3) case 1 fprintf('Stop\n'); case 2 fprintf('Manual (Normal Control)\n'); case 3 fprintf('Program\n'); case 4 fprintf('AutoTune\n'); case 5 fprintf('Fixed Output\n'); end if retval(4)==0, fprintf(' WARNING: Heater Alarm\n'); elseif retval(4)==1, fprintf(' No Heater Alarm\n'); else fprintf(' WARNING: Heater Status: %d',retval(4)); end if retval(5)==0, fprintf(' GUI Refresh required\n'); elseif retval(5)==1, fprintf(' GUI Refresh not required\n'); else fprintf(' WARNING: GUI Status: %d\n',retval(5)); end if retval(6)==0, fprintf(' Normal PID control\n'); elseif retval(6)==1, fprintf(' Zone PID control\n'); else fprintf(' WARNING: PID Type: %d\n',retval(6)); end fprintf(' PID Zone: %d\n',retval(7)); end fprintf(io,'CSEN?'); sensechan = fscanf(io,'CSEN %d',1); if sensechan == 1, fprintf(1, ' Sense Channel A\n'); elseif sensechan == 2, fprintf(1, ' Sense Channel B\n'); else fprintf(1, ' Sense Channel XX\n'); end fprintf(1,'\n'); otherwise if verbose >= 1, fprintf(1,'kpib/%s: Error, command not supported. ["%s"]\n',instrument,command); end end else % catch incorrect address errors if verbose >= 1, fprintf(1,'kpib/%s: ERROR: No instrument at GPIB %s\n',instrument,num2str(GPIB)); end retval=0; end validInst = 1; end %%%%% end SI_9700 % %%%%%
'FLK_290' Fluke 290 Series Waveform generator
The Fluke 294 arbitrary waveform generator has 4 output channels. This version (kpib v4.8) does not include support for arbitrary waveforms.
Note that the Fluke GPIB interface is a little sketchy, and appears to require that EOSMode is set to 'read&write', with EOSChar of 'LF'. This is handled in the PORT function.
%RETVAL = KPIB('INSTRUMENT', GPIB, 'COMMAND', VALUE, CHANNEL, AUX, VERBOSE) % Valid commands: % % 'init' Initializes instrument and makes ready for measurement ("*RST"). % % 'sine' / 'square' / 'triangle' / 'ramp' % Set the output to the specified waveform. VALUE is the % frequency in Hz, CHANNEL is the output CHANNEL, and AUX is % the offset in volts. % % 'phase' Set the output phase on CHANNEL to VALUE degrees. % 'offset' Set the DC offset to VALUE volts on CHANNEL. % 'amplitude' % Set the output amplitude on CHANNEL to VALUE in units of AUX, % which can be ['Vpp' | 'Vrms' | 'dBm'] (default Vpp). % 'on' Enables output on CHANNEL % 'off' Disables output on CHANNEL % if any(strcmpi(instrument, {'FLK_290','FLK_291','FLK_292','FLK_294'})) || strcmpi(instrument, 'all') baudrate = 0; % buffer size for GPIB (0 for default), baud rate for serial port instruments io = port(GPIB, instrument, baudrate, verbose); if (io ~=0) && (strcmp(get(io,'Status'),'open') ~=0) % This a multi-channel instrument, so CHANNEL should be specified. % If not, the command applies to the last-selected channel, or % channel 1 after power-up/reset/init. % check CHANNEL if any(channel == [1 2 3 4]) fprintf(io, 'SETUPCH %d',channel); else if verbose >= 1, fprintf(1,'kpib/%s: WARNING: no channel selected (''%s'')\n',instrument,command); end end switch command case 'init' fprintf(io,'*RST'); % reset the instrument case {'sin','sine','SIN'} fprintf(io,'WAVE SINE'); if verbose >= 2, fprintf(1, 'kpib/%s: Channel %d Sine wave; ',instrument,channel); end if isnumeric(value) && value > 0 fprintf(io,'WAVFREQ %f',value); if verbose >= 2, fprintf(1, 'Freq: %g Hz; ',value); end end if isnumeric(aux) && aux > 0 fprintf(io,'DCOFFS %f',aux); if verbose >= 2, fprintf(1, 'Offset: %g V',aux); end end if verbose >= 2, fprintf(1, '\n'); end case {'square','SQU'} fprintf(io,'WAVE SQUARE'); if verbose >= 2, fprintf(1, 'kpib/%s: Channel %d Sine wave; ',instrument,channel); end if isnumeric(value) && value > 0 fprintf(io,'WAVFREQ %f',value); if verbose >= 2, fprintf(1, 'Freq: %g Hz; ',value); end end if isnumeric(aux) && aux > 0 fprintf(io,'DCOFFS %f',aux); if verbose >= 2, fprintf(1, 'Offset: %g V',aux); end end if verbose >= 2, fprintf(1, '\n'); end case {'triangle','TRI'} fprintf(io,'WAVE TRIANG'); if verbose >= 2, fprintf(1, 'kpib/%s: Channel %d Triangle wave; ',instrument,channel); end if isnumeric(value) && value > 0 fprintf(io,'WAVFREQ %f',value); if verbose >= 2, fprintf(1, 'Freq: %g Hz; ',value); end end if isnumeric(aux) && aux > 0 fprintf(io,'DCOFFS %f',aux); if verbose >= 2, fprintf(1, 'Offset: %g V',aux); end end if verbose >= 2, fprintf(1, '\n'); end case {'ramp','RAMP','saw'} fprintf(io,'WAVE POSRMP'); if verbose >= 2, fprintf(1, 'kpib/%s: Channel %d Ramp (positive) wave; ',instrument,channel); end if isnumeric(value) && value > 0 fprintf(io,'WAVFREQ %f',value); if verbose >= 2, fprintf(1, 'Freq: %g Hz; ',value); end end if isnumeric(aux) && aux > 0 fprintf(io,'DCOFFS %f',aux); if verbose >= 2, fprintf(1, 'Offset: %g V',aux); end end if verbose >= 2, fprintf(1, '\n'); end case {'amplitude', 'ampl', 'amp'} if ~any(strcmpi(aux,{'Vpp','Vrms','dBm'})) aux='Vpp'; end fprintf(io,'AMPUNIT %s',upper(aux)); fprintf(io,'AMPL %f',value); if verbose >= 2, fprintf(1, 'kpib/%s: Channel %d Amplitude: %g %s\n',instrument,channel,value,aux); end case {'offset','offs'} if isnumeric(value) fprintf(io,'DCOFFS %f',value); if verbose >= 2, fprintf(1, 'kpib/%s: Channel %d DC offset: %g V\n',instrument,channel,value); end else if verbose >= 0, fprintf(1, 'kpib/%s: Error: Offset incorrectly specified (must be a number)\n',instrument); end end case {'phase','phse'} if isnumeric(value) fprintf(io,'PHASE %f',value); if verbose >= 2, fprintf(1, 'kpib/%s: Channel %d Phase: %d deg\n',instrument,channel,value); end else if verbose >= 0, fprintf(1, 'kpib/%s: Error: Phase incorrectly specified (must be a number)\n',instrument); end end case {'freq','frequency'} if isnumeric(value) fprintf(io,'WAVFREQ %f',value); if verbose >= 2, fprintf(1, 'kpib/%s: Channel %d Frequency: %g Hz\n',instrument,channel,value); end else if verbose >= 0, fprintf(1, 'kpib/%s: Error: Frequency incorrectly specified (must be a number)\n',instrument); end end case {'lock','lockmode','sync'} switch value case {'master'} fprintf(io, 'LOCKMODE MASTER'); if verbose >= 2, fprintf(1, 'kpib/%s: Channel %d is Master\n',instrument,channel); end case {'independent','indep'} fprintf(io, 'LOCKMODE INDEP'); if verbose >= 2, fprintf(1, 'kpib/%s: Channel %d is Independent\n',instrument,channel); end case {'slave'} fprintf(io, 'LOCKMODE SLAVE'); if verbose >= 2, fprintf(1, 'kpib/%s: Channel %d is Slave\n',instrument,channel); end case {'ftrack','freqtrack'} fprintf(io, 'LOCKMODE FTRACK'); if verbose >= 2, fprintf(1, 'kpib/%s: Channel %d is Master w/ Frequency Tracking\n',instrument,channel); end case {'on','ON'} fprintf(io, 'LOCKSTAT ON'); if verbose >= 2, fprintf(1, 'kpib/%s: Inter-channel synchronization ON\n',instrument); end case {'off','OFF'} fprintf(io, 'LOCKSTAT OFF'); if verbose >= 2, fprintf(1, 'kpib/%s: Inter-channel synchronization OFF\n',instrument); end end case {'channel','CH'} % set channel using VALUE if any(value == [1 2 3 4]) fprintf(io, 'SETUPCH %d',value); if verbose >= 2, fprintf(1,'kpib/%s: Channel %d selected\n',instrument,value'); end elseif any(channel == [1 2 3 4]) if verbose >= 2, fprintf(1, 'kpib/%s: Channel %d selected (CHANNEL). \n',instrument,channel); end else if verbose >= 1, fprintf(1, 'kpib/%s: WARNING: Channel selection (VALUE) must be 1-4\n',instrument); end end case {'off','OFF','stop','STOP'} fprintf(io, 'OUTPUT OFF'); % Disables output on selected channel. if verbose >= 2, fprintf(1, 'kpib/%s: Channel %d output off.\n',instrument,channel); end case {'on','ON','go','GO'} fprintf(io, 'OUTPUT ON'); % Enables output on selected channel. if verbose >= 2, fprintf(1, 'kpib/%s: Channel %d output on.\n',instrument,channel); end otherwise if verbose >= 1, fprintf(1,'kpib/%s: Error, command not supported. ["%s"]\n',instrument,command); end end else % catch incorrect address errors if verbose >= 1, fprintf(1,'kpib/%s: ERROR: No instrument at GPIB %s\n',instrument,num2str(GPIB)); end retval=0; end validInst = 1; end % %%%%% end <FLK_294> % %% %% %% %% %% %% %% %% %% %% %% %% %% %% %% %% %% %%
End of instrument drivers
% add new instruments above this line %% %% %% %% %% %% %% %% %% %% %% %% %% %% %% %% %% %%
% % Trap invalid instrument calls. If the drivers above did not recognize % % the instrument then we issue an error. if validInst == 0; if verbose >= 1 fprintf(1, 'kpib: ERROR, invalid instrument ["%s/%s"].\n',instrument,num2str(GPIB)); end retval=0; end return
function port
function io = port(addressGPIB, instrument, value, verbose)
% IO = PORT(ADRESSGPIB, INSTRUMENT, VALUE, VERBOSE) % PORT opens a GPIB or a serial port connection for a device. If % addressGPIB is a number, the connection is GPIB. If addressGPIB is a % string (e.g. 'COM1'), the connection is through a serial port. The % INSTRUMENT parameter allows port to adjust settings specific to each % instrument (mostly buffer size). VALUE is the buffer size for GPIB or % the baudrate for serial connections. VERBOSE level of 3 provides some % debugging details about the connection. % % PORT is hardwired to use a single National Instruments GPIB card. % If you are using different GPIB hardware, comment in/out the appropriate % section below. % % based on PORT by AP JUL2004 % ioTimout = 4; % Seconds that we wait for an instrument to reply before giving up ioInBuffsize = 1000; % Minimum buffer size for GPIB inputs serialTerminator = 'LF'; % default value for serial port % verbose defaults to on if nargin < 4 verbose = 2; end % input buffer default (set value above) if nargin < 3 value = ioInBuffsize; end % certain instruments require special settings % if the user has specified a larger buffer size, use it, but not smaller if isequal(instrument,'HP_89410A') %Test to see whether or not to implement special case. ioTimout = 30; end if isequal(instrument,'HP_34420A') %Test to see whether or not to implement special case. ioTimout = 10; %100 % May need to increase timeout for automatic data collection. end if isequal(instrument,'OH_EXP') serialTerminator = 'CR/LF'; % The Ohaus Explorers require CR/LF terminator. end % maybe the user wants some arbitrary value if value > ioInBuffsize ioInBuffsize = value; end
port: serial port instrument
is this a GPIB instrument or a serial instrument?
% if GPIB is not a number, then it must be a serial port if ~isnumeric(addressGPIB)
% check to see if the port exists already if isempty(instrfind('Type','serial','Port',addressGPIB)) io = serial(addressGPIB,'BaudRate',value); %io.InputBufferSize = ioInBuffsize; io.Timeout = ioTimout; io.Terminator = serialTerminator; fopen(io); stopasync(io); if verbose >= 3 fprintf(1,'kpib/port: Opening port %s',addressGPIB); b=get(io,'BaudRate'); p=get(io,'Parity'); s=get(io,'StopBit'); t=get(io,'Terminator'); fprintf(1,' with %d baud, Parity %s, %d stopbits, Terminator: %s \n',b,p,s,t); end else io = instrfind('Type','serial','Port',addressGPIB); if ~isequal(io.Status,'open') fopen(io); if verbose >= 3, fprintf('kpib/port: Existing serial port is closed; open it (%s)\n',num2str(addressGPIB)); end end if verbose >= 3 fprintf(1,'kpib/port: Port %s is already open',addressGPIB); b=get(io,'BaudRate'); p=get(io,'Parity'); s=get(io,'StopBit'); t=get(io,'Terminator'); fprintf(1,' with %d baud, Parity %s, %d stopbits, Terminator: %s \n',b,p,s,t); end end
port: GPIB instrument
% else if GPIB is a number, its a GPIB address
else
% % Choose between "regular" (PCI or similar) and USB (virtual serial port) % % GPIB interface hardware by commenting in/out the appropriate section below % % Uncomment for regular GPIB interface card (e.g. PCI)
port: GPIB PCI
if isempty(instrfind('Type','gpib','PrimaryAddress',addressGPIB)) try % CHANGE FOLLOWING LINE TO USE DIFFERENT GPIB CARD MANUFACTURER GPIBMAN % See MATLAB documentation for list of supported manufacturers % http://www.mathworks.com/products/instrument/supportedio13769.html % (If using USB with a COM port, then comment out this section and see below) gpib_interface_manufacturer = 'ni'; % 'ni' National Instruments % 'ics' ICS Electronics io = gpib(gpib_interface_manufacturer,0,addressGPIB); io.InputBufferSize = ioInBuffsize; io.Timeout=ioTimout; fopen(io); if verbose >= 3, fprintf('kpib/port: Create new GPIB port (%d).\n',addressGPIB); end catch gpibEX if verbose >= 1 fprintf('kpib/port: ERROR: cannot open GPIB address %d on interface %s\n',addressGPIB,gpib_interface_manufacturer); fprintf(' Use ''scan'' to see a list of available instruments.\n'); fprintf(' ("%s")\n',gpibEX.message); end io = 0; end else io = instrfind('Type','gpib','PrimaryAddress',addressGPIB); if verbose >= 3, fprintf('kpib/port: Use existing GPIB port (%d).\n',addressGPIB); end if ~isequal(io.Status,'open') fopen(io); if verbose >= 3, fprintf('kpib/port: Existing port is closed; open it (%d).\n',addressGPIB); end end end
port: Special GPIB settings
Some instruments require particular or unusual GPIB settings The End of Statement (EOS) setting is default none. Several instruments seem to operate more smmothly with a setting of 'read&write'. Documentation is scarce, results are down to experimentation.
In particular, the KTH_236 often hangs, and it has a default EOS char of CRLF, as opposed to the MATLAB default of LF. The KTH_236 'init' command changes the instrument to LF. Hard to say. (MH, v3.2,4.8) Subsequent testing with a KTH_238 indicates that the previous setting was not correct- the default setting for the output terminator is CR/LF, so a matlab setting of LF (the default) works fine.
if io ~= 0 if any(strcmp(instrument,{'FLK_294' 'HP_8753ES'})) set(io,'EOSMode','read&write'); % this setting may cause problems with USB adapters such as ICS % See % http://www.mathworks.com/support/solutions/en/data/1-1AY1U/index.html?product=IC&solution=1-1AY1U %set(io,'EOSCharCode','CR'); % 'LF' is default end if any(strcmp(instrument,{'WAT_981','ACT_981','ACT_TEMP','WAT_981'})) io.EOSCharCode = 13; % CR io.EOSmode='read&write'; end if verbose >= 3 EOImode=get(io,'EOIMode'); EOScc=get(io,'EOSCharCode'); EOSmode=get(io,'EOSMode'); TmOut=get(io,'Timeout'); BufSz=get(io,'InputBufferSize'); fprintf('kpib/port: EOIMode: %s; EOSMode: %s; EOSCharCode: %s; Timeout: %d sec; Buffer Size: %d bytes\n',EOImode,EOSmode,num2str(EOScc),TmOut,BufSz); end end % % End Regular GPIB interface card
port: GPIB serial
% % % Begin Enable Prologix USB/GPIB controller or similar interface % % that uses a COM port % % % The Prologix may not interface smoothly with some equipment, see the Prologix documentation for details. % % USBPro_SPECIAL is the list of instruments that require special treatment % % from the Prologix USB-Serial controller. Not all of the instruments supported by kpib have been tested with the Prologix, % % so you may have to add instruments to this list... % USBPro_SPECIAL={'KTH_2400'}; % % % uncomment this section only if using Prologix USB-GPIB (or similiar) % % get the COM port (COMx) from the USB driver installation process and % % specify it below % % % Which virtual COM port for the USB? What baudrate? (9600 is standard) % USB_COM = 'COM9'; baud = 9600; % % % if ~isempty(instrfind('Type','serial','Port',USB_COM)) % kpib('clear',0,0,0,0,0,1); % % NOTE: Re-using an open port does not seem to work for % % Prologix, so if a port exists, destroy it and make a % % new one % end % % create the port object % io = serial(USB_COM,'Baudrate',baud); % % % set the parameters for the serial port % % if any(strcmpi(instrument, USBPro_SPECIAL)) % % io.Terminator = 'CR'; % required for KTH_2400 % % else % io.Terminator = 'CR/LF'; % standard Prologix USB GPIB % % end % io.InputBufferSize = ioInBuffsize; % io.Timeout = ioTimout; % fopen(io); % if verbose >= 3 % %disp (io); % fprintf('kpib/port: Create new object for USB serial (%s/%s)\n',USB_COM,num2str(addressGPIB)); % end % % % % Configure Prologix Controller (v4.2+) % % configure as controller (++mode 1) % fprintf(io, '++mode 1'); %pause(1); % % read-after-write mode enabled, except for KTH_2400 % if any(strcmpi(instrument, USBPro_SPECIAL)) % fprintf(io, '++auto 0'); % else % fprintf(io, '++auto 1'); % end % % set instrument address % fprintf(io, ['++addr ' num2str(addressGPIB)]); % % % if verbose >= 3, % % Send Prologix Controller query version command % fprintf(io, '++ver'); %pause(1); % % Read and display response % ver = fgetl(io); % % if any(strcmpi(instrument, USBPro_SPECIAL)), t=fgetl(io); end % clear the orphan LF % fprintf('kpib/port: %s\n',ver); % fprintf(io, '++addr'); % addr = fgetl(io); % %if any(strcmpi(instrument, USBPro_SPECIAL)), t=fgetl(io); end % clear the orphan LF % fprintf('kpib/port: Prologix Serial USB Controller configured for GPIB %s\n',addr); % end % % % % End Prologix
end % open GPIB port return
function truncx
function retval = truncx(raw)
% RETVAL = TRUNCX(RAW) % This function is used to truncated the x data sent by the HP89410A. % The truncations below are hardcoded from the manual to match the y data % output. This function will take the x data in a column and will % truncate only the first column. % % JTL JUL2004 m = size(raw,1); %disp('truncX 89410') switch m case {64,65} for i = 8:58 retval(i-7,1) = raw(i); %#ok<AGROW> end case {128,129} for i = 15:115 retval(i-14,1) = raw(i); %#ok<AGROW> end case {256,257} for i = 29:229 retval(i-28,1) = raw(i); %#ok<AGROW> end case {512,513} for i = 57:457 retval(i-56,1) = raw(i); %#ok<AGROW> end case {1024,1025} for i = 113:913 retval(i-112,1) = raw(i); %#ok<AGROW> end case {2048,2049} for i = 225:1825 retval(i-224,1) = raw(i); %#ok<AGROW> end case {4096,4097} for i = 449:3649 retval(i-448,1) = raw(i); %#ok<AGROW> end otherwise fprintf(1,'kpib/truncX: data size error. m = %g\n',m); assignin('base','raw',raw); retval=raw; end % %% %% % % % SERIAL COMMUNICATION FUNCTIONS % % % These functions handle serial communications-related crap.
function makeBytes
function retval = makeBytes(value)
% turns a decimal VALUE into a two-byte (decimal) array suitable for serial % transmission by fwrite % uses twos-complement for negative values % returns an array of numbers ordered for transmission: % retval(1) = high byte % retval(2) = low byte % % MH AUG2006 % N = 16; % number of bits if value < 0 ndnum=bitcmp(abs(value),N); value=ndnum+1; end sp=dec2hex(value); if length(sp) > 2 sp1=sp(1:length(sp)-2); sp2=sp(length(sp)-1:length(sp)); else sp1=0; sp2=sp; end retval=[hex2dec(sp1) hex2dec(sp2)]; return
function makeDecimal
function retval = makeDecimal(value)
% turns a two-number decimal representation of a two-byte binary register % value into a single decimal value % (i.e., make byte hex value into decimal value) % VALUE is an array of decimal numbers (as typically returned from serial % port communications) % assumes twos-complement notation for negative numbers % can handle arbitrary size registers % % MH AUG2006 % N = 8; % how many bits per decimal value? (i.e., 1 byte registers) % VALUE is two numbers that represent the high and low bytes of a % 16-bit register. We need to combine them into a single binary number, % check for negative (twos complement) and then convert to a single % decimal number. cmd=[]; sp=dec2bin(value,N); numreg=size(sp); for i=1:numreg(1) cmd=[cmd sprintf('sp(%d,1:N) ',i)]; %#ok<AGROW> end %retval=hex2dec([sp(:,1:2)]); bnum=eval(['[' cmd ']']); dnum=bin2dec(bnum); % now we have a 16-bit binary number as a string % % check for negative if bitget(dnum,N*numreg(1))==1 ndnum=bitcmp(dnum,N*numreg(1)); dnum=-1*(ndnum+1); end retval=dnum; return
function makeCRC
function retval = makeCRC(message)
%RETVAL = MAKECRC(MESSAGE) % Create a 16-bit CRC to append to a message for serial transmission. % To create the CRC bytes, divide the message string by the CRC polynomial, % 0xA001 (1010000000000001). This can be done by bit shifting left. % % MESSAGE can be an array of decimal or hex values. They must be listed % in the order of transmission. RETVAL is returned as an array of two % decimal values, in order of transmission. % % This is a little strange in MATLAB because we will work in decimal. Is % there a better way to do this? % % A byte-wise 16-bit CRC: process the bits in the order that they will be % transmitted. When we are done, reverse the byte order of our answer for % transmission. % % MH JUL2006 % v1.0 % % is the message decimal or hex? % (regardless it must be in order of transmission, left first) if ~isnumeric(message) md=hex2dec(message); else md=message; end % the CRC polynomial to divide our message by %p='1010000000000001'; %pd=hex2dec('A001'); % hint: 40961 pd=40961; % loop through the message, shifting through each byte bit by bit % proceed in the order of byte transmission % initialize the result xf='FFFF'; xfd=hex2dec(xf); % loop over the bytes for i=1:length(md) % process message in byte chunks xfd=bitxor(md(i),xfd); % XOR new byte with result for j=1:8 % process bitwise if bitand(xfd,1) % if the LSB is 1 xfd=bitshift(xfd,-1); xfd=bitxor(xfd,pd); else xfd=bitshift(xfd,-1); end end end % we need to reverse the byte order of xfd for transmission xfdb=dec2bin(xfd,16); %xfdb(17:24)=xfdb(1:8); xfdb(1:8)=[]; retval(1)=bin2dec(xfdb(9:16)); retval(2)=bin2dec(xfdb(1:8)); return
function watwrite
function response=watwrite(io,packet,verbose)
% WATWRITE handles the writing to a register and reading the response % (interpreting any errors) using serial port. This is dedsigned for the % Watlow controller on the AO_800, but could be used for any Watlow % device that uses MODBUS registers. % % returns 0 for success % % MH AUG2006 % % send the packet to the controller and read the response % try fwrite(io,packet); confirm = fread(io,8); % confirm or deny? Handle errors if confirm(2)==134 && verbose >= 1 % command (0x06) is echoed with high bit is set to indicate error switch confirm(3) % see Watlow data communications manual p16 for error codes case 1 fprintf(1, 'kpib/AO_800: ERROR: "illegal command" (%d)\n',confirm(3)); case 2 fprintf(1, 'kpib/AO_800: ERROR: "illegal data address" (%d)\n',confirm(3)); case 3 fprintf(1, 'kpib/AO_800: ERROR: "illegal data value" (%d)\n',confirm(3)); otherwise fprintf(1, 'kpib/AO_800: ERROR: Unknown error (%d)\n',confirm(3)); end fprintf(1,' Sent: '); fprintf(1, ' %d',packet); fprintf(1,'\n'); fprintf(1,' Received: '); fprintf(1, ' %d',confirm); fprintf(1,'\n'); response = confirm(3); elseif confirm(5:6)' ~= packet(5:6) if verbose >= 1 fprintf(1, 'kpib/AO_800: WARNING: Controller did not confirm write. Returned:\n '); fprintf(1, ' %d', confirm); fprintf(1, '\n'); response = confirm(3); end else if verbose >= 3, fprintf(1, 'kpib/AO_800: Controller confirms register write\n'); end response = 0; end % catch % if at first you don't succeed % if verbose >= 1, fprintf(1,'kpib/AO_800: WARNING: write error (watwrite). Retrying...\n'); end % pause(2); % response=watwrite(io,packet,verbose); % end return
function BitToFloat
function retval = BitToFloat(numb) % This function converts a bit representation of a double precision % floating point number into a number. For more info, see % http://en.wikipedia.org/wiki/IEEE_floating-point_standard#Double-precision_64_bit % RH AUG2006 signBit=bitget(numb(1),8); expBit=[bitget(numb(1),7:-1:1) bitget(numb(2),8:-1:5)]; mantissaBit= [bitget(numb(2),4:-1:1) bitget(numb(3),8:-1:1) bitget(numb(4),8:-1:1) bitget(numb(5),8:-1:1) bitget(numb(6),8:-1:1) bitget(numb(7),8:-1:1) bitget(numb(8),8:-1:1)]; if(signBit==1) sign=-1; else sign=1; end %find the exponent exp=double(0); for eind = 0:1:length(expBit)-1 exp= exp + (2^eind)*double(expBit(length(expBit)-eind)); end e=exp-1023; %find the coefficent man=double(0); for mind = 1:1:length(mantissaBit) man= man + 2^(-1*mind)*double(mantissaBit(mind)); end retval = sign*(1+man)*2^e; return; %#ok<*ST2NM> %#ok<*ALIGN> % %% %% %% %% % % % END KPIB