LabVIEW

cancel
Showing results for 
Search instead for 
Did you mean: 

stuck in joystick while loop

I have a main top level vi which does a lot of I/O in separate threads (timed while loops). Everything worked fine, however, I added joystick logic based on the LabVIEW USB joystick example. This logic has its own timed while loop. From my debugging, it appears that the program is endlessly stuck in the joystick while loop. From my understanding of LabVIEW and data flow, this is because when the user deflects the joystick, there is essentially constant data that is being read by my main application and that is why it is getting stuck in the joystick while loop.

 

What are my options? The only thing I can think of is create a separate joystick executable and call that executable from my main vi executable. It is not absolutely necessary that I pass data between these two applications. My joystick application would control a device, in this case, a pedestal, and my main application would decode and display the AZ/EL from the pedestal. I wouldn't mind knowing how to pass data between the two applications (queues?), however.

Am I on the right track?

 

Best Regards,

RobL

 

0 Kudos
Message 1 of 12
(4,343 Views)

It's difficult to say exactly what the issue is without seeing your code.

 

The dataflow problem likely comes from you running the code in something of a series.  Old code, wire into joystick's while loop, post code.  What stops the joystick's loop? 

 

You shouldn't need to create two applications.  In fact, this is a rather silly way to handle the problem.  I'd say it's about as far from going in the right direction as possible.  Don't apply bandaid fixes.  Understand what is causing the problem and address that.  Don't create workarounds that don't need to exist.  If you run the two loops in parallel, it does something similar.  You can then easily use queues to pass data between loops rather than trying to create extra VIs.  You could take a look at the producer/consumer loop for this.  The example is a good start.

 

Is it possible to share the code so we can see what is causing the issue?

0 Kudos
Message 2 of 12
(4,328 Views)

natasftw, thanks for the reply

 

The code is on a stand alone computer not connected to the internet. Unfortunately, I cannot post the code. I will post a screenshot of the joystick routine tomorrow. I can look at the producer/consumer logic which is new to me. I inherited this legacy code which was developed under LabVIEW 6 and I have since upgraded to 2012. The main application is legacy code and contains a lot of timed while loops ("threads). The joystick while loop is within a Pedestal UDP while loop thread. I really do not want to have to re-architect the whole code unless it really makes sense. All the other legacy while loop threads have to work.

 

RobL

0 Kudos
Message 3 of 12
(4,312 Views)

If you can transfer the jpg, what prevents you from transferring the vi itself?  I'm more curious than anything there.

 

When you say timed while loops, do you mean while loops with a wait (ms) inside or are you looking at using timed loops? 

 

The producer/consumer isn't too particularly advanced.  It's pretty easy to pick up.  But, I'll explain the general idea so when you see the code you've already got a head start.

 

There are two independent loops.  The top loop is the "producer" and the bottom is the consumer.  Prior to the loops starting, a queue is created and passed as an input to each loop.  The producer runs as fast as it will and enqueues elements.  The consumer reads from the same queue.  When the queue is empty, it sits and waits.  When there's an element, it dequeues it and "consumes" it by doing whatever processing is necesarry.  When the producer is exited, the queue is destroyed.  This destruction throws an error in the consumer loop and this is often used to stop the consumer loop.  That way, both loops stop once the queue is no longer there.

 

You mentioned some I/O.  If you're working with Legacy, it's likely you're still using NI-DAQ.  You might consider the upgrade just to get into DAQmx and have code that can be modified more easily moving forward.  I'm not sure how advanced the application is.  It sounds like you've got a good start at knowing how to work with code and upgrade.  This might be an exercise worth your time for the learning experience if nothing else. 

 

As far as re-architecting the code, wouldn't creating a secondary VI to build into an executable to be called be a rather large re-architecting?  Modifying your code to run efficiently and self-sustained would be an architecture that "makes sense" in comparison.

0 Kudos
Message 4 of 12
(4,305 Views)

My guess is you don't understand how the Joystick works.  The Acquire Input Data function takes a single reading from the Joystick, returning you an array of Axes values (I think up to 8!), an array of Button (boolean) values (32), and an array of POV Hat values (4).  If you put it in a While loop, it will do what you are asking it to do, namely generate data "as fast as it can" and spit it out (what you do with it is up to you).  I have a relatively inexpensive Logitech Joystick (Extreme 3D Pro) that generates data at about 90 KHz -- if that is too fast for you, put a "Wait" in the While loop or gate your sampling with a Notifier (which is what I did).  The Joystick was in the Producer loop waiting on a Notifier, and guess who sends the Notifier -- why, it's the Consumer Loop!  Who's In Charge, Here?

 

Bob Schor

0 Kudos
Message 5 of 12
(4,261 Views)

I am just using the LabVIEW joystick example and it works fine by itself. I have a 250 ms Wait in my while loop with my Acquire inside it.  I can try moving the Acquire outside the while loop, but I want to periodically poll the joystick.  When I incorporate this in my main vi with other threads, the joystick axis data flow is taking up so much time I never seem to exit my joystick while loop.  I thought the wait was supposed to force the OS to exit the while loop periodically. The LabVIEW example has the Acquire in a loop with a Wait and it does not have producer/consumer logic, but maybe if I want to incorporate it correctly in my main vi then I must either use an event structure or combination of event structure and producer/consumer architecture. I have incorporated the event structure correctly although I had to figure out how to trigger an event on the axis indication. I am new to the producer/consumer logic as my background is text based languages. I will give it a try.

0 Kudos
Message 6 of 12
(4,247 Views)

The wait will NOT leave the while loop.  The while loop will continue to run.  What you're misunderstanding is how the while loop will interact with your processor.  LabVIEW will rail the processor without the wait.  By placing the wait, LabVIEW gives up control of the processor so other things can run on your computer.  This prevents you from going to 100% CPU with a simple while loop.

 

I'd be willing to wager you're making a dataflow error.  You likely have an output from the while loop wired into something else.  If this is the case, the VI will hang up in the joystick loop and continue to operate from the joystick loop until the loop is stopped.  When it's stopped, it will send the last value to whatever you have wired.  I'm guessing because you haven't shared your code.

 

If you want to poll the joystick regularly, you'll have to do one of two things:

1) Integrate the joystick read into your current loop.  You'd do this WITHOUT making a loop purely for the joystick.  While it would only be read once, it would be read once for each time you run the original loop so that would account for the polling you wish to perform.

 

2) Follow the advice and create something of a producer/consumer architecture.  With this, you'd send the joystick values via queues to the other loop so that both loops could run on their own. 

0 Kudos
Message 7 of 12
(4,229 Views)

 Thanks for the replies.

 

Yes, it is definitely a data flow problem. Coming from a text based programming background, the data flow paradigm throws me when I debug and put in breakpoints because the flow jumps from while loop (thread) to while loop depending on which one has the active data (UDP, serial, joystick, etc.). Unfortunately, I cannot post the code, but I will post a screen shot on Monday.

 

I think you are on to something with removing the inner loop with the 250 ms wait and putting the joystick code in the outer loop.  I will also look into adding the producer/consumer logic. Thanks

 

0 Kudos
Message 8 of 12
(4,206 Views)

If you can't post the exact code, consider making a smaller example.  You can make code that has a single data acquisition without any processing and the joystick polling.  That let's us see your general logic without seeing anything proprietary.  That way, we can debug the algorithm with you.

 

Data flow can be a bit confusing until you wrap your head around it.  But, it's really as simple as things execute once they get all of their inputs and don't send an output until they are finished.  If you have a  lop within a loop, nothing will happen until that inner loop is finished.

 

Instead of breakpoints, consider using highlight execution.  It's the lightbulb.  That will show you what data is being passed at any given moment.  It can help you visualize the data flow.

0 Kudos
Message 9 of 12
(4,194 Views)

I just coded up a Producer/Consumer demo for reading the Joystick once/second, giving you the numbers, until you push the Stop Button.  Since you plan to try to do this "on your own", and that's the best way to learn something, I'm going to hold off posting it unless you need more help.

 

Some hints:  Create a Queue based on the Axis Info produced by the Acquire Input Data function.  Your Producer loop should have three things in it -- Acquire Input Data, Enqueue Element, and an appropriate Time Delay (I used Wait ms, with 1000 wired to its input, to give a 1 Hz loop rate).  Wire the Error Out from the Enqueue Element to the While Loop's Stop indicator (do you see why?  It should be explained some place that discusses Consumer/Producer patterns in LabVIEW).

 

In the Consumer/Producer pattern, it is often the Consumer who is "in charge", starting the Producer when ready to "consume" (or use) the data being produced, and stopping the Producer when done.

 

Bob Schor

0 Kudos
Message 10 of 12
(4,188 Views)