def init(self): if self.task_state == "": self.task = TaskHandle() DAQmxCreateTask(b"", byref(self.task)) DAQmxCreateCITwoEdgeSepChan( self.task, "{}/{}".format(self.device_name, self.counter_chan).encode(), b"", float64(self.min_val), float64(self.max_val), DAQmx_Val_Seconds, self.first_edge_type, self.second_edge_type, b"", ) if self.source_terminal: tmp_data = c_char_p(self.source_terminal.encode()) DAQmxSetCITwoEdgeSepFirstTerm( self.task, "{}/{}".format(self.device_name, self.counter_chan).encode(), tmp_data, ) if self.destination_terminal: tmp_data = c_char_p(self.destination_terminal.encode()) DAQmxSetCITwoEdgeSepSecondTerm( self.task, "{}/{}".format(self.device_name, self.counter_chan).encode(), tmp_data, ) self.task_state = "init"
def write(self, data): """ The task should be in stopped state when calling write, it automatically starts the task through the DAQmxWriteDigitalLines call. When write is finished it is back in a stopped state :param data: :return: """ self.init() try: if len(data) % self.io_length: raise ValueError("data must be a length divisible by {}".format(self.io_length)) except TypeError as e: raise ValueError("data must be in an list divisible by {}".format(self.io_length)) from e if len(data) == self.io_length: # Sample clock only works for more than one sample so duplicate the sample data = list(data) data.extend(data) DAQmxCfgSampClkTiming(self.task, None, float64(self.frequency), DAQmx_Val_Rising, DAQmx_Val_FiniteSamps, uInt64(int(len(data) // self.io_length))) try: data_arr = numpy.zeros((len(data)), uInt8) data_arr[:] = data written = int32() DAQmxWriteDigitalLines(self.task, int(len(data) // self.io_length), 1, -1, DAQmx_Val_GroupByScanNumber, data_arr, written, None) self.task_state = "running" DAQmxWaitUntilTaskDone(self.task, -1) if written.value != len(data) // self.io_length: raise InstrumentError("Values not written correctly") finally: self.stop()
def _read(self): try: DAQmxReadCounterScalarF64(self.task, float64(self._thread_timeout), byref(self._data), None) except Exception as e: self._error_queue.put(ThreadError(e)) return
def init(self): if self.task_state == "": self.task = TaskHandle() DAQmxCreateTask(b"", byref(self.task)) DAQmxCreateCITwoEdgeSepChan(self.task, "{}/{}".format(self.device_name, self.counter_chan).encode(), b"", float64(self.min_val), float64(self.max_val), DAQmx_Val_Seconds, self.first_edge_type, self.second_edge_type, b"") if self.source_terminal: tmp_data = c_char_p(self.source_terminal.encode()) DAQmxSetCITwoEdgeSepFirstTerm(self.task, "{}/{}".format(self.device_name, self.counter_chan).encode(), tmp_data) if self.validate_terminals: tmp_data = c_char_p("".encode()) DAQmxGetCITwoEdgeSepFirstTerm(self.task, "{}/{}".format(self.device_name, self.counter_chan).encode(), tmp_data, uInt32(16)) if self.destination_terminal not in tmp_data.value.decode('utf-8'): raise InstrumentError( "Destination terminal is set to {}, should be /{}/{}".format(tmp_data.value.decode('utf-8'), self.device_name, self.destination_terminal)) if self.destination_terminal: tmp_data = c_char_p(self.destination_terminal.encode()) DAQmxSetCITwoEdgeSepSecondTerm(self.task, "{}/{}".format(self.device_name, self.counter_chan).encode(), tmp_data) if self.validate_terminals: tmp_data = c_char_p("".encode()) DAQmxGetCITwoEdgeSepSecondTerm(self.task, "{}/{}".format(self.device_name, self.counter_chan).encode(), tmp_data, uInt32(16)) if self.destination_terminal not in tmp_data.value.decode('utf-8'): raise InstrumentError( "Destination terminal is set to {}, should be /{}/{}".format(tmp_data.value.decode('utf-8'), self.device_name, self.destination_terminal)) self.task_state = "init"
def _read(self): self.init() return DAQmxReadCounterScalarF64(self.task, float64(10), byref(self._data), None)
class TwoEdgeSeparation(DaqTask): """ DAQmxGetCITwoEdgeSepFirstTerm and DAQmxGetCITwoEdgeSepSecondTerm currently have a bug where if they are called there is no way to create a new task unless the process is destroyed. Therefore there is no error checking on the encoding of the terminal for the source and destination terminal. A validate terminals parameter has been added but it should only be used once and as a debugging tool as it will prevent any future tasks being created """ _data = float64() _trigger_thread = None def __init__(self, device_name, counter_chan, min_val, max_val, first_edge_type, second_edge_type, source_terminal, destination_terminal, validate_terminals=False): self.device_name = device_name self.counter_chan = counter_chan self.min_val = min_val self.max_val = max_val self.first_edge_type = first_edge_type self.second_edge_type = second_edge_type self.source_terminal = source_terminal self.destination_terminal = destination_terminal self.validate_terminals = validate_terminals def init(self): if self.task_state == "": self.task = TaskHandle() DAQmxCreateTask(b"", byref(self.task)) DAQmxCreateCITwoEdgeSepChan(self.task, "{}/{}".format(self.device_name, self.counter_chan).encode(), b"", float64(self.min_val), float64(self.max_val), DAQmx_Val_Seconds, self.first_edge_type, self.second_edge_type, b"") if self.source_terminal: tmp_data = c_char_p(self.source_terminal.encode()) DAQmxSetCITwoEdgeSepFirstTerm(self.task, "{}/{}".format(self.device_name, self.counter_chan).encode(), tmp_data) if self.validate_terminals: tmp_data = c_char_p("".encode()) DAQmxGetCITwoEdgeSepFirstTerm(self.task, "{}/{}".format(self.device_name, self.counter_chan).encode(), tmp_data, uInt32(16)) if self.destination_terminal not in tmp_data.value.decode('utf-8'): raise InstrumentError( "Destination terminal is set to {}, should be /{}/{}".format(tmp_data.value.decode('utf-8'), self.device_name, self.destination_terminal)) if self.destination_terminal: tmp_data = c_char_p(self.destination_terminal.encode()) DAQmxSetCITwoEdgeSepSecondTerm(self.task, "{}/{}".format(self.device_name, self.counter_chan).encode(), tmp_data) if self.validate_terminals: tmp_data = c_char_p("".encode()) DAQmxGetCITwoEdgeSepSecondTerm(self.task, "{}/{}".format(self.device_name, self.counter_chan).encode(), tmp_data, uInt32(16)) if self.destination_terminal not in tmp_data.value.decode('utf-8'): raise InstrumentError( "Destination terminal is set to {}, should be /{}/{}".format(tmp_data.value.decode('utf-8'), self.device_name, self.destination_terminal)) self.task_state = "init" def read(self): self._trigger_thread.join(10) if self._trigger_thread.exec_info: try: raise self._trigger_thread.exec_info finally: self._trigger_thread = None self._trigger_thread = None return self._data def _read(self): self.init() return DAQmxReadCounterScalarF64(self.task, float64(10), byref(self._data), None) def trigger(self): if self._trigger_thread: self.clear() self._trigger_thread.stop() self._trigger_thread.join(10) if self._trigger_thread.is_alive(): raise InstrumentError("Existing Trigger Event in Progress") self._trigger_thread = ExcThread(target=self._read) self._trigger_thread.start()
class TwoEdgeSeparation(DaqTask): _data = float64() _trigger_thread = None def __init__( self, device_name, counter_chan, min_val, max_val, first_edge_type, second_edge_type, source_terminal, destination_terminal, ): self.device_name = device_name self.counter_chan = counter_chan self.min_val = min_val self.max_val = max_val self.first_edge_type = first_edge_type self.second_edge_type = second_edge_type self.source_terminal = source_terminal self.destination_terminal = destination_terminal self._error_queue = Queue() self._thread_timeout = 10 def init(self): if self.task_state == "": self.task = TaskHandle() DAQmxCreateTask(b"", byref(self.task)) DAQmxCreateCITwoEdgeSepChan( self.task, "{}/{}".format(self.device_name, self.counter_chan).encode(), b"", float64(self.min_val), float64(self.max_val), DAQmx_Val_Seconds, self.first_edge_type, self.second_edge_type, b"", ) if self.source_terminal: tmp_data = c_char_p(self.source_terminal.encode()) DAQmxSetCITwoEdgeSepFirstTerm( self.task, "{}/{}".format(self.device_name, self.counter_chan).encode(), tmp_data, ) if self.destination_terminal: tmp_data = c_char_p(self.destination_terminal.encode()) DAQmxSetCITwoEdgeSepSecondTerm( self.task, "{}/{}".format(self.device_name, self.counter_chan).encode(), tmp_data, ) self.task_state = "init" def read(self): self._trigger_thread.join(self._thread_timeout) if self._trigger_thread.is_alive(): raise InstrumentError("Trigger thread failed to terminate") try: err = self._error_queue.get_nowait() except Empty: # no error in queue pass else: raise err # TODO: consider making this return self._data.value. We should return a python # float object, not a ctypes.c_double return self._data def _read(self): try: DAQmxReadCounterScalarF64(self.task, float64(self._thread_timeout), byref(self._data), None) except Exception as e: self._error_queue.put(ThreadError(e)) return def trigger(self): if self._trigger_thread: self.clear() self._trigger_thread.join(self._thread_timeout) if self._trigger_thread.is_alive(): raise InstrumentError("Existing Trigger Event in Progress") self.init() self._trigger_thread = ExcThread(target=self._read) self._trigger_thread.start()