Example #1
0
class AnalogInput(object):
    ## This function is a constructor for the AnalogInput class.
    #
    # It creates the internal variables required to perform functions within the
    # class. This function does not initialize any hardware.
    def __init__(self):

        ## The DAQmx task reference.
        self.taskRef = Task()

        ## A boolean that is set to True when the AnalogInput card is initialized.
        self.initialized = False

        ## This is the status of the DAQmx task.
        #
        #  A value greater than 0 means that an error has occurred. When the status
        #  is greater than 0 an error should be reported by the class.
        self.status = int32()

        ## @var sampleRate
        #  This is the sample rate of the analog input.
        self._sampleRate = 100e3

        ## @var samplesPerChannel
        #  This is the number of samples per channel that will be
        #  acquired in Finite mode.
        self._samplesPerChannel = 100

        ## @var numChannels
        #  This is the number of channels configured in the task.
        self._numChannels = 0

        ## This is the timeout in seconds for functions in the task to timeout.
        self.timeout = 1

        ## This is the mode of operation for the analog inputs.
        #
        #  There are currently three modes available.
        #  Static mode is where one static voltage is acquired with no need
        #  for a sample clock.
        #  Finite mode is where a finite number of voltages will be acquired at a
        #  sample clock rate.
        #  Continuous mode is where a sequence of voltages are generated at a sample
        #  rate and then repeated until the stop() method is called.
        self.mode = dutil.Mode.Static

    ## Initializes the analog inputs based on the object's configuration.
    #  @param self The object pointer.
    #  @param physicalChannel A string representing the device and analog
    #  input channels. Example Value: "PXI1Slot3/ao0:7"
    def init(self, physicalChannel):
        self.__createTask(physicalChannel)
        self.getNumChannels()
        self.initialized = True

        #Static Mode
        if self.mode == dutil.Mode.Static:
            self.setSampleRate(self._sampleRate)
            self.setSamplesPerChannel(1)

    def __createTask(self, physicalChannel):
        """
        This is a private method that creates the Task object for use inside the
        AnalogInput class."""
        terminalConfig = DAQmx_Val_Cfg_Default
        self.status = self.taskRef.CreateAIVoltageChan(physicalChannel, "",
                terminalConfig, -10, 10, DAQmx_Val_Volts, None)

    ## This function returns the sample rate configured in the DAQmx Task.
    #  @param self The object pointer.
    def getSampleRate(self):
        if self.initialized:
            sampleRate = float64()
            self.status = self.taskRef.GetSampClkRate(ctypes.byref(sampleRate))
            self._sampleRate = sampleRate.value
        return self._sampleRate

    ## This funciton sets the sample rate in the DAQmx Task.
    #  @param self The object pointer.
    #  @param value The value of the sample rate.
    def setSampleRate(self, value):
        if self.initialized:
            self.status = self.taskRef.SetSampClkRate(float64(value))
        self._sampleRate = value

    sampleRate = property(getSampleRate, setSampleRate)

    ## This function returns the samples per channel configured in the DAQmx Task.
    #  @param self The object pointer.
    def getSamplesPerChannel(self):
        if self.initialized:
            samplesPerChannel = uInt64()
            self.status = self.taskRef.GetSampQuantSampPerChan(
                    ctypes.byref(samplesPerChannel))
            self._samplesPerChannel = samplesPerChannel.value
        return self._samplesPerChannel

    ## This function sets the samples per channel in the DAQmx Task.
    #  @param self The object pointer.
    #  @param value The value to set the samples per channel.
    def setSamplesPerChannel(self, value):
        if self.initialized:
            self.status = self.taskRef.SetSampQuantSampPerChan(uInt64(value))
        self._samplesPerChannel = value

    samplesPerChannel = property(getSamplesPerChannel, setSamplesPerChannel)

    ## This function returns the number of channels configured in the DAQmx Task.
    #  @param self The object pointer.
    def getNumChannels(self):
        if self.initialized:
            numChannels = uInt32()
            self.status = self.taskRef.GetTaskNumChans(ctypes.byref(numChannels))
            self._numChannels = numChannels.value
        return self._numChannels 

    numChannels = property(getNumChannels)

    ## This function reads the data from the analogn input based on previous
    #  configuration.
    #  @param self The object reference.
    def read(self):
        timeout = float64(self.timeout)
        arraySize = uInt32(self._numChannels * self._samplesPerChannel)
        readArray = numpy.zeros((arraySize.value,), dtype = numpy.float64)
        samplesRead = int32()
        self.taskRef.ReadAnalogF64(self._samplesPerChannel, timeout,
                DAQmx_Val_GroupByChannel, readArray, arraySize,
                ctypes.byref(samplesRead), None) 
        return readArray
    
    ## This function will close connection to the analog output device and channels.
    #  @param self The object pointer.
    def close(self):
        self.initialized = False
        '''
        if self.startTriggerSyncCard != '':
            DAQmxDisconnectTerms(self._startTriggerSource, self.startTriggerSyncCard)
        '''    
        self.status = self.taskRef.ClearTask()
        self.taskRef = Task()

    ## This is the destructor for the AnalogInput Class.
    #  @param self The object pointer.
    def __del__(self):
        if self.initialized:
            self.close()
Example #2
0
class daq(object):
    """This class prepares and configures a DAQ system for an analog adquisition. The required
    arguments are the name of the device as a string (p.e. 'Dev3'), the adquisition time in seconds
    (adqTime), the sampling frequency in Hz (adqFreq), the channels to read as a list of integer values
    with the available channels, the voltage range of the channels as a list with the maximum positive
    voltage value and with the same length as the channel list.
    
    Optional arguments:
        - mode = 'FiniteSamps': sets the adquisiton mode to finite sampling (default) or continuous 'ContSamps'
        - trigger = None: sets the trigger mode. If None it is taken as the clock edge. Otherwise,
                    a 2-element list can be passed, the first value being the channel number and the second
                    the voltage value to configure the trigger to an analog channel in rising mode.
    
    This class only contemplates reading volts signal of analog inputs in differential configuration.
    Future versions might implement other possibilities."""
    def __init__(self,
                 device,
                 adqTime,
                 adqFreq,
                 list_channels,
                 rang_channels,
                 mode='FiniteSamps',
                 trigger=None,
                 terminalConfig='diff'):
        """This will configure the DAQ and Task for the specified configuration"""
        self.device = device
        self.adqTime = adqTime  # In seconds
        self.adqFreq = adqFreq
        self.list_channels = list_channels
        self.rang_channels = rang_channels
        self.mode = mode
        self.N_samples = int(adqTime * adqFreq)
        self.N_channels = len(list_channels)
        if terminalConfig is 'diff':
            self.terminalConfig = DAQmx_Val_Diff
        elif terminalConfig is 'SE':
            self.terminalConfig = DAQmx_Val_RSE
        else:
            raise Error(
                'Terminal configuration "{}" not known'.format(terminalConfig))
        print('I will adquire {} samples for each {} channels'.format(
            self.N_samples, self.N_channels))
        # DAQmx Configure Code
        # We create a Task instance
        self.ai = Task()
        # Prepare the type of variable that it returns using the library ctypes that work with C-functions
        self.read = int32()
        # The vector data will contain the output of the DAQ card in a single vector with the data from different channels
        # in a single 1-D vector with the data concatenated
        self.data = np.zeros((self.N_samples * self.N_channels, ),
                             dtype=np.float64)
        #self.ai = Task()
        # This prepares the string that is needed for the ``CreateAIVoltageChan`` depending on the number of channels to
        # read
        for channel, Vrange in zip(self.list_channels, self.rang_channels):
            str_channels = r"{}/ai{:d}".format(self.device, channel)
            #print(r"{}/ai{:d}".format(self.device,channel) )
            self.ai.CreateAIVoltageChan(str_channels, "", self.terminalConfig,
                                        -1.0 * Vrange, Vrange, DAQmx_Val_Volts,
                                        None)

        if mode is 'FiniteSamps':
            self.ai.CfgSampClkTiming("", self.adqFreq, DAQmx_Val_Rising,
                                     DAQmx_Val_FiniteSamps, self.N_samples)
        elif mode is 'ContSamps':
            self.ai.CfgSampClkTiming("", self.adqFreq, DAQmx_Val_Rising,
                                     DAQmx_Val_ContSamps, self.N_samples)
        else:
            raise Error('Mode not known')
        if trigger is None:
            pass
        else:
            self.ai.CfgAnlgEdgeStartTrig(
                r"{}/ai{:d}".format(self.device, trigger[0]),
                DAQmx_Val_RisingSlope, trigger[1])
        # In the case the DAQ accept a trigger from one of the analog channels we could also setup it as
        #
    def start(self):
        self.ai.StartTask()

    def stop(self):
        self.ai.StopTask()
        self.data = np.zeros((self.N_samples * self.N_channels, ),
                             dtype=np.float64)

    def read_analog(self, timeout=10.0):
        """Calls the ReadAnalogF64 with the configured parameters.
        
        Optional arguments:
            - timeout = 10.0: timeout in number of seconds.
        """
        self.ai.ReadAnalogF64(self.N_samples, timeout,
                              DAQmx_Val_GroupByChannel,
                              self.data, self.N_samples * self.N_channels,
                              byref(self.read), None)
        return self.data.reshape((self.N_samples, self.N_channels), order="F")

    def clear(self):
        self.ai.ClearTask()
# In[40]:

#Setup the data that will be output on the trigger
AO_task.WriteAnalogF64(num_AO_samples, 0, 10.0, ni.DAQmx_Val_GroupByChannel,
                       waveform, ni.byref(written), None)

# In[41]:

AI_task.StartTask()  #This will start on the trigger
AO_task.StartTask()  #This will start on the trigger
triggerTask.StartTask()  # Start counter and trigger tasks

# In[42]:

# now, retrieve data
AI_task.ReadAnalogF64(num_AI_samples, 10.0, ni.DAQmx_Val_GroupByChannel, data,
                      num_AI_samples, ni.byref(read), None)

# In[43]:

# And clean up tasks:
AO_task.StopTask()
AI_task.StopTask()
triggerTask.StopTask()

# In[44]:

plt.plot(data)
plt.show()

# In[ ]: