Parcourir la source

Updated the calcAltitude() function and example

Kongduino il y a 4 ans
Parent
commit
e0f073e381
3 fichiers modifiés avec 225 ajouts et 113 suppressions
  1. 168 91
      Seeed_BMP280.cpp
  2. 2 1
      Seeed_BMP280.h
  3. 55 21
      examples/bmp280_example/bmp280_example.ino

+ 168 - 91
Seeed_BMP280.cpp

@@ -1,108 +1,185 @@
-/*
-    bmp280_example.ino
-    Example sketch for BMP280
+#include "Seeed_BMP280.h"
 
-    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
+// #define BMP280_DEBUG_PRINT
 
-    The MIT License (MIT)
+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;
+}
 
-    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:
+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;
+  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;
+}
 
-    The above copyright notice and this permission notice shall be included in
-    all copies or substantial portions of the Software.
+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;
+}
 
-    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>
+float BMP280::calcAltitude(float p0, float p1, float t) {
+  float C;
+  Serial.print("p0 = ");
+  Serial.println(p0);
+  Serial.print("p1 = ");
+  Serial.println(p1);
+  Serial.print("t = ");
+  Serial.println(t);
+  C = (p0 / p1);
+  Serial.print("C = ");
+  Serial.println(C);
+  C = pow(C, (1 / 5.25588)) - 1.0;
+  Serial.print("C = ");
+  Serial.println(C);
+  C = (C * (t + 273.15)) / 0.0065;
+  Serial.print("C = ");
+  Serial.println(C);
+  return C;
+}
 
-#include "Seeed_BMP280.h"
-#include <Wire.h>
-#include <ArduinoJson.h>
-// http://librarymanager/All#ArduinoJSON
+float BMP280::calcAltitude(float p0) {
+  if (!isTransport_OK) {
+    return 0;
+  }
+  float t = getTemperature();
+  float p1 = getPressure();
+  return calcAltitude(p0, p1, t);
+}
 
-BMP280 bmp280;
-float MSL = 102009; // Mean Sea Level in Pa
-#define INTERVAL 2000
-double t0;
+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();
+}
 
-void setup() {
-  Serial.begin(115200);
-  delay(2000);
-  Serial.println("\n\nBMP280 test");
-  if (!bmp280.init()) {
-    Serial.println("Device not connected or broken!");
-    while (1);
+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;
+  } else {
+    isTransport_OK = true;
   }
-  t0 = millis();
+  msb = Wire.read();
+  lsb = Wire.read();
+  return (uint16_t) msb << 8 | lsb;
 }
 
-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
+uint16_t BMP280::bmp280Read16LE(uint8_t reg) {
+  uint16_t data = bmp280Read16(reg);
+  return (data >> 8) | (data << 8);
+}
 
-    //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");
+int16_t BMP280::bmp280ReadS16(uint8_t reg) {
+  return (int16_t)bmp280Read16(reg);
+}
 
-    //get and print altitude data
-    // Pass MSL to the function
-    Serial.print("Altitude: ");
-    Serial.print(bmp280.calcAltitude(MSL));
-    Serial.println(" m");
+int16_t BMP280::bmp280ReadS16LE(uint8_t reg) {
+  return (int16_t)bmp280Read16LE(reg);
+}
 
-    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();
-    }
-    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 {
-      Serial.println("Parse error!");
+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
     }
   }
+  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
 }

+ 2 - 1
Seeed_BMP280.h

@@ -34,7 +34,8 @@ class BMP280 {
     bool init(int i2c_addr = BMP280_ADDRESS);
     float getTemperature(void);
     uint32_t getPressure(void);
-    float calcAltitude(float pressure);
+    float calcAltitude(float p0);
+    float calcAltitude(float p0, float p1, float t);
   private:
     bool isTransport_OK;
     int _devAddr;

+ 55 - 21
examples/bmp280_example/bmp280_example.ino

@@ -29,11 +29,19 @@
     OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
     THE SOFTWARE.
 */
+#undef max
+#undef min
+#include <string>
+
 #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;
+uint32_t MSL = 102009; // Mean Sea Level in Pa
 
 void setup() {
   Serial.begin(115200);
@@ -45,25 +53,51 @@ void setup() {
 }
 
 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
-
-  //get and print atmospheric pressure data
-  Serial.print("Pressure: ");
-  Serial.print(pressure / 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");
+  double t1 = millis();
+  if (t1 - t0 > INTERVAL) {
+    float p1;
 
-  Serial.println("\n");
-  //add a line between output of different times.
-  delay(1000);
+    //get and print temperatures
+    Serial.print("Temp: ");
+    float t = bmp280.getTemperature();
+    Serial.print(t);
+    Serial.println("C");
+    //get and print atmospheric pressure data
+    Serial.print("MSL: ");
+    Serial.print(MSL / 100.0);
+    Serial.println(" HPa");
+    Serial.print("Pressure: ");
+    p1 = bmp280.getPressure();
+    Serial.print(p1 / 100.0);
+    Serial.println(" HPa");
+    //get and print altitude data
+    //get and print altitude data
+    float a = bmp280.calcAltitude(MSL, p1, t);
+    Serial.print("Altitude: ");
+    Serial.print(a);
+    Serial.println(" m");
+    Serial.println("\n");
+    t0 = millis();
+  }
+  if (Serial.available()) {
+    char mb[255];
+    uint8_t ix = 0;
+    while (Serial.available()) {
+      mb[ix++] = Serial.read();
+    }
+    mb[ix] = 0;
+    Serial.println("Incoming:");
+    Serial.println(mb);
+    StaticJsonDocument<200> doc;
+    DeserializationError error = deserializeJson(doc, mb);
+    if (!error) {
+      float newMSL = doc["MSL"];
+      Serial.print("New MSL: "); Serial.println(newMSL);
+      if (newMSL > 0.0) {
+        MSL = newMSL * 100;
+      }
+    } else {
+      Serial.println("Parse error!");
+    }
+  }
 }