By Aristos Queue
Giant VI hierarchy. Runs for some long amount of time. Somewhere in the mess, a value is generated that is causing the program to go awry. You only know about it at the point where the program goes wrong, which appears to be a long way from where the value was generated.
Your challenge: Find the VI that is generating that value and make it generate some other value.
I've had to debug things like this in LabVIEW before... I just tried something that worked surprisingly well. It works if the value to be generated is somewhat unique in your application (i.e. a particular string or a particular double value... doesn't work so well for common values like "1" that may occur a lot in your application).
Run a quick bit of scripting to change all of your VIs to enable "Show front panel when called" and disable "Close afterwards if originally closed". See picture. Run your top-level VI. Set a breakpoint in the subVI where things are going wrong -- which you know has to be after the value is generated. (optional) Abort the VI hierarchy. This just cuts down on other stuff happening in the system. Now you can use ctrl+F and do a text find for the value. Because all the panels were open, the value they last emitted is on their panels. Even if it is nested inside an array of cluster of array of cluster of... etc. Even if it eventually got packaged into a DVR or passed through some other data-passing mechanism, the original VI that generated the value will still have the value on its panel unless that VI has been called again for some other purpose. This does slow down your whole application -- having the panel open makes LV spend a lot of time updating the controls and indicators, which is a lot more data copies. But at least in my most recent case, this strategy was effective. I figured I'd pass it along. By using the "Show front panel when called" option, you get all the reentrant clone VIs, which you won't get if you just open all of the source VIs in your project.
I got a strange queue behavior that is probably related to race conditions. The problem is eliminated (a way around is found), so there is no need in a quick solution. However, I would be happy to understand reasons for such a phenomenon.
BD of the â€œproblematicâ€ VI is attached. The queue size is limited to 1. The program consists of multiple asynchronous processes.
Execution reaches the Enqueue Element node than stops. The timeout never happens; the program hangs. However, there is more. If I try to execute the VI step-wise, everything works fine until the execution enters the internal Case Structure. When it enters, three Stepping buttons become disabled.
If I try to decompose the program, i.e. to use the same VI in a simple single-process program, both problems disappear.
Have you encountered such a strange behavior? Any ideas that can help to the poor creature (me) to avoid sleepless nights?
Have you ever tried to debug a large application and wished that you could quickly retain wire values on all VIs in the main application so you could find your problem with data etc?
I would love to have a function where I could quickly toggle the "Retain Wire Values" button on all my subvis (ideally also be able to choose how many levels I do this down the hierarchy). My colleague and I have searched for a property node or a method in the scripting functions but have not found anything other than "Highlight Execution" setting. Is this a hidden feature or have we just not looked hard enough.
This question was asked by others back in 2009 : http://forums.ni.com/t5/LabVIEW-Idea-Exchange/Enable-Retain-Wire-Values-for-entire-VI-hierarchy/idi-p/1045552
Vishal Devanath came up with a JKI RCF vi to do this back then but this no longer seems to work (at least in LabVIEW 2012).
"Give a man a fish, and he will live for a day. Teach him to program LabVIEW™ and he wont need fish again" Confucius cira 480BCE
I recently spent some time describing a logging tool that we use here at DMC that has significantly reduced our debug times and helped a lot with onsite support and I thought it was worth bringing it up to the LabVIEW community.
Essentially, it's a logging utility based off of NLog that allows the user to add the equivalent of print statements to their code - any string that can be built is fair game. It also allows a logging level to be associated with the print statement and this is the concept that makes it extremely powerful. Some statements can be low-level "trace" statements, while others are "warnings" or "errors". During run-time (even in an executable) the level of the logger can be changed and you can easily do trace-level debugging for a glitch, and then set it back to an informational level afterwards.
Multiple targets are supported, including RT console, log files, TCP/UDP streams, and email. All the calls are made asynchronously, so the debug statements have a minimal impact on the code execution.
At this point we are finishing and polishing the implementation, but more information and details can be found in a blog post I recently wrote:
NLog for LabVIEW: Logging done properly