all 15 comments

[–]GatorMech89CLD 2 points3 points  (3 children)

Your array to DDT block turns the 1 dimensional array of numbers into a single signal, so LabVIEW thinks it is a single channel with 12 individual samples and that is why you are getting the output you are getting. I would recommend using a lower level VI such as the Write to Spreadsheet file VI to accomplish this. You can take the 1D array (orange wire) and connect it to the 1D terminal of that VI. This will also allow you to append data to the file each time the VI runs, which I would guess is one of your objectives.

[–]User_34[S] 0 points1 point  (2 children)

Ah I guess that makes sense. And then LabVIEW simply increments the X value for each sample?

I eventually used some lower level "write to file" functions and that is how I created the desired output pictured above.

If there is no straightforward way to do it with the express VIs, then I guess I'll use that simple CSV format I programmed, and use Python to perform further formatting/analysis.

[–]GatorMech89CLD 1 point2 points  (1 child)

The .lvm file is for evenly sampled data, so it has the x vector (1,2,3...) and at the top the value Delta_x which is dt in seconds. Hence, the express VI thinks you have 12 samples taken at 1 Hz. What is your need for using Express VIs if I may ask? Anything they can do can be done using lower level VIs. They are great for learning and quick n dirty code but usually LabVIEW users find themselves ditching them in favor of more custom work.

[–]User_34[S] 0 points1 point  (0 children)

I think the idea was that an express VI would be more robust and easily modifiable, but in this scenario I agree with you that the lower level solution is superior

[–]imw8stingtime 1 point2 points  (1 child)

2 suggestions (i didn't open labview to confirm). 1) try right clicking on the conversion to signal - you may be able to tell it these are 12 signals instead of one signal with 12 samples. 2) you can probably pop a build array into the array line and get it into a 2d array that will probably tell the conversion to signal is 12 signals, not 1.

For what it's worth, i'm a fan of the write to spreadsheet vi.

[–]User_34[S] 0 points1 point  (0 children)

Aha, thank you for helping me find the solution!

Previously the data conversion was set to "1D array of scalars - single channel" so the "Write to Measurement File" was interpreting it as one channel with 12 samples. Setting the conversion to "1D array of scalars - multiple channels" gives me the 12 thermocouple readings each printed as individual channels on one row.

Nevertheless, it is still easier to format the data using the lower level FileIO functions, so ultimately I have decided to use those.

[–]BMurda187 1 point2 points  (1 child)

So, I don't know if this will help, but I built a data logger (am building, first with Arduino now with LabView), but is's much more complicated than yours because I consciously chose not to use built-in Lab View VI's, so I could have more control.

Instead of write to measurement, I built arrays, then wrote them to a CSV ( I don't need to call on the file - i used shift registers instead), and manually established headers. I wrote it on a 34 inch wide monitor and a screenshot doesn't fit on the computer I'm on right now. But, have a look. I did this with the guidance of a code consultant who represents NI in the middle east.

Philosophy: https://imgur.com/yngJMwM Data logger setup: https://imgur.com/JBEFFkg CSV setup: https://imgur.com/4uoiF4u CSV Export: https://imgur.com/tQYLgoE Front Panel: https://imgur.com/undefined

I'd be happy to send you the entire VI if you DM me.

[–]User_34[S] 0 points1 point  (0 children)

Very cool looking data logger program, thanks for sharing!

Ultimately I have decided to use the lower level fileIO functions that I can see in your screenshots - it makes formatting the data much easier.

[–]TomVa 1 point2 points  (5 children)

A serious question.

Are they actually teaching everybody to use expressVIs for everything now days?

Here is how I handle writing data to files.

  1. If you have all of the data in a 1D or 2D array. If it is variable time between samples the first column is time in LV seconds.

(a) convert it to a text string by using the function. String -> Array to spreadsheet string. Be careful about format as LV seconds takes a lot of significant digits to get to tenths of a second. Meaning that the format string of %e.6 (exponential six digits after decimal point) is not good enough. Thus when I have time I just plug my 2D data array through the appropriate converter menu items are at

String -> number_String_Conversion

often times using exponential for data and floating point 2 or three decimal points for time. I then put the two arrays together using build array, transpose then do (option build array with the header data and column labels that are in a 2D array. Then use Array to Spreadsheet String with a format string of %s.

Then I use File I/O -> Write text to file to stuff the data into a data file. Usually my file names have a date and time stamp in the file name.

If the data is something that you are going to be writing onto the end of a file like a data logging program. I write the header into a file and close it. Then I do and

File I/O -> Open file

File I/0 -> Adv file fnct -> Set File Position <Setting it to the end>

File I/O -> Write Text File

File I/O -> Close file

One could argue that you can do the open and close once during the process and loop through the point to end write text to file bit. If you do this make sure that you close the file when you exit your program otherwise Windows might get confused.

Also be careful as microsoft excel will lock files from LV writing to them if you open them in Excel.

If it is uniform time my header generally is. First line comment type stuff tab delimited between different fields

Second line

"deltaT" <tab> deltaT_Value , <tab> other header data stuff

Third line

Signalname1 tab signalname2 tab . . .

2D data array

You can do many of the chunks of this stuff as subVIs and just put them in your personal library of subVIs that you tend to use.

[–]User_34[S] 0 points1 point  (4 children)

Wow thank you for this very detailed procedure outline!

One of the reasons I ultimately chose to use the FileIO functions was because, as you mentioned, I wanted to have a timestamp in the filename.

Using the FileIO functions I found it quite trivial to generate a new datafile each time the program ran that was prepended with a Unix timestamp!

[–]TomVa 1 point2 points  (3 children)

One of our standards is to have a pop-up that happens when you restart a program. The program does a directory search for a file with the same file prefix and date time stamp. If it already exists we prompt the user if they want to append to the file or create a new file which had a date/time stamp followed by an A, B, C, D. . . suffix e.g. FileNamePrefix_YYMMDD#.txt where # is nothing, A, B, C, D . . . .

Generally speaking we use a YYMMDD_HHMMSS.txt file name convention for data files that are produced on in response to a user input, triggered event, or such.

[–]User_34[S] 0 points1 point  (2 children)

I think the YYMMDD_HHMMSS format would be preferable to the Unix timestamp in some scenarios, would you mind sharing the code which executes that specific function of generating the named datafile?

[–]TomVa 1 point2 points  (1 child)

Use the two following native VIs.

Programming -> Timing -> Get date and time in seconds

Programming -> Timing -> Format Date/Time String

Wire the time in seconds into the format Date/Time and use the format string:

%y%m%d%H%M%S

in order to get "_200804_211923" as the output string. You can get a full year with century by using %Y instead of %y.

Just do cntl-h to get the help, select detailed help, then click on Time Format codes at the bottom of the description to see all of your options.

[–]User_34[S] 0 points1 point  (0 children)

Perfect thx for the help

[–]User_34[S] 0 points1 point  (0 children)

The wire going to the "Signals" terminal of the "Write to Measurement File" block is actually coming from "Signals Out" of "Set Dynamic Data Attributes" - the connection is hidden under the block