I am unable to find the property controls for "Plot Area Top" and "Height". Using Labview 2017. Could it be that the properties are now labelled as something else? How did you nagtivate under properties structure to get to Plot Area Top and Height?
Re: Waveform graph label positions change in an undesired manner when resizing with pane.
XML timestamp to LabVIEW Time
Here is a VI that extracts the 'Timestamp' section of XML and outputs a LabVIEW timestamp...
LabVIEW 2018...if you have earlier labVIEW here is a screen shot of the code diagram...
Re: Fixed (Default) Array Lengths in Typedefs
Thanks, that is what I figured, but I'm pretty new when it comes to VI scripting. Going to give it a go tomorrow.
Re: How to Program Xilinix Artix-7 FPGA on my DUT using LabVIEW
That seems to be a pretty broad question with almost no detail. It sounds like what you're asking is "how do I use LabVIEW FPGA to program an FPGA chip - I'm already familiar with the Xilinx Vivado Tool". Is that about right?
If so, I can really only point you to the LabVIEW FPGA tutorials (there's a demo here) - I suspect it's almost nothing like programming in VHDL or similar, but perhaps you'll find that experience helpful.
Re: Wise use of Local Variable
wrote: wrote: Unfortunately, the forum does "pre-processing" of pictures before displaying them, so your snippet won't work. You'll have to upload the snippet as a file. I'm already afraid of what I'm seeing though. You know that LabVIEW doesn't really flow left to right; it just appears that way because you connect the nodes together from left to right - usually. That being said, the "floating code" that you have in there can execute at any time it feels, and if you have locals attached to it, you may or may not be operating with stale data.
Bill, you can download the png from the picture manager then the snippet works fine
Perhaps we should update the sticky at the top of the forum?
Re: Conditional parallelism on LabVIEW
wrote: wrote: wrote: It is muy importante to remember this little phrase:
"Remember that a node executes only when data is available at all of its input terminals and supplies data to the output terminals only when the node finishes execution."
Taken literally, you can see that the input to the shift register - considered to be an input terminal - will not have data supplied to it until the event structure produces an output. Your loop cannot iterate until the shift register gets some data out of the event loop.
I would as was suggested and convert this into a QMH design pattern, or something closely related.
Not sure why the loop wouldn't be able to execute - uninitialized shift registers are used all the time in FGVs. The code will run just fine, but the initial value is unpredictable on the first run of the program. I still recommend something like a QMH because I suspect that the actual application is much more complicated.
Billko is referring to the dataflow concept - the inner edge of the right side shift register is waiting for data.
Correct. It will get data when either of two events occur - the value changed event is registered or the timeout occurs. Granted in this case the timeout is unpredictable on first run.
Re: Wise use of Local Variable
"So, the calculation and the 8 reads can happen in any order! Imagine, 4 reads of stale data, a write to the indicator and 4 reads of new data! as an example! without dataflow the values read are unknowable."
I don't know how local variables work. But from what you are saying, the data transfer from the indicator to all other local variables don't happen simultaneously. So it can cause problems and wiring can eliminate them. Am I correct? Can you some simple example to demonstrate your idea.
Re: Wise use of Local Variable
@altenbach Could you please suggest me some resources from where I could learn good programming styles. Because it is difficult to make a good readable VI without good programming practices.
Re: Wise use of Local Variable
wrote: "So, the calculation and the 8 reads can happen in any order! Imagine, 4 reads of stale data, a write to the indicator and 4 reads of new data! as an example! without dataflow the values read are unknowable."
I don't know how local variables work. But from what you are saying, the data transfer from the indicator to all other local variables don't happen simultaneously. So it can cause problems and wiring can eliminate them. Am I correct? Can you some simple example to demonstrate your idea.
The intent of the local variable is to provide the current value of the control/indicator being read. Because your code does not have dataflow dependency it will attempt to run in parallel. The order in which parallel code runs is unpredictable. The local variable will not read the control/indicator until the local variable is ready to be read. In the meantime it could be possible for the value of the control/indicator to have changed.
Attached is a quickly written vi where I added waits to control the order of execution to show what can happen. In my example Numeric 2 and Numeric 3 both read from local variables from Numeric 1, but Numeric 2 reads the data, then Numeric 1 writes new data, then Numeric 3 reads the data. Thus Numeric 2 and Numeric 3 have different values.
Re: Wise use of Local Variable
Wires enforce ordering, because they have a direction. Things that receive data from a wire (e.g. indicators, or input terminals of other nodes) cannot run until data becomes available on that wire from the source (each wire can have only one source, but multiple destinations).
When you use a Local Variable, essentially you're allowing multiple sources for the "same" data. But you don't specify when they should be read (indeed, without ugly use of Flat Sequence Structures or similar, it's quite difficult to enforce ordering for a Local Variable). As a result, their values might be read at any time within their 'sequence block' (possibly not a real term - I mean the frame around them, e.g. For loop, While loop, Case Structure, etc), and if you have multiple copies, (especially containing reads and writes) they might not be the same.
I put together an example, but it didn't initially show the behaviour I'd expect. Once I added some parallelism, it very quickly fell apart (but possibly that's not representative of your situation). None-the-less, it does illustrate something
Re: Wise use of Local Variable
wrote: @altenbach Could you please suggest me some resources from where I could learn good programming styles. Because it is difficult to make a good readable VI without good programming practices.
When I got started in LabVIEW, I bought Peter Blume's "The LabVIEW Style Book" (and I've been bugging Peter to write a second edition for about a half-dozen years). I read it cover to cover at least three times my first year, and have read it several more times. I adopted and adapted many of his points, and try to "hint" to colleagues to adapt "better style", focusing on neat wiring, "one-screen" block diagrams, encapsulating detail in sub-VIs, making icons (even if only 3-4 lines of "text-in-a-box"), and always writing a minimum VI Description.
Bob Schor
Re: Wise use of Local Variable
Quick, albeit ugly looking, method based on @Kyle97330 excellent suggestion.
Lots more can be done, 2012 vi attached.
mcduff
Re: Wise use of Local Variable
wrote: @altenbach Could you please suggest me some resources from where I could learn good programming styles. Because it is difficult to make a good readable VI without good programming practices.
LabVIEW ships with many examples and design templates that you should inspect closely. There are also plenty of online examples and even books as suggested by others.
Nothing beats hands-on experience and constant exercise. Write code, step back and think about better alternatives. Make mistakes, recognize the mistakes, correct the mistakes and learn from them (and never make the same mistake twice!), make new mistakes, etc. Repeat!
Analogy: You cannot become a faster runner by only reading books about running. You primarily need to run as much as possible! Still, a book about running physiology (nutrition, posture, pacing, etc.) can help you get more efficient faster while avoiding injuries.
Re: Parallel Consumers Maintain Data Order
Time goes on and we learn some things along the way. Way back when I was moving this project from prototyping to a more final stage I discarded the promise queues in lieu of developing a thread pool manager which distributed tasks to worker threads, who then fed it back to the manager to distribute the result as it pleased. I was very gung-ho about learning software engineering theory and thought "yea, this works great with the 'do one thing well' philosophy"...
However, doing one thing well gets trumped by simplicity and using standard tools for the job. And there was a in fact really simple solution to this problem using built-ins and much less hocus pocus. See the snippet below. The modulo_wait.vi is just a simple demonstrator operation to keep the snippet clean. Actual application in my case is a ~100,000 sample FFT
In Teststand calling LabView that Calls Teststand sub-sequences
How can I get Teststand to call a LabVIEW VI that can do multiple calls to a Teststand Sub-Sequence multiple times while passing different parameter data during each sub-sequence call from within LabVIEW?. I've seen this done before, but not clear on how LabVIEW can get around calling external Teststand Sub-Sequences inside of the same Teststand.seq file, or external Teststand.seq file.
Re: EPICS server: access pv from another computer
In the drop-down menu in Figure 4, instead of selecting Project Items have you tried finding the variables under Network Items, where you are able to see other machines on the network? Using Network Items should let you find the network variables created on another machine.
Re: Wise use of Local Variable
Thinking more about the Giant Block Diagram and Plethora of Local Variables, I agree with McDuff's depiction of @Kyle97330's suggestion. I'd go a few steps more:
- I'd build a Cluster to hold the Front Panel Controls that I will be needing (a Cluster Wire is much less intrusive and can be passed to an "Unbundle by Name" to get out just what you need).
- I'd make a TypeDef of the Cluster and make an Icon for it for use when you Bundle by Name (you need to put the Cluster on the input of the Bundle by Name, and instead of a huge Cluster diagram, you can right-click it and it will "shrink" to an Icon, at least in the last 4-6 versions of LabVIEW).
- Build an Event Loop with Value Change cases for every Control where you add the new value into the Cluster. Put a Shift Register in this Loop and initialize it with code that initializes your Control Cluster. This will be the only place that you'll need the Controls, themselves, in the Block Diagram.
- Have an Event Case for every Control to update its value in the Cluster. [Magic is going to happen a few steps later ...]
- Create a Stop Control (not in the Cluster) that you will use to stop the entire Program. Create a Value Change Event for this Stop control and wire its NewVal output to the Stop of the Event Loop. Keep the Stop Control, itself, outside the Event's While Loop.
- In a separate While Loop, put the Program that needs to use these Controls. Wire the Stop Control to this While Loop's Stop indicator.
- All we now have to do is get the latest value of the Cluster into this While Loop. We could use a Notifier, but if you are running LabVIEW 2016 or later, I recommend that you use a Tag Channel Wire. I'll show you how ...
- Inside the Event Loop, right-click the Cluster Wire coming out of the Bundle by Name and choose "Channel Writer". Choose a Tag Channel. Bring your cursor near its output to get the Wiring Tool, click, and drag the Channel Wire (it will look like a pipe) to the outer edge of the Event's While Loop.
- On the outside of the While Loop, create a "wire" (looking like a pipe) and create a path to the separate While Loop (where your code will be), crossing into the While Loop (see below). Note that the "pipe" lies on top of the While Loops, indicating it is "jumping over the top" and allowing the data to flow "unimpeded" (that's why the formal name is "Asynchronous Channel Wire").
- On the stub inside the (lower) While Loop, right-click and Create Channel Reader. Right-click the Reader's output and you'll have the Control Cluster that you just updated in the Event Loop.
- One more step -- you don't (yet) have the initial value of the Cluster in the While Loop, just the value(s) after you make changes. So click on the Cluster wire as it goes into the Event Loop, create another Tag Channel, and join its output with the Pipe running from the Event Loop to the While Loop. Be sure you use a proper Pipe Flange.
- I put the 1-second Wait in the lower Loop to mimic "lots of processing", and also to avoid overheating the CPU ... This is Just an Example, after all.
- What if you are using LabVIEW 2012, where there were no Channel Wires? Well, Tags are analogous to Notifiers (which, I must confess, I "didn't get" for the longest time -- Tags, to me, are so much simpler ...).
Here is the code (as a LabVIEW 2016 Snippet -- I also attached the VI and TypeDef).
No Local Variables
I probably shouldn't mention this (as it is my first time presenting at NIWeek, and I'm slightly nervous), but I'll be discussing "Using and Abusing Channel Wires" on Monday, May 20 at 4:30 pm. It will be a tad more complicated than the above ...
Bob Schor
P.S. -- of course I forgot to attach my VI and Control, but was saved by the Edit Your Reponse button ...
Re: Wise use of Local Variable
wrote:
I probably shouldn't mention this (as it is my first time presenting at NIWeek, and I'm slightly nervous), but I'll be discussing "Using and Abusing Channel Wires" on Monday, May 20 at 4:30 pm. It will be a tad more complicated than the above ...
As long as you show your code, I think you will be fine, and give an excellent talk.
mcduff
Re: Conditional parallelism on LabVIEW
wrote: I am writing an application to update the numeric value given user's input value and depending on the user's input value the program checks if it is greater than 10 if it is greater than 10 then the program waits for 1 second and then will have a popup message says "true".
My intention was to call the conditional check, printing true every one second if the user's input value is greater than 10; in other words, the case structure was to be called regardless of the event structure in the same loop infinitely.
But it doesn't seem to work the way I expected. Unless there is user's new input value, getting into the event structure, the program doesn't get to the case structure even though the case structure is in a loop.
Is there any way to call the case structure not dependent to the event structure but I want to use a shift register for the numerical value and also having an event structure and a case structure in parallel.
If you want successful help, attach your code. It is a hurdle for everyone to recreate your picture from scratch, especially if certain things are ambiguous or not even visible (event configuration, code in other event case (e.g. timeout), valid control input ranges (data entry configuration), code in other cases of case structure, LabVIEW version, etc. etc.) So, as a first step, attach your VI!
I haven't read all the other comments, but here are some of the more glaring mistakes.
- Your dialog popup is modal and will stall the dataflow until acknowledged.
- Your reference and value property write is just plain silly because the controls already has the new value, else the event would not have fired.
- You are dealing with I32 integers (timeout, etc.) so change the representation to match.
- Again, you are creating a popup, not "printing" anything, whatever you mean by that.
- There are plenty of simple solutions to create the program you want, but that's not it.
- ...
Re: Wise use of Local Variable
Drat! I think I used the correct Snippet, but attached a flawed VI. Here's the correct one, with my apologies.
Bob Schor