LabVIEW

cancel
Showing results for 
Search instead for 
Did you mean: 

Multi-threading with multiple while loops... trouble?

I have no real formal LabVIEW training other then what I have learned on my own and on the job.  I have always run my code through a single while loop which tends to get messy and is problematic when I want to have different things running at different speeds.

So today I've been experimenting with parallel while loops and local variables between the while loops.  The application has one while loop that continuously sets an analog output as fast as it can.  The analog output is wired to one of my analog inputs which reads at a set rate and brings in a set number of samples.  So the sample rate and the amount of data that is read per itteration is controlling the speed of that loop.

I intend to throw in another PWM loop that uses a counter that operates at a slower rate to just further evaluate this setup.

I have two questions:
1. What is the most graceful way of terminating all while loops? 

My current setup uses two "stop" buttons, both of which are "Switch when pressed".  Stop button 1 is in its own while loop and continuously polled.  Stop button 1 has local variables in the other while loops that stop those while loops from happening.  There is an AND gate that comes from these and then feeds into a local variable that sets Stop 2 which terminates the while loop that is polling Stop 1.  Once that final while loop terminates both stop 1 and stop 2 are reset to "false" (depressing the button on the front panel).  My code capture shows this better then I can describe it.  Is there a more graceful way of doing this using the interrupt features or something else?  It would be nice to just use 1 stop button, but I have timeing problems with that.

2.  Am I getting myself in trouble with this setup?  Is there a more graceful way of doing what I am trying to do here?

Thanks for your input!

-Nickerbocker
0 Kudos
Message 1 of 23
(5,699 Views)
If I remove the "stop 2" control and change the AND gate to an NAND gate it seems to work with only one stop button.

I'm still nervous about this setup because if the loop that is polling the stop button stops executing before the other two loops, won't the other two loops never get the new value of "Stop" and just continue running in-definitly?


Download All
0 Kudos
Message 2 of 23
(5,693 Views)
Nickerbocker-

Using a local variable on the stop button is a very common way to stop multiple loops with a single boolena control. Your implementation in learning2.png is correct and should not cause any dead lock scenario. You probably noticed that when you created a local variable for a stop condition, LabVIEW forced you to use a switching mechanical action. This makes sure that once the stop button is thrown, all loops reading from a local variable also read the true value.

Xaq
0 Kudos
Message 3 of 23
(5,664 Views)

Since you're in "learning" mode, I'd also suggest you start looking into things like "Notifiers."  They can be used like local variables (with admittedly more complexity) OR they can be used to help enforce synchronization.  The usefulness is that they can be set to react immediately when the value gets updated but without wasting CPU by repeatedly polling and looking for a change.  Also, the main loop can destroy the notifier on termination, causing all other parallel loops containing a "Wait on Notification" to produce an error that can terminate them in turn.

Check 'em out, they're really pretty neat for accomplishing this kind of thing.

-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.
0 Kudos
Message 4 of 23
(5,645 Views)
Awesome.  Thanks for the tip.  I will look into those as I am a CPU% nazi 😛 and whatever I can do to lower that the better.

Just an aside: I love LabVIEW.  My company purchased for me the NI Developer Suite a little over a year ago and I've learned so much from using it.  Everytime I build something in LabVIEW it becomes increasingly simplified as I am exposed to more and more of the internal libraries and capabilites of LabVIEW.  I have a pretty extensive programming background: Visual Studio .NET, PHP/SQL for web pages, and C/Assembly for microcontrollers.  The other day in LabVIEW I wrote a program that consisted of a PID controller that controlled a heater band, a state machine to control a bunch of solenoids with complicated timing, and a data recorder that was taking in a plethora of transducer data and making state machine/PID controller decisions based on that data.  I was able to accomplish all of this with rather modest NI hardware and LabVIEW enabled me to get the program up and running from scratch in about 4 hours time.  I was telling my boss that with traditional programming languages on that particular setup we would have been in "beta testing" after about a week and a half of development.  Instead we were in production mode by the afternoon.  Worth every penny.
Message 5 of 23
(5,644 Views)

Thank you for the succes story!

I love to read them.

Ben

Retired Senior Automation Systems Architect with Data Science Automation LabVIEW Champion Knight of NI and Prepper LinkedIn Profile YouTube Channel
0 Kudos
Message 6 of 23
(5,631 Views)


@Nickerbocker wrote:
 Is there a more graceful way of doing what I am trying to do here?


The small loop at the bottom is NOT necessary. If you want to leave it, it needs a small wait primitive, otherwise it sucks up significant CPU resources spinning as fast as it can. It also will spin multiple times before releasing the thread. A wait primitive give all other parts a turn after each iteration.

There is no reason to poll for the stop button more often that the slowest loop (even if the small loop stops, the VI will continue to run until all loops have finished!), so place the stop button directly in one of the other loops and eliminate the small loop.

Also make sure that the other loops contain some reasonable timing.

Message 7 of 23
(5,628 Views)
I understand the need to appropriatly time my AO loop and get rid of my Stop button loop.  I am having problems with my top most AI loop.  When I am continuously sampling an AI channel at a particular rate and of a particular size per iteration, what timing should I assign the loop so that my samples still come in correctly and promptly?  I have tried to come up with a function based on the sample rate and sample size/channel to feed into the "wait for next ms" vi.  For instance, if I were sampling at 1000hz and waiting for 1000 samples, than wouldn't i submit to my "wait for next ms" the value of 1000ms.  I'm fairly certain I've had trouble with any value to "wait for next ms" inside an AI loop that is pulling multiple samples at high rates per iteration.
0 Kudos
Message 8 of 23
(5,618 Views)
I usually don't even put a wait in an aquisition loop. If you're sampling continuously at 1000Hz and you wire 1000 to the number of samples to read, AI Read will wait until the buffer has 1000 samples. If you have a 1 second wait alongside this, it won't really do anything because the 1000 sample acquisition will take 1 second anyway. Make sense?
0 Kudos
Message 9 of 23
(5,610 Views)


@Nickerbocker wrote:
The application has one while loop that continuously sets an analog output as fast as it can. 

This is pointless and makes everything unpredictable. The rate will change with every computer upgrade and it will continually change depending on how many other things are running on the computer. Pick a defined fast rate and stick with it.

There are a few more issues I noticed:

After you clear the graph history with a property node, wire the error output of the property node to the edge of the upper while loop. This data dependency ensures that the loop starts after the history clears. RIght now you have no data dependency and you cannot tell at which time the history clears. In the worst case, it might happen after new data has already be written to the graph (unlikely, but still.....).

If one loop stops due to error, the remaining loops will continue to run and there is no way to restart the failed loop without stopping the entire VI. It would make more sense to stop all loops if an error occurs in any one of them.

If your AI needs to run fast, place it in a separate loop writing to a FIFO (e.g.  a suitable LV2 style functional global). Don't place analysis and file IO (!!!) in a loop that needs to be fast. All this can be done at leisure with the buffered data.

 


 

Message 10 of 23
(5,611 Views)