From Friday, April 19th (11:00 PM CDT) through Saturday, April 20th (2:00 PM CDT), 2024, ni.com will undergo system upgrades that may result in temporary service interruption.

We appreciate your patience as we improve our online experience.

LabVIEW

cancel
Showing results for 
Search instead for 
Did you mean: 

DAQmx Organize Data Channels By Name

Solved!
Go to solution

Hello Everyone,

 

I have multiple physical channels concatenated together - just through task in/out - with the DAQmx Create Channel VI, all AI Voltage measurements, with their unique physical channels and titles for said channels. Long story short, I throw this in a queue, then dequeue it in the consumer loop, extracting the individual channels via indexing the array and pulling off of there.

 

Is there a way to do this more like a cluster than an array? I would like the physical channels to "bundle by name" so I can dequeue them and "unbundle by name", thus creating a level of independence from the building function, allowing more modular functions.

 

Thanks very much, in advance.

0 Kudos
Message 1 of 13
(4,312 Views)

@pswail wrote: thus creating a level of independence from the building function, allowing more modular functions.

Bundle By Name would actually INCREASE the dependence since the names have to be known at compile time.  It sounds like what you really want is to use Variant Attributes, where you put your channel data in named attributes stored in a single variant.  You can then get the data using a string look up with Get Variant Attribute.


GCentral
There are only two ways to tell somebody thanks: Kudos and Marked Solutions
Unofficial Forum Rules and Guidelines
"Not that we are sufficient in ourselves to claim anything as coming from us, but our sufficiency is from God" - 2 Corinthians 3:5
0 Kudos
Message 2 of 13
(4,304 Views)

.@crossrulz Great point about the Bundle By Name.

 

Could you please go into a little more detail? I think I'm tracking, however, I'm struggling to make the final connection: I can use a variant attribute for each channel in the task, as reference in the consumer loop for the waveform data?

0 Kudos
Message 3 of 13
(4,296 Views)
Solution
Accepted by topic author pswail

I think I understand what you are trying to do.  See if this is close:

  • You have (say) 16 channels of Analog Data.
  • 4 are Pressure Sensors, 4 are Temperature, 4 are Voltages, and 4 are Something Else (my imagination flamed out).
  • You want to send your data (all 16 channels, now neatly "bundled" in an Array of Waveform or 2D Array of Dbl) to various Processing routines.
  • You want "Process Pressure" to only do the Pressure Channels, "Process Temperature" to do only Temperature, etc.

So the first question (assuming the above makes sense to you) is how do you know which Channel is which?  Well, you could (and probably should) give your DAQmx Channels appropriate names -- not AI0, but Prsr0, not AI4, but Temp0.

 

Create an Enum, ChannelName, that lists your Channels in the order they appear in DAQmx.  To show you how this would work, I wrote this Enum Channels VI, which I'll explain:

Enum Channels.png

The first thing I did was create an Enum, which I named Channel (it's shown at the bottom of the Snippet -- it will also appear as a Control on the Front Panel).  I right-clicked and Edited it to have the values Press0 through Press3, Temp0 .. Temp3, Volt0 .. Volt3, and Other0 .. Other3.  These are designed to be the names of your 16 DAQ channels.

 

To test it, I build an array of 16 strings named Press0, Press1, ... Other3.  That's what the For loop does -- I use the loop Index, mod 4, and let the Quotient determine if it is Press, Temp, Volt, or Other (the Press case is shown), and use Format into String to add the Remainder as the digit, 0 .. 3.  It comes out as an Indexing Tunnel and saved as the String Array "Channels" (which you can inspect to see that it works as advertized).

 

Now we need an Event Structure that fires when the Channel Control (the Enum) changes and plucks out that element (which should have the same name as the Enum)..  That's simple -- since an Enum is encoded as an I16 (or I32), we just use it with Index Array to pluck out the Array Element.  

 

So what's the rest of the code underneath the For loop?  I decided to "play".  The first code create an Other3 Enum by using "Format into String" to add the number 3 (as a String) to Other, making a string "Other3".  I then use the opposite function, Scan from String, bringing my (so far unused) Enum Control as "what I want as the output" and it makes an Other3 Enum.  I bring this into the While loop -- instead of a Stop button, the loop stops when you choose Other3.  Cute, huh?  But it shows how you can go from Channel Name and Number to create the Enum.

 

What's the last bit of code?  Well, without it, there's no "initialization".  I discovered (before I added the code) that I had to change Channel before the Chosen element appeared.  What if I wanted to use the initial value of Channel?  That's what the last bit of code does -- I simply wire it to a Value Signaling Property of itself, and it initializes everything.

 

Even if you don't like this, and choose not to use it, I think it's a cool idea and I'll probably adopt it for my own work.  It also shows how Enums work and my two favorite unappreciated String functions.  Enjoy.

 

Bob Schor

Message 4 of 13
(4,250 Views)

@Bob_Schor

 

Awesome idea. Very interesting and I think this may be a phenomenal solution to my quandary. I think you just about hit the nail on the head. Thanks a ton!

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

@pswail wrote:

@Bob_Schor

 

Awesome idea. Very interesting and I think this may be a phenomenal solution to my quandary. I think you just about hit the nail on the head. Thanks a ton!


Not really, Bob and crossrulz are making duplicates of what LabVIEW does for you!

 

Create the Task with the DAQ Wizard, Label your Channels in the Task with Human Readable Names, Save the Task in MAX Or the LabVIEW Project!

Use the fully configured Task in your code! DAQmx Read AI N Ch N Samples.vi will return an ARRAY OF WAVEFORMS with the Waveform Attribute "NI Channel Name" as the human readable name you gave it (Plots even pick up this name as well as TDMS attributes.

 

Of course, you COULD problematically set wfm attibute NI Channel Name but WHY?


"Should be" isn't "Is" -Jay
0 Kudos
Message 6 of 13
(4,224 Views)

Labeling Channels in MAX, in LabVIEW Project, or programmatically as I did are equivalent ways of doing the same thing -- associating a "human-meaningful name" with a numeric Channel Number.  When and how you do this depends on circumstances -- if the Channels are "fixed in stone" or known in advance (and immutable), then you can certainly build it into the Task variable (in MAX or in the Project).  But if it needs to be flexible, or the names are specified at Run Time, then there's the programmatic option.  Multiple Solutions are a Good Thing (IMHO).

 

Bob Schor

Message 7 of 13
(4,211 Views)

@Bob_Schor wrote:

Labeling Channels in MAX, in LabVIEW Project, or programmatically as I did are equivalent ways of doing the same thing -- associating a "human-meaningful name" with a numeric Channel Number.  When and how you do this depends on circumstances.....  But if it needs to be flexible, or the names are specified at Run Time, then there's the programmatic option.  Multiple Solutions are a Good Thing (IMHO).

 

Bob Schor


Bob, you missremebering the NI DAQ folder contents,)  or the XML in the lvproj on MAX.

 

Ask Tim about. "SET DAQ Attributes"

 

There are some wfm attributes NI does for you    the full list has not been made public.   I would love to ask Chris C  about all the daq wizardry stuff.

 

Bonus, ask elsewhere!  It may be a rabbit hole with rusty nails,,,,   perhaps it is time to lock the interface down.....like I said, a subject for another board ...

 

Mega kudos 


"Should be" isn't "Is" -Jay
0 Kudos
Message 8 of 13
(4,204 Views)

Thanks for this. I am a little confused though. I am more of a newbie and dont have all the VI icons memorized. I see the png you posted:

Enum Channels.png

 

This looks like you are creating an enum with this code. How does the task with the 16 channels get created? I DO see your phrase here:

 


@Bob_Schor wrote:

 

What's the last bit of code?  Well, without it, there's no "initialization".  I discovered (before I added the code) that I had to change Channel before the Chosen element appeared.  What if I wanted to use the initial value of Channel?  That's what the last bit of code does -- I simply wire it to a Value Signaling Property of itself, and it initializes everything.


I don't understand it though.

In my case I need to create various channels with very different names:

Iso SP entering Meter
Poly SP entering Meter
Iso Disp at Head
Poly Disp at Head

Iso Disp leaving Meter
Poly Disp leaving Meter
Iso SP at pump
Poly SP at Pump
Motor on
Air pressure at stick pumps

 

These channels are voltage sensors that represent pressures. Some use different scales. I have ended up with an enormous and messy VI to create the channels:

 

flycast_0-1623761036775.png

A NI tech support person seems very distressed with this VI and has been trying to get me to create them using an autonaming strategy:

flycast_1-1623763934004.png

Which doesn't work for me since I don't get the names I need. Is my first VI with all the channel definitions really so bad?

0 Kudos
Message 9 of 13
(2,931 Views)

Hi flycast,

 

this thread here is not really related to your question…

 


@flycast wrote:

flycast_0-1623761036775.png

Is my first VI with all the channel definitions really so bad?


When it works as expected it should be ok…

I would place the channelnames for all channels with identical properties ("0-3000psi") into an array and call the DAQmxCreateChannel in a FOR loop to cleanup the code…

Best regards,
GerdW


using LV2016/2019/2021 on Win10/11+cRIO, TestStand2016/2019
0 Kudos
Message 10 of 13
(2,907 Views)