LabVIEW

cancel
Showing results for 
Search instead for 
Did you mean: 

Creating multiple DAQmx Scales for Accelerometer axes

Solved!
Go to solution
Highlighted

Error -200489 says: Specified channel cannot be added to the task, because a channel with the same name is already in the task.

 

You say that the names where already defined in the project so you can't use DAQmx Create Channels.vi. Try pulling down the DAQmx Channel property node (in the second snippet) and add Analog Input Custom Scale Name (under ActiveChans, replace Physical Channel Name with it) and feed it the newly created custom scale.

 

Ben64

--------------------------------------------------
The best way to say thanks is to give kudos!
0 Kudos
Message 11 of 19
(1,430 Views)
Highlighted

Got it!  [Ben -- I'm not sure I understand your last suggestion, but maybe it is what I'm about to show ...].

 

There are two pieces to the story.  First, following up a remark I think Ben made, I realized that I might be "illegally" modifying a Task after it had been used.  So I use the Task once to get "unscaled" data for Calibration, get the Calibration factors, then re-define the Task with Custom Scales.

 

There are a number of Key Points which I'll make "up front" -- I'm not 100% certain that all are necessary, but suspect that they might be (at least in my hands).

  • The Task (Triaxial) is defined in the Project.  It uses ai0, ai1, ai2 of a USB-6009.
  • Within the Task, I rename the three channels from Voltage_0 (1, 2) to X, Y, Z.
  • I define Custom Linear Scales, X_Scale, Y_Scale, Z_Scale, but don't use them (yet).
  • I gather "unscaled" samples from my Accelerometer in order to get data for a Calibration.  When I have the data, I clear the Task.
  • I re-define the Task, but this time I incorporate the Scaling Factors I got from Calibration and specify Custom Scaling for each axis.
  • Now when I sample, the numbers come out in units of "g".

Here's the over-all test routine.  I've "cheated" and manually entered into Triax Params a set of Calibration values from an earlier run.  The first two VIs get the Unscaled data to use for Calibration, then the Task is cleared.  The Triax Params are used in the next VI to set the scale, and a final sample is acquired, which should be scaled.

Triaxial Logic.png

Here is the Set g Scale VI.  Note that it gets a "fresh" Task Constant from the Project to build for its own use.

Set g Scale.png

In my earlier version, I used a Function, Create Scale, but I'm not sure it did what I thought it should do.  Here I just use a Scale Property Node and "fill in the same blanks" as the function.

 

Oops.  Something really strange is going on.  I was so focused on the code running without errors and with getting its calibration "set" that I didn't notice that when I set the Scale, it seemed to "stick" so that running the code again (without restarting LabVIEW) did not run with unscaled code.  Indeed, both Pre and Post Sample values were the same -- either both sets seemed to use Scaled channels, or both used Unscaled channels.

 

Close, but no seegar ...  (who remembers Pogo?).

 

Bob Schor

Message 12 of 19
(1,415 Views)
Highlighted

I didn't put all the details but this is what I was thinking of.

 

DAQmx Set Custom Scale.png

 

Ben64

--------------------------------------------------
The best way to say thanks is to give kudos!
0 Kudos
Message 13 of 19
(1,410 Views)
Highlighted

This works for me using an USB-6001 (units from custom scale must be set).

Ben64

DAQmx Set Custom Scale-2.png

--------------------------------------------------
The best way to say thanks is to give kudos!
Message 14 of 19
(1,400 Views)
Highlighted

Bob,

 

 

I wonder whether the persistence of the scaling assignment relates to the fact that the task is defined in the project.  Not sure whether that scaling assignment would be saved with the task if you saved the project after running the code that does the scaling assignment.  I suspect it would *not* be saved if the project-based task was defined without scaling, you then ran the code to assign it, and then shutdown the project *without saving* it.  

 

All of that to say that I tend to agree with Ben and have long been in the habit of creating all my tasks from scratch on the block diagram.  I kinda suspect your most recent attempt would have worked expectedly if you were creating your task from scratch in code at run time rather than pre-defining it with project scope at development time. In that mode though, the scaling assignment would have task scope and would need to be redone on every program run. 

 

So, in the end, I'd be inclined to capture the raw voltages, apply the calibration scaling parameters using normal math operations, then store both raw and scaled values (as well as a header with the cal params).

 

It's kinda seat-of-the-pants in the presence of the fancier features offered in DAQmx, but consider the debug time you've just put in.  It's like those billboards on the highway, "If you lived here, you'd be home now."

 

 

-Kevin P

Message 15 of 19
(1,395 Views)
Highlighted

I think we are (independently) converging to the same solution.  It appears to me, looking at my, Kevin's and Ben's code, that for most of the DAQmx functions that NI provides, there is also a DAQmx Property Node that does a lot of the same things (Create Channel vs Channel Property, Create Scale vs Scale Property, etc.  I also just got rid of the Task inside the Project and tried some (pretty crude, but effective) code that did everything from scratch.  I haven't yet had a chance to clean things up enough to run everything together, but it is looking more promising -- there may be a Light at the End of this Tunnel.  I should know when I come back to work tomorrow (I'll fix up the code at home).

 

Bob Schor

 

P.S. -- time to hand out some Kudos ...

0 Kudos
Message 16 of 19
(1,392 Views)
Highlighted

@Ben wrote:

And while I am waiting for an update I will rant a bit and tell a sea story.

 

While the investigation to learn how to use the DAQmx scaling may be an interesting achedemic question, I will often urge my customers to do the scaling explicitly in LV. This allows us to see the values both in scaled and unscaled form and will also make tasks like "Adsting the calibration live" trivial.

 

 


I hadn't seen this earlier -- I'm doing a Kudo run (as opposed to a Cootie run), and (being an academic) was "determined to understand this", but also realize that "explicit scaling" would certainly have been quicker, easier, etc.

 

Bob Schor

Message 17 of 19
(1,392 Views)
Highlighted

When you figure out exactly what went wrong, please feel free to document your findings and marking that update as a solution.

 

Ben

Retired Senior Automation Systems Architect with Data Science Automation LabVIEW Champion Knight of NI and Prepper LinkedIn Profile YouTube Channel
0 Kudos
Message 18 of 19
(1,347 Views)
Highlighted
Solution
Accepted by topic author Bob_Schor

OK, I've got it figured out, and (as is often the case,) was "hoist on my own Petard".

 

I've often mentioned the excellent NI White Paper on DAQmx that you can find by search for "Learn 10 Functions in NI-DAQmx".  What I did not realize was the importance of the "Create Task" function, which I had not been using.  Instead, I'd taken the (convenient) "short-cut" of defining the Task in MAX or in my Project.

 

What I failed to realize (and have not yet found documentation that states this explicitly) is that certain DAQmx Task Attributes, in particular the presence or absence of a Custom User Scale for a Channel, cannot be changed programmatically once it is defined for a Task.  My application required sampling Volts during the Calibration process, and then using the Calibration to set a Custom Scale so that subsequent readings would be in Custom Units.

 

Here's what I did to fix my code so that it does what I want it to do:

  1. I removed the Task declaration from the Project (and from MAX).
  2. I removed the Custom Scales from the Project (and from MAX).
  3. For my Calibration, I did a Create Task, Create Channel (Volts), took my Calibration readings, then Stop Task/Clear Task.
  4. I then used almost identical code to set up for taking Scaled Readings.  I did Create Task, Create Scale (Linear) based on the Calibration data, Create Channel (From Custom Scale), and took my (scaled) Data Readings.  Just to be safe, I end with Stop Task/Clear Task.

During this process, I noticed that there appear, in some instances, to be two methods for setting DAQmx properties.  One is to use a DAQmx Function, such as "Create Scale", while the other is to populate an equivalent Property Node (such as a Scale Property Node).  Other than aesthetics, is there a reason to use one rather than the other?

 

I'm going to mark this as the "Solution", although I was "nudged" in this direction by several of the responders (though I often saw the suggestion just after I had stumbled/bumbled to the same conclusion in my little test codes).  Thanks for your help and patience.

 

Bob Schor

Message 19 of 19
(1,336 Views)