[SOLVED] Adafruit BME280 Temp, Humidity, Barometric pressure sensor

Hey guys. I just got this sensor in the mail, thought I’d give it a go.
Was able to download and install the github files for Adafruit_Sensors.h, and Adafruit_BME library.
Compiled and uploaded just fine.

Should be fairly simple, but this is the error I get on the serial monitor:

BME280 test
Could not find a valid BME280 sensor, check wiring!

I swapped the SDI/O pins thinking maybe I got them wrong
I just want to see it work for now. I plan to tweak the sketch a bit later to add in an OLED display and run on a WEMOS D1 mini but for now…

Example sketch:

/***************************************************************************
  This is a library for the BME280 humidity, temperature & pressure sensor

  Designed specifically to work with the Adafruit BME280 Breakout
  ----> http://www.adafruit.com/products/2650

  These sensors use I2C or SPI to communicate, 2 or 4 pins are required
  to interface.

  Adafruit invests time and resources providing this open source code,
  please support Adafruit andopen-source hardware by purchasing products
  from Adafruit!

  Written by Limor Fried & Kevin Townsend for Adafruit Industries.
  BSD license, all text above must be included in any redistribution
 ***************************************************************************/

#include <Wire.h>
#include <SPI.h>
#include <Adafruit_Sensor.h>
#include <Adafruit_BME280.h>

#define BME_SCK 13
#define BME_MISO 12
#define BME_MOSI 11
#define BME_CS 10

#define SEALEVELPRESSURE_HPA (1013.25)

Adafruit_BME280 bme; // I2C
//Adafruit_BME280 bme(BME_CS); // hardware SPI
//Adafruit_BME280 bme(BME_CS, BME_MOSI, BME_MISO,  BME_SCK);

void setup() {
  Serial.begin(9600);
  Serial.println(F("BME280 test"));

  if (!bme.begin()) {
    Serial.println("Could not find a valid BME280 sensor, check wiring!");
    while (1);
  }
}

void loop() {
  Serial.print("Temperature = ");
  Serial.print(bme.readTemperature());
  Serial.println(" *C");

  Serial.print("Pressure = ");

  Serial.print(bme.readPressure() / 100.0F);
  Serial.println(" hPa");

  Serial.print("Approx. Altitude = ");
  Serial.print(bme.readAltitude(SEALEVELPRESSURE_HPA));
  Serial.println(" m");

  Serial.print("Humidity = ");
  Serial.print(bme.readHumidity());
  Serial.println(" %");

  Serial.println();
  delay(2000);
}

Run the I2C scanner to make sure that the sensor is on the bus and to confirm sensor address.

// I2C scanner by Nick Gammon.  Thanks Nick.

#include <Wire.h>

void setup() {
  Serial.begin (115200);  // make sure the serial monitor baud rate matches

  // Leonardo: wait for serial port to connect
  while (!Serial) 
    {
    }

  Serial.println ();
  Serial.println ("I2C scanner. Scanning ...");
  byte count = 0;
  
  Wire.begin();
  for (byte i = 1; i < 120; i++)
  {
    Wire.beginTransmission (i);
    if (Wire.endTransmission () == 0)
      {
      Serial.print ("Found address: ");
      Serial.print (i, DEC);
      Serial.print (" (0x");
      Serial.print (i, HEX);
      Serial.println (")");
      count++;
      delay (1);  // maybe unneeded?
      } // end of good response
  } // end of for loop
  Serial.println ("Done.");
  Serial.print ("Found ");
  Serial.print (count, DEC);
  Serial.println (" device(s).");
}  // end of setup

void loop() {}

To which type of Arduino and how did you connect the sensor?

Uploaded I2C scanner...

I2C scanner. Scanning ... Done. Found 0 device(s).

Arduino Uno 13 - SCK 12 - SDO 11 - SDI 10 - CS

3.3V - VIN GND - GND

Adafruit_BME280 bme; // I2C
//Adafruit_BME280 bme(BME_CS); // hardware SPI
//Adafruit_BME280 bme(BME_CS, BME_MOSI, BME_MISO,  BME_SCK);

You have it wired for SPI?
If you are going to use SPI you need to comment out the I2C line and uncomment the hardware SPI line.

Time for new glasses!

That worked. Thank you

Converted Temp to fahrenheit, adjusted altitude.

Tricky part would be to poll a local weather station for sea level pressure daily to adjust automatically.

/***************************************************************************
  This is a library for the BME280 humidity, temperature & pressure sensor

  Designed specifically to work with the Adafruit BME280 Breakout
  ----> http://www.adafruit.com/products/2650

  These sensors use I2C or SPI to communicate, 2 or 4 pins are required
  to interface.

  Adafruit invests time and resources providing this open source code,
  please support Adafruit andopen-source hardware by purchasing products
  from Adafruit!

  Written by Limor Fried & Kevin Townsend for Adafruit Industries.
  BSD license, all text above must be included in any redistribution
 ***************************************************************************/

#include <Wire.h>
#include <SPI.h>
#include <Adafruit_Sensor.h>
#include <Adafruit_BME280.h>

#define BME_SCK 13
#define BME_MISO 12
#define BME_MOSI 11
#define BME_CS 10

#define SEALEVELPRESSURE_HPA (1013.25)

//Adafruit_BME280 bme; // I2C
Adafruit_BME280 bme(BME_CS); // hardware SPI
//Adafruit_BME280 bme(BME_CS, BME_MOSI, BME_MISO,  BME_SCK);

void setup() {
  Serial.begin(9600);
  Serial.println(F("BME280 test"));

  if (!bme.begin()) {
    Serial.println("Could not find a valid BME280 sensor, check wiring!");
    while (1);
  }
}

void loop() {
    Serial.print("Temperature = ");
    Serial.print(bme.readTemperature()* 9/5 + 32);// (reads in C) C * 9/5 + 32 to convert to "F"
    Serial.println(" *F");

    Serial.print("Pressure = ");

    Serial.print(bme.readPressure() / 100.0F);
    Serial.println(" hPa");

//    Serial.print("Approx. Altitude = ");
//    Serial.print(bme.readAltitude(SEALEVELPRESSURE_HPA)+4);//   +4 to correct altitude
//    Serial.println(" m");

    Serial.print("Humidity = ");
    Serial.print(bme.readHumidity());
    Serial.println(" %");

    Serial.println();
    delay(2000);
}

Hey guys…

Pulled the sensor out of the box and I’m excited. Got it connected via I2C. It’s sending Temp Humidity and Pressure readings via serial print. What I want now is to send the sensor data via MQTT.

I’ve seen several examples. 1 says to convert to String or char

Another gives an example as sprintf

int Temp = bme.readTemperature();
int Humidity = bme.readHumidity();
int Hpa = bme.readPressure();

sprintf(“Temp”, “%d”, "Temp: ", bme.readTemperature());
client.publish(“BME280/Temp”, Temp);

VERY confusing to me since I’m not an everyday coder.

Best practices? What do you advise for publishing sensor data via MQTT?

Thanks

/*
   WiFi BME280 humidity, temperature & pressure sensor (I2C)
   Reports current weather data via Mosquitto MQTT, WiFi, Raspberry Pi3(b)
*/

//#include <EEPROM.h>
#include <ESP8266WiFi.h>
#include <PubSubClient.h>
//#include <Wire.h>
#include <SPI.h>
#include <Adafruit_Sensor.h>
#include <Adafruit_BME280.h>


// ASSIGN PINS  **************************************************
#define BME_SCK D1;//
//#define BME_MISO 12//
//#define BME_MOSI 11//
#define BME_CS D2;//

#define SEALEVELPRESSURE_HPA (1013.25)

Adafruit_BME280 bme; // I2C
//Adafruit_BME280 bme(BME_CS); // hardware SPI
//Adafruit_BME280 bme(BME_CS, BME_MOSI, BME_MISO,  BME_SCK);

// Connect to the WiFi
const char* ssid = "MYSSID";
const char* password = "MYPASSWORD";
const char* mqtt_server = "192.168.0.140";

WiFiClient espClient;
PubSubClient client(espClient);



boolean reconnect() {  // **********************************************************
  // Loop until we're reconnected
  while (!client.connected()) {
    Serial.print (F("Contacting MQTT server..."));
    // Attempt to connect
    if (client.connect("BME280")) {     //assign a "client name".  Each wemos must have a unique name
      Serial.println (F("connected"));

      // ... SUBSCRIBE TO TOPICS
      client.subscribe("BME280/Temp");//                  Is this the
      client.subscribe("BME280/Humidity");//             correct way
      client.subscribe("BME280/Hpa");//                    of doing this  or
      // client.subscribe("BME280");//                        This way?



      return client.connected();

      Serial.print (F("Failed to connect. "));
      Serial.println (F(" Attempting connection again in 3 seconds"));
      // Wait 3 seconds before retrying
      delay(3000);
      return 0;
    }
  }
}


void setup()
{
  {
    Serial.begin(9600);
    client.setServer(mqtt_server, 1883);
  }

  // Connect to WiFinetwork
  Serial.println();
  Serial.println();
  Serial.print (F("Connecting to "));
  Serial.println(ssid);

  WiFi.begin(ssid, password);
  WiFi.mode(WIFI_STA);
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    //Serial.begin(9600);
    Serial.print (F("."));
  }
  Serial.println (F(""));
  Serial.println (F("WiFi connected"));
  // Print the IP address
  Serial.print (F("Local IP: "));
  Serial.println(WiFi.localIP());


  //  *****************************************************************************
  {
    Serial.begin(9600);
    Serial.println(F("My weather station"));

    if (!bme.begin()) {
      Serial.println("Could not find a valid BME280 sensor, check wiring!");
      while (1);
    }
  }
}

//  *********************************************************************************
//  Convert BME280 saensor reading into string
float Temp;
float Humidity;
float Hg;


void loop() {
  if (!client.connected()) {
    reconnect();
  }


  //  ******************************************************************************

  int Temp = bme.readTemperature();
  int Humidity = bme.readHumidity();
  int Hpa = bme.readPressure();



  sprintf("Temp", "%d", "Temp: ", bme.readTemperature());
  client.publish("BME280/Temp", Temp);


  Serial.print("Temperature = ");
  Serial.print(bme.readTemperature() * 9 / 5 + 32); // (reads in C) C * 9/5 + 32 to convert to "F"
  Serial.println(" *F");
  client.publish("BME280/Temp", Temp);//    as you can see, I'm lost


  Serial.print("Pressure = ");

  Serial.print(bme.readPressure() / 100.0F);
  Serial.println(" hPa");
  client.publish("BME280", "bme.readPressure()");


  //    Serial.print("Approx. Altitude = ");
  //    Serial.print(bme.readAltitude(SEALEVELPRESSURE_HPA)+4);//   +4 to correct altitude
  //    Serial.println(" m");

  Serial.print("Humidity = ");
  Serial.print(bme.readHumidity());
  Serial.println(" % ");
  client.publish("BME280", "bme.readHumidity()");

  Serial.println();
  delay(10000);

  // *****************************************************************************

  client.loop();
}
sprintf("Temp", "%d", "Temp: ", bme.readTemperature());

That one won't work.

The first parameter to sprintf is a buffer to hold the resulting string, the second is the format string (correct in your example) and the rest are the parameters as specified in the format string. This would be correct if you omit the third parameter you specified. To make your code reliable you should only use the snprintf() version of that function as it limits the result to the size of the buffer.

When I uncomment the other sprintf, I don’t get anything printed out.
I can’t seem to get solid numbers via MQTT. See below code.

//  Convert BME280 saensor reading into string
float Temp;
float Humidity;
float Hg;


void loop() {
  if (!client.connected()) {
    reconnect();
  }


  //  ******************************************************************************

  int Temp = bme.readTemperature();
  int Humidity = bme.readHumidity();
  int Hpa = bme.readPressure();


  sprintf("Temp", "%d", bme.readTemperature()); //  THIS COMPILED, LEAVE IT
  //  sprintf("Humidity", "%d", bme.readHumidity());
  //  sprintf("Hpa", "%d", bme.readPressure());


  Serial.print("Temperature = ");
  Serial.print(bme.readTemperature() * 9 / 5 + 32); // (reads in C) C * 9/5 + 32 to convert to "F"
  Serial.println(" *F");
  client.publish("BME280/Temp", "Temp");


  Serial.print("Pressure = ");

  Serial.print(bme.readPressure() / 100.0F);
  Serial.println(" hPa");
  client.publish("BME280/Hpa", "Hpa");


  //    Serial.print("Approx. Altitude = ");
  //    Serial.print(bme.readAltitude(SEALEVELPRESSURE_HPA)+4);//   +4 to correct altitude
  //    Serial.println(" m");

  Serial.print("Humidity = ");
  Serial.print(bme.readHumidity());
  Serial.println(" % ");
  client.publish("BME280/Humidity", "Humidity");

  Serial.println();
  delay(10000);

mqtt.JPG

snprintf("Temp", "%d", bme.readTemperature()); doesn't compile. Errors:

Arduino: 1.8.4 (Windows 7), Board: "WeMos D1 R2 & mini, 80 MHz, 921600, 4M (3M SPIFFS)"

Build options changed, rebuilding all
C:\Users\User\Documents\Arduino\mqttTempSensor5\mqttTempSensor5.ino: In function 'void loop()':

mqttTempSensor5:121: error: invalid conversion from 'const char*' to 'size_t {aka unsigned int}' [-fpermissive]

   snprintf("Temp", "%d", bme.readTemperature()); // 

                                               ^

mqttTempSensor5:121: error: cannot convert 'float' to 'const char*' for argument '3' to 'int snprintf(char*, size_t, const char*, ...)'

Multiple libraries were found for "Adafruit_Sensor.h"
 Used: C:\Users\User\Documents\Arduino\libraries\Adafruit_Sensor
 Not used: C:\Program Files (x86)\Arduino\libraries\Adafruit_Sensor
Multiple libraries were found for "Adafruit_BME280.h"
 Used: C:\Program Files (x86)\Arduino\libraries\Adafruit_BME280
 Not used: C:\Users\User\Documents\Arduino\libraries\Adafruit_BME280_Library
Multiple libraries were found for "PubSubClient.h"
 Used: C:\Users\User\Documents\Arduino\libraries\pubsubclient-2.6
 Not used: C:\Program Files (x86)\Arduino\libraries\pubsubclient-2.6
exit status 1
invalid conversion from 'const char*' to 'size_t {aka unsigned int}' [-fpermissive]

This report would have more information with
"Show verbose output during compilation"
option enabled in File -> Preferences.

Did you read my description? Is "Temp" a buffer to hold the resulting string? No.

Try this:

#define INT_STR_SIZE 8
char buffer[INT_STR_SIZE];
snprintf(buffer, INT_STR_SIZE, "%d", bme.readTemperatur());

One search for "snprintf" on the Internet would have shown you a reference page that also contains examples. You don't seem to have much motivation to learn something...

I thought the buffer came from this

// Convert BME280 sensor reading into string float Temp; float Humidity; float Hg;

Obviously not...

I don’t like just copy & pasting without fully understanding. I “Semi-understand” this:

#define INT_STR_SIZE 8
  char buffer[INT_STR_SIZE];
  snprintf(buffer, INT_STR_SIZE, "%d", bme.readTemperature());

  Serial.print("Temperature = ");
  Serial.print(bme.readTemperature() * 9 / 5 + 32); // (reads in C) C * 9/5 + 32 to convert to "F"
  Serial.println(" *F");
   client.publish("BME280/Temp", buffer);//  "MQTT TOPIC", buffer data?

I suspect i’m not using the buffer correctly in the last line: client.publish(“BME280/Temp”, buffer);

I’m still getting 0 for the temperature

I Tried: client.publish(“BME280/Temp”, bme.readTemperature);
Got the following error codes:

Arduino: 1.8.4 (Windows 7), Board: "WeMos D1 R2 & mini, 80 MHz, 921600, 4M (3M SPIFFS)"

C:\Users\User\Documents\Arduino\mqttTempSensor5\mqttTempSensor5.ino: In function 'void loop()':

mqttTempSensor5:120: error: no matching function for call to 'PubSubClient::publish(const char [12], <unresolved overloaded function type>)'

   client.publish("BME280/Temp", bme.readTemperature);

                                                    ^

C:\Users\User\Documents\Arduino\mqttTempSensor5\mqttTempSensor5.ino:120:52: note: candidates are:

In file included from C:\Users\User\Documents\Arduino\mqttTempSensor5\mqttTempSensor5.ino:8:0:

C:\Users\User\Documents\Arduino\libraries\pubsubclient-2.6\src/PubSubClient.h:130:12: note: boolean PubSubClient::publish(const char*, const char*)

    boolean publish(const char* topic, const char* payload);

            ^

C:\Users\User\Documents\Arduino\libraries\pubsubclient-2.6\src/PubSubClient.h:130:12: note:   no known conversion for argument 2 from '<unresolved overloaded function type>' to 'const char*'

C:\Users\User\Documents\Arduino\libraries\pubsubclient-2.6\src/PubSubClient.h:131:12: note: boolean PubSubClient::publish(const char*, const char*, boolean)

    boolean publish(const char* topic, const char* payload, boolean retained);

            ^

C:\Users\User\Documents\Arduino\libraries\pubsubclient-2.6\src/PubSubClient.h:131:12: note:   candidate expects 3 arguments, 2 provided

C:\Users\User\Documents\Arduino\libraries\pubsubclient-2.6\src/PubSubClient.h:132:12: note: boolean PubSubClient::publish(const char*, const uint8_t*, unsigned int)

    boolean publish(const char* topic, const uint8_t * payload, unsigned int plength);

            ^

C:\Users\User\Documents\Arduino\libraries\pubsubclient-2.6\src/PubSubClient.h:132:12: note:   candidate expects 3 arguments, 2 provided

C:\Users\User\Documents\Arduino\libraries\pubsubclient-2.6\src/PubSubClient.h:133:12: note: boolean PubSubClient::publish(const char*, const uint8_t*, unsigned int, boolean)

    boolean publish(const char* topic, const uint8_t * payload, unsigned int plength, boolean retained);

            ^

C:\Users\User\Documents\Arduino\libraries\pubsubclient-2.6\src/PubSubClient.h:133:12: note:   candidate expects 4 arguments, 2 provided

Multiple libraries were found for "PubSubClient.h"
 Used: C:\Users\User\Documents\Arduino\libraries\pubsubclient-2.6
 Not used: C:\Program Files (x86)\Arduino\libraries\pubsubclient-2.6
Multiple libraries were found for "Adafruit_Sensor.h"
 Used: C:\Users\User\Documents\Arduino\libraries\Adafruit_Sensor
 Not used: C:\Program Files (x86)\Arduino\libraries\Adafruit_Sensor
Multiple libraries were found for "Adafruit_BME280.h"
 Used: C:\Program Files (x86)\Arduino\libraries\Adafruit_BME280
 Not used: C:\Users\User\Documents\Arduino\libraries\Adafruit_BME280_Library
exit status 1
no matching function for call to 'PubSubClient::publish(const char [12], <unresolved overloaded function type>)'

This report would have more information with
"Show verbose output during compilation"
option enabled in File -> Preferences.

I also tried increasing the buffer size from 8 to 25 but it still reads 0

Can I give the buffer a name, in this case; “Temp”, then “Hpa” and “Humidity”? or do I just use it “in-line” and the buffer data gets replaced for each instance as the program runs?

Thank you for your time with me, it is appreciated!

In trying to better understand the new function(new to me), I found this:

http://en.cppreference.com/w/cpp/io/c/fprintf

in the top section, int snprintf( char* buffer, std::size_t buf_size, const char* format, ... );

does that mean it converts it to an integer? That would solve my other problem. The decimal percentage in temperature is negligible unless used for calibration or scientific use.

As used in my sketch: snprintf(buffer, INT_STR_SIZE, "%d", bme.readTemperatur()); the %d is the same thing? or if I don't want a decimal, would I use %d0 ? Just to carry that thought out further... %d2 would carry that decimal to hundredths?

Can I give the buffer a name, in this case; "Temp", then "Hpa" and "Humidity"? or do I just use it "in-line" and the buffer data gets replaced for each instance as the program runs?

Either way. Giving each buffer a name if it is inside of a function makes the buffer local in scope so when the function is done, the memory is released. Making 3 global scope variables would use more memory. In any case the buffer must be sized to hold the right number of elements. So individual buffers could be sized for their use, a single buffer would need to be sized for the largest number of elements ever expected.

client.publish("BME280/Temp", bme.readTemperature);

You left the () off of the readTemperature() function. Without the () you are sending the publish method a pointer. The publish method has no version (overload) to handle a pointer, therefore the error.

groundFungus: You left the () off of the readTemperature() function. Without the () you are sending the publish method a pointer. The publish method has no version (overload) to handle a pointer, therefore the error.

Damn. Thank you for pointing that out. Well, that brings me back to the "Float" instead of the buffer. I hope I stated that correctly Then, I thought "well, let's try that with the buffer". client.publish("BME280/Temp", buffer());// "MQTT TOPIC", buffer data?

No then, I get an error that you can't assign buffer as a function.

I get assigning the buffer size to largest size if used as "global". My sketch is only using 20% of memory, I think I can get away with the individual naming of buffers, but then I'm thinking "Why would I do that". From someone with more experience, in my case with possibly only 3 buffers (Temp, Humidity, and Hpa) would this sound feasible, or should I just stick with the global buffer?

AND

I think I've "somewhat" tackled the buffer part, now on to MQTT "publish" to properly publish Temperature readings.

Thanks for all the help guys. Sorry if I'm a bit slow to catch on.

Here’s the current sketch:

#define INT_STR_SIZE 256
  char buffer[INT_STR_SIZE];
  snprintf(buffer, INT_STR_SIZE, "%d2", bme.readTemperature()); // (reads in C) C * 9/5 + 32 to convert to "F"
  Serial.print("Temperature = ");
  Serial.print(bme.readTemperature() * 9 / 5 + 32); // (reads in C) C * 9/5 + 32 to convert to "F"
  Serial.println(" *F");
  client.publish("BME280/Temp", buffer);//  "MQTT TOPIC", buffer data?

Still not getting the temperature that shows up on Serialprint
Putty/MQTT:
mqtt.JPG

Serialprint:
Serialprint.JPG

Let's try to show the same value on both interfaces:

#define INT_STR_SIZE 16
  char buffer[INT_STR_SIZE];
  dtostrf(9.0 * bme.readTemperature() / 5.0 + 32.0, 1, 2, buffer);
  Serial.print("Temperature = ");
  Serial.print(buffer);
  Serial.println(" *F");
  client.publish("BME280/Temp", buffer);

Please post the results in Serial Monitor and MQTT.

Edit: Accidentally used %f in format string but Arduino doesn't know that. Fixed with dtostrf().

Sorry, long day at work. Yes-sir, that worked! Thank you.
MQTT/Putty:
MQTT_Putty.JPG

Serialprint:
SerialPrint.JPG

I’m going to play with it a bit to understand it better. Then, see if I can print out the Pressure and Humidity myself.

Thank you all soo much.