What's the purpose of this project?
The purpose of this project is to interface the BME280 environmental sensor with an Arduino to measure and monitor temperature, humidity, and atmospheric pressure in various environments. This versatile sensor provides accurate readings for these parameters, making it ideal for applications such as weather stations, HVAC control, and indoor air quality monitoring. By capturing environmental data in real-time, users can develop systems that respond to changing conditions, improving energy efficiency and comfort in smart home and industrial applications.
What are we going to learn in this tutorial?
In this tutorial, you’ll learn how to:
- Connect the BME280 sensor to Arduino using SPI communication for reliable and fast environmental data transfer.
- Adapt an existing SPI-compatible library for Arduino, deepening your understanding of SPI data handling.
- Read temperature, humidity, and pressure values from the sensor, analyzing the data for real-world applications.
- Create environmental monitoring projects like weather stations and air quality systems, gaining skills for responsive, data-driven systems.
This hands-on guide provides insights into sensor integration and real-time data monitoring with Arduino.
What do we need to start this project?
As you probably know, we need some hardware and software to do this project. The titles of these hardware and software are provided to you in the table below and you can prepare/download by clicking on each of them and get ready to start.
Required hardware
|
Required software
|
---|---|
Arduino UNO
|
|
First as shown in the image below, we connect the GebraBit BME280 module to the Arduino UNO as follows:
Then download and add the GebraBit BME280 library to your Arduino IDE.
Required Library
|
---|
If you don’t know how to add GebraBit libraries to Arduino IDE, refer to the tutorial link below.
BME280 library and driver
In addition to the modular design of various sensors and ICs, GebraBit tries to provide variety of structured and hardware-independent libraries in C language for the ease of users in setting up and developing software.
For this purpose, after preparing each GebraBit module, the users can refer to the “tutorial” section of the desired module and download the dedicated library, which contains the “ .h” and “ .c” file (Header and Source) and a sample training program under “GebraBit STM32F303”, “GebraBit ATMEGA32A” or “Arduino” development boards.
All the defined functions and structures in the library are commented in full detail and all the received parameters in the arguments of the functions and their return values, are briefly explained. Since the libraries are hardware independed, the user can easily add the library in any of their favorite compilers and develop it by desired microcontroller and development board.
GebraBit_BME280.h header file
In this file, based on the datasheet of the sensor or IC, all address registers, the values of each register are defined in the form of “Enumeration”. Also, the casing of the BME280 sensor and the configurations related to each of the BME280 sensor internal blocks are defined in the form of a “STRUCT” with the name GebraBit_BME280. Finally, in the Debug Session environment, all the configurations related to each block can be seen in real time.
USER REGISTER MAP
The registry map or sensor commands are defined in this section:
#define BME280_ID (0xD0)
#define BME280_RESET (0xE0)
#define BME280_TEMP_PRESS_CALIB00_CALIB25 (0x88)//0x88 TO 0xA1
#define BME280_HUMIDITY_CALIB26_CALIB41 (0xE1)//0xE1 TO 0xE7
#define BME280_CTRL_MEAS (0xF4)
#define BME280_CTRL_HUM (0xF2)
#define BME280_CONFIG (0xF5)
#define BME280_DATA_ADDR (0xF7)//PRESS_MSB
#define BME280_STATUS (0xF3)
BME280_Ability Enum
The ability to activate or deactivate different parts of the sensor is defined in this enum:
1. typedef enum Ability
2. {
3. Disable = 0 ,
4. Enable
5. }BME280_Ability;
BME280_Power_Mode Enum
The values of this enum are used to select the sensor Power Mode:
1. typedef enum Power_Mode
2. {
3. SLEEP_MODE = 0,
4. FORCED_MODE = 1,
5. NORMAL_MODE = 3
6. } BME280_Power_Mode;
BME280_Sensor_Oversampling Enum
The values of this enum are used to select the sensor oversampling:
1. typedef enum Pressure_Oversampling
2. {
3. X1_OVERSAMPLING = 1 ,
4. X2_OVERSAMPLING = 2 ,
5. X4_OVERSAMPLING = 3 ,
6. X8_OVERSAMPLING = 4 ,
7. X16_OVERSAMPLING = 5
8. } BME280_Sensor_Oversampling;
BME280_Inactive_Duration Enum
The values of this enum are used to select the sensor stand-by time:
1. typedef enum Inactive_Duration
2. {
3. INACTIVE_DURATION_5_mS = 0 ,
4. INACTIVE_DURATION_62P5_mS = 1 ,
5. INACTIVE_DURATION_125_mS = 2 ,
6. INACTIVE_DURATION_250_mS = 3 ,
7. INACTIVE_DURATION_500_mS = 4 ,
8. INACTIVE_DURATION_1000_mS = 5 ,
9. INACTIVE_DURATION_10_mS = 6 ,
10. INACTIVE_DURATION_20_mS = 7
11. } BME280_Inactive_Duration;
BME280_IIR_Filter_Coefficient Enum
The values of this enum are used to select the appropriate values of sensor calibration coefficients:
1. typedef enum IIR_Filter_Coefficient
2. {
3. FILTER_OFF = 0 ,
4. FILTER_COEFFICIENT_2 = 1 ,
5. FILTER_COEFFICIENT_4 = 2 ,
6. FILTER_COEFFICIENT_8 = 3 ,
7. FILTER_COEFFICIENT_16 = 4
8. } BME280_IIR_Filter_Coefficient;
BME280_Preparation Enum
The values of this enum determine whether the data is ready or not:
1. typedef enum Preparation
2. {
3. IS_Ready = 0 ,
4. IS_NOT_Ready
5. }BME280_Preparation;
BME280_Reset_Status Enum
The values of this enum determine whether the sensor is reset or not:
1. typedef enum
2. {
3. DONE = 0 ,
4. FAILED = 1
5. }BME280_Reset_Status;
BME280 struct
1. typedef struct BME280
2. {
3. uint8_t REGISTER_CACHE;
4. BME280_Reset_Status RESET;
5. uint8_t DEVICE_ID;
6. BME280_Preparation CONVERSION_RESULT;
7. BME280_Preparation NVM_DATA;
8. BME280_Power_Mode POWER_MODE;
9. BME280_Ability TEMPERATURE;
10. BME280_Ability PRESSURE;
11. BME280_Ability HUMIDITY;
12. BME280_Sensor_Oversampling TEMPERATURE_OVERSAMPLING;
13. BME280_Sensor_Oversampling PRESSURE_OVERSAMPLING;
14. BME280_Sensor_Oversampling HUMIDITY_OVERSAMPLING;
15. BME280_IIR_Filter_Coefficient IIR_FILTER_TIME_CONATANT;
16. BME280_Inactive_Duration INACTIVE_DURATION;
17. uint8_t PRESS_TEMP_CALIBRATION_DATA[PRESS_TEMP_CALIBRATION_DATA_BUFFER_SIZE];
18. uint8_t HUMIDITY_CALIBRATION_DATA[HUMIDITY_CALIBRATION_DATA_BUFFER_SIZE];
19. int32_t dig_t1;
20. int32_t dig_t2;
21. int32_t dig_t3;
22. uint16_t dig_p1;
23. int16_t dig_p2;
24. int16_t dig_p3;
25. int16_t dig_p4;
26. int16_t dig_p5;
27. int16_t dig_p6;
28. int16_t dig_p7;
29. int16_t dig_p8;
30. int16_t dig_p9;
31. int32_t dig_h1;
32. int32_t dig_h2;
33. int32_t dig_h3;
34. int32_t dig_h4;
35. int32_t dig_h5;
36. int32_t dig_h6;
37. int32_t FINE_TEMP_RESOLUTIN;
38. uint8_t REGISTER_RAW_DATA_BUFFER[REGISTER_RAW_DATA_BYTE_QTY];
39. uint32_t REGISTER_RAW_PRESSURE;
40. uint32_t REGISTER_RAW_TEMPERATURE;
41. uint32_t REGISTER_RAW_HUMIDITY;
42. double COMPENSATED_TEMPERATURE;
43. double COMPENSATED_PRESSURE;
44. double ALTITUDE;
45. double COMPENSATED_HUMIDITY;
46. }GebraBit_BME280;
47.
Declaration of functions
At the end of this file, all the functions for reading and writing in BME280 registers, sensor configuration and receiving data from the sensor are declared:
1. /********************************************************
2. *Declare Read&Write BME280 Register Values Functions *
3. ********************************************************/
4. extern uint8_t GB_BME280_Read_Reg_Data ( uint8_t regAddr,uint8_t* data);
5. extern uint8_t GB_BME280_Read_Reg_Bits (uint8_t regAddr,uint8_t start_bit, uint8_t len, uint8_t* data);
6. extern uint8_t GB_BME280_Burst_Read(uint8_t regAddr,uint8_t *data, uint16_t byteQuantity);
7. extern uint8_t GB_BME280_Write_Reg_Data(uint8_t regAddr, uint8_t data);
8. extern uint8_t GB_BME280_Write_Reg_Bits(uint8_t regAddr, uint8_t start_bit, uint8_t len, uint8_t data);
9. extern uint8_t GB_BME280_Burst_Write ( uint8_t regAddr,uint8_t *data, uint16_t byteQuantity);
10. /********************************************************
11. * Declare BME280 Configuration Functions *
12. ********************************************************/
13. extern void GB_BME280_Soft_Reset ( GebraBit_BME280 * BME280 );
14. extern void GB_BME280_Get_Device_ID(GebraBit_BME280 * BME280);
15. extern void GB_BME280_Check_NVM_Data(GebraBit_BME280 * BME280 ) ;
16. extern void GB_BME280_Check_Conversion_Transferred_Register(GebraBit_BME280 * BME280 );
17. extern void GB_BME280_Turn_Humidity_OFF(GebraBit_BME280* BME280);
18. extern void GB_BME280_Humidity_OverSampling(GebraBit_BME280* BME280 ,BME280_Sensor_Oversampling hum_over);
19. extern void GB_BME280_Turn_Temperature_OFF(GebraBit_BME280* BME280);
20. extern void GB_BME280_Temperature_OverSampling(GebraBit_BME280* BME280 ,BME280_Sensor_Oversampling temp_over);
21. extern void GB_BME280_Turn_Pressure_OFF(GebraBit_BME280* BME280);
22. extern void GB_BME280_Pressure_OverSampling(GebraBit_BME280* BME280 ,BME280_Sensor_Oversampling press_over);
23. extern void GB_BME280_Power_Mode(GebraBit_BME280* BME280 ,BME280_Power_Mode pmode);
24. extern void GB_BME280_Inactive_Duration(GebraBit_BME280 * BME280 , BME280_Inactive_Duration dur ) ;
25. extern void GB_BME280_IIR_Filter_Coefficient (GebraBit_BME280 * BME280 , BME280_IIR_Filter_Coefficient filter);
26. extern void GB_BME280_Power_Mode(GebraBit_BME280* BME280 ,BME280_Power_Mode pmode);
27. extern void GB_BME280_Calculate_Calibration_Coefficients(GebraBit_BME280 * BME280) ;
28. extern void GB_BME280_Twos_Complement_Converter(int32_t *value, uint8_t length) ;
29. extern void GB_BME280_Compensate_Temperature(GebraBit_BME280 * BME280) ;
30. extern void GB_BME280_Compensate_Pressure(GebraBit_BME280 * BME280) ;
31. extern void GB_BME280_Compensate_Humidity(GebraBit_BME280 * BME280);
32.
33. /********************************************************
34. * Declare BME280 DATA Functions *
35. ********************************************************/
36. extern void GB_BME280_Get_Register_Raw_Pressure_Temperature_Humidity(GebraBit_BME280 * BME280 );
37. extern void GB_BME280_Altitude(GebraBit_BME280 * BME280);
38. extern void GB_BME280_Get_Data(GebraBit_BME280 * BME280 );
39. /********************************************************
40. * Declare BME280 HIGH LEVEL Functions *
41. ********************************************************/
42. extern void GB_BME280_initialize( GebraBit_BME280 * BME280 );
43. extern void GB_BME280_Configuration(GebraBit_BME280 * BME280);
44.
GebraBit_ BME280.cpp source file
In this file, which is written in C++ language, all the functions are commented in full detail, and all the parameters received in the arguments of the functions and their return values are clearly explained so we confine to these explanations and invite users to check this file directly for more information.
Sample program in Arduino
After connecting the module to Arduino and adding the library to the IDE, go to the following path: File > Examples > GebraBit_BME280 > temp-hum-pre
Description of Sample file
At the beginning of the file, you will find the GebraBit_BME280.h header included to provide access to the necessary structures, enums, and functions for the GebraBit BME280 module. Additionally, the required elements for the module’s operation have been added to these structures. A variable named BME280 of the GebraBit_BME280 structure type (defined in the GebraBit_BME280 header and detailed in the library’s description section) is then declared to configure the GebraBit BME280 module.
GebraBit_BME280 BME280;
In the next part of the written code, using the GB_BME280_initialize (&BME280) and GB_BME280_Configuration (&BME280) functions, we set the GebraBit BME280 module and finally, in the loop part of the program, the data is read from the sensor and the BME280 values are continuously received:
void setup() {
Serial.begin(9600);
SPI.begin();
pinMode(SPI_CS_Pin, OUTPUT);
digitalWrite(SPI_CS_Pin, HIGH);
GB_BME280_initialize(&BME280);
// Check if the device ID matches the expected value
GB_BME280_Get_Device_ID(&BME280);
if (BME280.DEVICE_ID != 0x60) {
Serial.println("Failed to initialize BME280 sensor!");
while (1);
} else {
Serial.println("BME280 sensor initialized successfully.");
}
GB_BME280_Configuration(&BME280);
}
void loop() {
GB_BME280_Get_Data(&BME280);
Serial.print("Temperature: ");
Serial.print(BME280.COMPENSATED_TEMPERATURE);
Serial.println(" °C");
Serial.print("Pressure: ");
Serial.print(BME280.COMPENSATED_PRESSURE);
Serial.println(" hPa");
Serial.print("Humidity: ");
Serial.print(BME280.COMPENSATED_HUMIDITY);
Serial.println(" %");
Serial.print("Altitude: ");
Serial.print(BME280.ALTITUDE);
Serial.println(" m");
delay(1000);
}
The Sample file code text:
#include "GebraBit_BME280.h"
#define SPI_CS_Pin 10 // Change this if your CS pin is different
GebraBit_BME280 BME280;
void setup() {
Serial.begin(9600);
SPI.begin();
pinMode(SPI_CS_Pin, OUTPUT);
digitalWrite(SPI_CS_Pin, HIGH);
GB_BME280_initialize(&BME280);
// Check if the device ID matches the expected value
GB_BME280_Get_Device_ID(&BME280);
if (BME280.DEVICE_ID != 0x60) {
Serial.println("Failed to initialize BME280 sensor!");
while (1);
} else {
Serial.println("BME280 sensor initialized successfully.");
}
GB_BME280_Configuration(&BME280);
}
void loop() {
GB_BME280_Get_Data(&BME280);
Serial.print("Temperature: ");
Serial.print(BME280.COMPENSATED_TEMPERATURE);
Serial.println(" °C");
Serial.print("Pressure: ");
Serial.print(BME280.COMPENSATED_PRESSURE);
Serial.println(" hPa");
Serial.print("Humidity: ");
Serial.print(BME280.COMPENSATED_HUMIDITY);
Serial.println(" %");
Serial.print("Altitude: ");
Serial.print(BME280.ALTITUDE);
Serial.println(" m");
delay(1000);
}
Connect your arduino to computer and select your Arduino Board
Then Verify and Upload the Sample code
After uploading the code, open the serial monitor and you can see the BME280 values.
In the following, you can download the GebraBit_BME280 Library, the schematic of the modules and the “BME280 datasheet”.
Program output video
The video of the module operation will be uploaded soon