LabVIEW

cancel
Showing results for 
Search instead for 
Did you mean: 

Writing data as an array

I'm trying to write LVDT and temperature data to a file that I can import into MATLAB for analysis, and I understand that the data simply has to be saved as an array. Ultimately I need one vector of displacement and one vector of temperature data, and for the purposes of analysis, it would be useful if they were a 2D array. I've created an XY graph of displacement vs temperature, but I'm having trouble getting the data into an array that I can wire to the Write To Spreadsheet vi.

I'm attaching my VI so my description makes more sense. Data is read from the LVDT and thermistor only when the thermistor outputs, hence all the action goes on in the "true" case of the case structure. I can't write to spreadsheet file every time the case structure is run (because it will execute many times), but if I put the Write To Spreadsheet outside the while loop as I think should be done (since the file should be saved only after the user presses the stop button and stops the while loop) then I have to wire something in the "false" case to the tunnel, but what would that be? Also, the data in the "true" case is only a single value, and as a student newbie, I don't really understand how to create an array without using a loop, which doesn't really seem reasonable in my case.

I found an old post referencing using queues that almost seems like it would be useful but I found it hard to follow...

Does anyone have any suggestions to how I can ultimately create an array that I can write to a file? Thanks a lot!

Message Edited by hyenah on 06-03-2007 03:41 AM

Message Edited by hyenah on 06-03-2007 03:48 AM

0 Kudos
Message 1 of 6
(7,944 Views)
First, you don't need queues. What you need is two loops: An outer loop that waits for you to press the stop button, and an inner loop that just waits for the next data point. What was confusing you was that you were trying to service both logical actions with a single loop. This is possible, but it complicates the logic.

Second, a modified version of your code is attached. You will notice several changes. To begin with, don't do comparisons that you don't need to do. Case statements in LV are polymorphic so you don't need the "> 0" operation. Just wire the byte count up to the selector node on the case and make the case where the acquisition code is at "20.." (20 bytes or greater) and the other case Default (logically, anything less than a complete response from the serial device).

Next, in terms of style, neatness counts. Wires should run is straight lines when possible and arrange things so there is a logical flow - like in a schematic diagram for an electrical circuit. The few moments you take in keeping a diagram neat will pay big dividends when it comes time to debug a problem. A few specific things:
  • Don't use unnecessary functions - like the constructor you were using.
  • Show functions as icons as they take up too much room on the diagram otherwise.
  • Do NOT show terminals as icons, for the same reason...
  • Do use floating text labels to logically identify wires - as with "x-axis" and "y-axis"
  • Use transparent borders on diagram labels. I know this seems like a little thing but they really clutter-up a diagram
  • Do take advantage of all the display functions of indicators and controls to avoid duplication of functionality. (strip charts have their own built-in digital displays all you have to do is turn them on by right clicking on the graph and checking it under the "View" submenu).
Finally, the functional changes I made: The inner loop, as I said before, waits until a timeout occurs (see the Default case) or a data value is read from the serial device. The timeout works by means of the top shift register. It is initialized to the current time when the loop starts and every time a data point is generated. If less than 20 bytes are at the serial port, the code compares the time in the shift register and if the difference is greater than 5 seconds, it stops the loops. To change the timeout, simply change the value in the constant.

If you have any questions as to how the logic works, or if you have any further questions - just ask...

Mike...

Certified Professional Instructor
Certified LabVIEW Architect
LabVIEW Champion

"... after all, He's not a tame lion..."

For help with grief and grieving.
Message 2 of 6
(7,931 Views)

Mike made some valid points, however he did not really address your question about creating a 2D array to save the data.

Here's my quick take on things:

  • I would only use a single loop and build the x and y arrays in shift registers. At the end, just merge them into 2D arrays. You should make sure that the program does not run "forever", else you'll run out of memory.
  • Actually, I would place the save operation in a loop so you get another chance to save the data in case you accidentally press cancel at the file dialog, for example (not shown in my example).
  • The "collectors" have a purpose, they keep the last 5 points so you actually average 20 points. However, this seems incorrect use because you'll have the average of five earlier values and 15 current values. Since you collect only one point per iteration, some of the five points could be from quite a few iterations back and thus don't relate much to the current iteration. What is your reasoning? I would just get the current value.
  • Building arrays just to get the average of the elements later is a waste of memory. Just add the values in a shift register and divide by the number of summed elements.
  • You should place a small wait somewhere. There is no need to check the serial port millions of times per second. You are running at 2400 baud, so it'll take about 10ms to get the 20 bytes you are waiting for anyway.
  • Your charts don't have a reasonable x-scale, because your times are somewhat randomly spaced. Maybe that's OK.
  • You could plot all data in one chart, reducing clutter. They share the same x-axis anyway. Simply create 3 Y scales (not shown in my example).

Attached is my quick attempt at a cleanup. Maybe it can give you some ideas. 🙂

(Sorry, I canont test because of missing subVIs and hardware. There might be bugs. Modify as needed. Let me know if anything is not clear.)

0 Kudos
Message 3 of 6
(7,917 Views)
Wow, thank you two so much for the quick turnaround and very helpful modifications..

I'd like to add that I put the collectors there (they were actually collecting 15 previous measurements each) because I wanted to average the voltage measurements before and after the "trigger" from the thermistor reading, because I was getting a lot of noise. I was trying to average some measurements before the trigger with some measurements after the trigger because that's what it took to get a somewhat stable reading when the core in the LVDT is motionless and there shouldn't be any change in voltage. There is probably a better way to do this, so I'll look into it further.

altenbach, what do you mean put the save operation in a loop? The only thing I can think of is to say, put it in a 2-count for loop so it prompts you twice -- except how would you avoid getting prompted again if you did save it correctly the first iteration?

mikeporter, this is probably a simple question, but how do you show terminals and functions just as icons?

I can't tell you how much I appreciate the help! I'll test out the modified VIs and post any questions I have.
0 Kudos
Message 4 of 6
(7,906 Views)
Hmmm... you're right I got so involved in making the data come out right, I forgot to put the data saving back in... Sorry...

Likewise, the comment about the serial data rate is a good one, there should be a delay in the "Default" case. Assuming a 2400bps data rate, a 10-bit total character length (1 start bit, 8 data bits and 1 stop bit) and a 20 character message length - and assuming that the messages are being streamed back-to-back, you'll see a new message about every 83 msec. I think I would start with a delay of about 50 msec or so.

In terms of your comments concerning the x-axis, it depends on what you are wanting to relate. If you are wanting to show position related to temperature, then the logic in the code makes sense. The x-axis doesn't always have to be related to time. I once had an application where it needed to show a pressure value related to the rotational position of a crankshaft. Now due to torsional forces the time the shaft took to rotate 1 deg varied widely during a single rotation (this was a 8000 horsepower reciprocating compressor), but the plot was valid because it showed what the customer was interested in: pressure as a function of crank position.

Mike...

Certified Professional Instructor
Certified LabVIEW Architect
LabVIEW Champion

"... after all, He's not a tame lion..."

For help with grief and grieving.
0 Kudos
Message 5 of 6
(7,896 Views)


@hyenah wrote:
altenbach, what do you mean put the save operation in a loop? The only thing I can think of is to say, put it in a 2-count for loop so it prompts you twice -- except how would you avoid getting prompted again if you did save it correctly the first iteration?

mikeporter, this is probably a simple question, but how do you show terminals and functions just as icons?

You could for example place a small case structure inside the default case of the existing case. Use the wire from the stop button and OR it to a [save] button so it goes true when you press the stop or save button. In the TRUE case, place the save operation and cancel the stop if the save operation encounters an error.

Actually, I would remove the "stop on idle" functionality, because the VI does not really do anything expensive. Just keep it running and stop it manually when needed.

To show terminals plainly, right-click the terminal and uncheck "view as icon".

0 Kudos
Message 6 of 6
(7,889 Views)