关于如何制作,制作的原理,网上已经有一大堆博主大神给与了回答,随便搜一搜就是一把一把,所以我在这里(也不算传授)就说说我调节PID的时候的的调节方法吧。当然最开始需要基础准备的。(大神的话,貌似用不着我这讲解了)
基础准备
1.(针对我这样的渣渣说的)这里有一个很重要的点就是AD采集电路中变阻器的电路连接,基本人人都知道滑动变阻器其实就是接两个脚就行了,但是这里就有一个问题了如图
这里你按照平常的接法是行不通的,所以必须接三根线(我试过了两根线能测得霍尔传感器的值,但是调节滑动变阻器没有反应,聪明的你肯定知道原因的)。
2.AD采集,当电路连接好以后,电压很大,或者很小,别先急着下定论,很有可能是因为滑动变阻器值没调好,可以把滑动变阻器的值得到的定压事先调节到2.4v左右。如果电路没问题,调节滑动变阻器,可以改变采集的AD数值。
3.模型的搭建,这个很多都说过了,我也没啥说的(比起大佬,差的远,太远 无奈)
PID调节
代码部分我就不说了,重要的就是频率问题。直接进入主题,说起PID调节,应该玩过平衡车什么的都很熟悉吧,而对于磁悬浮来说,这个需要调节两个PID,x轴和轴,但是也和你的硬件有关,假如你的硬件做的完美,那么你就用一套PID就行,如果和我一样是个硬件渣渣,那么久老实一个轴,一个轴来调。
这里又有一个问题,强磁铁是需要浮在空中的,一条轴一条轴来调似乎是不现实的,但是也不是没有可能,我是这么调的
首先把两个PID的值设置成一样,然后慢慢调节P值(这题目关键就在P值),调节到一种什么情况呢,就是小了完全感受不到线圈的拉力,大一点点就都得剧烈(最好调到最适合的P值),然后课看到浮子,在空中,来回那么两下,这时候就进入的初步阶段的。
然后我们需要进行分开调试,这时候你得用手充当固定的一个轴的力,但是记住,别卡死,要很松,就是不给它掉下去,然后对另外一轴进行精调,调节D值,如果过程中觉得还是抖的有点剧烈,可以尝试减小P值(到最适合的),继续调节D值,调到什么程度呢,就是你看到浮子不晃动了,或者轻微晃动。然后另外一个轴也是一样的调节方法。当你两个轴都调完的时候,合在一起,恭喜你,可以开始悬浮几秒钟了,想悬浮的久的话,还需要继续调节,这个时候就视情况而调节了。
主函数
while(1)
{
x_temp=AD_get(ADC_Channel_1,50,130,150);
y_temp=AD_get(ADC_Channel_2,50,170,190);
x_error=X_f-x_temp;
y_error=Y_f-y_temp;
if(x_error>=0)
{
A_po();//A正向输出
flag = 1;
printf(" 输出正 ");
}
else
{
A_ag();
printf(" 输出负 ");
}
if(y_error<=0)
{
B_po();//B正向输出
printf(" 输出正 ");
}
else
{
B_ag();
printf(" 输出负 ");
}
x=PID(0,X_f,x_temp);
y=PID(1,Y_f,y_temp);
TIM_SetCompare1(TIM3,x);//x轴
TIM_SetCompare2(TIM3,y);//y轴
printf("++out1 %f ++\n\n\n",x);
printf("++out2 %f ++\n\n\n",y);
//数据上传到上位机观察波形
USART1_AHRS_Report((short)(x), (short)(y), (short)(x_temp/2), (short)(y_temp/2));
PID部分
#include "pid.h"
#include "pwm.h"
#include "led.h"
#include "usart.h"
#define MAX_PID_OUTPUT 750
//#define P 0.2
//#define D 0.3
u16 flag=0;
float PID(u8 z,u16 x,u16 y)//标志位 当前值 给定值
{
static float kp ,ki , kd ,i,control;
static float X_e[2],Y_e[2];//X轴误差 Y轴误差
static float X_z_e,Y_z_e;//X轴积分参数 Y轴积分参数
static float pwnoutput1,pwnoutput2;
u8 flag;
if(z==0)
{
kp =0.18;
ki =0;
kd =0.36;
//积分分离
X_e[0] = y-x;//差值
if(X_e[0]>=60||X_e[0]<=-60) {flag = 0;}
else{flag = 1;X_z_e+=X_e[0];}
//积分限幅
i = 50000;
if(X_z_e>i) X_z_e = i;
else if(X_z_e<-i) X_z_e = -i;
pwnoutput1 = kp*X_e[0]+flag*ki*X_z_e+kd*(X_e[0]-X_e[1]);
X_e[1] = X_e[0];
if (pwnoutput1 > MAX_PID_OUTPUT) //限幅
(pwnoutput1 = MAX_PID_OUTPUT);
else if (pwnoutput1 < -MAX_PID_OUTPUT)
(pwnoutput1 = -MAX_PID_OUTPUT);
control=pwnoutput1;
if(control<0) control=-control;
}
else
{
kp =0.194;
ki =0;
kd =0.35;
Y_e[0] = y-x;//²îÖµ
if(Y_e[0]>=60||Y_e[0]<=-60) {flag = 0;}
else{flag = 1;Y_z_e+=Y_e[0];}
//»ý·ÖÏÞ·ù
i = 50000;
if(Y_z_e>i) Y_z_e = i;
else if(Y_z_e<-i) Y_z_e = -i;
pwnoutput2 = kp*Y_e[0]+flag*ki*Y_z_e+kd*(Y_e[0]-Y_e[1]);
Y_e[1] = Y_e[0];
if (pwnoutput2 > MAX_PID_OUTPUT) //限幅
(pwnoutput2 = MAX_PID_OUTPUT);
else if (pwnoutput2 < -MAX_PID_OUTPUT)
(pwnoutput2 = -MAX_PID_OUTPUT);
control=pwnoutput2;
if(control<0) control=-control;
}
return control;