0
\$\begingroup\$

I have been writing python automating scripts for an O-scope and an AWG. I am having issues sending Arbitrary waveforms to the AWG, the model is Siglent SDG2042X. I have the manual and it has an example using USB and the WVDT command. I am using ehternet and I am simply trying to use the example in the manual just to get things moving. The SCPI command has no effect on the AWG.

from Ethernet_Comm import Eth_Comm
from SCPI_Instruments import ScpiSDG2042X
import SDG2042X_Obj as sdg
import time
import binascii
import random

wave_data = [0xe000, 0xe000, 0xf000, 0xf000, 0x0000, 0x0000, 0x1000, 0x1000, 0x2000, 0x2000]
wave_points = []

for i in range(0,1):
    wave_points += wave_data
count=1

print(wave_points)
print(len(wave_points))

def create_wave_file():
"""create a file"""
f = open("wave4.bin", "wb")
for a in wave_points:
    b = hex(a)
    b = b[2:]
    len_b = len(b)
    if (0 == len_b):
        b = '0000'
    elif (1 == len_b):
        b = '000' + b
    elif (2 == len_b):
        b = '00' + b
    elif (3 == len_b):
        b = '0' + b
    b = b[2:4] + b[:2] #change big-endian to little-endian
    c = binascii.unhexlify(b)    #Hexadecimal integer to ASCii encoded string
    f.write(c)
    print(c)
f.close()



#     Set the Scope IP address and Port number

AWG_IP_ADDR = "192.168.1.230"
AWG_IP_PORT = 5024

awg = sdg.SDG2042X_Object(AWG_IP_ADDR, AWG_IP_PORT)
awg.open_connection()
awg.reset_inst()
#print(sc.get_id())

time.sleep(3)

create_wave_file() 

f = open("wave4.bin", "rb")    #wave4.bin is the waveform to be sent
data = f.read().decode("latin1")
print('write class:', type(data))
print('write bytes:',len(data))
print(data, type(data))
data.encode("latin1")
print(data, type(data))
awg.set_user_wave_params(channel_list[0], 'wave4', 2000.0, 4.0, 0.0, 0.0, data)    
awg.set_user_wave(channel_list[0], 'wave4')
f.close()

The first object "SDG2042_Obj" where the functions are sent

def set_user_wave_params(self, source, name, freq, amp, offset, phase, data):
    self.si.set_user_wave_params(source, name, freq, amp, offset, phase, data)

def set_user_wave(self, source, name):
    self.si.set_user_wave(source, name)

The next object "SCPI_INstruments"

def set_user_wave_params(self, source, name, freq, amp, offset, phase, data):
    self._send_qry(f"{source}:WVDT USER,{name}")

def set_user_wave(self, source, name):
    self._send_qry(f"{source}:ARWV NAME,{name}")

Totally lost here. I ultimately want to send my own waves that I create with a python script, but I need to get over this obstacle first. Here is the link to the manual

\$\endgroup\$
5
  • \$\begingroup\$ A link to the manual would be extremely helpful. \$\endgroup\$
    – Null
    Jul 6, 2022 at 20:36
  • \$\begingroup\$ Hi, please review your code snippets and fix the indentation to make it valid python code. \$\endgroup\$
    – polwel
    Jul 6, 2022 at 20:37
  • \$\begingroup\$ Your code is missing the crucial part where your are loading the library (VISA?) and instantiating the awg object. \$\endgroup\$
    – polwel
    Jul 6, 2022 at 20:39
  • \$\begingroup\$ I made the edits you guys requested. I didn't include every bit of code because it would a lot. I can communicate and do various setting on the AWG. My issue is the Arbitrary wave commands "WVDT" and "ARWV". The "ARWV" command works when setting builtin waves. The problem comes with setting custom waves. I have made your edits, and if you need more edits, please let me know so that you can take away the downvote \$\endgroup\$
    – Frank
    Jul 6, 2022 at 20:46
  • \$\begingroup\$ The problem isn't the instantiating of the device. I can communicate with the AWG. The problem is that the WVDT command just doesn't work \$\endgroup\$
    – Frank
    Jul 6, 2022 at 21:07

1 Answer 1

2
\$\begingroup\$

I'm not aware of the Python libraries you are using.

From the code, it looks as if it should at least upload the waveform. Have you checked the Stored Waveforms menu? It should contain a file called wave4.bin (if your instrument works the same as my SDG1032X).

The below code is a complete example and only uses standard Python functions.

create_wave_form() creates the waveform as a sequence of 16 bit signed integers (in little endian form). That's how they are transmitted even though my Siglent AWG has less resolution.

The BTWV command enables the instrument in burst mode. If you need something else, I think you can also use BSWV (basic wave) instead. This might be the part missing in your code.

import socket
import time
import sys
import binascii

def open_socket():
    try:
        s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        s.connect(('192.168.1.65', 5025))
        s.settimeout(0.5)
    except socket.error:
        print('Failed to connect')
        sys.exit()

    return s

def close_socket(s):
    s.close()
    time.sleep(.300)

def send_command(s, cmd):
    try:
        s.sendall(cmd)
        time.sleep(1)
    except socket.error:
        print('Command failed')
        sys.exit()

    try:
        response = s.recv(4096)
    except socket.timeout:
        response = b''

    return response

def create_wave_form():
    # digital waveform
    wave_points = [ 0, 0, 1, 0, 1, 1, 0, 1, 0, 0, 1, 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 0, 1, 1, 0, 0, 1, 0, 1, 0, 1, 0, 0, 0 ]
    # scale up to 16 bit signed integer, independent of AWGs resolution 
    data = b''
    for a in wave_points:
        for i in range(0, 100):
            data += (-32768 if a == 0 else 32767).to_bytes(2, 'little', signed=True)
    return data

def main():
    s = open_socket()
    qstr = send_command(s, b'*IDN?\n')
    print(qstr.decode('utf-8'))
    data = create_wave_form()
    qstr = send_command(s, b"C1:WVDT WVNM,abc,FREQ,30000.0,AMPL,1.0,OFST,0.5,PHASE,0.0,WAVEDATA," + data + b'\n')
    print(qstr.decode('utf-8'))
    qstr = send_command(s, b'C1:ARWV NAME,abc\n')
    print(qstr.decode('utf-8'))
    qstr = send_command(s, b'C1:BTWV STATE,ON,PRD,0.02,STPS,0,TRSR,INT,DLAY,0\n')
    print(qstr.decode('utf-8'))
    close_socket(s)

if __name__ == '__main__':
    proc = main()

Addition

The above code mixes the generation of the specific sample data and the binary encoding into wavedata. A more general approach is found below. The function takes an array of samples, each sample in the range between -1.0 and 1.0:

def waveform_data(samples):
    data = b''
    for s in samples:
        data += int(round(s * 32768 if s < 0 else s * 32767)).to_bytes(2, 'little', signed=True)
    return data
\$\endgroup\$
5
  • \$\begingroup\$ Thank you for your response. I tried your code and....sure enough I am an idiot!!! hahahaha. I can send your wave to the AWG. So now I just need to incorporate what you did and get my wave sent to the unit. My overall problem is that this is pretty far out of my skillset, but just have to keep moving forward. \$\endgroup\$
    – Frank
    Jul 6, 2022 at 21:40
  • \$\begingroup\$ I have a question. Keep in mind that my coding skills are like a baby trying to eat with a spoon, sometimes food makes it in my mouth. What is this line doing data += (-32768 if a == 0 else 32767).to_bytes(2, 'little', signed=True) \$\endgroup\$
    – Frank
    Jul 6, 2022 at 22:40
  • \$\begingroup\$ The original waveform is digital, either 0 or 1. It needs to be translated to the minimum value for 0 and maximum value for 1. For a 16 bit signed integer, the minimum is -32768 and the maximum is 32767. The line first converts 0/1 to -32768/32767, then converts it into 2 bytes in little endian format and finally appends it to the data byte array. \$\endgroup\$
    – Codo
    Jul 7, 2022 at 5:12
  • \$\begingroup\$ Also see my addition abvoe \$\endgroup\$
    – Codo
    Jul 7, 2022 at 7:34
  • \$\begingroup\$ Ah I see, that actually makes total sense. I should have taken more CompSci classes instead of E&M classes in grad school. Sure I can do some cool integrals, but when it comes to this practical stuff I bang my head against the wall. Anyways, thank you for the time and effort in helping with this \$\endgroup\$
    – Frank
    Jul 7, 2022 at 16:31

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.