Skip to content

Commit

Permalink
✨ add BMI323 [#7]
Browse files Browse the repository at this point in the history
Add support for BMI323.
Add examples for BMI323.
Move register addresses to enum classes. This improves auto-completion and structure of the sensor class.
Add unit tests.
  • Loading branch information
selyunin authored Nov 30, 2024
1 parent 4a93408 commit 75f0478
Show file tree
Hide file tree
Showing 17 changed files with 1,290 additions and 123 deletions.
17 changes: 17 additions & 0 deletions examples/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@ These are self-contained examples for using the `umrx-v3-py` with Application Bo
* [`switch_app_dfu.py`](./switch_app_dfu.py)
* [`switch_app_mtp.py`](./switch_app_mtp.py)


## [`bmi088`](https://www.bosch-sensortec.com/products/motion-sensors/imus/bmi088/)

The examples in the [`bmi088`](./bmi088) folder
show different communication features for the
[BMI088 shuttle](https://www.bosch-sensortec.com/media/boschsensortec/downloads/shuttle_board_flyer/application_board_3_1/bst-bmi088-sf000.pdf)
Expand All @@ -17,6 +20,20 @@ board:
* [`bmi088/bmi088_spi_polling_streaming.py`](./bmi088/bmi088_spi_polling_streaming.py)
* [`bmi088/bmi088_spi_interrupt_streaming.py`](./bmi088/bmi088_spi_interrupt_streaming.py)

## [`bmi323`](https://www.bosch-sensortec.com/products/motion-sensors/imus/bmi323/)

The examples in the [`bmi323`](./bmi323) folder
show different communication features for the
[BMI323 shuttle](https://www.bosch-sensortec.com/media/boschsensortec/downloads/shuttle_board_flyer/bst-bmi323-sf000.pdf)
board:

* [`bmi088/bmi323_i2c_read_write.py`](./bmi323/bmi323_i2c_read_write.py)
* [`bmi088/bmi323_i2c_polling_streaming.py`](./bmi323/bmi323_i2c_polling_streaming.py)
* [`bmi088/bmi323_i2c_interrupt_streaming.py`](./bmi323/bmi323_i2c_interrupt_streaming.py)
* [`bmi088/bmi323_spi_read_write.py`](./bmi323/bmi323_spi_read_write.py)
* [`bmi088/bmi323_spi_polling_streaming.py`](./bmi323/bmi323_spi_polling_streaming.py)
* [`bmi088/bmi323_spi_interrupt_streaming.py`](./bmi323/bmi323_spi_interrupt_streaming.py)


## Need a specific example or do not know how to read data from your sensor?

Expand Down
Empty file added examples/bmi323/__init__.py
Empty file.
46 changes: 46 additions & 0 deletions examples/bmi323/bmi323_i2c_interrupt_streaming.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
import logging
import struct
import sys
import time
from pathlib import Path

from umrx_app_v3.shuttle_board.bmi323.bmi323_shuttle import BMI323Shuttle


def setup_logging(level: int = logging.DEBUG) -> logging.Logger:
logger = logging.getLogger()
logger.setLevel(level)
stdout_handler = logging.StreamHandler(sys.stdout)
log_format = "(%(asctime)s) [%(levelname)-8s] %(filename)s:%(lineno)d: %(message)s"
log_formatter = logging.Formatter(log_format)
stdout_handler.setFormatter(log_formatter)
file_handler = logging.FileHandler(f"{Path(__file__).parent / Path(__file__).stem}.log", mode="w")
file_handler.setFormatter(log_formatter)
logger.addHandler(stdout_handler)
logger.addHandler(file_handler)
return logger


if __name__ == "__main__":
logger = setup_logging()
# This example is for Application Board 3.1 hardware
shuttle = BMI323Shuttle.on_hardware_v3_rev1()
shuttle.initialize()
shuttle.check_connected_hw()

shuttle.configure_i2c()
logger.info(f"acc_chip_id=0x{shuttle.sensor.chip_id:02X}")
assert shuttle.sensor.chip_id == 0x0043
shuttle.configure_interrupt_streaming()
shuttle.start_streaming()
time.sleep(0.1)
for idx in range(1000):
for streaming in shuttle.board.receive_interrupt_streaming_multiple(includes_mcu_timestamp=False):
sensor_id, packet, time_stamp, payload = streaming
d_x, d_y, d_z = struct.unpack("<xxhhh", payload)
if sensor_id == 1:
logger.info(f"[{idx}][a] {packet=:06d} {' ' * 30} a_x={d_x:04d}, a_y={d_y:04d}, a_z={d_z:04d}")
elif sensor_id == 2:
logger.info(f"[{idx}][g] {packet=:06d} g_x={d_x:04d}, g_y={d_y:04d}, g_z={d_z:04d}")
time.sleep(0.05)
shuttle.board.stop_interrupt_streaming()
48 changes: 48 additions & 0 deletions examples/bmi323/bmi323_i2c_polling_streaming.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
import logging
import struct
import sys
import time
from pathlib import Path

from umrx_app_v3.shuttle_board.bmi323.bmi323_shuttle import BMI323Shuttle


def setup_logging(level: int = logging.DEBUG) -> logging.Logger:
logger = logging.getLogger()
logger.setLevel(level)
stdout_handler = logging.StreamHandler(sys.stdout)
log_format = "(%(asctime)s) [%(levelname)-8s] %(filename)s:%(lineno)d: %(message)s"
log_formatter = logging.Formatter(log_format)
stdout_handler.setFormatter(log_formatter)
file_handler = logging.FileHandler(f"{Path(__file__).parent / Path(__file__).stem}.log", mode="w")
file_handler.setFormatter(log_formatter)
logger.addHandler(stdout_handler)
logger.addHandler(file_handler)
return logger


if __name__ == "__main__":
logger = setup_logging()
# This example is for Application Board 3.1 hardware
shuttle = BMI323Shuttle.on_hardware_v3_rev1()
shuttle.initialize()
shuttle.check_connected_hw()

shuttle.configure_i2c()
logger.info(f"chip_id=0x{shuttle.sensor.chip_id:04X}")
assert shuttle.sensor.chip_id == 0x0043
shuttle.configure_polling_streaming()
shuttle.start_streaming()
time.sleep(0.1)
for idx in range(1000):
for streaming in shuttle.board.receive_polling_streaming_multiple():
sensor_id, payload = streaming
a_x, a_y, a_z, g_x, g_y, g_z, temperature, time_stamp = struct.unpack("<xxhhhhhhHI", payload)
temperature_c = 23 + (temperature / 512)
time_stamp_second = time_stamp * 39.0625 / 1e6
logger.info(
f"[{idx=}], accel({a_x=:+05d}, {a_y=:+05d}, {a_z=:+05d}), gyro({g_x=:+05d}, {g_y=:+05d}, {g_z=:+05d}), "
f"T={temperature_c:+2.3f}, time_stamp(sec)={time_stamp_second:.6f}"
)
time.sleep(0.05)
shuttle.board.stop_polling_streaming()
59 changes: 59 additions & 0 deletions examples/bmi323/bmi323_i2c_read_write.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
import logging
import sys
import time
from pathlib import Path

from umrx_app_v3.shuttle_board.bmi323.bmi323_shuttle import BMI323Shuttle


def setup_logging(level: int = logging.DEBUG) -> logging.Logger:
logger = logging.getLogger()
logger.setLevel(level)
stdout_handler = logging.StreamHandler(sys.stdout)
log_format = "(%(asctime)s) [%(levelname)-8s] %(filename)s:%(lineno)d: %(message)s"
log_formatter = logging.Formatter(log_format)
stdout_handler.setFormatter(log_formatter)
file_handler = logging.FileHandler(f"{Path(__file__).parent / Path(__file__).stem}.log", mode="w")
file_handler.setFormatter(log_formatter)
logger.addHandler(stdout_handler)
logger.addHandler(file_handler)
return logger


if __name__ == "__main__":
logger = setup_logging()
shuttle = BMI323Shuttle.on_hardware_v3_rev1()
shuttle.initialize()
shuttle.check_connected_hw()

shuttle.configure_i2c()

logger.info(f"chip_id=0x{shuttle.sensor.chip_id:04X}")
logger.info(f"err_reg=0x{shuttle.sensor.err_reg:04X}")
logger.info(f"err_reg=0x{shuttle.sensor.status:04X}")

a_x, a_y, a_z = shuttle.sensor.acc_data
logger.info(f"acceleration=({a_x=:04X}, {a_y=:04X}, {a_z=:04X})")

g_x, g_y, g_z = shuttle.sensor.gyr_data
logger.info(f"angular_velocity=({g_x=:04X}, {g_y=:04X}, {g_z=:04X})")

logger.info(f"sensor_time={shuttle.sensor.sensor_time:04X}")

logger.info(f"acc_conf=0x{shuttle.sensor.acc_conf:04X}")
logger.info(f"gyr_conf=0x{shuttle.sensor.gyr_conf:04X}")

shuttle.sensor.acc_conf = 0x4027
shuttle.sensor.gyr_conf = 0x404B

logger.info(f"acc_conf=0x{shuttle.sensor.acc_conf:04X}")
logger.info(f"gyr_conf=0x{shuttle.sensor.gyr_conf:04X}")

logger.info(f"alt_acc_conf=0x{shuttle.sensor.alt_acc_conf:04X}")
logger.info(f"alt_gyr_conf=0x{shuttle.sensor.alt_gyr_conf:04X}")
time.sleep(0.1)
a_x, a_y, a_z = shuttle.sensor.acc_data
logger.info(f"acceleration=({a_x=}, {a_y=}, {a_z=})")

g_x, g_y, g_z = shuttle.sensor.gyr_data
logger.info(f"angular_velocity=({g_x=}, {g_y=}, {g_z=})")
49 changes: 49 additions & 0 deletions examples/bmi323/bmi323_spi_interrupt_streaming.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
import logging
import struct
import sys
import time
from pathlib import Path

from umrx_app_v3.shuttle_board.bmi323.bmi323_shuttle import BMI323Shuttle


def setup_logging(level: int = logging.DEBUG) -> logging.Logger:
logger = logging.getLogger()
logger.setLevel(level)
stdout_handler = logging.StreamHandler(sys.stdout)
log_format = "(%(asctime)s) [%(levelname)-8s] %(filename)s:%(lineno)d: %(message)s"
log_formatter = logging.Formatter(log_format)
stdout_handler.setFormatter(log_formatter)
file_handler = logging.FileHandler(f"{Path(__file__).parent / Path(__file__).stem}.log", mode="w")
file_handler.setFormatter(log_formatter)
logger.addHandler(stdout_handler)
logger.addHandler(file_handler)
return logger


if __name__ == "__main__":
logger = setup_logging()
# This example is for Application Board 3.1 hardware
shuttle = BMI323Shuttle.on_hardware_v3_rev1()
shuttle.initialize()
shuttle.check_connected_hw()

shuttle.configure_spi()
_ = shuttle.board.read_spi(shuttle.CS, 0, 1) # dummy read is required, do not delete

logger.info(f"acc_chip_id=0x{shuttle.sensor.chip_id:04X}")
assert shuttle.sensor.chip_id == 0x0043
shuttle.configure_interrupt_streaming()
shuttle.start_streaming()
time.sleep(0.1)
for idx in range(1000):
for streaming in shuttle.board.receive_interrupt_streaming_multiple(includes_mcu_timestamp=False):
sensor_id, packet, time_stamp, payload = streaming
if sensor_id == 1:
a_x, a_y, a_z = struct.unpack("<xhhh", payload)
logger.info(f"[{idx}][{packet}][a] {' ' * 30} a_x={a_x:04d}, a_y={a_y:04d}, a_z={a_z:04d} ")
elif sensor_id == 2:
g_x, g_y, g_z = struct.unpack("<xhhh", payload)
logger.info(f"[{idx}][{packet}][g] g_x={g_x:04d}, g_y={g_y:04d}, g_z={g_z:04d} ")
time.sleep(0.05)
shuttle.board.stop_interrupt_streaming()
51 changes: 51 additions & 0 deletions examples/bmi323/bmi323_spi_polling_streaming.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
import logging
import struct
import sys
import time
from pathlib import Path

from umrx_app_v3.shuttle_board.bmi323.bmi323_shuttle import BMI323Shuttle


def setup_logging(level: int = logging.DEBUG) -> logging.Logger:
logger = logging.getLogger()
logger.setLevel(level)
stdout_handler = logging.StreamHandler(sys.stdout)
log_format = "(%(asctime)s) [%(levelname)-8s] %(filename)s:%(lineno)d: %(message)s"
log_formatter = logging.Formatter(log_format)
stdout_handler.setFormatter(log_formatter)
file_handler = logging.FileHandler(f"{Path(__file__).parent / Path(__file__).stem}.log", mode="w")
file_handler.setFormatter(log_formatter)
logger.addHandler(stdout_handler)
logger.addHandler(file_handler)
return logger


if __name__ == "__main__":
logger = setup_logging()
# This example is for Application Board 3.1 hardware
shuttle = BMI323Shuttle.on_hardware_v3_rev1()
shuttle.initialize()
shuttle.check_connected_hw()

shuttle.configure_spi()
_ = shuttle.board.read_spi(shuttle.CS, 0, 1) # dummy read is required, do not delete

logger.info(f"chip_id=0x{shuttle.sensor.chip_id:02X}")
assert shuttle.sensor.chip_id == 0x0043
shuttle.configure_polling_streaming()
shuttle.start_streaming()
time.sleep(0.1)
for idx in range(1000):
for streaming in shuttle.board.receive_polling_streaming_multiple():
sensor_id, payload = streaming
a_x, a_y, a_z, g_x, g_y, g_z, temperature, time_stamp = struct.unpack("<xhhhhhhHI", payload)
temperature_c = 23 + (temperature / 512)
time_stamp_second = time_stamp * 39.0625 / 1e6
logger.info(
f"[{idx=}], accel({a_x=:+05d}, {a_y=:+05d}, {a_z=:+05d}), gyro({g_x=:+05d}, {g_y=:+05d}, {g_z=:+05d}), "
f"T={temperature_c:+2.3f}, time_stamp(sec)={time_stamp_second:.6f}"
)

time.sleep(0.05)
shuttle.board.stop_polling_streaming()
68 changes: 68 additions & 0 deletions examples/bmi323/bmi323_spi_read_write.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
import logging
import sys
import time
from pathlib import Path

from umrx_app_v3.shuttle_board.bmi323.bmi323_shuttle import BMI323Shuttle


def setup_logging(level: int = logging.DEBUG) -> logging.Logger:
logger = logging.getLogger()
logger.setLevel(level)
stdout_handler = logging.StreamHandler(sys.stdout)
log_format = "(%(asctime)s) [%(levelname)-8s] %(filename)s:%(lineno)d: %(message)s"
log_formatter = logging.Formatter(log_format)
stdout_handler.setFormatter(log_formatter)
file_handler = logging.FileHandler(f"{Path(__file__).parent / Path(__file__).stem}.log", mode="w")
file_handler.setFormatter(log_formatter)
logger.addHandler(stdout_handler)
logger.addHandler(file_handler)
return logger


if __name__ == "__main__":
logger = setup_logging()
# For using with Application board 3.0, replace the line below with:
# shuttle = BMI088Shuttle.on_hardware_v3_rev0()
shuttle = BMI323Shuttle.on_hardware_v3_rev1()
shuttle.initialize()
shuttle.check_connected_hw()

shuttle.configure_spi()
_ = shuttle.board.read_spi(shuttle.CS, 0, 1) # dummy read is required, do not delete

res = shuttle.board.read_spi(shuttle.CS, 0, 3)
logger.info(f"{res=}")

res = shuttle.board.read_spi(shuttle.CS, 0, 3)
logger.info(f"{res=}")

logger.info(f"chip_id=0x{shuttle.sensor.chip_id:04X}")
logger.info(f"err_reg=0x{shuttle.sensor.err_reg:04X}")
logger.info(f"err_reg=0x{shuttle.sensor.status:04X}")

a_x, a_y, a_z = shuttle.sensor.acc_data
logger.info(f"acceleration=({a_x=:04X}, {a_y=:04X}, {a_z=:04X})")

g_x, g_y, g_z = shuttle.sensor.gyr_data
logger.info(f"angular_velocity=({g_x=:04X}, {g_y=:04X}, {g_z=:04X})")

logger.info(f"sensor_time={shuttle.sensor.sensor_time:04X}")

logger.info(f"acc_conf=0x{shuttle.sensor.acc_conf:04X}")
logger.info(f"gyr_conf=0x{shuttle.sensor.gyr_conf:04X}")
# start accelerometer and gyro measurements
shuttle.sensor.acc_conf = 0x4027
shuttle.sensor.gyr_conf = 0x404B

logger.info(f"acc_conf=0x{shuttle.sensor.acc_conf:04X}")
logger.info(f"gyr_conf=0x{shuttle.sensor.gyr_conf:04X}")

logger.info(f"alt_acc_conf=0x{shuttle.sensor.alt_acc_conf:04X}")
logger.info(f"alt_gyr_conf=0x{shuttle.sensor.alt_gyr_conf:04X}")
time.sleep(0.1)
a_x, a_y, a_z = shuttle.sensor.acc_data
logger.info(f"acceleration=({a_x=}, {a_y=}, {a_z=})")

g_x, g_y, g_z = shuttle.sensor.gyr_data
logger.info(f"angular_velocity=({g_x=}, {g_y=}, {g_z=})")
Loading

0 comments on commit 75f0478

Please sign in to comment.