FPGARelated.com
Blogs

TCP/IP interface (Matlab/Octave)

Markus NentwigJune 17, 201210 comments

Communicate with measurement instruments via Ethernet (no-toolbox-Matlab or Octave)

Purpose

Measurement automation is digital signal processing in a wider sense: Getting a digital signal from an analog world usually involves some measurement instruments, for example a spectrum analyzer.
Modern instruments, and also many off-the-shelf prototyping boards such as FPGA cards [1] or microcontrollers [2] are able to communicate via Ethernet.
Here, I provide some basic mex-functions (compiled C code) to interface directly from Matlab (Octave) on Windows.
The task itself seems rather trivial - send and receive via a TCP/IP socket - but making it work from scratch can turn into a quite time-consuming exercise. I hope that the code will be useful as a simple example.
A non-Matlab program with similar functionality can be found as lanio.c in [3] (page 131).

Pros/cons/Alternatives

Intermediate layer

The code communicates directly via the network interface. No intermediate layer such as SICL [4] or VISA is used, and no additional DLLs need to be installed.
Use of an intermediate layer integrates for example devices with legacy GPIP interface transparently. On the other hand, it requires the installation of vendor-dependent software on the host PC, and may create more problems than it actually solves.

Addressing

Devices are addressed by their IP address. If needed, the hostname could be resolved as shown in [3], but I'd assume that a typical lab network is strictly firewalled from intra-/internet, uses static IP addresses and provides no DNS service.

Timeouts

No timeouts are implemented: Keep it simple and stupid and don't worry about commands timing out because they won't. Ever.
The downside is that a protocol error (typos) will lock up the session and require a restart of Matlab / Octave. This can be inconvenient, but happens rarely if I pay attention to my code.

Too many connections

A "debugging session" in an early development stage may involve many connection attempts that aren't properly closed. This can cause problems both on instrument and PC side after a while.
If the code suddenly stops working without apparent reason, reboot.

Instrument control toolbox (Matlab)

Mathworks' "Instrument control toolbox" [5] implements similar functionality.
If it is available, consider using it instead.

Protocol

Message and reply

Typical use is to send SCPI commands (see [6] page 3) and receive responses. Example commands are *RST (reset the instrument), or *IDN? (query the identity of a device).
As is common, the application code needs to read data when it is known to be available. Usually this is the case after submitting a query-type command (ending with a question mark). If the instrument needs some time for the response, the read() command will block for as long as is needed.

ASCII and binary

ASCII data from the instrument is a single line, terminated with a newline character (number 13, \n).
Binary data may include the newline character as part of the message, therefore it needs to be prefixed by a header that encodes its length.
For example, an instrument will transmit the string abcdef in binary mode as
#70000006abcdef\n
Here,

  • #as first character indicates a binary message
  • 7states the length will be transmitted as seven-digit number in ASCII format
  • 0000006is the length of the following binary data
  • abcdefis the binary data
  • \n is a newline character

#16abcdef\n would be equivalent and shorter.
The code example converts binary data to a vector of floats!
If this is not appropriate, copy instrIf_read.cc to a different name and modify the data conversion as required.

Implementation details

The contents of the SOCKET data structure in the C code are passed back to Matlab as an array of chars - this is unorthodox but conceptually sound: By fair means or foul, the contents of the data structure will be bitwise identical between invocations.

Usage

Maybe the most straightforward and robust way to use the code is to

  • open a connection: s = instrIf_socket('192.168.1.1'); % example IP address assigned to an instrument
  • send one single command: instrIf_write(s, ['*IDN?', 10]); % note the terminating character
  • receive the reply (if applicable): r = instrIf_read(s);
  • close the connection: instrIf_close(s);
  • repeat for the next command

The reason not to reuse the connection is the possibility of a program error between instrument queries (the query itself is unlikely to fail): If the program aborts with an error, there won't be any open connections.
The overhead caused by the repeated opening / closing is usually negligible.

Debugging

If the instrument does not respond, open a DOS command prompt and type ping 192.168.1.1. At least typical measurement instruments should reply to "ping", and failure indicates network configuration problems.

The "telnet" program can be useful for network debugging. The default port number for SCPI commands is 5025.

Download

The functions can be downloaded below. Save them all into the Matlab (Octave) working directory, and compile each individually.
instrIf_socket.cc (compile with mex instrIf_socket.cc).
instrIf_write.cc (compile with mex instrIf_write.cc).
instrIf_read.cc (compile with mex instrIf_read.cc).
instrIf_close.cc (compile with mex instrIf_close.cc).
headers.h (required in same folder)
myUtil.cc (required in same folder)

References

[1] Altera / Terasic Stratix 4 DE4 development board

[2] MBED LPC-1768 microcontroller board

[3] Agilent signal generators programming guide

[4] Agilent SICL User's Guide for Windows

[5] Matlab Instrument Control Toolbox

[6] Agilent Technologies: N5161A/62A/81A/82A/83A MXG Signal Generators: SCPI Command Reference

Warranty

This program is provided "as is" without warranties of any kind, either expressed or implied, including, but not limited to, the implied warranties of merchantability, fitness for a particular purpose or noninfringement. in no event shall the authors or copyright holders be liable for any claim, damages or other liability, arising from, out of or in connection with the software or the use or other dealings in the software.



[ - ]
Comment by Luiz EduardoJune 23, 2012
Dear Markus, Please, forgive my poor English. I'm a civil engineer and I´m trying to understand the FFT calculations. I have an "elementary" question and I'm lookng for some help. I´m using FORTRAN routines (FORTRAN 90/95 by S. Chapman's book). The question is: suppose I have a time history of velocities signals and I take a FFT of these signals, say, up to the Nyquist frequency. The real parts of my complex vector will return the amplitudes and the imaginary ones will return me the phases. So now, I will have the amplitudes related with the several frequencies. However, I would like to know how to obtain the transformation of these amplitudes in terms of my field (primary) variable, that is, in terms of velocities, so that I can get the spectrum in terms of velocities. In this case It will be possible to perform inverse FFTs for single values, that is, for each frequency of the spectrum? Thank you for your help, Luiz Eduardo luizeduardotferreira@gmail.com
[ - ]
Comment by mnentwigJune 23, 2012
Hi, this isn't the best place for the question, as this topic doesn't involve FFT. Anyway, while I'm here: >> The real parts of my complex vector will return the amplitudes and the imaginary ones will return me the phases. Please check your statement. Maybe it's just a typing mistake, or then there is a genuine misunderstanding. The imaginary part is NOT the same as the phase (and the real part is NOT the amplitude). If needed, check the Wikipedia entry, http://en.wikipedia.org/wiki/Complex_numbers keywords are "cartesian" and "polar" coordinates.
[ - ]
Comment by Luiz EduardoJuly 6, 2012
Mark, I would like to thank you for your response. Also, I would like to excuse me with you for using this space to talk about FFT. I really don’t know many things about blogs. However, let us go directly to the subject. In fact we had a misunderstood. The FORTRAN routines by S. Chapman that I´m using give the results as I wrote you before. These results are organized back from the routines into the two complex vectors previously used, so that the real part brings the amplitudes and imaginary ones, furnish the phases. Anyway, instead of doing IFFT for every bin of interest, I decided to use Omega Arithmetic to solve my problem faster, by calculating: omega (=2 * PI * frequency) V(f) = Sqrt{[I(f)/Omega]**2 + [-R(f)/Omega]**2} = Sqrt {I(f)**2 + R(f)**2} / Omega = A(f) / Omega. Concerning the complex algebra you suggested at Wikipedia, I have been looking at my 16th year old daughter‘s book for Math and it apparently gives the same idea about the theme. I think my huge problem is the English language. Best regards, anyway. Luiz Eduardo
[ - ]
Comment by driss35March 14, 2013
Hi Luiz, just about complex number. We have for a complexj this definition: z=a+j*b = Amplitude*exp[j*phase].

So Amplitude = sqrt(a²+b²) and Phase=arct(b/a).

I hope that will be usefull for you.
Best regards
Driss from Morocoo
[ - ]
Comment by frgboyFebruary 20, 2014
Markus,
Thank you so much for this code! I've been looking for a free alternative to the Instrument Control Toolbox and this is working great with my equipment. I have one instrument that has a 5 second delay when responding to the *IDN? query, but everything else is working great!
[ - ]
Comment by mnentwigFebruary 26, 2014
Hi,

I remember a similar delay when the device was on a shared network with a DHCP server etc.
Try to set up an Ethernet adapter with fixed IP (i.e. 192.168.1.250), and set a fixed IP address for the instrument (i.e.192.168.1.249). Then connect with a single network cable (if no "green light" you may need a crosslink cable or hub in-between).

"ping" can be a useful tool. If the response is inconsistent, you know it's a network problem and not the instrument code.

[ - ]
Comment by Hobbit13July 21, 2014
Hi, I'm trying to use this in Octave 3.8.1, using your build command, or "mkoctfile --mex instrIf_socket.cc"
I get errors such as "D:\temp\Matlab/instrIf_socket.cc:42: undefined reference to `_imp__socket@12'"

and only a file with '.o' extension is created. Could you point me into a direction to find a solution?

thanks in advance
[ - ]
Comment by tafkosNovember 27, 2016

I compile on windows in the following way:

----------------------

delete *.mex *.o

mkoctfile --mex -lws2_32 instrIf_close.cc myUtil.cc

mkoctfile --mex -lws2_32 instrIf_read.cc myUtil.cc 

mkoctfile --mex -lws2_32 instrIf_write.cc myUtil.cc

mkoctfile --mex -lws2_32 instrIf_socket.cc myUtil.cc

----------------------

BTW, need to add #include "headers.h" as first line in myUtil.cc

[ - ]
Comment by mnentwigNovember 28, 2016

Hi tafkos,

thanks for the comment. 

Yes, the -lws2_32 is required as gcc ignores '#pragma comment(lib, "Ws2_32.lib")'

If you switch the order of the files (see the "mex" example in the text, e.g. mkoctfile --mex -lws2_32 myUtil.cc instrIf_close.cc) I think we don't need to add "headers.h", as it's #included from myUtil.cc

[ - ]
Comment by mnentwigJuly 22, 2014
Hi,

it's a linker error. It can't find the "socket" function in any library.
If you are using an Octave binary from Sourceforge, there are two alternative executable packages:
- one built with Microsoft compiler
- the other one built with gcc
The former is considerably faster, but compilation will probably not work. Try the second one.
If this doesn't solve the problem, it may be that a library - probably "winsock" - is not given to the linker as argument, or libraries are in the wrong order. These things often take some trial-and-error, unfortunately.

To post reply to a comment, click on the 'reply' button attached to each comment. To post a new comment (not a reply to a comment) check out the 'Write a Comment' tab at the top of the comments.

Please login (on the right) if you already have an account on this platform.

Otherwise, please use this form to register (free) an join one of the largest online community for Electrical/Embedded/DSP/FPGA/ML engineers: