Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 25 additions & 2 deletions lib/bme280/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -163,6 +163,29 @@ Triggers a single forced measurement. Poll `data_ready()` for completion, then r

---

### Altitude

```python
alt = sensor.altitude()
```

Returns the estimated altitude in **meters** using the ICAO barometric formula.

You can also pass an already-read pressure value to avoid a redundant I2C read:

```python
temperature, pressure, humidity = sensor.read()
alt = sensor.altitude(pressure_hpa=pressure)
```

The computation uses `sea_level_pressure_hpa` as reference (default: 1013.25 hPa). Adjust it for your location:

```python
sensor.sea_level_pressure_hpa = 1020.0
```

---

## Data-Ready Status

```python
Expand Down Expand Up @@ -288,8 +311,8 @@ Performs a soft reset, re-reads calibration data, and re-applies default configu
| Oversampling (per channel) | ✅ | ✅ | ✅ | ✅ | ⚠️ Fixed x16 | ⚠️ Constants only |
| IIR filter | ✅ | ❌ | ✅ | ✅ | ⚠️ Fixed x16 | ❌ |
| Standby time | ✅ | ❌ | ✅ | ❌ | ⚠️ Fixed 500ms | ❌ |
| Altitude | | ✅ | ✅ | ✅ | ✅ | ❌ |
| Sea-level pressure | | ✅ | ✅ | ✅ | ✅ | ❌ |
| Altitude | | ✅ | ✅ | ✅ | ✅ | ❌ |
| Sea-level pressure | | ✅ | ✅ | ✅ | ✅ | ❌ |
| Dew point | ❌ | ✅ | ❌ | ❌ | ❌ | ❌ |
| Soft reset | ✅ | ❌ | ❌ | ❌ | ✅ | ❌ |
| Full reset + recalibration | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ |
Expand Down
14 changes: 14 additions & 0 deletions lib/bme280/bme280/device.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ class BME280(object):
def __init__(self, i2c, address=BME280_I2C_DEFAULT_ADDR):
self.i2c = i2c
self.address = address
self.sea_level_pressure_hpa = 1013.25
self._check_device()
self._wait_boot()
self._read_calibration()
Expand Down Expand Up @@ -395,3 +396,16 @@ def read_one_shot(self):
press_hpa = self._compensate_pressure(raw_press) / 25600.0
hum_rh = self._compensate_humidity(raw_hum) / 1024.0
return temp_c, press_hpa, hum_rh

def altitude(self, pressure_hpa=None):
"""Return estimated altitude in meters.

Uses the ICAO barometric formula with ``sea_level_pressure_hpa``
as reference (default 1013.25 hPa, adjustable).

Args:
pressure_hpa: pressure in hPa. If None, a new reading is taken
via :meth:`pressure_hpa`.
"""
p = self.pressure_hpa() if pressure_hpa is None else pressure_hpa
return 44330.0 * (1.0 - (p / self.sea_level_pressure_hpa) ** 0.1903)
16 changes: 5 additions & 11 deletions lib/bme280/examples/weather_station.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
"""Continuous weather monitoring with altitude estimation.

Reads temperature, pressure, and humidity every 5 seconds in normal mode,
computes approximate altitude from pressure using the barometric formula,
computes altitude using the driver's built-in barometric formula,
and logs each measurement to the DAPLink flash as CSV.
"""

Expand All @@ -13,15 +13,15 @@
from daplink_flash import DaplinkFlash
from machine import I2C

# Sea-level reference pressure in hPa (adjust to local conditions)
SEA_LEVEL_PRESSURE = 1013.25

i2c = I2C(1)

sensor = BME280(i2c)
bridge = DaplinkBridge(i2c)
flash = DaplinkFlash(bridge)

# Adjust sea-level pressure to local conditions for accurate altitude
# sensor.sea_level_pressure_hpa = 1020.0

# Configure for weather monitoring: high pressure resolution, moderate temp/hum
sensor.set_oversampling(temperature=OSRS_X2, pressure=OSRS_X16, humidity=OSRS_X2)
sensor.set_iir_filter(FILTER_16)
Expand All @@ -35,15 +35,9 @@

flash.write_line("temperature;pressure;humidity;altitude")


def altitude_m(pressure_hpa):
"""Estimate altitude in meters from pressure using the barometric formula."""
return 44330.0 * (1.0 - (pressure_hpa / SEA_LEVEL_PRESSURE) ** 0.1903)


while True:
temperature, pressure, humidity = sensor.read()
alt = altitude_m(pressure)
alt = sensor.altitude(pressure_hpa=pressure)

print(
"T: {:.1f} C P: {:.1f} hPa H: {:.1f} %RH Alt: {:.0f} m".format(
Expand Down
49 changes: 49 additions & 0 deletions tests/scenarios/bme280.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -581,3 +581,52 @@ tests:
result = len(forced_writes) == 1 and abs(t - 25.08) < 0.1
expect_true: true
mode: [mock]

# ----- Altitude -----

- name: "Default sea_level_pressure_hpa is 1013.25"
action: script
script: |
result = dev.sea_level_pressure_hpa == 1013.25
expect_true: true
mode: [mock]

- name: "altitude() returns plausible value with default reference"
action: script
script: |
alt = dev.altitude()
# Mock pressure ~1009.21 hPa → altitude ~33.7 m at 1013.25 hPa reference
result = abs(alt - 33.7) < 1.0
expect_true: true
mode: [mock]

- name: "altitude() uses custom sea_level_pressure_hpa"
action: script
script: |
dev.sea_level_pressure_hpa = 1020.0
alt = dev.altitude()
# Mock pressure ~1009.21 hPa → altitude ~89.6 m at 1020.0 hPa reference
result = abs(alt - 89.6) < 1.0
dev.sea_level_pressure_hpa = 1013.25
expect_true: true
mode: [mock]

- name: "altitude() returns zero when pressure equals reference"
action: script
script: |
# Set reference to match actual pressure so altitude should be ~0
dev.sea_level_pressure_hpa = dev.pressure_hpa()
alt = dev.altitude()
result = abs(alt) < 0.5
dev.sea_level_pressure_hpa = 1013.25
expect_true: true
mode: [mock]

- name: "altitude() accepts pressure_hpa parameter"
action: script
script: |
# Pass pressure directly to avoid redundant I2C read
alt = dev.altitude(pressure_hpa=1009.21)
result = abs(alt - 33.7) < 1.0
expect_true: true
mode: [mock]
Loading