send numpy/csv data to RIGOL DG4202 arbitrary waveform generator via LAN

Another very short one.

At work we have acquired a mid priced arbitrary function/waveform generator, the DG4202 by RIGOL (DG4000 series).
It has a USB and a network interface. Since I am an automation geek, the most interesting thing for me was:

How can I push some csv data or numpy vector to the device via network connection?

We’re going to use python3. Here’s what worked for me:

install necessary hardware communication module:

sudo apt-get update
sudo apt-get install python3-pip python3-numpy python3-scipy
sudo pip3 install update
sudo pip3 install setuptools
sudo pip3 install python-vxi11

I tried to do it with the pyvisa module first, which seemed to work just as well. However I ran into a limitation of the message size, which severely limited the amount of samples I could transmit of one waveform. I tried it again with vxi11, the problem was gone.

Activate/configure LAN on your AWG (press “Utility” button, then “I/O Config”->”LAN”). As you can see it conveniently displays the VISA/VXI11 device string:

Let’s make a small script to generate three periods of a sine wave as a test signal, and send it to the AWG:

#!/usr/bin/env python3

import numpy as np
import vxi11

# change the IP address to your instrument's IP
inst = vxi11.Instrument('TCPIP0::192.168.43.125::INSTR')
print(inst.ask('*IDN?'))


samples = 1000
x=np.linspace(0,6*np.pi,samples)
y=np.sin(x)


val_str = ",".join(map(str,y))

inst.write("TRACE:DATA VOLATILE,"+ val_str)

### you can also automate some other stuff
### see the programmers manual of the RIGOL DG4000 series
inst.write("OUTPUT2 OFF")
inst.write("OUTPUT1 ON")

print(inst.ask("OUTPUT1?"))
print(inst.ask("OUTPUT2?"))


If you are not familiar with python and numpy and just want a tool to send the contents of a csv data file to the device (e.g. “my_data.csv”, x/y value pairs, separated by tabs), then this is for you:

#!/usr/bin/env python3

import numpy as np
import vxi11
from scipy import interpolate

def resample(target_x,data_x,data_y):
  f = interpolate.interp1d(data_x,data_y,bounds_error=False, fill_value=0.)
  out_x = target_x
  out_y = f(target_x)
  return (out_x,out_y)
 
# change the IP address to your instrument's IP
inst = vxi11.Instrument('TCPIP0::192.168.43.125::INSTR')
print(inst.ask('*IDN?'))

# read in txt/csv file to numpy array
my_data = np.loadtxt("my_data.csv")

data_x = my_data[:,0]
data_y = my_data[:,1]

# number of target samples
samples = 1000
x=np.linspace(0,data_x[-1],samples)

# interpolate in case your csv time steps are not equal size,
# for example if it is exported by LTSpice
dummy, y = resample(x,data_x,data_y)

# normalize to maximum (pos/neg) amplitude
y = y/max( np.array([max(y), abs(min(y))]) )

val_str = ",".join(map(str,y))

inst.write("TRACE:DATA VOLATILE,"+ val_str)

See the device’s programming guide for automation command reference:

http://int.rigol.com/Product/Index/19

(with the manual I had some issue, my archive manager would not extract the .rar archive. However on the command line with “unrar e <file.rar>” it worked. The manual is a .chm file, some windows help document format. For me this could be viewed under linux with wine, without problems)

In this last example, we use both channels, generate two individual waveforms for them, set the sample period, set low and high voltage values and put both channels in burst mode, all remote:

#!/usr/bin/env python3
 
import numpy as np
import vxi11
from numpy import pi
 
# change the IP address to your instrument's IP
inst = vxi11.Instrument('TCPIP0::192.168.43.125::INSTR')
print(inst.ask('*IDN?'))

period = 2e-6 # 2us

v_high_1 = 0.5
v_low_1 = -1*v_high_1

v_high_2 = 2.5
v_low_2 = -1*v_high_2
 
samples = 2**12 # 4096 samples
time=np.linspace(0,period,samples)


y2=np.sin(time/period*2**5*2*pi)**2
y1=-1+2*(time >= 10e-9)
 
 
val_str_1 = ",".join(map(str,y1))
val_str_2 = ",".join(map(str,y2))
 
 
### you can also automate some other stuff
### see the programmers manual of the RIGOL DG4000 series
print(inst.ask("OUTPUT1?"))
print(inst.ask("OUTPUT2?"))

inst.write("OUTPUT1 ON")
inst.write("SOURCE1:TRACE:DATA VOLATILE,"+ val_str_1)
inst.write("SOURCE1:VOLTAGE:UNIT VPP")
print(inst.ask("SOURCE1:VOLTAGE:UNIT?"))
inst.write("SOURCE1:VOLTAGE:LOW {:f}".format(v_low_1))
inst.write("SOURCE1:VOLTAGE:HIGH {:f}".format(v_high_1))
inst.write("SOURCE1:PERIOD {:f}".format(period))
inst.write("SOURCE1:BURSt ON")
print(inst.ask("SOURCE1:BURST?"))
inst.write("SOURCE1:BURSt:MODE TRIGgered")
print(inst.ask("SOURCE1:BURST:MODE?"))

inst.write("OUTPUT2 ON")
inst.write("SOURCE2:TRACE:DATA VOLATILE,"+ val_str_2)
inst.write("SOURCE2:VOLTAGE:UNIT VPP")
print(inst.ask("SOURCE2:VOLTAGE:UNIT?"))
inst.write("SOURCE2:VOLTAGE:LOW {:f}".format(v_low_2))
inst.write("SOURCE2:VOLTAGE:HIGH {:f}".format(v_high_2))
inst.write("SOURCE2:PERIOD {:f}".format(period))
inst.write("SOURCE2:BURSt ON")
inst.write("SOURCE2:PERIOD {:f}".format(period))
print(inst.ask("SOURCE2:BURST?"))
inst.write("SOURCE2:BURSt:MODE TRIGgered")
print(inst.ask("SOURCE2:BURST:MODE?"))

 

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

This site uses Akismet to reduce spam. Learn how your comment data is processed.