02-15-2011 07:26 PM
I have 2 devices with serial port (Device1 uses COM1, Device2 uses COM2).
On the device level I created bunch of VIs - one VI per serial port command. All device level VIs use "WriteToSerialPort.vi" or/and "ReadFromSerialPort.vi"
Top level VI of program has 2 loops. One loop supports UI controls actions and calls device level VIs. Another loop reads from the devices (also uses device level VIs) some parameters constantly and renew according UI indicators.
Sometimes I had that loop1 reads answer after command of the loop2.
I made "WriteToAndReadFromSerialPort.vi" and used semaphore to avoid this problem. But I lost that "2 loops of the program send commands to different devices at the same time".
So how can I write program that
- 2 loops of the program send commands to different devices at the same time and don't touch each other answers
- 2 loops of the program can't send commands to the same device at the same time.
I know how I can do that in normal language, like C++, C#, or Java. But I can't understand this from LabVIEW manual.
Thanks!
Also I am not sure what is mean "task" in semaphore according help. Is loop in my program task?
02-15-2011 11:49 PM
Have you taken a look at the semaphores example that ships with LabVIEW?
I don't quite understand which "task" input you are referring to. There are no "task" inputs on the semaphore VIs.
02-16-2011 04:01 AM
The simplest solution is to call the obtain VI in each call, but this will leak 4 bytes each time if you don't release the reference and will have some performance implications if you do (although I'm not sure how much.
One easy way of working around this is to do something like this:
This obtains the reference once for each copy of the VI in the diagram and then gets it from the feedback node for every subsequent run, but the main problem with it is that assumes that every call of that instance on the diagram will be to the same port. This is a problem if you're not aware of this or if you're iterating over multiple ports in a loop, but there is a solution - you create a manager VI which accepts a VISA ref and returns the appropriate semaphore. Such a VI is non-reentrant and has a global internal buffer of VISA-semaphore pairs which it keeps track of:
If it finds the semaphore in the list, it validates it and outputs it. If not (or it's invalid), it creates a new one and adds it to the list.
In this example, I used variant attributes to hold the name-value pairs, but you could also manage it by building two arrays and doing the lookup yourself or by any other method.
You can find more info on this type of construct here - http://forums.ni.com/t5/LabVIEW/Community-Nugget-4-08-2007-Action-Engines/m-p/503801#M240328
02-16-2011 10:53 AM
smercurio_fc, please, read LabVIEW help about semaphore and you will find "task" word there.
02-16-2011 10:58 AM
tst - thanks!!!
I think reentrant VI should work. I would prefer to create structure with serial port and semaphore instead of your second VI.
02-16-2011 11:20 AM
@Vasilich2004 wrote:
@smercurio_fc, please, read LabVIEW help about semaphore and you will find "task" word there.
I thought you were referring to an input called task.
02-16-2011 12:31 PM
Think of a task as being how many concurrent things you want to happen at once before they any more are locked out. In probably 99% of the use cases, you are protecting a section of code so that only one "task" can access it at once. To go with the train metaphor, let's say you have a single track and potentially multiple trains possibly trying to run down it at the same time. You'd set the size input to 1. Let's say you have two parallel tracks. You'd want to allow up to two trains to run at once, but the third or more trains have to wait until at least one clears, then you'd set the size input to 2.
02-16-2011 12:55 PM
Thank you. I know about normal theory.
But what is "task" mean in LabVIEW? LabVIEW help index doesn't provide reasonable information. It points to DAQmx task!
For example, how does LabVIEW work if VI has two independent "lines"? It will create 2 buffers and puts commands from each line and then one real thread will implement comand from one buffer, then from another and so one. Or it will create another real thread for second "line"?
What is rule if the same VI is called from both "lines" at "like" the same time?
02-16-2011 02:04 PM
I think the term "task" used in the help file for the semaphore is a little bit ambiguous and certainly isn't the same as tasks for DAQmx.
I think the way they are using "task" as a general term in the help file just to say, "Hey, I have two different sections of code that each have something they want to do (i.e. a job, a task, a series of program functions) that I don't want them to do simultaneously."
In your description, I think using the term "buffers" and "lines" is just confusing things more in trying to describe semaphores, and I don't know how to answer you specific questions. All I can say is that if two different sections of code hit their respective semaphore gates at the same time, one or the other is going to get the lock first and will be able to move on, the code execution is going to pause for the other one. Once the first "task" gets done its execution and hits the release semaphore block, the semaphore is now released and the second series of code is now free to move beyond the lock semaphore function. It will lock the semaphore and move on to the following functions.
02-16-2011 03:02 PM
Task is not a technical term. It just means a piece of code which uses the semaphore.
Vasilich2004 wrote:
For example, how does LabVIEW work if VI has two independent "lines"? It will create 2 buffers and puts commands from each line and then one real thread will implement comand from one buffer, then from another and so one. Or it will create another real thread for second "line"?
What is rule if the same VI is called from both "lines" at "like" the same time?
The way LV executes parallel code changes based on the compiler version and specific conditions, so there's no way of providing a definitive answer, but in general, if you have two pieces of code which do not have a dataflow dependency, LV will try to execute them in parallel. If you want to dig into the LV execution engine, there are various documents available online.
As for the second questions, if the VI is non-reentrant, one instance will have to wait until the other finishes executing. If it's reentrant, you'll get two copies running in parallel.