# Control both Velocity and Position (Linear actuator)

I am trying to control the velocity+position of a linear actuator.

At this moment I am able to control the position or the velocity. But I'm trying to control both. What the control has to do: Let the linear actuator drive to a position i.e. 0 to 100 cm with a constant velocity of 1cm/s.

I control the actuator using a PWM signal. And I measure the velocity and position using a position sensor on the shaft.

What kind of control is preferred, PID in cascade? If so,what would the code look like. Any other kind of control would function better?

EDIT: A more describing picture. I want a Velocity controlled Position controller. Hopefully this will make it clear

EDIT

My first try is with a trapezoid wave. Maybe there is an easy way without to much calculation power to change it a s-curbe. Then the accelartion/jerk will be alot smoother. I let the microcontroller calculate 3 different formulas afterwards it will calculate it using loop iteration. This way I can use one PID for the position. The parameters in the following code will fictional:

    AccelerationLoops: 5                            //[Loops]
Velocity:      100                          //[mm/s]
DeltaPosition:     7.5                          //[mm]
Looptime:      5                            //[ms]
Loopfactor:        1000 / Looptime                  //[-]
VelocityLoop:      Velocity  /Loopfactor                //[mm/loop]
VelocityFactor:    VelocityLoop * .5 / AccelerationLoops        //[mm/loop]  (.5 found by integration)
Loops:         DeltaPosition / VelocityLoop / AccelartionLoops  //[Loops]

----Formula---
Formula1:      VelocityFactor * x^2
LastF1:        Last value of Formula1 Formula1(5)

Formula2:      VelocityLoop * x - LastF1

Formula3:      VelocityFactor * (Loops - x)^2 + DeltaPosition)

Using the parameters of above it will generate the following setpoint :
0   0,00
1   0,05
2   0,20
3   0,45
4   0,80
5   1,25
6   1,75
7   2,25
8   2,75
9   3,25
10  3,75
11  4,25
12  4,75
13  5,25
14  5,75
15  6,25
16  6,70
17  7,05
18  7,30
19  7,45
20  7,50


A big problem with the code above is that the amount of accelartion loops is a constant. It can not be changed except when you already know the amount of loops it will take.

I will be using two separate arduinos, they will be connected using a CAN-bus connection. Anyway, they won't communicate through it unless the load becomes too high. This will make Master/Slave impossible. Also the system has to be modular: adding another actuator to circuit won't be a problem. The actuator is speed controlled by using a PWM signal. The linear sensor will deliver a 0-10v signal which i will reduce to 0-5v by a simple voltage divider. The loop will be around 5 to 10 ms, will depend on the maximum looptime.

Arduino has a 10-bit(1023) ADC but use of oversampling I will probably try to increase it to 12-bit. To not decrease the reading speed I will decrease the prescaler of the ADC.

The PWM output is 8-bit(255), I am trying to find a way to further increase. Because I think 255 steps are too low for my application.

Because the Arduino has limit internal memory, pre calculating all the positions is impossible.

Thank you all for the help so far!

• Have you looked at feedforward and what do you know about the system/perturbations? – fibonatic Jun 15 '15 at 22:32
• Welcome to Robotics stack exchange KoenR. You could improve your question if you edited it to provide all of the information you added in comments to answers. That way people don't have to read every answer and every comment on those answers to see the details of what you are trying to do. – Mark Booth Jun 16 '15 at 18:51
• What does your PWM control? My assumption would be torque (current to the motor), but it would be useful to know if your PWM is connected to a speed or even position control input. – Mark Booth Jun 16 '15 at 20:02
• Also, to give us an idea of the constraints on your system, you may want to briefly mention the expected resolution of the encoders, the cycle time of your controller, the range of speeds you want to achieve, & the position/velocity errors which are acceptable. Precise details aren't needed, but ballpark figures will give us an idea of what you mean when you say you 'want both the position and the velocity to be exact'. They can never be 'exact' and you hit the encoder resolution limit long before the uncertainty principle kicks in. *8') – Mark Booth Jun 16 '15 at 20:44
• Thank you for you help. I updated my question to what I think is more clear. – KoenR Jun 17 '15 at 12:51

The first thing to realise is that this is not a control problem, this is a planning problem. If you conflate the two, you are making life much more complex than it needs to be.

## Solution - Motion planning

The traditional way to achieve what you want is to have two loops. The outer planning/supervisory loop generates way-points for specific points in time, while the lower level PID loop generates the appropriate PWM signals to keep the motor as close as possible to those way-points.

The more way-points you generate, the more closely you can track both velocity and position. Older systems often ran their floating point planning loop at a much lower rate than their integer PID loop, but these days even modest micro-controllers have more than enough compute power to do full trajectory planning of multiple axes at the PID control rate.

## Simple example

While the example you drew is an s-curve trajectory profile, it is easier to explain the principles by looking at a simple trapezoidal profile.

Let's say you want to move from 0 to 36mm in 9 seconds with cruise velocity (feed rate) of 6mm/s and an acceleration of 2mm/s/s. You might plan a move in 9 steps as follows:

\begin{array} {|r|r|} \hline time & t & 0 & 1 & 2 & 3 & 4 & 5 & 6 & 7 & 8 & 9\\ \hline acceleration& a & 0 & 2 & 2 & 2 & 0 & 0 & 0 & -2 & -2 & -2\\ velocity & v & 0 & 2 & 4 & 6 & 6 & 6 & 6 & 4 & 2 & 0\\ position & d & 0 & 1 & 4 & 9 & 15 & 21 & 27 & 32 & 35 & 36\\ \hline \end{array}

In this case, at time $t=0$ you would inject position $d=1$ into your PID (plus acceleration $a=2$ and velocity $v=1$ if your PID loop has acceleration and velocity feed forward). At $t=1$ you would inject $d=4$ into your PID and so on until at $t=8$ you command the PID to move to the final position $d=36$, then at $t=9$ the system should have stopped moving.

## Implementation

• If you are CPU limited on your micro-controller but have plenty of memory to store path profiles, you may want to pre-calculate the way-points.
• If you have plenty of CPU, you may want to calculate way-points on the fly.
• If you are limited in both CPU and memory, you may need to either lower your way-point generation frequency or use integer interval arithmetic to calculate approximation more quickly.

## Complications

If you find that your actuator jumps between way-points rather than moving smoothly, then you need to either reduce the time between way-points or optimise (tune) your PID loop for your motion (for example, reduce the proportional gain, increase derivative gain and/or increase the velocity/acceleration feed-forward gains). The moment you start using your PID loop to tune for expected motion however, you are making the motion worse for other kinds of move.

I see from comments that you want two linear actuators to match each other.

In this case, while the PID loops for each actuator will need to be run independently, the way-point inputs into those PID loops can be shared.

How closely each servo loop follow each other will be determined by how closely they follow the idealised trajectory as defined by the way-points.

If your individual PID loops are tuned well enough, and you set sensible limits on following error, the overall error between the two actuators should be at most the sum of their following errors, and is likely to be much less on average.

By the way, my experience on this comes from writing the control software for a 2x2m dual gantry cartesian robot. Even though we were accelerating the gantries up to 1m/s at 1g, we rarely had a following error of more than a few hundred microns, & the error between the two ends of the gantry was usually an order of magnitude lower. If we had used s-curve rather than trapezoidal move profiles, our errors would probably have been an order of magnitude lower still, but this was the 90's and micro-controllers had much lower floating point performance, so we went for simple & fast over complex & slow.

I'd say this problem is very much similar to The aerial refueling problem: sketch of a feedback controller whose one possible solution is then explained in https://robotics.stackexchange.com/a/5263/6941.

### EDIT

The minimum-jerk position profile (i.e. the s-curve) that lets the system go from the initial position $x_0$ to the desired position $x_d$ in $T$ seconds is:

$$x\left(t\right)=x_0+\left(x_d-x_0\right) \cdot \left(10\left(\frac{t}{T}\right)^3 - 15\left(\frac{t}{T}\right)^4 + 6\left(\frac{t}{T}\right)^5\right),$$

where $t \in \left[0,T\right]$ specifies the time granularity, thus the number of set-points.

Finally, $x\left(t\right)$ will be the reference for the position PID.

• I think I have something else in mind, could you check my edit? Thanks in advance – KoenR Jun 15 '15 at 16:15
• Try to answer yourself the following question: what if you're provided with one PID controller that makes the system track the position very precisely? How does the derivative of the position feedback look like? – Ugo Pattacini Jun 15 '15 at 17:29
• So your idea is to calculate all the different positions over time. Then to control it's position over this course? Thank you for your answer – KoenR Jun 16 '15 at 10:06
• This is a somewhat standard technique that goes under the umbrella of Input Shaping. You have to provide a varying reference anyhow, also if you imagine to control only the velocity (e.g. the trapezoidal waveform you depicted). – Ugo Pattacini Jun 16 '15 at 10:11
• To be more clear, there exists plenty of blocks filtering a step-wise input into a smoothly varying reference, therefore you are not required to compute the reference trajectory point by point. – Ugo Pattacini Jun 16 '15 at 10:14

I don't think you can control speed and position at the same time - what happens if you don't change the position reference but you have some non-zero speed reference? Did you want the output to stay still or go to the command speed?

I think what you are looking for is a software-imposed actuator authority limit. In this case you can just limit the output of the controller. I don't know what your actuator inputs are, but for the controller I would try something like:

dT = sampleTime;
input = positionRef;
feedback = positionFbk;
outputLimit = actuatorSpeedLimit;

errorP = input - feedback;
errorI = errorI + errorP;
errorD = (errorP - prevError)/dT;
prevError = errorP;

output = kP * errorP + kI * errorI + kD * errorD;

if abs(output) > outputLimit
output = sign(output) * outputLimit;
end


Now, as I mentioned, I don't know what your inputs to the actuator are. The model above assumes the output of the PID controller is a reference speed that you pass to the actuator. You cap the speed reference you pass to the actuator giving an electronic form of actuator saturation. The controller will continue to command higher and higher velocities until you reach a position close to the reference position, at which point it will begin to back off. It will back off below the outputLimit at which point the electronic saturation eases and control resumes like normal.

If your actuator uses a position input and it determines its own speed response, then the actuator probably uses a proportional controller, where the actuator speed it utilizes is given by:

vActuator = $(1/\tau)$(positionRef - positionFbk);

where here $\tau$ is the actuator's time constant. In this case you can estimate the actuator speed and throttle your position that you pass to the actuator, provided you can measure or estimate the time constant. Resuming the above code:

output = kP * errorP + kI * errorI + kD * errorD;

estVelocity = (1/\tau)*(output - feedback);

if abs(estVelocity) > actuatorSpeedLimit
output = (\tau) * actuatorSpeedLimit + feedback;
output = sign(estVelocity) * output;
end


Where again, in this example, your controller output is a position you pass to the actuator instead of a speed you pass to the actuator. You can do the same if you provide an acceleration to the actuator, but I don't think I've ever seen a linear actuator accept an acceleration as an input.

:EDIT:

Despite the fact that this question has been marked as answered (and I've been downvoted!), I would add that you could split the controls.

You are going for synchronized actuators, so have one actuator use PID to get to a command setpoint and the other actuator use PID to adjust its speed based on the first one. This sets up a master/slave or leader/follower, where the master follows the position reference and the slave follows the master.

As with any other PID controller, you can tune the slave to whatever threshold you want to achieve your desired speed difference tolerance.

• Thank you very much for you detailed answer. I also looked at cutting of the maximum speed. Though this delivers some problems. [plus next comment] – KoenR Jun 16 '15 at 10:05
• I want both the position and the velocity to be exact. Why: I am trying to synchronize two linear actuators between each other. Therefore both the velocity and position should be controlled The velocity is the most important to control. But when I control the velocity with a standard PID as described in your answer. The actuator won’t stop at his given end position. Would a PID for the velocity + a hysterese on the position work better? Thus exponentially reducing the velocity when the end position becomes closer. – KoenR Jun 16 '15 at 10:05
• It would be very helpful if this information in particular were edited into your question @KoenR. – Mark Booth Jun 16 '15 at 19:41
• Limiting pwm output to a fixed value won't work. If one motor is running at the desired speed, but the other one isn't, the follower will never be able to catch up & the following error will only increase. That's why the PID controller for each actuator need to be independent - if one falls behind, it needs to be allowed to work harder to catch up. Also, you will get much better response by feeding the same waypoint demand position into two independent control loops than if you slave one off the other (where the slave will effectively have double the time constant!). – Mark Booth Jun 16 '15 at 20:12
• Yes, I understand that now. My original response was based on his original question, "I am trying to control the velocity+position of $a$ linear actuator." (emphasis added). I had read "a" to mean "one" - meaning, I thought he was trying to do PID position control on one actuator while limiting the speed of the same actuator. I didn't realize he was trying to synch two actuators until his comment above earlier this morning. – Chuck Jun 16 '15 at 20:44