From Friday, April 19th (11:00 PM CDT) through Saturday, April 20th (2:00 PM CDT), 2024, ni.com will undergo system upgrades that may result in temporary service interruption.

We appreciate your patience as we improve our online experience.

Counter/Timer

cancel
Showing results for 
Search instead for 
Did you mean: 

Synchroneusly start an analog in task and semi period measurement task in X devices

I am trying to synchronize analog input with timestamps for all edges produced by an encoder.

 

In the DAQ M Series that I was using before, this was nicely achieved as follows:

 

A counter input task is set to do an implicitly buffered semi-period measurement, and it's Arm Start Trigger

is connected with the analog in sample clock. The cumulative sum of the semi-pulse widths then is directly

the timestamp in timebase ticks of each edge of the encoder, referenced to the start of the AI acquisition.

 

However, in the DAQ X Series, that method does not work. When doing semi-period measurements, the

counter does not start counting upon the HW Arm Start Trigger, but only on the first edge on the gate signal.

In fact, the documentation says it does start counting, but the count at the first edge is not stored, contrary to

the M Series. Of course, that first edge count does not correspond to a proper semi period measurement

(and the M Series manual correctly states that in most applications it should be discarded), but it is essential

to establish an absolute reference to start of the analog in acquisition. 

 

Is there any way to make the DAQ X series produce that first sample, or achieve the same effect in some other way?

 

One could of course switch to buffered edge counting with explicit timing (the AI sample clock), but this has two

disadvantages: Since the encoder edges happen much less often than the sample clock, this would be a waste of

data bandwith. Furthermore, using the previously outlined approach, I get sub-sample accurracy, which is

important particularly because the the encoder frequency is low.

 

Another idea that I was unable to completely work out is to try to trigger the analog in task instead onto that

first encoder edge. I can live with loosing the analog input up to that first encoder edge. However, the problem

here is that I cannot gate the encoder edges. As both the analog input and the counter input tasks effectively

start on "the first encoder edge" (after they have been armed), I need a way to arm them simultanesously to

be sure to start on the same edge for both. Unfortunately, the analog input does not seem to have an arm start trigger.

 

I am looking forward to hear any suggestion on how to implement this on DAQ X Series.

 

Thank you in advance,

Yves Delley

0 Kudos
Message 1 of 6
(5,966 Views)

Hi quantumuser,

 

can you tell me which hardware you are using? Also it would be helpfull if you attach the code you used with the M-Series.

 

Kind Regards.

0 Kudos
Message 2 of 6
(5,933 Views)

Hi Daniel

 

I am now using NI PCIe-6363 while before I used NI PCI-6229. My scripts are written in the python programming language, using the pylibnidaqmx wrapper around the NI-DAQmx C library. This wrapper basically exposes all functions of the C library as python functions, with pythonised names (i.e. lower_case_with_underscore instead of CamelCase). You should be able to guess what they are easily, as the LabVIEW blocks also match the NI-DAQmx C library pretty closely. Here is a version stripped down to the minimum:

 


import numpy
import nidaqmx

 

SAMPLERATE = 100e3 # 100 kHz sample-rate
TIME = 10 # 10 seconds
MAXEDGERATE = 10e3 # maximum rate of edges on PFI0, only needed for buffer.

 

# the counter input, detect edges on PFI0

CItask = nidaqmx.CounterInputTask()

CItask.create_channel_semi_period('/Dev1/ctr0')

CItask.configure_timing_implicit(

  # sample_mode = 'continuous',
  samples_per_channel = MAXEDGERATE * TIME
)
CItask.set_terminal_semi_period( '/Dev1/ctr0', '/Dev1/PFI0' )
CItask.set_arm_start_trigger()
CItask.set_arm_start_trigger_source(
  source = '/Dev1/ai/SampleClock',
)

 

# the analog input, simple buffered AI on ai0

AItask = nidaqmx.AnalogInputTask()

AItask.create_voltage_channel('/Dev1/ai0')

AItask.configure_timing_sample_clock(
  source = 'OnboardClock',
  # sample_mode = 'continuous',
  rate = SAMPLERATE,
  samples_per_channel = SAMPLERATE * TIME
)

 

# start the tasks.
# Important: CItask needs to go first, as it is triggered by the AI

CItask.start()
AItask.start()

 

# Wait for the data and read it
aidata = AItask.read() # block until all data is acquired
cidata = CItask.read(CItask.get_samples_per_channel_available(),timeout=1) # should not block

 

CItask.stop()
AItask.stop()

 

# process the data
CLKDIV = (80e6/SAMPLERATE) # in the 6229, the sample-clock is derived from the 80 MHz timebase
# the semi-period counter counts ticks of the 80 MHz timebase directly.
# to convert the counter data into timestamps we need to calculate the cumulative sum
# and divide by the AI's clock-divider.

timestamps = np.cumsum(cidata) / CLKDIV

 

# now *timestamps* contains the exact points in *aidata* when there was an edge on
# PFI0, to fractional sample precision.

 


 

In reality, I am using coninuous buffering, I read the task properties to ensure both tasks use the same timebase and I read the sample clock divider from the properties as-well. Furthermore, to really get absolute fractional sample precision, one has to get the start trigger delays and the delay between the sample clock and the convert clock right, particularly with multi-channel acquisitions. All of these can be read from the properties as well of course.

 

Thanks! 

 

 

 

0 Kudos
Message 3 of 6
(5,925 Views)

As you see in "NI PCIe-6363 Supported Properties" (http://zone.ni.com/reference/en-XX/help/370471Y-01/cdaqmxsupp/pcie-6363/) the start trigger isn't supported for counter inputs (and therefore retriggerable counter inputs aren't supported either).

0 Kudos
Message 4 of 6
(5,918 Views)

Actually, I do not see how you determine this from the "NI Supported Properties" page, as triggers are technically not "channel properties"

but have their own "trigger properties" section. So if you were to look for triggers in the analog input channel properties, you wouldn't find any either.

 

Nevertheless you are right in that "Start Trigger" is not supported for Counter Input tasks, neither in X Series nor in M Series.

However, the sequence above does not use "Start Trigger" at all, but "Arm Start Trigger", which is a quite different thing.

"Arm Start" is supported on both X Series and M Series. The differences are described in the X Series User Manual on

page 7-50 and the M Series User Manual on page 7-31. 

 

Also, I do not quite see how retriggering would help me here. I only need to start the tasks once and let them run continuously from

there, such that I get one continuous stream of data that is kept in sync by the fact that both are generated from clocks that are derived

from the same internal timebase of the DAQ card.

 

The point is, the triggering actually works fine both in X Series and M Series; The semi period counter input only starts responding to

edges once the analog input started. It is only the time between start of the counter and that first edge which is reported in the M Series

case but discarded in the X Series case. I was hoping that there is a property to select that behaviour, but could not find any.

 

Thanks for looking into this anyway,

Best, Yves

0 Kudos
Message 5 of 6
(5,909 Views)

Hey Yves,

 

This is a "feature" of X Series (I believe the idea was to only return "valid" measurements that actually represented a complete semi-period of the input signal--this was somewhat short-sighted as unfortunately it is not possible to read the time between the arm start and the first edge).  Here are two possible workarounds to get the original behavior you described:

 

1.  Use a digital input task with change detection timing to sample on rising and falling edges of your input signal from the encoder.  Then, configure an edge count task on a counter using an internal timebase as the source and using the change detection event as the sample clock (use the ai sample clock as the arm start like you were before).  

 

2.  Use a second counter to measure the time between the arm start trigger and the first edge of your encoder (two edge separation measurement), though this depends on knowing whether the first encoder edge will be rising or falling (or you would have to use a third counter!).

 

 

If either of those suggestions sound good to you I can elaborate if necessary.  I like #1 as long as you don't need to use a hardware-timed digital input task for something else.

 

 

Best Regards,

John Passiak
0 Kudos
Message 6 of 6
(5,879 Views)