v5.0 / 7 of 23 / 01 sep 99 / gvg
* VEE provides many facilities for dealing with instruments. This chapter provides an overview of these facilities.
* The most flexible and powerful of VEE I/O tools is the Direct I/O (DIO)
object, which allow you to directly send commands to and read data from an
object:
Interface Operations objects are also transaction objects, but they perform
transactions on an interface and support operations specific to a particular
type of interface.
Interface and Device Event objects allow a VEE program to wait for an event
(such as an HPIB service request) from an instrument.
Traditionally, VEE instrument I/O has been strongly oriented toward dealing
with instruments using instrument drivers, in which you have a software front
panel that simulates the front panel of an instrument. For example, the
instrument driver front panel for 3478 DMM would appear as follows:
If you only want to set or read one component, you can use a "component
driver" instead:
PNP drivers have not proven universally popular, but they are proving a
stepping stone for more advanced technology, such as the Interface to Virtual
Instruments (IVI) driver scheme, which is based on Microsoft ActiveX
technology and is now in advanced definition. Current expectations are that
VEE will track new driver developments.
This chapter discusses Direct I/O, the Interface Operations, and Interface
and Device Event objects. The types of instrument drivers are discussed in
the following chapter.
* VEE Direct I/O, as noted, allows sending and receiving data from devices
over VEE's supported interfaces.
For example, to perform a typical reset sequence for an HPIB 488.2-compatible
instrument, you could use the VEE I/O configure menu to bring up a DIO object
and then add the following transactions:
* Using VEE Direct I/O with serial (RS-232) is much the same, with a few
added features. An HP SE was trying to use an HP Omnibook portable computer
with an HP ALF (34401) DMM and having troubles; I cabled the Omnibook to an
Alf (34401) with the cable supplied with the Omnibook. I went to the
front-panel menu of the Alf and confirmed that it was set to the serial port
as the interface and that it was set to 9600 baud, 8 bits, no parity (that's
all you can set on the Alf itself).
Then I ran VEE and set the serial configuration to:
The sequence of commands used above is actually a pretty good test sequence
for dealing with a SCPI-compatible instrument. Note the use of the
"SYSTEM:REMOTE" command. This is required when using an ALF on serial to get
it to reliably communicate over RS-232.
* For another example of DIO use, an HP SE called me to ask: how would one
output an escape sequence (or, for that matter, any nonprinting characters)
from a VEE Direct I/O object?
I thought he could just embed a "\e" in the text he wanted to send, but this
gave an error message. Next I tried to use a "\27", an ESCAPE character
has the decimal value of 27, and the DIO object swallowed it, but it didn't
give the results I thought it should.
That being close, I tried the octal value instead ("\033") and it worked
fine. To confirm, I got my hands on an old HPIB ThinkJet printer. It can be
programmed to give an "expanded" font by sending it an "ESC&k1S", and can be
returned to its normal font by sending it an "ESC&k0S".
The following VEE example shows how to do this:
* There is an undocumented feature in VEE that likely should be documented
(I was surprised to find out about it myself).
If you have a Direct I/O object (or other transaction object) that performs
two READs to the same output pin (meaning the first is overwritten by the
second), and the two transactions send different data types to the output
pin:
There is a special "null" variable that allows you to get around this
problem, though. If you READ to it, then the data is thrown away and no
memory is allocated (and so there is none to be lost):
* One problem with VEE I/O is that there is no way to read an array from HPIB
to an EOI. The only thing that can be done is use a Direct I/O object to
read data a byte at a time and put the bytes in a Collector object.
You bring an error pin out on the Direct I/O object. You drive the Direct
I/O object with an Until Break object and break out of the loop when you
finally time out:
So you want to read it back one item at a time until you time out, and use an
error pin to trap the timeout:
* VEE 3.0 introduced the Multidevice Direct I/O object. This enhances the
traditional Direct I/O object by allowing a single transaction object to
communicate with multiple instruments.
The Multidevice Direct I/O object looks much like a Direct I/O object until
you try to specify a transaction. Then you get a dialog like this:
* The Interface Operations object can be used to specify various
interface level operations that can come in handy in a pinch.
You can select this object from the "I/O" menu's "Advanced I/O > Interface
Operations" object. You get a dialog asking for the desired interface --
say, "hpib7" -- and then get the object:
* If you select EXECUTE operations, you get a transaction dialog like this:
* However, you can make practical use of the Interface Operations object even
without much knowledge of HPIB protocols. For example, suppose you are
dealing with an instrument driver and occasionally get the HPIB in an
uncertain state. You could use the Interface Operations object to clear the
bus. All you have to do is create a thread in your program that looks like
this:
* One operation that was tricky in earlier versions of VEE was passing
control. It had to be done by synthesizing the bus transactions using the
Interface Operations object, and there was no way to detect if control was
passed back to VEE.
As of VEE 4.0, Interface Operations obtained an EXECUTE PASS CONTROL
transaction that passes control and then waits to get control back, greatly
simplifying this process.
Note that it is impractical to run VEE as a non-system controller. There is
no way for VEE to read or write data while it is not active controller.
* The HP E2050 LAN-HPIB gateway box has proven a reliable and easy-to-use
device that allows computers running HP VEE and other software to control
instruments at remote network locations.
One of the problems with the gateway, however, is that any controller on the
network can access it, and this can cause confusion if several different
computers try to access it at the same time.
The way around this problem is to allow the controller to "lock" the gateway
so that the controller will be the only one allowed access until it releases
the lock. In HP VEE, this is done using the LOCK INTERFACE and UNLOCK
INTERFACE transactions in the Interface Operations object.
For example, I have a 54600 scope connected to an E2050 LAN gateway with
the IP address 15.11.29.90; the scope address evaluated to 113. I wrote
the following small program to demonstrate the lock mechanism:
Running two of these programs on different controllers allows testing the
lock mechanism. If the gateway is unlocked, a controller can access it
readily. If it is locked, an attempt to access it gives an error of the
form:
* The Interface Event object allows you to check for the presence of an
interrupt condition from an external device, either an SRQ (from an HPIB
device) or (as of VEE 3.0) a DAV (input data valid) condition from a serial
device. It has the format:
The Device Event object allows you to check for SPOLL conditions from a
remote HPIB device. It has the format:
* A German HP field person said he was having various problems getting the
serial DAV (data valid) Interface Event to work, which gave me a good
opportunity to test out this functionality. I wrote two programs for two PCs
I had wired together with a null-modem cable.
In both systems I set up the serial ports to 9600 BPS, no parity, 1 stop bit,
and DTR/DSR handshaking. These were quite arbitrary settings. The first
program -- which used the Interface Event object -- was as follows (source
can be found in xserdav.vee):
* The user did some tinkering and got DAV to work reliably, but then he
wondered how to set a timeout on the Interface Event object.
I replied that timeouts don't apply to interface events. A programmer can
set it to WAIT and have it as a parallel branch that will be executed when
the event happens (as in the example above) or set it to NO WAIT and just
poll as needed.
There was no need for a timeout. It's not really an I/O operation, it's
really just a status test, and a programmer can "block" on the test or just
poll for it.
However, there is a timeout setting in the Interface Operation's object
menu (under "Properties"). However, this timeout doesn't do what a user
might think it is supposed to. In fact, all it does is determine how long
the Interface Operations object will wait before failing to acquire an
interface that is locked by another process.
* While the VEE To/From Socket object isn't a device-I/O object, it has
similarities and is useful to discuss in this context.
A "socket" is a network connection. In general terms, it makes a networking
connection between two different machines look just like a file, with
communications taking place between a "caller" program and a "receiver"
program. (Windows users will find the scheme similar to DDE, though sockets
are a much more reliable mechanism.)
Socket communications require that the receiver has selected a "port number"
-- a more or less arbitrary value in the range of 0 to 65,535 -- through
which it can be accessed and is waiting to accept a remote connection. The
caller will then try to connect to the receiver through through the
receiver's Internet address and the socket number.
Note that I said that port numbers are "more or less arbitrary". The
reservation in that statement refers to the fact that port numbers between 0
and 1023 are reserved for the operating system, and port numbers from 1023 to
5000 are reserved for commercial purposes. Port numbers above 5000 are open
for general use; ports above 5000 are referred to as "transient".
The To/From Socket object allows you to configure both ends of the socket
connection. For example, consider transferring a string from an arbitrary
caller to a receiver on a host named "hpislmmc" that has bound itself to port
number 5001:
Note that there is an EXECUTE transaction that allows you to specifically
terminate a connection. This should be done after the completion of each
transaction on both sides, or the socket will be left open and cannot be
accessed again.
Remember that when you do a "Bind Port" that your VEE program will hang on
that object and wait for something to happen (at least for the timeout
interval).
* A user was trying to program network sockets in VEE and found that if there
were, say, two VEE clients trying to access one server, only one client could
connect to the To/From Socket object in the server at a time.
This is not such an obstacle, however, since the programmer can set up
several To/From socket objects ports and poll among them: setting the
timeouts to a very short period (like a third of a second), trapping the
timeout error to see if the port should be used or not, and then moving on to
the next if not.
The lab people say this is essentially what most network-aware applications
do. Server software is of course much more sophisticated, but that is beyond
what could be reasonably done in VEE. The Euchre game provided with VEE 4.X
allows four people to play over a network, and implements this policy.
[7.1] I/O OBJECTS OVERVIEW
[7.2] DIRECT I/O
[7.3] MULTIDEVICE DIRECT I/O
[7.4] INTERFACE OPERATIONS OBJECT
[7.5] INTERFACE & DEVICE EVENT OBJECTS
[7.6] TO/FROM SOCKET
[7.1] I/O OBJECTS OVERVIEW
+----------------------------------+
| 34401 (34401 @ 723) |
+------------------------------+---+
| WRITE TEXT "*IDN?" STR | |
| READ TEXT X STR | X +-->
| | |
+------------------------------+---+
DIO objects are another example of VEE transaction I/O. You can create lists
of READ and WRITE data transactions, as well as perform some control
operations and WAITs.
+--------------------------+
| hp3478(LIVE) |
+--------------------------+
| [Reset] [ Main Panel ] |
| +----------------------+ |
| | ? | |
| +----------------------+ |
| |
| Function [ DCV ] |
| Range [Auto] [ * ] |
| Ndigits [ 4.5 ] |
| Trigger [ Hold ] |
| Auto Zero [ On ] |
| |
+--------------------------+
You can select other panels for the ID through the menu button labeled "Main
Panel" above. You can set this ID to the appropriate functions with a mouse
and the instrument (presuming it is connected) will respond accordingly. If
you execute an ID panel programmatically, it will send all its settings to
the instrument. You can select any of the components on the ID and turn them
into input or output pins as appropriate, allowing you to set ID functions
programmatically.
+---------------------------------------+
| hp3478(LIVE) |
+----------+------------------+---------+
| FUNCTION | | Reading |
| Int16 | | |
+----------+------------------+---------+
However, such instrument drivers have proven to be complicated to use, hard
to maintain and support, and nonstandard. As a result, HP moved towards a
new scheme, Plug&Play (PNP) drivers, that provide driver libraries that can
be used with different software applications besides VEE.
[7.2] DIRECT I/O
+----------------------------------+
| 34401 (34401 @ 723) |
+------------------------------+---+
| EXECUTE CLEAR | |
| WRITE TEXT "*RST;*CLS" | |
| WAIT 3 | X +-->
| WRITE TEXT "*IDN?" STR | |
| READ TEXT X STR | |
| | |
+------------------------------+---+
Note that as of VEE 3.0, you can add "Address" and "Timeout" pins to DIO
objects (and instrument drivers) to change the instrument address or timeout
"on the fly". If you bring out one or both of these pins on a single ID or
DIO object, it will change the address or timeout for all IDs and objects for
that particular device.
8 bits / 1 stop / no parity / 9600 baud / no flow control
-- and tried to run the following program (see xseralf1.vee for the
source):
+------------------------------------------+
DIO object: | serial(@9) |
+--------------------------------------+---+
Reset interface: | EXECUTE RESET | |
Clear ALF: | WRITE TEXT "*RST;*CLS" EOL | |
Wait for ALF to clear: | WAIT INTERVAL:3 | X +---+
Put ALF in remote mode: | WRITE TEXT "SYSTEM:REMOTE" EOL | | |
Display XYZZY on ALF: | WRITE TEXT "DISP:TEXT \'XYZZY\'" EOL | | |
Ask for ID string: | WRITE TEXT "*IDN?" EOL | | |
Read it back: | READ TEXT X STR | | |
+--------------------------------------+---+ |
|
+-------------------------------------------+
|
| +--------------------------+
| | AlphaNumeric |
| +--------------------------+
+--->| |
+--------------------------+
It displayed XYZZY on the display but got a timeout when it tried to read the
ID string. I changed the VEE configuration from "no flow control" to
"DTR/DSR" flow control and it worked, returning the ID string.
+--------------------------------------------+
| Direct IO (TJ @ 701) |
+---+------------------------------------+---+
| | WRITE TEXT "Normal!" EOL | |
| | WRITE TEXT "\033&k1SExpanded!" EOL | |
| | WRITE TEXT "\033&k0S" EOL | |
| | | |
+---+------------------------------------+---+
If you want to send blocks of binary data, you should use a separate BYTE
transaction.
READ TEXT X STRING
READ TEXT X REAL
-- then you will lose the memory provided for the data on the first
transaction, resulting in a memory leak.
READ TEXT null STRING
READ TEXT X REAL
This appears to be one of the few cases (possibly the only case) where you
can READ into anything but an output pin.
|
+---+---+
| Until |
| Break +------------------+
+---+---+ |
| |
+--------------+-------------+
| Direct I/O |
+--------------------+-------+
| READ BINARY X BYTE | X +------------>+-----------+
| | | | Collector +-->
| | error +--+--------->+-----+-----+
+--------------------+-------+ | |
| |
+---+---+ +---+---+
| Break | | Next |
+-------+ +-------+
Similarly, a VEE user wanted to read an indefinite-length array over an
RS-232 interface. The problem is that if you don't specify the array size
and don't have some sort of length header or terminator data in the input
data stream, VEE has no way of knowing how big the array should be, and will
time out.
|
+---+---+
| Until |
| Break +-----------+
+---+---+ |
| |
| +----------+----------+
| | Serial DIO |
| +-------------+-------+
| | READ BYTE X | X +---------------->+-----------+
| | | error +--+ | Collector +-->
| +----------+--+-------+ | +--->+-----------+
| | | |
| +---+---+ +---+---+ |
| | Next | | Break | |
| +-------+ +-------+ |
| |
+---------------------------------------+
This scheme is slow, but it doesn't matter, it's still faster than RS-232.
It is also a little simplistic, since it doesn't discriminate between
different types of errors. Improvements can be left as an exercise for the
user.
[7.3] MULTIDEVICE DIRECT I/O
+-----------------------------------------------------------------------+
| I/O Transaction |
+-----------------------------------------------------------------------+
| [ WRITE ] [ 3478 ] [ Default Address ] [ TEXT ] [a ] |
| [ DEFAULT FORMAT ] [ EOL ON ] |
| |
| |
| [ OK ] [ NOP ] [ Cancel ] |
+-----------------------------------------------------------------------+
You can click on the instrument field to select another instrument from those
you have configured under VEE:
[ WRITE ] [ 3478 ] [ Default Address ] [ TEXT ] [a ]
+--------+
| 3478 |
| 34401 |
| E1300 |
| E1326 |
| 54600 |
| Serial |
+--------+
You can also specify a different address in a transaction if you like:
[ WRITE ] [ 3478 ] [ Address: ] [723 ] [ TEXT ] [a ]
Once you have set up transactions they take the form:
+-------------------------------------+
| MultiDevice Direct I/O |
+---+-----------------------------+---+
| | WRITE 3478 TEXT A EOL | |
| A | READ 34401: 720 TEXT X REAL | X |
| | | |
+---+-----------------------------+---+
[7.4] INTERFACE OPERATIONS OBJECT
+-----------------------------------+
| Interface Op's: hpib7@7 |
+-----------------------------------+
| |
| |
| |
+-----------------------------------+
This works much like other transaction objects. Click on the work area,
(under the title bar) and you get a dialog to specify your first transaction:
+------------------------------------------------+
| I/O Bus Transaction |
+------------------------------------------------+
| [ SEND ] [ COMMAND: ] [ 0 ] |
| |
| |
| [ OK ] [ Cancel ] |
+------------------------------------------------+
There are two classes of I/O bus transactions: SEND (as shown) and EXECUTE.
SEND allows you to perform low-level HPIB transactions with a remote device,
as defined by the COMMAND field. Click on this and you get a dialog:
+---------------------------------------+
| Select I/O Send Command |
+--------+---------------------+--------+
| | COMMAND: | |
| | DATA: | |
| | TALK: | |
| | LISTEN: | |
| | SECONDARY: | |
| | UNLISTEN | |
| | UNTALK | |
| | MY LISTEN ADDR | |
| | MY TALK ADDR | |
| | MESSAGE: | |
+--------+---------------------+--------+
| COMMAND: |
+---------------------------------------+
| [ OK ] [ Cancel ] |
+---------------------------------------+
These are low-level HPIB commands whose definitions are beyond the scope of
this document. Please see a reference text on HPIB protocols for details.
Note that the entries that end with a ":" require parameters, and that there
is a field in the transaction dialog for those parameters.
+------------------------------------------------+
| I/O Bus Transaction |
+------------------------------------------------+
| [ EXECUTE ] [ CLEAR ] |
| |
| |
| [ OK ] [ Cancel ] |
+------------------------------------------------+
The CLEAR allows you to perform interface or bus (not device specific)
operations on the HPIB interface. Click on this field and you get the full
set of selections:
+---------------------------------------+
| Select I/O Execute Command |
+--------+---------------------+--------+
| | ABORT | |
| | CLEAR | |
| | TRIGGER | |
| | REMOTE | |
| | LOCAL | |
| | LOCAL LOCKOUT | |
| | | |
| | | |
+--------+---------------------+--------+
| CLEAR |
+---------------------------------------+
| [ OK ] [ Cancel ] |
+---------------------------------------+
Again, a real understanding of these operations requires a detail knowledge
of HPIB.
+-----------------------------------+
| Interface Op's: hpib7@7 |
+-----------------------------------+
| EXECUTE ABORT |
| EXECUTE CLEAR |
| |
+-----------------------------------+
This executes operations that stops (ABORTs) all HPIB operations, and then
puts the interface into a CLEAR state. Other operations as needed for the
particular system could be added as Interface Operation transactions, or with
a Direct-I/O object or objects.
+--------+
| Repeat |
| Until +--+
+--------+ |
|
+--+--+
| OK +-----+
+-----+ |
|
+--------------------+--------------------+
| Interface Ops: hpib1 on 15.11.29.90 @ 1 |
+-----------------------------------------+
| EXECUTE LOCK INTERFACE |
+--------------------+--------------------+
|
+---------------+---------------+
| Scope( @ 113 on 15.11.29.90 ) |
+---------------+---------------+
|
+--+--+
| OK +-----+
+-----+ |
|
+--------------------+--------------------+
| Interface Ops: hpib1 on 15.11.29.90 @ 1 |
+-----------------------------------------+
| EXECUTE UNLOCK INTERFACE |
+--------------------+--------------------+
|
+---+---+
| Next |
+-------+
All this program does is run in a cycle: the user presses the first OK
button to lock the interface and access the scope, then presses the second
OK button to unlock the interface and set up for a new access.
Lock Acquisition Failed
Once the other controller releases the lock, the first controller can then
access the interface.
[7.5] INTERFACE & DEVICE EVENT OBJECTS
+------------------------------+ +------------------------------+
| SRQ: hpib7 | | DAV: serial9 |
+----------------------+-------+ +----------------------+-------+
| Interface: [ hpib7 ] | | | Interface: [ hpib7 ] | |
| Action: [ WAIT ] | event +--> | Action: [NO WAIT] | event +-->
| Event: [ SRQ ] | | | Event: [ SRQ ] | |
+----------------------+-------+ +----------------------+-------+
The object can be either set to hang and wait for the event (WAIT) or simply
check for it and proceed (NO WAIT).
+--------------------------------------+
| Spoll:dmm(@ 722) |
+-----------------------------+--------+
| Device: [ dmm (@722) ] | |
| Event: [ Spoll ] | status +-->
| Action: [ ANY SET ] | |
| Mask: [ #H0 ] | |
+-----------------------------+--------+
This object simply performs a serial poll and uses the results (modified by
an AND with the "Mask" value) to return results and continue execution as
determined by the "Action" field, which can be set to "ANY SET", "ALL CLEAR",
or "NO WAIT".
+-------+
| Until |
| Break +--+
+-------+ |
|
+------+------+
| Wait On DAV | OK button
+------+------+
|
+---+---+
| DIO 1 | perform EXECUTE RESET on serial
+---+---+
|
+---+---+
| Until |
| Break +--+
+-------+ | +-----------------+
| | If-Then-Else |
Reset +---+---+ +---+------+------+
+->| Quit +--+-->| A | A==1 | then +---------+
| +---+---+ | +---+------+------+ |
+------|------+ +---+---+
| Toggle Button | Break |
| +-------+
| +-----------------+
+-----+-----+ | If-Then-Else | Poll for DAV and then
| Interface | +---+------+------+ display input string
| Event +--->| A | A!=0 | then +--+
+-----+-----+ +---+------+------+ |
| |
| +-------------------+
| |
| +---+---+ +----------------+
| | DIO 2 +-->| REMOTE TEST:25 |
| +-------+ +----------------+
| DIO 2 contains: READ TEXT x STR
|
+---+---+ +----------+ show current time to indicate
| now() +-->| 11:41:25 | something is going on
+-------+ +----------+
The other program sent the string: REMOTE TEST:<n>
+-------+
| Until |
| Break +--+
+-------+ |
|
+-----+-----+
| Send Data | OK button
+-----+-----+
|
+---+---+
| DIO 1 | perform EXECUTE RESET on serial
+---+---+
|
+---+---+
| Until |
| Break +--+
+-------+ | +-----------------+
| | If-Then-Else |
Reset +---+---+ +---+------+------+
+->| Quit +--+-->| A | A==1 | then +---------+
| +---+---+ | +---+------+------+ |
+------|------+ +---+---+
| Toggle Button | Break |
| +-------+
| +-----------------+
| | If-Then-Else |
Reset +---+---+ +---+------+------+ +---------+ +-------+
+->| Send! +--+-->| A | A==1 | then +-->| Counter +-->| DIO 2 |
| +-------+ | +---+------+------+ +---------+ +-------+
+-------------+ DIO2 contains: WRITE TEXT "REMOTE TEST:",a EOL
I ran this second program on my second PC against the first on my first PC.
Repeated tests indicated that the DAV event worked quite well and the
user had a configuration problem.
[7.6] TO/FROM SOCKET
+------------------------------+ +------------------------------+
| To/From Socket | | To/From Socket |
+--------------------------+---+ +---+--------------------------+
|[Connect Port][ 5001 ]| | | |[ Bind Port ][ 5001 ]|
| Host Name: [ hpislmmc ]| | | | Host Name: [ hpislmmc ]|
| Timeout: [ 60 ]| | | | Timeout: [ 60 ]|
+--------------------------+ X | | A +--------------------------+
|[WRITE TEXT A STR EOL ]| | | |[READ TEXT x STR ]|
|[EXECUTE CLOSE ]| | | |[EXECUTE CLOSE ]|
| | | | | |
+--------------------------+---+ +---+--------------------------+
caller receiver
The To/From Socket object allows you specify whether you want to connect to a
port (from a caller) or to bind to a port (on a receiver) and specify a
transaction timeout as well.