def analog_task(settings): """ """ try: samples_per_channel = settings['samples_per_channel'] number_of_channels = settings['number_of_channels_ai'] # Analog dev print("\nCreating analog task %s." % settings['name']) sys.stdout.flush() # settings task = pydaq.Task() task.CreateAIVoltageChan( settings['analog_input'].encode('utf-8'), **settings['parameters_create_ai'] ) task.CfgSampClkTiming( **settings['parameters_sample_clock_time_ai']) if 'parameters_export_signal' in settings: for sig in settings['parameters_export_signal']: task.ExportSignal(**sig) if 'parameters_start_trigger' in settings: task.CfgDigEdgeStartTrig(**settings['parameters_start_trigger']) total_samples = pydaq.int32() data_size = samples_per_channel * number_of_channels print("\nStarting analog task %s." % settings['name']) task.StartTask() total_samples.value = 0 run = True while run: run = yield data = np.zeros((data_size,), dtype=np.float64) task.ReadAnalogF64( samples_per_channel, 10.0, pydaq.DAQmx_Val_GroupByChannel, data, data_size, pydaq.byref(total_samples), None ) yield data except: pass task.StopTask() task.ClearTask()
def writeValues(self, chanNames, data): DebugLog.log("DAQhardware.writeValue(): chanNames= %s val= %s" % (repr(chanNames), repr(data))) self.analog_output = None # ensure the output task is closed samplesWritten = daqmx.int32() analog_output = daqmx.Task() data = np.vstack((data, data)) data = data.transpose() data = np.require(data, np.double, ['C', 'W']) numSamples = 2 outputRate = 1000 for chanName in chanNames: analog_output.CreateAOVoltageChan(chanName,"",-10.0,10.0, daqmx.DAQmx_Val_Volts, None) analog_output.CfgSampClkTiming("",outputRate, daqmx.DAQmx_Val_Rising, daqmx.DAQmx_Val_FiniteSamps, numSamples) analog_output.WriteAnalogF64(numSampsPerChan=numSamples, autoStart=True,timeout=1.0, dataLayout=daqmx.DAQmx_Val_GroupByChannel, writeArray=data, reserved=None, sampsPerChanWritten=byref(samplesWritten)) DebugLog.log("DAQhardware.setupAnalogOutput(): Wrote %d samples" % samplesWritten.value) # wait until write is completeled isDone = False isDoneP = daqmx.c_ulong() while not isDone: err = analog_output.IsTaskDone(byref(isDoneP)) isDone = isDoneP.value != 0 analog_output = None
def get_internal_chan_old(self, chan): """ Modifies example of PyDAQmx from https://pythonhosted.org/PyDAQmx/usage.html#task-object . There was a simpler version that I didn't notice before, now that one is implemented above. """ print('start get chan %s' %chan) # Declaration of variable passed by reference taskHandle = mx.TaskHandle() read = mx.int32() data = numpy.zeros((1,), dtype=numpy.float64) try: # DAQmx Configure Code mx.DAQmxCreateTask("",mx.byref(taskHandle)) mx.DAQmxCreateAIVoltageChan(taskHandle,"Dev1/_%s_vs_aognd" %chan,"",mx.DAQmx_Val_Cfg_Default,-10.0,10.0,mx.DAQmx_Val_Volts,None) mx.DAQmxCfgSampClkTiming(taskHandle,"",10000.0,mx.DAQmx_Val_Rising,mx.DAQmx_Val_FiniteSamps,2) # DAQmx Start Code mx.DAQmxStartTask(taskHandle) # DAQmx Read Code mx.DAQmxReadAnalogF64(taskHandle,1000,10.0,mx.DAQmx_Val_GroupByChannel,data,1000,mx.byref(read),None) except mx.DAQError as err: print ("DAQmx Error: %s"%err) finally: if taskHandle: # DAQmx Stop Code mx.DAQmxStopTask(taskHandle) mx.DAQmxClearTask(taskHandle) print('end get chan %s' %chan) return float(data[0])
def read_and_clean(self): """ This should be called after start(). Collects data from the running task, cleans up, then returns the data. """ # Fetch the data debug("fetch data") array_size = self["ai_samples"]*len(self["ai_channels"]) # create the array in which to store the data data = _n.zeros(array_size, dtype=_n.float64) bytes_read = _mx.int32() # read the data debug("_handle", self._handle) _mx.DAQmxReadAnalogF64( self._handle, # handle to the task self["ai_samples"], # number of samples per channel (-1 => Read ALL in Buffer) self["ai_timeout"], # timeout (sec) _mx.DAQmx_Val_GroupByChannel, # how to fill the data array data, # array to fill array_size, # array size (samples) _mx.byref(bytes_read), # samples per channel actually read None) # "reserved" # clean up the task self.clean() #Organize the data data = _n.split(data, len(self["ai_channels"])) return data
def read(self, name=None, timeout=0.01, num_samples=None): """ Reads data from a given physical channel :param name: The name of the channel from which we are going to read the data :param timeout: The amount of time, in seconds, to wait for the function to read the sample(s) (-1 for infinite) :param num_samples: The number of samples to acquire :return: Returns an array with the data read """ if name is None: name = self.physical_channels[0] if num_samples is None: index = self.physical_channels.index(name) num_samps_channel = self.n_samples[index] else: num_samps_channel = num_samples # Get task handle task = self.tasks[name] # Prepare the data to be read data = numpy.zeros((num_samps_channel,), dtype=numpy.float64) read = PyDAQmx.int32() # Start the task task.StartTask() # Read the data and return it! task.ReadAnalogF64( num_samps_channel, timeout, GROUP_BY_CHANNEL, data, num_samps_channel, PyDAQmx.byref(read), None ) # Stop the task task.StopTask() # Return in a list instead of numpy.array return data.tolist()
def digital_task(semaphore, semaphore_dev, counter, samples_queue, settings): """ Digital Need to start the dio task first! """ try: print("\nCreating digital task %s." % settings['name']) sys.stdout.flush() # settings samples_per_channel = settings['samples_per_channel'] number_of_channels = settings['number_of_channels_di'] total_samps = pydaq.int32() total_bytes = pydaq.int32() data_size = samples_per_channel * number_of_channels task = pydaq.Task() task.CreateDIChan( settings['digital_input'].encode('utf-8'), b'', pydaq.DAQmx_Val_ChanPerLine ) task.CfgSampClkTiming( **settings['parameters_sample_clock_time_di'] ) print("\nStarting digital task %s." % settings['name']) sys.stdout.flush() task.StartTask() total_samps.value = 0 total_bytes.value = 0 run = True while run: run = yield data = np.zeros((data_size,), dtype=np.uint8 ) task.ReadDigitalLines( samples_per_channel, # numSampsPerChan 10.0, # timeout pydaq.DAQmx_Val_GroupByChannel, # fillMode data, # readArray data_size, # arraySizeInBytes pydaq.byref(total_samps), # sampsPerChanRead pydaq.byref(total_bytes), # numBytesPerChan None # reserved ) yield data except: pass task.StopTask() task.ClearTask()
def send_signal(self): read = Daq.int32() self.StartTask() self.WriteDigitalU32(1, 0, 10.0, Daq.DAQmx_Val_GroupByChannel, self.strobeOn, Daq.byref(read), None) self.WriteDigitalU32(1, 0, 10.0, Daq.DAQmx_Val_GroupByChannel, self.strobeOff, Daq.byref(read), None) self.StopTask()
def send_signal(self, event): #print event read = Daq.int32() self.encode[0] = event #print self.encode self.StartTask() self.WriteDigitalU32(10000, 0, 5.0, Daq.DAQmx_Val_GroupByChannel, self.encode, Daq.byref(read), None) self.StopTask()
def send_signal(self, event): read = Daq.int32() self.StartTask() #print event self.yPosData[0] = event #print('y',self.yPosData) self.WriteAnalogF64(1, 0, -1, Daq.DAQmx_Val_GroupByChannel, self.yPosData, Daq.byref(read), None) self.StopTask()
def ReadTask(task, num): read = PDm.int32() data = (np.zeros((num,), dtype=np.float64)) task.ReadAnalogF64(num, 1000.0, PDm.DAQmx_Val_GroupByChannel, data, num, PDm.byref(read), None) return data[:read.value]
def get_sample_rate(self): """ Get the sample rate of the pulse generator hardware @return float: The current sample rate of the device (in Hz) Do not return a saved sample rate from an attribute, but instead retrieve the current sample rate directly from the device. """ rate = daq.float64() daq.DAQmxGetSampClkRate(self.pulser_task, daq.byref(rate)) return rate.value
def EveryNCallback(self): #print 'callback' read = Daq.int32() #print 'read', read self.ReadAnalogF64(1, 10.0, Daq.DAQmx_Val_GroupByScanNumber, self.EOGData, 2, Daq.byref(read), None) if self.event: self.event(self.EOGData) #print 'x,y', self.EOGData[0], self.EOGData[1] #print 'okay' return 0 # the function should return an integer
def wait_and_clean(self): """ This should be called after start(). Waits for the task to finish and then cleans up. """ #Wait for the task to finish complete = _mx.bool32() while not (complete): _mx.DAQmxGetTaskComplete(self._handle, _mx.byref(complete)) self.clean()
def __init__(self, device='Dev1', ports=['ao0'], read_buffer_size=10, timeout=5., sample_rate=400., AI_mode=pydaq.DAQmx_Val_Diff, save_buffer_size=8000, analog_minmax=(-10,10)): # DAQ properties pydaq.Task.__init__(self) self.device = device self.port_names = ports self.ports = ['/'.join([self.device,port]) for port in self.port_names] self.timeout = timeout self.minn,self.maxx = analog_minmax self.sample_rate = sample_rate self.AI_mode = AI_mode # params & data self.read_success = pydaq.int32() self.read_buffer_size = read_buffer_size self.effective_buffer_size = self.read_buffer_size * len(self.ports) self.read_data = np.zeros(self.effective_buffer_size) # memory for DAQmx to write into on read callbacks self.last_ts = None self.data_q = mp.Queue() # Setup task try: self.CreateAIVoltageChan(','.join(self.ports), '', self.AI_mode, self.minn, self.maxx, pydaq.DAQmx_Val_Volts, None) self.CfgSampClkTiming('', self.sample_rate, pydaq.DAQmx_Val_Rising, pydaq.DAQmx_Val_ContSamps, self.read_buffer_size) self.AutoRegisterEveryNSamplesEvent(pydaq.DAQmx_Val_Acquired_Into_Buffer, self.read_buffer_size, 0) self.AutoRegisterDoneEvent(0) self.StartTask() except: warnings.warn("DAQ task did not successfully initialize") raise
def get_voltage_ai(self, **kwargs): """ get_voltage_ai(self, **kwargs) Usage example: get_voltage_ai(self, channel='Dev1/ai6', voltage_limit=10, clock_freq=1e4, sampling_pts=1000, input_mode='diff') """ # Set the default values below channel = 'Dev1/ai6' voltage_limit = 10 clock_freq = 1e4 sampling_pts = 1000 input_mode = daq.DAQmx_Val_Diff # Read input args for key, value in kwargs.items(): if key == 'channel': channel = value elif key == 'voltage_limit': voltage_limit = value elif key == 'clock_freq': clock_freq = value elif key == 'sampling_pts': sampling_pts = value elif key == 'input_mode': if value.lower() == 'diff': input_mode = daq.DAQmx_Val_Diff elif value.lower() == 'nrse': input_mode = daq.DAQmx_Val_NRSE elif value.lower() == 'rse': input_mode = daq.DAQmx_Val_RSE else: raise ValueError('Unrecognized input mode!') # The code below is adopted from http://pythonhosted.org/PyDAQmx/usage.html sampling_pts = int(sampling_pts) # force int type for sampling_pts, otherwise will be type error analog_input = daq.Task() read = daq.int32() data = numpy.zeros((sampling_pts,), dtype=numpy.float64) recording_time = float(sampling_pts) / clock_freq if recording_time <= 5: fill_mode = 5 else: fill_mode = recording_time * 1.01 # The fill_mode here determines the max recording time USB6211 can go # DAQmx Configure Code #analog_input.CreateAIVoltageChan("Dev1/ai6","",DAQmx_Val_Cfg_Default,-voltage_range,voltage_range,DAQmx_Val_Volts,None) analog_input.CreateAIVoltageChan(channel,"",input_mode,-voltage_limit,voltage_limit,daq.DAQmx_Val_Volts,None) analog_input.CfgSampClkTiming("",clock_freq,daq.DAQmx_Val_Rising,daq.DAQmx_Val_FiniteSamps, sampling_pts) # DAQmx Start Code analog_input.StartTask() # DAQmx Read Code analog_input.ReadAnalogF64(sampling_pts, fill_mode, daq.DAQmx_Val_GroupByChannel,data,sampling_pts, daq.byref(read), None) print "Acquired %d points" % read.value return data
def every_n(self, taskHandle, everyNsamplesEventType, nSamples, callbackData_ptr): callbackdata = get_callbackdata_from_id(callbackData_ptr) read = pydaq.int32() self.read_data[:] = 0 pydaq.DAQmxReadAnalogF64(taskHandle,self.read_buffer_size,self.timeout,pydaq.DAQmx_Val_GroupByScanNumber,self.read_data,self.read_buffer_size,pydaq.byref(read),None) callbackdata.extend(self.read_data.tolist()) self.new_data = True return 0
def readAnalogInput(self, timeout=3.0): ## DAQmx Read Code read = daqmx.int32() numSamplesIn = len(self.dataIn) self.analog_input.ReadAnalogF64(numSamplesIn, timeout, daqmx.DAQmx_Val_GroupByChannel, self.dataIn, numSamplesIn, byref(read), None) DebugLog.log("DAQhardware.sendDigTrig(): Read %s samples" % repr(read)) data = self.dataIn return data
def __init__(self, dev='Dev1/'): self.analog_output0 = mx.Task() self.analog_output0.CreateAOVoltageChan(dev + 'ao0', '', -10.0, 10.0, mx.DAQmx_Val_Volts, None) self.analog_output1 = mx.Task() self.analog_output1.CreateAOVoltageChan(dev + 'ao1', '', -10.0, 10.0, mx.DAQmx_Val_Volts, None) self.voltage_data = np.zeros(1, dtype=mx.float64) # array for voltages self.read = mx.int32() # how many values were read by the DAQ self.voltage_input = mx.Task()
def __init__(self,resource_name, Name = 'NI6120 Digitizer'): Instrument.__init__(self, resource_name, Name = Name) self.read = pdmx.int32() # for sampsPerChanRead self.inputrange_max = 0.2 # can be 42, 20, 10, 5, 2, 1, 0.5, 0.2 Volts self.inputrange_min = -1.0*self.inputrange_max self.sample_rate = 8.0e5 # samples per second self.timeout = 20.0 # seconds self.samples_per_channel = 2e4
def WriteAnalogF64(self, numSampsPerChan, autoStart, timeout, dataLayout, writeArray #sampsPerChanWritten #reserved ): sampsPerChanWritten = PDm.int32() reserved = None super().WriteAnalogF64(numSampsPerChan, autoStart, timeout, dataLayout, writeArray, PDm.byref(sampsPerChanWritten), reserved) return sampsPerChanWritten.value
def set_voltage_ao1(self, voltage): """Set voltage on ao1 """ self.voltage_data[0] = voltage self.analog_output1.WriteAnalogF64(1, True, mx.DAQmx_Val_WaitInfinitely, mx.DAQmx_Val_GroupByChannel, self.voltage_data, mx.byref(self.read), None) return self.read
def get_internal_chan(self, chan): """ Modifies example of PyDAQmx from https://pythonhosted.org/PyDAQmx/usage.html#task-object . """ analog_input = mx.Task() read = mx.int32() data = numpy.zeros((1,), dtype=numpy.float64) # DAQmx Configure Code analog_input.CreateAIVoltageChan("Dev1/_%s_vs_aognd" %chan,"",mx.DAQmx_Val_Cfg_Default,-10.0,10.0,mx.DAQmx_Val_Volts,None) analog_input.CfgSampClkTiming("",10000.0,mx.DAQmx_Val_Rising,mx.DAQmx_Val_FiniteSamps,2) # DAQmx Start Code analog_input.StartTask() # DAQmx Read Code analog_input.ReadAnalogF64(1000,10.0,mx.DAQmx_Val_GroupByChannel,data,1000,mx.byref(read),None) x = data[0] return 0 if abs(x) < 1/150 else x # Stupid way to get around crashing at end of execution. If value returned is too small yet still nonzero, program will crash upon completion. Manually found threshold. It's exactly 1/150. No clue why.
def ReadAnalogF64(self, numSampsPerChan, timeout, fillMode, #readArray, arraySizeInSamps #sampsPerChanRead, #reserved) ): readArray = np.zeros((numSampsPerChan,), dtype = np.float64) sampsPerChanRead = PDm.int32() reserved = None super().ReadAnalogF64(numSampsPerChan, timeout, fillMode, readArray, arraySizeInSamps, PDm.byref(sampsPerChanRead), reserved) return readArray[:sampsPerChanRead.value]
def Ioff(self, mtr): sampsPerChanWritten = daq.int32() mtr["daq"].WriteDigitalU8( 1, True, 0, daq.DAQmx_Val_GroupByChannel, np.array(0, dtype=daq.uInt8), ctypes.byref(sampsPerChanWritten), None, )
def ConfigureTask(self): n_written = pydaq.int32() n_dig_samples = len(self.digital_data) self.CreateDOChan(self.lines, self.name_for_lines, pydaq.DAQmx_Val_ChanForAllLines) self.CfgSampClkTiming(self.ext_clock_line, expt_settings.max_expected_rate, pydaq.DAQmx_Val_Rising, pydaq.DAQmx_Val_FiniteSamps, n_dig_samples) self.WriteDigitalU32(n_dig_samples, False, -1, pydaq.DAQmx_Val_GroupByChannel, self.digital_data, ctypes.byref(n_written), None)
def digital_out(self,sig,dev_name,port,line,val_array = numpy.array([0,0,0,0,0,0,0,0])): # sig = 1 sets output of port,line to high, sig=0 sets output of port,line to low # inputs port and line are integers # labelling on USB600X is P0.0 = port 0, line 0 device_name = dev_name+"/port"+str(port)+"/line"+str(line) #concatenate string for device name digital_output=PyDAQmx.Task() #initialize task write = PyDAQmx.int32() digital_output.CreateDOChan(device_name,"",PyDAQmx.DAQmx_Val_ChanPerLine) #create task for specific channel #set output of specific digital output to either high or low if sig == 1: #print("high") val_array[7-line]=1 val_T = numpy.packbits(val_array) digital_output.WriteDigitalU8(1,True,10.0,PyDAQmx.DAQmx_Val_GroupByChannel,val_T,PyDAQmx.byref(write),None) elif sig == 0: #print("low") val_array[7-line]=0 val_F = numpy.packbits(val_array) digital_output.WriteDigitalU8(1,True,10.0,PyDAQmx.DAQmx_Val_GroupByChannel,val_F,PyDAQmx.byref(write),None) else: pass
def _test_for_test_device(): n = 1024 buff = ctypes.create_string_buffer(n) PyDAQmx.DAQmxGetSysDevNames(buff, n) if sys.version_info >= (3, ): value = buff.value.decode() else: value = buff.value if not test_device_name in map(str.strip, value.split(',')): raise Exception( 'Please install a virtual device called {0} in your system'.format( test_device_name))
def _write_scanner_ao(self, voltages, length=1 ,start=False): """Writes a set of voltages to the analoque outputs. @param float[][4] voltages: array of 4-part tuples defining the voltage points @param int length: number of tuples to write @param bool start: write imediately (True) or wait for start of task (False) @return int: error code (0:OK, -1:error) """ self._AONwritten = daq.int32() daq.DAQmxWriteAnalogF64(self._scanner_ao_task, length, # length of command start, # start task immediately (True), or wait for software start (False) self._RWTimeout, daq.DAQmx_Val_GroupByChannel, voltages, daq.byref(self._AONwritten), None) return self._AONwritten.value
def sendDigTrig(self, trigOutLine): # setup the digital trigger DebugLog.log("DAQhardware.sendDigTrig(): trigOutLine= %s " % trigOutLine) dig_out = daqmx.Task() dig_out.CreateDOChan(trigOutLine, "", daqmx.DAQmx_Val_ChanForAllLines) doSamplesWritten = daqmx.int32() doData = self.doTrigData numpts = len(doData) dig_out.WriteDigitalU32(numSampsPerChan=numpts, autoStart=True, timeout=1.0, dataLayout=daqmx.DAQmx_Val_GroupByChannel, writeArray=doData, reserved=None, sampsPerChanWritten=byref(doSamplesWritten)) DebugLog.log("DAQhardware.sendDigTrig(): Wrote %d samples" % doSamplesWritten.value) dig_out.ClearTask()
def supports_semiperiod_measurement(device_name): """Empirically determines if the DAQ supports semiperiod measurement. Args: device_name (str): NI-MAX device name. Returns: bool: True if semi-period measurements are supported by the device. """ import warnings with warnings.catch_warnings(): # PyDAQmx warns about a positive return value, but actually this is how you are # supposed to figure out the size of the array required. warnings.simplefilter("ignore") # Pass in null pointer and 0 len to ask for what array size is needed: npts = PyDAQmx.DAQmxGetDevCISupportedMeasTypes(device_name, int32(), 0) # Create that array result = (int32 * npts)() PyDAQmx.DAQmxGetDevCISupportedMeasTypes(device_name, result, npts) return c.DAQmx_Val_SemiPeriod in [result[i] for i in range(npts)]
def sendDigOutCmd(self, outLines, outCmd, timeBetweenPts=0.0001): dig_out = daqmx.Task() dig_out.CreateDOChan(outLines, "", daqmx.DAQmx_Val_ChanForAllLines) # print(dig_out) numpts = len(outCmd) doSamplesWritten = daqmx.c_int32() # dig_out.WriteDigitalU32(numSampsPerChan=numpts, autoStart=True, timeout=1.0, dataLayout=daqmx.DAQmx_Val_GroupByScanNumber, writeArray=outCmd, reserved=None, sampsPerChanWritten=byref(doSamplesWritten)) # DebugLog.log("Digital output: Wrote %d samples" % doSamplesWritten.value) for n in range(0, numpts): outCmd_n = np.array(outCmd[n]) dig_out.WriteDigitalU32(numSampsPerChan=1, autoStart=True, timeout=0.01, dataLayout=daqmx.DAQmx_Val_GroupByScanNumber, writeArray=outCmd_n, reserved=None, sampsPerChanWritten=byref(doSamplesWritten)) time.sleep(timeBetweenPts)
def analog_output_dc(self, conditions): """ Sets the analog output of the NI card. For the time being is thought as a DC constant value. :param dict conditions: specifies DEV and Value :return: """ dev = conditions['dev'] port = "Dev%s/ao%s" % (self.daq_num, dev.properties['port']) units = Q_(dev.properties['calibration']['units']) min_value = Q_(dev.properties['limits']['min']).to(units) max_value = Q_(dev.properties['limits']['max']).to(units) # Convert values to volts: value = conditions['value'].to(units) V = self.from_units_to_volts(value, dev) min_V = self.from_units_to_volts(min_value, dev) max_V = self.from_units_to_volts(max_value, dev) t = nidaq.Task() t.CreateAOVoltageChan(port, None, min_V, max_V, nidaq.DAQmx_Val_Volts, None) t.WriteAnalogScalarF64(nidaq.bool32(True), 0, V, None) t.StopTask() t.ClearTask()
def read_analog(self, task, conditions): """Gets the analog values acquired with the triggerAnalog function. conditions -- dictionary with the number of points ot be read """ if task is None: t = self.tasks[-1] else: t = self.tasks[task] read = nidaq.int32() points = int(conditions['points']) if points > 0: data = np.zeros((points,), dtype=np.float64) t.ReadAnalogF64(points, Config.ni_read_timeout, nidaq.DAQmx_Val_GroupByChannel, data, points, nidaq.byref(read), None) else: data = np.zeros((Config.ni_buffer,), dtype=np.float64) t.ReadAnalogF64(points, Config.ni_read_timeout, nidaq.DAQmx_Val_GroupByChannel, data, len(data), nidaq.byref(read), None) values = read.value return values, data
def GetDevName(self, ): # Get Device Name of Daq Card n = 1024 buff = ctypes.create_string_buffer(n) Daq.DAQmxGetSysDevNames(buff, n) if sys.version_info >= (3, ): value = buff.value.decode() else: value = buff.value Dev = value + '/{}' return Dev
def test_Device_Warning(self): t = PyDAQmx.Task() t.CreateAOVoltageChan('TestDevice/ao0', "", -5, 5, PyDAQmx.Val_Volts, None) t.CfgSampClkTiming("", 6E6, PyDAQmx.Val_Rising, PyDAQmx.Val_ContSamps, 1000) with warnings.catch_warnings(record=True) as w: t.StartTask() self.assertEqual(len(w), 1, 'There should be one warning') self.assertIsInstance( w[-1].message, PyDAQmx.SampClkRateViolatesSettlingTimeForGenWarning)
def reset(self): """ Reset the device. @return int: error code (0:OK, -1:error) """ try: daq.DAQmxResetDevice(self.device) except: self.log.exception('Could not reset NI device {0}'.format( self.device)) return -1 return 0
def stop(self): # TODO: I would love to be able to stop a task and keep it in memory # without having to restart; however, this will require some thought as # to the optimal way to do this. For now, we just clear everything. # Configuration is generally fairly quick. if not self._configured: return log.debug('Stopping engine') for task in self._tasks.values(): mx.DAQmxClearTask(task) self._callbacks = {} self._configured = False
def create_task(name=None): ''' Create niDAQmx task Parameters ---------- name : {None, str} Task name (optional). Primarily useful only for debugging purposes (e.g., this is what's reported in NI error messages) Returns ------- task : ctypes pointer Pointer to niDAQmx task ''' if name is None: name = '' task = mx.TaskHandle(0) mx.DAQmxCreateTask(name, ctypes.byref(task)) task._name = name return task
def read_AI_buffer(self, buffersize, fatalerror=True): #instead of 2 below, count the number of analog in channels data_AIs = np.zeros( shape=[self.main_gui.results_widget.no_ai_channels * buffersize]) # ReadAnalogF64( int32 numSampsPerChan, float64 timeout, bool32 fillMode, float64 readArray[], uInt32 arraySizeInSamps, int32 *sampsPerChanRead, bool32 *reserved) # BELOW, instead of buffersize*2, replace 2 with how many analog channels i have self.tasks['AI_task'].ReadAnalogF64( buffersize, self.timeout, mx.DAQmx_Val_GroupByScanNumber, data_AIs, buffersize * self.main_gui.results_widget.no_ai_channels, mx.byref(mx.int32(buffersize)), None) #self.tasks['AI_task'].WaitUntilTaskDone(self.timeout) # gives weird error???? # data_AIs also contains interleaved data, [x1, y1, x2, y2...] # Below, replace 2 with number of AI channels acquired self.data_AI = np.zeros( shape=[self.main_gui.results_widget.no_ai_channels, buffersize]) #Instead of 2 below, use number of AI channels for k in range(self.main_gui.results_widget.no_ai_channels): self.data_AI[k] = data_AIs[k::self.main_gui.results_widget. no_ai_channels]
def EveryNCallback_py(taskHandle, everyNsamplesEventType, nSamples, callbackData_ptr): callbackdata = PyDAQmx.DAQmxCallBack.get_callbackdata_from_id( callbackData_ptr) read = int32() data = zeros(1000) PyDAQmx.DAQmxReadAnalogF64(taskHandle, 1000, 10.0, DAQmx_Val_GroupByScanNumber, data, 1000, ctypes.byref(read), None) callbackdata.extend(data.tolist()) print "Acquired total %d samples" % len(data) return 0 # The function should return an integer
def _setup_channels(self): """ Setup channels to be channels measuring voltage """ pydaq.DAQmxCreateAIVoltageChan( self._task_handle, ','.join(channels ), # Channel, <channel_name>/ai<channel_num> e.g. emg/ai0 '', pydaq.DAQmx_Val_RSE, -10.0, # Max value 10.0, # Min Value pydaq.DAQmx_Val_Volts, # Unit to measure None)
def read_voltage(self, channel): """Read voltage on specific channel. Not efficient!! Debug use only.""" voltage_input = mx.Task() voltage_input.CreateAIVoltageChan('Dev1/ai' + str(channel), '', mx.DAQmx_Val_RSE, -10, 10, mx.DAQmx_Val_Volts, None) voltage_input.ReadAnalogF64(1, mx.DAQmx_Val_WaitInfinitely, mx.DAQmx_Val_GroupByChannel, self.voltage_data, 1, mx.byref(self.read), None) return self.voltage_data
def _start_analog_output(self): """ Creates for each physical channel a task and its virtual channel @returns: error code: ok = 0, error = -1 """ try: # create a dictionary with physical channel name as key and a pointer as value {'/Dev1/AO0': c_void_p(None), ... } taskhandles = dict([(name, daq.TaskHandle(0)) for name in self._ao_channels]) # if an analog task is already running, stop it first (safety if one of the created pointers already points somewhere) for channel in self._ao_channels: if taskhandles[channel].value is not None: # stop analog output task daq.DAQmxStopTask(taskhandles[channel]) # delete the configuration of the analog task daq.DAQmxClearTask(taskhandles[channel]) # set the task handle to None as a safety taskhandles[channel].value = None # create an individual task and a channel per analog output for n, channel in enumerate(self._ao_channels): daq.DAQmxCreateTask('', daq.byref(taskhandles[channel])) daq.DAQmxCreateAOVoltageChan(taskhandles[channel], channel, '', self._ao_voltage_ranges[n][0], self._ao_voltage_ranges[n][1], daq.DAQmx_Val_Volts, None) self.ao_taskhandles = taskhandles except: self.log.exception('Error starting analog output task.') return -1 return 0
def read_value(self, sensor): """ Reads the value of a sensor. .. todo:: Make this method work with sensors other than analog inputs. :param sensor: the sensor to read. :return: The value read, with units if appropriate. """ port = sensor.properties['port'] if sensor.properties['type'] == 'analog': port = "Dev%s/ai%s" % (self.daq_num, port) calibration = sensor.properties['calibration'] min_value = Q_(sensor.properties['limits']['min']) max_value = Q_(sensor.properties['limits']['max']) min_V = from_units_to_volts(min_value, calibration) max_V = from_units_to_volts(max_value, calibration) freq = Config.NI.Input.Analog.freq trigger = Config.NI.Input.Analog.trigger trigger_edge = Config.NI.Input.Analog.trigger_edge measure_mode = Config.NI.Input.Analog.measure_mode num_points = Config.NI.Input.Analog.num_points cont_finite = Config.NI.Input.Analog.cont_finite t = nidaq.Task() t.CreateAIVoltageChan(port, None, measure_mode, min_V, max_V, nidaq.DAQmx_Val_Volts, None) t.CfgSampClkTiming(trigger, freq, trigger_edge, cont_finite, num_points) t.StartTask() time.sleep(num_points*freq) timeout = Config.NI.Input.Analog.read_timeout read = nidaq.int32() data = np.zeros((num_points,), dtype=np.float64) t.ReadAnalogF64(num_points, timeout, nidaq.DAQmx_Val_GroupByChannel, data, num_points, nidaq.byref(read), None) value = np.mean(data) return from_volts_to_units(value, calibration)
def setup_event_timer(trigger, counter, clock, callback=None, edge='rising'): ''' Create timer to store timestamp of rising edge of trigger. Useful for tracking when changes to digital state occur in high precision. Parameters ---------- trigger : str Line to monitor for digital edge (e.g., '/Dev1/PFI1') counter : str Which counter channel to use (e.g., '/Dev1/Ctr0') clock : str Timebase for counter. The value read from the counter will be in units of the specified clock (e.g., 'ao/SampleClock'). edge : {'rising', 'falling'} Should an event time be acquired on the rising or falling edge of the sample clock? Returns ------- task : niDAQmx task Task configured to acquire event time. ''' task = create_task() if edge == 'rising': edge_value = mx.DAQmx_Val_Rising elif edge == 'falling': edge_value = mx.DAQmx_Val_Falling else: raise ValueError('Unsupported mode, {}, for edge'.format(edge)) # Set up a counter to count the number of rising edges from an input # terminal. The input terminal will be set to the value specified by # `clock`. Example terminals include the `ao/SampClock` (in which case the # counter will tell us how many samples have been generated by the analog # output) or the `10MHzRefClock` (in which case the counter will tell us the # the time elapsed since the task began with an accuracy of 1/10e6 seconds). # Every time a trigger is detected, the value of the counter will be saved # to a buffer and can be read into Python. mx.DAQmxCreateCICountEdgesChan(task, counter, '', mx.DAQmx_Val_Rising, 0, mx.DAQmx_Val_CountUp) mx.DAQmxSetCICountEdgesTerm(task, counter, clock) mx.DAQmxCfgSampClkTiming(task, trigger, 200e3, edge_value, mx.DAQmx_Val_ContSamps, 500) if callback is not None: cb = CallbackHelper(callback) # Create the callback. Be sure to store a reference to the callback # pointer on the task object otherwise the pointer will be # garbage-collected after this function exits. If the pointer is # garbage-collected, then the callback no longer exists and the program # will segfault when niDAQmx tries to call it. cb_ptr = mx.DAQmxSignalEventCallbackPtr(cb) mx.DAQmxRegisterSignalEvent(task, mx.DAQmx_Val_SampleCompleteEvent, 0, cb_ptr, None) task.__se_cb_ptr = cb_ptr mx.DAQmxTaskControl(task, mx.DAQmx_Val_Task_Commit) return task
def set_rate(self, rate=1e4, count=1000, delta=0, finite=False): """ Input buffer In continuous mode, count determines per-channel buffer size only if count EXCEEDS default buffer (1 MS over 1 MHz, 100 kS over 10 kHz, 10 kS over 100 Hz, 1 kS <= 100 Hz unless buffer explicitly set by DAQmxCfgInputBuffer() In finite mode, buffer size determined by count """ self.delta = delta if finite: adc_mode = mx.int32(mx.DAQmx_Val_FiniteSamps) else: adc_mode = mx.int32(mx.DAQmx_Val_ContSamps) adc_rate = mx.float64(rate) #override python type adc_count = mx.uInt64(int(count)) self.stop() #make sure task not running, # CfgSampClkTiming ( const char source[], float64 rate, int32 activeEdge, # int32 sampleMode, uInt64 sampsPerChan ); # default clock source is subsystem acquisition clock try: self.task.CfgSampClkTiming("", adc_rate, mx.DAQmx_Val_Rising, adc_mode, adc_count) adc_rate = mx.float64(0) #exact rate depends on hardware timer properties, may be slightly different from requested rate self.task.GetSampClkRate(mx.byref(adc_rate)) self._rate = adc_rate.value self._count = count self._mode = 'buffered' except mx.DAQError as err: self.error(err) self._rate = 0
def DAQmxGetSysDevNames(): import sys, io old_stdout = sys.stdout sys.stdout = io.StringIO() # dummy field to catch print() output try: numBytesNeeded = PyDAQmx.DAQmxGetSysDevNames(None, 0) except PyDAQmx.DAQError as e: numBytesNeeded = e.error if numBytesNeeded == 0: return [] # Restore stdout sys.stdout = old_stdout # We now know how many bytes are needed. # Allocate the buffer stringBuffer = ctypes.create_string_buffer(numBytesNeeded) # Get the device names PyDAQmx.DAQmxGetSysDevNames(stringBuffer, numBytesNeeded) # Extract the device name string names = ctypes.string_at(stringBuffer) names = str(names, 'utf-8') names = names.split(', ') return names
def set(self, data): ''' writes one sample per channel in immediate (non buffered) mode, fastest if task pre-started''' if not isinstance(data, np.ndarray) or data.dtype != np.float64: data = np.asarray(data, dtype=np.float64) if self._mode != 'single': self.set_single() self.start() writeCount = mx.int32(0) auto_start = mx.bool32(1) try: # WriteAnalogF64 (int32 numSampsPerChan, bool32 autoStart, float64 timeout, # bool32 dataLayout, float64 writeArray[], int32 *sampsPerChanWritten, bool32 *reserved) self.task.WriteAnalogF64(1, auto_start, 1.0, mx.DAQmx_Val_GroupByChannel, data, mx.byref(writeCount), None) except mx.DAQError as err: self.error(err) # print "samples {} written {}".format( self._sample_count, writeCount.value) assert writeCount.value == 1, \ "sample count {} transfer count {}".format( 1, writeCount.value )
def stream_stop(self): """ Re-implemented from RecorderParent. """ if self.audio_stream: task_done = pdaq.bool32() self.audio_stream.GetTaskComplete(task_done) if not task_done.value: self.audio_stream.StopTask() else: print('stream already stopped') else: print('No audio stream is set up')
def EveryNCallback(self): with self._data_lock: if self.data_gen is not None: self._data = self.data_gen.next( ) # get data from data generator if self.cha_type[0] is "input": assert self._data.shape[1] == self.num_channels self.ReadAnalogF64( DAQmx_Val_Auto, 1.0, DAQmx_Val_GroupByScanNumber, self._data, self.num_samples_per_chan * self.num_channels, daq.byref(self.read), None) elif self.cha_type[0] is "output": self.WriteAnalogF64(self._data.shape[0], 0, DAQmx_Val_WaitInfinitely, DAQmx_Val_GroupByChannel, self._data, daq.byref(self.read), None) if self.data_rec is not None: for data_rec in self.data_rec: data_rec.send(self._data) self._newdata_event.set() return 0 # The function should return an integer
def analog_output_samples(self, conditions): """ Prepares an anlog output from an array of values. :param conditions: dictionary of conditions. :return: """ t = nidaq.Task() dev = conditions['dev'][0] port = dev.properties['port'] min_val = self.from_units_to_volts(dev.properties['limits']['min'], dev) max_val = self.from_units_to_volts(dev.properties['limits']['max'], dev) t.CreateAOVoltageChan( 'Dev%s/ao%s' % (self.daq_num, port), None, min_val, max_val, nidaq.DAQmx_Val_Volts, None, ) freq = int(1 / conditions['accuracy'].to('s').magnitude) num_points = len(conditions['data']) t.CfgSampClkTiming('', freq, config.ni_trigger_edge, nidaq.DAQmx_Val_FiniteSamps, num_points) auto_trigger = nidaq.bool32(0) timeout = -1 dataLayout = nidaq.DAQmx_Val_GroupByChannel read = nidaq.int32() t.WriteAnalogF64(num_points, auto_trigger, timeout, dataLayout, conditions['data'], read, None) self.tasks.append(t) return len(self.tasks) - 1
def readDigitalInput(channel): if not channelTasks.has_key(channel): channelTasks[channel] = initializeDigitalInput(channel) digital_input = channelTasks[channel] value = daq.c_uint32 try: digital_input.ReadDigitalScalarU32(0, daq.byref(value), None) return value.value except Exception as ex: del channelTasks[channel] raise ex
def configure_pulser_task(self): """ Clear pulser task and set to current settings. @return: """ a_channels = [self.channel_map[k] for k in self.a_names] d_channels = [self.channel_map[k] for k in self.d_names] # clear task daq.DAQmxClearTask(self.pulser_task) # add channels if len(a_channels) > 0: print(self.a_names, a_channels) daq.DAQmxCreateAOVoltageChan( self.pulser_task, ', '.join(a_channels), ', '.join(self.a_names), self.min_volts, self.max_volts, daq.DAQmx_Val_Volts, '') if len(d_channels) > 0: print(self.d_names, d_channels) daq.DAQmxCreateDOChan( self.pulser_task, ', '.join(d_channels), ', '.join(self.d_names), daq.DAQmx_Val_ChanForAllLines) # set sampling frequency daq.DAQmxCfgSampClkTiming( self.pulser_task, 'OnboardClock', self.sample_rate, daq.DAQmx_Val_Rising, daq.DAQmx_Val_ContSamps, 10 * self.sample_rate)
def __init__(self, **kwargs): """ This object provides a command-line interface for a DAQmx task. kwargs overwrites default self.settings dictionary. """ # overwrite the defaults self(**kwargs) self._handle = _mx.TaskHandle() debug(self.settings)
def readTimer(self): if (self.taskCounter): # La fréquence d'echantillonnage sampling_frequency = self.get_task_sampling_rate(self.taskCounter) # Le nombre d'échantillons par voie sample_number = self.get_task_samples_number(self.taskCounter) data = np.zeros((sample_number, ), dtype=np.float64) sample_numberRead = pDaq.int32() self.taskCounter.ReadCounterF64(pDaq.DAQmx_Val_Auto, 10.0, data, sample_number, pDaq.byref(sample_numberRead), None) sample_numberRead = sample_numberRead.value if (sample_numberRead > 0): t = np.linspace(0, sample_numberRead / sampling_frequency, sample_numberRead) pos = np.mean(data) speed = (data[0] - data[-1]) / t[-1] acceleration = (data[0] - data[-1:]) / (t[-1]**2) self.encoderPosBuffer = np.append(self.encoderPosBuffer, pos) self.encoderSpeedBuffer = np.append(self.encoderSpeedBuffer, speed) self.encoderAccelerationBuffer = np.append( self.encoderAccelerationBuffer, acceleration) if (len(self.encoderTimeBuffer) == 0 ): # Si la longueur des temps est nulle # Alors on ajoute les données de temps en brut self.encoderTimeBuffer = np.append(self.encoderTimeBuffer, t[-1]) else: # Sinon on prend le dernier temps et on lui ajoute les # valeurs de temps obtenues self.encoderTimeBuffer = np.append( self.encoderTimeBuffer, self.encoderTimeBuffer[-1] + t[-1]) if (self.encoderAcquisition): self.counterThread = threading.Timer( sample_number / sampling_frequency * 0.8, self.readTimer) self.counterThread.start()
def setupAnalogOutput(self, chanNames, digTrigChan, outputRate, data, isContinuous=False): numSamples = data.shape[0] print( "DAQhardware.setupAnalogOutput(): chanNames= %s digTrigChan= %s outputRate= %f numSamples= %f" % (chanNames, digTrigChan, outputRate, numSamples)) self.clearAnalogOutput() # ensure the output task is closed samplesWritten = daqmx.int32() analog_output = daqmx.Task() data = np.require(data, np.float, ['C', 'W']) for chanName in chanNames: analog_output.CreateAOVoltageChan(chanName, "", -10.0, 10.0, daqmx.DAQmx_Val_Volts, None) sampleType = daqmx.DAQmx_Val_FiniteSamps if isContinuous: sampleType = daqmx.DAQmx_Val_ContSamps analog_output.CfgSampClkTiming("", outputRate, daqmx.DAQmx_Val_Rising, sampleType, numSamples) analog_output.CfgDigEdgeStartTrig(digTrigChan, daqmx.DAQmx_Val_Rising) #analog_output.WriteAnalogF64(numSampsPerChan=numSamples, autoStart=False,timeout=3.0, dataLayout=daqmx.DAQmx_Val_GroupByChannel, writeArray=data, reserved=None, sampsPerChanWritten=byref(samplesWritten)) analog_output.WriteAnalogF64( numSampsPerChan=numSamples, autoStart=False, timeout=3.0, dataLayout=daqmx.DAQmx_Val_GroupByScanNumber, writeArray=data, reserved=None, sampsPerChanWritten=byref(samplesWritten)) print("DAQhardware.setupAnalogOutput(): Wrote %d samples" % samplesWritten.value) self.analog_output = analog_output
def getCountersChannels(self): """Recupere les voies de compteur disponibles""" buffer_size = 1000 the_buffer = ctypes.create_string_buffer(buffer_size) devices = self.get_devices() self.counters = [] for dev in devices: if dev != '': pDaq.DAQmxGetDevCIPhysicalChans(dev, the_buffer, buffer_size) if (the_buffer.value != ''): self.counters = self.counters + \ [str.strip(c) for c in the_buffer.value.decode().split(',')] return self.counters
def __init__(self, mode, device='Dev1', ports=['ao0'], analog_minmax=(-10,10), read_buffer_size=10, timeout=5., sample_rate=400., AI_mode=pydaq.DAQmx_Val_Diff): # example digital port: 'Port1/Line0:3' # example analog port: 'ao0' # DAQ properties pydaq.Task.__init__(self) self.mode = mode self.device = device self.port_names = ports self.ports = ['/'.join([self.device,port]) for port in self.port_names] self.timeout = timeout self.sample_rate = sample_rate self.read = pydaq.int32() self.AI_mode = AI_mode self.last_ts = None # Trigger properties self.minn,self.maxx = analog_minmax if self.mode == self.ANALOG_OUT: self.clear_trig = Trigger(msg=[self.minn for _ in self.ports]) elif self.mode == self.DIGITAL_OUT: self.clear_trig = Trigger(msg=[0,0,0,0], dtype=np.uint8) # params & data self.read_buffer_size = read_buffer_size self.effective_buffer_size = self.read_buffer_size * len(self.ports) self.read_data = np.zeros(self.effective_buffer_size) # Setup task try: if self.mode == self.DIGITAL_OUT: for port in self.ports: self.CreateDOChan(port, "OutputOnly", pydaq.DAQmx_Val_ChanForAllLines) elif self.mode == self.ANALOG_OUT: for port in self.ports: self.CreateAOVoltageChan(port, '', self.minn, self.maxx, pydaq.DAQmx_Val_Volts, None) elif self.mode == self.ANALOG_IN: self.CreateAIVoltageChan(','.join(self.ports), '', self.AI_mode, self.minn, self.maxx, pydaq.DAQmx_Val_Volts, None) self.CfgSampClkTiming('', self.sample_rate, pydaq.DAQmx_Val_Rising, pydaq.DAQmx_Val_ContSamps, self.read_buffer_size) self.AutoRegisterEveryNSamplesEvent(pydaq.DAQmx_Val_Acquired_Into_Buffer, self.read_buffer_size, 0) self.AutoRegisterDoneEvent(0) self._data_lock = threading.Lock() self._newdata_event = threading.Event() self.StartTask() except: warnings.warn("DAQ task did not successfully initialize") raise
def readAnalogInput(self, timeout=3.0): ## DAQmx Read Code read = daqmx.int32() # numSamplesIn = len(self.dataIn) shp = self.dataIn.shape numSamplesIn = shp[1] arraySize = np.prod(shp) self.analog_input.ReadAnalogF64(numSamplesIn, timeout, daqmx.DAQmx_Val_GroupByChannel, self.dataIn, arraySize, byref(read), None) # self.analog_input.ReadAnalogF64(numSamplesIn, timeout, daqmx.DAQmx_Val_GroupByScanNumber, self.dataIn, arraySize, byref(read), None) print("DAQhardware.sendDigTrig(): Read %s samples" % repr(read)) data = self.dataIn return data