Code returning incorrect altitude - from BMP085 code

This code is straight out of the Adafruit BMP085 sample code and library.
But obviously I'm doing something wrong, because its returning.

23140.43 as the altitude. When I'm practically at sea level as it is. Maybe a 10 or so meters above sea level, but not 23,140 meters ....

The code is from the BMP085_U library basically.
The Arduino + Weathershield is returning everything else ok,

/* -------------- Get the altitude ---------------------- */  
/**************************************************************************/
/*!
    Calculates the altitude (in meters) from the specified atmospheric
    pressure (in hPa), sea-level pressure (in hPa), and temperature (in ?C)

    @param  seaLevel      Sea-level pressure in hPa
    @param  atmospheric   Atmospheric pressure in hPa
    @param  temp          Temperature in degrees Celsius
*/
/**************************************************************************/
  /* Hyposometric formula:                      */
  /*                                            */
  /*     ((P0/P)^(1/5.257) - 1) * (T + 273.15)  */
  /* h = -------------------------------------  */
  /*                   0.0065                   */
  /*                                            */
  /* where: h   = height (in meters)            */
  /*        P0  = sea-level pressure (in hPa)   */
  /*        P   = atmospheric pressure (in hPa) */
  /*        T   = temperature (in ?C)           */
  
  const uint32_t seaLevel, P0 = 1013.25;
  float pow (double base, double exponent);
  uint32_t temp, T = t;
  temp = t; // returned by sensor above, degrees C
  uint32_t atmospheric, P = p; // pressure in hpa
  uint32_t h, altitude; //height in meters
  h = (((float)pow((P0/P), 0.190223F) - 1.0F) * (T + 273.15F)) / 0.0065F;
  
  //h = (((float)pow((seaLevel/atmospheric), 0.190223F) - 1.0F)
  //       * (temp + 273.15F)) / 0.0065F;
  altitude = h;
  		putchar(',');
		utoa(altitude/100, buffer, 10);
		usart_puts(buffer);
		putchar('.');
		if (altitude%100 < 10)
		{
			putchar('0');
		}
		utoa(altitude%100, buffer, 10);
		usart_puts(buffer);
/*---------------------------------------------------------*/

Output of Arduino at present. Debug mode is on.

HEX,05,0d,a5,71,a8,10,TEMPERATURE:17.1
HEX,55,0d,a6,1f,9e,40,HUMIDITY:61
HEX,35,0d,a1,df,e2,20,WINDDIRECTION:NNW WINDSPEED:2.9
HEX,b5,0d,a3,60,c9,b0,GUSTDIRECTION:N   GUSTSPEED:5.4
HEX,05,0d,a5,71,a8,10,TEMPERATURE:17.1
HEX,55,0d,a6,1f,9e,40,HUMIDITY:61
HEX,35,0d,a1,df,e2,20,WINDDIRECTION:NNW WINDSPEED:2.9
HEX,b5,0d,a3,60,c9,b0,GUSTDIRECTION:N   GUSTSPEED:5.4
--END--
I2C UT=26976
I2C T=21
I2C UP=334676
I2C P=1007.36
80,27,27,17.1,61,-,N  ,5.4,NNW,2.9,1007.36,23140.43
Indoor Temp=21.2

Hi ShanghaiTimes

  float pow (double base, double exponent);

This looks like a function declaration but with no body? And C / C++ has a pow function already.

Can you post your complete program.

Thanks

Ray

const uint32_t seaLevel, P0 = 1013.25;

?

If I comment the line, in other words, if I don't declare it, I get the following error. The P0 is the default pressure at sea-level

ok, solved the pow thing.
#include <math.h>

however - altitude still returning... 20436.96

 const uint32_t seaLevel, P0 = 1013.25;
  //float pow (double base, double exponent);

I get this in the compile

Weather.c: In function 'Packet_Converter_WS3600':
Weather.c:603: warning: implicit declaration of function 'pow'
Weather.c:603: warning: incompatible implicit declaration of built-in function 'pow'
Weather.c:601: warning: unused variable 'atmospheric'

I also know about the two unused variables,

Weather.c:601: warning: unused variable 'atmospheric'
Weather.c:597: warning: unused variable 'seaLevel'

There is way too much code to put it here in the forum, but it is available from [here] - apart from my extra attempt at modifications to get the altitude.

Got it.
Based on the default 1013.25 sea level base, it returns 0.0. Which is right up to a point.

?Weather Station Receiver has powered up (v1)
Debug enabled
HEX,45,0f,a5,79,a8,f0,TEMPERATURE:17.9
HEX,15,0f,a5,6f,a9,20,HUMIDITY:56
HEX,25,0f,a4,08,bf,c0,RAINFALL:1032
HEX,35,0f,a1,ab,e5,00,WINDDIRECTION:WSW WINDSPEED:2.6
HEX,b5,0f,a2,5d,da,a0,GUSTDIRECTION:WNW GUSTSPEED:3.7
HEX,45,0f,a5,79,a8,f0,TEMPERATURE:17.9
HEX,15,0f,a5,6f,a9,20,HUMIDITY:56
HEX,25,0f,a4,08,bf,c0,RAINFALL:1032
HEX,35,0f,a1,ab,e5,00,WINDDIRECTION:WSW WINDSPEED:2.6
HEX,b5,0f,a2,5d,da,a0,GUSTDIRECTION:WNW GUSTSPEED:3.7
--END--
I2C UT=26910
I2C T=20
I2C UP=335126
I2C P=950.12
80,31,31,17.9,56,1032,WNW,3.7,WSW,2.6,950.12,0.00
Indoor Temp=20.9

The code change was this.

  const uint32_t P0 = 1013.25; // seaLevel,
  		ut = bmp180_get_value(BMP180_TEMPERATURE, 5);
		t = (bmp180_get_temperature(ut));
		up = bmp180_get_value(BMP180_PRESSURE_3, 26);
		p = bmp180_get_pressure(up);                 

  [b]uint32_t T = t/10;[/b]
  [b]uint32_t P = p/100;[/b] // atmospheric pressure in hpa
  uint32_t h, altitude; //height in meters
  h = (((double)pow((P0/P), 0.190223F) - 1.0F) * (T + 273.15F)) / 0.0065F;

thanks guys.

I've got a feeling I've already asked, but I'll ask again

const uint32_t P0 = 1013.25;

?

Hi there,

const uint32_t P0 = 1013.25;

This is the base - default - sea level hPa measurement. It takes no account of temperature or other weather factors. It's just the baseline measurement in the absence of anything else.
There is another formula, where you can put in the actual hPa, at your site, but as it changes ... you would have to keep updating it. If you know your actual real-time baseline pressure for your location, enter that instead. ie; you live next to an airport.

This is from the adafruit -BMP180.cpp library.

/**************************************************************************/
/*!
    Calculates the altitude (in meters) from the specified atmospheric
    pressure (in hPa), sea-level pressure (in hPa), and temperature (in ?C)

    @param  seaLevel      Sea-level pressure in hPa
    @param  atmospheric   Atmospheric pressure in hPa
    @param  temp          Temperature in degrees Celsius
*/
/**************************************************************************/
float Adafruit_BMP085_Unified::pressureToAltitude(float seaLevel, float atmospheric, float temp)
{
  /* Hyposometric formula:                      */
  /*                                            */
  /*     ((P0/P)^(1/5.257) - 1) * (T + 273.15)  */
  /* h = -------------------------------------  */
  /*                   0.0065                   */
  /*                                            */
  /* where: h   = height (in meters)            */
  /*        P0  = sea-level pressure (in hPa)   */
  /*        P   = atmospheric pressure (in hPa) */
  /*        T   = temperature (in ?C)           */

  return (((float)pow((seaLevel/atmospheric), 0.190223F) - 1.0F)
         * (temp + 273.15F)) / 0.0065F;
}

float Adafruit_BMP085_Unified::seaLevelForAltitude(float altitude, float atmospheric, float temp)
{
  /* Hyposometric formula:                      */
  /*                                            */
  /* P0=((((h*0.0065)/(temp + 273.15F))+1)^(^/0.190223F))*P */
  /*                                            */
  /* where: h   = height (in meters)            */
  /*        P0  = sea-level pressure (in hPa)   */
  /*        P   = atmospheric pressure (in hPa) */
  /*        T   = temperature (in ?C)           */
  
  return (float)pow((((altitude*0.0065)/(temp + 273.15F))+1), (1.0/0.190223F))*atmospheric;
}

and this is from the SFE_BMP180.cpp, similar tothe BMP180 data sheet.

double SFE_BMP180::sealevel(double P, double A)
// Given a pressure P (mb) taken at a specific altitude (meters),
// return the equivalent pressure (mb) at sea level.
// This produces pressure readings that can be used for weather measurements.
{
	return(P/pow(1-(A/44330.0),5.255));
}


double SFE_BMP180::altitude(double P, double P0)
// Given a pressure measurement P (mb) and the pressure at a baseline P0 (mb),
// return altitude (meters) above baseline.
{
	return(44330.0*(1-pow(P/P0,1/5.255)));
}
 uint32_t P0 = 1013.25;

Do you know what "int" is an abbreviation of?

AWOL:

 uint32_t P0 = 1013.25;

Do you know what "int" is an abbreviation of?

doh! ....

Now, that feels better :slight_smile:

 const double P0 = 1013.25; // seaLevel,
  		ut = bmp180_get_value(BMP180_TEMPERATURE, 5);
		t = (bmp180_get_temperature(ut));
		up = bmp180_get_value(BMP180_PRESSURE_3, 26);
		p = bmp180_get_pressure(up);                 

  double T = t/10;
  double P = p/100; // atmospheric pressure in hpa
  double h, altitude; //height in meters
  
  h = (((double)pow((P0/P), 0.190223F) - 1.0F) * (T + 273.15F)) / 0.0065F;
   altitude = h;
  		putchar(',');
		utoa(altitude, buffer, 10);
		usart_puts(buffer);
		putchar('.');
		if ((int)altitude%100 < 10)
		{
			putchar('0');
		}
		utoa((int)altitude%100, buffer, 10);
		usart_puts(buffer);

Hi ShanghaiTimes

Just in case it leads to odd problems later, be aware that double only gives the same precision as float on an Arduino (unless you are running on a Due).

Regards

Ray

Thanks, I'll keep an eye on it. Do some fiddling later.

I'm using Uno, and 4 bytes is probably enough for this particular task. I guess there isn't much option anyway.