LabVIEW

cancel
Showing results for 
Search instead for 
Did you mean: 

Probably a bad way to implement a timer...

Solved!
Go to solution

Hi all. I need to implement a timer application that manipulates controls on a VI based on a time protocol. We are controlling a stimulator, but it might as well be an LED for the sake of discussion. The time protocol consists of successive intervals, each of which has a duration and a mode. The mode is either "stim", "no stim" or "alternating".  Alternating intervals have a sub-interval duration. For example, a protocol might consist of a 2-minute "no stim" period, followed by a 30-second "stim" period, followed by a 1-minute interval during which stimulation is alternated on and off at 20-second sub-intervals.

 

We need to be able to pause the timer, and while paused, stimulation will be "off". 

 

My initial solution is attached - I found the pause handler in the forum. For simplicity, I am ignoring the alternating case at the moment. The "Stim on/off" indicator is a stand-in for the stimulation control button in the real application.

 

This appears to work, but I suspect a queued state machine might be a better solution. I can't figure out how to get started on that solution though. Any thoughts?

 

Thanks,

-Jamie

 

 

Download All
0 Kudos
Message 1 of 13
(3,038 Views)

Attached is a stop watch timer program I made a while ago. The logic can probably be improved. The stop watch has a start/stop button and a reset button. Hit the start button to start the timer, and the stop to stop it. If you hit start again, the timer will start again withou resetting the elapsed time. Hit reset to zero the elapsed time. Hope this helps.

 

See https://forums.ni.com/t5/LabVIEW/Pause-and-Resume-Time-Elapsed-with-Events/td-p/3149632

 

For this original post and other suggestions

 

Cheers,

mcduff

Message 2 of 13
(3,033 Views)

@jfalesi wrote:

This appears to work, but I suspect a queued state machine might be a better solution. I can't figure out how to get started on that solution though.


Your description just screams State Machine.  The first thing you need to do is define all of your states and make a state diagram.

 

Just at the top of my head, states may include Idle (where you check for user inputs with an Event Structure and have a timeout), Check Timer, Stim, Stop Stim, Shutdown.  During the waits, you just go back  and forth between Idle and Check Timer.  When enough time has elapsed, then move on to the next step.  Store the accumulated elapsed time and current time in shift registers to better handle the pause functionality.


GCentral
There are only two ways to tell somebody thanks: Kudos and Marked Solutions
Unofficial Forum Rules and Guidelines
"Not that we are sufficient in ourselves to claim anything as coming from us, but our sufficiency is from God" - 2 Corinthians 3:5
0 Kudos
Message 3 of 13
(2,985 Views)

@crossrulz

Just at the top of my head, states may include Idle (where you check for user inputs with an Event Structure and have a timeout), Check Timer, Stim, Stop Stim, Shutdown.  During the waits, you just go back  and forth between Idle and Check Timer.  When enough time has elapsed, then move on to the next step.  Store the accumulated elapsed time and current time in shift registers to better handle the pause functionality.


I follow you, but I'm not sure why I'd need an idle state along with Stim and No-Stim. During stim and no-stim periods, wouldn't the state machine still need to go back and forth between Stim (or No-Stim) and Check Timer? There really wouldn't be a period during which the timer would be counting down without being in either a "stim" or "no-stim" state. Maybe I just don't understand what your "idle" state is...

0 Kudos
Message 4 of 13
(2,953 Views)

@jfalesi wrote:

@crossrulz

Just at the top of my head, states may include Idle (where you check for user inputs with an Event Structure and have a timeout), Check Timer, Stim, Stop Stim, Shutdown.  During the waits, you just go back  and forth between Idle and Check Timer.  When enough time has elapsed, then move on to the next step.  Store the accumulated elapsed time and current time in shift registers to better handle the pause functionality.


I follow you, but I'm not sure why I'd need an idle state along with Stim and No-Stim. During stim and no-stim periods, wouldn't the state machine still need to go back and forth between Stim (or No-Stim) and Check Timer? There really wouldn't be a period during which the timer would be counting down without being in either a "stim" or "no-stim" state. Maybe I just don't understand what your "idle" state is...


Well, I guess it really depends on what you are doing when you stimulate whatever it is you are controlling.  In the case of your LED, you just need to write a TRUE once to the LED and then you don't have to do anything to it until the timer says to go to the next mode.  So there is no real point in going back to the Stim state.  Similar for the No-Stim except you are writing a FALSE.

 

The point of the Idle state was to check for user interactions such as aborting or pausing.  And with the timeout, then this also allows your CPU to rest for a little bit before checking the timer and doing whatever from there.


GCentral
There are only two ways to tell somebody thanks: Kudos and Marked Solutions
Unofficial Forum Rules and Guidelines
"Not that we are sufficient in ourselves to claim anything as coming from us, but our sufficiency is from God" - 2 Corinthians 3:5
0 Kudos
Message 5 of 13
(2,944 Views)

@crossrulz

Well, I guess it really depends on what you are doing when you stimulate whatever it is you are controlling.  In the case of your LED, you just need to write a TRUE once to the LED and then you don't have to do anything to it until the timer says to go to the next mode.  So there is no real point in going back to the Stim state.  Similar for the No-Stim except you are writing a FALSE.

 

The point of the Idle state was to check for user interactions such as aborting or pausing.  And with the timeout, then this also allows your CPU to rest for a little bit before checking the timer and doing whatever from there.


So user input is typically checked for in only a single state, i.e. a "wait for user input" state? So any state that accepts user input has to periodically transition into and out of this state?

 

Does it break any state machine rules to allow multiple states to act on the same user input (obviously, not simultaneously)?

0 Kudos
Message 6 of 13
(2,939 Views)

As always, it depends on your requirements.  I just find, especially when these types of waits are involved, that it is best to have a single case with an Event Structure to check for user inputs.  You definitely do NOT want multiple Event Structures in your state machine (too easy to cause some really weird issues such as locked panels).


GCentral
There are only two ways to tell somebody thanks: Kudos and Marked Solutions
Unofficial Forum Rules and Guidelines
"Not that we are sufficient in ourselves to claim anything as coming from us, but our sufficiency is from God" - 2 Corinthians 3:5
Message 7 of 13
(2,935 Views)

I've done it a couple different ways, depending on how sensitive I want to be to user input.  When I'm not particularly sensitive to user input or if checking for user input is one of my states, I'll put an event structure into one of the cases.  If I'm more sensitive to user input, particularly if I need to interrupt the normal flow of states, I'll use a normal event structure, and put the state machine in the timeout event.

Message 8 of 13
(2,927 Views)

@crossrulz wrote:

As always, it depends on your requirements.  I just find, especially when these types of waits are involved, that it is best to have a single case with an Event Structure to check for user inputs.  You definitely do NOT want multiple Event Structures in your state machine (too easy to cause some really weird issues such as locked panels).


I get your point. However, this seems like an artificial constraint on state machines based on LabVIEW's mechanics.

 

For one thing, it means that any state whose transitions depend on user (or other external) events has to transition immediately back into "Wait". This means that sometimes you can't have clean state transitions. For example, I would like to have a transition from "Wait" to "Stim" upon reception of the next time period (I decided the timer would operate one period at a time, sent to it from a Time Protocol loop/state machine/TBD). I would also like to have a transition from "Pause" to "Stim", if the user decides to resume the last time period (there is also the option to "repeat" the last time period or to stop). However, in the former case, the "Stim" state needs to reset the Countdown Timer (which will be a separate loop/state machine/TBD that sends a "time elapsed" event when the time is up) and in the latter case it does not. Ideally, I would check the previous state to see whether the transition was from "Pause" or "Wait". But since the system needs to wait for an event when paused, the previous state was "Wait" in both cases. So now I need to check what the state was two states ago...

 

In essence, there's a "state bottleneck" at the "wait for event" action, and almost every state is a pseudo-state that encompasses a bunch of state-specific actions plus the "Wait" state.

 

Unless I'm missing something?

0 Kudos
Message 9 of 13
(2,914 Views)

@jfalesi wrote:
Ideally, I would check the previous state to see whether the transition was from "Pause" or "Wait".

No.  The Stim does not care who caused the state transition.  There are variables stored in shift registers it might care about, but not any previous states.


GCentral
There are only two ways to tell somebody thanks: Kudos and Marked Solutions
Unofficial Forum Rules and Guidelines
"Not that we are sufficient in ourselves to claim anything as coming from us, but our sufficiency is from God" - 2 Corinthians 3:5
0 Kudos
Message 10 of 13
(2,903 Views)