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.

LabVIEW

cancel
Showing results for 
Search instead for 
Did you mean: 

Slow rate calculation

The attached VI is my attempt to calculate the feed rate of a pump which pumps out of a container on a scale. The rate is very slow, on the scale of about 10Kg/h. The best way I can think of to calculate such a rate is to time how long it takes for the scale to change. I also need some ability to filter out noise (bumping the scale, tubes being hit, breezes, instability between mass changes). It works, more or less, but I feel it could use improvement.

 

Assume the indicator, "Pump Mass", is constantly being updated with the current scale mass (which measures pounds and converts to kilograms by using a factor of 0.45)

 

The intention of my code is to first check the mass once per second. If the mass does not change, it increments the timer. When it does change, and if it has been more than 5 seconds (that's my filter), it calculates the current rate and then resets the process. 

 

1. Is there a better way to write my method than how I have written it? 

2. Is there a method that is better than my method?

0 Kudos
Message 1 of 17
(3,211 Views)

I try to avoid local variables in my programming because they have bitten me more then once by causing race conditions. 

 

I pretty much used your program but instead of local variables I pass the data with shift registers inside the loop.

 

The GetSetMass.vi is in a parallel loop just as an example but it can be used somewhere else in your program to bring in the updated Pump Mass information.

 

 

Brian
Download All
0 Kudos
Message 2 of 17
(3,179 Views)

So your shift registers eliminate not only the need for the locals but also the need for the hidden indicators I was using to store data. The subVI is simply a FGV, is that correct? Is it a common practice to use many SubVIs in this way? Are there other benefits besides avoiding race conditions?

 

Thank you for your good advice.

0 Kudos
Message 3 of 17
(3,162 Views)

Hi IMSargon,

 

"other benefits":

 Locals cause data copies, hence increase memory needs (bad when using big arrays). Making data copies almost always means slower execution too...

Best regards,
GerdW


using LV2016/2019/2021 on Win10/11+cRIO, TestStand2016/2019
0 Kudos
Message 4 of 17
(3,158 Views)

Brians example is somewhat flawed, so you should make a few corrections:

 

  • The loop in the lower left spins way too fast, consuming all CPU. It only needs to spin if the value changes.
  • The sequence structure has no purpose.
  • For efficieincy, all terminals of the subVI should be outside any structures.
  • There is no way to stop the program, we can only abort.

 

Here's a quick version without subVIs. It's just a dumb refactor without locals. I would still watch for a better algorithm. 🙂

 

 

Message Edited by altenbach on 06-19-2009 02:55 PM
0 Kudos
Message 5 of 17
(3,153 Views)

Loop spins too fast:

 This is merely a placeholder for the actual code that reads the scale. You can throw a 100ms wait in there if you want, as that's how often I check the scale.

 

Sequence structure has no purpose:

 Another benefit of using those shift registers instead of my locals. Thanks.

 

All terminals should be outside any structures:

 That's interesting. What about doing that makes it more efficient? It looks like just moving the terminals outside the case structure would change the behavior. How would you change the subVI?

 

No stop:

 As with the first flaw, this is just some demo code copied from a larger program so I could get some help. The larger program has a better stop function.

 

 

Your version is good, but would you change it if other loops in the program needed access to Pump Mass? With it in the loop, it seems I'd have to use locals again.

 

I'm always happy to hear a better algorithm. Using a timer rather than an increment each second would improve precision, but I never could get it working quite right. Actually, my algorithm is discussed on this other forum: http://mathforum.org/kb/message.jspa?messageID=6698550&tstart=0

I tried to implement a simple form of Hagman's first suggestion. If someone knows what he's talking about in his second suggestion, maybe that'd make a good algorithm.

0 Kudos
Message 6 of 17
(3,136 Views)

IMSargon wrote:

So your shift registers eliminate not only the need for the locals but also the need for the hidden indicators I was using to store data. The subVI is simply a FGV, is that correct? Is it a common practice to use many SubVIs in this way? Are there other benefits besides avoiding race conditions?

 

Thank you for your good advice.


Glad to help.
I use functional global variables(FGV) all the time... for passing many types of data  amongst VI's.
I do use local variables for initializing controls.
 
Brian
0 Kudos
Message 7 of 17
(3,133 Views)

IMSargon wrote:

>All terminals should be outside any structures:

 That's interesting. What about doing that makes it more efficient? It looks like just moving the terminals outside the case structure would change the behavior. How would you change the subVI?


I was talking about the FGV subVI by Brian. For a detailed discussion, see this post by Darren (read that entire thread for details).

 

No, it won't change the behavior if you do it right, it could for example look like that:

 


IMSargon wrote:

Your version is good, but would you change it if other loops in the program needed access to Pump Mass? With it in the loop, it seems I'd have to use locals again.


Not necessarily. (of course there is nothing wrong with a local here and there). Still, if you would use a queue, the loop would only spin when a new value is available. Keep track of the tick count and the code will know when the last significant change happenend.

Message Edited by altenbach on 06-20-2009 09:27 AM
0 Kudos
Message 8 of 17
(3,086 Views)

IMSargon wrote:

I'm always happy to hear a better algorithm. Using a timer rather than an increment each second would improve precision, but I never could get it working quite right. Actually, my algorithm is discussed on this other forum: http://mathforum.org/kb/message.jspa?messageID=6698550&tstart=0

I tried to implement a simple form of Hagman's first suggestion. If someone knows what he's talking about in his second suggestion, maybe that'd make a good algorithm.


I would just collect raw weight data every second and place a few hundred points (or whatever) into a FIFO buffer, then simply do some low-pass filtering or smoothing operation (e.g. fit to a polynomial of suitable order) to calculate the derivative at the newest edge of the data.

 

It seems way too convoluted to throw away data based on changes and such.

 

Do you have some typical raw data, e.g. weight reading every second for an hour or so to play with?

 

 

0 Kudos
Message 9 of 17
(3,083 Views)

Raw data? Great idea! I've attached two files with example data. In both cases the pump is running at a constant rate. The two files are two different scales with two different pumping rates.

 

Ideally, we would like to know the rate at which we are pumping in real time. However, the scale isn't sensitive enough to do that. So what's the next best thing?

Message Edited by IMSargon on 06-20-2009 12:48 PM
Download All
0 Kudos
Message 10 of 17
(3,077 Views)