tclvisais a standard Tcl extension providing a binding
to Virtual Instrument Software Architecture (VISA ) API. It allows to
use VISA functionality from regular Tcl scripts via set of commands.
Most of the commands have similar names and are intuitive to use for the
one who knows VISA API. For example, Tcl command visa::open is a front-end for
viOpen VISA function. The specifications of VISA can be
found here:
http://www.ivifoundation.org/specifications/default.aspx.
As an extention tclvisafollows conventions of Tcl
Extension Architecture (TEA). It is loaded dynamically into Tcl shell or
Tcl-based application on demand. Please refer to TEA documentations for
details:
Prior to usage of tclvisaone need VISA implementation
installed. There are several known implementations (e.g. National
Instruments VISA, or Agilent IO Library Suite). VISA libraries should be
installed in proper directories and be available for linking.
tclvisaitself should be installed as a typical Tcl
extension. Partcular details of installation, such as target directory,
are platform-dependent. Please refer to the documentation of your Tcl
version.
If you have no access to system directories to install
tclvisainto, you can install into arbitrary directory. In
order to make Tcl known about this directory, you should add path to it
to TCLLIBPATH environment variable.
Binary instalation package for Microsoft Windows can be downloaded
from tclvisasite. This package contains DLL with compiled
library code, documentation and demo scripts. All downloads can be found
here:
http://sourceforge.net/projects/tclvisa/files/.
In order to start using tclvisawithin Tcl one should
issue following command:
package require tclvisaIf the library is properly installed, this command returns version of
tclvisaloaded. Library is ready to use. All commands and
predefined variables are placed in visa:: namespace.
tclvisaVISA defines a lot of predefined contants with codes of attributes,
errors etc. Most of these constants are available in Tcl within
visa namespace and without VI_ prefix.
For example, VI_EXCLUSIVE_LOCK constant is represented
by visa::EXCLUSIVE_LOCK variable in Tcl. When using these
predefined variables in expressions, do not forget adding $
prefix prior to variable name.
Following example demonstrates usage of predefined constant:
# open instrument exclusively
set vi [visa::open $rm "ASRL2::INSTR" $visa::EXCLUSIVE_LOCK]Most of VISA functions operate with sessions which are
represented in C language by viSession type. In Tcl these
sessions are stored in standard channels. E.g. visa::open returns name of Tcl channel
to be used in subsequent operations. This approach has following
benefits:
Standard IO procedures are used in VISA IO: puts,
gets etc.
VISA sessions may be transparently passed to any procedure which accepts Tcl channel. If some third-party library works with regular Tcl channels, it therefore can read/write from/to VISA device.
Tcl automatically closes all opened channels when interpeter terminates.
tclvisaprovides a procedure to open VISA sessions: visa::open, which is a front-end of
viOpen VISA function. But tclvisadoes not
provide front-ends for viClose or viWrite VISA
functions. Instead one should use standard Tcl commands, such as
close or puts. Tcl detects type of the channel
and calls proper VISA function internally. For example, when
close is issued on VISA channel, opened by visa::open, then viClose
function is actually called within Tcl internals.
Following example demonstrates usage of VISA channel:
# open instrument
set vi [visa::open $rm "ASRL2::INSTR"]
# send "reset" command to instrument
puts $vi "*RST"
# close VISA session
close $viSee also table of correspondence between supported VISA functions and Tcl commands.
VISA IO functions, such as viWrite or
viRead, by default work with messages, where
message is a sequence of bytes of arbitrary length followed by special
“end-of-message” character. For example, SCPI messages
end with “new line” character (ASCII code is 0Ah). When I
send a message terminated by “end-of-message” via viWrite,
I can be sure that it is actually sent to the device rather than kept in
intermediate buffer. When I call viRead, it returns
immediately after receiving of “end-of-message” character regardless of
the length of input buffer.
Tcl channels by default work with continuous streams of bytes. IO
functions typically block until IO buffer is full or “end-of-data” is
detected. For example, read command called without a buffer
length specified on file channel blocks until entire file is read. It’s
evident that this approach does not work with message-based protocols
like SCPI.
Fortunately Tcl offers different buffering options, which can be set
or red by fconfigure command. One of them is
“-buffering line” which tells Tcl finish current IO
operation when “end-of-line” character is received or sent. When
buffering type is “line”, read blocks until
“end-of-line” is received, and puts actually sends data
right after “end-of-line” is found in outcoming data. In the terms or
SCPI commands, read blocks until complete response is
received from a device.
When VISA channel is created by visa::open, buffering type is
automatically set to “line”. If one needs to switch channel
mode, then fconfigure command with proper
-buffering option should be issued.
In VISA API IO message communication timeouts can be specified or
read by viSetAttribute and viGetAttribute
functions where attribute parameter is set to
VI_ATTR_TMO_VALUE.
In tclvisatimeout can be controlled in similar way via
visa::set-attribute and visa::get-attribute commands.
But preferred and more laconic approach is to use
fconfigure Tcl command with standard -timeout
option. Look at the example below:
# open an instrument
set vi [visa::open $rm "ASRL1::INSTR"]
# read current timeout value
set tm [fconfigure $vi -timeout]
# set new timeout value
fconfigure $vi -timeout [expr 2 * $tm]In this example we read current timeout value, then set a new value that is twice the original one.
Inside the tclvisathese invocations of
fconfigure are converted to corresponding calls of
viGetAttribute and viSetAttribute VISA API
functions.
Standard Tcl channels have a -blocking option which
“determines whether I/O operations on the channel can cause the process
to block indefinitely” (quote from the fconfigure
manual).
VISA API does not support non-blocking IO natively, probably because
it offers asynchronous operations for that. In
tclvisanon-blocking IO is emulated by setting IO
timeout to zero.
I.e. when user sets a VISA channel to non-blocking mode by
fconfigure command with -blocking 0 option,
tclvisainternally sets IO timeout for this channel to zero.
When channel is reverted back to the blocking mode (that is the default
state for all VISA channels), timeout is restored to the previous
value.
See also “Suppressed Errors” section.
Tcl fileevent command cannot be called upon
VISA channel. This functionality is not implemented yet.
Support of viWriteAsync and viReadAsync
VISA API functions is not implemented too.
When a standard Tcl channel is backed by a serial port, it has a set of specific options that control baud speed, parity etc.
VISA instruments which are connected to the serial port (their
addresses start with ASRL prefix) have full set of
corresponding attributes, such as VI_ATTR_ASRL_BAUD,
VI_ATTR_ASRL_PARITY and similar. In order to configure, for
instance, baud rate one can use visa::set-attribute command
with $visa::ATTR_ASRL_BAUD passed as an attribute name. But
preferred way is to use fconfigure Tcl command and standard
options. See example:
# open an instrument
set vi [visa::open $rm "ASRL1::INSTR"]
# set baud rate, parity, word length and stop bits
fconfigure $vi -mode 9600,n,8,1From the Tcl code’s point of view channel ‘vi’ behaves
like a regular serial port. For example, this channel can be
transparently passed to third-party library that implements some
serial-based protocol.
All serial-specific options supported and corresponding
VISA attributes are listed in table below. Format of each option is
described in the fconfigure command manual.
Serial-specific channel options and VISA equivalents:
| Tcl option | VISA Attribute(s) |
|---|---|
| handshake | VI_ATTR_ASRL_FLOW_CNTRL |
| mode | VI_ATTR_ASRL_BAUD, VI_ATTR_ASRL_PARITY, VI_ATTR_ASRL_DATA_BITS, VI_ATTR_ASRL_STOP_BITS |
| queue | VI_ATTR_ASRL_AVAIL_NUM |
| ttycontrol | VI_ATTR_ASRL_DTR_STATE, VI_ATTR_ASRL_RTS_STATE, VI_ATTR_ASRL_BREAK_STATE |
| ttystatus | VI_ATTR_ASRL_CTS_STATE, VI_ATTR_ASRL_DSR_STATE, VI_ATTR_ASRL_RI_STATE, VI_ATTR_ASRL_DCD_STATE |
| xchar | VI_ATTR_ASRL_XON_CHAR, VI_ATTR_ASRL_XOFF_CHAR |
See also demo/fconfigure.tcl script that demonstrates
usage of channel options.
All VISA API functions returns viStatus value with error
code. Zero code means successfull completion, positive value means that
operation returns some warning which may be ignored in the most of
cases. Negative code means error that should be handled by
application.
In scripting language like Tcl the API developer should follow “KISS”
principle and make things as simple as possible. This is why
tclvisacommands do not explicitly return error code to the
calling script. Instead they return either actual result of operation
(say, instance of the new channel created by visa::open command) or nothing, when
operation has no any meaningful result (e.g. visa::set-attribute).
When underlying VISA API function returns error, and
tclvisacannot handle this error itself, it throws an
exception which can be handled by catch command in the
calling script. This is a standard and expected behaviour for Tcl
command. For example, standard open command throws
exception when it cannot open a file. Exception handler receives a
string with error code and description in the following format:
[CODE] Text description
where CODE is the name of the predefined VISA error
constant.
In the following example we’re trying to open an instrument that does not actually exist:
# this attempt should return VI_ERROR_RSRC_NFOUND error
if { [catch { set vi [visa::open $rm ASRL99::INSTR] } rc] } {
puts "Error: $rc"
}This code produces following output:
Error: [VI_ERROR_RSRC_NFOUND] Insufficient location information
or resource not present in the system.
Calling side then can parse the error string to retrieve VISA error code which is placed between square brackets.
Some errors returned from VISA functions are suppressed by
tclvisa, i.e. do not cause Tcl exceptions:
Timeout error (VI_ERROR_TMO) is suppressed by IO
operations on VISA channels. For example, when read attempt expires, the
read command simply returns empty string.
VI_ERROR_RSRC_NFOUND error returned by
viFindRsrc or viFindNext is suppressed by visa::find command. For example, when
search criteria do not produce any result, this command simply returns
an empty list.
VI_ERROR_INV_RSRC_NAME and
VI_ERROR_RSRC_NFOUND errors returned by
viParseRsrc are suppressed by visa::parse-rsrc
command.
One can use visa::last-error command to
determine the exact status of the last VISA operation. This command
returns all errors, including suppressed ones.
Table below contains list of VISA API functions supported by
tclvisaand corresponding commands to use in Tcl.
VISA functions and Tcl equivalents:
| VISA API function | Tcl Command |
|---|---|
| viAssertIntrSignal | visa::assert-intr-signal |
| viAssertTrigger | visa::assert-trigger |
| viAssertUtilSignal | visa::assert-util-signal |
| viClear | visa::clear |
| viClose | close |
| viFindNext, viFindRsrc | visa::find |
| viGetAttribute | visa::get-attribute |
| viGpibCommand | visa::gpib-command |
| viGpibControlATN | visa::gpib-control-atn |
| viGpibControlREN | visa::gpib-control-ren |
| viGpibPassControl | visa::gpib-pass-control |
| viGpibSendIFC | visa::gpib-send-ifc |
| viLock | visa::lock |
| viOpen | visa::open |
| viOpenDefaultRM | visa::open-default-rm |
| viParseRsrc | visa::parse-rsrc |
| viPrintf | format, puts |
| viQueryf | format, puts, gets, scan |
| viRead | read |
| viReadToFile | visa::read-to-file |
| viScanf | gets, scan |
| viSetAttribute | visa::set-attribute |
| viUnlock | visa::unlock |
| viWrite | puts |
| viWriteFromFile | visa::write-from-file |
tclvisaCommand
ReferenceAsserts the specified interrupt or signal. This command is a
front-end for viAssertIntrSignal VISA API function.
`visa::assert-intr-signal session mode ?statusID?`session - channel containing reference to a VISA
resource session opened by visa::open.
mode - This specifies how to assert the interrupt.
Valid value is one of the predefined visa::ASSERT_xxx
constants. Please refer to your VISA documentation for detailed
help.
statusID - This is the status value to be presented
during an interrupt acknowledge cycle. This argument may be omitted on
certail bus types.
None
# open instrument
set vi [visa::open $rm "ASRL1::INSTR"]
# assert signal
visa::assert-intr-signal $vi $visa::ASSERT_USE_ASSIGNEDAsserts software or hardware trigger. This command is a front-end for
viAssertTrigger VISA API function.
`visa::assert-trigger session protocol`session - channel containing reference to a VISA
resource session opened by visa::open.
protocol - Trigger protocol to use during assertion.
Valid value is one of the predefined visa::TRIG_PROT_xxx
constants. Please refer to your VISA documentation for detailed
help.
None
# open instrument
set vi [visa::open $rm "ASRL1::INSTR"]
# assert trigger
visa::assert-trigger $vi $visa::TRIG_PROT_DEFAULTAsserts or deasserts the specified utility bus signal. This command
is a front-end for viAssertUtilSignal VISA API
function.
`visa::assert-util-signal session line`session - channel containing reference to a VISA
resource session opened by visa::open.
line - Specifies the utility bus signal to assert.
Valid value is one of the predefined visa::UTIL_xxx
constants. Please refer to your VISA documentation for detailed
help.
None
# open instrument
set vi [visa::open $rm "ASRL1::INSTR"]
# assert signal
visa::assert-util-signal $vi $visa::UTIL_ASSERT_SYSRESETClears a device. This command is a front-end for viClear
VISA API function.
`visa::clear session`session - channel containing reference to a VISA
resource session opened by visa::open.None
# open instrument with default access mode and timeout
set vi [visa::open $rm "ASRL1::INSTR"]
# set device to known state
visa::clear $viQueries a VISA system to locate the resources associated with a
specified interface. This command is a front-end for
viFindRsrc and viFindNext VISA API
functions.
`visa::open RMsession expr`RMsession - channel containing reference to open
Resource Manager session opened by visa::open-default-rm.
expr - regular expression followed by an optional
logical expression. Refer to VISA API documentation for detailed
discussion.
Tcl list with addresses of all resources found. If no resources found that match the given expression, empty list is returned.
# open resource manager session
set rm [visa::open-default-rm]
# get addresses of all serial instruments
foreach addr [visa::find $rm "ASRL?*INSTR"] {
# address is in $addr variable
}Retrieves the state of an attribute. This command is a front-end for
viGetAttribute VISA API function.
`visa::get-attribute session attribute`session - channel containing reference to a VISA
resource session opened by visa::open.
attribute - Integer value with ID of the VISA
attribute to retrieve. Use one of the predefned
visa::ATTR_XXX constants.
Attribute value.
# open instrument with default access mode and timeout
set vi [visa::open $rm "ASRL1::INSTR"]
# retrieve current baud rate of a serial bus
set baud [visa::get-attribute $vi $visa::ATTR_ASRL_BAUD]Write GPIB command bytes on the bus. This command is a front-end for
viGpibCommand VISA API function.
`visa::gpib-command session buf ?count?`session - channel containing reference to a VISA
resource session opened by visa::open.
buf - String containing valid GPIB
commands.
count - Number of bytes to be written. If argument
is omitted, string length of buf is assumed.
Number of bytes actually transferred.
# send command
set cmd ... # this variable contains command
set ret [visa::gpib-command $vi $cmd 10]
puts "$ret bytes are transmitted"Specifies the state of the ATN line and the local active controller
state. This command is a front-end for viGpibControlATN
VISA API function.
`visa::gpib-control-atn session mode`session - channel containing reference to a VISA
resource session opened by visa::open.
mode - Specifies the state of the ATN line and
optionally the local active controller state. Valid value is one of the
visa::GPIB_ATN_xxx predefined constants. Please refer to
your VISA documentation for detailed help.
None
# open a GPIB interface device
set vi [visa::open ...
# set "assert" state
visa::gpib-control-atn $vi $visa::GPIB_ATN_ASSERTControls the state of the GPIB Remote Enable (REN) interface line,
and optionally the remote/local state of the device. This command is a
front-end for viGpibControlREN VISA API function.
`visa::gpib-control-ren session mode`session - channel containing reference to a VISA
resource session opened by visa::open.
mode - Specifies the state of the REN line and
optionally the device remote/local state. Valid value is one of the
visa::GPIB_REN_xxx predefined constants. Please refer to
your VISA documentation for detailed help.
None
# open a GPIB interface device
set vi [visa::open ...
# set "assert" state
visa::gpib-control-ren $vi $visa::GPIB_REN_ASSERTTell the GPIB device at the specified address to become controller in
charge (CIC). This command is a front-end for
viGpibPassControl VISA API function.
`visa::gpib-pass-control session primAddr ?secAddr?`session - channel containing reference to a VISA
resource session opened by visa::open.
primAddr - Primary address of the GPIB device to
which you want to pass control.
secAddr - Secondary address of the targeted GPIB
device. If argument is omitted, default VI_NO_SEC_ADDR
value is assumed.
None
# open a GPIB device
set vi [visa::open ...
# affect the device at primary address 1
# and without secondary address
visa::gpib-pass-control $vi 1Pulse the interface clear line (IFC) for at least 100 microseconds.
This command is a front-end for viGpibSendIFC VISA API
function.
`visa::gpib-send-ifc session`session - channel containing reference to a VISA
resource session opened by visa::open.None
# open a GPIB device
set vi [visa::open ...
# send a signal
visa::gpib-send-ifc $viReturns last error occured on the channel or Resource Manager session. This command has no VISA API equivalent.
`visa::last-error session`session - channel containing reference to an either
resource session opened by visa::open or Resource Manager session
opened by visa::open-default-rm.List of three elements:
Numeric value of the last error.
Character code of the last error that refers to a name of the
corresponding C language macro. For example,
“VI_ERROR_TMO”.
Textual description of the last error or empty value if no error.
This command is especially useful when IO operations fail, because
exact VISA error is not translated to client code by standard Tcl IO
procedures, such as puts or read. In other
words, when IO procedure (say, puts) fails on a
tclvisachannel, only way to know what exactly occured is to
call visa::last-error.
Only result of last operation is stored. All subsequent calls of
tclvisaor IO commands on a channel rewrite error
information.
The Resource Manager session holds result of last operation the
session is used in, for example visa::open or visa::find.
In the following example we’re reading from an instrument and checking whether it timed out.
# read from device
set ans [gets $vi]
if { $ans == "" } {
# Either timeout error or empty device response
set err [visa::last-error $vi]
if { [lindex $err 0] == $visa::ERROR_TMO } {
puts stderr "Error [lindex $err 1] reading from a device"
puts stderr "[lindex $err 2]"
}
}If the read operation timed out, following message will be displayed:
Error VI_ERROR_TMO reading from a device
The read/write operation was aborted because timeout expired
while operation was in progress.
Establishes an access mode to the specified resource. This command is
a front-end for viLock VISA API function.
`visa::lock session ?lockType? ?timeout? ?requestedKey?`session - channel containing reference to a VISA
resource session opened by visa::open.
lockType - integer value determining type of
locking. May be either visa::EXCLUSIVE_LOCK or
visa::SHARED_LOCK. If argument is omitted,
visa::EXCLUSIVE_LOCK is assumed.
timeout - timeout of getting lock. If argument is
omitted, infinite timeout is assumed.
requestedKey - name of the shared lock to acquire.
If exclusive locking is requested, this argument is ignored.
If an exclusive lock is requiested and acquired, procedure returns nothing.
If an shared lock is requiested and acquired, procedure returns name of the lock.
# get exclusive lock and wait forever
visa::lock $vi
# get exclusive lock and wait 5 seconds
visa::lock $vi $visa::EXCLUSIVE_LOCK 5000
# get shared lock and wait 5 seconds
set key [visa::lock $vi $visa::SHARED_LOCK 5000 "MYLOCK"]Opens a session to the specified resource. This command is a
front-end for viOpen VISA API function.
`visa::open RMsession rsrcName ?accessMode? ?openTimeout?`RMsession - channel containing reference to open
Resource Manager session opened by visa::open-default-rm.
rsrcName - name of the VISA resource to connect
to.
accessMode - integer parameter determining access
mode. May be bitwise OR combination of the following constants:
visa::EXCLUSIVE_LOCK - acquire exclusive lock to a
resource;
visa::LOAD_CONFIG - use external
configuration;
Refer to VISA documentation for more details about access mode. If parameter is omitted, default zero value is used.
openTimeout - operation timeout. If parameter is
omitted, default timeout value is used.
Tcl channel with reference to opened VISA session. This channel can
be used in standard Tcl IO procedures, like puts.
There is no a Tcl wrapper for viClose VISA API function.
In order to close a VISA session one should use standard Tcl
close command instead, which calls viClose
internally.
# open resource manager session
set rm [visa::open-default-rm]
# open instrument with default access mode and timeout
set vi1 [visa::open $rm "ASRL1::INSTR"]
# open instrument exclusively
set vi2 [visa::open $rm "ASRL2::INSTR" $visa::EXCLUSIVE_LOCK]Returns a session to the Default Resource Manager resource. This
command is a front-end for viOpenDefaultRM VISA API
function.
`visa::open-default-rm`None
Tcl channel with reference to opened resource manager session. This
channel can be used in subsequent tclvisaprocedure
calls.
There is no a Tcl wrapper for viClose VISA API function.
In order to close a VISA session one should use standard Tcl
close command instead, which calls viClose
internally.
# open resource manager session
set rm [visa::open-default-rm]
# use session reference
...
# close session
close $rmSets the state of an attribute. This command is a front-end for
viSetAttribute VISA API function.
`visa::set-attribute session attribute attrState`session - channel containing reference to a VISA
resource session opened by visa::open.
attribute - Integer value with ID of the VISA
attribute to set. Use one of the predefned visa::ATTR_XXX
constants.
attrState - Integer value with desired attribute
state.
None
# open instrument with default access mode and timeout
set vi [visa::open $rm "ASRL1::INSTR"]
# set new baud rate of a serial bus
visa::set-attribute $vi $visa::ATTR_ASRL_BAUD 19200Parse a resource string to get the interface information. This
command is a front-end for viParseRsrc VISA API
function.
`visa::parse-rsrc RMsession rsrcName`RMsession - channel containing reference to open
Resource Manager session opened by visa::open-default-rm.
rsrcName - Unique symbolic name of a
resource.
On success returns Tcl list of two integers: interface type code and interface number.
If address given is not valid or device does not exists, returns empty value.
# open resource manager session
set rm [visa::open-default-rm]
# parse instrument address
lassign [visa::parse-rsrc $rm "ASRL1::INSTR"] intfType intfNum
if { $intfType == $visa::INTF_ASRL } {
puts "Have serial interface device with interface number $intfNum"
}Read data synchronously, and store the transferred data in a file.
This command is a front-end for viReadToFile VISA API
function.
`visa::read-to-file session fileName count`session - channel containing reference to a VISA
resource session opened by visa::open.
fileName - name of file to which data will be
written.
count - number of bytes to be read.
Number of bytes actually transferred.
# open instrument with default access mode and timeout
set vi [visa::open $rm "ASRL1::INSTR"]
# read up to 1024 bytes of data
# or until term char is received
visa::read-to-file $vi "raw.dat" 1024Relinquishes a lock for the specified resource. This command is a
front-end for viUnlock VISA API function.
`visa::unlock session`session - channel containing reference to a VISA
resource session opened by visa::open.None
# get exclusive lock and wait forever
visa::lock $vi
# release the lock
visa::unlock $viTake data from a file and write it out synchronously. This command is
a front-end for viWriteFromFile VISA API function.
`visa::write-from-file session fileName ?count?`session - channel containing reference to a VISA
resource session opened by visa::open.
fileName - name of file from which data will be
read.
count - number of bytes to be written. If omitted,
entire file is written.
Number of bytes actually transferred.
# open instrument with default access mode and timeout
set vi [visa::open $rm "ASRL1::INSTR"]
# write entire file content to device
visa::write-from-file $vi "raw.dat"