03-24-2015 03:43 PM
Hello,
I could really use some advice on the proper architecture for my application.
My application is to automate a test whose channel states will be independant from one another. To acheive this I have one State Machine per channel but am having some difficulty deciding how the While Loop fits in.
Besides the State Machines, I am continuously receiving test data via a TCP/IP connection. The test data is fed into the State Machines which then output a control string. The control strings are combined and sent to the controlling device using TCP Write. Because of the need for continuous TCP Reads and Writes, I am reluctant to place the State Machines, or rather Case Structures, into independant While Loops. In such a case, the only options I can see are either placing the State Machines (including While Loops) into a larger While Loop that houses the TCP Read and Write. I am reluctant to do this because of the nested While Loops. Alternatively, I could place a While Loop parrallel to the State Machines but that would throw off the TCP Read -> State Machine -> TCP Write sequence. My final idea is to place three Case Structures into a single While Loop that encompasses the TCP Read and Write but I wonder if the channels will no longer be independant of one another.
Hope to hear from you,
Yusif Nurizade
P.S. I wanted to get some input on architecture before getting to far with the VI. subVIs are complete but the main VI is pretty bare. I can throw together a block diagram if it would help illustrate the issue I am having.
03-24-2015 03:56 PM - edited 03-24-2015 03:57 PM
@Akello wrote:
Hello,
To acheive this I have one State Machine per channel but am having some difficulty deciding how the While Loop fits in.
By this do you mean you have one state machine on the block diagram per channel? (50 channels = 50 separate state machines on block diagram)
If this is the case, I strongly advise against this architecture. Aside from being large and difficult to read, it makes your program very difficult to expand if you need additional channels later. Instead, you could do an array of states (one element in array = state of 1 channel), and then a for loop containing a single state machine that just crunches through the logic of each channel.
You also could look in to the continuous measurement and logging sample project. It uses queued message handlers and the architecture very likely would support exactly what you are doing. It isn't a simple architecture but very expandable and it wouldn't take too much massaging to make it do what you needed.
Edit: clarity
03-24-2015 05:13 PM
Trust me, Microsoft Word (or whatever other word-processing software you prefer) will be your friend here. I ignored the advice "Write the Docummentation First" for many years, but as I've started working on more complex problems, I've started writing serious documentation (3-5 pages, minimum) before doing much programming, and it makes a tremendous difference! For one thing, it forces me to identify all of the relevant parameters I need to worry about, make a list of all of the sequential and parallel tasks I need to create, documents all of the communication paths that I think I'll need, etc.
Sounds like you are in the same situation. Try not thinking about LabVIEW, or how you are going to do what you need to do, but rather (in some detail) precisely what it is that you need to accomplish. Include the number and nature of your "channels", whether multiple channels are tested synchronously or asynchronously, whether tests are in a predetermined or "user-determined" order, what sort of input (controls) and outputs (reports, charts, files) you need.
Once you have some of the Big Picture ideas, you can start to think about architecture. Some of the Project Templates that ship with LabVIEW might well handle your task, once you have defined it more clearly and completely.
Bob Schor
03-24-2015 05:52 PM
03-25-2015 10:40 AM - edited 03-25-2015 10:42 AM
Thank you everyone for the responses. I appreciate your input and think that I will learn a good amount on LabVIEW architecture from this topic. Will try to address the suggestions point by point:
@BowenM: My initial plan was to do one State Machine per channel. For this application there is a hard maximum of 4 channels as that is all that the electronics will support. It occurs to me that this won't be an architecture that I can quickly throw together so I'm thinking I should get the program running with one channel and expand from there. I like your array of states idea and will be looking into the queued message handlers. Given the latter's complexity, is it an option worth pursuing given I am planning on a maximum of 4 channels?
@Bob_Schor: I do have quite a bit of documentation on how the test and automation is to be conducted. I kept it short for the sake of brevity on the forum but can expand on any of the points you mentioned upon request. Please let me know what needs to be clarified.
@mikeporter: As I mentioned in response to BowenM, there will be a maximum of 4 channels. I followed the link to your signature and read the post Reentrant Execution: Taking Flexibility to the Next Level: Dynamic Linking. Forgive me but I am still not entirely clear on how I will benefit from the reentrant aspect. The TCP Read will give me a string that is broken down and passed to the (up to) 4 channel State Machines. These share the limit parameters and will compare them against the data before making a decision regarding the state. Their outputs are then combined into a single string that is sent to the controlling instrument. Would they really get in eachother's way?
I knew going in that my method was not the best architecture to have. I am still wondering what the best way to keep the channels independant would be and in the mean time I am writing a simpler version of this VI for a single channel. I am hoping to flush out the best way to handle multiple independant channels and their corresponding control states.
Thanks again,
Yusif Nurizade
P.S. What is the proper way to reply when I receive multiple responses? This time I clicked reply to the last post but I am wondering if that will fail to notify the other posters.
03-25-2015 11:46 AM
03-25-2015 12:54 PM
Mike/Aslan,
Could you please elaborate on what you mean by device? The channels, rather the electrical components controlling the channel states, are controlled by an MCU. The MCU IO is controlled by the LabVIEW VI.
While the channels are controlled by one device, they need to be independant of one another. That is, if one channel reaches a limit faster than the others, it should switch to the corresponding state while the rest stay in the same state until the limit is reached. Would this not warrant seperate State Machines or at least seperate state variables?
Best,
Yusif Nurizade
03-25-2015 12:58 PM
It just might be the embedded developer in me, but why aren't those states maintained in the microcontroller? That would be the safest place for them since you could have communication issues.
03-25-2015 01:01 PM
Responding to your P.S., any reply to your Post (whether by you or by one of us) goes to everyone who has checked "Email me when someone replies", which (I'm guessing) most of us have done.
BS
03-25-2015 01:28 PM
I have an application that might be similar to yours. I have an Programmable Industrial Controller (PIC), about 15-20 year-old technology, that I "talk to" using a Serial line from LabVIEW. It controls three robotic axes by executing "trapezoid" moves (Move to Position P at Velocity V, Acceleration A, and Deceleration D). I'm running this "open loop" (meaning without feedback) and want to give the three axes independent movement profiles ("at time t0, move to a new position P1 using parameters V, A, and D, then use the same parameters to come back to the starting position P0, and do this N times").
The PIC needs to get a "Move" command essentially at the time of each movement (the times are predictable from the parameter set). The three axes are independent, so we can expect (for the most part) that at any given time, from 0 to 3 axes will get a Move command.
I've programmed this as an Action Engine, driven by a Scheduler, which is basically a clock-driven routine that has a list (Queue) of requests (e.g. Move Axis 1) to do when the Timer says that it is time to do it.
The Action Engine maintains three shift registers, one per axis, that contains the parameter information needed to generate the next command. When the "Move Axis 1" Action is presented, the Axis 1 parameter is read, a suitable command to the PIC is generated (and sent to the PIC), and the parameter is updated as appropriate, including counting down the number of times to move that axis.
The weakest part of this process (which seems to work well, by the way -- my three axes appear to move as I expect) is the timer. This code runs on a PC, so there's no guarantee that cycles won't be "stolen" by Windows. What I basically do is to have a parallel loop running with a 1 msec Timed Wait that fires the index of the While loop into a Notifier. My Scheduler has a Wait for Notification, compares the time from the Notifier with the time on the next Action, and either fires the Action (by putting it on the Action Engine Queue) or does nothing, waiting for the next tick. All the while, multiple other processes are going on (display, TCP/IP receipt of data from a RT system sampling multiple channels at 1KHz, streaming of sampled data to disk, etc.) quite happily in parallel.
If this sounds like your system, you might consider this approach.
Bob Schor