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.