nfsq246 / RTT_BMP280

基于RT-Thread的BMP280驱动
3 stars 2 forks source link

气压值数值偏差 #1

Open Tigerots opened 3 years ago

Tigerots commented 3 years ago

您好, 我在STM32F412的板子上使用该软件包进行bmp280读取测试, 发现读出的数据和我用bmp085相差较大(bmp280为95, bmp085为103, 且bmp085为以前的量产产品), 为做验证, 我用裸机直接写了个驱动, 读取的数值与bmp085一致, 故猜测问题应该发生在该软件包内, 但我尚未发现问题所在.

不知是我使用不正确, 还是有其他原因, 是否有其他攻城狮遇到过?

nfsq246 commented 3 years ago

@Tigerots 暂时没其他人遇到过 我重新看了下代码,也没发现问题在哪 能把你写的裸机代码发出来,让我看看来对照一下吗

Tigerots commented 3 years ago

您好, 我今天刚看到您的回复, 恰好有时间, 也仔细跟踪了一次代码, 确实没有发现什么异常, 于是用模拟IIC驱动又测试了下, 结果还是不一样, 我测试的代码发给您, 如果方便, 可以实际测试一下,(测试代码有部分来源于网络)。

头文件 ` /*

define BMP280_I2C_ADDR (0x76)

define BMP280_DEFAULT_CHIP_ID (0x58)

define BMP280_CHIP_ID (0xD0) / Chip ID Register /

define BMP280_RST_REG (0xE0) / Softreset Register /

define BMP280_STAT_REG (0xF3) / Status Register /

define BMP280_CTRL_MEAS_REG (0xF4) / Ctrl Measure Register /

define BMP280_CONFIG_REG (0xF5) / Configuration Register /

define BMP280_PRESSURE_MSB_REG (0xF7) / Pressure MSB Register /

define BMP280_PRESSURE_LSB_REG (0xF8) / Pressure LSB Register /

define BMP280_PRESSURE_XLSB_REG (0xF9) / Pressure XLSB Register /

define BMP280_TEMPERATURE_MSB_REG (0xFA) / Temperature MSB Reg /

define BMP280_TEMPERATURE_LSB_REG (0xFB) / Temperature LSB Reg /

define BMP280_TEMPERATURE_XLSB_REG (0xFC) / Temperature XLSB Reg /

define BMP280_TEMPERATURE_CALIB_DIG_T1_LSB_REG (0x88)

define BMP280_PRESSURE_TEMPERATURE_CALIB_DATA_LENGTH (24)

define BMP280_OVERSAMP_SKIPPED (0x00)

define BMP280_OVERSAMP_1X (0x01)

define BMP280_OVERSAMP_2X (0x02)

define BMP280_OVERSAMP_4X (0x03)

define BMP280_OVERSAMP_8X (0x04)

define BMP280_OVERSAMP_16X (0x05)

define BMP280_FILTER_COEFF_OFF (0x00)

define BMP280_FILTER_COEFF_2 (0x01)

define BMP280_FILTER_COEFF_4 (0x02)

define BMP280_FILTER_COEFF_8 (0x03)

define BMP280_FILTER_COEFF_16 (0x04)

define BMP280_FORCED_MODE (0x01)

define BMP280_NORMAL_MODE (0x03)

endif

测试文件 /*

include

include

include

include

include "my_bmp280.h"

define DBG_TAG "my_bmp280"

define DBG_LVL DBG_LOG

include

static struct rt_i2c_bus_device *i2c_bus_dev;

// 配置bmp280气压和温度过采样 工作模式

define BMP280_PRESSURE_OSR (BMP280_OVERSAMP_16X)

define BMP280_TEMPERATURE_OSR (BMP280_OVERSAMP_4X)

define BMP280_MODE (BMP280_PRESSURE_OSR << 2 | BMP280_TEMPERATURE_OSR << 5 | BMP280_NORMAL_MODE) //

// 配置bmp280气压IIR滤波器

define BMP280_FILTER (4 << 2) // BMP280_FILTER_COEFF_16

// 读取的数据长度

define BMP280_DATA_FRAME_SIZE (6)

typedef struct { uint16_t dig_T1; int16_t dig_T2; int16_t dig_T3; uint16_t dig_P1; int16_t dig_P2; int16_t dig_P3; int16_t dig_P4; int16_t dig_P5; int16_t dig_P6; int16_t dig_P7; int16_t dig_P8; int16_t dig_P9; int32_t t_fine; } bmp280Calib; bmp280Calib bmp280_cal;

static int8_t my_i2c_reg_write(uint8_t i2c_addr, uint8_t reg_addr, uint8_t *reg_data, uint16_t length) { rt_uint8_t tmp = reg_addr; struct rt_i2c_msg msgs[2];

msgs[0].addr  = i2c_addr;         /* Slave address */
msgs[0].flags = RT_I2C_WR;        /* Write flag */
msgs[0].buf   = &tmp;             /* Slave register address */
msgs[0].len   = 1;                /* Number of bytes sent */

msgs[1].addr  = i2c_addr;            /* Slave address */
msgs[1].flags = RT_I2C_WR | RT_I2C_NO_START;        /* Read flag */
msgs[1].buf   = reg_data;            /* Read data pointer */
msgs[1].len   = length;              /* Number of bytes read */

if (rt_i2c_transfer(i2c_bus_dev, msgs, 2) != 2)
{
    return -RT_ERROR;
}

return RT_EOK;

}

static int8_t my_i2c_reg_read(uint8_t i2c_addr, uint8_t reg_addr, uint8_t *reg_data, uint16_t length) { rt_uint8_t tmp = reg_addr; struct rt_i2c_msg msgs[2];

msgs[0].addr  = i2c_addr;             /* Slave address */
msgs[0].flags = RT_I2C_WR;        /* Write flag */
msgs[0].buf   = &tmp;             /* Slave register address */
msgs[0].len   = 1;                /* Number of bytes sent */

msgs[1].addr  = i2c_addr;             /* Slave address */
msgs[1].flags = RT_I2C_RD;        /* Read flag */
msgs[1].buf   = reg_data;             /* Read data pointer */
msgs[1].len   = length;              /* Number of bytes read */

if (rt_i2c_transfer(i2c_bus_dev, msgs, 2) != 2)
{
    return -RT_ERROR;
}
return RT_EOK;

}

uint8_t my_bmp280_chip_Init(void) { uint8_t id = 0x00; char dev_name[] = "i2c1";

rt_thread_delay(1000);

i2c_bus_dev = rt_i2c_bus_device_find(dev_name);
if (i2c_bus_dev == RT_NULL)
{
    LOG_E("can't find bmp280 %s device", dev_name);
}

for (int i=0; i<10; i++)
{
    my_i2c_reg_read(BMP280_I2C_ADDR, BMP280_CHIP_ID, &id, 1);//读取ID
    rt_kprintf("chip280 id = 0x%x \r\n", id);
    if (id == BMP280_DEFAULT_CHIP_ID)
    {
        break;
    }
    rt_thread_mdelay(10);
}

if (id == BMP280_DEFAULT_CHIP_ID)//读取正常
{
    uint8_t temp;
    my_i2c_reg_read(BMP280_I2C_ADDR, BMP280_TEMPERATURE_CALIB_DIG_T1_LSB_REG, (uint8_t *)&bmp280_cal, 24);//读取校准数据
    temp = BMP280_MODE;
    my_i2c_reg_write(BMP280_I2C_ADDR, BMP280_CTRL_MEAS_REG, &temp, 1);//设置过采样率和工作模式
    temp = BMP280_FILTER;
    my_i2c_reg_write(BMP280_I2C_ADDR, BMP280_CONFIG_REG, &temp, 1);//配置IIR滤波

    LOG_I("BMP280 I2C connection OK\r\n");
}
else
{
    LOG_I("BMP280 I2C connection FAIL\r\n");
}

return 0;

}

static int32_t bmp280_Pressure = 0; static int32_t bmp280_Temperature = 0; static void my_bmp280_get_press_temp(void) { uint8_t data[BMP280_DATA_FRAME_SIZE];

my_i2c_reg_read(BMP280_I2C_ADDR, BMP280_PRESSURE_MSB_REG, data, BMP280_DATA_FRAME_SIZE);
bmp280_Pressure = (int32_t)((((uint32_t)(data[0])) << 12) | (((uint32_t)(data[1])) << 4) | ((uint32_t)data[2] >> 4));
bmp280_Temperature = (int32_t)((((uint32_t)(data[3])) << 12) | (((uint32_t)(data[4])) << 4) | ((uint32_t)data[5] >> 4));

}

uint32_t bmp280_compensate_temp(int32_t adcT) { int32_t var1, var2, T;

var1 = ((((adcT >> 3) - ((int32_t)bmp280_cal.dig_T1 << 1))) * ((int32_t)bmp280_cal.dig_T2)) >> 11;
var2  = (((((adcT >> 4) - ((int32_t)bmp280_cal.dig_T1)) * ((adcT >> 4) - ((int32_t)bmp280_cal.dig_T1))) >> 12) * ((int32_t)bmp280_cal.dig_T3)) >> 14;
bmp280_cal.t_fine = var1 + var2;
T = (bmp280_cal.t_fine * 5 + 128) >> 8;

return T;

}

uint32_t bmp280_compensate_press(int32_t adcP) { int64_t var1, var2, p; var1 = ((int64_t)bmp280_cal.t_fine) - 128000; var2 = var1 var1 (int64_t)bmp280_cal.dig_P6; var2 = var2 + ((var1(int64_t)bmp280_cal.dig_P5) << 17); var2 = var2 + (((int64_t)bmp280_cal.dig_P4) << 35); var1 = ((var1 var1 (int64_t)bmp280_cal.dig_P3) >> 8) + ((var1 (int64_t)bmp280_cal.dig_P2) << 12); var1 = (((((int64_t)1) << 47) + var1)) ((int64_t)bmp280_cal.dig_P1) >> 33; if (var1 == 0) return 0; p = 1048576 - adcP; p = (((p << 31) - var2) 3125) / var1; var1 = (((int64_t)bmp280_cal.dig_P9) (p >> 13) (p >> 13)) >> 25; var2 = (((int64_t)bmp280_cal.dig_P8) * p) >> 19; p = ((p + var1 + var2) >> 8) + (((int64_t)bmp280_cal.dig_P7) << 4); return (uint32_t)p; }

void bmp280_get_data(float pressure, float temperature, float* asl) { my_bmp280_get_press_temp();

*temperature = bmp280_compensate_temp(bmp280_Temperature)/100.0f;  // 单位度
*pressure = bmp280_compensate_press(bmp280_Pressure)/256.0f; // 单位Pa

}

uint8_t bum280_init_flag = 0; static void my_bmp280_entry(void *arg) { char log_buf[100]; float t, p, a; while(1) { if (bum280_init_flag==0) { my_bmp280_chip_Init(); bum280_init_flag = 1; } bmp280_get_data(&p, &t, &a); sprintf(log_buf, "P = %.2f\tT = %.1f\tA = %.2f\r\n", p, t, a); rt_kprintf(log_buf); rt_thread_mdelay(1000); } }

/**函数描述***

INIT_APP_EXPORT(my_bmp280_init_test);

`

nfsq246 commented 3 years ago

@Tigerots 我看你的气压配置的参数跟我的不一样,你可以尝试配置一样的试下效果如何

`

conf.filter = BMP280_FILTER_COEFF_2;
/* Temperature oversampling set at 4x */
conf.os_temp = BMP280_OS_4X;
/* Pressure oversampling set at 4x */
conf.os_pres = BMP280_OS_4X;
/* Setting the output data rate as 1HZ(1000ms) */
conf.odr = BMP280_ODR_1000_MS;

`

steny91 commented 2 years ago
int8_t bmp280_get_comp_temp_32bit(int32_t *comp_temp, int32_t uncomp_temp, struct bmp280_dev *dev)
{
    int32_t var1, var2;
    int8_t rslt;

    rslt = null_ptr_check(dev);
    if (rslt == BMP280_OK)
    {
        var1 =
            ((((uncomp_temp / 8) - ((int32_t) dev->calib_param.dig_t1 << 1))) * ((int32_t) dev->calib_param.dig_t2)) /
            2048;
        var2 =
            (((((uncomp_temp / 16) - ((int32_t) dev->calib_param.dig_t1)) *
               ((uncomp_temp / 16) - ((int32_t) dev->calib_param.dig_t1))) / 4096) *
             ((int32_t) dev->calib_param.dig_t3)) /
            16384;
        dev->calib_param.t_fine = var1 + var2;

温度计算中更新了校准参数 _calib_param.tfine

int8_t bmp280_get_comp_pres_32bit(uint32_t *comp_pres, uint32_t uncomp_pres, const struct bmp280_dev *dev)
{
    int32_t var1, var2;
    int8_t rslt;

    rslt = null_ptr_check(dev);
    if (rslt == BMP280_OK)
    {
        var1 = (((int32_t) dev->calib_param.t_fine) / 2) - (int32_t) 64000;

压力计算中会使用这个参数 _calib_param.tfine,所以压力获取不能单独仅仅计算压力,需要先计算温度,再计算压力才会准确;