Skip to content

Instantly share code, notes, and snippets.

@tshaddix
Last active June 11, 2016 16:38
Show Gist options
  • Save tshaddix/120be52f59fb1f2acb57ae09d2c65356 to your computer and use it in GitHub Desktop.
Save tshaddix/120be52f59fb1f2acb57ae09d2c65356 to your computer and use it in GitHub Desktop.
IMU code in attempts to get orientation with Madgwick
/*****************************************************************
LSM9DS1_Basic_I2C.ino
SFE_LSM9DS1 Library Simple Example Code - I2C Interface
Jim Lindblom @ SparkFun Electronics
Original Creation Date: April 30, 2015
https://github.com/sparkfun/LSM9DS1_Breakout
The LSM9DS1 is a versatile 9DOF sensor. It has a built-in
accelerometer, gyroscope, and magnetometer. Very cool! Plus it
functions over either SPI or I2C.
This Arduino sketch is a demo of the simple side of the
SFE_LSM9DS1 library. It'll demo the following:
How to create a LSM9DS1 object, using a constructor (global
variables section).
How to use the begin() function of the LSM9DS1 class.
How to read the gyroscope, accelerometer, and magnetometer
using the readGryo(), readAccel(), readMag() functions and
the gx, gy, gz, ax, ay, az, mx, my, and mz variables.
How to calculate actual acceleration, rotation speed,
magnetic field strength using the calcAccel(), calcGyro()
and calcMag() functions.
How to use the data from the LSM9DS1 to calculate
orientation and heading.
Hardware setup: This library supports communicating with the
LSM9DS1 over either I2C or SPI. This example demonstrates how
to use I2C. The pin-out is as follows:
LSM9DS1 --------- Arduino
SCL ---------- SCL (A5 on older 'Duinos')
SDA ---------- SDA (A4 on older 'Duinos')
VDD ------------- 3.3V
GND ------------- GND
(CSG, CSXM, SDOG, and SDOXM should all be pulled high.
Jumpers on the breakout board will do this for you.)
The LSM9DS1 has a maximum voltage of 3.6V. Make sure you power it
off the 3.3V rail! I2C pins are open-drain, so you'll be
(mostly) safe connecting the LSM9DS1's SCL and SDA pins
directly to the Arduino.
Development environment specifics:
IDE: Arduino 1.6.3
Hardware Platform: SparkFun Redboard
LSM9DS1 Breakout Version: 1.0
This code is beerware. If you see me (or any other SparkFun
employee) at the local, and you've found our code helpful,
please buy us a round!
Distributed as-is; no warranty is given.
*****************************************************************/
// The SFE_LSM9DS1 library requires both Wire and SPI be
// included BEFORE including the 9DS1 library.
#include <Wire.h>
#include <SPI.h>
#include <SparkFunLSM9DS1.h>
#include <MadgwickAHRS.h>
Madgwick filter;
//////////////////////////
// LSM9DS1 Library Init //
//////////////////////////
// Use the LSM9DS1 class to create an object. [imu] can be
// named anything, we'll refer to that throught the sketch.
LSM9DS1 imu;
///////////////////////
// Example I2C Setup //
///////////////////////
// SDO_XM and SDO_G are both pulled high, so our addresses are:
#define LSM9DS1_M 0x1E // Would be 0x1C if SDO_M is LOW
#define LSM9DS1_AG 0x6B // Would be 0x6A if SDO_AG is LOW
unsigned long microsPerReading, microsPrevious;
void setup()
{
Serial.begin(9600);
// Before initializing the IMU, there are a few settings
// we may need to adjust. Use the settings struct to set
// the device's communication mode and addresses:
imu.settings.device.commInterface = IMU_MODE_I2C;
imu.settings.device.mAddress = LSM9DS1_M;
imu.settings.device.agAddress = LSM9DS1_AG;
// imu.settings.accel.scale = 2; // Set accel range to +/-2g
// imu.settings.gyro.scale = 250; // Set gyro range to +/-250dps
// imu.settings.mag.scale = 8; // Set mag range to +/-8Gs
// The above lines will only take effect AFTER calling
// imu.begin(), which verifies communication with the IMU
// and turns it on.
if (!imu.begin())
{
Serial.println("Failed to communicate with LSM9DS1.");
Serial.println("Double-check wiring.");
Serial.println("Default settings in this sketch will " \
"work for an out of the box LSM9DS1 " \
"Breakout, but may need to be modified " \
"if the board jumpers are.");
while (1)
;
}
// initialize variables to pace updates to correct rate
microsPerReading = 1000000 / 25;
microsPrevious = micros();
filter.begin(25);
}
void loop()
{
float roll, pitch, yaw;
unsigned long microsNow;
// check if it's time to read data and update the filter
microsNow = micros();
if (microsNow - microsPrevious >= microsPerReading) {
imu.readGyro();
imu.readAccel();
imu.readMag();
float gx, gy, gz, ax, ay, az, mx, my, mz;
// Use a right-handed coordinate system
// secondary -/+ from calibration
gx = imu.calcGyro(imu.gy) - 0.3;
gy = imu.calcGyro(imu.gx) - 1.0;
gz = imu.calcGyro(imu.gz) + 3.0;
ax = imu.calcAccel(imu.ay);
ay = imu.calcAccel(imu.ax);
az = imu.calcAccel(imu.az) - 1.0;
mx = imu.calcMag(imu.my);
my = -imu.calcMag(imu.mx);
mz = imu.calcMag(imu.mz);
// Use these prints with plotter to debug
// Serial.print("A: ");
// Serial.print(ax);
// Serial.print(",");
// Serial.print(ay);
// Serial.print(",");
// Serial.println(az);
//
// Serial.print("G: ");
// Serial.print(gx);
// Serial.print(",");
// Serial.print(gy);
// Serial.print(",");
// Serial.println(gz);
//
// Serial.print("M: ");
// Serial.print(mx);
// Serial.print(",");
// Serial.print(my);
// Serial.print(",");
// Serial.println(mz);
// update the filter, which computes orientation
filter.update(gx, gy, gz, ax, ay, az, mx, my, mz);
// print the heading, pitch and roll
roll = filter.getRoll();
pitch = filter.getPitch();
yaw = filter.getYaw();
Serial.print(yaw);
Serial.print(",");
Serial.print(pitch);
Serial.print(",");
Serial.println(roll);
// increment previous time, so we keep proper pace
microsPrevious = microsPrevious + microsPerReading;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment