2 LSM9DS0 Sensor input

Breakout boards, sensors, other Adafruit kits, etc.

Moderators: adafruit_support_bill, adafruit

Please be positive and constructive with your questions and comments.
User avatar
adafruit_support_bill
 
Posts: 88093
Joined: Sat Feb 07, 2009 10:11 am

Re: 2 LSM9DS0 Sensor input

Post by adafruit_support_bill »

OK. Next, connect the second sensor as you planned and make sure that the first one still works with the default code.

If that still works. Change the CS pin definition to address the second sensor and verify that it works too.

User avatar
rburke12
 
Posts: 22
Joined: Sun Oct 26, 2014 10:10 pm

Re: 2 LSM9DS0 Sensor input

Post by rburke12 »

So I finally was able to get them working together. The problem ended up being the line that has Adafruit_LSM9DS0_A and B. I just took the _A and _B off and it seemed to work.

New issue:
I have taken the equations from the ahrs c file and inserted them into the sensorapi file. I am trying to find the angle between the two sensors at all times. when I use the heading it will look fine one second and then completely off the next. So I tried the Pitch and that also works to a certain point. When I rotate the sensor one way or the other it will increase from zero to 90deg. After the sensor reaches the point it is vertical and starts going upside down it goes from 90 to zero. I was hoping to see it would continue from 90 to 180. That is not the case though. Is this a known issue and can you think of any workarounds? I'm stumped....

Thanks for your help!

User avatar
adafruit_support_bill
 
Posts: 88093
Joined: Sat Feb 07, 2009 10:11 am

Re: 2 LSM9DS0 Sensor input

Post by adafruit_support_bill »

Yes, that is a known limitation of the algorithms used. Things get ambiguous around 90 degrees.
The technical name for the condition is "Gimbal Lock" http://en.wikipedia.org/wiki/Gimbal_lock

The workaround involves some fairly complex mathematics. We are looking into it, but do not have an implementation of it at this time.

User avatar
rburke12
 
Posts: 22
Joined: Sun Oct 26, 2014 10:10 pm

Re: 2 LSM9DS0 Sensor input

Post by rburke12 »

Is the work around the quaternion? I've seen references on the internet to madwicks quaternion and maloneys too. Would this be something you would suggest?

User avatar
adafruit_support_bill
 
Posts: 88093
Joined: Sat Feb 07, 2009 10:11 am

Re: 2 LSM9DS0 Sensor input

Post by adafruit_support_bill »

Yes. Quaternions are the solution. There are some quaternion libraries out there. I don't have any experience with them. If you find one that works well for you, please let us know. Here is one:
http://www.camelsoftware.com/firetail/b ... -dof-ahrs/

User avatar
rburke12
 
Posts: 22
Joined: Sun Oct 26, 2014 10:10 pm

Re: 2 LSM9DS0 Sensor input

Post by rburke12 »

I ended up just using the roll feature and it seems to work for what I need. I am looking into bluetooth and was wondering if you had any suggestions for my project. Again I have two sensors feeding into the SPI connections. I was wondering if the bluefruit BLE module can be used. Does the bluetooth connect to another spi connection on the arduino? Also, the bluefruit Ez-link, when will that be available? Thanks!

User avatar
adafruit_support_bill
 
Posts: 88093
Joined: Sat Feb 07, 2009 10:11 am

Re: 2 LSM9DS0 Sensor input

Post by adafruit_support_bill »

Multiple devices can share the same SPI bus. You will just need a separate CS pin for each one. If you sign up for notifications, you will get an email as soon as the EZ-Links are back in stock.

User avatar
rburke12
 
Posts: 22
Joined: Sun Oct 26, 2014 10:10 pm

Re: 2 LSM9DS0 Sensor input

Post by rburke12 »

Do you think the Pro Trinket 5V 16MHz will be able to handle this project?

User avatar
adafruit_support_bill
 
Posts: 88093
Joined: Sat Feb 07, 2009 10:11 am

Re: 2 LSM9DS0 Sensor input

Post by adafruit_support_bill »

The Pro Trinket uses the same processor as the UNO, so it is mostly compatible. You do lose the use of pins 2 and 7. But unless you are dependent on those pins your code should port over fine.

User avatar
rburke12
 
Posts: 22
Joined: Sun Oct 26, 2014 10:10 pm

Re: 2 LSM9DS0 Sensor input

Post by rburke12 »

Can I use a 3.7 Lipo battery with the 5V Pro Trinket? I can't find a 5V battery for sale on the website.

User avatar
adafruit_support_mike
 
Posts: 67454
Joined: Thu Feb 11, 2010 2:51 pm

Re: 2 LSM9DS0 Sensor input

Post by adafruit_support_mike »

The chemistry of Lithium polymer only supplies about 3.7v.

You *can* power a 5v Pro Trinket with a 3.7v LiPo, but officially running the chip at 16MHz from less than 4.5v falls in the category of overclocking. Most chips don't seem to care, but it's possible to get one that's flaky at that speed and power.

If you want 5v we have devices like the PowerBoost that takes 3.7v from a LiPo and converts it to 5v: https://www.adafruit.com/product/1903

We also have a 3.3v version of the Pro Trinket made for LiPo power.

User avatar
rburke12
 
Posts: 22
Joined: Sun Oct 26, 2014 10:10 pm

Re: 2 LSM9DS0 Sensor input

Post by rburke12 »

I am having trouble implementing the Bluefruit BLE NRF8001 code into mine. Is there a good way to do this? below is my code. I need the variable called angle to spit out to the phone app!

Code: Select all

#include <SPI.h>
#include <Wire.h>
#include <Adafruit_Sensor.h>
#include <Adafruit_LSM9DS0.h>
/* This driver uses the Adafruit unified sensor library (Adafruit_Sensor),
which provides a common 'type' for sensor data and some helper functions.
To use this driver you will also need to download the Adafruit_Sensor
library and include it in your libraries folder.
You should also assign a unique ID to this sensor for use with
the Adafruit Sensor API so that you can identify this particular
sensor in any data logs, etc. To assign a unique ID, simply
provide an appropriate value in the constructor below (12345
is used by default in this example).
Connections (For default I2C)
===========
Connect SCL to analog 5
Connect SDA to analog 4
Connect VDD to 5V DC
Connect GROUND to common ground
History
=======
2014/JULY/25 - First version (KTOWN)
*/
/* Assign a unique base ID for this sensor */
//Adafruit_LSM9DS0 lsm = Adafruit_LSM9DS0(1000); // Use I2C, ID #1000
/* Or, use Hardware SPI:
SCK -> SPI CLK
SDA -> SPI MOSI
G_SDO + XM_SDO -> tied together to SPI MISO
then select any two pins for the two CS lines:
*/

float heading_A, heading_B, pitch_A, pitch_B, roll_A, roll_B, angle;
float const PI_F = 3.14159265F;

#define LSM9DS0_XM_CS_A 10
#define LSM9DS0_GYRO_CS_A 9
#define LSM9DS0_XM_CS_B 8
#define LSM9DS0_GYRO_CS_B 7
Adafruit_LSM9DS0 lsm_A = Adafruit_LSM9DS0(LSM9DS0_XM_CS_A, LSM9DS0_GYRO_CS_A, 1000);
Adafruit_LSM9DS0 lsm_B = Adafruit_LSM9DS0(LSM9DS0_XM_CS_B, LSM9DS0_GYRO_CS_B, 1003);
/* Or, use Software SPI:
G_SDO + XM_SDO -> tied together to the MISO pin!
then select any pins for the SPI lines, and the two CS pins above
*/
#define LSM9DS0_SCLK 13
#define LSM9DS0_MISO 12
#define LSM9DS0_MOSI 11
//Adafruit_LSM9DS0 lsm = Adafruit_LSM9DS0(LSM9DS0_SCLK, LSM9DS0_MISO, LSM9DS0_MOSI, LSM9DS0_XM_CS, LSM9DS0_GYRO_CS, 1000);
/**************************************************************************/
/*
Displays some basic information on this sensor from the unified
sensor API sensor_t type (see Adafruit_Sensor for more information)
*/
/**************************************************************************/
void displaySensorDetails(void)
{
sensor_t accel_A, mag_A, gyro_A, temp_A;
lsm_A.getSensor(&accel_A, &mag_A, &gyro_A, &temp_A);
sensor_t accel_B, mag_B, gyro_B, temp_B;
lsm_B.getSensor(&accel_B, &mag_B, &gyro_B, &temp_B);
//Serial.println(F("------------------------------------"));
//Serial.print (F("Sensor: ")); Serial.println(accel_A.name);
//Serial.print (F("Sensor: ")); Serial.println(accel_B.name);
//Serial.print (F("Driver Ver: ")); Serial.println(accel_A.version);
//Serial.print (F("Driver Ver: ")); Serial.println(accel_B.version);
//Serial.print (F("Unique ID: ")); Serial.println(accel_A.sensor_id);
//Serial.print (F("Unique ID: ")); Serial.println(accel_B.sensor_id);
//Serial.print (F("Max Value: ")); Serial.print(accel_A.max_value); Serial.println(F(" m/s^2"));
//Serial.print (F("Max Value: ")); Serial.print(accel_B.max_value); Serial.println(F(" m/s^2"));
//Serial.print (F("Min Value: ")); Serial.print(accel_A.min_value); Serial.println(F(" m/s^2"));
//Serial.print (F("Min Value: ")); Serial.print(accel_B.min_value); Serial.println(F(" m/s^2"));
//Serial.print (F("Resolution: ")); Serial.print(accel_A.resolution); Serial.println(F(" m/s^2"));
//Serial.print (F("Resolution: ")); Serial.print(accel_B.resolution); Serial.println(F(" m/s^2"));
//Serial.println(F("------------------------------------"));
//Serial.println(F(""));
//Serial.println(F("------------------------------------"));
//Serial.print (F("Sensor: ")); Serial.println(mag_A.name);
//Serial.print (F("Sensor: ")); Serial.println(mag_B.name);
//Serial.print (F("Driver Ver: ")); Serial.println(mag_A.version);
//Serial.print (F("Driver Ver: ")); Serial.println(mag_B.version);
//Serial.print (F("Unique ID: ")); Serial.println(mag_A.sensor_id);
//Serial.print (F("Unique ID: ")); Serial.println(mag_B.sensor_id);
//Serial.print (F("Max Value: ")); Serial.print(mag_A.max_value); Serial.println(F(" uT"));
//Serial.print (F("Max Value: ")); Serial.print(mag_B.max_value); Serial.println(F(" uT"));
//Serial.print (F("Min Value: ")); Serial.print(mag_A.min_value); Serial.println(F(" uT"));
//Serial.print (F("Min Value: ")); Serial.print(mag_B.min_value); Serial.println(F(" uT"));
//Serial.print (F("Resolution: ")); Serial.print(mag_A.resolution); Serial.println(F(" uT"));
//Serial.print (F("Resolution: ")); Serial.print(mag_B.resolution); Serial.println(F(" uT"));
//Serial.println(F("------------------------------------"));
//Serial.println(F(""));
//Serial.println(F("------------------------------------"));
//Serial.print (F("Sensor: ")); Serial.println(gyro_A.name);
//Serial.print (F("Sensor: ")); Serial.println(gyro_B.name);
//Serial.print (F("Driver Ver: ")); Serial.println(gyro_A.version);
//Serial.print (F("Driver Ver: ")); Serial.println(gyro_B.version);
//Serial.print (F("Unique ID: ")); Serial.println(gyro_A.sensor_id);
//Serial.print (F("Unique ID: ")); Serial.println(gyro_B.sensor_id);
//Serial.print (F("Max Value: ")); Serial.print(gyro_A.max_value); Serial.println(F(" rad/s"));
//Serial.print (F("Max Value: ")); Serial.print(gyro_B.max_value); Serial.println(F(" rad/s"));
//Serial.print (F("Min Value: ")); Serial.print(gyro_A.min_value); Serial.println(F(" rad/s"));
//Serial.print (F("Min Value: ")); Serial.print(gyro_B.min_value); Serial.println(F(" rad/s"));
//Serial.print (F("Resolution: ")); Serial.print(gyro_A.resolution); Serial.println(F(" rad/s"));
//Serial.print (F("Resolution: ")); Serial.print(gyro_B.resolution); Serial.println(F(" rad/s"));
//Serial.println(F("------------------------------------"));
//Serial.println(F(""));
//Serial.println(F("------------------------------------"));
////Serial.print (F("Sensor: ")); Serial.println(temp.name);
////Serial.print (F("Driver Ver: ")); Serial.println(temp.version);
////Serial.print (F("Unique ID: ")); Serial.println(temp.sensor_id);
////Serial.print (F("Max Value: ")); Serial.print(temp.max_value); Serial.println(F(" C"));
////Serial.print (F("Min Value: ")); Serial.print(temp.min_value); Serial.println(F(" C"));
////Serial.print (F("Resolution: ")); Serial.print(temp.resolution); Serial.println(F(" C"));
////Serial.println(F("------------------------------------"));
//Serial.println(F(""));
delay(500);
}
/**************************************************************************/
/*
Configures the gain and integration time for the TSL2561
*/
/**************************************************************************/
void configureSensor(void)
{
// 1.) Set the accelerometer range
lsm_A.setupAccel(lsm_A.LSM9DS0_ACCELRANGE_2G);
lsm_B.setupAccel(lsm_B.LSM9DS0_ACCELRANGE_2G);
//lsm.setupAccel(lsm.LSM9DS0_ACCELRANGE_4G);
//lsm.setupAccel(lsm.LSM9DS0_ACCELRANGE_6G);
//lsm.setupAccel(lsm.LSM9DS0_ACCELRANGE_8G);
//lsm.setupAccel(lsm.LSM9DS0_ACCELRANGE_16G);
// 2.) Set the magnetometer sensitivity
lsm_A.setupMag(lsm_A.LSM9DS0_MAGGAIN_2GAUSS);
lsm_B.setupMag(lsm_B.LSM9DS0_MAGGAIN_2GAUSS);
//lsm.setupMag(lsm.LSM9DS0_MAGGAIN_4GAUSS);
//lsm.setupMag(lsm.LSM9DS0_MAGGAIN_8GAUSS);
//lsm.setupMag(lsm.LSM9DS0_MAGGAIN_12GAUSS);
// 3.) Setup the gyroscope
lsm_A.setupGyro(lsm_A.LSM9DS0_GYROSCALE_245DPS);
lsm_B.setupGyro(lsm_B.LSM9DS0_GYROSCALE_245DPS);
//lsm.setupGyro(lsm.LSM9DS0_GYROSCALE_500DPS);
//lsm.setupGyro(lsm.LSM9DS0_GYROSCALE_2000DPS);
}
/**************************************************************************/
/*
Arduino setup function (automatically called at startup)
*/
/**************************************************************************/
void setup(void)
{
while (!Serial); // wait for flora/leonardo
Serial.begin(115200);
Serial.println(F("Knee  Session")); Serial.println("");
/* Initialise the sensor */
if(!lsm_A.begin()||!lsm_B.begin())
{
/* There was a problem detecting the LSM9DS0 ... check your connections */
Serial.print(F("Ooops, no LSM9DS0 detected ... Check your wiring or I2C ADDR!"));
while(1);
}
Serial.println(F("Begin Session!"));
/* Display some basic information on this sensor */
displaySensorDetails();
/* Setup the sensor gain and integration time */
configureSensor();
/* We're ready to go! */
Serial.println("");
}
/**************************************************************************/
/*
Arduino loop function, called once 'setup' is complete (your own code
should go here)
*/
/**************************************************************************/
void loop(void)
{
/* Get a new sensor event */
sensors_event_t accel_A, mag_A, gyro_A, temp_A;
lsm_A.getEvent(&accel_A, &mag_A, &gyro_A, &temp_A);
sensors_event_t accel_B, mag_B, gyro_B, temp_B;
lsm_B.getEvent(&accel_B, &mag_B, &gyro_B, &temp_B);
// The equations for the roll, pitch and heading are from the Adafruit_Simple_AHRS.cpp 
  //                    y                                                                           
  //      roll = atan2(---) //x,y,z from accelerometer                                                                        
  //                    z  

  roll_A = (float)atan2(accel_A.acceleration.y, accel_A.acceleration.z);
  roll_B = (float)atan2(accel_B.acceleration.y, accel_B.acceleration.z);

  //                                 -x                                                             
  //      pitch = atan(-------------------------------)    //x,y,z from accelerometer                                         
  //                    y * sin(roll) + z * cos(roll)  
      
  pitch_A = (float)atan(-accel_A.acceleration.x / (accel_A.acceleration.y * sin(roll_A) + \
                                                                     accel_A.acceleration.z * cos(roll_A)));
  
  pitch_B = (float)atan(-accel_B.acceleration.x / (accel_B.acceleration.y * sin(roll_B) + \
                                                                     accel_B.acceleration.z * cos(roll_B)));
  
  //                                       z * sin(roll) - y * cos(roll)                            
  //   heading = atan2(--------------------------------------------------------------------------)  //x,y,z from magnetometer.
  //                    x * cos(pitch) + y * sin(pitch) * sin(roll) + z * sin(pitch) * cos(roll)) 



 heading_A = (float)atan2(mag_A.magnetic.z * sin(roll_A) - mag_A.magnetic.y * cos(roll_A), \
                                      mag_A.magnetic.x * cos(pitch_A) + \
                                      mag_A.magnetic.y * sin(pitch_A) * sin(roll_A) + \
                                      mag_A.magnetic.z * sin(pitch_A) * cos(roll_A));

 heading_B = (float)atan2(mag_B.magnetic.z * sin(roll_B) - mag_B.magnetic.y * cos(roll_B), \
                                      mag_B.magnetic.x * cos(pitch_B) + \
                                      mag_B.magnetic.y * sin(pitch_B) * sin(roll_B) + \
                                      mag_B.magnetic.z * sin(pitch_B) * cos(roll_B));

//Convert from radians to degrees
heading_A = heading_A * 180 / PI_F;
heading_B = heading_B * 180 / PI_F;
roll_A = roll_A * 180 / PI_F;
roll_B = roll_B * 180 / PI_F;
pitch_A = pitch_A * 180 / PI_F;
pitch_B = pitch_B * 180 / PI_F;

//Calculates the angle between the two sensors while performing roll movements
angle = abs(180-abs((roll_A) - (roll_B)));    //Needs to subtract from 180 because the sensors read the horizontal plane as zero.

//Outputs the Angle, Roll_A and Roll_B readings
//Serial.print("Angle: "); 
Serial.println(angle);
//Serial.print("  ");
//Serial.print("Roll_A: "); 
//Serial.print(roll_A);
//Serial.print("  ");
//Serial.print("Roll_B: "); 
//Serial.println(roll_B);

delay(20);
}

User avatar
rburke12
 
Posts: 22
Joined: Sun Oct 26, 2014 10:10 pm

Re: 2 LSM9DS0 Sensor input

Post by rburke12 »

Oh and I did get the demo to work so I know everything is hooked up correctly for bluetooth...

User avatar
adafruit_support_mike
 
Posts: 67454
Joined: Thu Feb 11, 2010 2:51 pm

Re: 2 LSM9DS0 Sensor input

Post by adafruit_support_mike »

Writing data to the nRF8001 is just a matter of calling its .write() method with a character buffer and a length:

Code: Select all

Adafruit_BLE_UART BLEserial = Adafruit_BLE_UART(ADAFRUITBLE_REQ, ADAFRUITBLE_RDY, ADAFRUITBLE_RST);

char buffer[] = "14 char string";
BLESerial.write( buffer, 14 );
Converting a floating point number to a string you can print takes a bit more work. This page has a good description of how to do it: http://blog.protoneer.co.nz/arduino-flo ... lly-works/

User avatar
rburke12
 
Posts: 22
Joined: Sun Oct 26, 2014 10:10 pm

Re: 2 LSM9DS0 Sensor input

Post by rburke12 »

Mike,
I have tried your suggestion. I can't get it to work. I was finally able to get it to compile though. When I use the BLESerial.begin(); in the setup section it doesn't seem to work. when I comment it out I can open the serial monitor and it will say "write one byte 0x84" and the hex number changes as my sensor value changes. Do you think it is having conflicts with the two sensors that are sharing the same SPI bus? I feel like this should be easier and I'm over thinking it...

Locked
Please be positive and constructive with your questions and comments.

Return to “Other Products from Adafruit”