BOSCH BMP585 Barometric Pressure Sensor with Arduino
Table of Contents
Bosch BMP585 Barometric Pressure Sensor:
BOSCH BMP585 Barometric Pressure Sensor with Arduino- The Bosch BMP585 Barometric Pressure Sensor is the best Barometric Pressure Sensor so far. It’s a hidden gem I found for you guys. The technical details and uses of this sensor will amaze you. By using this tiny sensor, you can create high-tech gadgets.
Today, we will use the Bosch BMP585 Barometric Pressure Sensor with Arduino. With this sensor, we will measure the temperature and atmospheric pressure, and we will also use it to find out which floor a person is on in a building; we can precisely measure height with the BMP585. You should read this article from start to finish because the information I am going to share with you is not available anywhere else. I am the first one to use the Bosch BMP585 Sensor with the Arduino and in upcoming video and article, I will also use it with the ESP32 WiFi + Bluetooth module.
So, without any further delay, let’s get started!
Product Links:
Arduino Nano USB C type (Recommended)
*Please Note: These are affiliate links. I may make a commission if you buy the components through these links. I would appreciate your support in this way!
BOSCH BMP585 Barometric Pressure Sensor:
The Bosch BMP585 Barometric Pressure Sensor is an ultra-low current consumption and is renowned for its high accuracy and precision. With an absolute accuracy of ±50 pascals and a temperature coefficient offset of ±0.5 pascals per degree Kelvin, it establishes itself as an industry leader in pressure sensing technology. This sensor is so sensitive that it can detect very small height changes, even just a few centimeters. With an operational pressure range spanning from 300 to 1,250 hectopascals, it offers exceptional versatility.
The BMP585 is designed to operate from voltages of 1.08 to 3.6 volts for the IOs and 1.71 to 3.6 volts for the primary supply. Designed with a gel-filled cavity, it provides robust protection against water, chemicals, and other liquids. It can be used underwater and in harsh environments. It offers accurate localization and navigation. Due to its tiny size, the Bosch BMP585 Barometric Pressure Sensor is a single package solution for smart watches, wearables, home appliances, and much more.
BOSCH BMP585 Technical Data
Key Features:
- Pressure operating range: 30…125 kPa
- Temperature operating range: -40…+85°C
- Ultra-low noise and current consumption:
- Ultra-low noise: < 0.1 PaRMS natively (without low-pass filter enabled)
- 3 µA at 1 Hz in low power mode
- Absolute pressure accuracy: ± 30 Pa (typ)
- Relative pressure accuracy: ± 6 Pa (typ) per 10 kPa step
- Pressure temperature-induced offset: ± 0.5 Pa/K (typ)
- Provides true absolute pressure and temperature due to on-chip linearization and temperature compensation
- Primary digital interface:
- 12 MHz slave SPI (4-wire, 3-wire)
- 5 MHz I3C
- Up to 1 MHz I²C (Fm+)
- Output data rates:
- Up to 622 Hz in FORCED mode
- Up to 480 Hz in CONTINUOUS mode
- 125…240 Hz in NORMAL mode
- Wide power supply range:
- VDD 1.71…3.6 V
- VDDIO 1.08…3.6 V (both independent)
- Programmable low-pass filter
- On-chip FIFO buffer for up to 32 pressure samples
- Programmable interrupts (e.g., pressure change detection)
- 6 bytes of user-programmable non-volatile memory
- Compact 8-pin metal-lid LGA package (typ. 3.25 × 3.25 mm², max. 1.96 mm height)
- RoHS compliant, halogen, and lead-free
- Media robustness:
- No impact on performance and reliability by storage at 15 bar
- No failure upon exposure to common household chemicals (chlorine bleach, acetic acid, acetone, oleic acid, and insect repellent)
- Robustness to environmental stress factors (heat, moisture, mechanical forces)
- Second Level design proposal available for system integration
Typical Applications:
GPS navigation (time-to-first-fix improvement, dead-reckoning, slope detection)
Indoor navigation (floor and elevator detection)
Outdoor navigation
Sports applications (calorie counting, fitness activity identification, water sports)
Emergency caller location
Weather forecast
Vertical velocity indication (e.g., rise/sink speed)
Altitude control for drones and flying toys
Target Devices:
Mobile phones, tablet PCs, GPS devices
Navigation systems
Portable healthcare devices
Home weather stations
Drones and flying toys
Smart watches
Virtual and augmented reality devices
If you want to know more about this sensor, visit the product’s official page and download the datasheet.
Since I am using the BMP585 Barometric Pressure Sensor for the first time, I thought I should try a development board first. That’s why I bought the BMP585 Shuttle Board 3.0.
It’s a small PCB with the BMP585 pressure and temperature sensor already placed on it. You can download the PDF file for this board from the product’s official page.
“https://www.bosch-sensortec.com/products/environmental-sensors/pressure-sensors/bmp585/“
In this PDF file, you will also find the schematic, which will give you a clear idea of which resistors to use with the BMP585 and how to power it up. It also explains the pins in detail. Even though the BMP585 Shuttle Board 3.0 doesn’t have any labels, you can still easily figure out the pins by looking at the number of pins on each side. One side has 7 pins, and the other side has 9 pins. In the schematic above these are labeled as P1 and P2.
The pins on BMP585 Shuttle Board 3.0 are not breadboard-friendly, so if your soldering skills are not good, you might face some difficulty. To use the BMP585 Shuttle Board 3.0 with Arduino, ESP32, or any other controller, you will need to solder jumper wires to the pins of this board. During soldering the wires, I used my Andonstar Digital Microscope.
The schematic has so many pins that it can be confusing to figure out which pin to use and where to connect it. I only understood it after studying the BMP585 sensor’s datasheet. To save you time, I have created this schematic for you.
You only need 4 pins to connect the BMP585 to Arduino, ESP32, ESP8266, or any other controller: 3.3V and GND to power the sensor, and SDA and SCL for I2C communication.
I have designed my own PCB for this, which is completely breadboard-friendly.
Download the Schematic and PCB Files:
PCBWay:
PCBWay is a trusted leader in the PCB industry, offering custom-designed boards at competitive prices to suit projects of all sizes—from basic to highly specialized.
Whether you’re working with standard FR-4 or need advanced solutions like Rogers, HDI, or Flexible and Rigid-Flex boards, PCBWay provides high-quality options without the high cost. Get an instant quote at pcbway.com/orderonline.
Curious about what others are creating? Explore innovative projects and ideas from the PCB community on PCBWay’s open-source platform at pcbway.com/project/.
As you can see, I have connected the BMP585 Shuttle Board 3.0 to the Arduino. According to the shuttle board schematic, connect pins 1 and 2, labeled as VDD and VDDIO, to 3.3V on the Arduino.
Connect pin 3 to the Arduino GND.
On the other side.
Connect CS or CSB that is the first pin to 3.3V. Let me tell you the BMP585 provides one serial interface to the host. It acts as a slave to the host. The serial interface is configurable to the interface protocols SPI, I3C and I2C. As per the datasheet, if the CSB is connected to 3.3 Volts during power-up and not changed, the primary interface works in I2C or I3C mode. So, for using I2C and I3C, it is recommended to hard-wire the CSB line to VDDIO or 3.3V. For details on Protocol Selection, see the Digital Interface section in the datasheet.
Connect pin 2 labeled as SCK/SCL to the A5 pin on the Arduino.
Connect pin 3 labeled as SDO to 3.3V for I2C Slave address selection.
Finally, connect pin 4 labeled as SDI/SDA to the Arduino A4 pin.
BMP585 interfacing with Arduino:
There shouldn’t be any issues with the connections because we wired the BMP585 Barometric Pressure sensor according to the datasheet. But just to be sure, let’s run an I2C scanner code to check if we can read the I2C address.
I2C Scanner Code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 |
#include <Wire.h> void setup() { Wire.begin(); Serial.begin(115200); // Start serial communication at 115200 baud while (!Serial); // Wait for serial port to connect (necessary for some boards) Serial.println("\nI2C Scanner"); scanI2CDevices(); } void loop() { // Re-scan every 5 seconds delay(5000); scanI2CDevices(); } void scanI2CDevices() { byte error, address; int nDevices; Serial.println("Scanning..."); nDevices = 0; for (address = 1; address < 127; address++) { // The I2C scanner uses the return value of // Wire.endTransmission 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"); } |
Connect your Arduino board to the laptop and upload the above program. Once the program is successfully uploaded then open the Serial Monitor.
As you can see, we successfully read the I2C address.
Programming the BMP585 sensor was a bit challenging for me because I couldn’t find its library in the Arduino IDE and even on the product’s official page. While researching data for the BMP585, I came across the BMP581 sensor. Its technical specifications were almost the same as the BMP585, but the BMP585 is better in terms of accuracy and a few other things.
Anyway, the Arduino library for the BMP581 was available, so I installed that library. Honestly, I was pretty sure this library would work with the BMP585 sensor. To confirm, I opened a basic example code, uploaded the program, and then opened the Serial Monitor; but it didn’t work.
As I mentioned, there are some common things between the BMP585 and BMP581. So, I decided that instead of creating a completely new library, it’s better to use the BMP581 library. This way, I could use some parts from the BMP581 library and write some of the code myself. But this was not as easy as it sounds.
I studied the datasheet for two days. I carefully read about all the registers, and finally, I was able to write the code successfully.
BOSCH BMP585 Arduino Code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 |
#include <Wire.h> #include "SparkFun_BMP581_Arduino_Library.h" // Create a new sensor object BMP581 pressureSensor; #define I2C_ADDRESS_1 0x47 void setup() { Serial.begin(115200); Wire.begin(); Serial.println("BMP585 Pressure & Temperature Sensor"); // Scan for I2C devices Serial.println("Scanning for I2C devices..."); for (byte address = 1; address < 127; address++) { Wire.beginTransmission(address); byte error = Wire.endTransmission(); if (error == 0) { Serial.print("I2C device found at address 0x"); if (address < 16) Serial.print("0"); Serial.println(address, HEX); } } // Attempt to initialize the sensor with the first address Serial.println("Attempting to connect to sensor at 0x47..."); if (pressureSensor.beginI2C(I2C_ADDRESS_1) == BMP5_OK) { Serial.println("BMP585 connected at address 0x47!"); } else { // Attempt to initialize the sensor with the second address Serial.println("Attempting to connect to sensor at 0x7E..."); if (pressureSensor.beginI2C(I2C_ADDRESS_1) == BMP5_OK) { Serial.println("BMP585 connected at address 0x7E!"); } else { // Not connected, inform user Serial.println("Error: BMP581 not connected, check wiring and I2C address!"); // Wait a bit to see if connection is established delay(1000); } } //checkCommunication(I2C_ADDRESS_1); // Register 0x18 FIFO Selection configuration // for pressure and temperature data writeRegister(I2C_ADDRESS_1, 0x18, 0b00000011); delay(100); // Register (0x31) DSP IIR Configuration // sets the filter Coefficient:15 writeRegister(I2C_ADDRESS_1, 0x31, 0b00100100); delay(100); // Register (0x36) Over-sampling rate (OSR) configuration // enable sensor pressure measurements // over sampling rates for temperature and pressure 64x writeRegister(I2C_ADDRESS_1, 0x36, 0b01110110); // delay(100); // Write to register 0x37 // this disables the deep sleep mode of the sensor // set the ODR to 1 Hz // set the power mode to normal writeRegister(I2C_ADDRESS_1, 0x37, 0b01110001); delay(100); } void loop() { // // Optionally, read back to verify the write operation // uint8_t value1 = readRegister(I2C_ADDRESS_1, 0x37); //0x37 // // Serial.print("Value at 0x37 : 0x"); // Serial.println(value1, HEX); // Get measurements from the sensor bmp5_sensor_data data = {0,0}; int8_t err = pressureSensor.getSensorData(&data); // Check whether data was acquired successfully if(err == BMP5_OK) { // Acquisition succeeded, print temperature and pressure Serial.print("Temperature (C): "); Serial.print(data.temperature); Serial.print("\t\t"); // Get and the raw pressure value uint32_t rawPressure = readPressure(); //Serial.print("Raw Pressure: "); //Serial.println(rawPressure); // Convert raw pressure value to actual pressure float actualPressure = convertRawPressure(rawPressure); Serial.print("Actual Pressure (Pa): "); Serial.println(actualPressure); } else { // Acquisition failed, most likely a communication error (code -2) Serial.print("Error getting data from sensor! Error code: "); Serial.println(err); } // Only print every second //delay(100); } void writeRegister(uint8_t deviceAddress, uint8_t registerAddress, uint8_t value) { Wire.beginTransmission(deviceAddress); Wire.write(registerAddress); // Register address Wire.write(value); // Value to write Wire.endTransmission(); } uint8_t readRegister(uint8_t deviceAddress, uint8_t registerAddress) { Wire.beginTransmission(deviceAddress); Wire.write(registerAddress); // Register address Wire.endTransmission(); Wire.requestFrom(deviceAddress, (uint8_t)1); // Request 1 byte if (Wire.available()) { return Wire.read(); // Read and return the byte } else { Serial.print("Failed to read from address 0x"); Serial.println(deviceAddress, HEX); return 0; // Return 0 if read failed } } void checkCommunication(uint8_t address) { Wire.beginTransmission(address); Wire.write(0x37); // Example register, replace with a known readable register from BMP585 datasheet Wire.endTransmission(); Wire.requestFrom(address, 1); if (Wire.available()) { uint8_t data = Wire.read(); Serial.print("Status Register: 0x"); Serial.println(data, HEX); } else { Serial.print("Failed to read from address 0x"); Serial.println(address, HEX); } } uint32_t readPressure() { byte data[3]; // Read pressure registers (0x20 to 0x22) Wire.beginTransmission(I2C_ADDRESS_1); Wire.write(0x20); // Start from register 0x20 for pressure LSB Wire.endTransmission(false); // End I2C transmission without releasing the bus Wire.requestFrom(I2C_ADDRESS_1, 3); // Request 3 bytes of data if (Wire.available() == 3) { data[0] = Wire.read(); data[1] = Wire.read(); data[2] = Wire.read(); } // Combine data to get pressure value uint32_t pressure = ((uint32_t)data[2] << 16) | ((uint32_t)data[1] << 8) | data[0]; return pressure; } float convertRawPressure(uint32_t rawPressure) { // Convert raw pressure using the provided formula float pressure = rawPressure / 64.0; // Equivalent to dividing by 2^6 return pressure; } |
About the BMP585 Arduino Code:
1 2 3 4 5 6 7 |
#include <Wire.h> #include "SparkFun_BMP581_Arduino_Library.h" // Create a new sensor object BMP581 pressureSensor; |
You can see here that I am using the BMP581 library to create a new sensor object called pressureSensor.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 |
#define I2C_ADDRESS_1 0x47 This is the I2C address of the BMP585 sensor. // Register 0x18 FIFO Selection configuration // for pressure and temperature data writeRegister(I2C_ADDRESS_1, 0x18, 0b00000011); delay(100); // Register (0x31) DSP IIR Configuration // sets the filter Coefficient:15 writeRegister(I2C_ADDRESS_1, 0x31, 0b00100100); delay(100); // Register (0x36) Over-sampling rate (OSR) configuration // enable sensor pressure measurements // over sampling rates for temperature and pressure 64x writeRegister(I2C_ADDRESS_1, 0x36, 0b01110110); // delay(100); // Write to register 0x37 // this disables the deep sleep mode of the sensor // set the ODR to 1 Hz // set the power mode to normal writeRegister(I2C_ADDRESS_1, 0x37, 0b01110001); delay(100); |
After that, I went down to the bit level and configured each register according to my needs. I have added proper comments for every instruction, so you will not face any difficulty understanding the code. Right now, it might look a bit confusing, but when you compare it with the registers mentioned in the datasheet, everything will become clear.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 |
// Get measurements from the sensor bmp5_sensor_data data = {0,0}; int8_t err = pressureSensor.getSensorData(&data); // Check whether data was acquired successfully if(err == BMP5_OK) { // Acquisition succeeded, print temperature and pressure Serial.print("Temperature (C): "); Serial.print(data.temperature); Serial.print("\t\t"); // Get and the raw pressure value uint32_t rawPressure = readPressure(); //Serial.print("Raw Pressure: "); //Serial.println(rawPressure); // Convert raw pressure value to actual pressure float actualPressure = convertRawPressure(rawPressure); Serial.print("Actual Pressure (Pa): "); Serial.println(actualPressure); |
In the loop() function, we simply get measurements from the sensor and send it to the Serial Monitor. The temperature will be printed in Celsius and the pressure will be printed in Pascals. If you have any questions regarding this program, let me know in a comment. Anyway, let’s go ahead and upload this program.
Right now, you can see the temperature is 32.83 degrees Celsius and the atmospheric pressure is 97102.58.
As you can see, when I lift the BMP585 sensor up, the value starts to decrease, and when I bring it down, the value starts to increase again.
I have already confirmed that this pressure value is completely accurate. If you want a more stable value, you can go to the 0x36 register and set the Over-sampling rate (OSR) to 64x or 128x. Right now, I have already set it to 64x. During the practical demonstration it was set to 8x.
In the next project, we will find out which floor a person is on in a building. Let’s do it!
Height Measurement with BMP585:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 |
#include <Wire.h> #include "SparkFun_BMP581_Arduino_Library.h" // Create a new sensor object BMP581 pressureSensor; #define I2C_ADDRESS_1 0x47 uint32_t ground_reference = 97094; //current ground level pressure int32_t myaltitude = 0; int floorNumber = 0; void setup() { Serial.begin(115200); Wire.begin(); Serial.println("BMP581 Example1 begin!"); // Scan for I2C devices Serial.println("Scanning for I2C devices..."); for (byte address = 1; address < 127; address++) { Wire.beginTransmission(address); byte error = Wire.endTransmission(); if (error == 0) { Serial.print("I2C device found at address 0x"); if (address < 16) Serial.print("0"); Serial.println(address, HEX); } } // Attempt to initialize the sensor with the first address Serial.println("Attempting to connect to sensor at 0x47..."); if (pressureSensor.beginI2C(I2C_ADDRESS_1) == BMP5_OK) { Serial.println("BMP581 connected at address 0x47!"); } else { // Attempt to initialize the sensor with the second address Serial.println("Attempting to connect to sensor at 0x7E..."); if (pressureSensor.beginI2C(I2C_ADDRESS_1) == BMP5_OK) { Serial.println("BMP581 connected at address 0x7E!"); } else { // Not connected, inform user Serial.println("Error: BMP581 not connected, check wiring and I2C address!"); // Wait a bit to see if connection is established delay(1000); } } //checkCommunication(I2C_ADDRESS_1); // Register 0x18 FIFO Selection configuration // for pressure and temperature data writeRegister(I2C_ADDRESS_1, 0x18, 0b00000011); delay(100); // Register (0x31) DSP IIR Configuration // sets the filter Coefficient:1 writeRegister(I2C_ADDRESS_1, 0x31, 0b00000001); delay(100); // Register (0x36) Over-sampling rate (OSR) configuration // enable sensor pressure measurements // over sampling rates for temperature and pressure 64x writeRegister(I2C_ADDRESS_1, 0x36, 0b01110110); delay(100); // Write to register 0x37 // this disables the deep sleep mode of the sensor // set the ODR to 1 Hz // set the power mode to normal writeRegister(I2C_ADDRESS_1, 0x37, 0b01110001); delay(100); } void loop() { // // Optionally, read back to verify the write operation // uint8_t value1 = readRegister(I2C_ADDRESS_1, 0x37); //0x37 // // Serial.print("Value at 0x37 : 0x"); // Serial.println(value1, HEX); // Get measurements from the sensor bmp5_sensor_data data = {0,0}; int8_t err = pressureSensor.getSensorData(&data); // Check whether data was acquired successfully if(err == BMP5_OK) { // Acquisition succeeded, print temperature and pressure //Serial.print("Temperature (C): "); //Serial.print(data.temperature); //Serial.print("\t\t"); // Get and the raw pressure value uint32_t rawPressure = readPressure(); // Convert raw pressure value to actual pressure float actualPressure = convertRawPressure(rawPressure); // Serial.print("Pressure (Pa): "); // Serial.print(actualPressure); // Serial.print("\t"); myaltitude = ground_reference - actualPressure; myaltitude = myaltitude / 4; Serial.print("Altitude in feet: "); Serial.print(myaltitude); Serial.print("\t"); floorNumber = myaltitude / 10; // ceiling height from the floor is 10 feet. Serial.print("Floor Number: "); Serial.print(floorNumber); Serial.println(""); } else { // Acquisition failed, most likely a communication error (code -2) Serial.print("Error getting data from sensor! Error code: "); Serial.println(err); } // Only print every second //delay(100); } void writeRegister(uint8_t deviceAddress, uint8_t registerAddress, uint8_t value) { Wire.beginTransmission(deviceAddress); Wire.write(registerAddress); // Register address Wire.write(value); // Value to write Wire.endTransmission(); } uint8_t readRegister(uint8_t deviceAddress, uint8_t registerAddress) { Wire.beginTransmission(deviceAddress); Wire.write(registerAddress); // Register address Wire.endTransmission(); Wire.requestFrom(deviceAddress, (uint8_t)1); // Request 1 byte if (Wire.available()) { return Wire.read(); // Read and return the byte } else { Serial.print("Failed to read from address 0x"); Serial.println(deviceAddress, HEX); return 0; // Return 0 if read failed } } void checkCommunication(uint8_t address) { Wire.beginTransmission(address); Wire.write(0x37); // Example register, replace with a known readable register from BMP585 datasheet Wire.endTransmission(); Wire.requestFrom(address, 1); if (Wire.available()) { uint8_t data = Wire.read(); Serial.print("Status Register: 0x"); Serial.println(data, HEX); } else { Serial.print("Failed to read from address 0x"); Serial.println(address, HEX); } } uint32_t readPressure() { byte data[3]; // Read pressure registers (0x20 to 0x22) Wire.beginTransmission(I2C_ADDRESS_1); Wire.write(0x20); // Start from register 0x20 for pressure LSB Wire.endTransmission(false); // End I2C transmission without releasing the bus Wire.requestFrom(I2C_ADDRESS_1, 3); // Request 3 bytes of data if (Wire.available() == 3) { data[0] = Wire.read(); data[1] = Wire.read(); data[2] = Wire.read(); } // Combine data to get pressure value uint32_t pressure = ((uint32_t)data[2] << 16) | ((uint32_t)data[1] << 8) | data[0]; return pressure; } float convertRawPressure(uint32_t rawPressure) { // Convert raw pressure using the provided formula float pressure = rawPressure / 64.0; // Equivalent to dividing by 2^6 return pressure; } |
To count the number of floors, I used the ground level pressure as a reference.
1 |
uint32_t ground_reference = 97094; //current ground level pressure |
If you want to set any level as a reference point in real-time, you can also use a push button with the controller. So, whenever you press the push button, the current atmospheric pressure value will be saved in a variable. You can then use that saved value as a reference to measure the height.
1 2 3 |
int32_t myaltitude = 0; int floorNumber = 0; |
I also defined two variables for measuring altitude in feet and floor number.
This time, to make the value more stable, I have set the Over-sampling rate (OSR) to 64x in the 0x36 register. Now, the value will be much more stable.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
myaltitude = ground_reference - actualPressure; myaltitude = myaltitude / 4; Serial.print("Altitude in feet: "); Serial.print(myaltitude); Serial.print("\t"); floorNumber = myaltitude / 10; // ceiling height from the floor is 10 feet. Serial.print("Floor Number: "); Serial.print(floorNumber); Serial.println(""); |
Using these instructions, I first convert the pressure into altitude, and then to find the floor number, I divide it by 10. The reason I divide by 10 is because, in our house, the distance from the floor to the ceiling is around 10 feet.
For the distance measurement I used the Fnirsi Laser RangeFinder.
That’s why I used 10 for the division.
So, that’s all about the program. I have already uploaded this program and now let’s watch this in action.
Right now, you can see that the total height is 15 feet, and the floor number is 1. That’t because I am currently on the first floor, and my laptop and BMP585 sensor are on the table. To test this, I will first go to the ground floor, then come back to the first floor, then move up to the second floor, and finally, return to the first floor. I highly recommend that you watch the practical demonstration in the video given below. Anyway, here are some images.
As you saw, it successfully measured the height and also correctly identified which floor I was on. In the next video and article, I will use the BMP585 Barometric Pressure Sensor with the ESP32. So, that’s all for now!
Sorry newbie question, Is it possible to get pcbway.com to use your bmp585 design above above and get all of the parts and get them soldered onto the board, so it arrives ready for one to use?
yes they can.
Not finding one, I wrote a micropython driver for bmp585, bmp581, bmp390 sensors for Raspberry Pi: https://github.com/bradcar/MicroPython_BMP58x
The bmp585 and bmp581 are similar except the device ID is different, likely this is the reason why the Arduino driver didn’t work.
Not finding a Micropython driver, I wrote my own for Raspberry Pi at: https://github.com/bradcar/MicroPython_BMP58x, driver now also works for bmp585, bmp581, bmp390, and bmp280 in micropython. In the driver, one can set either altitude or nearest sea level pressure so it can be very accurate absolute altitude. Thanks to this youtube video I quickly hacked by shuttle board to write to my Raspberry Pi Pico 2. Likely the reason why the Arduino driver didn’t work in this video is that the device ID is different for bmp581 and bmp585. this should be easy to change. The bmp585 has almost the same registers and control.