Skip to content

Commit 20ec7e5

Browse files
authored
Merge pull request #3 from FoamyGuy/i2c_spi_combo
I2C/SPI Combined Driver
2 parents 0fc84b4 + c4fdeb0 commit 20ec7e5

File tree

5 files changed

+138
-18
lines changed

5 files changed

+138
-18
lines changed

adafruit_bmp5xx.py

Lines changed: 55 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
# SPDX-FileCopyrightText: 2017 Scott Shawcroft, written for Adafruit Industries
21
# SPDX-FileCopyrightText: Copyright (c) 2025 Tim Cocks for Adafruit Industries
32
#
43
# SPDX-License-Identifier: MIT
@@ -34,15 +33,17 @@
3433
import time
3534

3635
from adafruit_bus_device.i2c_device import I2CDevice
37-
from adafruit_register.i2c_bit import ROBit, RWBit
38-
from adafruit_register.i2c_bits import ROBits, RWBits
39-
from adafruit_register.i2c_struct import ROUnaryStruct, UnaryStruct
36+
from adafruit_bus_device.spi_device import SPIDevice # noqa: PLC0415
37+
from adafruit_register.register_accessor import I2CRegisterAccessor, SPIRegisterAccessor
38+
from adafruit_register.register_bit import ROBit, RWBit
39+
from adafruit_register.register_bits import ROBits, RWBits
4040
from micropython import const
4141

4242
try:
43-
from typing import Optional
43+
from typing import Optional, Union
4444

45-
from busio import I2C
45+
from busio import I2C, SPI
46+
from digitalio import DigitalInOut
4647
except ImportError:
4748
pass
4849

@@ -138,12 +139,12 @@
138139
BMP585_CHIP_ID = const(0x51)
139140

140141

141-
class BMP5XX_I2C:
142+
class BMP5XX:
142143
"""
143144
Bosche BMP5xx temperature and pressure sensor breakout CircuitPython driver.
144145
"""
145146

146-
chip_id: int = ROUnaryStruct(BMP5_REG_ID, "B")
147+
chip_id: int = ROBits(8, BMP5_REG_ID, 0)
147148

148149
# Status register bits
149150
status_nvm_ready: bool = ROBit(BMP5_REG_STATUS, 1) # NVM ready
@@ -219,14 +220,41 @@ class BMP5XX_I2C:
219220
output_data_rate = RWBits(5, BMP5XX_REG_ODR_CONFIG, 2)
220221
"""Output data rate. Must be one of the ODR constants."""
221222

222-
command = UnaryStruct(BMP5_REG_CMD, "B") # command register
223+
command = RWBits(8, BMP5_REG_CMD, 0) # command register
223224
"""Command register"""
224225

225-
def __init__(self, i2c: I2C, address: int = DEFAULT_ADAFRUIT_ADDR) -> None:
226-
try:
227-
self.i2c_device = I2CDevice(i2c, address)
228-
except ValueError:
229-
raise ValueError(f"No I2C device found at address 0x{address:02X}")
226+
@staticmethod
227+
def over_spi(spi: SPI, cs: DigitalInOut):
228+
"""
229+
Initialize BMP5XX breakout over SPI bus.
230+
231+
:param spi: busio.SPI instance to communicate over
232+
:param cs: DigitalInOut instance to use for chip select
233+
:return: Initialized BMP5XX object
234+
"""
235+
spi_device = SPIDevice(spi, cs)
236+
return BMP5XX(spi_device)
237+
238+
@staticmethod
239+
def over_i2c(i2c: I2C, address=DEFAULT_ADAFRUIT_ADDR):
240+
"""
241+
Initialize BMP5XX breakout over I2C bus.
242+
243+
:param i2c: busio.I2C instance to communicate over
244+
:param address: The I2C address to use. Defaults to DEFAULT_ADAFRUIT_ADDR
245+
:return: Initialized BMP5XX object
246+
"""
247+
i2c_device = I2CDevice(i2c, address)
248+
return BMP5XX(i2c_device)
249+
250+
def __init__(self, bus_device: Union[I2CDevice, SPIDevice]):
251+
if isinstance(bus_device, SPIDevice):
252+
self.register_accessor = SPIRegisterAccessor(bus_device)
253+
254+
elif isinstance(bus_device, I2CDevice):
255+
self.register_accessor = I2CRegisterAccessor(bus_device)
256+
else:
257+
raise ValueError("bus_device must be an instance of I2CDevice or SPIDevice.")
230258

231259
self.sea_level_pressure = 1013.25
232260
self.reset()
@@ -271,10 +299,11 @@ def altitude(self) -> float:
271299
def reset(self) -> None:
272300
"""Reset the BMP5xx device."""
273301
self.command = BMP5_SOFT_RESET_CMD
274-
time.sleep(0.006)
302+
time.sleep(0.012)
303+
_throwaway = self.chip_id
275304

276305
if self.chip_id not in {BMP581_CHIP_ID, BMP585_CHIP_ID}:
277-
raise ValueError(f"CHIP_ID was zero")
306+
raise ValueError(f"CHIP_ID was incorrect")
278307
if not self.status_nvm_ready:
279308
raise ValueError("NVM not ready")
280309
if self.status_nvm_err:
@@ -309,3 +338,13 @@ def mode(self, new_mode: int) -> None:
309338

310339
self.deep_disabled = True
311340
self._mode = new_mode
341+
342+
343+
def BMP5XX_I2C(i2c: I2C, address: int = DEFAULT_ADAFRUIT_ADDR) -> BMP5XX:
344+
import warnings # noqa: PLC0415, import outside top level
345+
346+
warnings.warn(
347+
"Warning: BMP5XX_I2C class is deprecated and will be removed in a future version. "
348+
"User code should be updated to use BMP5XX.over_i2c()"
349+
)
350+
return BMP5XX.over_i2c(i2c, address)

docs/examples.rst

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,3 +6,11 @@ Ensure your device works with this simple test.
66
.. literalinclude:: ../examples/bmp5xx_simpletest.py
77
:caption: examples/bmp5xx_simpletest.py
88
:linenos:
9+
10+
.. literalinclude:: ../examples/bmp5xx_spi_simpletest.py
11+
:caption: examples/bmp5xx_spi_simpletest.py
12+
:linenos:
13+
14+
.. literalinclude:: ../examples/bmp5xx_spi_multi_device.py
15+
:caption: examples/bmp5xx_spi_multi_device.py
16+
:linenos:

examples/bmp5xx_simpletest.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,15 +5,15 @@
55

66
import board
77

8-
from adafruit_bmp5xx import BMP5XX_I2C
8+
from adafruit_bmp5xx import BMP5XX
99

1010
SEALEVELPRESSURE_HPA = 1013.25
1111

1212
# I2C setup
1313
i2c = board.I2C() # uses board.SCL and board.SDA
1414
# i2c = board.STEMMA_I2C() # For using the built-in STEMMA QT connector on a microcontroller
1515

16-
bmp = BMP5XX_I2C(i2c)
16+
bmp = BMP5XX.over_i2c(i2c)
1717

1818
bmp.sea_level_pressure = SEALEVELPRESSURE_HPA
1919

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
# SPDX-FileCopyrightText: Copyright (c) 2025 Tim Cocks for Adafruit Industries
2+
#
3+
# SPDX-License-Identifier: MIT
4+
import time
5+
6+
import board
7+
from digitalio import DigitalInOut, Direction
8+
9+
from adafruit_bmp5xx import BMP5XX
10+
11+
SEALEVELPRESSURE_HPA = 1013.25
12+
13+
# SPI setup
14+
spi = board.SPI()
15+
16+
# first sensor setup
17+
cs1 = DigitalInOut(board.D10)
18+
cs1.direction = Direction.OUTPUT
19+
bmp1 = BMP5XX.over_spi(spi=spi, cs=cs1)
20+
21+
# second sensor setup, different CS pin, same SPI bus
22+
cs2 = DigitalInOut(board.D11)
23+
cs2.direction = Direction.OUTPUT
24+
bmp2 = BMP5XX.over_spi(spi=spi, cs=cs2)
25+
26+
bmp1.sea_level_pressure = SEALEVELPRESSURE_HPA
27+
bmp2.sea_level_pressure = SEALEVELPRESSURE_HPA
28+
29+
while True:
30+
if bmp1.data_ready:
31+
print(
32+
f"BMP1 temp F: {bmp1.temperature * (9 / 5) + 32} "
33+
f"pressure: {bmp1.pressure} hPa "
34+
f"Approx altitude: {bmp1.altitude} m"
35+
)
36+
37+
if bmp2.data_ready:
38+
print(
39+
f"BMP2 temp F: {bmp2.temperature * (9 / 5) + 32} "
40+
f"pressure: {bmp2.pressure} hPa "
41+
f"Approx altitude: {bmp2.altitude} m"
42+
)
43+
print("-----")
44+
time.sleep(1)

examples/bmp5xx_spi_simpletest.py

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
# SPDX-FileCopyrightText: Copyright (c) 2025 Tim Cocks for Adafruit Industries
2+
#
3+
# SPDX-License-Identifier: Unlicense
4+
import time
5+
6+
import board
7+
from digitalio import DigitalInOut, Direction
8+
9+
from adafruit_bmp5xx import BMP5XX
10+
11+
SEALEVELPRESSURE_HPA = 1013.25
12+
13+
# SPI setup
14+
spi = board.SPI()
15+
cs = DigitalInOut(board.D10)
16+
cs.direction = Direction.OUTPUT
17+
bmp = BMP5XX.over_spi(spi=spi, cs=cs)
18+
19+
20+
bmp.sea_level_pressure = SEALEVELPRESSURE_HPA
21+
22+
while True:
23+
if bmp.data_ready:
24+
print(
25+
f"temp F: {bmp.temperature * (9 / 5) + 32} "
26+
f"pressure: {bmp.pressure} hPa "
27+
f"Approx altitude: {bmp.altitude} m"
28+
)
29+
time.sleep(1)

0 commit comments

Comments
 (0)