LabVIEW

cancel
Showing results for 
Search instead for 
Did you mean: 

Timed Loop sometimes doesn't restart correctly if stopped using Stop Timed Structure VI

I'm using a Timed Loop whose period I want to be able to vary dynamically, and quickly. For example, if the period is one minute and I want to change it to one second, I don't want the loop to wait for the remainder of the minute before changing the period to one second.
 
I attempted this using a Timed Loop within a While Loop. A second thread invoked the Stop Timed Structure VI when the period control's value changed. This would cause the Timed Loop to stop, then restart using the new period.
 
This doesn't always work. Enclosed (assuming I'm using the Attachment feature correctly) is a VI that demonstrates the problem. On my computer, this VI fails under both 8.0.1 and 8.2.1. If I disable the signaling code in the first frame, it works. On a colleague's computer, it fails under 8.2.1 (with the signaling code enabled) but works under 8.5.
 
The failure mode is that the Timed Loop runs at top speed, using a period of zero. The Stop Timed Structure VI won't stop it- only a flag wired to the Timed Loop's conditional will stop it. (I put a 1 ms wait in the body of the loop, to keep it from hogging the CPU when it fails.)
 
This looks like bug ID 42CHH33W, which claims to have been fixed in 8.2.1. The workaround for that bug is, "Place the Stop Timed Structure VI in a Timed Loop with the same timing parameters as the Timed Loop it is meant to stop." This is not practical for me, because with that delay, the Stop Timed Structure VI might take too long to execute, and I might as well just wire the Timed Loop's conditional to a flag.
 
I'm guessing the problem has to do with restarting a Timed Loop that was stopped using the Stop Timed Structure VI.
 
Does anyone have a better workaround?
 
Thanks.
0 Kudos
Message 1 of 10
(4,438 Views)
Hi Ron,
 
I would like to clarify your question, you want a control that will change the timer of a loop without having to wait for the end of the loop to apply the time change. Essentially like an interrupt for the timer?
 
 
Juan Galindo
Applications Engineer
National Instruments
0 Kudos
Message 2 of 10
(4,407 Views)
Yes, that's what I want.
 
I ended up using nested while loops. The inner loop contains a 100 ms delay, and exits once it has executed a certain number of times. That number is my control, so I have 100 ms resolution. It's not a general solution, and it isn't pretty, but it works for my specific application.
 
The "right" tool for this would be a timing VI, like "Wait (ms)" or "Wait Until Next ms Multiple", but that would take a reference to a time or delay control, rather than a value. The VI would exit as soon as the time or delay was reached. Because it would use a reference, the time or delay control could be changed by another thread or by the user while the timing VI was running.
 
The trick would be to create such a VI that wouldn't be a processor hog, yet would still give ms (or usec for realtime systems) timing resolution.
 
-Ron
0 Kudos
Message 3 of 10
(4,392 Views)


@RonW wrote:
I'm using a Timed Loop whose period I want to be able to vary dynamically, and quickly. For example, if the period is one minute and I want to change it to one second, I don't want the loop to wait for the remainder of the minute before changing the period to one second.

All you need is a single loop and an event structure. Use the timeout in a shift register, so you can modify it in some events. Since any UI events will kill the timeout, you won't have any problems. See if this works for you. Always keep simple things simple. 🙂

See attached quick modification. Look ma, no local variables and no sequences! 🙂

Message 4 of 10
(4,378 Views)
You can also use an Occurrence to time your loop, instead of a nested Timed Loop. Occurrences have timeout values that you could set to be your loop timer. However, if in the middle of a loop you want to change the loop period, fire the occurrence and update the value.

Here's an example in LV8.2. This is not my invention either. OpenG has an abortable Wait ms timer that is based on Occurrences.

The downside to using event structure timeouts is that any event will interrupt the timeout event case from firing, even events not related to setting a new period. For instance, if you also needed to register for a Mouse Move event for some reason, then your loop timer would start over every time you moved the mouse.

Message Edited by Jarrod S. on 08-15-2007 05:33 PM

Jarrod S.
National Instruments
0 Kudos
Message 5 of 10
(4,362 Views)
Reading through all your posts... Occurrences fit all your timing needs. They are event-based, so they won't hog CPUs. You can get 1ms accuracy instead of 100. They are a very general, clean solution to build on. They require a lot less code than timed-loops or anything of that nature. Look into the OpenG packages I linked in the previous post. Download the Timing package and take a look at the Wait (ms) VI. It contains an optional Occurrence input to use as the timing source, which allows you to abort the timer at any time.

Message Edited by Jarrod S. on 08-15-2007 05:49 PM

Jarrod S.
National Instruments
0 Kudos
Message 6 of 10
(4,355 Views)
You could of course implement the kind of reference-based timer you spoke of in LabVIEW. Here's an example that takes a control reference for a numeric control as the timer value input. It waits until the control value's number of milliseconds have elapsed, or until the control changes values.

So anything's possible, but personally I'd prefer the light-weight occurrence-based solution to this. But it's a proof of concept. Open ref timer example.vi.
Jarrod S.
National Instruments
Download All
0 Kudos
Message 7 of 10
(4,351 Views)
So there are a lot of options. I wrote a notifier example based on the occurrence example, as NI says in their documentation:
 
"National Instruments encourages you to use the Notifier Operations functions in place of occurrences for most operations"
 
I like the event loop version, because of its flexibility. You can avoid missing or stretching cycles if you want. Enclosed is an example that looks a bit complicated, but it gives me correct cycle completion. For example, suppose the period is 30 seconds, and the loop is 5 seconds into it. If I reset the period to 15 seconds at this point, the loop will wait 10 more seconds (i.e. 15 seconds after the previous timeout) before it times out, rather than timing out immediately or after 15 seconds.
 
It also doesn't let cycles bunch up; if I set the period to 0 ms so the loop is racing, then set it to 10 ms, it will start immediately with the 10 ms period, rather than running through a lot of 0 ms periods first.
 
The problem of having other events interrupt the timeout can be avoided by simply not putting other events in this loop. Make another event loop instead, and make this loop an independent thread.
 
Thanks all. It looks like NI's suggested workaround was only one of many options.
 
-Ron
0 Kudos
Message 8 of 10
(4,327 Views)

RonW wrote:
The problem of having other events interrupt the timeout can be avoided by simply not putting other events in this loop. Make another event loop instead, and make this loop an independent thread.

Sorry, I only have access to LV 8.0 at the moment, so I cannot look at your code.

You can often solve things by dynamically recalculating the remaining timeout if other events occur, such as the light switch in my example:

RegulateTimeoutEvent1.vi 

(posted long ago here: http://forums.ni.com/ni/board/message?board.id=170&message.id=121087#M121087)

0 Kudos
Message 9 of 10
(4,319 Views)


@altenbach wrote:

Sorry, I only have access to LV 8.0 at the moment, so I cannot look at your code.



Here it is for LV 8.0.

-Ron

0 Kudos
Message 10 of 10
(4,316 Views)