BMP280 giving -ve altitude readings!! (I don't think I'm underground :) )

Hi All

So, I have a BMP280, set up, connected and reporting data to serial monitor using the Sparkfun library and code.

Temperature and Barometric pressure seem to be reporting pretty accurately, but the altitude reported is definitely incorrect. The reading is a negative value, and as far as I can tell, I am not under the sea!

So, not sure what the issue is here. Even if you make the value reported positive, it isn’t the correct altitude for where I am located. I live only about 50m above sea level and currently the BMP280 is reporting -199m :o

Here’s the code:

/******************************************************************************
I2C_ReadAllData.ino
BME280 Arduino and Teensy example
Marshall Taylor @ SparkFun Electronics
May 20, 2015
https://github.com/sparkfun/SparkFun_BME280_Arduino_Library

This sketch configures the BME280 to read all measurements.  The sketch also
displays the BME280's physical memory and what the driver perceives the
calibration words to be.

Resources:
Uses Wire.h for I2C operation
Uses SPI.h for SPI operation

Development environment specifics:
Arduino IDE 1.6.4
Teensy loader 1.23

This code is released under the [MIT License](http://opensource.org/licenses/MIT).
Please review the LICENSE.md file included with this example. If you have any questions 
or concerns with licensing, please contact techsupport@sparkfun.com.
Distributed as-is; no warranty is given.
******************************************************************************/

#include <stdint.h>
#include "SparkFunBME280.h"
//Library allows either I2C or SPI, so include both.
#include "Wire.h"
#include "SPI.h"

//Global sensor object
BME280 mySensor;

void setup()
{
	//***Driver settings********************************//
	//commInterface can be I2C_MODE or SPI_MODE
	//specify chipSelectPin using arduino pin names
	//specify I2C address.  Can be 0x77(default) or 0x76
	
	//For I2C, enable the following and disable the SPI section
	mySensor.settings.commInterface = I2C_MODE;
	mySensor.settings.I2CAddress = 0x76;
	
	//For SPI enable the following and dissable the I2C section
	//mySensor.settings.commInterface = SPI_MODE;
	//mySensor.settings.chipSelectPin = 10;


	//***Operation settings*****************************//
	
	//renMode can be:
	//  0, Sleep mode
	//  1 or 2, Forced mode
	//  3, Normal mode
	mySensor.settings.runMode = 3; //Normal mode
	
	//tStandby can be:
	//  0, 0.5ms
	//  1, 62.5ms
	//  2, 125ms
	//  3, 250ms
	//  4, 500ms
	//  5, 1000ms
	//  6, 10ms
	//  7, 20ms
	mySensor.settings.tStandby = 0;
	
	//filter can be off or number of FIR coefficients to use:
	//  0, filter off
	//  1, coefficients = 2
	//  2, coefficients = 4
	//  3, coefficients = 8
	//  4, coefficients = 16
	mySensor.settings.filter = 0;
	
	//tempOverSample can be:
	//  0, skipped
	//  1 through 5, oversampling *1, *2, *4, *8, *16 respectively
	mySensor.settings.tempOverSample = 1;

	//pressOverSample can be:
	//  0, skipped
	//  1 through 5, oversampling *1, *2, *4, *8, *16 respectively
    mySensor.settings.pressOverSample = 1;
	
	//humidOverSample can be:
	//  0, skipped
	//  1 through 5, oversampling *1, *2, *4, *8, *16 respectively
	mySensor.settings.humidOverSample = 1;
	
	Serial.begin(57600);
	Serial.print("Program Started\n");
	Serial.print("Starting BME280... result of .begin(): 0x");
	
	//Calling .begin() causes the settings to be loaded
	delay(10);  //Make sure sensor had enough time to turn on. BME280 requires 2ms to start up.
	Serial.println(mySensor.begin(), HEX);

	Serial.print("Displaying ID, reset and ctrl regs\n");
	
	Serial.print("ID(0xD0): 0x");
	Serial.println(mySensor.readRegister(BME280_CHIP_ID_REG), HEX);
	Serial.print("Reset register(0xE0): 0x");
	Serial.println(mySensor.readRegister(BME280_RST_REG), HEX);
	Serial.print("ctrl_meas(0xF4): 0x");
	Serial.println(mySensor.readRegister(BME280_CTRL_MEAS_REG), HEX);
	Serial.print("ctrl_hum(0xF2): 0x");
	Serial.println(mySensor.readRegister(BME280_CTRL_HUMIDITY_REG), HEX);

	Serial.print("\n\n");

	Serial.print("Displaying all regs\n");
	uint8_t memCounter = 0x80;
	uint8_t tempReadData;
	for(int rowi = 8; rowi < 16; rowi++ )
	{
		Serial.print("0x");
		Serial.print(rowi, HEX);
		Serial.print("0:");
		for(int coli = 0; coli < 16; coli++ )
		{
			tempReadData = mySensor.readRegister(memCounter);
			Serial.print((tempReadData >> 4) & 0x0F, HEX);//Print first hex nibble
			Serial.print(tempReadData & 0x0F, HEX);//Print second hex nibble
			Serial.print(" ");
			memCounter++;
		}
		Serial.print("\n");
	}
	
	
	Serial.print("\n\n");
	
	Serial.print("Displaying concatenated calibration words\n");
	Serial.print("dig_T1, uint16: ");
	Serial.println(mySensor.calibration.dig_T1);
	Serial.print("dig_T2, int16: ");
	Serial.println(mySensor.calibration.dig_T2);
	Serial.print("dig_T3, int16: ");
	Serial.println(mySensor.calibration.dig_T3);
	
	Serial.print("dig_P1, uint16: ");
	Serial.println(mySensor.calibration.dig_P1);
	Serial.print("dig_P2, int16: ");
	Serial.println(mySensor.calibration.dig_P2);
	Serial.print("dig_P3, int16: ");
	Serial.println(mySensor.calibration.dig_P3);
	Serial.print("dig_P4, int16: ");
	Serial.println(mySensor.calibration.dig_P4);
	Serial.print("dig_P5, int16: ");
	Serial.println(mySensor.calibration.dig_P5);
	Serial.print("dig_P6, int16: ");
	Serial.println(mySensor.calibration.dig_P6);
	Serial.print("dig_P7, int16: ");
	Serial.println(mySensor.calibration.dig_P7);
	Serial.print("dig_P8, int16: ");
	Serial.println(mySensor.calibration.dig_P8);
	Serial.print("dig_P9, int16: ");
	Serial.println(mySensor.calibration.dig_P9);
	
	Serial.print("dig_H1, uint8: ");
	Serial.println(mySensor.calibration.dig_H1);
	Serial.print("dig_H2, int16: ");
	Serial.println(mySensor.calibration.dig_H2);
	Serial.print("dig_H3, uint8: ");
	Serial.println(mySensor.calibration.dig_H3);
	Serial.print("dig_H4, int16: ");
	Serial.println(mySensor.calibration.dig_H4);
	Serial.print("dig_H5, int16: ");
	Serial.println(mySensor.calibration.dig_H5);
	Serial.print("dig_H6, uint8: ");
	Serial.println(mySensor.calibration.dig_H6);
		
	Serial.println();
}

void loop()
{
	//Each loop, take a reading.
	//Start with temperature, as that data is needed for accurate compensation.
	//Reading the temperature updates the compensators of the other functions
	//in the background.

	Serial.print("Temperature: ");
	Serial.print(mySensor.readTempC(), 2);
	Serial.println(" degrees C");

	Serial.print("Temperature: ");
	Serial.print(mySensor.readTempF(), 2);
	Serial.println(" degrees F");

	Serial.print("Pressure: ");
	Serial.print(mySensor.readFloatPressure()/100, 2);
	Serial.println(" Pa");

	Serial.print("Altitude: ");
	Serial.print(mySensor.readFloatAltitudeMeters(), 2);
	Serial.println("m");

	Serial.print("Altitude: ");
	Serial.print(mySensor.readFloatAltitudeFeet(), 2);
	Serial.println("ft");	

	Serial.print("%RH: ");
	Serial.print(mySensor.readFloatHumidity(), 2);
	Serial.println(" %");
	
	Serial.println();
	
	delay(1000);

}

A hefty and comprehensive sketch I appreciate, (as to be expected off Sparkfun) and of course, not all of it is needed, but this is the code I am currently running so thought I’d best post as-is!

Any ideas as to what might be happening please folks?

Thanks

It appears to derive altitude from the barometric pressure reading so it'll vary with the weather. Looks like you have a high pressure system over you today.

How do you calibrate the altitude sensor ?

Take a look at altitude calibration

UKHeliBob: How do you calibrate the altitude sensor ?

Hi Bob I have found an Adafruit library and sketch that allows an entry to the code for current pressure at seal level, when I enter the barometric pressure into that code, I get an accurate measurement of altitude. However, in the Sparkfun code i can't see anywhere to enter the sea level barometric pressure to allow for the same.

wildbill: It appears to derive altitude from the barometric pressure reading so it'll vary with the weather. Looks like you have a high pressure system over you today.

Bill, doesn't this sort of reduce the viability of the altitude reading given that it changes dependent on the current pressure and thus the code will always need to be amended to accomodate the current pressure? Unless, of course, I can programme it in somehow!

To do this would I instead of using a constant in the code for current barometric pressure, use the barometric reading obtained by the sensor? Hmmmm - or would that cause some form of circular reference?

Advice needed!

However, in the Sparkfun code i can't see anywhere to enter the sea level barometric pressure to allow for the same.

The sketch that I linked to just proves that the base altitude, in that case the floor, can be set.

UKHeliBob: The sketch that I linked to just proves that the base altitude, in that case the floor, can be set.

I'll take another look.

I tried to run the code, but received an error, needed the "CircularBuffer.h" library which I located (well, there are a few out there so no idea which one I need really - hence giving up with that code) but have been unable to install it.

Still learning you see :)

The calibration step is the inverse of the altitude problem.

Simply invert the formula that calculates altitude from the sea level pressure and the local pressure, to create a formula that calculates the current sea level pressure from the correct altitude and the local pressure.

Yes, it is a circular argument, but the air pressure usually changes over the course of many hours, so a calibration run should be good for a short while. If not, a weather front is passing over and you will know it!

This sensor measures atmospheric pressure. The pressure drops as you move up (look up "Atmospheric pressure" on Wikipedia), and the altitude function uses the difference between measured pressure and P0 to tell the altitude above the point at which you specified P0. Thus the altitude code is useful only for flying, where you'd use P0 at the ground level, and use altitude as the height above the ground, and not too long after you specified P0, since that changes all the time. Temperature and humidity affect the formula just a little.