VI High 43 - Learn How to Make and Implement a LabVIEW Functional Global Variable
In our last episode we saw how race conditions occur and how data encapsulation and hiding can fix that problem, specifically through using functional global variables. In this episode we actually make those variables and integrate them into our robot arm code.
You can also keep up with us at:
http://facebook.com/sixclear
http://twitter.com/#!/sixclear
In our last episode of VI High, we talked about Functional Global Variables and how they are a form of information hiding and data encapsulation. We showed how this VI, which moves a robot arm through global variables, is prone to race conditions and can be corrected by replacing this critical section of code with a Functional Global Variable. Like this. And I promised this time I’d actually do it. So let’s do it.
This VI resides in a project, ‘Robot Project - Global’, and we see that we have the global variable here. So to fix it, I’m going to make a copy of this project. File, Save As, Duplicate this project. And I’ll call it ‘Robot Project - Fixed’. And I’ll open this up and close the old project. This position global is still a dependency, but we’ll see that we’ll remove that. Let’s get rid of it on the block diagram so that it’s no longer a dependency, and there we go. No longer a dependency.
Now, I’ll open up a new VI. Save it as ‘New FGV’ for Functional Global Variable. On the front panel, I’ll put down an Enum, which I’ll call ‘Command’, and in here will be all the commands for this Functional Global Variable. Init, Process 1, Process 2, Read. And then an indicator on the front panel telling me the position. I’ll change it to an I-32.
And now to control data flow, on the calling VI, I’ll put down some error clusters. Error In, Error Out. Going to the block diagram, let’s get these out of the way for now, I’ll put down the infrastructure of a Functional Global Variable, which is a While Loop surrounding a Case Structure with my command Enum going to the Case Selector Terminal.
And then right click on the border of the While Loop, add a Shift Register. Into my Conditional Terminal, I’ll create a constant, which is True because we only want this While Loop to execute one time. I’ll first flip over to the Initialize, and the Initialize we’ll put in the initial position. So I’ll need that in the front panel. I’ll just copy the position since it’s already the right data type. Right click on it, change to control, and call it ‘Initial Position’. And align these all nicely to the left. Very nice.
And I’ll wire this into a Shift Register because I want that initial value being placed in the Shift Register. In Process 1, I want to take that value out and add a ‘10’ to it. And also write it out to the position. Now, the position can be inside or outside the While Loop. It doesn’t matter since it’s only running one time, but I’ll put it in here so we have fewer tunnels.
Process 2 is essentially going to be exactly the same, so I’ll just click on the Case Structure, Duplicate Case, and there we go. Change this to ‘5’, good. And then we’ll right click and add a case after to Read and at this point, we just wire this to the position out, and then also wire it to the hollow tunnel. We have one more case to fill in the value for, the position right here, and that will be whatever the initial position is.
So that’s the guts of a Functional Global Variable. Again, While Loop, with a Shift Register uninitialized, nothing going into it, in other words, so that it retains values between runs of the VI, a Case Structure inside with the command Enum going to the Selector Terminal, and a True constant going to the While Loop Conditional Terminal so that it only runs one time. For good data flow, I’ll now wrap this whole thing in a Case Structure, and my Error In Terminal will go here. Error Out over here. Hold down CTRL and use my mouse wheel to flip to the next case. There we go. That’s all done.
I’ll save it, head to the front panel, and assign the connector pane. We always like to keep the error clusters in the lower left and right, and then to edit the icon, I’ll just double click on it. I’ll select the whole thing, delete, put down a new border, go to the icon text, put down FGV, I don’t want to center it vertically, and then a nice glyph. Maybe something about a variable. Ok this looks good. Grab it and pull it on. That looks nice. Save.
Now that my Functional Global Variable is finished, I need to get it on the block diagram of the calling VI, so I’ll just go to the icon, click and drag it onto here. Very easy. And now we just call it in the appropriate place. I’ll put one instance over here, and in the command, I’ll right click and create a constant, initialize. That’s good. And the initial position will be wired into the initial position input here. So probably actually better put it up top. That’s smarter. Good. And since we want this to run before both of these, we were previously using this wire to control data flow. But now that we have this error cluster, we’ll use that instead.
We’ll need an instance over here in Process 1, so hold down CTRL, click and drag, and bring it over here. I’ll get rid of this ‘+’ since it’s already in there. And in fact so is the ‘10’.
Call Process 1. Good. Down below, same thing. Actually, I will need to keep that ‘5’. Clean that up. And create a ‘10’ again here. Just so we can do our validation at the end. Make a copy of this. Call this Process 2. Good. And then at the end we’re going to want to call this again over here, Read. And what comes out will be the final position. Again, we won’t need this piece of data flow because we’ll just use the error clusters again. Since I have two errors coming in, I’ll need the Merge Errors function. Right here.
Wire in my errors. This could be prettied up a bit, but you get the idea. Hmm, I wish I could get the idea, but my OCD won’t let me. That’s nicer. Ok. It’s time to test it out. Back to the front panel, and we run it. They match, that’s good, they match again. And just like before, I’m going to go grab some dinner while this runs for a while.
I’m back. I ate a lot of dinner, especially since I recorded these back to back. But let’s stop them, and just as we suspected, they’re exactly equal, no matter how large the number.
Well, that’s it for our Functional Global Variable implementation of information hiding and data encapsulation. As I mentioned in the last episode, there are other ways of doing this. Ask your nearest certified LabVIEW developer or architect, and they’ll have at least a dozen opinions. But if you’re just interested in the fundamentals, we have a whole course for that: Sixclear Lucid LabVIEW Fundamentals training. Check it out at sixclear.com/try. That’s T-R-Y.