BMP180 measuring very high pressure (no library)

Hello, I have some troubles with my BMP180.

I want to measure temperature and pressure to calculate altitude for my rocket. Temperature seems to be good, but if I want to measure pressure it measure somethilg like 223 171 pascals. I is first time that I am not using libraries, I am triing use registers only.

I print variables and after review I thing problem is with reading raw pressure (UP), in datasheet example is UP 23843 but mine moves around 19. I tryed to find some error but I can't see any. Please if someone see some error please write back.

Thanks for any answer :slight_smile:

my code:

#include <Wire.h>
#define BMP_ADRESS 0x77

class BMP180 {

private:
  byte _adress;

  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;

  float _temp;
  long _press;
  long _pressSeaLevel;

public:
  BMP180(byte adr) {
    _adress = adr;
  }

  void Setup() {

    Wire.beginTransmission(_adress);
    Wire.write(0xE0);  //reset register
    Wire.write(0xB6);
    Wire.endTransmission();

    delay(100);

    Wire.beginTransmission(_adress);
    Wire.write(0xAA);  //compensation first register
    Wire.endTransmission(false);

    Wire.requestFrom(_adress, (byte)22);


    _AC1 = Wire.read() << 8 | Wire.read();
    _AC2 = Wire.read() << 8 | Wire.read();
    _AC3 = Wire.read() << 8 | Wire.read();
    _AC4 = Wire.read() << 8 | Wire.read();
    _AC5 = Wire.read() << 8 | Wire.read();
    _AC6 = Wire.read() << 8 | Wire.read();
    _B1 = Wire.read() << 8 | Wire.read();
    _B2 = Wire.read() << 8 | Wire.read();
    _MB = Wire.read() << 8 | Wire.read();
    _MC = Wire.read() << 8 | Wire.read();
    _MD = Wire.read() << 8 | Wire.read();

  }

  void Measure(byte oss) {
    Wire.beginTransmission(_adress);
    Wire.write(0xF4);
    Wire.write(0x2E);
    Wire.endTransmission();

    delay(5);    
    
    Wire.beginTransmission(_adress);
    Wire.write(0xF6);
    Wire.endTransmission(false);

    Wire.requestFrom(_adress, (byte)2);
    long UT = Wire.read() << 8 | Wire.read();
        //Serial.println(UT); 
    //--------------------------------------------------- read raw temp

    Wire.beginTransmission(_adress);
    Wire.write(0xF4);
    Wire.write(0x34 + (oss << 6));
    Wire.endTransmission();

    if(oss == 0)
      delay(5);
    else if(oss == 1)
      delay(8);
    else if(oss == 2)
      delay(14);
    else if(oss == 3)
      delay(26);

    Wire.beginTransmission(_adress);
    Wire.write(0xF6);
    Wire.endTransmission(false);

    Wire.requestFrom(_adress, (byte)3);
    long UP = (Wire.read() << 16 | Wire.read() << 8 | Wire.read()) >> (8 - oss);
    
        //Serial.println(UP); 
    //--------------------------------------------------- read raw press


    long X1 = (UT - _AC6) * _AC5 / pow(2, 15);
    long X2 = _MC * pow(2, 11) / (X1 + _MD);
    long B5 = X1 + X2;
    long T = (B5 + 8) / pow(2, 4);
    _temp = (float)T / 10;
    //--------------------------------------------------- calc temp



    long B6 = B5 - 4000;
    X1 = (_B2 * (B6 * B6 / pow(2, 12))) / pow(2, 11);
    X2 = _AC2 * B6 / pow(2, 11);
    long X3 = X1 + X2;
    long B3 = (((_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);
    unsigned long B4 = _AC4 * (unsigned long)(X3 + 32768) / pow(2, 15);
    unsigned long B7 = ((unsigned long)UP - B3) * (50000 >> oss);
    long p;
    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);
    p = p + (X1 + X2 + 3791) / pow(2, 4);
    _press = p;
    //--------------------------------------------------- calc press
  }

  float GetTemp() {
    return _temp;
  }

  long GetPress() {
    return _press;
  }

  void SetSeaLevelPress(int alt){
    _pressSeaLevel = (long)((float)_press/pow((1-((float)alt/44330.0)),5.255));
  }

  int GetAlt(){
    return 44330 * (1.0-pow(_press/_pressSeaLevel,1.0/5.255));
  }
  
};

BMP180 BMP(BMP_ADRESS);



void setup() {
  // put your setup code here, to run once:

  Serial.begin(9600);
  //Serial.print("temp : ");

  Wire.begin();

  BMP.Setup();
  BMP.Measure(0);
  BMP.SetSeaLevelPress(320);
}

void loop() {
  // put your main code here, to run repeatedly:
  BMP.Measure(0);
    
  Serial.print("temp : ");
  Serial.println(BMP.GetTemp());

  Serial.print("press : ");
  Serial.println(BMP.GetPress());

  Serial.print("alt : ");
  Serial.println(BMP.GetAlt());
  
  Serial.println("------------------+0");
  
  delay(1000);
}

My recommendation would be to whittle down the sketch into the bare minimum that will read the UT register. Properly comment that code and post it here.

As it is, it's just too much work (sorry) to peel back the layers of reasoning in your code (although it's decently structured) and then wade through the mountain of undocumented magic numbers and compare them to the BMP180 datasheet.

First thing that comes to mind is you may have flipped an MSByte/LSByte in reading the pressure, but as said above, it would take me quite some time to verify this.

Why not use the library?

Thank you wery much for answers. You are so fast...

Sorry for my not much commented code.
After my first post I was playng guitar and than I got an idea. I tried that idea and it works. Error was in bad redata types.

old code:

long UP = (Wire.read() << 16 | Wire.read() << 8 | Wire.read()) >> (8 - oss);

new code:

long UP = ((long)Wire.read() << 16 | (long)Wire.read() << 8 | (long)Wire.read()) >> (8 - oss);

Thank you wery much for your time and sorry for my stupid question, uncommented code and bad english.

and I don't wanna use libraries becouse I want to know what is realy hapenning inside and save every bit.
:slight_smile: