def set_up_line(self, length=100): """ Sets up the analoque output for scanning a line. @param int length: length of the line in pixel @return int: error code (0:OK, -1:error) """ self._line_length = length if length < np.inf: daq.DAQmxCfgSampClkTiming(self._scanner_ao_task, # set up sample clock for task timing self._my_scanner_clock_channel+'InternalOutput', # use these pulses as clock self._scanner_clock_frequency, # maximum expected clock frequency daq.DAQmx_Val_Falling, daq.DAQmx_Val_FiniteSamps, # generate sample on falling edge, generate finite number of samples self._line_length) # samples to generate # set timing for scanner pulse and count task. daq.DAQmxCfgImplicitTiming(self._scanner_counter_daq_task, daq.DAQmx_Val_FiniteSamps, self._line_length+1) # read samples from beginning of acquisition, do not overwrite daq.DAQmxSetReadRelativeTo(self._scanner_counter_daq_task, daq.DAQmx_Val_CurrReadPos) # do not read first sample daq.DAQmxSetReadOffset(self._scanner_counter_daq_task, 1) daq.DAQmxSetReadOverWrite(self._scanner_counter_daq_task, daq.DAQmx_Val_DoNotOverwriteUnreadSamps) return 0
def task_handler(self, samples=None, rate=10e3, max_v=10., min_v=-10.): """Sets up a task handler for an analog input channel. Max sample rate for the PCIe-6320 is 250kS/s.""" if samples is None: # Return the channel parameters return self.params else: self.clear_task() self.params['samples'] = samples self.params['rate'] = rate self.params['max_v'] = max_v self.params['min_v'] = min_v self.chan_name = '{0:}/ai{1:}'.format(self.address, self.chan_num) self.task_handle = pydaq.TaskHandle() pydaq.DAQmxCreateTask('', pydaq.byref(self.task_handle)) pydaq.DAQmxCreateAIVoltageChan(self.task_handle, self.chan_name, '', pydaq.DAQmx_Val_Cfg_Default, self.params['min_v'], self.params['max_v'], pydaq.DAQmx_Val_Volts, None) pydaq.DAQmxCfgSampClkTiming(self.task_handle, '', self.params['rate'], pydaq.DAQmx_Val_Rising, pydaq.DAQmx_Val_FiniteSamps, self.params['samples'])
def makeAnalogIn(portString, handle, fSamp, nSamp): ## Create a task out of an existing handle # int32 DAQmxCreateTask (const char taskName[], TaskHandle *taskHandle); taskName = '' # Name of the task (I don't know when this would not be an empty string...) input1Pointer = ctypes.byref( handle ) # Equivalent to &setStates in C, the pointer to the task handle pydaqmx.DAQmxCreateTask(taskName, input1Pointer) ## Create Analog In voltage channel # int32 DAQmxCreateAIVoltageChan (TaskHandle taskHandle, const char physicalChannel[], const char nameToAssignToChannel[], int32 terminalConfig, float64 minVal, float64 maxVal, int32 units, const char customScaleName[]); chan = portString # Location of the channel (this should be a physical channel, but it will be used as a virtual channel?) chanName = "" # Name(s) to assign to the created virtual channel(s). "" means physical channel name will be used termConfig = pydaqmx.DAQmx_Val_Diff # Is this singled/double referenced, differential, etc.\ vMin = -10 # Minimum voltage you expect to measure (in units described by variable "units" below) vMax = 10 # Maximum voltage you expect to measure units = pydaqmx.DAQmx_Val_Volts # Units used in vMax/vMin. custUnits = None # If units where DAQmx_Val_FromCustomScale, specify scale. Otherwise, it should be None pydaqmx.DAQmxCreateAIVoltageChan(handle, chan, chanName, termConfig, vMin, vMax, units, custUnits) ## Configure the clock # int32 DAQmxCfgSampClkTiming (TaskHandle taskHandle, const char source[], float64 rate, int32 activeEdge, int32 sampleMode, uInt64 sampsPerChanToAcquire); source = None # If you use an external clock, specify here, otherwise it should be None rate = pydaqmx.float64( fSamp ) # The sampling rate in samples per second per channel. If you use an external source for the Sample Clock, set this value to the maximum expected rate of that clock. edge = pydaqmx.DAQmx_Val_Rising # Which edge of the clock (Rising/Falling) to acquire data sampMode = pydaqmx.DAQmx_Val_FiniteSamps # Acquire samples continuously or just a finite number of samples # sampMode = pydaqmx.DAQmx_Val_ContSamps sampPerChan = pydaqmx.uInt64( nSamp) # Total number of sample to acquire for each channel pydaqmx.DAQmxCfgSampClkTiming(handle, source, rate, edge, sampMode, sampPerChan)
def acquire_analog(self, channel, points, accuracy, limits=(-10.0, 10.0)): """Acquires an analog signal in the specified channel. The execution blocks the rest of the program. channel -- has to be defined as "Dev1/ai0", for example. points -- the total number of points to be acquired accuracy -- the time between acquisitions (in seconds) limits -- the limits of the expected values. A tuple of 2 values. Returns: numpy array of length points """ taskAnalogNumber = self.addTask({ 'name': 'TaskAnalog', 'TaskHandle': nidaq.TaskHandle() }) self.task_Analog = self.getTask(taskAnalogNumber)['TaskHandle'] self.read = nidaq.int32() points = int(points) data = np.zeros((points, ), dtype=np.float64) channel = str.encode(channel) waiting_time = points * accuracy * 1.05 # Adds a 5% waiting time in order to give enough time freq = 1 / accuracy # Accuracy in seconds nidaq.DAQmxCreateTask("", nidaq.byref(self.task_Analog)) nidaq.DAQmxCreateAIVoltageChan(self.task_Analog, channel, "", nidaq.DAQmx_Val_RSE, limits[0], limits[1], nidaq.DAQmx_Val_Volts, None) nidaq.DAQmxCfgSampClkTiming(self.task_Analog, "", freq, nidaq.DAQmx_Val_Rising, nidaq.DAQmx_Val_FiniteSamps, points) # DAQmx Start Code nidaq.DAQmxStartTask(self.task_Analog) nidaq.DAQmxReadAnalogF64(self.task_Analog, points, waiting_time, nidaq.DAQmx_Val_GroupByChannel, data, points, nidaq.byref(self.read), None) self.tasks[taskAnalogNumber]['alive'] = 0 return data
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 setup_hw_ao(fs, lines, expected_range, callback, callback_samples): # TODO: DAQmxSetAOTermCfg task = create_task() lb, ub = expected_range mx.DAQmxCreateAOVoltageChan(task, lines, '', lb, ub, mx.DAQmx_Val_Volts, '') mx.DAQmxCfgSampClkTiming(task, '', fs, mx.DAQmx_Val_Rising, mx.DAQmx_Val_ContSamps, int(fs)) # This controls how quickly we can update the buffer on the device. On some # devices it is not user-settable. On the X-series PCIe-6321 I am able to # change it. On the M-xeries PCI 6259 it appears to be fixed at 8191 # samples. mx.DAQmxSetBufOutputOnbrdBufSize(task, 8191) # If the write reaches the end of the buffer and no new data has been # provided, do not loop around to the beginning and start over. mx.DAQmxSetWriteRegenMode(task, mx.DAQmx_Val_DoNotAllowRegen) mx.DAQmxSetBufOutputBufSize(task, int(callback_samples*100)) result = ctypes.c_uint32() mx.DAQmxGetTaskNumChans(task, result) n_channels = result.value callback_helper = SamplesGeneratedCallbackHelper(callback, n_channels) cb_ptr = mx.DAQmxEveryNSamplesEventCallbackPtr(callback_helper) mx.DAQmxRegisterEveryNSamplesEvent(task, mx.DAQmx_Val_Transferred_From_Buffer, int(callback_samples), 0, cb_ptr, None) task._cb_ptr = cb_ptr return task
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 CCDTrig_open(freq, data): taskHandle = tp.TaskHandle() taskCounter = tp.TaskHandle() nsamples = len(data) idata = data.astype(tp.uInt32) startdata = N.array((5,5),dtype=tp.uInt32) try: daq.DAQmxCreateTask("",taskCounter) daq.DAQmxCreateCOPulseChanFreq(taskCounter,"Dev1/ctr0","",daq.DAQmx_Val_Hz,daq.DAQmx_Val_Low,0.0,freq,0.50) daq.DAQmxCfgImplicitTiming(taskCounter,daq.DAQmx_Val_ContSamps,1000) # print "taskCounter Value", taskCounter.value ## Create Digital Channel daq.DAQmxCreateTask("",taskHandle) # print "taskHandle Value", taskHandle.value daq.DAQmxCreateDOChan(taskHandle,"Dev1/port0/line0:7","",daq.DAQmx_Val_ChanForAllLines) daq.DAQmxCfgSampClkTiming(taskHandle,"Ctr0InternalOutput",freq,daq.DAQmx_Val_Rising,daq.DAQmx_Val_FiniteSamps,nsamples) ## Register done events (error checking) # q = daq.DAQmxRegisterDoneEvent(taskHandle,0,None,None) # print q,'c' # q = daq.DAQmxRegisterDoneEvent(taskCounter,0,None,None) # print q,'d' ## write startup values daq.DAQmxWriteDigitalU32(taskHandle,2,0,10.0,cnst.DAQmx_Val_GroupByChannel,startdata,None,None) daq.DAQmxStartTask(taskHandle) daq.DAQmxStopTask(taskHandle) ## load trigger sequence daq.DAQmxWriteDigitalU32(taskHandle,nsamples,0,10.0,cnst.DAQmx_Val_GroupByChannel,idata,None,None) print("Data Written\n") ## start counter daq.DAQmxStartTask(taskCounter) return taskHandle,taskCounter except: errBuff=tp.create_string_buffer(b"",2048) daq.DAQmxGetExtendedErrorInfo(errBuff,2048) print(errBuff.value)
def configClock(self, c, name, fSamp, nSamp): ## Configure the clock # int32 DAQmxCfgSampClkTiming (TaskHandle taskHandle, const char source[], float64 rate, int32 activeEdge, int32 sampleMode, uInt64 sampsPerChanToAcquire); source = None # If you use an external clock, specify here, otherwise it should be None rate = pydaqmx.float64( fSamp['Hz']) # The sampling rate in samples per second per channel. If you use an external source for the Sample Clock, set this value to the maximum expected rate of that clock. edge = pydaqmx.DAQmx_Val_Rising # Which edge of the clock (Rising/Falling) to acquire data sampMode = pydaqmx.DAQmx_Val_FiniteSamps # Acquire samples continuously or just a finite number of samples sampPerChan = pydaqmx.uInt64(nSamp) # Total number of sample to acquire for each channel pydaqmx.DAQmxCfgSampClkTiming(self.handleDict[name], source, rate, edge, sampMode, sampPerChan)
def analogSetup(self, taskNum, channel, points, accuracy, limits=(-10.0, 10.0)): """Prepares the task for an analog measurement. taskNum -- the number of the task (an integer) channel -- has to be defined as 1 or as [1,2], for example, meaning ai1, ai2, etc. points -- the total number of points to be acquired accuracy -- the time between acquisitions (in seconds) limits -- the limits of the expected values. A tuple of 2 values. """ taskAnalogNumber = self.addTask({ 'name': 'TaskAnalog', 'TaskHandle': nidaq.TaskHandle(taskNum) }) self.task_Analog = self.getTask(taskAnalogNumber)['TaskHandle'] points = int(points) dev = 'Dev%s' % self.deviceNumber if type(channel) != type([]): channel = [channel] channels = [] for c in channel: newChannel = '%s/ai%s' % (dev, int(c)) channels.append(newChannel) channels = ', '.join(channels) channels = str.encode(channels) freq = 1 / accuracy # Accuracy in seconds nidaq.DAQmxCreateTask("", nidaq.byref(self.task_Analog)) nidaq.DAQmxCreateAIVoltageChan(self.task_Analog, channels, None, nidaq.DAQmx_Val_RSE, limits[0], limits[1], nidaq.DAQmx_Val_Volts, None) if points > 0: nidaq.DAQmxCfgSampClkTiming(self.task_Analog, "", freq, nidaq.DAQmx_Val_Rising, nidaq.DAQmx_Val_FiniteSamps, points) else: nidaq.DAQmxCfgSampClkTiming(self.task_Analog, "", freq, nidaq.DAQmx_Val_Rising, nidaq.DAQmx_Val_ContSamps, points) return taskAnalogNumber
def makeAnalogOutSource(portString, handle, source, freq, amp, offset, waveform): outScan = handle taskName = '' # Name of the task (I don't know when this would not be an empty string...) input1Pointer = ctypes.byref( outScan ) # Equivalent to &setStates in C, the pointer to the task handle pydaqmx.DAQmxCreateTask(taskName, input1Pointer) chan = portString # Location of the channel (this should be a physical channel, but it will be used as a virtual channel?) chanName = "" # Name(s) to assign to the created virtual channel(s). "" means physical channel name will be used minVal = pydaqmx.float64(-10.0) maxVal = pydaqmx.float64(10.0) units = pydaqmx.DAQmx_Val_Volts pydaqmx.DAQmxCreateAOVoltageChan(outScan, chan, chanName, minVal, maxVal, units, 0) fSamp = 1000 nSamp = 1000 #source = None # If you use an external clock, specify here, otherwise it should be None rate = pydaqmx.float64( fSamp ) # The sampling rate in samples per second per channel. If you use an external source for the Sample Clock, set this value to the maximum expected rate of that clock. edge = pydaqmx.DAQmx_Val_Rising # Which edge of the clock (Rising/Falling) to acquire data sampMode = pydaqmx.DAQmx_Val_ContSamps # Acquire samples continuously or just a finite number of samples sampPerChan = pydaqmx.uInt64( nSamp) # Total number of sample to acquire for each channel pydaqmx.DAQmxCfgSampClkTiming(outScan, source, rate, edge, sampMode, sampPerChan) # writeArray = np.zeros((int(nSamp),), dtype=np.float64) if waveform == 'sin': x = 2 * np.pi * freq * np.array(range(nSamp)) / 1000.0 writeArray = np.array(amp * np.sin(x) + offset, dtype=np.float64) if waveform == 'saw': # The amplitude is the peak-to-peak voltage in this waveform if freq != np.ceil(freq): print( "I don't understand decimals yet, the frequency I'm actually using is " + str(np.ceil(freq) + "Hz")) writeArray = amp / 1000.0 * (np.array(range(1000)) * freq % 1000) + offset written = pydaqmx.int32() nSampPerChan = pydaqmx.int32(nSamp) pydaqmx.DAQmxWriteAnalogF64(outScan, nSampPerChan, pydaqmx.bool32(0), pydaqmx.DAQmx_Val_WaitInfinitely, pydaqmx.DAQmx_Val_GroupByChannel, writeArray, ctypes.byref(written), None)
def _setup_sampling(self, num_samples): """ Setup how, then and often measurements hould be taken """ pydaq.DAQmxCfgSampClkTiming( self._task_handle, '', self._samplingrate, # Sampling rate at which cdaq looks for data. IMPORTANT # this is NOT the same as the sampling rate of the EMG # device (although it makes sense). EMG can sample at 1kHz # and program can sample with only 10Hz pydaq.DAQmx_Val_Rising, # Flank of clock, here rising pydaq.DAQmx_Val_ContSamps, # Continueous samples (also fixed num_samples # number possible) )
def setup_hw_ai(fs, lines, expected_range, callback, callback_samples, sync_ao): # Record AI filter delay task = create_task() lb, ub = expected_range mx.DAQmxCreateAIVoltageChan(task, lines, '', mx.DAQmx_Val_RSE, lb, ub, mx.DAQmx_Val_Volts, '') if sync_ao: mx.DAQmxCfgDigEdgeStartTrig(task, 'ao/StartTrigger', mx.DAQmx_Val_Rising) mx.DAQmxCfgSampClkTiming(task, 'ao/SampleClock', fs, mx.DAQmx_Val_Rising, mx.DAQmx_Val_ContSamps, int(fs)) else: mx.DAQmxCfgSampClkTiming(task, '', fs, mx.DAQmx_Val_Rising, mx.DAQmx_Val_ContSamps, int(fs)) result = ctypes.c_uint32() mx.DAQmxGetBufInputBufSize(task, result) buffer_size = result.value mx.DAQmxGetTaskNumChans(task, result) n_channels = result.value log.debug('Buffer size for %s automatically allocated as %d samples', lines, buffer_size) log.debug('%d channels in task', n_channels) new_buffer_size = np.ceil(buffer_size/callback_samples)*callback_samples mx.DAQmxSetBufInputBufSize(task, int(new_buffer_size)) callback_helper = SamplesAcquiredCallbackHelper(callback, n_channels) cb_ptr = mx.DAQmxEveryNSamplesEventCallbackPtr(callback_helper) mx.DAQmxRegisterEveryNSamplesEvent(task, mx.DAQmx_Val_Acquired_Into_Buffer, int(callback_samples), 0, cb_ptr, None) task._cb_ptr = cb_ptr return task
def setup_timing(task, channels, delay=0): ''' Configures timing for task Parameters ---------- task : niDAQmx task handle Task to configure timing for channels : list of channels List of channels to configure References ---------- http://www.ni.com/white-paper/11369/en/ http://www.ni.com/pdf/manuals/371235h.pdf ''' fs = get_channel_property(channels, 'fs') sample_clock = get_channel_property(channels, 'sample_clock') start_trigger = get_channel_property(channels, 'start_trigger') samples = get_channel_property(channels, 'samples') reference_clock = get_channel_property(channels, 'reference_clock') if reference_clock: mx.DAQmxSetRefClkSrc(task, reference_clock) if start_trigger: mx.DAQmxCfgDigEdgeStartTrig(task, start_trigger, mx.DAQmx_Val_Rising) if samples == 0: sample_mode = mx.DAQmx_Val_ContSamps samples = 2 else: sample_mode = mx.DAQmx_Val_FiniteSamps samples += delay mx.DAQmxCfgSampClkTiming(task, sample_clock, fs, mx.DAQmx_Val_Rising, sample_mode, samples) properties = get_timing_config(task) actual_fs = properties['sample clock rate'] if round(actual_fs, 4) != round(fs, 4): names = ', '.join(get_channel_property(channels, 'name', True)) m = f'Actual sample clock rate of {actual_fs} does not match ' \ f'requested sample clock rate of {fs} for {names}' raise ValueError(m) return properties
def __init__(self, osas, simulation=False): """ :param osas: dictionary containing OSA configuration info :param simulation: if True we operate in simulation mode """ self.simulation = simulation self.osas = dict(osas) self.handles = {} if self.simulation: self.f0 = {} for osa_name, osa in self.osas.items(): self.f0[osa_name] = np.random.uniform(0, 1) * osa["num_samples"] return try: # Reset all DAQ cards devices = set([osa["device"] for _, osa in self.osas.items()]) for device in devices: PyDAQmx.DAQmxResetDevice(device) for name, osa in self.osas.items(): self.handles[name] = task_handle = PyDAQmx.TaskHandle(0) PyDAQmx.DAQmxCreateTask("osa_" + name, byref(task_handle)) PyDAQmx.DAQmxCreateAIVoltageChan( task_handle, "/{}/{}".format(osa["device"], osa["input_channel"]), "Voltage", PyDAQmx.DAQmx_Val_NRSE, -osa["v_span"] / 2, osa["v_span"] / 2, PyDAQmx.DAQmx_Val_Volts, None) PyDAQmx.DAQmxCfgSampClkTiming(task_handle, None, osa["sample_rate"], PyDAQmx.DAQmx_Val_Rising, PyDAQmx.DAQmx_Val_FiniteSamps, osa["num_samples"]) PyDAQmx.DAQmxCfgDigEdgeStartTrig( task_handle, "/{}/{}".format(osa["device"], osa["trigger_channel"]), PyDAQmx.DAQmx_Val_Falling) except DAQError as err: self.clear() raise OSAException(err)
def setup_counters(channels, task_name='counter'): lines = get_channel_property(channels, 'channel', True) names = get_channel_property(channels, 'name', True) log.debug('Configuring lines {}'.format(lines)) source_terminal = get_channel_property(channels, 'source_terminal') low_samples = get_channel_property(channels, 'low_samples') high_samples = get_channel_property(channels, 'high_samples') merged_lines = ','.join(lines) task = create_task(task_name) mx.DAQmxCreateCOPulseChanTicks(task, merged_lines, '', source_terminal, mx.DAQmx_Val_Low, 0, low_samples, high_samples) mx.DAQmxCfgSampClkTiming(task, source_terminal, 100, mx.DAQmx_Val_Rising, mx.DAQmx_Val_HWTimedSinglePoint, 2) return task
def set_sample_rate(self, sample_rate): """ Set the sample rate of the pulse generator hardware. @param float sample_rate: The sampling rate to be set (in Hz) @return float: the sample rate returned from the device (in Hz). Note: After setting the sampling rate of the device, use the actually set return value for further processing. """ task = self.pulser_task source = 'OnboardClock' rate = sample_rate edge = daq.DAQmx_Val_Rising mode = daq.DAQmx_Val_ContSamps samples = 10000 daq.DAQmxCfgSampClkTiming(task, source, rate, edge, mode, samples) self.sample_rate = self.get_sample_rate() return self.sample_rate
def setup_hw_di(fs, lines, callback, callback_samples, clock=None): ''' M series DAQ cards do not have onboard timing engines for digital IO. Therefore, we have to create one (e.g., using a counter or by using the analog input or output sample clock. ''' task = create_task() mx.DAQmxCreateDIChan(task, lines, '', mx.DAQmx_Val_ChanForAllLines) # Get the current state of the lines so that we know what happened during # the first change detection event. Do this before configuring the timing # of the lines (otherwise we have to start the master clock as well)! mx.DAQmxStartTask(task) initial_state = read_digital_lines(task, 1) mx.DAQmxStopTask(task) if clock is None: clock = '' if 'Ctr' in clock: clock_task = create_task() mx.DAQmxCreateCOPulseChanFreq(clock_task, clock, '', mx.DAQmx_Val_Hz, mx.DAQmx_Val_Low, 0, fs, 0.5) mx.DAQmxCfgImplicitTiming(clock_task, mx.DAQmx_Val_ContSamps, int(fs)) clock += 'InternalOutput' else: clock_task = None mx.DAQmxCfgSampClkTiming(task, clock, fs, mx.DAQmx_Val_Rising, mx.DAQmx_Val_ContSamps, int(fs)) callback_helper = DigitalSamplesAcquiredCallbackHelper(callback) cb_ptr = mx.DAQmxEveryNSamplesEventCallbackPtr(callback_helper) mx.DAQmxRegisterEveryNSamplesEvent(task, mx.DAQmx_Val_Acquired_Into_Buffer, int(callback_samples), 0, cb_ptr, None) task._cb_ptr = cb_ptr task._initial_state = initial_state return [task, clock_task]
units = pydaqmx.DAQmx_Val_Volts # Units used in vMax/vMin. custUnits = None # If units where DAQmx_Val_FromCustomScale, specify scale. Otherwise, it should be None pydaqmx.DAQmxCreateAIVoltageChan(handle, chan, chanName, termConfig, vMin, vMax, units, custUnits) ## Configure the clock # int32 DAQmxCfgSampClkTiming (TaskHandle taskHandle, const char source[], float64 rate, int32 activeEdge, int32 sampleMode, uInt64 sampsPerChanToAcquire); source = None # If you use an external clock, specify here, otherwise it should be None rate = pydaqmx.float64( 100 ) # The sampling rate in samples per second per channel. If you use an external source for the Sample Clock, set this value to the maximum expected rate of that clock. edge = pydaqmx.DAQmx_Val_Rising # Which edge of the clock (Rising/Falling) to acquire data sampMode = pydaqmx.DAQmx_Val_FiniteSamps # Acquire samples continuously or just a finite number of samples sampPerChan = pydaqmx.uInt64( 2) # Total number of sample to acquire for each channel pydaqmx.DAQmxCfgSampClkTiming(handle, source, rate, edge, sampMode, sampPerChan) #int32 __CFUNC DAQmxGetAIDevScalingCoeff(TaskHandle taskHandle, const char channel[], float64 *data, uInt32 arraySizeInElements); coeffArray = numpy.zeros(100, dtype=ctypes.c_double()) pydaqmx.DAQmxGetAIDevScalingCoeff(handle, '/Dev1/ai2', coeffArray.data, 100) print coeffArray # int32 DAQmxReadBinaryI16 (TaskHandle taskHandle, int32 numSampsPerChan, float64 timeout, bool32 fillMode, int16 readArray[], uInt32 arraySizeInSamps, int32 *sampsPerChanRead, bool32 *reserved); read = pydaqmx.int32( ) # Variable that will hold the value of how many samples we actually read (This gives us the freedom of putting in any sized dataBuffer and know exactly how much data is in it) nSampsPerChan = -1 # -1 in finite mode means wait until all samples are collected and read them timeout = -1 # -1 means wait indefinitely to read the samples fillMode = pydaqmx.DAQmx_Val_GroupByChannel # Controls organization of output. Specifies if you want to prioritize by lowest channel or lowest sample (if you have mutiple channels each getting multiple samples) dataBuffer = numpy.zeros(100, dtype=pydaqmx.int16()) dataBufferFloat = numpy.zeros(100, dtype=pydaqmx.float64()) arrSize = pydaqmx.uInt32(len(dataBuffer))
import PyDAQmx as daq import numpy as np task_handle = daq.TaskHandle() samps = 3000 test_array = np.full((samps, ), -1, dtype=np.uint32) daq.DAQmxCreateTask('count_test', daq.byref(task_handle)) daq.DAQmxCreateCICountEdgesChan(task_handle, '/Dev1/Ctr0', 'Counter test', daq.DAQmx_Val_Rising, 0, daq.DAQmx_Val_CountUp) daq.DAQmxCfgSampClkTiming(task_handle, '100kHzTimebase', 100000, daq.DAQmx_Val_Rising, daq.DAQmx_Val_FiniteSamps, samps) daq.DAQmxSetCICountEdgesTerm(task_handle, '/Dev1/Ctr0', '/Dev1/PFI0') done = daq.bool32() daq.DAQmxStartTask(task_handle) daq.DAQmxGetTaskComplete(task_handle, done) n_read_samples = daq.int32() daq.DAQmxReadCounterU32(task_handle, samps, 500., test_array, len(test_array), daq.byref(n_read_samples), None) done = daq.bool32() daq.DAQmxGetTaskComplete(task_handle, done) daq.DAQmxStopTask(task_handle)
def start(self, test=False, **kwargs): """ 1. Creates a task using settings. 2. Starts the task. You need to call wait_and_clean() after you start() kwargs are sent to self() to set parameters. """ self(**kwargs) # make sure everything that should be a list is a list if not isinstance(self["ao_channels"], Iterable): self["ao_channels"] = [self["ao_channels"]] # if the first element of the waveform is not an array if len(_n.shape(self["ao_waveforms"][0])) < 1: self["ao_waveforms"] = [self["ao_waveforms"]] # create the task object. This doesn't return an object, because # National Instruments. Instead, we have this handle, and we need # to be careful about clearing the thing attached to the handle. debug("output task handle") _mx.DAQmxClearTask(self._handle) _mx.DAQmxCreateTask(self["ao_task_name"], _mx.byref(self._handle)) # create all the output channels debug("output channels") # this is an array of output data arrays, grouped by channel samples = 0 data = _n.array([]) # loop over all the channels for n in range(len(self["ao_channels"])): # get the channel-specific attributes name = self["ao_channels"][n] nickname = name.replace("/", "") debug(name) if isinstance(self["ao_min"], Iterable): ao_min = self["ao_min"][n] else: ao_min = self["ao_min"] if isinstance(self["ao_max"], Iterable): ao_max = self["ao_max"][n] else: ao_max = self["ao_max"] if isinstance(self["ao_units"], Iterable): ao_units = self["ao_units"][n] else: ao_units = self["ao_units"] waveform = self["ao_waveforms"][n] # add an output channel _mx.DAQmxCreateAOVoltageChan(self._handle, name, nickname, ao_min, ao_max, ao_units, "") # add the corresponding output wave to the master data array debug("data", data, "waveform", waveform) data = _n.concatenate([data, waveform]) # Set the samples number to the biggest output array size samples = max(len(self["ao_waveforms"][n]), samples) # Configure the clock debug("output clock") # make sure we don't exceed the max #ao_max_rate = _mx.float64() #_mx.DAQmxGetSampClkMaxRate(self._handle, _mx.byref(ao_max_rate)) #if self['ao_rate'] > ao_max_rate.value: # print "ERROR: ao_rate is too high! Current max = "+str(ao_max_rate.value) # self.clean() # return False _mx.DAQmxCfgSampClkTiming(self._handle, self["ao_clock_source"], self["ao_rate"], self["ao_clock_edge"], self["ao_mode"], samples) # if we're supposed to, export a signal if not self['ao_export_terminal'] == None: _mx.DAQmxExportSignal(self._handle, self['ao_export_signal'], self['ao_export_terminal']) # update to the actual ao_rate (may be different than what was set) ao_rate = _mx.float64() _mx.DAQmxGetSampClkRate(self._handle, _mx.byref(ao_rate)) debug("output actual ao_rate =", ao_rate.value) self(ao_rate=ao_rate.value) # Configure the trigger debug("output trigger") _mx.DAQmxCfgDigEdgeStartTrig(self._handle, self["ao_trigger_source"], self["ao_trigger_slope"]) # Set the post-trigger delay try: n = self["ao_delay"] * 10e6 if n < 2: n = 2 _mx.DAQmxSetStartTrigDelayUnits(self._handle, _mx.DAQmx_Val_Ticks) _mx.DAQmxSetStartTrigDelay(self._handle, n) except: _traceback.print_exc() # write the data to the analog outputs (arm it) debug("output write", len(data)) write_success = _mx.int32() _mx.DAQmxWriteAnalogF64( self._handle, samples, False, self["ao_timeout"], _mx. DAQmx_Val_GroupByChannel, # Type of grouping of data in the array (for interleaved use DAQmx_Val_GroupByScanNumber) data, # Array of data to output _mx.byref(write_success), # Output the number of successful write None) # Reserved input (just put in None...) debug("success:", samples, write_success) if test: self.clean() else: # Start the task!! debug("output start") try: _mx.DAQmxStartTask(self._handle) except: _traceback.print_exc() return True
def start(self, test=False, **kwargs): """ 1. Creates a task using settings. 2. Starts the task. 3. Fetches data. You need to call read_and_clean() after start(). kwargs are sent to self() to set parameters. """ # update any last-minute settings self(**kwargs) debug(self.settings) # create the task object. This doesn't return an object, because # National Instruments. Instead, we have this handle, and we need # to be careful about clearing the thing attached to the handle. debug("input task handle") _mx.DAQmxClearTask(self._handle) _mx.DAQmxCreateTask(self["ai_task_name"], _mx.byref(self._handle)) # Loop over all the input channel names and create a channel for each debug("input channels") for n in range(len(self["ai_channels"])): # get the channel-specific attributes name = self["ai_channels"][n] nickname = name.replace("/", "") debug(name) if isinstance(self["ai_terminal_config"], Iterable): ai_terminal_config = self["ai_terminal_config"][n] else: ai_terminal_config = self["ai_terminal_config"] if isinstance(self["ai_min"], Iterable): ai_min = self["ai_min"][n] else: ai_min = self["ai_min"] if isinstance(self["ai_max"], Iterable): ai_max = self["ai_max"][n] else: ai_max = self["ai_max"] if isinstance(self["ai_units"], Iterable): ai_units = self["ai_units"][n] else: ai_units = self["ai_units"] # add an input channel debug(name) _mx.DAQmxCreateAIVoltageChan(self._handle, name, nickname, ai_terminal_config, ai_min, ai_max, ai_units, "") # set the input coupling (optional) if not self["ai_input_couplings"] == None: ai_input_coupling = self["ai_input_couplings"][n] if ai_input_coupling == "AC": _mx.DAQmxSetAICoupling(self._handle, name, _mx.DAQmx_Val_AC) if ai_input_coupling == "DC": _mx.DAQmxSetAICoupling(self._handle, name, _mx.DAQmx_Val_DC) if ai_input_coupling == "GND": _mx.DAQmxSetAICoupling(self._handle, name, _mx.DAQmx_Val_GND) # Configure the clock debug("input clock") # make sure we don't exceed the max ai_max_rate = _mx.float64() _mx.DAQmxGetSampClkMaxRate(self._handle, _mx.byref(ai_max_rate)) if self['ai_rate'] > ai_max_rate.value: print("ERROR: ai_rate is too high! Current max = " + str(ai_max_rate.value)) self.clean() return False _mx.DAQmxCfgSampClkTiming(self._handle, self["ai_clock_source"], self["ai_rate"], self["ai_clock_edge"], self["ai_mode"], self["ai_samples"]) # get the actual ai_rate ai_rate = _mx.float64() _mx.DAQmxGetSampClkRate(self._handle, _mx.byref(ai_rate)) debug("input actual ai_rate =", ai_rate.value) self(ai_rate=ai_rate.value) # Configure the trigger debug("input trigger") _mx.DAQmxCfgDigEdgeStartTrig(self._handle, self.settings["ai_trigger_source"], self.settings["ai_trigger_slope"]) # Set the post-trigger delay try: n = self["ai_delay"] * 10e6 if n < 2: n = 2 _mx.DAQmxSetStartTrigDelayUnits(self._handle, _mx.DAQmx_Val_Ticks) _mx.DAQmxSetStartTrigDelay(self._handle, n) except: _traceback.print_exc() # in test mode, just check that it doesn't fail and clean up. if test: self.clean() # otherwise, start the show! else: debug("input start") try: _mx.DAQmxStartTask(self._handle) except: _traceback.print_exc() return True
# daq.DAQmxCreateAOVoltageChan(outTask, 'DEV1/AO0','', 0, 10, daq.DAQmx_Val_Volts, '') # # daq.DAQmxCfgSampClkTiming(outTask, '', 1000, daq.DAQmx_Val_Rising, daq.DAQmx_Val_ContSamps, 100) # daq.DAQmxWriteAnalogF64(outTask, 10, False, 0, daq.DAQmx_Val_GroupByChannel, np.linspace(3, 10, 1000), daq.byref(written),None) # daq.StartTask(outTask) value = 0.5 task = daq.TaskHandle() daq.DAQmxCreateTask('con', daq.byref(task)) daq.CreateAOVoltageChan(task, "/Dev1/ao2", "", 0, 10.0, daq.DAQmx_Val_Volts, None) daq.StartTask(task) daq.WriteAnalogScalarF64(task, True, 10.0, value, None) daq.StopTask(task) data = np.zeros((100, ), dtype=np.float64) read = daq.TaskHandle() readAta = daq.int32() daq.DAQmxCreateTask("read", daq.byref(read)) daq.DAQmxCreateAIVoltageChan(read, 'Dev1/ai0', '', daq.DAQmx_Val_RSE, 0, 10, daq.DAQmx_Val_Volts, '') daq.DAQmxCfgSampClkTiming(read, '', 100, daq.DAQmx_Val_Rising, daq.DAQmx_Val_FiniteSamps, 1000) # daq.StartTask(outTask) daq.StartTask(read) daq.DAQmxReadAnalogF64(read, 100, 10, daq.DAQmx_Val_GroupByChannel, data, 100, daq.byref(readAta), None) print(data) daq.DAQmxResetDevice('dev1')
termConfig = pydaqmx.DAQmx_Val_Diff # Is this singled/double referenced, differential, etc.\ vMin = -10 # Minimum voltage you expect to measure (in units described by variable "units" below) vMax = 10 # Maximum voltage you expect to measure units = pydaqmx.DAQmx_Val_Volts # Units used in vMax/vMin. custUnits = None # If units where DAQmx_Val_FromCustomScale, specify scale. Otherwise, it should be None pydaqmx.DAQmxCreateAIVoltageChan(readPressAvg, chan, chanName, termConfig, vMin, vMax, units, custUnits) ## Configure the clock # int32 DAQmxCfgSampClkTiming (TaskHandle taskHandle, const char source[], float64 rate, int32 activeEdge, int32 sampleMode, uInt64 sampsPerChanToAcquire); source = None # If you use an external clock, specify here, otherwise it should be None rate = pydaqmx.float64(fSamp) edge = pydaqmx.DAQmx_Val_Rising # Which edge of the clock (Rising/Falling) to acquire data sampMode = pydaqmx.DAQmx_Val_FiniteSamps # Acquire samples continuously or just a finite number of samples sampPerChan = pydaqmx.uInt64(nSamp) pydaqmx.DAQmxCfgSampClkTiming(readPressAvg, source, rate, edge, sampMode, sampPerChan) ## Read from the specified line(s) # int32 DAQmxReadBinaryI16 (TaskHandle taskHandle, int32 numSampsPerChan, float64 timeout, bool32 fillMode, int16 readArray[], uInt32 arraySizeInSamps, int32 *sampsPerChanRead, bool32 *reserved); nSampsPerChan = -1 # -1 in finite mode means wait until all samples are collected and read them timeout = -1 # -1 means wait indefinitely to read the samples fillMode = pydaqmx.DAQmx_Val_GroupByChannel # Controls organization of output. Specifies if you want to prioritize by lowest channel or lowest sample (if you have mutiple channels each getting multiple samples) readArr = data # The array to read the samples into arrSize = pydaqmx.uInt32(nSamp) sampsPerChanRead = ctypes.byref(read) def readPress(): pydaqmx.DAQmxStartTask(readPressAvg) pydaqmx.DAQmxReadBinaryI16(readPressAvg, nSampsPerChan, timeout, fillMode, readArr, arrSize, sampsPerChanRead, None)