02-09-2017 08:49 PM
background: I'm trying to automate an experiment by making my data-acquisition VI command certain actions at certain times.
at t1, the VI should command (via serial) a motor to start moving at input_RPM/3
at t2, the VI should command the motor speed up to 2*input_RPM/3
at t3, the VI should command the motor speed up to input_RPM
at t4, the VI should command (via TCP) a myRIO to begin pitching a blade
at t5, the VI should command the myRIO to stop pitching and the motor to slow down to 2/3 speed
at t6, the VI should slow down the motor to 1/3 speed
at t7, the VI should stop the motor
at t8, the VI should stop recording
In between the specified times, the VI should command nothing. For example, I don't want the VI constantly commanding input_RPM/3 between t1 and t2 since the motor controller has already "heard" (and implemented) the first command.
attempted solution (code attached):
My code is essentially 9 layers of if-else statements. I'm using an enum to prevent command spamming.
at t=0, enum/state = default_pass (no action)
if(t>t1 && state == default_pass ) => cmd 1/3 speed, state = stage1
else if (t>t2 && state == stage1) => cmd 2/3 speed, state = stage2
else if (t>t3 && state == stage2) => cmd 3/3 speed, state = stage3
else if (t>t4 && state == stage3) => cmd pitching, state = stage4
else if (t>t5 && state == stage4) => cmd no pitch and 2/3 speed, state = stage5
else if (t>t6 && state == stage5) => cmd 1/3 speed, state = stage6
else if (t>t7 && state == stage6) => cmd 0 speed, state = stage7
else if (t>t8 && state == stage7) => stop recording, state = stage8
else => do nothing (state is unchanged)
debug tools: I added an elapsed time control to simulate different times.
The state change after outputting a command lets me keep checking the time without sending additional commands. For example, when t first passes t2, state is still stage1, so the VI commands 2/3 speed and changes state. At the next while iteration, t>t2 but t<t3, t4, t5...t8, so the last else statement executes and nothing gets commanded.
problem/questions: I feel like I've developed something very inefficient.
Thanks!
02-09-2017 09:17 PM
You've already said the key word when you talked about a "state change". What you want is a state machine architecture.
You have a series of states you'll cycle through. Another aspect of that is creating an array of of steps that contain a time, an action, and any other data you need with it (like a speed). You cycle through the states, when a step is complete, you increment an index to get data out of the array for the next step and go through the state machine again. This will be the answer for questions 1 and 4. It is much more expandable if you ever need to revise your steps in the future. (Now, you'd have to essentially rewrite everything if you just wanted to swap a few steps, or add or subtract a step.) Search the forums for "state machine", as well as LabVIEW help and File >> New..... which has templates for different architectures.
For question #2, a handful of comparisons won't take that long on a PC. But the question becomes moot once you implement a proper state machine.
For question #3. You need to make your enum a type def. Replace all instances of that enum with the typedef version. Then when you add an item, all instances of the enum get updated automatically. Create the typedef as soon as you first create it. Then you'll save yourself a whole bunch of work later (like you have to do now.)
02-10-2017 02:16 PM
@state machine: I thought about a state machine (hence the enum), but wouldn't I still need a bunch of if-elseif-else statements to check the time? I'm not using the elapsed time express VI because I'm worried about the added overhead.
@typdef: D'oh, I can't believe I forgot about that. Thanks for the reminder!
02-10-2017 02:31 PM
@aeroAggie wrote:
@state machine: I thought about a state machine (hence the enum), but wouldn't I still need a bunch of if-elseif-else statements to check the time? I'm not using the elapsed time express VI because I'm worried about the added overhead.
...
Depends on how you structure you State Machine.
If you do a...
Init- puts all of your steps and times in an array
Check TIme - if next step is now or past do the step else wait and come back to Check Time
Do the Step - will execute the step at teh top of the list and then go back to Check Time
Lather rinse repeat
New "sequecnes" can be processed jsut by changing the array. The State machine adjusts depending on the number of steps and type of steps.
Ben