Go Down

### Topic: PID control: how does it work? (Read 6187 times)previous topic - next topic

#### manda-rino

##### Nov 27, 2013, 11:04 pm
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/50*error-Kd*50*(Aangle-2*Lastangle+LLastangle);

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

Regards
Lorenzo

#### alvin2014

#1
##### Nov 28, 2013, 07:37 am
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.

#### manda-rino

#2
##### Nov 28, 2013, 07:41 am
Hello I'm using simply a continuos rotation servo directly driven by arduino uno

#### alvin2014

#3
##### Nov 28, 2013, 09:56 am
It sounds like less pain than the steppers lol

#### manda-rino

#4
##### Nov 28, 2013, 02:39 pm
what?
I don't understand !

Lorenzo

#### retrolefty

#5
##### Nov 28, 2013, 02:58 pm
Quote

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.

#### acboother

#6
##### Nov 28, 2013, 08:39 pm
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
Code: [Select]
`#ifndef _pid_h#define _pid_hstruct 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
Code: [Select]
`#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;}`

#### alvin2014

#7
##### Nov 28, 2013, 08:47 pm
Check these guys out
http://forum.arduino.cc/index.php?topic=8652.0
http://forum.arduino.cc/index.php?topic=8871.0
https://github.com/cyhex/bRobot
http://forum.arduino.cc/index.php?topic=197688.0

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

#### manda-rino

#8
##### Nov 28, 2013, 09:14 pm
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

#### Dwacito

#9
##### Nov 30, 2013, 09:11 pmLast Edit: Nov 30, 2013, 09:18 pm by Dwacito Reason: 1

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.

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

Code: [Select]
`  Aangle=ypr[1]*180/M_PI; // this is the angle from te sensorerror = 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)

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).

----------------------------------------

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 )

#10