DualDAC example


This ipython notebook demonstrates how to connect and program Aivon dualDAC metrological dual signal source using python. GPIB connection relies on python visa-library. Make sure your installation works.


In [ ]:
# these are the needed libraries.

import visa
import time
# the following are optional packages but recommended in python workflow
#from numpy import *
#from pylab import *

#from IPython.core.pylabtools import figsize
#figsize(15, 11)

%matplotlib inline
rm = visa.ResourceManager()
rm.list_resources() # this command shoould list dualDAC for example as u'GPIB0::10::INSTR' among other instruments

In [ ]:
# make instrument references and do simple test
dualDAC = rm.open_resource(u'GPIB0::10::INSTR', send_end=True, read_termination='',write_termination = '')
dualDAC.write(u"*IDN?")
print(dualDAC.read()) # should respond for example "Aivon/MIKES Sinewave Generator"

Below are the main functions that are used to make command strings for dualDAC.


In [ ]:
# functions for writing to dualDAC, kind of library

# from number (-1,1) to (65538,0)
def num2code(num):
    res = int(int((2**31-1*0)-num*2**31)>>16) # CreateSine.vi, vahennys poistettu (*0)
    if (res < 0) : return 0
    if (res > (2**16-1)) : return (2**16-1)
    return res 

# from (0,1) to (0,2**20-1) (this is for dualDAC2)
def num2code20(num):
    res = ceil(num*(2**20-1.0))
    return res

# hex 5 byte representation of 20bit number (this is for dualDAC2)
def code2hex20(num):
    return  "%05X" % num

# writes DAC multiplier (this is for dualDAC2)
def write_20bitDAC(string, channel=1):
    if (channel == 1): 
        dualDAC.write(u"SETDAC1")
    else:
        dualDAC.write(u"SETDAC2")
    dualDAC.write(string)

# returns strings numbers and codes for sinusoidal
def codes_sine(N, amp, phase=0.0):
    Ns = range(N)
    numbers = [] # array of actual values of samples
    codes = [] # array of actual codes of samples
    strings = [] # array of hexadecimal 4 byte strings representation of the codes
    for n in Ns:        
        numbers.append(amp*sin(2.0*pi*n/(1.0*N)-phase*pi/180.0)) # make the sinusoid
        codes.append(num2code(numbers[-1]))
        strings.append("%04X" % num2code(numbers[-1]))
        #print string
    return strings, numbers, codes

# returns codes for constant(same as codes_sine but produces constant output value arrays)
# takes a number in
def codes_const(N, const):
    Ns = range(N)
    numbers = []
    codes = []
    strings = []
    for n in Ns:        
        numbers.append(const)
        codes.append(num2code(numbers[-1]))
        strings.append("%04X" % num2code(numbers[-1]))
        #print string
    return strings, numbers, codes      

# returns codes for constant(same as codes_sine but produces constant output value arrays)
# takes a code in
def codes_from_num(N, const):
    Ns = range(N)
    numbers = []
    codes = []
    strings = []
    for n in Ns:        
        numbers.append(const)
        codes.append(const)
        strings.append("%04X" % const)
        #print string
    return strings, numbers, codes 

# builds code packet from string arrays that can be sent to dualDAC with LDATA command
def get_code_packets(strings1, strings2):
    packets = []
    packets.append("")
    counter = 0
    for s in zip(strings1, strings2):
        if (counter<8):
            packets[-1] += s[0] + s[1]
            counter += 1
        else:
            packets.append(s[0] + s[1]) 
            counter = 1;   
    if (counter == 8): 
        return packets # return if multiple of 8
    while (counter < 8): # fill 
        packets[-1] += "00000000" 
        counter +=1
    return packets

Finally a example session using definition and code above


In [ ]:
# test to write data to dualDAC

N = 32 # number of samples per cycle
amp1 = 1.0 # amplitude for channel 1
amp2 = 1.0 # amplitude for channel 2
phase1 = 0.0 # phase for channel 1
phase2 = 180.0 # phase for channel 2
const2 = 1.0 # constant 

# make strings data (uncomment commented for constant values)
strings1, numbers1, codes1 = codes_sine(N, amp1, phase1) 
#strings1, numbers1, codes1 = codes_from_num(N, 10000)
strings2, numbers2, codes2 = codes_sine(N, amp2, phase2) 
#strings2, numbers2, codes2 =  codes_from_num(N, 10000)

# build packets
packets = get_code_packets(strings1,strings2)

# set number of samples
dualDAC.write(u"SETN")
dualDAC.write(u"%i"%N)

# set actual data to the device
dualDAC.write(u"LDATA")
for pack in packets:
    dualDAC.write(pack)
    time.sleep(0.2)
""" # for dualDAC2    
# write to 20 bit DACS
dac20bit_code_ch1 = num2code20(0.201)
dac20bit_code_ch2 = num2code20(0.41)
dac20bit_hexstr_ch1 = '80000' #code2hex20(dac20bit_code_ch1)
dac20bit_hexstr_ch2 = '80000' #code2hex20(dac20bit_code_ch2)
write_20bitDAC(dac20bit_hexstr_ch1, channel=1)
write_20bitDAC(dac20bit_hexstr_ch2, channel=2)
print "Ch1 code %i hex:%s       Ch2 code %i hex:%s"%(dac20bit_code_ch1, dac20bit_hexstr_ch1, dac20bit_code_ch2, dac20bit_hexstr_ch2)
"""