LabVIEW

cancel
Showing results for 
Search instead for 
Did you mean: 

Trouble reading digital freqency

I have created a task in NI MAX that reads a frequency from my USB-6353. I'm having trouble creating a VI to accomplish the same task. I feel I've tried every possible setting, but haven't had any luck yet.

 

dourk_0-1576515650583.png

dourk_1-1576515898714.png

0 Kudos
Message 1 of 6
(1,059 Views)

I think the main problem is a subtle but fairly common one I just recently posted about to the idea exchange.

 

When you leave 'number of samples per channel' unwired in a call to DAQmx Read for a Continuous Sampling task, the default value -1 is used.  The *meaning* of that default value is "don't wait for any new samples to accumulate, just give me all the new ones that arrived since my last request, even if the # of new ones is 0."

 

As a result, your loop spins really really fast (like maybe 10's of kHz), and almost always returns an empty array.  On the relatively rare iterations there's new data from a 20-ish Hz signal, you'll iterate again in less than a msec to stomp on that data with a fresh empty array.

 

Wire up a number like 1 or 5 or 10 to the DAQmx Read call, and then also be prepared to handle the timeout error case.

 

 

-Kevin P

0 Kudos
Message 2 of 6
(1,031 Views)

Something like this works for me:

 

Example.png

Tim
GHSP
0 Kudos
Message 3 of 6
(995 Views)

A couple comments on the code Tim posted -- mainly for the sake of the OP.

 

1. I don't like the extra timing constraint of the "Wait (msec)" call.  The timeout on the call to DAQmx Read does enough by itself to throttle the loop iteration speed.  

 

2. I'd add code to handle the timeout error you can probably anticipate getting sometimes.  You can decide whether to stop the loop, auto-recover silently, or something else, depending on what makes sense for your overall app.

 

3. The posted snippet does silent auto-recovery (in the non-visible case of the snippet) but can probably do it faster.  I don't think it's necessary to clear or re-create the task.  It should be enough to Stop, clear the error, and Start again.

 

4. I'm a fan of starting tasks explicitly.  I'd call DAQmx Start before entering the loop.

 

 

-Kevin P

Message 4 of 6
(983 Views)

Hi Kevin,

 

Thank you for the feedback on the code:

 

Here is the reasoning for some of what I did:

 

1. I don't like the extra timing constraint of the "Wait (msec)" call.  The timeout on the call to DAQmx Read does enough by itself to throttle the loop iteration speed.  

 

You are right here the wait is probably unnecessary.

 

2. I'd add code to handle the timeout error you can probably anticipate getting sometimes.  You can decide whether to stop the loop, auto-recover silently, or something else, depending on what makes sense for your overall app.

 

I did as you noted below.

 

3. The posted snippet does silent auto-recovery (in the non-visible case of the snippet) but can probably do it faster.  I don't think it's necessary to clear or re-create the task.  It should be enough to Stop, clear the error, and Start again.

 

OK I did this the way I did because in the version I have for what I am doing I needed the frequency and the pulse width. I needed to use one counter to achieve this so I could test multiple parts. To achieve this using one counter I read the frequency every second or so and then read the pulse every loop iteration. I have to stop and close the task to keep from getting a memory leak.

 

4. I'm a fan of starting tasks explicitly.  I'd call DAQmx Start before entering the loop.

 

OK you are a fan but it seems to be unnecessary. Can you explain what advantage you get from doing this. I am always looking to learn new thing when ever I can. I ran it both ways and I do not see a difference.

 

 

Tim
GHSP
0 Kudos
Message 5 of 6
(890 Views)

Tim,

 

The comments were mainly aimed at the OP, I didn't figure you'd need any advice.  But I'll continue the conversation for the sake of whoever might come across the thread.

 

Sure wish there was a more convenient quoting mechanism, but I'll stick with red for me, blue for you:

 


1. I don't like the extra timing constraint of the "Wait (msec)" call.  The timeout on the call to DAQmx Read does enough by itself to throttle the loop iteration speed.  

 

You are right here the wait is probably unnecessary.

 

Mainly I'm just sensitized to this because I've been in a lot of threads for continuous DAQ where there were 2 separate mechanisms for timing the loop, often causing some of the symptoms that brought someone to the forums in the first place. 

    A classic version of it is an AI task that samples at 1000 Hz, requests 100 samples at a time (100 msec worth), and *also* has a 100 msec Wait timer.  As the loop iterations occasionally last 101 or 102 msec (Windows), the AI task 

starts having more and more *leftover* samples in its buffer after 100 msec worth get read out.  And the user keeps seeing and acting on staler and staler data.

   The symptoms can be subtle, and I've made it a point of emphasis in threads to tell people to choose 1 and only 1 method for timing their loop iterations.

 

...

 

3. The posted snippet does silent auto-recovery (in the non-visible case of the snippet) but can probably do it faster.  I don't think it's necessary to clear or re-create the task.  It should be enough to Stop, clear the error, and Start again.

 

OK I did this the way I did because in the version I have for what I am doing I needed the frequency and the pulse width. I needed to use one counter to achieve this so I could test multiple parts. To achieve this using one counter I read the frequency every second or so and then read the pulse every loop iteration. I have to stop and close the task to keep from getting a memory leak.

 

Makes sense for that situation.  More often when folks are needing to restart a task as part of error recovery, they'd prefer it to happen as fast as possible.

    To the OP: it's even faster to notice the specific easy-to-anticipate timeout error and simply clear/ignore it, and avoid any need for stop/re-start.

 

4. I'm a fan of starting tasks explicitly.  I'd call DAQmx Start before entering the loop.

 

OK you are a fan but it seems to be unnecessary. Can you explain what advantage you get from doing this. I am always looking to learn new thing when ever I can. I ran it both ways and I do not see a difference.

 

This has to do with the DAQmx Task State Model.  More info here, and also over here.

    I've been in a number of threads related to the task state model.  One classic example is for software retriggering of a DAQ task on a device that doesn't natively support hardware retriggering.  The goal is to get the fastest possible turnaround time from stopping one iteration of finite acquisition until starting the next one.  To accomplish this, it's very helpful to explicitly "commit" the task before the main loop.  Then the subsequent stop "unwinds" the task state as little as possible, minimizing the turnaround time needed to re-start it.

    You're right that explicit starts aren't always necessary or particularly helpful, but they also don't hurt.  Over the long haul, I see it as a good habit to take explicit control over such things, kind of an extended version of also advocating standard DAQmx over the DAQ Assistant.  


 

-Kevin P

0 Kudos
Message 6 of 6
(865 Views)