Wish Library wrapper for BME280 sensor

quique

Member
Licensed User
Longtime User
Hello!

I purchased a BME280 sensor, which delivers temperature, pressure and humidity with precision.

It is similar to the BMP280 and it's earlier "brother" the BMP180, but adds humidity, precision and less power consumption.

I've been trying to create a wrapper (you can peek at it on the rBME280.zip file) for the original Arduino lib which works like a charm on the arduino IDE (you can peek at it on the BME280.zip file).

The original Arduino BME280 library is Copyright (C) 2016 Tyler Glenn, which after checking almost every BME280 libraries out there, I decided it was the most interesting in terms of functionality.

This is the code I have successfully run through Arduino IDE, in order to test the sensor, which uses an OLED screen to show the results:

B4X:
/*
Connecting the BME280 Sensor:
Sensor              ->  Board
-----------------------------
Vin (Voltage In)    ->  3.3V
Gnd (Ground)        ->  Gnd
SDA (Serial Data)   ->  A4 on Uno/Pro-Mini, 20 on Mega2560/Due, 2 Leonardo/Pro-Micro
SCK (Serial Clock)  ->  A5 on Uno/Pro-Mini, 21 on Mega2560/Due, 3 Leonardo/Pro-Micro
 ==== Includes ==== */
#include <BME280.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#include <Wire.h>             // Needed for legacy versions of Arduino.
/* ==== Defines ==== */
#define SERIAL_BAUD 115200
#define OLED_RESET 4
Adafruit_SSD1306 display(OLED_RESET);
/* ==== Global Variables ==== */
BME280 bme;                   // Default : forced mode, standby time = 1000 ms
                              // Oversampling = pressure ×1, temperature ×1, humidity ×1, filter off,
bool metric = true;
Adafruit_SSD1306 ssd;
float temp(NAN), hum(NAN), pres(NAN),altitude(NAN);
uint8_t pressureUnit(B001);    // unit: B000 = Pa, B001 = hPa, B010 = Hg, B011 = atm, B100 = bar, B101 = torr, B110 = N/m^2, B111 = psi
/* ==== Setup ==== */
void setup() {
  Serial.begin(SERIAL_BAUD);
  ssd.begin(0x3C);  // initialize with the I2C addr 0x3C (for the 128x32)
  while(!Serial) {} // Wait
  while(!bme.begin()){
    Serial.println("Could not find BME280 sensor!");
    delay(1000);
  }
}
/* ==== Loop ==== */
void loop() {
  bme.ReadData(pres, temp, hum, metric, pressureUnit); 
  ssd.clearDisplay();
  ssd.setTextSize(1);
  ssd.setTextColor(WHITE);
  ssd.setCursor(0,0);
  ssd.print("Tem ");
  ssd.print(temp);
  ssd.println(" "+ String(metric ? 'C' :'F'));
  ssd.print("Hum ");
  ssd.print(hum);
  ssd.println("%");
  ssd.print("Pre ");
  ssd.print(pres);
  ssd.println(" hPa");
  ssd.print("Alt ");
  altitude = bme.CalculateAltitude(metric);
  ssd.print(altitude);
  ssd.println(" m");
  ssd.display();
   delay(600);
}


And this is the code I've been trying on B4R, which ends up giving "nan" as result or even hanging up the Arduino:

B4X:
Sub Process_Globals

Public Serial1 As Serial

Private ssd AsAdafruitSSD1305

Private bme AsBME280

EndSub



Private Sub AppStart

'i2c: OLED 0x3C    bme280 0x76

ssd.InitializeI2C(6, 0x3C)

Serial1.Initialize(115200)

Log("AppStart1")

ssd.ClearDisplay

ssd.GFX.SetCursor(0, 0)

ssd.GFX.ConfigureText(1, ssd.WHITE, False)

  ssd.GFX.DrawText("Initializing BME280")

bme.Initialize()

ssd.ClearDisplay

ssd.GFX.SetCursor(0, 0)

ssd.GFX.ConfigureText(1, ssd.WHITE, False)

ssd.GFX.DrawText("TEMP: ").DrawText(bme.readTemperature)

ssd.GFX.SetCursor(0,10)

ssd.GFX.DrawText("HUMI: ").DrawText(bme.readHumidity)

ssd.GFX.SetCursor(0,20)

ssd.GFX.DrawText("PRES: ").DrawText(bme.readPressure)  

ssd.Display

EndSub


If anyone can give an idea on what I am doing wrong on the wrapper, I would be thankful. C++ and Arduino native coding is NOT my thing. I am at a loss on what it is exactly I've been doing, other than inspecting carefully other B4R wrappings and trying to translate the idea into this wrapper I've been working on for the past two days.

Thanks, and hopefully this sensor will gain adepts, as it s a very fast and precise little thing...

Enrique
 

Attachments

  • rBME280.zip
    6.2 KB · Views: 468
  • BME280.zip
    5.1 KB · Views: 520

Erel

B4X founder
Staff member
Licensed User
Longtime User
I actually played with a BME280 however I think that I burnt it as I wasn't able to get any value.

The pointer you are using doesn't point to anything.

Change your code to:
B4X:
private:
       uint8_t be[sizeof(BME280)];
       BME280* bme;

     public:
       //Initializes the object. Returns True if successful.
       bool Initialize();
       float ReadTemperature();
       float ReadPressure();
       float ReadHumidity();
   };
cpp file:
B4X:
bool B4RBME280::Initialize() {
     bme = new (be) BME280();
     return bme->begin();
   }
 

quique

Member
Licensed User
Longtime User
Hi Erel! Yes that is what happened to me, I tried for two days, replacing different arduino libraries while constructing the rBME280 wrapper, and in all cases I either got nothing, or the arduino hanged up. I actually thought I had burnt the BME280 somehow.

But when I try the reference code on the Arduino IDE, same library, it works fine :(

Adding your change, it just returns "nan" for temperature, pressure and humidity (as it did before). This actually means that the library and wrapper are working, as the "NAN" value comes programmatically from the arduino library itself:

If you peek into bme280.cpp, the "nan" value comes from each of those functions, after trying to read data from the sensor, if the data array comes empty, the function does an "early" return with "nan".

So it is like, under B4R, the sensor cannot be read, for some reason. As an example, let me copy and paste the part of the ReadHumidity() function on the arduino class, where you can see on the third line, the return NAN:

B4X:
float BME280::ReadHumidity(){
  int32_t data[8];
  int32_t t_fine;
  if(!ReadData(data)){ return NAN; }
  uint32_t rawTemp = (data[3] << 12) | (data[4] << 4) | (data[5] >> 4);
  uint32_t rawHumidity = (data[6] << 8) | data[7];
  CalculateTemperature(rawTemp, t_fine);
  return CalculateHumidity(rawHumidity, t_fine);
}

Weird, to say the least ! Maybe you can trace the problem into an obscure bug or idiosyncrasy inside the way that b4r compiles the code for the arduino. Hopefully this investigation is helpful !

Enrique
 

quique

Member
Licensed User
Longtime User
Hi Erel,

In the case of B4R, the call to ReadData is inside the native BME280.cpp library, Inside the function I pasted before, in this case the ReadHumidity function.

I cannot call the ReadData function used on the arduino IDE project directly from B4R because I think it is impossible: It returns 3 values inside three of the four variables which is called with.

The "extended" ReadData is not even wrapped on the library adaptation. In order to use B4R, and the wrapper implementation, calls for simpler functions, one for humidity, one for temperature, one for pressure, so each can return one value.

The wrapped library, as I told, seems to be working. Problem is, as I told, when ReadData is invoked internally, the library cannot access the byte array inside the BME280 sensor with the read results.

I will do some tests, first by passing arbitrary fixed values from inside the native library, and debugging it at hand. If I cannot fix it, at least I may be able to confirm my suspicion or get an exact idea on which line of code in the native library is not working.

I will keep investigating, if I can find somehting, I will post it.

Enrique
 
Top