def __init__(self, bufferSize=20_000): self.taskIn_ = nidaqmx.Task() self.taskIn_.ai_channels.add_ai_voltage_chan("MyDAQ1/ai0:1") self.taskIn_.timing.cfg_samp_clk_timing( rate=200_000, sample_mode=constants.AcquisitionType.CONTINUOUS, samps_per_chan=bufferSize) self.analogMultiChannelReader_ = stream_readers.AnalogMultiChannelReader( self.taskIn_.in_stream) self.taskIn_.register_every_n_samples_acquired_into_buffer_event( bufferSize, self.callback) self.taskOut_ = nidaqmx.Task() self.taskOut_.co_channels.add_co_pulse_chan_time('myDAQ1/ctr0') self.taskOut_.timing.cfg_implicit_timing( sample_mode=nidaqmx.constants.AcquisitionType.CONTINUOUS) self.counterWriter_ = stream_writers.CounterWriter( self.taskOut_.out_stream, True) self.write_ = False self.counterWriter_.write_one_sample_pulse_time( .00095, .0015, timeout=nidaqmx.constants.WAIT_INFINITELY) time.sleep(3.0)
def prepare_task(self, trig=True): try: if self.task is not None: self.close() # time.sleep(2) # Necessary?? # Open the measurement task self.task = daq.Task("Monitor") # print "Task Handle: {}".format(self.task.name) add_ai_chan = self.task.ai_channels.add_ai_voltage_chan add_ai_chan(self.mychans, terminal_config=self.Terminal_Config) set_timing = self.task.timing.cfg_samp_clk_timing set_timing(self.sample_rate, sample_mode=self.Acquisition_Type) if trig: set_trig = self.task.triggers.start_trigger.cfg_dig_edge_start_trig set_trig("PFI0") self.task.start() self.task_in_stream = daq._task_modules.in_stream.InStream(self.task) self.reader = stream_readers.AnalogMultiChannelReader(self.task_in_stream) return except KeyboardInterrupt: self.close() # TODO : Proper traceback here raise KeyboardInterrupt
def streamer(self, value): if value is not None: raise AttributeError("Hey! You can't set this manually!") # If read mode, StreamReader. if not self.write_mode: if self.nchannels > 1: reader = sr.AnalogMultiChannelReader( self.__task.in_stream) else: reader = sr.AnalogSingleChannelReader( self.__task.in_stream) self.__streamer = reader # Else, StreamWriter for PWM output channel else: self.__streamer = sw.CounterWriter( self.__task.out_stream) # Reconfigure channels' streamer if self.nchannels > 0: try: self.pins.streamer = self.__streamer except: raise AttributeError("Coudn't set streamer to channels")
def open(self): # AI self.t_in = {} for c in self.ai_chan_list: kwargs = dict(c) kwargs.pop("name", None) kwargs.pop("type", None) if c['type'] == 'voltage': kwargs['max_val'] = kwargs.get('max_val', 5) kwargs['min_val'] = kwargs.get('min_val', 0) for k in kwargs: if isinstance(kwargs[k], str): if k == "thermocouple_type": kwargs[k] = thermocouple_type[kwargs[k]] elif k == "units": kwargs[k] = units[kwargs[k]] if not c['type'] in self.t_in: self.t_in[c['type']] = nidaqmx.Task() try: getattr(self.t_in[c['type']].ai_channels, "add_ai_%s_chan" % c['type'])(c['name'], **kwargs) except Exception: print("Invalid channel settings in nidaqmx:" + str(c)) raise self.stream_in = {} for chan_type, t in self.t_in.items(): self.stream_in[chan_type] = \ stream_readers.AnalogMultiChannelReader(t.in_stream) # AO if self.ao_channels: self.t_out = nidaqmx.Task() self.stream_out = stream_writers.AnalogMultiChannelWriter( self.t_out.out_stream, auto_start=True) for c in self.ao_channels: kwargs = dict(c) kwargs.pop("name", None) kwargs.pop("type", None) kwargs['max_val'] = kwargs.get('max_val', 5) kwargs['min_val'] = kwargs.get('min_val', 0) self.t_out.ao_channels.add_ao_voltage_chan(c['name'], **kwargs) # DI if self.di_channels: self.t_di = nidaqmx.Task() for c in self.di_channels: kwargs = dict(c) kwargs.pop("name", None) kwargs.pop("type", None) self.t_di.di_channels.add_di_chan(c['name'], **kwargs) if self.di_channels: self.di_stream = stream_readers.DigitalMultiChannelReader( self.t_di.in_stream) # DO if self.do_channels: self.t_do = nidaqmx.Task() for c in self.do_channels: kwargs = dict(c) kwargs.pop("name", None) kwargs.pop("type", None) self.t_do.do_channels.add_do_chan(c['name'], **kwargs) if self.do_channels: self.do_stream = stream_writers.DigitalMultiChannelWriter( self.t_do.out_stream)
output_array -= pidconstant * delta elif max(samples) < (pidvalue-0.1): delta = pidvalue - max(samples) output_array += pidconstant * delta return 0 # Now I start the actual PID loop with nid.Task() as write_task, nid.Task() as read_task: # First I configure the reading read_task.ai_channels.add_ai_voltage_chan( flatten_channel_string(channels_to_read), max_val=10, min_val=-10) reader = sr.AnalogMultiChannelReader(read_task.in_stream) # Now I configure the writing write_task.ao_channels.add_ao_voltage_chan( flatten_channel_string(channels_to_write), max_val=10, min_val=-10) writer = sw.AnalogMultiChannelWriter(write_task.out_stream) # source task. # Start the read and write tasks before starting the sample clock # source task. read_task.start() read_task.register_every_n_samples_acquired_into_buffer_event( 20, # Every 20 samples, call callback function callback)
measTime = 10 # measurement time in seconds rate = 10000 # sampling rate in Hz with nidaqmx.Task() as task: # add channels to task task.ai_channels.add_ai_voltage_chan( physical_channel='Dev1/ai0', name_to_assign_to_channel='B', units=nidaqmx.constants.VoltageUnits.VOLTS) task.ai_channels.add_ai_voltage_chan( physical_channel='Dev1/ai1', name_to_assign_to_channel='H', units=nidaqmx.constants.VoltageUnits.VOLTS) # set sampling rate task.timing.cfg_samp_clk_timing( rate=rate, sample_mode=constants.AcquisitionType.CONTINUOUS, samps_per_chan=measTime * rate) # start tasks task.start() # measure reader = stream_readers.AnalogMultiChannelReader(task.in_stream) data = np.zeros((2, measTime * rate)) reader.read_many_sample(data, measTime * rate) # start tasks task.stop()
def start_continuous_acq_n_gen(self): self._ao_task = ni.Task() self._ai_task = ni.Task() ai_args = { 'min_val': self.ai_min_val, 'max_val': self.ai_max_val, 'terminal_config': ni.constants.TerminalConfiguration[self.ai_terminal_config] } self._ai_task.ai_channels.add_ai_voltage_chan(self.ai_a_name, **ai_args) self._ai_task.ai_channels.add_ai_voltage_chan(self.ai_b_name, **ai_args) self._ai_task.timing.cfg_samp_clk_timing( rate=self.ai_fs, sample_mode=ni.constants.AcquisitionType.CONTINUOUS, samps_per_chan=self._input_frame_len) self._ai_task.triggers.start_trigger.cfg_dig_edge_start_trig( "ao/StartTrigger", trigger_edge=ni.constants.Edge.RISING) # Below is a bit clumsy EAFP but we have to be careful writing to properties because they may or may not be # present depending on device type while the "double locking" system with both OVERRIDE and property needing # change requires user to really know what he is doing. In most cases if some control attribute is not # implemented in a device, it can work without issues just with the default settings though. On NI6211, # this code is debugged with, only the default output buffer had to be changed to prevent underflow at high # UBS data rates. I leave this code though for users to experiment in case of issues with other DAQ models. if self.ATTEMPT_OVERRIDE_DEFAULT_INPUT_BUFFER_SIZE: try: self._ai_task.in_stream.input_buf_size = self.sw_input_buffer_size except ni.errors.DaqError as exc: print(exc) print('ATTEMPT_OVERRIDE_DEFAULT_INPUT_BUFFER_SIZE failed') if self.ATTEMPT_OVERRIDE_DEFAULT_INPUT_OVERWRITE_BEHAVIOUR is True: try: if self.INPUT_OVERWRITE is False: self._ai_task.in_stream.over_write = ni.constants.OverwriteMode.DO_NOT_OVERWRITE_UNREAD_SAMPLES elif self.INPUT_OVERWRITE is True: self._ai_task.in_stream.over_write = ni.constants.OverwriteMode.OVERWRITE_UNREAD_SAMPLES except ni.errors.DaqError as exc: print(exc) print( 'ATTEMPT_OVERRIDE_DEFAULT_INPUT_OVERWRITE_BEHAVIOUR failed' ) ao_args = {'min_val': self.ao_min_val, 'max_val': self.ao_max_val} ao_chan_a = self._ao_task.ao_channels.add_ao_voltage_chan( self.ao_a_name, **ao_args) ao_chan_b = self._ao_task.ao_channels.add_ao_voltage_chan( self.ao_b_name, **ao_args) if self.ATTEMPT_OVERRIDE_DEFAULT_USB_XFER is True: try: ao_chan_a.ao_usb_xfer_req_count = self.AO_USB_XFER_REQ_COUNT ao_chan_b.ao_usb_xfer_req_count = self.AO_USB_XFER_REQ_COUNT ao_chan_a.ao_usb_xfer_req_size = self.AO_USB_XFER_REQ_SIZE ao_chan_b.ao_usb_xfer_req_size = self.AO_USB_XFER_REQ_SIZE except ni.errors.DaqError as exc: print(exc) print('ATTEMPT_OVERRIDE_DEFAULT_USB_XFER failed') self._ao_task.timing.cfg_samp_clk_timing( rate=self.ao_fs, samps_per_chan=self._output_frame_len, #TODO bug on dev1 sample_mode=ni.constants.AcquisitionType.CONTINUOUS) if self.ATTEMPT_OVERRIDE_DEFAULT_OUTPUT_REGENERATION_MODE is True: try: if self.ALLOW_OUTPUT_REGENERATION is False: self._ao_task.out_stream.regen_mode = ni.constants.RegenerationMode.DONT_ALLOW_REGENERATION # prevents DAQ card from repeating output, it just waits for more data to be added to the buffer- > but on cards that cant handle to automatically pause output generation when out of buffer this setting will case random and unexpected crash! elif self.ALLOW_OUTPUT_REGENERATION is True: self._ao_task.out_stream.regen_mode = ni.constants.RegenerationMode.ALLOW_REGENERATION except ni.errors.DaqError as exc: print(exc) print( 'ATTEMPT_OVERRIDE_DEFAULT_OUTPUT_REGENERATION_MODE failed') if self.ATTEMPT_OVERRIDE_DEFAULT_UNDERFLOW_BEHAVIOR_TO_PAUSE is True: try: self._ao_task.timing.implicit_underflow_behavior = ni.constants.UnderflowBehavior.AUSE_UNTIL_DATA_AVAILABLE # SIC! except ni.errors.DaqError as exc: print(exc) print('Could not OVERRIDE_DEFAULT_UNDEFLOW_BEHAVIOR') if self._ao_task.out_stream.regen_mode == ni.constants.RegenerationMode.DONT_ALLOW_REGENERATION: print( 'WARNING: Your device does not support pause in case of output underflow while auto ' 'regeneration of the AO buffer is not allowed.\n ' 'In case of output buffer underflow due to system resources the application will crash!\n ' 'To prevent this warning and risk of crash its highly recommended to set _out_stream.regen_' 'mode to ALLOW_REGENERATION.\n ' 'This will allow output glitches in theory but will prevent ' 'application from crashing on output buffer underflow.' ) if self.ATTEMPT_OVERRIDE_DEFAULT_OUTPUT_BUFFER_SIZE is True: try: self._ao_task.out_stream.output_buf_size = self.sw_output_buffer_size # seems like buffer is not calculating correct and we must call out explicitly on NI6211. # Not setting this property leads to a chain of very confusing warnings/glitches. except ni.errors.DaqError as exc: print(exc) self._stream_reader = stream_readers.AnalogMultiChannelReader( self._ai_task.in_stream) self._stream_writer = stream_writers.AnalogMultiChannelWriter( self._ao_task.out_stream) # fill AO buffer with data self.function_gen.generate() buffer_frame = self.function_gen.output_frame for frames in range(self.CM_OUTPUT_FRAMES_PER_BUFFER - 1): # TODO UGLY self.function_gen.generate() buffer_frame = np.append(buffer_frame, self.function_gen.output_frame, axis=1) self._ao_task.write(buffer_frame) self._ai_task.register_every_n_samples_acquired_into_buffer_event( self._input_frame_len, self.reading_task_callback) self._ao_task.register_every_n_samples_transferred_from_buffer_event( self._output_frame_len, self.writing_task_callback) self._ai_task.start() # arm but do not trigger the acquisition self._ao_task.start( ) # trigger both generation and acquisition simultaneously self.cm_measurement_is_running = True