PID control: need D values > 10000??

We’re using CANJaguar and PID control on our robot arm’s shoulder joint. The arm is driven by a pair of highly-geared motors, with an encoder directly on the joint. We’re having a very tough time getting the right values for PID, and need some help. Specifically, we feel we need some D to prevent oscillation and overshoot, but have had no success getting any value of D to work.

We’ve been testing different PID values using BDC-Comm, initially with motor power disconnected. We’re trying out different values of P, I and D, and watching the motor output voltage as we move the arm. Our P and I experimentation gives us sensible results, but D seems almost non-functional. We test by setting P and I to zero, choosing a value for D, and the moving the arm and watching the motor voltage. Unless we set D above 10000 (yes, ten thousand) the BDC-Comm voltage display never budges from zero. The max value for D (at least in BDC-Comm) is 32767, so that seems really strange.

BDC-Comm testing with motor connected shows that if I have all three terms set to 0, and stop action set to coast then the arm can easily be moved (obviously). I’d expect that I could then use a D value as a brake, resisting any motion. But, I have to bump my D value up to above 5000 before I get any braking action. If I set D to very negative (-10000) I get an apparent reduction in friction.

Why does this require such enormous values of D? It’s conceivable that if we could use a D of, say, 100000 we’d be fine, but that won’t work in BDC-Comm, and even if they’d work in Java using weird values “because they work” doesn’t seem like the right approach.

Thanks,
Dan

Edit: I think I’ve found the answer, but my three posts to that effect have yet to show up, So, I’m trying this.

Ether pointed me the right way: the problem is our counts-per-second. Arm moves 220 degrees max, directly coupled to a 360 degree per rotation encoder, so that’s only 220 counts total. We want control of motions of a few degrees a second, or a few counts a second. Given the PID iteration time of a millisecond, that won’t work (and is why D is totally ineffective; P and I are probably hampered as well.) Lesson: we gotta get more counts, probably moving the encoder to an intermediate shaft on our gearbox.

Have you tried using the Ziegler-Nichols Method for tuning your PID Controller? I’m not familiar with BDC-Comm. Did you write your own PID code?

BDC-Comm is the TI tool for communicating over CAN bus directly to a Jaguar motor controller. No cRIO or Driver Station involved, which lets us try values quickly and without worrying about possible software bugs (at least outside the Jaguar).

We have a controls expert who was stymied at getting good PID control working due to the ineffective D term. I don’t think it’s our tuning procedure; it’s either a bug in the Jaguar’s firmware (which seems unlikely) or a problem in our understanding of the use of PID on the Jaguar (more likely).

According to this post, D is multiplied by the difference in error, not by the (difference in error)/(sample time). Since the PID in the Jag runs at 1000Hz, that factor of 1000 needs to be in your D gain. That’s my guess.

What’s the resolution (counts per degree) of your encoder, and how fast are you moving the arm (degrees per millisecond) when you’re looking for a voltage?

I would assume this maximum exists because the D value is stored in 16 bits. (2^16)/2 = 32768

And I have a question. When you have a functioning system, what are your other values? Because it’s possible that your P could be too low, as well. (but Ether’s idea above me looks right, as well)

[quote]The max value for D (at least in BDC-Comm) is 32767, so that seems really strange

I would assume this maximum exists because the D value is stored in 16 bits. (2^16)/2 = 32768[/quote]

Sorry I wasn’t clear: the exact maximum is unsurprising (in a binary world), but that it is so close to the useful value (and may even be lower than the best value) was surprising.

According to this post, D is multiplied by the difference in error, not by the (difference in error)/(sample time). Since the PID in the Jag runs at 1000Hz, that factor of 1000 needs to be in your D gain. That’s my guess.

What’s the resolution (counts per degree) of your encoder, and how fast are you moving the arm (degrees per millisecond) when you’re looking for a voltage?

I think you’ve hit upon the answer. We’re using a 360 count/rev encoder (one count per degree) which is connected directly to the shoulder joint. We’d like good regulation with the arm moving a maximum of 220 degrees or counts per second, which is about .2 counts per PID iteration. Even with 4x encoding, that’s less than one count per PID iteration. Regulation needs to continue down to less than 10 degrees or counts per second, or about 1 count every 100 PID iterations. That’s gotta be problematic.

Our two motors drive Banebot 16:1 gearboxes, which are both plugged into a single 6:1 Andymark Toughbox driving the shoulder. Moving the encoder to the output of one of the Banebot gearboxes would cut the required D term by a factor of six, which might be enough. Moving the encoder to the shaft of one of the motors would be even better, but I don’t think that’s possible with our motors.

Lesson: if you want reasonable PID control, you need to have a reasonable number of counts per second on your encoder.

Thanks, all!
Dan

The D (derivative) term helps to compensate for short term disturbances. Its effect decays over time. It can have a destabilizing influence on the loop. It is generally the last term to determined if it is used at all. Generally a properly tuned loop will have a little overshoot & oscillation decaying to 0 in 2-4 oscillations. I am not sure how you tune a loop without the load connected.

The jags use a 32 fixed point integer for the constants–16.16. one bit for sign, 15 bits lefts of the decimal point, 16 bit right of the decimal point.

I don’t know much about the Jaguar/CAN PID implementation but I can tell you that your system will act very differently with the load attached. The control loop is electro-mechanical. The numbers you get w/o a load are nearly useless and perhaps why D has little or no effect.

HTH

My reading of the OP’s post is that he is not trying to tune the system without a load. He is observing the effect of the P, I, and D gains in order to confirm that they do what he would expect. And he is questioning what he is observing.

We’ve been testing different PID values using BDC-Comm, initially with motor power disconnected. We’re trying out different values of P, I and D, and watching the motor output voltage as we move the arm. Our P and I experimentation gives us sensible results, but D seems almost non-functional. We test by setting P and I to zero, choosing a value for D, and the moving the arm and watching the motor voltage.

BDC-Comm testing with motor connected shows that if I have all three terms set to 0, and stop action set to coast then the arm can easily be moved (obviously). I’d expect that I could then use a D value as a brake, resisting any motion.

I’m not necessarily disagreeing, but where did you get this information?

*For a position PID, the D term looks at how fast the process variable is moving toward or away from the setpoint, and whether the process variable is above or below the setpoint.

For a fixed setpoint, the effect of the D term on the PID output is such that it acts as a speed-dependent “brake” whenever the process variable is moving toward or away from the setpoint.

I’m not necessarily disagreeing, but where did you get this information?

From the TI 2012 FAQ on the jags Question 41 addresses it. The file name is spma033a.pdf.

I used to tune flow & pressure control loops. Admittedly the transfer function for a position or velocity loop might look different. I generally found the process measurement value to be noisy enough to make the derivative term useless. Obviously others have found it useful since it is a lot easier to find PID controllers rather than PI controllers.

Thanks!

I generally found the process measurement value to be noisy enough to make the derivative term useless.

Yup. GIGO :slight_smile:

Depending on the kind of noise (amplitude and frequency components relative to the control cycle), sometimes a small filter on the input can allow the derivative term to still improve the response time. Not as good as eliminating the noise, but might be better than not using the derivative at all.

It is about as easy to make a generic PID controller as PI, and then the user has the option of setting the D term to zero, resulting in a PI controller. So, from a marketing point of view, it makes sense to make the PID controller whether most people use the D or not.

Excerpt from Q41:

Most fixed-point values used in the motor controller are contained in a 32-bit integer and are a 16.16 format.

It doesn’t explicitly say that the D gain is fixed point, or if it is fixed-point, if it is 16:16.

Here’s an excerpt from the Jag firmware source code that I linked to in an earlier post:

// Compute the new control value.
//
llOutput = (((long long)psState->lPGain * (long long)lError) +
            ((long long)psState->lIGain *
             (long long)psState->lIntegrator) +
            ((long long)psState->lDGain *
             (long long)(lError - psState->lPrevError)));

I’m not a C++ guru. I can’t tell from that snippet what data type DGain is. The naming convention may be a clue though. There’s a leading “l” in the lDGain variable name.

You would have to go back and find where the variable is declared? I don’t do much with C++ either. But a long long seems to be an 64 bit integer (thanks google)

I have used <0 decimal numbers when playing with the loops in BCDCOMM though. So it the 16.16 format makes sense.