|
| 1 | +# SPDX-FileCopyrightText: 2023 Cedar Grove Maker Studios |
| 2 | +# SPDX-License-Identifier: MIT |
| 3 | + |
| 4 | +""" |
| 5 | +'lis3mdl_calibrator.py' is a simple CircuitPython calibrator example for |
| 6 | +the LIS3MDL magnetometer. The resultant offset values can be used to |
| 7 | +compensate for 'hard iron' effects, static magnetic fields, or to orient |
| 8 | +the sensor with the earth's magnetic field for use as a compass. |
| 9 | +
|
| 10 | +The calibrator measures the minimum and maximum values for each axis as |
| 11 | +the sensor is moved. The values are captured over a fixed number of |
| 12 | +samples. A middle-of-the-range calibration offset value is calculated |
| 13 | +and reported after all samples are collected. |
| 14 | +
|
| 15 | +The sensor needs to be tumbled during the collection period in a manner |
| 16 | +that exercises the entire range of each axis. A series of overlapping |
| 17 | +figure-eight patterns is recommended. |
| 18 | +
|
| 19 | +This code was derived from the '9dof_calibration.py' Blinka code |
| 20 | +authored by Melissa LeBlanc-Williams for the 'Adafruit SensorLab - |
| 21 | +Magnetometer Calibration' learning guide (c)2020. |
| 22 | +""" |
| 23 | + |
| 24 | +import time |
| 25 | +import board |
| 26 | +import busio |
| 27 | +from adafruit_lis3mdl import LIS3MDL |
| 28 | + |
| 29 | +SAMPLE_SIZE = 2000 |
| 30 | + |
| 31 | +i2c = busio.I2C(board.SCL, board.SDA) |
| 32 | +magnetometer = LIS3MDL(i2c) |
| 33 | + |
| 34 | +while True: |
| 35 | + print("=" * 40) |
| 36 | + print("LIS3MDL MAGNETOMETER CALIBRATION") |
| 37 | + print(" Tumble the sensor through a series of") |
| 38 | + print(" overlapping figure-eight patterns") |
| 39 | + print(f" for approximately {SAMPLE_SIZE/100:.0f} seconds \n") |
| 40 | + |
| 41 | + print(" countdown to start:", end=" ") |
| 42 | + for i in range(5, -1, -1): |
| 43 | + print(i, end=" ") |
| 44 | + time.sleep(1) |
| 45 | + print("\n MOVE the sensor...") |
| 46 | + print(" > progress <") |
| 47 | + print(" ", end="") |
| 48 | + |
| 49 | + # Initialize the min/max values |
| 50 | + mag_x, mag_y, mag_z = magnetometer.magnetic |
| 51 | + min_x = max_x = mag_x |
| 52 | + min_y = max_y = mag_y |
| 53 | + min_z = max_z = mag_z |
| 54 | + |
| 55 | + for i in range(SAMPLE_SIZE): |
| 56 | + # Capture the samples and show the progress |
| 57 | + if not i % (SAMPLE_SIZE / 20): |
| 58 | + print("*", end="") |
| 59 | + |
| 60 | + mag_x, mag_y, mag_z = magnetometer.magnetic |
| 61 | + |
| 62 | + min_x = min(min_x, mag_x) |
| 63 | + min_y = min(min_y, mag_y) |
| 64 | + min_z = min(min_z, mag_z) |
| 65 | + |
| 66 | + max_x = max(max_x, mag_x) |
| 67 | + max_y = max(max_y, mag_y) |
| 68 | + max_z = max(max_z, mag_z) |
| 69 | + |
| 70 | + time.sleep(0.01) |
| 71 | + |
| 72 | + # Calculate the middle of the min/max range |
| 73 | + offset_x = (max_x + min_x) / 2 |
| 74 | + offset_y = (max_y + min_y) / 2 |
| 75 | + offset_z = (max_z + min_z) / 2 |
| 76 | + |
| 77 | + print( |
| 78 | + f"\n\n Final Calibration: X:{offset_x:6.2f} Y:{offset_y:6.2f} Z:{offset_z:6.2f} uT\n" |
| 79 | + ) |
| 80 | + |
| 81 | + time.sleep(5) |
0 commit comments