🤖Have you ever tried Chat.M5Stack.com before asking??😎
    M5Stack Community
    • Categories
    • Recent
    • Tags
    • Popular
    • Users
    • Groups
    • Search
    • Register
    • Login

    M5Paper and BME280 Sensor

    PROJECTS
    1
    2
    4.0k
    Loading More Posts
    • Oldest to Newest
    • Newest to Oldest
    • Most Votes
    Reply
    • Reply as topic
    Log in to reply
    This topic has been deleted. Only users with topic management privileges can see it.
    • P
      Powersoft
      last edited by

      Because the BME280 library didn't want to work with the M5Paper Wire1 I2c connection, I changed the routines so that they now work.

      The adjustment now works for M5Stack, the M5Paper and for the Core2.
      I post the complete code here, because I cannot upload a zip file.
      he whole consists of:

      1. M5Paper_BME280.uno
      2. BME280.h
      3. BME280_routines

      1. M5Paper_BME280.uno

      /*
       * BME280 Sensor (Temperature,Pressure, and Humidity) 
       * Is working now also for M5Paper, and testest on all M5Stack devices
       * Rewritten by J.Kromhout (NL)
       * Version 1.0
       * Date : 24-02-2021
       * 
       * Todo:  Beter input for smapling etc.
       *        Making the routine universal for BME280 and BMP280
       */
      
      #include <M5EPD.h>
      #include <Wire.h>
      
      #include "BME280.h" /* definition file */
      
      double p,t,h; /* pressure,temperature and humidity */
      
      void setup() {
        M5.begin();
        Wire1.begin(25,32); /* start Wire1 on M5Paper */
        getBME280(&Wire1, &t, &p, &h); /* get messurment*/
        Serial.println("-------------------------");
        Serial.printf("Temperature : %6.1f °C\n",   t);
        Serial.printf("Barometer   : %6.1f hPa\n",  p);
        Serial.printf("Humidity    : %6.1f %%\n",   h);
        Serial.println("-------------------------");
      }
      
      void loop() {
        // put your main code here, to run repeatedly:
      
      }
      
      
      void getBME280(TwoWire *theWire, double *t, double *p, double *h)
      {
        _i2c = theWire;
      
        /* check of BME280 is avilable */
        uint8_t value = read8(0xD0);  
        if (value == 0x60)
          Serial.println("BME280 found");
        else
        {
          Serial.println("No BME280 found! Check your device........");
          while(true);
        }
        reset_BME280();                                     // Reset BME280      
        write8(BME280_REGISTER_CONTROLHUMID,(uint8_t)0x01); // Select control humidity register
        write8(BME280_REGISTER_CONTROL,     (uint8_t)0x27); // Select control measurement register
        write8(BME280_REGISTER_CONFIG,      (uint8_t)0xA0); // Select config register
        readCoefficients();                                 // Read coefficients from BME280
        *t = get_Temperature();                             // Get temperature
        *p = get_Pressure()/100.0;                          // Get pressure
        *h = get_Humidity();                                // Get Humidity
      }
      

      2. BME280.h

      #define BME280_ADDRESS 0x77  /* Primary I2C Address */
      TwoWire *_i2c;
      uint8_t _i2caddr = BME280_ADDRESS;
      
      
      int32_t t_fine; /* tempory variable */
      
      /* calibration data, need for calculation */
      uint16_t  dig_T1; 
      int16_t   dig_T2;  
      int16_t   dig_T3;  
      
      uint16_t  dig_P1; 
      int16_t   dig_P2;  
      int16_t   dig_P3;  
      int16_t   dig_P4;  
      int16_t   dig_P5;  
      int16_t   dig_P6;  
      int16_t   dig_P7;  
      int16_t   dig_P8; 
      int16_t   dig_P9;  
      
      uint8_t   dig_H1; 
      int16_t   dig_H2; 
      uint8_t   dig_H3; 
      int16_t   dig_H4; 
      int16_t   dig_H5; 
      int8_t    dig_H6;  
      
      /* Calibrate registers addresses */
      #define BME280_REGISTER_DIG_T1        0x88
      #define BME280_REGISTER_DIG_T2        0x8A
      #define BME280_REGISTER_DIG_T3        0x8C
      #define BME280_REGISTER_DIG_P1        0x8E
      #define BME280_REGISTER_DIG_P2        0x90
      #define BME280_REGISTER_DIG_P3        0x92
      #define BME280_REGISTER_DIG_P4        0x94
      #define BME280_REGISTER_DIG_P5        0x96
      #define BME280_REGISTER_DIG_P6        0x98
      #define BME280_REGISTER_DIG_P7        0x9A
      #define BME280_REGISTER_DIG_P8        0x9C
      #define BME280_REGISTER_DIG_P9        0x9E
      #define BME280_REGISTER_DIG_H1        0xA1
      #define BME280_REGISTER_DIG_H2        0xE1
      #define BME280_REGISTER_DIG_H3        0xE3
      #define BME280_REGISTER_DIG_H4        0xE4
      #define BME280_REGISTER_DIG_H5        0xE5
      #define BME280_REGISTER_DIG_H6        0xE7
      /* ontrol registers */
      #define BME280_REGISTER_CHIPID        0xD0
      #define BME280_REGISTER_VERSION       0xD1
      #define BME280_REGISTER_SOFTRESET     0xE0
      #define BME280_REGISTER_CAL26         0xE1 
      #define BME280_REGISTER_CONTROLHUMID  0xF2
      #define BME280_REGISTER_STATUS        0xF3
      #define BME280_REGISTER_CONTROL       0xF4
      #define BME280_REGISTER_CONFIG        0xF5
      #define BME280_REGISTER_PRESSUREDATA  0xF7
      #define BME280_REGISTER_TEMPDATA      0xFA
      #define BME280_REGISTER_HUMIDDATA     0xFD
      

      3. BME280_routines

      uint8_t read8(byte reg) 
      {
        uint8_t value;
        _i2c->beginTransmission((uint8_t)BME280_ADDRESS);
        _i2c->write((uint8_t)reg);
        _i2c->endTransmission();
        _i2c->requestFrom((uint8_t)BME280_ADDRESS,(uint8_t)1);
        value = _i2c->read();
        return value;
      }
          
      void write8(byte reg , byte value) 
      {
        _i2c->beginTransmission((uint8_t)BME280_ADDRESS);
        _i2c->write((uint8_t)reg);
        _i2c->write((uint8_t)value);
        _i2c->endTransmission();
      }
      
      uint16_t read16(byte reg) 
      {
        uint16_t value;
        _i2c->beginTransmission((uint8_t) BME280_ADDRESS);
        _i2c->write((uint8_t)reg);
        _i2c->endTransmission();
        _i2c->requestFrom((uint8_t)BME280_ADDRESS,(uint8_t)2);
        value = (_i2c->read() << 8) | _i2c->read();
        return value;
      }
      
      uint32_t read24(byte reg) 
      {
        uint32_t value;
          _i2c->beginTransmission((uint8_t)BME280_ADDRESS);
          _i2c->write((uint8_t)reg);
          _i2c->endTransmission();
          _i2c->requestFrom((uint8_t)BME280_ADDRESS,(uint8_t)3);
      
          value = _i2c->read();
          value <<= 8;
          value |= _i2c->read();
          value <<= 8;
          value |= _i2c->read();
          return value;
      }
      
      uint16_t read16_LE(byte reg) 
      {
        uint16_t temp = read16(reg);
        return (temp >> 8) | (temp << 8);
      }
      
      int16_t readS16(byte reg) 
      { 
        return (int16_t) read16(reg); 
      }
      
      int16_t readS16_LE(byte reg) 
      {
        return (int16_t) read16_LE(reg);
      }
      
      void readCoefficients() 
      {
        dig_T1  = read16_LE(BME280_REGISTER_DIG_T1);
        dig_T2  = readS16_LE(BME280_REGISTER_DIG_T2);
        dig_T3  = readS16_LE(BME280_REGISTER_DIG_T3);
      
        dig_P1  = read16_LE(BME280_REGISTER_DIG_P1);
        dig_P2  = readS16_LE(BME280_REGISTER_DIG_P2);
        dig_P3  = readS16_LE(BME280_REGISTER_DIG_P3);
        dig_P4  = readS16_LE(BME280_REGISTER_DIG_P4);
        dig_P5  = readS16_LE(BME280_REGISTER_DIG_P5);
        dig_P6  = readS16_LE(BME280_REGISTER_DIG_P6);
        dig_P7  = readS16_LE(BME280_REGISTER_DIG_P7);
        dig_P8  = readS16_LE(BME280_REGISTER_DIG_P8);
        dig_P9  = readS16_LE(BME280_REGISTER_DIG_P9);
      
        dig_H1 = read8(BME280_REGISTER_DIG_H1);
        dig_H2 = readS16_LE(BME280_REGISTER_DIG_H2);
        dig_H3 = read8(BME280_REGISTER_DIG_H3);
        dig_H4 = ((int8_t)read8(BME280_REGISTER_DIG_H4) << 4) | (read8(BME280_REGISTER_DIG_H4 + 1) & 0xF);
        dig_H5 = ((int8_t)read8(BME280_REGISTER_DIG_H5 + 1) << 4) | (read8(BME280_REGISTER_DIG_H5) >> 4);
        dig_H6 = (int8_t)read8(BME280_REGISTER_DIG_H6);
      }
      
      double get_Temperature() {
        int32_t var1, var2;
        int32_t adc_T = read24(BME280_REGISTER_TEMPDATA);
        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;
      
        double T = (t_fine * 5 + 128) >> 8;
        return T / 100;
      }
      
      double get_Pressure() {
        int64_t var1, var2, p;
        // Must be done first to get the t_fine variable set up
        get_Temperature();
      
        int32_t adc_P = read24(BME280_REGISTER_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 (double)p / 256;
      }
      
      double get_Humidity(void) {
        get_Temperature(); // must be done first to get t_fine
      
        int32_t adc_H = read16(BME280_REGISTER_HUMIDDATA);
        if (adc_H == 0x8000) // value in case humidity measurement was disabled
          return NAN;
      
        int32_t v_x1_u32r;
      
        v_x1_u32r = (t_fine - ((int32_t)76800));
      
        v_x1_u32r = (((((adc_H << 14) - (((int32_t)dig_H4) << 20) -
                        (((int32_t)dig_H5) * v_x1_u32r)) +
                       ((int32_t)16384)) >>
                      15) * (((((((v_x1_u32r * ((int32_t)dig_H6)) >> 10) *
                          (((v_x1_u32r * ((int32_t)dig_H3)) >> 11) + ((int32_t)32768))) >>
                         10) + ((int32_t)2097152)) * ((int32_t)dig_H2) + 8192) >> 14));
      
        v_x1_u32r = (v_x1_u32r - (((((v_x1_u32r >> 15) * (v_x1_u32r >> 15)) >> 7) * ((int32_t)dig_H1)) >> 4));
        v_x1_u32r = (v_x1_u32r < 0) ? 0 : v_x1_u32r;
        v_x1_u32r = (v_x1_u32r > 419430400) ? 419430400 : v_x1_u32r;
        double h = (v_x1_u32r >> 12);
        return h / 1024.0;
      }
      
      
      void reset_BME280()
      {
        write8(BME280_REGISTER_SOFTRESET , (uint8_t)0xB6);
      }
      

      Have fun with it. Let us know when there are improvements.
      Cheers,

      Jan

      1 Reply Last reply Reply Quote 0
      • P
        Powersoft
        last edited by

        Make an improvement in the main call routine. The return value of getBME280 is a boolean.
        now it is possible to check whether a BME280 is connected correctly.

        bool getBME280(TwoWire *theWire, double *t, double *p, double *h)
        {
          _i2c = theWire;
        
          /* check of BME280 is avilable */
          uint8_t value = read8(0xD0);  
          if (value == 0x60)                                    // BME280 detected
          {
            reset_BME280();                                     // Reset BME280      
            write8(BME280_REGISTER_CONTROLHUMID,(uint8_t)0x01); // Select control humidity register
            write8(BME280_REGISTER_CONTROL,     (uint8_t)0x27); // Select control measurement register
            write8(BME280_REGISTER_CONFIG,      (uint8_t)0xA0); // Select config register
            readCoefficients();                                 // Read coefficients from BME280
            *t = get_Temperature();                             // Get temperature
            *p = get_Pressure()/100.0;                          // Get pressure
            *h = get_Humidity();                                // Get Humidity
            return true;
          }
          else
          {
            return false;                                       // No BME280 detected
          }
        }
        

        Cheers,

        Jan

        1 Reply Last reply Reply Quote 0
        • First post
          Last post