12-02-2011 11:30 AM
I have attached an example for review. @Lynn, with your help the RS232 communication queue was achieved. now, I have extended the concept to using a queue to sending the data to main SM controls.
I Created this example for my understanding. I know there is redundant use of Local variables. I think for sure the local variables can be safely changed to Globals and data from Loop 2 can be sent to Loop3 by using Global varialbes. If I replace with Global variables, then I wouldn't need queues between loop2 and loop3 correct? I would like you guys to point out my errors.
#1 error: obvious, redundant use of local variables. Is there any more?
P.S. I haven't looked at Stopping loops yet.
12-02-2011 12:29 PM
@VeeJay wrote:
Or would you think implementing parallel state machines for each parallel system would be more efficient?
If the tasks are essentially independent of each other I would create a separate task for each with it's own state machine. An added benefit is that if you need to do a similar system that would use one of the tasks it is much easier to reuse the code if they are separate. As you endeavor down this path make sure you always think about restorability. As you develop a way to stop multiple tasks (also include things like start and exit) think about encapsulating that functionality into a reusable package. That way when you start your next project you have a working model for that functionality and you simply reuse it. As you increase the size of your reuse library your applications become much easier to write. You no longer have to spend thinking about or recoding the common stuff and you can focus on the application itself.
12-02-2011 07:31 PM
VeeJay,
Send the data via queues. Do not use local or global variables for that purpose. If you really need a global, use a functional global VI or Action Engine rather than the native globals. Your locals have race conditions. Replacing them with globals would not eliminate the race conditions. Shift registers should be used to pass data around within the loop. Queues to send to another loop.
Loop 2 will never stop unless a 170 is sent from the RS-232 loop. Stop should stop all the loops, or at least inform the state machine i those loops with state machines that a stop command has been generated.
Loop 2 has two Dequeues with infinite timeouts. The Enqueues are in different loops. Depending on the timing of the other loops you could get behavior which might not be what you expected. Often it is better to set a finite timeout and examine the timed out? output to see if the queue produced valid data.
Now to add even another complication: I recommend that all the pushbuttons be put into another loop with an event structure. Then data only goes into the queue when a button is pressed rather than every tem milliseconds. (then you really do need the timeouts on the Dequeues!)
I agree that you have made a lot of progress from your earliest posts. Keep working at it. I learned LV on my own also, but did not have the benefit of the Forum to help until a few years ago.
Lynn
12-08-2011 12:39 PM
@Lynn @Mark,
You had suggested that I refrain from having State machines within state machines. In which case, I will have while loops within while loops. You had asked me to make use of the outer loop for iteration.
As I see it, if I have like 3 states within a particular State of the outer SM, I might as well just define them as states in the outer SM itself. Is this the way to go?
VB
12-08-2011 01:10 PM
Also, in general principle, Can Outer SM sit in different states for different amounts of time? i.e. can the outer loop not iterate until whatever is running inside completes, then update the shift register? Just a question. Thanks!
12-08-2011 01:21 PM
This code is unnecessarily complex and convoluted. I see no reason for your Loop 2. Selection of the correct data to send can be a simple subVI that gets called after each read. Your upper loop won't do anything until it processes the read anyway so why process the response in a different task. Your situation looks like a basic command/response system. The logic for your application control in general is very hard to follow. Parallel processing is a good thing but don't use it simply to use it. You should have good reasons for separating out the tasks.
12-08-2011 02:03 PM
Hi Mark, I have to clarify. THe code posted is not complete. I guess I should take it out, lest it confuses more. That is a skeletal vi, not even close to 1% of entire code. Sorry about that. There is a sequential nature to my application and all I tried to do in that code is see if it would make sense to send data that way, instead of using property nodes like I do now, I replaced them with locals.
My question is related to Lynn's previous suggestion on SM within an SM (loop within loop). And in that LOOP3 which is a SM will have states within multiple states within. That was what I was referring to.
THanks!
12-08-2011 04:29 PM
Locals are not really better than using property nodes. They are faster but you still have all of the issues with race conditions. When I have suggested separating the processing of teh data with a receive task this is for cases where the receive task is doing nothing but receiving data. In your case you receive data, process it the send data. This can all be done in the same task. No need to complicate it by separating it inot multiple tasks.
The sequential nature of your code can be implemented using a state machine. Depending an the amount of activity it may be one state or several states. If you reuse a portion many times this would make it a good candidate for a separate state or at least a subVI.
You can have small state machines within aother state machine. The main thing to consider is whether the inner state machines are finite and do not need to run continuously. There is no single answer as to whether it is appropriate or not. It depends on the specific system.
12-09-2011 09:32 PM
VeeJay,
Let me try to address your questions:
"As I see it, if I have like 3 states within a particular State of the outer SM, I might as well just define them as states in the outer SM itself. Is this the way to go?"
That is a straightforward way to get started. As Mark pointed out, you really need to define what is appropriately considered a state. When designing a state machine for a complicated process, defining the states and the transitions between states often takse more time, and definitely more thought, than writing the code to implement the program. In the early stages of the desing process I prefer to err on the side of having more states rather than fewer states. If you decide later that two states always occur together they can be combined or if two states perform almost the same task one can be eliminated.
"Also, in general principle, Can Outer SM sit in different states for different amounts of time? i.e. can the outer loop not iterate until whatever is running inside completes, then update the shift register?"
Of course. The nature of dataflow requires the last part to be true - the loop cannot iterate until the code inside completes.
This is another element of the design process. How long can the system be allowed to remain in one state without checking for errors or user inputs? If a task might require an hour to complete, such as warming up a large furnace, you may not want a Wait for Warm-Up state with a one hour wait inside. The Warm Up state might wait 1 second and the check to see if the user has sent an Stop command. If not, re-enter the Warm Up staet for another second. The while loop would iterate 3600 times, going through the Warm Up state 3600 times, before going to a different state. But if the user discovered after 20 minutes that the wrong samples had been placed in the oven, the process could be interupted in one second.
I agree with Mark that in certain situations having a state machine within a state machine is perfectly acceptable. For example using a state machine to parse a string received from an instrument via a serial port might be fine. The inner state machine could determine whether the sting was valid, whether it contained an array of data, or whether it reported an error from the instrument. This kind of state machine would probably execute in microseconds and would always stop when it completed parsing the input string.
Lynn
12-12-2011 09:48 AM
Thank you Lynn! I see you point and agree with everything you said. It is a little difficult for me to define my states because it is a complicated system, so I am going with generics like Start, Operational, Wait etc.
With reference to your example, I have a question and a comment on the way I do it in my application. Like you said, if the user hits stop in 20 mins, the fact that the loop runs once a second helps with detecting that stop and hence stoppng the Warm-up state. But, the way I have implemented is when multiple states run inside a given state of outer SM, I pass reference of STOP boolean into the inner states. In that way, When a STOP command is issued, the inner states stop what they were doing which inturn frees up the outer SM to go to the next state. This is definitely a round about way of doing things, but I have a working (not efficient) system 🙂
I have been working hard to elimate duplicate states and make my application robust as possible. Thank you for your comments/help. Keep them coming. I love improving and learning which will help me when I take my CLD. 🙂