BMP388 understand Data

Hey Guys,

i'm working on a own Arduino Flightcontroller and am trying to get a BMP388 working. I want to estimate the altitude.

I got the task done with the Adafruit Library, but it takes 2.5 microseconds to read the Sensor and get the altitude. Thats way to slow for a quadrocopter.

That's why i try to write my own Code and for a performance. I think i'm able to read the 24bit pressure data from the register 0x04:

Wire.beginTransmission(BMP_ADDR);                                     //Start communication with the BMP.
 Wire.write(0x04);                                                    //Start reading @ register 0x04 and auto increment with every read.
 Wire.endTransmission();                                              //End the transmission.
 Wire.requestFrom(BMP_ADDR,6);                                        //Request 6 bytes from the gyro.    
 while(Wire.available() < 6);                                         //Wait until 6 Byte are recieved
 pressure = (Wire.read()<<16) | (Wire.read()<< 8 ) | (Wire.read());
 druck = (float)pressure/0.33;
 temperature = (Wire.read()<<16) | (Wire.read()<< 8 ) | (Wire.read())

But i'm not sure if i understand how to get the pressure in Pa the right way.
What i do:

druck = (float)pressure/0.33;

I set the Oversamplingrate of the Pressure to x8. In the Datasheet is wirtten on page 13:
x8 Oversampling 19bit/0.33 Pa resolution.

Did i calculated the pressure the right way ?

https://www.mouser.com/pdfdocs/BST-BMP388-DS001-01.pdf

Please remove this line:

while(Wire.available() < 6);        //Wait until 6 Byte are recieved

Explanation: Common mistakes #1.

Please show the full sketch. There is a website for it: https://snippets-r-us.com/.

The Wire.read() returns an integer. That is 16 bits on a Arduino Uno or Mega. When shifting that 16 times to the left you end up with nothing.

Adafruit library: GitHub - adafruit/Adafruit_BMP3XX.

The datasheet and the Adafruit library do many calculations to get the temperature and the pressure.
I see now that a faster sampling is possible when the temperature is not needed. The 0.33 is the resolution. As far as I can tell the number from the registers is not the pressure in Pa, I think you still have to do all those calculations. But I'm not sure, I always use a library with all those calculations for a Bosch sensor, without thinking about it.

My Code. I really need a faster library. It's kinda difficult, to get this done by myself.

#define BMP_ADDR 0x76
#include <Wire.h>
uint32_t pressure,temperature;
float druck;
void setup() {
  // put your setup code here, to run once:
Serial.begin(115200);
Wire.begin();
TWBR = 12;                                                                //Set the I2C clock speed to 400kHz.
SetupBMP();
}

void loop() 
{
  // put your main code here, to run repeatedly:
GetBMPData();
Serial.println(druck);
delay(20);
}
void I2C_WriteOneByte(uint8_t DevAddr, uint8_t RegAddr, uint8_t value)
{
  Wire.beginTransmission(DevAddr);
  Wire.write(RegAddr);
  Wire.write(value);
  Wire.endTransmission();
}
uint8_t I2C_ReadOneByte(uint8_t DevAddr, uint8_t RegAddr)
{
  uint8_t value;

  Wire.beginTransmission(DevAddr);
  Wire.write((byte)RegAddr);
  Wire.endTransmission();

  Wire.requestFrom(DevAddr, (byte)1);
  value = Wire.read();

  return value;
}
void SetupBMP()
{
I2C_WriteOneByte(BMP_ADDR,0x7E,0xB6); //Trigger a Softreset
delay(20);
I2C_WriteOneByte(BMP_ADDR,0x1C,0x03); //Set Oversampling for pressure (x8) and Temperature(x1)
delay(20);
I2C_WriteOneByte(BMP_ADDR,0x1D,0x02); //Set the Output Data Rate 50Hz = 20ms
delay(20);
I2C_WriteOneByte(BMP_ADDR,0x1F,0x02); //Set the IIR Filter Coefficients = 3
delay(20);
I2C_WriteOneByte(BMP_ADDR,0x1B,0x01|0x10|0x30); //Setup Serial Interface Settings
}
void GetBMPData(){
 Wire.beginTransmission(BMP_ADDR);                                     //Start communication with the gyro.
 Wire.write(0x04);                                                    //Start reading @ register 43h and auto increment with every read.
 Wire.endTransmission();                                              //End the transmission.
 Wire.requestFrom(BMP_ADDR,3);                                        //Request 14 bytes from the gyro.    
 while(Wire.available() < 3);                                         //Wait until 3 Byte are recieved
 pressure = (Wire.read()<<16) | (Wire.read()<< 8 ) | (Wire.read());
 druck = (float)pressure/0.33;
 temperature = (Wire.read()<<16) | (Wire.read()<< 8 ) | (Wire.read());
}

Please remove this line: while(Wire.available() < 3);

In the function GetBMPData(), you request 3 bytes, but you read 6 bytes (pressure and temperature).

To set the speed, the function Wire.setClock() can be used.

You can measure it with micros():

void loop()
{
  unsigned long t1 = micros();
  GetBMPData();
  unsigned long t2 = micros();

  Serial.print( "GetBMPData: ");
  Serial.print( druck);
  Serial.print( " (");
  Serial.print( t2 - t1);
  Serial.print( " microseconds)");
  delay(20);
}

400kHz is about 25µs per byte.
The GetBMPData transfers 6 bytes (or 9 with the bug). That is 150µs (or 225µs with the bug). Plus 50% overhead. Plus the rest of the function.

To get higher speed, you need to use the SPI bus.

it takes 2.5 microseconds to read the Sensor and get the altitude. Thats way to slow for a quadrocopter

Have I misunderstood something about quads?

TheMemberFormerlyKnownAsAWOL:
Have I misunderstood something about quads?

More cryptical pls....

My Loop refreshrate is 4ms (250 Hz). The PWM takes between 1ms - 2ms. So have 2ms for Calculations.
So 2.5 ms for reading altitude is too much.

I dont get, how modern flightcontrollers get 8kHz, but this is another story...

You wrote 2.5 microseconds, not milliseconds.

I don't get why you would want to calculate air pressure at 250Hz anyway. Calculate it as often as possible.