# Balancing robot - Tuning

We are doing a balancing robot in a school project which we are almost done with. The last part is to tune the robots's pid and to implement a steering control through an ESP8266 WiFi. The trouble we have is that the robot start oscillating back and forward along the targetAngle. The targetAngle is calculated through a PI based on the speed of the motors which is received from an encoder, but the robot still overdue the targetAngle and then starts to go back and forward until it reach full speed an falls. How do we solve the problem, by tuning the PID and PI or by implementing something else? (See video and part of the code below, in the next post posted by me) Thanks in advance

Balancing robot project video

(Edit) Code removed and moved to my next post.

The code fragment you posted is completely useless. Edit your post to include the entire code, posted using code tags.

There is this project a friend of mine did: Balance Bot. See if it helps in some way.

The following code is the velocity PID that calculates the TargetAngle based on the targetVel which is 0. This makes it possible for the robot to balance even though the centre of gravity isn't in the middle. This should also prevent the robot from oscillate back and forth.

``````double targetVel = 0;
double velError;
double integralVel;
double lastVelError;
double piSum;

double kiVel = 0.0005;
double kpVel = 0.009;

void velocityPi() {

velError = targetVel-wheelVel;
integralVel = integralVel + velError*kiVel;
lastVelError = velError;
TargetAngle = velError * kpVel + integralVel;
//TargetAngle is the output of the velocity PID, and is sent to the balancing pid.
}
``````

And this is the PID for balancing

``````void loopPid()
{
CurrentAngle = ypr[2] * 180/M_PI;
error = TargetAngle - CurrentAngle;
integral = integral + error*ki;
derivative = (error - lastError)*kd;

lastError = error;
pidsum = error*kp+derivative+integral;

if(pidsum>0)
{
digitalWrite(rightEngine1, LOW);
digitalWrite(rightEngine2, HIGH);

digitalWrite(leftEngine1, LOW);
digitalWrite(leftEngine2, HIGH);
}
else if (pidsum<0)
{
digitalWrite(rightEngine1, HIGH);
digitalWrite(rightEngine2, LOW);

digitalWrite(leftEngine1, HIGH);
digitalWrite(leftEngine2, LOW);
}

analogWrite(rightEnginePwm, 30+(abs(pidsum) * 5)*1);
analogWrite(leftEnginePwm, 30+(abs(pidsum) * 5)*1);
}
``````

The problem is still left that it starts oscillate back and forth as on the video in the first post. Does anyone know how to prevent it from going back and forth?

Unintentional oscillation is due to improper tuning or inadequate electromechanical design. Kp may be much too high, or the motor/motor power behavior is too nonlinear for PID to compensate.

What are the magic numbers 5, 30 and 1 doing in the motor analogWrite() call? Where do you check for excessive values for PWM?

Create a GUI using the Tkinter library in Python with sliders for the PID gains. Send these gain values dynamically to your robot, and tune the values in run time. This would make the tuning process a ton easier and you would get better results.

jremington: Unintentional oscillation is due to improper tuning or inadequate electromechanical design. Kp may be much too high, or the motor/motor power behavior is too nonlinear for PID to compensate.

What are the magic numbers 5, 30 and 1 doing in the motor analogWrite() call? Where do you check for excessive values for PWM?

Yes, we removed + 30 PWM. What do you mean with excessive values for PWM? If it is over 255, it will only send 255 anyway.

It works pretty well without the second PI (PID without derivative), but the targetAngle needs to be exact in order for it to stand still. While using the second PI-loop for velocity (targetVelocity = zero) it doesn't correct itself fast enough, but if we raise the PI values it will start oscillating as of the targetAngle changes to much. How do we fix so it will try reach zero speed faster, without starting to oscillate because of the overreaction in targetAngle while it tries to correct itself. Should we use derivative aswell in the second PI loop?

Remove the "5" as well, and go through the tuning process again.

For PID to work properly, almost all of the values sent to analogWrite() must be in the range of 0-255, with resolution (increments) of 1, if possible.

The "5" makes the latter impossible.

This is how it looks right now after we removed the static PWM and adjusted some values. It does still start to oscillate.

Balancing robot project video (Sorry for the small screen, uploaded it from my mobile)

Obviously, it is not tuned correctly, or you have one or more serious program errors (wrong sign of derivative, etc.).