LabVIEW

cancel
Showing results for 
Search instead for 
Did you mean: 

RPM measurement using Counter Errors Timeout/Lag

Hi all,

 

so I'm trying to read a motor's rpm using the Counter from a NI DAQ Device (USB 6212). It works...as long as the motor is switched on before running the VI. From other solutions I've seen I've managed to cancel the relevant error and output a zero. However this causes a huge slow-down (possibly due to the timeout but I'm not sure; the timeout was originally unwired), which is bad because this vi is placed within a sub vi where other data acquisition is taking place so it causes the entire sub VI to lag.

 

Also, when the VI is running, and the motor is switched off halfway, it outputs a zero (which is ok and correct), but when the motor is switched back on, the Read keeps outputting the zero and error -200474 even though it's cleared every time it happens.

 

I would like to be able to:

 

1) When the programme runs before the motor is switched on, it shows zero and shows the rpm when the motor is switched on again (right now it will only show the rpm when the motor is on before the running the vi)

2) When the motor is switched off and on again while the vi is running, the indicator changes accordingly without lagging.

3) Both the above are possible programmatically without further user input (i.e no Boolean switch on the user part to indicate if motor is on or off)

 

Other troubleshooting steps I've tried:

- Duplicate Count Prevention set to True but the resulting RPM values are false and ever-increasing

- I tried reading Available Samples per Channel so that Read will only occur after a certain value but didn't go anywhere because I keep getting the error -200455: You cannot get the specified property, because the task is not an input buffered task (I'm not sure how to set the buffer)

 

Could someone point me in the right direction? Because I can't guarantee that the motor is switched on before the vi starts. Thank you.

0 Kudos
Message 1 of 5
(2,919 Views)

So there are a few methods to measure frequency, as you've probably seen.

Some links describing these are here: Choosing a Counter Frequency Measurement MethodFrequency Measurements: How-To Guide.

Unfortunately, I don't think the 6212 supports the "Sample Clocked" method, which would be my favourite in your application.

 

I had similar problems for a long time using X-series hardware, which is a little different (and may support some additional methods) but you can find some descriptions of the steps I took here: Making pulse frequency measurements with NI-USB 6356Rotation Speed vs Time measurement - measuring 0Meaning of CI.Velocity.MeasTime with a known DAQmx Timing set Sample Clock.

 

I suspect the thread about measuring zero is specifically useful to you, but the other two might also be interesting. In the 3rd thread, I think I had already moved to using a cRIO system, which massively simplified my problem, and since then I haven't had to worry about it at all. 


GCentral
Message 2 of 5
(2,861 Views)

I'll chime in a bit too.  Some of the discussion in those threads gets fairly in-depth so I want to focus on simplicity here.  

   Brief summary: I don't see any obvious flaws in your posted code to explain the persistent timeout errors after previously-present pulses go away and later come back.  Below are a few more details.

 

1. Since you never call DAQmx Timing, your task should operate in "on-demand" mode.  When you call DAQmx Read, the counter will measure the frequency of the *next* full interval.

    In contrast to "on demand" mode, there's a "sampling mode" that gets invoked when you include "DAQmx Timing" in the config chain.  Counter tasks start getting more complex when you include sampling and buffering, so I'd advise that you focus first on solving this problem while staying in "on-demand" mode.  Once that's all sorted out, *then* you might want to consider hw-timed sampling and buffering.

 

2. Sometimes, DAQmx errors can be persistent to the task, requiring a stop and restart.  Typically, I don't expect *timeout* errors to be persistent this way.  And if anything, an "on-demand" task should be especially forgiving.  

    Thus, the persistence you seem to observe seems unexpected to me but I'm not near hw to do any testing.  However, since you're only querying frequency measurements every 200 msec, you could probably try stopping and re-starting the task as a workaround, at least for now.

 

3. The array building and Mean don't make a lot of sense to me.  You should probably be using "Mean Pt-by-Pt" which will give you an average of recent readings using a sliding window.  Then you can also get rid of the array and shift register.

 

4. I'd also suggest that you terminate your loop if any other error comes out of the case structure (after having cleared any -200474 error, if present).   And once you're set up to terminate on error, you should probably change the error shift register into a regular tunnel -- no need to preserve it for a next iteration that'll never happen as you terminate the loop.

 

 

-Kevin P

ALERT! LabVIEW's subscription-only policy came to an end (finally!). Unfortunately, pricing favors the captured and committed over new adopters -- so tread carefully.
Message 3 of 5
(2,830 Views)

@cbutcher thanks for the links! I'll definitely bookmark them for future references

@Kevin_Price

1. I've been trying to avoid using the DAQmx Timing because I'm not sure how it'll affect the other parts of code (since this counter is only a small part of a Sub Vi)

2. Yes, I tried this method before your reply came in and it turns out stopping and restarting works (I used the 'unreserve' of Control Task to do it but I've since switched it to a Stop and Start per your suggestion). 

 

3. The reason why it's built that way is because it gave a more accurate (when comparing it to values of a handheld tachometer) and 'stable' value. However I did realise that it was difficult for me to reinitialize the array (I tried several ways by filtering and deleting the arrays with zeros, reinitializing with a constant, etc). 

 

I've tried using the Mean Pt by Pt and the result is in the VI attached. If I switch the motor off and on while it's running, depending on how quick or slow I do it, the indicator sometimes shows the 'right' value right away, otherwise it takes 3 seconds for it to 'stabilize' to the correct value. The inconsistency and occasional 3 s time lag is not optimal of course, but it does provide a workaround. I've tried playing around with the wait time and timeout as well as number of samples but this is best I could get. Maybe you might have another idea?

 

4. I deleted shift registers. The reason why I didn't use an error to terminate the loop is because the actual VI would not have a while loop (it'll be built as a Sub VI and inserted into the main with a while loop.

 

Thanks for all your help.

0 Kudos
Message 4 of 5
(2,793 Views)

I reworked your latest posted vi a bit.  There are still some things for you to consider and address.  Summary:

 

  • starting task before loop
  • feeding freq data to 'Mean Pt-by-Pt' only if no error
  • stopping and restarting task after each error
  • using shift register to allow resetting 'Mean Pt-by-Pt' after each error

Remaining for you to consider:

  • appropriate polling rate.  Right now, each iteration will take at least 100 msec plus the time to acquire the next freq sample (or another 100 msec, whichever is shorter)
  • # of samples to average with 'Mean Pt-by-Pt'.  You may want this to depend on the polling rate.  Right now you're calculating RPM based on the average of the last 20 samples.  With your present polling rate, measurements continue to influence the average for 2 seconds into the future.   You need to consider what's appropriate for your overall app.

 

-Kevin P

 

 

ALERT! LabVIEW's subscription-only policy came to an end (finally!). Unfortunately, pricing favors the captured and committed over new adopters -- so tread carefully.
Message 5 of 5
(2,782 Views)