Limiting the speed of a motor driven by a position based PID.  - Page 1
Forum section: electronics / projects

author: perdrix
author_rank: Frequent Contributor
timestamp: January 24, 2022, 01:42:25 pm
content: I have a PID that controls the position of a servo motor which has a 1024 tick encoder. For larger moves (many thousands of ticks), I want to limit the rotation speed to (say) 5000 rpm == 85600 ticks/second.My initial naive attempt simply said that if the speed was greater than the speed limit, then use the result from a secondary speed PID to replace the value from the position based PID. The result (in retrospect obviously) wasn't that clever (see the first plot in the attached PDF) which shows violent oscillation of the PWM value (PID output) as the code switches between the position based PWM value and the speed based PWM value. Please ignore the PID values in the title of the first plot - they don't relate to the PID values used for the position based move which are in the name of the file.The second plot is just the actual (moving average) motor speed (ticks/10ms) so 856 is 85600 ticks/s and the output value of the speed based PID.I'm looking for recommendations of approaches that are known to work such that as the speed approaches the speed limit the main PID output is toned down until it is just holding the speed at the desired value (if you will a secondary target or setpoint value) and finally reducing as the position setpoint is approached.Thank youDavid

author: Siwastaja
author_rank: Super Contributor
timestamp: January 24, 2022, 01:55:34 pm
content: ORing parallel feedback loops usually does not work well.Instead, recognize the natural order of loops and cascade them in series (plant output -> setpoint)Normally, motor control involves these three:Winding current (PI)Speed (FF+PID)Position (PID)So, position error drives speed setpoint. Speed error drives current setpoint. Current error drives PWM.You should first concentrate on the speed controller alone, make it responsive and stable to fast setpoint changes. Then add position feedback. Don't cross the boundaries, position controller should only control speed setpoint.

author: perdrix
author_rank: Frequent Contributor
timestamp: January 24, 2022, 02:07:39 pm
content: Could I ask you to expand on that? And what was FF in the Speed line?I have no training in control theory, only a bit of online reading about PID control and the position based control is pretty much working as desired.The average motor current should simply be directly proportional to the PID output that's driving the PWM controller.If I interpret what you said correctly I need to write a complete new set of test code for the PIC that only handles motor speed to determine PID coeefficients for the a motor speed PID.I should then use the position based pid to output a speed value based on current position versus the position setpoint?Not arguing just seeking clarification as it doesn't seem that obvious an approach.ThanksDavid

author: bhave
author_rank: Contributor
timestamp: January 24, 2022, 02:35:49 pm
content: I am not sure exactly how your loops work, but it sounds like you can limit the output of the position PID using the speed PID (excuse the bad pseudo code):if (position_PID_output > speed_PID_output){position_PID_output = speed_PID_output;position_PID_integrator = speed_PID_output;}This assumes all the PIDs are normalized to the same output levels

author: Siwastaja
author_rank: Super Contributor
timestamp: January 24, 2022, 02:56:36 pm
content: I was going to link to the thread where I explained what "FF" is, and other relevant information (https://www.eevblog.com/forum/projects/pid-motor-control/) but just now realized it's your thread but you haven't spent much effort in reading and trying to understand the replies. Start from there.Lack of "training" in control theory does not matter because if you learned this stuff in university for example, you would completely lack the big picture and totally unable to do anything. Control theory is confusing, because it concentrates so much on explaining what PID is and then about zillion of esoteric ways of tuning and autotuning of the coefficients, to the point that you easily lose the big picture, which should be control, not the feedback loop in isolation. Feedforward is a great example of this phenomenon at work; its complete lack is a telltale sign that the book / whatever resource we are talking about is very limited and only for academic interest, not very useful for real world.Similarly, choice ofwhich parameters are inputs, which are outputsis way more important than the exact tuning process of the coefficients. (Typical example being controlling voltage (roughly: PWM duty cycle), when you should be controlling current, if you want stable and quickly reacting loop.Quote from: perdrix on January 24, 2022, 02:07:39 pmNo, the idea is to remove the "should" here and make the motor current an actually controlled parameter: add feedback! Control is needed because if you just give PWM duty (or voltage) to a motor, current heavily depends on the voltage difference between applied and back-EMF.PI loop is fine: (current setpoint - current measurement) -> PWM duty setting. Easy to tune, doesn't need to be exact. If this is brushed motor, then it's literally just that: current error (using shunt resistor etc.) -> PI -> PWM duty. (For a BLDC, you need to do the FOC trickery, i.e., measure phase currents, vector rotate them in sync with measured rotor position, then have two PI controllers for Iq and Id currents, then rotate the PWM duties back to the moving rotor.)The current might be "average" yes but only during very short time. Usually with a lot of motor inductance and high enough PWM frequency, current ripple is small, and you can just sample the current always at the same point during the PWM period, no averaging needed or wanted. Response needs to be fast.QuoteDo it in this order:1) Write a current controller. This basically creates atorquecontroller. Setpoint is current, which is roughly torque, which for a freely rotating rotor (not much friction, no "resistive" mechanical load, just mass) is ~ acceleration.Test it: change setpoints quickly, measure the actual current (for example, logging the current measurements in .csv file). Tune P, I for fastest possible reaction to setpoint change, without much overshoot. The idea is, with current = 0, motor freewheels i.e. slows down slowly only due to friction. With current > 0, positive torque is generated and motor accelerates. With current < 0, negative torque is generated and motor decelerates, regenerating into the DC bus. Acceleration, i.e. rate of speed change depends on magnitude of current.2)Now that you have this sorted out, start working with speed controller. Setpoint = speed command. Output = current command to the current controller you just did.At this point, you should have whatever mechanical system you are tuning for already physically driven by the motor!Contrary to feedback literature, I'd say start with FF from setpoint and another FF from setpoint's derivative. These are easy because you have the setpoint variable available. Justcurrent = F1 * speed_setpoint + F2 * (speed_setpoint - prev_speed_setpoint);Adjust F1 and F2 until you get the ballpark right response. Not the exact speed, can't do that without feedback, but right type of response to speed setpoint changes, without huge overshoot. The idea is, you have just two parameters, you can do it. Make yourself a development environment where you can change these values in the fly, without reflashing the firmware. You quickly learn what I mean when you play around for 10 minutes!Andnowadd P,I,D. Keep D=0 first, again only two parameters to tune at once. Make the motor run at constant speed you set without oscillating. Do quick changes on that setpoint and make it find the new speed quickly and without much overshoot.Once done,3) Only now start work on the position feedback.QuoteExactly.But it doesn't necessarily need to be exactly that way. It's just how it's usually done with proven track record. I don't know if it is intuitive, many things in engineering are not. Being such blockhead I am, I have once tried direct positional feedback (position error -> motor current) and ended up rewriting it later with this classic position -> speed cascade.

author: perdrix
author_rank: Frequent Contributor
timestamp: January 25, 2022, 10:42:58 am
content: Hardware already exists and there's ZERO possibility to change it to measure the actual motor current. Commutator DC motors are actually pretty linear.I didn't monitor the other thread because I specifically requested OFF-LINE contact (at the time I only had very limited access to online forums for various reasons). So please don't tell me off for not reading it.Feed-Forward - most interesting - will look into that if I can't get the speed control PID to behave (it seems tractable so far).The crucial bit was using the output of the position PID to drive the speed PID and I am most grateful for that - it was a "great leap forward" for me.ThanksDavid

author: Siwastaja
author_rank: Super Contributor
timestamp: January 25, 2022, 10:48:15 am
content: If it has got no current sensing, it's no motor controller. If it's sold as one, it's either an extremely cost-optimized toy, just driving a tiny motor, or a scam. Sorry. Youneedto start from proper hardware. Trivial cases (small inefficient motors) aside, you just can't properly drive motors without current sense. Can't cheap out on this one. Destruction of the motor controller itself is the most likely outcome.Yes, commutator DC motors current is linear as per I = (U_applied - Ubemf) / R. The problem is, for a highly efficient motor, R is basically zero. Only way to control current is to utilize existing L and sense the current to create the triangle ramp (similar to buck regulator inductor current).Like you can't build a motor controller without current sensing, you also can't use internet forums to give hit-and-run questions and ask for personal off-line contacts (snail mail? telephone? what?). People will respond to the threads because then it also helps others. The excuse of not reading the another thread for technical reasons when you could somehow create a new one sounds iffy.Good luck anyway.

author: perdrix
author_rank: Frequent Contributor
timestamp: January 25, 2022, 05:53:16 pm
content: Well it's no toy I assure you. It has however no current sense circuitry - it was removed (before I got involved) in a previous hardware iteration to save money. The motors are small DC commutator motors with limited current draw (under 3A worst case) and while the motor control H-Bridges do burn out it's because people sometimes mis-wire the motors even though it's designed to be pretty hard to achieve that!I've been working to improve the software for the existing hardware - sometimes you don't get given the choice to redesign hardware.My situation WRT to forum access is now resolved as I am back at base - when I opened the original thread I only had very limited access to forums (20 mile drive) or webmail for email.And for your amusement see attached pdf (ignore PID values in title line - they are unrelated to the speed controlled slew) which shows the speed controlled slew working nicely. Interestingly I couldn't get the speed PID to behave sensibly using PonE (either it didn't reach the required speed or it oscillated or both) but once I switched to PonM it worked very well and was pretty easy to tune.D.

author: nctnico
author_rank: Super Contributor
timestamp: January 25, 2022, 08:31:46 pm
content: Quote from: Siwastaja on January 24, 2022, 02:56:36 pmStill, there is a potential problem here. While the speed is constant, the integrator for the position will keep increasing (either positive or negative) causing an overshoot when you reach the setpoint. A way around is to only have the integrator part enabled (as in changing based on the error) when the positional error is below a certain threshold.IIRC the RPM of commutating motors is proportional to their voltage so you could probably use these open loop and limit the maximum PWM duty cycle in order to limit the speed (unless speed control is critical as well). If so, you could use 1 position PID loop where the I part for the PID loop is only active when the position is close to the required position.

author: Siwastaja
author_rank: Super Contributor
timestamp: January 26, 2022, 08:02:26 am
content: Quote from: nctnico on January 25, 2022, 08:31:46 pmYeah, for voltage-based drive (which I do not generally recommend, but works for small motors), just use a lot of feedforward. Assuming 100% efficient motor with R=0 (which also kills the voltage-based driver), PWM duty ~ RPM, so feedforward alone gives accurate speed. With real motors, R > 0 and RPM depends on the mechanical load, but feedforward can still do most of the job, and PID can handle the finetuning.The problem with this is the lack of torque limiting, but clearly OP has small and inefficient motors where even "stall current"* is small, and maximum torque clearly not too much. It's a forgiving set of hardware.*) Defined as current flowing when full nominal voltage is applied at locked rotor i.e. zero BEMF situation: I = U / R. With large, efficient motors, this parameter is irrelevant because you just can't apply unlimited current to them.

author: perdrix
author_rank: Frequent Contributor
timestamp: January 26, 2022, 11:32:30 am
content: You can burn out these little motors too if you stall themWe check for a stall by determining if the motor moved only a small amount with a high PWM value.D.

author: Siwastaja
author_rank: Super Contributor
timestamp: January 26, 2022, 11:46:35 am
content: Yes, current control has many purposes:* Protect the power switches (MOSFETs) and wiring; other alternative is massive oversizing* Protect the motor itself (windings and possible brushes)* Provide controlled torque* Only use the motor within its true torque range, maximizing efficiency. Torque ~ current, but you can increase current towards infinity and the torque definitely does not follow, after some point - iron saturation. In other words, if a certain motor has nominal current of 10A and stall current of 100A, the point where efficiency really starts to drop and torque flats out might be at 20-30A.Current limiting has the advantage that there is no such a thing as "stall" anymore. Any motor speed is equally good to any other motor speed, including zero speed. It gives the torque you set, and at speed=0, does no mechanical work. All the energy goes into I^2*R losses, but this loss is not any higher than when rotating at full speed at the same current; the motor can handle that heating.Without current sense, you can always guess. You can ramp up the speed slowly and assume the BEMF rises due to rising RPM. You can experimentally find good ramp rates. You can create detection logic for stalls looking at speed sensors. It's just that just implementing current control gets rid of all edge cases automatically and finally saves work.Motor is really similar load compared to a battery (or a large capacitor, say ultracap), or an LED. In motor, V ~ RPM. In battery, V ~ SoC. In LED, V = nearly constant, but varies with units and temperature. All three require active current control, and in all cases, you can use a voltage source and significant amount of resistance, but this leads to poor efficiency and poor control of current so is only suitable for small motors (stall current of a few A max), small LEDs (indicators), and small, self-shunting batteries (think about the classic 10-hour NiCd charger). As a result, every modern LED driver for illumination purposes use a constant current mode power supply; even quite simple LED driver ICs nowadays tend to be constant current drivers, even if linear. Every battery charger implements CC. And, every motor controller controls current. This is a terminology thing, but I simply don't call indicator LED blinkers "led drivers", large-value RTC battery top-off resistors "battery chargers", and similarly, if a gadget simply controls a small motor with a FET, without current sensing, I just don't call it "motor controller".

author: nfmax
author_rank: Super Contributor
timestamp: January 26, 2022, 12:10:08 pm
content: Quote from: Siwastaja on January 26, 2022, 11:46:35 amExcept, possibly, if it is cooled by a shaft-mounted fan!

author: Siwastaja
author_rank: Super Contributor
timestamp: January 26, 2022, 12:58:23 pm
content: Quote from: nfmax on January 26, 2022, 12:10:08 pmGood point, although shaft-mounted fans perform pretty poorly well before reaching zero speed (and produce quadratical power waste at high speeds). So they really work as intended only within some sweet spot RPM range. For large range of variable speeds and significant torque at any speed, separate fan is the usual choice, this would be typical in CNC machinery for example, and basically all traction applications. Of course, maximizing efficiency pays off here, too: less cooling required makes cooling efforts easier.

author: benwillcocks
author_rank: Newbie
timestamp: April 08, 2025, 02:12:59 pm
content: You could try managing the position demand going into your PID position controller. When a new target position arrives, have your position demand move towards the target position following a trapezoidal speed profile. In other words, there's a period of acceleration, then a period of constant speed (at your speed limit), then a period of deceleration. Of course, for short moves the speed limit may not be reached, and there will only be a period of acceleration and a period of deceleration.At a given time, the desired speed is the minimum of:the speed limitsqrt(2 * deceleration * remaining distance)previous speed + (acceleration * sampling period)