167 lines
5.2 KiB
C++
167 lines
5.2 KiB
C++
#include <Wire.h>
|
|
#include <Adafruit_Sensor.h>
|
|
#include <Mahony.h>
|
|
#include <Madgwick.h>
|
|
|
|
// Note: This sketch is a WORK IN PROGRESS
|
|
|
|
#define ST_LSM303DLHC_L3GD20 (0)
|
|
#define ST_LSM9DS1 (1)
|
|
#define NXP_FXOS8700_FXAS21002 (2)
|
|
|
|
// Define your target sensor(s) here based on the list above!
|
|
// #define AHRS_VARIANT ST_LSM303DLHC_L3GD20
|
|
#define AHRS_VARIANT NXP_FXOS8700_FXAS21002
|
|
|
|
#if AHRS_VARIANT == ST_LSM303DLHC_L3GD20
|
|
#include <Adafruit_L3GD20_U.h>
|
|
#include <Adafruit_LSM303_U.h>
|
|
#elif AHRS_VARIANT == ST_LSM9DS1
|
|
// ToDo!
|
|
#elif AHRS_VARIANT == NXP_FXOS8700_FXAS21002
|
|
#include <Adafruit_FXAS21002C.h>
|
|
#include <Adafruit_FXOS8700.h>
|
|
#else
|
|
#error "AHRS_VARIANT undefined! Please select a target sensor combination!"
|
|
#endif
|
|
|
|
|
|
// Create sensor instances.
|
|
#if AHRS_VARIANT == ST_LSM303DLHC_L3GD20
|
|
Adafruit_L3GD20_Unified gyro(20);
|
|
Adafruit_LSM303_Accel_Unified accel(30301);
|
|
Adafruit_LSM303_Mag_Unified mag(30302);
|
|
#elif AHRS_VARIANT == ST_LSM9DS1
|
|
// ToDo!
|
|
#elif AHRS_VARIANT == NXP_FXOS8700_FXAS21002
|
|
Adafruit_FXAS21002C gyro = Adafruit_FXAS21002C(0x0021002C);
|
|
Adafruit_FXOS8700 accelmag = Adafruit_FXOS8700(0x8700A, 0x8700B);
|
|
#endif
|
|
|
|
// Mag calibration values are calculated via ahrs_calibration.
|
|
// These values must be determined for each board/environment.
|
|
// See the image in this sketch folder for the values used
|
|
// below.
|
|
|
|
// Offsets applied to raw x/y/z mag values
|
|
float mag_offsets[3] = { 0.93F, -7.47F, -35.23F };
|
|
|
|
// Soft iron error compensation matrix
|
|
float mag_softiron_matrix[3][3] = { { 0.943, 0.011, 0.020 },
|
|
{ 0.022, 0.918, -0.008 },
|
|
{ 0.020, -0.008, 1.156 } };
|
|
|
|
float mag_field_strength = 50.23F;
|
|
|
|
// Offsets applied to compensate for gyro zero-drift error for x/y/z
|
|
float gyro_zero_offsets[3] = { 0.0F, 0.0F, 0.0F };
|
|
|
|
// Mahony is lighter weight as a filter and should be used
|
|
// on slower systems
|
|
Mahony filter;
|
|
//Madgwick filter;
|
|
|
|
void setup()
|
|
{
|
|
Serial.begin(115200);
|
|
|
|
// Wait for the Serial Monitor to open (comment out to run without Serial Monitor)
|
|
// while(!Serial);
|
|
|
|
Serial.println(F("Adafruit AHRS Fusion Example")); Serial.println("");
|
|
|
|
// Initialize the sensors.
|
|
if(!gyro.begin())
|
|
{
|
|
/* There was a problem detecting the gyro ... check your connections */
|
|
Serial.println("Ooops, no gyro detected ... Check your wiring!");
|
|
while(1);
|
|
}
|
|
|
|
#if AHRS_VARIANT == NXP_FXOS8700_FXAS21002
|
|
if(!accelmag.begin(ACCEL_RANGE_4G))
|
|
{
|
|
Serial.println("Ooops, no FXOS8700 detected ... Check your wiring!");
|
|
while(1);
|
|
}
|
|
#else
|
|
if (!accel.begin())
|
|
{
|
|
/* There was a problem detecting the accel ... check your connections */
|
|
Serial.println("Ooops, no accel detected ... Check your wiring!");
|
|
while (1);
|
|
}
|
|
|
|
if (!mag.begin())
|
|
{
|
|
/* There was a problem detecting the mag ... check your connections */
|
|
Serial.println("Ooops, no mag detected ... Check your wiring!");
|
|
while (1);
|
|
}
|
|
#endif
|
|
|
|
// Filter expects 70 samples per second
|
|
// Based on a Bluefruit M0 Feather ... rate should be adjuted for other MCUs
|
|
filter.begin(10);
|
|
}
|
|
|
|
void loop(void)
|
|
{
|
|
sensors_event_t gyro_event;
|
|
sensors_event_t accel_event;
|
|
sensors_event_t mag_event;
|
|
|
|
// Get new data samples
|
|
gyro.getEvent(&gyro_event);
|
|
#if AHRS_VARIANT == NXP_FXOS8700_FXAS21002
|
|
accelmag.getEvent(&accel_event, &mag_event);
|
|
#else
|
|
accel.getEvent(&accel_event);
|
|
mag.getEvent(&mag_event);
|
|
#endif
|
|
|
|
// Apply mag offset compensation (base values in uTesla)
|
|
float x = mag_event.magnetic.x - mag_offsets[0];
|
|
float y = mag_event.magnetic.y - mag_offsets[1];
|
|
float z = mag_event.magnetic.z - mag_offsets[2];
|
|
|
|
// Apply mag soft iron error compensation
|
|
float mx = x * mag_softiron_matrix[0][0] + y * mag_softiron_matrix[0][1] + z * mag_softiron_matrix[0][2];
|
|
float my = x * mag_softiron_matrix[1][0] + y * mag_softiron_matrix[1][1] + z * mag_softiron_matrix[1][2];
|
|
float mz = x * mag_softiron_matrix[2][0] + y * mag_softiron_matrix[2][1] + z * mag_softiron_matrix[2][2];
|
|
|
|
// Apply gyro zero-rate error compensation
|
|
float gx = gyro_event.gyro.x + gyro_zero_offsets[0];
|
|
float gy = gyro_event.gyro.y + gyro_zero_offsets[1];
|
|
float gz = gyro_event.gyro.z + gyro_zero_offsets[2];
|
|
|
|
// The filter library expects gyro data in degrees/s, but adafruit sensor
|
|
// uses rad/s so we need to convert them first (or adapt the filter lib
|
|
// where they are being converted)
|
|
gx *= 57.2958F;
|
|
gy *= 57.2958F;
|
|
gz *= 57.2958F;
|
|
|
|
// Update the filter
|
|
filter.update(gx, gy, gz,
|
|
accel_event.acceleration.x, accel_event.acceleration.y, accel_event.acceleration.z,
|
|
mx, my, mz);
|
|
|
|
// Print the orientation filter output
|
|
// Note: To avoid gimbal lock you should read quaternions not Euler
|
|
// angles, but Euler angles are used here since they are easier to
|
|
// understand looking at the raw values. See the ble fusion sketch for
|
|
// and example of working with quaternion data.
|
|
float roll = filter.getRoll();
|
|
float pitch = filter.getPitch();
|
|
float heading = filter.getYaw();
|
|
Serial.print(millis());
|
|
Serial.print(" - Orientation: ");
|
|
Serial.print(heading);
|
|
Serial.print(" ");
|
|
Serial.print(pitch);
|
|
Serial.print(" ");
|
|
Serial.println(roll);
|
|
|
|
delay(10);
|
|
}
|