目前,我想写的一个pid用来控制正反转,我写了一个pid程序。他正转可以实现、但是翻转却疯转了。pid控制中正反转不应该是一致的吗。(我的电机正反转是用高低电平来控制的)
我尝试了把预期值和反馈量都变为正,结果还是和一开始的一样。请教一下,我到底是哪里出了问题QAQ
初始化
int want_speed_x[4];
int encoder_errorall_x[4];
int encoder_store_x[4];
float encoder_error_x[4];
float encoder_speed_x[4];
float last_encoder_error_x[4];
float encoder_kp0=0.045;
float encoder_ki0=0;
float encoder_kd0=0;
float encoder_kp1=0.045;
float encoder_ki1=0;
float encoder_kd1=0;
float encoder_kp2=0.045;
float encoder_ki2=0;
float encoder_kd2=0;
float encoder_kp3=0.045;
float encoder_ki3=0.0;
float encoder_kd3=0.0;
pid
int pid_x(int a)
{
want_speed_x[0]=-500;
want_speed_x[1]=-500;
want_speed_x[2]=-500;
want_speed_x[3]=-500;
encoder_error_x[0] = want_speed_x[0] - encoder_data[0];
encoder_errorall_x[0]+=encoder_error_x[0];
encoder_store_x[0] += (int)(encoder_kp0*encoder_error_x[0] +encoder_ki0*encoder_errorall_x[0]+ encoder_kd0*(encoder_error_x[0] - last_encoder_error_x[0]));
last_encoder_error_x[0] = encoder_error_x[0];
encoder_error_x[1] = want_speed_x[1] - encoder_data[1];
encoder_errorall_x[1]+=encoder_error_x[1];
encoder_store_x[1] += (int)(encoder_kp1*encoder_error_x[1] +encoder_ki1*encoder_errorall_x[1] +encoder_kd1*(encoder_error_x[1] - last_encoder_error_x[1]));
last_encoder_error_x[1] = encoder_error_x[1];
encoder_error_x[2] = want_speed_x[2] - encoder_data[2];
encoder_errorall_x[2]+=encoder_error_x[2];
encoder_store_x[2] += (int)(encoder_kp2*encoder_error_x[2] +encoder_ki2*encoder_errorall_x[2]+encoder_kd2*(encoder_error_x[2] - last_encoder_error_x[2]));
last_encoder_error_x[2] = encoder_error_x[2];
encoder_error_x[3] = want_speed_x[3] - encoder_data[3];
encoder_errorall_x[3]+=encoder_error_x[3];
encoder_store_x[3] += (int)(encoder_kp3*encoder_error_x[3] +encoder_ki3*encoder_errorall_x[3]+ encoder_kd3*(encoder_error_x[3] - last_encoder_error_x[3]));
last_encoder_error_x[3] = encoder_error_x[3];
motor(a,encoder_store_x[0],encoder_store_x[1],encoder_store_x[2],encoder_store_x[3]);
PRINTF("%d,%d,%d,%d,%d,%d,%d,%d\n",encoder_data[0],encoder_data[1],encoder_data[2],encoder_data[3],encoder_store_x[0],encoder_store_x[1],encoder_store_x[2],encoder_store_x[3]);
return 0;
}
电机控制
void motor(int move,int a,int b,int c,int d)
{
int A;int B;int C;int D;
A=abs(a); B=abs(b); C=abs(c); D=abs(d);
//move 0==前进 1==后 2==左 3==右
if (move==0)
{
gpio_set(D14,1);
gpio_set(D15,1);
gpio_set(D0,1);
gpio_set(D1,1);
pwm_duty(PWM2_MODULE3_CHB_D3,A);
pwm_duty(PWM2_MODULE3_CHA_D2,B);
pwm_duty(PWM1_MODULE0_CHB_D13,C);
pwm_duty(PWM1_MODULE0_CHA_D12,D);
}
if (move==1)
{
gpio_set(D14,0);
gpio_set(D15,0);
gpio_set(D0,0);
gpio_set(D1,0);
pwm_duty(PWM2_MODULE3_CHB_D3,A);
pwm_duty(PWM2_MODULE3_CHA_D2,B);
pwm_duty(PWM1_MODULE0_CHB_D13,C);
pwm_duty(PWM1_MODULE0_CHA_D12,D);
}
}
你的gpio是控制电机方向的吧 你考虑过没有 一但转速超过了目标速度你的pid结果可能需要改变方向(例如你给定的速度是负一,结果电机跑到了负二,那么新的电机给定速度方向可能会变成正的,但你的电机方向却是gpio给定的,结果就造成越差越多 越多越差 就转疯了
PID的参数只针对一种运行条件的,正转调好的参数,并不适用于反转,运行条件不一样,参数就不一样了,你需要建立两套PID参数,分别对应正反转运行,调出各自的参数。正转有正转的参数,反转有反转的参数才行。这里可以参考下:
https://blog.csdn.net/qq_19979629/article/details/123451333
Codesys使用ST语言实现离散PID模型的仿真
不能只用一个PID