libraries / BMP180_Breakout_Arduino_Library-master / src / SFE_BMP180.cppon commit Added link to project report (97a3ba0)
   1/*
   2        SFE_BMP180.cpp
   3        Bosch BMP180 pressure sensor library for the Arduino microcontroller
   4        Mike Grusin, SparkFun Electronics
   5
   6        Uses floating-point equations from the Weather Station Data Logger project
   7        http://wmrx00.sourceforge.net/
   8        http://wmrx00.sourceforge.net/Arduino/BMP085-Calcs.pdf
   9
  10        Forked from BMP085 library by M.Grusin
  11
  12        version 1.0 2013/09/20 initial version
  13        Verison 1.1.2 - Updated for Arduino 1.6.4 5/2015
  14
  15        Our example code uses the "beerware" license. You can do anything
  16        you like with this code. No really, anything. If you find it useful,
  17        buy me a (root) beer someday.
  18*/
  19
  20#include <SFE_BMP180.h>
  21#include <Wire.h>
  22#include <stdio.h>
  23#include <math.h>
  24
  25
  26SFE_BMP180::SFE_BMP180()
  27// Base library type
  28{
  29}
  30
  31
  32char SFE_BMP180::begin()
  33// Initialize library for subsequent pressure measurements
  34{
  35        double c3,c4,b1;
  36        
  37        // Start up the Arduino's "wire" (I2C) library:
  38        
  39        Wire.begin();
  40
  41        // The BMP180 includes factory calibration data stored on the device.
  42        // Each device has different numbers, these must be retrieved and
  43        // used in the calculations when taking pressure measurements.
  44
  45        // Retrieve calibration data from device:
  46        
  47        if (readInt(0xAA,AC1) &&
  48                readInt(0xAC,AC2) &&
  49                readInt(0xAE,AC3) &&
  50                readUInt(0xB0,AC4) &&
  51                readUInt(0xB2,AC5) &&
  52                readUInt(0xB4,AC6) &&
  53                readInt(0xB6,VB1) &&
  54                readInt(0xB8,VB2) &&
  55                readInt(0xBA,MB) &&
  56                readInt(0xBC,MC) &&
  57                readInt(0xBE,MD))
  58        {
  59
  60                // All reads completed successfully!
  61
  62                // If you need to check your math using known numbers,
  63                // you can uncomment one of these examples.
  64                // (The correct results are commented in the below functions.)
  65
  66                // Example from Bosch datasheet
  67                // AC1 = 408; AC2 = -72; AC3 = -14383; AC4 = 32741; AC5 = 32757; AC6 = 23153;
  68                // B1 = 6190; B2 = 4; MB = -32768; MC = -8711; MD = 2868;
  69
  70                // Example from http://wmrx00.sourceforge.net/Arduino/BMP180-Calcs.pdf
  71                // AC1 = 7911; AC2 = -934; AC3 = -14306; AC4 = 31567; AC5 = 25671; AC6 = 18974;
  72                // VB1 = 5498; VB2 = 46; MB = -32768; MC = -11075; MD = 2432;
  73
  74                /*
  75                Serial.print("AC1: "); Serial.println(AC1);
  76                Serial.print("AC2: "); Serial.println(AC2);
  77                Serial.print("AC3: "); Serial.println(AC3);
  78                Serial.print("AC4: "); Serial.println(AC4);
  79                Serial.print("AC5: "); Serial.println(AC5);
  80                Serial.print("AC6: "); Serial.println(AC6);
  81                Serial.print("VB1: "); Serial.println(VB1);
  82                Serial.print("VB2: "); Serial.println(VB2);
  83                Serial.print("MB: "); Serial.println(MB);
  84                Serial.print("MC: "); Serial.println(MC);
  85                Serial.print("MD: "); Serial.println(MD);
  86                */
  87                
  88                // Compute floating-point polynominals:
  89
  90                c3 = 160.0 * pow(2,-15) * AC3;
  91                c4 = pow(10,-3) * pow(2,-15) * AC4;
  92                b1 = pow(160,2) * pow(2,-30) * VB1;
  93                c5 = (pow(2,-15) / 160) * AC5;
  94                c6 = AC6;
  95                mc = (pow(2,11) / pow(160,2)) * MC;
  96                md = MD / 160.0;
  97                x0 = AC1;
  98                x1 = 160.0 * pow(2,-13) * AC2;
  99                x2 = pow(160,2) * pow(2,-25) * VB2;
 100                y0 = c4 * pow(2,15);
 101                y1 = c4 * c3;
 102                y2 = c4 * b1;
 103                p0 = (3791.0 - 8.0) / 1600.0;
 104                p1 = 1.0 - 7357.0 * pow(2,-20);
 105                p2 = 3038.0 * 100.0 * pow(2,-36);
 106
 107                /*
 108                Serial.println();
 109                Serial.print("c3: "); Serial.println(c3);
 110                Serial.print("c4: "); Serial.println(c4);
 111                Serial.print("c5: "); Serial.println(c5);
 112                Serial.print("c6: "); Serial.println(c6);
 113                Serial.print("b1: "); Serial.println(b1);
 114                Serial.print("mc: "); Serial.println(mc);
 115                Serial.print("md: "); Serial.println(md);
 116                Serial.print("x0: "); Serial.println(x0);
 117                Serial.print("x1: "); Serial.println(x1);
 118                Serial.print("x2: "); Serial.println(x2);
 119                Serial.print("y0: "); Serial.println(y0);
 120                Serial.print("y1: "); Serial.println(y1);
 121                Serial.print("y2: "); Serial.println(y2);
 122                Serial.print("p0: "); Serial.println(p0);
 123                Serial.print("p1: "); Serial.println(p1);
 124                Serial.print("p2: "); Serial.println(p2);
 125                */
 126                
 127                // Success!
 128                return(1);
 129        }
 130        else
 131        {
 132                // Error reading calibration data; bad component or connection?
 133                return(1);
 134        }
 135}
 136
 137
 138char SFE_BMP180::readInt(char address, int16_t &value)
 139// Read a signed integer (two bytes) from device
 140// address: register to start reading (plus subsequent register)
 141// value: external variable to store data (function modifies value)
 142{
 143        unsigned char data[2];
 144
 145        data[0] = address;
 146        if (readBytes(data,2))
 147        {
 148                value = (int16_t)((data[0]<<8)|data[1]);
 149                //if (*value & 0x8000) *value |= 0xFFFF0000; // sign extend if negative
 150                return(1);
 151        }
 152        value = 0;
 153        return(0);
 154}
 155
 156
 157char SFE_BMP180::readUInt(char address, uint16_t &value)
 158// Read an unsigned integer (two bytes) from device
 159// address: register to start reading (plus subsequent register)
 160// value: external variable to store data (function modifies value)
 161{
 162        unsigned char data[2];
 163
 164        data[0] = address;
 165        if (readBytes(data,2))
 166        {
 167                value = (((uint16_t)data[0]<<8)|(uint16_t)data[1]);
 168                return(1);
 169        }
 170        value = 0;
 171        return(0);
 172}
 173
 174
 175char SFE_BMP180::readBytes(unsigned char *values, char length)
 176// Read an array of bytes from device
 177// values: external array to hold data. Put starting register in values[0].
 178// length: number of bytes to read
 179{
 180        char x;
 181
 182        Wire.beginTransmission(BMP180_ADDR);
 183        Wire.write(values[0]);
 184        _error = Wire.endTransmission();
 185        if (_error == 0)
 186        {
 187                Wire.requestFrom(BMP180_ADDR,length);
 188                while(Wire.available() != length) ; // wait until bytes are ready
 189                for(x=0;x<length;x++)
 190                {
 191                        values[x] = Wire.read();
 192                }
 193                return(1);
 194        }
 195        return(0);
 196}
 197
 198
 199char SFE_BMP180::writeBytes(unsigned char *values, char length)
 200// Write an array of bytes to device
 201// values: external array of data to write. Put starting register in values[0].
 202// length: number of bytes to write
 203{
 204        char x;
 205        
 206        Wire.beginTransmission(BMP180_ADDR);
 207        Wire.write(values,length);
 208        _error = Wire.endTransmission();
 209        if (_error == 0)
 210                return(1);
 211        else
 212                return(0);
 213}
 214
 215
 216char SFE_BMP180::startTemperature(void)
 217// Begin a temperature reading.
 218// Will return delay in ms to wait, or 0 if I2C error
 219{
 220        unsigned char data[2], result;
 221        
 222        data[0] = BMP180_REG_CONTROL;
 223        data[1] = BMP180_COMMAND_TEMPERATURE;
 224        result = writeBytes(data, 2);
 225        if (result) // good write?
 226                return(5); // return the delay in ms (rounded up) to wait before retrieving data
 227        else
 228                return(0); // or return 0 if there was a problem communicating with the BMP
 229}
 230
 231
 232char SFE_BMP180::getTemperature(double &T)
 233// Retrieve a previously-started temperature reading.
 234// Requires begin() to be called once prior to retrieve calibration parameters.
 235// Requires startTemperature() to have been called prior and sufficient time elapsed.
 236// T: external variable to hold result.
 237// Returns 1 if successful, 0 if I2C error.
 238{
 239        unsigned char data[2];
 240        char result;
 241        double tu, a;
 242        
 243        data[0] = BMP180_REG_RESULT;
 244
 245        result = readBytes(data, 2);
 246        if (result) // good read, calculate temperature
 247        {
 248                tu = (data[0] * 256.0) + data[1];
 249
 250                //example from Bosch datasheet
 251                //tu = 27898;
 252
 253                //example from http://wmrx00.sourceforge.net/Arduino/BMP085-Calcs.pdf
 254                //tu = 0x69EC;
 255                
 256                a = c5 * (tu - c6);
 257                T = a + (mc / (a + md));
 258
 259                /*              
 260                Serial.println();
 261                Serial.print("tu: "); Serial.println(tu);
 262                Serial.print("a: "); Serial.println(a);
 263                Serial.print("T: "); Serial.println(*T);
 264                */
 265        }
 266        return(result);
 267}
 268
 269
 270char SFE_BMP180::startPressure(char oversampling)
 271// Begin a pressure reading.
 272// Oversampling: 0 to 3, higher numbers are slower, higher-res outputs.
 273// Will return delay in ms to wait, or 0 if I2C error.
 274{
 275        unsigned char data[2], result, delay;
 276        
 277        data[0] = BMP180_REG_CONTROL;
 278
 279        switch (oversampling)
 280        {
 281                case 0:
 282                        data[1] = BMP180_COMMAND_PRESSURE0;
 283                        delay = 5;
 284                break;
 285                case 1:
 286                        data[1] = BMP180_COMMAND_PRESSURE1;
 287                        delay = 8;
 288                break;
 289                case 2:
 290                        data[1] = BMP180_COMMAND_PRESSURE2;
 291                        delay = 14;
 292                break;
 293                case 3:
 294                        data[1] = BMP180_COMMAND_PRESSURE3;
 295                        delay = 26;
 296                break;
 297                default:
 298                        data[1] = BMP180_COMMAND_PRESSURE0;
 299                        delay = 5;
 300                break;
 301        }
 302        result = writeBytes(data, 2);
 303        if (result) // good write?
 304                return(delay); // return the delay in ms (rounded up) to wait before retrieving data
 305        else
 306                return(0); // or return 0 if there was a problem communicating with the BMP
 307}
 308
 309
 310char SFE_BMP180::getPressure(double &P, double &T)
 311// Retrieve a previously started pressure reading, calculate abolute pressure in mbars.
 312// Requires begin() to be called once prior to retrieve calibration parameters.
 313// Requires startPressure() to have been called prior and sufficient time elapsed.
 314// Requires recent temperature reading to accurately calculate pressure.
 315
 316// P: external variable to hold pressure.
 317// T: previously-calculated temperature.
 318// Returns 1 for success, 0 for I2C error.
 319
 320// Note that calculated pressure value is absolute mbars, to compensate for altitude call sealevel().
 321{
 322        unsigned char data[3];
 323        char result;
 324        double pu,s,x,y,z;
 325        
 326        data[0] = BMP180_REG_RESULT;
 327
 328        result = readBytes(data, 3);
 329        if (result) // good read, calculate pressure
 330        {
 331                pu = (data[0] * 256.0) + data[1] + (data[2]/256.0);
 332
 333                //example from Bosch datasheet
 334                //pu = 23843;
 335
 336                //example from http://wmrx00.sourceforge.net/Arduino/BMP085-Calcs.pdf, pu = 0x982FC0;   
 337                //pu = (0x98 * 256.0) + 0x2F + (0xC0/256.0);
 338                
 339                s = T - 25.0;
 340                x = (x2 * pow(s,2)) + (x1 * s) + x0;
 341                y = (y2 * pow(s,2)) + (y1 * s) + y0;
 342                z = (pu - x) / y;
 343                P = (p2 * pow(z,2)) + (p1 * z) + p0;
 344
 345                /*
 346                Serial.println();
 347                Serial.print("pu: "); Serial.println(pu);
 348                Serial.print("T: "); Serial.println(*T);
 349                Serial.print("s: "); Serial.println(s);
 350                Serial.print("x: "); Serial.println(x);
 351                Serial.print("y: "); Serial.println(y);
 352                Serial.print("z: "); Serial.println(z);
 353                Serial.print("P: "); Serial.println(*P);
 354                */
 355        }
 356        return(result);
 357}
 358
 359
 360double SFE_BMP180::sealevel(double P, double A)
 361// Given a pressure P (mb) taken at a specific altitude (meters),
 362// return the equivalent pressure (mb) at sea level.
 363// This produces pressure readings that can be used for weather measurements.
 364{
 365        return(P/pow(1-(A/44330.0),5.255));
 366}
 367
 368
 369double SFE_BMP180::altitude(double P, double P0)
 370// Given a pressure measurement P (mb) and the pressure at a baseline P0 (mb),
 371// return altitude (meters) above baseline.
 372{
 373        return(44330.0*(1-pow(P/P0,1/5.255)));
 374}
 375
 376
 377char SFE_BMP180::getError(void)
 378        // If any library command fails, you can retrieve an extended
 379        // error code using this command. Errors are from the wire library: 
 380        // 0 = Success
 381        // 1 = Data too long to fit in transmit buffer
 382        // 2 = Received NACK on transmit of address
 383        // 3 = Received NACK on transmit of data
 384        // 4 = Other error
 385{
 386        return(_error);
 387}
 388