Embedded System Journey #4: External Sensors (Temperature, Altitude, and Pressure)

Vincent Franstyo
8 min readMar 3, 2023

--

— Introduction🧠

Hi, I’m back again. Yes, it’s Vincent. Last week, we talked about ESP32 Internal sensors. If you haven’t read it, please kindly visit this page. If you have never dealt with ESP32, I highly recommend you to read all the blogs that I’ve posted before starting with this one. This week, guest what, we’re gonna talk about external sensors. The exact sensor we use in this experiment is the BMP280 sensors. You are actually free to choose either BMP280 or BMP180 or BME280. BME280 is the best sensor compared to the other two. However, it will tear your wallet down. I suggest you to get either BMP280 (6 legs) or BMP180 (4 legs). BMP280 is a sensor that will retrieve the data of the current temperature, altitude, and pressure. Let’s jump into it!!

— Components🤌🏻

This project actually only requires you to have the ESP32 and the BMP280 and some other small components, but I will list them down, so you won’t be confused.

The components are:

  • ESP32 Board DOIT DEVKIT V1
  • BMP280 (Pro tip: get the BMP280 soldered when you buy it)
  • 4 Male-to-male jumper cable / 4 Male-to-female jumper cable
  • breadboard (optional, but recommended)

I guess I have covered all the essentials (and don’t forget to have a PC capable of using Arduino IDE and Micro-USB to USB-A Cable). Let’s see how we will complete this challenge!

— Steps👣

As usual, we will look into Google for the reference. Here I use an unusual source since randomnerdstutorial do not have any reference for BMP280.

Basic Scheme
  1. Setting up the environment. We will be using external library, called Adafruit BMP280 Library. You can hover your mouse to Tools toolbar in Arduino IDE and click on Manage Libraries or you can just use Ctrl + Shift + I to open this view. Install the Adafruit BMP280 Library you found in the library manager.
  2. Let’s get into the circuit. As usual, push your ESP32 into the breadboard until none of the legs are seen anymore. Leave the right side (with 3V3 and GND pin) open.
  3. Install the BMP280 into the breadboard as shown above.
  4. Now we get into the wiring. I will attach an image below to make the wiring clearer. You can just follow the picture to know how the cable should be connected. You can use either male-to-male jumper cable or male-to-female jumper cable to connect them.
Adafruit BMP280 Library
Wiring between ESP32 and BMP280

Now, you are done :D We can go to through the code to understand it a little.

— Code Overview💻

This code is available through the library we installed before. You can hover to File Toolbar -> Examples -> Scroll down until you find Adafruit BMP280 test. SWOOSSHHH the code came out. 💨💨

#include <Wire.h>
#include <SPI.h>
#include <Adafruit_BMP280.h>

#define BMP_SCK (13)
#define BMP_MISO (12)
#define BMP_MOSI (11)
#define BMP_CS (10)

Adafruit_BMP280 bmp; // I2C
//Adafruit_BMP280 bmp(BMP_CS); // hardware SPI
//Adafruit_BMP280 bmp(BMP_CS, BMP_MOSI, BMP_MISO, BMP_SCK);

// const int ledPin3 = 4;
// const int ledPin1 = 5;
// const int ledPin2 = 23;

// double temp = 0;
// double alt = 0;
// double pressure = 0;

void setup() {
Serial.begin(9600);
while ( !Serial ) delay(100); // wait for native usb
Serial.println(F("BMP280 test"));
unsigned status;
//status = bmp.begin(BMP280_ADDRESS_ALT, BMP280_CHIPID);
status = bmp.begin(0x76);
if (!status) {
Serial.println(F("Could not find a valid BMP280 sensor, check wiring or "
"try a different address!"));
Serial.print("SensorID was: 0x"); Serial.println(bmp.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);
}

/* Default settings from datasheet. */
bmp.setSampling(Adafruit_BMP280::MODE_NORMAL, /* Operating Mode. */
Adafruit_BMP280::SAMPLING_X2, /* Temp. oversampling */
Adafruit_BMP280::SAMPLING_X16, /* Pressure oversampling */
Adafruit_BMP280::FILTER_X16, /* Filtering. */
Adafruit_BMP280::STANDBY_MS_500); /* Standby time. */

// pinMode(ledPin1, OUTPUT);
// pinMode(ledPin2, OUTPUT);
// pinMode(ledPin3, OUTPUT);
// pinMode(buttonPin, INPUT);
}

void loop() {
// buttonState = digitalRead(buttonPin);
Serial.print(F("Temperature = "));
Serial.print(bmp.readTemperature());

Serial.println(" *C");

Serial.print(F("Pressure = "));
Serial.print(bmp.readPressure());
Serial.println(" Pa");

Serial.print(F("Approx altitude = "));
Serial.print(bmp.readAltitude(1013.25)); /* Adjusted to local forecast! */
Serial.println(" m");

Serial.println();
temp = bmp.readTemperature();
pressure = bmp.readPressure();
alt = bmp.readAltitude(1013.25);

delay(2000);
}

Yeah I’m lazy to review this code I guess you can just understand them by yourself :D. The key is just to compile and upload it to your ESP32 and you’re done. Swoosh. The altitude, pressure, and temperature will show up in your serial monitor.

— Room for Errors💀

There was nothing showing up in my serial monitor at first. I thought I set the wrong baud for it. However, recompiling or changing up the series didn’t make any changes. I was confused and found no solution on the internet (or I didn’t dive deep enough). I read a senior’s medium and I found that I have to check the I2C address. I asked my friend who has finished it first. He gave me a link that might guide me through all the process. There, I found a code that will allow me to check the I2C address.

// --------------------------------------
// i2c_scanner
//
// Version 1
// This program (or code that looks like it)
// can be found in many places.
// For example on the Arduino.cc forum.
// The original author is not know.
// Version 2, Juni 2012, Using Arduino 1.0.1
// Adapted to be as simple as possible by Arduino.cc user Krodal
// Version 3, Feb 26 2013
// V3 by louarnold
// Version 4, March 3, 2013, Using Arduino 1.0.3
// by Arduino.cc user Krodal.
// Changes by louarnold removed.
// Scanning addresses changed from 0...127 to 1...119,
// according to the i2c scanner by Nick Gammon
// http://www.gammon.com.au/forum/?id=10896
// Version 5, March 28, 2013
// As version 4, but address scans now to 127.
// A sensor seems to use address 120.
// Version 6, November 27, 2015.
// Added waiting for the Leonardo serial communication.
//
//
// This sketch tests the standard 7-bit addresses
// Devices with higher bit address might not be seen properly.
//

#include <Wire.h>


void setup()
{
Wire.begin();

Serial.begin(9600);
while (!Serial); // Leonardo: wait for serial monitor
Serial.println("\nI2C Scanner");
}


void loop()
{
byte error, address;
int nDevices;

Serial.println("Scanning...");

nDevices = 0;
for(address = 1; address < 127; address++ )
{
// The i2c_scanner uses the return value of
// the Write.endTransmisstion to see if
// a device did acknowledge to the 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.print(address,HEX);
Serial.println(" !");

nDevices++;
}
else if (error==4)
{
Serial.print("Unknown 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); // wait 5 seconds for next scan
}

I compiled and uploaded the code to my ESP32 and it shows that my I2C address is at 0x76. I went back to the original code and look for a placeholder where I can input the address. I tried to input it to the status variable in the setup function and compiled it again. Magically, it worked!! 🤯🤯What a mindblowing discovery. You’ll now available to see the temperature, altitude, and pressure showing up in the serial monitor.

— Result🏁

Here’s how it should look like in the serial monitor. You will see the altitude, temperature, and pressure approximation made by the BMP280.

— Personal Experiment🧪

Here’s how the scheme would look like in real life.

With LEDs

I also altered the code a lil bit to match what I want. It’s just some if-else statement. I guess you should be able to understand it with noproblemo.

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

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

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_BMP280.h>

#define BMP_SCK (13)
#define BMP_MISO (12)
#define BMP_MOSI (11)
#define BMP_CS (10)

Adafruit_BMP280 bmp; // I2C
//Adafruit_BMP280 bmp(BMP_CS); // hardware SPI
//Adafruit_BMP280 bmp(BMP_CS, BMP_MOSI, BMP_MISO, BMP_SCK);

const int ledPin3 = 4;
const int ledPin1 = 5;
const int ledPin2 = 23;

double temp = 0;
double alt = 0;
double pressure = 0;

void setup() {
Serial.begin(9600);
while ( !Serial ) delay(100); // wait for native usb
Serial.println(F("BMP280 test"));
unsigned status;
//status = bmp.begin(BMP280_ADDRESS_ALT, BMP280_CHIPID);
status = bmp.begin(0x76);
if (!status) {
Serial.println(F("Could not find a valid BMP280 sensor, check wiring or "
"try a different address!"));
Serial.print("SensorID was: 0x"); Serial.println(bmp.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);
}

/* Default settings from datasheet. */
bmp.setSampling(Adafruit_BMP280::MODE_NORMAL, /* Operating Mode. */
Adafruit_BMP280::SAMPLING_X2, /* Temp. oversampling */
Adafruit_BMP280::SAMPLING_X16, /* Pressure oversampling */
Adafruit_BMP280::FILTER_X16, /* Filtering. */
Adafruit_BMP280::STANDBY_MS_500); /* Standby time. */

pinMode(ledPin1, OUTPUT);
pinMode(ledPin2, OUTPUT);
pinMode(ledPin3, OUTPUT);
// pinMode(buttonPin, INPUT);
}

void loop() {
// buttonState = digitalRead(buttonPin);
Serial.print(F("Temperature = "));
Serial.print(bmp.readTemperature());

Serial.println(" *C");

Serial.print(F("Pressure = "));
Serial.print(bmp.readPressure());
Serial.println(" Pa");

Serial.print(F("Approx altitude = "));
Serial.print(bmp.readAltitude(1013.25)); /* Adjusted to local forecast! */
Serial.println(" m");

Serial.println();
temp = bmp.readTemperature();
pressure = bmp.readPressure();
alt = bmp.readAltitude(1013.25);

if (temp > 27){
digitalWrite(ledPin1, HIGH);
Serial.println("Suhu tinggi (> 27)");
}
else{
digitalWrite(ledPin1, LOW);
}

if (pressure > 92563){
digitalWrite(ledPin2, HIGH);
Serial.println("Tekanan tinggi ");
}
else{
digitalWrite(ledPin2, LOW);
}

if (alt > 755){
digitalWrite(ledPin3, HIGH);
Serial.println("Terlalu tinggi");
}

else{
digitalWrite(ledPin3, LOW);
}

delay(2000);
}

— Result 🏁

Pressure Indicator :

Temperature Indicator:

Altitude indicator:

— Outro 👋🏻

IT’S A WRAP!! Thanks for staying tuned here. Imma still be uploading lots of article here. CIAO 🙋🏻‍♂️

--

--