LabVIEW

cancel
Showing results for 
Search instead for 
Did you mean: 

Serial communication with a system stearing up to 8 devices.

I am writing a program to stear motors using serial communication (both RS232 and GPIB).
The program itself is relatively simple. I use an event structure. During time out I read the position and status of the motor. Possible events are among others absolute and relative movements of the motor.

However this program for one motor should be extended for a system with up to 8 motors. All these motors are connected to one single controller.

One could think about loading 8 copies of the vi for a single motor and running them at the same time. However I assume that this can't work because of the serial communication. If one vi asks for the position of 'its' motor the other vi's should wait until this communication is finished. Not sure how that would work. Furthermore there should be a 'main' vi for setting up communication parameters (choice between GPIB or serial + baud rate, ...)

The other option is to extend the vi from one motor to 8 motors. However this should be done in a clever way such that during time-out the program only reads in the position and status of the connected motors (of course not that difficult to implement) and that the front panel only shows the buttons and controllers for the connected motors (always the first x motors, so not motor 1,4 and 5 but rather motor 1 till 4 or motor 1 till 8). If I have 8 motors than the number of events in the event structure becomes rather larger (8 times move relative left, 8 times move relative right, 8 times move absolute left, and many many more..) .  The main disadvantage of this method is that  when future changes are made for one motor one has to do this for all motors (e.g. adding 8 times a button for memorizing a position).

All sugestions are welcome

Steven





0 Kudos
Message 1 of 6
(3,318 Views)
You should seperate this into 2 parts.
 
First, talking to the motors. My suggestion is to take an object oriented approach - think about the file functions - when you call the Open File VI, it returns a reference to a file which you then use to operate on the file. You can use the same functions to work on many files at the same time.
In the same way, you can define your motor as the object and create VIs like Create Motor, Config Motor, Move Absolute, Get Current Position, etc. The Create VI will return a reference which you then use to refer to the specific motor. Each reference is used as a pointer to a cluster holding the data for the motor (its name, its current position, etc.).
The key in having synchronization is to have the communication VI non-reentrant, so that whenever one instance is using it the others have to wait.
 
The actual implementation of OOP in LV varies, but there are several free options. My own experience is with DQGOOP, but searching for GOOP will find you some other options (like GOOP Developer, which supports inheritance). These tools take care of the whole behind the scenes stuff - creating a class for you, managing the tracking of objects, etc. OOP is not always simple to get into, but for things like your system, it's worth it.
 
Second, the UI. One suggestion would be to use an array of clusters to represent the active motors. You can control the number of visible elements by using a property node and you can monitor the array for events and compare the NewVal to the OldVal to know which element changed and how. I believe that by using programmatic registration you even register for changes for specific controls inside the clusters.
 
Another option is to use subpanels, but I think that's a complicated solution.
 
These two options are extensible and will reduce the number of events you need.

___________________
Try to take over the world!
Message 2 of 6
(3,315 Views)
Thank you for the very usefull input. Although I do my fair share of programming (fortran, matlab, labview, tcl, ...) I was not working yet with OOP (my course on C++ was already a long time ago and haven't used it since then). But I will play around a little bit.
 
So I started with the 'easier' part. You wrote: "One suggestion would be to use an array of clusters to represent the active motors. You can control the number of visible elements by using a property node and you can monitor the array for events and compare the NewVal to the OldVal to know which element changed and how".
 
I have included a test-vi that tries to work out this idea. Changing the number of visible elements works fine. Also checking which element has changed is of course no problem.
 
However there are some other difficulties. This main problem is that I would need different types of events for different parts of the cluster. E.g. I have to check for a 'mouse down' event when the user pushes the '<' or the '>' button (move relative left or right). But I have to check for 'value changes' when the user inputs an new absolute position (numeric controller above the <> buttons). Furthermore I assume I cannot have the current motor position (upper indicator) in the cluster because that would trigger new events every time the position changes.
 
One solution would be that one can register of events at a specific controller inside the cluster. But this is not accessible the way I have programmed it now.
 
An additional problem is that I also cannot access the mechanical action of the booleans (<> buttons) inside the array of clusters. So the latch function does not work.
 
 
 
 
 
 
0 Kudos
Message 3 of 6
(3,293 Views)
As I previously mentioned, you can get different events for different controls (see the attached), but you should think whether you need to. I believe that the Value Change event should be all you need. Note that changing the value programmatically does not trigger a Value Change event unless you are using the Value (Signaling) property.
 
As for the booleans, its true that you can't have latch actions, but you can have a switch until released action if you set it before you put it in the array. I believe that is the action you will want.
 
Note that you can not have controls and indicators in the same cluster or array, but you can turn your controls into indicator by setting their enabled state to disabled (right click>>Advanced).

___________________
Try to take over the world!
Message 4 of 6
(3,277 Views)
Thanks for the suggestions. I have a program that seems to work fine now. But I am not complete satisfied with the methods used.
I have included a test vi to show this.
 
1. During the time out I write a random value to one element of the cluster (simulation reading out a device). However when I add one element in the array (e.g. changing number of column from 2 to 3) then this new element is not active until the user changes one of the values of the cluster of this new array element. I assume there must be a way to activate an element of an array without user input.
 
2. The switch-until-released option seems to work fine (for the < and > buttons), except for the fact that 2 event are created why comparing old and new value of the array, that is, one during mouse down and one during mouse up (when the button is pressed longer that 100ms). This is demostrated by the led. Up till now I have solved this by checking that the actual value of the pressed button is 'true'  (not in the example vi) so only 'mouse down' events are used for further evaluation. However this makes the program (unnecessary?) complicated. Is there a way to optimize this?
 
3. In order to find which button was pressed I use two for loops and fine where the 'old' and 'new' value are different. I only check for the first 3 elements of the cluster (so I avoid that events are created when the user changes the controller between the < and > button). I was wondering if there is a more elegant way to do this.
 
Steven
0 Kudos
Message 5 of 6
(3,225 Views)
1. During the time out I write a random value to one element of the cluster (simulation reading out a device). However when I add one element in the array (e.g. changing number of column from 2 to 3) then this new element is not active until the user changes one of the values of the cluster of this new array element. I assume there must be a way to activate an element of an array without user input.
"Activating" an array element is done by putting a value into it. Your for loop (which controls the value of the array) only runs on the existing elements of the array. Note that you could have a race condition here. If you were to add an element after the first local was read and before the second was written, writing to the local would erase what you have done because it would restore the data which was read before you changed the array.
What you might want to do is keep the array data elsewhere and build the array from scratch each time instead of reading-changing-writing which is what you're doing now. Then, the protection for the array can be in whatever mechanism you use (a class, an LV2 global, etc.). For example, you could create a class with an "add element" method and a "get elements" method or you could have these as actions in an LV2 global.
2. The switch-until-released option seems to work fine (for the < and > buttons), except for the fact that 2 event are created why comparing old and new value of the array, that is, one during mouse down and one during mouse up (when the button is pressed longer that 100ms). This is demostrated by the led. Up till now I have solved this by checking that the actual value of the pressed button is 'true'  (not in the example vi) so only 'mouse down' events are used for further evaluation. However this makes the program (unnecessary?) complicated. Is there a way to optimize this?
Probably not. Since you want the switching events, checking the value is the only way to know which event you got.
3. In order to find which button was pressed I use two for loops and fine where the 'old' and 'new' value are different. I only check for the first 3 elements of the cluster (so I avoid that events are created when the user changes the controller between the < and > button). I was wondering if there is a more elegant way to do this.
You can replace the internal while loop with a Search 1D Array function and search for True. If the index is >=0 you can stop the loop and return the index.
 
To learn more about LabVIEW, I suggest you try searching this site and google for LabVIEW tutorials. Here, here, here, here and here are a few you can start with and here are some tutorial videos. You can also contact your local NI office and join one of their courses.
In addition, I suggest you read the LabVIEW style guide and the LabVIEW user manual (Help>>Search the LabVIEW Bookshelf).

___________________
Try to take over the world!
0 Kudos
Message 6 of 6
(3,215 Views)