Embedded System #4 — ESP32 with External Sensor

Syafiq Ziyadul Arifin
6 min readFeb 23, 2023

--

Hi, it’s me again, Syafiq Ziyadul Arifin, also known as Safiq. In this fourth project (get the list here), I am excited to show you how to use the BMP280 sensor to gather data such as temperature, pressure, and altitude. This sensor is a valuable addition to your ESP32 toolkit, and I can’t wait to help you learn how to use it effectively. So, let’s dive in!

Components Used:

  • ESP32 Devkit V1
  • Data cable (USB type A to Micro B)
  • BMP280 (you can also use either BME280, with humidity sensor, or BMP180)
  • Jumper cables (male to male and male to female)
  • 2k2 Ω resistors
  • Seven segment displays
  • Breadboard

BMP280 Library

Installing the library is easy. Simply access the Library Manager in your Arduino IDE, search for “BMP280”, and then select the Adafruit BMP280 Library by Adafruit. From there, click on the “Install” button, and wait for the installation process to complete.

In case you encounter any issues with the Library Manager, you can download the latest version of the library from https://github.com/adafruit/Adafruit_BMP280_Library/releases (zip) instead. Once downloaded, go to Sketch > Include Library > Add .ZIP Library… and select the zip file. Additionally, make sure to install the dependent libraries as well, namely https://github.com/adafruit/Adafruit_BusIO/releases and https://github.com/adafruit/Adafruit_Sensor/releases.

Seven Segment Display

A seven segment display is a type of electronic display device that consists of seven individually illuminated segments shaped like an eight, with an additional segment for a decimal point. There are two types of seven-segment displays, namely, the common anode and common cathode displays. The primary difference between the two is the center pins of each side, where the common anode display is connected to Vcc (+), while the common cathode display is connected to Gnd (-).

In this project, I am using a common anode display to show the temperature readings obtained from BMP280. In order to display the correct number, I am using a binary method to store the state for each segment. This will ensure that the correct segment is illuminated to display the corresponding number.

Circuit

After installing the necessary libraries, the next step is to create the circuit. However, since the Wokwi simulator doesn’t have the BMP280 sensor, we will create the circuit without it. You can get the circuit here.

Additionally, you will need to add four male-to-female jumper wires. One wire should connect the VCC pin from the BMP280 to the positive rail in the breadboard, while another should connect the GND pin to the negative rail. The remaining two wires should connect the SCL and SDA pins.*2 Follow these simple steps to build the circuit:

  1. Connect a jumper wire from the 3V3 and GND pins on the ESP32 to the positive and negative rails, respectively, on the breadboard.
  2. Connect 8 digital pins for each seven segment display. Don’t forget to add a resistor between the connections to prevent excessive current flow. Currently, 2k2 Ω resistors are used, but you can use any resistors higher than 300 Ω.
  3. Connect the center pins of each seven segment display to the positive rail to ensure that the display can light up properly.
  4. Connect the VCC pin of the BMP280 to the positive rail and the GND pin to the negative rail.
  5. Finally, connect the SCL and SDA pins to digital pins 22 and 21, respectively, to allow the sensor to communicate with the ESP32.

Code

This is the code I have developed:

#include <Adafruit_Sensor.h>
#include <Adafruit_BMP280.h>

// constants won't change. They're used here to set pin numbers, etc.
const int pinSS[2][8] = {{33, 32, 12, 14, 27, 25, 26, 13}, {5, 17, 4, 2, 15, 18, 19, 16}};
// segments: a, b, c, d, e, f, g, dp
const int hexNumber[] = {0x3F, 0x06, 0x5B, 0x4F, 0x66, 0x6D, 0x7D, 0x07, 0x7F, 0x6F};
// in binary: 00111111, 00000110, 01011011, 01001111, 01100110, 01101101,01111101, 00000111, 01111111, 01101111

// define the BMP sensor
Adafruit_BMP280 bmp;

// variables will change:
float temperature;
float pressure;
float altitude;

// to display a number to a seven segment
void changeNumber(int ssNumber, int number) {
for (int i = 0; i < 8; i++) {
// use bitwise op to get the bit that represents the segment
digitalWrite(pinSS[ssNumber - 1][i], !((hexNumber[number] >> i) & 0x1));
}
}

void setup() {
// put your setup code here, to run once:
// initialize the serial and bmp:
Serial.begin(9600);
bmp.begin(0x76); // [0x76, 0x77]

// looping to initialize all segment pins as OUTPUT, then turn off all the segments
// the HIGH and LOW is reversed here, HIGH = OFF, LOW = ON
for (int i = 0; i < 8; i++) {
pinMode(pinSS[0][i], OUTPUT);
pinMode(pinSS[1][i], OUTPUT);
digitalWrite(pinSS[0][i], HIGH);
digitalWrite(pinSS[1][i], HIGH);
}
}

void loop() {
// put your main code here, to run repeatedly:
// get the temperature, pressure, and altitude from bmp280
temperature = bmp.readTemperature();
pressure = bmp.readPressure();
altitude = bmp.readAltitude();

// change the number of seven segments as the temperature
changeNumber(1, (int)(floor(temperature) / 10));
changeNumber(2, (int)(floor(temperature)) % 10);

// print the temperature
Serial.print("Temperature: ");
Serial.print(temperature);
Serial.println(" oC");

// print the pressure
Serial.print("Pressure: ");
Serial.print(pressure);
Serial.println(" Pa");

// print the altitude
Serial.print("Altitude: ");
Serial.print(altitude);
Serial.println(" m");

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

Let’s break down the code. First, there is a 2D matrix called pinSS which stores the pins that are used for the seven segment displays. This allows for easy reference to the pins throughout the code.

Next, there is an array called hexNumber which stores the byte used to display each number from 0 to 9. This array is used later on in the code to display the temperature reading on the seven segment displays.

The BMP280 sensor is declared with the type Adafruit_BMP280 and is set up using the begin() function. This initializes the sensor so that it can start taking readings.

Inside the loop() function, there are six functions used: readTemperature(), readPressure(), readAltitude(), changeNumber(), print(), and println(). The three readX() functions are responsible for taking new readings of the temperature, pressure, and altitude from the BMP280 sensor. These readings are then used by the changeNumber() function to convert the temperature reading into a format that can be displayed on the seven segment displays using the hexNumber array. The print() function then displays the temperature on the seven segment displays. Finally, the println() function adds a new line character to the output, which can be useful for formatting the output in certain cases.

Overall, the loop() function runs continuously and takes new temperature readings every two seconds using delay(2000). The temperature readings are then displayed on the seven segment displays in real-time.

Congratulations! You have successfully finished your fourth project using the ESP32 and the Arduino IDE. Now, your seven segments will be displaying the temperature read from the BMP280 sensor in real time. I hope you had fun and learned a lot about using the ESP32 and the BMP280 sensor. Don’t hesitate to try out new projects and experiment with different components and sensors. If you have any questions, feel free to reach out to me. Happy tinkering!

(*) Trivia:

  • SCL (Serial Clock) and SDA (Serial Data) are two communication lines used in the I2C (Inter-Integrated Circuit) protocol. I2C is a communication protocol used by microcontrollers and other devices to communicate with each other over short distances.
  • The SCL line is used to transmit a clock signal to synchronize the data transfer between the devices, while the SDA line is used to transmit the actual data between the devices.

--

--