Explorar el Código

Updated the calcAltitude() function and example

Kongduino hace 4 años
padre
commit
1749478653
Se han modificado 3 ficheros con 131 adiciones y 207 borrados
  1. 3 1
      README.md
  2. 101 183
      Seeed_BMP280.cpp
  3. 27 23
      examples/bmp280_example/bmp280_example.ino

+ 3 - 1
README.md

@@ -7,7 +7,9 @@
 
 Thanks to Bosch, now we’ve got a high-precision environmental sensor at even lower cost, the Grove – Barometer Sensor(BMP280). It is based on their new BMP280 sensor, which is an upgraded version of the old BMP180 used in Grove – Barometer Sensor (BMP180). The module provides precise measurement of barometric pressure and temperature in the environment. The air pressure can be measured in a range from 300 hPa to 1100hPa with ±1.0 hPa absolute accuracy. As for the temperature the sensor works perfectly for temperatures between - 40 and 85 with an accuracy of ±1.
 
-Owing to its high accuracy on measuring the pressure, and the pressure changes with altitude, we can calculate the altitude with ±1 meter accuracy, which makes it a precise altimeter as well. Another great thing about this module is that, you don’t even need to worry about the I2C collisions as it provides both I2C and SPI interfaces. To use SPI, simply de-solder the bonding pads on the back. If you go with I2C, the board also provides 2 I2C addresses for you to select as you want.
+Owing to its high accuracy on measuring the pressure, and the pressure changes with altitude, we can calculate the altitude with ±1 meter accuracy, which makes it a precise altimeter as well. However, for the formula to work properly, you must update the mean sea-level pressure. See the updated `calcAltitude()` function and example. (@Kongduino)
+
+Another great thing about this module is that, you don’t even need to worry about the I2C collisions as it provides both I2C and SPI interfaces. To use SPI, simply de-solder the bonding pads on the back. If you go with I2C, the board also provides 2 I2C addresses for you to select as you want.
 
 More information please visit [wiki page](http://wiki.seeedstudio.com/Grove-Barometer_Sensor-BMP280/).
 

+ 101 - 183
Seeed_BMP280.cpp

@@ -1,190 +1,108 @@
-#include "Seeed_BMP280.h"
-
-// #define BMP280_DEBUG_PRINT
-
-bool BMP280::init(int i2c_addr) {
-    uint8_t chip_id = 0;
-    uint8_t retry = 0;
-
-    _devAddr = i2c_addr;
-    Wire.begin();
-
-    while ((retry++ < 5) && (chip_id != 0x58)) {
-        chip_id = bmp280Read8(BMP280_REG_CHIPID);
-        #ifdef BMP280_DEBUG_PRINT
-        Serial.print("Read chip ID: ");
-        Serial.println(chip_id);
-        #endif
-        delay(100);
-    }
-
-    dig_T1 = bmp280Read16LE(BMP280_REG_DIG_T1);
-    dig_T2 = bmp280ReadS16LE(BMP280_REG_DIG_T2);
-    dig_T3 = bmp280ReadS16LE(BMP280_REG_DIG_T3);
-
-    dig_P1 = bmp280Read16LE(BMP280_REG_DIG_P1);
-    dig_P2 = bmp280ReadS16LE(BMP280_REG_DIG_P2);
-    dig_P3 = bmp280ReadS16LE(BMP280_REG_DIG_P3);
-    dig_P4 = bmp280ReadS16LE(BMP280_REG_DIG_P4);
-    dig_P5 = bmp280ReadS16LE(BMP280_REG_DIG_P5);
-    dig_P6 = bmp280ReadS16LE(BMP280_REG_DIG_P6);
-    dig_P7 = bmp280ReadS16LE(BMP280_REG_DIG_P7);
-    dig_P8 = bmp280ReadS16LE(BMP280_REG_DIG_P8);
-    dig_P9 = bmp280ReadS16LE(BMP280_REG_DIG_P9);
-
-    writeRegister(BMP280_REG_CONTROL, 0x3F);
-    return true;
-}
-
-float BMP280::getTemperature(void) {
-    int32_t var1, var2;
-
-    int32_t adc_T = bmp280Read24(BMP280_REG_TEMPDATA);
-    // Check if the last transport successed
-    if (!isTransport_OK) {
-        return 0;
-    }
-    adc_T >>= 4;
-    var1 = (((adc_T >> 3) - ((int32_t)(dig_T1 << 1))) *
-            ((int32_t)dig_T2)) >> 11;
+/*
+    bmp280_example.ino
+    Example sketch for BMP280
+
+    Copyright (c) 2016 seeed technology inc.
+    Website    : www.seeedstudio.com
+    Author     : Lambor, CHN
+    Create Time:
+    Change Log :  2021/03/11 by @Kongduino
+                  Reworked example to display true altitude based on MSL
+
+    The MIT License (MIT)
+
+    Permission is hereby granted, free of charge, to any person obtaining a copy
+    of this software and associated documentation files (the "Software"), to deal
+    in the Software without restriction, including without limitation the rights
+    to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+    copies of the Software, and to permit persons to whom the Software is
+    furnished to do so, subject to the following conditions:
+
+    The above copyright notice and this permission notice shall be included in
+    all copies or substantial portions of the Software.
+
+    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+    AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+    THE SOFTWARE.
+*/
+#undef max
+#undef min
+#include <string>
 
-    var2 = (((((adc_T >> 4) - ((int32_t)dig_T1)) *
-              ((adc_T >> 4) - ((int32_t)dig_T1))) >> 12) *
-            ((int32_t)dig_T3)) >> 14;
-
-    t_fine = var1 + var2;
-    float T = (t_fine * 5 + 128) >> 8;
-    return T / 100;
-}
-
-uint32_t BMP280::getPressure(void) {
-    int64_t var1, var2, p;
-
-    // Call getTemperature to get t_fine
-    getTemperature();
-    // Check if the last transport successed
-    if (!isTransport_OK) {
-        return 0;
-    }
-
-    int32_t adc_P = bmp280Read24(BMP280_REG_PRESSUREDATA);
-    adc_P >>= 4;
-
-    var1 = ((int64_t)t_fine) - 128000;
-    var2 = var1 * var1 * (int64_t)dig_P6;
-    var2 = var2 + ((var1 * (int64_t)dig_P5) << 17);
-    var2 = var2 + (((int64_t)dig_P4) << 35);
-    var1 = ((var1 * var1 * (int64_t)dig_P3) >> 8) + ((var1 * (int64_t)dig_P2) << 12);
-    var1 = (((((int64_t)1) << 47) + var1)) * ((int64_t)dig_P1) >> 33;
-    if (var1 == 0) {
-        return 0; // avoid exception caused by division by zero
-    }
-    p = 1048576 - adc_P;
-    p = (((p << 31) - var2) * 3125) / var1;
-    var1 = (((int64_t)dig_P9) * (p >> 13) * (p >> 13)) >> 25;
-    var2 = (((int64_t)dig_P8) * p) >> 19;
-    p = ((p + var1 + var2) >> 8) + (((int64_t)dig_P7) << 4);
-    return (uint32_t)p / 256;
+#include "Seeed_BMP280.h"
+#include <Wire.h>
+#include <ArduinoJson.h>
+// http://librarymanager/All#ArduinoJSON
+
+BMP280 bmp280;
+float MSL = 102009; // Mean Sea Level in Pa
+#define INTERVAL 2000
+double t0;
+
+void setup() {
+  Serial.begin(115200);
+  delay(2000);
+  Serial.println("\n\nBMP280 test");
+  if (!bmp280.init()) {
+    Serial.println("Device not connected or broken!");
+    while (1);
+  }
+  t0 = millis();
 }
 
-float BMP280::calcAltitude(float pressure) {
-    if (!isTransport_OK) {
-        return 0;
+void loop() {
+  double t1 = millis();
+  if (t1 - t0 > INTERVAL) {
+    uint32_t pressure = bmp280.getPressure();
+    //get and print temperatures
+    Serial.print("Temp: ");
+    Serial.print(bmp280.getTemperature());
+    Serial.println(" *C");
+    // Using "*C" as the unit for Celsius because the Arduino IDE doesn't support special symbols
+
+    //get and print atmospheric pressure data
+    Serial.print("Pressure: ");
+    Serial.print(pressure / 100.0);
+    Serial.println(" HPa");
+    Serial.print("MSL: ");
+    Serial.print(MSL / 100.0);
+    Serial.println(" HPa");
+
+    //get and print altitude data
+    // Pass MSL to the function
+    Serial.print("Altitude: ");
+    Serial.print(bmp280.calcAltitude(MSL));
+    Serial.println(" m");
+
+    Serial.println("\n");
+    //add a line between output of different times.
+    t0 = millis();
+  }
+  if (Serial.available()) {
+    char mb[255];
+    uint8_t ix = 0;
+    while (Serial.available()) {
+      mb[ix++] = Serial.read();
     }
-    float A = pressure / 101325;
-    float B = 1 / 5.25588;
-    float C = pow(A, B);
-    C = 1.0 - C;
-    C = C / 0.0000225577;
-    return C;
-}
-
-uint8_t BMP280::bmp280Read8(uint8_t reg) {
-    Wire.beginTransmission(_devAddr);
-    Wire.write(reg);
-    Wire.endTransmission();
-
-    Wire.requestFrom(_devAddr, 1);
-    // return 0 if slave didn't response
-    if (Wire.available() < 1) {
-        isTransport_OK = false;
-        return 0;
-    } else if (isTransport_OK == false) {
-        isTransport_OK = true;
-    }
-
-    return Wire.read();
-}
-
-uint16_t BMP280::bmp280Read16(uint8_t reg) {
-    uint8_t msb, lsb;
-
-    Wire.beginTransmission(_devAddr);
-    Wire.write(reg);
-    Wire.endTransmission();
-
-    Wire.requestFrom(_devAddr, 2);
-    // return 0 if slave didn't response
-    if (Wire.available() < 2) {
-        isTransport_OK = false;
-        return 0;
+    mb[ix] = 0;
+    Serial.println("Incoming:");
+    Serial.println(mb);
+    StaticJsonDocument<200> doc;
+    DeserializationError error = deserializeJson(doc, mb);
+    // Pass a JSON packet to change current MSL. eg:
+    // {"MSL":1021}
+    if (!error) {
+      float newMSL = doc["MSL"];
+      Serial.print("New MSL: "); Serial.println(newMSL);
+      if (newMSL > 0.0) {
+        MSL = newMSL * 100;
+      }
     } else {
-        isTransport_OK = true;
-    }
-
-    msb = Wire.read();
-    lsb = Wire.read();
-
-    return (uint16_t) msb << 8 | lsb;
-}
-
-uint16_t BMP280::bmp280Read16LE(uint8_t reg) {
-    uint16_t data = bmp280Read16(reg);
-    return (data >> 8) | (data << 8);
-}
-
-int16_t BMP280::bmp280ReadS16(uint8_t reg) {
-    return (int16_t)bmp280Read16(reg);
-}
-
-int16_t BMP280::bmp280ReadS16LE(uint8_t reg) {
-    return (int16_t)bmp280Read16LE(reg);
-}
-
-uint32_t BMP280::bmp280Read24(uint8_t reg) {
-    uint32_t data;
-
-    Wire.beginTransmission(_devAddr);
-    Wire.write(reg);
-    Wire.endTransmission();
-
-    Wire.requestFrom(_devAddr, 3);
-
-    // return 0 if slave didn't response
-    if (Wire.available() < 3) {
-        isTransport_OK = false;
-        return 0;
-    } else if (isTransport_OK == false) {
-        isTransport_OK = true;
-        if (!init(_devAddr)) {
-            #ifdef BMP280_DEBUG_PRINT
-            Serial.println("Device not connected or broken!");
-            #endif
-        }
+      Serial.println("Parse error!");
     }
-
-    data = Wire.read();
-    data <<= 8;
-    data |= Wire.read();
-    data <<= 8;
-    data |= Wire.read();
-
-    return data;
-}
-
-void BMP280::writeRegister(uint8_t reg, uint8_t val) {
-    Wire.beginTransmission(_devAddr); // start transmission to device
-    Wire.write(reg);       // send register address
-    Wire.write(val);         // send value to write
-    Wire.endTransmission();     // end transmission
+  }
 }

+ 27 - 23
examples/bmp280_example/bmp280_example.ino

@@ -6,7 +6,8 @@
     Website    : www.seeedstudio.com
     Author     : Lambor, CHN
     Create Time:
-    Change Log :
+    Change Log :  2021/03/11 by @Kongduino
+                  Reworked example to display true altitude based on MSL
 
     The MIT License (MIT)
 
@@ -32,34 +33,37 @@
 #include <Wire.h>
 
 BMP280 bmp280;
+float MSL = 102009; // Mean Sea Level in Pa
 
 void setup() {
-    Serial.begin(9600);
-    if (!bmp280.init()) {
-        Serial.println("Device not connected or broken!");
-    }
+  Serial.begin(115200);
+  delay(2000);
+  Serial.println("\n\nBMP280 test");
+  if (!bmp280.init()) {
+    Serial.println("Device not connected or broken!");
+  }
 }
 
 void loop() {
+  float pressure = bmp280.getPressure();
+  //get and print temperatures
+  Serial.print("Temp: ");
+  Serial.print(bmp280.getTemperature());
+  Serial.println(" *C");
+  // Using "*C" as the unit for Celsius because the Arduino IDE doesn't support special symbols
 
-    float pressure;
+  //get and print atmospheric pressure data
+  Serial.print("Pressure: ");
+  Serial.print(pressure / 100.0);
+  Serial.println(" HPa");
 
-    //get and print temperatures
-    Serial.print("Temp: ");
-    Serial.print(bmp280.getTemperature());
-    Serial.println("C"); // The unit for  Celsius because original arduino don't support speical symbols
+  //get and print altitude data
+  // Pass MSL to the function
+  Serial.print("Altitude: ");
+  Serial.print(bmp280.calcAltitude(MSL));
+  Serial.println(" m");
 
-    //get and print atmospheric pressure data
-    Serial.print("Pressure: ");
-    Serial.print(pressure = bmp280.getPressure());
-    Serial.println("Pa");
-
-    //get and print altitude data
-    Serial.print("Altitude: ");
-    Serial.print(bmp280.calcAltitude(pressure));
-    Serial.println("m");
-
-    Serial.println("\n");//add a line between output of different times.
-
-    delay(1000);
+  Serial.println("\n");
+  //add a line between output of different times.
+  delay(1000);
 }