# Proportional Control Balance Beam

Bit of an unorthodox question I'm sure, but I'm making a balance beam (two rotors on either end of a see saw) with proportional control, and I can't seem to get it to balance at 0.

The proportional gain is controlled via a potentiometer, but there is no 'sweet spot' between oscillation and insufficient motor correction around 0, meaning the beam either oscillates wildly around 0, or the gain is too small and the beam drifts and settles around 5-10 degrees either side. The odd thing is if I set it to go to another angle that isn't 0 it settles no problem.

The values being read from the IMU are fine (it knows it's settling at 5 degrees, it doesn't think it's 0). The sample rate of the IMU matches the update rate of the motors too, so it's not that the I'm feeding the motors old data.

I've tried to take measures to reduce external forces acting on it too, such as the weight of components and turbulence, but to no effect.

I know I can introduce integral control and that will correct against this slight drift, but I'd really like to have this balancing using just proportional - oscillating slightly either side of 0.

My code is in the format:

float error = sqrt(roll*roll);
Positive_esc = 0.15 + (error*Kp);
Negative_esc = 0.3 - Positive_esc;

if(roll<0){
LeftMotor = Positive_esc;
RightMotor = Negative_esc;
}
if(roll>0){
LeftMotor = Negative_esc;
RightMotor = Positive_esc;
}


Where both motors signals add to make 0.3.

I'm aware there's no definitive answer to this question, but I'm just looking for some creative thinking/some things I might not have considered, because I'm fully stumped on this one.

UPDATE to include transfer functions of response:

UPDATE to include graph of response

As can be seen, the beam will sit quite happily around 3 degrees. However, what concerns me is the positive correction when the error is already positive (can be observed most prominently around t=230).

• you gotta turn the GAIN way down, and slow down the system; and accept the final errors. – analogsystemsrf Mar 22 at 17:32
• Inability to maintain a zero, when an offset is easier to maintain, usually indicates the need to introduce an integrator into the control loop. – Chu Mar 22 at 18:07
• some details of your rotor/motors might help us: are they servos?...are they slow?...do they exhibit "stiction"? – glen_geek Mar 22 at 18:14
• A sketch would be nice. – TimWescott Mar 22 at 19:59
• Hi. Thanks for the comments on this. I'm aware that a integrator should be introduced into the control loop, and would probably help resolve (or reduce) this issue, but I would like to get the beam oscillating around 0 using just proportional. @Chu are you suggesting this is impossible/very hard to do? – el16a2t Mar 25 at 15:10

simulate this circuit – Schematic created using CircuitLab

Figure 1. Proportional and "anti-proportional" gain control where both motors sum to unity.

I'm no expert but I would be doing something like this:

// e is the error, Kp is proportional gain
MotorA = 0.5 + Kp * e         // 50% power at zero error
if (MotorA < 0) {MotorA = 0}  // Don't go below 0%
if (MotorA > 1) {MotorA = 1}  // Don't go above 100%
MotorB = 1 - MotorA           // Sum to 100%


At balance the motors will run at 50%.

float error = sqrt(roll*roll);
Positive_esc = 0.15 + (error*Kp);
Negative_esc = 0.3 - Positive_esc;

if(roll<0){
LeftMotor = Positive_esc;
RightMotor = Negative_esc;
}
if(roll>0){
LeftMotor = Negative_esc;
RightMotor = Positive_esc;
}


This code gives the following transfer functions.

simulate this circuit

Figure 2. The upgraded code has major issues.

Note that your Positive_esc and Negative_esc are not complimentary. The big problem is the major discontinuity of the left and right motor drives around the zero point.

Did you try my suggested code?

• Hi @Transistor. I tried your suggested code, but as it is simply the same as mine (however with a clamp at the minimum and maximum drive limits - very useful and sensible addition, thanks very much) I observed a very similar response. In your diagram (b) is incorrect - Negative_esc will never be greater than 0.15. In fact at 0, both Positive_esc and Negative_esc will be 0.15, so there is continuity of both motor drives around the 0 point. I will update the question to include these transfer functions. – el16a2t Mar 26 at 13:41

Because

$$A = \begin{cases} k_p \cdot error & error > 0 \\ \frac{1}{2} - k_p \cdot error & \text{otherwise} \end{cases}$$ and $$B = \begin{cases} \frac{1}{2} - k_p \cdot error & error > 0 \\ k_p \cdot error & \text{otherwise} \end{cases}$$

In other words, you have honkin' big discontinuities in your motor drives. Even if this would otherwise lead to correct behavior (which I doubt), the motors are going to go crazy close to zero error.

("honkin' big" = American slang for "very big".)

simulate this circuit – Schematic created using CircuitLab

Figure 1. Graphical representation showing discontinuities. (Added by @Transistor.)

• @Transistor if I'm reading the OP's code right, B goes negative. I'm not sure that's the intent -- your graph (thank you, but!) would work if they're using the absolute value of $error$ when it is negative. – TimWescott Mar 23 at 16:00
• Agreed. I've redrawn it, paying much more attention to the equations. B would go in reverse, if possible for a negative error or stop if it's clamped at zero. Does that agree with your equations now. I've never come across your notation style before. Does it have a name? – Transistor Mar 23 at 16:28
• @Transistor you mean this: $\begin{cases} 3 & 0 < x < 4 \\ 0 & \text{otherwise} \end{cases}$? I'm not absolutely sure what the official name is, but I'm almost certain it's "piecewise". It's pretty common in the technical literature -- you should have run across it even in advanced algebra or calculus. In LaTeX you use the "cases" environment. – TimWescott Mar 23 at 16:57
• That's it. It may not have been invented when I was studying. Thanks. – Transistor Mar 23 at 16:59
• Sorry for the confusion, caused by me oversimplifying my code for the sake of demonstration. Neither motor signal is ever negative, and 'error' is an absolute value. Essentially both motors sum to x, and if the tilt is one way Motor A = 0.5x + (Kp * error). If the tilt is the other way Motor B = 0.5x + (Kp * error). The other motor in both cases, as @Transistor phrased it, observes 'anti-proportional' gain. In short, the signal of one motor increases proportional to the error and the signal of the other decreases proportional to the error, so that they always sum to 'x'. – el16a2t Mar 25 at 15:30