ADD EXAMPLES OF THE MATH BEHIND THIS!

Housekeeping

close all; clear; clc; s = tf('s');

Suppose we wish to control a system with one pole (in the LHP) and one zero (in the RHP), with both quite close to the origin. Let's find the maximum gain we can apply before it becomes unstable.

t = 0:0.01:60;
 
p = -1;
z = +1;
 
Plant = (s-z)/(s-p)
Plant = s - 1 ----- s + 1 Continuous-time transfer function. Model Properties
 
minGain = 0.1;
maxGain = 10;
stepGain = 0.01;
gains = minGain:stepGain:maxGain;
 
for k=minGain:stepGain:maxGain
Controller = k;
System = feedback(Controller*Plant,1);
poles = pole(System);
 
if poles>0
maxK = k;
break
end
end
 
 
f1 = figure(); f1.Position = [0 0 1600 600];
 
subplot(1,2,1); title('Pole Zero Map'); hold on;
scatter(real(p), imag(p), 150, 'x', 'k', 'LineWidth', 1); hold on;
scatter(real(z), imag(z), 150, 'o', 'k', 'LineWidth', 1); hold off;
xline(0); xlim([-2 2]);
yline(0); ylim([-2 2]);
 
subplot(1,2,2); title('Step Response[s]'); hold on;
step(feedback(0.95*maxK*Plant,1), t); hold on;
step(feedback(1.05*maxK*Plant,1), t); hold off;
legend('gain<max','gain>max', 'Fontsize', 12, 'Location', 'southwest');
text(35, -10, 'Gain < '+string(maxK), 'FontSize', 15);
text(35, -50, 'Gain > '+string(maxK), 'FontSize', 15);

Here we can see that a gain of roughly 1 is the best we can do, and even values slightly greater than 1 will cause the system to becomes unstable. Not only that, but our response is negative!

Suppose now that our situation is such that the only controller in our "toolbox" is a proportional controller. How then do we achieve a suitable response? The answer in our case, may be FEEDFORWARD CONTROL.

Feedback Only.png

Here we confirm the response the above feedback example produces an equal response to the MATLAB code.

t_start = 0;
t_step = 0.01;
t_stop = 60;
t = t_start:t_step:t_stop;
 
r_mag = 1;
r_t = r_mag*ones(length(t),1);
r = timeseries(r_t,t');
 
FFgain = 0;
 
f1 = figure(); f1.Position = [0 0 800 600];
 
k = 0.95*maxK;
simout = sim('FeedforwardExample.slx');
time = simout.tout;
resp = simout.y.Data;
plot(time, resp); hold on;
 
k = 1.05*maxK;
simout = sim('FeedforwardExample.slx');
time = simout.tout;
resp = simout.y.Data;
plot(time, resp); hold off;
 
title('Step Response');
xlabel('time (s)');
ylabel('amplitude');

Now, for our feedforward example, we will choose a negative gain of simply -1 to reverse the reversing effect of the RHP pole.

Simple Feedforward.png

The total transfer function of this system can be described by: where is the feedback gain and is the feedforward gain.

f2 = figure(); f2.Position = [0 0 800 600];
 
FFgain = -1;
 
k = 0.95*maxK;
simout = sim('FeedforwardExample.slx');
time = simout.tout;
resp = simout.y.Data;
yline(1, '--'); hold on;
plot(time, resp); hold on;
xlim([0 300]);
ylim([-0.2 1.2]);
 
title('Step Response');
xlabel('time (s)');
ylabel('amplitude');

Based on this example, a simple feedforward controller can essentially reverse the effect of a pole in the RHP by forcing a positive response and generating a stable response. Unfortunatley the response is currently quite slow. Interestingly enough, a solutin to this problem is to actually ofload more of the control work to the feedforwar controller by DECREASING the feedback gain value.

f3 = figure(); f3.Position = [0 0 800 600];
 
FFgain = -1;
 
k = 0.95*maxK;
simout = sim('FeedforwardExample.slx');
time = simout.tout;
resp = simout.y.Data;
yline(1, '--'); hold on;
plot(time, resp); hold on;
xlim([0 300]);
ylim([-0.2 1.2]);
 
title('Step Response');
xlabel('time (s)');
ylabel('amplitude');

Almost counter-intuitively, by DECREASING the gain inside our feedback loop, we can leave the pole further in the LHP and increase our response time. In this way the bulk of the control is then driven by the feedforward gain rather than the feedback gain.

ADD EXAMPLES OF THE MATH BEHIND THIS!

f4 = figure(); f4.Position = [0 0 800 600];
 
FFgain = -1;
 
for k = maxK*(0:0.3:0.9)
simout = sim('FeedforwardExample.slx');
time = simout.tout;
resp = simout.y.Data;
plot(time, resp, 'DisplayName', 'k='+string(k)); hold on;
end
yline(1, '--', 'DisplayName', 'input'); hold on;
xlim([0 30]);
ylim([-0.2 1.2]);
title('Step Response');
xlabel('time (s)');
ylabel('amplitude');
legend();

As we can see in this example, the lower the gain the faster our response time! By analyzing our system however, this makes intuitive sense as the feedback gain will push the pole closer to the zero in the RHP, slowing it's response. Counterintuitively, by using gains less than one (or even equal to zero!) we can actually increase our system response time!

It may be tempting to ask yourself then, "What if we simply made the feedback gain negative! Then we might not even need the feedforward gain!". Considering our transfer function however, by setting we can arrive at: , which when applying we arrive at: which, being an improper system notwithstanding, would have 50% steady state error as shown.

f5 = figure(); f5.Position = [0 0 800 600];
 
FFgain = 0;
 
k = -0.95*maxK; % gain is now negative!
simout = sim('FeedforwardExample.slx');
time = simout.tout;
resp = simout.y.Data;
yline(1, '--'); hold on;
plot(time, resp); hold on;
xlim([0 30]);
ylim([-0.2 1.2]);
 
title('Step Response');
xlabel('time (s)');
ylabel('amplitude');

From this we can conclude that for at least some systems that have zeros in the RHP, simple feedforward control is a viable solution to the "reverse-response" effect, and minimizing our feedback gain results in a system with a faster response.

All with controllers no more complex than proportional control!

NOTE: Proportional controllers with negative gain may sound odd, but consider the following examples:

Hydraulic:

- Hydraulic systems with input/output cylinders in opposite directions

Mechanical:

- Levers (each side will go in the opposite direction)

- Gears (paired gears will rotate in opposite directions

Electrical:

- Inverting amplifiers