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@0:06dc60296e6e, 2014-07-03 (annotated)
- Committer:
- onehorse
- Date:
- Thu Jul 03 20:05:55 2014 +0000
- Revision:
- 0:06dc60296e6e
Initial commit
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
onehorse | 0:06dc60296e6e | 1 | #ifndef BMP180_H |
onehorse | 0:06dc60296e6e | 2 | #define BMP180_H |
onehorse | 0:06dc60296e6e | 3 | |
onehorse | 0:06dc60296e6e | 4 | #include "mbed.h" |
onehorse | 0:06dc60296e6e | 5 | |
onehorse | 0:06dc60296e6e | 6 | #define BMP180_ADDRESS 0x77<<1 // I2C address of BMP180, eight bit address on mbed |
onehorse | 0:06dc60296e6e | 7 | #define BMP180_WHO_AM_I 0xD0 // WHO_AM_I id of BMP180, should return 0x55 |
onehorse | 0:06dc60296e6e | 8 | #define BMP180_RESET 0xE0 |
onehorse | 0:06dc60296e6e | 9 | #define BMP180_CONTROL 0xF4 |
onehorse | 0:06dc60296e6e | 10 | #define BMP180_OUT_MSB 0xF6 |
onehorse | 0:06dc60296e6e | 11 | #define BMP180_OUT_LSB 0xF7 |
onehorse | 0:06dc60296e6e | 12 | #define BMP180_OUT_XLSB 0xF8 |
onehorse | 0:06dc60296e6e | 13 | |
onehorse | 0:06dc60296e6e | 14 | // Set initial input parameters |
onehorse | 0:06dc60296e6e | 15 | |
onehorse | 0:06dc60296e6e | 16 | enum OSS { // BMP-085 sampling rate |
onehorse | 0:06dc60296e6e | 17 | OSS_0 = 0, // 4.5 ms conversion time |
onehorse | 0:06dc60296e6e | 18 | OSS_1, // 7.5 |
onehorse | 0:06dc60296e6e | 19 | OSS_2, // 13.5 |
onehorse | 0:06dc60296e6e | 20 | OSS_3 // 25.5 |
onehorse | 0:06dc60296e6e | 21 | }; |
onehorse | 0:06dc60296e6e | 22 | |
onehorse | 0:06dc60296e6e | 23 | uint8_t OSS = OSS_3; // maximum pressure resolution |
onehorse | 0:06dc60296e6e | 24 | |
onehorse | 0:06dc60296e6e | 25 | //Set up I2C, (SDA,SCL) |
onehorse | 0:06dc60296e6e | 26 | I2C i2c(I2C_SDA, I2C_SCL); |
onehorse | 0:06dc60296e6e | 27 | |
onehorse | 0:06dc60296e6e | 28 | // These are constants used to calculate the temperature and pressure from the BMP-180 sensor |
onehorse | 0:06dc60296e6e | 29 | int16_t ac1, ac2, ac3, b1, b2, mb, mc, md, b5; |
onehorse | 0:06dc60296e6e | 30 | uint16_t ac4, ac5, ac6; |
onehorse | 0:06dc60296e6e | 31 | |
onehorse | 0:06dc60296e6e | 32 | class BMP180 { |
onehorse | 0:06dc60296e6e | 33 | |
onehorse | 0:06dc60296e6e | 34 | protected: |
onehorse | 0:06dc60296e6e | 35 | |
onehorse | 0:06dc60296e6e | 36 | public: |
onehorse | 0:06dc60296e6e | 37 | //=================================================================================================================== |
onehorse | 0:06dc60296e6e | 38 | //====== Set of useful function to access pressure and temperature data |
onehorse | 0:06dc60296e6e | 39 | //=================================================================================================================== |
onehorse | 0:06dc60296e6e | 40 | |
onehorse | 0:06dc60296e6e | 41 | void writeByte(uint8_t address, uint8_t subAddress, uint8_t data) |
onehorse | 0:06dc60296e6e | 42 | { |
onehorse | 0:06dc60296e6e | 43 | char data_write[2]; |
onehorse | 0:06dc60296e6e | 44 | data_write[0] = subAddress; |
onehorse | 0:06dc60296e6e | 45 | data_write[1] = data; |
onehorse | 0:06dc60296e6e | 46 | i2c.write(address, data_write, 2, 0); |
onehorse | 0:06dc60296e6e | 47 | } |
onehorse | 0:06dc60296e6e | 48 | |
onehorse | 0:06dc60296e6e | 49 | char readByte(uint8_t address, uint8_t subAddress) |
onehorse | 0:06dc60296e6e | 50 | { |
onehorse | 0:06dc60296e6e | 51 | char data[1]; // `data` will store the register data |
onehorse | 0:06dc60296e6e | 52 | char data_write[1]; |
onehorse | 0:06dc60296e6e | 53 | data_write[0] = subAddress; |
onehorse | 0:06dc60296e6e | 54 | i2c.write(address, data_write, 1, 1); // no stop |
onehorse | 0:06dc60296e6e | 55 | i2c.read(address, data, 1, 0); |
onehorse | 0:06dc60296e6e | 56 | return data[0]; |
onehorse | 0:06dc60296e6e | 57 | } |
onehorse | 0:06dc60296e6e | 58 | |
onehorse | 0:06dc60296e6e | 59 | void readBytes(uint8_t address, uint8_t subAddress, uint8_t count, uint8_t * dest) |
onehorse | 0:06dc60296e6e | 60 | { |
onehorse | 0:06dc60296e6e | 61 | char data[14]; |
onehorse | 0:06dc60296e6e | 62 | char data_write[1]; |
onehorse | 0:06dc60296e6e | 63 | data_write[0] = subAddress; |
onehorse | 0:06dc60296e6e | 64 | i2c.write(address, data_write, 1, 1); // no stop |
onehorse | 0:06dc60296e6e | 65 | i2c.read(address, data, count, 0); |
onehorse | 0:06dc60296e6e | 66 | for(int ii = 0; ii < count; ii++) { |
onehorse | 0:06dc60296e6e | 67 | dest[ii] = data[ii]; |
onehorse | 0:06dc60296e6e | 68 | } |
onehorse | 0:06dc60296e6e | 69 | } |
onehorse | 0:06dc60296e6e | 70 | |
onehorse | 0:06dc60296e6e | 71 | |
onehorse | 0:06dc60296e6e | 72 | // Stores all of the BMP180's calibration values into global variables |
onehorse | 0:06dc60296e6e | 73 | // Calibration values are required to calculate temp and pressure |
onehorse | 0:06dc60296e6e | 74 | // This function should be called at the beginning of the program |
onehorse | 0:06dc60296e6e | 75 | // These BMP-180 functions were adapted from Jim Lindblom of SparkFun Electronics |
onehorse | 0:06dc60296e6e | 76 | void BMP180Calibration() |
onehorse | 0:06dc60296e6e | 77 | { |
onehorse | 0:06dc60296e6e | 78 | ac1 = readByte(BMP180_ADDRESS, 0xAA) << 8 | readByte(BMP180_ADDRESS, 0xAB); |
onehorse | 0:06dc60296e6e | 79 | ac2 = readByte(BMP180_ADDRESS, 0xAC) << 8 | readByte(BMP180_ADDRESS, 0xAD); |
onehorse | 0:06dc60296e6e | 80 | ac3 = readByte(BMP180_ADDRESS, 0xAE) << 8 | readByte(BMP180_ADDRESS, 0xAF); |
onehorse | 0:06dc60296e6e | 81 | ac4 = readByte(BMP180_ADDRESS, 0xB0) << 8 | readByte(BMP180_ADDRESS, 0xB1); |
onehorse | 0:06dc60296e6e | 82 | ac5 = readByte(BMP180_ADDRESS, 0xB2) << 8 | readByte(BMP180_ADDRESS, 0xB3); |
onehorse | 0:06dc60296e6e | 83 | ac6 = readByte(BMP180_ADDRESS, 0xB4) << 8 | readByte(BMP180_ADDRESS, 0xB5); |
onehorse | 0:06dc60296e6e | 84 | b1 = readByte(BMP180_ADDRESS, 0xB6) << 8 | readByte(BMP180_ADDRESS, 0xB7); |
onehorse | 0:06dc60296e6e | 85 | b2 = readByte(BMP180_ADDRESS, 0xB8) << 8 | readByte(BMP180_ADDRESS, 0xB9); |
onehorse | 0:06dc60296e6e | 86 | mb = readByte(BMP180_ADDRESS, 0xBA) << 8 | readByte(BMP180_ADDRESS, 0xBB); |
onehorse | 0:06dc60296e6e | 87 | mc = readByte(BMP180_ADDRESS, 0xBC) << 8 | readByte(BMP180_ADDRESS, 0xBD); |
onehorse | 0:06dc60296e6e | 88 | md = readByte(BMP180_ADDRESS, 0xBE) << 8 | readByte(BMP180_ADDRESS, 0xBF); |
onehorse | 0:06dc60296e6e | 89 | } |
onehorse | 0:06dc60296e6e | 90 | |
onehorse | 0:06dc60296e6e | 91 | // Temperature returned will be in units of 0.1 deg C |
onehorse | 0:06dc60296e6e | 92 | int16_t BMP180GetTemperature() |
onehorse | 0:06dc60296e6e | 93 | { |
onehorse | 0:06dc60296e6e | 94 | int16_t ut = 0; |
onehorse | 0:06dc60296e6e | 95 | writeByte(BMP180_ADDRESS, 0xF4, 0x2E); // start temperature measurement |
onehorse | 0:06dc60296e6e | 96 | wait(0.005); |
onehorse | 0:06dc60296e6e | 97 | uint8_t rawData[2] = {0, 0}; |
onehorse | 0:06dc60296e6e | 98 | readBytes(BMP180_ADDRESS, 0xF6, 2, &rawData[0]); // read raw temperature measurement |
onehorse | 0:06dc60296e6e | 99 | ut = (((int16_t) rawData[0] << 8) | rawData[1]); |
onehorse | 0:06dc60296e6e | 100 | |
onehorse | 0:06dc60296e6e | 101 | long x1, x2; |
onehorse | 0:06dc60296e6e | 102 | |
onehorse | 0:06dc60296e6e | 103 | x1 = (((long)ut - (long)ac6)*(long)ac5) >> 15; |
onehorse | 0:06dc60296e6e | 104 | x2 = ((long)mc << 11)/(x1 + md); |
onehorse | 0:06dc60296e6e | 105 | b5 = x1 + x2; |
onehorse | 0:06dc60296e6e | 106 | |
onehorse | 0:06dc60296e6e | 107 | return ((b5 + 8)>>4); |
onehorse | 0:06dc60296e6e | 108 | } |
onehorse | 0:06dc60296e6e | 109 | |
onehorse | 0:06dc60296e6e | 110 | // Calculate pressure read calibration values |
onehorse | 0:06dc60296e6e | 111 | // b5 is also required so BMP180GetTemperature() must be called first. |
onehorse | 0:06dc60296e6e | 112 | // Value returned will be pressure in units of Pa. |
onehorse | 0:06dc60296e6e | 113 | long BMP180GetPressure() |
onehorse | 0:06dc60296e6e | 114 | { |
onehorse | 0:06dc60296e6e | 115 | long up = 0; |
onehorse | 0:06dc60296e6e | 116 | writeByte(BMP180_ADDRESS, 0xF4, 0x34 | OSS << 6); // Configure pressure measurement for highest resolution |
onehorse | 0:06dc60296e6e | 117 | wait((5.0f + 8.0f*3.0f)/1000.0f); // delay 5 ms at lowest resolution, 29 ms at highest |
onehorse | 0:06dc60296e6e | 118 | uint8_t rawData[3] = {0, 0, 0}; |
onehorse | 0:06dc60296e6e | 119 | readBytes(BMP180_ADDRESS, 0xF6, 3, &rawData[0]); // read raw pressure measurement of 19 bits |
onehorse | 0:06dc60296e6e | 120 | up = (((long) rawData[0] << 16) | ((long)rawData[1] << 8) | rawData[2]) >> (8 - OSS); |
onehorse | 0:06dc60296e6e | 121 | |
onehorse | 0:06dc60296e6e | 122 | long x1, x2, x3, b3, b6, p; |
onehorse | 0:06dc60296e6e | 123 | unsigned long b4, b7; |
onehorse | 0:06dc60296e6e | 124 | |
onehorse | 0:06dc60296e6e | 125 | b6 = b5 - 4000; |
onehorse | 0:06dc60296e6e | 126 | // Calculate B3 |
onehorse | 0:06dc60296e6e | 127 | x1 = (b2 * (b6 * b6)>>12)>>11; |
onehorse | 0:06dc60296e6e | 128 | x2 = (ac2 * b6)>>11; |
onehorse | 0:06dc60296e6e | 129 | x3 = x1 + x2; |
onehorse | 0:06dc60296e6e | 130 | b3 = (((((long)ac1)*4 + x3)<<OSS) + 2)>>2; |
onehorse | 0:06dc60296e6e | 131 | |
onehorse | 0:06dc60296e6e | 132 | // Calculate B4 |
onehorse | 0:06dc60296e6e | 133 | x1 = (ac3 * b6)>>13; |
onehorse | 0:06dc60296e6e | 134 | x2 = (b1 * ((b6 * b6)>>12))>>16; |
onehorse | 0:06dc60296e6e | 135 | x3 = ((x1 + x2) + 2)>>2; |
onehorse | 0:06dc60296e6e | 136 | b4 = (ac4 * (unsigned long)(x3 + 32768))>>15; |
onehorse | 0:06dc60296e6e | 137 | |
onehorse | 0:06dc60296e6e | 138 | b7 = ((unsigned long)(up - b3) * (50000>>OSS)); |
onehorse | 0:06dc60296e6e | 139 | if (b7 < 0x80000000) |
onehorse | 0:06dc60296e6e | 140 | p = (b7<<1)/b4; |
onehorse | 0:06dc60296e6e | 141 | else |
onehorse | 0:06dc60296e6e | 142 | p = (b7/b4)<<1; |
onehorse | 0:06dc60296e6e | 143 | |
onehorse | 0:06dc60296e6e | 144 | x1 = (p>>8) * (p>>8); |
onehorse | 0:06dc60296e6e | 145 | x1 = (x1 * 3038)>>16; |
onehorse | 0:06dc60296e6e | 146 | x2 = (-7357 * p)>>16; |
onehorse | 0:06dc60296e6e | 147 | p += (x1 + x2 + 3791)>>4; |
onehorse | 0:06dc60296e6e | 148 | |
onehorse | 0:06dc60296e6e | 149 | return p; |
onehorse | 0:06dc60296e6e | 150 | } |
onehorse | 0:06dc60296e6e | 151 | |
onehorse | 0:06dc60296e6e | 152 | |
onehorse | 0:06dc60296e6e | 153 | |
onehorse | 0:06dc60296e6e | 154 | }; |
onehorse | 0:06dc60296e6e | 155 | #endif |