气压计-加速度计数据如何融合?气压计受到太阳照射怎么办?

百科   2024-12-10 21:47   北京  

在高度数据获取时,最常用到的是气压计和加速度计。无人机一般都会使用气压计,给飞控定高,还可以做天气监控,因为温度和风速的变化都会影响测量结果。

一、气压计-加速度计数据融合

方法一:通过气压计测量得到的气压P,用公式:

H=44300*(1- (P/P0)^(1/5.256))

计算得到海拔高度,式中P0=大气压(101.325kPa@0℃)

注:有需要说明的是,气压计计算高度并不完全是海拔高度,因为使用的是标准海平面大气压,而不是当前海平面大气压。

但是直接得到的气压数据一般噪声较大无法直接使用。气压计获得的高度数据波形如图所示:

方法二:通过加速度积分。但是,加速度对时间的二阶积分容易产生误差累积造成的漂移。加速度积分获得的速度和高度波形如图所示:

鉴于两者数据各自的特点,可以利用它们各自的优点进行数据融合。那么,我们通过什么方法可以将两者数据的优点融合在一起,从而得到一组能真正用到工程测量中的数据呢?可以使用卡尔曼融合、互补融合等。卡尔曼滤波器作为当今最先进的状态估计的滤波算法,肯定是最好的选择。下面分享一下高度数据卡尔曼融合的经验。

二、BMP180气压计受到太阳照射影响的说明

使用博世的BMP180的气压计测高度,用于惯性导航方向,所以经常在室外做实验,发现在太阳光下和树荫下的高度差很大,见下图:

曲线高的地方在太阳光下面,曲线数值小的部分在树荫下。

后来,在做了遮光处理后这种现象竟然消失了,见下图:

PS:气压计BMP280使用记录

BOSCH的BMP280气压传感器,可以用于测量气压、海拔高度等。目前已经出了BMP380、BMP390,精度更高。

一)传感器特性:

在睡眠模式(sleep mode)下,不进行任何测量。正常模式(normal mode)包括自动在活动测量周期和非活动待机周期之间的永久循环。在强制模式(forced mode)下,执行单次测量,测量完成后传感器返回睡眠模式。

二)BMP180、BMP280 对比:

三)代码:用的是轮询去读数据。

初始化部分,主要是读补偿参数、设置工作模式、设置过采样参数等:

BMP280 bmp280_inst;
BMP280* bmp280 = &bmp280_inst;  //用来保存存在芯片内ROM补偿参数
void Bmp_Init(void)
{
 u8 Lsb,Msb; 

 //温度传感器的矫正值
 Lsb = BMP280_Read_Byte(BMP280_DIG_T1_LSB_REG);
 Msb = BMP280_Read_Byte(BMP280_DIG_T1_MSB_REG);
 bmp280->T1 = (((u16)Msb)<<8) + Lsb;   //高位加低位
 Lsb = BMP280_Read_Byte(BMP280_DIG_T2_LSB_REG);
 Msb = BMP280_Read_Byte(BMP280_DIG_T2_MSB_REG);
 bmp280->T2 = (((u16)Msb)<<8) + Lsb;  
 Lsb = BMP280_Read_Byte(BMP280_DIG_T3_LSB_REG);
 Msb = BMP280_Read_Byte(BMP280_DIG_T3_MSB_REG);
 bmp280->T3 = (((u16)Msb)<<8) + Lsb;  
 
 //大气压传感器的矫正值
 Lsb = BMP280_Read_Byte(BMP280_DIG_P1_LSB_REG);
 Msb = BMP280_Read_Byte(BMP280_DIG_P1_MSB_REG);
 bmp280->P1 = (((u16)Msb)<<8) + Lsb;  
 Lsb = BMP280_Read_Byte(BMP280_DIG_P2_LSB_REG);
 Msb = BMP280_Read_Byte(BMP280_DIG_P2_MSB_REG);
 bmp280->P2 = (((u16)Msb)<<8) + Lsb; 
 Lsb = BMP280_Read_Byte(BMP280_DIG_P3_LSB_REG);
 Msb = BMP280_Read_Byte(BMP280_DIG_P3_MSB_REG);
 bmp280->P3 = (((u16)Msb)<<8) + Lsb; 
 Lsb = BMP280_Read_Byte(BMP280_DIG_P4_LSB_REG);
 Msb = BMP280_Read_Byte(BMP280_DIG_P4_MSB_REG);
 bmp280->P4 = (((u16)Msb)<<8) + Lsb; 
 Lsb = BMP280_Read_Byte(BMP280_DIG_P5_LSB_REG);
 Msb = BMP280_Read_Byte(BMP280_DIG_P5_MSB_REG);
 bmp280->P5 = (((u16)Msb)<<8) + Lsb; 
 Lsb = BMP280_Read_Byte(BMP280_DIG_P6_LSB_REG);
 Msb = BMP280_Read_Byte(BMP280_DIG_P6_MSB_REG);
 bmp280->P6 = (((u16)Msb)<<8) + Lsb; 
 Lsb = BMP280_Read_Byte(BMP280_DIG_P7_LSB_REG);
 Msb = BMP280_Read_Byte(BMP280_DIG_P7_MSB_REG);
 bmp280->P7 = (((u16)Msb)<<8) + Lsb; 
 Lsb = BMP280_Read_Byte(BMP280_DIG_P8_LSB_REG);
 Msb = BMP280_Read_Byte(BMP280_DIG_P8_MSB_REG);
 bmp280->P8 = (((u16)Msb)<<8) + Lsb; 
 Lsb = BMP280_Read_Byte(BMP280_DIG_P9_LSB_REG);
 Msb = BMP280_Read_Byte(BMP280_DIG_P9_MSB_REG);
 bmp280->P9 = (((u16)Msb)<<8) + Lsb; 
 /******************************************************/
 BMP280_Write_Byte(BMP280_RESET_REG,BMP280_RESET_VALUE); //写入给定值
 
 BMP_OVERSAMPLE_MODE   BMP_OVERSAMPLE_MODEStructure;
 BMP_OVERSAMPLE_MODEStructure.P_Osample = BMP280_P_MODE_3;
 BMP_OVERSAMPLE_MODEStructure.T_Osample = BMP280_T_MODE_1;
 BMP_OVERSAMPLE_MODEStructure.WORKMODE  = BMP280_NORMAL_MODE;
 BMP280_Set_TemOversamp(&BMP_OVERSAMPLE_MODEStructure);
 
 BMP_CONFIG     BMP_CONFIGStructure;
 BMP_CONFIGStructure.T_SB = BMP280_T_SB1;
 BMP_CONFIGStructure.FILTER_COEFFICIENT = BMP280_FILTER_MODE_4;
 BMP_CONFIGStructure.SPI_EN = DISABLE;
 
 BMP280_Set_Standby_FILTER(&BMP_CONFIGStructure);
}

bmp280.h

typedef enum {
 BMP280_SLEEP_MODE = 0x0,
 BMP280_FORCED_MODE = 0x1//???0x2
 BMP280_NORMAL_MODE = 0x3
} BMP280_WORK_MODE;

typedef enum 
{
 BMP280_P_MODE_SKIP = 0x0/*skipped*/
 BMP280_P_MODE_1,   /*x1*/
 BMP280_P_MODE_2,   /*x2*/
 BMP280_P_MODE_3,   /*x4*/
 BMP280_P_MODE_4,   /*x8*/
 BMP280_P_MODE_5       /*x16*/
} BMP280_P_OVERSAMPLING; 

typedef enum {
 BMP280_T_MODE_SKIP = 0x0/*skipped*/
 BMP280_T_MODE_1,   /*x1*/
 BMP280_T_MODE_2,   /*x2*/
 BMP280_T_MODE_3,   /*x4*/
 BMP280_T_MODE_4,   /*x8*/
 BMP280_T_MODE_5       /*x16*/
} BMP280_T_OVERSAMPLING;
         
//IIR
typedef enum {
 BMP280_FILTER_OFF = 0x0/*filter off*/
 BMP280_FILTER_MODE_1,  /*0.223*ODR*/ /*x2*/
 BMP280_FILTER_MODE_2,  /*0.092*ODR*/ /*x4*/
 BMP280_FILTER_MODE_3,  /*0.042*ODR*/ /*x8*/
 BMP280_FILTER_MODE_4  /*0.021*ODR*/ /*x16*/
} BMP280_FILTER_COEFFICIENT;

typedef enum {
 BMP280_T_SB1 = 0x0,  /*0.5ms*/
 BMP280_T_SB2,   /*62.5ms*/
 BMP280_T_SB3,   /*125ms*/
 BMP280_T_SB4,   /*250ms*/
 BMP280_T_SB5,   /*500ms*/
 BMP280_T_SB6,   /*1000ms*/
 BMP280_T_SB7,   /*2000ms*/
 BMP280_T_SB8,   /*4000ms*/
} BMP280_T_SB;

typedef struct  
{

 /* T1~P9 */
 uint16_t T1;
 int16_t T2;
 int16_t T3;
 uint16_t P1;
 int16_t P2;
 int16_t P3;
 int16_t P4;
 int16_t P5;
 int16_t P6;
 int16_t P7;
 int16_t P8;
 int16_t P9;
} BMP280;

typedef   long signed int    BMP280_S32_t;
typedef   long unsigned int   BMP280_U32_t;
typedef   long long signed int  BMP280_S64_t;

#define dig_T1   bmp280->T1 
#define dig_T2   bmp280->T2 
#define dig_T3   bmp280->T3 
#define dig_P1   bmp280->P1
#define dig_P2   bmp280->P2
#define dig_P3   bmp280->P3
#define dig_P4   bmp280->P4
#define dig_P5   bmp280->P5
#define dig_P6   bmp280->P6
#define dig_P7   bmp280->P7
#define dig_P8   bmp280->P8
#define dig_P9   bmp280->P9
/*************************CUT************************/
typedef struct
{

 BMP280_P_OVERSAMPLING P_Osample;
 BMP280_T_OVERSAMPLING T_Osample;
 BMP280_WORK_MODE  WORKMODE;
} BMP_OVERSAMPLE_MODE;
 
typedef struct
{

 BMP280_T_SB     T_SB;
 BMP280_FILTER_COEFFICIENT  FILTER_COEFFICIENT;
 FunctionalState    SPI_EN;
} BMP_CONFIG;

extern BMP280* bmp280;

u8 BMP280_Check(void);
void BMP280_Set_TemOversamp(BMP_OVERSAMPLE_MODE * Oversample_Mode);
void BMP280_Set_Standby_FILTER(BMP_CONFIG * BMP_Config);
void Bmp_Init(void);
u8  BMP280_GetStatus(u8 status_flag);
//long BMP280_Get_Pressure(void);
double BMP280_Get_Pressure(void);
double bmp280_compensate_T_double(BMP280_S32_t adc_T);
double bmp280_compensate_P_double(BMP280_S32_t adc_P);

主函数:

详情见视频:




雨飞工作室
本着“让人有所知,让人有所思”的理念,带你游走在无人机及机器人、智能交通、物联网领域,领略人间芳华,感受百味人生。
 最新文章