Skip to main content

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.

ShellMicroPython
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 BMM350

Constructor. 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

TypeNameDescription
I2Ci2cAn initialized machine.I2C object. Optional only on the boards the module detects (see the constructor above).
intaddressI2C address. BMM350_I2C_ADSEL_SET_LOW (0x14, the default) or BMM350_I2C_ADSEL_SET_HIGH (0x15).
perform_self_test()returns dict

Runs 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 str

Describes 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.