LabVIEW

cancel
Showing results for 
Search instead for 
Did you mean: 

auto create local variables

Solved!
Go to solution

Is there a way to use property nodes to reference items on the diagram, say a case structure within a for loop?

0 Kudos
Message 11 of 30
(1,393 Views)

I don't understand your question... why do you want a property node of a case structure??? can't you just wire the case value to choose which case runs? that is the purpose of a case strucutre afterall.

0 Kudos
Message 12 of 30
(1,390 Views)

@SRamirez wrote:

Is there a way to use property nodes to reference items on the diagram, say a case structure within a for loop?


Could you provide some code or an illustration or a more detailed explanation of the problem you want your code to solve? Don't explain how you're trying to implement the solution, explain at a higher level what you want to accomplish. If you're relying heavily on local variables, there's probably a better way to do it.

0 Kudos
Message 13 of 30
(1,382 Views)

I have attached my VI.  I am having one loop read data from the FPGA while the second loop converts the CAN frame data and then logs it.  I have two for loops in the second while loop, one for the conversion and the other for the logging.  I am only logging every tenth iteration so as to have a sample and hold feature.  Each case in the case structure within the conversion for loop denotes the message ID. I want to make it such that, if I add more cases, the logging loop and the clear buffer case selector will be automatically updated with the newly created indicators in the newly created cases.  Is this at all possible while still maintaining a sample and hold feature?  I have tried various things and either the sample and hold no longer is in effect or the tdms file does not save with the appropriate channels.

0 Kudos
Message 14 of 30
(1,363 Views)

There are some potential problems here, and there's room for improvement.

 

Local variables are not a good way to pass data between loops. A queue would be a better choice for passing data between the receiving loop, and the frame/channel conversion. You have no guaranteed synchronization right now. For example, right now it's possible that the CAN Frame Read Loop would write the N value, then pause while waiting for data from the FIFO. Meanwhile the Frame to Channel Conversion Loop could read both the N and data local variables - but they won't match! You'll be reading a new value for N and and old value of Data. A better approach would be to use a queue, which would remove the need for N. You would just enqueue 6-element arrays (a cluster of 6 elements would also be appropriate). This should also eliminate unnecessary math in the Frame to Channel Conversion Loop.

 

There is a lot of other inefficient and unnecessary code. For example, why do you have a for loop with N wired to 1? Eliminate the For loop. Then there's the odd use of array subset followed by reshape array. Just use Index Array, where the index is the iteration count from the for loop, as shown:

simplified.png

 

Once you make that simplification, then remove the case structure, along with the duplicate data and channel indicators. Instead, use a 2D array in a shift register around the while loop, assigning one row (or column, if you prefer) to each channel. Then you can expand this automatically to as many channels as you want, just initialize the array to a number of rows equal to the number of channels. The value that is currently wired to the case structure selector becomes an index into that array.

 

Why is the "sample/hold" functionality useful here? Are you simply saying that you only want to log one out of every 10 pieces of data, or is there some other additional reason for doing this? If all you need is to log one out of every 10 data points, then using that same array stored in a shift register, you would simply log the entire contents of that array once out of every 10 iterations.

 

If you need more help or further explanation of any of these suggestions, or you want to know if you're doing it right, post your code again and I'm happy to help.

Message 15 of 30
(1,355 Views)

@SRamirez wrote:

Could you explain that a bit further?  My working knowledge of labview is still not what it should be but if I understood correctly, I should have the data in each case feed into an index array block and then into a replace array block and finally, bundle to cluster.  Correct?  


ClusteredArray.png

 

/Y

G# - Award winning reference based OOP for LV, for free! - Qestit VIPM GitHub

Qestit Systems
Certified-LabVIEW-Developer
0 Kudos
Message 16 of 30
(1,342 Views)

nathand,

 

As always you have been very helpful.  I can definetly see now how I had plenty of redundant and inefficient elements in use.  I made some changes but I am a bit unsure how to implement the 2D array instead of the case selector.  The reason I have the case selector is because not every message contains the same number of channels.  In addition, I have some .ndc files that have random message IDs that are not sequential so using that as the index seems like it could cause some problems.  At the moment I am logging three messages with two having two channels each and the third having five.  The reason for the sample and hold was to obtain one value for each nine channels once every tenth iteration.  Without it, the number of data logged for each channel does not always equal. Should I also use queues for tranfering the converted data for logging and will this eliminate the different size problem?

0 Kudos
Message 17 of 30
(1,315 Views)

Can you share some of your actual data and CAN database files? My understanding is that you're logging one row of data per channel, regardless of how many channels are in the message. Is that correct?

 

You can come up with a way to generate an array that's essentially a lookup table from channel and message to an index into the 2D array of data. When a message arrives, you search through that array for that channel and message combination, and write the data into the data array at the corresponding index. After looking at your code a bit more, it appears that you don't need a 2D array; a 1D array is sufficient.

0 Kudos
Message 18 of 30
(1,303 Views)

nathand,

 

I have attached the database file and some data I obtained using my original code.  I am sending in dummy signals through PCAN so thats why the data isn't changing.  And yes you are correct.  The sample and hold is allowing me to log once every second instead of every milisecond while also ensuring that the channels all have the same number of elements.

0 Kudos
Message 19 of 30
(1,270 Views)
Solution
Accepted by topic author SRamirez

Here's a more thorough re-work of your VI than I intended, which shows how you could use a 1D array to store the most recent value on all channels but only log occasionally. It assumes that you change your CAN acquisition loop to enqueue complete CAN packets. I left the queue timeout unwired, so it will process data as fast as it can dequeue it or wait as long as it takes for data to arrive, but you may want to change that.

 

This VI reads all the channel names once, when it starts. It creates a 1D array for the data, with an extra element for the timestamp. It also creates corresponding arrays of message IDs and offsets into that 1D data array. In your example, message ID 1 has 2 channels, ID 2 has 2 channels, and ID 3 has 5 channels, so you get one array of message IDs containing [1,2,3] and a second array of offsets containing [0,2,7]. The data from ID 1 is in array indices 0-1, ID 2 in 2-6, and ID 3 in 7-8. The timestamp is index 9. You do not need to make any changes to the code when the NCD file changes.

 

When a message arrives, it splits out the message ID, then looks it up in the message ID array. The index at which the message ID is found is used as an index into the offset array, to determine where to store the incoming data.

 

A couple of other things to note. I removed ALL the for loops since they were unnecessary. The Convert U32 Frame to Channel function returns all the channel at once, so there was no reason to iterate through them. The Write TDMS File function also requires array inputs, so it's not necessary to get individual elements and then convert them to arrays in a loop - just write the whole array at once. Finally, it looks like you are picking the wrong array elements to use for the timestamp - you are using the same values that you're using for the data.

 

I hope these suggestions make sense and are helpful.

DAQ PCAN SH overflow simplified.png

Message 20 of 30
(1,260 Views)