12-07-2024 10:53 AM
Hi all. I am a controls engineer with PLC experience dabbling in LabVIEW for the first time. The program for my current project is relatively straight forward and consists of only digital IO (including two counter inputs and two counter outputs). All analog signals will be sent/received by interfacing with a benchtop power supply (this and the counter IO is the main reason for using LabVIEW/DAQ over a traditional PLC).
Anyway, I am struggling to understand everything that's required to properly configure the IO. I have had success creating project tasks and wiring them directly to the Start Task VI outside my main processing loop, then using Read/Write inside the loop, and stopping/clearing the tasks outside the loop. This seems to work, although I'm not sure if I'm missing any steps or if it is the most efficient (the program seemed to lag slightly more for each IO point I added).
A few specific questions I have:
1. Where do the Timing/Triggering VIs come into play? Do I need to use these with the counter IO or even all IO?
2. What is the best option between using Create Virtual Channel, DAQ Assistant, or directly wiring a program task constant to the Start Task VI? DAQ Assistant seems to do a lot of the thinking/configuring for me, but I'm not sure if this will cause significantly more lag compared to the other options.
3. Do I need to connect the task wires to shift registers in the main while loop? I noticed many of the examples don't do this.
Obviously, I am a LabVIEW beginner and lack a technical understanding of how the DAQmx tasks work, so please keep that in mind in your answer. Please do not tell me to study more of the fundamentals before proceeding. This is a one-off LabVIEW project that I need to get working ASAP, so I am more interested in building a functional program than developing my LabVIEW skills. Also, you shouldn't need to see my program to answer these questions, so I'm not going to attach any VIs.
Thanks!
12-07-2024 01:32 PM
Since you provided no VI's (and no clear description of your timing tasks, including how many channels are being activated (I assume two), what makes them "turn on" and "turn off", what the relative timing is, etc., it is difficult to know what to suggest.
I'm not certain why you are using a counter. In general, when you want to turn a digital "something" on, you use a Digital-to-Analog control and set its input to True, and to turn it off, set the input to False.
Bob Schor
12-07-2024 02:19 PM - edited 12-07-2024 02:20 PM
1. One of the counter channels is for producing pulses to control a stepper motor. Another is reading pulses from that same stepper motor (the counter output on the DAQ controlling the stepper motor is hard wired to this counter input).
2. The other counter IOs are for controlling and monitoring a DC motor that is being quality tested. One is an output producing a PWM output for the motor speed control. The other is an input reading a tach signal from the test motor.
If it's not clear, the stepper motor in (1) is completely separate from the DC motor in (2).
And for the strictly digital IO, can I just put these all on the same task (or two, one for inputs and one for outputs), or do they all need to be separate? All the digital IO needs to function like they would in a PLC program, which shouldn't be too hard given they are inside a while loop.
12-08-2024 09:49 AM - edited 12-08-2024 09:53 AM
For the specific things you're doing, I'll confirm that 4 separate counter tasks are the right choice. It may also be a good idea to operate your 2 stepper motor tasks in a separate loop from the loop for your 2 DC motor tasks.
1. The Timing and Triggering VIs come into play when you want hardware-level precise control over sample timing and the start time of a task. Timing config is typically (but not always) important, Triggering is more dependent on specific app needs.
2. The DAQ Assistant will let you do simple things easily but will also entirely prevent you from being able to accomplish certain more complex things. Particularly when you want to coordinate multiple tasks. My advice is to stay away from the DAQ Assistant -- it's fool's gold.
I have habitually created tasks in code starting with "Create Virtual Channel". It gives you a lot of flexibility and the learning curve is merely medium for most things. A good starting reference is to look at code from shipping examples (Menu: Help->Find Examples->Hardware I/O->DAQmx)
You *might* be able to accomplish all you need by defining tasks at the project level and then wiring them to DAQmx Start. I can't speak to the details, but there's at least one trustworthy expert around these parts that often advocates this approach.
3. You generally don't need send task wires through shift wires in a While loop, regular tunnels are just fine. The task wire is analagous to an "alias" to the underlying task. Branches and copies of the task wire still keep referring to the one and only original task. And changes in task status have no effect on the "alias". So it's fine that the value wired into a tunnel keeps being used to reference the task as the loop goes through many iterations and the task may change its operating state (such as error out or finish).
Some make a habit of using shift registers because it *can* be important for a certain degenerate For Loop situation that calls for 0 iterations. That can never happen with While loops so it isn't necessary there, but some just maintain the habit anyway because it also doesn't *hurt*.
-Kevin P
12-08-2024 11:24 AM
Thanks for the detailed reply! A couple follow up questions.
Why do you suggest putting the stepper counter tasks in a separate loop? I could do this, but it may be an annoying change with my current architecture.
Also, the "Create Virtual Channel" VI seemed like the most flexible to me too, but when creating a counter task for this VI asks for parameters (such as freq and duty cycle in pulse generation), and then the read block again asks for these values. It seems redundant and potentially problematic to write these values twice.
And lastly, would you suggest grouping all the normal digital IO in their own tasks (DI in one and DO in another)?
12-09-2024 08:54 AM
Why do you suggest putting the stepper counter tasks in a separate loop? I could do this, but it may be an annoying change with my current architecture.
I've found that it's usually very useful to work with hardware devices this way -- an independent loop per device. (See later note as an exception). This makes the code dealing with each device more independent, particularly in terms of timing or state logic. If you need to to something time consuming with one of your motors, it will naturally not affect the other loop where you deal with the other motor.
Also, the "Create Virtual Channel" VI seemed like the most flexible to me too, but when creating a counter task for this VI asks for parameters (such as freq and duty cycle in pulse generation), and then the read block again asks for these values. It seems redundant and potentially problematic to write these values twice.
Check out the shipping examples (Help->Find Examples...). You'll see that when you define freq / duty cycle at "Create Virutal Channel", it isn't necessary to later call DAQmx Write to set them again. But most counters do *allow* you to write new freq / duty cycle params while the task is running and change the pulse train characteristics on the fly.
And lastly, would you suggest grouping all the normal digital IO in their own tasks (DI in one and DO in another)?
This can be a useful idea and will usually be *necessary* when using a hardware-based sample clock. When running in software-timed "on demand" mode, I sometimes make 1 task per individual I/O channel because it makes more logical sense in *some* kinds of code to keep them independent.
So now back to the exception about 1 loop per hardware device. It's not just about the *external* device, sometimes the internal DAQ device puts a additional constraint on you that requires, for example, *all* AI must be done with 1 task in 1 loop. Many DAQ devices only support 1 hardware-clocked task per I/O type, so all hardware-clocked I/O might need to be managed by a single loop.
-Kevin P
12-09-2024 12:55 PM
Kevin's handling your specific questions excellently, so allow me to throw out a couple more "general" suggestions.
First, this is a great article for learning when you need which function: https://www.ni.com/en/support/documentation/supplemental/06/learn-10-functions-in-ni-daqmx-and-handl...
Second, the DAQ Assistant is generally to be avoided. It's not bad for very quick and dirty prototyping, but it's very limited compared to what the hardware can do. That said... it's a very good place to learn HOW to use the underlying functions. If you create a DAQ Assistant task, you can right click on it and say "Convert to SubVI" and it'll change it to a regular function. Open it up and you'll see the code it generated, which will be a good starting place for whatever it is you're trying to do. It's not perfect, but it's better than nothing and it might help demystify your question of "When do I use Create Virtual Channel vs DAQ Assistant?". The short answer is that the DAQ Assistant uses Create Virtual Channel internally, and it just sort of guesses at the rest of your configuration.
Last, a note on when to use timing- generally speaking, if you need very strict IO timing (aka Hardware Timing), you'll need to use the timing VI's to configure things. If you just need to read an IO once a second or so, then software timed is fine, and you can just call DAQmx Read.
12-10-2024 05:56 PM
I still don't get it. I don't see how I add multiple IO ports to a task and then wire them to a write block individually. There's just no way. And none of the examples help because I open it and it has 100 SubVIs that I've never even seen before. Do the Labview developers understand the concept of encapsulation?
Today I just go ahead and create a task for each separate IO (around 20 for the whole project) since that's the only thing that works, and of course the program runs unbelievably slow. Like 5 seconds per iteration with a 10ms time delay slow. This is ridiculous. It's absolute rocket science to work with IO in these controllers. I don't know what to do...
12-10-2024 06:23 PM
I have no idea what I'm doing with the DAQ IO mapping. None of the examples or resources I've found help. One aspect of my project needs to function like a PLC program, monitoring and controlling several digital signals during the main control loop. Tried creating a task for each one but the program runs way, way to slow and doesn't even function in some respects. I don't see how to put all these on one task and then individually reference them with the DAQmx write VI (as the write VI only takes a task input). I tried using an array as the input data and it didn't work.
What am I doing wrong. Someone please explain it to me like I'm 5 because I need to get this working.
12-10-2024 08:10 PM
You failed to mention your hardware and only speak in gross generalizations such as "using an array and it did not work". You need to be significantly more specific.