LabVIEW

cancel
Showing results for 
Search instead for 
Did you mean: 

Single Action Events in Continuous Loop

Solved!
Go to solution

Hello all,

 

I am looking for some guidance on ways to execute single time actions inside a continuous while loop.

 

I have a large program to control a heating system. It is written using LabVIEW 2022 Q3 on a Windows 10 machine. An NI cDAQ-9174 is used for I/O, it has 9485 and 9210 modules for temperature reading and relay control. As part of that program, I want to store timepoints when certain events occur for later programmatic manipulation. Where I am running into problems is that I only want to store the first time those events occur.

 

I have attached a set of VIs that I think get at the problem I am having. "CalculateFromCompare" has a main while loop, with every iteration it is reading thermocouple data. Also inside the while loop is a case structure that is tied to "Execute". When the value of "Execute" changes, the current timestamp is taken and a set of comparisons between the current data and the baseline data is taken. "Compare5Percent" checks if the current value is 5% greater than the baseline value. The same for "Compare20Percent" but 20% greater. The problem with the way it is implemented now is that the comparison resets/ the timestamp overwrites with every loop cycle.

 

I can see potential solutions, but they all involve lots of shift registers and nested boolean conditions. Maybe those are the only ways. But I'm interested in hearing if there are other ways to have a section of code in a continuous loop stop executing after a condition is met the first time?

 

Thank you,

Thayer

 

 

0 Kudos
Message 1 of 17
(1,874 Views)
Solution
Accepted by topic author thayermcc

Sorry I can not see you program because I am running 2019 right now.  Can you either save it as an earlier version or show some screen snaps.

 

If it was me inside the main do while loop would be a state machine so that you can control program flow.   

 

For example, my general slow data acquisition software has a FileWriteInterval l variable.  In the wait state it compares the current time to the LastFileWriteTime (Local variable read) plus FileWriteInterval.  When that is true the next state is the WriteData state.  In the write data state the last thing that it does before it exits is updates the LastFileWriteTime variable.

 

One can also pass some of this stuff around using a cluster and a shift register rather than use local variables.

0 Kudos
Message 2 of 17
(1,859 Views)

Here are a couple of screenshots of the VIs. The first is the VI that shows the timing problem I am running into. The second is one of the comparison VIs.

Timing.PNGComparison.PNG

0 Kudos
Message 3 of 17
(1,830 Views)

You said you want to store timepoints when "certain" events occur. Can you be more specific? What events exactly are you referring to?

Also you said, when the value of "execute" changes, the current timestamp is taken. Now my question, are you expecting execute to change automatically or you have to change it manually?

 

So if the current is 5% greater or 20% greater than the baseline, we want to record timestamp. Is that right?

 

It would be nice to have a sequence of operations. For example: step 1: Read data > step 2: Compare read data to threshold > step 3: save data to file, etc...

 

If you come up at least with a sequence of operations, I'll get the job super quick for you.

 

Also you need to correct "compare5percent" subVI. I think it should be 0.05 which corresponds to 5%

GRCK5000_0-1689218081198.png

 

 

 

 

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Philippians 4:13 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 

0 Kudos
Message 4 of 17
(1,798 Views)

Since you are spinning the loop anyway, an event structure is pointless. What's the mechanical action of the switch (e.g. latch or switch action?)

 

IF switch action, just use the boolean crossing to trigger zeroing of the time.

Since you are only interested in relative time, I would recommend to use the high resolution relative seconds instead.

Wouldn't it be more reasonable to only have a single subVI that has a percentage input?

 

As has been requested already, please do a "save for previous" and reattach your VIs. I only have LabVIEW 2020 here at the moment.

0 Kudos
Message 5 of 17
(1,782 Views)

Let me ask you a thought question.  Which occurs first grab the data and do the comparison or set the time for the shift register on the right.  The short answer is you do not know because they are not programmatically linked using a wire.  Further the order of operation can change the next time you assemble the program. There are multiple ways to address this I think for what you want you should blow away the execute event structure and move the get time in seconds into the true state of the T/F and wiring the last value of the sift  to the output on the false part. 

 

What is the value that goes to the output for comparison in the false state.  Unless it is a local variable of "output of comparison" the variable of output of comparison will just flash the correct value then reset to what ever is in the false state.  To that end move "output of comparison" into the T/F.

 

I unless there is some reason that this program has to run as fast as it possibly can I would put a stall data flow for 10 ms in the middle of the clock value coming out of the T/F so that you know for sure that the next time you get to the T/F you get a time that is bigger than the last time.

 

I don't use event structures enough to know this for sure but I thought that the variable that you were triggering the event on had to be inside the state that it was being triggered by.  Further it is not clear to me what would happen if your execute variable was a momentary contact switch that was read and cleared before the event structure executed, which gets back to the not knowing what is going on with the order of execution. 

0 Kudos
Message 6 of 17
(1,761 Views)

My apologies for the poor initial explanation, thank you for your replies in spite of that. Here's an attempt at a better explanation.

 

As I mentioned the VI is running a heater system. As part of that, information about the physical nature of the system needs to be obtained occasionally. My plan was to have a test that would turn the heater on and observe information about the response. The code I've included assumes that an increasing temperature is being recorded. As such, in order I want the following things to happen:

 

1) The test is initiated

2) Timestamp is recorded

3) Temperature begins to rise

4) Temperature reaches +5% of the initial value

5) Time to reach +5% is calculated

6) Temperature reaches +20% of initial value

7) Time to reach +20% is calculated

😎 Those times are recorded and can be used in later calculations

 

I've attached code that accomplishes this (and in a previous version too!) I just feel like there is probably a simpler solution to this problem. But maybe there isn't.

0 Kudos
Message 7 of 17
(1,739 Views)

This attached VI is what I came up with, but yours is probably better. Check it out and let us know. 

 

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Mark 1:15 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

0 Kudos
Message 8 of 17
(1,716 Views)

Sorry but the logic in your programming is way inconsistent with the program outline that you just provided.  What your program does is on execute check to see if the value is 5% above the initial value and if it is 20% above the initial value.  If neither is met then it outputs the start time (maybe).

 

Here is what I think you want to do.  It would be really cool to do it in a state machine but one could also do it using successive DoWhile loops.

 

I will describe it in the DoWhile loops.

 

Go in like you are doing on the init and start acq. Also set the abort button to false. Grab a value and call that your BaselineValue wire that into your first DoWhile Loop. Do all of this in a single flat sequence box so that you know that it happens first.

 

Wire the baseline value and the ACQ task to the input of loop 1.

Inside loop1

Analog DBL read the value, read current time.

Check to see if the value exceeds the BaseLine x 1.05

If (yes or abort*) is clicked exit loop passing out the time for the baseline x 1.05 and the ACQ task.

 

Wire the ACQ task** out of loop 1 and the initial value into Loop 2

Inside Loop2

Analog dbl read the value and current time.

Check to see if the value exceeds baseline x 1.20

If (Yes or Abort) is clicked exit loop passing out the time for the baseline and 1.20.

 

Either show or subtract or what ever the time differences out of each loop and the baseline and display them.

 

*Abort is necessary so that you can exit the loops if things don't work.

**You have to wire something out of the first loop into the second loop to insure program order.

 

I would also display the current value of the ACQ in each loop so  that you can watch what is going on.

 

0 Kudos
Message 9 of 17
(1,702 Views)

I don't see how the program is highly inconsistent with my outline. It is entirely possible that I have missed something, but I think I might know where our disconnect is. If I am wrong, please correct me.

 

I agree with what you said about what my program does, under the assumption that the code tied to "execute" only triggers once. However, the mechanical action of the boolean is such that the code inside the case structure runs with every loop iteration until the boolean is manually turned off. So at every iteration the value is checked to see if it is both 5% and 20% the initial value. If it is, a timestamp is recorded and boolean that says that the timestamp was recorded is changed. This timestamp recorded boolean then inputs into the next loop iteration to prevent the timestamp from being overwritten.

 

I did notice that there was a problem with this overwrite check process initially, that would have caused it to flip between preventing and allowing an overwrite with consecutive iterations, but I have fixed this.

 

I appreciate your suggestion and agree that it is more effective at ensuring a linear process. The problem is that per my original post, all this code is running inside a larger program with a single overarching while loop. Consecutive loops won't work with my other code and so to implement your suggestion I would have to use nested while loops, which from my understanding would be worse.

 

Like I said, if I am missing something that is causing this code to be drastically different than what I explained, please point out to me where that disconnect is.

 

Thanks!

0 Kudos
Message 10 of 17
(1,682 Views)