diff --git a/instruments/ADwin/ADbasic_8Read_4Write.BAK b/instruments/ADwin/ADbasic_8Read_4Write.BAK index 4e3523f..7c30fa4 100644 --- a/instruments/ADwin/ADbasic_8Read_4Write.BAK +++ b/instruments/ADwin/ADbasic_8Read_4Write.BAK @@ -11,18 +11,19 @@ ' Info_Last_Save = DARWIN-PC Darwin-PC\PNPNteam '
#Include ADwinGoldII.inc -DIM DATA_1[40000] AS LONG AS FIFO -DIM DATA_2[40000] AS LONG AS FIFO -DIM DATA_3[40000] AS LONG AS FIFO -DIM DATA_4[40000] AS LONG AS FIFO -DIM DATA_5[40000] AS LONG AS FIFO -DIM DATA_6[40000] AS LONG AS FIFO -DIM DATA_7[40000] AS LONG AS FIFO -DIM DATA_8[40000] AS LONG AS FIFO -DIM DATA_9[40000] AS LONG AS FIFO -DIM DATA_10[40000] AS LONG AS FIFO -DIM DATA_11[40000] AS LONG AS FIFO -DIM DATA_12[40000] AS LONG AS FIFO +DIM DATA_1[40003] AS LONG AS FIFO +DIM DATA_2[40003] AS LONG AS FIFO +DIM DATA_3[40003] AS LONG AS FIFO +DIM DATA_4[40003] AS LONG AS FIFO +DIM DATA_5[40003] AS LONG AS FIFO +DIM DATA_6[40003] AS LONG AS FIFO +DIM DATA_7[40003] AS LONG AS FIFO +DIM DATA_8[40003] AS LONG AS FIFO +DIM DATA_9[40003] AS LONG AS FIFO +DIM DATA_10[40003] AS LONG AS FIFO +DIM DATA_11[40003] AS LONG AS FIFO +DIM DATA_12[40003] AS LONG AS FIFO +DIM counter AS LONG INIT: FIFO_Clear(1) @@ -40,21 +41,21 @@ INIT: Rem set continuous conversion and range [-5, 5]V for ADCs Seq_Mode(2, 2) - Seq_Set_Gain(2, 1) + Seq_Set_Gain(2, 0) Seq_Mode(4, 2) - Seq_Set_Gain(4, 1) + Seq_Set_Gain(4, 0) Seq_Mode(6, 2) - Seq_Set_Gain(6, 1) + Seq_Set_Gain(6, 0) Seq_Mode(8, 2) - Seq_Set_Gain(8, 1) + Seq_Set_Gain(8, 0) Seq_Mode(10, 2) - Seq_Set_Gain(10, 1) + Seq_Set_Gain(10, 0) Seq_Mode(12, 2) - Seq_Set_Gain(12, 1) + Seq_Set_Gain(12, 0) Seq_Mode(14, 2) - Seq_Set_Gain(14, 1) + Seq_Set_Gain(14, 0) Seq_Mode(16, 2) - Seq_Set_Gain(16, 1) + Seq_Set_Gain(16, 0) Seq_Select(1010101010101010b) Rem selects even ADCs (look in ADwin Gold II manual) Seq_Start(1010101010101010b) @@ -70,25 +71,37 @@ INIT: Rem start flag Par_80 = 0 + Rem Amount of data to write + Par_79 = 0 + Rem counter + counter = -1 + + EVENT: If (Par_80 = 1) Then - Rem writing - Par_1 = DATA_1 - DAC(1, Par_1) - Par_2 = DATA_2 - DAC(2, Par_2) - Par_3 = DATA_3 - DAC(3, Par_3) - Par_4 = DATA_4 - DAC(4, Par_4) + If (counter < Par_79) Then + If (counter < Par_79 - 1) Then + Rem writing + Par_1 = DATA_1 + DAC(1, Par_1) + Par_2 = DATA_2 + DAC(2, Par_2) + Par_3 = DATA_3 + DAC(3, Par_3) + Par_4 = DATA_4 + DAC(4, Par_4) + EndIf - Rem reading - DATA_5 = Seq_Read(2) - DATA_6 = Seq_Read(4) - DATA_7 = Seq_Read(6) - DATA_8 = Seq_Read(8) - DATA_9 = Seq_Read(10) - DATA_10 = Seq_Read(12) - DATA_11 = Seq_Read(14) - DATA_12 = Seq_Read(16) + Rem reading + DATA_5 = Seq_Read(2) + DATA_6 = Seq_Read(4) + DATA_7 = Seq_Read(6) + DATA_8 = Seq_Read(8) + DATA_9 = Seq_Read(10) + DATA_10 = Seq_Read(12) + DATA_11 = Seq_Read(14) + DATA_12 = Seq_Read(16) + + Inc(counter) + EndIf EndIf diff --git a/instruments/ADwin/ADbasic_8Read_4Write.TB1 b/instruments/ADwin/ADbasic_8Read_4Write.TB1 index 5cae5ee..edc970b 100644 Binary files a/instruments/ADwin/ADbasic_8Read_4Write.TB1 and b/instruments/ADwin/ADbasic_8Read_4Write.TB1 differ diff --git a/instruments/ADwin/ADbasic_8Read_4Write.bas b/instruments/ADwin/ADbasic_8Read_4Write.bas index 4531b7f..7c30fa4 100644 --- a/instruments/ADwin/ADbasic_8Read_4Write.bas +++ b/instruments/ADwin/ADbasic_8Read_4Write.bas @@ -23,6 +23,7 @@ DIM DATA_9[40003] AS LONG AS FIFO DIM DATA_10[40003] AS LONG AS FIFO DIM DATA_11[40003] AS LONG AS FIFO DIM DATA_12[40003] AS LONG AS FIFO +DIM counter AS LONG INIT: FIFO_Clear(1) @@ -40,21 +41,21 @@ INIT: Rem set continuous conversion and range [-5, 5]V for ADCs Seq_Mode(2, 2) - Seq_Set_Gain(2, 1) + Seq_Set_Gain(2, 0) Seq_Mode(4, 2) - Seq_Set_Gain(4, 1) + Seq_Set_Gain(4, 0) Seq_Mode(6, 2) - Seq_Set_Gain(6, 1) + Seq_Set_Gain(6, 0) Seq_Mode(8, 2) - Seq_Set_Gain(8, 1) + Seq_Set_Gain(8, 0) Seq_Mode(10, 2) - Seq_Set_Gain(10, 1) + Seq_Set_Gain(10, 0) Seq_Mode(12, 2) - Seq_Set_Gain(12, 1) + Seq_Set_Gain(12, 0) Seq_Mode(14, 2) - Seq_Set_Gain(14, 1) + Seq_Set_Gain(14, 0) Seq_Mode(16, 2) - Seq_Set_Gain(16, 1) + Seq_Set_Gain(16, 0) Seq_Select(1010101010101010b) Rem selects even ADCs (look in ADwin Gold II manual) Seq_Start(1010101010101010b) @@ -70,25 +71,37 @@ INIT: Rem start flag Par_80 = 0 + Rem Amount of data to write + Par_79 = 0 + Rem counter + counter = -1 + + EVENT: If (Par_80 = 1) Then - Rem writing - Par_1 = DATA_1 - DAC(1, Par_1) - Par_2 = DATA_2 - DAC(2, Par_2) - Par_3 = DATA_3 - DAC(3, Par_3) - Par_4 = DATA_4 - DAC(4, Par_4) + If (counter < Par_79) Then + If (counter < Par_79 - 1) Then + Rem writing + Par_1 = DATA_1 + DAC(1, Par_1) + Par_2 = DATA_2 + DAC(2, Par_2) + Par_3 = DATA_3 + DAC(3, Par_3) + Par_4 = DATA_4 + DAC(4, Par_4) + EndIf - Rem reading - DATA_5 = Seq_Read(2) - DATA_6 = Seq_Read(4) - DATA_7 = Seq_Read(6) - DATA_8 = Seq_Read(8) - DATA_9 = Seq_Read(10) - DATA_10 = Seq_Read(12) - DATA_11 = Seq_Read(14) - DATA_12 = Seq_Read(16) + Rem reading + DATA_5 = Seq_Read(2) + DATA_6 = Seq_Read(4) + DATA_7 = Seq_Read(6) + DATA_8 = Seq_Read(8) + DATA_9 = Seq_Read(10) + DATA_10 = Seq_Read(12) + DATA_11 = Seq_Read(14) + DATA_12 = Seq_Read(16) + + Inc(counter) + EndIf EndIf diff --git a/instruments/ADwin/adwinIO.py b/instruments/ADwin/adwinIO.py index 17f64d3..475a7ba 100644 --- a/instruments/ADwin/adwinIO.py +++ b/instruments/ADwin/adwinIO.py @@ -10,6 +10,7 @@ import os import numpy as np import time +import matplotlib.pyplot as plt DEVICENUMBER = 1 RAISE_EXCEPTIONS = 1 @@ -21,26 +22,29 @@ def initInstrument(): adw = ADwin(DEVICENUMBER, RAISE_EXCEPTIONS) return adw -def FloatToLong(x): +def FloatToLong(x, Vmax): ''' Converts float values to integers, - more specifically this function maps [-10, 10] -> [0, 65536] + more specifically this function maps [-10, 10) -> [0, 65536) ''' for i in range(len(x)): - x[i] = int((x[i] + 10) / 20 * 65536) + x[i] = int(np.round((x[i] + Vmax) / (2*Vmax / 65535))) return x def LongToFloat(x, Vmax): ''' Converts integer values to floats, - more specifically this function maps [0, 65536] -> [-Vmax, Vmax] + more specifically this function maps [0, 65536) -> [-Vmax, Vmax) ''' - for i in range(len(x)): - x[i] = 2*Vmax/65536 * x[i] - Vmax + if isinstance(x, int): + x = 2*Vmax/65536 * x - Vmax + else: + for i in range(len(x)): + x[i] = 2*Vmax/65536 * x[i] - Vmax return x -def IO(adw, inputs, Fs, inputPorts = [1, 0, 0, 0, 0, 0, 0]): +def IO(adw, Input, Fs, inputPorts = [1, 0, 0, 0, 0, 0, 0]): ''' This function will write each row of array inputs on a separate analog output of the ADwin at the specified sample frequency Fs. @@ -54,14 +58,30 @@ def IO(adw, inputs, Fs, inputPorts = [1, 0, 0, 0, 0, 0, 0]): Please look at the ADbasic file while reading this file. Write FIFOs: 1 - 4 Read FIFOs: 5 - 12 + + Inputs arguments + ---------------- + adw: adwin + Input: N x M array, N output ports, M datapoints + Fs: sample frequency + inputPorts**: binary list containing ones for the used input ports + + Returns + ------- + P x M output array, P input ports, M datapoints ''' # Input preparation + if len(Input.shape) == 1: + Input = Input[np.newaxis,:] + + inputs = Input.copy() InputSize = inputs.shape[1] for i in range(inputs.shape[0]): - inputs[i, :] = FloatToLong(list(inputs[i, :])) + inputs[i, :] = FloatToLong(list(inputs[i, :]), 10) x = np.zeros((8, InputSize), dtype = int) x[:inputs.shape[0], :] = inputs outputs = [[], [], [], [], [], [], [], []] # Eight empty output lists + lastWrite = False try: if os.name == 'posix': @@ -70,7 +90,6 @@ def IO(adw, inputs, Fs, inputPorts = [1, 0, 0, 0, 0, 0, 0]): adw.Boot('C:\\ADwin\\ADwin' + PROCESSORTYPE + '.btl') adw.Load_Process('C:\\Users\\PNPNteam\\Documents\\GitHub\\SkyNEt\\instruments\\ADwin\\ADbasic_8Read_4Write.TB1') adw.Set_Processdelay(1, int(300e6 / Fs)) # delay in clock cycles - adw.Start_Process(1) # Clear all FIFOs @@ -87,22 +106,36 @@ def IO(adw, inputs, Fs, inputPorts = [1, 0, 0, 0, 0, 0, 0]): for i in range(1, 5): adw.SetFifo_Long(i, list(x[i-1, :]), InputSize) written = InputSize + lastWrite = True + + + # Notices the ADbasic how much datapoints to + adw.Set_Par(79, InputSize) # Start reading/writing FIFO's when Par80 == 1 adw.Set_Par(80, 1) read = -1 # Read additional datapoint, because write lags behind + if (lastWrite): + time.sleep((InputSize - read)/Fs) # If the last values are put in the write memory, wait a bit until they are written + while(read < InputSize): empty = adw.Fifo_Empty(1) full = adw.Fifo_Full(5) # Read values if read FIFOs are full enough - if(full > 2000): + if(full > 2000 and not lastWrite): for i in range(5, 13): # Read ports are 5 to 12 y = adw.GetFifo_Long(i, 2000) - outputs[i-5] += LongToFloat(list(y), 5) + outputs[i-5] += LongToFloat(list(y), 10) read += 2000 + elif(lastWrite): + for i in range(5, 13): # Read ports are 5 to 12 + y = adw.GetFifo_Long(i, full) + outputs[i-5] += LongToFloat(list(y), 10) + read += full + # Write values if write FIFOs are empty enough if(written < InputSize): if(empty > 2000 and written+2000 <= InputSize): @@ -113,6 +146,8 @@ def IO(adw, inputs, Fs, inputPorts = [1, 0, 0, 0, 0, 0, 0]): for i in range(1, 5): adw.SetFifo_Long(i, list(x[i-1, written:]), InputSize-written) written = InputSize + lastWrite = True + time.sleep((InputSize - read)/Fs) # If the last values are put in the write memory, wait a bit until they are written adw.Stop_Process(1) adw.Clear_Process(1) @@ -126,19 +161,21 @@ def IO(adw, inputs, Fs, inputPorts = [1, 0, 0, 0, 0, 0, 0]): i = 0 for index, val in enumerate(inputPorts): if(val): - outputArray[i] = outputs[index, 1:InputSize + 1] + outputArray[i] = outputs[index, 1:InputSize+1] i += 1 return outputArray + def setControlVoltages(adw, x, Fs): ''' x is a list of 4 values with desired control voltages in V. ''' + x = np.asarray(x) #convert x to numpy array x = (x + 10) / 20 * 65536 x = x.astype(int) - + x = np.tile(x, (FifoSize, 1)) InputBin = x.copy() # convert float array to integer values @@ -163,3 +200,26 @@ def setControlVoltages(adw, x, Fs): except ADwinError as e: print('***', e) + + +def reset(adw): + ''' + Resets the 4 DACs to 0V at a speed of 0.5V/s + ''' + Fs = 1000 + stepsize = 0.0005 # in units of V + DAC_values = [] + DAC_diff = [] + no_steps = [] + + for i in range(1,5): + DAC_values += [LongToFloat(adw.Get_Par(i), 10)] + no_steps += [int(abs(DAC_values[i-1]/stepsize))] + + reset_inputs = np.zeros((4, max(no_steps))) + for i in range(reset_inputs.shape[0]): + reset_inputs[i,:no_steps[i]] = np.linspace(DAC_values[i], 0, no_steps[i], endpoint = True) + + resetData = IO(adw, reset_inputs, Fs) + + diff --git a/instruments/niDAQ/nidaqIO.py b/instruments/niDAQ/nidaqIO.py index 90a8ba7..49df156 100644 --- a/instruments/niDAQ/nidaqIO.py +++ b/instruments/niDAQ/nidaqIO.py @@ -12,23 +12,45 @@ def reset_device(): dev = device.Device(name='Dev1') dev.reset_device() -def IO(y, Fs): + +def IO(y, Fs, inputPorts = [1, 0, 0, 0, 0, 0, 0]): ''' Input/output function for communicating with the NI USB 6216 when measuring with one input and one output. - Input argument: - y; 1D numpy array with data you wish to send on port ao0 - Fs; sample frequency at which data will be sent - Returns: - data; 1D numpy array with data measured on ai0 + + Input arugments + --------------- + y: N x M array, N output ports, M datapoints + Fs: sample frequency + n_ai: number of input ports + + Return + ------- + data: P x M array, P input ports, M datapoints ''' - N = len(y) + if len(y.shape) == 1: + n_ao = 1 + else: + n_ao = y.shape[0] + + if n_ao == 1: + if (len(y.shape) == 2): # This means that the input is a 2D array + y = y[0] + N = len(y) + if n_ao == 2: + N = y.shape[1] + np.append(y, 0) # Finish by setting dacs to 0 with nidaqmx.Task() as output_task, nidaqmx.Task() as input_task: - # Define ao/ai channels - output_task.ao_channels.add_ao_voltage_chan('Dev1/ao0', 'ao0', -10, 10) - input_task.ai_channels.add_ai_voltage_chan('Dev1/ai0') + # Define ao/ai channels + for i in range(n_ao): + output_task.ao_channels.add_ao_voltage_chan('Dev1/ao'+str(i)+'', 'ao'+str(i)+'', -5, 5) + for i in range(len(inputPorts)): + if(inputPorts[i] == 1): + input_task.ai_channels.add_ai_voltage_chan('Dev1/ai'+str(i)+'') + + # Configure sample rate and set acquisition mode to finite output_task.timing.cfg_samp_clk_timing(Fs, sample_mode=constants.AcquisitionType.FINITE, samps_per_chan = N+1) input_task.timing.cfg_samp_clk_timing(Fs, sample_mode=constants.AcquisitionType.FINITE, samps_per_chan = N+1) @@ -37,6 +59,7 @@ def IO(y, Fs): output_task.triggers.start_trigger.cfg_dig_edge_start_trig('/Dev1/ai/StartTrigger') # Fill the output buffer + output_task.write(y, auto_start=False) # Start tasks @@ -45,96 +68,15 @@ def IO(y, Fs): #read data read_data = input_task.read(N + 1, math.ceil(N/Fs)) - data = read_data[1:] #trim off the first datapoint, read lags one sample behind write - - # Stop and close the tasks - input_task.stop() - output_task.stop() - - return data - - -def IO_2D(x, Fs): - ''' - Input/output function for communicating with the NI USB 6216 when measuring - with one input and two outputs. - Input argument: - y; 2D numpy array (2 rows!) with data you wish to send on port ao0 and ao1 - Fs; sample frequency at which data will be sent - Returns: - data; 1D numpy array with data measured on ai0 - ''' - N = x.shape[1] - np.append(x, [[0], [0]], axis=1) # Finish by setting dacs to 0 - with nidaqmx.Task() as output_task, nidaqmx.Task() as input_task: - # Define ao/ai channels - output_task.ao_channels.add_ao_voltage_chan('Dev1/ao0', 'ao0', -10, 10) - output_task.ao_channels.add_ao_voltage_chan('Dev1/ao1', 'ao1', -10, 10) - input_task.ai_channels.add_ai_voltage_chan('Dev1/ai0') - # Configure sample rate and set acquisition mode to finite - output_task.timing.cfg_samp_clk_timing(Fs, sample_mode=constants.AcquisitionType.FINITE, samps_per_chan = N + 1) - input_task.timing.cfg_samp_clk_timing(Fs, sample_mode=constants.AcquisitionType.FINITE, samps_per_chan = N + 1) + read_data = np.asarray(read_data) + if len(read_data.shape) == 1: + read_data = read_data[np.newaxis,:] - # Output triggers on the read operation - output_task.triggers.start_trigger.cfg_dig_edge_start_trig('/Dev1/ai/StartTrigger') - - # Fill the output buffer - output_task.write(x, auto_start=False) - - # Start tasks - output_task.start() - input_task.start() - - # Read data - read_data = input_task.read(N + 1, math.ceil(N/Fs)) - data = read_data[1:] #trim off the first datapoint, read lags one sample behind write - - # Stop and close the tasks - input_task.stop() - output_task.stop() - - return data - -def IO_2D2I(x, Fs): - ''' - Input/output function for communicating with the NI USB 6216 when measuring - with two inputs and two outputs. - Input argument: - y; 2D numpy array (2 rows!) with data you wish to send on port ao0 and ao1 - Fs; sample frequency at which data will be sent - Returns: - data; 2D numpy array with data measured on ai0 and ai1 - ''' - N = x.shape[1] - np.append(x, [[0], [0]], axis=1) # Finish by setting dacs to 0 - with nidaqmx.Task() as output_task, nidaqmx.Task() as input_task: - # Define ao/ai channels - output_task.ao_channels.add_ao_voltage_chan('Dev1/ao0', 'ao0', -10, 10) - output_task.ao_channels.add_ao_voltage_chan('Dev1/ao1', 'ao1', -10, 10) - input_task.ai_channels.add_ai_voltage_chan('Dev1/ai0') - input_task.ai_channels.add_ai_voltage_chan('Dev1/ai1') - - # Configure sample rate and set acquisition mode to finite - output_task.timing.cfg_samp_clk_timing(Fs, sample_mode=constants.AcquisitionType.FINITE, samps_per_chan = N + 1) - input_task.timing.cfg_samp_clk_timing(Fs, sample_mode=constants.AcquisitionType.FINITE, samps_per_chan = N + 1) - - # Output triggers on the read operation - output_task.triggers.start_trigger.cfg_dig_edge_start_trig('/Dev1/ai/StartTrigger') - - # Fill the output buffer - output_task.write(x, auto_start=False) - - # Start tasks - output_task.start() - input_task.start() - - # Read data - read_data = input_task.read(N + 1, math.ceil(N/Fs)) - data = read_data[1:] #trim off the first datapoint, read lags one sample behind write + data = np.delete(read_data,(0), axis=1) #trim off the first datapoint, read lags one sample behind write # Stop and close the tasks input_task.stop() output_task.stop() - return data + return data \ No newline at end of file