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.
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
Generated on Fri Jul 15 2022 23:49:39 by 1.7.2