# PID control: how does it work?

Hello guys,
I’m tring to do a easy mini self balancing robot but…I’m facing some issue with pid control and so I’d like to understand more on it…
first of all if I understood well when the robot is perfectly in balance I think the PID control should give me 0 value: is it right?

unlucky in my implementation does not happen as I thought: it gives me a negative value!! and so, as consequence, my robot give an acceleration to the motor and so on.
I don’t understan why…!!!
I’m using this formula for PID control:

LLastangle=Lastangle;
Lastangle=Aangle;
Aangle=ypr[1]180/M_PI;
// error is the Desired angle - actual angle
error=Dangle-Aangle;
// PID controller at 50 HZ
COcommand=COcommand-Kp
(Aangle-Lastangle)+Ki/50error-Kd50*(Aangle-2*Lastangle+LLastangle);

but it seems it doens’work !!uff.
where is the error in your opinion??

Regards
Lorenzo

I'm not in the PID part yet but are you using a stepper motor and a Big EasyDriver? I'm doing a self balancing robot also and my stepper motors wont go any faster.

Hello I'm using simply a continuos rotation servo directly driven by arduino uno

It sounds like less pain than the steppers lol

what? I don't understand !

Lorenzo

first of all if I understood well when the robot is perfectly in balance I think the PID control should give me 0 value: is it right?

The PID control algorithm maintains and continuously adjusts whatever output value the system requires to keep the balance point error to 0. That is how feedback systems in general operate.

PID does three things:

It considers the

current error situation - what you want and what it currently is - the P part
the past error situation - a sum of previous errors within a time frame so as you don’t get a big value - the I part
the anticipated future error situation - based on what has been happening it guesses what might be the case - the D part

the algorithm ‘blends’ these three components to generate a number… this number you have to find a way to map to your driver/actuator system.

PID algorithms ‘blend’ the P, I and D parts in various ways… your job is to tune this blending so that each contributes in a way that achieves sufficient response without over adjusting or adjusting too slowly… easy… not

Just as a sample here is my PID code. There are others similar. Your job is to come up with fpGain, fiGain and fdGain. Some research on Google will give you some advice how to go about finding something suitable for your needs.

_pid.h

``````#ifndef _pid_h
#define _pid_h

struct pid
{
float   fPreviousError;
float   fProportional;
float   fIntegral;
float   fDerivative;

float   fiMax, fiMin; // Maximum and minimum allowable integrator Integral
float   fiGain, // integral gain
fpGain, // proportional gain
fdGain; // derivative gain
float   fpTerm, fiTerm, fdTerm;
};

float fPIDupdate(pid *pid, float fTarget, float fMeasured, long lMicros);

#endif
``````

and _pid.c

``````#include <Arduino.h>
#include <_pid.h>

float fPIDupdate(pid *pid, float fTarget, float fMeasured, long lMicros)
{
float fOutput;
pid->fProportional= fTarget - fMeasured;

pid->fIntegral =  pid->fIntegral + (pid->fProportional * (float)lMicros);

pid->fDerivative = (pid->fProportional - pid->fPreviousError) / (float)lMicros;

pid->fpTerm = pid->fpGain * pid->fProportional;
pid->fiTerm = pid->fiGain * pid->fIntegral;
pid->fdTerm = pid->fdGain * pid->fDerivative;

pid->fPreviousError = pid->fProportional;
fOutput = pid->fpTerm + pid->fiTerm - pid->fdTerm;

if (pid->fIntegral > pid->fiMax)
pid->fIntegral = pid->fiMax;
else if (pid->fIntegral < pid->fiMin)
pid->fIntegral = pid->fiMin;

pid->fIntegral *= 0.8;

return fOutput;
}
``````

1)setting up DC motors 2)the rest of the 1) project 3) he uploaded his code and everything 4) he made one with the 2) help

Hope this helps, all my research shows it has not been done with steppers yet... any tips would be greatly appreciated. Good Luck :)

Thank you very much acboother and alvin !! very good!thanks a lot! Ok I'll try to study the code and examples !!then I'll give you my feedbacks! Many thanks again! Bye, Lorenzo

manda-rino: Hello guys, I'm tring to do a easy mini self balancing robot but...I'm facing some issue with pid control and so I'd like to understand more on it... first of all if I understood well when the robot is perfectly in balance I think the PID control should give me 0 value: is it right?

Hi mate,

in theory if the robot is still and balanced the PID will return 0, that means the motors are doing noting. But in practice there will always be small corrections so never exactly 0.

manda-rino: unlucky in my implementation does not happen as I thought: it gives me a negative value!!

If you did the code you posted directly and hoped it would work, then you did too many things at once :)

1. first you need to determine your target angle (the "DAngle" in your code). Assuming your angle sensor is well calibrated etc. Deactivate the motors and put a Serial print of the estimated angle of the robot, and manually move it until you feel it's balanced (you almost shouldn't have to hold it). The angle when balanced will be your target (DAngle). Later on you can refine this if you see your robot is drifting in the same direction all the time.

2. Start with only the P term of your PID! Start simple, make sure it works then add more things. Otherwise you'll never understand where the problem comes from. Your PID formula is very weird. Maybe it works but it doesn't make sense to me. With your variable names the PID should be something like

``````Aangle=ypr[1]*180/M_PI; // this is the angle from te sensor
error = Aangle - Dangle // Dangle is a constant you estimated, see above
COcommand = Kp * error; //COcommand is then sent to the motors
``````

You then need to map COcommand to something usable by the motors (use the "map" function).

Then try to adjust Kp until you feel the robot is trying to balance. Even with a small Kp the robot will not balance but you will feel it's trying to, means the motors will spin to try and compensate the tilt. If it's doing the opposite (accelerating the tilt) then negate the command. After you're sure the motors spin the right way increase Kp until you get decent balance. With just Kp it will only balance for a couple seconds though.

Then add Kd, the term will be something like COcommand = Kp * error + Kd * (error - last-error) (you will need to add last_error to your code)

The most important is that you understand what you're doing! After that you'll have no problems finishing the PID code (check other posts linked in this thread).

alvin2014: Hope this helps, all my research shows it has not been done with steppers yet...

It has been done, and it's possibly the most performant I've seen so far (and I've seen a few :D )