-
-
Save pklaus/7e4cbac1009b668eafab to your computer and use it in GitHub Desktop.
#!/usr/bin/env python | |
""" | |
Download data from a Rigol DS1052E oscilloscope and graph with matplotlib. | |
By Ken Shirriff, http://righto.com/rigol | |
Based on http://www.cibomahto.com/2010/04/controlling-a-rigol-oscilloscope-using-linux-and-python/ | |
by Cibo Mahto. | |
""" | |
import numpy | |
import matplotlib.pyplot as plot | |
import sys | |
import visa | |
rm = visa.ResourceManager() | |
# Get the USB device, e.g. 'USB0::0x1AB1::0x0588::DS1ED141904883' | |
instruments = rm.list_resources() | |
usb = list(filter(lambda x: 'USB' in x, instruments)) | |
if len(usb) != 1: | |
print('Bad instrument list', instruments) | |
sys.exit(-1) | |
scope = rm.open_resource(usb[0], timeout=20, chunk_size=1024000) # bigger timeout for long mem | |
# Grab the raw data from channel 1 | |
scope.write(":STOP") | |
# Get the timescale | |
timescale = float(scope.query(":TIM:SCAL?")) | |
# Get the timescale offset | |
timeoffset = float(scope.query(":TIM:OFFS?")[0]) | |
voltscale = float(scope.query(':CHAN1:SCAL?')[0]) | |
# And the voltage offset | |
voltoffset = float(scope.query(":CHAN1:OFFS?")[0]) | |
scope.write(":WAV:POIN:MODE RAW") | |
rawdata = scope.query(":WAV:DATA? CHAN1").encode('ascii')[10:] | |
data_size = len(rawdata) | |
sample_rate = scope.query(':ACQ:SAMP?')[0] | |
print('Data size:', data_size, "Sample rate:", sample_rate) | |
scope.write(":KEY:FORCE") | |
scope.close() | |
data = numpy.frombuffer(rawdata, 'B') | |
# Walk through the data, and map it to actual voltages | |
# This mapping is from Cibo Mahto | |
# First invert the data | |
data = data * -1 + 255 | |
# Now, we know from experimentation that the scope display range is actually | |
# 30-229. So shift by 130 - the voltage offset in counts, then scale to | |
# get the actual voltage. | |
data = (data - 130.0 - voltoffset/voltscale*25) / 25 * voltscale | |
# Now, generate a time axis. | |
time = numpy.linspace(timeoffset - 6 * timescale, timeoffset + 6 * timescale, num=len(data)) | |
# See if we should use a different time axis | |
if (time[-1] < 1e-3): | |
time = time * 1e6 | |
tUnit = "uS" | |
elif (time[-1] < 1): | |
time = time * 1e3 | |
tUnit = "mS" | |
else: | |
tUnit = "S" | |
# Plot the data | |
plot.plot(time, data) | |
plot.title("Oscilloscope Channel 1") | |
plot.ylabel("Voltage (V)") | |
plot.xlabel("Time (" + tUnit + ")") | |
plot.xlim(time[0], time[-1]) | |
plot.show() |
With my setup (Rigol DS1054Z on a Windows 10 PC) the command "scope.query(':CHAN1:SCAL?')" returns a string of the form 1.00000e-2. The command "float(scope.query(':CHAN1:SCAL?')[0])" therefore returns either the first digit, or crashes if the offset is negative (float can't convert "-" to a floating point decimal). The problem can be easily solved by simply removing the slice command [0] and converting the entire string to a float.
TLDR:
I used
"timeoffset = float(scope.query(":TIM:OFFS?"))
voltscale = float(scope.query(':CHAN1:SCAL?'))
voltoffset = float(scope.query(":CHAN1:OFFS?"))"
The mapping from binary to real voltages provided by Cibo Mahto did not work on my setup. The mapping that did work was:
"data1 = np.frombuffer(rawdata, 'B')
data = (data1 - 128.0) * 10 * voltscale / 256 - voltoffset"
The command "sample_rate = scope.query(':ACQ:SAMP?')[0]" returned a time-out error. As the sample_rate variable was not used elsewhere I simply removed it.
Does anyone know how to actually get 1 million points? I am only getting 1200.
@josiahsinclair I think 1200 is all you can get. BTW, your comments are useful!
My script crashed at line #39:
"rawdata = scope.query(":WAV:DATA? CHAN1").encode('ascii')[10:]"
The system complained that 0x97 was found at position 10 and was NOT ascii.I replaced the line with
This fixed the problem.scope.write(":WAV:DATA? CHAN1") #Request the data
rawdata = scope.read_raw() #Read the block of data
rawdata = rawdata[ 10 : ] #Drop the heading