class DigitalOutput(object): ## 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 function sets the sample rate in the DAQmx Task. # @param self The object pointer. # @param value The value to set the sample rate. def setSampleRate(self, value): if self.initialized: self.status = self.taskRef.SetSampClkRate(float64(value)) self._sampleRate = value ## This function deletes the sample rate variable inside the DigitalOutput # object. # @param self The object pointer. def _delSampleRate(self): del self._sampleRate sampleRate = property(getSampleRate, setSampleRate, _delSampleRate, doc= """The sample rate of the digital output.""") #-- Samples Per Channel Property ## 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 ## This function deletes the samplesPerChannel variable from the DigitalOutput # object. # @param self The object pointer. def _delSamplesPerChannel(self): del self._samplesPerChannel samplesPerChannel = property(getSamplesPerChannel, setSamplesPerChannel, _delSamplesPerChannel, """The samples per channel of the digital output.""") #-- Clock Source Property ## This function returns the sample clock source configured in the DAQmx Task. # @param self The object pointer. def getClkSource(self): if self.initialized: buffSize = uInt32(255) buff = ctypes.create_string_buffer(buffSize.value) self.status = self.taskRef.GetSampClkSrc(buff, buffSize) self._clkSource = buff.value return self._clkSource ## This function sets the sample clock source in the DAQmx Task. # @param self The object pointer. # @param value The value to set the clock source. def setClkSource(self, value): if self.initialized: self.status = self.taskRef.SetSampClkSrc(value) value = self.getClkSource() self._clkSource = value ## This function deletes the clkSource variable within the DigitalOutput # object. # @param self The object pointer. def _delClkSource(self): del self._clkSource clkSource = property(getClkSource, setClkSource, _delClkSource, """The clock source for the digital outputsample clock.""") #-------------------- Functions -------------------- ## This function is a constructor for the DigitalOutput class. # # It creates the internal variables required to perform functions within # the class. This function does not initialize any hardware. # @param self This object pointer def __init__(self): ## The DAQmx task reference. self.taskRef = Task() ## 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() ## This is a boolean that is true when the DAQmx task has been # initialized. self.initialized = False ## @var sampleRate # This is the sample rate of the digital output. self._sampleRate = 100e3 ## @var samplesPerChannel # This is the number of samples per channel that will be generated in # Finite mode. self._samplesPerChannel = 100 ## @var clkSource # This is the sample clock source terminal. It can be set to an # internal clock or external clock such as a PFI line i.e. "/PXI1Slot3/PFI15." self._clkSource = '' ## This is the mode of operation for the digital outputs. # # There are currently three modes available. Static mode is where one # static digital sample is set with no need for a sample clock. # Finite mode is where a finite number of digital samples will be set # 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.Finite ## The number of time to iterate over a Finite number of samples. # # This value is only useful in the "Finite" mode. It is the number of # times that a sequence of digital samples will be looped. The default # is allways 1. self.loops = 1 ## Initialize the digital outputs based on the object's configuration. # @param self The object pointer. # @param physicalChannel A string representing the device and digital # output channels. Example value: "PXI1Slot3/ao0:7" def init(self, physicalChannel): self.__createTask(physicalChannel) self.initialized = True #Finite Mode if self.mode == dutil.Mode.Finite: self.status = self.taskRef.SetWriteRegenMode(DAQmx_Val_AllowRegen) self.__configTiming(DAQmx_Val_FiniteSamps) #Continuous Mode if self.mode == dutil.Mode.Continuous: self.status = self.taskRef.SetWriteRegenMode(DAQmx_Val_AllowRegen) self.__configTiming(DAQmx_Val_ContSamps) #Static Mode if self.mode == dutil.Mode.Static: pass ## This function returns a random 1D numpy array of samples for writing the # buffer of digital output channels. # @param self The objet pointer. def createTestBuffer(self): data = numpy.random.rand(self._samplesPerChannel) data = numpy.ubyte(data * 255) return data ## This function returns the number of digital lines configured in the DAQmx # Task. # @param self The object pointer. def getNumLines(self): numLines = uInt32() #bufferSize = 255 #channel = ctypes.create_string_buffer(bufferSize) #self.taskRef.GetTaskChannels(channel, bufferSize) #print channel.value self.taskRef.GetDONumLines('', ctypes.byref(numLines)) return numLines.value ## This function returns the number of digital channels configured in the # DAQmx Task. # @param self The object pointer. def getNumChannels(self): numChannels = uInt32() self.taskRef.GetTaskNumChans(ctypes.byref(numChannels)) return numChannels.value ## This function writes the specified values into the buffer. # @param self The object pointer. # @param data This is a 1D 8-bit unsigned integer array that contians samples for # each digital channel. Channels are non-interleaved (channel1 n-samples # then channel2 n-samples). def writeToBuffer(self, data): autostart = self.mode == dutil.Mode.Static samplesWritten = int32() self.status = self.taskRef.WriteDigitalU8(self._samplesPerChannel, autostart, 10, DAQmx_Val_GroupByChannel, data, ctypes.byref(samplesWritten), None) #print 'Samples Written: ' + str(samplesWritten.value) return samplesWritten.value ## This function starts the digital output generation. # @param self The object pointer. def start(self): self.status = self.taskRef.StartTask() ## This functions waits for the digital output generation to complete. # @param self The object pointer. def waitUntilDone(self): sampPerChan = uInt64() self.status = self.taskRef.GetSampQuantSampPerChan( ctypes.byref(sampPerChan)) #print 'DO Samples Per Channel: ' + str(sampPerChan.value) estAcqTime = (self.loops * sampPerChan.value) / self._sampleRate #print "Estimated Acquisition Time: " + str(estAcqTime) if self.mode != dutil.Mode.Static: self.status = self.taskRef.WaitUntilTaskDone(float64(estAcqTime + 0.1)) ## This function stops the digital output generation. # @param self The object pointer. def stop(self): self.status = self.taskRef.StopTask() ## This is a private method that creates the Task object for use inside the # DigitalOutput class. def __createTask(self, physicalChannel): self.status = self.taskRef.CreateDOChan(physicalChannel, '', DAQmx_Val_ChanForAllLines) ## This is a private method that configures the timing for the DigitalOutput # class. # @param self The object pointer. def __configTiming(self, sampleMode): totalSamples = self._samplesPerChannel * self.loops self.taskRef.CfgSampClkTiming(self._clkSource, float64(self._sampleRate), DAQmx_Val_Falling, sampleMode, uInt64(totalSamples)) ## This function will close connection to the digital ouput device and # channels. # @param self The object pointer. def close(self): """""" self.initialized = False self.status = self.taskRef.ClearTask() self.taskRef = Task() ## This is the destructor for the DigitalOutput Class. # @param self The object pointer. def __del__(self): if self.initialized: self.close() del self.taskRef del self.status del self.initialized del self.sampleRate del self.samplesPerChannel del self.clkSource del self.mode del self.loops
class digFreqGenerator(object): def __init__(self): self.counter = '' self.Task = Task() self.initialized = False self.initialDelay = 0 self.dutyCycle = 0.50 self.frequency = 1e6 self._numberOfPulses = 0 self.status = 0 self._startTriggerSource = '' self.triggerType = TriggerType.Software self.timeout = -1 def _getStartTriggerSource(self): if self.initialized: buffSize = uInt32(255) buff = ctypes.create_string_buffer(buffSize.value) self.status = self.Task.GetDigEdgeStartTrigSrc(buff, buffSize) self._startTriggerSource = buff.value return self._startTriggerSource def _setStartTriggerSource(self, value): if self.initialized: self.status = self.Task.SetDigEdgeStartTrigSrc(value) #value = self._getStartTriggerSource() self._startTriggerSource = value startTriggerSource = property(_getStartTriggerSource, _setStartTriggerSource) def _getNumberOfPulses(self): if self.initialized: sampPerChan = uInt32() self.status = self.Task.GetSampQuantSampPerChan(sampPerChan) self._numberOfPulses = sampPerChan.value return self._numberOfPulses def _setNumberOfPulses(self, value): if self.initialized: self.status = self.Task.SetSampQuantSampPerChan(value) if value > 0: self.status = self.Task.SetSampQuantSampMode( DAQmx_Val_FiniteSamps) else: self.status = self.Task.SetSampQuantSampMode( DAQmx_Val_ContSamps) self._numberOfPulses = value numberOfPulses = property(_getNumberOfPulses, _setNumberOfPulses) def init(self, counter=None): if counter is not None: self.counter = counter self.status = self.Task.CreateCOPulseChanFreq(self.counter, '', DAQmx_Val_Hz, DAQmx_Val_Low, numpy.float64(self.initialDelay), numpy.float64(self.frequency), numpy.float64(self.dutyCycle)) if self._numberOfPulses > 0: self.status = self.Task.CfgImplicitTiming(DAQmx_Val_FiniteSamps, uInt64(self._numberOfPulses)) else: self.status = self.Task.CfgImplicitTiming(DAQmx_Val_ContSamps, uInt64(int(1e6))) if self.triggerType == TriggerType.Hardware: self.status = self.Task.CfgDigEdgeStartTrig( self._startTriggerSource, DAQmx_Val_Rising) self.status = self.Task.SetStartTrigRetriggerable(bool32(True)) self.initialized = True def _getOutputTerm(self): buffSize = uInt32(255) buff = ctypes.create_string_buffer(buffSize.value) self.status = self.Task.GetCOPulseTerm(self.counter, buff, buffSize) return buff.value def _setOutputTerm(self, term = 'PFI0'): self.status = self.Task.SetCOPulseTerm(self.counter, term) outputTerm = property(_getOutputTerm, _setOutputTerm) def start(self): self.status = self.Task.StartTask() def waitUntilDone(self): self.status = self.Task.WaitUntilTaskDone(self.timeout) def stop(self): retriggerable = bool32() self.status = self.Task.GetStartTrigRetriggerable(retriggerable) try: if retriggerable == 0: self.status = self.Task.StopTask() except DAQError as e: print(e.error) print(retriggerable.value) if e.error == 200010 and retriggerable.value == 1: print('caught') pass else: raise e def close(self): self.status = self.Task.ClearTask() self.Task = Task() self.initialized = False
class AnalogOutput(object): ## This function is a constructor for the AnalogOutput 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() ## This is a boolean that is true when the DAQmx task has been 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 output. self._sampleRate = 100e3 ## @var numChannels # This is the number of channels configured in the task. self._numChannels = 0 ## @var samplesPerChannel # This is the number of samples per channel that will be # generated in Finite mode. self._samplesPerChannel = 100 ## @var clkSource # This is the sample clock source terminal. It can be set to an # internal clock or external clock such as a PFI line i.e. "/PXI1Slot3/PFI15." self._clkSource = '' ## @var startTriggerSource # This is the start trigger source terminal. The software # ignores this value when the triggerType is set to "Software". Otherwise when # the triggerType is "Hardware," this terminal is used to start analog # generation. Example Value: "/PXI1Slot3/PFI0" self._startTriggerSource = '' ## @var pauseTriggerSource # The source terminal of the pause trigger. This can be # any PFI or backplane trigger such as 'PFI5' and 'PXI_TRIG5' self._pauseTriggerSource = '' ## This is the start trigger terminal of the NI-Sync card. # # Setting this value will make sure that the start trigger will be # propogated through the PXI backplane. If there is no sync card needed # leave the value default. self.startTriggerSyncCard = '' ## This is the mode of operation for the analog outputs. # # There are currently three modes available. Static mode is where one # static voltage is set with no need for a sample clock. Finite mode is # where a finite number of voltages will be set 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.Finite ## The trigger type for the analog outputs. # # There are currently two trigger types - "Software" and # "Hardware." The "Software" mode means that analog output channels are not # syncronized. While "Hardware" means that analog output channels are # syncronized to a start trigger. The startTriggerSouce attribute must be # configured appropriately. self.triggerType = dutil.TriggerType.Software ## The number of times to iterate over a Finite number of samples. # # This value is only useful in the "Finite" mode. It is the number of # times that a sequence of voltages will be looped. The default is allways 1. self.loops = 1 ## The estimated time to generate the samples for a Finite generation. # # Once the input buffer of the analog input is configured, the # amount of time it takes to generate the voltages in the buffer can be # estimated. This is a function of the sample rate and the number of samples # per channel. (This attribute is for internal use only. This attribute may # not return an accurate value.) self.estAcqTime = 0 ## The analog output buffer. # # This is the data that is stored in the buffer of the Analog Output card. self.buff = None self._timeoutPad = 0.01 def _getDone(self): done = bool32() if self.initialized: self.status = self.taskRef.GetTaskComplete(ctypes.byref(done)) else: done.value = 1 return bool(done.value) ## @var done # Returns the task done status. # # This mode works differently depending on the mode. <br /> # <ul> # <li><B>Static and Continuous</B>: done is false after a start # method and true</li> # only after a stop method. # <li><B>Finite</B>: done is false until all samples are # generated.</li></ul> done = property(_getDone) def _getPauseTriggerSource(self): if self.initialized: buffSize = uInt32(255) buff = ctypes.create_string_buffer(buffSize.value) self.status = self.taskRef.GetDigLvlPauseTrigSrc(buff, buffSize) self._pauseTriggerSource = buff.value return self._pauseTriggerSource def _setPauseTriggerSource(self, value): if self.initialized: if value == '': self.status = self.taskRef.SetPauseTrigType(DAQmx_Val_None) self.status = self.taskRef.ResetDigLvlPauseTrigSrc() else: self.status = self.taskRef.SetDigLvlPauseTrigWhen( DAQmx_Val_High) self.status = self.taskRef.SetPauseTrigType(DAQmx_Val_DigLvl) self.status = self.taskRef.SetDigLvlPauseTrigSrc(value) self._pauseTriggerSource = value pauseTriggerSource = property(_getPauseTriggerSource, _setPauseTriggerSource) ## Initializes the analog outputs based on the object's configuration. # @param self The object pointer. # @param physicalChannel A string representing the device and analog # output channels. Example Value: "PXI1Slot3/ao0:7" def init(self, physicalChannel): self.__createTask(physicalChannel) self.initialized = True #Finite Mode if self.mode == dutil.Mode.Finite: self.status = self.taskRef.SetWriteRegenMode(DAQmx_Val_AllowRegen) self.__configTiming(DAQmx_Val_FiniteSamps) #Continuous Mode elif self.mode == dutil.Mode.Continuous: self.status = self.taskRef.SetWriteRegenMode(DAQmx_Val_AllowRegen) self.__configTiming(DAQmx_Val_ContSamps) #Static Mode elif self.mode == dutil.Mode.Static: self.setSampleRate(self._sampleRate) self.setSamplesPerChannel(1) self.pauseTriggerSource = self._pauseTriggerSource #print self.samplesPerChannel #print self._sampleRate #print self.clkSource #print self.startTriggerSource ## 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 ## This funciton deletes the samplesPerChannel variable inside the AnalogOutput # object. # # It is an internal function that is called in the class destructor. It should # not be called. def _delSamplesPerChannel(self): """ This funciton deletes the samplesPerChannel variable inside the AnalogOutput object. It is an internal function that is called in the class destructor. It should not be called. """ del self._samplesPerChannel samplesPerChannel = property(getSamplesPerChannel, setSamplesPerChannel, _delSamplesPerChannel) ## This function returns the sample clock source configured in the DAQmx Task. # @param self The object pointer. def getClkSource(self): if self.initialized: buffSize = uInt32(255) buff = ctypes.create_string_buffer(buffSize.value) self.status = self.taskRef.GetSampClkSrc(buff, buffSize) self._clkSource = buff.value return self._clkSource ## This function sets the sample clock source in the DAQmx Task. # @param self The object pointer. # @param value The string value for the clock source terminal. def setClkSource(self, value): if self.initialized: self.status = self.taskRef.SetSampClkSrc(value) value = self.getClkSource() self._clkSource = value ## This function deletes the clkSource variable within the AnalogOutput object. # # It is an internal function that is called in the class destructor. It should # not be called. def _delClkSource(self): del self._clkSource clkSource = property(getClkSource, setClkSource, _delClkSource) ## This function return the start trigger source configured in the DAQmx Task. # @param self The object pointer. def getStartTriggerSource(self): if self.initialized: buffSize = uInt32(255) buff = ctypes.create_string_buffer(buffSize.value) self.status = self.taskRef.GetDigEdgeStartTrigSrc(buff, buffSize) self._startTriggerSource = buff.value return self._startTriggerSource ## This function sets the start trigger source in the DAQmx Task. # @param self The object pointer. # @param value The string vaue of the start trigger source. # Example value: "\PXI1Slot3\PFI0" def setStartTriggerSource(self, value): if self.initialized: self.status = self.taskRef.SetDigEdgeStartTrigSrc(value) value = self.getStartTriggerSource() self._startTriggerSource = value ## This function deletes the startTriggerSource variable within the AnalogOutput object. # # It is an internal function that is called in the class destructor. It should # not be called. def _delStartTriggerSource(self): del self._startTriggerSource startTriggerSource = property(getStartTriggerSource, setStartTriggerSource, _delStartTriggerSource) ## 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 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 ## This function deletes the sample rate variable inside the AnalogOutput object. # @param self The object pointer. def _delSampleRate(self): del self._sampleRate sampleRate = property(getSampleRate, setSampleRate, _delSampleRate) ## This function returns a 1D numpy array of samples with random voltages. # The returned value is intended to be used to write samples to the buffer with # the writeToBuffer() method. # @param self The object pointer. # @param numChannels The number of channels to generate. If this parameter is # not provided, Then the function will generate the number of channels configured # in the analog output task. def createTestBuffer(self, numChannels=0): numChannels = numChannels if numChannels > 0 else self.getNumChannels() return numpy.float64( numpy.random.rand(self._samplesPerChannel * numChannels)) ## This function returns a 1D numpy array of sine waves. The returned # value is intended to be used to write samples to the buffer with the # writeToBuffer() method. # @param self The object pointer. def createSineTestBuffer(self): from .createSineWave import createSineWave numChannels = self.getNumChannels() for i in range(numChannels): data = createSineWave(10, 100e3, self._sampleRate, self._samplesPerChannel, ((2 * numpy.pi) / numChannels) * i) if i == 0: sineData = data['amplitude'] else: sineData = numpy.append(sineData, data['amplitude']) return sineData ## This function writes the specified values into the buffer. # @param self The object pointer. # @param data This is a 1D 64-bit floating point numpy array that contians data # for each channel. Channels are non-interleaved (channel1 n-samples then # channel2 n-samples). def writeToBuffer(self, data): autostart = self.mode == dutil.Mode.Static self.buff = data samplesWritten = int32() self.status = self.taskRef.WriteAnalogF64(self._samplesPerChannel, autostart, 10, DAQmx_Val_GroupByChannel, data, ctypes.byref(samplesWritten), None) return samplesWritten.value ## This function starts the analog output generation. # @param self The object pointer. def start(self): self.status = self.taskRef.StartTask() ## This functions waits for the analog output generation to complete. # @param self The object pointer. def waitUntilDone(self): sampPerChan = uInt64() self.status = self.taskRef.GetSampQuantSampPerChan( ctypes.byref(sampPerChan)) self.estAcqTime = (self.loops * sampPerChan.value) / self._sampleRate #print 'SamplesPerChannel: ' + str(sampPerChan.value) #print 'Estimated Acquisition Time: ' + str(self.estAcqTime) #if (self.estAcqTime >= 0.01 and self.mode != dutil.Mode.Static): if self.mode != dutil.Mode.Static: self.status = self.taskRef.WaitUntilTaskDone( float64(self.estAcqTime + self._timeoutPad)) ## This function stops the analog output generation. # @param self The object pointer. def stop(self): self.status = self.taskRef.StopTask() def __createTask(self, physicalChannel): """ This is a private method that creates the Task object for use inside the AnalogOutput class.""" self.status = self.taskRef.CreateAOVoltageChan(physicalChannel, "", -10, 10, DAQmx_Val_Volts, None) def __configTiming(self, sampleMode): """ This is a private method that configures the timing for the Analog Output class. """ totalSamples = self._samplesPerChannel * self.loops onDemand = bool32() self.status = self.taskRef.GetOnDemandSimultaneousAOEnable( ctypes.byref(onDemand)) #print 'On Demand: ' + str(onDemand.value) #print 'Trigger Type: ' + str(self.triggerType) #print 'Software Trigger Type: ' + str(dutil.TriggerType.Software) if self.triggerType == dutil.TriggerType.Software: #print 'Software Timing' self.status = self.taskRef.CfgSampClkTiming( 'OnboardClock', float64(self._sampleRate), DAQmx_Val_Rising, sampleMode, uInt64(totalSamples)) elif self.triggerType == dutil.TriggerType.Hardware: #print 'Hardware Timing' self.status = self.taskRef.CfgSampClkTiming( self._clkSource, float64(self._sampleRate), DAQmx_Val_Falling, sampleMode, uInt64(totalSamples)) self.status = self.taskRef.CfgDigEdgeStartTrig( self._startTriggerSource, DAQmx_Val_Rising) if self.startTriggerSyncCard != '': DAQmxConnectTerms(self.startTriggerSyncCard, self._startTriggerSource, DAQmx_Val_DoNotInvertPolarity) ## 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 AnalogOutput Class. # @param self The object pointer. def __del__(self): if self.initialized: self.close() del self.taskRef del self.initialized del self.status del self.sampleRate del self._numChannels del self.samplesPerChannel del self.clkSource del self.startTriggerSource del self.startTriggerSyncCard del self.mode del self.triggerType del self.loops del self.estAcqTime
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()
class DigitalOutput(object): #-- Sample Rate Property ## This function returns the sample rate configured in the DAQmx Task. # @param self The object reference. def getSampleRate(self): if self.initialized: sampleRate = float64() self.status = self.taskRef.GetSampClkRate(ctypes.byref(sampleRate)) self._sampleRate = sampleRate.value return self._sampleRate ## This function sets the sample rate in the DAQmx Task. # @param self The object reference. # @param value The value to set the sample rate. def setSampleRate(self, value): if self.initialized: self.status = self.taskRef.SetSampClkRate(float64(value)) self._sampleRate = value ## This function deletes the sample rate variable inside the # DigitalOutput object. # @param self The object reference. def _delSampleRate(self): del self._sampleRate sampleRate = property(getSampleRate, setSampleRate, _delSampleRate, doc="""The sample rate of the digital output.""") #-- Samples Per Channel Property ## This function returns the samples per channel configured in the # DAQmx Task. # @param self The object reference. 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 reference. # @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 ## This function deletes the samplesPerChannel variable from the # DigitalOutput object. # @param self The object reference. def _delSamplesPerChannel(self): del self._samplesPerChannel samplesPerChannel = property( getSamplesPerChannel, setSamplesPerChannel, _delSamplesPerChannel, """The samples per channel of the digital output.""") #-- Clock Source Property ## This function returns the sample clock source configured in the # DAQmx Task. # @param self The object reference. def getClkSource(self): if self.initialized: buffSize = uInt32(255) buff = ctypes.create_string_buffer(buffSize.value) self.status = self.taskRef.GetSampClkSrc(buff, buffSize) self._clkSource = buff.value return self._clkSource ## This function sets the sample clock source in the DAQmx Task. # @param self The object reference. # @param value The value to set the clock source. def setClkSource(self, value): if self.initialized: self.status = self.taskRef.SetSampClkSrc(value) value = self.getClkSource() self._clkSource = value ## This function deletes the clkSource variable within the # DigitalOutput # object. # @param self The object reference. def _delClkSource(self): del self._clkSource clkSource = property( getClkSource, setClkSource, _delClkSource, """The clock source for the digital outputsample clock.""") #-- Start Trigger Property ## This function returns the start trigger source configured in the # DAQmx Task. # @param self The object reference. def _getStartTriggerSource(self): if self.initialized: buffSize = uInt32(255) buff = ctypes.create_string_buffer(buffSize.value) self.status = self.taskRef.GetDigEdgeStartTrigSrc(buff, buffSize) self._startTriggerSource = buff.value return self._startTriggerSource ## This function sets the start trigger source in the DAQmx Task. # @param self The object reference. # @param value The value to set the start trigger. def _setStartTriggerSource(self, value): if self.initialized: self.status = self.taskRef.SetDigEdgeStartTrigSrc(value) value = self.getStartTriggerSource() self._startTriggerSource = value startTriggerSource = property(_getStartTriggerSource, _setStartTriggerSource) #-- Done Property def _getDone(self): done = bool32() if self.initialized: self.status = self.taskRef.GetTaskComplete(ctypes.byref(done)) else: done.value = 1 return bool(done.value) ## @var done # Returns the task done status. # # This mode works differently depending on the mode. <br /> # <ul> # <li><B>Static and Continuous</B>: done is false after a start # method and true</li> # only after a stop method. # <li><B>Finite</B>: done is false until all samples are # generated.</li></ul> done = property(_getDone) #-- Pause Trigger Source def _getPauseTriggerSource(self): if self.initialized: buffSize = uInt32(255) buff = ctypes.create_string_buffer(buffSize.value) self.status = self.taskRef.GetDigLvlPauseTrigSrc(buff, buffSize) self._pauseTriggerSource = buff.value return self._pauseTriggerSource def _setPauseTriggerSource(self, value): if self.initialized: if value == '': self.status = self.taskRef.SetPauseTrigType(DAQmx_Val_None) self.status = self.taskRef.ResetDigLvlPauseTrigSrc() else: self.status = self.taskRef.SetDigLvlPauseTrigWhen( DAQmx_Val_High) self.status = self.taskRef.SetPauseTrigType(DAQmx_Val_DigLvl) self.status = self.taskRef.SetDigLvlPauseTrigSrc(value) self._pauseTriggerSource = value pauseTriggerSource = property(_getPauseTriggerSource, _setPauseTriggerSource) #-------------------- Functions -------------------- ## This function is a constructor for the DigitalOutput class. # # It creates the internal variables required to perform functions # within the class. This function does not initialize any hardware. # @param self This object reference def __init__(self): ## The DAQmx task reference. self.taskRef = Task() ## 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() ## This is a boolean that is true when the DAQmx task has been # initialized. self.initialized = False ## @var sampleRate # This is the sample rate of the digital output. self._sampleRate = 100e3 ## @var samplesPerChannel # This is the number of samples per channel that will be generated # in Finite mode. self._samplesPerChannel = 100 ## @var clkSource # This is the sample clock source terminal. It can be set to an # internal clock or external clock such as a PFI line i.e. # "/PXI1Slot3/PFI15." self._clkSource = '' ## @var startTriggerSource # This is the start trigger source terminal. It can be set to # a PFI line such as "/PXISlot3/PFI0" self._startTriggerSource = '' ## @var pauseTriggerSource # The source terminal of the pause trigger. This can be # any PFI or backplane trigger such as 'PFI5' and 'PXI_TRIG5' self._pauseTriggerSource = '' ## This is the mode of operation for the digital outputs. # # There are currently three modes available. Static mode is # where one static digital sample is set with no need for a # sample clock. Finite mode is where a finite number of digital # samples will be set 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.Finite self.triggerType = dutil.TriggerType.Software ## The number of time to iterate over a Finite number of samples. # # This value is only useful in the "Finite" mode. It is the # number of times that a sequence of digital samples will be # looped. The default is allways 1. self.loops = 1 ## The time in seconds to wait for a trigger or for a digital # state change. self.timeout = 1 self.timeoutPad = 10 self._pCh = '' ## Initialize the digital outputs based on the object's configuration. # @param self The object reference. # @param physicalChannel A string representing the device and digital # output channels. Example value: "PXI1Slot3/ao0:7" def init(self, physicalChannel): self._pCh = physicalChannel self.__createTask(physicalChannel) self.initialized = True #Finite Mode if self.mode == dutil.Mode.Finite: self.status = self.taskRef.SetWriteRegenMode(DAQmx_Val_AllowRegen) self.__configTiming(DAQmx_Val_FiniteSamps) #Continuous Mode if self.mode == dutil.Mode.Continuous: self.status = self.taskRef.SetWriteRegenMode(DAQmx_Val_AllowRegen) self.__configTiming(DAQmx_Val_ContSamps) #Static Mode if self.mode == dutil.Mode.Static: pass ## This function returns a random 1D numpy array of samples for # writing the buffer of digital output channels. # @param self The objet reference. def createTestBuffer(self): import numpy data = numpy.random.rand(self._samplesPerChannel) data = numpy.ubyte(data * 255) return data ## This function returns the number of digital lines configured in # the DAQmx Task. # @param self The object reference. def getNumLines(self): numLines = uInt32() #bufferSize = 255 #channel = ctypes.create_string_buffer(bufferSize) #self.taskRef.GetTaskChannels(channel, bufferSize) #print channel.value self.taskRef.GetDONumLines('', ctypes.byref(numLines)) return numLines.value ## This function returns the number of digital channels configured in # the DAQmx Task. # @param self The object reference. def getNumChannels(self): numChannels = uInt32() self.taskRef.GetTaskNumChans(ctypes.byref(numChannels)) return numChannels.value ## This function writes the specified values into the buffer. # @param self The object reference. # @param data This is a 1D 8-bit unsigned integer array that # contians samples for each digital channel. Channels are # non-interleaved (channel1 n-samples then channel2 n-samples). def writeToBuffer(self, data): autostart = self.mode == dutil.Mode.Static samplesWritten = int32() self.buff = data self.status = self.taskRef.WriteDigitalU8(self._samplesPerChannel, autostart, 10, DAQmx_Val_GroupByChannel, data, ctypes.byref(samplesWritten), None) #print 'Samples Written: ' + str(samplesWritten.value) return samplesWritten.value ## This function writes a static value to the digital line(s) # configured in the init() method. # @param self The object reference. # @param data The static value to send to the digital line(s). def writeStatic(self, data): if isinstance(data, bool) and data == True: digLineNum = int(self._pCh[len(self._pCh) - 1]) data = 2**digLineNum autostart = True self.status = self.taskRef.WriteDigitalScalarU32( autostart, float64(self.timeout), uInt32(data), None) ## This function starts the digital output generation. # @param self The object reference. def start(self): self.status = self.taskRef.StartTask() ## This functions waits for the digital output generation to complete. # @param self The object reference. def waitUntilDone(self): sampPerChan = uInt64() self.status = self.taskRef.GetSampQuantSampPerChan( ctypes.byref(sampPerChan)) #print 'DO Samples Per Channel: ' + str(sampPerChan.value) estAcqTime = (self.loops * sampPerChan.value) / self._sampleRate #print "Estimated Acquisition Time: " + str(estAcqTime) if self.mode != dutil.Mode.Static: self.status = self.taskRef.WaitUntilTaskDone( float64(estAcqTime + self.timeoutPad)) ## This function stops the digital output generation. # @param self The object reference. def stop(self): self.status = self.taskRef.StopTask() ## This is a private method that creates the Task object for use # inside the DigitalOutput class. def __createTask(self, physicalChannel): self.status = self.taskRef.CreateDOChan(physicalChannel, '', DAQmx_Val_ChanForAllLines) ## This is a private method that configures the timing for the # DigitalOutput class. # @param self The object reference. def __configTiming(self, sampleMode): totalSamples = self._samplesPerChannel * self.loops if self.triggerType == dutil.TriggerType.Software: self.status = self.taskRef.CfgSampClkTiming( self._clkSource, float64(self._sampleRate), DAQmx_Val_Falling, sampleMode, uInt64(totalSamples)) elif self.triggerType == dutil.TriggerType.Hardware: self.status = self.taskRef.CfgSampClkTiming( self._clkSource, float64(self._sampleRate), DAQmx_Val_Falling, sampleMode, uInt64(totalSamples)) self.status = self.taskRef.CfgDigEdgeStartTrig( self._startTriggerSource, DAQmx_Val_Falling) ## This function will close connection to the digital ouput device and # channels. # @param self The object reference. def close(self): self.initialized = False self.status = self.taskRef.ClearTask() self.taskRef = Task() ## This is the destructor for the DigitalOutput Class. # @param self The object reference. def __del__(self): if self.initialized: self.close() del self.taskRef del self.status del self.initialized del self.sampleRate del self.samplesPerChannel del self.clkSource del self.mode del self.loops del self.timeout del self.timeoutPad del self._pCh