LabVIEW

cancel
Showing results for 
Search instead for 
Did you mean: 

Timing after event without locking out the user

Solved!
Go to solution

Hi, I am trying to create some software to control a powersupply. One feature that I am having trouble adding is a timer.

 

I have an event structure that is activated when the user presses buttons, most of which slowly increase the current over a user defined time. I want the timer to count up to this user defined time (in seconds) after the event is triggered. One thing, however, is that I need to be free to trigger another event (which stops the power supply in case of emergency) so I can not have this timing process lock me out from pressing buttons.

 

I was experimenting with the millisecond timer as well as with a for loop that iterates with a defined time interval, but it doesn't quite give me the functionality that I want. (I've been placing these timing loops outside the event structure to allow other events to still execute, but I want the timer to only starts timing after an event is triggered, is this even possible?)

 

If you need more info, just ask, thanks!

0 Kudos
Message 1 of 20
(3,940 Views)

Are you familiar with different programming design patterns, such as a simple producer consumer loop? Perhaps your requirements could be fulfilled by this design pattern.

 

Basically, create two parallel loops. Having two parallel processes allows independent execution rates of what's happening in those two loops. The first loop is the "producer" loop, which contains the Event Handler Structure. This will service UI events, such as button presses. When buttons are pressed, a control message will be sent to the lower loop via a Queue. This lower loop is set to continually poll (set the Dequeue timeout to the nominal loop rate time), which will allow the timer to increment/decrement. Subsequent messages can either pause/reset/stop this loop timing variable.

 

Another method (simpler, yet arguably less flexible) would involve wiring a value to the Timeout Terminal of the Event Handler structure. This would allow the While Loop that contains the Event Handler to poll, where code in the Timeout case would execute periodically.

 

Feel free to post code, and I (and others) will gladly and kindly critique and suggest design decisions.

Message 2 of 20
(3,929 Views)

Here is an example of the producer-consumer loop that Jack was talking about.  I had to add one more loop, to show an example of how to control a process from the consumer loop, and be able to do an emergency stop.  The third loop has to be in parallel to the consumer loop so that the consumer can process the stop button (emergency stop).  When the OK button is pressed, the third loop will start a counter.  You can put your current ramping code here.  It will stop when the Counter Value is reached.  While counting, you can also press the stop button to abort the counter and stop everything.

The vi is in LV2009.

 

 

- tbob

Inventor of the WORM Global
0 Kudos
Message 3 of 20
(3,922 Views)

Personally, I would go with one or two loops, not three. The consumer loop would have 10msec wired to the "Dequeue", and a case structure fed from the Dequeue's "timed out?" terminal. If the Dequeue times out, the True case would execute the timer increment/decrement storing the current value in a shift register. If a message is received, "timed out?" would evaluate to "True" and the code inside would reset, pause, or stop the counter. Also, this eliminates the need for two more extraneous variables, Count Enable and Loop Stop. (Arguably, Count Enable would still remain, yet might instead manifest itself as a wire and shift register rather than a Front Panel control)

 

This method could even be collapsed into one loop and no messaging queue for the ultimate in simplicity.

 

I don't have a LabVIEW version on this computer I can distribute code with, so I am unable to provide an example.

0 Kudos
Message 4 of 20
(3,918 Views)

I'm not sure I've followed the 'producer-consumer' template you were talking about. I am not familiar with queues either, but I can look into that. I have been learning LabVIEW as of two months ago and it is kind of the first computer programming I've done.

 

Here I have taken a screenshot of the block diagram. On the left of the while loop the power supply is initialized, and on the right communication is terminated. I have added comments which pertain to the red rectangles. The event structure has 10 events, including time out, and right now you see one that aborts a current ramp if one has been started.

 

One closing question: can you use that 'time' box in the event structure for timing anything?

 

Thanks!

0 Kudos
Message 5 of 20
(3,902 Views)

It is hard to tell from a picture because we can't see what is in the other events.  Attach your full vi.  However, here are some suggestions:

 

Don't use local variables,  You have many on the lower right.  Where are the real controls/indicators for these locals?  It would be best just to use a wire fron the real control/indicator to the math functions.  The wire is the variable.

 

Put your booleans inside the event case for each boolean.  For instance, if you have boolean labeled Stop, place that boolean control inside the event case for Stop: Value Change.  This way, the code will read the boolean when the event gets fired.  If the booleans are set for a mechanical action of any latch type, they may not be read when the event fires, and the latch will be stuck (will not go back to False).

 

I'm not sure about your Timer indicator because I don't know what you want to do with it.  Where is the code that times anything?

 

- tbob

Inventor of the WORM Global
0 Kudos
Message 6 of 20
(3,883 Views)

Previously, there was no code to time anything, just a timer indicator. I have added something you might call a consumer as another loop. Please bear in mind that I have not used queues before... I will leave the local variables where they are for now, just for time's sake, and go back and take your suggestion once I send this.

 

You can add the attached sorensen drivers to the instr.lib folder if you want them to appear correctly in the block diagram.

Download All
0 Kudos
Message 7 of 20
(3,872 Views)

A brief clarification: I want the timer to count up to the number given by "ramp duration" so the user can see how the ramp is progressing. Once it gets to the "ramp duration" I want it to stay at that number, and then go back to zero once a new ramp is started.

0 Kudos
Message 8 of 20
(3,871 Views)
Solution
Accepted by topic author gjacob

Thnigs to do to greatly improve your code:

 

You don't need the separate loop.  Put your timer code inside the event structure Timeout case.  Set the timeout value to 50 instead of 500 to match what is in your separate loop.  You can get rid of the queue becaue it won't be necessary anymore.  Create shift register on the main loop.  When the event happens to start the timer, pass the time to the shift register on the right side.  Wire the shift register from the left side to the Timeout event to use its value.  BTW, the shift register in your separate loop serves no purpose because you are not changing the value on the wire.  Don't put the entire loop into the Timeout case, Get rid of the loop and just put the code from the loop, except for the End variable which can be deleted, and the 50mS delay, which can be deleted.

 

Put the Start Inc boolean inside the Start Inc Value Change event case.  Same for all other booleans.  Put them inside their particular event case.

 

Get rid of the local variables now.  You will have race conditions if you don't, causing you trouble that you don't need especially at this time.  Look at the Current Limit control.  Add a wire from the Current Limit control to where the Current Limit local variable feeds.  Delete the local.

 

Move all controls from inside the event structure to outside the event structure but still inside the main loop.  Wire the controls to where they go.  Now you can eliminate all thos local variables and just wire from the control to where they are needed.

 

All of those Error Outs.  You only need one.  Create an Error In on your front panel.  On the block diagram wire the error in to the first Sorrensen function before the loop.  Where the error out from the Sorrensen function hits the loop, change that terminal to a shift register (right click and select Replace with Shift Register).  Move the Error Out 2 to outside the loop on the right side.  Wire the error out 2 to the shift register on the right side.  Everywhere you need an error in, branch it off of the error in wire as it comes into the loop.  Wire all your error outs from the event cases and from the last Sorrensen function to a Merge Error function.  Wire that error out to the shift register.  All of your errors come together in just one indicator.

 

That should do it for now.

 

- tbob

Inventor of the WORM Global
Message 9 of 20
(3,859 Views)

Thank you, I can see why you are a trusted enthusiast! I will try these and post my success/failure

0 Kudos
Message 10 of 20
(3,852 Views)