Published 2026-03-18
Do you often encounter this situation when playing withservos: you want the gimbal to be pointed steadily at the target, but it keeps shaking; or you want it to turn to a specified angle, but it always fails to turn in place? This is actually a typical PID control that is not adjusted properly. Many friends who are new to STM32 think of PID as too complicated. In fact, it is a set of mathematical methods that help us solve "how to make theservoobedient". Today we will talk about how to use STM32 to write a PID program that can make theservoaccurately obey the instructions, ensuring that you can understand and use it.
Simply put, PID is like a super smart "corrector". Imagine you are grabbing a moving object with your hands. Your eyes see the position of the object (feedback value). Your brain will calculate where the object is and how fast it is moving, and then direct the hand to adjust (output). This is what PID does. It calculates the difference between the target position and the current actual position in real time, and then tells you how much force to use to correct the difference. P is proportion, which determines the intensity of correction; I is integral, which helps you eliminate long-term accumulated errors; D is differential, which can sense changing trends in advance and prevent overshoot.
This is the most troublesome problem. In most cases, it is because the P value is adjusted too high. Proportional control is like when you drive and see a car in front of you, the P value determines how hard you press the accelerator. If P is too large, you will slam on the accelerator as soon as you see that the distance is a bit far away, and you will overshoot. Then you slam on the brakes. If you go back and forth like this, the car will rock back and forth. The same is true for the servo. If P is too large, it will cause it to oscillate back and forth at the target position. At this time, you need to appropriately reduce P, or introduce differential control D. D can play a "damping" role, suppress this oscillation, and make the steering gear stable.
It's not difficult. The core code is actually only a few lines. You need to first define three parameters (Kp, Ki, Kd) and several variables (target value, current value, last error, integral term). In the main loop, the current position of the servo is continuously read (usually the ADC value fed back by the potentiometer), and then the error is calculated. Proportional term P = errorKp. Integral term I = cumulative integral term + errorKi, which can help you slowly make up for the small deviations caused by friction and other reasons. Differential term D = (current error - last error) * Kd. Finally, the output PWM value = P + I + D. Assign the calculated PWM value to the timer to drive the servo to rotate. This completes the most basic closed-loop control.
For steering gear control, we usually use positional PID. Positional PID calculates the absolute position (PWM duty cycle) you want to eventually give to the servo. It is intuitive and easy to understand. It literally tells you "Now you should go to this angle." Incremental PID calculates the "change" of the current output relative to the previous output. It is suitable for scenarios like stepper motors that require precise control of the number of steps taken each time. What we care about when controlling the servo is where it stops, not how it goes, so positional PID is more in line with the needs, and the code implementation is simpler, and it is not prone to integral saturation problems.
You worked hard all afternoon and finally got the servo to be stable. You can't reset it every time the power goes off, right? This requires using the STM32's internal Flash simulation, or plugging in an external chip. In the program, you can define the three adjusted parameters Kp, Ki, and Kd as structures. When debugging is completed, the save function is triggered by pressing a button and the data of this structure is written to the specified Flash address. The next time the system starts, read the data from that address in the initialization code and assign it to the three parameters of the PID. In this way, the parameters are saved when the power is turned off, and your debugging results are retained forever.
This requires the use of the "integral separation" trick. With traditional PID, when your servo just starts to rotate and the position error is large, the integral term I will desperately accumulate a large value. When the servo is about to approach the target, this huge integral value will produce a serious "overshoot", causing the servo to overshoot. The solution is to set a threshold. For example, when the error is greater than 50 degrees, we clear the integral term I and prevent it from working. Only when the error is less than 50 degrees and the servo is almost in place, let the integral term I intervene to eliminate the last little static difference. This ensures both rapid start-up and accuracy when in place.
Okay, regarding the PID program for STM32 control of the servo, the core ideas and steps are probably these. When actually doing the tuning, parameter tuning is a process that requires patience and may take more time than writing the code itself. I don’t know if you prefer to use positional PID when working on a project, or have you tried other more intelligent control algorithms? Welcome to share your experience in the comment area. If you think this article is helpful to you, don’t forget to like it, save it, and forward it to more friends who play servos!
Update Time:2026-03-18
Contact Kpower's product specialist to recommend suitable motor or gearbox for your product.