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

    M5Paper and BME280 Sensor

    Scheduled Pinned Locked Moved PROJECTS
    2 Posts 1 Posters 4.9k Views
    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 Offline
      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 Offline
        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

        Hello! It looks like you're interested in this conversation, but you don't have an account yet.

        Getting fed up of having to scroll through the same posts each visit? When you register for an account, you'll always come back to exactly where you were before, and choose to be notified of new replies (either via email, or push notification). You'll also be able to save bookmarks and upvote posts to show your appreciation to other community members.

        With your input, this post could be even better 💗

        Register Login
        • First post
          Last post