Channel: credentiality
Viewing all articles
Browse latest Browse all 94

Linux data acquisition with an Agilent Infiniium MSO9404A oscilloscope

I need to capture some analog data.  My coworker has a National Instruments USB data acquisition module, but as far as I can tell, the drivers are all proprietary and focused on using Labview.

So instead I used a fancy 9000-series Agilent Infiniium scope.  I plugged my laptop's ethernet cable into the scope, then used the Windows control panel on the scope to set its IPv4 address to  I set my laptop to, and found that I could ping the scope.  So far so good.

Back in the day, test equipment was controllable over a serial GPIB bus.  Today's fancy gear uses the same conventions over TCP/IP.  There's a confusing mess of acronyms like VXI-11 and VISA, and a bunch of half-baked libraries and crappy-looking system drivers that appear to be required to use them.  pyvisa looks nice, but wants a proprietary National Instruments driver distributed as a .iso(!).  Not my cup of tea.

Then I ran across this MATLAB example that's basically just chatting with the device over TCP/IP. That led me to Agilent's Programmer's Reference guide for the 9000-series scopes.

After fighting with the 1100-page manual for a few hours, I came up with the following settings that let me get samples at a specific rate like I would from an ADC.

Note that you can also interactively talk to the scope using nc or telnet to port 5025 while you're experimenting.


# Using ethernet to talk to an Agilent Infiniium MSO9404A
# See also the "Infiniium 9000A Programmer's Reference"

import socket
import sys

sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.connect(("", 5025))

def cmd(s):
sock.send(s + "\n")

def resp():
r = sock.recv(1048576)
while not r.endswith("\n"):
r += sock.recv(1048576)
return r

print "Querying scope"

print "Scope identifies as: ", resp(),

# This doesn't seem to affect the samples we receive
cmd(":timebase:range 1E-6")
cmd(":timebase:delay 0")

cmd(":channel1:range 5")
cmd(":channel1:offset 2.5")
cmd(":channel1:input dc")

cmd(":trigger:mode edge")
cmd(":trigger:slope positive")
cmd(":trigger:level chan1,2.5")

cmd(":system:header off")

cmd(":acquire:mode rtime") # Realtime mode; don't average multiple passes
cmd(":acquire:complete 100")

cmd(":waveform:source channel1")
cmd(":waveform:format ascii")

cmd(":acquire:count 1")
cmd(":acquire:srate:auto off")
cmd(":acquire:srate 4000")
cmd(":acquire:points:auto off")
cmd(":acquire:points 16")
# This was on by default, and took me a long time to figure out why
# I was getting ~16x the number of samples I requested.
cmd(":acquire:interpolate off")

cmd(":digitize channel1")
# This should block until the capture is done, since we used :digitize

sample_string = resp().rstrip().rstrip(",")
ascii_samples = sample_string.split(",")

samples = []
for f in ascii_samples:
print "Couldn't convert:", f

print "Got ", len(samples), " samples. Values 1-10:", samples[:10]

Viewing all articles
Browse latest Browse all 94

Latest Images

Trending Articles

Latest Images