With the introduction of the LSM9DS1 9 axis sensor I thought it would be nice to see if it works.
So what I did was build a jig that holds a servo with the LSM9DS1 attached to it. By doing this I can move the sensor through a number of positions and see if returns the angle that it set too.
Thanks to 3D printers I was able to quickly print a mounting bracket and attachment to hold the sensor shown below.
As you can see from the picture I have a Standard Parallax servo attached to the Parallax Flip along with a 1 amp battery power supply used to drive the servo. On the servo is the LSM9DS1 that is balanced on the servo horn.
The LSM9DS1 is different from the other 9 axis sensors in that it returns the raw value of the reading and not the converted value based on the range you set for the measurements. This means that it returns a value between plus and minus 32767. From there you need to calculate the actual range value. For example the accelerometer on the Z axis will return 16384 which would be 1g of force when set on the 2g range of the device. 32767 would be 2g of force.
For my application I decide to write my own library for the LSM9DS1 device as the one from Parallax required more pins and was interrupt driven. It also provide the calculated values and I wanted to work with the raw values and keep the math simple.
The first think that needs to be done is calibrate the sensor. For the accelerometer this can be done once for the area your in and then use those values from then on. For the Gyro you need to do it each time its starts up. Remember the Gyro returns the degree of movement and not the angle.
You also need to make sure the accelerometer is level and not leaning one way or the other otherwise the calibrated values will be off. I used a level on my desk to make sure it was level and placed the unit flat on that surface. My library has a basic calibration routine that will then give you the X, Y and Z offset to use.
Once we have these values were are ready to put the unit through its paces.
I wrote some code that starts up a servo process with a starting value of 1400 PWM. Once the servo is set to this value I attached the unit to the servo. Because the teeth do not always line up the unit maybe tilled slightly and this is where I used an offset value to get the unit level after attaching the unit. So if everything is attached correctly the unit will show both 0 degrees for the Accelerometer and the Gyro. The Gyro will be an aggregated value of movements recorded over the time span. This is where I created a timer routine to keep track of the amount of time that has passed so that I could add the Gyro movement to the aggregated value.
There is also a LSM9DS1 cog running to retrieve the two sensor values as they are ready. So when you setup the sensor you tell it how often you want a reading taken and it will tell you when it is ready and you just read the values as they become available. For the Gyro this is critical to obtaining the correct angle of change.
The code also allows input so that you can set the servo from 500 PWM to 2300 PWM so that you can see the reading at 90 degrees and at minus 90 degrees. This is where the rubber meets the road as this is the hole point of the jig. Does the angle of the accelerometer match the angle of the Gyro and of the jig. If it doesn't then we have a problem.
So lets talk about some math then. The accelerometer at range 0 returns a value of plus or minus 16384 or 1g. So when it is straight up it will return 16384 and when it is straight down it will report minus 16384. Level should return 0. So if we divide the value by 16384 and multiple by 90 we should get a value between plus and minus 90 degrees right.
Next lets do the Gyro. The Gyro returns degrees per second and so we need to scale that value to seconds as the reading come out at different rates and need to be adjusted to the second. As the Gyro moves it will return how fast it is moving and we will take that value and adjust it to the second and sum it up to get the angle it is at when at rest or stops moving. So if the Gyro is turning at 1 degree per second and we turn the Gyro for 10 seconds it will be at 10 degrees when it stops. So at each second we need to sum that value to get a total of 10. Well since the sensor returns many more value than that in a second we need to go down to the milliseconds.
Also there is a correction factor that is used based on the range you select. Table 3 in the LSM9DS1 manual shows these values. For the 2g range the value is .061mg. So this would be the same as .000061g's or 16393 per g. This would indicate that at 1 g the value is 16393 and not 16384. For the Gyro at range 0 the value is 8.75mdps. So that would be .00875dps or 114 per degree.
Now lets talk about clipping. Clipping is when the unit of measure is exceeded by the device. For example the unit is moving faster than it can measure causing overflow. Since we are using a servo to move the LSM9DS1 sensor using range 0 for the Gyro is a bad thing. The values returned are too small for that actual rate of movement and so the angle that is returned is off. This is easily fixed by going to the next range value of 1.
Here is the customer library and basic test jig code to move the servo and display the resulting angle.
In addition there is code to go through the full scale starting at 500 PWM and ending with 2300 PWM show each value as it moves.
use 'a1400' to go to position 1400 PWM.
use 'g' to run through all values between 500 and 2300 PWM.
use 'r' to set Gyro value to Accel value.
Next by changing the angle code and using atan2 we can get a linear angle that matches the Gyro values. If the Accelerometer returns linear values why does the original math not work. Isn't gravity at 45 degrees half of 1g.