Using BME280 to display temperature, humidity, and pressure with ESP32

zhil
7 min readFeb 27, 2022

In THIS ARTICLE, I will show you how I measured my room’s temperature, humidity, and pressure and display it on an LCD using ESP32. This little project is carried out under the guidance of the excellent Luqman Muhammad Zagi, S.T., M.T. of the Bandung Institute of Technology.

Prerequisites

  1. An ESP32 microcontroller, along with its vertebrate
  2. A BME280 Barometric Sensor
  3. A 16×2 LCD, complete with its I2C serial communication bus (soldered!)
  4. A breadboard
  5. A Micro-USB cord
  6. A few male-to-male jumper wires
  7. A few male-to-female jumper wires
  8. A few 3mm LEDs
  9. A few 330Ω resistors
  10. Arduino IDE installed for ESP32. I have made a detailed installation guide in my previous article: https://zhillan-arf.medium.com/blink-the-led-with-esp32-5c3f358ea2ff

Setting up the BME280

There are a few sensors available to measure the likes of humidity and temperature; the most popular in the market being the BME280 Barometric Sensor and its far cheaper (by like a magnitude of 10) “knock-off”, BMP280. The difference being BME280 is able to also measure humidity in addition to temperature and pressure, while BMP280 can only measure the latter two.

Being two different components, they use completely different libraries to run. Visually, though, they are incredibly similar.

Indeed the only noticeable, conclusive difference is the position of the pinhole on the small metal rectangle in the middle of either component. For this reason, anyone must be careful while buying, as they might be scammed by sellers who provided a BMP at the cost of a BME.

Now, the version of BME I used is compatible with both SPC and I2C communication protocols. Here, I used the I2C protocol.

This is the schematic necessary to use the BME:

  1. Connect ESP32’s GPIO22 to the BME280’s SCL pin (blue wire)
  2. Connect ESP32’s GPIO21 to the BME280’s SDA pin (green wire)
  3. Connect ESP32’s 3v3 power outlet to the BME32’s VCC pin (red wire)
  4. Connect ESP32’s GND to BME32’s GND (black wire)

My hardware-side is now ready, so I moved to installing the Adafruit_BME280 and Adafruit Unified Sensor library in my Arduino IDE to actually run the program. This is done by opening Sketch > Include Library > Manage Libraries and selecting the aforementioned library to install. Then, restart the IDE.

Reading the values

After this, I used a simple example from the library as the base code, found in File > Examples > Adafruit BME280 library > bme280 test.

I then plugged and compiled the code (which will be revealed later). However, when I ran it, apparently the program is unable to detect the BME.

It is time for troubleshooting.

First, I checked the wirings — after all, I might just miss a cable placement or four. After that is cleared, I then try to find the inbuilt I2C scanner’s address using this code:

#include <Wire.h>

void setup() {
Wire.begin();
Serial.begin(115200);
Serial.println("\nI2C Scanner");
}

void loop() {
byte error, address;
int nDevices;
Serial.println("Scanning...");
nDevices = 0;
for(address = 1; address < 127; address++ ) {
Wire.beginTransmission(address);
error = Wire.endTransmission();
if (error == 0) {
Serial.print("I2C device found at address 0x");
if (address<16) {
Serial.print("0");
}
Serial.println(address,HEX);
nDevices++;
}
else if (error==4) {
Serial.print("Unknow error at address 0x");
if (address<16) {
Serial.print("0");
}
Serial.println(address,HEX);
}
}
if (nDevices == 0) {
Serial.println("No I2C devices found\n");
}
else {
Serial.println("done\n");
}
delay(5000);
}

The eldritch revelation it displayed suggests a problem here.

However, it’s quite simple: mismatch in the baud rate. After it was debugged, the program was able to detect the I2C device.

The last information is important. Apparently, I have to plug in the address 0x76 to the bme entity. That is, the final code looks like this:

#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); // software SPI
unsigned long delayTime;
void setup() {
Serial.begin(9600);
while(!Serial); // time to get serial running
Serial.println(F(“BME280 test”));
unsigned status;

// default settings
status = bme.begin(0x76);
// You can also pass in a Wire library object like &Wire2
// status = bme.begin(0x76, &Wire2)
if (!status) {
Serial.println(“Could not find a valid BME280 sensor, check wiring, address, sensor ID!”);
Serial.print(“SensorID was: 0x”); Serial.println(bme.sensorID(),16);
Serial.print(“ ID of 0xFF probably means a bad address, a BMP 180 or BMP 085\n”);
Serial.print(“ ID of 0x56–0x58 represents a BMP 280,\n”);
Serial.print(“ ID of 0x60 represents a BME 280.\n”);
Serial.print(“ ID of 0x61 represents a BME 680.\n”);
while (1) delay(10);
}

Serial.println(“ — Default Test — “);
delayTime = 1000;
Serial.println();
}
void loop() {
printValues();
delay(delayTime);
}
void printValues() {
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();
}

After that, the program runs just fine!

Setting up the LCD

For the second part, I used a 16x2 LCD with I2C communication protocol. Which is a problem: this means that I need to set up two separate buses and I/O for both the BME and the LCD. I did this using Wire’s TwoWire entity. First, I set the pins as follows:

  1. Connect ESP32’s GPIO22 to the LCD’s SCL pin (brown wire)
  2. Connect ESP32’s GPIO21 to the LCD’s SDA pin (white wire)
  3. Connect ESP32’s GPIO4 to the BME280’s SCL pin (yellow wire)
  4. Connect ESP32’s GPIO5 to the BME280’s SDA pin (green wire)
  5. Connect ESP32’s 3v3 power outlet to the both component’s VCC pin (red wire)
  6. Connect ESP32’s GND to both component’s GND (black wire)

I then installed the LiquidCrystal_I2C library by johnrickman at https://github.com/johnrickman/LiquidCrystal_I2C . I downloaded the zip and put it in the library directory of my Arduino program directory, and restarted the IDE. After which, I ran this program to find the LCD’s address (note the TwoWire entity I used as the bus):

#include <Wire.h>//Set pins for LCD
#define LCD_SDA 5
#define LCD_SCL 4
//Set pins for BME
#define BME_SDA 21
#define BME_SCL 22
TwoWire I2C_LCD = TwoWire(0); //LCD bus
TwoWire I2C_BME = TwoWire(1); //BME bus
void setup() {
I2C_LCD.begin(LCD_SDA, LCD_SCL);
I2C_BME.begin(BME_SDA, BME_SCL);
Serial.begin(115200);
Serial.println(“\nI2C Scanner”);
}

void loop() {
byte error, address;
int nDevices;
Serial.println(“Scanning…”);
nDevices = 0;
for(address = 1; address < 127; address++ ) {
I2C_LCD.beginTransmission(address);
error = I2C_LCD.endTransmission();
if (error == 0) {
Serial.print(“I2C device found at address 0x”);
if (address<16) {
Serial.print(“0”);
}
Serial.println(address,HEX);
nDevices++;
}
else if (error==4) {
Serial.print(“Unknow error at address 0x”);
if (address<16) {
Serial.print(“0”);
}
Serial.println(address,HEX);
}
}
if (nDevices == 0) {
Serial.println(“No I2C devices found\n”);
}
else {
Serial.println(“done\n”);
}
delay(5000);
}

Now, I modified the code to get the BME’s address:

I can thus start to actually use those components. First, I will test the LCD by displaying “Hello, world!”. The result was really faint, however; I was unable to turn down the backlight (for now).

Connecting the BME to the LCD

Lastly, I combined the two and created this code:

#include <Wire.h>
#include <SPI.h>
#include <Adafruit_Sensor.h>
#include <Adafruit_BME280.h>
#include <LiquidCrystal_I2C.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; // I2
// set the LCD number of columns and rows
int lcdColumns = 16;
int lcdRows = 2;
// set LCD address, number of columns and rows
LiquidCrystal_I2C lcd(0x27, lcdColumns, lcdRows);
unsigned long delayTime;void setup() {
Serial.begin(9600);
// initialize LCD
lcd.init();
// turn on LCD backlight
lcd.backlight();
while(!Serial); // time to get serial running
Serial.println(F(“BME280 test”));
unsigned status;

// default settings
status = bme.begin(0x76);
// You can also pass in a Wire library object like &Wire2
// status = bme.begin(0x76, &Wire2)
if (!status) {
Serial.println(“Could not find a valid BME280 sensor, check wiring, address, sensor ID!”);
Serial.print(“SensorID was: 0x”); Serial.println(bme.sensorID(),16);
Serial.print(“ ID of 0xFF probably means a bad address, a BMP 180 or BMP 085\n”);
Serial.print(“ ID of 0x56–0x58 represents a BMP 280,\n”);
Serial.print(“ ID of 0x60 represents a BME 280.\n”);
Serial.print(“ ID of 0x61 represents a BME 680.\n”);
while (1) delay(10);
}

Serial.println(“ — Default Test — “);
delayTime = 1000;
Serial.println();
}
void loop() {
printValues();
delay(delayTime);
}
void printValues() {
// Temperature
lcd.setCursor(0, 0);
lcd.print(“Temp. (°C)”);
lcd.setCursor(0,1);
lcd.print(bme.readTemperature());
delay(1000);
lcd.clear();
// Pressure
lcd.setCursor(0, 0);
lcd.print(“Press. (hPa)”);
lcd.setCursor(0,1);
lcd.print(bme.readPressure() / 100.0F);
delay(1000);
lcd.clear();
// Altitude
lcd.setCursor(0, 0);
lcd.print(“Alt. (m)”);
lcd.setCursor(0,1);
lcd.print(bme.readAltitude(SEALEVELPRESSURE_HPA));
delay(1000);
lcd.clear();
// Humidity
lcd.setCursor(0, 0);
lcd.print(“Hum. (%)”);
lcd.setCursor(0,1);
lcd.print(bme.readHumidity());
delay(1000);
lcd.clear();
}

And voila! It worked! (It’s really faint but I promise it’s there if you look hard enough).

Well, that is all for me! See you later, bye-onara~.

--

--