Jump to content

bharathb

Newcomers
  • Posts

    1
  • Joined

  • Last visited

bharathb's Achievements

Newbie

Newbie (1/4)

0

Reputation

  1. I'm not sure the project I'm trying to build is very unique, but I've been having trouble getting a python script I've written up using the sdk to function as desired. Here are my requirements: - Wavegen should play particular waveforms imported from csv files. Number of samples is ~80000, sample rate 12kHz - scope should operate in record mode and save the scope data from both channels to a/separate csv files. Similarly collect 80000 samples at 12kHz. - all channels of scope and wavegen should be triggered simultaneously. - ideally would want this as a python script I can invoke from Matlab to integrate with the rest of my workflow, with the required args. (This has been working fine) I've used bits and pieces from the different examples posted. When using a single device and triggering the scope channels with trigsrcAnalogOut1, with the existing logic in the examples for Record/play, I get arbitrary delays between the scope channel compared to the input waveform. with synchronization setup using the relevant examples, and using the second device purely to generate the external trigger signal for the main AD device, I see 4096 samples of delay. I'm guessing this is because of the different sizes of the buffers between scope(8k) and wavegen (4k) instruments. I could in theory account for this 4096 sample delay if it was consistent, but I can get up to 4200 samples of delay if I run the script from a slower computer. The application I'm using this for does not allow synchronization in post processing because there are inherently unknown delays between the input and output. What am I doing wrong here? The files below are what I used: data_acq2.py - single device, scope channels triggered from analog out from ctypes import * from dwfconstants import * import math import time import matplotlib.pyplot as plt import sys import numpy as np import csv if sys.platform.startswith("win"): dwf = cdll.LoadLibrary("dwf.dll") elif sys.platform.startswith("darwin"): dwf = cdll.LoadLibrary("/Library/Frameworks/dwf.framework/dwf") else: dwf = cdll.LoadLibrary("libdwf.so") #declare ctype variables hdwf = c_int() sts = c_byte() hzAcq_int = int(sys.argv[1]) hzAcq = c_double(hzAcq_int) rate = hzAcq nSamples = int(sys.argv[2]) sRun = 1.0*nSamples/hzAcq.value # Load Play data filename1 = sys.argv[3] filename2 = sys.argv[4] play1 = np.genfromtxt(filename1,dtype=float,delimiter='',skip_header=0) play2 = np.genfromtxt(filename2,dtype=float,delimiter='',skip_header=0) # AnalogOut expects double normalized to +/-1 value play1_max = play1.max() play1 /= play1_max data1 = (c_double * nSamples)(*play1) play2_max = play2.max() play2 /= play2_max data2 = (c_double * nSamples)(*play2) #print(DWF version version = create_string_buffer(16) dwf.FDwfGetVersion(version) # print("DWF Version: "+str(version.value)) #open device # print("Opening first device") if dwf.FDwfDeviceOpen(c_int(-1), byref(hdwf)) != 1 or hdwf.value == hdwfNone.value: szerr = create_string_buffer(512) dwf.FDwfGetLastErrorMsg(szerr) print(str(szerr.value)) print("failed to open device") quit() iRecord = 0 record1 = (c_double*nSamples)() record2 = (c_double*nSamples)() #set up acquisition sRecord = nSamples/hzAcq.value dwf.FDwfAnalogInChannelEnableSet(hdwf, c_int(0), c_int(1)) # channel 1 dwf.FDwfAnalogInChannelEnableSet(hdwf, c_int(1), c_int(1)) # channel 2 dwf.FDwfAnalogInChannelRangeSet(hdwf, c_int(-1), c_double(5.0)) dwf.FDwfAnalogInChannelOffsetSet(hdwf, c_int(-1), c_double(0)) dwf.FDwfAnalogInAcquisitionModeSet(hdwf, acqmodeRecord) dwf.FDwfAnalogInFrequencySet(hdwf, c_double(hzAcq.value)) dwf.FDwfAnalogInRecordLengthSet(hdwf, c_double(sRecord)) #set up trigger dwf.FDwfAnalogInTriggerAutoTimeoutSet(hdwf, c_double(0)) # 10 second auto trigger timeout # dwf.FDwfAnalogInTriggerSourceSet(hdwf, trigsrcDetectorAnalogIn) # trigsrcDetectorAnalogIn dwf.FDwfAnalogInTriggerSourceSet(hdwf, trigsrcAnalogOut1) # trigsrcDetectorAnalogIn # dwf.FDwfAnalogInTriggerPositionSet(hdwf, c_double(nSamples/2/rate.value)) # -0.25 = trigger at 25% dwf.FDwfAnalogInTriggerPositionSet(hdwf, c_double(0)) # -0.25 = trigger at 25% dwf.FDwfAnalogInTriggerTypeSet(hdwf, c_int(0)) # trigtypeEdge dwf.FDwfAnalogInTriggerChannelSet(hdwf, trigsrcDetectorAnalogIn) # AnalogOut1 # dwf.FDwfAnalogInTriggerChannelSet(hdwf, c_int(-1)) dwf.FDwfAnalogInTriggerLevelSet(hdwf, c_double(0)) # 0V dwf.FDwfAnalogInTriggerHysteresisSet(hdwf, c_double(0.01)) # 0.001V dwf.FDwfAnalogInTriggerConditionSet(hdwf, c_int(0)) # trigcondRisingPositive # #wait at least 2 seconds for the offset to stabilize time.sleep(2) # print("Starting oscilloscope") dwf.FDwfAnalogInConfigure(hdwf, c_int(0), c_int(1)) # print("Playing file...") iPlay = 0 channel = c_int(-1) # AWG 1 & 2 channel1 = c_int(0) # AWG 1 channel2 = c_int(1) # AWG 2 dwf.FDwfAnalogOutNodeEnableSet(hdwf, channel, 0, c_int(1)) dwf.FDwfAnalogOutNodeFunctionSet(hdwf, channel, 0, funcPlay) dwf.FDwfAnalogOutRepeatSet(hdwf, channel, c_int(1)) dwf.FDwfAnalogOutRunSet(hdwf, channel, c_double(sRun)) dwf.FDwfAnalogOutNodeFrequencySet(hdwf, channel, 0, rate) dwf.FDwfAnalogOutNodeAmplitudeSet(hdwf, channel1, 0, c_double(play1_max)) dwf.FDwfAnalogOutNodeAmplitudeSet(hdwf, channel2, 0, c_double(play2_max)) # Trigger channel2 Output trigger dwf.FDwfAnalogOutTriggerSourceSet(hdwf, channel2, trigsrcAnalogOut1) dwf.FDwfAnalogOutTriggerSlopeSet(hdwf, channel, 2) # prime the buffer with the first chunk of data cBuffer = c_int(0) dwf.FDwfAnalogOutNodeDataInfo(hdwf, channel, 0, 0, byref(cBuffer)) if cBuffer.value > nSamples : cBuffer.value = nSamples dwf.FDwfAnalogOutNodeDataSet(hdwf, channel1, 0, data1, cBuffer) dwf.FDwfAnalogOutNodeDataSet(hdwf, channel2, 0, data2, cBuffer) iPlay += cBuffer.value dwf.FDwfAnalogOutConfigure(hdwf, channel, c_int(1)) iSample = 0 dataLost = c_int(0) dataFree = c_int(0) dataAvailable = c_int(0) dataCorrupted = c_int(0) sts = c_ubyte(0) totalLost = 0 totalCorrupted = 0 # loop to send out and read in data chunks while iRecord < nSamples : if dwf.FDwfAnalogOutStatus(hdwf, channel, byref(sts)) != 1: # handle error print("Error") szerr = create_string_buffer(512) dwf.FDwfGetLastErrorMsg(szerr) print(szerr.value) break # play, analog out data chunk if sts.value == DwfStateRunning.value and iPlay < nSamples : # running and more data to stream dwf.FDwfAnalogOutNodePlayStatus(hdwf, channel, 0, byref(dataFree), byref(dataLost), byref(dataCorrupted)) totalLost += dataLost.value totalCorrupted += dataCorrupted.value if iPlay + dataFree.value > nSamples : # last chunk might be less than the free buffer size dataFree.value = nSamples - iPlay if dataFree.value > 0 : if dwf.FDwfAnalogOutNodePlayData(hdwf, channel1, 0, byref(data1, iPlay*8), dataFree) != 1: # offset for double is *8 (bytes) print("Error") break if dwf.FDwfAnalogOutNodePlayData(hdwf, channel2, 0, byref(data2, iPlay*8), dataFree) != 1: # offset for double is *8 (bytes) print("Error") break iPlay += dataFree.value # handle error if dwf.FDwfAnalogInStatus(hdwf, c_int(1), byref(sts)) != 1: print("FDwfAnalogInStatus Error") szerr = create_string_buffer(512) dwf.FDwfGetLastErrorMsg(szerr) print(szerr.value) break # record, analog in data chunk if sts.value == DwfStateRunning.value or sts.value == DwfStateDone.value : # recording or done dwf.FDwfAnalogInStatusRecord(hdwf, byref(dataAvailable), byref(dataLost), byref(dataCorrupted)) iRecord += dataLost.value totalLost += dataLost.value totalCorrupted += dataCorrupted.value if dataAvailable.value > 0 : if iRecord+dataAvailable.value > nSamples : dataAvailable = c_int(nSamples-iRecord) dwf.FDwfAnalogInStatusData2(hdwf, c_int(0), byref(record1, sizeof(c_double)*iRecord), c_int(0), dataAvailable) # get channel 1 data chunk, offset for 16bit data is 2* dwf.FDwfAnalogInStatusData2(hdwf, c_int(1), byref(record2, sizeof(c_double)*iRecord), c_int(0), dataAvailable) # get channel 2 data chunk iRecord += dataAvailable.value # print("Lost: "+str(totalLost)) # print("Corrupted: "+str(totalCorrupted)) print("done") dwf.FDwfAnalogOutReset(hdwf, channel) dwf.FDwfDeviceClose(hdwf) if iSample != 0 : record1 = record1[iSample:]+record1[:iSample] record2 = record2[iSample:]+record2[:iSample] ch1_save = sys.argv[5] ch2_save = sys.argv[6] f = open(ch1_save, "w") for v in record1: f.write("%s\n" % v) f.close() f = open(ch2_save, "w") for v in record2: f.write("%s\n" % v) f.close() # plt.plot(np.fromiter(record1, dtype = float), color='orange') # plt.plot(np.fromiter(record2, dtype = float), color='blue') # plt.show() data_acq_rev3.py - two devices, device 0 acts as the trigger source for device 1 which runs the scope and wavegen instruments all triggered by external trigger 1 (the T1 ports on the two devices are connected) from ctypes import * from dwfconstants import * import math import time import matplotlib.pyplot as plt import sys import numpy as np import csv if sys.platform.startswith("win"): dwf = cdll.LoadLibrary("dwf.dll") elif sys.platform.startswith("darwin"): dwf = cdll.LoadLibrary("/Library/Frameworks/dwf.framework/dwf") else: dwf = cdll.LoadLibrary("libdwf.so") #declare ctype variables hdwf = c_int() rghdwf = [] cDevices = c_int() sts = c_byte() hzAcq_int = int(sys.argv[1]) hzAcq = c_double(hzAcq_int) rate = hzAcq nSamples = int(sys.argv[2]) sRun = 1.0*nSamples/hzAcq.value # Load Play data filename1 = sys.argv[3] filename2 = sys.argv[4] play1 = np.genfromtxt(filename1,dtype=float,delimiter='',skip_header=0) play2 = np.genfromtxt(filename2,dtype=float,delimiter='',skip_header=0) # AnalogOut expects double normalized to +/-1 value play1_max = play1.max() play1 /= play1_max data1 = (c_double * nSamples)(*play1) play2_max = play2.max() play2 /= play2_max data2 = (c_double * nSamples)(*play2) iRecord = 0 record1 = (c_double*nSamples)() record2 = (c_double*nSamples)() #set up acquisition period sRecord = nSamples/hzAcq.value #print(DWF version version = create_string_buffer(16) dwf.FDwfGetVersion(version) # print("DWF Version: "+str(version.value)) # declare string variables devicename = create_string_buffer(64) serialnum = create_string_buffer(16) # enumerate connected devices dwf.FDwfEnum(c_int(0), byref(cDevices)) if cDevices.value == 0: print("No device found") dwf.FDwfDeviceCloseAll() sys.exit(0) # open devices for iDevice in range(0, cDevices.value): dwf.FDwfEnumDeviceName(c_int(iDevice), devicename) dwf.FDwfEnumSN(c_int(iDevice), serialnum) print("------------------------------") print("Device "+str(iDevice+1)+" : \t" + str(devicename.value) + "\t" + str(serialnum.value)) dwf.FDwfDeviceOpen(c_int(iDevice), byref(hdwf)) if hdwf.value == 0: szerr = create_string_buffer(512) dwf.FDwfGetLastErrorMsg(szerr) print(str(szerr.value)) dwf.FDwfDeviceCloseAll() sys.exit(0) rghdwf.append(hdwf.value) if iDevice == 0: dwf.FDwfAnalogInFrequencySet(hdwf, c_double(hzAcq.value)) dwf.FDwfAnalogInChannelEnableSet(hdwf, c_int(0), c_int(1)) dwf.FDwfAnalogInChannelOffsetSet(hdwf, c_int(0), c_double(0)) dwf.FDwfAnalogInChannelRangeSet(hdwf, c_int(0), c_double(5)) dwf.FDwfAnalogInAcquisitionModeSet(hdwf, acqmodeRecord) dwf.FDwfAnalogInRecordLengthSet(hdwf, c_double(sRecord)) dwf.FDwfAnalogInTriggerPositionSet(hdwf, c_double(nSamples/2/rate.value)) # 0 is middle, 4/10 = 10% dwf.FDwfAnalogInTriggerSourceSet(hdwf, trigsrcPC) # 11 = trigsrcExternal1, T1 dwf.FDwfAnalogInConfigure(hdwf, c_int(1), c_int(0)) # trigger output on external trigger 2 of analog-out (AWG) 1 # on first device drive External T1 (0) with trigsrcPC (1) # expects T1 of each device to be connected together for synchronization dwf.FDwfDeviceTriggerSet(hdwf, c_int(0), c_byte(1)) # 0 = T1 , 1 = trigsrcPC, 7 = trigsrcAnalogOut1 dwf.FDwfAnalogOutTriggerSourceSet(hdwf, c_int(0), trigsrcPC) # 11 = trigsrcExternal1 dwf.FDwfAnalogOutNodeEnableSet(hdwf, c_int(0), c_int(0), c_int(1)) dwf.FDwfAnalogOutNodeFunctionSet(hdwf, c_int(0), c_int(0), c_byte(1)) # funcSine dwf.FDwfAnalogOutNodeFrequencySet(hdwf, c_int(0), c_int(0), c_double(100)) dwf.FDwfAnalogOutNodeAmplitudeSet(hdwf, c_int(0), c_int(0), c_double(1.5)) dwf.FDwfAnalogOutNodeOffsetSet(hdwf, c_int(0), c_int(0), c_double(0)) else: dwf.FDwfAnalogInFrequencySet(hdwf, c_double(hzAcq.value)) dwf.FDwfAnalogInChannelEnableSet(hdwf, c_int(-1), c_int(1)) dwf.FDwfAnalogInChannelOffsetSet(hdwf, c_int(-1), c_double(0)) dwf.FDwfAnalogInChannelRangeSet(hdwf, c_int(-1), c_double(5)) dwf.FDwfAnalogInAcquisitionModeSet(hdwf, acqmodeRecord) dwf.FDwfAnalogInRecordLengthSet(hdwf, c_double(sRecord)) dwf.FDwfAnalogInTriggerPositionSet(hdwf, c_double(nSamples/2/rate.value)) # 0 is middle, 4/10 = 10% # dwf.FDwfAnalogInTriggerPositionSet(hdwf, c_double(0)) # 0 is middle, 4/10 = 10% # trigger source external trigger 1 dwf.FDwfAnalogInTriggerSourceSet(hdwf, c_byte(11)) # 11 = trigsrcExternal1, T1 dwf.FDwfAnalogInConfigure(hdwf, c_int(1), c_int(0)) iPlay = 0 channel = c_int(-1) # AWG 1 & 2 channel1 = c_int(0) # AWG 1 channel2 = c_int(1) # AWG 2 dwf.FDwfAnalogOutNodeEnableSet(hdwf, channel, 0, c_int(1)) dwf.FDwfAnalogOutNodeFunctionSet(hdwf, channel, 0, funcPlay) dwf.FDwfAnalogOutRepeatSet(hdwf, channel, c_int(1)) dwf.FDwfAnalogOutRunSet(hdwf, channel, c_double(sRun)) dwf.FDwfAnalogOutNodeFrequencySet(hdwf, channel, 0, rate) dwf.FDwfAnalogOutNodeAmplitudeSet(hdwf, channel1, 0, c_double(play1_max)) dwf.FDwfAnalogOutNodeAmplitudeSet(hdwf, channel2, 0, c_double(play2_max)) # Trigger channel Output trigger dwf.FDwfAnalogOutTriggerSourceSet(hdwf, channel, c_byte(11)) # 11 = trigsrcExternal1, T1 # prime the buffer with the first chunk of data cBuffer = c_int(0) dwf.FDwfAnalogOutNodeDataInfo(hdwf, channel, 0, 0, byref(cBuffer)) if cBuffer.value > nSamples : cBuffer.value = nSamples dwf.FDwfAnalogOutNodeDataSet(hdwf, channel1, 0, data1, cBuffer) dwf.FDwfAnalogOutNodeDataSet(hdwf, channel2, 0, data2, cBuffer) iPlay += cBuffer.value dwf.FDwfAnalogOutConfigure(hdwf, channel, c_int(1)) # #wait at least 2 seconds for the offset to stabilize time.sleep(3) # print("Starting oscilloscope") # start analog-in (Scope) for iDevice in range(len(rghdwf)): hdwf.value = rghdwf[iDevice] dwf.FDwfAnalogInConfigure(hdwf, c_int(0), c_int(1)) # wait for the last configured device to be armed too hdwf.value = rghdwf[cDevices.value-1] while True: dwf.FDwfAnalogInStatus(hdwf, c_int(0), byref(sts)) if sts.value == 1 : # DwfStateArmed break # print("Playing file...") iSample = 0 dataLost = c_int(0) dataFree = c_int(0) dataAvailable = c_int(0) dataCorrupted = c_int(0) sts = c_ubyte(0) totalLost = 0 totalCorrupted = 0 hdwf.value = rghdwf[0] dwf.FDwfAnalogOutConfigure(hdwf, c_int(0), c_int(1)) # start analog-out (AWG) 1 of first device # generate trigger signal dwf.FDwfDeviceTriggerPC(hdwf) # Select, play and colelct from main device hdwf.value = rghdwf[1] # loop to send out and read in data chunks while iRecord < nSamples : if dwf.FDwfAnalogOutStatus(hdwf, channel, byref(sts)) != 1: # handle error print("Error") szerr = create_string_buffer(512) dwf.FDwfGetLastErrorMsg(szerr) print(szerr.value) break # play, analog out data chunk if sts.value == DwfStateRunning.value and iPlay < nSamples : # running and more data to stream dwf.FDwfAnalogOutNodePlayStatus(hdwf, channel, 0, byref(dataFree), byref(dataLost), byref(dataCorrupted)) totalLost += dataLost.value totalCorrupted += dataCorrupted.value if iPlay + dataFree.value > nSamples : # last chunk might be less than the free buffer size dataFree.value = nSamples - iPlay if dataFree.value > 0 : if dwf.FDwfAnalogOutNodePlayData(hdwf, channel1, 0, byref(data1, iPlay*8), dataFree) != 1: # offset for double is *8 (bytes) print("Error") break if dwf.FDwfAnalogOutNodePlayData(hdwf, channel2, 0, byref(data2, iPlay*8), dataFree) != 1: # offset for double is *8 (bytes) print("Error") break iPlay += dataFree.value # handle error if dwf.FDwfAnalogInStatus(hdwf, c_int(1), byref(sts)) != 1: print("FDwfAnalogInStatus Error") szerr = create_string_buffer(512) dwf.FDwfGetLastErrorMsg(szerr) print(szerr.value) break # record, analog in data chunk if sts.value == DwfStateRunning.value or sts.value == DwfStateDone.value : # recording or done dwf.FDwfAnalogInStatusRecord(hdwf, byref(dataAvailable), byref(dataLost), byref(dataCorrupted)) iRecord += dataLost.value totalLost += dataLost.value totalCorrupted += dataCorrupted.value if dataAvailable.value > 0 : if iRecord+dataAvailable.value > nSamples : dataAvailable = c_int(nSamples-iRecord) dwf.FDwfAnalogInStatusData2(hdwf, c_int(0), byref(record1, sizeof(c_double)*iRecord), c_int(0), dataAvailable) # get channel 1 data chunk, offset for 16bit data is 2* dwf.FDwfAnalogInStatusData2(hdwf, c_int(1), byref(record2, sizeof(c_double)*iRecord), c_int(0), dataAvailable) # get channel 2 data chunk iRecord += dataAvailable.value # print("Lost: "+str(totalLost)) # print("Corrupted: "+str(totalCorrupted)) print("done") dwf.FDwfAnalogOutReset(hdwf, channel) dwf.FDwfDeviceCloseAll() if iSample != 0 : record1 = record1[iSample:]+record1[:iSample] record2 = record2[iSample:]+record2[:iSample] ch1_save = sys.argv[5] ch2_save = sys.argv[6] f = open(ch1_save, "w") for v in record1: f.write("%s\n" % v) f.close() f = open(ch2_save, "w") for v in record2: f.write("%s\n" % v) f.close() # plt.plot(np.fromiter(record1, dtype = float), color='orange') # plt.plot(np.fromiter(record2, dtype = float), color='blue') # plt.show() I'd also like to say that I've implemented this very easily on the GUI itself, and don't have any such delay issues. But I can't use the GUI for now since I can't automate it with the rest of my workflow on Matlab. I understand there's the WaveForms scripter as well, which might be more appropriate for this implementation, but I haven't worked with JS before, so haven't explored that yet. If you think that's a better way to run this, please let me know.
×
×
  • Create New...