LabVIEW

cancel
Showing results for 
Search instead for 
Did you mean: 

Help me speed up my program

Solved!
Go to solution

Hi everyone,

 

I have a fairly simple program and I would like to improve it's performance, if possible.

 

Basically, my program sends three digital pulses to a digital I/O card (which at this stage are just LEDs) that are each preceeded by three seperate time delays. ie. delay1, pulse1, delay2, pulse2, delay3, pulse3. The delays should be customisable and I would like them to be accurate to 1ms. I will be using delays between 5ms to 5s. Also, the order of the pulses needs to be adjustable as well. For example I may want to send pulse2 before pule1.

 

The program that I have written already does all of this except now with the precision that I require. For example, if i set all of my delays to 100ms I tend to measure delays between 90ms and 110ms. If I set my delays to 50ms I tend to meaure delays between 47ms and 63ms.

 

I am hoping somebody could look at my code and see if there is a more efficient way to write my code, in order to make my timings more precise.

 

To run my program just open 'REFCT Testing program v2' and click 'initiate fault' and you will be able to see that 'actual' delays vs the input delays.

 

Perhaps the solution is to use hardware timing via a counter, though my preliminary testing showed that using the 'wait(ms)' function gives better results.

 

0 Kudos
Message 1 of 17
(3,765 Views)

What kind of hardware are you using? Maybe you should try to implement hardware timing instead.

 

You really need to do a few tutorial and get rid of all these unecessary local variables. For example, th subVI would work identically if you would change is as the attached VI. Also the toplevel VI could use significant changes. The code is just way too chopped up. Your LED terminals are not even connected to anything! That is serious misuse of locals. Way too much duplicate code!

Message 2 of 17
(3,747 Views)

Marc has been told about those local variable abuse before, but he refuses to change his behaviour.

Even worse: the "Running" case of his "testing" VI uses even more local variables hidden in a stacked sequence structure…

 

THINK DATAFLOW!

Use wires instead of local variables!

Best regards,
GerdW


using LV2016/2019/2021 on Win10/11+cRIO, TestStand2016/2019
Message 3 of 17
(3,727 Views)

@altenbach wrote:

What kind of hardware are you using? Maybe you should try to implement hardware timing instead.

 


 

Exactly.  From here it looks like the original poster has a 9174 chassis--I would do something like this using the counters (you'll need to add a digital I/O module such as a 9401):

 

 

CounterOutputSyncExample.png

 

 

It will give you 12.5 ns delay resolution with 50 ppm accuracy--you will never achieve close to these numbers with software timing no matter how optimized your code is (consider the non-determinism of the bus transfers alone...).

 

 

Best Regards,

John Passiak
Message 4 of 17
(3,679 Views)

Thank you everybody for the feedback.

 

altenbach: Your code made me realise that the way I wrote my code was quite retarded. I have rewritten my code using your code as a basis. I have now eliminated all local variables (thank you gerdW) at least in the 'running' state of my case structure. I have attached my new program, which I am quite happy with. It seems to perform the delays to an accuracy of 1ms, which is what I'm after.

 

I suspect that when i start writing to physical outputs (as opposed to switching some LEDs which is what I'm currently doing) the DAQmx functions will slow down my code as well as the transfers to the digital IO card (I have a NI-9401). I will try to implement John Passiak's code, but at this stage I'm struggling to understand it. I cannot actually get it to run either. I'm getting this error:

 

Error -50103 occurred at DAQmx Start Task.vi:1

 

Possible reason(s):

NI Platform Services:  The specified resource is reserved. The operation could not be completed as specified.

Task Name: _unnamedTask<AF>

 

 

John I have a few questions for you:

 

- Why use three seperate physical counters instead of one?

- When do the three counters end counting? I'm assumming this affects the 'DAQmx is task done.vi' function.

- I don't understand why you need a trigger counter? What is it doing and how long does it run for?

- What would be the best way to measure the delays to see if they are consistent with the specified values?

- What is the point of the 50ms delays in the while loop?

 

Again, I really appreciate everyones help.

0 Kudos
Message 5 of 17
(3,623 Views)

Why use three seperate physical counters instead of one?

You will be driving 3 different digital outputs, no?  One counter can't simultaneously generate 3 unique pulses on different output lines.

 

When do the three counters end counting? I'm assumming this affects the 'DAQmx is task done.vi' function.

"DAQmx is Task Done?" will return TRUE when the counter has finished generating its pulse (essentially the sum of the delay and pulse width specified).

 

I don't understand why you need a trigger counter? What is it doing and how long does it run for?

It generates a single pulse that starts the other 3 counters at the same time t=0.  This allows all 3 of your counters which are actually outputting pulses to start relative to the same initial time.  If you're pressed for counters you can get by with 3 by referencing the initial delays to the output of the first counter and using that counter's internal output as the start trigger, but since you mentioned that the order might change I figured it was easier to just do it this way.  You could alternatively provide an external TTL signal as a start trigger.

 

It runs for a very brief period of time (100 ns pulse duration).  The act of starting/waiting/stopping/clearing will take several ms in software though, but it's irrelevant to the timing of any of the output pulses.

 

What would be the best way to measure the delays to see if they are consistent with the specified values?

If you're concerned you could scope it.

 

What is the point of the 50ms delays in the while loop?

The loop is just polling for each of the 3 tasks to check if they are finished--this prevents the loop from consuming unnecessary CPU (50 ms seems like a reasonable polling interval to me, you can change it if you really want to--it has no impact on the signals that are generated).  If you don't like polling you can use DAQmx Events to tell you when your output has completed--I didn't include them to spare myself the trouble of having to explain it.

 

 

Best Regards,

John Passiak
0 Kudos
Message 6 of 17
(3,579 Views)

@DarkMarc86 wrote:

 

I'm getting this error:

 

Error -50103 occurred at DAQmx Start Task.vi:1

 

Possible reason(s):

NI Platform Services:  The specified resource is reserved. The operation could not be completed as specified.

Task Name: _unnamedTask<AF>


 

Are you specifying 4 different counters?

 

 

Best Regards,

John Passiak
0 Kudos
Message 7 of 17
(3,572 Views)

Hi John,

 

So assuming I can get your program to run, would I then add a 'DAQmx write.vi' function right after the 'DAQmx is task done.vi' function (within the for loop inside the large while loop) so that I can send the three 5V output signals through my NI-9401?

 

Yes, I think I am using four different counters. Though I am confused as to why Labview thinks my system has at least 8 counters. The datasheet says the NI-9174 has four counters. My counter selection list has 'cDAQ1Mod1/ctr0:3' and 'cDAQ1/_ctr0:3'.

 

EDIT: Just had a few more goes at running your program. I can get it to run if i remove the three element 'counter' array and replace it with a single counter, but it doesn't seem to like multiple counters (tried two as well). It keeps telling me that a resource is reserved and to try 'DAQmx control task' to reserve all taks that use this device.

0 Kudos
Message 8 of 17
(3,559 Views)

Oh, the 9401 is a little peculiar.  Try reserving your tasks first:

 

CounterOutputSyncExample2.png

 

You don't need to call DAQmx Write--the pulses should be present on the default output terminals (check MAX device pinouts for the defaults) or you can use a DAQmx channel property to explicitly set the output terminal to some other PFI line.

 

 

Best Regards,

John Passiak
0 Kudos
Message 9 of 17
(3,522 Views)

Thanks you very much John!

 

The only other thing that I'm unsure about is that when the counter starts (after the delays) will it output a square wave or will it output a constant 'high' signal? I need the output to be 'low', and when the user hits 'start', after the delay, the output should change to 'high' and remain 'high' untill the user hits the stop button.

control program description.PNG

0 Kudos
Message 10 of 17
(3,508 Views)