Altitude monitoring with BMP280 using ESP32 and Node-Red

Varul Jain
9 min readFeb 27, 2019

--

The BME280 I2C module has great significance in measuring Altitude application which is especially working to measure the distance between the from the Rigid Objects and Earth and read the parameters using MQTT in Node-Red Services

This Blogtut will show you how you can measure Read the Temperature, Pressure, and Altitude (using precise values) and with the help of wireless communication (Wifi) with new device ESP32. We can create the wireless sensor network as well as send the parameters online by using inbuilt BLE(Bluetooth Low Energy) and WIFI in it.

Hardware Required

BMP280 I2C module

ESP32

I2C cable

Software

Arduino IDE

Node-Red

IOT Platform

MQTT

JSON

For Installation of ESP32 device, newbies can follow the blog post

If you are not familiar with Node-Red Installation and using MQTT node in Node-Red, I suggest to check out the previous blogtut in which I have shared all the detailed information for Getting Started with Node-Red services.

About BMP280 I2C module

The BMP280 IC package manufactured by BOSCH Sensortec operates on lower Noise. With EMC robustness, High Accuracy it performs greatly in various application like:

  • Atmospheric Pressure and Temperature monitoring system
  • Intruder Alarming via Pressure Precision
  • Intruder Alarm
  • Altitude measurement
  • Vertical Velocity Sink

BMP280 I2C module is a digital Pressure Sensor 300–1100hPa(hectopascals) or mbar(millibar) uses the modular breakout board with advance I2C speed of 3.4Mbit/sec with the resolution 0.01hPa.

Code

  • Initialize the Wire.h file called as I2C Library especially use in Arduino IDE
#include <Wire.h>
  • Initialize the I2C registers of sensor module which is specified to work with 2 wire protocol.
#define Addr 0x76
  • Begin the I2C transmission and Initialize the baud rate as per the requirements for serial communication.
Wire.begin(21,22);Serial.begin(115200);setup_wifi(); //We will be using simple Wifi.h library
  • Request for 8 bytes of Data which we want to read from the sensor through I2C connection for reading the Temperature Coefficient and Pressure Coefficients
for (int i = 0; i < 8; i++){// Start I2C TransmissionWire.beginTransmission(Addr);// Select data registerWire.write((247 + i));// Stop I2C TransmissionWire.endTransmission();// Request 1 byte of dataWire.requestFrom(Addr, 1);// Read 1 byte of dataif (Wire.available() == 1){data[i] = Wire.read();}}
  • If bytes are available then use the mentioned below formula will help to convert the data bytes and display desired values
// Convert pressure and temperature data to 19-bits
long adc_p = (((long)(data[0] & 0xFF) * 65536) + ((long)(data[1] & 0xFF) * 256) + (long)(data[2] & 0xF0)) / 16;
long adc_t = (((long)(data[3] & 0xFF) * 65536) + ((long)(data[4] & 0xFF) * 256) + (long)(data[5] & 0xF0)) / 16;// Temperature offset calculationsdouble var1 = (((double)adc_t) / 16384.0 — ((double)dig_T1) / 1024.0) * ((double)dig_T2);double var2 = ((((double)adc_t) / 131072.0 — ((double)dig_T1) / 8192.0) *(((double)adc_t) / 131072.0 — ((double)dig_T1) / 8192.0)) * ((double)dig_T3);double t_fine = (long)(var1 + var2);// Pressure offset calculationsvar1 = ((double)t_fine / 2.0) — 64000.0;var2 = var1 * var1 * ((double)dig_P6) / 32768.0;var2 = var2 + var1 * ((double)dig_P5) * 2.0;var2 = (var2 / 4.0) + (((double)dig_P4) * 65536.0);var1 = (((double) dig_P3) * var1 * var1 / 524288.0 + ((double) dig_P2) * var1) / 524288.0;var1 = (1.0 + var1 / 32768.0) * ((double)dig_P1);double p = 1048576.0 — (double)adc_p;p = (p — (var2 / 4096.0)) * 6250.0 / var1;var1 = ((double) dig_P9) * p * p / 2147483648.0;var2 = p * ((double) dig_P8) / 32768.0;
  • Manipulate the Temperature and Pressure parameters as per the requirement through Sensitivity and resolution settings given in the datasheet
double cTemp = (var1 + var2) / 5120.0;
double fTemp = cTemp * 1.8 + 32;
double pressure = (p + (var1 + var2 + ((double)dig_P7)) / 16.0) / 100;
  • Using Serial.print you will be able to read the sensor data in the serial monitor screen.
Serial.print(“Altitude : “);
Serial.print(height);
Serial.println(“ m”);
Serial.print(“Altitude in Feet : “);
Serial.println(h);
Serial.print(“Pressure : “);
Serial.print(pressure);
Serial.println(“ hPa”);
Serial.print(“Temperature in Celsius : “);
Serial.print(cTemp);
Serial.println(“ C”);
Serial.print(“Temperature in Fahrenheit : “);
Serial.print(fTemp);
Serial.println(“ F”);

BMP280 Application

While working on BMP280 sensor I was able to test the pressure and temperature.

But!!! Besides that, I have used one graph Image and formulae which help me to understand and find out the Altitude parameters (in meters) using this sensor as well as using some basic Standard Units Conversion method. I have converted the parameters to work with Feet units also

Measuring heights of Civil Infrastructure

There are many core application when it comes to monitoring Civil Projects construction to measure the height with precise parameters.

Measuring Altitude between Earth and Aeroplane in Air Atmosphere

This Application plays the most important role to monitor the Altitude for AeroSpace vehicles. As we haven’t worked in depth but yes mentioned below code will definitely help you to understand the basic physics concept, which can direct you to advanced field application also.

Using ESP32 with I2C sensor

One of the best Device to use as a gateway receiver to make your sensor communicate wireless with the internet using Wifi. Besides that using Ultra Low Power we can use special BLE protocol with this sensor which will help to create the private network between sensor and smartphone and display the parameters using Sensor Application. We are using WiFi Library and Pubsub client using Arduino IDE

Node-Red

After unlocking one the application for measuring the altitude using Arduino, let’s detect the parameters with Node-RED dashboard — (Line Graphs and Bar Graphs).

For installation of Node-Red and to install the different nodes in node red in windows operating and to use MQTT please go through the previous blogtut.

In this project, We will be using MQTT, JSON, Function nodes in Node-RED dashboard which is already mentioned in Axial Monitoring with Node-Red Service. The MQTT connection has been created with the help of PUB-SUB client in Arduino.

But Function node is the best way to parse the data from the sensor and with help of Split node you can individually use the data to send it to online platform easily in JSON format or parsed according to requirements. We will be working more advanced with JSON format in next blogtut till then we have already used a basic example to display the whole object through JSON and function node connection which is further connected to message payload by

  • After Drag and Drop double click on function node
  • Write the small piece of code to parse the data in JSON Object
p = JSON.parse(msg.payload);
node.log(typeof p);
msg.payload = p;
return msg;

Final Flow

Output

Arduino Serial Monitor Output
JSON Object using JSON and Function Node
Node-Red Dashboard Output

Code

#include <Wire.h>
#include <PubSubClient.h>
#include <WiFi.h>
// BMP280 I2C address is 0x76(108)
#define Addr 0x76
//Wifi Credentials
#define wifi_ssid "DcubeAirtel"
#define wifi_password "D@Airtel190"
//Define MQTT server and topics
#define mqtt_server "iot.eclipse.org"
#define Ctemp_topic "TempC"
#define Ftemp_topic "TempF"
#define Prsr_topic "Pressure"
#define Altm_topic "MAltitude"
#define AltF_topic "FAltitude"
WiFiClient espClient;
PubSubClient client;
volatile float tempc, tempf, presr, altm, altf;
void setup()
{
Wire.begin(21,22);
Serial.begin(115200);
Serial.println("RX Pin --->"+RX);
Serial.println("TX Pin --->"+TX);
setup_wifi();
client.setServer(mqtt_server, 1883);
client.setClient(espClient);
}
//Wifi Setup
void setup_wifi() {
delay(10);
// We start by connecting to a WiFi network
Serial.println();
Serial.print("Connecting to ");
Serial.println(wifi_ssid);

WiFi.begin(wifi_ssid, wifi_password);

while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}

Serial.println("");
Serial.println("WiFi connected");
Serial.println("IP address: ");
Serial.println(WiFi.localIP());
}

//Reconnect
void reconnect() {
// Loop until we're reconnected
while (!client.connected()) {
Serial.print("Attempting MQTT connection...");
if (client.connect("ESP32Client")) {
Serial.println("connected");
}
else {
Serial.print("failed, rc=");
Serial.print(client.state());
Serial.println(" try again in 5 seconds");
// Wait 5 seconds before retrying
delay(500);
}
}
}
void loop()
{
bmp280();
delay(100);
if (!client.connected()) {
reconnect();
}

//Mentioned below directly executed in String url

Serial.print("C Temp: ");
Serial.println(String(tempc).c_str());
client.publish(Ctemp_topic, String(tempc).c_str(), true);

Serial.print("F Temp: ");
Serial.println(String(tempf).c_str());
client.publish(Ftemp_topic, String(tempf).c_str(), true);

Serial.print("Pressure: ");
Serial.println(String(presr).c_str());
client.publish(Prsr_topic, String(presr).c_str(), true);

Serial.print("Altitude meters: ");
Serial.println(String(altm).c_str());
client.publish(Altm_topic, String(altm).c_str(), true);

Serial.print("Altitude Feet: ");
Serial.println(String(altf).c_str());
client.publish(AltF_topic, String(altf).c_str(), true);
client.loop();
}
void bmp280()
{
unsigned int b1[24];
unsigned int data[8];
for (int i = 0; i < 24; i++)
{
// Start I2C Transmission
Wire.beginTransmission(Addr);
// Select data register
Wire.write((136 + i));
// Stop I2C Transmission
Wire.endTransmission();
// Request 1 byte of data
Wire.requestFrom(Addr, 1);
// Read 1 byte of data
if (Wire.available() == 1)
{
b1[i] = Wire.read();
}
}
// Convert the data
// temp coefficients
unsigned int dig_T1 = (b1[0] & 0xFF) + ((b1[1] & 0xFF) * 256);
int dig_T2 = b1[2] + (b1[3] * 256);
int dig_T3 = b1[4] + (b1[5] * 256);
// pressure coefficients
unsigned int dig_P1 = (b1[6] & 0xFF) + ((b1[7] & 0xFF) * 256);
int dig_P2 = b1[8] + (b1[9] * 256);
int dig_P3 = b1[10] + (b1[11] * 256);
int dig_P4 = b1[12] + (b1[13] * 256);
int dig_P5 = b1[14] + (b1[15] * 256);
int dig_P6 = b1[16] + (b1[17] * 256);
int dig_P7 = b1[18] + (b1[19] * 256);
int dig_P8 = b1[20] + (b1[21] * 256);
int dig_P9 = b1[22] + (b1[23] * 256);
// Start I2C Transmission
Wire.beginTransmission(Addr);
// Select control measurement register
Wire.write(0xF4);
// Normal mode, temp and pressure over sampling rate = 1
Wire.write(0x27);
// Stop I2C Transmission
Wire.endTransmission();
// Start I2C Transmission
Wire.beginTransmission(Addr);
// Select config register
Wire.write(0xF5);
// Stand_by time = 1000ms
Wire.write(0xA0);
// Stop I2C Transmission
Wire.endTransmission();
for (int i = 0; i < 8; i++)
{
// Start I2C Transmission
Wire.beginTransmission(Addr);
// Select data register
Wire.write((247 + i));
// Stop I2C Transmission
Wire.endTransmission();
// Request 1 byte of data
Wire.requestFrom(Addr, 1);
// Read 1 byte of data
if (Wire.available() == 1)
{
data[i] = Wire.read();
}
}
// Convert pressure and temperature data to 19-bits
long adc_p = (((long)(data[0] & 0xFF) * 65536) + ((long)(data[1] & 0xFF) * 256) + (long)(data[2] & 0xF0)) / 16;
long adc_t = (((long)(data[3] & 0xFF) * 65536) + ((long)(data[4] & 0xFF) * 256) + (long)(data[5] & 0xF0)) / 16;
// Temperature offset calculations
double var1 = (((double)adc_t) / 16384.0 - ((double)dig_T1) / 1024.0) * ((double)dig_T2);
double var2 = ((((double)adc_t) / 131072.0 - ((double)dig_T1) / 8192.0) *
(((double)adc_t) / 131072.0 - ((double)dig_T1) / 8192.0)) * ((double)dig_T3);
double t_fine = (long)(var1 + var2);
double cTemp = (var1 + var2) / 5120.0;
double fTemp = cTemp * 1.8 + 32;
// Pressure offset calculations
var1 = ((double)t_fine / 2.0) - 64000.0;
var2 = var1 * var1 * ((double)dig_P6) / 32768.0;
var2 = var2 + var1 * ((double)dig_P5) * 2.0;
var2 = (var2 / 4.0) + (((double)dig_P4) * 65536.0);
var1 = (((double) dig_P3) * var1 * var1 / 524288.0 + ((double) dig_P2) * var1) / 524288.0;
var1 = (1.0 + var1 / 32768.0) * ((double)dig_P1);
double p = 1048576.0 - (double)adc_p;
p = (p - (var2 / 4096.0)) * 6250.0 / var1;
var1 = ((double) dig_P9) * p * p / 2147483648.0;
var2 = p * ((double) dig_P8) / 32768.0;
double pressure = (p + (var1 + var2 + ((double)dig_P7)) / 16.0) / 100;
float height = 44330 * (1 - pow((pressure / 1013.25), 0.1903));
float h = height * 0.3048;

// Output data to serial monitor
// Serial.print("Altitude : ");
// Serial.print(height);
// Serial.println(" m");
// Serial.print("Altitude in Feet : ");
// Serial.println(h);
//
// Serial.print("Pressure : ");
// Serial.print(pressure);
// Serial.println(" hPa");
// Serial.print("Temperature in Celsius : ");
// Serial.print(cTemp);
// Serial.println(" C");
// Serial.print("Temperature in Fahrenheit : ");
// Serial.print(fTemp);
// Serial.println(" F");
//volatile float tempc, tempf, presr, altim, altif tempc = cTemp;
tempf = fTemp;
presr = pressure;
altm = height;
altf = h;
delay(1000);
}

JSON Object in Node-Red

[{"id":"6e2fed4b.325c24","type":"tab","label":"Flow 1","disabled":false,"info":""},{"id":"cf1bcee.62c9b3","type":"mqtt in","z":"6e2fed4b.325c24","name":"","topic":"TempC","qos":"2","broker":"2f70a0d2.a0ff7","x":84.78122329711914,"y":81.9176082611084,"wires":[["dc6fdc66.f71fb","8754c0da.c5f9c","9284055c.420db8"]]},{"id":"7ef09837.92cbe8","type":"mqtt in","z":"6e2fed4b.325c24","name":"","topic":"TempF","qos":"2","broker":"2f70a0d2.a0ff7","x":91.78406143188477,"y":180.9204216003418,"wires":[["2914dd13.33f262","67fdbfea.b0ff1","9284055c.420db8"]]},{"id":"ebbe39a4.ec43c8","type":"mqtt in","z":"6e2fed4b.325c24","name":"","topic":"Pressure","qos":"2","broker":"2f70a0d2.a0ff7","x":102.78975296020508,"y":240.92321968078613,"wires":[["9c7a94d2.676388","91c23ee3.44a0f","9284055c.420db8"]]},{"id":"ffd75aa6.973ad8","type":"mqtt in","z":"6e2fed4b.325c24","name":"","topic":"FAltitude","qos":"2","broker":"2f70a0d2.a0ff7","x":102.79261016845703,"y":304.92326736450195,"wires":[["7c55d2fe.0c519c","73f96b.3b607694","9284055c.420db8"]]},{"id":"8754c0da.c5f9c","type":"ui_chart","z":"6e2fed4b.325c24","name":"","group":"699c61b6.51c8e","order":2,"width":0,"height":0,"label":"C Temp","chartType":"line","legend":"false","xformat":"HH:mm","interpolate":"linear","nodata":"","dot":false,"ymin":"0","ymax":"50","removeOlder":1,"removeOlderPoints":"","removeOlderUnit":"3600","cutout":0,"useOneColor":false,"colors":["#1f77b4","#aec7e8","#ff8040","#2ca02c","#98df8a","#d62728","#ff9896","#9467bd","#c5b0d5"],"useOldStyle":false,"x":294.78406143188477,"y":85.7159013748169,"wires":[[],[]]},{"id":"67fdbfea.b0ff1","type":"ui_chart","z":"6e2fed4b.325c24","name":"","group":"699c61b6.51c8e","order":1,"width":0,"height":0,"label":"F temp","chartType":"line","legend":"false","xformat":"HH:mm","interpolate":"linear","nodata":"","dot":false,"ymin":"0","ymax":"50","removeOlder":1,"removeOlderPoints":"","removeOlderUnit":"3600","cutout":0,"useOneColor":false,"colors":["#1f77b4","#aec7e8","#ff7f0e","#2ca02c","#98df8a","#a61e1e","#ff9896","#9467bd","#c5b0d5"],"useOldStyle":false,"x":341.7925796508789,"y":166.7130241394043,"wires":[[],[]]},{"id":"91c23ee3.44a0f","type":"ui_chart","z":"6e2fed4b.325c24","name":"","group":"6d81d54e.2e9c4c","order":1,"width":0,"height":0,"label":"Pressure","chartType":"bar","legend":"false","xformat":"HH:mm:ss","interpolate":"linear","nodata":"","dot":false,"ymin":"0","ymax":"1000","removeOlder":1,"removeOlderPoints":"","removeOlderUnit":"3600","cutout":0,"useOneColor":false,"colors":["#1f77b4","#aec7e8","#ff7f0e","#2ca02c","#98df8a","#d62728","#ff9896","#9467bd","#c5b0d5"],"useOldStyle":false,"x":321.79257583618164,"y":245.71016120910645,"wires":[[],[]]},{"id":"7c55d2fe.0c519c","type":"ui_chart","z":"6e2fed4b.325c24","name":"","group":"6d81d54e.2e9c4c","order":2,"width":0,"height":0,"label":"Altitude","chartType":"line","legend":"false","xformat":"HH:mm","interpolate":"linear","nodata":"","dot":false,"ymin":"0","ymax":"1000","removeOlder":1,"removeOlderPoints":"","removeOlderUnit":"3600","cutout":0,"useOneColor":false,"colors":["#1f77b4","#aec7e8","#ff7f0e","#2ca02c","#98df8a","#d62728","#ff9896","#9467bd","#c5b0d5"],"useOldStyle":false,"x":324.7897415161133,"y":298.7101707458496,"wires":[[],[]]},{"id":"dc6fdc66.f71fb","type":"debug","z":"6e2fed4b.325c24","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","x":272.7926025390625,"y":52.95738220214844,"wires":[]},{"id":"2914dd13.33f262","type":"debug","z":"6e2fed4b.325c24","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","x":327.7897529602051,"y":124.95169448852539,"wires":[]},{"id":"9c7a94d2.676388","type":"debug","z":"6e2fed4b.325c24","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","x":287.7926139831543,"y":203.94882774353027,"wires":[]},{"id":"73f96b.3b607694","type":"debug","z":"6e2fed4b.325c24","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","x":305.78690338134766,"y":343.9573230743408,"wires":[]},{"id":"9284055c.420db8","type":"join","z":"6e2fed4b.325c24","name":"","mode":"custom","build":"object","property":"payload","propertyType":"msg","key":"topic","joiner":"","joinerType":"str","accumulate":true,"timeout":"4","count":"4","reduceRight":false,"reduceExp":"","reduceInit":"","reduceInitType":"","reduceFixup":"","x":129.7840518951416,"y":401.926100730896,"wires":[["a2ed8c13.c2f8c"]]},{"id":"d2abecc.983171","type":"function","z":"6e2fed4b.325c24","name":"","func":"p = JSON.parse(msg.payload);\nnode.log(typeof p);\nmsg.payload = p;\nreturn msg;","outputs":1,"noerr":0,"x":393.7812309265137,"y":398.9289665222168,"wires":[["c665b986.34e148"]]},{"id":"a2ed8c13.c2f8c","type":"json","z":"6e2fed4b.325c24","name":"","property":"payload","action":"","pretty":false,"x":257.7925796508789,"y":397.92608642578125,"wires":[["d2abecc.983171"]]},{"id":"c665b986.34e148","type":"debug","z":"6e2fed4b.325c24","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","x":547.7840805053711,"y":400.9460029602051,"wires":[]},{"id":"2f70a0d2.a0ff7","type":"mqtt-broker","z":"","name":"iot.eclipse.org","broker":"iot.eclipse.org","port":"1883","clientid":"","usetls":false,"compatmode":true,"keepalive":"5","cleansession":true,"birthTopic":"","birthQos":"0","birthPayload":"","closeTopic":"","closeQos":"0","closePayload":"","willTopic":"","willQos":"0","willPayload":""},{"id":"699c61b6.51c8e","type":"ui_group","name":"Group 1","tab":"f4a73006.d45dc","order":1,"disp":true,"width":6},{"id":"6d81d54e.2e9c4c","type":"ui_group","name":"Group 2","tab":"f4a73006.d45dc","order":2,"disp":true,"width":6},{"id":"f4a73006.d45dc","type":"ui_tab","z":"","name":"Altitude","icon":"dashboard","order":3}]

Code

Credits

Node-red Tutorials

BMP280 control everything Library

--

--

Varul Jain

IOT developer, Technical Writer, Beginner in blogging, Passionate about about present, Experienced about past.