LabVIEW

cancel
Showing results for 
Search instead for 
Did you mean: 

Efficient time-based triggering

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.

  1. Can I trigger my experiment without a bunch of case-structures? Can you think of a way to get down to the last (default) else case without traversing all the other cases? Now that I write that out, I think it's impossible (it's default for a reason), but I'm open to ideas of revamping my code. I'm developing this VI as a general template for future experiments, so the more intuitive the better.
  2. Regardless of 1's answer, how can I make my code less time-consuming for the PC?
    Or am I over-estimating the added timing of my triggering logic? 9 comparisons may seem annoying to me, but I imagine it should only take microseconds for my laptop's CPU.
    Note: in the final version of my VI, each while-loop iteration will also transfer data from a DAQ's buffer into my computer at 100 Hz and potentially send TCP and serial commands (depending on the stage)
  3. How can I auto-update the enums in my current code?
    If I add or remove a case from my enum, I have to manually delete and paste a new version of the enum at every enum constant's location. How can configure my code so changing a single enum constant at one location updates all of the constants in my code?
  4. Why does my code trigger up the if-else ladder?
    If I input t* where t4<t*<t5 and the desired outcome is a command to pitch, my code executes every single case up to the desired command. That is, my code commands "rpm1, rpm2, ..., start pitching". How can I set it to simply command "start pitching"?

Thanks!

0 Kudos
Message 1 of 4
(2,448 Views)

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.)

Message 2 of 4
(2,444 Views)

@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!

 

 

 

 

0 Kudos
Message 3 of 4
(2,397 Views)

@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 

 

Retired Senior Automation Systems Architect with Data Science Automation LabVIEW Champion Knight of NI and Prepper LinkedIn Profile YouTube Channel
0 Kudos
Message 4 of 4
(2,393 Views)