Project Setup
Are you new to using CircuitPython? No worries, there is a full getting-started guide here.
Plug the device into your computer with a known good USB cable (not a charge-only cable). The device will appear to your computer in File Explorer or Finder (depending on your operating system) as a flash drive named CIRCUITPY. If the drive does not appear, you can install CircuitPython on your device and then return here.
Download the project files with the Download Project Bundle button below. Unzip the file and copy/paste the code.py and other project files to your CIRCUITPY drive using File Explorer or Finder (depending on your operating system).
Run Calibrate Script
In order for the compass function most effectively you must obtain some calibration values from the sensor breakout by running the calibration script on this page. The script is included in the project bundle with the name calibrate.py.
To run it, connect to the serial console (for example in the Mu program Serial window), press Ctrl-C on your keyboard to enter the REPL. Then type import calibrate
and press enter. Example output is shown below.
Watch the serial output and follow the directions shown there. The script will first prompt you to set the sensor down on a flat surface and leave it perfectly still. After it takes several readings it will then ask you to start moving the sensor around. Pick up the box and carefully wave it around in a figure eight motion twisting and turning it as you go. The goal is to move the sensor into every possible orientation while the calibration code keeps track of the extremes of the values in each axis.
Once the script is finish select the calibration values printed at the end and copy them. They need to be pasted into the code.py script of the compass on the next page.
>>> import calibrate Preparing gyroscope calibration. Keep board perfectly still on flat surface. Starting gyroscope calibration.. Uncalibrated gyro: (-0.00473421, -0.00290161, 0.00122173) Calibrated gyro: (-0.00946841, -0.00580322, 0.00244346) ... Gyroscope calibrated! Preparing magnetometer calibration. Move board around in 3D space. Starting magnetometer calibration.. Uncalibrated: -56.3578 29.0558 -37.3283 Calibr: -1.0 1.0 1.0 MAG_MIN = [-56.3578, 28.1935, -37.8398] MAG_MAX = [-55.9047, 29.0558, -37.3283] ... MAG_MIN = [-75.1973, -22.5665, -34.5221] MAG_MAX = [-1.2131, 68.1379, 20.8126] GYRO_CAL = [-0.0038, -0.0026, -0.0011]
The code for the calibrate.py script is shown below.
# SPDX-FileCopyrightText: 2025 Tim Cocks for Adafruit Industries # SPDX-License-Identifier: MIT # # Adapted from Liz Clark's calibrate.py in the QualiaS3 Compass learn guide # https://learn.adafruit.com/qualia-s3-compass/code-the-compass # # Which was adapted from Gamblor21's calibrate.py in the Gamblor21_CircuitPython_AHRS library # https://github.com/gamblor21/Gamblor21_CircuitPython_AHRS/blob/master/examples/calibrate.py # # Gyro will be calibrated first, followed by magnetometer # Keep the board still for gyro, move around for magnetometer import time import board from adafruit_lsm6ds.lsm6dsox import LSM6DSOX import adafruit_lis3mdl i2c = board.STEMMA_I2C() accel_gyro = LSM6DSOX(i2c) magnetometer = adafruit_lis3mdl.LIS3MDL(i2c) MAG_MIN = [1000, 1000, 1000] MAG_MAX = [-1000, -1000, -1000] def map_range(x, in_min, in_max, out_min, out_max): """ Maps a number from one range to another. :return: Returns value mapped to new range :rtype: float """ mapped = (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min if out_min <= out_max: return max(min(mapped, out_max), out_min) return min(max(mapped, out_max), out_min) def calibrate_gyro(): """ Calibrates gyroscope Gyroscope values are in rads/s """ gx, gy, gz = accel_gyro.gyro min_gx = gx min_gy = gy min_gz = gz max_gx = gx max_gy = gy max_gz = gz mid_gx = gx mid_gy = gy mid_gz = gz for _ in range(10): gx, gy, gz = accel_gyro.gyro min_gx = min(min_gx, gx) min_gy = min(min_gy, gy) min_gz = min(min_gz, gz) max_gx = max(max_gx, gx) max_gy = max(max_gy, gy) max_gz = max(max_gz, gz) mid_gx = (max_gx + min_gx) / 2 mid_gy = (max_gy + min_gy) / 2 mid_gz = (max_gz + min_gz) / 2 print("Uncalibrated gyro: ", (gx, gy, gz)) print("Calibrated gyro: ", (gx + mid_gx, gy + mid_gy, gz + mid_gz)) print("Gyro calibration: ", (mid_gx, mid_gy, mid_gz)) time.sleep(1) mid_gx = float(f"{mid_gx:.4f}") mid_gy = float(f"{mid_gy:.4f}") mid_gz = float(f"{mid_gz:.4f}") _CAL = [mid_gx, mid_gy, mid_gz] return _CAL def calibrate_mag(): """ Calibrates a magnometer """ countavg = 0 x, y, z = magnetometer.magnetic mag_vals = [x, y, z] for i in range(3): MAG_MIN[i] = min(MAG_MIN[i], mag_vals[i]) MAG_MAX[i] = max(MAG_MAX[i], mag_vals[i]) for _ in range(10): x, y, z = magnetometer.magnetic mag_vals = [x, y, z] for i in range(3): MAG_MIN[i] = min(MAG_MIN[i], mag_vals[i]) MAG_MAX[i] = max(MAG_MAX[i], mag_vals[i]) countavg += 1 print("Uncalibrated:", x, y, z) cal_x = map_range(x, MAG_MIN[0], MAG_MAX[0], -1, 1) cal_y = map_range(y, MAG_MIN[1], MAG_MAX[1], -1, 1) cal_z = map_range(z, MAG_MIN[2], MAG_MAX[2], -1, 1) print("Calibrate: ", cal_x, cal_y, cal_z) print("MAG_MIN =", MAG_MIN) print("MAG_MAX =", MAG_MAX) time.sleep(1) return MAG_MIN, MAG_MAX print("Preparing gyroscope calibration. Keep board perfectly still on flat surface.") time.sleep(5) print("Starting gyroscope calibration..") print() GYRO_CAL = calibrate_gyro() print("Gyroscope calibrated!") print("Preparing magnetometer calibration. Move board around in 3D space.") time.sleep(5) print("Starting magnetometer calibration..") print() MAG_MIN, MAG_MAX = calibrate_mag() print("Magnetometer calibrated!") print() print("MAG_MIN =", MAG_MIN) print("MAG_MAX =", MAG_MAX) print("GYRO_CAL =", GYRO_CAL)
Page last edited February 26, 2025
Text editor powered by tinymce.