Self-test
What this example shows
Checking that the sensor's X and Y channels work, with the BMM350's built-in self-test. The sensor generates an internal field of about 130 µT on one axis at a time and measures the difference. A channel passes when the difference is at least 130 µT. The script runs the test once.
The example creates I2C bus 0 with SCL on GPIO 9 and SDA on GPIO 8. Change these pins to the ones you wired.
The example code
# FILE: bmm350-selfTest.py
# AUTHOR: Soldered Electronics
# BRIEF: Runs the BMM350's built-in self-test. The self-test generates an
# internal ~130 uT magnetic field on the X and Y channels and reports
# the resulting field difference; per the datasheet (section 5.1.6),
# a channel is considered working if its reported value is >= 130 uT.
# WORKS WITH: BMM350 Geomagnetic Sensor breakout: www.solde.red/333359
# LAST UPDATED: 2026-09-22
from bmm350 import BMM350, BMM350_OK
from machine import I2C, Pin
# Minimum self-test field difference to consider a channel passing,
# per the datasheet's self-test section
SELF_TEST_THRESHOLD_UT = 130.0
# Change these to match how your board wires I2C
i2c = I2C(0, scl=Pin(9), sda=Pin(8))
sensor = BMM350(i2c)
if sensor.status != BMM350_OK:
raise Exception("Failed to initialize BMM350: " + sensor.status_string())
print("BMM350 connected!")
# Run the self-test. The sensor automatically returns to normal mode
# afterwards since the constructor already left it there.
result = sensor.perform_self_test()
if result is not None:
x_pass = result["out_ust_x"] >= SELF_TEST_THRESHOLD_UT
y_pass = result["out_ust_y"] >= SELF_TEST_THRESHOLD_UT
print("X axis field: {:.2f} uT -> {}".format(result["out_ust_x"], "PASS" if x_pass else "FAIL"))
print("Y axis field: {:.2f} uT -> {}".format(result["out_ust_y"], "PASS" if y_pass else "FAIL"))
else:
print("Self-test failed to run:", sensor.status_string())
🔗Open the complete example
bmm350-selfTest.py at commit 0995e8d
This example also uses machine.I2C
(MicroPython reference)
and machine.Pin
(MicroPython reference),
which come with the MicroPython firmware and are not part of the bmm350
module.
Expected result: BMM350 connected!, then two result lines, X axis field:
and Y axis field:, each with the field difference in uT and PASS or
FAIL.
BMM350 connected!
X axis field: 146.83 uT -> PASS
Y axis field: 148.27 uT -> PASS
If the test cannot run, the script prints Self-test failed to run: and the
reason instead.
Functions used
BMM350(i2c=None, address=BMM350_I2C_ADSEL_SET_LOW)returns BMM350Constructor. Resets the sensor, checks its chip ID, loads its calibration data, sets 100 Hz with 4-sample averaging, enables all axes and starts normal mode. Raises an exception when the sensor does not answer or another chip answers. Without an i2c object it uses I2C(0, scl=Pin(22), sda=Pin(21)) when the firmware reports itself as esp32, esp8266 or one Soldered board's own firmware name, and raises an exception on any other board.
ReturnsThe sensor object.
Parameters
| Type | Name | Description |
|---|---|---|
I2C | i2c | An initialized machine.I2C object. Optional only on the boards the module detects (see the constructor above). |
int | address | I2C address. BMM350_I2C_ADSEL_SET_LOW (0x14, the default) or BMM350_I2C_ADSEL_SET_HIGH (0x15). |
perform_self_test()returns dictRuns the sensor's built-in self-test on the X and Y axes. When the sensor was in normal mode before, it returns to normal mode afterwards.
ReturnsA dict with out_ust_x and out_ust_y, the field difference on each axis in µT (130.0 or more is a pass), or None on an I2C error.
status_string()returns strDescribes the current sensor.status code.
ReturnsThe description, or an empty string when the status is BMM350_OK.
Putting it together
The constructor leaves the sensor in normal mode, so perform_self_test()
puts it back in normal mode when the test ends. The script compares
out_ust_x and out_ust_y with SELF_TEST_THRESHOLD_UT (130.0) and prints
PASS or FAIL for each axis.