Basic program to read temperature and pressure data from BMP-180 altimeter, convert the temperature into Centigrade and Fahrenheit, and average pressure for highest precision. Use pressure to obtain altitude in meters and feet. Display all to four 4-digit eight-segment bubble displays.

Dependencies:   mbed

Dependents:   GloboMet

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers BMP180.h Source File

BMP180.h

00001 #ifndef BMP180_H
00002 #define BMP180_H
00003  
00004 #include "mbed.h"
00005 
00006 #define BMP180_ADDRESS          0x77<<1 // I2C address of BMP180, eight bit address on mbed
00007 #define BMP180_WHO_AM_I         0xD0    // WHO_AM_I id of BMP180, should return 0x55
00008 #define BMP180_RESET            0xE0
00009 #define BMP180_CONTROL          0xF4
00010 #define BMP180_OUT_MSB          0xF6
00011 #define BMP180_OUT_LSB          0xF7
00012 #define BMP180_OUT_XLSB         0xF8
00013 
00014 // Set initial input parameters
00015 
00016 enum OSS {  // BMP-085 sampling rate
00017   OSS_0 = 0,  // 4.5 ms conversion time
00018   OSS_1,      // 7.5
00019   OSS_2,      // 13.5
00020   OSS_3       // 25.5
00021 };
00022 
00023 uint8_t OSS = OSS_3;           // maximum pressure resolution
00024 
00025 //Set up I2C, (SDA,SCL)
00026 I2C i2c(I2C_SDA, I2C_SCL);
00027     
00028 // These are constants used to calculate the temperature and pressure from the BMP-180 sensor
00029 int16_t ac1, ac2, ac3, b1, b2, mb, mc, md, b5;  
00030 uint16_t ac4, ac5, ac6;
00031 
00032 class BMP180 {
00033  
00034     protected:
00035  
00036     public:
00037   //===================================================================================================================
00038 //====== Set of useful function to access pressure and temperature data
00039 //===================================================================================================================
00040 
00041     void writeByte(uint8_t address, uint8_t subAddress, uint8_t data)
00042 {
00043    char data_write[2];
00044    data_write[0] = subAddress;
00045    data_write[1] = data;
00046    i2c.write(address, data_write, 2, 0);
00047 }
00048 
00049     char readByte(uint8_t address, uint8_t subAddress)
00050 {
00051     char data[1]; // `data` will store the register data     
00052     char data_write[1];
00053     data_write[0] = subAddress;
00054     i2c.write(address, data_write, 1, 1); // no stop
00055     i2c.read(address, data, 1, 0); 
00056     return data[0]; 
00057 }
00058 
00059     void readBytes(uint8_t address, uint8_t subAddress, uint8_t count, uint8_t * dest)
00060 {     
00061     char data[14];
00062     char data_write[1];
00063     data_write[0] = subAddress;
00064     i2c.write(address, data_write, 1, 1); // no stop
00065     i2c.read(address, data, count, 0); 
00066     for(int ii = 0; ii < count; ii++) {
00067      dest[ii] = data[ii];
00068     }
00069 } 
00070  
00071 
00072 // Stores all of the BMP180's calibration values into global variables
00073 // Calibration values are required to calculate temp and pressure
00074 // This function should be called at the beginning of the program
00075 // These BMP-180 functions were adapted from Jim Lindblom of SparkFun Electronics
00076 void BMP180Calibration()
00077 {
00078   ac1 = readByte(BMP180_ADDRESS, 0xAA) << 8 | readByte(BMP180_ADDRESS, 0xAB);
00079   ac2 = readByte(BMP180_ADDRESS, 0xAC) << 8 | readByte(BMP180_ADDRESS, 0xAD);
00080   ac3 = readByte(BMP180_ADDRESS, 0xAE) << 8 | readByte(BMP180_ADDRESS, 0xAF);
00081   ac4 = readByte(BMP180_ADDRESS, 0xB0) << 8 | readByte(BMP180_ADDRESS, 0xB1);
00082   ac5 = readByte(BMP180_ADDRESS, 0xB2) << 8 | readByte(BMP180_ADDRESS, 0xB3);
00083   ac6 = readByte(BMP180_ADDRESS, 0xB4) << 8 | readByte(BMP180_ADDRESS, 0xB5);
00084   b1  = readByte(BMP180_ADDRESS, 0xB6) << 8 | readByte(BMP180_ADDRESS, 0xB7);
00085   b2  = readByte(BMP180_ADDRESS, 0xB8) << 8 | readByte(BMP180_ADDRESS, 0xB9);
00086   mb  = readByte(BMP180_ADDRESS, 0xBA) << 8 | readByte(BMP180_ADDRESS, 0xBB);
00087   mc  = readByte(BMP180_ADDRESS, 0xBC) << 8 | readByte(BMP180_ADDRESS, 0xBD);
00088   md  = readByte(BMP180_ADDRESS, 0xBE) << 8 | readByte(BMP180_ADDRESS, 0xBF);
00089 }
00090 
00091   // Temperature returned will be in units of 0.1 deg C
00092   int16_t BMP180GetTemperature()
00093   {
00094   int16_t ut = 0;
00095   writeByte(BMP180_ADDRESS, 0xF4, 0x2E); // start temperature measurement
00096   wait(0.005);
00097   uint8_t rawData[2] = {0, 0};
00098   readBytes(BMP180_ADDRESS, 0xF6, 2, &rawData[0]); // read raw temperature measurement
00099   ut = (((int16_t) rawData[0] << 8) | rawData[1]);
00100  
00101  long x1, x2;
00102   
00103   x1 = (((long)ut - (long)ac6)*(long)ac5) >> 15;
00104   x2 = ((long)mc << 11)/(x1 + md);
00105   b5 = x1 + x2;
00106 
00107   return  ((b5 + 8)>>4);  
00108 }
00109 
00110 // Calculate pressure read calibration values  
00111 // b5 is also required so BMP180GetTemperature() must be called first.
00112 // Value returned will be pressure in units of Pa.
00113 long BMP180GetPressure()
00114 {
00115   long up = 0;
00116   writeByte(BMP180_ADDRESS, 0xF4, 0x34 | OSS << 6); // Configure pressure measurement for highest resolution
00117   wait((5.0f + 8.0f*3.0f)/1000.0f); // delay 5 ms at lowest resolution, 29 ms at highest
00118   uint8_t rawData[3] = {0, 0, 0};
00119   readBytes(BMP180_ADDRESS, 0xF6, 3, &rawData[0]); // read raw pressure measurement of 19 bits
00120   up = (((long) rawData[0] << 16) | ((long)rawData[1] << 8) | rawData[2]) >> (8 - OSS);
00121 
00122   long x1, x2, x3, b3, b6, p;
00123   unsigned long b4, b7;
00124   
00125   b6 = b5 - 4000;
00126   // Calculate B3
00127   x1 = (b2 * (b6 * b6)>>12)>>11;
00128   x2 = (ac2 * b6)>>11;
00129   x3 = x1 + x2;
00130   b3 = (((((long)ac1)*4 + x3)<<OSS) + 2)>>2;
00131   
00132   // Calculate B4
00133   x1 = (ac3 * b6)>>13;
00134   x2 = (b1 * ((b6 * b6)>>12))>>16;
00135   x3 = ((x1 + x2) + 2)>>2;
00136   b4 = (ac4 * (unsigned long)(x3 + 32768))>>15;
00137   
00138   b7 = ((unsigned long)(up - b3) * (50000>>OSS));
00139   if (b7 < 0x80000000)
00140     p = (b7<<1)/b4;
00141   else
00142     p = (b7/b4)<<1;
00143     
00144   x1 = (p>>8) * (p>>8);
00145   x1 = (x1 * 3038)>>16;
00146   x2 = (-7357 * p)>>16;
00147   p += (x1 + x2 + 3791)>>4;
00148   
00149   return p;
00150 }      
00151 
00152  
00153  
00154   };
00155 #endif