Objectives: After completing this lab session you should: .... In most instances, simply acquiring the data is only half the battle; saving the data so that it can.
ME 411
Winter 2010
Lab Assignment 2: SubVIs, Writing Files, Acquiring Data Objectives: After completing this lab session you should:
Know how to create and implement your own subVIs. Be able to save data using LabVIEW. Understand the basics of configuring and using a DAQ.
This week you will create a series of VIs that build upon each other until you have a top level program with which you read data, display it in real‐time and save it to a file for later use. Example 1: Column Header One thing that makes automated data acquisition so powerful is the ability to monitor many different variables simultaneously, something that is extremely difficult to do by hand. That ability is only useful if it is properly implemented, and labeling groups of data is a big factor in having useful data.
Figure 1. Front panel for first version of Column Header.
1.
Open a blank VI and place a For Structure on the Block Diagram. Create a Numeric Control named Number of Channels and connect it to the count terminal (the blue N in the upper left corner). The For Structure will loop however many times it is instructed to. Inside the structure, place a string constant with the value “Channel .” If you don’t leave a space in the constant then there will be no separation between the word “Channel” and the following number. Place a Number to Decimal String and a Concatenate inside the For Loop, wiring the iteration counter (the small blue i) into the Number to Decimal String converter and sending the subsequent output to the Concatenate.
1
ME 411
Winter 2010
Figure 2. Block diagram for first version of Column Header.
2.
Now create a String Array Indicator to display the output. To do this you will first have to place an Array Indicator from the Array, Matrix & Cluster menu of the Controls Palette and then place a String Indicator inside the empty Array Indicator. Change the label to “Column Headers”. Once you have everything wired together as shown in Figure 2, the VI should be ready to run. If you see a broken wire between the output from the For Loop and Column Header, this is most likely because Auto‐Indexing was disabled. Right click on the tunnel (the small box connecting the wire from Concatenate to the wire going to Column Header) and select Enable Indexing if that option appears. If your VI will still not run, try List Errors (the broken Run button) to discover the problem. Run the VI with a Number of Channels value greater than one. If you did not alter your Column Headers Indicator then you will only see the first output, “Channel 0.” In order to see more of the array, you will have to stretch the indicator, either vertically or horizontally. This can be tricky because you can select either the Array portion of the Indicator or the single String Indicator within the array itself. If you stretch the Array portion you will get more cells of the Array, but if you stretch an individual String Indicator within the array, you will only make that particular field bigger. This can take some trial and error and, ironically, once you have more than one cell in the indicator it gets easier to stretch exactly the item you want.
3.
4.
This VI creates an array of strings that can be used as column headers for acquired data that you wish to save.
2
ME 411
Winter 2010
The following steps change the VI in order to allow the individual numbering of the different channels.
Figure 3. Front panel for second version of Column Header.
Figure 4. Block Diagram for second version of Column Header.
5.
Inside the For Loop, place a Case Structure as shown in Figure 4. For the True case, insert two functions, Index Array and Number to Decimal String. Create an array control named Channel Names (either by placing an array control and then, inside of it, a numeric control on the Front Panel or by right clicking on the wiring node on Index Array and selecting Create → Control). Wire them together as shown. For the False case, place a Number to Decimal String converter, wiring it so that its input comes from the iteration counter and its output goes to the data tunnel. 3
ME 411 6.
Winter 2010
On the Front Panel, place a Boolean control. You can use any kind of switch or button you choose, but be aware of their default mechanical actions and the issue of seeing their Boolean Text. To enable the Boolean Text, right click on the item and select Visible Items → Boolean Text. After it’s enabled, you can change the text itself to something more appropriate to that button’s actual use. In Figure 3 you can see a Slide Switch was used; its mechanical action is automatically “switch when pressed” and its coloration and layout make it easy to see the Boolean Text. Change the name of the control to “Name Channels?” and wire its output to the case selector. At this point your VI should be ready to run. If you select the option to name the channels, the channel numbers you enter into the control array will be given as numbers for the channels in the order they appear in the array. Consequently, if you enter no numbers into the Channel Names array after selecting the option to name them, then they will all have the name “Channel 0.” Again, this VI is perfectly functional and should work fine. However, for a couple minutes extra work you can have the option of a column header for time data.
Figure 5. Front panel for final version of Column Header.
4
ME 411
Winter 2010
Figure 6. Block diagram for final version of Column Header.
7.
Add another Case Structure, this time outside of the For Loop. Place a string constant and one Insert Into Array (from the Array menu) into the True case. Give the string constant a value of “Time” and wire it as shown above noting that there is an unwired node between the two string inputs for Insert Into Array. For the False case simply wire the input from the incoming data tunnel right across to the outgoing data tunnel.
8.
On the Front Panel, add another button or switch and change its name to Include Time? For ease of use, it’s probably a good idea to make the Boolean text visible. Wire the output from this control into the case selector for the new case structure. Now your VI will create any number of column headers you desire, naming them automatically or assigning them names you provide and optionally appending a header for the time column. This is all well and good, but it is not very useful on its own. In order to make the best use of this VI, you will enable it to receive inputs and generate an output.
Figure 7. Menu bar showing icon for the current VI on the right hand side.
9.
In the upper right corner of the Front Panel screen, you can see the VI’s icon. It is located inside the red circle in Figure 7. Right click on it and select Show connector. Now you should see something that looks similar to Figure 8, with the difference being that your connectors have not been assigned to anything yet. 5
ME 411
Winter 2010
Figure 8. Menu bar showing connector for the current VI on the right hand side.
10.
To assign the connectors to the inputs and outputs of your VI, simply click on one of the boxes in the connector display (this will change your cursor to the wire spool) and then click on whichever input or output you would like that connector to be. What you are doing is creating wiring nodes for this VI so that you can place it inside of another VI, thus making it a subVI, saving yourself a great deal of space and a lot of time. You should assign Number of Channels, Name Channels?, Channel Names, Include Time? and Column Headers to connectors. Also, in keeping with the general scheme of data flowing from left to right in LabVIEW, it’s probably a good idea to keep inputs on the left and outputs on the left, which is how most of the built‐in subVIs and functions already work.
Once you have the connectors assigned how you would like them, save the VI as Column Header in a location you will remember, close it and open a new blank VI. Example 2: Spreadsheet File Starter In most instances, simply acquiring the data is only half the battle; saving the data so that it can be retrieved when necessary is no less important. This VI opens an existing file or creates a new one by combining a given base name with the date and time. Once the file is created the VI writes the file name, the date and time, optional text and column headers (using the VI you just created) to the beginning. The resulting file is then passed along as an output. 1.
The first item you will place on the Block Diagram will be the Column Header VI. On the Functions Palette choose Select VI… (if it is not visible you may have to expand the Functions palettle), select Column Header (you may have to navigate your file structure in order to find it, so hopefully you remember where it is saved) and place it on the Block Diagram. You can quickly get all the controls for this subVI by right clicking on the wiring nodes and selecting Create → Control. You may have to do some rearranging on your Front Panel, but notice that the names do not need to be altered.
6
ME 411 2.
Winter 2010
On the Front Panel, place a Path control and two String controls, all of which can be found in the String & Path menu. Change the name of one String Control to Base File Name and the other to Header Text.
Figure 9. Front panel for Spreadsheet File Starter.
3.
The Block Diagram will need two Concatenate functions, an Array to Spreadsheet String function and a Carriage Return constant from the String menu. From the Timing menu, place a Format Date/Time String function. From the File I/O menu, place a Build Path, Open/Create/Replace File and a Write to Text File function.
4.
The first Concatenate should collect together, in this order, the Base File Name, the output from Format Date/Time String and a string constant with a value of “.txt” which you will have to create. To format the date/time string, create another constant and give it a value of “%Y‐%m‐%d %H‐%M” which will make the string have an output of Year‐Month‐Day 7
ME 411
Winter 2010
Hour‐Minute. The output from the first concatenate should go to the bottom input on Build Path. The top input for Build Path should come from the Path control. This creates a file name and path that contains the Base File Name, the date and time and the file extension txt so that it will automatically be a text file. If you do not want your files to automatically be in the txt format you can change that. Also, if you are not comfortable with the Year‐Month‐Day format for the date, you can change that as well, although the Year‐Month‐Day format is in many ways easier to sort.
Figure 10. Block diagram for Spreadsheet File Starter.
The output from Build Path should be wired into the Open/Create/Replace File function. Directly under the wiring node for the File Path there are two more wiring nodes named operation and access. They both have default values that work in many instances, but for this exercise you are going to change them. Create a constant for both of them by right clicking on them and change their values, operation should be open/create and access
5.
8
ME 411
Winter 2010
should be read/write. This function can now create a file using the name and path given to it, or, should that file already exist, it will open that file. 6.
The output from Column Header should go to the Array to Spreadsheet String function. Additionally, you will need a format string for this function. In the example you can see the “%e” was used, which puts any numbers that appear into engineering format. That isn’t particularly relevant for this exercise, but it is something to keep in mind. Also, as a separator for the columns, this example uses the default for the function, which is a tab. That can be changed to suit your own preferences if you so choose. The second Concatenate function should collect together the Base File Name, the date/time string, the Header Text and the output from Array to Spreadsheet String with a Carriage Return between each. This is the actual text that will get written to the file. The Carriage Return simply ensures that each item appears on its own line.
7.
8.
The Write to Text File function should get its text from the second Concatenate and its file from the Open/Create/Replace File. For its output, create an indicator by right clicking on the wiring node. This will create a refnum indicator, which is necessary if this VI is to be useful as a subVI.
9.
In order to get this VI to work in a more useful way for your purposes, right click on the Path control and select Browse Options. Under Selection Mode you should enable “Folders” and “New or Existing.” This will allow you to select a folder into which your file will be placed or create a new folder into which you would like your file placed.
10.
Now assign the wiring nodes just as you did for Column Header; right click on the image of the icon and select Show Connector. You should assign wiring nodes to all of the Front Panel items, so there should be eight connectors being used when you’re done. Give this VI a couple of test runs to be sure that it is working properly. Notice that if you run it twice in the same minute it does not create a new file but instead writes over the old one; the easiest way to test this is to have some optional text in one and different text (or no text) in the other. If you don’t like that option you can change the access on the Open/Create/Replace File function. Name this VI Spreadsheet File Creator, save it and close it. 9
ME 411
Winter 2010
Example 3: Voltage Reader Now that you have VIs that will create and name a file with column headers for sorting data, it’s time to collect some data. In this example you will construct a simple VI for acquiring voltage data and, optionally, a time stamp for each data point.
Figure 11. Front Panel for Voltage Reader.
10
ME 411
Winter 2010
Figure 12. Block Diagram for Voltage Reader.
1. To get started, place the VI you just created, Spreadsheet File Creator, on the Block Diagram and create all the necessary controls. 2. Now create a While Loop. Inside the While Loop you will place a DAQ Assistant express VI, which you can find either in Measurement I/O → NI‐DAQmx or in Express → Input. After you place the DAQ Assistant, a series of dialogue boxes will appear, this may take a while, just be patient. First you will select Acquire Signals, then Analog Input and then Voltage. LabVIEW will then survey the available data acquisition devices, find all the channels you could possibly use to collect voltage data and then ask you which ones you would like to use. You should be able to look at your data acquisition device and tell which channel to select. After you select a channel, click Finish. This will open a new screen after a few seconds. 3. You should see the properties screen for the DAQ Assistant. Here you will configure a variety of settings that will affect your data collection. Most of the default settings are fine for this application, but you will have to alter the Timing Settings. For this exercise, change the Acquisition Mode to “1 Sample (On Demand).” This setting will make the VI read data from the device only one time per iteration of the While Loop. If you select “N 11
ME 411
Winter 2010
Samples” then every iteration of the loop will generate however many samples you request. “Continuous Samples” will not work in this implementation; it would be much the same as having a While Loop that never stops inside of another While Loop. Once the settings are all set, click OK. You can always open this screen by double clicking on the DAQ Assistant or right clicking on it and selecting Properties. There are several issues that can arise when dealing with sampling frequency in LabVIEW. The most common one is a disparity between how fast LabVIEW will try to get data from a device and how quickly a device can generate data. Often times LabVIEW can determine the maximum frequency at which a device can operate and warn you if you request invalid rates, but this is not always the case. In this exercise, you shouldn’t have any problems if you use the specified settings. 4. Now place a Time Delay with a value of 0.01 seconds and an Elapsed Time with the “Automatically reset after time target” option deselected. 5. From the File I/O menu under Adv File Funcs, place a Set File Position and create a constant for the “from” node with a value of “end.” You will also need a Write to Text File inside the While Loop and, outside the While Loop, a Close File. Create a shift register for the while loop. Now wire the file path data from the Spreadsheet File Creator subVI into the left shift register, then from the shift register to the Set File Position, then to Write to Text File, then to the right shift register and finally to Close File. The Set File Position makes sure that anything that gets added to the file in an iteration of the While Loop gets added to the end. This is not strictly necessary, but it’s a fast and easy safeguard. 6. In order to get the data from the DAQ Assistant and to the Write to Text File, you will need a converter. Under Express → Signal Manipulation you will find From DDT. Place that inside the While Loop and when the properties box opens, select “Single Scalar” under the “Resulting data type” option. This will take the dynamic data type (DDT) and convert it into a single number, which is all that is necessary for this exercise. If you were collecting two voltage measurements using two different channels, a single scalar would not work; you would need to use an array. 7. Place a Build Array with two inputs and an Array to Spreadsheet String inside the While Loop. Wire the data from the DAQ Assistant into the Convert from Dynamic Data, then wire that output into the top input for Build Array. The lower input for Build Array should come from Elapsed Time. The output from Build Array goes into the Array to Spreadsheet String which should output to Write to Text File. For this exercise, the 12
ME 411
Winter 2010
format string for Array to Spreadsheet String can be whatever you choose, although %f is recommended. 8. Finally, in order to see your data, a simple Waveform Chart is a quick and easy way to do so. Place one on the Front Panel and then you can wire the dynamic data directly from the DAQ Assistant to the Waveform Chart function. Once you give the VI a path for the file and a base name it should be ready to run. Turn on the function generator, set the range to 20 and start the VI. You should be able to see the voltage signal on your Waveform Chart. After you acquire a few seconds worth of data, stop the VI and open the text file it just created to verify that everything is working as desired. Save this VI as Voltage Reader so that you can use it either for reference in future exercises or as a template for later VIs. There are numerous ways to make use of the data in a text file; you can import the data to an Excel spreadsheet, read and sort the data using MATLAB, etc.
13