M5Paper and BME280 Sensor



  • 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



  • 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