Skip to content

IMU Component #48

@Mikefly123

Description

@Mikefly123

What Does This Component Do?

This is a generic component for pulling data from an IMU sensor. This component should accomplish the following at this stage:

  • Identify if the I2C device is present on the selected bus
  • Read 3-Axis Accelerometer Data (in m/s)
  • Read 3-Axis Gyroscope Data (in deg/s and rad/s)
  • Read 3-Axis Magnetometer Data (in uT)
  • Control Sleep / Wake for the Components
  • Control Operations Modes (things like adjusting the sensitivity range or entering a calibration mode)

Design Notes

LSM303AGR Datasheet
LSM5DSOX Datasheet

Default I2C Addresses 
LSM6: 110101xb #0x35
LSM3: 0011001b #0x19

Due to tricky component availability during the initial creation of the PROVES Kit, we employed a pair of IC's to accomplish IMU tasks rather than a single one. On V4 Flight Controller Boards you will find the LSM6DSOTR Accelerometer and Gyroscope alongside an LSM303AGR Accelerometer and Magnetometer. In the future it is possible that we will reconsolidate these two devices back into a single 9-DoF (9-Degree of Freedom) IMU, thus it might be productive to write the IMU component in a relatively generic way so you can just drop in and out the underlying device library while maintaining the structure of the function calls, telemetry, and events.

The IMU component has two functions, the first and primary being to provide gyroscope and magnetometer data while on-orbit to a future Attitude Determination and Control Component that will use these sensor inputs to orient the satellite. For now it will be good to just capture this data and make it available for logging into a state of health component. The second function of the IMU component is as one of the fundamental learning tools for understanding how to interact with hardware and sensors. Although the accelerometer is relatively useless in the zero g environment of space, here on the ground it is a fantastic way to have newcomers gain an intuition for using code to interact with hardware and see direct results from moving the board around in 3D space.

Relevant Libraries

Adafruit LSM6DS Library
Adafruit LSM303AGR Library
Adafruit LSM303 Arduino Tutorial

If using the Adafruit developed C++ libraries for these sensors it may be productive to explore using the Adafruit Unified Sensor System. The Unified Sensor Library seems to have been a way for Adafruit to try and introduce one generalized library that would provide an abstraction layer between common sensors and the resulting data that they output.

Adafruit Unified Sensor
Adafruit BusIO
   
The F' Baremetal System Reference has a Sensors Component that wraps up code for interfacing with an MPU 9250 IMU and pulling accelerometer and gyro data from it. In previous iterations of the F' workshop, collecting IMU data was part of the tutorial task, but it seems like in recent years that has been descoped to just the LED tutorial.

Example CircuitPython Implementation

In pysquared.py

from adafruit_lsm6ds.lsm6dsox import LSM6DSOX  # IMU
import adafruit_lis2mdl  # Magnetometer
...
class Satellite:
    def __init__(self):
        """
        IMU Initialization
        """
        try:
            self.imu = LSM6DSOX(self.i2c1)
            self.hardware["IMU"] = True
        except Exception as e:
            self.error_print("[ERROR][IMU]" + "".join(traceback.format_exception(e)))

        # Initialize Magnetometer
        try:
            self.mangetometer = adafruit_lis2mdl.LIS2MDL(self.i2c1)
            self.hardware["Mag"] = True
        except Exception as e:
            self.error_print("[ERROR][Magnetometer]")
            traceback.print_exception(None, e, e.__traceback__)
    ...
    @property
    def gyro(self):
        try:
            return self.imu.gyro
        except Exception as e:
            self.error_print("[ERROR][GYRO]" + "".join(traceback.format_exception(e)))

    @property
    def accel(self):
        try:
            return self.imu.acceleration
        except Exception as e:
            self.error_print("[ERROR][ACCEL]" + "".join(traceback.format_exception(e)))

    @property
    def imu_temp(self):
        try:
            return self.imu.temperature
        except Exception as e:
            self.error_print("[ERROR][TEMP]" + "".join(traceback.format_exception(e)))

    @property
    def mag(self):
        try:
            return self.mangetometer.magnetic
        except Exception as e:
            self.error_print("[ERROR][mag]" + "".join(traceback.format_exception(e)))

In functions.py

        def do_detumble():
            try:
                import detumble

                for _ in range(3):
                    data = [self.cubesat.IMU.Gyroscope, self.cubesat.IMU.Magnetometer]
                    data[0] = list(data[0])
                    for x in range(3):
                        if data[0][x] < 0.01:
                            data[0][x] = 0.0
                    data[0] = tuple(data[0])
                    dipole = detumble.magnetorquer_dipole(data[1], data[0])
                    self.debug_print("Dipole: " + str(dipole))
                    self.send("Detumbling! Gyro, Mag: " + str(data))
                    time.sleep(1)
                    actuate(dipole, dur)
            except Exception as e:
                self.debug_print(
                    "Detumble error: " + "".join(traceback.format_exception(e))
                )

Reference Schematic

image

Metadata

Metadata

Assignees

No one assigned

    Labels

    new componentCreating a new component for this tasksensorRelating to a sensor implementation

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions