bring up code for the Bosch barometer and thermometer BMP085. This code is forked from http://mbed.org/users/tkreyche/notebook/bmp085-pressure-sensor/ but with a lot more comments and links to references. The extraction of the altitude via 2 methods is also implemented. Overall temperature seems way off (but implementation is correct). Altitude is off too (but implementation is correct).
main.cpp@0:184eb17ff158, 2012-12-28 (annotated)
- Committer:
- Rom
- Date:
- Fri Dec 28 06:09:46 2012 +0000
- Revision:
- 0:184eb17ff158
Bring up program of the Bosch Barometer + temperature. Absolute values are wrong despite correct implementation.
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
Rom | 0:184eb17ff158 | 1 | #include "mbed.h" |
Rom | 0:184eb17ff158 | 2 | |
Rom | 0:184eb17ff158 | 3 | /* sample code for the barometer BMP085 as provided on the breakout board from sparkfun. |
Rom | 0:184eb17ff158 | 4 | Pull up resistors for I2C are already provided (aka already on the board). |
Rom | 0:184eb17ff158 | 5 | Link to sparkfun board: https://www.sparkfun.com/products/11282? |
Rom | 0:184eb17ff158 | 6 | |
Rom | 0:184eb17ff158 | 7 | Datasheet of barometer: http://dlnmh9ip6v2uc.cloudfront.net/datasheets/Sensors/Pressure/BST-BMP085-DS000-06.pdf |
Rom | 0:184eb17ff158 | 8 | |
Rom | 0:184eb17ff158 | 9 | Comments: |
Rom | 0:184eb17ff158 | 10 | - pressure values returned by the moving average seems believable (1090 Hecto Pascal on 12/18/2012) |
Rom | 0:184eb17ff158 | 11 | - Temperature seems to oscillate between 365 and 87 and seems totally wrong. |
Rom | 0:184eb17ff158 | 12 | - Altitude is off (obviously fluctates with weather) but roughly speaking |
Rom | 0:184eb17ff158 | 13 | indicates -800m when altitude should be 0m |
Rom | 0:184eb17ff158 | 14 | |
Rom | 0:184eb17ff158 | 15 | Example of output in the terminal: |
Rom | 0:184eb17ff158 | 16 | |
Rom | 0:184eb17ff158 | 17 | Temperature: 87 (raw value (uncomp): 61184) |
Rom | 0:184eb17ff158 | 18 | Pressure (Pa): 106626 (raw: 249856) Mov Avg: 62353 |
Rom | 0:184eb17ff158 | 19 | altitude is (m): -432.270721 |
Rom | 0:184eb17ff158 | 20 | wikipedia altitude (m): -432.061523 |
Rom | 0:184eb17ff158 | 21 | |
Rom | 0:184eb17ff158 | 22 | Temperature: 365 (raw value (uncomp): 62464) |
Rom | 0:184eb17ff158 | 23 | Pressure (Pa): 109312 (raw: 244736) Mov Avg: 67558 |
Rom | 0:184eb17ff158 | 24 | altitude is (m): -644.688416 |
Rom | 0:184eb17ff158 | 25 | wikipedia altitude (m): -644.382446 |
Rom | 0:184eb17ff158 | 26 | |
Rom | 0:184eb17ff158 | 27 | Temperature: 365 (raw value (uncomp): 62464) |
Rom | 0:184eb17ff158 | 28 | Pressure (Pa): 111417 (raw: 249856) Mov Avg: 72864 |
Rom | 0:184eb17ff158 | 29 | altitude is (m): -808.229309 |
Rom | 0:184eb17ff158 | 30 | wikipedia altitude (m): -807.841614 |
Rom | 0:184eb17ff158 | 31 | |
Rom | 0:184eb17ff158 | 32 | */ |
Rom | 0:184eb17ff158 | 33 | |
Rom | 0:184eb17ff158 | 34 | #define EE 22 //The EEPROM has 176bits of calibration data (176/8 = 22 Bytes) |
Rom | 0:184eb17ff158 | 35 | #define BMP085ADDR 0xEF // I2C address of the barometer |
Rom | 0:184eb17ff158 | 36 | |
Rom | 0:184eb17ff158 | 37 | //Calibration variables |
Rom | 0:184eb17ff158 | 38 | long b5; |
Rom | 0:184eb17ff158 | 39 | short ac1; |
Rom | 0:184eb17ff158 | 40 | short ac2; |
Rom | 0:184eb17ff158 | 41 | short ac3; |
Rom | 0:184eb17ff158 | 42 | unsigned short ac4; |
Rom | 0:184eb17ff158 | 43 | unsigned short ac5; |
Rom | 0:184eb17ff158 | 44 | unsigned short ac6; |
Rom | 0:184eb17ff158 | 45 | short b1; |
Rom | 0:184eb17ff158 | 46 | short b2; |
Rom | 0:184eb17ff158 | 47 | short mb; |
Rom | 0:184eb17ff158 | 48 | short mc; |
Rom | 0:184eb17ff158 | 49 | short md; |
Rom | 0:184eb17ff158 | 50 | |
Rom | 0:184eb17ff158 | 51 | // Function to compute the human interpretable values |
Rom | 0:184eb17ff158 | 52 | int calcPress(int upp, int oversampling_setting); |
Rom | 0:184eb17ff158 | 53 | int calcTemp(int ut); |
Rom | 0:184eb17ff158 | 54 | float calcAltitude(int pressure); |
Rom | 0:184eb17ff158 | 55 | float calcWikipediaAltitude(int pressure); |
Rom | 0:184eb17ff158 | 56 | |
Rom | 0:184eb17ff158 | 57 | //Moving average variables |
Rom | 0:184eb17ff158 | 58 | #define COEFZ 21 // 21 bits used for computing the moving average |
Rom | 0:184eb17ff158 | 59 | static int k[COEFZ]; // an array used for the moving average |
Rom | 0:184eb17ff158 | 60 | static int movAvgIntZ (int input); |
Rom | 0:184eb17ff158 | 61 | |
Rom | 0:184eb17ff158 | 62 | //address of commands |
Rom | 0:184eb17ff158 | 63 | #define CMD_READ_VALUE 0xF6 |
Rom | 0:184eb17ff158 | 64 | #define CMD_READ_CALIBRATION 0xAA |
Rom | 0:184eb17ff158 | 65 | |
Rom | 0:184eb17ff158 | 66 | #define OVERSAMPLING_ULTRA_LOW_POWER 0 |
Rom | 0:184eb17ff158 | 67 | #define OVERSAMPLING_STANDARD 1 |
Rom | 0:184eb17ff158 | 68 | #define OVERSAMPLING_HIGH_RESOLUTION 2 |
Rom | 0:184eb17ff158 | 69 | #define OVERSAMPLING_ULTRA_HIGH_RESOLUTION 3 |
Rom | 0:184eb17ff158 | 70 | |
Rom | 0:184eb17ff158 | 71 | const float ALTITUDE_EXPONENT = 1/5.255; |
Rom | 0:184eb17ff158 | 72 | const float ALTITUDE_PRESSURE_REFERENCE = 101325.0; // In Pa |
Rom | 0:184eb17ff158 | 73 | const float ALTITUDE_COEFF = 44330.0; |
Rom | 0:184eb17ff158 | 74 | |
Rom | 0:184eb17ff158 | 75 | const float TEMPERATURE_LAPSE_RATE = 0.0065; // in K/m |
Rom | 0:184eb17ff158 | 76 | const float SEA_LEVEL_STANDARD_TEMPERATURE = 288.15; // in Kelvins |
Rom | 0:184eb17ff158 | 77 | const float GRAVITATIONAL_ACCELERATION = 9.81; // in m/(s*s) |
Rom | 0:184eb17ff158 | 78 | const float MOLAR_MASS_AIR = 0.0289644; // in Kg/mol |
Rom | 0:184eb17ff158 | 79 | const float R = 8.31447; // in J/(mol*K) universal gas constant |
Rom | 0:184eb17ff158 | 80 | |
Rom | 0:184eb17ff158 | 81 | const float WIKIPEDIA_EXPONENT = GRAVITATIONAL_ACCELERATION * MOLAR_MASS_AIR/ (R * TEMPERATURE_LAPSE_RATE); |
Rom | 0:184eb17ff158 | 82 | |
Rom | 0:184eb17ff158 | 83 | |
Rom | 0:184eb17ff158 | 84 | I2C i2c(p28, p27); // sda, scl |
Rom | 0:184eb17ff158 | 85 | InterruptIn dr(p26); // EOC, conversion notification |
Rom | 0:184eb17ff158 | 86 | // Note that XCLR is floating = not connected (power for analog portion?) |
Rom | 0:184eb17ff158 | 87 | |
Rom | 0:184eb17ff158 | 88 | uint32_t drFlag; |
Rom | 0:184eb17ff158 | 89 | |
Rom | 0:184eb17ff158 | 90 | void cvt(); // Send I2C command to start pressure conversion (?) |
Rom | 0:184eb17ff158 | 91 | void drSub(); // set a flag to one. Pretty poorly written code IMO. |
Rom | 0:184eb17ff158 | 92 | |
Rom | 0:184eb17ff158 | 93 | Serial pc(USBTX, USBRX); // tx, rx |
Rom | 0:184eb17ff158 | 94 | |
Rom | 0:184eb17ff158 | 95 | int main() { |
Rom | 0:184eb17ff158 | 96 | |
Rom | 0:184eb17ff158 | 97 | // let hardware settle |
Rom | 0:184eb17ff158 | 98 | wait(1); |
Rom | 0:184eb17ff158 | 99 | |
Rom | 0:184eb17ff158 | 100 | ///////////////////////////////////////////////// |
Rom | 0:184eb17ff158 | 101 | // set up timer to trigger pressure conversion |
Rom | 0:184eb17ff158 | 102 | ///////////////////////////////////////////////// |
Rom | 0:184eb17ff158 | 103 | Ticker convert; |
Rom | 0:184eb17ff158 | 104 | convert.attach_us(&cvt, 50000); // 50 ms, 20 Hz //Pointer to a void function |
Rom | 0:184eb17ff158 | 105 | |
Rom | 0:184eb17ff158 | 106 | ///////////////////////////////////////////////// |
Rom | 0:184eb17ff158 | 107 | // set up data ready interrupts |
Rom | 0:184eb17ff158 | 108 | ///////////////////////////////////////////////// |
Rom | 0:184eb17ff158 | 109 | // set up interrupts |
Rom | 0:184eb17ff158 | 110 | __disable_irq(); |
Rom | 0:184eb17ff158 | 111 | // ADC data ready |
Rom | 0:184eb17ff158 | 112 | drFlag = 0; |
Rom | 0:184eb17ff158 | 113 | dr.mode(PullDown); |
Rom | 0:184eb17ff158 | 114 | dr.rise(&drSub); |
Rom | 0:184eb17ff158 | 115 | |
Rom | 0:184eb17ff158 | 116 | ///////////////////////////////////////////////// |
Rom | 0:184eb17ff158 | 117 | // set up i2c |
Rom | 0:184eb17ff158 | 118 | ///////////////////////////////////////////////// |
Rom | 0:184eb17ff158 | 119 | char addr = BMP085ADDR; // define the I2C Address |
Rom | 0:184eb17ff158 | 120 | int oversampling_setting = OVERSAMPLING_HIGH_RESOLUTION; // called oss in the documentation |
Rom | 0:184eb17ff158 | 121 | // read page 12 of doc. 3 is ultra high precision and it requires a lot of time for the device to do the conversion |
Rom | 0:184eb17ff158 | 122 | char rReg[3] = {0,0,0}; // read registers for I2C |
Rom | 0:184eb17ff158 | 123 | char wReg[2] = {0,0}; // write registers for I2C |
Rom | 0:184eb17ff158 | 124 | char cmd = 0x00; |
Rom | 0:184eb17ff158 | 125 | |
Rom | 0:184eb17ff158 | 126 | ///////////////////////////////////////////////// |
Rom | 0:184eb17ff158 | 127 | // get EEPROM calibration parameters |
Rom | 0:184eb17ff158 | 128 | ///////////////////////////////////////////////// |
Rom | 0:184eb17ff158 | 129 | |
Rom | 0:184eb17ff158 | 130 | char data[EE]; |
Rom | 0:184eb17ff158 | 131 | cmd = CMD_READ_CALIBRATION; // EEPROM calibration command |
Rom | 0:184eb17ff158 | 132 | |
Rom | 0:184eb17ff158 | 133 | for (int i = 0; i < EE; i++) { // read over the 22 registers of the EEPROM |
Rom | 0:184eb17ff158 | 134 | i2c.write(addr, &cmd, 1); |
Rom | 0:184eb17ff158 | 135 | i2c.read(addr, rReg, 1); // rReg is array? of size 3. We only read the 1st register??? |
Rom | 0:184eb17ff158 | 136 | data[i] = rReg[0]; |
Rom | 0:184eb17ff158 | 137 | cmd += 1; |
Rom | 0:184eb17ff158 | 138 | wait_ms(10); |
Rom | 0:184eb17ff158 | 139 | } |
Rom | 0:184eb17ff158 | 140 | |
Rom | 0:184eb17ff158 | 141 | // parameters AC1-AC6 |
Rom | 0:184eb17ff158 | 142 | //The calibration is partioned in 11 words of 16 bits, each of them representing a coefficient |
Rom | 0:184eb17ff158 | 143 | ac1 = (data[0] <<8) | data[1]; // AC1(0xAA, 0xAB)... and so on |
Rom | 0:184eb17ff158 | 144 | ac2 = (data[2] <<8) | data[3]; |
Rom | 0:184eb17ff158 | 145 | ac3 = (data[4] <<8) | data[5]; |
Rom | 0:184eb17ff158 | 146 | ac4 = (data[6] <<8) | data[7]; |
Rom | 0:184eb17ff158 | 147 | ac5 = (data[8] <<8) | data[9]; |
Rom | 0:184eb17ff158 | 148 | ac6 = (data[10] <<8) | data[11]; |
Rom | 0:184eb17ff158 | 149 | // parameters B1,B2 |
Rom | 0:184eb17ff158 | 150 | b1 = (data[12] <<8) | data[13]; |
Rom | 0:184eb17ff158 | 151 | b2 = (data[14] <<8) | data[15]; |
Rom | 0:184eb17ff158 | 152 | // parameters MB,MC,MD |
Rom | 0:184eb17ff158 | 153 | mb = (data[16] <<8) | data[17]; |
Rom | 0:184eb17ff158 | 154 | mc = (data[18] <<8) | data[19]; |
Rom | 0:184eb17ff158 | 155 | md = (data[20] <<8) | data[21]; |
Rom | 0:184eb17ff158 | 156 | |
Rom | 0:184eb17ff158 | 157 | // ready to start sampling loop |
Rom | 0:184eb17ff158 | 158 | __enable_irq(); |
Rom | 0:184eb17ff158 | 159 | |
Rom | 0:184eb17ff158 | 160 | // END OF INITIALIZATION |
Rom | 0:184eb17ff158 | 161 | |
Rom | 0:184eb17ff158 | 162 | ///////////////////////////////////////////////// |
Rom | 0:184eb17ff158 | 163 | // main |
Rom | 0:184eb17ff158 | 164 | ///////////////////////////////////////////////// |
Rom | 0:184eb17ff158 | 165 | pc.printf("Starting barometer main()!!\n\r"); |
Rom | 0:184eb17ff158 | 166 | while (1) { |
Rom | 0:184eb17ff158 | 167 | if (drFlag == 1) { |
Rom | 0:184eb17ff158 | 168 | // Documentation recommend the following chronology: |
Rom | 0:184eb17ff158 | 169 | // read uncomp temp, read uncomp pressure, compute true temp, |
Rom | 0:184eb17ff158 | 170 | // compute true pressure |
Rom | 0:184eb17ff158 | 171 | |
Rom | 0:184eb17ff158 | 172 | ///////////////////////////////////////////////// |
Rom | 0:184eb17ff158 | 173 | // uncomp temperature |
Rom | 0:184eb17ff158 | 174 | ///////////////////////////////////////////////// |
Rom | 0:184eb17ff158 | 175 | wReg[0] = 0xF4; |
Rom | 0:184eb17ff158 | 176 | wReg[1] = 0x2E; |
Rom | 0:184eb17ff158 | 177 | i2c.write(addr, wReg, 2); // write 0x2E in reg 0XF4 |
Rom | 0:184eb17ff158 | 178 | wait_ms(4.5); |
Rom | 0:184eb17ff158 | 179 | cmd = CMD_READ_VALUE; // 0xF6 |
Rom | 0:184eb17ff158 | 180 | i2c.write(addr, &cmd, 1); // set pointer on 0xF6 before reading it? |
Rom | 0:184eb17ff158 | 181 | i2c.read(addr, rReg, 2); // read 0xF6 (MSB) and 0xF7 (LSB)// rReg is 3 long though |
Rom | 0:184eb17ff158 | 182 | int uncomp_temperature = (rReg[0] << 8) | rReg[1]; // UT = MSB << 8 + LSB |
Rom | 0:184eb17ff158 | 183 | |
Rom | 0:184eb17ff158 | 184 | ///////////////////////////////////////////////// |
Rom | 0:184eb17ff158 | 185 | // uncomp pressure |
Rom | 0:184eb17ff158 | 186 | ///////////////////////////////////////////////// |
Rom | 0:184eb17ff158 | 187 | |
Rom | 0:184eb17ff158 | 188 | //write 0x34 + (oss<<6) into reg 0xF4, wait (waiting time not specified in doc) |
Rom | 0:184eb17ff158 | 189 | int uncomp_pressure_cmd = 0x34 + (oversampling_setting<<6); |
Rom | 0:184eb17ff158 | 190 | wReg[0] = 0xF4; |
Rom | 0:184eb17ff158 | 191 | wReg[1] = uncomp_pressure_cmd; |
Rom | 0:184eb17ff158 | 192 | i2c.write(addr, wReg, 2); |
Rom | 0:184eb17ff158 | 193 | // See page 12 of documentation |
Rom | 0:184eb17ff158 | 194 | switch (oversampling_setting) { |
Rom | 0:184eb17ff158 | 195 | case OVERSAMPLING_ULTRA_LOW_POWER: |
Rom | 0:184eb17ff158 | 196 | wait_ms(4.5); |
Rom | 0:184eb17ff158 | 197 | break; |
Rom | 0:184eb17ff158 | 198 | case OVERSAMPLING_STANDARD: |
Rom | 0:184eb17ff158 | 199 | wait_ms(7.5); |
Rom | 0:184eb17ff158 | 200 | break; |
Rom | 0:184eb17ff158 | 201 | case OVERSAMPLING_HIGH_RESOLUTION: |
Rom | 0:184eb17ff158 | 202 | wait_ms(13.5); |
Rom | 0:184eb17ff158 | 203 | break; |
Rom | 0:184eb17ff158 | 204 | case OVERSAMPLING_ULTRA_HIGH_RESOLUTION: |
Rom | 0:184eb17ff158 | 205 | wait_ms(25.5); |
Rom | 0:184eb17ff158 | 206 | break; |
Rom | 0:184eb17ff158 | 207 | } |
Rom | 0:184eb17ff158 | 208 | |
Rom | 0:184eb17ff158 | 209 | cmd = CMD_READ_VALUE; // 0xF6 |
Rom | 0:184eb17ff158 | 210 | i2c.write(addr, &cmd, 1); |
Rom | 0:184eb17ff158 | 211 | i2c.read(addr, rReg, 3); // read 0xF6 (MSB), 0xF7 (LSB), 0xF8 (XLSB) |
Rom | 0:184eb17ff158 | 212 | int uncomp_pressure = ((rReg[0] << 16) | (rReg[1] << 8) | rReg[2]) >> (8 - oversampling_setting); |
Rom | 0:184eb17ff158 | 213 | // UP = (MSB<<16 + LSB<<8 + XLSB)>>(8-oss) |
Rom | 0:184eb17ff158 | 214 | |
Rom | 0:184eb17ff158 | 215 | // true temperature |
Rom | 0:184eb17ff158 | 216 | int temperature = calcTemp(uncomp_temperature); |
Rom | 0:184eb17ff158 | 217 | pc.printf("Temperature: %d (raw value (uncomp): %d)\n\r", temperature, uncomp_temperature); |
Rom | 0:184eb17ff158 | 218 | // even though implementation seems right, |
Rom | 0:184eb17ff158 | 219 | //returned value is wrong hostilating between 87 and 365 (i.e. 8.7C and 36.5C) |
Rom | 0:184eb17ff158 | 220 | |
Rom | 0:184eb17ff158 | 221 | // True pressure |
Rom | 0:184eb17ff158 | 222 | int pressure = calcPress(uncomp_pressure, oversampling_setting); |
Rom | 0:184eb17ff158 | 223 | int avg_pressure = movAvgIntZ(pressure); |
Rom | 0:184eb17ff158 | 224 | pc.printf("Pressure (Pa): %d (raw: %d) Mov Avg: %d\n\r", pressure, uncomp_pressure, avg_pressure); |
Rom | 0:184eb17ff158 | 225 | |
Rom | 0:184eb17ff158 | 226 | //Compute an estimate of altitude |
Rom | 0:184eb17ff158 | 227 | // see page 15 of manual |
Rom | 0:184eb17ff158 | 228 | float altitude = calcAltitude(pressure); |
Rom | 0:184eb17ff158 | 229 | pc.printf("altitude is (m): %f\n\r", altitude); // note that the implementation is correct but returns wrong absolute numbers |
Rom | 0:184eb17ff158 | 230 | |
Rom | 0:184eb17ff158 | 231 | float wiki_altitude = calcWikipediaAltitude(pressure); |
Rom | 0:184eb17ff158 | 232 | pc.printf("wikipedia altitude (m): %f\n\r", wiki_altitude); // results are VERY similar and therefore not |
Rom | 0:184eb17ff158 | 233 | |
Rom | 0:184eb17ff158 | 234 | ///////////////////////////////////////////////// |
Rom | 0:184eb17ff158 | 235 | // data ready cleanup tasks |
Rom | 0:184eb17ff158 | 236 | ///////////////////////////////////////////////// |
Rom | 0:184eb17ff158 | 237 | drFlag = 0; // This should stop the while loop... but it does not! |
Rom | 0:184eb17ff158 | 238 | pc.printf("\n\r"); |
Rom | 0:184eb17ff158 | 239 | } |
Rom | 0:184eb17ff158 | 240 | wait(3); // just to make reading in the terminal easier |
Rom | 0:184eb17ff158 | 241 | } //end while |
Rom | 0:184eb17ff158 | 242 | } |
Rom | 0:184eb17ff158 | 243 | |
Rom | 0:184eb17ff158 | 244 | //////////////////////////////////////////////////////////////////////////////////// |
Rom | 0:184eb17ff158 | 245 | // start pressure conversion |
Rom | 0:184eb17ff158 | 246 | //////////////////////////////////////////////////////////////////////////////////// |
Rom | 0:184eb17ff158 | 247 | void cvt() { //This is only called once during the initialization phase! |
Rom | 0:184eb17ff158 | 248 | char w[2] = {0xF4, 0xF4}; |
Rom | 0:184eb17ff158 | 249 | i2c.write(BMP085ADDR, w, 2); |
Rom | 0:184eb17ff158 | 250 | } |
Rom | 0:184eb17ff158 | 251 | |
Rom | 0:184eb17ff158 | 252 | //////////////////////////////////////////////////////////////////////////////////// |
Rom | 0:184eb17ff158 | 253 | // Handle data ready interrupt, just sets data ready flag |
Rom | 0:184eb17ff158 | 254 | //////////////////////////////////////////////////////////////////////////////////// |
Rom | 0:184eb17ff158 | 255 | void drSub() { |
Rom | 0:184eb17ff158 | 256 | drFlag = 1; |
Rom | 0:184eb17ff158 | 257 | } |
Rom | 0:184eb17ff158 | 258 | |
Rom | 0:184eb17ff158 | 259 | ///////////////////////////////////////////////// |
Rom | 0:184eb17ff158 | 260 | // calculate compensated pressure |
Rom | 0:184eb17ff158 | 261 | ///////////////////////////////////////////////// |
Rom | 0:184eb17ff158 | 262 | int calcPress(int upp, int oversampling_setting) { |
Rom | 0:184eb17ff158 | 263 | // Return the pressure in Pa (Pascals) |
Rom | 0:184eb17ff158 | 264 | |
Rom | 0:184eb17ff158 | 265 | long pressure, x1, x2, x3, b3, b6; |
Rom | 0:184eb17ff158 | 266 | unsigned long b4, b7; |
Rom | 0:184eb17ff158 | 267 | // read page 12 of doc. This is ultra high precision and it requires a lot of time for the device to do the conversion |
Rom | 0:184eb17ff158 | 268 | |
Rom | 0:184eb17ff158 | 269 | unsigned long up = (unsigned long)upp; |
Rom | 0:184eb17ff158 | 270 | |
Rom | 0:184eb17ff158 | 271 | b6 = b5 - 4000; |
Rom | 0:184eb17ff158 | 272 | // calculate B3 |
Rom | 0:184eb17ff158 | 273 | x1 = (b6*b6) >> 12; // full formula(b2*(b6*b6)/pow(2,12))/pow(2,11) |
Rom | 0:184eb17ff158 | 274 | x1 *= b2; |
Rom | 0:184eb17ff158 | 275 | x1 >>= 11; |
Rom | 0:184eb17ff158 | 276 | |
Rom | 0:184eb17ff158 | 277 | x2 = (ac2*b6); |
Rom | 0:184eb17ff158 | 278 | x2 >>= 11; |
Rom | 0:184eb17ff158 | 279 | |
Rom | 0:184eb17ff158 | 280 | x3 = x1 + x2; |
Rom | 0:184eb17ff158 | 281 | |
Rom | 0:184eb17ff158 | 282 | b3 = (((((long)ac1 )*4 + x3) <<oversampling_setting) + 2) >> 2; // doc says /4! |
Rom | 0:184eb17ff158 | 283 | |
Rom | 0:184eb17ff158 | 284 | // calculate B4 |
Rom | 0:184eb17ff158 | 285 | x1 = (ac3* b6) >> 13; |
Rom | 0:184eb17ff158 | 286 | x2 = (b1 * ((b6*b6) >> 12) ) >> 16; |
Rom | 0:184eb17ff158 | 287 | x3 = ((x1 + x2) + 2) >> 2; |
Rom | 0:184eb17ff158 | 288 | b4 = (ac4 * (unsigned long) (x3 + 32768)) >> 15; |
Rom | 0:184eb17ff158 | 289 | |
Rom | 0:184eb17ff158 | 290 | b7 = ((unsigned long) up - b3) * (50000>>oversampling_setting); |
Rom | 0:184eb17ff158 | 291 | if (b7 < 0x80000000) { |
Rom | 0:184eb17ff158 | 292 | pressure = (b7 << 1) / b4; |
Rom | 0:184eb17ff158 | 293 | } else { |
Rom | 0:184eb17ff158 | 294 | pressure = (b7 / b4) << 1; |
Rom | 0:184eb17ff158 | 295 | } |
Rom | 0:184eb17ff158 | 296 | |
Rom | 0:184eb17ff158 | 297 | x1 = pressure >> 8; |
Rom | 0:184eb17ff158 | 298 | x1 *= x1; // pressure/pow(2,8) * pressure/pow(2, 8) |
Rom | 0:184eb17ff158 | 299 | x1 = (x1 * 3038) >> 16; |
Rom | 0:184eb17ff158 | 300 | x2 = (pressure * -7357) >> 16; |
Rom | 0:184eb17ff158 | 301 | pressure += (x1 + x2 + 3791) >> 4; // pressure in Pa |
Rom | 0:184eb17ff158 | 302 | |
Rom | 0:184eb17ff158 | 303 | return (pressure); |
Rom | 0:184eb17ff158 | 304 | } |
Rom | 0:184eb17ff158 | 305 | |
Rom | 0:184eb17ff158 | 306 | ///////////////////////////////////////////////// |
Rom | 0:184eb17ff158 | 307 | // calculate compensated temp from uncompensated |
Rom | 0:184eb17ff158 | 308 | ///////////////////////////////////////////////// |
Rom | 0:184eb17ff158 | 309 | int calcTemp(int ut) { |
Rom | 0:184eb17ff158 | 310 | // Returns the temperature in °C |
Rom | 0:184eb17ff158 | 311 | |
Rom | 0:184eb17ff158 | 312 | int temp; |
Rom | 0:184eb17ff158 | 313 | long x1, x2; |
Rom | 0:184eb17ff158 | 314 | |
Rom | 0:184eb17ff158 | 315 | x1 = (((long) ut - (long) ac6) * (long) ac5) >> 15; // aka (ut-ac6) * ac5/pow(2,15) |
Rom | 0:184eb17ff158 | 316 | x2 = ((long) mc << 11) / (x1 + md); // aka mc * pow(2, 11) / (x1 + md) |
Rom | 0:184eb17ff158 | 317 | b5 = x1 + x2; |
Rom | 0:184eb17ff158 | 318 | temp = ((b5 + 8) >> 4); // (b5+8)/pow(2, 4) |
Rom | 0:184eb17ff158 | 319 | // temperature in 0.1°C (aka 1903 = 190.3°C) |
Rom | 0:184eb17ff158 | 320 | return (temp); |
Rom | 0:184eb17ff158 | 321 | } |
Rom | 0:184eb17ff158 | 322 | |
Rom | 0:184eb17ff158 | 323 | //////////////////////////////////////////////////////////////////////////////////// |
Rom | 0:184eb17ff158 | 324 | // int version of moving average filter |
Rom | 0:184eb17ff158 | 325 | //////////////////////////////////////////////////////////////////////////////////// |
Rom | 0:184eb17ff158 | 326 | |
Rom | 0:184eb17ff158 | 327 | static int movAvgIntZ (int input) { |
Rom | 0:184eb17ff158 | 328 | int cum = 0; |
Rom | 0:184eb17ff158 | 329 | for (int i = 0; i < COEFZ; i++) { |
Rom | 0:184eb17ff158 | 330 | k[i] = k[i+1]; // do we really need k as a global variable? |
Rom | 0:184eb17ff158 | 331 | } |
Rom | 0:184eb17ff158 | 332 | k[COEFZ - 1] = input; |
Rom | 0:184eb17ff158 | 333 | for (int i = 0; i < COEFZ; i++) { |
Rom | 0:184eb17ff158 | 334 | cum += k[i]; |
Rom | 0:184eb17ff158 | 335 | } |
Rom | 0:184eb17ff158 | 336 | return (cum/COEFZ) ; |
Rom | 0:184eb17ff158 | 337 | } |
Rom | 0:184eb17ff158 | 338 | |
Rom | 0:184eb17ff158 | 339 | float calcAltitude(int pressure) { |
Rom | 0:184eb17ff158 | 340 | //Compute an estimate of altitude |
Rom | 0:184eb17ff158 | 341 | // see page 15 of manual |
Rom | 0:184eb17ff158 | 342 | float float_comp_pressure = (float) pressure; |
Rom | 0:184eb17ff158 | 343 | float altitude = float_comp_pressure/ALTITUDE_PRESSURE_REFERENCE; |
Rom | 0:184eb17ff158 | 344 | altitude = pow(altitude, ALTITUDE_EXPONENT); |
Rom | 0:184eb17ff158 | 345 | altitude = 1.0 - altitude; |
Rom | 0:184eb17ff158 | 346 | altitude *= ALTITUDE_COEFF; |
Rom | 0:184eb17ff158 | 347 | // formula is: altitude = 44330 * (1-pow((p/p0), 1/5.255)) |
Rom | 0:184eb17ff158 | 348 | return altitude; |
Rom | 0:184eb17ff158 | 349 | } |
Rom | 0:184eb17ff158 | 350 | |
Rom | 0:184eb17ff158 | 351 | float calcWikipediaAltitude(int pressure) { |
Rom | 0:184eb17ff158 | 352 | // compute the altitude in meters |
Rom | 0:184eb17ff158 | 353 | // per: http://en.wikipedia.org/wiki/Atmospheric_pressure |
Rom | 0:184eb17ff158 | 354 | float float_comp_pressure = (float) pressure; |
Rom | 0:184eb17ff158 | 355 | |
Rom | 0:184eb17ff158 | 356 | float altitude = float_comp_pressure/ALTITUDE_PRESSURE_REFERENCE; |
Rom | 0:184eb17ff158 | 357 | float exponent = 1.0/WIKIPEDIA_EXPONENT; |
Rom | 0:184eb17ff158 | 358 | altitude = pow(altitude, exponent); |
Rom | 0:184eb17ff158 | 359 | altitude = 1.0 - altitude; |
Rom | 0:184eb17ff158 | 360 | altitude *= (SEA_LEVEL_STANDARD_TEMPERATURE/TEMPERATURE_LAPSE_RATE); |
Rom | 0:184eb17ff158 | 361 | |
Rom | 0:184eb17ff158 | 362 | return altitude; |
Rom | 0:184eb17ff158 | 363 | } |