Matlab provides an instrument control toolbox to drive GPIB devices under Windows. However this doesn't seem to work under Linux (Matlab 7.2.0.294). It appears, while there's a driver for National Instrument GPIB devices under Linux, the Matlab-GPIB interface isn't implemented.
Here we present a simple way to send GPIB commands from Linux.
We make us of NI's Linux driver. To interface this to Matlab we create a C-language program which uses Matlab's MEX external interface. The NI GPIB driver, when installed, can be linked to a C program using -lgpibapi.
Receive function
A Matlab function resultString=ibrd(gpibPrimaryAddress,bytesToRead) to receive bytes as Matlab strings from the GPIB device is presented below:
#include "ni488.h"
#include <stdlib.h>
#include <stdio.h>
#include "mex.h"
int i;
int Device = 0; /* Device unit descriptor */
int BoardIndex = 0; /* Interface Index (GPIB0=0,GPIB1=1,etc.) */
#define RESPONSE_LENGTH 100 /* default length of maximum response we can read from the GPIB device */
/* this is the entry point called from Matlab */
/* resultString = ibrd(gpibPrimaryAddress) */
/* resultString = ibrd(gpibPrimaryAddress,bytesToRead) */
void mexFunction(
int nlhs, mxArray *plhs,
int nrhs, const mxArray *prhs)
{
int PrimaryAddress = 2; /* Primary address of the device */
int SecondaryAddress = 0; /* Secondary address of the device */
char Buffer101; /* Read buffer */
int readLength=0;
int mrows, ncols;
char *input_buf, *output_buf;
int buflen,status;
/* Check for proper number of arguments. */
if (nrhs != 1 && nrhs!=2) {
mexErrMsgTxt("One or two inputs required.");
}
/* The first input must be an integer.*/
mrows = mxGetM(prhs0);
ncols = mxGetN(prhs0);
if (!mxIsDouble(prhs0) || mxIsComplex(prhs0) ||
!(mrows == 1 && ncols == 1)) {
mexErrMsgTxt("Input must be a single integer");
}
/* read the address parameter from the supplied Matlab matrix */
PrimaryAddress = (int) *(mxGetPr(prhs0));
/* if we're supplied with a number of bytes to read, use that instead of
* our default of RESPONSE_LENGTH */
if (nrhs>1)
{
/* The input must be a noncomplex scalar double.*/
mrows = mxGetM(prhs1);
ncols = mxGetN(prhs1);
if (!mxIsDouble(prhs1) || mxIsComplex(prhs1) ||
!(mrows <= 1 && ncols <= 1)) {
mexErrMsgTxt("Input must be a noncomplex scalar double.");
}
/* if it's a null matrix, ignore it */
if (mrows == 0 || ncols == 0) {
readLength=0;
}
else
{
readLength = (int) *(mxGetPr(prhs1));
}
}
else
readLength=0;
if (readLength==0)
readLength=RESPONSE_LENGTH;
/* Allocate memory for output string. */
output_buf = mxCalloc(readLength, sizeof(char));
/*****************************************************************************
* GPIB Initialization - Done only once at the beginning of your application.
*****************************************************************************/
Device = ibdev( /* Create a unit descriptor handle */
BoardIndex, /* Board Index (GPIB0 = 0, GPIB1 = 1, ...) */
PrimaryAddress, /* Device primary address */
SecondaryAddress, /* Device secondary address */
T10s, /* Timeout setting (T10s = 10 seconds) */
1, /* Assert EOI line at end of write */
0); /* EOS termination mode */
if (ibsta & ERR) { /* Check for GPIB Error */
mexErrMsgTxt("ibdev Error");
}
/*****************************************************************************
* Main Application Body - Write the majority of your GPIB code here.
*****************************************************************************/
ibrd(Device, output_buf, readLength); /* Read bytes from the device */
if (ibsta & ERR) {
mexErrMsgTxt("ibrd Error");
}
output_bufibcntl = '\0'; /* Null terminate the ASCII string */
ibonl(Device, 0); /* Take the device offline */
if (ibsta & ERR) {
mexErrMsgTxt("ibonl Error");
}
/* return a pointer to the result string to Matlab */
plhs0 = mxCreateString(output_buf);
}
Send function
...and a send function ibwrt(gpibAddress,stringToSend):
#include "ni488.h"
#include <stdlib.h>
#include <stdio.h>
#include "mex.h"
int i;
int Device = 0; /* Device unit descriptor */
int BoardIndex = 0; /* Interface Index (GPIB0=0,GPIB1=1,etc.) */
/* ibwrt(gpibPrimaryAddress,stringToSend) */
void mexFunction(
int nlhs, mxArray *plhs,
int nrhs, const mxArray *prhs)
{
int PrimaryAddress; /* Primary address of the device */
int SecondaryAddress = 0; /* Secondary address of the device */
int mrows, ncols;
char *input_buf, *output_buf;
int buflen,status;
/* Check for proper number of arguments. */
if (nrhs != 2) {
mexErrMsgTxt("2 inputs required.");
}
/* The input 0 must be a noncomplex scalar double.*/
mrows = mxGetM(prhs0);
ncols = mxGetN(prhs0);
if (!mxIsDouble(prhs0) || mxIsComplex(prhs0) ||
!(mrows == 1 && ncols == 1)) {
mexErrMsgTxt("Input must be a noncomplex scalar double.");
}
/* Assign pointers to each input and output. */
PrimaryAddress = (int) *(mxGetPr(prhs0));
/*printf("PrimaryAddress = %d\n",PrimaryAddress);*/
/* Input 1 must be a string. */
if (mxIsChar(prhs1) != 1)
mexErrMsgTxt("Input must be a string.");
/* Input 1 must be a row vector. */
if (mxGetM(prhs1) != 1)
mexErrMsgTxt("Input must be a row vector.");
/* Get the length of the input string. */
buflen = (mxGetM(prhs1) * mxGetN(prhs1)) + 1;
/* Allocate memory for input and output strings. */
input_buf = mxCalloc(buflen, sizeof(char));
/* Copy the string data from prhs0 into a C string
* input_buf. */
status = mxGetString(prhs1, input_buf, buflen);
if (status != 0)
mexWarnMsgTxt("Not enough space. String is truncated.");
/*****************************************************************************
* Initialization - Done only once at the beginning of your application.
*****************************************************************************/
Device = ibdev( /* Create a unit descriptor handle */
BoardIndex, /* Board Index (GPIB0 = 0, GPIB1 = 1, ...) */
PrimaryAddress, /* Device primary address */
SecondaryAddress, /* Device secondary address */
T10s, /* Timeout setting (T10s = 10 seconds) */
1, /* Assert EOI line at end of write */
0); /* EOS termination mode */
if (ibsta & ERR) { /* Check for GPIB Error */
mexErrMsgTxt("ibdev Error");
}
/*****************************************************************************
* Main Application Body - Write the majority of your GPIB code here.
*****************************************************************************/
ibwrt(Device, input_buf, buflen-1); /* Send the command */
if (ibsta & ERR) {
mexErrMsgTxt("ibwrt Error");
}
ibonl(Device, 0); /* Take the device offline */
if (ibsta & ERR) {
mexErrMsgTxt("ibonl Error");
}
}
These need to be compiled from within Matlab - you need GCC and the GPIB library installed. To compile, issue:
>> mex -lgpibapi ibwrt.c >> mex -lgpibapi ibrd.c
then you can call the functions as in this example to access GPIB device 2:
>> ibwrt(2,'xsetup0'); >> ibwrt(2,'xr'); >> response=ibrd(2) response = XM0000334 >> ibwrt(2,'xr'); >> response=ibrd(2,4) response = XM00 >> response=ibrd(2,5) response = 00334 >>
It would be fairly straightforward for these functions to pass through another parameter to select the secondary address of the device.