BMP180 use as a baro (not altitude) sensor...

For other supported Arduino products from Adafruit: Shields, accessories, etc.

Moderators: adafruit_support_bill, adafruit

Please be positive and constructive with your questions and comments.
Locked
User avatar
Varmint
 
Posts: 43
Joined: Sat Aug 23, 2014 8:13 pm

BMP180 use as a baro (not altitude) sensor...

Post by Varmint »

I've got the beginnings of a long term monitoring weather station. Regardless of anyone else's ideas on the merit of such a system, I've always wanted a weather logger that samples once per minute, all day, every day, 365 days a year, multiple years.

In any event, I'm using the Adafruit DS1307 RTC breakout, MCP9808 breakout, GA1A1S202WP log light sensor, and most recently added the BMP180 for baro readings. All of the readings are (or will be) saved once a minute to a 16GB uSDHC card in the Adafruit Micro-SD breakout,

Key note here is the intended use is absolute barometric pressure, I have no need for altitude. My trouble is figuring out a way to record the raw data from the sensor, or, convert the data returned from the sensorapi example code into a format I can store in the uSD card. Right now all of the sensor data is stored in csv format, then imported into an excel spreadsheet that handles the conversion and charting of the raw values.

With the exception of the BMP180 data, all of the rest works perfectly, and the charts are really quite impressively detailed and meaningful. Once the baro is out of the way, the likely final step(s) will be wind speed monitoring, maybe even particulate counting to catalog the timing, intensity, and duration of pollen season.

So, my request is tips on how to convert/store the data, or tips on how to rewrite the libraries so I can utilize raw sensor values (readRawPressure returns an error).

Thanks for any insight you might be able to provide.

DAS
Last edited by Varmint on Mon Aug 25, 2014 9:41 am, edited 1 time in total.

User avatar
Varmint
 
Posts: 43
Joined: Sat Aug 23, 2014 8:13 pm

Re: BMP180 use as a baro (not altitude) sensor...

Post by Varmint »

Addenum:

I realize for the baro reading to be "legitimate", I need to input the elevation of the area at which the readings are taken, which in this case is 1584ft, or 482.8032m.

So then, I need to record the raw data and either do the math to adjust for altitude/temperature before saving it, or the spreadsheet needs to account for it. My preference is completely raw data (spreadsheet does the math).

I'd also like to use the temperature from the MCP9808, as is it is more accurate and more linear over true temperature than the temperature sensor inside the BMP180.

Thanks,

DAS

User avatar
Franklin97355
 
Posts: 23910
Joined: Mon Apr 21, 2008 2:33 pm

Re: BMP180 use as a baro (not altitude) sensor...

Post by Franklin97355 »

Let's start with
utilize raw sensor values (readRawPressure returns an error).
What error are you getting?

User avatar
Varmint
 
Posts: 43
Joined: Sat Aug 23, 2014 8:13 pm

Re: BMP180 use as a baro (not altitude) sensor...

Post by Varmint »

The requested function is not a member of the class.

User avatar
Franklin97355
 
Posts: 23910
Joined: Mon Apr 21, 2008 2:33 pm

Re: BMP180 use as a baro (not altitude) sensor...

Post by Franklin97355 »

Which library are you using?

User avatar
Varmint
 
Posts: 43
Joined: Sat Aug 23, 2014 8:13 pm

Re: BMP180 use as a baro (not altitude) sensor...

Post by Varmint »

your (adafruit) libraries, sensor and BMP085_U.

User avatar
adafruit_support_bill
 
Posts: 88091
Joined: Sat Feb 07, 2009 10:11 am

Re: BMP180 use as a baro (not altitude) sensor...

Post by adafruit_support_bill »

That function is not a member of the class as defined in the library (see below).
Use getPressure() to get the raw pressure and pressureToAltitude() if you want to convert.

Code: Select all

class Adafruit_BMP085_Unified : public Adafruit_Sensor
{
  public:
    Adafruit_BMP085_Unified(int32_t sensorID = -1);
  
    bool  begin(bmp085_mode_t mode = BMP085_MODE_ULTRAHIGHRES);
    void  getTemperature(float *temp);
    void  getPressure(float *pressure);
    float pressureToAltitude(float seaLevel, float atmospheric, float temp);
    float seaLevelForAltitude(float altitude, float atmospheric, float temp);
    void  getEvent(sensors_event_t*);
    void  getSensor(sensor_t*);

  private:
    int32_t computeB5(int32_t ut);
    int32_t _sensorID;
};

User avatar
Varmint
 
Posts: 43
Joined: Sat Aug 23, 2014 8:13 pm

Re: BMP180 use as a baro (not altitude) sensor...

Post by Varmint »

I cant get that to work for some reason. Could you give me the exact syntax?

User avatar
adafruit_support_bill
 
Posts: 88091
Joined: Sat Feb 07, 2009 10:11 am

Re: BMP180 use as a baro (not altitude) sensor...

Post by adafruit_support_bill »

Define this before your setup()

Code: Select all

Adafruit_BMP085_Unified bmp = Adafruit_BMP085_Unified(10085);
And then in your loop:

Code: Select all

    float pressure;

    bmp.getPressure(&pressure);

    Seral.print("Pressure = ");
    Serial.println(pressure);

User avatar
Varmint
 
Posts: 43
Joined: Sat Aug 23, 2014 8:13 pm

Re: BMP180 use as a baro (not altitude) sensor...

Post by Varmint »

OK, I see my error, I'm not expressing myself well.

I'd like the RAW data, pure digital format, not the floating point representation.

Barring that, a means of converting it back to long. I tried a conversion, but of course it stripped the stuff after the decimal, and I'm not smart enough to find a way to preserve the entire count.

DAS

User avatar
adafruit_support_bill
 
Posts: 88091
Joined: Sat Feb 07, 2009 10:11 am

Re: BMP180 use as a baro (not altitude) sensor...

Post by adafruit_support_bill »

How raw do you want it? It is not simply a matter of a floating point conversion. There is temperature compensation as well. In any case, you will need to get into the guts of the library and look at the private functions that are not exposed: https://github.com/adafruit/Adafruit_BM ... P085_U.cpp

This reads the RAW pressure.

Code: Select all

static void readRawPressure(int32_t *pressure)
{
  #if BMP085_USE_DATASHEET_VALS
    *pressure = 23843;
  #else
    uint8_t  p8;
    uint16_t p16;
    int32_t  p32;

    writeCommand(BMP085_REGISTER_CONTROL, BMP085_REGISTER_READPRESSURECMD + (_bmp085Mode << 6));
    switch(_bmp085Mode)
    {
      case BMP085_MODE_ULTRALOWPOWER:
        delay(5);
        break;
      case BMP085_MODE_STANDARD:
        delay(8);
        break;
      case BMP085_MODE_HIGHRES:
        delay(14);
        break;
      case BMP085_MODE_ULTRAHIGHRES:
      default:
        delay(26);
        break;
    }

    read16(BMP085_REGISTER_PRESSUREDATA, &p16);
    p32 = (uint32_t)p16 << 8;
    read8(BMP085_REGISTER_PRESSUREDATA+2, &p8);
    p32 += p8;
    p32 >>= (8 - _bmp085Mode);
    
    *pressure = p32;
  #endif
}
This does the temperature compensation and converts it into a float:

Code: Select all

/**************************************************************************/
/*!
    @brief  Gets the compensated pressure level in kPa
*/
/**************************************************************************/
void Adafruit_BMP085_Unified::getPressure(float *pressure)
{
  int32_t  ut = 0, up = 0, compp = 0;
  int32_t  x1, x2, b5, b6, x3, b3, p;
  uint32_t b4, b7;

  /* Get the raw pressure and temperature values */
  readRawTemperature(&ut);
  readRawPressure(&up);

  /* Temperature compensation */
  b5 = computeB5(ut);

  /* Pressure compensation */
  b6 = b5 - 4000;
  x1 = (_bmp085_coeffs.b2 * ((b6 * b6) >> 12)) >> 11;
  x2 = (_bmp085_coeffs.ac2 * b6) >> 11;
  x3 = x1 + x2;
  b3 = (((((int32_t) _bmp085_coeffs.ac1) * 4 + x3) << _bmp085Mode) + 2) >> 2;
  x1 = (_bmp085_coeffs.ac3 * b6) >> 13;
  x2 = (_bmp085_coeffs.b1 * ((b6 * b6) >> 12)) >> 16;
  x3 = ((x1 + x2) + 2) >> 2;
  b4 = (_bmp085_coeffs.ac4 * (uint32_t) (x3 + 32768)) >> 15;
  b7 = ((uint32_t) (up - b3) * (50000 >> _bmp085Mode));

  if (b7 < 0x80000000)
  {
    p = (b7 << 1) / b4;
  }
  else
  {
    p = (b7 / b4) << 1;
  }

  x1 = (p >> 8) * (p >> 8);
  x1 = (x1 * 3038) >> 16;
  x2 = (-7357 * p) >> 16;
  compp = p + ((x1 + x2 + 3791) >> 4);

  /* Assign compensated pressure value */
  *pressure = compp;
}
If you want any part of that, you will also need the parts that read the temperature and define the coefficients for the compensation.

User avatar
Varmint
 
Posts: 43
Joined: Sat Aug 23, 2014 8:13 pm

Re: BMP180 use as a baro (not altitude) sensor...

Post by Varmint »

OK, thanks for the assist.

As an engineer, my mantra when handling data is to always store the native form, derivations are easy to produce after the fact, but "rewinding" the derivations to reconstruct the native readings is not guaranteed should there be rounding at any step.

However, in this case, quite a bit of transformation is applied, so I might just reconsider my approach. After all, all I require is a running record, were not doing vector calculations for a missile intercept or anything.

I've come a long way with C since I started playing with Arduino. I've written millions of lines of assembly (mostly Motorola microcontrollers) and a similar amount of VBS for systems administration, but C and its derivatives have always thrown me for a loop. I'm getting there slowly but surely, and again I thank you for the assist.

DAS

User avatar
adafruit_support_bill
 
Posts: 88091
Joined: Sat Feb 07, 2009 10:11 am

Re: BMP180 use as a baro (not altitude) sensor...

Post by adafruit_support_bill »

If you are at home with Motorola assembly for the 6800 family, C should not be too much of a stretch. Both are thinly disguised derivatives of PDP-11 assembler.

User avatar
Varmint
 
Posts: 43
Joined: Sat Aug 23, 2014 8:13 pm

Re: BMP180 use as a baro (not altitude) sensor...

Post by Varmint »

For me, it's the syntax, and that few compilers report the actual problem with the code but seem to miss the "offence" so badly as to almost seem like purposeful misdirection.

That and the monumental bloat:

Two decades ago I designed a fuel injection system for lawnmower that worked phenominally well. It was based on a MC68HC11, a 8K UVEPROM, a couple Motorola vacuum/pressure senors, and a few interface components. In the end, with as many bells and whistles I could throw at it, I had a hard time getting close to 2K of object code. Being a one-off build it suffered from connection failures due to vibration, if it had been a PCB with everything soldered and better isolation mounting, it might still be working today.

The little logger I'm working on? 23K and counting, with only 121 lines of my code. I know for certain I could do it in less than 1K on a Moto '11. To that end, I'll probably spend more time in the AVR studio and see how I adapt to the AVR instruction set.

Have a great day.

DAS

Locked
Please be positive and constructive with your questions and comments.

Return to “Other Arduino products from Adafruit”