|
接触四轴有半个月了。在网上看到了gale 大哥的KKC代码。里面有详细的注释。相对其它四轴程序比较简单容易理解。给了我们这些菜鸟级的四轴爱好者一个很好的入门教程与编程思路。感谢gale大哥的无私奉献和辛苦工作。看了几天代码,借助这个平台写一写我的简单理解和疑惑。望懂的朋友能对每个疑问点给些详细的回答。对现在或以后学习KK_C程序的朋友也算是解惑吧。
看到这个贴的朋友顶顶 别沉了。希望大家都能看到参与讨论共同 进步!。
void main(void)
{
Init(); //Board init 初始化系统
PpmWaitSignal(); //Wait rx signal, led will flash 等待接收机的信号,等待时LED闪烁
Setup(); //Load & Adjust parameters 加载&调节参数
//Main loop 主循环
LED0_OFF();
while(1)
{
TimerRst();
CaclAttitude(); //Caculate plane attitude 计算飞行器姿态
TimerTo(1000);
//Do something between MotorControlBegin() and MotorControlEnd
//See functions declaration, can not exceed 1000us
//在MotorControlBegin()和MotorControlEnd()之间干点事儿,注意不要超过1000us
MotorControlBegin(); //Output head of ppm signal 输出PPM信号的头部分
PpmReadSignal(); //Read rx 读取接收机信号 140us
if(RxThr<RxThrLow) //If thr shutdown 如果油门关闭
{
GyroGainRead(); //Read gain 读取感度电位器 670us
ArmingRoutine(); //Arm/disarm 加锁解锁测试 5us
}
else
{
AxisMixer(); //Cacl motor signal 计算电机信号 305us
}
//If locked(arm) or no gyro base, shutdown all motor
//如果处于锁定态或者陀螺仪基准未建立,关闭所有马达
if(InLock || GyroBaseCnt || RxThr<5)
{
Motor1=Motor2=Motor3=Motor4=0;
}
//MOTOR6_L(); //I use it for test execute period 我用来观察执行时间的
MotorControlEnd(); //Output whole ppm signal 输出完整的PPM信号
}
}
从main函数开始看: Init(); //Board init 初始化系统 设置IO端口和定时器。
第二个函数调用:void PpmWaitSignal(void)
{
uchar rxcnt;
//Wait for 5 times signal received
//等待收到5次信号
for(rxcnt=RxValid=0;rxcnt<20;)
{
//Read ppm signals
PpmReadSignal();
//If got signal, inc rxcnt
if(RxValid==0x0f)
{
RxValid=0;
rxcnt++;
}
LED0_TOG();
Delay1ms(50);
}
}
里面有个函数:void PpmReadSignal(void) 读取PPM信号并作处理和限副。
疑问1:RxValid为四个通道都有效读取的标志。Rxcnt<20一直运行。那么应该是等待收到20次信号 怎么是5次呢?
第三个函数:
Setup(); 根据油门杆位置进行相应参数设置。
接着进入死循环:
TimerRst(); 类似于开始计时器。
接着调用:
void CaclAttitude(void)
{
GyroRead();// 采样陀螺仪,进行相应滤波。
//If no gyro base, calibrate gyro
//如果还未建立,建立它
if(GyroBaseCnt) 建立基准
{
GyroBaseRol+=GyroRol;
GyroBaseRol/=2;
GyroBasePit+=GyroPit;
GyroBasePit/=2;
GyroBaseYaw+=GyroYaw;
GyroBaseYaw/=2;
GyroBaseCnt--;
if(!(GyroBaseCnt&7)) LED0_TOG(); //Shine LED show gyro cali 闪烁LED表示在进行陀螺仪校准
GyroRolI=GyroPitI=GyroYawI=0;//Reset I value 清空积分值
}
else
{
if(InLock)
{
//熄灭LED表示在锁定中
LED0_OFF();
}
else
{
//Remove base part from gyro value
//减去基础值
GyroRol-=GyroBaseRol;
GyroPit-=GyroBasePit;
GyroYaw-=GyroBaseYaw;
//Reverse gyro signals if necessary
//根据设置反转各个陀螺仪信号
if(BITTST(DevRev,GYRO_ROL)) GyroRol=-GyroRol;
if(BITTST(DevRev,GYRO_PIT)) GyroPit=-GyroPit;
if(BITTST(DevRev,GYRO_YAW)) GyroYaw=-GyroYaw;
//Gyro feature compensation
//陀螺仪特性补偿
GyroRol=GyroCompe(GyroRol,GyroRolPN);
GyroPit=GyroCompe(GyroPit,GyroPitPN);
GyroYaw=GyroCompe(GyroYaw,GyroYawPN);
//Sum integral value with return
//带回归计算积分值
GyroRolI=GyroIntegral(GyroRolI,GyroRol);
GyroPitI=GyroIntegral(GyroPitI,GyroPit);
GyroYawI=GyroIntegral(GyroYawI,GyroYaw);
//Light LED
//点亮LED表示在工作中
LED0_ON();
}
}
}
int GyroIntegral(int v,int delta)
{
//Integral gain
//内部积分增益
delta/=4;//delta=-511~511 -> -127~127
v+=delta;
//Limit value
//限幅
if(v>I_MAX) v=I_MAX;
if(v<-I_MAX) v=-I_MAX;
//Return value
//回归
v/=I_RETSTEP; //I_RETSTEP== 2
return v;
}
疑问2:里面用到的积分回归法。我个人理解 i是对角速度积分然后 调节I的值 随着误差值的减少而作相应衰减增加而相应增加。自身除于2就算回归算法了吗,但不知道这个这个算法具体怎么起作用的,在实际应用中有什么好处?在帖子中看gale大哥回答是积分回归是为了避免漂移的一种不得已做法,就是让积分作用自行慢慢消失,这样,即使出现较大漂移,也不会“发疯”,如果没有回归,又没有加速度校准,四轴飞起来会很稳,但是一旦摇摆几次后,就会发疯。这样的话随着陀螺仪与目标值的差值减少而趋近于0
接着往下:
TimerTo(1000); 等待到1000us 否则一直喂狗
MotorControlBegin();
PpmReadSignal();//读PPm 140us
GyroRol-=GyroBaseRol;
GyroPit-=GyroBasePit;
GyroYaw-=GyroBaseYaw;
ail+=GainAdj(GyroRol,GainRol)+GainAdj(GyroRolI,GainPit);
ele+=GainAdj(GyroPit,GainRol)+GainAdj(GyroPitI,GainPit);
rud=RxRud/4+GainAdj(GyroYaw,GainYaw);//+GainAdj(GyroYawI,GainPit);
int GyroIntegral(int v,int delta)
{
//Integral gain
//内部积分增益
delta/=4;//delta=-511~511 -> -127~127
v+=delta;
//Limit value
//限幅
if(v>I_MAX) v=I_MAX;
if(v<-I_MAX) v=-I_MAX;
//Return value
//回归
v/=I_RETSTEP;
return v;
}
疑问3:I+= delta/4/2 相当于除于8 也就是i大概在-63~63内变化?但我看有的朋友分析说[[[对速度进行积分,将陀螺的输出值GyroYaw/4再加上积分值GyroYawI(初始是0)一次积分后增加6
6 ,如何把陀螺仪的输出变成电机控制信号 首先加上感度信息,算法是积分值GyroYawI×感度
(0-128)×0.0078 , 副翼ail输出量=当前角数度+角速度积分积分。
同理可以得到下面几个调整量
副翼 ail=3
升降 ele=3
方向 rud=3]]]
这些值他怎么算的?
调整量:
ail+=GainAdj(GyroRol,GainRol)+GainAdj(GyroRolI,GainPit);
ele+=GainAdj(GyroPit,GainRol)+GainAdj(GyroPitI,GainPit);
rud=RxRud/4+GainAdj(GyroYaw,GainYaw);//+GainAdj(GyroYawI,GainPit);
化成另外一种形式:ail+= GyroRol*GainRol/128+ GyroRolI*GainPit/128
ail+= (GyroRol*GainRol+ GyroRolI*GainPit)/128
疑问4:GainRol应该相当于微调了。这个式子应该是算增量了,难道前面的是P后面的是I吗?如果按这样理解的话 等化下:ail+= GyroRol*P+ I*(GainPit/128) 那么P值是根据感度值/128了 这样P值就在(0~1)之间了,I的话为什么乘与(GainPit/128)不是应该是GainRol吗?,天啊,为什么 十万个为什么!
(:P 哥不才,脑子此刻浆糊了)其它式子也一窍不通了
// 假设 X模式下
// 1 2
// X
// 3 4
如果我现在要翻滚动作 (1,4转向同向 2,3同向, 12前方位置)
那应该设法增加1,3的转速 (相邻轴方向反抵消自转)
Motor1=MotorLimitValue(thr + ail - ele + rud);
Motor2=MotorLimitValue(thr - ail - ele - rud);
Motor3=MotorLimitValue(thr + ail + ele - rud);
Motor4=MotorLimitValue(thr - ail + ele + rud);
上述1,3式子中很明显有+ail的动作。而2,4是在减。同理可知其它动作的调整。
|
阿莫论坛20周年了!感谢大家的支持与爱护!!
曾经有一段真挚的爱情摆在我的面前,我没有珍惜,现在想起来,还好我没有珍惜……
|