You can easily calibrate a sensor using the Raspberry Pi using our calibration script. It runs from the command line using Blinka. This page assumes you have already set up Blinka on the Raspberry Pi, but if not, be sure to follow our CircuitPython Libraries on Linux and Raspberry Pi guide.
The easiest way to connect a 9-DoF sensor to the Raspberry Pi is to use a STEMMA QT/Qwiic connector which many of our sensors include.
Using a STEMMA QT Cable
To add a STEMMA connector to your Pi, the easiest way is to use one of our Raspberry Pi add ons that feature the STEMMA QT connector such as a display:
Or if you'd prefer something more minimal, you could even use a STEMMA QT SHIM:
You'll need a STEMMA cable as well.
Wiring the Sensor
If your sensor does not have a STEMMA connector, you could just wire it up directly to the Pi. The sensors typically have an I2C interface and connecting them up is easy. Here's an example using the LIS3MDL+LSM6DS33 sensor:
- Pi 3V to sensor VCC (red wire)
- Pi GND to sensor GND (black wire)
- Pi SCL to sensor SCL (green wire)
- Pi SDA to sensor SDA (yellow wire)
For more details on wiring up other sensors, be sure to check out the Python page in our ST 9-DoF Combo Breakouts and Wings guide.
Install the libraries
The calibration script uses the the Adafruit_CircuitPython_LIS3MDL and Adafruit_CircuitPython_LSM6DS libraries. To install, run the following commands:
pip3 install adafruit-circuitpython-lis3mdl
pip3 install adafruit-circuitpython-lsm6ds
If your default Python is version 3 you may need to run 'pip' instead. Just make sure you aren't trying to use CircuitPython on Python 2.x, it isn't supported! On some boards, you may need to add sudo
before pip3
.
If that complains about pip3 not being installed, then run this first to install it:
sudo apt-get install python3-pip
Full Example Code
Here's the full script to run the calibration. Go ahead and save that to your Pi as 9dof_calibration.py.
# SPDX-FileCopyrightText: 2020 Melissa LeBlanc-Williams for Adafruit Industries # # SPDX-License-Identifier: MIT import threading import time import board import busio from adafruit_lsm6ds import LSM6DSOX from adafruit_lis3mdl import LIS3MDL SAMPLE_SIZE = 500 class KeyListener: """Object for listening for input in a separate thread""" def __init__(self): self._input_key = None self._listener_thread = None def _key_listener(self): while True: self._input_key = input() def start(self): """Start Listening""" if self._listener_thread is None: self._listener_thread = threading.Thread( target=self._key_listener, daemon=True ) if not self._listener_thread.is_alive(): self._listener_thread.start() def stop(self): """Stop Listening""" if self._listener_thread is not None and self._listener_thread.is_alive(): self._listener_thread.join() @property def pressed(self): "Return whether enter was pressed since last checked" "" result = False if self._input_key is not None: self._input_key = None result = True return result def main(): # pylint: disable=too-many-locals, too-many-statements i2c = busio.I2C(board.SCL, board.SDA) gyro_accel = LSM6DSOX(i2c) magnetometer = LIS3MDL(i2c) key_listener = KeyListener() key_listener.start() ############################ # Magnetometer Calibration # ############################ print("Magnetometer Calibration") print("Start moving the board in all directions") print("When the magnetic Hard Offset values stop") print("changing, press ENTER to go to the next step") print("Press ENTER to continue...") while not key_listener.pressed: pass mag_x, mag_y, mag_z = magnetometer.magnetic min_x = max_x = mag_x min_y = max_y = mag_y min_z = max_z = mag_z while not key_listener.pressed: mag_x, mag_y, mag_z = magnetometer.magnetic print( "Magnetometer: X: {0:8.2f}, Y:{1:8.2f}, Z:{2:8.2f} uT".format( mag_x, mag_y, mag_z ) ) min_x = min(min_x, mag_x) min_y = min(min_y, mag_y) min_z = min(min_z, mag_z) max_x = max(max_x, mag_x) max_y = max(max_y, mag_y) max_z = max(max_z, mag_z) offset_x = (max_x + min_x) / 2 offset_y = (max_y + min_y) / 2 offset_z = (max_z + min_z) / 2 field_x = (max_x - min_x) / 2 field_y = (max_y - min_y) / 2 field_z = (max_z - min_z) / 2 print( "Hard Offset: X: {0:8.2f}, Y:{1:8.2f}, Z:{2:8.2f} uT".format( offset_x, offset_y, offset_z ) ) print( "Field: X: {0:8.2f}, Y:{1:8.2f}, Z:{2:8.2f} uT".format( field_x, field_y, field_z ) ) print("") time.sleep(0.01) mag_calibration = (offset_x, offset_y, offset_z) print( "Final Magnetometer Calibration: X: {0:8.2f}, Y:{1:8.2f}, Z:{2:8.2f} uT".format( offset_x, offset_y, offset_z ) ) ######################### # Gyroscope Calibration # ######################### gyro_x, gyro_y, gyro_z = gyro_accel.gyro min_x = max_x = gyro_x min_y = max_y = gyro_y min_z = max_z = gyro_z print("") print("") print("Gyro Calibration") print("Place your gyro on a FLAT stable surface.") print("Press ENTER to continue...") while not key_listener.pressed: pass for _ in range(SAMPLE_SIZE): gyro_x, gyro_y, gyro_z = gyro_accel.gyro print( "Gyroscope: X: {0:8.2f}, Y:{1:8.2f}, Z:{2:8.2f} rad/s".format( gyro_x, gyro_y, gyro_z ) ) min_x = min(min_x, gyro_x) min_y = min(min_y, gyro_y) min_z = min(min_z, gyro_z) max_x = max(max_x, gyro_x) max_y = max(max_y, gyro_y) max_z = max(max_z, gyro_z) offset_x = (max_x + min_x) / 2 offset_y = (max_y + min_y) / 2 offset_z = (max_z + min_z) / 2 noise_x = max_x - min_x noise_y = max_y - min_y noise_z = max_z - min_z print( "Zero Rate Offset: X: {0:8.2f}, Y:{1:8.2f}, Z:{2:8.2f} rad/s".format( offset_x, offset_y, offset_z ) ) print( "Rad/s Noise: X: {0:8.2f}, Y:{1:8.2f}, Z:{2:8.2f} rad/s".format( noise_x, noise_y, noise_z ) ) print("") gyro_calibration = (offset_x, offset_y, offset_z) print( "Final Zero Rate Offset: X: {0:8.2f}, Y:{1:8.2f}, Z:{2:8.2f} rad/s".format( offset_x, offset_y, offset_z ) ) print("") print("------------------------------------------------------------------------") print("Final Magnetometer Calibration Values: ", mag_calibration) print("Final Gyro Calibration Values: ", gyro_calibration) if __name__ == "__main__": main()
Using the Script
Start the script by typing:
python3 9dof_calibration.py
The script will first start by letting you know that it wants to calibrate the magnetometer.
Press ENTER to continue.
It will start measuring the magnetometer and scrolling the values. Start moving the sensor around in every direction.
The magnetic Hard Offset values should stop changing after a bit. After it does, press ENTER again.
The next step is to calibrate the Gyroscope. Place the sensor on a flat surface like a desk or table. Once it is lying still, press ENTER.
It will run through the numbers and then give you your final calibration values.
Using a different Sensor
If you are using a different sensor, you will need to install the appropriate library and then make a few changes to the script. The easiest way to find the correct library for your sensor is to look at the associated learn guide for that sensor. This can usually be found on the product page or by searching the Adafruit Learn System.
Here are the changes you will need to make depending on the sensor you have:
LIS3MDL+LSM6DSOX
No changes are necessary for this sensor.
LIS3MDL+LSM6DS33
You will need to change the import line from
from adafruit_lsm6ds import LSM6DSOX
to
from adafruit_lsm6ds import LSM6DS33
You will also need to change the declaration line from
gyro_accel = LSM6DSOX(i2c)
to
gyro_accel = LSM6DS33(i2c)
LSM9DS1
You will need to change the import lines from
from adafruit_lsm6ds import LSM6DSOX from adafruit_lis3mdl import LIS3MDL
to
from adafruit_lsm9ds1 import LSM9DS1_I2C
You will also need to change the declaration lines from
gyro_accel = LSM6DSOX(i2c) magnetometer = LIS3MDL(i2c)
to
magnetometer = gyro_accel = LSM9DS1_I2C(i2c)
FXOS8700 + FXAS21002
You will need to change the import lines from
from adafruit_lsm6ds import LSM6DSOX from adafruit_lis3mdl import LIS3MDL
to
from adafruit_fxos8700 import FXOS8700 from adafruit_fxas21002c import FXAS21002C
You will also need to change the declaration lines from
gyro_accel = LSM6DSOX(i2c) magnetometer = LIS3MDL(i2c)
to
gyro_accel = FXAS21002C(i2c) magnetometer = FXOS8700(i2c)
Also, change any instance of gyro_accel.gyro
to gyro_accel.gyroscope
and any instance of magnetometer.magnetic
to magnetometer.magnetometer
.
Text editor powered by tinymce.