Skip to content

Commit 225dd4f

Browse files
committed
🎉 add support for BMM350 [#16]
Add support for BMM350 magnetometer. Closes #16
1 parent 1bdd94c commit 225dd4f

File tree

11 files changed

+1018
-9
lines changed

11 files changed

+1018
-9
lines changed

README.md

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -276,15 +276,16 @@ print(result)
276276

277277
Take a look at the additional [examples](./examples):
278278

279-
* [bma400](examples/bma400)
280-
* [bma456](examples/bma456)
281-
* [bma530](examples/bma530)
282-
* [bma580](examples/bma580)
283-
* [bme280](examples/bme280)
284-
* [bmi088](examples/bmi088)
285-
* [bmi323](examples/bmi323)
286-
* [bmp390](examples/bmp390)
287-
* [bmp585](examples/bmp585)
279+
* [`bma400`](examples/bma400)
280+
* [`bma456`](examples/bma456)
281+
* [`bma530`](examples/bma530)
282+
* [`bma580`](examples/bma580)
283+
* [`bme280`](examples/bme280)
284+
* [`bmi088`](examples/bmi088)
285+
* [`bmi323`](examples/bmi323)
286+
* [`bmm350`](examples/bmm350)
287+
* [`bmp390`](examples/bmp390)
288+
* [`bmp585`](examples/bmp585)
288289

289290
## Default firmware
290291

examples/README.md

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,19 @@ board:
114114
* [`bmi323/bmi323_spi_polling_streaming.py`](./bmi323/bmi323_spi_polling_streaming.py)
115115
* [`bmi323/bmi323_spi_interrupt_streaming.py`](./bmi323/bmi323_spi_interrupt_streaming.py)
116116

117+
118+
## [`bmm350`](https://www.bosch-sensortec.com/products/motion-sensors/magnetometers/bmm350/)
119+
120+
The examples in the [`bmm350`](./bmm350) folder
121+
show different communication features for the
122+
[BMM350 shuttle](https://www.bosch-sensortec.com/media/boschsensortec/downloads/shuttle_board_flyer/application_board_3_1/bst-bmm350-sf000.pdf)
123+
board:
124+
125+
* [`bmm350/bmm350_i2c_read_write.py`](./bmm350/bmm350_i2c_read_write.py)
126+
* [`bmm350/bmm350_i2c_polling_streaming.py`](./bmm350/bmm350_i2c_polling_streaming.py)
127+
* [`bmm350/bmm350_i2c_interrupt_streaming.py`](./bmm350/bmm350_i2c_interrupt_streaming.py)
128+
129+
117130
## [`bmp390`](https://www.bosch-sensortec.com/products/environmental-sensors/pressure-sensors/bmp390/)
118131

119132
The examples in the [`bmp390`](./bmp390) folder

examples/bmm350/__init__.py

Whitespace-only changes.
Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
import logging
2+
import struct
3+
import sys
4+
import time
5+
from pathlib import Path
6+
7+
from umrx_app_v3.sensors.bmm350 import BMM350
8+
from umrx_app_v3.shuttle_board.bmm350.bmm350_shuttle import BMM350Shuttle
9+
10+
11+
def setup_logging(level: int = logging.DEBUG) -> logging.Logger:
12+
logger = logging.getLogger()
13+
logger.setLevel(level)
14+
stdout_handler = logging.StreamHandler(sys.stdout)
15+
log_format = "(%(asctime)s) [%(levelname)-8s] %(message)s"
16+
log_formatter = logging.Formatter(log_format)
17+
stdout_handler.setFormatter(log_formatter)
18+
file_handler = logging.FileHandler(f"{Path(__file__).parent / Path(__file__).stem}.log", mode="w")
19+
file_handler.setFormatter(log_formatter)
20+
logger.addHandler(stdout_handler)
21+
logger.addHandler(file_handler)
22+
return logger
23+
24+
25+
if __name__ == "__main__":
26+
logger = setup_logging()
27+
shuttle = BMM350Shuttle.on_hardware_v3_rev1()
28+
shuttle.initialize()
29+
shuttle.check_connected_hw()
30+
31+
shuttle.configure_i2c()
32+
logger.info(f"chip_id=0x{shuttle.sensor.chip_id:02X}")
33+
assert shuttle.sensor.chip_id == 0x33
34+
_ = shuttle.sensor.compensate_magnetometer_and_temperature(0, 0, 0, 0) # cache OTP
35+
shuttle.close_otp()
36+
shuttle.configure_interrupt_streaming()
37+
shuttle.start_streaming()
38+
time.sleep(0.1)
39+
for idx in range(1000):
40+
for streaming in shuttle.board.receive_interrupt_streaming_multiple(includes_mcu_timestamp=False):
41+
sensor_id, packet, time_stamp, payload = streaming
42+
(
43+
m_x_xlsb,
44+
m_x_lsb,
45+
m_x_msb,
46+
m_y_xlsb,
47+
m_y_lsb,
48+
m_y_msb,
49+
m_z_xlsb,
50+
m_z_lsb,
51+
m_z_msb,
52+
temp_xlsb,
53+
temp_lsb,
54+
temp_msb,
55+
time_xlsb,
56+
time_lsb,
57+
time_msb,
58+
) = struct.unpack("<xxBBBBBBBBBBBBBBB", payload)
59+
m_x_raw = (m_x_msb << 16) | (m_x_lsb << 8) | m_x_xlsb
60+
m_y_raw = (m_y_msb << 16) | (m_y_lsb << 8) | m_y_xlsb
61+
m_z_raw = (m_z_msb << 16) | (m_z_lsb << 8) | m_z_xlsb
62+
m_x_signed, m_y_signed, m_z_signed = BMM350.sign_convert_magnetometer(m_x_raw, m_y_raw, m_z_raw)
63+
temp_raw = (temp_msb << 16) | (temp_lsb << 8) | temp_xlsb
64+
temp_signed = BMM350.sign_convert_24_bit(temp_raw)
65+
sensor_time = ((time_msb << 16) | (time_lsb << 8) | time_xlsb) * 39.0625e-6
66+
m_x, m_y, m_z, temp = shuttle.sensor.compensate_magnetometer_and_temperature(
67+
m_x_signed, m_y_signed, m_z_signed, temp_signed
68+
)
69+
logger.info(
70+
f"[{idx=:03d}], magnetometer(uT)=(x={m_x:+3.3f}, y={m_y:+3.3f}, z={m_z:+3.3f}), "
71+
f"temperature(C)={temp:.3f}, "
72+
f"time_stamp(s)={sensor_time:.3f}"
73+
)
74+
time.sleep(0.05)
75+
shuttle.board.stop_interrupt_streaming()
Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
import logging
2+
import struct
3+
import sys
4+
import time
5+
from pathlib import Path
6+
7+
from umrx_app_v3.sensors.bmm350 import BMM350
8+
from umrx_app_v3.shuttle_board.bmm350.bmm350_shuttle import BMM350Shuttle
9+
10+
11+
def setup_logging(level: int = logging.DEBUG) -> logging.Logger:
12+
logger = logging.getLogger()
13+
logger.setLevel(level)
14+
stdout_handler = logging.StreamHandler(sys.stdout)
15+
log_format = "(%(asctime)s) [%(levelname)-8s] %(message)s"
16+
log_formatter = logging.Formatter(log_format)
17+
stdout_handler.setFormatter(log_formatter)
18+
file_handler = logging.FileHandler(f"{Path(__file__).parent / Path(__file__).stem}.log", mode="w")
19+
file_handler.setFormatter(log_formatter)
20+
logger.addHandler(stdout_handler)
21+
logger.addHandler(file_handler)
22+
return logger
23+
24+
25+
if __name__ == "__main__":
26+
logger = setup_logging()
27+
# This example is for Application Board 3.1 hardware
28+
shuttle = BMM350Shuttle.on_hardware_v3_rev1()
29+
shuttle.initialize()
30+
shuttle.check_connected_hw()
31+
32+
shuttle.configure_i2c()
33+
logger.info(f"chip_id=0x{shuttle.sensor.chip_id:04X}")
34+
assert shuttle.sensor.chip_id == 0x33
35+
_ = shuttle.sensor.compensate_magnetometer_and_temperature(0, 0, 0, 0) # cache OTP
36+
shuttle.close_otp()
37+
shuttle.configure_polling_streaming()
38+
shuttle.start_streaming()
39+
time.sleep(0.1)
40+
for idx in range(1000):
41+
for streaming in shuttle.board.receive_polling_streaming_multiple():
42+
sensor_id, payload = streaming
43+
(
44+
m_x_xlsb,
45+
m_x_lsb,
46+
m_x_msb,
47+
m_y_xlsb,
48+
m_y_lsb,
49+
m_y_msb,
50+
m_z_xlsb,
51+
m_z_lsb,
52+
m_z_msb,
53+
temp_xlsb,
54+
temp_lsb,
55+
temp_msb,
56+
time_xlsb,
57+
time_lsb,
58+
time_msb,
59+
) = struct.unpack("<xxBBBBBBBBBBBBBBB", payload)
60+
m_x_raw = (m_x_msb << 16) | (m_x_lsb << 8) | m_x_xlsb
61+
m_y_raw = (m_y_msb << 16) | (m_y_lsb << 8) | m_y_xlsb
62+
m_z_raw = (m_z_msb << 16) | (m_z_lsb << 8) | m_z_xlsb
63+
m_x_signed, m_y_signed, m_z_signed = BMM350.sign_convert_magnetometer(m_x_raw, m_y_raw, m_z_raw)
64+
temp_raw = (temp_msb << 16) | (temp_lsb << 8) | temp_xlsb
65+
temp_signed = BMM350.sign_convert_24_bit(temp_raw)
66+
sensor_time = ((time_msb << 16) | (time_lsb << 8) | time_xlsb) * 39.0625e-6
67+
m_x, m_y, m_z, temp = shuttle.sensor.compensate_magnetometer_and_temperature(
68+
m_x_signed, m_y_signed, m_z_signed, temp_signed
69+
)
70+
logger.info(
71+
f"[{idx=:03d}], magnetometer(uT)=(x={m_x:+3.3f}, y={m_y:+3.3f}, z={m_z:+3.3f}), "
72+
f"temperature(C)={temp:.3f}, "
73+
f"time_stamp(s)={sensor_time:.3f}"
74+
)
75+
time.sleep(0.05)
76+
shuttle.board.stop_polling_streaming()
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
import logging
2+
import sys
3+
import time
4+
from pathlib import Path
5+
6+
from umrx_app_v3.shuttle_board.bmm350.bmm350_shuttle import BMM350Shuttle
7+
8+
9+
def setup_logging(level: int = logging.DEBUG) -> logging.Logger:
10+
logger = logging.getLogger()
11+
logger.setLevel(level)
12+
stdout_handler = logging.StreamHandler(sys.stdout)
13+
log_format = "(%(asctime)s) [%(levelname)-8s] %(filename)s:%(lineno)d: %(message)s"
14+
log_formatter = logging.Formatter(log_format)
15+
stdout_handler.setFormatter(log_formatter)
16+
file_handler = logging.FileHandler(f"{Path(__file__).parent / Path(__file__).stem}.log", mode="w")
17+
file_handler.setFormatter(log_formatter)
18+
logger.addHandler(stdout_handler)
19+
logger.addHandler(file_handler)
20+
return logger
21+
22+
23+
if __name__ == "__main__":
24+
logger = setup_logging()
25+
shuttle = BMM350Shuttle.on_hardware_v3_rev1()
26+
shuttle.initialize()
27+
shuttle.check_connected_hw()
28+
29+
shuttle.configure_i2c()
30+
31+
logger.info(f"chip_id=0x{shuttle.sensor.chip_id:02X}")
32+
logger.info(f"err_reg=0x{shuttle.sensor.err_reg:02X}")
33+
logger.info(f"pmu_cmd_aggr_set=0x{shuttle.sensor.pmu_cmd_aggr_set:02X}")
34+
logger.info(f"pmu_cmd_axis_en=0x{shuttle.sensor.pmu_cmd_axis_en:02X}")
35+
36+
logger.info(f"magnetometer_raw={shuttle.sensor.magnetometer_raw}")
37+
logger.info(f"temperature_raw={shuttle.sensor.temperature_raw:08X}")
38+
_ = shuttle.sensor.compensate_magnetometer_and_temperature(0, 0, 0, 0) # cache OTP
39+
shuttle.close_otp()
40+
shuttle.start_measurement()
41+
time.sleep(0.1)
42+
logger.info(f"pmu_cmd_status_0=0b{shuttle.sensor.pmu_cmd_status_0:08b}")
43+
logger.info(f"pmu_cmd_status_1=0b{shuttle.sensor.pmu_cmd_status_1:08b}")
44+
45+
magnetometer_raw = shuttle.sensor.magnetometer_raw
46+
temperature_raw = shuttle.sensor.temperature_raw
47+
m_x, m_y, m_z, temp = shuttle.sensor.compensate_magnetometer_and_temperature(*magnetometer_raw, temperature_raw)
48+
logger.info(f"magnetometer(uT)=(x={m_x}, y={m_y}, z={m_z})")
49+
logger.info(f"temperature(C)={temp}")
50+
logger.info(f"sensor_time(s)={shuttle.sensor.sensor_time}")

0 commit comments

Comments
 (0)