LabVIEW

cancel
Showing results for 
Search instead for 
Did you mean: 

Populating an Array with measurements

I am currently working on my second LabVIEW VI, and have run into a snag.  The software will be to test the resistance of printed resistors, with several on a panel.  I would like to be able to take the resistance of each resistor, and write the resistance reading to a spreadsheet with one sheet per row.  In the VI,  the value of "Sites" is the number of parts on a sheet.  Array 2 is taking the place of the write function.  I am currently unable to get each reading to cycle into the array in the way that I would like. 

 

I'm fairly certain that I am overlooking/overthinking this as it's not all that complex.  Any comments on my code would also be welcome, as being a beginner I'm sure there are several things that could be improved upon.

 

0 Kudos
Message 1 of 13
(5,220 Views)
  • Do not maximize the front panel and diagram to the screen
  • Your VI uses 100% of a CPU core when not doing anything, spinning the loop as fast as the computer allows (would drain the battery quickly on a laptop!).
  • It would probably make more sense top open the VISA session once at the beginning outside the loop and close it after the program has completed. Creating and closing a VISA session every nanosecond (even in idle mode) seems ill advised.
  •  You have a lot of duplicate code (e.g. all the VISA "trains"). Once instance of that code is probably sufficient.
  • Instead of stacks and stacks of case structures and while loops, use a proper state machine (one loop, one case structure)
  • In the middle you build an array with two elements and immediately index out the second element. Wouldn't it make more sense to just branch from the scalar wire?
  • There is an "in range?" function, that could replace both comparisons.
  • You are way overusing local variables.
  • What's the purpose of the last inner FOR loop with the uninitialized shift register?
  • There are scenarios where your inner loops will never stop (e.g. if there is a VISA error).
  • Which array are you trying to populate?
0 Kudos
Message 2 of 13
(5,200 Views)

-Do not maximize the front panel and diagram to the screen

     I'm not sure what you mean by this.  In general my code and front panel are larger than they need to be?

 

-Your VI uses 100% of a CPU core when not doing anything, spinning the loop as fast as the computer allows (would drain the battery quickly on a laptop!).

     It didn't even think about when the program was doing nothing.  Just added a 100ms delay in there.

 

-It would probably make more sense top open the VISA session once at the beginning outside the loop and close it after the program has completed. Creating and closing a VISA session every nanosecond (even in idle mode) seems ill advised.

 I've moved both the VISA Open and Close outside of the loop, though putting the close outside of the loop leaves some tunnels unwired in some cases.

 

-You have a lot of duplicate code (e.g. all the VISA "trains"). Once instance of that code is probably sufficient.

 I agree, there is a significant amount of duplicate code.  However, I am unsure how to take the VISA trains down to one.  This is because (going from left to right) the first VISA reading is simply there to detect when a measurement is being taken.  As in when the resistance being measure is no longer an open.  The second VISA train is there to take new measurements until there are two consecutive measurements that are within 0.1 Ohms of one another.  This is an attempt to ensure that the program is not catching a reading until it has settled, or if an operator does not have a good connection.  This reading cannot be passed from the first VISA train as that would simply pass the "NOT open" value twice and exit the loop.  The third VISA train is there to sense when the operator removes the test leads from the part being measured.  This came into play, because I did not want a continuous measurement of the same value.  This isn't a timed action, it is a user manually taking resistance measurements of multiple parts on a panel.  Because I only want one resistance reading per part, it was necessary to take readings until the program could sense that the meter was now reading an open, and exit the loop in preparation for the next part.  Again, if the values from the previous VISA trains were passed to this loop, then you would simply have the previous values passed, and the loop would never exit.

I would not be surprised if there are other/better ways of doing this without the redundant code, but I at least wanted to pass on my rationale for it.

 

-Instead of stacks and stacks of case structures and while loops, use a proper state machine (one loop, one case structure)

I am having trouble seeing how exactly this program would fit into a state machine architecture, though that is likely my own ignorance.  I will do some more research on them, and see if that helps.

 

-There is an "in range?" function, that could replace both comparisons.

Thanks for that, I didn't realize!

 

In the middle you build an array with two elements and immediately index out the second element. Wouldn't it make more sense to just branch from the scalar wire?

Building that array was simply there for my testing purposes, so I could watch consecutive values be compared.  At the end of the day, a scalar wire will be used.

 

-You are way overusing local variables.

 Noted.  I have now used wires to eliminate Min/Max/Sites locals.  Not completely sure how to eliminate the Test Status locals at this point.  But that will likely show itself as I continue to work with this.

 

- What's the purpose of the last inner FOR loop with the uninitialized shift register?

 That FOR loop is simply me trying different ways to populate Array 2 in the way that I desire.  It is more of an experiment in progress than anything else.

 

-There are scenarios where your inner loops will never stop (e.g. if there is a VISA error).

 I plan to OR the VISA errors with the current method of stopping each loop.

 

-Which array are you trying to populate?

 I am trying to populate Array 2.  Array 2 will be replaced with Writing to a spreadsheet.  For now, Array 2 is simply there so I am visually able to test that values are being passed there in the desired way.  The goal is for Array 2 to be a 1D array with a total index of "Sites".  Sites is simply the number of parts on a given panel.  The goal is for an operator to test each part on a panel, those values are stored in an array until the entire panel is measured.  Once an entire panel is measured, then that array is output to a spreadsheet as a single row.(along with the value of the Test Type case structure)

 

Thank you for your input, I look forward to hearing more on how to improve.

 

0 Kudos
Message 3 of 13
(5,173 Views)

To append to an existing array with each iteration of the outer loop, the shift register containing the array needs to be anchored to the outer while loop and initialized with an empty array of the right type. Use "built array" to append the new value to the existing array. Don't use inner loops for that. Of course if you are just incrementally writing to an existing file, you don't need to build any array. Open the file once, keep appending whenever needed, and close the file at completion of the program.

 

If I open your VI on my system. both front panel and diagram fill my entire monitor. I prefer a defined size instead.

 

If you have unwired output tunnels, you need to make sure to wire the value across in the other case(s) unchanged.

 

 

 

 

 

0 Kudos
Message 4 of 13
(5,168 Views)

altenbach,

 

Thanks for your reply.  Just to be sure I am understanding you correctly, please see the following:

 

Build_Array.JPG

If I am understanding you correctly, this is what you were describing, correct?

This does pass the previous measurement to the next element in the array. However, with this configuration, the number of elements in the array is determined by how many elements the build array is stretched to.  Is there any way to control the number of elements by an input of some sort?  This size of this array should be determined by the number of parts on a given panel, which depends on the specific part.

 

The intention is to take measurements for one panels worth of parts, then write those values in a single row of a CSV.  Panel 2 would be line 2 etc.

 

When it comes to a defined size, am I correct to think you are speaking of Window Appearance under VI Properties?

0 Kudos
Message 5 of 13
(5,135 Views)

I expect what was meant is probably something more like this:

 

sr.png

 

Here, the array is on the shift register (it is the thing passed from iteration to iteration) and each iteration, a new element (here a random number) is added to the end of the array.

 


@TAmbriole wrote:

 

Is there any way to control the number of elements by an input of some sort?  This size of this array should be determined by the number of parts on a given panel, which depends on the specific part.

 

The intention is to take measurements for one panels worth of parts, then write those values in a single row of a CSV.  Panel 2 would be line 2 etc.

 


In terms of controlling the number of elements, it sounds like you might prefer a For loop (rather than a While loop). A For loop has a specified number of iterations, either by autoindexing an array or wiring a constant to the N in the top left.

 

The problem you might run into is that an array has to have the same length in each row, when it is 2D. That is, you can't build a 2D array and have some rows be longer than others. You could work around this either by using a special value (like NaN), or alternatively, by instead recording an array of clusters of an array.

 

In the latter case, you place each 1D Array into a Bundle node when you have finished building it, which creates a Cluster containing a 1D array. Then, you use Build Array on each of your resulting clusters, to form a 1D array of clusters of 1D arrays of doubles (or whichever datatype). Since your arrays are all 1D, they can have varying lengths. The second array is of single element clusters, which are fine. It might make your later calculations more complicated however...


GCentral
0 Kudos
Message 6 of 13
(5,124 Views)

cbutcher,

 

Thanks for stopping by to help at this thread, too.

Seeing how inputting an array can be used to dictate the number of times a for loop will run, I used the value in "Sites" wired to the n of a for loop which uses a shift register to pass the iteration number out.  This effectively creates an array with the number of elements that "Sites" specifies. 

 

At this point, I am trying to populate Array 2 with resistance measurements.  As of now, the array is populating with a 0(on first iteration of the program), resistor value, 9999999(open).  This is with the sites set to 3.  When watching in highlighted execution, this makes sense.  However, I am having issues determining what the for loop should encompass in order to capture the value of each resistor reading one time per program cycle, and nothing else.

 

0 Kudos
Message 7 of 13
(5,113 Views)

I'll throw in a few more comments - I can almost see what you're trying to do, and it looks quite clever, but I think there might be a couple of logical holes that your planned sequence is falling through.

 

  • Why are you reading the CSV in the outer loop? Is this for multiple tests, and you don't want to restart the VI?
  • In the For loop, you only need to do what you're doing with the shift register if you actually intent to use the values. If you only need a suitably sized array, you can just auto-index 'i'. If you only need the number of iterations, you can wire the result to 'N'
  • Assuming everything starts nicely, you get a value for N that is number of sites. Then, your loop is checking against the "Less than 999999" node to start the measurement. You touch the measurement points to the resistor, and it jumps to the true case (on the next outer while loop iteration, which will have read the CSV again, and again, and again by this point 😉 ). The value settles to R. R is passed from shift register to the second While loop (inside the For loop). This loop keeps spinning until you remove the measurement points, at which point the VISA reads an open value, and R is passed to the outer shift register. The first value, as you noted, is the default 0 (on subsequent runs it would be whatever came last - this is from the uninitialized shift register).
  • The For loop now restarts. Because the 999999 check is OUTSIDE the For loop, it determines that 999999 is a stable value (or whatever you measure is stable) and quickly finishes both For loops, pushing out a value of the open resistance.
  • The last iteration repeats the open measurement, but the values output are the ones at the beginning, not the ends of the iterations - hence (0, R, open), rather than (R, open, open).
  • You can instead just wire the value (from the top of the 3 wires, currently connected to the shift register) to the outside of the for loop - this will remove the 0. However, it won't solve your issue with near instantly finishing the For loop making open readings.

As has been mentioned before, a State Machine might be better for you here. I've attached a VI below giving some possible state transitions based on how I understood your process. It's possible I've horribly misunderstood, in which case, apologies. I haven't worked out if I can backsave snippets (I don't think so...) and many users aren't using 2017 yet (and I don't have 2016 on this computer), so I didn't attach a snippet.

 

 


GCentral
Message 8 of 13
(5,105 Views)

@cbutcher

You should look into installing the Code Capture Tool via VIPM

You can automatically backsave snippets

possibleStates_BD.png


"Should be" isn't "Is" -Jay
Message 9 of 13
(5,100 Views)

  • Why are you reading the CSV in the outer loop? Is this for multiple tests, and you don't want to restart the VI?

There are several hundred unique parts that are being loaded by the CSV. With that said, any given spreadsheet should only contain data from a single given run. As long as the user is able to select what part they are taking measurements on, then I am fine with it. Ideally, this would be done as soon as the user opens the program, but I can easily see times where a user starts taking measurements then realizes that they forgot to change the part number(which will likely be caught when parts begin failing).

 


  • In the For loop, you only need to do what you're doing with the shift register if you actually intent to use the values. If you only need a suitably sized array, you can just auto-index 'i'. If you only need the number of iterations, you can wire the result to 'N'

Noted and changed as it is simpler.

 


  • Assuming everything starts nicely, you get a value for N that is number of sites. Then, your loop is checking against the "Less than 999999" node to start the measurement. You touch the measurement points to the resistor, and it jumps to the true case (on the next outer while loop iteration, which will have read the CSV again, and again, and again by this point ). The value settles to R. R is passed from shift register to the second While loop (inside the For loop). This loop keeps spinning until you remove the measurement points, at which point the VISA reads an open value, and R is passed to the outer shift register. The first value, as you noted, is the default 0 (on subsequent runs it would be whatever came last - this is from the uninitialized shift register).

 With you and agree until reading the CSV.  With the read function outside of the while loop, wouldn't it only run once?  I'm guessing I'm missing something here.  The rest of this is correct from the conceptual standpoint of what I'm trying to achieve. 

 


As has been mentioned before, a State Machine might be better for you here. I've attached a VI below giving some possible state transitions based on how I understood your process. It's possible I've horribly misunderstood, in which case, apologies. I haven't worked out if I can backsave snippets (I don't think so...) and many users aren't using 2017 yet (and I don't have 2016 on this computer), so I didn't attach a snippet.

 I am still having issues wrapping my head around coding this as a state machine, but I think that is because say I have a state that is for "Open".  This would not work as a state because I have two different actions that need to be performed depending on when an open is detected.  With that said, I will have a look at your VI and see if that helps clarify things.

0 Kudos
Message 10 of 13
(5,097 Views)