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.

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?

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.

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.

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.

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?

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?

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.

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.

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.

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.

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

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.

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.

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.

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.

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?

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!!!

I’m also curious if it is clear why the error message wasn’t making its way to the DS.

Greg McKaskle

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.

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. :slight_smile:

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.