LabVIEW

cancel
Showing results for 
Search instead for 
Did you mean: 

Averaging multiple channels when button pressed

Solved!
Go to solution

Hi Aggie,

 


@aeroAggie wrote:

I know how to create a VI to access data from the various sensors and instruments. I created this VI with dummy signals (the array of numeric controls) to try and code the averaging feature. In the future, I will replace the dummy signals in the producer loop with actual data from DAQmx and the instrument library. Does that make sense?


Right now there is an array containing simulated data samples.

But in your first message you wrote you want to combining samples from:

I'm measuring torque using a strain gauge module, rpm using a counter, and electrical power from an external instrument via VISA.

How does that array present those data from different devices?

Especially with this sentence:

The torque output will be an array (size set by DAQ buffer), the RPM sensor output will be ???, and the instrument reading will be a scalar.

Again: how does the "simulated data array" represent your torque sample array plus RPM sensor "???" plus "scalar instrument reading"? What kind of "???" signal do you get from your RPM sensor?

Best regards,
GerdW


using LV2020 on Win8.1+cRIO
0 Kudos
Message 11 of 24
(110 Views)

Hi GerdW, sorry for the confusion.

 

How does that array present those data from different devices?

My averaging function takes in an array. Nominally, each array element would represent a reading from a sensor. When the averaging button is pressed, the averaging function keeps a cumulative sum of readings until N data points have been collected for each sensor. Then, the function takes an average for each sensor and writes the averages to a file. Any red flags so far?

 

I didn't have access to hardware when I started coding, so I used numeric controls to build dummy inputs for the averaging function. I know what goes, and I know what should come out for debugging the averaging logic. Once I have access to hardware, I will replace the numeric controls feeding the array with readings from a load cell, RPM sensor, and power analyzer.

 

For the power analyzer, it will be a straightforward replacement because the instrument library's "read function" returns a scalar. That scalar will be one element of the array I sent to my averaging function. Again, so far so good?

 

For the DAQ-based readings (load cell, RPM sensor), the replacement will not be as simple. I continuously sample these sensors and capture an array of data from each sensor. At all times, I will plot these torque and speed readings on the front panel so I can see how the test rig is behaving. That is why I'm not just taking a scalar reading at the same rate as the power analyzer.

 

My plan was to average each of these "DAQ arrays" into a scalar. These scalars would then be the second and third elements of the averaging function's "input array". Does that make sense?


What kind of "???" signal do you get from your RPM sensor?

I should have asked for clarification there. Sorry.

I know how DAQmx continuous sampling of an analog input works. You set a sampling rate (fs [S/s]) and buffer size (bf [S]). The while loop which reads from the device will execute at fs/bf [/s]. At each iteration, you will capture an array of size bf.

I don't understand how DAQmx continuous sampling of a counter input. If the object under test is already spinning, I can start continuously measuring the speed using a frequency counter with implicit timing. But I don't think the buffer size was ever uniform. If the test object is not spinning, the counter read crashes.

 

Thanks a lot for the critique, AeroAggie.

0 Kudos
Message 12 of 24
(92 Views)

Btw. I suggest to rethink your program design: I don't think it's a good idea to access UI elements used in the producer loop also in the consumer loop, especially when you need property/method nodes to do so…

 

I had both loops accessing the averaging button (1) during debugging (2) and because I wanted to shut off the UI element while the consumer loop was active.

 

Instead, I will limit access solely to the producer loop. I will add an LED indicator accessed only by the consumer loop. It will activate when the consumer loop is averaging so the user knows not to push the averaging button.

0 Kudos
Message 13 of 24
(81 Views)

I've attached a cleaner and simplified version of my code.

 

What should I do if I want the following:

 

There are N signals. When a user presses the "average" button, the VI should an average of M data points for each signal. After the average is computed, the average button should reinitialize.
(I call M the "average buffer" in the main VI).

 

Thanks,
AeroAggie

0 Kudos
Message 14 of 24
(77 Views)
Solution
Accepted by topic author aeroAggie

Hi Farid,

 


@aeroAggie wrote:

What should I do if I want the following:

There are N signals. When a user presses the "average" button, the VI should an average of M data points for each signal. After the average is computed, the average button should reinitialize.
(I call M the "average buffer" in the main VI).


  • I would place the "average" button in the consumer loop.
  • I would set that button to "latch" mode.
  • When the button is pressed you start to average the data, until "M" samples are calculated for each channel.

Like this:

Best regards,
GerdW


using LV2020 on Win8.1+cRIO
0 Kudos
Message 15 of 24
(62 Views)

Hmm, I hadn't thought of putting the average button in the consumer loop...

 

Right now, have a case structure in the producer loop that queues elements only when average button is pressed (it's in the "read" sub VI). Otherwise, I don't queue any data. If I move the average button to consumer loop, then I have to remove that case structure and constantly send data to the consumer loop--even when I don't want to average. Is that OK?

 

I thought I could minimize the load on LabVIEW by having the average button intelligently engage queuing in this manner.

 

On a related note, how should I time the two loops? I suppose data-acquisition will apply a wait time on the producer loop. Should I add an explicit wait to the consumer loop?

0 Kudos
Message 16 of 24
(54 Views)

@aeroAggie wrote:

I don't understand how DAQmx continuous sampling of a counter input. If the object under test is already spinning, I can start continuously measuring the speed using a frequency counter with implicit timing. But I don't think the buffer size was ever uniform. If the test object is not spinning, the counter read crashes.

Yeah, counters are *different*.  You might want to check and see if your hw supports a kinda new-ish freq measurement mode that allows constant-rate sampling.  In the desktop DAQ world, you'd probably need an X-series MIO board.  Not sure offhand which cDAQ chassis support it, but a starting guess is that I'd expect the ones with a 100 MHz master timebase clock probably do.

 

Barring that, when you use Implicit timing for freq measurement, you buffer up freq measurements at exactly that external frequency.  If it varies, so does the rate at which the data is captured.  And when that freq is 0, there's literally nothing available for you to capture and that's why your Read times out.  Note that a timeout error is *recoverable* so it's quite a bit different from "crashing".  All you need to do is watch for that timeout error code and have your code choose how to react.  In situations where such timeouts are expected and normal, you can choose to ignore or clear the error.

 

 

-Kevin P

0 Kudos
Message 17 of 24
(47 Views)

Hi Kevin,

 

Thanks for the info.

 

To your point about recoverable vs. crash (too harsh on my part): I think at some point I started ignoring the timeouts.

 

Can you tell me more about that new sampling mode you're talking about? I'm using a USB 6361 DAQ and SC-2345 connector block. Are you suggesting I do an on-demand sampling using an onboard 100 MHz timebase?

0 Kudos
Message 18 of 24
(45 Views)

Gerd,

 

What was your problem with the property node stuff I was doing earlier? Was it the fact that I was using a property node to begin with? Or were you concerned about using a property node in the consumer loop to change a control in the producer loop?

 

If you were concerned about accessing nodes in two different loops, how about the following...

 

Move average button back to producer loop. Switch when pressed mechanical action.

Modify queue data type into cluster. Cluster contains data array plus a write flag

Initialize VI with sum array (zeros) and sum counter (zero)

 

Producer loop:

  1. Acquire data
  2. If average button pressed:
    1. Increment sum counter
    2. If sum counter >= M samples (user input):
      1. Create a true boolean
      2. Reinitialize average button to false
        (via node or variable...whichever safer)
      3. Reinitialize counter to zero
    3. Else:
      1. Create a false boolean
    4. Enqueue cluster(data + boolean)
  3. Else: do nothing

Producer loop:

  1. If Dequeued data array is non-zero:
    1. Add data to sum array
  2. If dequeued boolean is true:
    1. Computer average = sum array / M samples (user input)
    2. Write averages to file
    3. Reinitialize sum array to zero
0 Kudos
Message 19 of 24
(36 Views)

Hi Farid,

 


@aeroAggie wrote:

What was your problem with the property node stuff I was doing earlier? Was it the fact that I was using a property node to begin with? Or were you concerned about using a property node in the consumer loop to change a control in the producer loop?


  • Property nodes usually are the slowest you can use compared to terminals and local variables…
  • By mixing controls/properties in both producer and consumer loop prevents you from putting each loop into their own subVI!

Think about code organization, encapsulation, and so on…

 


@aeroAggie wrote:

Move average button back to producer loop. Switch when pressed mechanical action.

Modify queue data type into cluster. Cluster contains data array plus a write flag

Initialize VI with sum array (zeros) and sum counter (zero)


I'm a fan of "one task per subVI, one subVI per task"!

Why do you want to mix

  • DAQ
  • UI handling (checking the average? button)
  • signal analysis (averaging/counting)
  • and signal forwarding (queue)
  • maybe even data display (?)

all in the producer loop?

What's the problem of sending the DAQ data to the next loop to have it handle the averaging?

How much data do you handle? Is it <= 1kS/s or do we talk about >=1MS/s?

 


@aeroAggie wrote:

how about the following...


Now you also want to split the averaging code (counting and computing the average) into two loops?

Why do you think it is a good idea to handle the very same data (cluster of sum array and counter) in two places?

Best regards,
GerdW


using LV2020 on Win8.1+cRIO
0 Kudos
Message 20 of 24
(33 Views)