LabVIEW

cancel
Showing results for 
Search instead for 
Did you mean: 

Interrupting code within an event structure

Solved!
Go to solution

Hello all,

 

I am writing a program where I am using an event-driven state machine to handle a user interface for an external instrument, sending commands via serial corresponding to button presses.

 

Some processes that the instrument undertakes are quite long, and I want to be able to read back from the instrument when they finish. Reading back requires sending another command after the correct amount of time. Originally I implemented this as:

 

Write the "process" command > Wait x milliseconds whilst the process occurs > Write the "read values" command > Read the output

 

Where the sequence is triggered by a button press event.

 

The issue I am having is that for safety reasons the program also needs to be able to interrupt the process with another button press which will overwrite the original command, but because of the wait time the front panel is completely unresponsive until it finishes and reads back. I can't simply exit the loop or the VI because the instrument itself will continue with what it was doing unless specifically told to stop.

 

I have tried running another event structure in parallel (which I know is generally advised against) to no avail. I have also tried having a case strucutre within each event structure, connected to a boolean outside the event structure to control them all - this gives a broken wire from the boolean (?) which I don't understand.

 

Could I wrap the entire event machine in a case structure and have the "emergency stop" button press as the true case, having only the "stop" command inside, with the false case having the event-driven state machine inside? Would a change in the button interrupt the event case during execution, or would the front panel remain frozen? i.e., would a change in the case structure execute even if the code inside the event case was still continuing? Edit: I tried this, and it also does not work.

 

Any help would be greatly appreciated! Many thanks!

Samuel Allen
University of St Andrews
0 Kudos
Message 1 of 15
(565 Views)

Would be easier to advise if some code, but...

 

You have an event driven state machine, TAKE Advantage of it!!

Make the following states:

  1. Process/Write Command
  2. Set Timeout of Event Structure to XXX ms
  3. Read Command
  4. Set Timeout of Event Structure to -1 ms

Any event that occurs before the timeout is complete will allow you to stop/change the process.

 

EDIT: Your states should not be in the Event Structure, look at the JKI State Machine for an example. Download it from VIPM

 

mcduff_0-1721319447872.png

mcduff_1-1721319476851.png

 

 

Message 2 of 15
(547 Views)

@smallen wrote:

Hello all,

 

I am writing a program where I am using an event-driven state machine to handle a user interface for an external instrument, sending commands via serial corresponding to button presses.

 

Some processes that the instrument undertakes are quite long, and I want to be able to read back from the instrument when they finish. Reading back requires sending another command after the correct amount of time. Originally I implemented this as:

 

Write the "process" command > Wait x milliseconds whilst the process occurs > Write the "read values" command > Read the output

 

Where the sequence is triggered by a button press event.

 

The issue I am having is that for safety reasons the program also needs to be able to interrupt the process with another button press which will overwrite the original command, but because of the wait time the front panel is completely unresponsive until it finishes and reads back. I can't simply exit the loop or the VI because the instrument itself will continue with what it was doing unless specifically told to stop.

 

I have tried running another event structure in parallel (which I know is generally advised against) to no avail. I have also tried having a case strucutre within each event structure, connected to a boolean outside the event structure to control them all - this gives a broken wire from the boolean (?) which I don't understand.

 

Could I wrap the entire event machine in a case structure and have the "emergency stop" button press as the true case, having only the "stop" command inside, with the false case having the event-driven state machine inside? Would a change in the button interrupt the event case during execution, or would the front panel remain frozen? i.e., would a change in the case structure execute even if the code inside the event case was still continuing? Edit: I tried this, and it also does not work.

 

Any help would be greatly appreciated! Many thanks!


If this is indeed a safety issue, I would rely on a physical e-stop button to physically shut the test station down!

Bill
CLD
(Mid-Level minion.)
My support system ensures that I don't look totally incompetent.
Proud to say that I've progressed beyond knowing just enough to be dangerous. I now know enough to know that I have no clue about anything at all.
Humble author of the CLAD Nugget.
0 Kudos
Message 3 of 15
(536 Views)

Once an event case starts, it has to either finish or the entire VI hierarchy has to stop because its execution was interrupted (which is not recommended...).  There's no way to just do a hard stop on one small bit of a VI. 

 

As some of the other posters here like to say, "THINK DATAFLOW!".  Execution order is entirely dependent on the rules of dataflow, which do not allow for hard stops of any kind without completing every single step remaining.

 

This isn't to say your task is impossible, it just means you need to write code inside the event structure that is more interruptible.

 

For instance, instead of this:

Kyle97330_1-1721319588072.png

Replace it with this:

Kyle97330_2-1721319785679.png  +  Kyle97330_3-1721319807206.png  +  Kyle97330_4-1721319834621.png

 

Using something like that still obeys the rules of dataflow but allows for an interrupt between each VI because of the way the loop is designed.

 

Similarly, with anything built-in that uses a timeout, you can manage it by lowering the timeout and managing it yourself:

Kyle97330_7-1721320385910.png

 

Message 4 of 15
(535 Views)

@smallen wrote:

Hello all,

 

I am writing a program where I am using an event-driven state machine to handle a user interface for an external instrument, sending commands via serial corresponding to button presses.

 

Some processes that the instrument undertakes are quite long, and I want to be able to read back from the instrument when they finish. Reading back requires sending another command after the correct amount of time. Originally I implemented this as:

 

Write the "process" command > Wait x milliseconds whilst the process occurs > Write the "read values" command > Read the output

 

Where the sequence is triggered by a button press event.

 

The issue I am having is that for safety reasons the program also needs to be able to interrupt the process with another button press which will overwrite the original command, but because of the wait time the front panel is completely unresponsive until it finishes and reads back. I can't simply exit the loop or the VI because the instrument itself will continue with what it was doing unless specifically told to stop.

 

I have tried running another event structure in parallel (which I know is generally advised against) to no avail. I have also tried having a case strucutre within each event structure, connected to a boolean outside the event structure to control them all - this gives a broken wire from the boolean (?) which I don't understand.

 

Could I wrap the entire event machine in a case structure and have the "emergency stop" button press as the true case, having only the "stop" command inside, with the false case having the event-driven state machine inside? Would a change in the button interrupt the event case during execution, or would the front panel remain frozen? i.e., would a change in the case structure execute even if the code inside the event case was still continuing? Edit: I tried this, and it also does not work.

 

Any help would be greatly appreciated! Many thanks!


You know what? I once posted a response about revising a State Machine to help interrupt "Long Processes. "  I suggested A trip to Grandma's House as a better method of structuring States.


"Should be" isn't "Is" -Jay
Message 5 of 15
(508 Views)

Hi Bill,

 

We do have a physical interrupt button, don't worry! The cutoff in LabVIEW is just an extra feature that has been requested by members of the lab.

 

Sam

Samuel Allen
University of St Andrews
Message 6 of 15
(460 Views)

Hi there,

 

Just to check I am understanding you correctly - you mean send the command, set the timeout of the event structure to the calculated time the command takes to execute, have the read in the timeout case, then set the timeout back to -1?

 

This seems like it would work if I had only one read command and one command to send, but I have many such different commands and as far as I am aware I can only have one timeout case!

 

i.e., I need to be able to send "change x", wait, "read x", "change y, wait, "read y", etc where the wait times for x, y are different!

 

Forgive me, but I don't really understand how you have shown that being implemented in the pictures you provided. What is selecting between the two cases in the case structure?

 

Thank you,

 

Sam

Samuel Allen
University of St Andrews
0 Kudos
Message 7 of 15
(457 Views)

Hi there,

 

Am I right in thinking that the case structures are being selected for by the processes/subVIs 1 and 2 completing? So the case is being determined by the iteration of the loop?

 

Also, will this not still freeze up the VI if the "2" box is just a wait? I think your suggestion will allow me to interrupt the write and read which are over serial and practically instantaneous compared to the exection time of the process on the instrument (which is variable depending on the command and could be any value from 20 ms to several minutes)

 

Thank you for your help, but I think if the wait is "2" in your example, I am looking for how I can interrupt "2" itself rather than between the three processes.

 

Please correct me if I am misunderstanding you!

 

Thanks,

 

Sam

Samuel Allen
University of St Andrews
0 Kudos
Message 8 of 15
(453 Views)

Hi there,

 

Reading your analogy I think I understand better, but I am still unsure how I would implement this.

 

I had a thought reading your post however. The instrument in question has been built in-house, and is based on an arduino microcontroller. Would a better way to handle the wait to be to program the arduino to send the data itself when it is finished (very easy to do, just adding a serial.print() at the end of the function) rather than requesting it by writing a command?

 

I could then just have a timeout state where I just repeatedly read until I get the data back. This way the VI could still respond to new events but would also automatically read the values back when the process ends?

 

i.e., button press triggers event case > case writes the command > VI returns to timeout > timeout reads for output constantly (so will catch the values when the command has finished executing on the instrument)

 

Does that make sense or is that more complicated than the other suggestions that have been made?

 

Thanks,

 

Sam

Samuel Allen
University of St Andrews
0 Kudos
Message 9 of 15
(448 Views)

@smallen wrote:

Hi there,

 

Just to check I am understanding you correctly - you mean send the command, set the timeout of the event structure to the calculated time the command takes to execute, have the read in the timeout case, then set the timeout back to -1?

 

This seems like it would work if I had only one read command and one command to send, but I have many such different commands and as far as I am aware I can only have one timeout case!


You need multiple states:

  1. State 1 - Write Command
  2. State 2 - Set Timeout
  3. State 3 - Read Command

The states would proceed like so, Write -> Set Timeout -> Timeout State -> Read State.

 

The Read does not occur in the timeout state, it is its own separate state.

 

If you need to interrupt a current state because a button is pressed, you will need to implement a parallel loop. One loop to monitor, one loop to process. You will have to send a message (queue, channel, user event) to the state that you want to stop.

 

How are you monitoring the "Stop Button"? If it is a hardware switch and you have a DIO module, a DAQmx change detection event could work. That could be embedded in the loop.

Message 10 of 15
(417 Views)