I'm having some trouble understanding PID loops

Hello, my team this year is wanting our shooter run off a PID loop, but even through extensive research, I am having some trouble implementing it. I understand the concept (I’m I’m calculus, so I get why the terms are what they are), but I just dont know where to start.

We are using a tachometer for our RPM, and it is a bit inconsistent, so I made a method that averages the RPM for use in the pid loop, but I dont know where to go from there.

I was thinking of adding some PID calculations through a while loop to my shooterSpeed method, but I was told that while loops are bad in robotics.

I understand that there is a PIDcontroller class that helps with this kind of stuff, but the examples and wpi docs confused me with their explanation.

Sorry if I sounded really vague, but can anyone point me in the right direction?

Thank you!

By the way, I’m using the Java Command Robot template.

Your best bet would probably be to use WPI’s PIDController, just because it’s already implemented and has some nice features. You would create an instance of a PID controller and initialize it with your constants. Then, in some function that gets called periodically like robotPeriodic(), you take a measurement (and use your averaging filter to remove some sensor noise), then call calculate(measurement) - this will return some value to give to the motor, such as a percent output / voltage / whatever your team wants to use. Then you take the result of calculate() and command the motor to it. You also have to give it the right setpoint, so you would want to call setSetpoint(RPM) with the RPM you want it to be at. This could be in a periodic call if you keep track of the setpoint yourself, or you can calculate it on a button press/etc. Then if it oscillates too much you may want to consider playing around with their minimum and maximum integrator values

I agree with the advice above. But…

(OK, before you start: If the tach is inconsistent, your results will also be inconsistent. Averaging it just makes you think it is consistent.)

Anyway: Let’s say you want 2000 RPM. Subtract the tach reading (also in RPM) from 2000. What you have just measured is your “Speed Error”.

If Speed Error is positive, increase your motor speed; if negative, decrease it. How much you increase (or decrease) it is up to you, as is how often. (You might use the value of the error to determine how much it is in/decreased. You might do this every 1/10 of a second or so.)

This, is a P loop, the first factor of a PID loop.

Now, I and D might be needed, or might not.

Does that help?

For a shooter, you may also want to consider a “bang-bang” control, which will get you to speed quickly, recover quickly, and is easier to implement.

Each call to your execute() method, decide if the current speed is too slow, too fast, or within your tolerance.
If too slow, run at 100%. If too fast, run at 0% (use coast mode). If just right, repeat what you did last time*.

[This is actually a PID with a very large P, and no I or D.)

* Alternately, if you’re in the zone, you may want to do some intermediate value which you find works to maintain speed reasonably well; this would be like adding an F (feed forward) term.

As for any confusion about PID loops, this video helped me a lot and will probably help you a lot. As for a code example, here is my team’s PID class I wouldn’t suggest copying and pasting it but especially the calc function should give a good overview of the under the hood aspects of PIDs.


What types of controllers are you using? If you have any smart controllers like the TalonSRX, they have PID controls built-in, with a 1ms feedback time (vs. the 20ms feedback time for anything running in the WPIlib.)

What’s especially helpful is that the CTR documentation for the Talon has a ton of different examples, including some basic formulas for good starting points for PID values depending on encoder characteristics, motor speeds, gear ratio, etc., and examples of both position control and velocity control. Also, the Phoenix Tuner software from CTR allows you to select a motor and get a live graph of any of the attributes (position, speed, etc.) so that when you give it commands, you can see the response. You can even tune the PID parameters right from the Phoenix software. Your goal is going to be to tune the velocity PID so that it reaches shooting speed quickly and then doesn’t oscillate, and you can keep activating and deactivating the motor in the software to make sure it’s consistent.

Using smart controllers reduces the coding down to just a few lines. One to initialize, one to set the parameters, one to specify the encoder sensor selection, and then in the rest of the code, it’s just one line to say “spin at velocity X” and you magically get that speed consistently. I’m a fan.

It’s also handy to see how quickly it gets back up to speed after encountering resistance. Look at what the velocity graph does in the tuner right after you shoot a ball. It should dip slightly, then get right back to speed without oscillating. Calculate how long it takes to recover and use that to determine how much time you need to wait between shooting cells.

A few basic thoughts:

  1. Definitely use a pre-made library if possible. Understand the underlying concepts so you can apply the library correctly, but use something that someone else has already validated.
  1. Sometimes this can be good. However, keep in mind that this will add delay to the speed measurement. Un-acccounted-for delay is generally the opponent of good control system behavior. I’m not saying it’s wrong, but I am saying it’s an extra variable in your system, which others may not have. If possible, I’d recommend taking it out as much possible, and fixing the mechanical or electrical roots of your measurement errors.

  2. If you’d like a ground-up mathy treatment of the topic, this five part series may be of help.

Using the provided WPILib classes has just as little code overhead.

This topic was automatically closed 365 days after the last reply. New replies are no longer allowed.