zzipeng 发表于 2014-11-15 14:24:38

加速度数据滑动滤波莫名错误!求救!

本帖最后由 zzipeng 于 2014-11-15 16:40 编辑

如题,我现在弄四轴代码。姿态已经初步解算出来。但是遇到一个很奇怪的问题。即加速度数据平滑滤波时,输出的数据莫名变大。先上代码:

#define gyro_denominator 3753.15f //陀螺仪灵敏度
#define acc_denominator 836.943f //加计灵敏度8192/9.788=836.943 广州重力加速度 9.788m/s^2
int16_t G_X,G_Y,G_Z,A_X,A_Y,A_Z;//减去零偏后的数据
int16_t ACC_Axis_X,ACC_Axis_Y,ACC_Axis_Z;//加计滑动滤波后输出的数据
float IMU_GYRO_X,IMU_GYRO_Y,IMU_GYRO_Z;//角速度rad/s
float IMU_ACC_X,IMU_ACC_Y,IMU_ACC_Z;//加速度m/s^2
。。。。。。。。
if(Data_Slid_Analys==TRUE)//检测加计平滑滤波标志
        {
                uint8_t i;
                static u8 coun=0;
                static int16_t ACC_BUF_X;
                static int16_t ACC_BUF_Y;
                static int16_t ACC_BUF_Z;
                int32_t Tempx,Tempy,Tempz;
               
       
                ACC_BUF_X = A_X;
                   ACC_BUF_Y = A_Y;
                ACC_BUF_Z = A_Z;
               
                for(i=0;i<20;i++)
                {
                        Tempx+=ACC_BUF_X;
                        Tempy+=ACC_BUF_Y;
                        Tempz+=ACC_BUF_Z;
            }
               
                ACC_Axis_X=Tempx / 20;//求平均输出
                ACC_Axis_Y=Tempy / 20;
                ACC_Axis_Z=Tempz / 20;

       
                IMU_ACC_X=ACC_Axis_X / acc_denominator; //将滑动滤波后的加计数据转换成以m/s^2为单位的加速度数据
                IMU_ACC_Y=ACC_Axis_Y / acc_denominator;
                IMU_ACC_Z=ACC_Axis_Z / acc_denominator;
               
                IMU_GYRO_X=G_X / gyro_denominator; //将陀螺仪数据转换成以rad/s为单位的角速度数据
                IMU_GYRO_Y=G_Y / gyro_denominator;//
                IMU_GYRO_Z=G_Z / gyro_denominator; //
               
                coun++;
                if(coun==20)   {coun=0;        IMUupdate_Flag=TRUE;//可以解算姿态了}
               
       
        }
可以看到,代码其实很简单的。就是对减去零偏后的加计数据平滑滤波后转换成加速度输出,陀螺仪数据不作滤波处理,直接转换成角速度输出。问题是我用匿名的上位机对加计平滑滤波后的数据进行显示观看。发现变量ACC_Axis_X明显变大,直接飙到26000!见图1。奇怪的是ACC_Axis_Y,ACC_Axis_Z并无影响。于是我将ACC_Axis_X=Tempx / 20;//求平均输出这语句屏蔽掉;将IMU_ACC_X=ACC_Axis_X / acc_denominator; 这语句中的ACC_Axis_X 改为A_X,即X轴加计数据放弃滤波输出,这时发现轮到ACC_Axis_Y数据发飙了,ACC_Axis_Z无影响!
        试过将acc_denominator,gyro_denominator两个参数改为整数,结果并无变化。。。

john800422 发表于 2014-11-15 15:22:58

可以參考我之前寫的
https://github.com/QCopter/QCopterFlightControl/blob/Pre-v2.2/Software/QCopterFC_FlightControl/Program/Algorithms/algorithm_moveAve.c

沒仔細看, 但覺得可能是靈敏度或是益位問題

asha 发表于 2014-11-15 15:42:26

额 还没有累加到20个数 就去求均值?

zzipeng 发表于 2014-11-15 16:37:48

asha 发表于 2014-11-15 15:42
额 还没有累加到20个数 就去求均值?

这个代码是局部的。。。实际的代码是这个函数执行20次之后才允许后面姿态解算

zzipeng 发表于 2014-11-15 16:52:24

john800422 发表于 2014-11-15 15:22
可以參考我之前寫的
https://github.com/QCopter/QCopterFlightControl/blob/Pre-v2.2/Software/QCopterFC_ ...

你给的链接上的代码看了,感觉没什么区别啊。。。原理都一样
能讲一下什么事溢位吗?与溢出有什么不同。。。谢了

lans0625 发表于 2014-11-15 17:00:49

应该是硬件的问题。。。。

lovecxm 发表于 2014-11-15 14:24:39

累加和Tempx临时变量,会不会有时候进入的时候不是0呢?一般我们定义成静态变量,,计算一次之后清0,也就是=20的时候清0.

zzipeng 发表于 2014-11-15 20:39:43

本帖最后由 zzipeng 于 2014-11-15 20:43 编辑

lovecxm 发表于 2014-11-15 19:11
累加和Tempx临时变量,会不会有时候进入的时候不是0呢?一般我们定义成静态变量,,计算一次之后清0,也就 ...

靠。。按你的说法,将Tempx、Tempy、Tempz三个变量由临时类型改为static类型还真奇迹发生了——问题解决。见图

dj1981812 发表于 2014-11-15 21:20:49

给你一个平滑滤波的算法。我已经用了10年了,非常好用,比起你那个20点统计一次并求平均的算法要简单很多。这个算法同样也是求平均值滤波算法。
uint8filter_NUM=20; //定义需要滤波数据的个数
Out_AD_Data=(filter_NUM*AD_Data_filter_last+AD_Data))/(filter_NUM+1);
AD_Data_filter_last=Out_AD_Data;

Out_AD_Data是最终输出后的滤波值,也就是你要用的值
AD_Data_filter_last是缓存值,存储上一次得到的滤波数据结果
AD_Data为AD采样到的数据
filter_NUM为定义需要滤波数据的个数

这个算法有个缺点,当前20个数据进入前Out_AD_Data输出数据会偏小很多。但是一旦AD数据超过20个以后,这个平滑滤波系统输出数据就很稳定了,并且不需要每次都采集20个数据后再进行滤波。可以直接一直滤波。      

zzipeng 发表于 2014-11-15 21:28:25

dj1981812 发表于 2014-11-15 21:20
给你一个平滑滤波的算法。我已经用了10年了,非常好用,比起你那个20点统计一次并求平均的算法要简单很多。 ...

谢谢!代码看了,的确很巧妙!{:handshake:}

dj1981812 发表于 2014-11-15 21:57:17

不客气,好用就行。

onev 发表于 2014-11-16 10:17:41

你这个不对吧?!temp本来就应该是临时变量,所以你贴的源码没有错误。然后就是,加速度计静止时读数不应该是零而是重力加速度值,所以一般平放时Z轴会有很大的输出。另外确保没有数据类型错误!

oner 发表于 2014-11-16 10:30:38

略看了一下代码,发现你Tempx,Tempy,Tempz根本没清零,不飙大数据才奇怪呢。
你用的是均值滤波,连续采集20次后,再求平均值。即在
                ACC_Axis_X=Tempx / 20;//求平均输出
                ACC_Axis_Y=Tempy / 20;
                ACC_Axis_Z=Tempz / 20;
后面加上一下清零代码:
                Tempx =0;
                Tempy =0;
                Tempz =0;
这样就解决你的问题了。目测是这个问题,你可以试一下。

应用在四轴上不太建议用均值滤波,降低频响.......

zzipeng 发表于 2014-11-16 12:15:05

oner 发表于 2014-11-16 10:30
略看了一下代码,发现你Tempx,Tempy,Tempz根本没清零,不飙大数据才奇怪呢。
你用的是均值滤波,连续采集20 ...

已经按照你的意见将Tempx、Tempy、Tempz三个变量由static改为临时变量(去掉static),然后加上Tempx=0;Tempy=0;Tempz=0;几句代码,结果并无改变。忘记说了,我现在用的代码是Tempx、Tempy、Tempz为static变量,然后Tempx=0;Tempy=0;Tempz=0;这三句代码也是有的。
还有要说明的是,我用的是滑动滤波而不是简单的每采样20次然后求平均值输出。看到        ACC_BUF_X=A_X;这代码中的coun和数组ACC_BUF_X[]为static 变量就知道了。
                       
                       

oner 发表于 2014-11-17 17:43:19

zzipeng 发表于 2014-11-16 12:15
已经按照你的意见将Tempx、Tempy、Tempz三个变量由static改为临时变量(去掉static),然后加上Tempx=0;Te ...

哦哦,的确是滑动滤波,我之前没细看误导你了。

yanghuanchun 发表于 2015-4-11 14:39:59

dj1981812 发表于 2014-11-15 21:20
给你一个平滑滤波的算法。我已经用了10年了,非常好用,比起你那个20点统计一次并求平均的算法要简单很多。 ...

你这个滤波算法滞后会不会很大,第一个点怎么取呢

dj1981812 发表于 2015-5-7 10:16:32

yanghuanchun 发表于 2015-4-11 14:39
你这个滤波算法滞后会不会很大,第一个点怎么取呢

当然会有滞后了,要看你怎么设计了,你的滤波计数的多少决定你的延迟时间。

CCShader 发表于 2015-7-7 15:52:24

dj1981812 发表于 2014-11-15 21:20
给你一个平滑滤波的算法。我已经用了10年了,非常好用,比起你那个20点统计一次并求平均的算法要简单很多。 ...

这个实际就是加权平均~

leeloo 发表于 2015-7-7 16:03:00

临时变量声明,求和是,变量要初始化为0,不然会错
页: [1]
查看完整版本: 加速度数据滑动滤波莫名错误!求救!