搜索
bottom↓
回复: 4

经过对MK代码以及各位前辈们在论坛里留下的精华帖,最近对MK代码小有理解,望各位大神指

[复制链接]

出0入0汤圆

发表于 2011-2-27 16:22:16 | 显示全部楼层 |阅读模式
飞控算法:

首先,陀螺仪是一个瞬时数据误差较小的传感器,在短时间内,陀螺仪的数据就能够表示当前四轴的姿态,对陀螺仪的数据MesswertNick进行PI控制得到电机的值MoterWert。但是陀螺仪的很大一个问题就是误差累积。因此引入加速度计,加速度计则相反,瞬时误差可能很大,数据很敏感,但是滤波后的加速度就较接近于真实值。由此加速度的积分也能够描述出四轴的姿态。怎样把一个长时间才能稳定的数据,和一个短时间误差小的数据融合在一起,真实的反映出四轴的姿态?
就是MK里的融合算法,即长期融合和实时融合。

实时融合:
    tmp_long = (long)(IntegralNick / EE_Parameter.GyroAccFaktor - (long)Mittelwert_AccNick);
    tmp_long2 = (long)(IntegralRoll / EE_Parameter.GyroAccFaktor - (long)Mittelwert_AccRoll);
    tmp_long /= 16;
    tmp_long2 /= 16;
   if((MaxStickNick > 15) || (MaxStickRoll > 15))
    {
    tmp_long  /= 3;
    tmp_long2 /= 3;
    }
   if(abs(PPM_in[EE_Parameter.Kanalbelegung[K_GIER]]) > 25)
    {
    tmp_long  /= 3;
    tmp_long2 /= 3;
    }

#define AUSGLEICH 32
    if(tmp_long >  AUSGLEICH)  tmp_long  = AUSGLEICH;
    if(tmp_long < -AUSGLEICH)  tmp_long  =-AUSGLEICH;
    if(tmp_long2 > AUSGLEICH)  tmp_long2 = AUSGLEICH;
    if(tmp_long2 <-AUSGLEICH)  tmp_long2 =-AUSGLEICH;

    Mess_IntegralNick -= tmp_long;
Mess_IntegralRoll -= tmp_long2;
长期融合:
        IntegralAccNick = (EE_Parameter.GyroAccFaktor * IntegralAccNick) / ABGLEICH_ANZAHL;
        IntegralAccRoll = (EE_Parameter.GyroAccFaktor * IntegralAccRoll) / ABGLEICH_ANZAHL;
    IntegralAccZ    = IntegralAccZ / ABGLEICH_ANZAHL;
// Nick ++++++++++++++++++++++++++++++++++++++++++++++++
    IntegralFehlerNick = (long)(MittelIntegralNick - (long)IntegralAccNick);
    ausgleichNick = IntegralFehlerNick / EE_Parameter.GyroAccAbgleich;
// Roll ++++++++++++++++++++++++++++++++++++++++++++++++     
    IntegralFehlerRoll = (long)(MittelIntegralRoll - (long)IntegralAccRoll);
    ausgleichRoll = IntegralFehlerRoll / EE_Parameter.GyroAccAbgleich;

    LageKorrekturNick = ausgleichNick / ABGLEICH_ANZAHL;
LageKorrekturRoll = ausgleichRoll / ABGLEICH_ANZAHL;
(ps、LageKorrekturNick是在每个程序周期都会补偿到Mess_IntegralNick变量中,它应该是对陀螺仪漂移的估计,然后再将实际测得的陀螺仪数值减去这个漂移估计,得到一个较接近真实值的数据)
有漂移的话说明这个时候应该再对陀螺仪重新设定中立点,防止数据误差越来越大,大到无法控制了。
下面一段代码就是长期融合里的陀螺仪中立点修改:
// Nick +++++++++++++++++++++++++++++++++++++++++++++++++
        cnt = 1;// + labs(IntegralFehlerNick) / 4096;
        if(labs(MittelIntegralNick_Alt - MittelIntegralNick) < BEWEGUNGS_LIMIT)
        {
                /*必须连续两次的误差都很大,才能进入下面的if语句*/

        if(IntegralFehlerNick >  FEHLER_LIMIT2)
         {
           if(last_n_p)
           {
                   /*连续两次误差较大时,对陀螺仪漂移进行补偿*/
                   /*最后改变了LageKorrekturNick的值*/
            cnt += labs(IntegralFehlerNick) / FEHLER_LIMIT2;
            ausgleichNick = IntegralFehlerNick / 8;
            if(ausgleichNick > 5000) ausgleichNick = 5000;
            LageKorrekturNick += ausgleichNick / ABGLEICH_ANZAHL;
           }
           else last_n_p = 1;
         } else  last_n_p = 0;
        if(IntegralFehlerNick < -FEHLER_LIMIT2)
         {
           if(last_n_n)
            {
             cnt += labs(IntegralFehlerNick) / FEHLER_LIMIT2;
             ausgleichNick = IntegralFehlerNick / 8;
             if(ausgleichNick < -5000) ausgleichNick = -5000;
             LageKorrekturNick += ausgleichNick / ABGLEICH_ANZAHL;
            }
           else last_n_n = 1;
         } else  last_n_n = 0;
        } else cnt = 0;
        if(cnt > EE_Parameter.Driftkomp) cnt = EE_Parameter.Driftkomp;
        if(IntegralFehlerNick >  FEHLER_LIMIT)   AdNeutralNick += cnt;
        if(IntegralFehlerNick < -FEHLER_LIMIT)   AdNeutralNick -= cnt;
如果不对陀螺仪的中立点进行修改,那陀螺仪的数据误差会越来越大,实时的加速度计补偿根本不能够抵消陀螺仪的误差。

最后每0.5s修改一次陀螺仪中立点,每2ms得到一个较接近真实数据的MesswertNick。
再进行PI控制得到最终数据Moterwert。

阿莫论坛20周年了!感谢大家的支持与爱护!!

知道什么是神吗?其实神本来也是人,只不过神做了人做不到的事情 所以才成了神。 (头文字D, 杜汶泽)

出0入0汤圆

 楼主| 发表于 2011-3-1 10:11:02 | 显示全部楼层
还有一个疑问,就是为什么MK主函数while循环是每2ms执行一次?(只有MK代码里注释了一下,但是没说为什么?难道他们计算过每次要运行多少指令?)

出0入0汤圆

发表于 2011-3-1 10:57:36 | 显示全部楼层
2ms是时钟ticks。

出0入0汤圆

发表于 2011-3-1 14:46:40 | 显示全部楼层
mark

出0入0汤圆

 楼主| 发表于 2011-3-1 18:13:05 | 显示全部楼层
回复【2楼】modelfly
-----------------------------------------------------------------------

怎么看的。?
SIGNAL (SIG_OVERFLOW0)    // 8kHz
{
    static unsigned char cnt_1ms = 1,cnt = 0;
    unsigned char pieper_ein = 0;
//    TCNT0 -= 250;//TIMER_RELOAD_VALUE;

   if(!cnt--)//这个中断0.125ms运行一次。这个if语句又是10个0.125ms运行一次(1.25ms)
    {
     cnt = 9;
     cnt_1ms++;
     cnt_1ms %= 2;
     if(!cnt_1ms) UpdateMotor = 1;//这个if语句是每2个1.25ms执行一次。那算一下UpdateMotor应该是每2.5ms设置为1.周期应该是2.5ms啊。为什么都说是2ms??
     CountMilliseconds++;
     }   
}
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片。注意:要连续压缩2次才能满足要求!!】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|Archiver|amobbs.com 阿莫电子技术论坛 ( 粤ICP备2022115958号, 版权所有:东莞阿莫电子贸易商行 创办于2004年 (公安交互式论坛备案:44190002001997 ) )

GMT+8, 2024-7-24 12:55

© Since 2004 www.amobbs.com, 原www.ourdev.cn, 原www.ouravr.com

快速回复 返回顶部 返回列表