1

I have a barometer (BMP180) and am interfacing it with aSTM32. I have to read the altitude which should have a precision of a foot.

While interfacing the barometer, I get a consistent real value of temperature but the pressure comes in the range of 59400 Pa (Pa - as per Bosch Datasheet). The example given in the datasheet also has pressure of 69964 Pa.

I have taken care of the delays required for the barometer to sample the data by using software based counters. Also, I checked my sensor with available libraries and everything comes consistent. But due to some academic reasons I can't use the libraries and so I need help in measuring the pressure.

Here is my STM32 Code:

//calibration params from the sensor
static int16_t AC1 = 8353; 
static int16_t AC2 = -1041;  
static int16_t AC3 = -14621; 
static uint16_t AC4 = 33880; 
static uint16_t AC5 = 25158; 
static uint16_t AC6 = 18608; 
static int16_t B1 = 6515; 
static int16_t B2 = 35; 
static int16_t MB = -32768; 
static int16_t MC = -11786; 
static int16_t MD = 2724;

static int TMPCNT = 0, PRSCNT=0;    //loop counters
static double temperature, pressure;
static uint8_t oss = 3;             // bmp high resolution 
static long UT, X1, X2, B5, UP;

int main() {
  while (1) {
    if (TMPCNT == 2) {  //2.7*2 > 5ms so sample temp every 5 ms 
      MSR_TEMP();       //measure for previous request
      RQST_TEMP();      // request again
      TMPCNT = 0;
    }
    TMPCNT++;       
                
    if (PRSCNT == 10) { //sample pressure every 27ms (25ms wait time for UH resolution)
      MSR_PRESS();
      RQST_PRESS();
      PRSCNT = 0;
    }
    PRSCNT++;

    /* some more code which takes 2.7 milliseconds */
  }
}

void RQST_TEMP() {
  i2c_transmit(BMP, 0xF4, 0x2E);   // transmit 0x2E to 0xF4 reg of BMP addr
}

void MSR_TEMP() {
  char buff[2];
  requestData(BMP, 0xF6, buff, 2); //request 2 bytes from BMP addr, reg 0xF6, and put it in the buff
  UT = (buff[0] << 8 | buff[1]);
  X1 = (long)((UT - AC6) * AC5 * pow(2, -15));
  X2 = (long)(MC * pow(2, 11) / (X1 + MD));
  B5 = X1 + X2;
  temperature = ((B5 + 8) * pow(2, -4)) / 10.0;
}

void RQST_PRESS(){
  i2c_transmit(BMP, 0xF4, (char)(0x34 + (oss << 6)));   
}

void MSR_PRESS() {
  long B6,x1,x2,x3,B3,p;
  unsigned long B4,B7;  
  char buff[3];

  requestData(BMP, 0xF6, buff, 3);
  UP = ((buff[0] << 16) + (buff[1] << 8) + buff[2]) >> (8-oss);
  B6 = B5 - 4000;
  x1 = (long)((B2 * (B6 * B6 * pow(2, -12))) * pow(2, -11));
  x2 = (long)(AC2 * B6 * pow(2, -11));
  x3 = x1 + x2;
  B3 = ((((long)AC1 * 4 + x3) << oss) + 2) / 4;
  x1 = AC3 * B6 * pow(2, -13);
  x2 = (B1 * (B6 * B6 * pow(2, -12))) * pow(2, -16);
  x3 = ((x1 + x2) + 2) * pow(2, -2);
  B4 = AC4 * (unsigned long)(x3 + 32768) * pow(2, -15);
  B7 = ((unsigned long)UP - B3) * (50000 >> oss);
  if (B7 < 0x80000000) {
    p = (B7 * 2) / B4;
  } else {
    p = (B7 / B4) * 2;
  }
  x1 = (p * pow(2, -8)) * (p * pow(2, -8));
  x1 = (x1 * 3038) * pow(2, -16);
  x2 = (-7357 * p) * pow(2, -16);
  pressure = p + ((x1 + x2 + 3791) * pow(2, -4)); // pressure is in Pa as per data sheet
  // SerialPrint("%lf\n",pressure);
}

The code written is based on the algorithm mentioned in the datasheet. Here is the datasheet. I dont know what I am doing wrong. My location should have pressure of 101209Pa which is way far from what I am getting. My I2C driver functions are also working as they should. So I cant figure out where exactly the problem is. I'll surely appreciate some help.

ocrdu
  • 2,172
  • 6
  • 15
  • 22
Sajil
  • 87
  • 8
  • Each BMP180 comes with factory calibration data stored on the device. Are the calibration parameters defined at the top some that you found or that you actually retrieved from the sensor internal data? – Shunya Jan 18 '21 at 17:17
  • @Shunya I read them from the sensor itself. Then I just hardcoded them instead of reading same thing every time. – Sajil Jan 18 '21 at 17:31

0 Answers0