LabVIEW

cancel
Showing results for 
Search instead for 
Did you mean: 

DAQmx Task not propagated through FGV/AE

Hi all,

I'm trying out FGVs and decided to create a simple one to see if it works. Naturally, it didn't and hence I'm here. 

 

The Enum ring contains "Init", "Read" and "Close". I keep getting the Error -200088 and after probing the wires, it seems that the task isn't being sent through the shift register to the DAQmx Read. 

 

1) Is this a characteristic of DAQ that it doesn't work in a FGV?

2) I tinkered with the idea of using the FGVs within a DQMH architecture and was using the API Tester to trigger the "Init" and "Read" of the FGV. Would the architecture affect the FGV? (The FGV is a simple vi built outside of the module but i call it by placing it in the MHL after a request is made)

3) Someone else on the forum wrote that there was a workaround (without giving details) regarding DAQ Tasks in a FGV, but what is best practice?

 

nikvl_0-1745494409050.png

Thank you in advance.

0 Kudos
Message 1 of 13
(829 Views)

Please attach your actual code and the example you are trying to use this Action Engine with. There are way to many variables that we cannot see here with an image.

 

Some possibilities:

1. You did not properly wire up the output tunnel from the case structure in one of the cases.

2. You are not keeping the AE in memory through a single run instance. If the AE does not stay in a run state, the data could be cleared out.

3. The AE is reentrant, which will not allow the singleton pattern you need for an AE.

 

With all of that said, I do not like using an Action Engine to handle a DAQ task. At least for analog inputs, you really want a separate loop to be constantly reading from the DAQ and then use a queue (possibly in an AE) to pass the data to a processing and/or logging loop.


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
Message 2 of 13
(817 Views)

Thank you for your prompt response, your tips helped, it now works. Sorry for not posting code, I just felt the entire DQMH project might have been too much. It was a silly mistake in my DQMH Helper Loop where an error was triggered so it tried stopping the task before it even started.

 

By the way, what do you mean by your statement in 2) about keeping the AE in memory through a single run instance? Is it the same as a non-reentrant vi? 

 

Is there a reason for your preference of not using an Action Engine to handle a DAQ task? Granted, you mention for analog inputs, but at some point I'd need to control a bunch of valves (using the DAQ digital outputs) and an AE seemed like a neater and more manageable way to keep everything together "under one roof". Then there are also controller valves which utilizes analog inputs and outputs, so I figured the DAQ tasks could be kept separate and reduce mistakes due to faulty wiring of one task to the wrong read, etc. Or are there better ways to go about that? 

 

 

0 Kudos
Message 3 of 13
(794 Views)

@nikvl wrote:

Is there a reason for your preference of not using an Action Engine to handle a DAQ task? Granted, you mention for analog inputs, but at some point I'd need to control a bunch of valves (using the DAQ digital outputs) and an AE seemed like a neater and more manageable way to keep everything together "under one roof". Then there are also controller valves which utilizes analog inputs and outputs, so I figured the DAQ tasks could be kept separate and reduce mistakes due to faulty wiring of one task to the wrong read, etc. Or are there better ways to go about that?


For analog inputs, it is best to have a loop dedicated to only reading from the DAQ in order to avoid buffer overflows. I would do the same for digital waveform tasks. Basically, any task that has timing involved should have its own dedicated loop. For static DIO, an AE is just fine. I've done that in many applications with no issue.


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
Message 4 of 13
(779 Views)

@crossrulz wrote:

Please attach your actual code and the example you are trying to use this Action Engine with. There are way to many variables that we cannot see here with an image.

 

Some possibilities:

1. You did not properly wire up the output tunnel from the case structure in one of the cases.

2. You are not keeping the AE in memory through a single run instance. If the AE does not stay in a run state, the data could be cleared out.

3. The AE is reentrant, which will not allow the singleton pattern you need for an AE.


4) The AE initialization is executed in a different Top Level VI Hierarchy than the function to work on the DAQmx Task. DAQmx Tasks are also LabVIEW refnums, just with a user readable name attached. All LabVIEW refnums have a controlled lifetime that depends on the Top Level VI in whose hierarchy the refnum was created. Once that VI goes idle, the refnums are closed and the hidden Magic Cookie in the refnum value that is identifying that refnum is not valid anymore.

 

What probably happens is that you run this AE discreetly to test its function. Once you run it with the Init method, then again with the Read method. But if you do that the AE is its own top level VI and as soon as it stops executing its Init execution it goes idle and the refnum is collected. Then you run it with the Read method but the refnum stored in the shift register is not valid anymore. You need to create another top level VI in which you first execute the Init method and then the Read method.

 

That all said I agree with crossrulz, use of Action Engines, or Intelligent Globals with DAQmx tasks is not the best way to deal with these things. It doesn't scale at all if you need multiple tasks and is in the end simply a glorified global with all its pitfalls and drawbacks.

 

I was a big proponent of Action Engines in the past (>20 years ago) but have come to consider them as a design anti-pattern since, except for quick and dirty test applications.

 

And yes, use of this in a DQMH architecture is very likely to run into the same problems if you are not VERY VERY careful. The different message handlers run all as their own top level VI with their own VI hierarchy and all have their own lifetime and as soon as a message handler that created a DAQmx task, or any other LabVIEW refnum (that includes all dark green and purple wires), goes idle, that refnum is closed no matter in how many other message handlers you try to use it. Don't pass refnums across VI hierarchies ever unless you are REALLY VERY careful about the lifetime of the hierarchy in which it was created. And I can guarantee you that while you may be VERY careful now, in three months from now, when your boss comes to you to ask you to add this trivial new feature, you will have forgotten about this requirement and then find out that this quick addition turns into a major refactoring of your application due to this global resource sharing ugliness.

Rolf Kalbermatter
My Blog
0 Kudos
Message 5 of 13
(724 Views)

@rolfk wrote:

@crossrulz wrote:

Please attach your actual code and the example you are trying to use this Action Engine with. There are way to many variables that we cannot see here with an image.

 

Some possibilities:

1. You did not properly wire up the output tunnel from the case structure in one of the cases.

2. You are not keeping the AE in memory through a single run instance. If the AE does not stay in a run state, the data could be cleared out.

3. The AE is reentrant, which will not allow the singleton pattern you need for an AE.


4) The AE initialization is executed in a different Top Level VI Hierarchy than the function to work on the DAQmx Task. DAQmx Tasks are also LabVIEW refnums, just with a user readable name attached. All LabVIEW refnums have a controlled lifetime that depends on the Top Level VI in whose hierarchy the refnum was created. Once that VI goes idle, the refnums are closed and the hidden Magic Cookie in the refnum value that is identifying that refnum is not valid anymore.

 

What probably happens is that you run this AE discreetly to test its function. Once you run it with the Init method, then again with the Read method. But if you do that the AE is its own top level VI and as soon as it stops executing its Init execution it goes idle and the refnum is collected. Then you run it with the Read method but the refnum stored in the shift register is not valid anymore. You need to create another top level VI in which you first execute the Init method and then the Read method.

 

That all said I agree with crossrulz, use of Action Engines, or Intelligent Globals with DAQmx tasks is not the best way to deal with these things. It doesn't scale at all if you need multiple tasks and is in the end simply a glorified global with all its pitfalls and drawbacks.

 

I was a big proponent of Action Engines in the past (>20 years ago) but have come to consider them as a design anti-pattern since, except for quick and dirty test applications.

 

And yes, use of this in a DQMH architecture is very likely to run into the same problems if you are not VERY VERY careful. The different message handlers run all as their own top level VI with their own VI hierarchy and all have their own lifetime and as soon as a message handler that created a DAQmx task, or any other LabVIEW refnum (that includes all dark green and purple wires), goes idle, that refnum is closed no matter in how many other message handlers you try to use it. Don't pass refnums across VI hierarchies ever unless you are REALLY VERY careful about the lifetime of the hierarchy in which it was created. And I can guarantee you that while you may be VERY careful now, in three months from now, when your boss comes to you to ask you to add this trivial new feature, you will have forgotten about this requirement and then find out that this quick addition turns into a major refactoring of your application due to this global resource sharing ugliness.


Hi Rolf, thank you for your insights. I was basing it off this Nugget article, which admittedly, is almost ten years old. I'm wondering if there's a way to use the AE as a way to encapsulate and perform different functions on the same task without making the leap to OOP.

0 Kudos
Message 6 of 13
(696 Views)

@nikvl wrote:


Hi Rolf, thank you for your insights. I was basing it off this Nugget article, which admittedly, is almost ten years old. I'm wondering if there's a way to use the AE as a way to encapsulate and perform different functions on the same task without making the leap to OOP.


Of course you can, almost nothing is impossible. But that doesn't necessarily mean that you should. Action Engines and LabVIEW refnums are not inherently incompatible with each other, they just don't work together in the way you tried to test it.

 

Action Engines can be very powerful when designed properly but they have one huge disadvantage: they are not instantiable. By the very nature of an Action Engine they only work as a single global instance of itself.

 

So your beautifully designed super Action Engine works perfect and then your boss or customer comes with the very common request to want to use 10 of the resources that your Action Engine manages instead of one. You can't clone the Action Engine as it can not be clonable to work properly.

 

So you can either redesign the Action Engine to manage those 10 resources together, but that tends to get very complicated and cumbersome very fast, or you copy the Action Engine 10 times to different names and create another kind of monster, since you now will sooner or later drop Action Engine for Resource 5 on your diagram when really wanting to execute a method on Resource 8. And when you find a bug in your Action Engine you have now 10 copies that you may never forget to apply that bug fix on. Terrible design choice!!

 

If you can't with absolute certainty exclude the possibility that you will need to manage at some point two or more instances of that resource in an application, your choice for an Action Engine will with pretty strong certainty end up being a liability later on.

Rolf Kalbermatter
My Blog
0 Kudos
Message 7 of 13
(490 Views)

I am probably "Someone else "


@nikvl wrote:

Hi all,

I'm trying out FGVs and decided to create a simple one to see if it works. Naturally, it didn't and hence I'm here. 

 

The Enum ring contains "Init", "Read" and "Close". I keep getting the Error -200088 and after probing the wires, it seems that the task isn't being sent through the shift register to the DAQmx Read. 

 

1) Is this a characteristic of DAQ that it doesn't work in a FGV?

2) I tinkered with the idea of using the FGVs within a DQMH architecture and was using the API Tester to trigger the "Init" and "Read" of the FGV. Would the architecture affect the FGV? (The FGV is a simple vi built outside of the module but i call it by placing it in the MHL after a request is made)

3) Someone else on the forum wrote that there was a workaround (without giving details) regarding DAQ Tasks in a FGV, but what is best practice?

 

nikvl_0-1745494409050.png

Thank you in advance.


Rolf already mentioned that the CONTEXT is important.   So, I have to ask you where is the Task saved?  Is it in MAX?  is it in a lvproj? Is it only on that shift register?  

 

Almost every time I used a DAQmx resource I created what I called a "Resource Module" very similar to the Action Engine you show. (I would never use a Read, default method, stop that! it's like picking your nose in public)  yet, you need to be aware of the application context or else you wind up calling your code with a bad Task Resource. 

 

For example,  if your Task is saved as part of a lvproj and your AE is called as a TestStand Step you MUST configure that Step to call through the project to find the DAQmx definition.   

 

Basically,  you are going the right way but haven't given us enough information to tell you which Rock you tripped over.


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

@JÞB wrote:

I am probably "Someone else "


@nikvl wrote:

Hi all,

I'm trying out FGVs and decided to create a simple one to see if it works. Naturally, it didn't and hence I'm here. 

 

The Enum ring contains "Init", "Read" and "Close". I keep getting the Error -200088 and after probing the wires, it seems that the task isn't being sent through the shift register to the DAQmx Read. 

 

1) Is this a characteristic of DAQ that it doesn't work in a FGV?

2) I tinkered with the idea of using the FGVs within a DQMH architecture and was using the API Tester to trigger the "Init" and "Read" of the FGV. Would the architecture affect the FGV? (The FGV is a simple vi built outside of the module but i call it by placing it in the MHL after a request is made)

3) Someone else on the forum wrote that there was a workaround (without giving details) regarding DAQ Tasks in a FGV, but what is best practice?

 

nikvl_0-1745494409050.png

Thank you in advance.


Rolf already mentioned that the CONTEXT is important.   So, I have to ask you where is the Task saved?  Is it in MAX?  is it in a lvproj? Is it only on that shift register?  

 

Almost every time I used a DAQmx resource I created what I called a "Resource Module" very similar to the Action Engine you show. (I would never use a Read, default method, stop that! it's like picking your nose in public)  yet, you need to be aware of the application context or else you wind up calling your code with a bad Task Resource. 

 

For example,  if your Task is saved as part of a lvproj and your AE is called as a TestStand Step you MUST configure that Step to call through the project to find the DAQmx definition.   

 

Basically,  you are going the right way but haven't given us enough information to tell you which Rock you tripped over.


It's only on the shift register, and for now it's only from a simulated hardware created in MAX. Yes, the "Read, Default" was silly and I have since corrected it.

I found out the cause of the original problem and it's now working as expected. Though I did ask some follow-up questions to see if I should abandon AE structure altogether if it involves task resources. So to be honest, it's not (yet) a huge rock that I've tripped over because I have barely started and was trying to investigate ways to prevent from that happening and figure out the best way from here on out. 

 

Following the comments, I would probably not use AE for data acquisition but it might still be useful for DIO functions. For example, I'd have 14 valves (fixed number hence fixed number of resources) and trying to figure out the state each individual state at any given time is going to be a challenge so I was wondering if it might be easier to manage that in an AE.

0 Kudos
Message 9 of 13
(428 Views)

@nikvl wrote:

Following the comments, I would probably not use AE for data acquisition but it might still be useful for DIO functions. For example, I'd have 14 valves (fixed number hence fixed number of resources) and trying to figure out the state each individual state at any given time is going to be a challenge so I was wondering if it might be easier to manage that in an AE.


With time and experience you will find out that if someone tells you that there is a fixed number of resources to be handled, that is only a valid statement for that moment. Tomorrow they may decide that they need to have a 15th valve because they can't control the process properly otherwise!

Rolf Kalbermatter
My Blog
0 Kudos
Message 10 of 13
(409 Views)