# [embedded code] Application of PID balance control in intelligent patrol robot

Attitude balance control

Adding speed negative feedback to vertical control can not achieve the purpose of speed closed loop, but also destroy the vertical control system. Therefore, under the condition of ensuring the priority of vertical control, developers should put speed control in front of vertical control, that is, the result of speed control adjustment is only to change the target value of vertical control.

According to experience, the running speed of the trolley is related to the inclination angle of the trolley. For example, to increase the forward speed of the trolley, it is necessary to increase the forward tilt angle of the trolley. After the tilt angle increases, the wheels need to move forward under the vertical control to keep the trolley balanced and the speed increases; If you want to reduce the forward speed of the trolley, you need to reduce the forward tilt angle of the trolley. After the tilt angle is reduced, the wheels move backward under the action of vertical control to maintain the balance of the trolley and reduce the speed.

Developers connect the speed and vertical controllers in series, in which the output of speed control is used as the input of vertical control and the output of vertical control is used as the output of the system, which is actually a cascade control system. PD control is used for vertical control. Because of the possible noise of the encoder, in order to prevent the noise from being amplified and eliminate the static error of the system, PI control is used for speed control here.

Vertical PD control

```int balance(float Angle,float Gyro)
{
float Bias;
int balancePID;
Bias=Angle-Angle_OFFSET;                       //===Calculate the median angle of balance and mechanical correlation
balancePID=Balance_Kp*Bias+Gyro*Balance_Kd;   //===Motor PWM PD control with calculated balance control    kp is the P coefficient and kd is the D coefficient
return balancePID;
}```

Speed PI control

```int velocity(int encoder_left,int encoder_right)
{
static float Velocity,Encoder_Least,Encoder,Movement;
static float Encoder_Integral,Target_Velocity;
//=============Remote control forward and backward section=======================//
Target_Velocity=40;
if(Direction.Current==GO_STRAIGHT)      Movement=-Target_Velocity/Flag_speed;           //===Forward sign position 1
else if(Direction.Current==GO_BACK) Movement=Target_Velocity/Flag_speed;         //===Reverse flag position 1
else  Movement=0;
//=============Speed PI controller=======================//
Encoder_Least =(encoder_left+encoder_right)-0;
Encoder *= 0.8;                                                     //===First order low pass filter
Encoder += Encoder_Least*0.2;                                       //===First order low pass filter
Encoder_Integral +=Encoder;                                       //===Integration out displacement integration time: 10ms
Encoder_Integral=Encoder_Integral-Movement;                       //===Receive remote control data and control forward and backward
if(Encoder_Integral>8000)   Encoder_Integral=8000;             //===Integral limiting
if(Encoder_Integral<-8000)  Encoder_Integral=-8000;              //===Integral limiting
Velocity=Encoder*Velocity_Kp+Encoder_Integral*Velocity_Ki;        //===Speed control
if(Turn_Off(Angle_Balance,BAT_VOL)==1||Direction.Current==TURN_OFF)
Encoder_Integral=0;
return Velocity;
}```

Steering control

In addition to maintaining balance, the trolley also involves left and right rotation, so steering control needs to be added, which can be referred to as follows

```int turn(int encoder_left,int encoder_right,float gyro)//Steering control
{
static float Turn_Target,Turn,Encoder_temp,Turn_Convert=0.9,Turn_Count;
float Turn_Amplitude=30/Flag_speed,Kp=32,Kd=0;
if(Direction.Current==TURN_LEFT||Direction.Current==TURN_RIGHT)
{
if(++Turn_Count==1)
Encoder_temp=myabs(encoder_left+encoder_right);
Turn_Convert=50/Encoder_temp;
if(Turn_Convert<0.6)Turn_Convert=0.6;
if(Turn_Convert>3)Turn_Convert=3;
}
else
{
Turn_Convert=0.9;
Turn_Count=0;
Encoder_temp=0;
}
if(Direction.Current==TURN_LEFT){
Turn_Target+=Turn_Convert;
}
else if(Direction.Current==TURN_RIGHT){
Turn_Target-=Turn_Convert;
}
else Turn_Target=0;

if(Turn_Target>Turn_Amplitude)  Turn_Target=Turn_Amplitude;    //===Steering speed limiting
if(Turn_Target<-Turn_Amplitude) Turn_Target=-Turn_Amplitude;
if(Direction.Current==GO_STRAIGHT||Direction.Current==GO_BACK||Direction.Current==KEEP_STOP)
Kd=-1 ;
else
Kd=0;
//=============Steering PD controller=======================//
Turn=-Turn_Target*Kp-gyro*Kd;                 //===PD control combined with Z-axis gyroscope
return Turn;
}```

Motor PWM control

After the above series of control calculations, the developer obtains the PWM value to balance the trolley (Moto1 and Moto2 in the following program).

```    Balance_Pwm = balance(Angle_Balance,Gyro_Balance);//===Balanced PID control
Velocity_Pwm= velocity(Enconder_left,Enconder_right);//===Speed loop PID control
Turn_Pwm   = turn(Enconder_left,Enconder_right,Gyro_Turn);//===Steering ring PID control
Moto1=Balance_Pwm+Velocity_Pwm-Turn_Pwm;//===Calculate the final PWM of the left wheel motor
Moto2=Balance_Pwm+Velocity_Pwm+Turn_Pwm;//===Calculate the final PWM of the right wheel motor
Limit_Pwm();                            //===PWM limiting
Set_Pwm(Moto1,Moto2);                   //===Assigned to PWM register ```

By giving the PWM amplitude to the corresponding register, you can view the actual motion state of the trolley.

```void Set_Pwm(int moto1,int moto2)
{
if(moto2>0)     {AIN2_RESET;AIN1_SET;}
else            {AIN2_SET;AIN1_RESET;}
TIM16_PWM_Set(myabs(moto2));
​
if(moto1>0) {BIN1_RESET;BIN2_SET;}
else        {BIN1_SET;BIN2_RESET;}
TIM17_PWM_Set(myabs(moto1));
}
​```

Keywords: pid

Added by markbm on Sat, 04 Sep 2021 04:39:14 +0300