博世BPM085压力计算

时间:2012-08-26 22:00:31

标签: c embedded-linux sensor i2c raspberry-pi

我是i2c编程的新手,我正在尝试从Bosch BPM085(datasheet)读取压力和温度值。我计算的温度值似乎是正确的,但hPa压力值不是我预期的。 实际上我得到了~996 hPa但是我应该在我的位置获得大约1017 hPa的东西。 作为平台,我正在使用支持I2C的Raspberry Pi。与I2C的通信通过/ dev / i2c-0完成。

传感器的接线方式如数据表第10页所述,但未连接XCLR和EOC。

到目前为止我认识到了:

  • 压力变化
  • 时压力场会发生变化
  • bmp085_calibration_data_t结构包含实际值
  • 计算算术应与Bosch API
  • 中的相同
  • 我测试了另一个传感器,以验证传感器没有缺陷。
  • 的值相同

有人可以在下面的代码中看到失败吗? i2c通信是否正确实现(如第14页的数据表中所述)?

这是我的代码:(因为我不是C开发人员请考虑一下; - )

#define BMP085_I2C_ADDR         (0xEE>>1) //i2c addr of the sensor

#define BMP085_PROM_START_ADDR      0xaa //start addr of calibration coefficients
#define BMP085_PROM_DATA_LEN        22 //length of calibration coefficients

#define BMP085_CTRL_MEAS_REG        0xF4
#define BMP085_T_MEASURE        0x2E // temperature measurement
#define BMP085_P_MEASURE        0x34 // pressure measurement

#define BMP085_ADC_OUT_MSB_REG      0xF6
#define BMP085_ADC_OUT_LSB_REG      0xF7
#define BMP085_ADC_OUT_XLSB_REG     0xF8

typedef struct {
    short ac1;
    short ac2;
    short ac3;
    unsigned short ac4;
    unsigned short ac5;
    unsigned short ac6;
    short b1;
    short b2;
    short mb;
    short mc;
    short md;              
} bmp085_calibration_data_t;

int file;
char buf[10] = {0};
bmp085_calibration_data_t calibrationData;
long T = 0l; // TEMPERATURE VALUE
long P = 0l; // PRESSURE VALUE

void bmp085_init(char *filename) {
    if((file = open(filename, O_RDWR)) < 0) {
        perror("failed to open the i2c bus.\n");    
        exit(1);
    }

    if(ioctl(file, I2C_SLAVE, BMP085_I2C_ADDR) < 0) {
        perror("failed to acquire bus access and / or talk to slave.\n");
        exit(1);
    }

    buf[0] = BMP085_PROM_START_ADDR;
    writeToBus(file, buf, 1);

    unsigned char data[BMP085_PROM_DATA_LEN];
    if (read(file,data,BMP085_PROM_DATA_LEN) != BMP085_PROM_DATA_LEN) {
        perror("Failed to read from the i2c bus.\n");
        exit(1);
    } else {
        calibrationData.ac1 = (data[0] <<8) | data[1];  
        calibrationData.ac2 = (data[2] <<8) | data[3];  
        calibrationData.ac3 = (data[4] <<8) | data[5];  
        calibrationData.ac4 = (data[6] <<8) | data[7];  
        calibrationData.ac5 = (data[8] <<8) | data[9];  
        calibrationData.ac6 = (data[10] <<8) | data[11];    
        calibrationData.b1 = (data[12] <<8) | data[13]; 
        calibrationData.b2 = (data[14] <<8) | data[15]; 
        calibrationData.mb = (data[16] <<8) | data[17]; 
        calibrationData.mc = (data[18] <<8) | data[19]; 
        calibrationData.md = (data[20] <<8) | data[21]; 
    }
}

// oss is the oversampling setting. in my case set to 0.
void read_sensor(short oss) {
    long ut, up, X1, X2, X3, B3, B5, B6;
    unsigned long B4, B7;

    ///////////// read uncompensated temperature /////////////
    buf[0] = BMP085_CTRL_MEAS_REG;
    buf[1] = BMP085_T_MEASURE;
    writeToBus(file, buf, 2);

    usleep(5000); // wait 5ms

    buf[0] = BMP085_ADC_OUT_MSB_REG;
    writeToBus(file, buf, 1);

    char uncompTemp[2];
    readFromBus(file, uncompTemp, 2);
    ut = (uncompTemp[0]<<8) | uncompTemp[1];

    ///////////// calculate temperature /////////////
    X1 = (((long) ut - (long) calibrationData.ac6) * (long) calibrationData.ac5) >> 15;
    X2 = ((long) calibrationData.mc << 11) / (X1 + calibrationData.md);
    B5 = X1 + X2;
    T = ((B5 + 8) >> 4);


    ///////////// read uncompensated pressure //////////////
    buf[0] = BMP085_CTRL_MEAS_REG;
    buf[1] = BMP085_P_MEASURE + (oss<<6);

    writeToBus(file, buf, 2);

    usleep((2 + (3 << oss)) * 1000); // wait

    char upBuf[3];
    buf[0] = BMP085_ADC_OUT_MSB_REG;
    writeToBus(file, buf, 1);

    readFromBus(file, upBuf, 3);
    up = (((unsigned long)upBuf[0]<<16) | ((unsigned long)upBuf[1]<<8) | (unsigned long)upBuf[2]) >> (8-oss);

    //printf("up: %li\n", up);

    ///////////// calculate pressure /////////////
    B6 = B5 - 4000;

    X1 = (B6 * B6) >> 12;
    X1 *= calibrationData.b2;
    X1 >>=11;

    X2 = calibrationData.ac2 * B6;
    X2 >>=11;

    X3 = X1 + X2;
    B3 = (((((long)calibrationData.ac1 )*4 + X3) <<oss) + 2) >> 2;

    X1 = (calibrationData.ac3 * B6) >> 13;
    X2 = (calibrationData.b1 * ((B6 * B6) >> 12)) >> 16;
    X3 = ((X1 + X2) + 2) >> 2;
    B4 = (calibrationData.ac4 * (unsigned long)(X3 + 32768)) >> 15;
    B7 = ((unsigned long)(up - B3) * (50000 >> oss));
    if(B7 < 0x80000000) {
        P = (B7 << 1) / B4;
    } else  {
        P = (B7 / B4) << 1;
    }

    X1 = (P >> 8);
    X1 *= X1;
    X1 = (X1 * 3038) >> 16;
    X2 = (-7357 * P) >> 16;
    P += (X1 + X2 + 3791) >> 4;
}

void writeToBus(int file, char* data, int len) {
    if(write(file, data, len) != len) {
         perror("could not write data to bus\n");
         exit(1);
    }
}

void readFromBus(int file, char* data, int len) {
    if(read(file, data, len) != len) {
         perror("could not read from bus\n");
         exit(1);
    }
}

0 个答案:

没有答案