Multifunction DAQ

cancel
Showing results for 
Search instead for 
Did you mean: 

Time sync between applications

Solved!
Go to solution

I am converting several applications that used the old nidaq driver to NIDAQmx 9.7.0 using the ANSI C interface to a pxi-6602.

 

Application #1 creates a 1-second pulse on Ctr0 to synchronize timing with an external device;

DAQmxCreateCOPulseChanTime(counterTaskHandle, "Dev1/ctr0", "", DAQmx_Val_Seconds, DAQmx_Val_Low, 0.9, 0.9, 0.1);

DAQmxCfgImplicitTiming(counterTaskHandle, DAQmx_Val_ContSamps, 0);
DAQmxStartTask(counterTaskHandle);


This is working fine. But I also have another application that also must be timed off of this same pulse. In order to do this, it attempts to read the tick count from the timer to determine how long to delay in order to sync up with application #1. The two problems I am having are:

1) When I attempt to access Ctr0 from application #2, I get error code -50103 The specified resource is reserved.

2) I do not see a function that can return the time or tick count since the last pulse anyway. The old code that I am updating used GPCTR_Watch to get this value, but I do not see a replacement.

 

I suppose that at least the first problem is not entirely unexpected, but I need to find something that can replace this functionallity.

 

Thanks,

--Sean

0 Kudos
Message 1 of 10
(5,119 Views)

Ok, I have figured out how to read the counter from the application that started it using DAQmxGetCOCount. Now I just need to know how it is possible to get this counter from another application, or otherwise perform timing based on that counter.

0 Kudos
Message 2 of 10
(5,092 Views)

Hi,

 

what did you mean by getting this counter from another application? Are you trying to use two daqmx tasks in the same source file, or is it two separate source files? Below is a post that might be relevant to what you're trying to do (albeit he's talking about multi-threaded tasks, it might be in the same general line of thought) It would be helpful if you could provide a bit more information about what you mean by multiple applications.

 

Thanks

Gabriel M.
Product Marketing Engineer - Academic Courseware
National Instruments
0 Kudos
Message 3 of 10
(5,075 Views)

Totally forgot to link the post. My bad, the first reply might prove useful to you.

 

http://forums.ni.com/t5/Multifunction-DAQ/porting-GPCTR-Watch-to-NI-DAQMX/td-p/787760

Gabriel M.
Product Marketing Engineer - Academic Courseware
National Instruments
0 Kudos
Message 4 of 10
(5,064 Views)

It is two different tasks in two seperate processes (windows applications) that are running at the same time on the same machine. It does sound very similar to the setup in the post that you linked.

 

One process sends a once-per-second pulse over the pxi6602, and uses that to time measurements using another hardware interface. The second process performs network operations that also need to be timed to that same once-per-second pulse.

 

Here is what I have working so far:

 

Process1 creates Task1 and adds the counter:

 

    DAQmxCreateTask("", &taskHandle1);

    DAQmxCreateCOPulseChanTime(taskHandle1, "Dev1/ctr0", "", DAQmx_Val_Seconds, DAQmx_Val_Low, 0.9, 0.9, 0.1);

    DAQmxCfgImplicitTiming(taskHandle1, DAQmx_Val_ContSamps, 1000);
    DAQmxStartTask(taskHandle1);

 

On a timer in Process1, I can call this to get the state of the counter, so I could calculate the time until the next pulse:

 

    DAQmxGetCOCount(taskHandle1, "Dev1/ctr0", &data);

 

But now I need to get that counter value inside Process2 instead. This is as close as I have come so far:

 

Process2 creates Task2 to read a different counter (ctr4). The output from Dev1/ctr0 is set as the input terminal to Dev1/ctr4:

 

    DAQmxCreateTask("", &taskHandle2);

    DAQmxCreateCIPulseWidthChan(taskHandle2,"Dev1/ctr4","", 0.0001, 20.0, DAQmx_Val_Seconds, DAQmx_Val_Falling, NULL);
    DAQmxSetCIPulseWidthTerm(taskHandle2, "Dev1/ctr4", "/Dev1/PFI36");

    DAQmxStartTask(taskHandle2);

 

Then on a timer in Process2, I call this:

 

    DAQmxGetCICount(taskHandle2, "Dev1/ctr4", &data);

 

And this apparently is working, except the data I get back is the pulse width of the counter created in Process1. What I need is the time since the last pulse received.

 

I am trying switching around different types of counters that I create in Process2, but so far have not found a way to get the timing data that I need.

 

0 Kudos
Message 5 of 10
(5,058 Views)

Hi Sean,

 

so you are only using one hardware device am I right? Also, have you tried doing a semi-period measurement? The semi-period measurement would give you the width of the pulse, as well as the low time before the next pulse is received. You could also try doing a pulse period, which would give the length of the entire pulse + the time it takes to get the next pulse high.

Gabriel M.
Product Marketing Engineer - Academic Courseware
National Instruments
0 Kudos
Message 6 of 10
(5,034 Views)

You are correct, I am using only one hardware device (pxi-6602)

 

I am still not getting the results that I need. Here is what I am trying, please correct me if I am doing something wrong.

 

DAQmxCreateCISemiPeriodChan(counterTask, "Dev1/ctr4", "", 0.0001, 20.0, DAQmx_Val_Ticks, NULL);

DAQmxSetCISemiPeriodTerm(counterTask, "Dev1/ctr4", "/Dev1/PFI36");

DAQmxCfgImplicitTiming(counterTask, DAQmx_Val_ContSamps, 1000);

DAQmxStartTask(counterTask);

 

Then if I periodically call this:

 

DAQmxReadCounterU32(counterTask, DAQmx_Val_Auto, 0, data, sizeof(data)/sizeof(uInt32), &sampsPerChanRead, NULL);

I get back values of 71999999 and 8000001, which if I use DAQmxGetCICtrTimebaseRate to convert give me 0.9 and 0.1 seconds.

 

If I call this instead:

 

DAQmxGetCICount(counterTask, "Dev1/ctr4", &data);

 

I get a similar result. It always returns 8000001.

 

But these values don't do me any good. I already know the high and low time of the signal. What I need is the exact time at any instant since the last time the line has gone low (or high).

 

Thanks,

--Sean

0 Kudos
Message 7 of 10
(5,003 Views)

Are you using LabWindows CVI? If so, you might be able to do this with a DAQmxGetChanAttribute(). The DAQmxGetChanAttribute lets you get the current count of counter input task so it could be possible that this is what you are looking for?

Gabriel M.
Product Marketing Engineer - Academic Courseware
National Instruments
0 Kudos
Message 8 of 10
(4,981 Views)
Solution
Accepted by topic author sbaker48

Well for what it's worth DAQmxGetCICount does work on my X Series card (i.e. it returns the current value of the count register like you were hoping that it would).  What you're seeing might be a hardware limitation of the TIO (660x) devices.

 

However, I think something like this ought to do what you are asking for (unfortunately I can't verify on real hardware):

 

//initialization
DAQmxCreateCICountEdgesChan(counterTask, "Dev1/ctr4", "", DAQmx_Val_Rising, 0, DAQmx_Val_CountUp);
DAQmxSetCICountEdgesTerm(counterTask, "", "/Dev1/80MHzTimebase");

DAQmxSetCICountEdgesCountResetEnable(counterTask, "", TRUE);
DAQmxSetCICountEdgesCountResetResetCount(counterTask, "", 0);
DAQmxSetCICountEdgesCountResetTerm(counterTask, "", "/Dev1/PFI36");

DAQmxStartTask(counterTask);
//call this to get the time (in timebase ticks) relative to the last rising edge of the clock DAQmxReadCounterU32(counterTask, DAQmx_Val_Auto, 0, data, sizeof(data)/sizeof(uInt32), &sampsPerChanRead, NULL);

 

According to my simulated device anyway, It looks like TIO devices should now support the count reset functionality (not sure which driver version though, when DAQmx first added the feature it was for X Series only).

 

 

 

Best Regards,

John Passiak
Message 9 of 10
(4,945 Views)

This worked!

 

I did have to pass a timeout greather than 0 to DAQmxReadCounterU32 or else it would return a DAQmxErrorOperationTimedOut error.  DAQmxGetCICount also works fine to retrieve the counter when the task is configured like this.

 

Thanks for your help!

--Sean

 

0 Kudos
Message 10 of 10
(4,929 Views)