搜索
bottom↓
回复: 422

四轴飞行讨论: 飞控算法讨论

  [复制链接]

出0入0汤圆

发表于 2009-5-17 10:47:34 | 显示全部楼层 |阅读模式
阿莫一下子开了这么多贴,可惜都不是我所感兴趣的!
那么多贴,都没有关于算法的!

我个人觉得如果先解决程序算法问题是关键!知道了飞控控制原型,那样选型才准确!
现在什么都没弄明白,绝大多数人(真正看过源码,写过算法的人就不说了)都是盲目的凭感觉选!

开个算法讨论帖吧!相信现在很多高手都已经把源码消化的差不多了!说说你们的感想,整个程序的框架等等!

个人想法~


应该改名了~感谢各位大虾!现在柳暗花明了~

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

一只鸟敢站在脆弱的枝条上歇脚,它依仗的不是枝条不会断,而是自己有翅膀,会飞。

出0入0汤圆

发表于 2009-5-17 10:49:37 | 显示全部楼层
支持

出0入0汤圆

发表于 2009-5-17 10:55:35 | 显示全部楼层
按照我现在对MK的代码的理解,我的四轴稳定性已经达到LAMA的程度了,对MK的这部分代码我也差不多明白了。
其实选型,一般都可以做到这种程度,就有几点要注意。

一个是姿态控制MCU的处理速度,MK的可是工作在500Hz,我的目前是400Hz,UAVP目前的版本最大是400Hz,UAVP-NG的是1000Hz,所以一个强大的处理器还是需要的。有必要的话需要多处理器协同工作。

另外就是电调,用I2C电调才能做出好效果。至于马达、桨,850KV的和1000KV的看不出差别,10英寸GWS 3叶桨不但能飞好,而且稳定性甚至比9英寸的还好。

其它部分没有什么特殊的,甚至机架重心不对称都没关系。

至于传感器,最最低档的ENC-03也足够了,配合便宜的ADXL330也可以达到好效果。

出0入0汤圆

发表于 2009-5-17 12:30:35 | 显示全部楼层
支持!

出0入0汤圆

发表于 2009-5-17 13:34:19 | 显示全部楼层
看了很久的贴了,发现能说在点子上的少之又少。
对网站搞的这个开发能够脱离玩具层,取得完全成功持极其悲观态度……

出0入0汤圆

发表于 2009-5-17 13:47:12 | 显示全部楼层
to  cnmusic
不知你对MK的加速度感测与陀螺感测整合以及控制上的coupling修正有深入了解吗
可不可以稍微分享一下…
因为我做到后面还是觉得这两个东西是关键

出0入0汤圆

发表于 2009-5-17 14:07:52 | 显示全部楼层
【5楼】 white
这个是重点中的重点,我会整理思路后写出来的。
目前我参考MK的算法已经取得比较好的效果了。

出0入0汤圆

 楼主| 发表于 2009-5-17 14:52:05 | 显示全部楼层
我把核心贴出来吧~也不能算很好!只是其中一个版本,可以说是后续版本的雏形吧~
大虾们尽管拍砖~俺抛砖引玉~

ANALOG_OFF;
        //==============AD测量平均值========================//
        if(MessanzahlNick)    (MesswertNick = AccumulateNick / MessanzahlNick);
        if(MessanzahlRoll)    (MesswertRoll = AccumulateRoll / MessanzahlRoll);
        if(MessanzahlGier)    (MesswertGier = AccumulateGier / MessanzahlGier);
        if(messanzahl_AccNick) Mittelwert_AccNick = ((long)Mittelwert_AccNick * 7 + ((ACC_AMPLIFY * (long)accumulate_AccNick) / messanzahl_AccNick)) / 8L;
        if(messanzahl_AccRoll) Mittelwert_AccRoll = ((long)Mittelwert_AccRoll * 7 + ((ACC_AMPLIFY * (long)accumulate_AccRoll) / messanzahl_AccRoll)) / 8L;
        if(messanzahl_AccHoch) Mittelwert_AccHoch = ((long)Mittelwert_AccHoch * 7 + ((long)accumulate_AccHoch) / messanzahl_AccHoch) / 8L;
    AccumulateNick = 0;   MessanzahlNick = 0;
    AccumulateRoll = 0;   MessanzahlRoll = 0;
    AccumulateGier = 0;   MessanzahlGier = 0;
    accumulate_AccRoll = 0;messanzahl_AccRoll = 0;
    accumulate_AccNick = 0;messanzahl_AccNick = 0;
    accumulate_AccHoch = 0;messanzahl_AccHoch = 0;
       
//============AD里直接积分===========================//
    Integral_Gier  = Mess_Integral_Gier;
        Integral_Gier2 = Mess_Integral_Gier2;//待修改测试
    IntegralNick = Mess_IntegralNick;
    IntegralRoll = Mess_IntegralRoll;
    IntegralNick2 = Mess_IntegralNick2;
    IntegralRoll2 = Mess_IntegralRoll2;
       
    ANALOG_ON;       

//---------------------??---------------------------------------------------------
    if(MesswertNick > 200)  MesswertNick += 4 * (MesswertNick - 200);
    else if(MesswertNick < -200) MesswertNick += 4 * (MesswertNick + 200);

    if(MesswertRoll > 200)  MesswertRoll += 4 * (MesswertRoll - 200);
    else if(MesswertRoll < -200) MesswertRoll += 4 * (MesswertRoll + 200);
       
       
    GRN_ON;
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++               
//陀螺仪漂移补偿
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++               
#define DRIFT_FAKTOR 3        //漂移因子
        if(ZaehlMessungen >= 1000 / DRIFT_FAKTOR)//AD转换次数次数大于333次,约432*7=3S
        {
                IntegralFehlerNick = IntegralNick2 - IntegralNick;//?这里是0么?//积分偏差
                IntegralFehlerRoll = IntegralRoll2 - IntegralRoll;//待修改
               
               
                ZaehlMessungen = 0;//转换次数清零
                if(IntegralFehlerNick > 500/DRIFT_FAKTOR)   AdNeutralNick++;
                if(IntegralFehlerNick < -500/DRIFT_FAKTOR)  AdNeutralNick--;
                if(IntegralFehlerRoll > 500/DRIFT_FAKTOR)   AdNeutralRoll++;
                if(IntegralFehlerRoll < -500/DRIFT_FAKTOR)  AdNeutralRoll--;
                if(Mess_Integral_Gier2 > 500/DRIFT_FAKTOR)  AdNeutralGier--;         
                if(Mess_Integral_Gier2 <-500/DRIFT_FAKTOR)  AdNeutralGier++;         
                ANALOG_OFF;
                Mess_IntegralNick2 = IntegralNick;//?
                Mess_IntegralRoll2 = IntegralRoll;
                Mess_Integral_Gier2 = Integral_Gier;
                ANALOG_ON;
        }
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++               
//使用陀螺仪数据补偿加速度计数据
#define GyroAccFaktor1 26
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++               
    tmp_long = (long)(IntegralNick / GyroAccFaktor1 - (long)Mittelwert_AccNick) / 16;  
    tmp_long2 = (long)(IntegralRoll / GyroAccFaktor1 - (long)Mittelwert_AccRoll) / 16;   

#define AUSGLEICH 500//补偿参数
    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;
        ANALOG_OFF;
        Mess_IntegralNick -= tmp_long;
         Mess_IntegralRoll -= tmp_long2;

   
ANALOG_ON;

出0入0汤圆

发表于 2009-5-17 21:37:24 | 显示全部楼层
首先我们使用V0.71h Code Redesign killagreg的代码,这个代码基本都是英文变量名和注释,看起来容易些。所有核心的姿态控制都在fc.c文件里。这个代码可以在MK的CVS中免费下到,位于branches目录下。

MK的融合代码主要做了3件事:
第一件是即时融合,就是实时地根据加速度计的数值反推出陀螺仪积分应有的数值,然后根据当前的陀螺仪积分进行调整。

第二件是长期融合,在代码里它用0.5秒的时间采集加速度计的数据,然后到0.5秒时对这些数据进行平均,依此来得到一个相对稳定的加速度计数值。根据这个数值来相对准确地知道四轴这0.5秒的姿态,然后再修整调整量,做到自动稳定到平衡位置。

第三件是根据调整量的大小,决定是否需要修改陀螺仪中立点。这部分我目前还搞不太明白,所以先暂且不提。有前2部分已经可以做到让四轴稳定到LAMA的程度了。


下面结合代码来详细解说:

首先是即时融合的代码,位于fc.c的890行开始。
        if(!Looping_Nick && !Looping_Roll) // if not lopping in any direction
        {
                int32_t tmp_long, tmp_long2;
                if(FCParam.Kalman_K != -1)
                {
                        // determine the deviation of gyro integral from averaged acceleration sensor
                        tmp_long   = (int32_t)(IntegralNick / ParamSet.GyroAccFactor - (int32_t)Mean_AccNick);
                        tmp_long   = (tmp_long * FCParam.Kalman_K) / (32 * 16);
                        tmp_long2  = (int32_t)(IntegralRoll   / ParamSet.GyroAccFactor - (int32_t)Mean_AccRoll);
                        tmp_long2  = (tmp_long2 * FCParam.Kalman_K) / (32 * 16);

                        if((MaxStickNick > 64) || (MaxStickRoll > 64)) // reduce effect during stick commands
                        {
                                tmp_long  /= 2;
                                tmp_long2 /= 2;
                        }
                        if(abs(PPM_in[ParamSet.ChannelAssignment[CH_YAW]]) > 25) // reduce further if yaw stick is active
                        {
                                tmp_long  /= 3;
                                tmp_long2 /= 3;
                        }
                        // limit correction effect
                        if(tmp_long >  (int32_t)FCParam.Kalman_MaxFusion)  tmp_long  = (int32_t)FCParam.Kalman_MaxFusion;
                        if(tmp_long < -(int32_t)FCParam.Kalman_MaxFusion)  tmp_long  =-(int32_t)FCParam.Kalman_MaxFusion;
                        if(tmp_long2 > (int32_t)FCParam.Kalman_MaxFusion)  tmp_long2 = (int32_t)FCParam.Kalman_MaxFusion;
                        if(tmp_long2 <-(int32_t)FCParam.Kalman_MaxFusion)  tmp_long2 =-(int32_t)FCParam.Kalman_MaxFusion;
                }
                else
                {
                        // determine the deviation of gyro integral from averaged acceleration sensor
                        tmp_long   =  (int32_t)(IntegralNick / ParamSet.GyroAccFactor - (int32_t)Mean_AccNick);
                        tmp_long  /= 16;
                        tmp_long2  = (int32_t)(IntegralRoll   / ParamSet.GyroAccFactor - (int32_t)Mean_AccRoll);
                        tmp_long2 /= 16;

                        if((MaxStickNick > 64) || (MaxStickRoll > 64)) // reduce effect during stick commands
                        {
                                tmp_long  /= 3;
                                tmp_long2 /= 3;
                        }
                        if(abs(PPM_in[ParamSet.ChannelAssignment[CH_YAW]]) > 25) // reduce further if yaw stick is active
                        {
                                tmp_long  /= 3;
                                tmp_long2 /= 3;
                        }

                        #define BALANCE 32
                        // limit correction effect
                        if(tmp_long >  BALANCE)  tmp_long  = BALANCE;
                        if(tmp_long < -BALANCE)  tmp_long  =-BALANCE;
                        if(tmp_long2 > BALANCE)  tmp_long2 = BALANCE;
                        if(tmp_long2 <-BALANCE)  tmp_long2 =-BALANCE;
                }
                // correct current readings
                Reading_IntegralGyroNick -= tmp_long;
                Reading_IntegralGyroRoll -= tmp_long2;
        }

重点地部分是:
                        // determine the deviation of gyro integral from averaged acceleration sensor
                        tmp_long   =  (int32_t)(IntegralNick / ParamSet.GyroAccFactor - (int32_t)Mean_AccNick);
                        tmp_long  /= 16;
                        tmp_long2  = (int32_t)(IntegralRoll   / ParamSet.GyroAccFactor - (int32_t)Mean_AccRoll);
                        tmp_long2 /= 16;

                        if((MaxStickNick > 64) || (MaxStickRoll > 64)) // reduce effect during stick commands
                        {
                                tmp_long  /= 3;
                                tmp_long2 /= 3;
                        }
                        if(abs(PPM_in[ParamSet.ChannelAssignment[CH_YAW]]) > 25) // reduce further if yaw stick is active
                        {
                                tmp_long  /= 3;
                                tmp_long2 /= 3;
                        }

                        #define BALANCE 32
                        // limit correction effect
                        if(tmp_long >  BALANCE)  tmp_long  = BALANCE;
                        if(tmp_long < -BALANCE)  tmp_long  =-BALANCE;
                        if(tmp_long2 > BALANCE)  tmp_long2 = BALANCE;
                        if(tmp_long2 <-BALANCE)  tmp_long2 =-BALANCE;
                }
                // correct current readings
                Reading_IntegralGyroNick -= tmp_long;
                Reading_IntegralGyroRoll -= tmp_long2;

首先,MK根据IntegralNick变量(这个变量是当前陀螺仪的积分值),利用ParamSet.GyroAccFactor(这个是一个设置值,用来标定加速度计变化1,陀螺仪积分应该变化多少),得出在目前的陀螺仪积分下,对应的加速度计的偏差量应该是多少。然后用这个值减去现在的加速度计数值,得到的就是当前从加速度计角度“看到”的陀螺仪积分偏差。下面的/16用来对这个值进行衰减。在下面如果有遥控器操作(MaxStickNick > 64)那么还要更进一步衰减,甚至Z轴有操作也要再衰减。最后对这个偏差值进行限幅,避免绝对值超过BALANCE的大小。剩下的就只要把修正值修正到陀螺仪积分里就完成了,Reading_IntegralGyroNick就是陀螺仪的积分。

看起来这个代码比较容易理解,不过这里有两点需要注意的。
一是这个代码是利用加速度计来看陀螺仪积分偏差,得出的调整量是加速度计的数值。也许你会觉得奇怪,怎么能用加速度计的数据来加减陀螺仪积分呢?2者似乎是风马牛不相及。不过这里这2者还是有关系的,ParamSet.GyroAccFactor,MK这么做可以将调整量缩小。
二是这个调整量很小,本来加速度计的变化量就很小了,又除了16,甚至还要再除3。最后还能剩多少啊?实际情况是剩的确实不多,我的四轴数据测量后,这个调整值一般也就是3左右,没有看到超过5的。而陀螺仪积分随便就几百上去了,这点根本不算什么。

这么说起来,大家可能对这个调整量的效率产生疑问。确实,这个调整量是很慢。我在我的四轴上实际测量过,按照400Hz的陀螺仪积分频率,在没有积分的情况下,光靠这个加速度计的调整值,要想让陀螺仪积分恢复到和加速度计的对应状态,需要超过2秒钟。

那么大家肯定又有疑问了,这么慢的调整速度,怎么能实现稳定呢?这就是MK的高明之处。俗话说“四两拨千斤”,用在这里还是很合适的。

整个MK的调整速度,不是标准接收机的50Hz,也不是100Hz,而是高达500Hz。可以在main.c里查找变量UpdateMotor,可以看到注释“reset Flag, is enabled every 2 ms by isr of timer0”,没有错,就是2ms触发一次。在Timer0.c的ISR(TIMER0_OVF_vect)里,还可以看到注释“every 2nd run (976Hz/2 = 488 Hz)”,这就是它的执行频率。

心细的人肯定又会继续产生疑问,为什么要这么快?有必要这么快吗?1000KV的马达,3S电池,一分钟最多也就是12000转,换算成秒一秒最多也就转200圈。500Hz的调整频率难道转0.25圈就换一个转速吗?

实际情况是这样的:
首先大家都明白机械振动对于四轴姿态调整的干扰,如果完全没有机械振动,那么想让四轴飞稳会比现在简单很多倍。但既然不可能完全避免,那么我们就必须想办法来克服它。于是就有我以前采用的加权移动平均或类似的算法。但这些算法都有一个缺点,如果想要状态准确,不可避免地就会造成响应速度低。反过来响应速度高则抗震动效果就不会好。这是一对矛盾,一对让人头大的矛盾。

MK也有这个问题,于是他们想到了一个非常巧妙的解决方法。既然马达转速不可能无限快,那么完全可以通过提高控制频率来应对震动。与其过滤震动,不如加快速度跟上震动,将震动引起的错误数据也当作正确的来处理,反正到马达端震动会被消除的,因为机械震动大都是往复的。而且I2C电调本身的速度也很快,所以频率就可以轻松达到500Hz或更高。

既然明白了加快调整的原因,那么对于弱化加速度计的调整量也就不难理解了。加速度计对于震动实在太敏感了,对于基本没做处理(实际是加速度计的数据只有一个移动期为2的移动平均,就是保留一个历史数据然后和新数据相加除2)的加速度计数据,如果调整量大了,势必造成陀螺仪积分变化非常大,一个显而易见的结果就是引起四轴振荡。实际测试也是如此。

虽然上面说了这么多,我想大家还是不完全明白有了这部分代码后能做到什么。下面就来说说这段代码的效果。

有了这些代码后,设置好合适的I,关掉P,拿起四轴,让一个轴倾斜,你会在倾斜的同时感觉到这个轴的马达转速快速提升,和你的倾斜动作完全同步。你什么时候倾斜,马达什么时候加速,你倾斜的角度越大,马达转速越快。这就是效果。

正确的融合结果是四轴的每个轴都可以一直保持这种“反抗精神”。不管你倾斜多久,不管你倾斜角度有多大都不会“放弃”。而且当你基本回到平衡位置时,马达们应该都安静下来了,四轴不会因为以前的倾斜发生震荡来“报复”你,即使你反复左右倾斜试图引起震荡也不会。

如果融合有问题,有可能马达反抗一会儿就放弃了,然后按照当前的倾斜位置作为新的平衡位置。或者引发震荡,造成四轴晃动。


为了引出下面的算法,现在请你将四轴小幅度倾斜一点,不要离平衡位置太远,看看马达会有何表示。
试验的结果,是不是在小幅度的时候,马达基本没有加速的动作?

原因并不是你代码弄错了,而是这种平衡策略的天生缺陷。由于这种平衡需要通过陀螺仪积分也就是绝对倾斜角度来调整马达转速,总有一个情况就是当倾斜角度很小的时候,无法让马达产生足够的调整动力来最终把四轴拉平。这就是为什么MK要引入第二种,也就是长期融合。

长期融合的代码位于fc.c文件的949行。

        if(MeasurementCounter >= BALANCE_NUMBER) // averaging number has reached
        {
                static int16_t cnt = 0;
                static int8_t last_n_p, last_n_n, last_r_p, last_r_n;
                static int32_t MeanIntegralNick_old, MeanIntegralRoll_old;

                // if not lopping in any direction (this should be alwais the case,
                // because the Measurement counter is reset to 0 if looping in any direction is active.)
                if(!Looping_Nick && !Looping_Roll && !FunnelCourse)
                {
                        // Calculate mean value of the gyro integrals
                        MeanIntegralNick /= BALANCE_NUMBER;
                        MeanIntegralRoll  /= BALANCE_NUMBER;

                        // Calculate mean of the acceleration values
                        IntegralAccNick = (ParamSet.GyroAccFactor * IntegralAccNick) / BALANCE_NUMBER;
                        IntegralAccRoll  = (ParamSet.GyroAccFactor * IntegralAccRoll ) / BALANCE_NUMBER;

                        // Nick ++++++++++++++++++++++++++++++++++++++++++++++++
                        // Calculate deviation of the averaged gyro integral and the averaged acceleration integral
                        IntegralErrorNick = (int32_t)(MeanIntegralNick - (int32_t)IntegralAccNick);
                        CorrectionNick = IntegralErrorNick / ParamSet.GyroAccTrim;
                        AttitudeCorrectionNick = CorrectionNick / BALANCE_NUMBER;
                        // Roll ++++++++++++++++++++++++++++++++++++++++++++++++
                        // Calculate deviation of the averaged gyro integral and the averaged acceleration integral
                        IntegralErrorRoll = (int32_t)(MeanIntegralRoll - (int32_t)IntegralAccRoll);
                        CorrectionRoll  = IntegralErrorRoll / ParamSet.GyroAccTrim;
                        AttitudeCorrectionRoll  = CorrectionRoll  / BALANCE_NUMBER;

                        if(((MaxStickNick > 64) || (MaxStickRoll > 64) || (abs(PPM_in[ParamSet.ChannelAssignment[CH_YAW]]) > 25)) && (FCParam.Kalman_K == -1) )
                        {
                                AttitudeCorrectionNick /= 2;
                                AttitudeCorrectionRoll /= 2;
                        }

核心部分:
                        MeanIntegralNick /= BALANCE_NUMBER;
                        MeanIntegralRoll  /= BALANCE_NUMBER;

                        // Calculate mean of the acceleration values
                        IntegralAccNick = (ParamSet.GyroAccFactor * IntegralAccNick) / BALANCE_NUMBER;
                        IntegralAccRoll  = (ParamSet.GyroAccFactor * IntegralAccRoll ) / BALANCE_NUMBER;

                        // Nick ++++++++++++++++++++++++++++++++++++++++++++++++
                        // Calculate deviation of the averaged gyro integral and the averaged acceleration integral
                        IntegralErrorNick = (int32_t)(MeanIntegralNick - (int32_t)IntegralAccNick);
                        CorrectionNick = IntegralErrorNick / ParamSet.GyroAccTrim;
                        AttitudeCorrectionNick = CorrectionNick / BALANCE_NUMBER;
                        // Roll ++++++++++++++++++++++++++++++++++++++++++++++++
                        // Calculate deviation of the averaged gyro integral and the averaged acceleration integral
                        IntegralErrorRoll = (int32_t)(MeanIntegralRoll - (int32_t)IntegralAccRoll);
                        CorrectionRoll  = IntegralErrorRoll / ParamSet.GyroAccTrim;
                        AttitudeCorrectionRoll  = CorrectionRoll  / BALANCE_NUMBER;

                        if(((MaxStickNick > 64) || (MaxStickRoll > 64) || (abs(PPM_in[ParamSet.ChannelAssignment[CH_YAW]]) > 25)) && (FCParam.Kalman_K == -1) )
                        {
                                AttitudeCorrectionNick /= 2;
                                AttitudeCorrectionRoll /= 2;
                        }

这里MeanIntegralNick是陀螺仪积分,IntegralAccNick是加速度计的积分总合,是经过BALANCE_NUMBER次姿态调整累加下来的。ParamSet.GyroAccFactor依旧是那个关键的系数。

代码首先将陀螺仪积分求平均,得到一个平均值。同样对加速度计的积分也进行了这样的处理,只是代码里MK先将加速度计的数值换算成对应的陀螺仪积分后再求得平均。于是下面就是2个陀螺仪积分的对比了,和上面的算法有些不同。

在下面的代码就更好懂了,先求出这2个积分的差异,然后利用ParamSet.GyroAccTrim缩小,最后再除以BALANCE_NUMBER,小到一点点的地步。后面的代码也对遥控器操作情况下再度进行衰减。在我的四轴上,这个调整量基本小于0.1,有时候甚至都是0.000XXX的级别。为什么要这么小?原因就是变量AttitudeCorrectionNick的应用是每次积分都用到了(fc.c的317行,        Reading_IntegralGyroNick  += Reading_GyroNick - AttitudeCorrectionNick;),所以如果大了,那么一下子就大幅度改变了陀螺仪积分,引起麻烦。

这里有个隐含的疑问,既然Reading_IntegralGyroNick每次都有进行过调整,那么和第一种算法会不会冲突呢?实际情况不会。因为第一种调整虽然调整量比第二种大很多倍,而且调整速度也非常快,加速度计的数据虽然长期看来确实可以反映出四轴的姿态,而在1/500秒看来基本可以算是随机的。所以有很大情况这2种调整量不会互相覆盖。

加入了这个代码以后,再小幅度倾斜四轴看看。四轴会慢慢地自己增加马达转速,直到把自身拉平才会罢休。这就可以大幅度减小漂移的程度。从图表角度看,随着四轴的倾斜,陀螺仪积分也随之水涨船高,转速自然就上去了。

有了这2部分代码以后,四轴基本可以自己做到自主悬停了。

以上分析只是从代码和现象层面进行的理解,MK肯定也采用了一种比较经典的控制算法,只是目前我没有找到相关的资料。欢迎大家继续探索。

出0入0汤圆

发表于 2009-5-17 21:39:09 | 显示全部楼层
ourdev_440208.rar(文件大小:2.42M)&nbsp;(原文件名:V0.71h&nbsp;Code&nbsp;Redesign&nbsp;killagreg.rar)

出0入0汤圆

发表于 2009-5-17 21:43:27 | 显示全部楼层
【5楼】 white

目前我对MK的控制还有些疑虑,从代码角度看,如果遥控器进行方向操作后,四轴可以无限制地倾斜。如果遇到风,这个缺陷就会让四轴失控。所以控制部分我目前还没有太过仔细看。

出0入0汤圆

 楼主| 发表于 2009-5-17 21:48:57 | 显示全部楼层
强顶!cnmusic ,你让我有点震惊了!赞一个~
天天关注中~

出0入0汤圆

发表于 2009-5-17 21:51:11 | 显示全部楼层
【11楼】 wygood123

我是软件出身的,而且自己实际做过,自然能有所感悟。

出0入0汤圆

发表于 2009-5-17 22:52:33 | 显示全部楼层
【8楼】 cnmusic

一语惊醒梦中人啊,诸多的困惑和不解迎刃而开,沿着你的思路往下走,一路柳暗花明,天高云淡,思路豁然开朗。cnmusic  辛苦了,
谢谢!
头像被屏蔽

出0入0汤圆

发表于 2009-5-17 23:34:36 | 显示全部楼层
【8楼】 cnmusic  ,

Cool!

cnmusic 必是一位高人。能自我介绍一下吗?谢谢。

出0入0汤圆

发表于 2009-5-18 09:09:35 | 显示全部楼层
我是硬件BC+航模BC+机械BC。
老本行是软件开发,用Visual C++的。

接触四轴纯粹是好玩。本来只想做一个平衡仪来把我很早以前买的华科尔4#直升机飞起来,但是当初经验不足,于是就先从LAMA开始做起。不慎被老总发现,于是老总想卖钱。可对方认为LAMA这种共轴双浆机怎么看都是玩具,四旋翼看起来像个东西。就这样我只好改行做四轴了。

我从去年10月开始做四轴,一直做到现在。

出0入0汤圆

发表于 2009-5-18 10:35:26 | 显示全部楼层
http://you.video.sina.com.cn/b/20861649-1407327420.html

这是我的四轴的最新视频,和MK的还有一些差距,但现在已经是我在控制四轴,而不是四轴控制我了。
400Hz的调整速度就是比500Hz的慢些,代码还需要提高。

出0入0汤圆

 楼主| 发表于 2009-5-18 13:10:24 | 显示全部楼层
飞得非常牛了!
很稳定~不过飞行时似乎还有点颤抖~

这已经非常接近于德国的了~可能有些参数还需要细微调整~

个人看法~

出0入0汤圆

发表于 2009-5-18 14:21:44 | 显示全部楼层
是的,还有些细节需要不断优化。

出0入0汤圆

 楼主| 发表于 2009-5-18 14:44:34 | 显示全部楼层
请问cnmusic,FC.C的273行处的代码,我没看明白计算原理~是Yaw对Nick 和Roll的补偿么?

// Coupling fraction
        if(!Looping_Nick && !Looping_Roll && (ParamSet.GlobalConfig & CFG_AXIS_COUPLING_ACTIVE))
        {
                tmpl = (Reading_GyroYaw * Reading_IntegralGyroNick) / 2048L;
                tmpl *= FCParam.Yaw_PosFeedback;
                tmpl /= 4096L;
                tmpl2 = ( Reading_GyroYaw * Reading_IntegralGyroRoll) / 2048L;
                tmpl2 *= FCParam.Yaw_PosFeedback;
                tmpl2 /= 4096L;
                if(labs(tmpl) > 128 || labs(tmpl2) > 128) FunnelCourse = 1;
        }
        else  tmpl = tmpl2 = 0;

出0入0汤圆

发表于 2009-5-18 14:47:50 | 显示全部楼层
to 【阿莫】

cnmusic独立研究四轴很久了,是不多的几个坚持独立设计算法的之一,全力推荐【阿莫】加之为专家

出0入0汤圆

发表于 2009-5-18 15:01:08 | 显示全部楼层
【21楼】 wygood123  

这部分我还没有认真研究呢,我觉得MK的代码,有一个问题就是有些基本没效果的东西也在代码里。
而我是倾向于先发现问题,然后去MK的代码里找答案。这样就非常明确哪部分代码到底起什么作用。

你提到的这部分代码,我现在也是一头雾水呢。

出0入0汤圆

 楼主| 发表于 2009-5-18 15:06:57 | 显示全部楼层
to 【22楼】 feng_matrix 和【阿莫】

我也这样认为~他帮很多人走出了迷雾~

出0入0汤圆

发表于 2009-5-18 19:06:45 | 显示全部楼层
to wygood123

coupling这部份是在解决四轴耦合问题的代码
你试着想看看 当要yaw时又同时要roll pitch 这四颗马达的输出值是互相影响的
如果没有这段代码 虽然可以靠调整PID去克服 但是通常不给会产生些微绕圆震荡才是
不过这倒是影响不大只是能提高稳定性 因为代码里只在不做动作时才给予修正

出0入0汤圆

 楼主| 发表于 2009-5-18 19:23:56 | 显示全部楼层
to【25楼】 white

我也就这个感觉,但是说不出来~应该是理论力学没学好~嘿嘿!
看来可以先不用管,只是保证四轴更稳定!
虽然现在达不到用的级别,但是以后一定会用到的!谢谢解答!

出0入0汤圆

发表于 2009-5-18 22:46:15 | 显示全部楼层
刚才看完了MK的一段视频:http://www.mikrokopter.de/ucwiki/VideoAbspielen?id=181

看到里面那个人把一个照相机挂到四轴上后,四轴依旧可以保持自动平衡,忽然明白MK调整代码的“第三件是根据调整量的大小,决定是否需要修改陀螺仪中立点”的作用,看起来是用来自动适应负载变化的。

MK的真是厉害,居然可以让四轴在天空里玩360度空翻,太牛了!

出0入0汤圆

发表于 2009-5-19 18:36:53 | 显示全部楼层
【阿莫】看进来吧

我推荐【cnmusic】为四轴分坛的新版主
理由是他独立研读了MK的控制代码,并在自己的四轴上实现之,我与之讨论四轴控制一年有余
深觉他既有DIY动手能力,又有四轴开发经验,并且乐于与人交流,是四轴论坛版主的不二人选
请【阿莫】斟酌

出0入0汤圆

 楼主| 发表于 2009-5-19 19:37:40 | 显示全部楼层
to 【28楼】 feng_matrix 悟

"我与之讨论四轴控制一年有余"

-----------------------------------

你们什么时候开始的?挺羡慕你们的!有个知己来谈论!我都是一个人干!哎……无奈~

出0入0汤圆

发表于 2009-5-20 21:24:16 | 显示全部楼层
经过和feng_matrix的讨论,我认为我的四轴晃动原因并不是积分跟踪加速度计太紧密或别的原因,而是四轴自身重量不平衡,造成依靠重力无法稳定保持在平衡位置。使得四轴必须频繁纠正姿态,所以引起晃动。

看起来我必须看懂MK的第三种算法了,已经躲不掉了。

出0入0汤圆

发表于 2009-5-20 23:19:55 | 显示全部楼层
说得不错,cnmusic极热心的,我也向他请教过几次。
头像被屏蔽

出0入0汤圆

发表于 2009-5-20 23:28:18 | 显示全部楼层
【28楼】 feng_matrix 悟
【阿莫】看进来吧
我推荐【cnmusic】为四轴分坛的新版主  
------------------------------
支持! 我另发一新帖通知吧。

出0入0汤圆

发表于 2009-5-21 17:46:37 | 显示全部楼层
看起来MK的第三种算法并不能解决我的问题,也不能做到视频里的挂重物改变重心后依旧平稳。

今天在我的四轴上试验了一下,发现一个很关键的问题——如果陀螺仪中立点没有变化,为了能够自动补充重心改变引起的不平衡,而手动调整了中立点,最大的问题是这样积分就会一下子变化很大,是根本无法继续做到平衡的。

看起来我的问题还需要自己想办法,下了最新版的MK的源代码,没有找到能做到那个效果的部分。

出0入0汤圆

 楼主| 发表于 2009-5-21 21:28:49 | 显示全部楼层
【33楼】 cnmusic
----------------------
陀螺仪的平衡中点和四轴的重心不对称没多大关系吧!我觉得应该是在电机控制那一块吧!还在看!

是不是积分参数设置过大?

出0入0汤圆

发表于 2009-5-21 22:16:54 | 显示全部楼层
【34楼】 wygood123
我当初的理解,修改陀螺仪中立点后,相当于给对角位置的马达增加了固定的转速差异,这样也许就可以做到自动适应重心变化。因为转速差异就可以让四轴改变姿态,也有可能让四轴自动从倾斜状态回到水平。

但我没有注意到的是如果中立点变了,那么每次的积分也会随之水涨船高,造成新的问题。所以这条路走不通了。

出0入0汤圆

发表于 2009-5-21 22:24:52 | 显示全部楼层
目前我在查的地方有几个:
1、机架配重不对称,目前是容易左右晃动,所以我检查了一下左右的配重。除了发现多了一个铜柱外没有什么太大差异。
2、姿态控制频率一致性不够。由于加入了SD卡,所以那个文件系统时不时地要写一下SD,这样就会造成延迟。引起频率变化从425Hz到470Hz都有。也许这个会引起积分变化,引起晃动。这个是目前重点怀疑的。
3、P参数过大。这个也会引起震动,因为过大的P会把陀螺仪震动也放大,引起机身震动。这个我前几天试飞只用P后已经调整到一个比较合适的参数了。

出0入0汤圆

 楼主| 发表于 2009-5-22 09:51:27 | 显示全部楼层
据我的观测,使用德国的源代码飞行在重心严重失衡时(如在其中一个电机下挂个重物),也能很平稳平稳!
说明在飞控源代码里,肯定有识别重心并校正电机转速的代码!目前还在寻找……

出0入0汤圆

发表于 2009-5-22 13:59:36 | 显示全部楼层
据我的观测,使用德国的源代码飞行在重心严重失衡时(如在其中一个电机下挂个重物),也能很平稳平稳!
说明在飞控源代码里,肯定有识别重心并校正电机转速的代码!目前还在寻找……
/*-----------------------------------------------------------------------------------*/

这个同意!

出0入0汤圆

发表于 2009-5-22 15:14:18 | 显示全部楼层
to cnmusic
想请问你的四轴的抵抗力(手拿四轴故意给他小角度或大角度倾斜的反力矩)大约是MK的多少%
我自制的四轴(用PIC做飞控板再搭配MK电调)小角度抵抗力很弱 但是大角度还可以 我估计顶多只有70% MK的等级…MK真的很难扳动它
所以我的四轴室内飞行几乎跟MK一样稳定可以放手 但是在外面受风吹他就会有小震荡甚至抖动….所以我还在克服中

另外你的姿态估测法跟MK一样都是AD直就拿去做计算? 我是采取较正统方式gyro先积分成deg然后加速规与重力求倾角单位也是deg
同单位后再去做MK那种修正算法 不过因为单位不同 那些系数因子就只能胡搞乱猜了 不知道你对这有何看法 或是有特别求出那些参数的方法

出0入0汤圆

发表于 2009-5-22 15:24:49 | 显示全部楼层
不能下载了,,不知为啥,  cnmusic  能重新上传一下吗?  或发到我的邮箱上 jinglinxu@126.com  谢谢

出0入0汤圆

发表于 2009-5-22 20:03:01 | 显示全部楼层
【38楼】 nomoneyiv  

目前我也在寻找,不知道哪部分代码在高速姿态调整下可以起到这个作用。

【39楼】 white
目前我还在增加积分量,现在的积分量已经很大了,反抗力感觉不比MK的弱。用I2C电调,就可以积分很大而不会引起振荡。我的目标就是要达到MK的程度,正在努力中。你用I2C电调也可以用大的I,只要P足够好就可以克服震荡。这样小角度时也可以有很大的反抗力。

姿态算法MK和我都是直接拿AD去计算,没有转换成角度。我以前有用卡尔曼滤波换算成角度然后再进行调整,后来被卡尔曼的延迟搞到头大。现在觉得简单的就是好的,既然直接计算MK都可以做好,为什么我做不好?

【40楼】 jlxu
什么不能下载了?

出0入0汤圆

发表于 2009-5-22 20:07:26 | 显示全部楼层
【40楼】 jlxu
应该是那个V0.71h Code Redesign killagreg.rar吧

点击此处下载 ourdev_446983.rar(文件大小:186K) (原文件名:V0.71h Code Redesign killagreg.rar)

出0入0汤圆

发表于 2009-5-22 20:17:59 | 显示全部楼层
今天稳定性有了点收获。

我把四个马达都换掉了,以前用的850KV的马达有一个桨夹被一次倒扣给撞弯了,然后只要高转速就会非常抖,抖到手根本拿不住。而另外2个马达就没这个问题。由于桨夹没有单卖的,只好把4个马达全都换了。现在也是新西达2212 1000KV的马达了。

经过这个调整后,现在水平方向已经比较平稳了,以前的晃动被消除了。不过前后又开始晃动,真是按下葫芦瓢又起。不过这回的抖动我知道原因——重心配比不平衡,由于我这个四轴并不是完全对称的机架,以前手工设置的马达调整量不完全正确,所以四轴自己拉平后一撤掉调整量就又歪了,于是就开始晃动。

现在的姿态调整频率已经稳定到500Hz,这是拿示波器量过确认的。我把SD卡部分的代码放到了main里,这样就不用担心姿态调整中断被打扰了。给我的感觉现在有可能上到1000Hz的调整速度呢。

出0入0汤圆

发表于 2009-5-22 22:50:16 | 显示全部楼层
桨夹没有单卖 ?

自己做的机架?

出0入0汤圆

发表于 2009-5-23 08:08:27 | 显示全部楼层
【44楼】 luzhengmao
只和马达一起卖,一套要¥100多,贵死。

出0入0汤圆

发表于 2009-5-23 13:16:46 | 显示全部楼层
to cnmusic  

  PCB是自己重做吗??

出0入0汤圆

发表于 2009-5-23 13:48:06 | 显示全部楼层
【46楼】 jlxu  

全部自己重新设计的,没有采用MK的。

出0入0汤圆

发表于 2009-5-23 14:07:42 | 显示全部楼层
兼用MK代码吗,,,发个图上来学习一下,,

出0入0汤圆

发表于 2009-5-23 15:25:02 | 显示全部楼层
【48楼】 jlxu

100%不兼容。 http://www.ourdev.cn/bbs/bbs_content.jsp?bbs_sn=3329702&bbs_page_no=1&bbs_id=1025 这里有图。


----------------------------------------------------------------------------------------------------------------
今天继续有所收获。

本来是根据MK的四轴来调整我的四轴I参数的,我发现MK的四轴在倾斜45度后马达转速加倍,于是我就用这个来调整我的I参数,可确发现了这个问题。


(原文件名:1.gif)


陀螺仪积分放一阵子不动会自己衰减下去。这个以前还没注意到过。

又仔细看了看MK的数据,他的没有这个问题。


(原文件名:3.gif)

陀螺仪积分和加速度配合的很好。

可这时为什么呢?忽然我想到以前看到单没有引起注意的一个参数:ACC_AMPLIFY。

在MK的融合算法的即时融合里,我注意到他用加速度计去补偿陀螺仪的积分,这2种风马牛不相及的东西居然可以放到一起,这个ACC_AMPLIFY起到了关键的作用。它将加速度计的数据放大,做到和积分差不多,然后才能用来补偿。而我犯的错误就是直接拿原始的加速度计数据去补偿了,结果怎么算积分也是偏大,这就造成了陀螺仪积分逐渐地被越衰减越小。

重新设置的放大倍数为3的ACC_AMPLIFY参数后,四轴地积分曲线终于正常了,不再会衰减了。

   
(原文件名:2.gif)

出0入0汤圆

发表于 2009-5-23 23:34:26 | 显示全部楼层
顶CNM,支持.

出0入0汤圆

发表于 2009-5-24 09:10:44 | 显示全部楼层
在我调整数据到

(原文件名:1.gif)

后,悬停的时候左右、前后都不晃了。不过现在对水平位置锁定还有问题,开始往后飘了。
另外方向操作后还会晃一晃,估计是积分过大的问题。

出0入0汤圆

发表于 2009-5-24 14:24:59 | 显示全部楼层
to cnmusic

呵呵…
我就是遇到这样的问题
我的姿态P(就是MK里的积分I 我用正统PID写法分两层 姿态部分用了PID内层的rate部分用P所以跟MK不太一样 因为MK用了不是很正统的PID写算是他自己的变形)调太大虽然反抗力很强不过只要受到一点扰动或是打了一个动作 回复时就会震荡 虽然是收敛 但是就是会振好几次才稳定所以只好把值调小..调小反抗力就差了点不过我倒是可以自己稳定回水平 室内飞行几乎不用碰遥控器 只需要偶尔动一下油门让高度在一个水平(我没有做高度控制)

出0入0汤圆

发表于 2009-5-24 16:32:18 | 显示全部楼层
今天搞定了视频http://www.mikrokopter.de/ucwiki/VideoAbspielen?id=181 里的那个挂相机的动作,终于明白了为什么MK的可以做到这种稳定。

我的四轴现在也可以在重心变化的时候保持稳定了,原因很简单,就是因为陀螺仪。

在挂上重物后,四轴一起飞,势必往重的方向倾斜,这就产生了一个这个方向的角速度。可以角速度可以被陀螺仪检测到并由PID处理。由于处理频率很快,所以基本没有时间让这个角速度产生位移就处理完了。这就形成了在外部看来四轴完全不受重心改变的影响。这个效果并不需要特殊的代码就可以做到,实在是很巧妙的。核心就是一个相当大的I参数,大到可以产生足够的拉力把重物拉起来。


【52楼】 white
这个效果如果减小I积分的话就会做不到。我的那个方向操作后的晃动除了减小I参数外还有别的可以修改的途径。
不过我目前一直想搞定漂移的问题,所以先不去管它了。

出0入0汤圆

发表于 2009-5-24 17:24:33 | 显示全部楼层
今天还把陀螺仪温飘的修正代码加上了,不过在试飞的时候并没有出现过调整动作。

   // deviation of gyro nick integral (IntegralNick is corrected by averaged acc sensor)
   IntegralErrorNick  = IntegralNick2 - IntegralNick;
   Reading_IntegralGyroNick2 -= IntegralErrorNick;

   cnt = 1;// + labs(IntegralErrorNick) / 4096;
   CorrectionNick = 0;
   if((labs(MeanIntegralNick_old - MeanIntegralNick) < MOVEMENT_LIMIT) || (FCParam.Kalman_MaxDrift > 3* 16))
   {
    if(IntegralErrorNick >  ERROR_LIMIT2)
    {
     if(last_n_p)
     {
      cnt += labs(IntegralErrorNick) / ERROR_LIMIT2;
      CorrectionNick = IntegralErrorNick / 8;
      if(CorrectionNick > 5000) CorrectionNick = 5000;
      AttitudeCorrectionNick += CorrectionNick / BALANCE_NUMBER;
     }
     else last_n_p = 1;
    }
    else  last_n_p = 0;
    if(IntegralErrorNick < -ERROR_LIMIT2)
    {
     if(last_n_n)
     {
      cnt += labs(IntegralErrorNick) / ERROR_LIMIT2;
      CorrectionNick = IntegralErrorNick / 8;
      if(CorrectionNick < -5000) CorrectionNick = -5000;
      AttitudeCorrectionNick += CorrectionNick / BALANCE_NUMBER;
     }
     else last_n_n = 1;
    }
    else  last_n_n = 0;
   }
   else
   {
    cnt = 0;
    BadCompassHeading = 1000;
   }
   if(cnt > ParamSet.DriftComp) cnt = ParamSet.DriftComp;
   if(cnt * 16 > FCParam.Kalman_MaxDrift) cnt = FCParam.Kalman_MaxDrift / 16;
   // correct Gyro Offsets
   if(IntegralErrorNick >  ERROR_LIMIT)   AdNeutralNick += cnt;
   if(IntegralErrorNick < -ERROR_LIMIT)   AdNeutralNick -= cnt;

这是MK的0点调整代码,再解说之前,先看看为什么需要进行温飘调整。

还是这个图:
<br>
<br>&nbsp;(原文件名:1.gif)&nbsp;

通过这个图可以很明确地看出来,如果不进行温飘调整,到后来陀螺仪会越偏越大,直到超过加速度计的调整范围。
在实际测试中,如果让马达转2分钟,在没有0点调整代码的情况下,会明显感觉四轴开始慢慢地向一边歪,而程序则将这个歪的位置认为是平衡位置。

看到这个图,我们大概也可以明白如何进行0点调整了。那就是我们需要比较陀螺仪的原始数据的积分和我们经过调整后的积分值之间的差异,如果这个差异过大,那么说明我们需要动一下0点了。MK的流程也差不多是这样,只是他写的比较复杂。

   // deviation of gyro nick integral (IntegralNick is corrected by averaged acc sensor)
   IntegralErrorNick  = IntegralNick2 - IntegralNick;
   Reading_IntegralGyroNick2 -= IntegralErrorNick;

这部分,就是计算陀螺仪原始数据积分和调整后积分的差异的。IntegralNick2,Reading_IntegralGyroNick2  是陀螺仪原始数据积分,IntegralNick是经过加速度计调整后的积分,IntegralErrorNick  就是他们的差异。
第一行求出差异,第二行将这个差异从陀螺仪的原始积分里去掉,Reading_IntegralGyroNick2 这个是真正在AD部分用的陀螺仪原始数据积分。这个去掉的动作很重要,否则的话一旦积分差异超过上限,就会一直调整下去。

下面的部分就是根据这个差异进行判断,其实很多时候代码执行起来是这样的:
   cnt = 1;
   // correct Gyro Offsets
   if(IntegralErrorNick >  ERROR_LIMIT)   AdNeutralNick += cnt;
   if(IntegralErrorNick < -ERROR_LIMIT)   AdNeutralNick -= cnt;

关键部分就是:
  if(IntegralErrorNick >  ERROR_LIMIT)   AdNeutralNick += cnt;
   if(IntegralErrorNick < -ERROR_LIMIT)   AdNeutralNick -= cnt;

其中ERROR_LIMIT是(BALANCE_NUMBER * 4),意思是如果我们每次进行积分,2个数据差异都有4,那么说明我们确实应该调整一下中立点了。
代码简化成上面的形式就容易理解多了,就是看一下差异,如果超过ERROR_LIMIT那么就对陀螺仪中立点增加1,如果小于-ERROR_LIMIT,那么就减1。
而这个差异是执行了BALANCE_NUMBER次计算后的,也就是积分要在0.5秒内差出这么多才可以。条件还是很严格的。

不过MK还多想了一些,还想到了如果在这0.5秒内一下子差出(BALANCE_NUMBER * 16)的情况:
cnt = 1;// + labs(IntegralErrorNick) / 4096;
   CorrectionNick = 0;
   if((labs(MeanIntegralNick_old - MeanIntegralNick) < MOVEMENT_LIMIT) || (FCParam.Kalman_MaxDrift > 3* 16))
   {
    if(IntegralErrorNick >  ERROR_LIMIT2)
    {
     if(last_n_p)
     {
      cnt += labs(IntegralErrorNick) / ERROR_LIMIT2;
      CorrectionNick = IntegralErrorNick / 8;
      if(CorrectionNick > 5000) CorrectionNick = 5000;
      AttitudeCorrectionNick += CorrectionNick / BALANCE_NUMBER;
     }
     else last_n_p = 1;
    }
    else  last_n_p = 0;
    if(IntegralErrorNick < -ERROR_LIMIT2)
    {
     if(last_n_n)
     {
      cnt += labs(IntegralErrorNick) / ERROR_LIMIT2;
      CorrectionNick = IntegralErrorNick / 8;
      if(CorrectionNick < -5000) CorrectionNick = -5000;
      AttitudeCorrectionNick += CorrectionNick / BALANCE_NUMBER;
     }
     else last_n_n = 1;
    }
    else  last_n_n = 0;
   }

首先,如果上次的陀螺仪积分平均值和这次的差异不大,那么去判断是否需要调整中立点。具体为什么,不知道,有待后续研究。
下面就是判断的流程,如果积分差异超过ERROR_LIMIT2,也就是(BALANCE_NUMBER * 16),且出现了2次(last_n_p标志位),那么我们根据这个积分差异来计算cnt这个调整量的数值。
然后根据差异算出AttitudeCorrectionNick 的调整量。

不过我比较怀疑有多大几率陀螺仪0点会一下子飘很多,一般情况下都是慢慢飘的,所以我怀疑这部分复杂逻辑在实际飞行时有没有起到很多的作用。

出0入0汤圆

发表于 2009-5-25 11:28:27 | 显示全部楼层
能否上个视频看看呢?

出0入0汤圆

发表于 2009-5-26 22:13:52 | 显示全部楼层
【55楼】 gcc4isr

看16楼。

-------------------------------------------------------
刚才又仔细看了看MK的控制部分的代码,因为从我买的四轴的实际动作来看,我以前的理解有误。

仔细研究了以后,发现几个以前的理解错误:
1、Looping_Nick、Looping_Roll指的是四轴飞3D时在空中翻跟头时用的变量,而不是一般的方向控制。
2、那些融合代码,目地都是让陀螺仪积分紧跟加速度计,而不是试图让四轴维持在水平位置。

所以当有方向操作时,虽然四轴会倾斜,但也不能无限制倾斜,还是会被积分限制住。而不像我以前的算法,被积分给拉回平衡位置。
这和我以前的理解不大一样,让我更佩服MK了。

出0入0汤圆

发表于 2009-5-27 14:12:16 | 显示全部楼层
有看头!顶!!!!!!!!!!!!!!!!!!!!!!!!!!!!

出0入0汤圆

发表于 2009-5-29 00:00:24 | 显示全部楼层
楼主,我是指您修正后的,可以挂重物的视频啊.

出0入0汤圆

发表于 2009-5-29 14:44:10 | 显示全部楼层
【58楼】 gcc4isr
还没拍摄,正在调新板子呢。

出0入0汤圆

发表于 2009-6-1 17:56:53 | 显示全部楼层
今天继续试飞,换上了德国的EPP1045桨,确实震动小多了。

今天对平衡算法又有些新的理解:
1、那个长期,即时的陀螺仪积分和加速度计的融合,都是针对下一次PI的,而不是当前的这次。我以前都以为是针对当前的呢,结果相当于把误差放大了,造成晃动。

2、对于那个长期融合,看起来MK基本没发挥作用。首先是这个调整量非常小,我按照MK的参数运算后得到的几乎没有超过1的,最大也不过0.5。在MK的代码里他用了整数,所以我分析这部分代码和没有差不多。另外我把我的代码里的这部分调整去掉后,得到的效果和MK的非常接近了。离平衡位置的调整“死区”非常小,而加上这部分代码后情况就变糟糕了。

明天继续试飞,还是要拿实践来检验的。

出0入0汤圆

发表于 2009-6-2 09:27:13 | 显示全部楼层
to 【60楼】 cnmusic

看到你对德国四轴程序的分析和讲解,简直就是透彻到底。让我这个菜鸟来说受益匪浅呀!。呵呵!辛苦了。。。。。。。

楼主,我也试过更改了下飞控的程序。。。发现了个不解的问题 如:我现在仿的德国四轴,用的加速度是MMA7261。。。和原版的不同。。。所以为了达到波形重合的效果,更改了ACC_AMPLIFY 的赋值,进行了德国源代码的编译。。值由原来的12改到了18,结果波形的重合性非常的理想。但结果我试飞感觉也不是非常明显的改善。于是把值改成了8,结果波形重合性就很差了。结果试飞。本以为理论上是很差的???但结果感觉和改前没有明显的区别。

结论:是不是波形重合的好坏,直接影响四轴飞行的重要因素之一呢?还请楼主分析下。。TKS

出0入0汤圆

发表于 2009-6-2 11:20:03 | 显示全部楼层
【61楼】 gl516
那个加速度计的数值,不是越大越好的。

很重要的一点就是MK用加速度计来修正陀螺仪,虽然有进行除16衰减,但如果你的加速度计放大倍数太大的话,这样衰减下来也是不够小。这样就会把振动引入到陀螺仪积分里,然后就很难飞了。

我昨天就把那个除16的衰减倍数降低,变成4.8,结果基本没法飞了,数据显示积分已经是一大糊涂了。

相比波形是否重合,调整量的大小更关键一些。如果波形重合不好,至多是不会自动回到平衡位置,不会会的很稳,很准,会有些偏差。而如果调整量过大,那基本就是灾难了。

要想看出这个重合的效果,就要在四轴倾斜的时候放开控,看它多久回到平衡位置。或者在它悬停的时候放开控,看它能悬停多久不会自己歪掉。

出0入0汤圆

发表于 2009-6-2 16:55:56 | 显示全部楼层
TO 【62楼】 cnmusic  

非常感谢你详细的分析。。。但确实我通过试验证明了,波形的重合性的好坏,感觉对四轴并不是影响很大呀@!@。。。也许是在家中飞行感觉不出来???

按照你说的方法,今晚再去测试下。。。哦!今天DAC的片子到了,估计要升级下飞控了。感觉下用DA来进行的校正能带来多大的改善!随后我会反馈测试的所有信息的!TKS

出0入0汤圆

发表于 2009-6-4 14:39:32 | 显示全部楼层
上一个最新的视频:
http://you.video.sina.com.cn/b/21405754-1407327420.html

周围有2-3级风。看起来还可以飞更高,但飞高了太小了我都没法操作了。

出0入0汤圆

发表于 2009-6-4 20:32:38 | 显示全部楼层
刚刚从外面飞回来。。。呵呵!不是真的飞机。。。

一个字“爽”。。。两个字“具爽”。。。。。第一次在开阔地飞行,没有任何的约束。。。。飞的很高!。。。(*^__^*) 嘻嘻……今天没有带相机呀。。。看不到照片和视频了!

GL516-四轴---《飞后感》:

1,的却在宽阔的地方飞行。。。飞的就是爽。。你可以升到10M左右的地方,放开遥控任它飞去。
2,高空中(在没有大风的情况下)飞行的稳定还算行。
3,低空飞行不怎么理想。。老是高度不稳定;会飘。。(大概在1~3m 的高度,时上时下,需要不停控制好油门)
4,电池的飞行能力估计也就是15~20左右。(还是间接飞行的)
5,机机爬升的速度超级快!一加大油门。。嗖。。一下飞的好高!

总结:需继续改善。。。做到更好!软件方面还得请CNMUSIC帮忙...tks!

出0入0汤圆

发表于 2009-6-4 23:07:16 | 显示全部楼层
问个问题,4轴下降时,是怎么控制的? 是不是随风飘下来的.如果遇到风大,是不是会被风越吹越高?

出0入0汤圆

发表于 2009-6-5 00:17:18 | 显示全部楼层
不错记号

出0入0汤圆

发表于 2009-6-6 12:11:52 | 显示全部楼层
To cnmusic
不知道你可否解释一下analog.c里面MK抓取AD值要累加好几次??
ATMEGA644应该是10bit AD所以照理说AD值应该为0~1023
不过似乎FC.c里面的gyro与加速度的AD值都有乘个倍数??
可以详细说明这部分吗??
另外..再想请问一个…MK是不是吧遥控器讯号的值域转换成跟传感器的值域一样??

出0入0汤圆

发表于 2009-6-6 15:04:46 | 显示全部楼层
【68楼】 white  

AD反复取值都是为了求平均来过滤掉干扰和振动。边上的注释写的很清楚。

fc.c里的加速度数值乘倍数是为了能让加速度计和陀螺仪积分大小差不多,达到【49楼】的MK界面里的那个效果,这个和AD的数据范围无关。否则没法准确融合和识别陀螺仪中立点温漂。如果没有这个倍数,陀螺仪积分始终会比加速度计的数值大,这样在判断中立点漂移的时候就会一直以为在飘,就没法进行纠正了。关于中立点修正部分再详细的看【54楼】。

对于加速度计融合进陀螺仪,一定是以陀螺仪积分为主,而加速度计的修正量为辅。每次的调整量都是很小的,这样才能避免机械振动把陀螺仪积分搞乱套。这个融合速度,有一个ParamSet.GyroAccFactor来决定。MK代码中还有写死的一个 /16。

如果不把加速计放大,光靠ParamSet.GyroAccFactor,就会变成【49楼】第一个图的样子,积分会自己变小,这样子飞起来就会自己晃动。原因就是陀螺仪积分和加速度计数值不匹配,总是积分大,加速度计小,于是就会一直衰减。而放大后就没有这个问题了,【51楼】的第一个图就是比较完美的结果。



至于有没有把遥控器转换相同的大小,我认为有转。只不过这部分和姿态关系不是很紧密,所以我没有过多地去研究。

出0入0汤圆

 楼主| 发表于 2009-6-8 09:30:14 | 显示全部楼层
偶到现在看来,算法并不非常复杂(归功于楼主的讲解)~就是参数非常不好定!
偶觉得mega8好像都可以胜任控制器了~当然需要除去很多不必要的元素~

现在实现基本悬停(会左右上下漂移)编写出来的代码HEX大小8K不到~

出0入0汤圆

发表于 2009-6-8 11:37:07 | 显示全部楼层
呵呵..我做的四轴终于可以像MK一样侧边挂重物了
我有试挂一颗电池跟一瓶装半满水的宝特瓶只挂一边
他依然可以保持水平…..
我没有照MK的写法而是自己用正统的PID写法分两层 约200Hz控制
内层rate control外层angle control….参数还蛮好调整的
rate那部份用了PD,angle那部份用了PI
不过我觉得我问题还是在姿态估测那里…..
把加速度传感器调整灵敏会因为震动而姿态飘移….
调迟钝又会影响姿态的反应….
所以目前一起飞会稍微倾斜一个小角度然后才慢慢自我恢复水平

出0入0汤圆

发表于 2009-6-8 13:15:09 | 显示全部楼层
其实挂重物的逻辑并不想想象中的那么复杂,只要I够大都可以做到。不过我的四轴目前会在这种不平衡的时候产生小幅度的晃动,但晃动角度和重物重量没有关系。产生这个晃动的原因我想是中立点的识别不够准确,由于加速度计和陀螺仪震动的关系。

要是像达到那个录像里那么稳,恐怕还要下些功夫。至少机架刚性要足够,桨震动要小。

姿态平衡算法有很多种,MK只是其中的一种。我花时间研究它是因为看他的效果比较好,至少比我自拍脑袋想的要好。

出0入0汤圆

发表于 2009-6-8 13:18:32 | 显示全部楼层
【70楼】 wygood123  

我也觉得M8可以胜任,就是代码难度可能要上去了,因为要同时处理的东西挺多,资源有限,要节省使用。
参数确实很让人头疼,特别是自己实现的话。什么参数都可以调整带来的问题就是不知道应该调哪个,这个问题上我花了好多时间呢。

出0入0汤圆

 楼主| 发表于 2009-6-8 14:24:42 | 显示全部楼层
请问,看德国的全是用遥控来飞!至于什么惯导等都没用上(偶分析0.68版的源码得出的结论),脱离遥控后只能乱飞!
最后却选择GPS和气压传感器来限位。所以好像还没有达到单键自控制的水平,偶想这也应该是非常难达到的水平。

如果能做到脱离GPS和气压传感器后,仅凭“悬停”“前进”“后退”“左偏”“右偏”“上”“下”“降落”“起飞”“旋转”等这几个小按钮来控制就高级了~没有指示时,自动进入“悬停”状态……

不知道我们什么时候能到达这个水平!

出0入0汤圆

发表于 2009-6-8 16:21:43 | 显示全部楼层
【74楼】 wygood123
我想至少需要计算机视觉。

出10入95汤圆

发表于 2009-6-8 23:59:22 | 显示全部楼层
路过,好东西!

出0入0汤圆

发表于 2009-7-2 15:32:19 | 显示全部楼层
惊人的发现,呵呵!要学习啊!

出0入0汤圆

发表于 2009-7-7 18:08:57 | 显示全部楼层
自己打算开始读V0.71h Code Redesign killagreg的代码,请问各个C文件里主要完成哪些工作
analog.c   eeprom.c  fifo.c   main.c   mk3mg.c    mm3.c    mymath.c    printf_p.c     rc.c   spi.c......
看了一下以上帖子,对fc.c有一些了解了,代码里似乎有一些是没有真正意义的,请大家就这一方面解答一下

出0入0汤圆

发表于 2009-7-7 22:33:38 | 显示全部楼层
剩下那些模块看起来都没有什么难度了,包括处理AD信号,EEPROM中的默认参数,主循环,3轴电子罗盘,一些辅助函数,遥控器接口等等,都很好理解了。自己稍微花点时间就都看明白了。

出0入0汤圆

发表于 2009-7-16 15:42:44 | 显示全部楼层
这么好的帖子怎么就沉默了呢?高手们不要吝啬你们的智慧!!!

出0入0汤圆

发表于 2009-7-23 16:09:35 | 显示全部楼层
学习中,GOOD

出0入0汤圆

 楼主| 发表于 2009-7-26 16:04:51 | 显示全部楼层
【80楼】 dreamshl

-------------------
cnmusic已经很明白的解说了飞控算法的事!
再说只能是画蛇添足了!要飞起来,凭借 cnmusic的思路就可以了!但是想飞好,飞稳,可要下点功夫了!偶还在实验阶段!感觉比较难控制!没有电子罗盘和GPS很难!只能慢慢来了!

出0入0汤圆

发表于 2009-8-7 16:41:38 | 显示全部楼层
学习中

出0入0汤圆

发表于 2009-8-8 11:36:49 | 显示全部楼层
Reading_IntegralGyroRoll 、 IntegralRoll  都是陀螺仪积分,有什么区别?

出0入0汤圆

发表于 2009-8-17 21:26:45 | 显示全部楼层
这些变量,Reading_开头的都是从传感器直接读出的,没有的是一些临时变量,只是一次姿态调整时使用,然后就重新赋值了。
那些Reading_的变量不会直接被重新赋值,属于积累性质的。后面有2的是原始的,没有的那些是增加了调整量的。

出0入0汤圆

发表于 2009-8-23 13:26:45 | 显示全部楼层
学习

出0入0汤圆

发表于 2009-8-23 18:36:56 | 显示全部楼层
cnmusic,不知你的四轴研究到啥程度了呀,透露下。

出0入0汤圆

发表于 2009-8-27 09:48:43 | 显示全部楼层
到目前为止,已经调试了2架四轴,发现MK代码里的长期融合还是必不可少的。

虽然我最开始测试的四轴,经过“千锤百摔”后陀螺仪性能达到相当稳定的程度,只依靠加速度计的即时融合就可以修正好积分偏差。但并不是所有的四轴都是这样,我后来做的几个就都都有积分越来越大的问题。这会引发一个非常严重的问题——长时间飞行后四轴会越来越歪,歪到遥控器必须满舵量才能让四轴飞平。数据显示原因就是积分越来越大,而修正量总是不够大,虽然在小幅度范围内积分有大有小,但总体趋势是越来越大。

在反复调整螺旋桨、机架试图减小振动没有效果后,我只好手动加了一个让积分衰减的代码:
        if (nIntegralPitch > 0.0)
        {
                nIntegralPitch -= 0.01;
        }
        
        if (nIntegralPitch < 0.0)
        {
                nIntegralPitch += 0.01;
        }
        

        if (nIntegralRoll > 0.0)
        {
                nIntegralRoll -= 0.01;
        }
        
        if (nIntegralRoll < 0.0)
        {
                nIntegralRoll += 0.01;
        }
这样一来就不再出现越来越偏的问题了。

这段代码看起来的执行效果和MK的长期融合非常接近,但由于只是盲目地增大或者减小积分,导致四轴漂移比较大,在平衡位置10度左右就无法拉平了。所以今天我就重新启用MK的长期融合逻辑,只是把衰减量由原来的/16改成/32,这样调整量也基本在0.0X附近。刚才试飞效果不错,漂移明显减小了。

出0入0汤圆

发表于 2009-8-27 22:37:38 | 显示全部楼层
【88楼】 cnmusic
很早就看了你的这个帖子,真的很经典,如此好的帖子,希望你能再将你最近的研究成果一起总结总结,整理成一个文档,那样将会长远流传下去,有时候不是不想研究程序,只是有很多障碍,我最近也在开始看程序,但问题依然很多,希望能得到你的帮助,不知能留个联系方式不?

出0入0汤圆

发表于 2009-8-28 23:16:16 | 显示全部楼层
楼上看这个:
http://www.ourdev.cn/bbs/bbs_content.jsp?bbs_sn=3237183&bbs_page_no=1&search_mode=1&search_text=看看我们的&bbs_id=1025

出0入0汤圆

发表于 2009-8-30 11:22:57 | 显示全部楼层
【90楼】 verystupid
谢谢,去找他们问问,呵呵

出0入0汤圆

发表于 2009-9-5 00:46:30 | 显示全部楼层
都是牛人啊

出0入0汤圆

发表于 2009-9-9 22:15:50 | 显示全部楼层
我现在要做的项目要用到LIS302DL+3片ENC-03MA.做物体运动采样!
虽然不是四轴飞行,应该还有共同的地方

出0入0汤圆

发表于 2009-9-13 20:03:10 | 显示全部楼层
还是应该坚持从代码看起。

出0入0汤圆

发表于 2009-10-18 21:32:50 | 显示全部楼层
新手一个!继续潜水学习!

出0入0汤圆

发表于 2009-10-20 12:04:07 | 显示全部楼层
经典的帖子,现在还没有足够的功力来看懂,标记!

出0入0汤圆

发表于 2009-11-13 12:24:36 | 显示全部楼层
学习ing

出0入0汤圆

发表于 2009-11-25 23:48:17 | 显示全部楼层
新手,虽然看不懂,非常关注。感谢cnmusic 精彩讲解!

出0入0汤圆

发表于 2009-11-26 01:02:16 | 显示全部楼层
学习中。。。

出0入0汤圆

发表于 2009-11-29 09:25:09 | 显示全部楼层
学习了,谢谢

出0入0汤圆

发表于 2009-12-3 07:48:09 | 显示全部楼层
学习中
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

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

GMT+8, 2024-3-29 04:44

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

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