下面是我对气压计获取数据的解读,水平有限,可以通过这篇文章来理清楚获取高度数据的思路
单片机数字滤波器的文档
FBM320的数据手册
小马哥robofly四轴开源项目GitHub上
FBMTYPE FBM; //首先定义一个结构体用来结合FBM返回的数据计算高度
uint8_t ALTIUDE_OK = 0,ALT_Updated = 0;
float RPFilter;
下面是一些函数
**uint8_t FBM320_WriteByte(uint8_t reg,uint8_t data):写一个字节到
FBM320寄存器
uint8_t FBM320_WriteMultBytes(uint8_t reg,uint8_t len,uint8_t *buf):从指定寄存器写入指定长度数据
uint8_t FBM320_ReadMultBytes(uint8_t reg,uint8_t len,uint8_t *buf):从指定寄存器读取指定长度数据
uint8_t FBM320_getDeviceID(void):读取 FBM320 WHO_AM_I 标识将返回 0x42
uint8_t FBM320_testConnection(void) :检测FBM320 是否已经连接,可以检查FBM320是否能和主机通信
void FBM320_Check(void):检测IIC总线上的FBM320是否存在
void FBM320_Init(void):初始化FBM320并获取FBM320校准数据
void FBM320_GetCoeff(void):获取存储在FBM320片内的校准数据**
void FBM320_GetCoeff(void)
{
uint8_t data[20],i = 0;
uint16_t R[10];
FBM320_ReadMultBytes(FBM_COEFF1,18,data); //从这个地址FBM_COEFF1:0xAA(187)-0xBB(170)开始拿18个数据放到data里
FBM320_ReadByte(FBM_COEFF3,&data[18]); //将从FBM_COEFF3获取到的数据放到data[18]
FBM320_ReadByte(FBM_COEFF4,&data[19]); //将从FBM_COEFF4获取到的数据放到data[19],刚好就20个
for(i=0;i<10;i++)
{
R[i] = (uint16_t)(data[2*i]<<8)|data[2*i+1]; //数据获取后的常见操作,16bit类型的数据=8bit高位 接上 8bit地位,这里的接上就是进行或运算,但是要先将8bit的高位转换为16位比如:11000011->11000011 00000000 | 11111110 =
11000011 11111110
}
/* Use R0~R9 calculate C0~C12 of FBM320-02 */ //这个就直接参考例程,通过传感器获取的data,然后转换为R[],然后在通过下面的方法获取计算气压和温度的C0---C12
FBM.C0 = R[0] >> 4;
FBM.C1 = ((R[1] & 0xFF00) >> 5) | (R[2] & 7);
FBM.C2 = ((R[1] & 0xFF) << 1) | (R[4] & 1);
FBM.C3 = R[2] >> 3;
FBM.C4 = ((uint32_t)R[3] << 2) | (R[0] & 3);
FBM.C5 = R[4] >> 1;
FBM.C6 = R[5] >> 3;
FBM.C7 = ((uint32_t)R[6] << 3) | (R[5] & 7);
FBM.C8 = R[7] >> 3;
FBM.C9 = R[8] >> 2;
FBM.C10 = ((R[9] & 0xFF00) >> 6) | (R[8] & 3);
FBM.C11 = R[9] & 0xFF;
FBM.C12 = ((R[0] & 0x0C) << 1) | (R[7] & 7);
}
void FBM320_Calculate(int32_t UP, int32_t UT) :将FBM320获取到AD值转换成物理量,通过测量得到的温度值和气压值求出
这里获取FBM结构体中的RT和RP值,RP值在气压计初始化求初始高度和求出实际高度时用到,具体怎么实现的我们也不用管
void FBM320_Calculate(int32_t UP, int32_t UT)
{
int32_t DT, DT2, X01, X02, X03, X11, X12, X13, X21, X22, X23, X24, X25, X26, X31, X32, CF, PP1, PP2, PP3, PP4;
DT = ((UT - 8388608) >> 4) + (FBM.C0 << 4);
X01 = (FBM.C1 + 4459) * DT >> 1;
X02 = ((((FBM.C2 - 256) * DT) >> 14) * DT) >> 4;
X03 = (((((FBM.C3 * DT) >> 18) * DT) >> 18) * DT);
FBM.RT = ((2500 << 15) - X01 - X02 - X03) >> 15;
DT2 = (X01 + X02 + X03) >> 12;
X11 = ((FBM.C5 - 4443) * DT2);
X12 = (((FBM.C6 * DT2) >> 16) * DT2) >> 2;
X13 = ((X11 + X12) >> 10) + ((FBM.C4 + 120586) << 4);
X21 = ((FBM.C8 + 7180) * DT2) >> 10;
X22 = (((FBM.C9 * DT2) >> 17) * DT2) >> 12;
X23 = (X22 >= X21) ? (X22 - X21) : (X21 - X22);
X24 = (X23 >> 11) * (FBM.C7 + 166426);
X25 = ((X23 & 0x7FF) * (FBM.C7 + 166426)) >> 11;
X26 = (X21 >= X22) ? (((0 - X24 - X25) >> 11) + FBM.C7 + 166426) : (((X24 + X25) >> 11) + FBM.C7 + 166426);
PP1 = ((UP - 8388608) - X13) >> 3;
PP2 = (X26 >> 11) * PP1;
PP3 = ((X26 & 0x7FF) * PP1) >> 11;
PP4 = (PP2 + PP3) >> 10;
CF = (2097152 + FBM.C12 * DT2) >> 3;
X31 = (((CF * FBM.C10) >> 17) * PP4) >> 2;
X32 = (((((CF * FBM.C11) >> 15) * PP4) >> 18) * PP4);
FBM.RP = ((X31 + X32) >> 15) + PP4 + 99880; //99880气压补偿
}
至此,我们获取到FBM结构体中的,
接下来看转换为实际高度的函数:
void FBM320_GetAltitude(void):FBM320的气压值转换成相对高度
void FBM320_GetAltitude(void) //200Hz
{
uint8_t buf[3];
static uint8_t timecnt = 0;
float AltitudeFilter;
switch(timecnt)//温度和气压数据转换时间不一样
{
case 0:
FBM320_WriteByte(FBM_CONFIG,TEMP_CONVERSION); //280usTEMP_CONVERSION=0x2E
break;
case 1: //5ms转换一次 (836us)
FBM320_ReadMultBytes(DATA_MSB,3,buf);
FBM.ADTemp = (buf[0]<<16)|(buf[1]<<8)|buf[2];
FBM320_WriteByte(FBM_CONFIG,PRES_CONVERSION+OSR8192); //开启气压转化
break;
case 5: //15ms转换一次 (834us)
FBM320_ReadMultBytes(DATA_MSB,3,buf);
FBM.ADPress = (buf[0]<<16)|(buf[1]<<8)|buf[2];
FBM320_WriteByte(FBM_CONFIG,TEMP_CONVERSION); //开启温度转换
FBM320_Calculate( FBM.ADPress , FBM.ADTemp ); //将FBM320的原始数据转换成物理量 气压单位是帕,温度单位摄氏度
if(Init_Altitude()) //这里通过Init_Altitude()函数获取到FBM.InitPress用于后面气压转换为高度
{
BAR_Offset_LED();//气压计校准成功指示灯
ALTIUDE_OK = 1;
}
SortAver_Filter((float)FBM.RP,&FBM.RPFilter,12); //去极值均值滤波,取极值均值滤波:顾名思义,在12个数据中排序,去掉最大和最小的,剩下的10个求平均值,赋值给当前时刻的FBM.RPFilter
//printf("FBM.RP:%0.2f FBM.RPFilter:%0.2f\r\n",FBM.RP,FBM.RPFilter);
if(FBM.RPFilter && ALTIUDE_OK)
{
ALT_Updated = 1;
FBM.Altitude = 44330.0f * (1 - powf((float)FBM.RPFilter/ FBM.InitPress, 0.190295f));
}
SortAver_Filter1(FBM.Altitude ,&AltitudeFilter,12); //去极值均值滤波
if(AltitudeFilter)
Aver_Filter1(AltitudeFilter,&FBM.AltitudeFilter,8); //滑动窗口滤波,滑动窗口滤波如下图
FBM.Altitude = ((float)Abs_Altitude((int32_t)FBM.RPFilter))/1000; //计算绝对高度(相对于海平面) 2021-3去掉注释
break;
default:
break;
}
timecnt++; //转换时间计数
if(timecnt>5)
timecnt = 0;
}
函数中用到的寄存器:
至此我们就求得了当前的高度。整理一下思路:先获取C0-C12 ->FBM.RP 和 FBM.RT ->FBM.ADTemp和FBM.ADPress ->更精确的FBM.RP->滤波->结合FBM.InitPres->FBM.Altitude->滤波->FBM.AltitudeFilter 用于后面定高算法
与气压计相关的参考资料: