Kenji Arai / BME280
Revision:
6:f94ffb546799
Parent:
5:c1f1647004c4
Child:
7:d94871acb463
diff -r c1f1647004c4 -r f94ffb546799 BME280.cpp
--- a/BME280.cpp	Sat Mar 11 04:21:14 2017 +0000
+++ b/BME280.cpp	Sat Dec 29 05:49:55 2018 +0000
@@ -27,6 +27,15 @@
  * THE SOFTWARE.
  */
 
+/*
+ *  Modified by Kenji Arai / JH1PJL
+ *
+ *  http://www.page.sannet.ne.jp/kenjia/index.html
+ *  http://mbed.org/users/kenjiArai/
+ *      Created:    November  21st, 2018
+ *      Revised:    December  29th, 2018
+ */
+
 #include "mbed.h"
 #include "BME280.h"
 
@@ -59,13 +68,32 @@
 void BME280::initialize()
 {
     char cmd[18];
- 
+    uint8_t id;
+
+    wait_ms(2);
+    id = getID();
+    if (id != 0x60){
+        if (address == DEFAULT_SLAVE_ADDRESS){
+            address = DEFAULT_SLAVE_ADDRESS;
+        } else if (address == ANOTHER_SLAVE_ADDRESS){
+            address = DEFAULT_SLAVE_ADDRESS;
+        }
+        id = getID();
+        if (id != 0x60){
+            cmd[0] = 0xe0;  // reset addr
+            cmd[1] = 0xb6;  // reset command
+            i2c.write(address, cmd, 2);
+            wait_ms(2);
+        }
+    }
+
     cmd[0] = 0xf2; // ctrl_hum
     cmd[1] = 0x01; // Humidity oversampling x1
     i2c.write(address, cmd, 2);
  
     cmd[0] = 0xf4; // ctrl_meas
-    cmd[1] = 0x27; // Temparature oversampling x1, Pressure oversampling x1, Normal mode
+    // Temparature oversampling x1, Pressure oversampling x1, Normal mode
+    cmd[1] = 0x27;
     i2c.write(address, cmd, 2);
  
     cmd[0] = 0xf5; // config
@@ -96,7 +124,10 @@
     dig_P8 = (cmd[15] << 8) | cmd[14];
     dig_P9 = (cmd[17] << 8) | cmd[16];
  
-    DEBUG_PRINT("dig_P = 0x%x, 0x%x, 0x%x, 0x%x, 0x%x, 0x%x, 0x%x, 0x%x, 0x%x\n", dig_P1, dig_P2, dig_P3, dig_P4, dig_P5, dig_P6, dig_P7, dig_P8, dig_P9);
+    DEBUG_PRINT(
+        "dig_P = 0x%x, 0x%x, 0x%x, 0x%x, 0x%x, 0x%x, 0x%x, 0x%x, 0x%x\n",
+        dig_P1, dig_P2, dig_P3, dig_P4, dig_P5, dig_P6, dig_P7, dig_P8, dig_P9
+    );
  
     cmd[0] = 0xA1; // read dig_H regs
     i2c.write(address, cmd, 1);
@@ -112,7 +143,9 @@
     dig_H5 = (cmd[6] << 4) | ((cmd[5]>>4) & 0x0f);
     dig_H6 = cmd[7];
  
-    DEBUG_PRINT("dig_H = 0x%x, 0x%x, 0x%x, 0x%x, 0x%x, 0x%x\n", dig_H1, dig_H2, dig_H3, dig_H4, dig_H5, dig_H6);
+    DEBUG_PRINT("dig_H = 0x%x, 0x%x, 0x%x, 0x%x, 0x%x, 0x%x\n",
+                 dig_H1, dig_H2, dig_H3, dig_H4, dig_H5, dig_H6
+    );
 }
  
 float BME280::getTemperature()
@@ -120,7 +153,10 @@
     uint32_t temp_raw;
     float tempf;
     char cmd[4];
- 
+
+    if(check_chip() == false){
+        return 100.0f;
+    }
     cmd[0] = 0xfa; // temp_msb
     i2c.write(address, cmd, 1);
     i2c.read(address, &cmd[1], 3);
@@ -131,7 +167,8 @@
  
     temp =
         (((((temp_raw >> 3) - (dig_T1 << 1))) * dig_T2) >> 11) +
-        ((((((temp_raw >> 4) - dig_T1) * ((temp_raw >> 4) - dig_T1)) >> 12) * dig_T3) >> 14);
+        ((((((temp_raw >> 4) - dig_T1) * ((temp_raw >> 4) - dig_T1)) >> 12)
+         * dig_T3) >> 14);
  
     t_fine = temp;
     temp = (temp * 5 + 128) >> 8;
@@ -145,7 +182,11 @@
     uint32_t press_raw;
     float pressf;
     char cmd[4];
- 
+
+    if(check_chip() == false){
+        return 2000.0f;
+    }
+
     cmd[0] = 0xf7; // press_msb
     i2c.write(address, cmd, 1);
     i2c.read(address, &cmd[1], 3);
@@ -159,7 +200,8 @@
     var2 = (((var1 >> 2) * (var1 >> 2)) >> 11) * dig_P6;
     var2 = var2 + ((var1 * dig_P5) << 1);
     var2 = (var2 >> 2) + (dig_P4 << 16);
-    var1 = (((dig_P3 * (((var1 >> 2)*(var1 >> 2)) >> 13)) >> 3) + ((dig_P2 * var1) >> 1)) >> 18;
+    var1 = (((dig_P3 * (((var1 >> 2)*(var1 >> 2)) >> 13)) >> 3)
+             + ((dig_P2 * var1) >> 1)) >> 18;
     var1 = ((32768 + var1) * dig_P1) >> 15;
     if (var1 == 0) {
         return 0;
@@ -170,7 +212,8 @@
     } else {
         press = (press / var1) * 2;
     }
-    var1 = ((int32_t)dig_P9 * ((int32_t)(((press >> 3) * (press >> 3)) >> 13))) >> 12;
+    var1 = ((int32_t)dig_P9 * ((int32_t)(((press >> 3)
+             * (press >> 3)) >> 13))) >> 12;
     var2 = (((int32_t)(press >> 2)) * (int32_t)dig_P8) >> 13;
     press = (press + ((var1 + var2 + dig_P7) >> 4));
  
@@ -184,6 +227,10 @@
     float humf;
     char cmd[4];
  
+    if(check_chip() == false){
+        return 0.0f;
+    }
+
     cmd[0] = 0xfd; // hum_msb
     i2c.write(address, cmd, 1);
     i2c.read(address, &cmd[1], 2);
@@ -193,11 +240,13 @@
     int32_t v_x1;
  
     v_x1 = t_fine - 76800;
-    v_x1 =  (((((hum_raw << 14) -(((int32_t)dig_H4) << 20) - (((int32_t)dig_H5) * v_x1)) +
-               ((int32_t)16384)) >> 15) * (((((((v_x1 * (int32_t)dig_H6) >> 10) *
-                                            (((v_x1 * ((int32_t)dig_H3)) >> 11) + 32768)) >> 10) + 2097152) *
-                                            (int32_t)dig_H2 + 8192) >> 14));
-    v_x1 = (v_x1 - (((((v_x1 >> 15) * (v_x1 >> 15)) >> 7) * (int32_t)dig_H1) >> 4));
+    v_x1 =  (((((hum_raw << 14) -(((int32_t)dig_H4) << 20)
+             - (((int32_t)dig_H5) * v_x1)) + ((int32_t)16384)) >> 15)
+              * (((((((v_x1 * (int32_t)dig_H6) >> 10)
+              * (((v_x1 * ((int32_t)dig_H3)) >> 11) + 32768)) >> 10) + 2097152)
+              * (int32_t)dig_H2 + 8192) >> 14));
+    v_x1 = (v_x1 - (((((v_x1 >> 15) * (v_x1 >> 15)) >> 7)
+              * (int32_t)dig_H1) >> 4));
     v_x1 = (v_x1 < 0 ? 0 : v_x1);
     v_x1 = (v_x1 > 419430400 ? 419430400 : v_x1);
  
@@ -205,3 +254,171 @@
  
     return (humf/1024.0f);
 }
+
+//------------------------------------------------------------------------------
+// Added functions by JH1PJL
+//------------------------------------------------------------------------------
+//  Read chip ID
+uint8_t BME280::getID(void)
+{
+    char cmd[4];
+
+    cmd[0] = 0xd0;  // ID addr
+    i2c.write(address, cmd, 1, true);
+    i2c.read(address, cmd, 2, false);
+    return cmd[0];
+}
+
+bool BME280::check_chip(void)
+{
+    uint8_t id;
+
+    id = getID();
+    if (id != 0x60){
+        if (address == DEFAULT_SLAVE_ADDRESS){
+            address = DEFAULT_SLAVE_ADDRESS;
+        } else if (address == ANOTHER_SLAVE_ADDRESS){
+            address = DEFAULT_SLAVE_ADDRESS;
+        }
+        id = getID();
+        if (id != 0x60){
+            return resetChip_by_sw();
+        }
+    }
+    return true;
+}
+
+//  Reset the chip by software
+bool BME280::resetChip_by_sw(void)
+{
+    uint8_t id;
+    char cmd[4];
+
+    if (address == DEFAULT_SLAVE_ADDRESS){
+        ;
+    } else if (address == ANOTHER_SLAVE_ADDRESS){
+        ;
+    } else {
+        address = DEFAULT_SLAVE_ADDRESS;
+    }
+    // 1st try
+    cmd[0] = 0xe0;  // reset addr
+    cmd[1] = 0xb6;  // reset command
+    i2c.write(address, cmd, 2);
+    wait_ms(2);
+    id = getID();
+    if (id == 0x60){
+        initialize();
+        return true;
+    }
+    // 2nd retry (reset again and read again)
+    cmd[0] = 0xe0;  // reset addr
+    cmd[1] = 0xb6;  // reset command
+    i2c.write(address, cmd, 2);
+    wait_ms(2);
+    id = getID();
+    if (id == 0x60){
+        initialize();
+        return true;
+    }
+    // 3rd retry (reaset again and another chip addr)
+    if (address == DEFAULT_SLAVE_ADDRESS){
+        address = DEFAULT_SLAVE_ADDRESS;
+    } else if (address == ANOTHER_SLAVE_ADDRESS){
+        address = DEFAULT_SLAVE_ADDRESS;
+    } else {
+        return false;
+    }
+    cmd[0] = 0xe0;  // reset addr
+    cmd[1] = 0xb6;  // reset command
+    i2c.write(address, cmd, 2);
+    wait_ms(2);
+    id = getID();
+    if (id == 0x60){
+        initialize();
+        return true;
+    }
+    return false;
+}
+
+// Get compensated data
+void BME280::getAll_compensated_data(BME280_Data_TypeDef *dt) { 
+    uint32_t raw_data;
+    char cmd[8];
+ 
+    // Temperatue
+    cmd[0] = 0xfa; // temp_msb
+    i2c.write(address, cmd, 1);
+    i2c.read(address, &cmd[1], 3);
+    raw_data = (cmd[1] << 12) | (cmd[2] << 4) | (cmd[3] >> 4);
+    double var1, var2;
+    var1 = ((( double)raw_data) /  16384.0 - ((double)dig_T1) / 1024.0) *
+             ((double)dig_T2);
+    var2 = ((((double)raw_data) / 131072.0 - ((double)dig_T1) / 8192.0) *
+            (((double)raw_data) / 131072.0 - ((double)dig_T1) / 8192.0))
+            * ((double)dig_T3);
+    int32_t t_fine = (int32_t)(var1 + var2);
+    dt->temperatue = (var1 + var2) / 5120.0;
+    // Pressue
+    cmd[0] = 0xf7; // press_msb
+    i2c.write(address, cmd, 1);
+    i2c.read(address, &cmd[1], 3);
+    raw_data = (cmd[1] << 12) | (cmd[2] << 4) | (cmd[3] >> 4);
+    double p;
+    var1 = ((double)t_fine / 2.0) - 64000.0;
+    var2 = var1 * var1 * ((double)dig_P6) / 32768.0;
+    var2 = var2 + var1 * ((double)dig_P5) * 2.0;
+    var2 = (var2 / 4.0)+(((double)dig_P4) * 65536.0);
+    var1 = (((double)dig_P3) * var1 * var1 / 524288.0 +
+            ((double)dig_P2) * var1) / 524288.0;
+    var1 = (1.0 + var1 / 32768.0)*((double)dig_P1);
+    if (var1 == 0.0) {
+        dt->pressue = 0.0;
+        return; //avoid exception caused by division by zero
+    }
+    p = 1048576.0 - (double)raw_data;
+    p = (p - (var2 / 4096.0)) * 6250.0 / var1;
+    var1 = ((double)dig_P9) * p * p / 2147483648.0;
+    var2 = p * ((double)dig_P8) / 32768.0;
+    p = p + (var1 + var2 + ((double)dig_P7)) / 16.0;
+    dt->pressue = p / 100.0;
+    // Humidity
+    cmd[0] = 0xfd; // hum_msb
+    i2c.write(address, cmd, 1);
+    i2c.read(address, &cmd[1], 2);
+    raw_data = (cmd[1] << 8) | cmd[2];
+    double var_H;
+    var_H = (((double)t_fine) - 76800.0);
+    var_H = (raw_data - (((double)dig_H4) * 64.0 + 
+            ((double)dig_H5) / 16384.0 * var_H)) *
+            (((double)dig_H2) / 65536.0 * (1.0 + 
+            ((double)dig_H6) / 67108864.0 * var_H * 
+            (1.0 + ((double)dig_H3) / 67108864.0 * var_H)));
+    var_H = var_H * (1.0 - ((double)dig_H1) * var_H / 524288.0);
+    if (var_H > 100.0) {
+        var_H = 100.0;
+    } else if (var_H < 0.0) {
+        var_H = 0.0;
+    }
+    dt->humidity = var_H;
+}
+
+#if 0
+double calcAltitude(float pressure,float temperature) 
+{ 
+    // Equation taken from BMP180 datasheet (page 16): 
+    //  http://www.adafruit.com/datasheets/BST-BMP180-DS000-09.pdf 
+  
+
+    // Note that using the equation from wikipedia can give bad results 
+    // at high altitude.  See this thread for more information: 
+    //  http://forums.adafruit.com/viewtopic.php?f=22&t=58064 
+    /*
+    double altitude = (temperature + 273.15) 
+      * (pow(MEAN_SEA_LEVEL_PRESSURE/pressure, 0.190294957)-1.0) / 0.0065;
+    */ 
+    double altitude =
+        44330.0 * (1.0 - pow(pressure / MEAN_SEA_LEVEL_PRESSURE, 0.190294957)); 
+    return altitude; 
+}
+#endif
\ No newline at end of file