作为四轴飞行器的小白,机缘巧合我们参加国赛的三个组被迫选择四轴飞行器的控制类题目。当时四轴所有的东西都是我一手配置,对于四轴界的小白当时逛了整整两天淘宝,看了许多配置四轴的帖子。这里提出几点个人这么久调试四轴对于当初购买元件的心得:
1.作为大四轴作为电机驱动的电调,这里一定不能节省,一定买个好点的牌子电调。作为学生党当初为了尽量省钱买了一个没有牌子的电调,这里电机的调试发现电机控制很粗糙怎么调试程序都达不到理想的效果,后来和网上的朋友交流发现他的程序和我的几乎一样,后来才发现是电调的问题。
2.还有一个就是电机的选择,我自己选择的是新西达的电机,只因为便宜啊!经济条件好的小伙伴电机还是选择好的,四轴总结一句话就是烧钱。会给你后期调试PID带来很大的好处。电机越好控制效果越精准,转速差异就越小。这里还有就是电机和浆的配置这个网上有很多普及的帖子在这就不细谈了。
3.其他的对于机架和电池大家尽量考虑满足要求越轻越好,这里也不过多介绍。
下面是我要和大家分享的也是我在这一个月里面折磨我最久的PID算法的问题,经过多番调试开始我们使用单纯的位置形PID很难达到很稳定的效果。于是在网上各种找他人的四轴算法的介绍。最终我们决定用串级PID。单纯的位置型还是模模糊糊,刚开始来个串级PID弄得我们云里雾里,一方面网上能看懂的代码资源太少,只能不断的找文字说明的帖子,把程序拼揍了出来,最后经过多番修改,折磨了一个礼拜的时间。最后终于达到了稳定的效果,串级PID的稳定效果确实很不错。这里我的机架子是X型机架(F330),调试完全与+字不同,这里给个帖子给大家参考,有详细介绍。http://www.amobbs.com/thread-5554367-1-1.html 这里也感谢这位网友帖子对我的帮助。我一直相信被帮助然后传播这种分享,会让我们在学习的路上少走更多弯路。下面贴上我们调试的PID代码,希望能对正在搞串级PID的小伙伴有点帮助,也希望大家发现错误给我指出,这个算法的问题是还是偶尔会出现PID死角,飞机失控,一边电机极速加速。尚未解决。。希望有小伙伴解决了这个问题的给点提示。
[mw_shl_code=c,true]float X,Y,Z; //定义角度设定值
float AX,AY,AZ; //角度实际值
float GZ; //定义Z轴内环设定值
float err_ox,err_oy; //定义外环差值
float err_ix,err_iy,err_iz; //定义内环差值
float err_last_x_out,err_last_y_out; //定义外环上一次的偏差值
float err_last_x_in,err_last_y_in,err_last_z_in; //定义内环上一次的偏差值
//-----------------------------------------------
void intheback(void)//回中平衡设定值
{
X=0.0,Y=-1.0,Z=0.0;
GZ=0.0;
}
char pid_f_out=1,pid_f_in=1;
void PID_init(void)
{
intheback();
// pid.max=30; pid.min=-30;
//X、Y轴外环P、I、D参数
pid.Kp_x_out=6.5; pid.Kp_y_out=6.5;
pid.Ki_x_out=0.0; pid.Ki_y_out=0.0;
pid.Kd_x_out=0.0; pid.Kd_y_out=0.0;
//三轴内环P、I、D参数
pid.Kp_x=3.9; pid.Kp_y=3.9; pid.Kp_z=0.0;
pid.Ki_x=0.0; pid.Ki_y=0.00; pid.Ki_z=0.00;
pid.Kd_x=(-3.51); pid.Kd_y=(-3.500); pid.Kd_z=0.0;
}
//内外环积分
float xi_out,yi_out;
float xi_in,yi_in,zi_in;
//设置积分分离标志位,使系统调节更稳定
char inde_x_out=1,inde_y_out=1;
char inde_x_in=1,inde_y_in=1,inde_z_in=1;
//内外环输出
float Out_X,Out_Y;
float Out_x,Out_y,Out_z;
void PID_contrl(float x,float y,float z,float gx,float gy,float gz)
{
//************外环控制*********************************************************************************************************
//输入实际值
AX=x; AY=y; AZ=z;
//采用位置型PID,积分采用梯形积分
//计算外环误差(PD)
err_ox=X-AX; //if(abs(err_ox)>0.05) inde_x_out=0; else inde_x_out=1; //积分分离,如果误差过大(这里为两毫秒变换0.05度=每秒25度)
// xi_out+=err_ox; //取消积分调控
// if(xi_out>20) {xi_out=20;} if(xi_out<-20) {xi_out=-20;} //积分限幅
Out_X=pid.Kp_x_out*err_ox+pid.Kd_x_out*(err_ox-err_last_x_out); //pid.Ki_x_out*inde_x_out*xi_out/2;
err_last_x_out=err_ox;
err_oy=Y-AY; //if(abs(err_oy)>0.05) inde_y_out=0; else inde_y_out=1;
// yi_out+=err_oy;
// if(yi_out>20) {yi_out=20;} if(yi_out<-20) {yi_out=-20;} //积分限幅
Out_Y=pid.Kp_y_out*err_oy+pid.Kd_y_out*(err_oy-err_last_y_out); //pid.Ki_y_out*inde_y_out*yi_out/2;
err_last_y_out=err_oy;
//*************内环控制**********************************************************************************************************
//内环误差(PID)
err_ix=Out_X-gx;
xi_in+=err_ix;
if(xi_in>30) {xi_in=30;} if(xi_in<-30) {xi_in=-30;} //积分限幅
Out_x=pid.Kp_x*err_ix+pid.Ki_x*inde_x_in*xi_in/2+pid.Kd_x*(err_ix-err_last_x_in);
//限制调解PWM的值
if(Out_x>600) Out_x=600;
if(Out_x<-600) Out_x=-600;
err_last_x_in=err_ix;
err_iy=Out_Y-gy;
yi_in+=err_iy;
if(yi_in>30) {yi_in=30;} if(yi_in<-30) {yi_in=-30;} //积分限幅
Out_y=pid.Kp_y*err_iy+pid.Ki_y*inde_y_in*yi_in/2+pid.Kd_y*(err_iy-err_last_y_in);
//限制调解PWM的值
if(Out_y>600) Out_y=600;
if(Out_y<-600) Out_y=-600;
err_last_y_in=err_iy;
//Z轴参数还未调试
err_iz=GZ-gz;
zi_in+=err_iz;
Out_z=pid.Kp_z*err_iz+pid.Ki_z*zi_in/2+pid.Kd_z*(err_iz-err_last_z_in);
err_last_z_in=err_iz;
PID_PWM(Out_x,Out_y,Out_z);
}[/mw_shl_code]
|