用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法。