LabVIEW

cancel
Showing results for 
Search instead for 
Did you mean: 

Possible Bug: DAQmx Create Channel w/o Task In Specified

Solved!
Go to solution

The DAQmx VI "DAQmx Create Channel (AI-Voltage-Basic).vi" does not require Task In to be wired, and its detailed help claims "task in specifies the task to which to add the virtual channels this VI creates. If you do not specify a task, NI-DAQmx creates a task for you and adds the virtual channels this VI creates to that task."

 

From my recent experience, I think there is a problem with that functionality. If no task is specified, sometimes this VI will create a new task without issues, but other times it will overwrite an existing task, which causes errors later when trying to reference the overwritten tasks.

 

In my code I have 7 tasks running, two digital (DIO), one analog in (AI), and four analog out (AO). One of the AO and the AI tasks did not use a Create Task VI before the Create Channel VI. I recently added this AO task without creating a new task manually, based on copying the legacy code for the AI channel that also didn't create a new task. With two tasks missing the create task VI, I found it fairly common (~20% of runs) that another task would be overwritten, causing errors when the task was used, either being the wrong i/o type, wrong number of channels, etc. I do believe I saw this error before I added the second task without create task, but it was so rare that I didn't pay it much mind, and I would just restart my VI. Now that it was occuring more often, I hunted it down. By simply adding "DAQmx Create Task.vi" before the Create Channel call and wiring the new task into the Task In, the problem seems fixed.

 

It is easy to add Create Task to avoid this issue, but it seems to me that the Detailed Help for Create Channel indicates that this is an unnecessary step. Thanks.

0 Kudos
Message 1 of 10
(8,333 Views)

Reading your description leaves me completely confused. What exactly is your problem?

What do you mean with "overwrite a task"? What errors are you refering to (error IDs please!)?

 

Norbert

Norbert
----------------------------------------------------------------------------------------------------
CEO: What exactly is stopping us from doing this?
Expert: Geometry
Marketing Manager: Just ignore it.
0 Kudos
Message 2 of 10
(8,282 Views)

Sorry, I'll try to explain it more clearly. This is a bug within Labview, not an issue with my code. My code now runs without errors, so I don't have error codes for you.

 

I believe the issue is a poorly written pointer within the Library Function Call inside the DAQmx Create AO Channel (sub).vi:3590004 and other, similar subvi's (AI, DIO, etc). This subvi is called by DAQmx Create Channel (AO-Voltage-Basic).vi:187003. If you specify the Task In when calling Create Channel, there are no issues. According to the documentation, you should be able to not specify Task In, and it should create a new task for you. This will sporadically cause errors at runtime. The solution is to use the Create Task subvi before calling Create Channel, and pass your new, blank Task into Create Channel. I suspect what is happening is the Library Function Call tries to create a new task, but isn't careful about where its variables are pointing in memory, and sometimes it overwrites an existing task. See below for a better description of the runtime behavior.

 

Let's say I have a subvi that creates a bunch of Tasks and passes them to my main vi using a cluster, then my main VI separates them by name and uses them in different parts of the code to read and write data via DAQmx. Let's say I create the following Tasks:

Task1 - 3 AO channels

Task2 - 2 AI channels

Task3 - 1 DIO channel

Task4 - 1 AO channel

 

For each task, I first check for and clear any existing tasks that might have been left behind from previous runs. For the first three tasks, I make a new task, then call Create Channels as appropriate. For the fourth task, I don't create a new task, I simply call Create Channel with a null Task In. My main VI will then have four tasks, none of which are compatible with one another. Task1 would be going to an Nchannel 1sample Write, Task2 would be going to an Nchannel Nsample Read, Task3 would be going to a 1channel digital read/write, and Task4 would be going to a 1channel 1sample Write.

 

Now, if I run this code, it will generally run just fine. However, sometimes one of the first three tasks will be overwritten by Task4. What I mean is, when Task4 is created, it has a chance to literally point to Task2 in memory. If this happens and you sample Task2's values in the main VI, you will see it has 1AO channel, where it should have had 2AI channels. This will cause the Nchannel Nsample Read to fail due to wrong number of channels (expected 2, only had 1). Other error codes are possible depending on which tasks are overwritten. This is why I suspect it is a bad pointer in the Library Function Call; it is an intermitent error and it has the chance to overwrite any of the existing values, not just one.

 

In my specific case, I currently have 7 tasks, and two of those did not create a new task. I was seeing an issue maybe 20% of the time I ran my code. Previously, I had 5 tasks, and only one of those did not create a new task. I do recall occationally seeing an error that I think was similar to what I saw now, but it was so infrequent that I didn't bother looking into it further.

 

A quick fix for NI would be to simply add a null check and Create Task call inside either of the vi's I mentioned above. As it stands now, it will pass the null value all the way down. Or, if a new task should always be created manually, the documentation should be changed. A quick fix for anyone writing code this way is to always create a new task. Maybe this is common practice for most people, but I'm new to writing DAQmx calls and the documentation says it shouldn't be necessary. Sorry if this was the wrong place to post this and for my first post being a little confusing. Thanks.

0 Kudos
Message 3 of 10
(8,249 Views)

Hi MDI-AJT,

 

Would it be possible for you to post your code, so that we can try and recreate this behaviour? When creating DAQmx calls, be sure to use the "Create Virtual Channel" function, as it will create a task when the physical channel is specified. Additionally, are you using one piece of DAQ hardware, or multiple? Certain DAQ devices have a limit to the number of tasks of the same type that can be created. 

 

BeenCoughin

0 Kudos
Message 4 of 10
(8,204 Views)

Hi,

I don't want to post the code, but I think I managed to make a VI with the same bug, and am now more convinced it's a memory error...

 

Run the code below with the button off, and it should run forever. I've run it up to ~3000 counts twice.

 

Run the code with the button on, and for me it stops every time at 877 counts. It will stop if the Purge Gas channel name is found under one of the other task's channel names. My main vi is much larger, which is why I think the error happens more frequently. With this Bug Finding vi, it takes a lot longer for the memory error to poke its head out.

 

The image "From main VI" shows similar array fields taken from my actual VI in three states, working with and without Create Tasks, and bugged.

 

Side note:

In the vi below I can't understand why, when the On=Bug? button is on, the last element of Array reads Purge Gas. "last element" comes up null when indexing that same element, but it displays as Purge Gas to me in the array.

 

 

 

 

Download All
0 Kudos
Message 5 of 10
(8,179 Views)

I'm sorry to say that: i am confident that the issue is within your code.

 

Most important, your code really needs cleanup and a proper structure. Without it, your code is really hard to read.

From what i see from your code, you have race conditions.

 

Besides that, the screenshot of your FP does NOT match the code.

Example:

Your Gas task is array index 0, but the list shows it at index 2 while Cool Line is index 3 in the array but displays as index 0. Obvious, the screenshot comes from a different code.....

 

Norbert

Norbert
----------------------------------------------------------------------------------------------------
CEO: What exactly is stopping us from doing this?
Expert: Geometry
Marketing Manager: Just ignore it.
0 Kudos
Message 6 of 10
(8,148 Views)

I very clearly said the screanshot was from my actual VI, and what I posted here was a recreation of just the buggy part of my VI.

 

New, slightly modified vi attached here, behaves the same for me.

 

The code is sloppy because I threw it together purely to post here, but it is a very simple program. On the left you have 7 flat sequence structures, each of which creates one Task (for seven tasks total). To create a task, it stops existings tasks of that name, clears the task, creates a new task, and adds channels to it. Depending on the state of the "On=Bug" button, two of those tasks will not use the Create Task subvi. The tasks are then grouped into an array and passed into 3 for loops. First I pull out the task name, channel names, and number of channels, and write them to some arrays. If the program stops or if you have One Run on, then you will be able to see the values of the tasks displayed.

 

Have you run this code? Set Run Once to false and On=Bug to true. My claim is that it will terminate after the same number of loops every time. For me that number is 877. If you then turn On=Bug to false, it should run indefinately without stopping. However sloppy or 'bad' the code is, the only difference between these two runs is the use of Create Task, which should not be necessary given the documentation for the Create Channels VI.

 

Your comments that my code is sloppy and needs structure are not helpful; this isn't my real codebase. It also isn't helpful that you're nitpicking the order of the items in the image. You claim I have race conditions, but you don't tell me where? I rewired the final for loop so it happens in sequence. That is the only possible race condition I see, and it doesn't fix the bug.

0 Kudos
Message 7 of 10
(8,124 Views)
Solution
Accepted by topic author MDI-AJT

Hi MDI-AJT,

 

This looks like an issue with the code you posted, per Norbert's suggestion. When creating Task Handles, you should only do this at the beginning of your code outside of any loops, otherwise you will create errors as you overwrite memory locations each iteration. If you move your Create Virtual Channel calls outside of your loops, as well as not call the task handle to be cleared beforehand (and implicitly creating the task rather than explicitly), then this behavior should stop. 

 

I would recommend trying this with a single line rather than 7 DAQmx calls, and follow the DAQmx architecture as seen in the Examples under "Help" » "Find Examples", and see if that behavior persists. By following that architecture, I have not been able to recreate this behavior. 

 

BeenCoughin

0 Kudos
Message 8 of 10
(8,071 Views)

DAQmx seems to have a "lazy" approach to destroying tasks. It SEEMS as if the request to kill a task is handled ansyncronously so...

 

I would not be surprised if the destroy is not happening before you loop back around and try to create again. If that is the case, then you are indeed adding a duplicate to an existing task.

 

Just my gut feel.

 

Ben

Retired Senior Automation Systems Architect with Data Science Automation LabVIEW Champion Knight of NI and Prepper LinkedIn Profile YouTube Channel
Message 9 of 10
(8,063 Views)

Thanks for the comments. I'm definately planning to learn a bit more about DAQmx, go through demos and online training. As I'm working with years old legacy code, I have this as my starting point. Really the only reason I looped in this case was to simulate manually running the code over and over. Otherwise my tasks are built when the code starts and then used through the entire rest of the run. My gut feeling is that my main program crashes more frequently because it is larger in size, so I added the loop here so I didn't have to manually run it 877 times.

 

Anyway, if its not the perfered way to do things, then there's no point in discussing it further really. Maybe the Create Task vi does an extra check that helps clean up dangling tasks (as opposed to Create Channels improperly creating a new task). Fun to think about at least. Cheers.

Message 10 of 10
(8,056 Views)