Example #1
0
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)
Example #2
0
    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
Example #3
0
 def __init__(self, period=.1, duty_cycle=0.5, counter="Dev1/ctr0", reset=False):
     if reset:
         daq.DAQmxResetDevice(counter.split('/')[0])
     taskHandle = daq.TaskHandle()
     daq.DAQmxCreateTask("", daq.byref(taskHandle))
     daq.DAQmxCreateCOPulseChanFreq(taskHandle, counter, "", daq.DAQmx_Val_Hz, daq.DAQmx_Val_Low,
                                0.0, 1 / float(period), duty_cycle)
     daq.DAQmxCfgImplicitTiming(taskHandle, daq.DAQmx_Val_ContSamps, 1000)
     self.taskHandle = taskHandle
Example #4
0
def setup_hw_di(fs, lines, callback, callback_samples, start_trigger=None,
                clock=None, task_name='hw_di'):
    '''
    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(task_name)
    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)

    # M-series acquisition boards don't have a dedicated engine for digital
    # acquisition. Use a clock to configure the acquisition.
    if clock is not None:
        clock_task = create_task('{}_clock'.format(task_name))
        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'
        if start_trigger:
            mx.DAQmxCfgDigEdgeStartTrig(clock_task, start_trigger,
                                        mx.DAQmx_Val_Rising)
        setup_timing(task, clock, -1, None)
    else:
        setup_timing(task, fs, -1, start_trigger)

    cb_helper = DigitalSamplesAcquiredCallbackHelper(callback)
    cb_ptr = mx.DAQmxEveryNSamplesEventCallbackPtr(cb_helper)
    mx.DAQmxRegisterEveryNSamplesEvent(task, mx.DAQmx_Val_Acquired_Into_Buffer,
                                       int(callback_samples), 0, cb_ptr, None)

    task._cb_ptr = cb_ptr
    task._cb_helper = cb_helper
    task._initial_state = initial_state

    rate = ctypes.c_double()
    mx.DAQmxGetSampClkRate(task, rate)

    mx.DAQmxTaskControl(task, mx.DAQmx_Val_Task_Reserve)
    mx.DAQmxTaskControl(clock_task, mx.DAQmx_Val_Task_Reserve)

    return [task, clock_task]
    def set_odmr_length(self, length=100):
        """ Sets up the trigger sequence for the ODMR and the triggered microwave.

        @param int length: length of microwave sweep in pixel

        @return int: error code (0:OK, -1:error)
        """
        self._odmr_length = length
        try:
            daq.DAQmxCfgImplicitTiming(
                # define task
                self._scanner_clock_daq_task,
                daq.DAQmx_Val_FiniteSamps,
                self._odmr_length)
            # + 1)

        except BaseException:
            self.log.exception('Error while setting up ODMR counter.')
            return -1
        return 0
Example #6
0
    def set_up_scanner_clock(self, clock_frequency = None, clock_channel = None):
        """ Configures the hardware clock of the NiDAQ card to give the timing. 
        
        @param float clock_frequency: if defined, this sets the frequency of the clock
        @param string clock_channel: if defined, this is the physical channel of the clock
        
        @return int: error code (0:OK, -1:error)
        """ 
        
        if self._scanner_clock_daq_task != None:            
            self.logMsg('Another clock is already running, close this one first.', \
            msgType='error')
            return -1
        
        self._scanner_clock_daq_task = daq.TaskHandle()  # create handle for task, this task will generate pulse signal for photon counting
        if clock_frequency != None:
            self._scanner_clock_frequency = float(clock_frequency)
        if clock_channel != None:
            self._scanner_clock_channel = clock_channel
        
        daq.DAQmxCreateTask('', daq.byref(self._scanner_clock_daq_task))    # create task for pulse_out, here the parameter self.pulse_out_task has to be passed by reference (passing a pointer) 
        daq.DAQmxCreateCOPulseChanFreq( self._scanner_clock_daq_task,      # the task to which to add the channels that this function creates
                            		    self._scanner_clock_channel,  # use this counter; the name to assign to the created channel
										'Clock Task',    # name to assign to channel (NIDAQ uses by default the physical channel name as the virtual channel name. If name is specified, then you must use the name when you refer to that channel in other NIDAQ functions)
										daq.DAQmx_Val_Hz, #units
										daq.DAQmx_Val_Low, #idle state
										0, #initial delay
										self._scanner_clock_frequency / 2.,   #pulse frequency, divide by 2 such that length of semi period = count_interval
										0.5 ) #duty cycle of pulses, 0.5 such that high and low duration are both = count_interval
        
        # set timing to continuous, i.e. set only the number of samples to 
        # acquire or generate without specifying timing
        daq.DAQmxCfgImplicitTiming( self._scanner_clock_daq_task,  #define task
                                    daq.DAQmx_Val_ContSamps,  #continuous running
                                    1000) #buffer length
                                    
        daq.DAQmxStartTask(self._scanner_clock_daq_task) 
                       
        return 0
Example #7
0
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]
    def set_up_clock(self,
                     clock_frequency=None,
                     clock_channel=None,
                     scanner=False,
                     idle=False,
                     delay=2.0):
        """ Configures the hardware clock of the NiDAQ card to give the timing.

        @param float clock_frequency: if defined, this sets the frequency of
                                      the clock in Hz
        @param string clock_channel: if defined, this is the physical channel
                                     of the clock within the NI card.
        @param bool scanner: if set to True method will set up a clock function
                             for the scanner, otherwise a clock function for a
                             counter will be set.
        @param bool idle: set whether idle situation of the counter (where
                          counter is doing nothing) is defined as
                                True  = 'Voltage High/Rising Edge'
                                False = 'Voltage Low/Falling Edge'

        @return int: error code (0:OK, -1:error)
        """

        if not scanner and self._clock_daq_task is not None:
            self.log.error(
                'Another counter clock is already running, close this one first.'
            )
            return -1

        if scanner and self._scanner_clock_daq_task is not None:
            self.log.error(
                'Another scanner clock is already running, close this one first.'
            )
            return -1

        # Create handle for task, this task will generate pulse signal for
        # photon counting
        my_clock_daq_task = daq.TaskHandle()
        smiq = daq.TaskHandle()
        switch = daq.TaskHandle()
        cam = daq.TaskHandle()

        # assign the clock frequency, if given
        if clock_frequency is not None:
            if not scanner:
                self._clock_frequency = float(clock_frequency)
            else:
                self._scanner_clock_frequency = float(clock_frequency)
                self._smiq_clock_frequency = float(clock_frequency) / 2.
                self._switch_clock_frequency = float(clock_frequency) / 2.
                self._cam_clock_frequency = float(clock_frequency)
        else:
            if not scanner:
                self._clock_frequency = self._default_clock_frequency
            else:
                self._scanner_clock_frequency = self._default_scanner_clock_frequency

        # use the correct clock in this method
        if scanner:
            my_clock_frequency = self._scanner_clock_frequency * 2
        else:
            my_clock_frequency = self._clock_frequency * 2

        # assign the clock channel, if given
        if clock_channel is not None:
            if not scanner:
                self._clock_channel = clock_channel
            else:
                self._scanner_clock_channel = clock_channel

        # use the correct clock channel in this method
        if scanner:
            my_clock_channel = self._scanner_clock_channel
            self._smiq_channel = self._smiq_channel
            self._switch_channel = self._switch_channel
            self._cam_channel = self._cam_channel
        else:
            my_clock_channel = self._clock_channel

        # check whether only one clock pair is available, since some NI cards
        # only one clock channel pair.
        if self._scanner_clock_channel == self._clock_channel:
            if not ((self._clock_daq_task is None) and
                    (self._scanner_clock_daq_task is None)):
                self.log.error(
                    'Only one clock channel is available!\n'
                    'Another clock is already running, close this one first '
                    'in order to use it for your purpose!')
                return -1
        if self.pseudo_pulsed:
            self.clock_duty = self.duty_value / (
                1 / self._scanner_clock_frequency) / 2
            self.switch_duty = self.duty_value / (
                1 / self._switch_clock_frequency) / 2
            self.switch_delay = 0
        else:
            self.clock_duty = 0.9998
            self.switch_duty = 0.5
            self.switch_delay = 0
        # Adjust the idle state if necessary
        my_idle = daq.DAQmx_Val_High if idle else daq.DAQmx_Val_Low
        try:
            # create task for clock
            task_name = 'ScannerClock' if scanner else 'CounterClock'
            daq.DAQmxCreateTask(task_name, daq.byref(my_clock_daq_task))

            # create a digital clock channel with specific clock frequency:
            daq.DAQmxCreateCOPulseChanFreq(
                # The task to which to add the channels
                my_clock_daq_task,
                # which channel is used?
                my_clock_channel,
                # Name to assign to task (NIDAQ uses by # default the physical channel name as
                # the virtual channel name. If name is specified, then you must use the name
                # when you refer to that channel in other NIDAQ functions)
                'Clock Producer',
                # units, Hertz in our case
                daq.DAQmx_Val_Hz,
                # idle state
                my_idle,
                # initial delay
                delay,
                my_clock_frequency / 2,
                self.clock_duty)

            daq.DAQmxCfgImplicitTiming(
                # Define task
                my_clock_daq_task,
                daq.DAQmx_Val_ContSamps,
                # buffer length which stores temporarily the number of
                # generated samples
                1000)
            ##############################
            # Configure SMIQ trigger clock
            ##############################
            duty_cycle = 0.1
            d = 0
            daq.DAQmxCreateTask('mySmiqTask', daq.byref(smiq))
            # Create channel to generate digital pulses that freq and dutyCycle
            # define and adds the channel to the task
            daq.DAQmxCreateCOPulseChanFreq(
                smiq,
                self.
                _smiq_channel,  # The name of the counter to use to create virtual channels
                "mySmiqChannel",  # The name to assign to the created virtual channel
                daq.DAQmx_Val_Hz,  # The units in which to specify freq.
                daq.DAQmx_Val_Low,  # The resting state of the output terminal.
                d,
                # The amount of time in seconds to wait before generating the
                # first pulse.
                self._smiq_clock_frequency,
                # The frequency at which to generate pulses.
                duty_cycle,
                # The width of the pulse divided by the pulse period.
            )

            j = 1000
            # # Sets only the number of samples to acquire or generate without specifying timing.
            daq.DAQmxCfgImplicitTiming(
                smiq,
                # daq.DAQmx_Val_ContSamps,
                daq.DAQmx_Val_ContSamps,
                # Acquire or generate samples until you stop the task.
                j  # the buffer size
            )
            daq.DAQmxCfgDigEdgeStartTrig(smiq,
                                         my_clock_channel + 'InternalOutput',
                                         daq.DAQmx_Val_Rising)
            ##############################
            # Configure switch trigger clock
            ##############################
            duty_cycle = 0.5
            d = 0
            daq.DAQmxCreateTask('mySwitchTask', daq.byref(switch))
            # Create channel to generate digital pulses that freq and dutyCycle
            # define and adds the channel to the task
            daq.DAQmxCreateCOPulseChanFreq(
                switch,
                self.
                _switch_channel,  # The name of the counter to use to create virtual channels
                "mySwitchChannel",  # The name to assign to the created virtual channel
                daq.DAQmx_Val_Hz,  # The units in which to specify freq.
                daq.DAQmx_Val_High,
                # The resting state of the output terminal.
                self.switch_delay,
                # The amount of time in seconds to wait before generating the
                # first pulse.
                self._switch_clock_frequency,
                # The frequency at which to generate pulses.
                self.switch_duty,
                # The width of the pulse divided by the pulse period.
            )

            j = 1000
            # # Sets only the number of samples to acquire or generate without specifying timing.
            daq.DAQmxCfgImplicitTiming(
                switch,
                # daq.DAQmx_Val_ContSamps,
                daq.DAQmx_Val_ContSamps,
                # Acquire or generate samples until you stop the task.
                j  # the buffer size
            )
            daq.DAQmxCfgDigEdgeStartTrig(switch,
                                         my_clock_channel + 'InternalOutput',
                                         daq.DAQmx_Val_Rising)
            ##############################
            # Configure cam trigger clock
            ##############################
            duty_cycle = 0.1
            d = (1. / self._cam_clock_frequency) / 4.
            d = 0
            daq.DAQmxCreateTask('myCamTask', daq.byref(cam))
            # Create channel to generate digital pulses that freq and dutyCycle
            # define and adds the channel to the task
            daq.DAQmxCreateCOPulseChanFreq(
                cam,
                self.
                _cam_channel,  # The name of the counter to use to create virtual channels
                "myCamChannel",  # The name to assign to the created virtual channel
                daq.DAQmx_Val_Hz,  # The units in which to specify freq.
                daq.DAQmx_Val_Low,  # The resting state of the output terminal.
                d,
                # The amount of time in seconds to wait before generating the
                # first pulse.
                self._cam_clock_frequency,
                # The frequency at which to generate pulses.
                duty_cycle,
                # The width of the pulse divided by the pulse period.
            )

            j = 1000
            # # Sets only the number of samples to acquire or generate without specifying timing.
            daq.DAQmxCfgImplicitTiming(
                cam,
                # daq.DAQmx_Val_ContSamps,
                daq.DAQmx_Val_ContSamps,
                # Acquire or generate samples until you stop the task.
                j  # the buffer size
            )
            daq.DAQmxCfgDigEdgeStartTrig(cam,
                                         my_clock_channel + 'InternalOutput',
                                         daq.DAQmx_Val_Rising)

            if scanner:
                self._scanner_clock_daq_task = my_clock_daq_task
                # Added the daq tasks to class variables
                self._smiq_clock_daq_task = smiq
                self._switch_clock_daq_task = switch
                self._cam_clock_daq_task = cam
            else:
                # actually start the preconfigured clock task
                daq.DAQmxStartTask(my_clock_daq_task)
                self._clock_daq_task = my_clock_daq_task
        except BaseException:
            self.log.exception('Error while setting up clock.')
            return -1
        return 0
Example #9
0
    def create_task(self):

        # need to check if task exists and fail

        #self.task = PyDAQmx.Task()
        self.task_handle = mx.TaskHandle(0)
        mx.DAQmxCreateTask("", byref(self.task_handle))

        if self.mode == 'large_range':
            logger.debug('counter_chan {}'.format(self.counter_chan))
            logger.debug('input_terminal {}'.format(self.input_terminal))

            mx.DAQmxCreateCIFreqChan(
                self.task_handle,
                counter=str(self.counter_chan),
                nameToAssignToChannel="",
                minVal=5e1,  # applies measMethod is DAQmx_Val_LargeRng2Ctr
                maxVal=1e8,  # applies measMethod is DAQmx_Val_LargeRng2Ctr
                units=DAQmx_Val_Hz,
                edge=DAQmx_Val_Rising,
                measMethod=DAQmx_Val_LargeRng2Ctr,
                measTime=1.0,  # applies measMethod is DAQmx_Val_HighFreq2Ctr
                divisor=100,  # applies measMethod is DAQmx_Val_LargeRng2Ctr
                customScaleName=None,
            )
        elif self.mode == 'high_freq':
            mx.DAQmxCreateCIFreqChan(
                self.task_handle,
                counter=self.counter_chan,
                nameToAssignToChannel="",
                minVal=1e1,  # applies measMethod is DAQmx_Val_LargeRng2Ctr
                maxVal=1e7,  # applies measMethod is DAQmx_Val_LargeRng2Ctr
                units=DAQmx_Val_Hz,
                edge=DAQmx_Val_Rising,
                measMethod=DAQmx_Val_HighFreq2Ctr,
                measTime=0.05,  # applies measMethod is DAQmx_Val_HighFreq2Ctr
                divisor=100,  # applies measMethod is DAQmx_Val_LargeRng2Ctr
                customScaleName=None,
            )
        elif self.mode == 'low_freq':
            mx.DAQmxCreateCIFreqChan(
                self.task_handle,
                counter=self.counter_chan,
                nameToAssignToChannel="",
                minVal=1e1,  # applies measMethod is DAQmx_Val_LargeRng2Ctr
                maxVal=1e7,  # applies measMethod is DAQmx_Val_LargeRng2Ctr
                units=DAQmx_Val_Hz,
                edge=DAQmx_Val_Rising,
                measMethod=DAQmx_Val_LowFreq1Ctr,
                measTime=0.05,  # applies measMethod is DAQmx_Val_HighFreq2Ctr
                divisor=100,  # applies measMethod is DAQmx_Val_LargeRng2Ctr
                customScaleName=None,
            )

        ### data = c_int32(0)
        ### self.task.GetCIDataXferMech(channel=self.counter_chan, data=data )
        ### print "XFmethod" , data.value

        # set DMA
        #self.task.SetCIDataXferMech(channel=self.counter_chan, data=DAQmx_Val_DMA)

        ### self.task.GetReadOverWrite(data=byref(data))
        ### print "overwrite", data.value

        #Set the input terminal of the counter
        mx.DAQmxSetCIFreqTerm(self.task_handle,
                              channel=self.counter_chan,
                              data=self.input_terminal)

        #Set the counter channel to continuously sample into a buffer.  The size of the
        #buffer is set by sampsPerChan.
        mx.DAQmxCfgImplicitTiming(self.task_handle,
                                  sampleMode=DAQmx_Val_ContSamps,
                                  sampsPerChan=1000)

        mx.DAQmxSetReadOverWrite(self.task_handle,
                                 DAQmx_Val_OverwriteUnreadSamps)

        ### self.task.GetReadOverWrite(data=byref(data))
        ### print "overwrite", data.value

        # Sample buffer
        self._sample_buffer_count = c_int32(0)
        self.sample_buffer = np.zeros((SAMPLE_BUFFER_SIZE, ), dtype=np.float64)
Example #10
0
 def set_up_counter(self, counter_channel = None, photon_source = None, clock_channel = None):
     """ Configures the actual counter with a given clock. 
     
     @param string counter_channel: if defined, this is the physical channel of the counter
     @param string photon_source: if defined, this is the physical channel where the photons are to count from
     @param string clock_channel: if defined, this specifies the clock for the counter
     
     @return int: error code (0:OK, -1:error)
     """
     
     if self._clock_daq_task == None and clock_channel == None:            
         self.logMsg('No clock running, call set_up_clock before starting the counter.', \
         msgType='error')
         return -1
     if self._counter_daq_task != None:            
         self.logMsg('Another counter is already running, close this one first.', \
         msgType='error')
         return -1
         
     self._counter_daq_task = daq.TaskHandle()  # this task will count photons with binning defined by pulse_out_task
     if counter_channel != None:
         self._counter_channel = counter_channel
     if photon_source != None:
         self._photon_source = photon_source
     
     if clock_channel != None:
         my_clock_channel = clock_channel
     else: 
         my_clock_channel = self._clock_channel
     
     daq.DAQmxCreateTask('', daq.byref(self._counter_daq_task))  # create task for counter_in, here the parameter self.counter_in_task has to be passed by reference (passing a pointer) 
     
     # set up semi period width measurement in photon ticks, i.e. the width
     # of each pulse (high and low) generated by pulse_out_task is measured
     # in photon ticks.
     #   (this task creates a channel to measure the time between state 
     #    transitions of a digital signal and adds the channel to the task 
     #    you choose)
     daq.DAQmxCreateCISemiPeriodChan(self._counter_daq_task,    # The task to which to add the channels that this function creates
                                     self._counter_channel,  # use this counter; the name to assign to the created channel
                                     'Counting Task',  #name
                                     0,  #expected minimum value
                                     self._max_counts/2./self._clock_frequency,    #expected maximum value
                                     daq.DAQmx_Val_Ticks, #units of width measurement, here photon ticks
                                     '')   
     
     # set the pulses to counter self._trace_counter_in
     daq.DAQmxSetCISemiPeriodTerm( self._counter_daq_task, self._counter_channel, my_clock_channel+'InternalOutput')
     # set the timebase for width measurement as self._photon_source
     daq.DAQmxSetCICtrTimebaseSrc( self._counter_daq_task, self._counter_channel, self._photon_source )  
     
     daq.DAQmxCfgImplicitTiming( self._counter_daq_task,
                                 daq.DAQmx_Val_ContSamps, 
                                 1000)
     # read most recent samples
     daq.DAQmxSetReadRelativeTo(self._counter_daq_task, daq.DAQmx_Val_CurrReadPos) 
     daq.DAQmxSetReadOffset(self._counter_daq_task, 0) 
     
     #unread data in buffer will be overwritten
     daq.DAQmxSetReadOverWrite(self._counter_daq_task, daq.DAQmx_Val_DoNotOverwriteUnreadSamps) 
     
     daq.DAQmxStartTask(self._counter_daq_task) 
     
     return 0