Chief Delphi

Chief Delphi (http://www.chiefdelphi.com/forums/index.php)
-   NI LabVIEW (http://www.chiefdelphi.com/forums/forumdisplay.php?f=182)
-   -   100% CPU Utilization Using 10ms Periodic Task (http://www.chiefdelphi.com/forums/showthread.php?t=126306)

Phalanx 12-02-2014 11:32

100% CPU Utilization Using 10ms Periodic Task
 
Here's what I'm doing. In the 10ms loop in Periodic Tasks I have the following:

2 separate GET digital I/O VI's
Each output I perform a Boolean NOT
Each output is stored in a Boolean global variable.
The RefnumGet VI's are outside the loop.

When this code is added, my CRIO cpu spikes to 100%.
When I remove this code my CRIO CPU is at 50%.

I'm rather puzzled/stumped that this little bit of code causes that much pain.
Any ideas?

Alan Anderson 12-02-2014 11:49

Re: 100% CPU Utilization Using 10ms Periodic Task
 
Check the diagnostics window on the Driver Station for any error messages. If you have a broken RefNum or something similar, the error processing has a significant effect on the CPU.

gpetilli 12-02-2014 12:03

Re: 100% CPU Utilization Using 10ms Periodic Task
 
We observed similar symptoms. We tried a 10ms PID timed loop which read some I2C sensors and wrote to the PWM outputs and we measured periods of 11ms to 16ms. We have changed our scheduler to do 15ms since this appears to be the limit of either the cRIO or the scheduler. Do you really need 10ms?

Phalanx 12-02-2014 12:05

Re: 100% CPU Utilization Using 10ms Periodic Task
 
Alan,

I don't get any error messages other than RobotDrive isn't running fast enough when that code is enabled. Without that code enabled, I receive no error messages at all. Hence, my puzzlement.


Quote:

Originally Posted by gpetilli (Post 1341803)
We observed similar symptoms. We tried a PID timed loop which read some I2C sensors and wrote to the PWM outputs and we measured periods of 11ms to 16ms. We have changed our scheduler to do 15ms since this appears to be the limit of either the cRIO or the scheduler. Do you really need 10ms?

I don't NEED 10ms. I prefer something faster than Teleop for what I have in mind.
In a worst case scenario I work something else out.

gpetilli 12-02-2014 12:27

Re: 100% CPU Utilization Using 10ms Periodic Task
 
Quote:

Originally Posted by Phalanx (Post 1341804)
Alan,

I don't get any error messages other than RobotDrive isn't running fast enough when that code is enabled. Without that code enabled, I receive no error messages at all. Hence, my puzzlement.




I don't NEED 10ms. I prefer something faster than Teleop for what I have in mind.
In a worst case scenario I work something else out.

We were less concerned with 10ms than the consistency of the period, although faster is certainly easier to stabilize. The teleop period is nominally 20ms but it is determined by the drivers station across WiFi and has considerable variability.
What else are you considering for your worst case scenario? Keep in mind that all actuator controls must come directly from the cRIO - safety feature so that the field can shut it down.

Phalanx 12-02-2014 12:45

Re: 100% CPU Utilization Using 10ms Periodic Task
 
We've got a winch and pulley that pulls down our spring loaded launcher, and there's a limit switch to let us know when it's fully tensioned so we can turn off the motor and lock it in place.

The winch is really fast, it takes less than 1 second to reload. So I wanted something really fast to make sure we turn off the motor quickly to avoid breaking anything.

In a worst case scenario, I can slow it down and monitor it all in Teleop. I just didn't want to do that. The global variables are later sent in Teleop to the dashboard via network tables as indicators of it's readiness, although we may move that code to the 100ms loop.

Mark McLeod 12-02-2014 13:05

Re: 100% CPU Utilization Using 10ms Periodic Task
 
I dropped what you described into a (almost) default project and didn't see the major jump in CPU utilization that you got.
Sounds like other code cross influences may be at work.

If you want a second set of eyes on your code we can do that.

Joe Ross 12-02-2014 13:09

Re: 100% CPU Utilization Using 10ms Periodic Task
 
Quote:

Originally Posted by gpetilli (Post 1341803)
We observed similar symptoms. We tried a 10ms PID timed loop which read some I2C sensors and wrote to the PWM outputs and we measured periods of 11ms to 16ms. We have changed our scheduler to do 15ms since this appears to be the limit of either the cRIO or the scheduler. Do you really need 10ms?

I would expect that I2C could be less efficient then DIO. You were also doing your test in java and with lots of additional calculations, right?

Alan Anderson 12-02-2014 13:12

Re: 100% CPU Utilization Using 10ms Periodic Task
 
Quote:

Originally Posted by Phalanx (Post 1341804)
I don't get any error messages other than RobotDrive isn't running fast enough when that code is enabled. Without that code enabled, I receive no error messages at all. Hence, my puzzlement.

What you're doing shouldn't give you what you're getting. Something else is going on here. To start with, can you show us the loop that pegs the CPU?

gpetilli 12-02-2014 13:14

Re: 100% CPU Utilization Using 10ms Periodic Task
 
Quote:

Originally Posted by Phalanx (Post 1341824)
We've got a winch and pulley that pulls down our spring loaded launcher, and there's a limit switch to let us know when it's fully tensioned so we can turn off the motor and lock it in place.

The winch is really fast, it takes less than 1 second to reload. So I wanted something really fast to make sure we turn off the motor quickly to avoid breaking anything.

In a worst case scenario, I can slow it down and monitor it all in Teleop. I just didn't want to do that. The global variables are later sent in Teleop to the dashboard via network tables as indicators of it's readiness, although we may move that code to the 100ms loop.

For a similar function on our bot, I am strongly recommending using a Jaguar and hooking the limit switch directly to the limit switch inputs on the Jaguar. This has the added advantage that if the winch moves during a collision, the Jaguar will retention. I also feel safer if high force mechanisms are directly controlled by hardware. If software also needs to see the limit switch, you could poll it via CAN bus.

Alan Anderson 12-02-2014 13:24

Re: 100% CPU Utilization Using 10ms Periodic Task
 
Quote:

Originally Posted by Phalanx (Post 1341824)
We've got a winch and pulley that pulls down our spring loaded launcher, and there's a limit switch to let us know when it's fully tensioned so we can turn off the motor and lock it in place.

It is possible to set up the switch to trigger an interrupt. However, I wouldn't try that until every other option is exhausted. Normally one wouldn't want to do actual motor control in an interrupt service routine.

gpetilli 12-02-2014 13:30

Re: 100% CPU Utilization Using 10ms Periodic Task
 
Quote:

Originally Posted by Joe Ross (Post 1341836)
I would expect that I2C could be less efficient then DIO. You were also doing your test in java and with lots of additional calculations, right?

Understood that DIO is much faster and yes we are using Java. Rough calculations show ~1ms to read the sensors, so that is significant, but should not be a show stopper.
Lots of calculations is a relative term, we are doing the heavy lifting (atan) in the teleop routine and as little as possible in the PID routine. If I were coding it, it could be even faster, but we try to stay within the capabilities of the students. 15ms should be fine for a drive train PID (WPI uses 50ms). Most of our sensors have programmable on chip filtering which we set to <50Hz bandwidth to minimize aliasing.

chris.boyle 12-02-2014 14:29

Re: 100% CPU Utilization Using 10ms Periodic Task
 
Quote:

Originally Posted by Alan Anderson (Post 1341787)
Check the diagnostics window on the Driver Station for any error messages. If you have a broken RefNum or something similar, the error processing has a significant effect on the CPU.

Replace the tunnels into the loop with Shift Registers. This will help if there are any errors found during any loop. Without them, the code has to find the errors every loop.

Phalanx 12-02-2014 16:10

Re: 100% CPU Utilization Using 10ms Periodic Task
 
Quote:

Originally Posted by Mark McLeod (Post 1341834)
I dropped what you described into a (almost) default project and didn't see the major jump in CPU utilization that you got.
Sounds like other code cross influences may be at work.

I'm beginning to think that as well. Finding it will be the challenge.

Quote:

Originally Posted by Alan Anderson (Post 1341843)
It is possible to set up the switch to trigger an interrupt. However, I wouldn't try that until every other option is exhausted. Normally one wouldn't want to do actual motor control in an interrupt service routine.

Exactly. I definitely don't want to be doing much in an ISR. ISR's need short and sweet. Learned that lesson a long long time ago.

Quote:

Originally Posted by Alan Anderson (Post 1341843)
What you're doing shouldn't give you what you're getting. Something else is going on here. To start with, can you show us the loop that pegs the CPU?

I agree, which is why I'm so puzzled by this. I'll post loop later when I have access to it. It's really simple and straight forward, but another pair of eyes never hurts. It's got to be something else, something I'm not seeing, something I'm missing.

Quote:

Originally Posted by chris.boyle (Post 1341843)
Replace the tunnels into the loop with Shift Registers. This will help if there are any errors found during any loop. Without them, the code has to find the errors every loop.

Interesting idea, not something I want to resort to. I'd much rather isolate, identify and fix it.

Thanks everyone for your input and advice. Time to delve deeper, cross "T's" dot "I's" and make sure there isn't something stupid, which there probably is.

Phalanx 13-02-2014 00:06

Re: 100% CPU Utilization Using 10ms Periodic Task
 
I found the problem. One of the GetRefNum's had an incorrect name. The name in Begin.VI was "Ball Collector Limit Switch" and in PeriodicTasks.VI it was "Ball Limit Switch". I corrected that issue and now CPU is back to normal levels.

So as I'm fond of saying.... "Programmers don't need to spell correctly, just consistently!!!"

Thanks for your insights, help and input.

Alan Anderson 13-02-2014 00:37

Re: 100% CPU Utilization Using 10ms Periodic Task
 
Congratulations on finding and fixing the problem.

In normal usage, an incorrect RefNum name should have given you an error message on the Driver Station. Did you do something with the error output on the RefNum Get function that would have caused the system to think you were checking and handling the error yourself?

Chris Hibner 13-02-2014 06:16

Re: 100% CPU Utilization Using 10ms Periodic Task
 
Quote:

Originally Posted by Phalanx (Post 1342215)
I found the problem. One of the GetRefNum's had an incorrect name. The name in Begin.VI was "Ball Collector Limit Switch" and in PeriodicTasks.VI it was "Ball Limit Switch". I corrected that issue and now CPU is back to normal levels.

So as I'm fond of saying.... "Programmers don't need to spell correctly, just consistently!!!"

Thanks for your insights, help and input.

I have a rule with our software students: if I catch you typing a refnum name in any VI other than Begin.vi, you get the mother superior whack on the knuckles with a ruler. Copy/Paste ONLY!!!!

Greg McKaskle 13-02-2014 07:04

Re: 100% CPU Utilization Using 10ms Periodic Task
 
I'm also curious if it is clear why the error message wasn't making its way to the DS.

Greg McKaskle

Alan Anderson 13-02-2014 08:30

Re: 100% CPU Utilization Using 10ms Periodic Task
 
Quote:

Originally Posted by Chris Hibner (Post 1342268)
I have a rule with our software students: if I catch you typing a refnum name in any VI other than Begin.vi, you get the mother superior whack on the knuckles with a ruler. Copy/Paste ONLY!!!!

We're going one better than that this year. The names only appear in one place in the code.

Chris Hibner 13-02-2014 09:35

Re: 100% CPU Utilization Using 10ms Periodic Task
 
Quote:

Originally Posted by Alan Anderson (Post 1342298)
We're going one better than that this year. The names only appear in one place in the code.

Global variables? Please share how you're doing it.

chris.boyle 13-02-2014 09:37

Re: 100% CPU Utilization Using 10ms Periodic Task
 
1 Attachment(s)
Quote:

Originally Posted by Alan Anderson (Post 1342298)
We're going one better than that this year. The names only appear in one place in the code.

We have the same philosophy about keeping the names in only one place.

This is how we are avoiding refnum errors. Requires more work up front, but should never have an 'invalid' refnum problem. Just make sure you pick the correct one. :)

Timing is not an issue, as they are only called once at start up and the refnum values are stored in the shift registers for the duration. In addition, we only allow access to a particular device in one loop. It is not allowed to have multiple loops trying to access the same refnum.

Alan Anderson 13-02-2014 11:35

Re: 100% CPU Utilization Using 10ms Periodic Task
 
We have our code separated into drivebase and "other" sections. The Drivebase vi is a Case statement with cases for Begin, Teleop, Finish, and 10ms Periodic. The refnum name constants are outside the case and tunneled in.

We call the Drivebase vi from inside Begin, passing it the "Begin" selector. We also call it from within Teleop, Finish, and a 10ms loop in Periodic Tasks, passing the appropriate selector each time.

The "other" vi (name withheld to protect the mechanism) is similar, but also includes 5ms and 100ms cases.

I started out trying to use shift registers in a single-execution while loop to hold the refnum values, but Test mode requires everything to be in the RefNum Registry. Since I had to use Refnum Set anyway, I went with Refnum Get wherever resources are used. I might do some timing tests to see how the timing is affected by using shift registers instead.

Joe Ross 13-02-2014 11:42

Re: 100% CPU Utilization Using 10ms Periodic Task
 
Quote:

Originally Posted by chris.boyle (Post 1342343)
This is how we are avoiding refnum errors. Requires more work up front, but should never have an 'invalid' refnum problem. Just make sure you pick the correct one. :)

You can simplify this by using "Format Into String" on the enum.

Alan Anderson 13-02-2014 12:02

Re: 100% CPU Utilization Using 10ms Periodic Task
 
Quote:

Originally Posted by Joe Ross (Post 1342428)
You can simplify this by using "Format Into String" on the enum.

That's how we did it last year. It was a lot of upfront work to create all the typedefs, but it made the programming completely safe from simple typing errors. We wrote wrappers around all the RefNum Get functions so they could accept either strings or enums.

We also had bunch of special global cluster arrays defining everything necessary to open relays, digital inputs, counters, encoders, drivebase motor sets, individual motors, solenoids, analog inputs, etc. Begin and Finish ran through the arrays opening (and closing) everything, so once we had the basic code framework written we never needed to touch those VIs again.

Phalanx 13-02-2014 15:39

Re: 100% CPU Utilization Using 10ms Periodic Task
 
Quote:

Originally Posted by Alan Anderson (Post 1342227)
In normal usage, an incorrect RefNum name should have given you an error message on the Driver Station. Did you do something with the error output on the RefNum Get function that would have caused the system to think you were checking and handling the error yourself?

We didn't wire anything to the error out terminal. So we weren't masking it or handling it ourselves. I didn't see an error message at the time.

Quote:

Originally Posted by Greg McKaskle (Post 1342227)
I'm also curious if it is clear why the error message wasn't making its way to the DS.

Greg, I can't answer that other than to say, that the error message was probably missed and the DS log wasn't closely scrutinized. My programming team told me last night, that they did see an error message the next day.

I've got to do a better job teaching this stuff. This is for a team that had zero programmers at the start of build season. I'm not that dissatisfied with where they've gotten given the short time.

wt200999 13-02-2014 16:27

Re: 100% CPU Utilization Using 10ms Periodic Task
 
2 Attachment(s)
Quote:

Originally Posted by chris.boyle (Post 1342343)
This is how we are avoiding refnum errors. Requires more work up front, but should never have an 'invalid' refnum problem. Just make sure you pick the correct one. :)

Do you inline this SubVI?

If my understanding of the LabVIEW compiler/optimizer is correct, if you were to inline that VI, every instance of that VI would be copied down into the code and the controls would all be optimized out. The case structure would also be optimized out leaving the 'normal' method for accessing resources. This would give you the less CPU usage overhead compared to format into string or a subVI call, while supporting the normal methodology used by the WPI Library.

Greg McKaskle 13-02-2014 19:47

Re: 100% CPU Utilization Using 10ms Periodic Task
 
I was asking just to see if there was a bug or something that could be improved for the future.

One such thing is to make the errors be on the front page instead of the second page. Other things can be done so that the errors or number of errors are more obvious. The other issue is that the current error routing is too slow and often causes watchdog issues. I believe that is fixed for next year along with a deploy issue that it can sometimes cause.

As for the string dictionary that was demonstrated. That is a great way of preventing inconsistent spelling. I'm not sure if it is necessary or good for all teams, but if you have the skills to make the subVI and update the typedef enum, it is a great solution. The overhead of the subVI should be quite small. Making it a subroutine would shrink that by quite a bit. Making it be inlined will, as pointed out, should make it disappear entirely as the compiler substitutes the code, then propagates constants, then removes unreachable code.

Greg McKaskle

chris.boyle 14-02-2014 14:52

Re: 100% CPU Utilization Using 10ms Periodic Task
 
We are not really concerned with the efficiency of the string dictionary as these are only called once at the entry of Begin, Periodic Tasks, Finish and Disabled if they are motors.

The references returned are stored in the Shift Register for the duration of the execution. With our rule of only a single Get Reference allowed, it has not been a problem with speed, just planning.

plnyyanks 14-02-2014 19:02

Re: 100% CPU Utilization Using 10ms Periodic Task
 
Quote:

Originally Posted by wt200999 (Post 1342662)
If my understanding of the LabVIEW compiler/optimizer is correct, if you were to inline that VI, every instance of that VI would be copied down into the code and the controls would all be optimized out.

Close. Making a sub-VI inline makes LabVIEW think that the code in that VI is actually on the block diagram's parent (and avoids the overhead of making a subVI call). So having an inline subVI is exactly equivalent to not having the subVI there at all (and its code just in the block diagram of its parent).

Quote:

A third way to minimize subVI overhead is to inline subVIs into their calling VIs. When you inline a subVI, LabVIEW inserts the compiled code of the subVI into the compiled code of the calling VI. If you then make changes to the subVI, LabVIEW recompiles all calling VIs of that subVI to include those changes. Essentially, inlining a subVI removes the need to call the subVI at run time. Instead, LabVIEW executes the subVI code inside the compiled code of the calling VI.

Inlining subVIs is most useful for small subVIs, subVIs within a loop, subVIs with unwired outputs, or subVIs you call only once. To inline a subVI, place a checkmark in the Inline subVI into calling VIs checkbox on the Execution page of the VI Properties dialog box. You must also place a checkmark in the Reentrant execution checkbox on the same page of the dialog box. LabVIEW automatically preallocates clones for each instance when it inlines the subVI.
Source, and for more light reading on the subject, a description of how the compiler works with some nifty diagrams on what inlining does if you scroll down a little.

Greg McKaskle 15-02-2014 00:19

Re: 100% CPU Utilization Using 10ms Periodic Task
 
Once the code is inlined, the compiler will propagate constants, we call it constant-folding. The result of this is that the string is known at compile time and all other cases are eliminated for that instance because they are unreachable. The overhead when inlined, both in runtime size and execution is equivalent to wiring a constant.

Greg McKaskle


All times are GMT -5. The time now is 01:46.

Powered by vBulletin® Version 3.6.4
Copyright ©2000 - 2017, Jelsoft Enterprises Ltd.
Copyright © Chief Delphi