LabVIEW

cancel
Showing results for 
Search instead for 
Did you mean: 

Trigger an Event After Some Delay

Starting with a basic state machine + event structure, I want to implement a way of moving to a state after X seconds delay, but without blocking anything else during the delay time. Ideally I wanted to build something general-purpose, so I can use the delayed-state function without thinking about it.

 

Attached is a stripped-down version of what I came up with on a first pass. It seems to work fine, but I'd appreciate any review or critiques of my approach, or suggestions for improvements.

 

 

In short: I created a second loop parallel to my main event loop to handle counting down the timer, and sending a user event when the timer reaches 0. When the user event eventually fires, it pushes the desired state to the state machine.

 

I passed the timer information between loops using globals. Once something in the main loop sets up the timer global, the second loop takes over in counting down. Using globals is probably the LabVIEW faux pas I should fix here. I can spot a potential race collision already: between the main loop writing to the timer global (to set up a new event) and the second loop also writing to the global (during the counting down).

 

Before I get to fixing that problem, I thought I'd ask the experts for any other general advice!

 

LV2019 attached.

0 Kudos
Message 1 of 6
(235 Views)

I cannot look at your VI, no LabVIEW on this computer.

  1. You are correct, try to avoid globals.
  2. Rather than create a second loop, I would create a reentrant VI that functions as a count down timer. It should have the following inputs:
    1. Countdown time - then no globals needed, set when called.
    2. Timer Name - If you have more than one timer, you can distinguish which one fired
    3. User Event - Use this to fire an event to your state machine
  3. Use the Call and Forget Mode to start your Countdown timer (look in the example finder), You can then call your timer in a state multiple times and no second loop required
Message 2 of 6
(209 Views)

That's way more complicated than I would like.

Here's how I would do it.

0 Kudos
Message 3 of 6
(160 Views)

I can't open your file.  My recommendation is to get a proper state machine like the JKI state machine template.  This can be found on VIPM. 

aputman
0 Kudos
Message 4 of 6
(152 Views)

This worked neat!

 

The Call and Forget example used the 0x80 flag in the async call. Do I also need the 0x40 flag if I want the async timer VI to be able to have multiple running copies? I set the async VI to 'Preallocated clone' and called it using 0xC0, and it seems to work but I don't fully understand the different options for either.

JeremyPeterson_0-1752514748454.png

 

I also found that the async called VIs stay running if the caller VI terminates, which was a bit ugly. I hacked in a fix to this by passing a reference to the caller and monitoring Execution.State during the countdown, aborting if the caller isn't executing. I wonder if there's a call setting that might avoid needing to do this.

0 Kudos
Message 5 of 6
(98 Views)

Note that it you use a strictly-typedef'd reference to your sub VI for the "type specifier VI Refnum (for type only)" input to "Open VI Reference", then your code will be more robust:

Timed_State - cleaned.vi Snippet.png

Message 6 of 6
(83 Views)