The Perl Toolchain Summit needs more sponsors. If your company depends on Perl, please support this very important event.

NAME

GPIB - Perl extension for GPIB devices

SYNOPSIS

  use GPIB;

  $g = GPIB->new("name");
  $g = GPIB->new($interface_module_name, @interface_parameters);

  # GPIB Functions
  $var = $g->ibcnt              # Read GPIB ibcnt variable
  $var = $g->iberr              # Read GPIB iberr variable
  $var = $g->ibsta              # Read GPIB ibsta variable

  $data = $g->ibrd($maxcnt)     # Read from device
  $data = $g->ibrda($maxcnt)
  $data = $g->ibrdf($maxcnt)

  $ibsta = $g->ibwrta($data)    # Write data to device
  $ibsta = $g->ibwrt($data)
  $ibsta = $g->ibwrtf($data)

  $ibsta = $g->ibcmd            # Write commands to GPIB bus
  $ibsta = $g->ibcmda 

  # GPIB Functions
  $value = $g->ibask($option)
  $ibsta = $g->ibbna($name)
  $ibsta = $g->ibcac($v)
  $ibsta = $g->ibclr 
  $ibsta = $g->ibconfig ($option, $value)
  $ibsta = $g->ibdma($v) 
  $ibsta = $g->ibeos($v) 
  $ibsta = $g->ibeot($v) 
  $ibsta = $g->ibgts($v) 
  $ibsta = $g->ibist($v) 
  $lines = $g->iblines 
  $dev = $g->ibln($pad, $sad)
  $ibsta = $g->ibloc 
  $ibsta = $g->ibnotify($v) 
  $ibsta = $g->ibonl($v) 
  $ibsta = $g->ibpad($v) 
  $ibsta = $g->ibpct 
  $ibsta = $g->ibppc($v) 
  $pp = $g->ibrpp($v) 
  $ibsta = $g->ibrsc($v) 
  $sp = $g->ibrsp($v) 
  $ibsta = $g->ibrsv($v) 
  $ibsta = $g->ibsad($v) 
  $ibsta = $g->ibsic 
  $ibsta = $g->ibsre($v) 
  $ibsta = $g->ibstop 
  $ibsta = $g->ibtmo($v) 
  $ibsta = $g->ibtrg($v) 
  $ibsta = $g->ibwait($mask) 

  # Utility Function
  $result = $g->query($command);
  print "OK" if $g->devicePresent;
  print $g->hexDump($data);
  $g->errorCheck;
  $g->printStatus;
  $g->printConfig;

  GPIB::msleep($milliseconds);

  # Normally not called by user, GPIB->new() calls these
  $ibsta = $g->ibfind()
  $ibsta = $g->ibdev()

DESCRIPTION

Gpib.pm provides a convenient and powerful interface to electronic test equipment through GPIB, serial, or other interfaces. The module provides Perl versions of familiar GPIB calls through an object interface.

GPIB.pm works in conjunction with interface modules that perform low level access. GPIB::ni is an XS module that interfaces to National Instruments GPIB cards, GPIB::hpserial is an XS module that interfaces to the serial port of HP equipment, GPIB::rmt is a client to access a GPIB sever running on a remote machine with TCP/IP protocols. GPIB::rmt also provides a standalone Perl server to allow remote access.

Normally, the GPIB module uses /etc/pgpib.conf file to configure the low level interface for particular devices. In general, the applications programmer doesn't need to be aware of the lower level interface and applications work transparent to the lower level interface.

GPIB->new() is used to create a reference for operations on a device. A typical program might use the following to open a device:

    use GPIB;

    $g = GPIB->new("Generator");

First, Generator is looked up in /etc/pgpib.conf (c:\pgpib.conf on Windows). A typical /etc/pgpib.conf entry is:

    # name      driver    Board   PAD   SAD TMO  EOT  EOS
    Generator   GPIB::ni  0       0x10  0   T1s  1    0

This entry describes a device called "Generator" that uses the National Instruments driver, board 0, primary address 16, and a timeout value of 1 second. See the sample /etc/pgpib.conf.sample file for more information on parameters for other interfaces.

GPIB->new() can be called to open a device bypassing /etc/pgpib.conf. Used in this manner, the first parameter is the name of the low level interface module. Other parameters are those required by the low level module. Here is an example for opening a device using the National Instruments driver with a primary address of 16. In the case of the GPIB::ni module, the parameters to new() are the parameters passed to ibdev() in a GPIB program written in C:

    $g = GPIB->new("GPIB::ni", 0, 16, 0, GPIB->T1s, 1, 0);

If GPIB::ni gets 6 parameters it uses ibdev() to open the device. If it gets 1 parameter it calls ibfind() to open the device. To open the bus (as opposed to a specific device), ibfind() is used with the nameof the bus as a parameter. Here is an example for open the GPIB bus on the first board. This can also be done in the /etc/pgpib.conf file.

   $g = GPIB->new("GPIB::ni", "gpib0");

The reference return by GPIB->new is used by all other GPIB methods to indentify the device. Most of the methods are object methods of standard GPIB function calls. A simple program for accessing the device is shown below:

    use GPIB;

    $g = GPIB->new("Generator");
    $g->tmo(GPIB->T3s);             # Set timeout to 3s
    $g->ibwrt('*IDN?');             # Send *IDN? to device
    $id = $g->ibrd(1024);           # Read result
    print "Got $id\n";

See GPIB documentation or example programs for examples using standard GPIB calls.

$t = $g->hexDump($data) produces a human readable dump of scalar containing binary data. This is useful for debugging GPIB programs.

GPIB::msleep($milliseconds) sleeps for specified number of mS. This is often useful in GPIB programming.

$result = $g->query($command) is a convenience function that does an $g->ibwrt($command) followed by an $g->ibrd() if the write succeeds. This simplifies the example shown above for read the ID string as follows:

    use GPIB;

    $g = GPIB->new("Generator");
    print "Got ", $g->query('*IDN?');

$g->printStatus() and $g->printConfig() are utility functions for printing status of the last operation (printStatus) or the configuration of the device (printConfig).

$g->errorCheck() is convenience function that check the ibsta return code from the previous operation. If there was an error then some diagnostic information is printed and the program exits. It's a quick and dirty method for doing error checking:

    use GPIB;

    $g = GPIB->new("device");   # new() dies on error

    $g->ibwrt('*IDN?');
    $g->errorCheck("ibwrt error ");

    $d = $g->ibrd(1024);
    $g->errorCheck("ibrd error ");

$g->ibsta(), $g->ibcnt(), and $g->iberr() are methods for accessing the global ibsta, ibcnt, and iberr variables normally associated with GPIB programming. These are usually global variables in GPIB C programs. In Perl these are instance variables. GPIB constants are accessed in the GPIB namespace. A typical piece of code for checking errors is:

    $g->ibwrt("Hello, world.");
    print "There was an error\n" if $g->ibsta & GPIB->ERR;
    print "Timeout\n" if $g->ibsta & GPIB->TIMO;

Look in GPIB.pm for a list of exportable constants.

INHERITANCE

The GPIB module is written with the intention of it being inherited by other modules. Driver modules that provide functionality for specific devices inherit GPIB. See documentation for specific modules, a short example is shown below. The GPIB::hp33120a driver module provides methods for conveniently setting parameters on this device while still providing all of the functionality of the GPIB module. An example is shown below:

    use GPIB::hp33120a;
  
    $g = GPIB::hp33120a->new("name");

    $g->freq(20000.0);    # Set frequency to 20kHz
    $g->shape(SIN);       # Sine wave
    $g->amplitude(4)      # 4v peak-to-peak
    $g->offset(2)         # Dc offset of 2v

The GPIB::hp33120a module is a very simple module written in completely in Perl. It inherits GPIB and implements methods that generate SCPI commands for the HP33120A functionality. It's very easy to write these modules and create resuable code useful for other projects.

POLYMORPHISM

A big word for a small piece of advice. If device driver modules that provide similar functionality for different devices adopt consistent naming for their methods, application programmers can write programs that might work across a number of devices. For example, if someone writes a new module for a function generator and she uses the same naming convention as GPIB::hp33120a, life is more convenient for everyone:

    use GPIB::hp33120a;
    use GPIB::xyzgen;

    $g[0] = GPIB::hp33120a->new("device1");
    $g[1] = GPIB::xyzgen->new("device2");

    for (@g) {
        $_->freq(1000000.0);
        $_->shape(SIN);
    }

In the example above, an array contains references to function generators. The loop sets all function generators to 1MHz sine waves without knowledge of the details of each device. This is a really great concept, but it only works if a consistent naming convention is used for similar modules. Please keep this in mind when you write new instrument drivers.

CONFIGURATION

/etc/pgpib.conf (C:\PGPIB.CONF on NT) contains local configuration information. It associates a name with the proper low level driver and parameters for that driver. In most cases, local configurations issues can be resolved with this file.

The file has one device per line. Blank lines or lines beginning with a '#' are ignored. The file is read once the first time GPIB->new() is called. From that point the configuration information is held in memory in a hash called %gpib::config. %gpib::config is a hash keyed off the name of the entry. Each element is a reference to an array of parameters on the configuration line. test.pl in the gpib traverses this data structure.

Each parameter in the file can be either a string, a decimal number, a hex number if it begins with '0x', or one of the National Instruments timeout constants TNONE, T10us, T30uS, etc.

It's not essential to have a /etc/pgpib.conf file, but it makes life much easier to confine all local configuration issues to this one file. If the address of a device is changed or if a device is moved from GPIB to a serial port, the only change required is in this file. When using Perl-GPIB the first time it's probably best to enter a device or two into this file and do some simple tests from the Perl debugger until you get confortable that things are working. Here's a sample test on my setup:

    % perl -MGPIB::hp33120a -de1

    Loading DB routines from perl5db.pl version 1.0401
    Emacs support available.
    
      DB<1> $g = GPIB::hp33120a->new("HP33120A")

      DB<2> x $g->get
            0  'SIN'
            1  '1.000000000000E+06'
            2  '+1.000000E+00'
            3  '+0.000000E+00'

      DB<3> p $g->query('*IDN?')
            HEWLETT-PACKARD,33120A,0,7.0-4.0-1.0

Entries for the GPIB::ni (National Instruments GPIB) interface look like this. The parameters after GPIB::ni correspond to the 6 parameters to ibdev():

  # NI GPIB card
  # name                      Board   PAD     SAD     TMO     EOT     EOS
  #
  K2002       GPIB::ni        0       0x10    0       T1s     1       0

Entries for the GPIB::rmt remote access interface look like this:

  # Remote connections
  # name        driver        machine          user   password  device
  #
  HP33120A      GPIB::rmt     sparky.mock.com  jeff   fiddle    HP33120A 

Entries for the GPIB::hpserial serial port interface look like this:

  # Serial port
  # name      driver              port        speed   TMO     EOS     FLAG
  #
  HP33120AS   GPIB::hpserial      /dev/cua1   9600    T3s     0x0a    0x0001

CREDIT

These modules were insprired by a GPIB module written by Steve Tell at the MSL at UNC (tell@cs.unc.edu). Steve's module showed me how great Perl is as a language for GPIB programming. So much of GPIB programming is munging text strings and Perl just can't be beat for this.

AUTHOR

Jeff Mock, jeff@mock.com

SEE ALSO

perl(1), GPIB::hpserial(3), GPIB::ni(3), GPIB::hp33120a(3), pgpib.conf(4).