08-20-2015 03:43 PM - edited 08-20-2015 03:44 PM
Hi all,
So I've been writing a Labview program to control two machines. Very simply, one is a voltage source, and the other is a Lock-In Amplifier. What I want to do is change the applied voltage, wait a few seconds for the LIA's response to settle down, then take some number of measurements from the LIA, then average those and save them to file.
Here's a flowchart of what I mean:
I've actually got it mostly, but I'm having a little trouble with the delay. The actual VI file is massive, so I tried to make a simplified one that shows the basics of what I'm doing:
(The string constants and array constant aren't actually what I use, it's just to illustrate, because I don't know how to make a quick easy placeholder for diagrams...is there an easy way?)
So, my assumption here (and it seems like it's what's happening) is that, for each iteration of the larger outside loop, the first thing it does is start the timer and start the change applied voltage/etc CONCURRENTLY, right?
And then, it only goes into the LIA measurement loop once it has completed both of those tasks, right? (Please correct me if I'm wrong!)
So how would I go about making a delay after the LIA measurement loop? If what I said so far is correct, then if I put a "wait" in the main loop, I don't think that would work (or at least not be very precise) because it would start as soon as the iteration started, so would be counting while the LIA was measuring, and thus not wait the right amount of time after the LIA loop was finished (if I even set it to be long enough so that it was still going after that loop was finished).
Am I correct in what I said?
what's the smart way of doing this?
thanks!
Solved! Go to Solution.
08-20-2015 03:46 PM
The smart way? Glad you asked... State Machine. http://www.ni.com/tutorial/7595/en/
08-20-2015 03:48 PM - edited 08-20-2015 03:48 PM
You are correct about the data flow order, which is usually the downfall of most starting LabVIEW developers.
To add a wait after the inside loop, put down a Wait node inside of some structure (the easiest being a Flat Sequence structure) and add some sort of data flow from the output of that loop to the Wait's structure. This will force that structure to not operate until the loop finishes.
That being said, there is a better way to do all of this. Look in to the Simple State Machine architecture template that ships with LabVIEW 2012 and newer.
Edit: NIquist beat me to it.
Cheers
--------, Unofficial Forum Rules and Guidelines ,--------
'--- >The shortest distance between two nodes is a straight wire> ---'
08-20-2015 03:51 PM - edited 08-20-2015 03:52 PM
@NIquist wrote:
The smart way? Glad you asked... State Machine. http://www.ni.com/tutorial/7595/en/
Thanks, I'll have to look into this for the future.
08-20-2015 03:54 PM
@James.M wrote:
You are correct about the data flow order, which is usually the downfall of most starting LabVIEW developers.
To add a wait after the inside loop, put down a Wait node inside of some structure (the easiest being a Flat Sequence structure) and add some sort of data flow from the output of that loop to the Wait's structure. This will force that structure to not operate until the loop finishes.
That being said, there is a better way to do all of this. Look in to the Simple State Machine architecture template that ships with LabVIEW 2012 and newer.
Edit: NIquist beat me to it.
It's interesting but certainly a little counterintuitive at first, because basically all the coding I've done before this has been stuff that happens in parallel, even if it goes deep into many other functions.
I'll probably use your structure method at the moment to get it working, and learn about state machine stuff once I have that.
Thank you both!
08-20-2015 03:58 PM
Do you know about State Machines? Your diagram shows several States -- Change Voltage, Wait 10 seconds, Acquire Data (repeated as needed), Process (average) Data, Save Data, Wait a Few Seconds, and go back to Change Voltage. The simple implementation of this is a While Loop with a Shift Register to hold the State, a Case Structure inside to "do" the State, and a decision mechanism at the end of each State to decide what State to do next. In particular, most States simply wire the Next State to the State Shift Register on exit except for Acquire Data, which wires Acquire Data (again) unless it's time to stop, in which case it wires Process Data.
Because you are effectively "stacking" each State in the same While loop with the Case Statement, all the States can share data by the simple expedient of putting the data on a Shift Register. Thus before Acquire Data, you'd wire an empty array to Data. Each pass through Acquire Data, you'd add a point to the array. During Process Data, you'd have the entire array available to process. And so on.
This is the simplest form of the State Machine, and may be enough for your situation. There are multiple variations in the implementation, but they all have the idea of a loop where you choose, when entering the loop, what you want to do at this moment. Generally, States are designed to be done quickly and not "block" (or stop the State Machine from running) -- the two exceptions here are Acquire, which runs at the speed of Acquisition (i.e. if you are sampling at 10 Hz, it takes 100 msec to get a point) and the Wait state (which is designed to block). There are also ways to avoid "wait blocks", but this is the simplest conceptual way to think about your task.
Bob Schor
08-20-2015 04:04 PM
@Bob_Schor wrote:
Do you know about State Machines? Your diagram shows several States -- Change Voltage, Wait 10 seconds, Acquire Data (repeated as needed), Process (average) Data, Save Data, Wait a Few Seconds, and go back to Change Voltage. The simple implementation of this is a While Loop with a Shift Register to hold the State, a Case Structure inside to "do" the State, and a decision mechanism at the end of each State to decide what State to do next. In particular, most States simply wire the Next State to the State Shift Register on exit except for Acquire Data, which wires Acquire Data (again) unless it's time to stop, in which case it wires Process Data.
Because you are effectively "stacking" each State in the same While loop with the Case Statement, all the States can share data by the simple expedient of putting the data on a Shift Register. Thus before Acquire Data, you'd wire an empty array to Data. Each pass through Acquire Data, you'd add a point to the array. During Process Data, you'd have the entire array available to process. And so on.
This is the simplest form of the State Machine, and may be enough for your situation. There are multiple variations in the implementation, but they all have the idea of a loop where you choose, when entering the loop, what you want to do at this moment. Generally, States are designed to be done quickly and not "block" (or stop the State Machine from running) -- the two exceptions here are Acquire, which runs at the speed of Acquisition (i.e. if you are sampling at 10 Hz, it takes 100 msec to get a point) and the Wait state (which is designed to block). There are also ways to avoid "wait blocks", but this is the simplest conceptual way to think about your task.
Bob Schor
Thanks for the response, I actually took a class in finite state automata ages ago and loved it so I know the basics of it. It's really more that I need to get an experiment up and running quickly, and I'll definitely save time in the long run by learning how to do it in LV but it would probably take several hours of futzing around with it for me to implement it successfully here. I'll definitely learn about it when I can though. Thank you!
08-20-2015 04:17 PM
Don't forget that there are pre-made templates for state machine and several other useful architectures (Mater/Slave, Producer/Consumer) built it to LabVIEW. Start there when you're ready to "futz"...
08-20-2015 04:53 PM
Use the Pt By Pt Std Deviation VI rather than waiting. If the std dev of a certain amount of pts is less than 0.1, for example, then the signal can be considered settled. That way you don't wait unnecessarily long (or short).