Temperature, humidity and pressure readings in one chip? Certainly! The BME280.
I’ve recently spent more time than I care to think, trying to get a BME280 driver to work – finally done it by adapting some work from this fellow (Cosmin Plasoianu) who’s code is good but was out of date for the current Espressif SDK and also referred to another chip as so many bits of code do – the BMP280.
So what’s the difference? Well, the BMP280 is a modern temperature + atmospheric pressure chip – but it does NOT do what the lovely BME280 does – and that is humidity. In other words it can form a replacement for the DHT22 as long as you don’t mind using another wire (i2c). It responds quickly and is relatively accurate. The BME280 is also on a different I2c address to the BMP280. Anyway – all SORTED.
It is not cheap at nearly £4 but adding in pressure lets you do all sorts of weather-predicting stuff! As usual I limit accuracy to the nearest degrees C or percentage humidity because while seeing decimal points looks good – the ultimate accuracy does not warrant it.
I’ve updated the manual {temp_type:3} – and this uses i2c. The new command assuming GPIO4 and 5 are used for I2c and assuming there are pull-ups in use – this fills in the variables temperature, pressure and humidity which can be accessed as {temperature?} {pressure} and {humidity} as normal and are also generated automatically – see manual.
One more success for Home Control 2016.
I’ve finally gotten around to setting one of these up and getting it almost working. i2c_check reports 1 device on address 76. When I query temperature I get a response of 345 and when I query pressure I get 568 (which may or may not be right). {humidity?} produces zero.
I suppose it’s possible I have a bmP280 instead of a bmE, but wouldn’t that show at address 77? Also, any idea why the ridiculously high temperature? I’m not using hightemperature. It’s about 60 degrees F in here right now.
Thanks for all your hard work. I love reading your blog. I’m working on a project to teach myself electronics:, Arduino.ide, Linux, MQTT, a little bit of Python.
Working with my RaspberryPi 3b, Wemos D-1 Mini(ESP8266) and an Adafruit BME280.
Got most of it worked out. Having trouble publishing the actual sensor data to MQTT. I would also like to convert the data to an integer as the decimal percentages are negligible. Thanks. Here’s my code:
/*
WiFi BME280 humidity, temperature & pressure sensor (I2C)
Reports current weather data via Mosquitto MQTT, WiFi, Raspberry Pi3(b)
*/
//#include
#include
#include
//#include
#include
#include
#include
// 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”);
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);
}
}
}
// *********************************************************************************
void loop() {
if (!client.connected()) {
reconnect();
}
// ******************************************************************************
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”, “bme.readTemperature()”);
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();
}
Yes, Pete. I think I get it. Subscribe to each topic/data I want to send.
BME/Temp
BME/Humidity
BME/Hg
Convert data to a string.
Print String
Thanks.
You don’t HAVE to subscribe to the things you want to publish – you’d typically subscribe to them elsewhere…
The point being you COULD subscribe as you say..
BME/Temp
BME/Humidity
BME/Hg
OR subscribe to the lot and read the topic to differentiate
BME/#
On datasheet I found:
accuracy +- 0,5
repeatability +- 0,2
so in my opinion without decimal you loose in resolution.
Please also see a temperature log that I done with DHT22 where you can clearly see decimals in action.
https://s3.postimg.org/ele7n1zeb/Schermata_del_2016_08_17_07_58_54.png
I would decimal to control fancoils in my house (speed down fan speed when approaching target)
Regards
Fabio
Understand both points here about the accuracy etc… as I’ve used an integer for other chips – I’d have to break compatibility with existing stuff and change code to do this – not happy about that as I can see a barrage of gripes about temperature not working properly…. of course as the code is open to all, anyone who wishes to make that change can do so.
OK so to keep everyone happy – I’ve added a {hightemperature?} command to bring back the temperature * 10 – so you can use divide and mod to get your 0.1 degree.
I’ve also added an experiment – port expander on I2c GPIO4 and 5 – gives you (just simple out for now) extra outputs out17 to out24. I was getting sick of running out of outputs. See I2c and port expander – and I’ve updated the manual
Great !
Ok, please note the section on the right of the blog where it says “I don’t teach programming”.
And if you’re asking folk to look at something – it really would help if you only sent the relevant stuff so they don’t have to wade through everything.
In this case I’ll make an exception as I’ve had lots of help from people today..
client.publish(“BME280”, “bme.readTemperature()”);
I assume you did not wish to just send the text “bmw.readTemperature()” to MQTT but would prefer the value. That is text – nothing more – it isn’t going to tell you anything.
What you REALLY wanted to send, I’m guessing – is a string with the temperature in it.
So, here is one way to do it.. get the temperature (which is a number) into a string…
char myString[20];
sprintf(myString,”%d”,bmw.readTemperature());
client.publish(“BME280″, myString);
So let’s go through that while I’m here…
You define some space to put the string…. then use the sprintf function to get that numerical result into a string..
You could have just as easily put….
sprintf(myString,”Result is: %d”,bmw.readTemperature());
and you’d get something like “Result is: 22″ out. %d means substitute a decimal value.
Another way to do that – just to give you the flavour of sprintf..
sprintf(mystring,”%s %d”,”Result is:”,bmw.readTemperature());
Get the general idea, %s is a string, %d is a number, if you want a formatted number with 2 decimal points use %02d
And now the topic – your topic is FINE – but it’s a good idea to follow the way this is done generally – so your topic might be…
“bme280/temperature”
Why?
Because if you are also doing humidity, that might be “bme280/humidity”
If I’m not mistaken that chip does pressure as well so you could have “bme280/pressure”
And that makes sense and you could subscribe to either or all of those externally – or you could subscribe to “bme280/#” which is all three of them then read the topic to see which one it is.
– get the general idea???
Pete.
Hi Pete, long time reader but first time poster here!
I think you’re conflating precision and accuracy. Accuracy is how close the measured value is to the true value, while precision is how much noise there is in the output.
According to the datasheet, the BME280 is rated for an *accuracy* of +/- 0.5 C like you say, but the *precision* is much higher (RMS error of 0.005 C with automatic oversampling). In other words, at least the first decimal place reported is reliable. The range of the accuracy of the sensor is not a big deal, it can be calibrated out; it’s the precision you care about when determining how many decimal places are significant.
First of all thanks for your usefull work.
Today I tryed your firmware and I relly like it.
I noted that for DHT22 there wasnt decimals so I searched and found “As usual I limit accuracy to the nearest degrees C”.
Thare is an Easy way to see One decimal point? Would be usefull for temperature regulation.
Have a nice evening
The accuracy just does not warrant it.
And I quote – accuracy – temperature <+-0.5Celsius So it could be plus or minus 0.5c - a total range of 1 degree C.. Hence I go to the nearest degree.
And unless you are controlling a special oven – keeping a house to within one degree temperature would be a very neat trick indeed – and would involve a lot of turning on and off of the heating system.