PIDController tuning

First, physical setup:
We’ve got a set up with 3 motors, each getting feedback from a different potentiometer. Two motors are AndyMark PG-71’s, mated with a 1-turn potentiometer. For one of them (we’ll call it the A motor), we cover about 3/4 of the potentiometer, and the second (we’ll call it the B motor) uses about half of the turn. Lastly, we have a Mini-CIM hooked up through a toughbox mini and an additional 2-1 reduction (we’ll call this the C motor), with a 10 turn potentiometer going through about 8 turns total.

Friday we spent an ungodly amount of time trying to tune the PID constants for each of these motors, and simply could not get it to stop oscillating horribly at whatever setpoint we wanted it to be at. Getting fed up and wanting to see some progress before going home, we finally replaced the PIDController class with our own little function that implemented some simple rate-smoothing feedback, which mostly works. However, we’ve now discovered that the battery voltage really affects our function (It was working perfectly smoothly and predictably… then we replaced the battery and started getting some oscillation in the movement we didn’t have before). We can add in a term for that to compensate (along with sufficient testing to ensure it does what its supposed to do), but I’d really rather just have the PIDController class working correctly.

So, who has experience working with this class, and can give us some pointers on roughly what values we should be passing in for our P, I, and D constants? Is it worth spending more time trying to get that class to work, or should we continue down the path with our own custom class? Would the PIDController class have the same issue with varied behavior based on battery voltage?

The actual coefficients depend heavily on the actual mechanism. For starters, set I and D to zero, and set P really really low. You want it to start very conservatively and not oscillate. Then continue increasing P until it starts to oscillate; if you back off from this the P alone is enough for many mechanisms.

If you want to get to your set point faster without overshoot, You can begin tweaking in D. If you have high friction causing a steady-state error, use I to overcome it.

I had some success this year using “method a” at this link. You will need some way to collect data and graph it. Using PID should allow you to get consistent operation under varying battery charge.

Hi, PID is a very nice tool when you get the hang of it, the first thing i would suggest is to not use I, I can cause oscillation over time because I adds power over time if the setpoint is not reached, P and D are what you want to use, I would suggest starting at about 0.01 for both P and D and work your way up. D will help you solve your overshooting problem because it will slow down the motor as you approach your setpoint.

Hope it helps,

-Matt

Be sure your PID is not stuck in a loop. We had wild oscillation yesterday because the PID was in a loop that was being called by periodic tasks. I strongly advocate a ‘no loops’ architecture.

to determine what range of number makes sense - let’s say your position feedback is in degrees, so your setpoint is also in degrees. the motor velocity is in the range of -1 to 1. By definition, your P gain is applied to the difference between commanded and actual (your p error) so if you are off by 5 degrees, and you want to apply a 0.5 motor speed to correct for it, your P gain should be around 0.1, as a starting point. If it still oscillates too much, then back it off a bit.

for integral gain (our PID is on an arm where the load changes based on position, so we use I to close the gap), remember that it is a time parameter measured in minutes. In our case, we ended up with about 0.01 for I.

it is really handy if you can have it graph position in real time. Tell it to do a step move (say from 100 to 150 degrees) and see the shape of how it gets from one to the other. If it doesn’t get to exactly the right point, make I smaller (more powerful). If overshoots too far, make P smaller (weaker).

Most systems build in FRC don’t need D gain, IMO

Just an alternate note. This may or may not apply to your setup.
It can be untunable if the three PID loops are operating independently of one another, but are affected by one another. They can’t forecast the blind-siding they get from the other loops and end up fighting the others for position.

In such an interdependent system one simple approach might be to have one of the motors act as the master (one ring to rule them all) with the others slaving themselves to it’s position. Feed the master pot to the slaves as their continually changing setpoint (normalized to match the range of the slave pots and applying any relationship equation).That provides sort of a cooperative feed forward term to the slaves. I typically make the slowest mechanism the master (sometimes purposely slowing it down) and the faster mechanisms the slaves, because you can structure it so that the slaves reach equilibrium quickly and have reduced affect on the master. Overall thrashing is eliminated as the slaves make smaller incremental changes as they trail along behind the master instead of racing ahead.

I believe you mean to make I larger. The PIDController class multiplies the integrated error by I, so larger I means stronger integral action.

Also, changing battery voltage will change the performance of your PIDController unless you’re using a CANJaguar in Voltage Mode, which would add another bit of control action in the Jaguar itself which might confuse things. The reason is that all speed controller commands are in percentage of battery voltage. Higher battery voltage means stronger motor action, which is the equivalent of turning up all your gains slightly. To compensate for this, your best option is to tune with a freshly charged battery and no other systems running. If your system is stable under these conditions, it will most likely be even more stable as battery voltage drops under load during a match.

Depends on the form of PID being used. Java seems to use the parallel form. The LabVIEW help seems to imply that it uses the academic form. I’ve not been able to look inside the LabVIEW VI to see what it’s actually doing.

*





A big thanks to everyone who chimed in here. We managed to get it working flawlessly for all but 1 setpoint tonight, and the tips and thoughts shared here certainly helped! We’ll tackle that last one before we bag tomorrow :slight_smile:

Looked for myself out of curiosity. Labview multiplies the integrated error by Kp/Ki and multiplies the derivative by Kp x Kd. Definitely the academic form of a PID there. Which is probably unsurprising, really.