用stm32+超声波通过pid控制小车与墙保持15cm距离

用stm32+超声波通过pid控制小车与墙保持15cm距离,打开开关后,就一上来,会来回撞墙,过一会就要么一直向后,要么一直向前了,是什么原因?
main.c


#include "stm32f10x.h"
#include "usart.h"
#include "delay.h"
#include "string.h"
#include "OLED.h"
#include "HSC4.h"
#include "PWM.h"
#include "PID.h"


void main(void)
{
//    Time_init();
    OLED_Init();
    Hcsr04Init();
    Pid_init();
    OLED_ShowString(1,1,"distance:");
    while (1)
    {
        OLED_ShowNum(1,11,Hcsr04GetLength(),3);
        Pid_op();
        Pidto_pwm();

    }
}

PID.c


#include "PID.h"
#include "HSC4.h"
#include "PWM.h"
#include "Motor.h"
struct Pid
{
    float distance;//当前距离
    float targetdistance;//目标距离
    float err; //误差
    float last_err;//上次的误差
    float kp;
    float ki;
    float kd;
    float count_err;//累积误差
    float pout;
}pid;

void Pid_init(){
    pid.kp = 300;
    pid.ki = 100;
    pid.kd = 1000;
    pid.targetdistance = 15;

}

void Pid_op(){
    pid.distance = Hcsr04GetLength();
    pid.err = pid.distance - pid.targetdistance;//计算误差
    pid.count_err += pid.err;
    pid.pout = pid.kp*pid.err + pid.ki*pid.count_err+pid.kd*(pid.err - pid.last_err);
    pid.last_err = pid.err;
}

void Pidto_pwm(){
    Motor_Init();
    if(pid.pout>0){
        if(pid.pout>500){//前进
            pid.pout = 500;
            go_forward(pid.pout);
        } else if(pid.pout<300){
            pid.pout = 150;//转换成输出
            go_forward(pid.pout);
        }
    } else if(pid.pout<0){//后退
        if(pid.pout<-500){
            pid.pout = 500;
            go_back(pid.pout);//转换输出
        } else if(pid.pout<-300){
            pid.pout = 150;
            go_back(pid.pout);//转换输出
        }

    } else if(pid.pout == 0)
    {
        pid.pout = 0;
    }





}

可能是你的PID参数设置不合适导致的。在PID控制中,kp是比例系数,ki是积分系数,kd是微分系数,它们三个之间的相对大小关系和取值范围会影响PID控制的效果。

可能是kp,ki,kd的值过大导致的。过大的kp值会导致系统过于敏感,响应过快,容易使系统震荡,而过大的ki值会导致系统积分饱和,收敛过慢。

这个问题可能是由于PID控制参数不合适导致的。在程序中,你使用了kp=300,ki=100,kd=1000来计算输出。这些值对于你的系统可能不够合适,导致小车无法稳定地保持15cm的距离。你可以尝试调整这些参数,或者使用其他的方法来确定最佳的PID参数,例如手动调节法或Ziegler-Nichols法。