0
\$\begingroup\$

I have built for myself an inverted pendulum balancer. It comprises a straight, horizontal metal track upon which rides a carriage which is driven by a stepper motor. The pendulum is mounted on the carriage. It balances very well, even being tolerant of modest poking with a careful finger or thumb.

The balancing part is achieved by using a traditional PID control algorithm ("Balancer").

Sometimes the Balancer is able to find perfect balance (it strikes upon a position where friction in the pendulum's pivot basically causes the pendulum to come to rest at exactly vertical, which is great). More often though the carriage reaches a steady state by gliding to left or right very slowly. I understand this behaviour and I wish to find a way to counteract it. Naturally, this gliding eventually causes the pendulum to reach the end-stop of the track (left or right) and the system stops.

My approach so far has been to create a second PID control algorithm ("Centralizer") in parallel with the Balancer. In other words the two PID controller equations are simply added together to provide a combined effect.

This Centralizer uses the centerpoint of the linear track as the zero set-point. The position of the carriage is the error relative to this zero set point. I have not been able to tune this Centralizer PID algorithm to work in harmony with the Balancer PID algorithm.

I realise that these two PID controllers will interact with eachother because they are both feeding back into the same system. So with this in mind I have given the Balancer more influence over the system, and the Centralizer much less influence. If the Balancer can't do it's job then there's no point centering the carriage!

Is my approach to this problem sane? I feel that my PID controllers are competing with eachother rather than cooperating. I have been playing with different coefficients for the Centralizer PID controller all day, large values, small values, even very tiny values. All to no avail.

I understand there are MANY variables at play here, I'm hoping someone can give me some rule of thumb, or an intuitive nudge in the right direction. I'm 90% happy with this project and am ready to call it a day but if I can get it to balance the pendulum and also have a tendency to centre itself in the middle then it would be the icing on the cake.

This is a hobby project, just something for fun and learning.

Thank you.

\$\endgroup\$
1
  • 1
    \$\begingroup\$ It is possible to do a successful balancer PID that seeks to zero velocity rather than position...OP may have done this. Offsets in the feedback loop cause it to drift to one end. Another integration may be required in the feedback loop of the existing PID to eliminate drift...OP's second loop might do this. Re-doing the loop including another integrator isn't a trivial task. This isn't an answer, because not enough loop details are included in the question. \$\endgroup\$
    – glen_geek
    May 21, 2023 at 16:38

2 Answers 2

0
\$\begingroup\$

I have finally managed to solve the problem.

I decided not to use a second PID controller, but instead modify the balancing PID controller to take into account the position of the carriage on the track.

To each of the P, I and D terms of the balancer, I added a very tiny proportion of the X-Axis position of the carriage.

This took several days of frustrating experimentation, but eventually it settled down and is now working better than I could have imagined.

Here is a small exerpt of my C language program that runs the stepper motor now...

void PID()
{
  //------ Proportional term...

  //Since we're seeking zero (12 o'clock) and increases
  //clockwise, the angle *is* the error.

  balance_error = ((float)angle) + (xpos * 0.000010f);

  //----------------------------------------------- Integral term...

  balance_integral = balance_integral + (balance_error * Td) + (xpos * 0.00001f);

  if((balance_error < -50.0f) || (balance_error > 50.0f))
    balance_integral = 0;

  //----------------------------------------------- Derivative term...

  balance_derivative = ((balance_error - balance_prev_error) + (xpos * 0.005f) ) / Td;
  balance_prev_error = balance_error;

  //----------------------------------------------- Final sum...

  motor_speed += (balance_Kp * balance_error)
               + (balance_Ki * balance_integral)
               + (balance_Kd * balance_derivative)
               ;   
}

The thing to look for here is xpos and the very tiny numbers I'm multiplying it by, while adding it to each of the P, I and D terms.

Of course this is entirely dependant on my hardware. But it does work incredibly well now. I have it running beside me as I write this. It has been running continuously for well over 20 minutes and is showing signs of interesting periodic behaviour.

Sometimes it settles on a slow left and right movement (which is reminiscent of a Cobra snake doing its dance), sometimes it gets very close to a perfect balance. And then it will change its mind and revert to the other behaviour. It is entirely obvious that its stable behaviour is somewhat chaotic and I'm totally happy with that. I can still interact with the pendulum by moving it by hand, or even lifting the entire apparatus gently off the table and still it manages to compensate for the disturbances.

Job done.

\$\endgroup\$
0
\$\begingroup\$

You can use nested PID controllers.

The inner loop controller is your existing pendulum balancer. It controls cart position and keeps the pendulum upright or at some other angle (setpoint) as requested by the outer loop controller.

The outer loop controller is the centralizer. It controls the linear acceleration of the pendulum by requesting it to be held at an angle. If the outer loop controller wants the pendulum to accelerate to the right with 1m/s², it instructs the inner loop controller to hold the pendulum at an angle of

$$ \text{atan}\left(\frac{1\frac{m}{s^2}}{9.81\frac{m}{s^2}}\right)=5.8°. $$

The outer loop controller uses pendulum position for the error variable. It does not attempt to centralize the cart, it centralizes the pendulum! More precisely, the error variable is the linear position of the pendulum's center of gravity, which can be calculated from cart position, pendulum angle and half the pendulum's height (or full height for a lightweight rod, heavy tip pendulum).

With this type of nested controller you should get a fairly agile system that can quickly move back and forth between linear positions (step change on the linear position setpoint) while keeping the pendulum upright. When accelerating, the pendulum leans into the linear motion like a motorcyclist leans into a turn.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.