From 273ed571e060676a4ac551ae5859fa9996484c51 Mon Sep 17 00:00:00 2001 From: FemmeVerbeek <65541097+FemmeVerbeek@users.noreply.github.com> Date: Sun, 24 May 2020 15:52:14 +0200 Subject: [PATCH 01/15] Add files via upload New version of the LSM9DS1 library for the IMU chip. It was tested on a Nano 33 BLE Sense board and should be backwards compatible with V1.01.0. New for all 9 DOF is the possibility: to give it calibration zero offset and slope factors. to change the output unit to set and get the ODR sample rate frequency , to set and get the internal full scale setting of the chip (IFS) giving it more accuracy at the expense of the range. Several fixed values in version 1.01 are replaced by functions that produce the value according to the current chip register setting. As a result there are a lot of new set... and get... functions. Offset and Slope are organised in such way that they can be calibrated separately or together. Their values are independent of the full scale setting or the output unit. Copy their values in a new sketch and it will return calibrated output even when you choose to view it in a different setting. The voids set...Offset and set...Slope are made for calibration purposes only. To store their values from read measurements according to the above features. Perhaps they need a better name to reflect this. --- CHANGELOG.txt | 14 + LSM9DS1_V2 notes and manual.txt | 385 ++++++++++++++++++ .../LSM9DS1_RegisterTest.ino | 68 ++++ .../LSM9DS1_calibrate_gyro_offset.ino | 76 ++++ .../LSM9DS1_calibrated_XY_compass.ino | 93 +++++ keywords.txt | 72 +++- src/LSM9DS1.cpp | 228 +++++++++-- src/LSM9DS1.h | 85 +++- 8 files changed, 966 insertions(+), 55 deletions(-) create mode 100644 CHANGELOG.txt create mode 100644 LSM9DS1_V2 notes and manual.txt create mode 100644 examples/LSM9DS1_RegisterTest/LSM9DS1_RegisterTest.ino create mode 100644 examples/LSM9DS1_calibrate_gyro_offset/LSM9DS1_calibrate_gyro_offset.ino create mode 100644 examples/LSM9DS1_calibrated_XY_compass/LSM9DS1_calibrated_XY_compass.ino diff --git a/CHANGELOG.txt b/CHANGELOG.txt new file mode 100644 index 0000000..b754b58 --- /dev/null +++ b/CHANGELOG.txt @@ -0,0 +1,14 @@ +Arduino_LSM9DS1 ?.?.? - ????.??.?? + +Arduino_LSM9DS1 1.0.0 - 2019.07.31 + +* Initial release + +Arduino_LSM9DS1 1.1.0 - 2020.02.11 + +* Added support for FIFO continuous reading of values + +Arduino_LSM9DS1 2.0.0 - 2020.05.15 + +* Offset, Full scale, sample rate on all DOF. +* Calibration parameters integrated \ No newline at end of file diff --git a/LSM9DS1_V2 notes and manual.txt b/LSM9DS1_V2 notes and manual.txt new file mode 100644 index 0000000..7df2c3d --- /dev/null +++ b/LSM9DS1_V2 notes and manual.txt @@ -0,0 +1,385 @@ +Notes on version 2.0 of the LSM9DS1 library +Written by Femme Verbeek, Pijnacker, The Netherlands +https://www.linkedin.com/in/femmeverbeek/ +23 may 2020 + + +Contents: + Introduction + Naming strategy + Output of Read method + Calibration + Offset + Slope + Offset and Slope Combined + Overview of Code + Derivation of linear correction + Offset + Slope + +***************************************************************************************************************************** +***************************************** Introduction ********************************************** +***************************************************************************************************************************** + +The reason for writing this update is that the LSM9DS1 chip is not calibrated and the output may vary per instance of the chip. +In my case the magnetic field offset was larger than the Earth magnetic field. The gyroscope offset of 3 deg/s does not sound +like much, but when trying to track the orientation it corresponds to a full circle misalignment in two minutes. Without +calibration it is impossible to make a working compass for sensing magnetic field or a gyro-compass, artificial horizon etc. + +This new version 2 provides a method to compensate for manufacturing differences between chips and produce calibrated output +on the read methods. This library does not provide prescribed useable methods for measuring or calibrating. The development +of this is still the task of the user of this library. The examples are just for learning, but they are not part of the +library code itself. + +New for all 9 DOF (degrees of freedom) is the possibility: + to set and get the sample rate frequency , + to give it calibration zero offset and slope factors + to change the output unit + to change the internal full scale setting of the chip (IFS) giving it more accuracy at the expense of the range. + +With respect to version 1.1.0 almost all of the code was modified or added new. +With all new settings to their default values, programs using version 1.1.0 should still work and produce the same output. + + +***************************************************************************************************************************** +***************************************** Naming strategy ********************************************** +***************************************************************************************************************************** + +Keeping the same naming convention of version 1.1.0 resulted in very long names for the new functions, making formulas +difficult to read, increasing the chance of making typo's and it was not always clear what was meant. +For this reason a number of shorter aliases were created most of them following the datasheet: +https://www.st.com/resource/en/datasheet/lsm9ds1.pdf + +Accel for Accelleration, +Gyro for Gyroscope, +Magnet for MagneticField, +ODR for SampleRate (= Output Data Rate), +FS for FullScale, +BW for BandWdth, +addition of "set" and "get" in the names of ODR, BW and FS functions. + +e.g. magneticFieldSampleRate still works, but in the library code it is now getMagnetODR reflecting that it is not longer +a constant but a function that interrogates the LSM9DS1 chip. + +Not used were the documentation's XL, M and G since it may confuse with gravity, Gauss and of course the size of clothes. :) + + +***************************************************************************************************************************** +********************************** Output of Read method **************************************** +***************************************************************************************************************************** + +Measuring the offset shows that it scales with the chip internal full scale setting (IFS). That means that it is caused +by the internal transducer and not by the DAC. So it is sufficient to calibrate for just one of the full scale settings +and compensate for the others by means of a multiplication. + +The output of the read methods for each of the 9 DOF is now + + Read = Unit * Slope *( (PFS / 32786 * Data - Offset ) + +Data = the measurement value showing up on the chip registers +PFS = the in Program Full Scale setting (float LSM9DS1Class::get...FS() ) counteracting the internal chip setting so that + the output result remains unchanged. +Unit = the unit the measured physical property is expressed in. +Slope and Offset = calibration parameters. +Note that the read method still produces the same output as in library version 1.01 on the condition that Slope = 1; +Offset=0; and Unit set to its default value. + +There are several ways in which a linear correction can be applied. The chosen method has the highest amount of advantages. +The offset and slope are independent of each other and of any of the other settings in the program. They can be measured +independently and really counteract the internal transducer differences. (For mathematical derivation see below) +All Unit factors equal 1 for their default settings. + + +***************************************************************************************************************************** +********************************** Calibration **************************************** +***************************************************************************************************************************** + +In the text below ... stands for any of the three measurement properties, Accell, Gyro, Magnet. + +For a full calibration we must find a set of two factors (Slope and Offset) for each property ... and each of the three +directions (x, y, z). So in total 18 calibration factors. + +Following the procedures below, the calibration values are stored in the arrays ...Offset[3]={0,0,0} and ...Slope[3]={1,1,1} +Should you want to use these values again in a sketch, it's up to you to print them and put them in program code. +The library is designed in such a way that the stored values don't depend on any of the settings in the program, like ...Unit, +...SR (sample rate), ...FS (full scale). So changing any of the settings before or after restoring their values in the +arrays has no effect on the status of being calibrated. + +********************************************* Offset ********************************************* + +In order to find the value of Offset we must do a zero point measurement. That means that the physical property ... +we are trying to measure should actually result in a value of 0. E.g. keeping the board still should result in zero +gyroscope values for x,y and z. For acceleration the two axes perpendicular to the Earth gravity should be zero. + +An offset calibration involves three steps +1 set the offset factors to 0, using the set...Offset method +2 do zero-point measurements with the read... method +3 store the measured ReadResults using the same set...Offset method to make the calibration effective. + +ad.1: in your sketch: IMO.set...Offset(0,0,0); +ad.2: The readResult should probably be the average value of a number of measurements +ad.3: in your sketch: IMO.set...Offset(resultX,resultY,resultZ); + +Alternatively if it is difficult to get a zero property, you could try to find the maximum and minimum values and +use the point in the middle + + readResult = ( Read_max + Read_min ) / 2 + +This is probably more complex than what it looks like. Both Read_min and Read_max can best be some sort of average, but +if you simply use the min() and max() procedures, the final results are just one measurement each. The chances are high +that these are the worst measurements. +Calculating separate averages of the min and max values, is like a chicken and egg. Before the calibration program can +decide to which average a measurement belongs, it needs a rough calibration first. +The best method is probably 3D elliptical regression, where the values of Offset correspond to the centre of the +elliptoid. So far I did not venture into the mathematics of this. :0 + +********************************************* Slope ********************************************* + +Slope is a dimensionless number that compensates for the sensitivity of the chip's internal transducer. In case it is not +possible to measure this, best leave it at the value 1. For Magnet and Accel this is probably allright, but for Gyro the +sensitivity matters if you want to keep track of orientation. + +A slope calibration involves three steps +1 set the offset factor to 1, using the set...Slope method +2 do slope measurements with the read... method +3 store the readResult using the same set...Slope method. + +ad.1: in your sketch: IMO.set...Slope(1,1,1); +ad.2: The read result should probably be two different averages of a number of measurements each +ad.3: in your sketch: IMO.set...Slope(resultX,resultY,resultZ) + +In order to calibrate the Slope parameter at least two measurements (say 1 and 2) must be done where the physical quantity, +(let's call it Q), has a known difference, so Q_1 - Q_2 = known value. + +The value of slope follows from + + Result = abs (( Q_1 - Q_2) / ( Read_1 - Read_2 )) + +E.g. the Earth gravity should produce a value of 1g. Holding the board upside down should measure -1g. So the difference + ( Q_1 - Q_2) = 2g +The local strength of the magnetic field (in nT) can be found at +https://en.wikipedia.org/wiki/Earth%27s_magnetic_field + + +*************************************** Offset and Slope Combined ********************************************* + +With the above methods Slope and Offset can be measured independently. It does not matter which procedure comes first, +as long as you don't change any of the settings between measuring and assigning. This could accidently happen in case +of a combined measurement by setting the value of Slope before that of Offset. +Note that the dimensionless stored Offset values differ from the Read measurements by a factor (Unit * Slope). + + +A safe following order of steps is +1 set the Slope factors to 1, set...Slope(1,1,1); +2 set the Offset factors to 0, set...Offset(0,0,0); +3 do the measurements with the read... method +4 First store the Offset results using set...Offset +5 Store the Slope results second using set...Slope + +Example +Lets assume that readAccel produces values of 1.3 and - 0.9 + + Offset = (1.3 + (-0.9)) / 2 = 0.2 + Slope = (1 - (-1)) / (1.3 - (-0.9) = 2 / 2.2 = 0.90909 + +Note that set...Offset stores the measured values as ReadResult/(Unit * Slope). +If you store Slope first, the Offset becomes 0.2/0.90909 = 0.22 + +***************************************************************************************************************************** +********************************** Overview of Code **************************************** +***************************************************************************************************************************** + +(almost) unchanged + int begin(); + void end(); + void setContinuousMode(); + void setOneShotMode(); + virtual int accelAvailable(); // Number of samples in the FIFO. + virtual int gyroAvailable(); // Number of samples in the FIFO. + virtual int magnetAvailable(); // Number of samples in the FIFO. + +existing functions changed for new functionality. Results reflect calibration, full scale and unit settings + virtual int readAcceleration(float& x, float& y, float& z); // Results are in G (earth gravity) or m/s2. + virtual int readGyroscope(float& x, float& y, float& z); // Results are in degrees/second or rad/s. + virtual int readMagneticField(float& x, float& y, float& z); // Results are in uT (micro Tesla). + +existing functions that now actually do something + virtual float getAccelSR(); // Sampling rate of the sensor (Hz). + virtual float getGyroSR(); // Sampling rate of the sensor (Hz). + virtual float magnetSR(); // Sampling rate of the sensor (Hz). + +New the possibility to change the ODR registers (Output Data Rate) + virtual int setAccelSR(int8_t range); // 0:off, 1:10Hz, 2:50Hz, 3:119Hz, 4:238Hz, 5:476Hz, 6:952Hz, 7:NA + virtual int setGyroSR(int8_t range); // 0:off, 1:10Hz, 2:50Hz, 3:119Hz, 4:238Hz, 5:476Hz, 6:952Hz, 7:NA + virtual int setMagnetSR(int8_t range) // range (0..7) corresponds to {0.625,1.25,2.5,5.0,10.0,20.0,40.0,80.0}Hz + +New constants used in ..Unit setting +#define GAUSS 1.0 +#define MICROTESLA 100.0 // default +#define GRAVITY 1.0 // default +#define METERPERSECOND2 9.81 +#define DEGREEPERSECOND 1.0 //default +#define RADIANSPERSECOND 3.141592654/180 + +Unit settings: + float accelUnit = GRAVITY or METERPERSECOND2 + float gyroUnit = DEGREEPERSECOND or RADIANSPERSECOND + float magnetUnit = MICROTESLA or GAUSS + +Calibration parameters Slope ans Offset : See Calibration. + float accelOffset[3] = {0,0,0}; // zero point offset correction factor for calibration + float gyroOffset[3] = {0,0,0}; // zero point offset correction factor for calibration + float magnetOffset[3] = {0,0,0};// zero point offset correction factor for calibration + float accelSlope[3] = {1,1,1}; // slope correction factor for calibration + float gyroSlope[3] = {1,1,1}; // slope correction factor for calibration + float magnetSlope[3] = {1,1,1}; // slope correction factor for calibration + +Methods for setting the calibration + virtual void setAccelOffset(float x, float y, float z); + virtual void setAccelSlope(float x, float y, float z); + virtual void setGyroSlope(float x, float y, float z); + virtual int setGyroSR(int8_t range); //Sampling Rate 0:off, 1:10Hz, 2:50Hz, 3:119Hz, 4:238Hz, 5:476Hz, 6:952Hz, 7:NA + virtual void setMagnetOffset(float x, float y, float z); + virtual void setMagnetSlope(float x, float y, float z); + +Unitsettings that read returns measurement results in. + float accelUnit = GRAVITY; // GRAVITY OR METERPERSECOND2 + float gyroUnit = DEGREEPERSECOND; // DEGREEPERSECOND or RADIANSPERSECOND + float magnetUnit = MICROTESLA; // GAUSS MICROTESLA NANOTESLA + +New: changing the full scale sensitivity of the sensors. +The functions modify the FS (full scale) registers of the LSM9DS1 chip changing sensitivity at the expence of range. +Changing this setting does not change the x,y,z output of the read functions, but assigns just more or less bits +to the sensor measurement. + virtual int setAccelFS(int8_t range); // 0: ±2g ; 1: ±16g ; 2: ±4g ; 3: ±8g + virtual int setGyroFS(int8_t range); // 0= ±245 dps; 1= ±500 dps; 2= ±1000 dps; 3= ±2000 dps + virtual int setMagnetFS(int8_t range); // 0=400.0; 1=800.0; 2=1200.0 , 3=1600.0 (µT) +*note* According to the data sheet gyroscope setting 2 = 1000 dps should not be available. For some reason it worked + like a charm on my BLE Sense board, so I added the possibility. + +New functions return the Full Scale setting of the corresponding DOF as set with the corresponding set...FS functions + virtual float getAccelFS(); // output = 2.0, 16.0 , 4.0 , 8.0) + virtual float getGyroFS(); // output = 245.0, 500.0 , 1000.0, 2000.0) + virtual float getMagnetFS(); // output 400.0 ; 800.0 ; 1200.0 , 1600.0 + + +***************************************************************************************************************************** +********************************** Derivation of linear correction **************************************** +***************************************************************************************************************************** + +******************************************* Offset *************************************************** + + +Sorry for the very formal derivation below. It suits verifiability but probably only my own purpose :) +It took a lot of puzzling to get it right. Don't read it if you don't want to. :( + +Assuming good linearity of the transducer, we can model the data output of the chip as + + Data = (32768 / IFS) *( A*Q + B) (1) + +Data = the measured value showing up on the chip registers +Q = the actual physical quantity we are trying to measure in any of the 9 DOF +IFS = the chip Internal Fullscale Setting. +A,B unknown constants representing chip instance differences + +Since the chip outputs dimensionless bits and bytes only, the dimensions of IFS and B must equal the dimension of Q. + +The challenge is to get rid of the unknown constants A and B and translate them into measurable quantities produced by the +library's Read methods. Since a good calibrated Read should produce a number equal to the actual physical quantity +we can state + + Read = Q + +Further, we do not want to recalibrate when we change the Full Scale setting or the Unit. + +Define +PFS = the in-program Full Scale function counteracting the IFS so that the output result remains unchanged. + (dimensionless, but its value corresponds to that of the chosen default unit) +Slope = in-program correction factor for the sensor sensitivity +Offset = in-program correction factor for the sensor zero point offset + +The output of the read methods is (see above) + + Read = Unit * Slope * (PFS / 32786 * Data - Offset ) (2) + +Substitute eq(1) + + Read = Unit * slope * (PFS / IFS * 32786/32786 * ( A*Q + B ) - Offset ) + + Read = Unit * slope * (PFS / IFS * ( A*Q + B ) - Offset ) (3) + +In case of the calibrated zero point measurement Q = Read = 0 +Substitute in eq.(3) we get + + 0 = Unit * slope * (PFS / IFS * ( A*0 + B ) - Offset ) + + Unit * slope * Offset = Unit * slope * PFS / IFS * B (4) + +For an uncalibrated measurement of a zero point (ZP) filling in Offset=0 and Q=0 in eq(3) we get + + Read_uncalibrated_ZP = Unit * slope * PFS / IFS * B (5) + +The righthand terms in equation (4) and (5) are identical so it follows that + + Offset = read_uncalibrated_ZP / (Unit * slope) (6) + +This defines how we should do the calibration measurements. In the library the methods called set...Offset +use of eq(6) to assign the uncalibrated zero-point read values to the corresponding program parameters. +Eq.(6) suggests that Offset depends on Unit and Slope, but this is not the case as the Read method scales +with the same value. To proof this we write eg(4) in a different form + + Offset = (Unit * Slope) / (Unit * Slope) * PFS/IFS * B (7) + +Further since the dimensionless PFS counteracts IFS in size +and the dimension of IFS equals that of Q, the ratio PFS/IFS is 1/Unit. +or in other words + + Unit * PFS /IFS = 1 (8) + +eq(7) reduces to + + Offset = B / Unit = B (9) + +So Offset equals the dimensionless form of B and does not depend on any other parameter. + + +******************************************** Slope *************************************************** + +In order to calibrate the Slope at least two measurements (say 1 and 2) must be done where the measured quantity Q +has a known difference. The calibrated Read equals Q so + + Q_1 - Q_2 = Read_1 - Read_2 = known value (10) + +Substitute eq(2) + + Q_1 - Q_2 = Unit*Slope*(PFS/32786*Data_1 - Offset) - Unit*Slope*(PFS/32786*Data_2 - Offset) + + = Unit*Slope*(PFS/32786*(Data_1 - Data_2) (11) + +So the difference between the measurements gets rid of the Offset +For an uncalibrated measurement we must set Slope = 1. +Eq(2) becomes + + Read_uncalibrated = Unit * (PFS / 32786 * Data - Offset ) + +In eq(11) we get + + Q_1 -Q_2 = Slope * ( Read_uncalibrated_1 - Read_uncalibrated_2) + + Slope = (( Read_uncalibrated_1 - Read_uncalibrated_2) / (Q_1 -Q_2) (12) + +So in order to measure the slope we must first set the Slope parameter to 1. + +In order to prove that Slope is independent of all the other program parameters we substitute eq(1) in eq(11) + + Q_1 - Q_2 = Unit*Slope*(PFS/32786)*(32786/IFS)*(A*Q1 +B - A*Q2 -B)) + + (Q_1 - Q_2) = Slope* Unit*(PFS/IFS)* A *(Q1 - Q2) (12) + +and with eq(8) + + ( 1 ) = Slope * 1 * A *( 1 ) + + Slope = 1 / A + +QED diff --git a/examples/LSM9DS1_RegisterTest/LSM9DS1_RegisterTest.ino b/examples/LSM9DS1_RegisterTest/LSM9DS1_RegisterTest.ino new file mode 100644 index 0000000..ddbeb38 --- /dev/null +++ b/examples/LSM9DS1_RegisterTest/LSM9DS1_RegisterTest.ino @@ -0,0 +1,68 @@ +/*Test program for Arduino__LSM9DS1 Library version 2.0 extensions + * Written by Femme Verbeek Pijnacker the Netherlands 23 may 2020. + * Run through all the new set and get functions + */ + +#include + +void setup() { + Serial.begin(115200); + while(!Serial); + Serial.println(); + if (!IMU.begin()) { + Serial.println("Failed to initialize IMU!"); + while (1); } + + for (int i = 0;i<=3;i++){ + if (IMU.setAccelFS(i)) + printResult ("Accelleration Full Scale range param = ", i ,IMU.getAccelFS()," g "); + else Serial.println ("failed setting accelleration scale value "); } + + for (int i = 0;i<=3;i++){ + if (IMU.setGyroFS(i)) + printResult ("Gyroscope Full Scale range param = ",i,IMU.getGyroFS()," deg/s "); + else Serial.println ("failed setting gyroscope scale value ");} + + for (int i = 0;i<=3;i++){ + if (IMU.setMagnetFS(i)) + printResult ("magnetic range param = ", i ,IMU.getMagnetFS()," µT "); + else Serial.println ("failed setting magnetic field scale value "); } + + for (int i = 0;i<=7;i++){ + if (IMU.setAccelODR(i)) + { printResult ("accelleration sample rate param = ", i , IMU.getAccelODR()," Hz "); + // printResult ("Gyroscope sample rate param = ", i , IMU.getGyroODR()," Hz "); + Serial.println(" automatic bandwidth setting (Hz) "+ String (IMU.getAccelBW())); + for (int j = 0;j<=3;j++) + { IMU.setAccelBW(j); // override automatic bandwith + printResult("Accel bandwidth override ", j ,IMU.getAccelBW(), "Hz " ); + } + } + else Serial.println ("failed setting accelleration sample rate ");} + + for (int i = 0;i<=7;i++){ + if (IMU.setGyroODR(i)){ + printResult ("gyroscope sample rate param = ", i , IMU.getGyroODR()," Hz" ); + for (int j = 0;j<=3;j++) + { IMU.setGyroBW(j); // override automatic bandwith + printResult("Gyro bandwidth setting ", j ,IMU.getGyroBW(), "Hz " ); + } + } + else Serial.println ("failed setting gyroscope sample rate "); } + + for (int i = 0;i<=7;i++){ + if (IMU.setMagnetODR(i)) + printResult ("magnetic field sample rate param = ", i , IMU.getMagnetODR()," Hz "); + else Serial.println ("failed setting magnetic field sample rate ");} +} + +void loop() { + +} + +void printResult (String msg, int nr,float value, String dimension) + { Serial.print (msg+String(nr)); + // Serial.print (nr); + Serial.print(" setting "+String(value)); + // Serial.print(value); + Serial.println(dimension);} diff --git a/examples/LSM9DS1_calibrate_gyro_offset/LSM9DS1_calibrate_gyro_offset.ino b/examples/LSM9DS1_calibrate_gyro_offset/LSM9DS1_calibrate_gyro_offset.ino new file mode 100644 index 0000000..60ca0cc --- /dev/null +++ b/examples/LSM9DS1_calibrate_gyro_offset/LSM9DS1_calibrate_gyro_offset.ino @@ -0,0 +1,76 @@ +/*Example program for Arduino__LSM9DS1 Library version 2.0 + * Tested on Arduino Nano 33 BLE SENSE + * Written by Femme Verbeek 15 may 2020. + * + * Measures the gyroscope offset and sets the IMU.gyroOffset parameters for X,Y,Z + * To start the calibration measurement, open the serial monitor. + * For a good result the board must be held still during the calibration measurements + * During the calibration the onboard LED's are blinking + * When finished the program prints the calibration result + * The program pauses till you press enter + * Next the program will continue measuring and print the now calibrated results. + * Best close the serial monitor first, open the serial monitor and send the character from there. + * + * To see a graphic result of the measurements, close the serial monitor when the program pauses, + * open the serial plotter, type any character and press "send". + */ +const int averageNSamples=10; //average output over N measurements + +#include +//unsigned long timer; +void setup() +{ Serial.begin(115200); + while(!Serial); + delay(1); + if (!IMU.begin()) { + Serial.println("Failed to initialize IMU!"); + while (1); } + IMU.setGyroODR(4); //Sampling Rate 0:off, 1:10Hz, 2:50Hz, 3:119Hz, 4:238Hz, 5:476Hz, 6:952Hz, 7:NA + IMU.setGyroBW(0); // bandwidth see table 47 datasheet + Serial.print("Gyro ODR "+String( IMU.getGyroODR() ) ); + Serial.println(" BW setting "+String( IMU.getGyroBW() ) ); + Serial.println("Calibrating. Just a moment. "); + Serial.println("Keep the sensor still as long as the LED's are flashing"); + + calibrateGyroOffset(12000); // do calibration measurements during 12000 ms. + + Serial.println("calibration results"); + Serial.print("Content of IMU.gyroOffset : "); + for (int i= 0; i<=2 ; i++) {Serial.print(IMU.gyroOffset[i],6);Serial.print(" ");} + Serial.println(); + Serial.println("Press enter to start mesuring"); + Serial.println("To see a graph of the measurements, close this serial monitor, open the serial plotter type any character and click the send button"); + while (!Serial.available()); // pause the program, enter continues + while (Serial.available()) Serial.read(); // clear the read buffer + Serial.println(" X \t Y \t Z "); +} + +// continue doing calibrated measurements, this is best viewed in the serial plotter +void loop() +{ float x, y, z, averX=0, averY=0, averZ=0; + for (int i=1;i<=averageNSamples;i++) + { while (!IMU.gyroAvailable()); + IMU.readGyro(x, y, z); + averX += x; averY += y; averZ += z; + } + Serial.print(String(averX/averageNSamples,6)+'\t'); + Serial.print(String(averY/averageNSamples,6)+'\t'); + Serial.println(averZ/averageNSamples,6); +} + +void calibrateGyroOffset(unsigned int duration){ // don't move the board during calibration +unsigned long count = 0, start = millis(); +float x, y, z, addX=0, addY=0, addZ=0 ; + IMU.setGyroOffset(0,0,0); // Offsets must be zero when calibrating + while ((millis()-start) < duration) + { if (IMU.gyroscopeAvailable()) + { IMU.readGyroscope(x, y, z); + count++; + addX += x; addY += y; addZ += z; + digitalWrite(LED_BUILTIN, (millis()/125)%2); // blink onboard led every 250ms + } + } + IMU.setGyroOffset(addX/count, addY/count, addZ/count); // Store the average measurements as offset + digitalWrite(LED_BUILTIN, 0); // onboard led off + Serial.println("nr of samples "+String(count)); +} diff --git a/examples/LSM9DS1_calibrated_XY_compass/LSM9DS1_calibrated_XY_compass.ino b/examples/LSM9DS1_calibrated_XY_compass/LSM9DS1_calibrated_XY_compass.ino new file mode 100644 index 0000000..a9f7ba0 --- /dev/null +++ b/examples/LSM9DS1_calibrated_XY_compass/LSM9DS1_calibrated_XY_compass.ino @@ -0,0 +1,93 @@ +/* Calibrated compass example for the Nano 33 BLE Sense + * You need version 2.0 or higher of the LMS9DS1 library to run this example + * + * The compass must be calibrated for the magnetic disturbance of the environment. + * Calibration starts automaticlly when the serial monitor is opened and stops after a given time. + * Calibration in progress is indicated by the flashing onboard LED. + * + * During calibration the board must be turned slowly over a full 360 deg. + * When finished calibrating the program stores and prints the offset and slope factors. + * + * After pressing "enter" the program continues working as a compass. + * + * Written by Femme Verbeek 2020 + * Released to the public domain +*/ + +#include + +float EarthMagField = 49000; //= nT For local value see https://en.wikipedia.org/wiki/Earth%27s_magnetic_field +int averageCompassByN = 10; //number of samples per compass reading. Higher number = more accurate but slower +int averageCalibrationByN = 10; //goldielocs number too high = fewer measurements in 360deg turn, to low = more noise +int calibrationTime = 20; //s +void setup() { + pinMode(LED_BUILTIN,OUTPUT); + Serial.begin(115200); + while(!Serial); // wait till the serial monitor connects + delay(1); + if (!IMU.begin()) { + Serial.println("Failed to initialize IMU!"); + while (1); } + IMU.setMagnetODR(7); // Sample Rate (0..7) corresponds to {0.625,1.25,2.5,5.0,10.0,20.0,40.0,80.0}Hz + IMU.magnetUnit = NANOTESLA; // calibrate in nanotesla as this corresponds to the local field strenth number we found. + Serial.println("Calibrating. Just a moment. "); + Serial.println("Keep the compass sensor horizontal."); + Serial.print("In the next "+String(calibrationTime)); + Serial.println(" seconds the compass must be turned slowly over a full 360 degrees!"); + + calibrateMagnet(calibrationTime*1000); + + Serial.println("calibration results"); + Serial.print("IMU.magnetOffset[] : "); + for (int i= 0; i<=2 ; i++){ Serial.print(IMU.magnetOffset[i],4);Serial.print(" ");} + Serial.println(); + Serial.print("IMU.magnetSlope[] : "); + for (int i= 0; i<=2 ; i++){ Serial.print(IMU.magnetSlope[i],4);Serial.print(" ");} + Serial.println(); + Serial.println("Press enter to start the compass"); + while (!Serial.available()); // pause the program, enter continues, use the serial plotter to view a graph + while (Serial.available()) Serial.read(); // clear the read buffer + Serial.println("Direction\tFieldStrength\tmagX\tmagY"); // legend for serial plotter + IMU.magnetUnit = MICROTESLA; // Switch to microtesla as this looks better in the graph + +} + +void loop () +{ float magY,magX; + doNMeasurements (averageCompassByN,magX,magY,false); + float heading= atan2(magY,magX)*180/PI +180; + float fieldStrength = sqrt(magX*magX +magY * magY); + Serial.print(heading); Serial.print("\t"); Serial.print(fieldStrength);Serial.print("\t"); + Serial.print(magX); Serial.print("\t"); Serial.print(magY);Serial.print("\t"); + Serial.println(); +} + +void doNMeasurements(unsigned int N, float& averX, float& averY, boolean showLeds) +{ float x, y, z; + averX=0; averY =0; + for (int i=1;i<=N;i++) + { digitalWrite(LED_BUILTIN, bitRead(millis(),7)&& showLeds ); // blink onboard led + while (!IMU.magneticFieldAvailable()); + IMU.readMagneticField(x, y, z); + averX += x/N; + averY += y/N; + } +} + +void calibrateMagnet(unsigned int duration) // measure Offset and Slope of XY +{ float x, y, Xmin, Xmax, Ymin, Ymax ; + IMU.setMagnetOffset(0,0,0); // Offsets must be 0 when calibrating + IMU.setMagnetSlope(1,1,1); // slopes must be 1 when calibrating + doNMeasurements(averageCalibrationByN,Xmin, Ymin, true ); // find some starting values + Xmax = Xmin; Ymax = Ymin; + unsigned long start = millis(); + while ((millis()-start) < duration) + { doNMeasurements(averageCompassByN ,x, y ,true); + Xmax = max (Xmax, x); Xmin = min (Xmin, x); + Ymax = max (Ymax, y); Ymin = min (Ymin, y); + } + IMU.setMagnetOffset( (Xmax+Xmin)/2,(Ymax+Ymin)/2, 0 ) ; // store offset + IMU.setMagnetSlope ( (2*EarthMagField)/(Xmax-Xmin),(2*EarthMagField)/(Ymax-Ymin),1) ; // store slope +// Serial.print("Xmin = ");Serial.print(Xmin); Serial.print(" Xmax = ");Serial.println(Xmax); +// Serial.print("Ymin = ");Serial.print(Ymin); Serial.print(" Ymax = ");Serial.println(Ymax); +} diff --git a/keywords.txt b/keywords.txt index 8c39cca..618e062 100644 --- a/keywords.txt +++ b/keywords.txt @@ -14,19 +14,85 @@ IMU KEYWORD1 begin KEYWORD2 end KEYWORD2 +setContinuousMode KEYWORD2 +setOneShotMode KEYWORD2 readAcceleration KEYWORD2 readGyroscope KEYWORD2 readMagneticField KEYWORD2 -gyroscopeAvailable KEYWORD2 + +readAccel KEYWORD2 +readGyro KEYWORD2 +readMagnet KEYWORD2 + accelerationAvailable KEYWORD2 +gyroscopeAvailable KEYWORD2 magneticFieldAvailable KEYWORD2 + +accelAvailable KEYWORD2 +gyroAvailable KEYWORD2 +magnetAvailable KEYWORD2 + accelerationSampleRate KEYWORD2 gyroscopeSampleRate KEYWORD2 magneticFieldSampleRate KEYWORD2 -setContinuousMode KEYWORD2 -setOneShotMode KEYWORD2 + +setAccelerationSampleRate KEYWORD2 +setGyroscopeSampleRate KEYWORD2 +setMagneticFieldSampleRate KEYWORD2 + +accelOffset KEYWORD2 +gyroOffset KEYWORD2 +magnetOffset KEYWORD2 + +accelScale KEYWORD2 +gyroScale KEYWORD2 +magnetScale KEYWORD2 + +accelUnit KEYWORD2 +gyroUnit KEYWORD2 +magnetUnit KEYWORD2 + +accelerationFullScale KEYWORD2 +gyroscopeFullScale KEYWORD2 +magneticFieldFullScale KEYWORD2 + +setAccelerationFullScale KEYWORD2 +setGyroscopeFullScale KEYWORD2 +setMagneticFieldFullScale KEYWORD2 + +getAccelODR KEYWORD2 +getGyroODR KEYWORD2 +getMagnetODR KEYWORD2 +setAccelODR KEYWORD2 +setGyroODR KEYWORD2 +setMagnetODR KEYWORD2 + +getAccelFS KEYWORD2 +getGyroFS KEYWORD2 +getMagnetFS KEYWORD2 +setAccelFS KEYWORD2 +setGyroFS KEYWORD2 +setMagnetFS KEYWORD2 + +setAccelBW KEYWORD2 +getAccelBW KEYWORD2 +setGyroBW KEYWORD2 +getGyroBW KEYWORD2 + +readAccel KEYWORD2 +readGyro KEYWORD2 +readMagnet KEYWORD2 + + ####################################### # Constants ####################################### + +GAUSS LITERAL1 +MICROTESLA LITERAL1 +GRAVITY LITERAL1 +METERPERSECOND2 LITERAL1 +DEGREEPERSECOND LITERAL1 +RADIANSPERSECOND LITERAL1 diff --git a/src/LSM9DS1.cpp b/src/LSM9DS1.cpp index 0403018..d3595fb 100644 --- a/src/LSM9DS1.cpp +++ b/src/LSM9DS1.cpp @@ -15,6 +15,11 @@ You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + + Modifications by Femme Verbeek, Pijnacker, the Netherlands 23 may 2020, + Released to the public domain + version 2.0.0 + */ #include "LSM9DS1.h" @@ -38,6 +43,14 @@ #define LSM9DS1_STATUS_REG_M 0x27 #define LSM9DS1_OUT_X_L_M 0x28 +// Add these right after defines at the beginning +#define LSM9DS1_OFFSET_X_REG_L_M 0x05 +#define LSM9DS1_OFFSET_X_REG_H_M 0x06 +#define LSM9DS1_OFFSET_Y_REG_L_M 0x07 +#define LSM9DS1_OFFSET_Y_REG_H_M 0x08 +#define LSM9DS1_OFFSET_Z_REG_L_M 0x09 +#define LSM9DS1_OFFSET_Z_REG_H_M 0x0A + LSM9DS1Class::LSM9DS1Class(TwoWire& wire) : continuousMode(false), _wire(&wire) { @@ -106,26 +119,25 @@ void LSM9DS1Class::end() _wire->end(); } -int LSM9DS1Class::readAcceleration(float& x, float& y, float& z) -{ - int16_t data[3]; +//************************************ Accelleration ***************************************** +int LSM9DS1Class::readAccel(float& x, float& y, float& z) +{ int16_t data[3]; if (!readRegisters(LSM9DS1_ADDRESS, LSM9DS1_OUT_X_XL, (uint8_t*)data, sizeof(data))) { x = NAN; y = NAN; z = NAN; - return 0; } - - x = data[0] * 4.0 / 32768.0; - y = data[1] * 4.0 / 32768.0; - z = data[2] * 4.0 / 32768.0; - + // See releasenotes read = Unit * Slope * (PFS / 32786 * Data - Offset ) + float scale = getAccelFS()/32768.0 ; + x = accelUnit * accelSlope[0] * (scale * data[0] - accelOffset[0]); + y = accelUnit * accelSlope[1] * (scale * data[1] - accelOffset[1]); + z = accelUnit * accelSlope[2] * (scale * data[2] - accelOffset[2]); return 1; } -int LSM9DS1Class::accelerationAvailable() +int LSM9DS1Class::accelAvailable() { if (continuousMode) { // Read FIFO_SRC. If any of the rightmost 8 bits have a value, there is data. @@ -137,81 +149,211 @@ int LSM9DS1Class::accelerationAvailable() return 1; } } - return 0; } -float LSM9DS1Class::accelerationSampleRate() -{ - return 119.0F; +void LSM9DS1Class::setAccelOffset(float x, float y, float z) //Look out, from measurements only +{ accelOffset[0] = x /(accelUnit * accelSlope[0]); + accelOffset[1] = y /(accelUnit * accelSlope[1]); + accelOffset[2] = z /(accelUnit * accelSlope[2]); } -int LSM9DS1Class::readGyroscope(float& x, float& y, float& z) -{ - int16_t data[3]; +void LSM9DS1Class::setAccelSlope(float x, float y, float z) +{ accelSlope[0] = x ; + accelSlope[1] = y ; + accelSlope[2] = z ; +} - if (!readRegisters(LSM9DS1_ADDRESS, LSM9DS1_OUT_X_G, (uint8_t*)data, sizeof(data))) { - x = NAN; +int LSM9DS1Class::setAccelODR(int8_t range) //Sample Rate 0:off, 1:10Hz, 2:50Hz, 3:119Hz, 4:238Hz, 5:476Hz, 6:952Hz, 7:NA +{ if (range==7) range =0; + range = (range & B00000111) << 5; + uint8_t setting = ((readRegister(LSM9DS1_ADDRESS, LSM9DS1_CTRL_REG6_XL) & B00011111) | range); + return writeRegister(LSM9DS1_ADDRESS, LSM9DS1_CTRL_REG6_XL,setting) ; +} +float LSM9DS1Class::getAccelODR() +{ float Ranges[] ={0.0, 10.0, 50.0, 119.0, 238.0, 476.0, 952.0, 0.0 }; + uint8_t setting = readRegister(LSM9DS1_ADDRESS, LSM9DS1_CTRL_REG6_XL) >> 5; + return Ranges [setting]; +} + +float LSM9DS1Class::setAccelBW(int8_t range) //0,1,2,3 Override autoBandwidth setting see doc.table 67 +{ range = range & B00000011; + uint8_t RegIs = readRegister(LSM9DS1_ADDRESS, LSM9DS1_CTRL_REG6_XL) & B11111000; + RegIs = RegIs | B00000100 | range ; + return writeRegister(LSM9DS1_ADDRESS, LSM9DS1_CTRL_REG6_XL,RegIs) ; +} + +float LSM9DS1Class::getAccelBW() //Bandwidth setting 0,1,2,3 see documentation table 67 +{ float autoRange[] ={0.0, 408.0, 408.0, 50.0, 105.0, 211.0, 408.0, 0.0 }; + float BWXLRange[] ={ 408.0, 211.0, 105.0, 50.0 }; + uint8_t RegIs = readRegister(LSM9DS1_ADDRESS, LSM9DS1_CTRL_REG6_XL); + if (bitRead(2,RegIs)) return BWXLRange [RegIs & B00000011]; + else return autoRange [ RegIs >> 5 ]; +} + +int LSM9DS1Class::setAccelFS(int8_t range) // 0: ±2g ; 1: ±16g ; 2: ±4g ; 3: ±8g +{ range = (range & B00000011) << 3; + uint8_t setting = ((readRegister(LSM9DS1_ADDRESS, LSM9DS1_CTRL_REG6_XL) & 0xE7) | range); + return writeRegister(LSM9DS1_ADDRESS, LSM9DS1_CTRL_REG6_XL,setting) ; +} + +float LSM9DS1Class::getAccelFS() // Full scale (output = 2.0, 16.0 , 4.0 , 8.0) +{ float ranges[] ={2.0, 16.0, 4.0, 8.0}; //g + uint8_t setting = (readRegister(LSM9DS1_ADDRESS, LSM9DS1_CTRL_REG6_XL) & 0x18) >> 3; + return ranges[setting] ; +} + +//************************************ Gyroscope ***************************************** + +int LSM9DS1Class::readGyro(float& x, float& y, float& z) +{ int16_t data[3]; + if (!readRegisters(LSM9DS1_ADDRESS, LSM9DS1_OUT_X_G, (uint8_t*)data, sizeof(data))) + { x = NAN; y = NAN; z = NAN; - return 0; } - - x = data[0] * 2000.0 / 32768.0; - y = data[1] * 2000.0 / 32768.0; - z = data[2] * 2000.0 / 32768.0; - + float scale = getGyroFS() / 32768.0; + x = gyroUnit * gyroSlope[0] * (scale * data[0] - gyroOffset[0]); + y = gyroUnit * gyroSlope[1] * (scale * data[1] - gyroOffset[1]); + z = gyroUnit * gyroSlope[2] * (scale * data[2] - gyroOffset[2]); return 1; } -int LSM9DS1Class::gyroscopeAvailable() +int LSM9DS1Class::gyroAvailable() { if (readRegister(LSM9DS1_ADDRESS, LSM9DS1_STATUS_REG) & 0x02) { return 1; } - return 0; } -float LSM9DS1Class::gyroscopeSampleRate() -{ - return 119.0F; +void LSM9DS1Class::setGyroOffset(float x, float y, float z) //Look out, from measurements only +{ gyroOffset[0] = x /(gyroUnit * gyroSlope[0]); + gyroOffset[1] = y /(gyroUnit * gyroSlope[1]); + gyroOffset[2] = z /(gyroUnit * gyroSlope[2]); +} + +void LSM9DS1Class::setGyroSlope(float x, float y, float z) +{ gyroSlope[0] = x ; + gyroSlope[1] = y ; + gyroSlope[2] = z ; +} + +int LSM9DS1Class::setGyroODR(int8_t range) // 0:off, 1:10Hz, 2:50Hz, 3:119Hz, 4:238Hz, 5:476Hz, 6:952Hz, 7:NA +{ if (range==7) range =0; + range = (range & B00000111) << 5; + uint8_t setting = ((readRegister(LSM9DS1_ADDRESS, LSM9DS1_CTRL_REG1_G) & B00011111) | range); + return writeRegister(LSM9DS1_ADDRESS, LSM9DS1_CTRL_REG1_G,setting) ; +} + +float LSM9DS1Class::getGyroODR() +{ float Ranges[] ={0.0, 10.0, 50.0, 119.0, 238.0, 476.0, 952.0, 0.0 }; //Hz + uint8_t setting = readRegister(LSM9DS1_ADDRESS, LSM9DS1_CTRL_REG1_G) >> 5; + return Ranges [setting]; // return 119.0F; +} + +int LSM9DS1Class::setGyroBW(int8_t range) +{ range = range & B00000011; + uint8_t setting = readRegister(LSM9DS1_ADDRESS, LSM9DS1_CTRL_REG1_G) & B11111100; + return writeRegister(LSM9DS1_ADDRESS, LSM9DS1_CTRL_REG1_G,setting | range) ; +} + +#define ODRrows 8 +#define BWcols 4 +float BWtable[ ODRrows ][ BWcols ] = // acc to + { { 0, 0, 0, 0 }, + { 0, 0, 0, 0 }, + { 16, 16, 16, 16 }, + { 14, 31, 31, 31 }, + { 14, 29, 63, 78 }, + { 21, 28, 57, 100 }, + { 33, 40, 58, 100 }, + { 0, 0, 0, 0 } }; + +float LSM9DS1Class::getGyroBW() +{ uint8_t setting = readRegister(LSM9DS1_ADDRESS, LSM9DS1_CTRL_REG1_G) ; + uint8_t ODR = setting >> 5; + uint8_t BW = setting & B00000011; + return BWtable[ODR][BW]; +} + +int LSM9DS1Class::setGyroFS(int8_t range) // (0: 245 dps; 1: 500 dps; 2: 1000 dps; 3: 2000 dps) +{ range = (range & B00000011) << 3; + uint8_t setting = ((readRegister(LSM9DS1_ADDRESS, LSM9DS1_CTRL_REG1_G) & 0xE7) | range ); + return writeRegister(LSM9DS1_ADDRESS, LSM9DS1_CTRL_REG1_G,setting) ; } +float LSM9DS1Class::getGyroFS() // +{ float Ranges[] ={245.0, 500.0, 1000.0, 2000.0}; //dps + uint8_t setting = (readRegister(LSM9DS1_ADDRESS, LSM9DS1_CTRL_REG1_G) & 0x18) >> 3; + return Ranges[setting] ; +} + +//************************************ Magnetic field ***************************************** + int LSM9DS1Class::readMagneticField(float& x, float& y, float& z) -{ - int16_t data[3]; +{ int16_t data[3]; if (!readRegisters(LSM9DS1_ADDRESS_M, LSM9DS1_OUT_X_L_M, (uint8_t*)data, sizeof(data))) { x = NAN; y = NAN; z = NAN; - return 0; } - - x = data[0] * 4.0 * 100.0 / 32768.0; - y = data[1] * 4.0 * 100.0 / 32768.0; - z = data[2] * 4.0 * 100.0 / 32768.0; - + float scale = getMagnetFS() / 32768.0; + x = magnetUnit * magnetSlope[0] * (scale * data[0] - magnetOffset[0]); + y = magnetUnit * magnetSlope[1] * (scale * data[1] - magnetOffset[1]); + z = magnetUnit * magnetSlope[2] * (scale * data[2] - magnetOffset[2]); return 1; } int LSM9DS1Class::magneticFieldAvailable() -{ +{ //return (readRegister(LSM9DS1_ADDRESS_M, LSM9DS1_STATUS_REG_M) & 0x08)==0x08; if (readRegister(LSM9DS1_ADDRESS_M, LSM9DS1_STATUS_REG_M) & 0x08) { return 1; } - return 0; } -float LSM9DS1Class::magneticFieldSampleRate() -{ - return 20.0; +void LSM9DS1Class::setMagnetOffset(float x, float y, float z) //Look out, from measurements only +{ magnetOffset[0] = x /(magnetUnit * magnetSlope[0]); + magnetOffset[1] = y /(magnetUnit * magnetSlope[1]); + magnetOffset[2] = z /(magnetUnit * magnetSlope[2]); +} + +void LSM9DS1Class::setMagnetSlope(float x, float y, float z) +{ magnetSlope[0] = x ; + magnetSlope[1] = y ; + magnetSlope[2] = z ; +} + +int LSM9DS1Class::setMagnetFS(int8_t range) // 0=400.0; 1=800.0; 2=1200.0 , 3=1600.0 (µT) +{ range = (range & B00000011) << 5; + return writeRegister(LSM9DS1_ADDRESS, LSM9DS1_CTRL_REG2_M,range) ; +} + +float LSM9DS1Class::getMagnetFS() // +{ const float Ranges[] ={400.0, 800.0, 1200.0, 1600.0}; // + uint8_t setting = readRegister(LSM9DS1_ADDRESS, LSM9DS1_CTRL_REG2_M) >> 5; + return Ranges[setting] ; +} + +int LSM9DS1Class::setMagnetODR(int8_t range) // range (0..7) corresponds to {0.625,1.25,2.5,5.0,10.0,20.0,40.0,80.0}Hz +{ range = (range & B00000111) << 2; + uint8_t setting = ((readRegister(LSM9DS1_ADDRESS_M, LSM9DS1_CTRL_REG1_M) & B11100011) | range); + return writeRegister(LSM9DS1_ADDRESS_M, LSM9DS1_CTRL_REG1_M,setting) ; } +float LSM9DS1Class::getMagnetODR() // Output {0.625, 1.25, 2.5, 5.0, 10.0, 20.0, 40.0 , 80.0}; //Hz +{ const float ranges[] ={0.625, 1.25,2.5, 5.0, 10.0, 20.0, 40.0 , 80.0}; //Hz + uint8_t setting = (readRegister(LSM9DS1_ADDRESS_M, LSM9DS1_CTRL_REG1_M) & B00011100) >> 2; + return ranges[setting]; +} + +//************************************ Private functions ***************************************** + + int LSM9DS1Class::readRegister(uint8_t slaveAddress, uint8_t address) { _wire->beginTransmission(slaveAddress); diff --git a/src/LSM9DS1.h b/src/LSM9DS1.h index 242d790..68a4694 100644 --- a/src/LSM9DS1.h +++ b/src/LSM9DS1.h @@ -15,10 +15,49 @@ You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + + Modifications by Femme Verbeek, Pijnacker, the Netherlands 23 may 2020, + Released to the public domain + version 2.0.0 */ +#ifndef LSM9DS1_V2.0 + #define LSM9DS1_V2.0 +#endif + +#define accelerationSampleRate getAccelODR +#define gyroscopeSampleRate getGyroODR +#define magneticFieldSampleRate getMagnetODR + +#define setAccelerationSampleRate setAccelODR //development +#define setGyroscopeSampleRate setGyroODR //development +#define setMagnetisFieldSampleRate setMagnetODR // development + +#define accelerationFullScale getAccelFS //development +#define gyroscopeFullScale getGyroFS //development +#define magneticFieldFullScale getMagnetFS //development + +#define setAccelerationFullScale setAccelFS //development +#define setGyroscopeFullScale setGyroFS //development +#define setMagneticFieldFullScale setMagnetFS //development + +#define readAcceleration readAccel +#define readGyroscope readGyro +#define readMagneticField readMagnet + +#define accelerationAvailable accelAvailable +#define gyroscopeAvailable gyroAvailable +#define magneticFieldAvailable magnetAvailable + #include #include +#define GAUSS 0.01 +#define MICROTESLA 1.0 // default +#define NANOTESLA 1000.0 +#define GRAVITY 1.0 // default +#define METERPERSECOND2 9.81 +#define DEGREEPERSECOND 1.0 //default +#define RADIANSPERSECOND 3.141592654/180 class LSM9DS1Class { public: @@ -34,19 +73,47 @@ class LSM9DS1Class { void setOneShotMode(); // Accelerometer - virtual int readAcceleration(float& x, float& y, float& z); // Results are in G (earth gravity). - virtual int accelerationAvailable(); // Number of samples in the FIFO. - virtual float accelerationSampleRate(); // Sampling rate of the sensor. + float accelOffset[3] = {0,0,0}; // zero point offset correction factor for calibration + float accelSlope[3] = {1,1,1}; // slope correction factor for calibration + float accelUnit = GRAVITY; // GRAVITY OR METERPERSECOND2 + virtual int readAccel(float& x, float& y, float& z); // Results are in G (earth gravity) or m/s2. + virtual int accelAvailable(); // Number of samples in the FIFO. + virtual void setAccelOffset(float x, float y, float z); //Look out, from measurements only + virtual void setAccelSlope(float x, float y, float z); + virtual int setAccelODR(int8_t range); // Sample Rate 0:off, 1:10Hz, 2:50Hz, 3:119Hz, 4:238Hz, 5:476Hz, 6:952Hz, 7:NA Automatic setting of BW + virtual float getAccelODR(); // Sample Rate of the sensor. + virtual float setAccelBW(int8_t range); //0,1,2,3 Override autoBandwidth setting see doc.table 67 + virtual float getAccelBW(); //Bandwidth setting 0,1,2,3 see documentation table 67 + virtual int setAccelFS(int8_t range); // 0: ±2g ; 1: ±16g ; 2: ±4g ; 3: ±8g + virtual float getAccelFS(); // Full Scale setting (output = 2.0, 16.0 , 4.0 , 8.0) // Gyroscope - virtual int readGyroscope(float& x, float& y, float& z); // Results are in degrees/second. - virtual int gyroscopeAvailable(); // Number of samples in the FIFO. - virtual float gyroscopeSampleRate(); // Sampling rate of the sensor. + float gyroOffset[3] = {0,0,0}; // zero point offset correction factor for calibration + float gyroSlope[3] = {1,1,1}; // slope correction factor for calibration + float gyroUnit = DEGREEPERSECOND; // DEGREEPERSECOND or RADIANSPERSECOND + virtual int readGyro(float& x, float& y, float& z); // Results are in degrees/second or rad/s. + virtual int gyroAvailable(); // Number of samples in the FIFO. + virtual void setGyroOffset(float x, float y, float z); //Look out, from measurements only + virtual void setGyroSlope(float x, float y, float z); + virtual int setGyroODR(int8_t range); //Sampling Rate 0:off, 1:10Hz, 2:50Hz, 3:119Hz, 4:238Hz, 5:476Hz, 6:952Hz, 7:NA + virtual float getGyroODR(); // Sampling rate of the sensor. + virtual int setGyroBW(int8_t range); //Bandwidth setting 0,1,2,3 see documentation table 46 and 47 + virtual float getGyroBW(); //Bandwidth setting 0,1,2,3 see documentation table 46 and 47 + virtual int setGyroFS(int8_t range); // (0= ±245 dps; 1= ±500 dps; 2= ±1000 dps; 3= ±2000 dps) + virtual float getGyroFS(); // (output = 245.0, 500.0 , 1000.0, 2000.0) // Magnetometer - virtual int readMagneticField(float& x, float& y, float& z); // Results are in uT (micro Tesla). - virtual int magneticFieldAvailable(); // Number of samples in the FIFO. - virtual float magneticFieldSampleRate(); // Sampling rate of the sensor. + float magnetOffset[3] = {0,0,0}; // zero point offset correction factor for calibration + float magnetSlope[3] = {1,1,1}; // slope correction factor for calibration + float magnetUnit = MICROTESLA; // GAUSS or MICROTESLA + virtual int readMagnet(float& x, float& y, float& z); // Default results are in uT (micro Tesla) + virtual int magnetAvailable(); // Number of samples in the FIFO. + virtual void setMagnetOffset(float x, float y, float z); //Look out, from measurements only + virtual void setMagnetSlope(float x, float y, float z); + virtual int setMagnetODR(int8_t range); // Sampling rate (0..7) corresponds to {0.625,1.25,2.5,5.0,10.0,20.0,40.0,80.0}Hz + virtual float getMagnetODR(); // Sampling rate of the sensor in Hz. + virtual int setMagnetFS(int8_t range); // 0=400.0; 1=800.0; 2=1200.0 , 3=1600.0 (µT) + virtual float getMagnetFS(); // get chip's full scale setting private: bool continuousMode; From 7d890dae5ba30d0a90328624220598d5cb5ce40a Mon Sep 17 00:00:00 2001 From: Martin Hapl Date: Sun, 24 May 2020 22:19:46 +0200 Subject: [PATCH 02/15] Fixed formatting and deprecation messages Fixed old notation of bool variables, version string of the library, and CHANGELOG extension --- CHANGELOG | 5 + CHANGELOG.txt | 14 -- src/LSM9DS1.cpp | 335 +++++++++++++++++++++++++++--------------------- src/LSM9DS1.h | 171 ++++++++++++------------ 4 files changed, 282 insertions(+), 243 deletions(-) delete mode 100644 CHANGELOG.txt diff --git a/CHANGELOG b/CHANGELOG index e2a62a0..b754b58 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -7,3 +7,8 @@ Arduino_LSM9DS1 1.0.0 - 2019.07.31 Arduino_LSM9DS1 1.1.0 - 2020.02.11 * Added support for FIFO continuous reading of values + +Arduino_LSM9DS1 2.0.0 - 2020.05.15 + +* Offset, Full scale, sample rate on all DOF. +* Calibration parameters integrated \ No newline at end of file diff --git a/CHANGELOG.txt b/CHANGELOG.txt deleted file mode 100644 index b754b58..0000000 --- a/CHANGELOG.txt +++ /dev/null @@ -1,14 +0,0 @@ -Arduino_LSM9DS1 ?.?.? - ????.??.?? - -Arduino_LSM9DS1 1.0.0 - 2019.07.31 - -* Initial release - -Arduino_LSM9DS1 1.1.0 - 2020.02.11 - -* Added support for FIFO continuous reading of values - -Arduino_LSM9DS1 2.0.0 - 2020.05.15 - -* Offset, Full scale, sample rate on all DOF. -* Calibration parameters integrated \ No newline at end of file diff --git a/src/LSM9DS1.cpp b/src/LSM9DS1.cpp index d3595fb..59833cd 100644 --- a/src/LSM9DS1.cpp +++ b/src/LSM9DS1.cpp @@ -24,35 +24,34 @@ #include "LSM9DS1.h" -#define LSM9DS1_ADDRESS 0x6b +#define LSM9DS1_ADDRESS 0x6b -#define LSM9DS1_WHO_AM_I 0x0f -#define LSM9DS1_CTRL_REG1_G 0x10 -#define LSM9DS1_STATUS_REG 0x17 -#define LSM9DS1_OUT_X_G 0x18 -#define LSM9DS1_CTRL_REG6_XL 0x20 -#define LSM9DS1_CTRL_REG8 0x22 -#define LSM9DS1_OUT_X_XL 0x28 +#define LSM9DS1_WHO_AM_I 0x0f +#define LSM9DS1_CTRL_REG1_G 0x10 +#define LSM9DS1_STATUS_REG 0x17 +#define LSM9DS1_OUT_X_G 0x18 +#define LSM9DS1_CTRL_REG6_XL 0x20 +#define LSM9DS1_CTRL_REG8 0x22 +#define LSM9DS1_OUT_X_XL 0x28 // magnetometer -#define LSM9DS1_ADDRESS_M 0x1e +#define LSM9DS1_ADDRESS_M 0x1e -#define LSM9DS1_CTRL_REG1_M 0x20 -#define LSM9DS1_CTRL_REG2_M 0x21 -#define LSM9DS1_CTRL_REG3_M 0x22 -#define LSM9DS1_STATUS_REG_M 0x27 -#define LSM9DS1_OUT_X_L_M 0x28 +#define LSM9DS1_CTRL_REG1_M 0x20 +#define LSM9DS1_CTRL_REG2_M 0x21 +#define LSM9DS1_CTRL_REG3_M 0x22 +#define LSM9DS1_STATUS_REG_M 0x27 +#define LSM9DS1_OUT_X_L_M 0x28 // Add these right after defines at the beginning -#define LSM9DS1_OFFSET_X_REG_L_M 0x05 -#define LSM9DS1_OFFSET_X_REG_H_M 0x06 -#define LSM9DS1_OFFSET_Y_REG_L_M 0x07 -#define LSM9DS1_OFFSET_Y_REG_H_M 0x08 -#define LSM9DS1_OFFSET_Z_REG_L_M 0x09 -#define LSM9DS1_OFFSET_Z_REG_H_M 0x0A - -LSM9DS1Class::LSM9DS1Class(TwoWire& wire) : - continuousMode(false), _wire(&wire) +#define LSM9DS1_OFFSET_X_REG_L_M 0x05 +#define LSM9DS1_OFFSET_X_REG_H_M 0x06 +#define LSM9DS1_OFFSET_Y_REG_L_M 0x07 +#define LSM9DS1_OFFSET_Y_REG_H_M 0x08 +#define LSM9DS1_OFFSET_Z_REG_L_M 0x09 +#define LSM9DS1_OFFSET_Z_REG_H_M 0x0A + +LSM9DS1Class::LSM9DS1Class(TwoWire &wire) : continuousMode(false), _wire(&wire) { } @@ -70,19 +69,21 @@ int LSM9DS1Class::begin() delay(10); - if (readRegister(LSM9DS1_ADDRESS, LSM9DS1_WHO_AM_I) != 0x68) { + if (readRegister(LSM9DS1_ADDRESS, LSM9DS1_WHO_AM_I) != 0x68) + { end(); return 0; } - if (readRegister(LSM9DS1_ADDRESS_M, LSM9DS1_WHO_AM_I) != 0x3d) { + if (readRegister(LSM9DS1_ADDRESS_M, LSM9DS1_WHO_AM_I) != 0x3d) + { end(); return 0; } - writeRegister(LSM9DS1_ADDRESS, LSM9DS1_CTRL_REG1_G, 0x78); // 119 Hz, 2000 dps, 16 Hz BW + writeRegister(LSM9DS1_ADDRESS, LSM9DS1_CTRL_REG1_G, 0x78); // 119 Hz, 2000 dps, 16 Hz BW writeRegister(LSM9DS1_ADDRESS, LSM9DS1_CTRL_REG6_XL, 0x70); // 119 Hz, 4G writeRegister(LSM9DS1_ADDRESS_M, LSM9DS1_CTRL_REG1_M, 0xb4); // Temperature compensation enable, medium performance, 20 Hz @@ -92,7 +93,8 @@ int LSM9DS1Class::begin() return 1; } -void LSM9DS1Class::setContinuousMode() { +void LSM9DS1Class::setContinuousMode() +{ // Enable FIFO (see docs https://www.st.com/resource/en/datasheet/DM00103319.pdf) writeRegister(LSM9DS1_ADDRESS, 0x23, 0x02); // Set continuous mode @@ -101,7 +103,8 @@ void LSM9DS1Class::setContinuousMode() { continuousMode = true; } -void LSM9DS1Class::setOneShotMode() { +void LSM9DS1Class::setOneShotMode() +{ // Disable FIFO (see docs https://www.st.com/resource/en/datasheet/DM00103319.pdf) writeRegister(LSM9DS1_ADDRESS, 0x23, 0x00); // Disable continuous mode @@ -121,16 +124,18 @@ void LSM9DS1Class::end() //************************************ Accelleration ***************************************** -int LSM9DS1Class::readAccel(float& x, float& y, float& z) -{ int16_t data[3]; - if (!readRegisters(LSM9DS1_ADDRESS, LSM9DS1_OUT_X_XL, (uint8_t*)data, sizeof(data))) { +int LSM9DS1Class::readAccel(float &x, float &y, float &z) +{ + int16_t data[3]; + if (!readRegisters(LSM9DS1_ADDRESS, LSM9DS1_OUT_X_XL, (uint8_t *)data, sizeof(data))) + { x = NAN; y = NAN; z = NAN; return 0; } // See releasenotes read = Unit * Slope * (PFS / 32786 * Data - Offset ) - float scale = getAccelFS()/32768.0 ; + float scale = getAccelFS() / 32768.0; x = accelUnit * accelSlope[0] * (scale * data[0] - accelOffset[0]); y = accelUnit * accelSlope[1] * (scale * data[1] - accelOffset[1]); z = accelUnit * accelSlope[2] * (scale * data[2] - accelOffset[2]); @@ -139,76 +144,94 @@ int LSM9DS1Class::readAccel(float& x, float& y, float& z) int LSM9DS1Class::accelAvailable() { - if (continuousMode) { + if (continuousMode) + { // Read FIFO_SRC. If any of the rightmost 8 bits have a value, there is data. - if (readRegister(LSM9DS1_ADDRESS, 0x2F) & 63) { + if (readRegister(LSM9DS1_ADDRESS, 0x2F) & 63) + { return 1; } - } else { - if (readRegister(LSM9DS1_ADDRESS, LSM9DS1_STATUS_REG) & 0x01) { + } + else + { + if (readRegister(LSM9DS1_ADDRESS, LSM9DS1_STATUS_REG) & 0x01) + { return 1; } } return 0; } -void LSM9DS1Class::setAccelOffset(float x, float y, float z) //Look out, from measurements only -{ accelOffset[0] = x /(accelUnit * accelSlope[0]); - accelOffset[1] = y /(accelUnit * accelSlope[1]); - accelOffset[2] = z /(accelUnit * accelSlope[2]); +void LSM9DS1Class::setAccelOffset(float x, float y, float z) +{ + accelOffset[0] = x / (accelUnit * gyroSlope[0]); + accelOffset[1] = y / (accelUnit * gyroSlope[1]); + accelOffset[2] = z / (accelUnit * gyroSlope[2]); } -void LSM9DS1Class::setAccelSlope(float x, float y, float z) -{ accelSlope[0] = x ; - accelSlope[1] = y ; - accelSlope[2] = z ; +void LSM9DS1Class::setAccelSlope(float x, float y, float z) +{ + accelSlope[0] = x; + accelSlope[1] = y; + accelSlope[2] = z; } int LSM9DS1Class::setAccelODR(int8_t range) //Sample Rate 0:off, 1:10Hz, 2:50Hz, 3:119Hz, 4:238Hz, 5:476Hz, 6:952Hz, 7:NA -{ if (range==7) range =0; - range = (range & B00000111) << 5; - uint8_t setting = ((readRegister(LSM9DS1_ADDRESS, LSM9DS1_CTRL_REG6_XL) & B00011111) | range); - return writeRegister(LSM9DS1_ADDRESS, LSM9DS1_CTRL_REG6_XL,setting) ; +{ + if (range == 7) + range = 0; + range = (range & 0b00000111) << 5; + uint8_t setting = ((readRegister(LSM9DS1_ADDRESS, LSM9DS1_CTRL_REG6_XL) & 0b00011111) | range); + return writeRegister(LSM9DS1_ADDRESS, LSM9DS1_CTRL_REG6_XL, setting); } float LSM9DS1Class::getAccelODR() -{ float Ranges[] ={0.0, 10.0, 50.0, 119.0, 238.0, 476.0, 952.0, 0.0 }; - uint8_t setting = readRegister(LSM9DS1_ADDRESS, LSM9DS1_CTRL_REG6_XL) >> 5; - return Ranges [setting]; +{ + float Ranges[] = {0.0, 10.0, 50.0, 119.0, 238.0, 476.0, 952.0, 0.0}; + uint8_t setting = readRegister(LSM9DS1_ADDRESS, LSM9DS1_CTRL_REG6_XL) >> 5; + return Ranges[setting]; } float LSM9DS1Class::setAccelBW(int8_t range) //0,1,2,3 Override autoBandwidth setting see doc.table 67 -{ range = range & B00000011; - uint8_t RegIs = readRegister(LSM9DS1_ADDRESS, LSM9DS1_CTRL_REG6_XL) & B11111000; - RegIs = RegIs | B00000100 | range ; - return writeRegister(LSM9DS1_ADDRESS, LSM9DS1_CTRL_REG6_XL,RegIs) ; +{ + range = range & 0b00000011; + uint8_t RegIs = readRegister(LSM9DS1_ADDRESS, LSM9DS1_CTRL_REG6_XL) & 0b11111000; + RegIs = RegIs | 0b00000100 | range; + return writeRegister(LSM9DS1_ADDRESS, LSM9DS1_CTRL_REG6_XL, RegIs); } float LSM9DS1Class::getAccelBW() //Bandwidth setting 0,1,2,3 see documentation table 67 -{ float autoRange[] ={0.0, 408.0, 408.0, 50.0, 105.0, 211.0, 408.0, 0.0 }; - float BWXLRange[] ={ 408.0, 211.0, 105.0, 50.0 }; +{ + float autoRange[] = {0.0, 408.0, 408.0, 50.0, 105.0, 211.0, 408.0, 0.0}; + float BWXLRange[] = {408.0, 211.0, 105.0, 50.0}; uint8_t RegIs = readRegister(LSM9DS1_ADDRESS, LSM9DS1_CTRL_REG6_XL); - if (bitRead(2,RegIs)) return BWXLRange [RegIs & B00000011]; - else return autoRange [ RegIs >> 5 ]; + if (bitRead(2, RegIs)) + return BWXLRange[RegIs & 0b00000011]; + else + return autoRange[RegIs >> 5]; } -int LSM9DS1Class::setAccelFS(int8_t range) // 0: ±2g ; 1: ±16g ; 2: ±4g ; 3: ±8g -{ range = (range & B00000011) << 3; - uint8_t setting = ((readRegister(LSM9DS1_ADDRESS, LSM9DS1_CTRL_REG6_XL) & 0xE7) | range); - return writeRegister(LSM9DS1_ADDRESS, LSM9DS1_CTRL_REG6_XL,setting) ; +int LSM9DS1Class::setAccelFS(int8_t range) // 0: ±2g ; 1: ±16g ; 2: ±4g ; 3: ±8g +{ + range = (range & 0b00000011) << 3; + uint8_t setting = ((readRegister(LSM9DS1_ADDRESS, LSM9DS1_CTRL_REG6_XL) & 0xE7) | range); + return writeRegister(LSM9DS1_ADDRESS, LSM9DS1_CTRL_REG6_XL, setting); } -float LSM9DS1Class::getAccelFS() // Full scale (output = 2.0, 16.0 , 4.0 , 8.0) -{ float ranges[] ={2.0, 16.0, 4.0, 8.0}; //g +float LSM9DS1Class::getAccelFS() // Full scale (output = 2.0, 16.0 , 4.0 , 8.0) +{ + float ranges[] = {2.0, 16.0, 4.0, 8.0}; //g uint8_t setting = (readRegister(LSM9DS1_ADDRESS, LSM9DS1_CTRL_REG6_XL) & 0x18) >> 3; - return ranges[setting] ; + return ranges[setting]; } //************************************ Gyroscope ***************************************** -int LSM9DS1Class::readGyro(float& x, float& y, float& z) -{ int16_t data[3]; - if (!readRegisters(LSM9DS1_ADDRESS, LSM9DS1_OUT_X_G, (uint8_t*)data, sizeof(data))) - { x = NAN; +int LSM9DS1Class::readGyro(float &x, float &y, float &z) +{ + int16_t data[3]; + if (!readRegisters(LSM9DS1_ADDRESS, LSM9DS1_OUT_X_G, (uint8_t *)data, sizeof(data))) + { + x = NAN; y = NAN; z = NAN; return 0; @@ -222,80 +245,92 @@ int LSM9DS1Class::readGyro(float& x, float& y, float& z) int LSM9DS1Class::gyroAvailable() { - if (readRegister(LSM9DS1_ADDRESS, LSM9DS1_STATUS_REG) & 0x02) { + if (readRegister(LSM9DS1_ADDRESS, LSM9DS1_STATUS_REG) & 0x02) + { return 1; } return 0; } -void LSM9DS1Class::setGyroOffset(float x, float y, float z) //Look out, from measurements only -{ gyroOffset[0] = x /(gyroUnit * gyroSlope[0]); - gyroOffset[1] = y /(gyroUnit * gyroSlope[1]); - gyroOffset[2] = z /(gyroUnit * gyroSlope[2]); +void LSM9DS1Class::setGyroOffset(float x, float y, float z) +{ + gyroOffset[0] = x / (gyroUnit * gyroSlope[0]); + gyroOffset[1] = y / (gyroUnit * gyroSlope[1]); + gyroOffset[2] = z / (gyroUnit * gyroSlope[2]); } -void LSM9DS1Class::setGyroSlope(float x, float y, float z) -{ gyroSlope[0] = x ; - gyroSlope[1] = y ; - gyroSlope[2] = z ; +void LSM9DS1Class::setGyroSlope(float x, float y, float z) +{ + gyroSlope[0] = x; + gyroSlope[1] = y; + gyroSlope[2] = z; } - + int LSM9DS1Class::setGyroODR(int8_t range) // 0:off, 1:10Hz, 2:50Hz, 3:119Hz, 4:238Hz, 5:476Hz, 6:952Hz, 7:NA -{ if (range==7) range =0; - range = (range & B00000111) << 5; - uint8_t setting = ((readRegister(LSM9DS1_ADDRESS, LSM9DS1_CTRL_REG1_G) & B00011111) | range); - return writeRegister(LSM9DS1_ADDRESS, LSM9DS1_CTRL_REG1_G,setting) ; +{ + if (range == 7) + range = 0; + range = (range & 0b00000111) << 5; + uint8_t setting = ((readRegister(LSM9DS1_ADDRESS, LSM9DS1_CTRL_REG1_G) & 0b00011111) | range); + return writeRegister(LSM9DS1_ADDRESS, LSM9DS1_CTRL_REG1_G, setting); } float LSM9DS1Class::getGyroODR() -{ float Ranges[] ={0.0, 10.0, 50.0, 119.0, 238.0, 476.0, 952.0, 0.0 }; //Hz - uint8_t setting = readRegister(LSM9DS1_ADDRESS, LSM9DS1_CTRL_REG1_G) >> 5; - return Ranges [setting]; // return 119.0F; +{ + float Ranges[] = {0.0, 10.0, 50.0, 119.0, 238.0, 476.0, 952.0, 0.0}; //Hz + uint8_t setting = readRegister(LSM9DS1_ADDRESS, LSM9DS1_CTRL_REG1_G) >> 5; + return Ranges[setting]; // return 119.0F; } int LSM9DS1Class::setGyroBW(int8_t range) -{ range = range & B00000011; - uint8_t setting = readRegister(LSM9DS1_ADDRESS, LSM9DS1_CTRL_REG1_G) & B11111100; - return writeRegister(LSM9DS1_ADDRESS, LSM9DS1_CTRL_REG1_G,setting | range) ; +{ + range = range & 0b00000011; + uint8_t setting = readRegister(LSM9DS1_ADDRESS, LSM9DS1_CTRL_REG1_G) & 0b11111100; + return writeRegister(LSM9DS1_ADDRESS, LSM9DS1_CTRL_REG1_G, setting | range); } #define ODRrows 8 #define BWcols 4 -float BWtable[ ODRrows ][ BWcols ] = // acc to - { { 0, 0, 0, 0 }, - { 0, 0, 0, 0 }, - { 16, 16, 16, 16 }, - { 14, 31, 31, 31 }, - { 14, 29, 63, 78 }, - { 21, 28, 57, 100 }, - { 33, 40, 58, 100 }, - { 0, 0, 0, 0 } }; +float BWtable[ODRrows][BWcols] = // acc to + {{0, 0, 0, 0}, + {0, 0, 0, 0}, + {16, 16, 16, 16}, + {14, 31, 31, 31}, + {14, 29, 63, 78}, + {21, 28, 57, 100}, + {33, 40, 58, 100}, + {0, 0, 0, 0}}; float LSM9DS1Class::getGyroBW() -{ uint8_t setting = readRegister(LSM9DS1_ADDRESS, LSM9DS1_CTRL_REG1_G) ; - uint8_t ODR = setting >> 5; - uint8_t BW = setting & B00000011; - return BWtable[ODR][BW]; +{ + uint8_t setting = readRegister(LSM9DS1_ADDRESS, LSM9DS1_CTRL_REG1_G); + uint8_t ODR = setting >> 5; + uint8_t BW = setting & 0b00000011; + return BWtable[ODR][BW]; } - + int LSM9DS1Class::setGyroFS(int8_t range) // (0: 245 dps; 1: 500 dps; 2: 1000 dps; 3: 2000 dps) -{ range = (range & B00000011) << 3; - uint8_t setting = ((readRegister(LSM9DS1_ADDRESS, LSM9DS1_CTRL_REG1_G) & 0xE7) | range ); - return writeRegister(LSM9DS1_ADDRESS, LSM9DS1_CTRL_REG1_G,setting) ; +{ + range = (range & 0b00000011) << 3; + uint8_t setting = ((readRegister(LSM9DS1_ADDRESS, LSM9DS1_CTRL_REG1_G) & 0xE7) | range); + return writeRegister(LSM9DS1_ADDRESS, LSM9DS1_CTRL_REG1_G, setting); } -float LSM9DS1Class::getGyroFS() // -{ float Ranges[] ={245.0, 500.0, 1000.0, 2000.0}; //dps +float LSM9DS1Class::getGyroFS() // +{ + float Ranges[] = {245.0, 500.0, 1000.0, 2000.0}; //dps uint8_t setting = (readRegister(LSM9DS1_ADDRESS, LSM9DS1_CTRL_REG1_G) & 0x18) >> 3; - return Ranges[setting] ; + return Ranges[setting]; } //************************************ Magnetic field ***************************************** -int LSM9DS1Class::readMagneticField(float& x, float& y, float& z) -{ int16_t data[3]; +int LSM9DS1Class::readMagneticField(float &x, float &y, float &z) +{ + int16_t data[3]; - if (!readRegisters(LSM9DS1_ADDRESS_M, LSM9DS1_OUT_X_L_M, (uint8_t*)data, sizeof(data))) { + if (!readRegisters(LSM9DS1_ADDRESS_M, LSM9DS1_OUT_X_L_M, (uint8_t *)data, sizeof(data))) + { x = NAN; y = NAN; z = NAN; @@ -310,78 +345,89 @@ int LSM9DS1Class::readMagneticField(float& x, float& y, float& z) int LSM9DS1Class::magneticFieldAvailable() { //return (readRegister(LSM9DS1_ADDRESS_M, LSM9DS1_STATUS_REG_M) & 0x08)==0x08; - if (readRegister(LSM9DS1_ADDRESS_M, LSM9DS1_STATUS_REG_M) & 0x08) { + if (readRegister(LSM9DS1_ADDRESS_M, LSM9DS1_STATUS_REG_M) & 0x08) + { return 1; } return 0; } -void LSM9DS1Class::setMagnetOffset(float x, float y, float z) //Look out, from measurements only -{ magnetOffset[0] = x /(magnetUnit * magnetSlope[0]); - magnetOffset[1] = y /(magnetUnit * magnetSlope[1]); - magnetOffset[2] = z /(magnetUnit * magnetSlope[2]); +void LSM9DS1Class::setMagnetOffset(float x, float y, float z) +{ + magnetOffset[0] = x / (magnetUnit * magnetSlope[0]); + magnetOffset[1] = y / (magnetUnit * magnetSlope[1]); + magnetOffset[2] = z / (magnetUnit * magnetSlope[2]); } -void LSM9DS1Class::setMagnetSlope(float x, float y, float z) -{ magnetSlope[0] = x ; - magnetSlope[1] = y ; - magnetSlope[2] = z ; +void LSM9DS1Class::setMagnetSlope(float x, float y, float z) +{ + magnetSlope[0] = x; + magnetSlope[1] = y; + magnetSlope[2] = z; } - + int LSM9DS1Class::setMagnetFS(int8_t range) // 0=400.0; 1=800.0; 2=1200.0 , 3=1600.0 (µT) -{ range = (range & B00000011) << 5; - return writeRegister(LSM9DS1_ADDRESS, LSM9DS1_CTRL_REG2_M,range) ; +{ + range = (range & 0b00000011) << 5; + return writeRegister(LSM9DS1_ADDRESS, LSM9DS1_CTRL_REG2_M, range); } -float LSM9DS1Class::getMagnetFS() // -{ const float Ranges[] ={400.0, 800.0, 1200.0, 1600.0}; // - uint8_t setting = readRegister(LSM9DS1_ADDRESS, LSM9DS1_CTRL_REG2_M) >> 5; - return Ranges[setting] ; +float LSM9DS1Class::getMagnetFS() // +{ + const float Ranges[] = {400.0, 800.0, 1200.0, 1600.0}; // + uint8_t setting = readRegister(LSM9DS1_ADDRESS, LSM9DS1_CTRL_REG2_M) >> 5; + return Ranges[setting]; } -int LSM9DS1Class::setMagnetODR(int8_t range) // range (0..7) corresponds to {0.625,1.25,2.5,5.0,10.0,20.0,40.0,80.0}Hz -{ range = (range & B00000111) << 2; - uint8_t setting = ((readRegister(LSM9DS1_ADDRESS_M, LSM9DS1_CTRL_REG1_M) & B11100011) | range); - return writeRegister(LSM9DS1_ADDRESS_M, LSM9DS1_CTRL_REG1_M,setting) ; +int LSM9DS1Class::setMagnetODR(int8_t range) // range (0..7) corresponds to {0.625,1.25,2.5,5.0,10.0,20.0,40.0,80.0}Hz +{ + range = (range & 0b00000111) << 2; + uint8_t setting = ((readRegister(LSM9DS1_ADDRESS_M, LSM9DS1_CTRL_REG1_M) & 0b11100011) | range); + return writeRegister(LSM9DS1_ADDRESS_M, LSM9DS1_CTRL_REG1_M, setting); } -float LSM9DS1Class::getMagnetODR() // Output {0.625, 1.25, 2.5, 5.0, 10.0, 20.0, 40.0 , 80.0}; //Hz -{ const float ranges[] ={0.625, 1.25,2.5, 5.0, 10.0, 20.0, 40.0 , 80.0}; //Hz - uint8_t setting = (readRegister(LSM9DS1_ADDRESS_M, LSM9DS1_CTRL_REG1_M) & B00011100) >> 2; +float LSM9DS1Class::getMagnetODR() // Output {0.625, 1.25, 2.5, 5.0, 10.0, 20.0, 40.0 , 80.0}; //Hz +{ + const float ranges[] = {0.625, 1.25, 2.5, 5.0, 10.0, 20.0, 40.0, 80.0}; //Hz + uint8_t setting = (readRegister(LSM9DS1_ADDRESS_M, LSM9DS1_CTRL_REG1_M) & 0b00011100) >> 2; return ranges[setting]; } //************************************ Private functions ***************************************** - int LSM9DS1Class::readRegister(uint8_t slaveAddress, uint8_t address) { _wire->beginTransmission(slaveAddress); _wire->write(address); - if (_wire->endTransmission() != 0) { + if (_wire->endTransmission() != 0) + { return -1; } - if (_wire->requestFrom(slaveAddress, 1) != 1) { + if (_wire->requestFrom(slaveAddress, 1) != 1) + { return -1; } return _wire->read(); } -int LSM9DS1Class::readRegisters(uint8_t slaveAddress, uint8_t address, uint8_t* data, size_t length) +int LSM9DS1Class::readRegisters(uint8_t slaveAddress, uint8_t address, uint8_t *data, size_t length) { _wire->beginTransmission(slaveAddress); _wire->write(0x80 | address); - if (_wire->endTransmission(false) != 0) { + if (_wire->endTransmission(false) != 0) + { return -1; } - if (_wire->requestFrom(slaveAddress, length) != length) { + if (_wire->requestFrom(slaveAddress, length) != length) + { return 0; } - for (size_t i = 0; i < length; i++) { + for (size_t i = 0; i < length; i++) + { *data++ = _wire->read(); } @@ -393,7 +439,8 @@ int LSM9DS1Class::writeRegister(uint8_t slaveAddress, uint8_t address, uint8_t v _wire->beginTransmission(slaveAddress); _wire->write(address); _wire->write(value); - if (_wire->endTransmission() != 0) { + if (_wire->endTransmission() != 0) + { return 0; } diff --git a/src/LSM9DS1.h b/src/LSM9DS1.h index 68a4694..5829ec8 100644 --- a/src/LSM9DS1.h +++ b/src/LSM9DS1.h @@ -21,27 +21,27 @@ version 2.0.0 */ -#ifndef LSM9DS1_V2.0 - #define LSM9DS1_V2.0 -#endif +#ifndef LSM9DS1_V2 +#define LSM9DS1_V2 +#endif #define accelerationSampleRate getAccelODR #define gyroscopeSampleRate getGyroODR #define magneticFieldSampleRate getMagnetODR -#define setAccelerationSampleRate setAccelODR //development -#define setGyroscopeSampleRate setGyroODR //development -#define setMagnetisFieldSampleRate setMagnetODR // development +#define setAccelerationSampleRate setAccelODR //development +#define setGyroscopeSampleRate setGyroODR //development +#define setMagnetisFieldSampleRate setMagnetODR // development -#define accelerationFullScale getAccelFS //development -#define gyroscopeFullScale getGyroFS //development -#define magneticFieldFullScale getMagnetFS //development +#define accelerationFullScale getAccelFS //development +#define gyroscopeFullScale getGyroFS //development +#define magneticFieldFullScale getMagnetFS //development -#define setAccelerationFullScale setAccelFS //development -#define setGyroscopeFullScale setGyroFS //development -#define setMagneticFieldFullScale setMagnetFS //development +#define setAccelerationFullScale setAccelFS //development +#define setGyroscopeFullScale setGyroFS //development +#define setMagneticFieldFullScale setMagnetFS //development -#define readAcceleration readAccel +#define readAcceleration readAccel #define readGyroscope readGyro #define readMagneticField readMagnet @@ -51,78 +51,79 @@ #include #include -#define GAUSS 0.01 -#define MICROTESLA 1.0 // default -#define NANOTESLA 1000.0 -#define GRAVITY 1.0 // default -#define METERPERSECOND2 9.81 -#define DEGREEPERSECOND 1.0 //default -#define RADIANSPERSECOND 3.141592654/180 - -class LSM9DS1Class { - public: - LSM9DS1Class(TwoWire& wire); - virtual ~LSM9DS1Class(); - - int begin(); - void end(); - - // Controls whether a FIFO is continuously filled, or a single reading is stored. - // Defaults to one-shot. - void setContinuousMode(); - void setOneShotMode(); - - // Accelerometer - float accelOffset[3] = {0,0,0}; // zero point offset correction factor for calibration - float accelSlope[3] = {1,1,1}; // slope correction factor for calibration - float accelUnit = GRAVITY; // GRAVITY OR METERPERSECOND2 - virtual int readAccel(float& x, float& y, float& z); // Results are in G (earth gravity) or m/s2. - virtual int accelAvailable(); // Number of samples in the FIFO. - virtual void setAccelOffset(float x, float y, float z); //Look out, from measurements only - virtual void setAccelSlope(float x, float y, float z); - virtual int setAccelODR(int8_t range); // Sample Rate 0:off, 1:10Hz, 2:50Hz, 3:119Hz, 4:238Hz, 5:476Hz, 6:952Hz, 7:NA Automatic setting of BW - virtual float getAccelODR(); // Sample Rate of the sensor. - virtual float setAccelBW(int8_t range); //0,1,2,3 Override autoBandwidth setting see doc.table 67 - virtual float getAccelBW(); //Bandwidth setting 0,1,2,3 see documentation table 67 - virtual int setAccelFS(int8_t range); // 0: ±2g ; 1: ±16g ; 2: ±4g ; 3: ±8g - virtual float getAccelFS(); // Full Scale setting (output = 2.0, 16.0 , 4.0 , 8.0) - - // Gyroscope - float gyroOffset[3] = {0,0,0}; // zero point offset correction factor for calibration - float gyroSlope[3] = {1,1,1}; // slope correction factor for calibration - float gyroUnit = DEGREEPERSECOND; // DEGREEPERSECOND or RADIANSPERSECOND - virtual int readGyro(float& x, float& y, float& z); // Results are in degrees/second or rad/s. - virtual int gyroAvailable(); // Number of samples in the FIFO. - virtual void setGyroOffset(float x, float y, float z); //Look out, from measurements only - virtual void setGyroSlope(float x, float y, float z); - virtual int setGyroODR(int8_t range); //Sampling Rate 0:off, 1:10Hz, 2:50Hz, 3:119Hz, 4:238Hz, 5:476Hz, 6:952Hz, 7:NA - virtual float getGyroODR(); // Sampling rate of the sensor. - virtual int setGyroBW(int8_t range); //Bandwidth setting 0,1,2,3 see documentation table 46 and 47 - virtual float getGyroBW(); //Bandwidth setting 0,1,2,3 see documentation table 46 and 47 - virtual int setGyroFS(int8_t range); // (0= ±245 dps; 1= ±500 dps; 2= ±1000 dps; 3= ±2000 dps) - virtual float getGyroFS(); // (output = 245.0, 500.0 , 1000.0, 2000.0) - - // Magnetometer - float magnetOffset[3] = {0,0,0}; // zero point offset correction factor for calibration - float magnetSlope[3] = {1,1,1}; // slope correction factor for calibration - float magnetUnit = MICROTESLA; // GAUSS or MICROTESLA - virtual int readMagnet(float& x, float& y, float& z); // Default results are in uT (micro Tesla) - virtual int magnetAvailable(); // Number of samples in the FIFO. - virtual void setMagnetOffset(float x, float y, float z); //Look out, from measurements only - virtual void setMagnetSlope(float x, float y, float z); - virtual int setMagnetODR(int8_t range); // Sampling rate (0..7) corresponds to {0.625,1.25,2.5,5.0,10.0,20.0,40.0,80.0}Hz - virtual float getMagnetODR(); // Sampling rate of the sensor in Hz. - virtual int setMagnetFS(int8_t range); // 0=400.0; 1=800.0; 2=1200.0 , 3=1600.0 (µT) - virtual float getMagnetFS(); // get chip's full scale setting - - private: - bool continuousMode; - int readRegister(uint8_t slaveAddress, uint8_t address); - int readRegisters(uint8_t slaveAddress, uint8_t address, uint8_t* data, size_t length); - int writeRegister(uint8_t slaveAddress, uint8_t address, uint8_t value); - - private: - TwoWire* _wire; +#define GAUSS 0.01 +#define MICROTESLA 1.0 // default +#define NANOTESLA 1000.0 +#define GRAVITY 1.0 // default +#define METERPERSECOND2 9.81 +#define DEGREEPERSECOND 1.0 //default +#define RADIANSPERSECOND 3.141592654 / 180 + +class LSM9DS1Class +{ +public: + LSM9DS1Class(TwoWire &wire); + virtual ~LSM9DS1Class(); + + int begin(); + void end(); + + // Controls whether a FIFO is continuously filled, or a single reading is stored. + // Defaults to one-shot. + void setContinuousMode(); + void setOneShotMode(); + + // Accelerometer + float accelOffset[3] = {0, 0, 0}; // zero point offset correction factor for calibration + float accelSlope[3] = {1, 1, 1}; // slope correction factor for calibration + float accelUnit = GRAVITY; // GRAVITY OR METERPERSECOND2 + virtual int readAccel(float &x, float &y, float &z); // Results are in G (earth gravity) or m/s2. + virtual int accelAvailable(); // Number of samples in the FIFO. + virtual void setAccelOffset(float x, float y, float z); //Look out, from measurements only + virtual void setAccelSlope(float x, float y, float z); + virtual int setAccelODR(int8_t range); // Sample Rate 0:off, 1:10Hz, 2:50Hz, 3:119Hz, 4:238Hz, 5:476Hz, 6:952Hz, 7:NA Automatic setting of BW + virtual float getAccelODR(); // Sample Rate of the sensor. + virtual float setAccelBW(int8_t range); //0,1,2,3 Override autoBandwidth setting see doc.table 67 + virtual float getAccelBW(); //Bandwidth setting 0,1,2,3 see documentation table 67 + virtual int setAccelFS(int8_t range); // 0: ±2g ; 1: ±16g ; 2: ±4g ; 3: ±8g + virtual float getAccelFS(); // Full Scale setting (output = 2.0, 16.0 , 4.0 , 8.0) + + // Gyroscope + float gyroOffset[3] = {0, 0, 0}; // zero point offset correction factor for calibration + float gyroSlope[3] = {1, 1, 1}; // slope correction factor for calibration + float gyroUnit = DEGREEPERSECOND; // DEGREEPERSECOND or RADIANSPERSECOND + virtual int readGyro(float &x, float &y, float &z); // Results are in degrees/second or rad/s. + virtual int gyroAvailable(); // Number of samples in the FIFO. + virtual void setGyroOffset(float x, float y, float z); //Look out, from measurements only + virtual void setGyroSlope(float x, float y, float z); + virtual int setGyroODR(int8_t range); //Sampling Rate 0:off, 1:10Hz, 2:50Hz, 3:119Hz, 4:238Hz, 5:476Hz, 6:952Hz, 7:NA + virtual float getGyroODR(); // Sampling rate of the sensor. + virtual int setGyroBW(int8_t range); //Bandwidth setting 0,1,2,3 see documentation table 46 and 47 + virtual float getGyroBW(); //Bandwidth setting 0,1,2,3 see documentation table 46 and 47 + virtual int setGyroFS(int8_t range); // (0= ±245 dps; 1= ±500 dps; 2= ±1000 dps; 3= ±2000 dps) + virtual float getGyroFS(); // (output = 245.0, 500.0 , 1000.0, 2000.0) + + // Magnetometer + float magnetOffset[3] = {0, 0, 0}; // zero point offset correction factor for calibration + float magnetSlope[3] = {1, 1, 1}; // slope correction factor for calibration + float magnetUnit = MICROTESLA; // GAUSS or MICROTESLA + virtual int readMagnet(float &x, float &y, float &z); // Default results are in uT (micro Tesla) + virtual int magnetAvailable(); // Number of samples in the FIFO. + virtual void setMagnetOffset(float x, float y, float z); //Look out, from measurements only + virtual void setMagnetSlope(float x, float y, float z); + virtual int setMagnetODR(int8_t range); // Sampling rate (0..7) corresponds to {0.625,1.25,2.5,5.0,10.0,20.0,40.0,80.0}Hz + virtual float getMagnetODR(); // Sampling rate of the sensor in Hz. + virtual int setMagnetFS(int8_t range); // 0=400.0; 1=800.0; 2=1200.0 , 3=1600.0 (µT) + virtual float getMagnetFS(); // get chip's full scale setting + +private: + bool continuousMode; + int readRegister(uint8_t slaveAddress, uint8_t address); + int readRegisters(uint8_t slaveAddress, uint8_t address, uint8_t *data, size_t length); + int writeRegister(uint8_t slaveAddress, uint8_t address, uint8_t value); + +private: + TwoWire *_wire; }; extern LSM9DS1Class IMU; From 5884be7289f4de3580a0ace56985e2a0bb8a6924 Mon Sep 17 00:00:00 2001 From: Martin Hapl Date: Sun, 24 May 2020 22:23:04 +0200 Subject: [PATCH 03/15] Revert "Fixed formatting and deprecation messages" This reverts commit 7d890dae5ba30d0a90328624220598d5cb5ce40a. --- CHANGELOG | 5 - CHANGELOG.txt | 14 ++ src/LSM9DS1.cpp | 335 +++++++++++++++++++++--------------------------- src/LSM9DS1.h | 171 ++++++++++++------------ 4 files changed, 243 insertions(+), 282 deletions(-) create mode 100644 CHANGELOG.txt diff --git a/CHANGELOG b/CHANGELOG index b754b58..e2a62a0 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -7,8 +7,3 @@ Arduino_LSM9DS1 1.0.0 - 2019.07.31 Arduino_LSM9DS1 1.1.0 - 2020.02.11 * Added support for FIFO continuous reading of values - -Arduino_LSM9DS1 2.0.0 - 2020.05.15 - -* Offset, Full scale, sample rate on all DOF. -* Calibration parameters integrated \ No newline at end of file diff --git a/CHANGELOG.txt b/CHANGELOG.txt new file mode 100644 index 0000000..b754b58 --- /dev/null +++ b/CHANGELOG.txt @@ -0,0 +1,14 @@ +Arduino_LSM9DS1 ?.?.? - ????.??.?? + +Arduino_LSM9DS1 1.0.0 - 2019.07.31 + +* Initial release + +Arduino_LSM9DS1 1.1.0 - 2020.02.11 + +* Added support for FIFO continuous reading of values + +Arduino_LSM9DS1 2.0.0 - 2020.05.15 + +* Offset, Full scale, sample rate on all DOF. +* Calibration parameters integrated \ No newline at end of file diff --git a/src/LSM9DS1.cpp b/src/LSM9DS1.cpp index 59833cd..d3595fb 100644 --- a/src/LSM9DS1.cpp +++ b/src/LSM9DS1.cpp @@ -24,34 +24,35 @@ #include "LSM9DS1.h" -#define LSM9DS1_ADDRESS 0x6b +#define LSM9DS1_ADDRESS 0x6b -#define LSM9DS1_WHO_AM_I 0x0f -#define LSM9DS1_CTRL_REG1_G 0x10 -#define LSM9DS1_STATUS_REG 0x17 -#define LSM9DS1_OUT_X_G 0x18 -#define LSM9DS1_CTRL_REG6_XL 0x20 -#define LSM9DS1_CTRL_REG8 0x22 -#define LSM9DS1_OUT_X_XL 0x28 +#define LSM9DS1_WHO_AM_I 0x0f +#define LSM9DS1_CTRL_REG1_G 0x10 +#define LSM9DS1_STATUS_REG 0x17 +#define LSM9DS1_OUT_X_G 0x18 +#define LSM9DS1_CTRL_REG6_XL 0x20 +#define LSM9DS1_CTRL_REG8 0x22 +#define LSM9DS1_OUT_X_XL 0x28 // magnetometer -#define LSM9DS1_ADDRESS_M 0x1e +#define LSM9DS1_ADDRESS_M 0x1e -#define LSM9DS1_CTRL_REG1_M 0x20 -#define LSM9DS1_CTRL_REG2_M 0x21 -#define LSM9DS1_CTRL_REG3_M 0x22 -#define LSM9DS1_STATUS_REG_M 0x27 -#define LSM9DS1_OUT_X_L_M 0x28 +#define LSM9DS1_CTRL_REG1_M 0x20 +#define LSM9DS1_CTRL_REG2_M 0x21 +#define LSM9DS1_CTRL_REG3_M 0x22 +#define LSM9DS1_STATUS_REG_M 0x27 +#define LSM9DS1_OUT_X_L_M 0x28 // Add these right after defines at the beginning -#define LSM9DS1_OFFSET_X_REG_L_M 0x05 -#define LSM9DS1_OFFSET_X_REG_H_M 0x06 -#define LSM9DS1_OFFSET_Y_REG_L_M 0x07 -#define LSM9DS1_OFFSET_Y_REG_H_M 0x08 -#define LSM9DS1_OFFSET_Z_REG_L_M 0x09 -#define LSM9DS1_OFFSET_Z_REG_H_M 0x0A - -LSM9DS1Class::LSM9DS1Class(TwoWire &wire) : continuousMode(false), _wire(&wire) +#define LSM9DS1_OFFSET_X_REG_L_M 0x05 +#define LSM9DS1_OFFSET_X_REG_H_M 0x06 +#define LSM9DS1_OFFSET_Y_REG_L_M 0x07 +#define LSM9DS1_OFFSET_Y_REG_H_M 0x08 +#define LSM9DS1_OFFSET_Z_REG_L_M 0x09 +#define LSM9DS1_OFFSET_Z_REG_H_M 0x0A + +LSM9DS1Class::LSM9DS1Class(TwoWire& wire) : + continuousMode(false), _wire(&wire) { } @@ -69,21 +70,19 @@ int LSM9DS1Class::begin() delay(10); - if (readRegister(LSM9DS1_ADDRESS, LSM9DS1_WHO_AM_I) != 0x68) - { + if (readRegister(LSM9DS1_ADDRESS, LSM9DS1_WHO_AM_I) != 0x68) { end(); return 0; } - if (readRegister(LSM9DS1_ADDRESS_M, LSM9DS1_WHO_AM_I) != 0x3d) - { + if (readRegister(LSM9DS1_ADDRESS_M, LSM9DS1_WHO_AM_I) != 0x3d) { end(); return 0; } - writeRegister(LSM9DS1_ADDRESS, LSM9DS1_CTRL_REG1_G, 0x78); // 119 Hz, 2000 dps, 16 Hz BW + writeRegister(LSM9DS1_ADDRESS, LSM9DS1_CTRL_REG1_G, 0x78); // 119 Hz, 2000 dps, 16 Hz BW writeRegister(LSM9DS1_ADDRESS, LSM9DS1_CTRL_REG6_XL, 0x70); // 119 Hz, 4G writeRegister(LSM9DS1_ADDRESS_M, LSM9DS1_CTRL_REG1_M, 0xb4); // Temperature compensation enable, medium performance, 20 Hz @@ -93,8 +92,7 @@ int LSM9DS1Class::begin() return 1; } -void LSM9DS1Class::setContinuousMode() -{ +void LSM9DS1Class::setContinuousMode() { // Enable FIFO (see docs https://www.st.com/resource/en/datasheet/DM00103319.pdf) writeRegister(LSM9DS1_ADDRESS, 0x23, 0x02); // Set continuous mode @@ -103,8 +101,7 @@ void LSM9DS1Class::setContinuousMode() continuousMode = true; } -void LSM9DS1Class::setOneShotMode() -{ +void LSM9DS1Class::setOneShotMode() { // Disable FIFO (see docs https://www.st.com/resource/en/datasheet/DM00103319.pdf) writeRegister(LSM9DS1_ADDRESS, 0x23, 0x00); // Disable continuous mode @@ -124,18 +121,16 @@ void LSM9DS1Class::end() //************************************ Accelleration ***************************************** -int LSM9DS1Class::readAccel(float &x, float &y, float &z) -{ - int16_t data[3]; - if (!readRegisters(LSM9DS1_ADDRESS, LSM9DS1_OUT_X_XL, (uint8_t *)data, sizeof(data))) - { +int LSM9DS1Class::readAccel(float& x, float& y, float& z) +{ int16_t data[3]; + if (!readRegisters(LSM9DS1_ADDRESS, LSM9DS1_OUT_X_XL, (uint8_t*)data, sizeof(data))) { x = NAN; y = NAN; z = NAN; return 0; } // See releasenotes read = Unit * Slope * (PFS / 32786 * Data - Offset ) - float scale = getAccelFS() / 32768.0; + float scale = getAccelFS()/32768.0 ; x = accelUnit * accelSlope[0] * (scale * data[0] - accelOffset[0]); y = accelUnit * accelSlope[1] * (scale * data[1] - accelOffset[1]); z = accelUnit * accelSlope[2] * (scale * data[2] - accelOffset[2]); @@ -144,94 +139,76 @@ int LSM9DS1Class::readAccel(float &x, float &y, float &z) int LSM9DS1Class::accelAvailable() { - if (continuousMode) - { + if (continuousMode) { // Read FIFO_SRC. If any of the rightmost 8 bits have a value, there is data. - if (readRegister(LSM9DS1_ADDRESS, 0x2F) & 63) - { + if (readRegister(LSM9DS1_ADDRESS, 0x2F) & 63) { return 1; } - } - else - { - if (readRegister(LSM9DS1_ADDRESS, LSM9DS1_STATUS_REG) & 0x01) - { + } else { + if (readRegister(LSM9DS1_ADDRESS, LSM9DS1_STATUS_REG) & 0x01) { return 1; } } return 0; } -void LSM9DS1Class::setAccelOffset(float x, float y, float z) -{ - accelOffset[0] = x / (accelUnit * gyroSlope[0]); - accelOffset[1] = y / (accelUnit * gyroSlope[1]); - accelOffset[2] = z / (accelUnit * gyroSlope[2]); +void LSM9DS1Class::setAccelOffset(float x, float y, float z) //Look out, from measurements only +{ accelOffset[0] = x /(accelUnit * accelSlope[0]); + accelOffset[1] = y /(accelUnit * accelSlope[1]); + accelOffset[2] = z /(accelUnit * accelSlope[2]); } -void LSM9DS1Class::setAccelSlope(float x, float y, float z) -{ - accelSlope[0] = x; - accelSlope[1] = y; - accelSlope[2] = z; +void LSM9DS1Class::setAccelSlope(float x, float y, float z) +{ accelSlope[0] = x ; + accelSlope[1] = y ; + accelSlope[2] = z ; } int LSM9DS1Class::setAccelODR(int8_t range) //Sample Rate 0:off, 1:10Hz, 2:50Hz, 3:119Hz, 4:238Hz, 5:476Hz, 6:952Hz, 7:NA -{ - if (range == 7) - range = 0; - range = (range & 0b00000111) << 5; - uint8_t setting = ((readRegister(LSM9DS1_ADDRESS, LSM9DS1_CTRL_REG6_XL) & 0b00011111) | range); - return writeRegister(LSM9DS1_ADDRESS, LSM9DS1_CTRL_REG6_XL, setting); +{ if (range==7) range =0; + range = (range & B00000111) << 5; + uint8_t setting = ((readRegister(LSM9DS1_ADDRESS, LSM9DS1_CTRL_REG6_XL) & B00011111) | range); + return writeRegister(LSM9DS1_ADDRESS, LSM9DS1_CTRL_REG6_XL,setting) ; } float LSM9DS1Class::getAccelODR() -{ - float Ranges[] = {0.0, 10.0, 50.0, 119.0, 238.0, 476.0, 952.0, 0.0}; - uint8_t setting = readRegister(LSM9DS1_ADDRESS, LSM9DS1_CTRL_REG6_XL) >> 5; - return Ranges[setting]; +{ float Ranges[] ={0.0, 10.0, 50.0, 119.0, 238.0, 476.0, 952.0, 0.0 }; + uint8_t setting = readRegister(LSM9DS1_ADDRESS, LSM9DS1_CTRL_REG6_XL) >> 5; + return Ranges [setting]; } float LSM9DS1Class::setAccelBW(int8_t range) //0,1,2,3 Override autoBandwidth setting see doc.table 67 -{ - range = range & 0b00000011; - uint8_t RegIs = readRegister(LSM9DS1_ADDRESS, LSM9DS1_CTRL_REG6_XL) & 0b11111000; - RegIs = RegIs | 0b00000100 | range; - return writeRegister(LSM9DS1_ADDRESS, LSM9DS1_CTRL_REG6_XL, RegIs); +{ range = range & B00000011; + uint8_t RegIs = readRegister(LSM9DS1_ADDRESS, LSM9DS1_CTRL_REG6_XL) & B11111000; + RegIs = RegIs | B00000100 | range ; + return writeRegister(LSM9DS1_ADDRESS, LSM9DS1_CTRL_REG6_XL,RegIs) ; } float LSM9DS1Class::getAccelBW() //Bandwidth setting 0,1,2,3 see documentation table 67 -{ - float autoRange[] = {0.0, 408.0, 408.0, 50.0, 105.0, 211.0, 408.0, 0.0}; - float BWXLRange[] = {408.0, 211.0, 105.0, 50.0}; +{ float autoRange[] ={0.0, 408.0, 408.0, 50.0, 105.0, 211.0, 408.0, 0.0 }; + float BWXLRange[] ={ 408.0, 211.0, 105.0, 50.0 }; uint8_t RegIs = readRegister(LSM9DS1_ADDRESS, LSM9DS1_CTRL_REG6_XL); - if (bitRead(2, RegIs)) - return BWXLRange[RegIs & 0b00000011]; - else - return autoRange[RegIs >> 5]; + if (bitRead(2,RegIs)) return BWXLRange [RegIs & B00000011]; + else return autoRange [ RegIs >> 5 ]; } -int LSM9DS1Class::setAccelFS(int8_t range) // 0: ±2g ; 1: ±16g ; 2: ±4g ; 3: ±8g -{ - range = (range & 0b00000011) << 3; - uint8_t setting = ((readRegister(LSM9DS1_ADDRESS, LSM9DS1_CTRL_REG6_XL) & 0xE7) | range); - return writeRegister(LSM9DS1_ADDRESS, LSM9DS1_CTRL_REG6_XL, setting); +int LSM9DS1Class::setAccelFS(int8_t range) // 0: ±2g ; 1: ±16g ; 2: ±4g ; 3: ±8g +{ range = (range & B00000011) << 3; + uint8_t setting = ((readRegister(LSM9DS1_ADDRESS, LSM9DS1_CTRL_REG6_XL) & 0xE7) | range); + return writeRegister(LSM9DS1_ADDRESS, LSM9DS1_CTRL_REG6_XL,setting) ; } -float LSM9DS1Class::getAccelFS() // Full scale (output = 2.0, 16.0 , 4.0 , 8.0) -{ - float ranges[] = {2.0, 16.0, 4.0, 8.0}; //g +float LSM9DS1Class::getAccelFS() // Full scale (output = 2.0, 16.0 , 4.0 , 8.0) +{ float ranges[] ={2.0, 16.0, 4.0, 8.0}; //g uint8_t setting = (readRegister(LSM9DS1_ADDRESS, LSM9DS1_CTRL_REG6_XL) & 0x18) >> 3; - return ranges[setting]; + return ranges[setting] ; } //************************************ Gyroscope ***************************************** -int LSM9DS1Class::readGyro(float &x, float &y, float &z) -{ - int16_t data[3]; - if (!readRegisters(LSM9DS1_ADDRESS, LSM9DS1_OUT_X_G, (uint8_t *)data, sizeof(data))) - { - x = NAN; +int LSM9DS1Class::readGyro(float& x, float& y, float& z) +{ int16_t data[3]; + if (!readRegisters(LSM9DS1_ADDRESS, LSM9DS1_OUT_X_G, (uint8_t*)data, sizeof(data))) + { x = NAN; y = NAN; z = NAN; return 0; @@ -245,92 +222,80 @@ int LSM9DS1Class::readGyro(float &x, float &y, float &z) int LSM9DS1Class::gyroAvailable() { - if (readRegister(LSM9DS1_ADDRESS, LSM9DS1_STATUS_REG) & 0x02) - { + if (readRegister(LSM9DS1_ADDRESS, LSM9DS1_STATUS_REG) & 0x02) { return 1; } return 0; } -void LSM9DS1Class::setGyroOffset(float x, float y, float z) -{ - gyroOffset[0] = x / (gyroUnit * gyroSlope[0]); - gyroOffset[1] = y / (gyroUnit * gyroSlope[1]); - gyroOffset[2] = z / (gyroUnit * gyroSlope[2]); +void LSM9DS1Class::setGyroOffset(float x, float y, float z) //Look out, from measurements only +{ gyroOffset[0] = x /(gyroUnit * gyroSlope[0]); + gyroOffset[1] = y /(gyroUnit * gyroSlope[1]); + gyroOffset[2] = z /(gyroUnit * gyroSlope[2]); } -void LSM9DS1Class::setGyroSlope(float x, float y, float z) -{ - gyroSlope[0] = x; - gyroSlope[1] = y; - gyroSlope[2] = z; +void LSM9DS1Class::setGyroSlope(float x, float y, float z) +{ gyroSlope[0] = x ; + gyroSlope[1] = y ; + gyroSlope[2] = z ; } - + int LSM9DS1Class::setGyroODR(int8_t range) // 0:off, 1:10Hz, 2:50Hz, 3:119Hz, 4:238Hz, 5:476Hz, 6:952Hz, 7:NA -{ - if (range == 7) - range = 0; - range = (range & 0b00000111) << 5; - uint8_t setting = ((readRegister(LSM9DS1_ADDRESS, LSM9DS1_CTRL_REG1_G) & 0b00011111) | range); - return writeRegister(LSM9DS1_ADDRESS, LSM9DS1_CTRL_REG1_G, setting); +{ if (range==7) range =0; + range = (range & B00000111) << 5; + uint8_t setting = ((readRegister(LSM9DS1_ADDRESS, LSM9DS1_CTRL_REG1_G) & B00011111) | range); + return writeRegister(LSM9DS1_ADDRESS, LSM9DS1_CTRL_REG1_G,setting) ; } float LSM9DS1Class::getGyroODR() -{ - float Ranges[] = {0.0, 10.0, 50.0, 119.0, 238.0, 476.0, 952.0, 0.0}; //Hz - uint8_t setting = readRegister(LSM9DS1_ADDRESS, LSM9DS1_CTRL_REG1_G) >> 5; - return Ranges[setting]; // return 119.0F; +{ float Ranges[] ={0.0, 10.0, 50.0, 119.0, 238.0, 476.0, 952.0, 0.0 }; //Hz + uint8_t setting = readRegister(LSM9DS1_ADDRESS, LSM9DS1_CTRL_REG1_G) >> 5; + return Ranges [setting]; // return 119.0F; } int LSM9DS1Class::setGyroBW(int8_t range) -{ - range = range & 0b00000011; - uint8_t setting = readRegister(LSM9DS1_ADDRESS, LSM9DS1_CTRL_REG1_G) & 0b11111100; - return writeRegister(LSM9DS1_ADDRESS, LSM9DS1_CTRL_REG1_G, setting | range); +{ range = range & B00000011; + uint8_t setting = readRegister(LSM9DS1_ADDRESS, LSM9DS1_CTRL_REG1_G) & B11111100; + return writeRegister(LSM9DS1_ADDRESS, LSM9DS1_CTRL_REG1_G,setting | range) ; } #define ODRrows 8 #define BWcols 4 -float BWtable[ODRrows][BWcols] = // acc to - {{0, 0, 0, 0}, - {0, 0, 0, 0}, - {16, 16, 16, 16}, - {14, 31, 31, 31}, - {14, 29, 63, 78}, - {21, 28, 57, 100}, - {33, 40, 58, 100}, - {0, 0, 0, 0}}; +float BWtable[ ODRrows ][ BWcols ] = // acc to + { { 0, 0, 0, 0 }, + { 0, 0, 0, 0 }, + { 16, 16, 16, 16 }, + { 14, 31, 31, 31 }, + { 14, 29, 63, 78 }, + { 21, 28, 57, 100 }, + { 33, 40, 58, 100 }, + { 0, 0, 0, 0 } }; float LSM9DS1Class::getGyroBW() -{ - uint8_t setting = readRegister(LSM9DS1_ADDRESS, LSM9DS1_CTRL_REG1_G); - uint8_t ODR = setting >> 5; - uint8_t BW = setting & 0b00000011; - return BWtable[ODR][BW]; +{ uint8_t setting = readRegister(LSM9DS1_ADDRESS, LSM9DS1_CTRL_REG1_G) ; + uint8_t ODR = setting >> 5; + uint8_t BW = setting & B00000011; + return BWtable[ODR][BW]; } - + int LSM9DS1Class::setGyroFS(int8_t range) // (0: 245 dps; 1: 500 dps; 2: 1000 dps; 3: 2000 dps) -{ - range = (range & 0b00000011) << 3; - uint8_t setting = ((readRegister(LSM9DS1_ADDRESS, LSM9DS1_CTRL_REG1_G) & 0xE7) | range); - return writeRegister(LSM9DS1_ADDRESS, LSM9DS1_CTRL_REG1_G, setting); +{ range = (range & B00000011) << 3; + uint8_t setting = ((readRegister(LSM9DS1_ADDRESS, LSM9DS1_CTRL_REG1_G) & 0xE7) | range ); + return writeRegister(LSM9DS1_ADDRESS, LSM9DS1_CTRL_REG1_G,setting) ; } -float LSM9DS1Class::getGyroFS() // -{ - float Ranges[] = {245.0, 500.0, 1000.0, 2000.0}; //dps +float LSM9DS1Class::getGyroFS() // +{ float Ranges[] ={245.0, 500.0, 1000.0, 2000.0}; //dps uint8_t setting = (readRegister(LSM9DS1_ADDRESS, LSM9DS1_CTRL_REG1_G) & 0x18) >> 3; - return Ranges[setting]; + return Ranges[setting] ; } //************************************ Magnetic field ***************************************** -int LSM9DS1Class::readMagneticField(float &x, float &y, float &z) -{ - int16_t data[3]; +int LSM9DS1Class::readMagneticField(float& x, float& y, float& z) +{ int16_t data[3]; - if (!readRegisters(LSM9DS1_ADDRESS_M, LSM9DS1_OUT_X_L_M, (uint8_t *)data, sizeof(data))) - { + if (!readRegisters(LSM9DS1_ADDRESS_M, LSM9DS1_OUT_X_L_M, (uint8_t*)data, sizeof(data))) { x = NAN; y = NAN; z = NAN; @@ -345,89 +310,78 @@ int LSM9DS1Class::readMagneticField(float &x, float &y, float &z) int LSM9DS1Class::magneticFieldAvailable() { //return (readRegister(LSM9DS1_ADDRESS_M, LSM9DS1_STATUS_REG_M) & 0x08)==0x08; - if (readRegister(LSM9DS1_ADDRESS_M, LSM9DS1_STATUS_REG_M) & 0x08) - { + if (readRegister(LSM9DS1_ADDRESS_M, LSM9DS1_STATUS_REG_M) & 0x08) { return 1; } return 0; } -void LSM9DS1Class::setMagnetOffset(float x, float y, float z) -{ - magnetOffset[0] = x / (magnetUnit * magnetSlope[0]); - magnetOffset[1] = y / (magnetUnit * magnetSlope[1]); - magnetOffset[2] = z / (magnetUnit * magnetSlope[2]); +void LSM9DS1Class::setMagnetOffset(float x, float y, float z) //Look out, from measurements only +{ magnetOffset[0] = x /(magnetUnit * magnetSlope[0]); + magnetOffset[1] = y /(magnetUnit * magnetSlope[1]); + magnetOffset[2] = z /(magnetUnit * magnetSlope[2]); } -void LSM9DS1Class::setMagnetSlope(float x, float y, float z) -{ - magnetSlope[0] = x; - magnetSlope[1] = y; - magnetSlope[2] = z; +void LSM9DS1Class::setMagnetSlope(float x, float y, float z) +{ magnetSlope[0] = x ; + magnetSlope[1] = y ; + magnetSlope[2] = z ; } - + int LSM9DS1Class::setMagnetFS(int8_t range) // 0=400.0; 1=800.0; 2=1200.0 , 3=1600.0 (µT) -{ - range = (range & 0b00000011) << 5; - return writeRegister(LSM9DS1_ADDRESS, LSM9DS1_CTRL_REG2_M, range); +{ range = (range & B00000011) << 5; + return writeRegister(LSM9DS1_ADDRESS, LSM9DS1_CTRL_REG2_M,range) ; } -float LSM9DS1Class::getMagnetFS() // -{ - const float Ranges[] = {400.0, 800.0, 1200.0, 1600.0}; // - uint8_t setting = readRegister(LSM9DS1_ADDRESS, LSM9DS1_CTRL_REG2_M) >> 5; - return Ranges[setting]; +float LSM9DS1Class::getMagnetFS() // +{ const float Ranges[] ={400.0, 800.0, 1200.0, 1600.0}; // + uint8_t setting = readRegister(LSM9DS1_ADDRESS, LSM9DS1_CTRL_REG2_M) >> 5; + return Ranges[setting] ; } -int LSM9DS1Class::setMagnetODR(int8_t range) // range (0..7) corresponds to {0.625,1.25,2.5,5.0,10.0,20.0,40.0,80.0}Hz -{ - range = (range & 0b00000111) << 2; - uint8_t setting = ((readRegister(LSM9DS1_ADDRESS_M, LSM9DS1_CTRL_REG1_M) & 0b11100011) | range); - return writeRegister(LSM9DS1_ADDRESS_M, LSM9DS1_CTRL_REG1_M, setting); +int LSM9DS1Class::setMagnetODR(int8_t range) // range (0..7) corresponds to {0.625,1.25,2.5,5.0,10.0,20.0,40.0,80.0}Hz +{ range = (range & B00000111) << 2; + uint8_t setting = ((readRegister(LSM9DS1_ADDRESS_M, LSM9DS1_CTRL_REG1_M) & B11100011) | range); + return writeRegister(LSM9DS1_ADDRESS_M, LSM9DS1_CTRL_REG1_M,setting) ; } -float LSM9DS1Class::getMagnetODR() // Output {0.625, 1.25, 2.5, 5.0, 10.0, 20.0, 40.0 , 80.0}; //Hz -{ - const float ranges[] = {0.625, 1.25, 2.5, 5.0, 10.0, 20.0, 40.0, 80.0}; //Hz - uint8_t setting = (readRegister(LSM9DS1_ADDRESS_M, LSM9DS1_CTRL_REG1_M) & 0b00011100) >> 2; +float LSM9DS1Class::getMagnetODR() // Output {0.625, 1.25, 2.5, 5.0, 10.0, 20.0, 40.0 , 80.0}; //Hz +{ const float ranges[] ={0.625, 1.25,2.5, 5.0, 10.0, 20.0, 40.0 , 80.0}; //Hz + uint8_t setting = (readRegister(LSM9DS1_ADDRESS_M, LSM9DS1_CTRL_REG1_M) & B00011100) >> 2; return ranges[setting]; } //************************************ Private functions ***************************************** + int LSM9DS1Class::readRegister(uint8_t slaveAddress, uint8_t address) { _wire->beginTransmission(slaveAddress); _wire->write(address); - if (_wire->endTransmission() != 0) - { + if (_wire->endTransmission() != 0) { return -1; } - if (_wire->requestFrom(slaveAddress, 1) != 1) - { + if (_wire->requestFrom(slaveAddress, 1) != 1) { return -1; } return _wire->read(); } -int LSM9DS1Class::readRegisters(uint8_t slaveAddress, uint8_t address, uint8_t *data, size_t length) +int LSM9DS1Class::readRegisters(uint8_t slaveAddress, uint8_t address, uint8_t* data, size_t length) { _wire->beginTransmission(slaveAddress); _wire->write(0x80 | address); - if (_wire->endTransmission(false) != 0) - { + if (_wire->endTransmission(false) != 0) { return -1; } - if (_wire->requestFrom(slaveAddress, length) != length) - { + if (_wire->requestFrom(slaveAddress, length) != length) { return 0; } - for (size_t i = 0; i < length; i++) - { + for (size_t i = 0; i < length; i++) { *data++ = _wire->read(); } @@ -439,8 +393,7 @@ int LSM9DS1Class::writeRegister(uint8_t slaveAddress, uint8_t address, uint8_t v _wire->beginTransmission(slaveAddress); _wire->write(address); _wire->write(value); - if (_wire->endTransmission() != 0) - { + if (_wire->endTransmission() != 0) { return 0; } diff --git a/src/LSM9DS1.h b/src/LSM9DS1.h index 5829ec8..68a4694 100644 --- a/src/LSM9DS1.h +++ b/src/LSM9DS1.h @@ -21,27 +21,27 @@ version 2.0.0 */ -#ifndef LSM9DS1_V2 -#define LSM9DS1_V2 -#endif +#ifndef LSM9DS1_V2.0 + #define LSM9DS1_V2.0 +#endif #define accelerationSampleRate getAccelODR #define gyroscopeSampleRate getGyroODR #define magneticFieldSampleRate getMagnetODR -#define setAccelerationSampleRate setAccelODR //development -#define setGyroscopeSampleRate setGyroODR //development -#define setMagnetisFieldSampleRate setMagnetODR // development +#define setAccelerationSampleRate setAccelODR //development +#define setGyroscopeSampleRate setGyroODR //development +#define setMagnetisFieldSampleRate setMagnetODR // development -#define accelerationFullScale getAccelFS //development -#define gyroscopeFullScale getGyroFS //development -#define magneticFieldFullScale getMagnetFS //development +#define accelerationFullScale getAccelFS //development +#define gyroscopeFullScale getGyroFS //development +#define magneticFieldFullScale getMagnetFS //development -#define setAccelerationFullScale setAccelFS //development -#define setGyroscopeFullScale setGyroFS //development -#define setMagneticFieldFullScale setMagnetFS //development +#define setAccelerationFullScale setAccelFS //development +#define setGyroscopeFullScale setGyroFS //development +#define setMagneticFieldFullScale setMagnetFS //development -#define readAcceleration readAccel +#define readAcceleration readAccel #define readGyroscope readGyro #define readMagneticField readMagnet @@ -51,79 +51,78 @@ #include #include -#define GAUSS 0.01 -#define MICROTESLA 1.0 // default -#define NANOTESLA 1000.0 -#define GRAVITY 1.0 // default -#define METERPERSECOND2 9.81 -#define DEGREEPERSECOND 1.0 //default -#define RADIANSPERSECOND 3.141592654 / 180 - -class LSM9DS1Class -{ -public: - LSM9DS1Class(TwoWire &wire); - virtual ~LSM9DS1Class(); - - int begin(); - void end(); - - // Controls whether a FIFO is continuously filled, or a single reading is stored. - // Defaults to one-shot. - void setContinuousMode(); - void setOneShotMode(); - - // Accelerometer - float accelOffset[3] = {0, 0, 0}; // zero point offset correction factor for calibration - float accelSlope[3] = {1, 1, 1}; // slope correction factor for calibration - float accelUnit = GRAVITY; // GRAVITY OR METERPERSECOND2 - virtual int readAccel(float &x, float &y, float &z); // Results are in G (earth gravity) or m/s2. - virtual int accelAvailable(); // Number of samples in the FIFO. - virtual void setAccelOffset(float x, float y, float z); //Look out, from measurements only - virtual void setAccelSlope(float x, float y, float z); - virtual int setAccelODR(int8_t range); // Sample Rate 0:off, 1:10Hz, 2:50Hz, 3:119Hz, 4:238Hz, 5:476Hz, 6:952Hz, 7:NA Automatic setting of BW - virtual float getAccelODR(); // Sample Rate of the sensor. - virtual float setAccelBW(int8_t range); //0,1,2,3 Override autoBandwidth setting see doc.table 67 - virtual float getAccelBW(); //Bandwidth setting 0,1,2,3 see documentation table 67 - virtual int setAccelFS(int8_t range); // 0: ±2g ; 1: ±16g ; 2: ±4g ; 3: ±8g - virtual float getAccelFS(); // Full Scale setting (output = 2.0, 16.0 , 4.0 , 8.0) - - // Gyroscope - float gyroOffset[3] = {0, 0, 0}; // zero point offset correction factor for calibration - float gyroSlope[3] = {1, 1, 1}; // slope correction factor for calibration - float gyroUnit = DEGREEPERSECOND; // DEGREEPERSECOND or RADIANSPERSECOND - virtual int readGyro(float &x, float &y, float &z); // Results are in degrees/second or rad/s. - virtual int gyroAvailable(); // Number of samples in the FIFO. - virtual void setGyroOffset(float x, float y, float z); //Look out, from measurements only - virtual void setGyroSlope(float x, float y, float z); - virtual int setGyroODR(int8_t range); //Sampling Rate 0:off, 1:10Hz, 2:50Hz, 3:119Hz, 4:238Hz, 5:476Hz, 6:952Hz, 7:NA - virtual float getGyroODR(); // Sampling rate of the sensor. - virtual int setGyroBW(int8_t range); //Bandwidth setting 0,1,2,3 see documentation table 46 and 47 - virtual float getGyroBW(); //Bandwidth setting 0,1,2,3 see documentation table 46 and 47 - virtual int setGyroFS(int8_t range); // (0= ±245 dps; 1= ±500 dps; 2= ±1000 dps; 3= ±2000 dps) - virtual float getGyroFS(); // (output = 245.0, 500.0 , 1000.0, 2000.0) - - // Magnetometer - float magnetOffset[3] = {0, 0, 0}; // zero point offset correction factor for calibration - float magnetSlope[3] = {1, 1, 1}; // slope correction factor for calibration - float magnetUnit = MICROTESLA; // GAUSS or MICROTESLA - virtual int readMagnet(float &x, float &y, float &z); // Default results are in uT (micro Tesla) - virtual int magnetAvailable(); // Number of samples in the FIFO. - virtual void setMagnetOffset(float x, float y, float z); //Look out, from measurements only - virtual void setMagnetSlope(float x, float y, float z); - virtual int setMagnetODR(int8_t range); // Sampling rate (0..7) corresponds to {0.625,1.25,2.5,5.0,10.0,20.0,40.0,80.0}Hz - virtual float getMagnetODR(); // Sampling rate of the sensor in Hz. - virtual int setMagnetFS(int8_t range); // 0=400.0; 1=800.0; 2=1200.0 , 3=1600.0 (µT) - virtual float getMagnetFS(); // get chip's full scale setting - -private: - bool continuousMode; - int readRegister(uint8_t slaveAddress, uint8_t address); - int readRegisters(uint8_t slaveAddress, uint8_t address, uint8_t *data, size_t length); - int writeRegister(uint8_t slaveAddress, uint8_t address, uint8_t value); - -private: - TwoWire *_wire; +#define GAUSS 0.01 +#define MICROTESLA 1.0 // default +#define NANOTESLA 1000.0 +#define GRAVITY 1.0 // default +#define METERPERSECOND2 9.81 +#define DEGREEPERSECOND 1.0 //default +#define RADIANSPERSECOND 3.141592654/180 + +class LSM9DS1Class { + public: + LSM9DS1Class(TwoWire& wire); + virtual ~LSM9DS1Class(); + + int begin(); + void end(); + + // Controls whether a FIFO is continuously filled, or a single reading is stored. + // Defaults to one-shot. + void setContinuousMode(); + void setOneShotMode(); + + // Accelerometer + float accelOffset[3] = {0,0,0}; // zero point offset correction factor for calibration + float accelSlope[3] = {1,1,1}; // slope correction factor for calibration + float accelUnit = GRAVITY; // GRAVITY OR METERPERSECOND2 + virtual int readAccel(float& x, float& y, float& z); // Results are in G (earth gravity) or m/s2. + virtual int accelAvailable(); // Number of samples in the FIFO. + virtual void setAccelOffset(float x, float y, float z); //Look out, from measurements only + virtual void setAccelSlope(float x, float y, float z); + virtual int setAccelODR(int8_t range); // Sample Rate 0:off, 1:10Hz, 2:50Hz, 3:119Hz, 4:238Hz, 5:476Hz, 6:952Hz, 7:NA Automatic setting of BW + virtual float getAccelODR(); // Sample Rate of the sensor. + virtual float setAccelBW(int8_t range); //0,1,2,3 Override autoBandwidth setting see doc.table 67 + virtual float getAccelBW(); //Bandwidth setting 0,1,2,3 see documentation table 67 + virtual int setAccelFS(int8_t range); // 0: ±2g ; 1: ±16g ; 2: ±4g ; 3: ±8g + virtual float getAccelFS(); // Full Scale setting (output = 2.0, 16.0 , 4.0 , 8.0) + + // Gyroscope + float gyroOffset[3] = {0,0,0}; // zero point offset correction factor for calibration + float gyroSlope[3] = {1,1,1}; // slope correction factor for calibration + float gyroUnit = DEGREEPERSECOND; // DEGREEPERSECOND or RADIANSPERSECOND + virtual int readGyro(float& x, float& y, float& z); // Results are in degrees/second or rad/s. + virtual int gyroAvailable(); // Number of samples in the FIFO. + virtual void setGyroOffset(float x, float y, float z); //Look out, from measurements only + virtual void setGyroSlope(float x, float y, float z); + virtual int setGyroODR(int8_t range); //Sampling Rate 0:off, 1:10Hz, 2:50Hz, 3:119Hz, 4:238Hz, 5:476Hz, 6:952Hz, 7:NA + virtual float getGyroODR(); // Sampling rate of the sensor. + virtual int setGyroBW(int8_t range); //Bandwidth setting 0,1,2,3 see documentation table 46 and 47 + virtual float getGyroBW(); //Bandwidth setting 0,1,2,3 see documentation table 46 and 47 + virtual int setGyroFS(int8_t range); // (0= ±245 dps; 1= ±500 dps; 2= ±1000 dps; 3= ±2000 dps) + virtual float getGyroFS(); // (output = 245.0, 500.0 , 1000.0, 2000.0) + + // Magnetometer + float magnetOffset[3] = {0,0,0}; // zero point offset correction factor for calibration + float magnetSlope[3] = {1,1,1}; // slope correction factor for calibration + float magnetUnit = MICROTESLA; // GAUSS or MICROTESLA + virtual int readMagnet(float& x, float& y, float& z); // Default results are in uT (micro Tesla) + virtual int magnetAvailable(); // Number of samples in the FIFO. + virtual void setMagnetOffset(float x, float y, float z); //Look out, from measurements only + virtual void setMagnetSlope(float x, float y, float z); + virtual int setMagnetODR(int8_t range); // Sampling rate (0..7) corresponds to {0.625,1.25,2.5,5.0,10.0,20.0,40.0,80.0}Hz + virtual float getMagnetODR(); // Sampling rate of the sensor in Hz. + virtual int setMagnetFS(int8_t range); // 0=400.0; 1=800.0; 2=1200.0 , 3=1600.0 (µT) + virtual float getMagnetFS(); // get chip's full scale setting + + private: + bool continuousMode; + int readRegister(uint8_t slaveAddress, uint8_t address); + int readRegisters(uint8_t slaveAddress, uint8_t address, uint8_t* data, size_t length); + int writeRegister(uint8_t slaveAddress, uint8_t address, uint8_t value); + + private: + TwoWire* _wire; }; extern LSM9DS1Class IMU; From 340be41ec9278793fd80c5faf5140326d211521f Mon Sep 17 00:00:00 2001 From: Martin Hapl Date: Sun, 24 May 2020 22:26:40 +0200 Subject: [PATCH 04/15] Fix formatting and deprecation messages #2 Fixed old notation of bool variables, version string of the library, and CHANGELOG extension, this time without excessive changes --- CHANGELOG | 5 +++++ CHANGELOG.txt | 14 -------------- src/LSM9DS1.h | 28 ++++++++++++++-------------- 3 files changed, 19 insertions(+), 28 deletions(-) delete mode 100644 CHANGELOG.txt diff --git a/CHANGELOG b/CHANGELOG index e2a62a0..b754b58 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -7,3 +7,8 @@ Arduino_LSM9DS1 1.0.0 - 2019.07.31 Arduino_LSM9DS1 1.1.0 - 2020.02.11 * Added support for FIFO continuous reading of values + +Arduino_LSM9DS1 2.0.0 - 2020.05.15 + +* Offset, Full scale, sample rate on all DOF. +* Calibration parameters integrated \ No newline at end of file diff --git a/CHANGELOG.txt b/CHANGELOG.txt deleted file mode 100644 index b754b58..0000000 --- a/CHANGELOG.txt +++ /dev/null @@ -1,14 +0,0 @@ -Arduino_LSM9DS1 ?.?.? - ????.??.?? - -Arduino_LSM9DS1 1.0.0 - 2019.07.31 - -* Initial release - -Arduino_LSM9DS1 1.1.0 - 2020.02.11 - -* Added support for FIFO continuous reading of values - -Arduino_LSM9DS1 2.0.0 - 2020.05.15 - -* Offset, Full scale, sample rate on all DOF. -* Calibration parameters integrated \ No newline at end of file diff --git a/src/LSM9DS1.h b/src/LSM9DS1.h index 68a4694..e30f538 100644 --- a/src/LSM9DS1.h +++ b/src/LSM9DS1.h @@ -21,8 +21,8 @@ version 2.0.0 */ -#ifndef LSM9DS1_V2.0 - #define LSM9DS1_V2.0 +#ifndef LSM9DS1_V2 + #define LSM9DS1_V2 #endif #define accelerationSampleRate getAccelODR @@ -74,12 +74,12 @@ class LSM9DS1Class { // Accelerometer float accelOffset[3] = {0,0,0}; // zero point offset correction factor for calibration - float accelSlope[3] = {1,1,1}; // slope correction factor for calibration - float accelUnit = GRAVITY; // GRAVITY OR METERPERSECOND2 + float accelSlope[3] = {1,1,1}; // slope correction factor for calibration + float accelUnit = GRAVITY; // GRAVITY OR METERPERSECOND2 virtual int readAccel(float& x, float& y, float& z); // Results are in G (earth gravity) or m/s2. virtual int accelAvailable(); // Number of samples in the FIFO. - virtual void setAccelOffset(float x, float y, float z); //Look out, from measurements only - virtual void setAccelSlope(float x, float y, float z); + virtual void setAccelOffset(float x, float y, float z); //Look out, from measurements only + virtual void setAccelSlope(float x, float y, float z); virtual int setAccelODR(int8_t range); // Sample Rate 0:off, 1:10Hz, 2:50Hz, 3:119Hz, 4:238Hz, 5:476Hz, 6:952Hz, 7:NA Automatic setting of BW virtual float getAccelODR(); // Sample Rate of the sensor. virtual float setAccelBW(int8_t range); //0,1,2,3 Override autoBandwidth setting see doc.table 67 @@ -88,13 +88,13 @@ class LSM9DS1Class { virtual float getAccelFS(); // Full Scale setting (output = 2.0, 16.0 , 4.0 , 8.0) // Gyroscope - float gyroOffset[3] = {0,0,0}; // zero point offset correction factor for calibration - float gyroSlope[3] = {1,1,1}; // slope correction factor for calibration + float gyroOffset[3] = {0,0,0}; // zero point offset correction factor for calibration + float gyroSlope[3] = {1,1,1}; // slope correction factor for calibration float gyroUnit = DEGREEPERSECOND; // DEGREEPERSECOND or RADIANSPERSECOND virtual int readGyro(float& x, float& y, float& z); // Results are in degrees/second or rad/s. virtual int gyroAvailable(); // Number of samples in the FIFO. - virtual void setGyroOffset(float x, float y, float z); //Look out, from measurements only - virtual void setGyroSlope(float x, float y, float z); + virtual void setGyroOffset(float x, float y, float z); //Look out, from measurements only + virtual void setGyroSlope(float x, float y, float z); virtual int setGyroODR(int8_t range); //Sampling Rate 0:off, 1:10Hz, 2:50Hz, 3:119Hz, 4:238Hz, 5:476Hz, 6:952Hz, 7:NA virtual float getGyroODR(); // Sampling rate of the sensor. virtual int setGyroBW(int8_t range); //Bandwidth setting 0,1,2,3 see documentation table 46 and 47 @@ -103,13 +103,13 @@ class LSM9DS1Class { virtual float getGyroFS(); // (output = 245.0, 500.0 , 1000.0, 2000.0) // Magnetometer - float magnetOffset[3] = {0,0,0}; // zero point offset correction factor for calibration - float magnetSlope[3] = {1,1,1}; // slope correction factor for calibration + float magnetOffset[3] = {0,0,0}; // zero point offset correction factor for calibration + float magnetSlope[3] = {1,1,1}; // slope correction factor for calibration float magnetUnit = MICROTESLA; // GAUSS or MICROTESLA virtual int readMagnet(float& x, float& y, float& z); // Default results are in uT (micro Tesla) virtual int magnetAvailable(); // Number of samples in the FIFO. - virtual void setMagnetOffset(float x, float y, float z); //Look out, from measurements only - virtual void setMagnetSlope(float x, float y, float z); + virtual void setMagnetOffset(float x, float y, float z); //Look out, from measurements only + virtual void setMagnetSlope(float x, float y, float z); virtual int setMagnetODR(int8_t range); // Sampling rate (0..7) corresponds to {0.625,1.25,2.5,5.0,10.0,20.0,40.0,80.0}Hz virtual float getMagnetODR(); // Sampling rate of the sensor in Hz. virtual int setMagnetFS(int8_t range); // 0=400.0; 1=800.0; 2=1200.0 , 3=1600.0 (µT) From 2c337981c2f3892ad634b4fbcbebb5c1f90c3715 Mon Sep 17 00:00:00 2001 From: Martin Hapl Date: Sun, 24 May 2020 22:36:51 +0200 Subject: [PATCH 05/15] Updated to remove bool deprecation messages For real --- src/LSM9DS1.cpp | 46 +++++++++++++++++++++++----------------------- 1 file changed, 23 insertions(+), 23 deletions(-) diff --git a/src/LSM9DS1.cpp b/src/LSM9DS1.cpp index d3595fb..49e2224 100644 --- a/src/LSM9DS1.cpp +++ b/src/LSM9DS1.cpp @@ -152,10 +152,10 @@ int LSM9DS1Class::accelAvailable() return 0; } -void LSM9DS1Class::setAccelOffset(float x, float y, float z) //Look out, from measurements only -{ accelOffset[0] = x /(accelUnit * accelSlope[0]); - accelOffset[1] = y /(accelUnit * accelSlope[1]); - accelOffset[2] = z /(accelUnit * accelSlope[2]); +void LSM9DS1Class::setAccelOffset(float x, float y, float z) +{ accelOffset[0] = x /(accelUnit * gyroSlope[0]); + accelOffset[1] = y /(accelUnit * gyroSlope[1]); + accelOffset[2] = z /(accelUnit * gyroSlope[2]); } void LSM9DS1Class::setAccelSlope(float x, float y, float z) @@ -166,8 +166,8 @@ void LSM9DS1Class::setAccelSlope(float x, float y, float z) int LSM9DS1Class::setAccelODR(int8_t range) //Sample Rate 0:off, 1:10Hz, 2:50Hz, 3:119Hz, 4:238Hz, 5:476Hz, 6:952Hz, 7:NA { if (range==7) range =0; - range = (range & B00000111) << 5; - uint8_t setting = ((readRegister(LSM9DS1_ADDRESS, LSM9DS1_CTRL_REG6_XL) & B00011111) | range); + range = (range & 0b00000111) << 5; + uint8_t setting = ((readRegister(LSM9DS1_ADDRESS, LSM9DS1_CTRL_REG6_XL) & 0b00011111) | range); return writeRegister(LSM9DS1_ADDRESS, LSM9DS1_CTRL_REG6_XL,setting) ; } float LSM9DS1Class::getAccelODR() @@ -177,9 +177,9 @@ float LSM9DS1Class::getAccelODR() } float LSM9DS1Class::setAccelBW(int8_t range) //0,1,2,3 Override autoBandwidth setting see doc.table 67 -{ range = range & B00000011; - uint8_t RegIs = readRegister(LSM9DS1_ADDRESS, LSM9DS1_CTRL_REG6_XL) & B11111000; - RegIs = RegIs | B00000100 | range ; +{ range = range & 0b00000011; + uint8_t RegIs = readRegister(LSM9DS1_ADDRESS, LSM9DS1_CTRL_REG6_XL) & 0b11111000; + RegIs = RegIs | 0b00000100 | range ; return writeRegister(LSM9DS1_ADDRESS, LSM9DS1_CTRL_REG6_XL,RegIs) ; } @@ -187,12 +187,12 @@ float LSM9DS1Class::getAccelBW() //Bandwidth setting 0,1,2,3 see documentation { float autoRange[] ={0.0, 408.0, 408.0, 50.0, 105.0, 211.0, 408.0, 0.0 }; float BWXLRange[] ={ 408.0, 211.0, 105.0, 50.0 }; uint8_t RegIs = readRegister(LSM9DS1_ADDRESS, LSM9DS1_CTRL_REG6_XL); - if (bitRead(2,RegIs)) return BWXLRange [RegIs & B00000011]; + if (bitRead(2,RegIs)) return BWXLRange [RegIs & 0b00000011]; else return autoRange [ RegIs >> 5 ]; } int LSM9DS1Class::setAccelFS(int8_t range) // 0: ±2g ; 1: ±16g ; 2: ±4g ; 3: ±8g -{ range = (range & B00000011) << 3; +{ range = (range & 0b00000011) << 3; uint8_t setting = ((readRegister(LSM9DS1_ADDRESS, LSM9DS1_CTRL_REG6_XL) & 0xE7) | range); return writeRegister(LSM9DS1_ADDRESS, LSM9DS1_CTRL_REG6_XL,setting) ; } @@ -228,7 +228,7 @@ int LSM9DS1Class::gyroAvailable() return 0; } -void LSM9DS1Class::setGyroOffset(float x, float y, float z) //Look out, from measurements only +void LSM9DS1Class::setGyroOffset(float x, float y, float z) { gyroOffset[0] = x /(gyroUnit * gyroSlope[0]); gyroOffset[1] = y /(gyroUnit * gyroSlope[1]); gyroOffset[2] = z /(gyroUnit * gyroSlope[2]); @@ -242,8 +242,8 @@ void LSM9DS1Class::setGyroSlope(float x, float y, float z) int LSM9DS1Class::setGyroODR(int8_t range) // 0:off, 1:10Hz, 2:50Hz, 3:119Hz, 4:238Hz, 5:476Hz, 6:952Hz, 7:NA { if (range==7) range =0; - range = (range & B00000111) << 5; - uint8_t setting = ((readRegister(LSM9DS1_ADDRESS, LSM9DS1_CTRL_REG1_G) & B00011111) | range); + range = (range & 0b00000111) << 5; + uint8_t setting = ((readRegister(LSM9DS1_ADDRESS, LSM9DS1_CTRL_REG1_G) & 0b00011111) | range); return writeRegister(LSM9DS1_ADDRESS, LSM9DS1_CTRL_REG1_G,setting) ; } @@ -254,8 +254,8 @@ float LSM9DS1Class::getGyroODR() } int LSM9DS1Class::setGyroBW(int8_t range) -{ range = range & B00000011; - uint8_t setting = readRegister(LSM9DS1_ADDRESS, LSM9DS1_CTRL_REG1_G) & B11111100; +{ range = range & 0b00000011; + uint8_t setting = readRegister(LSM9DS1_ADDRESS, LSM9DS1_CTRL_REG1_G) & 0b11111100; return writeRegister(LSM9DS1_ADDRESS, LSM9DS1_CTRL_REG1_G,setting | range) ; } @@ -274,12 +274,12 @@ float BWtable[ ODRrows ][ BWcols ] = // acc to float LSM9DS1Class::getGyroBW() { uint8_t setting = readRegister(LSM9DS1_ADDRESS, LSM9DS1_CTRL_REG1_G) ; uint8_t ODR = setting >> 5; - uint8_t BW = setting & B00000011; + uint8_t BW = setting & 0b00000011; return BWtable[ODR][BW]; } int LSM9DS1Class::setGyroFS(int8_t range) // (0: 245 dps; 1: 500 dps; 2: 1000 dps; 3: 2000 dps) -{ range = (range & B00000011) << 3; +{ range = (range & 0b00000011) << 3; uint8_t setting = ((readRegister(LSM9DS1_ADDRESS, LSM9DS1_CTRL_REG1_G) & 0xE7) | range ); return writeRegister(LSM9DS1_ADDRESS, LSM9DS1_CTRL_REG1_G,setting) ; } @@ -316,7 +316,7 @@ int LSM9DS1Class::magneticFieldAvailable() return 0; } -void LSM9DS1Class::setMagnetOffset(float x, float y, float z) //Look out, from measurements only +void LSM9DS1Class::setMagnetOffset(float x, float y, float z) { magnetOffset[0] = x /(magnetUnit * magnetSlope[0]); magnetOffset[1] = y /(magnetUnit * magnetSlope[1]); magnetOffset[2] = z /(magnetUnit * magnetSlope[2]); @@ -329,7 +329,7 @@ void LSM9DS1Class::setMagnetSlope(float x, float y, float z) } int LSM9DS1Class::setMagnetFS(int8_t range) // 0=400.0; 1=800.0; 2=1200.0 , 3=1600.0 (µT) -{ range = (range & B00000011) << 5; +{ range = (range & 0b00000011) << 5; return writeRegister(LSM9DS1_ADDRESS, LSM9DS1_CTRL_REG2_M,range) ; } @@ -340,14 +340,14 @@ float LSM9DS1Class::getMagnetFS() // } int LSM9DS1Class::setMagnetODR(int8_t range) // range (0..7) corresponds to {0.625,1.25,2.5,5.0,10.0,20.0,40.0,80.0}Hz -{ range = (range & B00000111) << 2; - uint8_t setting = ((readRegister(LSM9DS1_ADDRESS_M, LSM9DS1_CTRL_REG1_M) & B11100011) | range); +{ range = (range & 0b00000111) << 2; + uint8_t setting = ((readRegister(LSM9DS1_ADDRESS_M, LSM9DS1_CTRL_REG1_M) & 0b11100011) | range); return writeRegister(LSM9DS1_ADDRESS_M, LSM9DS1_CTRL_REG1_M,setting) ; } float LSM9DS1Class::getMagnetODR() // Output {0.625, 1.25, 2.5, 5.0, 10.0, 20.0, 40.0 , 80.0}; //Hz { const float ranges[] ={0.625, 1.25,2.5, 5.0, 10.0, 20.0, 40.0 , 80.0}; //Hz - uint8_t setting = (readRegister(LSM9DS1_ADDRESS_M, LSM9DS1_CTRL_REG1_M) & B00011100) >> 2; + uint8_t setting = (readRegister(LSM9DS1_ADDRESS_M, LSM9DS1_CTRL_REG1_M) & 0b00011100) >> 2; return ranges[setting]; } From 183667e3baa3fa17fce1a99bac46c787e369e48d Mon Sep 17 00:00:00 2001 From: FemmeVerbeek Date: Tue, 26 May 2020 23:56:59 +0200 Subject: [PATCH 06/15] Added comments RPM RPS Added comments constants REVSPERSECOND REVSPERMINUTE setAccel bug --- CHANGELOG | 8 ++++-- src/LSM9DS1.cpp | 66 +++++++++++++++++++++++++++---------------------- src/LSM9DS1.h | 44 +++++++++++++++++---------------- 3 files changed, 65 insertions(+), 53 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index b754b58..e822191 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -10,5 +10,9 @@ Arduino_LSM9DS1 1.1.0 - 2020.02.11 Arduino_LSM9DS1 2.0.0 - 2020.05.15 -* Offset, Full scale, sample rate on all DOF. -* Calibration parameters integrated \ No newline at end of file +* Added support for Full scale setting, +* Added support for ODR sample rate, +* Added support for Band width +* Added support for changing output unit +* Added support for separate or combined sensor calibration +* Calibration parameters are dimensionless, independent of each other and of the other settings diff --git a/src/LSM9DS1.cpp b/src/LSM9DS1.cpp index 49e2224..cc996fe 100644 --- a/src/LSM9DS1.cpp +++ b/src/LSM9DS1.cpp @@ -43,13 +43,6 @@ #define LSM9DS1_STATUS_REG_M 0x27 #define LSM9DS1_OUT_X_L_M 0x28 -// Add these right after defines at the beginning -#define LSM9DS1_OFFSET_X_REG_L_M 0x05 -#define LSM9DS1_OFFSET_X_REG_H_M 0x06 -#define LSM9DS1_OFFSET_Y_REG_L_M 0x07 -#define LSM9DS1_OFFSET_Y_REG_H_M 0x08 -#define LSM9DS1_OFFSET_Z_REG_L_M 0x09 -#define LSM9DS1_OFFSET_Z_REG_H_M 0x0A LSM9DS1Class::LSM9DS1Class(TwoWire& wire) : continuousMode(false), _wire(&wire) @@ -152,21 +145,26 @@ int LSM9DS1Class::accelAvailable() return 0; } +//Store zero-point calibration measurement as offset, +//Dimension analysis: +//The measurement is stripped from it's unit and sensitivity it was measured with. +//This enables independent calibration and changing the unit later +//In a combined calibration this value must be set before setting the Slope void LSM9DS1Class::setAccelOffset(float x, float y, float z) -{ accelOffset[0] = x /(accelUnit * gyroSlope[0]); - accelOffset[1] = y /(accelUnit * gyroSlope[1]); - accelOffset[2] = z /(accelUnit * gyroSlope[2]); +{ accelOffset[0] = x /(accelUnit * accelSlope[0]); + accelOffset[1] = y /(accelUnit * accelSlope[1]); + accelOffset[2] = z /(accelUnit * accelSlope[2]); } - +//Slope is already dimensionless, so it can be stored as is. void LSM9DS1Class::setAccelSlope(float x, float y, float z) { accelSlope[0] = x ; accelSlope[1] = y ; accelSlope[2] = z ; } -int LSM9DS1Class::setAccelODR(int8_t range) //Sample Rate 0:off, 1:10Hz, 2:50Hz, 3:119Hz, 4:238Hz, 5:476Hz, 6:952Hz, 7:NA -{ if (range==7) range =0; - range = (range & 0b00000111) << 5; +int LSM9DS1Class::setAccelODR(uint8_t range) //Sample Rate 0:off, 1:10Hz, 2:50Hz, 3:119Hz, 4:238Hz, 5:476Hz, 6:952Hz, 7:NA +{ range = range << 5; + if (range==0b11100000) range =0; uint8_t setting = ((readRegister(LSM9DS1_ADDRESS, LSM9DS1_CTRL_REG6_XL) & 0b00011111) | range); return writeRegister(LSM9DS1_ADDRESS, LSM9DS1_CTRL_REG6_XL,setting) ; } @@ -176,7 +174,7 @@ float LSM9DS1Class::getAccelODR() return Ranges [setting]; } -float LSM9DS1Class::setAccelBW(int8_t range) //0,1,2,3 Override autoBandwidth setting see doc.table 67 +float LSM9DS1Class::setAccelBW(uint8_t range) //0,1,2,3 Override autoBandwidth setting see doc.table 67 { range = range & 0b00000011; uint8_t RegIs = readRegister(LSM9DS1_ADDRESS, LSM9DS1_CTRL_REG6_XL) & 0b11111000; RegIs = RegIs | 0b00000100 | range ; @@ -191,7 +189,7 @@ float LSM9DS1Class::getAccelBW() //Bandwidth setting 0,1,2,3 see documentation else return autoRange [ RegIs >> 5 ]; } -int LSM9DS1Class::setAccelFS(int8_t range) // 0: ±2g ; 1: ±16g ; 2: ±4g ; 3: ±8g +int LSM9DS1Class::setAccelFS(uint8_t range) // 0: ±2g ; 1: ±16g ; 2: ±4g ; 3: ±8g { range = (range & 0b00000011) << 3; uint8_t setting = ((readRegister(LSM9DS1_ADDRESS, LSM9DS1_CTRL_REG6_XL) & 0xE7) | range); return writeRegister(LSM9DS1_ADDRESS, LSM9DS1_CTRL_REG6_XL,setting) ; @@ -227,22 +225,26 @@ int LSM9DS1Class::gyroAvailable() } return 0; } - +//Store zero-point calibration measurement as offset, +//Dimension analysis: +//The measurement is stripped from it's unit and sensitivity it was measured with. +//This enables independent calibration and changing the unit later +//In a combined calibration this value must be set before setting the Slope void LSM9DS1Class::setGyroOffset(float x, float y, float z) -{ gyroOffset[0] = x /(gyroUnit * gyroSlope[0]); +{ gyroOffset[0] = x /(gyroUnit * gyroSlope[0]); gyroOffset[1] = y /(gyroUnit * gyroSlope[1]); gyroOffset[2] = z /(gyroUnit * gyroSlope[2]); } - +//Slope is already dimensionless, so it can be stored as is. void LSM9DS1Class::setGyroSlope(float x, float y, float z) { gyroSlope[0] = x ; gyroSlope[1] = y ; gyroSlope[2] = z ; } -int LSM9DS1Class::setGyroODR(int8_t range) // 0:off, 1:10Hz, 2:50Hz, 3:119Hz, 4:238Hz, 5:476Hz, 6:952Hz, 7:NA -{ if (range==7) range =0; - range = (range & 0b00000111) << 5; +int LSM9DS1Class::setGyroODR(uint8_t range) // 0:off, 1:10Hz, 2:50Hz, 3:119Hz, 4:238Hz, 5:476Hz, 6:952Hz, 7:NA +{ range = range << 5; + if (range==0b11100000) range =0; uint8_t setting = ((readRegister(LSM9DS1_ADDRESS, LSM9DS1_CTRL_REG1_G) & 0b00011111) | range); return writeRegister(LSM9DS1_ADDRESS, LSM9DS1_CTRL_REG1_G,setting) ; } @@ -253,7 +255,7 @@ float LSM9DS1Class::getGyroODR() return Ranges [setting]; // return 119.0F; } -int LSM9DS1Class::setGyroBW(int8_t range) +int LSM9DS1Class::setGyroBW(uint8_t range) { range = range & 0b00000011; uint8_t setting = readRegister(LSM9DS1_ADDRESS, LSM9DS1_CTRL_REG1_G) & 0b11111100; return writeRegister(LSM9DS1_ADDRESS, LSM9DS1_CTRL_REG1_G,setting | range) ; @@ -261,7 +263,7 @@ int LSM9DS1Class::setGyroBW(int8_t range) #define ODRrows 8 #define BWcols 4 -float BWtable[ ODRrows ][ BWcols ] = // acc to +float BWtable[ ODRrows ][ BWcols ] = // acc to table 47 dataheet { { 0, 0, 0, 0 }, { 0, 0, 0, 0 }, { 16, 16, 16, 16 }, @@ -278,7 +280,7 @@ float LSM9DS1Class::getGyroBW() return BWtable[ODR][BW]; } -int LSM9DS1Class::setGyroFS(int8_t range) // (0: 245 dps; 1: 500 dps; 2: 1000 dps; 3: 2000 dps) +int LSM9DS1Class::setGyroFS(uint8_t range) // (0: 245 dps; 1: 500 dps; 2: 1000 dps; 3: 2000 dps) { range = (range & 0b00000011) << 3; uint8_t setting = ((readRegister(LSM9DS1_ADDRESS, LSM9DS1_CTRL_REG1_G) & 0xE7) | range ); return writeRegister(LSM9DS1_ADDRESS, LSM9DS1_CTRL_REG1_G,setting) ; @@ -315,20 +317,24 @@ int LSM9DS1Class::magneticFieldAvailable() } return 0; } - +//Store zero-point calibration measurement as offset, +//Dimension analysis: +//The measurement is stripped from it's unit and sensitivity it was measured with. +//This enables independent calibration and changing the unit later +//In a combined calibration this value must be set before setting the Slope void LSM9DS1Class::setMagnetOffset(float x, float y, float z) -{ magnetOffset[0] = x /(magnetUnit * magnetSlope[0]); +{ magnetOffset[0] = x /(magnetUnit * magnetSlope[0]); magnetOffset[1] = y /(magnetUnit * magnetSlope[1]); magnetOffset[2] = z /(magnetUnit * magnetSlope[2]); } - +//Slope is already dimensionless, so it can be stored as is. void LSM9DS1Class::setMagnetSlope(float x, float y, float z) { magnetSlope[0] = x ; magnetSlope[1] = y ; magnetSlope[2] = z ; } -int LSM9DS1Class::setMagnetFS(int8_t range) // 0=400.0; 1=800.0; 2=1200.0 , 3=1600.0 (µT) +int LSM9DS1Class::setMagnetFS(uint8_t range) // 0=400.0; 1=800.0; 2=1200.0 , 3=1600.0 (µT) { range = (range & 0b00000011) << 5; return writeRegister(LSM9DS1_ADDRESS, LSM9DS1_CTRL_REG2_M,range) ; } @@ -339,7 +345,7 @@ float LSM9DS1Class::getMagnetFS() // return Ranges[setting] ; } -int LSM9DS1Class::setMagnetODR(int8_t range) // range (0..7) corresponds to {0.625,1.25,2.5,5.0,10.0,20.0,40.0,80.0}Hz +int LSM9DS1Class::setMagnetODR(uint8_t range) // range (0..7) corresponds to {0.625,1.25,2.5,5.0,10.0,20.0,40.0,80.0}Hz { range = (range & 0b00000111) << 2; uint8_t setting = ((readRegister(LSM9DS1_ADDRESS_M, LSM9DS1_CTRL_REG1_M) & 0b11100011) | range); return writeRegister(LSM9DS1_ADDRESS_M, LSM9DS1_CTRL_REG1_M,setting) ; diff --git a/src/LSM9DS1.h b/src/LSM9DS1.h index e30f538..b5a3f26 100644 --- a/src/LSM9DS1.h +++ b/src/LSM9DS1.h @@ -58,6 +58,8 @@ #define METERPERSECOND2 9.81 #define DEGREEPERSECOND 1.0 //default #define RADIANSPERSECOND 3.141592654/180 +#define REVSPERMINUTE 60.0/360.0 +#define REVSPERSECOND 1.0/360.0 class LSM9DS1Class { public: @@ -74,45 +76,45 @@ class LSM9DS1Class { // Accelerometer float accelOffset[3] = {0,0,0}; // zero point offset correction factor for calibration - float accelSlope[3] = {1,1,1}; // slope correction factor for calibration - float accelUnit = GRAVITY; // GRAVITY OR METERPERSECOND2 + float accelSlope[3] = {1,1,1}; // slope correction factor for calibration + float accelUnit = GRAVITY; // GRAVITY OR METERPERSECOND2 virtual int readAccel(float& x, float& y, float& z); // Results are in G (earth gravity) or m/s2. virtual int accelAvailable(); // Number of samples in the FIFO. - virtual void setAccelOffset(float x, float y, float z); //Look out, from measurements only - virtual void setAccelSlope(float x, float y, float z); - virtual int setAccelODR(int8_t range); // Sample Rate 0:off, 1:10Hz, 2:50Hz, 3:119Hz, 4:238Hz, 5:476Hz, 6:952Hz, 7:NA Automatic setting of BW + virtual void setAccelOffset(float x, float y, float z); //Store zero-point measurements as offset + virtual void setAccelSlope(float x, float y, float z); //Store measurements as slope + virtual int setAccelODR(uint8_t range); // Sample Rate 0:off, 1:10Hz, 2:50Hz, 3:119Hz, 4:238Hz, 5:476Hz, 6:952Hz, 7:NA Automatic setting of BW virtual float getAccelODR(); // Sample Rate of the sensor. - virtual float setAccelBW(int8_t range); //0,1,2,3 Override autoBandwidth setting see doc.table 67 + virtual float setAccelBW(uint8_t range); //0,1,2,3 Override autoBandwidth setting see doc.table 67 virtual float getAccelBW(); //Bandwidth setting 0,1,2,3 see documentation table 67 - virtual int setAccelFS(int8_t range); // 0: ±2g ; 1: ±16g ; 2: ±4g ; 3: ±8g + virtual int setAccelFS(uint8_t range); // 0: ±2g ; 1: ±16g ; 2: ±4g ; 3: ±8g virtual float getAccelFS(); // Full Scale setting (output = 2.0, 16.0 , 4.0 , 8.0) // Gyroscope - float gyroOffset[3] = {0,0,0}; // zero point offset correction factor for calibration - float gyroSlope[3] = {1,1,1}; // slope correction factor for calibration - float gyroUnit = DEGREEPERSECOND; // DEGREEPERSECOND or RADIANSPERSECOND + float gyroOffset[3] = {0,0,0}; // zero point offset correction factor for calibration + float gyroSlope[3] = {1,1,1}; // slope correction factor for calibration + float gyroUnit = DEGREEPERSECOND; // DEGREEPERSECOND RADIANSPERSECOND REVSPERMINUTE REVSPERSECOND virtual int readGyro(float& x, float& y, float& z); // Results are in degrees/second or rad/s. virtual int gyroAvailable(); // Number of samples in the FIFO. - virtual void setGyroOffset(float x, float y, float z); //Look out, from measurements only - virtual void setGyroSlope(float x, float y, float z); - virtual int setGyroODR(int8_t range); //Sampling Rate 0:off, 1:10Hz, 2:50Hz, 3:119Hz, 4:238Hz, 5:476Hz, 6:952Hz, 7:NA + virtual void setGyroOffset(float x, float y, float z); //Store zero-point measurements as offset + virtual void setGyroSlope(float x, float y, float z); //Store measurements as slope + virtual int setGyroODR(uint8_t range); //Sampling Rate 0:off, 1:10Hz, 2:50Hz, 3:119Hz, 4:238Hz, 5:476Hz, 6:952Hz, 7:NA virtual float getGyroODR(); // Sampling rate of the sensor. - virtual int setGyroBW(int8_t range); //Bandwidth setting 0,1,2,3 see documentation table 46 and 47 + virtual int setGyroBW(uint8_t range); //Bandwidth setting 0,1,2,3 see documentation table 46 and 47 virtual float getGyroBW(); //Bandwidth setting 0,1,2,3 see documentation table 46 and 47 - virtual int setGyroFS(int8_t range); // (0= ±245 dps; 1= ±500 dps; 2= ±1000 dps; 3= ±2000 dps) + virtual int setGyroFS(uint8_t range); // (0= ±245 dps; 1= ±500 dps; 2= ±1000 dps; 3= ±2000 dps) virtual float getGyroFS(); // (output = 245.0, 500.0 , 1000.0, 2000.0) // Magnetometer - float magnetOffset[3] = {0,0,0}; // zero point offset correction factor for calibration - float magnetSlope[3] = {1,1,1}; // slope correction factor for calibration + float magnetOffset[3] = {0,0,0}; // zero point offset correction factor for calibration + float magnetSlope[3] = {1,1,1}; // slope correction factor for calibration float magnetUnit = MICROTESLA; // GAUSS or MICROTESLA virtual int readMagnet(float& x, float& y, float& z); // Default results are in uT (micro Tesla) virtual int magnetAvailable(); // Number of samples in the FIFO. - virtual void setMagnetOffset(float x, float y, float z); //Look out, from measurements only - virtual void setMagnetSlope(float x, float y, float z); - virtual int setMagnetODR(int8_t range); // Sampling rate (0..7) corresponds to {0.625,1.25,2.5,5.0,10.0,20.0,40.0,80.0}Hz + virtual void setMagnetOffset(float x, float y, float z); //Store zero-point measurements as offset + virtual void setMagnetSlope(float x, float y, float z); //Store measurements as slope + virtual int setMagnetODR(uint8_t range); // Sampling rate (0..7) corresponds to {0.625,1.25,2.5,5.0,10.0,20.0,40.0,80.0}Hz virtual float getMagnetODR(); // Sampling rate of the sensor in Hz. - virtual int setMagnetFS(int8_t range); // 0=400.0; 1=800.0; 2=1200.0 , 3=1600.0 (µT) + virtual int setMagnetFS(uint8_t range); // 0=400.0; 1=800.0; 2=1200.0 , 3=1600.0 (µT) virtual float getMagnetFS(); // get chip's full scale setting private: From e5d63f6e87ee7832bedcbb4bcb4f46cc5f96e2ee Mon Sep 17 00:00:00 2001 From: FemmeVerbeek <65541097+FemmeVerbeek@users.noreply.github.com> Date: Wed, 27 May 2020 20:26:32 +0200 Subject: [PATCH 07/15] Update README.adoc --- README.adoc | 1 + 1 file changed, 1 insertion(+) diff --git a/README.adoc b/README.adoc index 579fd6c..aaceb3a 100644 --- a/README.adoc +++ b/README.adoc @@ -3,6 +3,7 @@ image:https://github.com/arduino-libraries/Arduino_LSM9DS1/workflows/Compile%20Examples/badge.svg["Compile Examples Status", link="https://github.com/arduino-libraries/Arduino_LSM9DS1/actions?workflow=Compile+Examples"] image:https://github.com/arduino-libraries/Arduino_LSM9DS1/workflows/Spell%20Check/badge.svg["Spell Check Status", link="https://github.com/arduino-libraries/Arduino_LSM9DS1/actions?workflow=Spell+Check"] Allows you to read the accelerometer, magnetometer and gyroscope values from the LSM9DS1 IMU on your Arduino Nano 33 BLE Sense. +For more accurate measurements the sensor must be calibrated first. == License == From d337259a6ca342d3a14c2378b1afff545eb42881 Mon Sep 17 00:00:00 2001 From: FemmeVerbeek <65541097+FemmeVerbeek@users.noreply.github.com> Date: Thu, 28 May 2020 01:08:11 +0200 Subject: [PATCH 08/15] Update CHANGELOG --- CHANGELOG | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/CHANGELOG b/CHANGELOG index e822191..9b4867c 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -14,5 +14,6 @@ Arduino_LSM9DS1 2.0.0 - 2020.05.15 * Added support for ODR sample rate, * Added support for Band width * Added support for changing output unit -* Added support for separate or combined sensor calibration +* Added support for sensor calibration, separate or combined measurement of slope and offset * Calibration parameters are dimensionless, independent of each other and of the other settings +* Added calibration examples, notes and calibration manual From 703caa02e6bf96e17299d710e834c144a3db7fbf Mon Sep 17 00:00:00 2001 From: FemmeVerbeek Date: Sun, 31 May 2020 22:49:05 +0200 Subject: [PATCH 09/15] Operational mode, calibrated ODR modes are Off, Accel only, Accel + Gyro Set...ODR measures the actual ODR get...ODR returns the measured value --- CHANGELOG | 8 +- .../LSM9DS1_RegisterTest.ino | 64 +++++++--- .../LSM9DS1_calibrate_gyro_offset.ino | 18 ++- keywords.txt | 2 + src/LSM9DS1.cpp | 113 +++++++++++++++--- src/LSM9DS1.h | 39 +++--- 6 files changed, 181 insertions(+), 63 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index 9b4867c..d3f92a1 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -8,12 +8,12 @@ Arduino_LSM9DS1 1.1.0 - 2020.02.11 * Added support for FIFO continuous reading of values -Arduino_LSM9DS1 2.0.0 - 2020.05.15 +Arduino_LSM9DS1 2.0.0 - 2020.05.30 * Added support for Full scale setting, -* Added support for ODR sample rate, +* Added support for Operational mode: off, Accel only, Gyro + Accel +* Added support for ODR sample rate, ODR values are automatically calibrated * Added support for Band width * Added support for changing output unit -* Added support for sensor calibration, separate or combined measurement of slope and offset +* Added support for separate or combined sensor calibration * Calibration parameters are dimensionless, independent of each other and of the other settings -* Added calibration examples, notes and calibration manual diff --git a/examples/LSM9DS1_RegisterTest/LSM9DS1_RegisterTest.ino b/examples/LSM9DS1_RegisterTest/LSM9DS1_RegisterTest.ino index ddbeb38..e244ed2 100644 --- a/examples/LSM9DS1_RegisterTest/LSM9DS1_RegisterTest.ino +++ b/examples/LSM9DS1_RegisterTest/LSM9DS1_RegisterTest.ino @@ -28,32 +28,58 @@ void setup() { printResult ("magnetic range param = ", i ,IMU.getMagnetFS()," µT "); else Serial.println ("failed setting magnetic field scale value "); } - for (int i = 0;i<=7;i++){ - if (IMU.setAccelODR(i)) + Serial.println("Op mode "+String(IMU.getOperationalMode())); + IMU.setGyroODR(0); + Serial.println("setGyroODR(0) Op mode "+String(IMU.getOperationalMode())); + IMU.setAccelODR(0); + Serial.println("setAccelODR(0) Op mode "+String(IMU.getOperationalMode())); + IMU.setGyroODR(3); + Serial.println("setGyroODR(3) Op mode "+String(IMU.getOperationalMode())); + + Serial.println(" setGyroODR result "); + for (int i=0;i<=7;i++) + { if (IMU.setGyroODR(i)==0) Serial.println("Gyro settting outof range "+String(i)); + else printODRData(i); + } + Serial.println(" setAccelODR result "); + for (int i=0;i<=7;i++) + { if (IMU.setAccelODR(i)==0) Serial.println("Accel settting outof range "+String(i)); + else printODRData(i); + } + Serial.println("Switch off Gyro"); + IMU.setGyroODR(0); //switch off gyro + for (int i=0;i<=7;i++) + { if (IMU.setAccelODR(i)==0) Serial.println("Accel settting outof range "+String(i)); + else printODRData(i); + } + + for (int i = 0;i<=7;i++){ + if (IMU.setMagnetODR(i)) + printResult ("magnetic field sample rate param = ", i , IMU.getMagnetODR()," Hz "); + else Serial.println ("failed setting magnetic field sample rate ");} + + for (int i = 0;i<=7;i++) + { if (IMU.setAccelODR(i)) { printResult ("accelleration sample rate param = ", i , IMU.getAccelODR()," Hz "); - // printResult ("Gyroscope sample rate param = ", i , IMU.getGyroODR()," Hz "); Serial.println(" automatic bandwidth setting (Hz) "+ String (IMU.getAccelBW())); for (int j = 0;j<=3;j++) { IMU.setAccelBW(j); // override automatic bandwith printResult("Accel bandwidth override ", j ,IMU.getAccelBW(), "Hz " ); } } - else Serial.println ("failed setting accelleration sample rate ");} - - for (int i = 0;i<=7;i++){ - if (IMU.setGyroODR(i)){ - printResult ("gyroscope sample rate param = ", i , IMU.getGyroODR()," Hz" ); + else Serial.println ("failed setting accelleration sample rate "); + } + for (int i = 0;i<=7;i++) + { if (IMU.setGyroODR(i)){ + printResult ("gyroscope sample rate param = ", i , IMU.getGyroODR()," Hz" ); for (int j = 0;j<=3;j++) { IMU.setGyroBW(j); // override automatic bandwith printResult("Gyro bandwidth setting ", j ,IMU.getGyroBW(), "Hz " ); } } - else Serial.println ("failed setting gyroscope sample rate "); } - - for (int i = 0;i<=7;i++){ - if (IMU.setMagnetODR(i)) - printResult ("magnetic field sample rate param = ", i , IMU.getMagnetODR()," Hz "); - else Serial.println ("failed setting magnetic field sample rate ");} + else Serial.println ("failed setting gyroscope sample rate "); + } + } void loop() { @@ -62,7 +88,13 @@ void loop() { void printResult (String msg, int nr,float value, String dimension) { Serial.print (msg+String(nr)); - // Serial.print (nr); Serial.print(" setting "+String(value)); - // Serial.print(value); Serial.println(dimension);} + +void printODRData(int i) +{ Serial.print("Settting "+String(i)); + Serial.print(" Op mode "+String(IMU.getOperationalMode())); + Serial.print(" ODR Gyro "+String( IMU.getGyroODR(),3 ) ); + Serial.print("Hz Accel "+String( IMU.getAccelODR(),3 ) ); + Serial.println("Hz"); +} diff --git a/examples/LSM9DS1_calibrate_gyro_offset/LSM9DS1_calibrate_gyro_offset.ino b/examples/LSM9DS1_calibrate_gyro_offset/LSM9DS1_calibrate_gyro_offset.ino index 60ca0cc..6c37b0a 100644 --- a/examples/LSM9DS1_calibrate_gyro_offset/LSM9DS1_calibrate_gyro_offset.ino +++ b/examples/LSM9DS1_calibrate_gyro_offset/LSM9DS1_calibrate_gyro_offset.ino @@ -20,13 +20,16 @@ const int averageNSamples=10; //average output over N measurements //unsigned long timer; void setup() { Serial.begin(115200); + IMU.gyroOffset[0]=0; + IMU.gyroOffset[1]=0; + IMU.gyroOffset[2]=0; + while(!Serial); delay(1); if (!IMU.begin()) { Serial.println("Failed to initialize IMU!"); while (1); } IMU.setGyroODR(4); //Sampling Rate 0:off, 1:10Hz, 2:50Hz, 3:119Hz, 4:238Hz, 5:476Hz, 6:952Hz, 7:NA - IMU.setGyroBW(0); // bandwidth see table 47 datasheet Serial.print("Gyro ODR "+String( IMU.getGyroODR() ) ); Serial.println(" BW setting "+String( IMU.getGyroBW() ) ); Serial.println("Calibrating. Just a moment. "); @@ -35,10 +38,13 @@ void setup() calibrateGyroOffset(12000); // do calibration measurements during 12000 ms. Serial.println("calibration results"); - Serial.print("Content of IMU.gyroOffset : "); - for (int i= 0; i<=2 ; i++) {Serial.print(IMU.gyroOffset[i],6);Serial.print(" ");} - Serial.println(); - Serial.println("Press enter to start mesuring"); + Serial.println("Content of IMU.gyroOffset "); + for (int i= 0; i<=2 ; i++) + { Serial.print("IMU.gyroOffset["+String(i)); + Serial.print("]= "+String(IMU.gyroOffset[i],6)); + Serial.println(";"); + } + Serial.println("Press enter to start calibrated measuring"); Serial.println("To see a graph of the measurements, close this serial monitor, open the serial plotter type any character and click the send button"); while (!Serial.available()); // pause the program, enter continues while (Serial.available()) Serial.read(); // clear the read buffer @@ -68,9 +74,9 @@ float x, y, z, addX=0, addY=0, addZ=0 ; count++; addX += x; addY += y; addZ += z; digitalWrite(LED_BUILTIN, (millis()/125)%2); // blink onboard led every 250ms + if ((count%100)==0)Serial.print('.'); } } IMU.setGyroOffset(addX/count, addY/count, addZ/count); // Store the average measurements as offset digitalWrite(LED_BUILTIN, 0); // onboard led off - Serial.println("nr of samples "+String(count)); } diff --git a/keywords.txt b/keywords.txt index 618e062..97d9cca 100644 --- a/keywords.txt +++ b/keywords.txt @@ -16,6 +16,8 @@ begin KEYWORD2 end KEYWORD2 setContinuousMode KEYWORD2 setOneShotMode KEYWORD2 +getOperationalMode KEYWORD2 +measureAccelGyroODR KEYWORD2 readAcceleration KEYWORD2 readGyroscope KEYWORD2 diff --git a/src/LSM9DS1.cpp b/src/LSM9DS1.cpp index cc996fe..f418a08 100644 --- a/src/LSM9DS1.cpp +++ b/src/LSM9DS1.cpp @@ -81,7 +81,7 @@ int LSM9DS1Class::begin() writeRegister(LSM9DS1_ADDRESS_M, LSM9DS1_CTRL_REG1_M, 0xb4); // Temperature compensation enable, medium performance, 20 Hz writeRegister(LSM9DS1_ADDRESS_M, LSM9DS1_CTRL_REG2_M, 0x00); // 4 Gauss writeRegister(LSM9DS1_ADDRESS_M, LSM9DS1_CTRL_REG3_M, 0x00); // Continuous conversion mode - + setGyroODR(3); return 1; } @@ -112,6 +112,31 @@ void LSM9DS1Class::end() _wire->end(); } +float LSM9DS1Class::measureAccelGyroODR(unsigned int duration) +{ if (getOperationalMode()==0) return 0; + float x, y, z; //dummies + unsigned long lastEventTime, count = 0; + duration *=1000; //switch to micros + while (count<2) //throw away nr of samples + { if (IMU.accelAvailable()) + { IMU.readAccel(x, y, z); // empty read buffer + count++; + } + } + count=0; + unsigned long start = micros(); + while ((micros()- start) < duration) // measure + { if (IMU.accelAvailable()) + { IMU.readAccel(x, y, z); + count++; + lastEventTime = micros(); + } + } +// Serial.print(" Count "+String( count ) ); + return (1000000.0*float(count)/float(lastEventTime-start) ); +} + + //************************************ Accelleration ***************************************** int LSM9DS1Class::readAccel(float& x, float& y, float& z) @@ -162,16 +187,36 @@ void LSM9DS1Class::setAccelSlope(float x, float y, float z) accelSlope[2] = z ; } -int LSM9DS1Class::setAccelODR(uint8_t range) //Sample Rate 0:off, 1:10Hz, 2:50Hz, 3:119Hz, 4:238Hz, 5:476Hz, 6:952Hz, 7:NA -{ range = range << 5; - if (range==0b11100000) range =0; - uint8_t setting = ((readRegister(LSM9DS1_ADDRESS, LSM9DS1_CTRL_REG6_XL) & 0b00011111) | range); - return writeRegister(LSM9DS1_ADDRESS, LSM9DS1_CTRL_REG6_XL,setting) ; -} +// range 0: switch off Accel and Gyro write in CTRL_REG6_XL; +// range !=0: switch on Accel: write range in CTRL_REG6_XL ; +// Operational mode Accel + Gyro: write setting in CTRL_REG1_G, shared ODR +int LSM9DS1Class::setAccelODR(uint8_t range) //Sample Rate 0:off, 1:10Hz, 2:50Hz, 3:119Hz, 4:238Hz, 5:476Hz, 6:952Hz +{ if (range >= 7) return 0; + uint8_t setting = ((readRegister(LSM9DS1_ADDRESS, LSM9DS1_CTRL_REG6_XL) & 0b00011111) | (range << 5)); + if (writeRegister(LSM9DS1_ADDRESS, LSM9DS1_CTRL_REG6_XL,setting)==0) return 0; + switch (getOperationalMode()) { + case 0 : { accelODR=0; + gyroODR=0; + break; + } + case 1 : { accelODR= measureAccelGyroODR(350); + gyroODR = 0; + break; + } + case 2 : { setting = ((readRegister(LSM9DS1_ADDRESS, LSM9DS1_CTRL_REG1_G) & 0b00011111) | (range << 5) ); + writeRegister(LSM9DS1_ADDRESS, LSM9DS1_CTRL_REG1_G,setting) ; + accelODR= measureAccelGyroODR(350); + gyroODR = accelODR; + } + } + return 1; +} + float LSM9DS1Class::getAccelODR() -{ float Ranges[] ={0.0, 10.0, 50.0, 119.0, 238.0, 476.0, 952.0, 0.0 }; - uint8_t setting = readRegister(LSM9DS1_ADDRESS, LSM9DS1_CTRL_REG6_XL) >> 5; - return Ranges [setting]; +{ return accelODR; +// float Ranges[] ={0.0, 10.0, 50.0, 119.0, 238.0, 476.0, 952.0, 0.0 }; +// uint8_t setting = readRegister(LSM9DS1_ADDRESS, LSM9DS1_CTRL_REG6_XL) >> 5; +// return Ranges [setting]; } float LSM9DS1Class::setAccelBW(uint8_t range) //0,1,2,3 Override autoBandwidth setting see doc.table 67 @@ -241,18 +286,48 @@ void LSM9DS1Class::setGyroSlope(float x, float y, float z) gyroSlope[1] = y ; gyroSlope[2] = z ; } - -int LSM9DS1Class::setGyroODR(uint8_t range) // 0:off, 1:10Hz, 2:50Hz, 3:119Hz, 4:238Hz, 5:476Hz, 6:952Hz, 7:NA -{ range = range << 5; - if (range==0b11100000) range =0; - uint8_t setting = ((readRegister(LSM9DS1_ADDRESS, LSM9DS1_CTRL_REG1_G) & 0b00011111) | range); - return writeRegister(LSM9DS1_ADDRESS, LSM9DS1_CTRL_REG1_G,setting) ; + +int LSM9DS1Class::getOperationalMode() //0=off , 1= Accel only , 2= Gyro +Accel +{ + if ((readRegister(LSM9DS1_ADDRESS, LSM9DS1_CTRL_REG6_XL) & 0b11100000) ==0 ) return 0; + if ((readRegister(LSM9DS1_ADDRESS, LSM9DS1_CTRL_REG1_G) & 0b11100000) ==0 ) return 1; + else return 2; +} + + + +// range ==0 : switch off gyroscope - write 0 in CTRL_REG1_G; +// range !0 : switch on Accel+Gyro mode- write in CTRL_REG6_XL and CTRL_REG1_G; + +int LSM9DS1Class::setGyroODR(uint8_t range) // 0:off, 1:10Hz, 2:50Hz, 3:119Hz, 4:238Hz, 5:476Hz, 6:952Hz +{ if (range >= 7) return 0; + uint8_t setting = ((readRegister(LSM9DS1_ADDRESS, LSM9DS1_CTRL_REG1_G) & 0b00011111) | (range << 5 ) ); + writeRegister(LSM9DS1_ADDRESS, LSM9DS1_CTRL_REG1_G,setting); + if (range > 0 ) + { setting = ((readRegister(LSM9DS1_ADDRESS, LSM9DS1_CTRL_REG6_XL) & 0b00011111) | (range << 5)); + writeRegister(LSM9DS1_ADDRESS, LSM9DS1_CTRL_REG6_XL,setting); + } + switch (getOperationalMode()) { + case 0: { accelODR=0; //off + gyroODR=0; + break; + } + case 1: { accelODR= measureAccelGyroODR(350); //accelerometer only + gyroODR = 0; + break; + } + case 2: { accelODR= measureAccelGyroODR(350); //shared ODR + gyroODR = accelODR; + } + } + return 1; } float LSM9DS1Class::getGyroODR() -{ float Ranges[] ={0.0, 10.0, 50.0, 119.0, 238.0, 476.0, 952.0, 0.0 }; //Hz - uint8_t setting = readRegister(LSM9DS1_ADDRESS, LSM9DS1_CTRL_REG1_G) >> 5; - return Ranges [setting]; // return 119.0F; +{ return gyroODR; +// float Ranges[] ={0.0, 10.0, 50.0, 119.0, 238.0, 476.0, 952.0, 0.0 }; //Hz +// uint8_t setting = readRegister(LSM9DS1_ADDRESS, LSM9DS1_CTRL_REG1_G) >> 5; +// return Ranges [setting]; // used to be return 119.0F; } int LSM9DS1Class::setGyroBW(uint8_t range) diff --git a/src/LSM9DS1.h b/src/LSM9DS1.h index b5a3f26..753a0e8 100644 --- a/src/LSM9DS1.h +++ b/src/LSM9DS1.h @@ -73,45 +73,48 @@ class LSM9DS1Class { // Defaults to one-shot. void setContinuousMode(); void setOneShotMode(); - + int getOperationalMode(); //0=off , 1= Accel only , 2= Gyro +Accel + float measureAccelGyroODR(unsigned int duration); // Accelerometer float accelOffset[3] = {0,0,0}; // zero point offset correction factor for calibration - float accelSlope[3] = {1,1,1}; // slope correction factor for calibration - float accelUnit = GRAVITY; // GRAVITY OR METERPERSECOND2 + float accelSlope[3] = {1,1,1}; // slope correction factor for calibration + float accelUnit = GRAVITY; // GRAVITY OR METERPERSECOND2 + float accelODR; // Stores the actual value of Output Data Rate virtual int readAccel(float& x, float& y, float& z); // Results are in G (earth gravity) or m/s2. virtual int accelAvailable(); // Number of samples in the FIFO. - virtual void setAccelOffset(float x, float y, float z); //Store zero-point measurements as offset - virtual void setAccelSlope(float x, float y, float z); //Store measurements as slope - virtual int setAccelODR(uint8_t range); // Sample Rate 0:off, 1:10Hz, 2:50Hz, 3:119Hz, 4:238Hz, 5:476Hz, 6:952Hz, 7:NA Automatic setting of BW - virtual float getAccelODR(); // Sample Rate of the sensor. + virtual void setAccelOffset(float x, float y, float z); //Store zero-point measurements as offset + virtual void setAccelSlope(float x, float y, float z); //Store measurements as slope + virtual int setAccelODR(uint8_t range); // Sample Rate 0:off, 1:10Hz, 2:50Hz, 3:119Hz, 4:238Hz, 5:476Hz, 6:952Hz Automatic BW setting + virtual float getAccelODR(); // Measured Sample Rate of the sensor. virtual float setAccelBW(uint8_t range); //0,1,2,3 Override autoBandwidth setting see doc.table 67 virtual float getAccelBW(); //Bandwidth setting 0,1,2,3 see documentation table 67 virtual int setAccelFS(uint8_t range); // 0: ±2g ; 1: ±16g ; 2: ±4g ; 3: ±8g virtual float getAccelFS(); // Full Scale setting (output = 2.0, 16.0 , 4.0 , 8.0) // Gyroscope - float gyroOffset[3] = {0,0,0}; // zero point offset correction factor for calibration - float gyroSlope[3] = {1,1,1}; // slope correction factor for calibration + float gyroOffset[3] = {0,0,0}; // zero point offset correction factor for calibration + float gyroSlope[3] = {1,1,1}; // slope correction factor for calibration float gyroUnit = DEGREEPERSECOND; // DEGREEPERSECOND RADIANSPERSECOND REVSPERMINUTE REVSPERSECOND + float gyroODR; // Stores the actual value of Output Data Rate virtual int readGyro(float& x, float& y, float& z); // Results are in degrees/second or rad/s. - virtual int gyroAvailable(); // Number of samples in the FIFO. - virtual void setGyroOffset(float x, float y, float z); //Store zero-point measurements as offset - virtual void setGyroSlope(float x, float y, float z); //Store measurements as slope - virtual int setGyroODR(uint8_t range); //Sampling Rate 0:off, 1:10Hz, 2:50Hz, 3:119Hz, 4:238Hz, 5:476Hz, 6:952Hz, 7:NA - virtual float getGyroODR(); // Sampling rate of the sensor. + virtual int gyroAvailable(); // Number of samples in the FIFO. + virtual void setGyroOffset(float x, float y, float z); //Store zero-point measurements as offset + virtual void setGyroSlope(float x, float y, float z); //Store measurements as slope + virtual int setGyroODR(uint8_t range); //Sampling Rate 0:off, 1:10Hz, 2:50Hz, 3:119Hz, 4:238Hz, 5:476Hz, 6:952Hz + virtual float getGyroODR(); // Measured Sample rate of the sensor. virtual int setGyroBW(uint8_t range); //Bandwidth setting 0,1,2,3 see documentation table 46 and 47 virtual float getGyroBW(); //Bandwidth setting 0,1,2,3 see documentation table 46 and 47 virtual int setGyroFS(uint8_t range); // (0= ±245 dps; 1= ±500 dps; 2= ±1000 dps; 3= ±2000 dps) virtual float getGyroFS(); // (output = 245.0, 500.0 , 1000.0, 2000.0) // Magnetometer - float magnetOffset[3] = {0,0,0}; // zero point offset correction factor for calibration - float magnetSlope[3] = {1,1,1}; // slope correction factor for calibration + float magnetOffset[3] = {0,0,0}; // zero point offset correction factor for calibration + float magnetSlope[3] = {1,1,1}; // slope correction factor for calibration float magnetUnit = MICROTESLA; // GAUSS or MICROTESLA virtual int readMagnet(float& x, float& y, float& z); // Default results are in uT (micro Tesla) virtual int magnetAvailable(); // Number of samples in the FIFO. - virtual void setMagnetOffset(float x, float y, float z); //Store zero-point measurements as offset - virtual void setMagnetSlope(float x, float y, float z); //Store measurements as slope + virtual void setMagnetOffset(float x, float y, float z); //Store zero-point measurements as offset + virtual void setMagnetSlope(float x, float y, float z); //Store measurements as slope virtual int setMagnetODR(uint8_t range); // Sampling rate (0..7) corresponds to {0.625,1.25,2.5,5.0,10.0,20.0,40.0,80.0}Hz virtual float getMagnetODR(); // Sampling rate of the sensor in Hz. virtual int setMagnetFS(uint8_t range); // 0=400.0; 1=800.0; 2=1200.0 , 3=1600.0 (µT) From ccb4c7532ce2e445b7fffa5580c0f48b5eb1f218 Mon Sep 17 00:00:00 2001 From: FemmeVerbeek Date: Sun, 7 Jun 2020 13:31:01 +0200 Subject: [PATCH 10/15] 400Hz magnetic, DIY calibration, level setMagnetODR(8); now produces measurements @400Hz. The DIY calibration is a menu driven program that explains what to do for a simple calibration, does the measurements and produces the data that can be copy/pasted in a sketch. Waterlevel is jus what is says in two directions. The XY compass also produces magnetic inclination. --- CHANGELOG | 2 +- README.adoc => Licence.adoc | 0 .../LSM9DS1_DIY_Calibration.ino | 380 ++++++++ .../LSM9DS1_RegisterTest.ino | 238 +++-- .../LSM9DS1_XY_compass/LSM9DS1_XY_compass.ino | 52 ++ .../LSM9DS1_calibrate_gyro_offset.ino | 82 -- .../LSM9DS1_calibrated_XY_compass.ino | 93 -- .../LSM9DS1_waterlevel/LSM9DS1_waterlevel.ino | 50 ++ keywords.txt | 36 +- ...DS1_V2 notes and manual.txt => readme.txt | 811 +++++++++--------- src/LSM9DS1.cpp | 137 ++- src/LSM9DS1.h | 28 +- 12 files changed, 1207 insertions(+), 702 deletions(-) rename README.adoc => Licence.adoc (100%) create mode 100644 examples/LSM9DS1_DIY_Calibration/LSM9DS1_DIY_Calibration.ino create mode 100644 examples/LSM9DS1_XY_compass/LSM9DS1_XY_compass.ino delete mode 100644 examples/LSM9DS1_calibrate_gyro_offset/LSM9DS1_calibrate_gyro_offset.ino delete mode 100644 examples/LSM9DS1_calibrated_XY_compass/LSM9DS1_calibrated_XY_compass.ino create mode 100644 examples/LSM9DS1_waterlevel/LSM9DS1_waterlevel.ino rename LSM9DS1_V2 notes and manual.txt => readme.txt (76%) diff --git a/CHANGELOG b/CHANGELOG index d3f92a1..5111c36 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -12,7 +12,7 @@ Arduino_LSM9DS1 2.0.0 - 2020.05.30 * Added support for Full scale setting, * Added support for Operational mode: off, Accel only, Gyro + Accel -* Added support for ODR sample rate, ODR values are automatically calibrated +* Added support for ODR sample rate, ODR values are automatically calibrated, include fast ODR for magnet * Added support for Band width * Added support for changing output unit * Added support for separate or combined sensor calibration diff --git a/README.adoc b/Licence.adoc similarity index 100% rename from README.adoc rename to Licence.adoc diff --git a/examples/LSM9DS1_DIY_Calibration/LSM9DS1_DIY_Calibration.ino b/examples/LSM9DS1_DIY_Calibration/LSM9DS1_DIY_Calibration.ino new file mode 100644 index 0000000..978af06 --- /dev/null +++ b/examples/LSM9DS1_DIY_Calibration/LSM9DS1_DIY_Calibration.ino @@ -0,0 +1,380 @@ +/* DIY calibration program for the LSM9DS1 chip + * + * Follow the instructions on the screen how to do calibration measurements. + * No special tools or setups are needed, however it is handy if the board with the LSM9DS1 chip is fitted inside + * a non-metalic rectangular box. + * The offset and slope factors are displayed on screen as code that can be copy/pasted directly into a sketch. + * Each new instance of the chip will require it's own unique set of calibration factors. + * + * written by Femme Verbeek 30-5-2020 + * + * This program uses V2 of the LSM9DS1 library + * Tested on an Arduino Nano 33 BLE Sense board. + */ + +#include +//boolean blinkEnabled=false; +const float gyroSlopeCriterion = 10; +const float accelCriterion = 0.06; +float EarthMagnetStrength = 49.0; //= µT +float EarthMagnetInclination = 67.0; //= degree + +void setup() { + Serial.begin(115200); + while (!Serial); + pinMode(LED_BUILTIN,OUTPUT); + delay(10); + if (!IMU.begin()) { Serial.println("Failed to initialize IMU!");while (1); } + IMU.setGyroODR(4); //238Hz + IMU.setMagnetODR(7); //80Hz +} + +void loop() +{ MainMenu(); +} + + +void MainMenu() +{ Serial.println("\n\n\n\n\n\n\n\n"); + Serial.println(" DIY Calibration program \n"); + Serial.println("The board with the LSM9DS1 sensor is best fitted into a non metallic rectangular box with flat sides."); + Serial.println("In the following procedures you'll be asked to rotate the sensor around one of it's axes at the time"); + Serial.println("or simply aim the axis upward and keep still. The simplest way is to put the box with one of its flat"); + Serial.println("sides on the table "); + Serial.println("To operate the menu in the IDE serial monitor you must press a letter key followed by Enter \n"); + + Serial.println(" Calibrate \n"); + Serial.println("(A)ccelerometer "); + Serial.println("(G)yroscope "); + Serial.println("(M)agnetometer "); + Serial.println("\n\n\n\n\n\n\n\n"); + while (!Serial.available()) ; + char incomingByte = toupper (Serial.read()); // read the incoming byte + if (byte(incomingByte)!=13) Serial.readStringUntil(13); // empty readbuffer + switch (incomingByte) + { case 'A': {calibrateAccelMenu(); break;} + case 'G': {calibrateGyroMenu(); break;} + case 'M': {calibrateMagnetMenu(); break;} + default : {Serial.println("I received: "+String(incomingByte)); break;} + } +} + +float maxAX = 1, maxAY=1, maxAZ=1, minAX=-1, minAY=-1, minAZ=-1; + +void calibrateAccelMenu() +{char incomingByte = 0; + while (incomingByte!='X') + { Serial.println("\n\n"); + Serial.println("Calibrate Accelerometer"); + Serial.println("Place the board on a horizontal surface with one of its axes vertical"); + Serial.println("Each of the axes must be measured facing up and facing down, so at least a total of 6 measurements. "); + Serial.println("The program recognises which axis is held vertical. If the angle is to far oblique the measurement is not valid."); + + Serial.println("\nPress (M) to start a calibration measurement. "); + Serial.println("\nPress (X) to exit \n"); + Serial.print ("Max values X="+String(maxAX,4)); Serial.print ("\tY="+String(maxAX,4));Serial.println ("\tZ="+String(maxAZ,4)); + Serial.print ("Min values X="+String(minAX,4)); Serial.print ("\tY="+String(minAX,4));Serial.println ("\tZ="+String(minAZ,4)); + + Serial.println("\nWhen all directions are measured, the code below can be copy/pasted in a sketch\n"); + for (int i= 0; i<=2 ; i++) + { Serial.print(" IMU.accelOffset["+String(i)); + Serial.print("] = "+String(IMU.accelOffset[i],6)); + Serial.print(";"); + } + Serial.println(); + for (int i= 0; i<=2 ; i++) + { Serial.print(" IMU.accelSlope ["+String(i)); + Serial.print("] = "+String(IMU.accelSlope[i],6)); + Serial.print(";"); + } + Serial.println("\n\n"); + while (!Serial.available()) ; // wait for character to be entered + incomingByte = toupper(Serial.read()); + if (byte(incomingByte)!=13) Serial.readStringUntil(13); // empty readbuffer + if ((incomingByte)=='M') calibrateAccel(); + } +} + + +void calibrateGyroMenu() +{char incomingByte = 0; +boolean OffsetCalibrated=false; +int turnangle = 180; + Serial.println("\n\n\n\n\n\n\n\n\n\n\n"); + while (incomingByte!='X') + { Serial.println(" Calibrate Gyroscope\n"); + if (!OffsetCalibrated) Serial.println(" Start by calibrating the Offset\n"); + else + { Serial.println("Each of the gyroscope's axes, XYZ, must be individually calibrated for it's sensitivity (slope) "); + Serial.println("During a slope calibration measurement the board must be rotated about one axis over a known turn angle. "); + Serial.println("The rotation must be pure, i.e. without much rotation about the other two axes. An easy method is to"); + Serial.println("place the board on a flat surface with the rotation axis vertical and its side pushed against a non moving"); + Serial.println("object. Rotate it over the turn angle in a few seconds, press it against the object again and hit Enter "); + Serial.println("to stop measuring. Each of the axes X,Y and Z must be measured. The program automatically detects which. \n"); + Serial.print (" (A)ngle "+String(turnangle));Serial.println("°, change angle to rotate the sensor over "); + Serial.println(" (M)easure Slope, turn the board and press enter when finished "); + } + Serial.println(" (C)alibrate Offset, just keep the sensor still during 5 sec measurement\n"); + Serial.println(" (X) eXit to the main menu"); + if (OffsetCalibrated) + { Serial.println("\n The code below can be copy/pasted in a sketch\n"); + for (int i= 0; i<=2 ; i++) + { Serial.print(" IMU.gyroOffset["+String(i)); + Serial.print("] = "+String(IMU.gyroOffset[i],6)); + Serial.print(";"); + } + Serial.println(); + for (int i= 0; i<=2 ; i++) + { Serial.print(" IMU.gyroSlope ["+String(i)); + Serial.print("] = "+String(IMU.gyroSlope[i],6)); + Serial.print(";"); + } + Serial.println(); + } + else Serial.println("\n\n\n\n\n\n\n\n"); + while (!Serial.available()); // wait for anything to be entered + incomingByte = toupper(Serial.read()); // read char and convert to upcase + if (byte(incomingByte)!=13) Serial.readStringUntil(13); // empty readbuffer + switch (incomingByte) + { case 'C': {Serial.println("\n\nMeasuring. Just a moment."); + calibrateGyroOffset(); + OffsetCalibrated=true; + break;} + case 'A': { turnangle *=2; + if (turnangle>360) turnangle=90; + break;} + case 'M': { Serial.print("\n\n\n\n\n\nMeasuring. Turn the sensor over "+String(turnangle));Serial.println(" degrees\n"); + Serial.println("Press Enter when finished."); + calibrateGyroslope(turnangle); + break;} + default : {Serial.println("I received: "+String(incomingByte)); break;} + } + Serial.println(""); + } +} +void calibrateMagnetMenu() +{char incomingByte = 0; +String ans; + Serial.println("\n\n\n\n\n\n\n\n\n\n\n"); + while (incomingByte!='X') + { Serial.println("Calibrate Magnetometer"); + Serial.println("The magnetic field measurement will be heavily disturbed by your set-up, so an \"in-situ\" calibration is advised."); + Serial.println("The demonstrated min-max calibration was slightly improved to diminish outlyers but is still only very simple."); + Serial.println("While measuring the min and max magnetic values must be found for all axes by twisting the board around. The "); + Serial.println("min-max values are constantly printed. If one of them changes you found a higher or lower value. It helps if you "); + Serial.println("know the direction of the Earth magnetic fieldlines. All you have to do is align the sensor axes with it. "); + Serial.println("More info about the Earth magnetic field https://en.wikipedia.org/wiki/Earth%27s_magnetic_field "); + Serial.println(" "); + Serial.print (" (S)trength of Local Earth magnetic field "+String(EarthMagnetStrength));Serial.println(" µT Needed for correct Slope setting"); + Serial.println(" (M)in-Max Calibration, twist board around, press enter to stop measuring"); + Serial.println(" (X) eXit to the main menu"); + Serial.println(" "); + Serial.println("\n The code below can be copy/pasted in a sketch\n"); + for (int i= 0; i<=2 ; i++) + { Serial.print(" IMU.magnetOffset["+String(i)); + Serial.print("] = "+String(IMU.magnetOffset[i],6)); + Serial.print(";"); + } + Serial.println(); + for (int i= 0; i<=2 ; i++) + { Serial.print(" IMU.magnetSlope ["+String(i)); + Serial.print("] = "+String(IMU.magnetSlope[i],6)); + Serial.print(";"); + } + Serial.println("\n\n"); + while (!Serial.available()) ; // wait for character to be entered + incomingByte = toupper(Serial.read()); + if (byte(incomingByte)!=13) Serial.readStringUntil(13); // empty readbuffer + switch (incomingByte) + { case 'S': { readAnswer("\n\nEnter local Field intensity " ,EarthMagnetStrength ); break;} + case 'M': { calibrateMagnet() ; + Serial.print("\n\n\n\n\n\n"); + break;} + default : {Serial.println("I received: "+String(incomingByte)); break;} + } + + + } +} + +void readAnswer(String msg, float& param) +{String ans; + Serial.print(msg); + while (!Serial.available()); + ans = Serial.readStringUntil(13); + Serial.println(ans); + if (ans!="") param= ans.toFloat(); + Serial.println("\n\n\n\n\n\n\n"); +} + +void calibrateMagnet() // measure Offset and Slope of XYZ +{ float x, y, z, Xmin, Xmax, Ymin, Ymax, Zmin, Zmax ; + unsigned long count=0; + IMU.setMagnetOffset(0,0,0); // Offsets must be 0 when calibrating + IMU.setMagnetSlope(1,1,1); // slopes must be 1 when calibrating + IMU.setMagnetODR(8); //Fast rate 400Hz + read_N_Magnet(10, Xmin, Ymin, Zmin); // starting values + Xmax = Xmin; Ymax = Ymin; Zmax = Zmin; + while (!Serial.available()) // measure until enter key pressed + { read_N_Magnet(10, x, y, z); //average over a number of samples to reduce the effect of outlyers + Xmax = max (Xmax, x); Xmin = min (Xmin, x); + Ymax = max (Ymax, y); Ymin = min (Ymin, y); + Zmax = max (Zmax, z); Zmin = min (Zmin, z); + count++; + if ((count & 5)==0) //reduce the number of prints by a factor + { Serial.print("Xmin = "+String(Xmin)); Serial.print(" Xmax = "+String(Xmax)); + Serial.print(" Ymin = "+String(Ymin)); Serial.print(" Ymax = "+String(Ymax)); + Serial.print(" Zmin = "+String(Zmin)); Serial.print(" Zmax = "+String(Zmax)); + Serial.println(); + } + } + Serial.readStringUntil(13); //Empty read buffer + IMU.setMagnetOffset( (Xmax+Xmin)/2,(Ymax+Ymin)/2, (Zmax+Zmin)/2 ) ; // store offset + IMU.setMagnetSlope ( (2*EarthMagnetStrength)/(Xmax-Xmin),(2*EarthMagnetStrength)/(Ymax-Ymin),(2*EarthMagnetStrength)/(Zmax-Zmin)); // store slope + +} + + + +void calibrateGyroslope(unsigned int turnangle) // rotate board over known angle +{ float tempSlope[3]; + boolean validMmt=false; + float dirX=0, dirY=0, dirZ=0,sigmaX2=0,sigmaY2=0,sigmaZ2=0; + float x, y, z; + unsigned int count=0; + for (int i =0;i<=2;i++) tempSlope[i]= IMU.gyroSlope[i]; + IMU.setGyroSlope(1,1,1); + while (!Serial.available()) // measure until enter pressed + { while (!IMU.gyroAvailable()); + IMU.readGyro(x, y, z); + dirX += x/IMU.getGyroODR(); dirY += y/IMU.getGyroODR(); dirZ += z/IMU.getGyroODR(); + sigmaX2 +=x*x; sigmaY2+=y*y; sigmaZ2+=z*z; + count++; + if ((count%30)==0)Serial.print('.'); + digitalWrite(LED_BUILTIN, (millis()/125)%2); // blink onboard led every 250ms + } + digitalWrite(LED_BUILTIN,0); // led off + Serial.readStringUntil(13); //Empty read buffer + Serial.print("\n\n\nMeasured direction change X "); + Serial.print(String(dirX,6)+"°\tY "); Serial.print(String(dirY,6)+"°\t Z "); Serial.println(String(dirZ,6)+"°"); + sigmaX2 /= count; sigmaY2 /= count; sigmaZ2 /= count; + Serial.print("Std.dev. "); + Serial.print(String(sigmaX2,6)+'\t'); Serial.print(String(sigmaY2,6)+'\t'); Serial.println(sigmaZ2,6); + dirX=abs(dirX); dirY=abs(dirY); dirZ=abs(dirZ); + if (dirX>max(dirY,dirZ)) + { + if (sigmaY2max(dirX,dirZ)) + { if (sigmaX2max(dirY,dirX)) + { if (sigmaY2max(abs(y),abs(z))) + { Serial.println("X detected"); + if (sqrt(y*y+z*z)/x0) maxAX=x; else minAX=x; + } + } + if (abs(y)>max(abs(x),abs(z))) + { Serial.println("Y detected"); + if (sqrt(x*x+z*z)/y0) maxAY=y; else minAY=y; + } + } + if (abs(z)>max(abs(x),abs(y))) + { Serial.println("Z detected"); + if ( sqrt(x*x+y*y)/z0) maxAZ=z; else minAZ=z; + } + } + IMU.setAccelOffset((maxAX+minAX)/2,(maxAY+minAY)/2,(maxAZ+minAZ)/2); + IMU.setAccelSlope((maxAX-minAX)/2,(maxAY-minAY)/2,(maxAZ-minAZ)/2); + if ( !validMmt ) + { Serial.print("\n\n\nNot a valid measurement! "); + Serial.print("x="+String(x));Serial.print(" y="+String(y));Serial.println(" z="+String(z)); + } +} + +void read_N_Accel(unsigned int N, float& averX, float& averY, float& averZ) +{ float x, y, z; + averX=0; averY =0;averZ =0; + for (int i=1;i<=N;i++) + { while (!IMU.accelAvailable()); + IMU.readAccel(x, y, z); + averX += x; averY += y; averZ += z; + digitalWrite(LED_BUILTIN, (millis()/125)%2); // blink onboard led every 250ms + if ((i%30)==0)Serial.print('.'); + } + averX /= N; averY /= N; averZ /= N; + digitalWrite(LED_BUILTIN,0); // led off +} + +void read_N_Gyro(unsigned int N, float& averX, float& averY, float& averZ) +{ float x, y, z; + averX=0; averY =0;averZ =0; + for (int i=1;i<=N;i++) + { while (!IMU.gyroAvailable()); + IMU.readGyro(x, y, z); + averX += x; averY += y; averZ += z; + digitalWrite(LED_BUILTIN, (millis()/125)%2); // blink onboard led every 250ms + if ((i%30)==0)Serial.print('.'); + } + averX /= N; averY /= N; averZ /= N; + digitalWrite(LED_BUILTIN,0); // led off +} + +void read_N_Magnet(unsigned int N, float& averX, float& averY, float& averZ) +{ float x, y, z; + averX=0; averY =0;averZ =0; + for (int i=1;i<=N;i++) + { while (!IMU.magnetAvailable()); + IMU.readMagnet(x, y, z); + averX += x; averY += y; averZ += z; + digitalWrite(LED_BUILTIN, (millis()/125)%2); // blink onboard led every 250ms + if ((i%30)==0)Serial.print('.'); + } + averX /= N; averY /= N; averZ /= N; + digitalWrite(LED_BUILTIN,0); // led off +} diff --git a/examples/LSM9DS1_RegisterTest/LSM9DS1_RegisterTest.ino b/examples/LSM9DS1_RegisterTest/LSM9DS1_RegisterTest.ino index e244ed2..0fe6c37 100644 --- a/examples/LSM9DS1_RegisterTest/LSM9DS1_RegisterTest.ino +++ b/examples/LSM9DS1_RegisterTest/LSM9DS1_RegisterTest.ino @@ -1,5 +1,5 @@ /*Test program for Arduino__LSM9DS1 Library version 2.0 extensions - * Written by Femme Verbeek Pijnacker the Netherlands 23 may 2020. + * Written by Femme Verbeek Pijnacker the Netherlands 30 may 2020. * Run through all the new set and get functions */ @@ -7,94 +7,204 @@ void setup() { Serial.begin(115200); - while(!Serial); - Serial.println(); - if (!IMU.begin()) { + while(!Serial); //Wait for serial connection + delay(10); + if (!IMU.begin()) { Serial.println("Failed to initialize IMU!"); while (1); } - - for (int i = 0;i<=3;i++){ + float x,y,z; + Serial.println("Testing all library chip settings\n"); + Serial.println ("Full Scale settings should hardly inluence measured values"); + for (int i = 0;i<=4;i++){ if (IMU.setAccelFS(i)) - printResult ("Accelleration Full Scale range param = ", i ,IMU.getAccelFS()," g "); - else Serial.println ("failed setting accelleration scale value "); } + { printResult ("setAccelFS(", i ,IMU.getAccelFS()," g "); + read_N_Accel(2,x,y,z); //throw away first two samples + read_N_Accel(50,x,y,z); + printXYZData("Accel uncalibrated ",x,y,z,"g "); + } + else Serial.println ("setAccelFS parameter out of range \n"); } - for (int i = 0;i<=3;i++){ - if (IMU.setGyroFS(i)) - printResult ("Gyroscope Full Scale range param = ",i,IMU.getGyroFS()," deg/s "); - else Serial.println ("failed setting gyroscope scale value ");} + read_N_Gyro(50,x, y, z); + IMU.setGyroOffset(x,y,z); //Calibrate Offset + for (int i = 0;i<=4;i++){ + if (IMU.setGyroFS(i)) + { printResult ("setGyroFS(",i,IMU.getGyroFS()," deg/s "); + read_N_Gyro(2,x,y,z); //throw away first two samples + read_N_Gyro(50,x,y,z); + printXYZData("Gyro offset calibrated ",x,y,z,"dps "); + } + else Serial.println ("setGyroFS full scale parameter out of range \n");} - for (int i = 0;i<=3;i++){ + for (int i = 0;i<=4;i++){ if (IMU.setMagnetFS(i)) - printResult ("magnetic range param = ", i ,IMU.getMagnetFS()," µT "); - else Serial.println ("failed setting magnetic field scale value "); } - - Serial.println("Op mode "+String(IMU.getOperationalMode())); + { printResult ("setMagnetFS(", i ,IMU.getMagnetFS()," µT "); + read_N_Magnet(2,x,y,z); //throw away first two samples + read_N_Magnet(10,x,y,z); + printXYZData("Magnet ",x,y,z,"dps "); + } + else Serial.println ("setMagnetFS full scale parameter out of range \n"); } + + Serial.println("\nTest Operational Mode 0=off, 1 accelerometer only, 2= Accel + Gyro \n"); + Serial.println("Default operational mode "+String(IMU.getOperationalMode())); IMU.setGyroODR(0); - Serial.println("setGyroODR(0) Op mode "+String(IMU.getOperationalMode())); + Serial.println("setGyroODR(0) Operational mode "+String(IMU.getOperationalMode())); IMU.setAccelODR(0); - Serial.println("setAccelODR(0) Op mode "+String(IMU.getOperationalMode())); + Serial.println("setAccelODR(0) Operational mode "+String(IMU.getOperationalMode())); IMU.setGyroODR(3); - Serial.println("setGyroODR(3) Op mode "+String(IMU.getOperationalMode())); + Serial.println("setGyroODR(3) Operational mode "+String(IMU.getOperationalMode())); - Serial.println(" setGyroODR result "); + Serial.println("\n setGyroODR result (shared ODR, i>0 overrules the Accel setting)"); for (int i=0;i<=7;i++) - { if (IMU.setGyroODR(i)==0) Serial.println("Gyro settting outof range "+String(i)); + if (IMU.setGyroODR(i)==0) Serial.println("setGyroODR parameter out of range "+String(i)); else printODRData(i); - } - Serial.println(" setAccelODR result "); + + Serial.println("\n setAccelODR result (shared ODR, i=0 switches off Gyro and Accel)"); for (int i=0;i<=7;i++) - { if (IMU.setAccelODR(i)==0) Serial.println("Accel settting outof range "+String(i)); - else printODRData(i); - } - Serial.println("Switch off Gyro"); + if (IMU.setAccelODR(i)==0) Serial.println("setAccelODR parameter out of range "+String(i)); + else printODRData(i); + + Serial.println("\n Switch off Gyro (Accelerometer only mode)"); IMU.setGyroODR(0); //switch off gyro for (int i=0;i<=7;i++) - { if (IMU.setAccelODR(i)==0) Serial.println("Accel settting outof range "+String(i)); + if (IMU.setAccelODR(i)==0) Serial.println("setAccelODR parameter out of range "+String(i)); else printODRData(i); + + Serial.println("\n setMagnetODR sample rate result"); + for (int i = 0;i<=16;i++){ + if (IMU.setMagnetODR(i)) + printResult ("setMagnetODR(", i , IMU.getMagnetODR()," Hz \n"); + else Serial.println ("setMagnetODR parameter out of range "+String(i));} + + Serial.println("\n Accelerometer automatic band width result "); + for (int i=0;i<=6;i++) + { IMU.setAccelODR(i); + Serial.print("Accel ODR = "+String(IMU.getAccelODR())); + Serial.println(" automatic BW setting (Hz) "+ String (IMU.getAccelBW())); } - for (int i = 0;i<=7;i++){ - if (IMU.setMagnetODR(i)) - printResult ("magnetic field sample rate param = ", i , IMU.getMagnetODR()," Hz "); - else Serial.println ("failed setting magnetic field sample rate ");} - - for (int i = 0;i<=7;i++) - { if (IMU.setAccelODR(i)) - { printResult ("accelleration sample rate param = ", i , IMU.getAccelODR()," Hz "); - Serial.println(" automatic bandwidth setting (Hz) "+ String (IMU.getAccelBW())); - for (int j = 0;j<=3;j++) - { IMU.setAccelBW(j); // override automatic bandwith - printResult("Accel bandwidth override ", j ,IMU.getAccelBW(), "Hz " ); - } - } - else Serial.println ("failed setting accelleration sample rate "); + Serial.println ("\n Accelerometer band width override"); + for (int i = 0;i<=4;i++) + { if (IMU.setAccelBW(i) ) // override automatic bandwith + printResult("setAccelBW(", i ,IMU.getAccelBW(), "Hz \n" ); + else Serial.println ("setAccelBW parameter out of range "+String(i) ); } - for (int i = 0;i<=7;i++) - { if (IMU.setGyroODR(i)){ - printResult ("gyroscope sample rate param = ", i , IMU.getGyroODR()," Hz" ); - for (int j = 0;j<=3;j++) - { IMU.setGyroBW(j); // override automatic bandwith - printResult("Gyro bandwidth setting ", j ,IMU.getGyroBW(), "Hz " ); - } - } - else Serial.println ("failed setting gyroscope sample rate "); + + Serial.println ("\n Gyroscope band width setting"); + for (int i = 0;i<=6;i++) + { if (IMU.setGyroODR(i)) + { Serial.println ("Gyroscope ODR = " + String( IMU.getGyroODR() ) ); + for (int j = 0;j<=4;j++) + { if (IMU.setGyroBW(j) ) // the gyro has no automatic bandwith + printResult("setGyroBW(", j ,IMU.getGyroBW(), "Hz \n" ); + else Serial.println ("setGyroBW parameter out of range"+String(j)); + } + } + else Serial.println ("failed setting gyroscope sample rate "); } -} + Serial.println ("\n Change output Units changes the value of read... \n"); + + Serial.print("Change accel output unit to m/s2 "); + IMU.accelUnit= METERPERSECOND2; + read_N_Accel(20,x, y, z); + printXYZData("readAccel uncalibrated ",x,y,z,"m/s2 "); + + Serial.print("Change accel output unit to g "); + IMU.accelUnit= GRAVITY; + read_N_Accel(20,x, y, z); + printXYZData("readAccel uncalibrated ",x,y,z,"g "); -void loop() { + Serial.print("\nSimulate gyro measurement by offsetting 100 dps "); + IMU.setGyroOffset(0,0,0); //Zero offset + read_N_Gyro(20,x, y, z); + IMU.setGyroOffset(100+x,100+y,100+z); //Add 100 dps to measurement to simulate a measurement + + Serial.print("\nChange gyro output unit to deg/s "); + IMU.gyroUnit = DEGREEPERSECOND; + read_N_Gyro(20,x, y, z); + printXYZData("readGyro offset ",x,y,z,"deg/s "); + + Serial.print("Change gyro output unit to rad/s "); + IMU.gyroUnit = RADIANSPERSECOND; + read_N_Gyro(20,x, y, z); + printXYZData("readGyro offset ",x,y,z,"rad/s "); + + Serial.print("Change gyro output unit to Rev/M "); + IMU.gyroUnit = REVSPERMINUTE; + read_N_Gyro(20,x, y, z); + printXYZData("readGyro offset ",x,y,z,"RPM "); + + Serial.print("Change gyro output unit to Rev/s "); + IMU.gyroUnit = REVSPERSECOND; + read_N_Gyro(20,x, y, z); + printXYZData("readGyro offset ",x,y,z,"RPS "); + + Serial.print("\nChange Magnet output unit to microTesla "); + IMU.magnetUnit = MICROTESLA; + read_N_Magnet(20,x, y, z); + printXYZData("readMagnet ",x,y,z,"µT "); + + Serial.print("Change Magnet output unit to nanoTesla "); + IMU.magnetUnit = NANOTESLA; + read_N_Magnet(20,x, y, z); + printXYZData("readMagnet ",x,y,z,"nT "); + + Serial.print("Change Magnet output unit to Gauss "); + IMU.magnetUnit = GAUSS; + read_N_Magnet(20,x, y, z); + printXYZData("readMagnet ",x,y,z,"G "); } -void printResult (String msg, int nr,float value, String dimension) - { Serial.print (msg+String(nr)); - Serial.print(" setting "+String(value)); - Serial.println(dimension);} +void loop() { } +void printResult (String msg, int nr,float value, String dimension) +{ Serial.print (msg+String(nr)); + Serial.print(") Setting "+String(value)); + Serial.print(dimension); +} void printODRData(int i) -{ Serial.print("Settting "+String(i)); - Serial.print(" Op mode "+String(IMU.getOperationalMode())); - Serial.print(" ODR Gyro "+String( IMU.getGyroODR(),3 ) ); - Serial.print("Hz Accel "+String( IMU.getAccelODR(),3 ) ); - Serial.println("Hz"); +{ Serial.print("Settting "+String(i)); + Serial.print(" Oper.mode "+String(IMU.getOperationalMode())); + Serial.print(" ODR Gyro "+String( IMU.getGyroODR(),3 ) ); + Serial.print("Hz Accel "+String( IMU.getAccelODR(),3 ) ); + Serial.println("Hz"); } +void printXYZData(String msg, float x,float y,float z,String unit) +{ Serial.print (msg); + Serial.print (x+unit ); + Serial.print (y+unit ); + Serial.println (z+unit ); +} + +void read_N_Accel(unsigned int N, float& averX, float& averY, float& averZ) +{ float x, y, z; + averX=0; averY =0;averZ =0; + for (int i=1;i<=N;i++) + { while (!IMU.accelAvailable()); + IMU.readAccel(x, y, z); + averX += x/N; averY += y/N; averZ += z/N; + } +} +void read_N_Gyro(unsigned int N, float& averX, float& averY, float& averZ) +{ float x, y, z; + averX=0; averY =0;averZ =0; + for (int i=1;i<=N;i++) + { while (!IMU.gyroAvailable()); + IMU.readGyro(x, y, z); + averX += x/N; averY += y/N; averZ += z/N; + } +} +void read_N_Magnet(unsigned int N, float& averX, float& averY, float& averZ) +{ float x, y, z; + averX=0; averY =0;averZ =0; + for (int i=1;i<=N;i++) + { while (!IMU.magnetAvailable()); + IMU.readMagnet(x, y, z); + averX += x/N; averY += y/N; averZ += z/N; + } +} + + + + diff --git a/examples/LSM9DS1_XY_compass/LSM9DS1_XY_compass.ino b/examples/LSM9DS1_XY_compass/LSM9DS1_XY_compass.ino new file mode 100644 index 0000000..f3ddad5 --- /dev/null +++ b/examples/LSM9DS1_XY_compass/LSM9DS1_XY_compass.ino @@ -0,0 +1,52 @@ +/* Compass example for the Nano 33 BLE (Sense) + * You need version 2.0 or higher of the LMS9DS1 library to run this example + * + * The compass must be calibrated for the magnetic disturbance of the setup and the environment. + * Run the DIY calibration program first and copy/paste the Magnetometer calibration data below where it's indicated. + * + * Written by Femme Verbeek + * 6 June 2020 + * Released to the public domain +*/ + +#include + +void setup() { + Serial.begin(115200); + while(!Serial); // wait till the serial monitor connects + delay(1); + if (!IMU.begin()) { + Serial.println("Failed to initialize IMU!"); + while (1); } + IMU.setMagnetODR(8); // Sample Rate (0..7) corresponds to {0.625,1.25,2.5,5,10,20,40,80,400}Hz + +//******************** Replace the lines below by the magnetic output of the DIY Calibration program ********************* + + IMU.magnetOffset[0] = 0; IMU.magnetOffset[1] = 0; IMU.magnetOffset[2] = 0; + IMU.magnetSlope [0] = 1; IMU.magnetSlope [1] = 1; IMU.magnetSlope [2] = 1; + +//**************************************************************************************************************************** + Serial.println(" Heading \t Inclination \t Strength \t mag.X \t mag.Y \t mag.Z "); +} + +void loop () +{ float magY,magX,magZ; + doNMeasurements (50,magX,magY,magZ); //Average measurements to reduce noise + float heading= atan2(magY,magX)*180/PI +180; + float fieldStrength = sqrt(magX*magX +magY*magY+magZ*magZ); + float inclination = atan(-magZ/sqrt(magX*magX +magY*magY)) *180/PI; // by definition a positive inclination means the Z component is negative + Serial.print(String(heading)+'\t'); Serial.print(String(inclination)+'\t'); Serial.print(String(fieldStrength)+'\t'); + Serial.print(String(magX)+"µT\t"); Serial.print(String(magY)+"µT\t"); Serial.print(String(magZ)+"µT\n"); +} + +void doNMeasurements(unsigned int N, float& averX, float& averY, float& averZ) +{ float x, y, z; + averX=0; averY =0; averZ =0; + for (int i=1;i<=N;i++) + { while (!IMU.magneticFieldAvailable()); + IMU.readMagneticField(x, y, z); + averX += x; averY += y; averZ += z; + } + averX /= N; averY /= N; averZ /= N; +} + diff --git a/examples/LSM9DS1_calibrate_gyro_offset/LSM9DS1_calibrate_gyro_offset.ino b/examples/LSM9DS1_calibrate_gyro_offset/LSM9DS1_calibrate_gyro_offset.ino deleted file mode 100644 index 6c37b0a..0000000 --- a/examples/LSM9DS1_calibrate_gyro_offset/LSM9DS1_calibrate_gyro_offset.ino +++ /dev/null @@ -1,82 +0,0 @@ -/*Example program for Arduino__LSM9DS1 Library version 2.0 - * Tested on Arduino Nano 33 BLE SENSE - * Written by Femme Verbeek 15 may 2020. - * - * Measures the gyroscope offset and sets the IMU.gyroOffset parameters for X,Y,Z - * To start the calibration measurement, open the serial monitor. - * For a good result the board must be held still during the calibration measurements - * During the calibration the onboard LED's are blinking - * When finished the program prints the calibration result - * The program pauses till you press enter - * Next the program will continue measuring and print the now calibrated results. - * Best close the serial monitor first, open the serial monitor and send the character from there. - * - * To see a graphic result of the measurements, close the serial monitor when the program pauses, - * open the serial plotter, type any character and press "send". - */ -const int averageNSamples=10; //average output over N measurements - -#include -//unsigned long timer; -void setup() -{ Serial.begin(115200); - IMU.gyroOffset[0]=0; - IMU.gyroOffset[1]=0; - IMU.gyroOffset[2]=0; - - while(!Serial); - delay(1); - if (!IMU.begin()) { - Serial.println("Failed to initialize IMU!"); - while (1); } - IMU.setGyroODR(4); //Sampling Rate 0:off, 1:10Hz, 2:50Hz, 3:119Hz, 4:238Hz, 5:476Hz, 6:952Hz, 7:NA - Serial.print("Gyro ODR "+String( IMU.getGyroODR() ) ); - Serial.println(" BW setting "+String( IMU.getGyroBW() ) ); - Serial.println("Calibrating. Just a moment. "); - Serial.println("Keep the sensor still as long as the LED's are flashing"); - - calibrateGyroOffset(12000); // do calibration measurements during 12000 ms. - - Serial.println("calibration results"); - Serial.println("Content of IMU.gyroOffset "); - for (int i= 0; i<=2 ; i++) - { Serial.print("IMU.gyroOffset["+String(i)); - Serial.print("]= "+String(IMU.gyroOffset[i],6)); - Serial.println(";"); - } - Serial.println("Press enter to start calibrated measuring"); - Serial.println("To see a graph of the measurements, close this serial monitor, open the serial plotter type any character and click the send button"); - while (!Serial.available()); // pause the program, enter continues - while (Serial.available()) Serial.read(); // clear the read buffer - Serial.println(" X \t Y \t Z "); -} - -// continue doing calibrated measurements, this is best viewed in the serial plotter -void loop() -{ float x, y, z, averX=0, averY=0, averZ=0; - for (int i=1;i<=averageNSamples;i++) - { while (!IMU.gyroAvailable()); - IMU.readGyro(x, y, z); - averX += x; averY += y; averZ += z; - } - Serial.print(String(averX/averageNSamples,6)+'\t'); - Serial.print(String(averY/averageNSamples,6)+'\t'); - Serial.println(averZ/averageNSamples,6); -} - -void calibrateGyroOffset(unsigned int duration){ // don't move the board during calibration -unsigned long count = 0, start = millis(); -float x, y, z, addX=0, addY=0, addZ=0 ; - IMU.setGyroOffset(0,0,0); // Offsets must be zero when calibrating - while ((millis()-start) < duration) - { if (IMU.gyroscopeAvailable()) - { IMU.readGyroscope(x, y, z); - count++; - addX += x; addY += y; addZ += z; - digitalWrite(LED_BUILTIN, (millis()/125)%2); // blink onboard led every 250ms - if ((count%100)==0)Serial.print('.'); - } - } - IMU.setGyroOffset(addX/count, addY/count, addZ/count); // Store the average measurements as offset - digitalWrite(LED_BUILTIN, 0); // onboard led off -} diff --git a/examples/LSM9DS1_calibrated_XY_compass/LSM9DS1_calibrated_XY_compass.ino b/examples/LSM9DS1_calibrated_XY_compass/LSM9DS1_calibrated_XY_compass.ino deleted file mode 100644 index a9f7ba0..0000000 --- a/examples/LSM9DS1_calibrated_XY_compass/LSM9DS1_calibrated_XY_compass.ino +++ /dev/null @@ -1,93 +0,0 @@ -/* Calibrated compass example for the Nano 33 BLE Sense - * You need version 2.0 or higher of the LMS9DS1 library to run this example - * - * The compass must be calibrated for the magnetic disturbance of the environment. - * Calibration starts automaticlly when the serial monitor is opened and stops after a given time. - * Calibration in progress is indicated by the flashing onboard LED. - * - * During calibration the board must be turned slowly over a full 360 deg. - * When finished calibrating the program stores and prints the offset and slope factors. - * - * After pressing "enter" the program continues working as a compass. - * - * Written by Femme Verbeek 2020 - * Released to the public domain -*/ - -#include - -float EarthMagField = 49000; //= nT For local value see https://en.wikipedia.org/wiki/Earth%27s_magnetic_field -int averageCompassByN = 10; //number of samples per compass reading. Higher number = more accurate but slower -int averageCalibrationByN = 10; //goldielocs number too high = fewer measurements in 360deg turn, to low = more noise -int calibrationTime = 20; //s -void setup() { - pinMode(LED_BUILTIN,OUTPUT); - Serial.begin(115200); - while(!Serial); // wait till the serial monitor connects - delay(1); - if (!IMU.begin()) { - Serial.println("Failed to initialize IMU!"); - while (1); } - IMU.setMagnetODR(7); // Sample Rate (0..7) corresponds to {0.625,1.25,2.5,5.0,10.0,20.0,40.0,80.0}Hz - IMU.magnetUnit = NANOTESLA; // calibrate in nanotesla as this corresponds to the local field strenth number we found. - Serial.println("Calibrating. Just a moment. "); - Serial.println("Keep the compass sensor horizontal."); - Serial.print("In the next "+String(calibrationTime)); - Serial.println(" seconds the compass must be turned slowly over a full 360 degrees!"); - - calibrateMagnet(calibrationTime*1000); - - Serial.println("calibration results"); - Serial.print("IMU.magnetOffset[] : "); - for (int i= 0; i<=2 ; i++){ Serial.print(IMU.magnetOffset[i],4);Serial.print(" ");} - Serial.println(); - Serial.print("IMU.magnetSlope[] : "); - for (int i= 0; i<=2 ; i++){ Serial.print(IMU.magnetSlope[i],4);Serial.print(" ");} - Serial.println(); - Serial.println("Press enter to start the compass"); - while (!Serial.available()); // pause the program, enter continues, use the serial plotter to view a graph - while (Serial.available()) Serial.read(); // clear the read buffer - Serial.println("Direction\tFieldStrength\tmagX\tmagY"); // legend for serial plotter - IMU.magnetUnit = MICROTESLA; // Switch to microtesla as this looks better in the graph - -} - -void loop () -{ float magY,magX; - doNMeasurements (averageCompassByN,magX,magY,false); - float heading= atan2(magY,magX)*180/PI +180; - float fieldStrength = sqrt(magX*magX +magY * magY); - Serial.print(heading); Serial.print("\t"); Serial.print(fieldStrength);Serial.print("\t"); - Serial.print(magX); Serial.print("\t"); Serial.print(magY);Serial.print("\t"); - Serial.println(); -} - -void doNMeasurements(unsigned int N, float& averX, float& averY, boolean showLeds) -{ float x, y, z; - averX=0; averY =0; - for (int i=1;i<=N;i++) - { digitalWrite(LED_BUILTIN, bitRead(millis(),7)&& showLeds ); // blink onboard led - while (!IMU.magneticFieldAvailable()); - IMU.readMagneticField(x, y, z); - averX += x/N; - averY += y/N; - } -} - -void calibrateMagnet(unsigned int duration) // measure Offset and Slope of XY -{ float x, y, Xmin, Xmax, Ymin, Ymax ; - IMU.setMagnetOffset(0,0,0); // Offsets must be 0 when calibrating - IMU.setMagnetSlope(1,1,1); // slopes must be 1 when calibrating - doNMeasurements(averageCalibrationByN,Xmin, Ymin, true ); // find some starting values - Xmax = Xmin; Ymax = Ymin; - unsigned long start = millis(); - while ((millis()-start) < duration) - { doNMeasurements(averageCompassByN ,x, y ,true); - Xmax = max (Xmax, x); Xmin = min (Xmin, x); - Ymax = max (Ymax, y); Ymin = min (Ymin, y); - } - IMU.setMagnetOffset( (Xmax+Xmin)/2,(Ymax+Ymin)/2, 0 ) ; // store offset - IMU.setMagnetSlope ( (2*EarthMagField)/(Xmax-Xmin),(2*EarthMagField)/(Ymax-Ymin),1) ; // store slope -// Serial.print("Xmin = ");Serial.print(Xmin); Serial.print(" Xmax = ");Serial.println(Xmax); -// Serial.print("Ymin = ");Serial.print(Ymin); Serial.print(" Ymax = ");Serial.println(Ymax); -} diff --git a/examples/LSM9DS1_waterlevel/LSM9DS1_waterlevel.ino b/examples/LSM9DS1_waterlevel/LSM9DS1_waterlevel.ino new file mode 100644 index 0000000..05b1894 --- /dev/null +++ b/examples/LSM9DS1_waterlevel/LSM9DS1_waterlevel.ino @@ -0,0 +1,50 @@ +/* Water level example for the Nano 33 BLE (Sense) + * You need version 2.0 or higher of the LMS9DS1 library to run this example + * + * Calibration makes the difference between a few degrees and within a degree accuracy + * Run the DIY calibration program first and copy/paste the Accelerometer calibration data below where it's indicated. + * + * Written by Femme Verbeek + * 6 June 2020 + * Released to the public domain +*/ +#include + +void setup() { + Serial.begin(115200); + while(!Serial); //wait for a serial connection + delay(1); + if (!IMU.begin()) {Serial.println("Failed to initialize IMU!"); while (1); } + IMU.setAccelODR(5); //476 Hz + +//***************** Replace the lines below by the accelerometer output of the DIY Calibration program ******************* + + IMU.accelOffset[0] = 0; IMU.accelOffset[1] = 0; IMU.accelOffset[2] = 0; + IMU.accelSlope [0] = 1; IMU.accelSlope [1] = 1; IMU.accelSlope [2] = 1; + +//**************************************************************************************************************************** + Serial.println("pitchX\tpitchY"); //shows in the legend of the serial plotter. +} + +void loop() +{ float x, y, z, pitchx, pitchy; + read_N_Accel(50,x,y,z); + if (abs(x)>0.1 || abs(z)>0.1) pitchx = atan2(x,z)*180/PI; + else pitchx=0; + if (abs(y)>0.1 || abs(z)>0.1) pitchy = atan2(y,z)*180/PI; + else pitchy=0; + Serial.print(pitchx, 1); + Serial.print('\t'); + Serial.println(pitchy, 1); +} + +void read_N_Accel(unsigned int N, float& averX, float& averY, float& averZ) +{ float x, y, z; + averX=0; averY =0;averZ =0; + for (int i=1;i<=N;i++) + { while (!IMU.accelAvailable()); + IMU.readAccel(x, y, z); + averX += x; averY += y; averZ += z; + } + averX /= float(N); averY /= float(N); averZ /= float(N); +} diff --git a/keywords.txt b/keywords.txt index 97d9cca..3aeaf22 100644 --- a/keywords.txt +++ b/keywords.txt @@ -39,30 +39,26 @@ accelerationSampleRate KEYWORD2 gyroscopeSampleRate KEYWORD2 magneticFieldSampleRate KEYWORD2 -setAccelerationSampleRate KEYWORD2 -setGyroscopeSampleRate KEYWORD2 -setMagneticFieldSampleRate KEYWORD2 - accelOffset KEYWORD2 gyroOffset KEYWORD2 magnetOffset KEYWORD2 -accelScale KEYWORD2 -gyroScale KEYWORD2 -magnetScale KEYWORD2 +setAccelOffset KEYWORD2 +setGyroOffset KEYWORD2 +setMagnetOffset KEYWORD2 + +accelSlope KEYWORD2 +gyroSlope KEYWORD2 +magnetSlope KEYWORD2 + +setAccelSlope KEYWORD2 +setGyroSlope KEYWORD2 +setMagnetSlope KEYWORD2 accelUnit KEYWORD2 gyroUnit KEYWORD2 magnetUnit KEYWORD2 -accelerationFullScale KEYWORD2 -gyroscopeFullScale KEYWORD2 -magneticFieldFullScale KEYWORD2 - -setAccelerationFullScale KEYWORD2 -setGyroscopeFullScale KEYWORD2 -setMagneticFieldFullScale KEYWORD2 - getAccelODR KEYWORD2 getGyroODR KEYWORD2 getMagnetODR KEYWORD2 @@ -82,19 +78,17 @@ getAccelBW KEYWORD2 setGyroBW KEYWORD2 getGyroBW KEYWORD2 -readAccel KEYWORD2 -readGyro KEYWORD2 -readMagnet KEYWORD2 - - - ####################################### # Constants ####################################### GAUSS LITERAL1 +NANOTESLA LITERAL1 MICROTESLA LITERAL1 GRAVITY LITERAL1 METERPERSECOND2 LITERAL1 DEGREEPERSECOND LITERAL1 RADIANSPERSECOND LITERAL1 +REVSPERMINUTE LITERAL1 +REVSPERSECOND LITERAL1 + diff --git a/LSM9DS1_V2 notes and manual.txt b/readme.txt similarity index 76% rename from LSM9DS1_V2 notes and manual.txt rename to readme.txt index 7df2c3d..a6b0624 100644 --- a/LSM9DS1_V2 notes and manual.txt +++ b/readme.txt @@ -1,385 +1,426 @@ -Notes on version 2.0 of the LSM9DS1 library -Written by Femme Verbeek, Pijnacker, The Netherlands -https://www.linkedin.com/in/femmeverbeek/ -23 may 2020 - - -Contents: - Introduction - Naming strategy - Output of Read method - Calibration - Offset - Slope - Offset and Slope Combined - Overview of Code - Derivation of linear correction - Offset - Slope - -***************************************************************************************************************************** -***************************************** Introduction ********************************************** -***************************************************************************************************************************** - -The reason for writing this update is that the LSM9DS1 chip is not calibrated and the output may vary per instance of the chip. -In my case the magnetic field offset was larger than the Earth magnetic field. The gyroscope offset of 3 deg/s does not sound -like much, but when trying to track the orientation it corresponds to a full circle misalignment in two minutes. Without -calibration it is impossible to make a working compass for sensing magnetic field or a gyro-compass, artificial horizon etc. - -This new version 2 provides a method to compensate for manufacturing differences between chips and produce calibrated output -on the read methods. This library does not provide prescribed useable methods for measuring or calibrating. The development -of this is still the task of the user of this library. The examples are just for learning, but they are not part of the -library code itself. - -New for all 9 DOF (degrees of freedom) is the possibility: - to set and get the sample rate frequency , - to give it calibration zero offset and slope factors - to change the output unit - to change the internal full scale setting of the chip (IFS) giving it more accuracy at the expense of the range. - -With respect to version 1.1.0 almost all of the code was modified or added new. -With all new settings to their default values, programs using version 1.1.0 should still work and produce the same output. - - -***************************************************************************************************************************** -***************************************** Naming strategy ********************************************** -***************************************************************************************************************************** - -Keeping the same naming convention of version 1.1.0 resulted in very long names for the new functions, making formulas -difficult to read, increasing the chance of making typo's and it was not always clear what was meant. -For this reason a number of shorter aliases were created most of them following the datasheet: -https://www.st.com/resource/en/datasheet/lsm9ds1.pdf - -Accel for Accelleration, -Gyro for Gyroscope, -Magnet for MagneticField, -ODR for SampleRate (= Output Data Rate), -FS for FullScale, -BW for BandWdth, -addition of "set" and "get" in the names of ODR, BW and FS functions. - -e.g. magneticFieldSampleRate still works, but in the library code it is now getMagnetODR reflecting that it is not longer -a constant but a function that interrogates the LSM9DS1 chip. - -Not used were the documentation's XL, M and G since it may confuse with gravity, Gauss and of course the size of clothes. :) - - -***************************************************************************************************************************** -********************************** Output of Read method **************************************** -***************************************************************************************************************************** - -Measuring the offset shows that it scales with the chip internal full scale setting (IFS). That means that it is caused -by the internal transducer and not by the DAC. So it is sufficient to calibrate for just one of the full scale settings -and compensate for the others by means of a multiplication. - -The output of the read methods for each of the 9 DOF is now - - Read = Unit * Slope *( (PFS / 32786 * Data - Offset ) - -Data = the measurement value showing up on the chip registers -PFS = the in Program Full Scale setting (float LSM9DS1Class::get...FS() ) counteracting the internal chip setting so that - the output result remains unchanged. -Unit = the unit the measured physical property is expressed in. -Slope and Offset = calibration parameters. -Note that the read method still produces the same output as in library version 1.01 on the condition that Slope = 1; -Offset=0; and Unit set to its default value. - -There are several ways in which a linear correction can be applied. The chosen method has the highest amount of advantages. -The offset and slope are independent of each other and of any of the other settings in the program. They can be measured -independently and really counteract the internal transducer differences. (For mathematical derivation see below) -All Unit factors equal 1 for their default settings. - - -***************************************************************************************************************************** -********************************** Calibration **************************************** -***************************************************************************************************************************** - -In the text below ... stands for any of the three measurement properties, Accell, Gyro, Magnet. - -For a full calibration we must find a set of two factors (Slope and Offset) for each property ... and each of the three -directions (x, y, z). So in total 18 calibration factors. - -Following the procedures below, the calibration values are stored in the arrays ...Offset[3]={0,0,0} and ...Slope[3]={1,1,1} -Should you want to use these values again in a sketch, it's up to you to print them and put them in program code. -The library is designed in such a way that the stored values don't depend on any of the settings in the program, like ...Unit, -...SR (sample rate), ...FS (full scale). So changing any of the settings before or after restoring their values in the -arrays has no effect on the status of being calibrated. - -********************************************* Offset ********************************************* - -In order to find the value of Offset we must do a zero point measurement. That means that the physical property ... -we are trying to measure should actually result in a value of 0. E.g. keeping the board still should result in zero -gyroscope values for x,y and z. For acceleration the two axes perpendicular to the Earth gravity should be zero. - -An offset calibration involves three steps -1 set the offset factors to 0, using the set...Offset method -2 do zero-point measurements with the read... method -3 store the measured ReadResults using the same set...Offset method to make the calibration effective. - -ad.1: in your sketch: IMO.set...Offset(0,0,0); -ad.2: The readResult should probably be the average value of a number of measurements -ad.3: in your sketch: IMO.set...Offset(resultX,resultY,resultZ); - -Alternatively if it is difficult to get a zero property, you could try to find the maximum and minimum values and -use the point in the middle - - readResult = ( Read_max + Read_min ) / 2 - -This is probably more complex than what it looks like. Both Read_min and Read_max can best be some sort of average, but -if you simply use the min() and max() procedures, the final results are just one measurement each. The chances are high -that these are the worst measurements. -Calculating separate averages of the min and max values, is like a chicken and egg. Before the calibration program can -decide to which average a measurement belongs, it needs a rough calibration first. -The best method is probably 3D elliptical regression, where the values of Offset correspond to the centre of the -elliptoid. So far I did not venture into the mathematics of this. :0 - -********************************************* Slope ********************************************* - -Slope is a dimensionless number that compensates for the sensitivity of the chip's internal transducer. In case it is not -possible to measure this, best leave it at the value 1. For Magnet and Accel this is probably allright, but for Gyro the -sensitivity matters if you want to keep track of orientation. - -A slope calibration involves three steps -1 set the offset factor to 1, using the set...Slope method -2 do slope measurements with the read... method -3 store the readResult using the same set...Slope method. - -ad.1: in your sketch: IMO.set...Slope(1,1,1); -ad.2: The read result should probably be two different averages of a number of measurements each -ad.3: in your sketch: IMO.set...Slope(resultX,resultY,resultZ) - -In order to calibrate the Slope parameter at least two measurements (say 1 and 2) must be done where the physical quantity, -(let's call it Q), has a known difference, so Q_1 - Q_2 = known value. - -The value of slope follows from - - Result = abs (( Q_1 - Q_2) / ( Read_1 - Read_2 )) - -E.g. the Earth gravity should produce a value of 1g. Holding the board upside down should measure -1g. So the difference - ( Q_1 - Q_2) = 2g -The local strength of the magnetic field (in nT) can be found at -https://en.wikipedia.org/wiki/Earth%27s_magnetic_field - - -*************************************** Offset and Slope Combined ********************************************* - -With the above methods Slope and Offset can be measured independently. It does not matter which procedure comes first, -as long as you don't change any of the settings between measuring and assigning. This could accidently happen in case -of a combined measurement by setting the value of Slope before that of Offset. -Note that the dimensionless stored Offset values differ from the Read measurements by a factor (Unit * Slope). - - -A safe following order of steps is -1 set the Slope factors to 1, set...Slope(1,1,1); -2 set the Offset factors to 0, set...Offset(0,0,0); -3 do the measurements with the read... method -4 First store the Offset results using set...Offset -5 Store the Slope results second using set...Slope - -Example -Lets assume that readAccel produces values of 1.3 and - 0.9 - - Offset = (1.3 + (-0.9)) / 2 = 0.2 - Slope = (1 - (-1)) / (1.3 - (-0.9) = 2 / 2.2 = 0.90909 - -Note that set...Offset stores the measured values as ReadResult/(Unit * Slope). -If you store Slope first, the Offset becomes 0.2/0.90909 = 0.22 - -***************************************************************************************************************************** -********************************** Overview of Code **************************************** -***************************************************************************************************************************** - -(almost) unchanged - int begin(); - void end(); - void setContinuousMode(); - void setOneShotMode(); - virtual int accelAvailable(); // Number of samples in the FIFO. - virtual int gyroAvailable(); // Number of samples in the FIFO. - virtual int magnetAvailable(); // Number of samples in the FIFO. - -existing functions changed for new functionality. Results reflect calibration, full scale and unit settings - virtual int readAcceleration(float& x, float& y, float& z); // Results are in G (earth gravity) or m/s2. - virtual int readGyroscope(float& x, float& y, float& z); // Results are in degrees/second or rad/s. - virtual int readMagneticField(float& x, float& y, float& z); // Results are in uT (micro Tesla). - -existing functions that now actually do something - virtual float getAccelSR(); // Sampling rate of the sensor (Hz). - virtual float getGyroSR(); // Sampling rate of the sensor (Hz). - virtual float magnetSR(); // Sampling rate of the sensor (Hz). - -New the possibility to change the ODR registers (Output Data Rate) - virtual int setAccelSR(int8_t range); // 0:off, 1:10Hz, 2:50Hz, 3:119Hz, 4:238Hz, 5:476Hz, 6:952Hz, 7:NA - virtual int setGyroSR(int8_t range); // 0:off, 1:10Hz, 2:50Hz, 3:119Hz, 4:238Hz, 5:476Hz, 6:952Hz, 7:NA - virtual int setMagnetSR(int8_t range) // range (0..7) corresponds to {0.625,1.25,2.5,5.0,10.0,20.0,40.0,80.0}Hz - -New constants used in ..Unit setting -#define GAUSS 1.0 -#define MICROTESLA 100.0 // default -#define GRAVITY 1.0 // default -#define METERPERSECOND2 9.81 -#define DEGREEPERSECOND 1.0 //default -#define RADIANSPERSECOND 3.141592654/180 - -Unit settings: - float accelUnit = GRAVITY or METERPERSECOND2 - float gyroUnit = DEGREEPERSECOND or RADIANSPERSECOND - float magnetUnit = MICROTESLA or GAUSS - -Calibration parameters Slope ans Offset : See Calibration. - float accelOffset[3] = {0,0,0}; // zero point offset correction factor for calibration - float gyroOffset[3] = {0,0,0}; // zero point offset correction factor for calibration - float magnetOffset[3] = {0,0,0};// zero point offset correction factor for calibration - float accelSlope[3] = {1,1,1}; // slope correction factor for calibration - float gyroSlope[3] = {1,1,1}; // slope correction factor for calibration - float magnetSlope[3] = {1,1,1}; // slope correction factor for calibration - -Methods for setting the calibration - virtual void setAccelOffset(float x, float y, float z); - virtual void setAccelSlope(float x, float y, float z); - virtual void setGyroSlope(float x, float y, float z); - virtual int setGyroSR(int8_t range); //Sampling Rate 0:off, 1:10Hz, 2:50Hz, 3:119Hz, 4:238Hz, 5:476Hz, 6:952Hz, 7:NA - virtual void setMagnetOffset(float x, float y, float z); - virtual void setMagnetSlope(float x, float y, float z); - -Unitsettings that read returns measurement results in. - float accelUnit = GRAVITY; // GRAVITY OR METERPERSECOND2 - float gyroUnit = DEGREEPERSECOND; // DEGREEPERSECOND or RADIANSPERSECOND - float magnetUnit = MICROTESLA; // GAUSS MICROTESLA NANOTESLA - -New: changing the full scale sensitivity of the sensors. -The functions modify the FS (full scale) registers of the LSM9DS1 chip changing sensitivity at the expence of range. -Changing this setting does not change the x,y,z output of the read functions, but assigns just more or less bits -to the sensor measurement. - virtual int setAccelFS(int8_t range); // 0: ±2g ; 1: ±16g ; 2: ±4g ; 3: ±8g - virtual int setGyroFS(int8_t range); // 0= ±245 dps; 1= ±500 dps; 2= ±1000 dps; 3= ±2000 dps - virtual int setMagnetFS(int8_t range); // 0=400.0; 1=800.0; 2=1200.0 , 3=1600.0 (µT) -*note* According to the data sheet gyroscope setting 2 = 1000 dps should not be available. For some reason it worked - like a charm on my BLE Sense board, so I added the possibility. - -New functions return the Full Scale setting of the corresponding DOF as set with the corresponding set...FS functions - virtual float getAccelFS(); // output = 2.0, 16.0 , 4.0 , 8.0) - virtual float getGyroFS(); // output = 245.0, 500.0 , 1000.0, 2000.0) - virtual float getMagnetFS(); // output 400.0 ; 800.0 ; 1200.0 , 1600.0 - - -***************************************************************************************************************************** -********************************** Derivation of linear correction **************************************** -***************************************************************************************************************************** - -******************************************* Offset *************************************************** - - -Sorry for the very formal derivation below. It suits verifiability but probably only my own purpose :) -It took a lot of puzzling to get it right. Don't read it if you don't want to. :( - -Assuming good linearity of the transducer, we can model the data output of the chip as - - Data = (32768 / IFS) *( A*Q + B) (1) - -Data = the measured value showing up on the chip registers -Q = the actual physical quantity we are trying to measure in any of the 9 DOF -IFS = the chip Internal Fullscale Setting. -A,B unknown constants representing chip instance differences - -Since the chip outputs dimensionless bits and bytes only, the dimensions of IFS and B must equal the dimension of Q. - -The challenge is to get rid of the unknown constants A and B and translate them into measurable quantities produced by the -library's Read methods. Since a good calibrated Read should produce a number equal to the actual physical quantity -we can state - - Read = Q - -Further, we do not want to recalibrate when we change the Full Scale setting or the Unit. - -Define -PFS = the in-program Full Scale function counteracting the IFS so that the output result remains unchanged. - (dimensionless, but its value corresponds to that of the chosen default unit) -Slope = in-program correction factor for the sensor sensitivity -Offset = in-program correction factor for the sensor zero point offset - -The output of the read methods is (see above) - - Read = Unit * Slope * (PFS / 32786 * Data - Offset ) (2) - -Substitute eq(1) - - Read = Unit * slope * (PFS / IFS * 32786/32786 * ( A*Q + B ) - Offset ) - - Read = Unit * slope * (PFS / IFS * ( A*Q + B ) - Offset ) (3) - -In case of the calibrated zero point measurement Q = Read = 0 -Substitute in eq.(3) we get - - 0 = Unit * slope * (PFS / IFS * ( A*0 + B ) - Offset ) - - Unit * slope * Offset = Unit * slope * PFS / IFS * B (4) - -For an uncalibrated measurement of a zero point (ZP) filling in Offset=0 and Q=0 in eq(3) we get - - Read_uncalibrated_ZP = Unit * slope * PFS / IFS * B (5) - -The righthand terms in equation (4) and (5) are identical so it follows that - - Offset = read_uncalibrated_ZP / (Unit * slope) (6) - -This defines how we should do the calibration measurements. In the library the methods called set...Offset -use of eq(6) to assign the uncalibrated zero-point read values to the corresponding program parameters. -Eq.(6) suggests that Offset depends on Unit and Slope, but this is not the case as the Read method scales -with the same value. To proof this we write eg(4) in a different form - - Offset = (Unit * Slope) / (Unit * Slope) * PFS/IFS * B (7) - -Further since the dimensionless PFS counteracts IFS in size -and the dimension of IFS equals that of Q, the ratio PFS/IFS is 1/Unit. -or in other words - - Unit * PFS /IFS = 1 (8) - -eq(7) reduces to - - Offset = B / Unit = B (9) - -So Offset equals the dimensionless form of B and does not depend on any other parameter. - - -******************************************** Slope *************************************************** - -In order to calibrate the Slope at least two measurements (say 1 and 2) must be done where the measured quantity Q -has a known difference. The calibrated Read equals Q so - - Q_1 - Q_2 = Read_1 - Read_2 = known value (10) - -Substitute eq(2) - - Q_1 - Q_2 = Unit*Slope*(PFS/32786*Data_1 - Offset) - Unit*Slope*(PFS/32786*Data_2 - Offset) - - = Unit*Slope*(PFS/32786*(Data_1 - Data_2) (11) - -So the difference between the measurements gets rid of the Offset -For an uncalibrated measurement we must set Slope = 1. -Eq(2) becomes - - Read_uncalibrated = Unit * (PFS / 32786 * Data - Offset ) - -In eq(11) we get - - Q_1 -Q_2 = Slope * ( Read_uncalibrated_1 - Read_uncalibrated_2) - - Slope = (( Read_uncalibrated_1 - Read_uncalibrated_2) / (Q_1 -Q_2) (12) - -So in order to measure the slope we must first set the Slope parameter to 1. - -In order to prove that Slope is independent of all the other program parameters we substitute eq(1) in eq(11) - - Q_1 - Q_2 = Unit*Slope*(PFS/32786)*(32786/IFS)*(A*Q1 +B - A*Q2 -B)) - - (Q_1 - Q_2) = Slope* Unit*(PFS/IFS)* A *(Q1 - Q2) (12) - -and with eq(8) - - ( 1 ) = Slope * 1 * A *( 1 ) - - Slope = 1 / A - -QED +Notes on version 2.0 of the LSM9DS1 library +Written by Femme Verbeek, Pijnacker, The Netherlands +https://www.linkedin.com/in/femmeverbeek/ +5 june 2020 + + +Contents: + Introduction + Naming strategy + Output of Read method + Calibration + Offset + Slope + Offset and Slope Combined + Overview of Code + Derivation of linear correction + Offset + Slope + +***************************************************************************************************************************** +***************************************** Introduction ********************************************** +***************************************************************************************************************************** + +The reason for writing this update is that the LSM9DS1 chip has several settings that can be used to tweak the measurement +results. The sensors are not calibrated and the output may vary per instance of the chip. +In my case the magnetic field offset was larger than the Earth magnetic field. The gyroscope offset of 3 deg/s does not sound +like much, but when trying to track the orientation it corresponds to a full circle misalignment in two minutes. Without +calibration it is impossible to make a working magnetic or gyro compass, artificial horizon etc. + +This new version 2 provides a simple DIY calibration program that gives instructions on how to do measurements. It returns +the parameters on screen so that they can be copy/pasted directly into the code of your sketch. For a rough calibration you +have to do this only once per instance of the chip. But the magnetic field is very easily disturbed. In a different set-up +the chip may return completely different magnetic values. + +In spite of some examples, this library does not prescribe the methods for measuring or calibrating, provide quaternions or +Euler transformations. The development of these is still the task of the user of this library. The examples are just for +learning, but they are not part of the library code itself. + +New for all 9 DOF (degrees of freedom) is the possibility: + to set and get the Output Data Rate (ODR), including fast rate magnetic sampling. The values returned by get...ODR are + now the actual values rather than those in the documentation. + to change the internal full scale setting of the chip (FS) giving it more accuracy at the expence of the range + to change the band width filtering of the chip + to change the output unit + to give it calibration zero offset and slope factors + to change the operational mode (off, Acceleration only, Acceleration + Gyroscope + +The values returned by the read... methods change according to the settings. If left to their default, the output will still +be the same as from version 1.1.0. +The way this is organised is rather unique. (mathematical derivation at the end of this document) + + All the settings and calibration factors are independent of each other. + +This means that +- changing the FS does not change the read... value, giving it more accuracy at the expense of the range. +- calibration of slope and offset factors can be done combined or separately in any following order. +- calibration can be done in any chosen Unit, FS, ODR, the factors copy/pasted in a sketch which on turn can use the LSM9DS1 + in any other combination of Unit, FS or ODR. + + +***************************************************************************************************************************** +***************************************** Naming strategy ********************************************** +***************************************************************************************************************************** + +Keeping the same naming convention of version 1.1.0 resulted in very long names for the new functions, making formulas +difficult to read, increasing the chance of making typo's and it was not always clear what was meant. +For this reason a number of shorter aliases were created most of them following the datasheet: +https://www.st.com/resource/en/datasheet/lsm9ds1.pdf + +Accel for Accelleration, +Gyro for Gyroscope, +Magnet for MagneticField, +ODR for SampleRate (= Output Data Rate), +FS for FullScale, +BW for BandWdth, +addition of "set" and "get" in the names of ODR, BW and FS functions. + +e.g. magneticFieldSampleRate still works, but in the library code it is now getMagnetODR reflecting that it is not longer +a constant but a function corresponding to the LSM9DS1 chip setting. + +Not used were the documentation's XL, M and G since it may confuse with gravity, Gauss and of course the size of clothes. :) + + +***************************************************************************************************************************** +********************************** Output of Read method **************************************** +***************************************************************************************************************************** + +Measuring the offset shows that it scales with the chip internal full scale setting (IFS). That means that it is caused +by the internal transducer and not by the DAC. So it is sufficient to calibrate for just one of the full scale settings +and compensate for the others by means of a multiplication. + +The output of the read methods for each of the 9 DOF is now + + Read = Unit * Slope *( (FS / 32786) * Data - Offset ) + +Data = the measurement value showing up on the chip registers +FS = the in Program Full Scale setting (float LSM9DS1Class::get...FS() ) counteracting the internal chip setting so that + the output result remains unchanged. +Unit = the unit the measured physical property is expressed in. +Slope and Offset = calibration parameters. +Note that the read method still produces the same output as in library version 1.01 on the condition that Slope = 1; +Offset=0; and Unit set to its default value. + +There are several ways in which a linear correction can be applied. The chosen method has the highest amount of advantages. +The offset and slope are independent of each other and of any of the other settings in the program. They can be measured +independently and really counteract the internal transducer differences. (For mathematical derivation see below) +All Unit factors equal 1 for their default settings. + + +***************************************************************************************************************************** +********************************** Calibration **************************************** +***************************************************************************************************************************** + +In the text below ... stands for any of the three measurement properties, Accell, Gyro, Magnet. + +For a full calibration we must find a set of two factors (Slope and Offset) for each property ... and each of the three +directions (x, y, z). So in total 18 calibration factors. + +Following the procedures below, the calibration values are stored in the arrays ...Offset[3]={0,0,0} and ...Slope[3]={1,1,1} +Should you want to use these values again in a sketch, it's up to you to print them and put them in program code. +The library is designed in such a way that the stored values don't depend on any of the settings in the program, like ...Unit, +...SR (sample rate), ...FS (full scale). So changing any of the settings before or after restoring their values in the +arrays has no effect on the status of being calibrated. + +********************************************* Offset ********************************************* + +In order to find the value of Offset we must do a zero point measurement. That means that the physical property ... +we are trying to measure should actually result in a value of 0. E.g. keeping the board still should result in zero +gyroscope values for x,y and z. For acceleration the two axes perpendicular to the Earth gravity should be zero. + +An offset calibration involves three steps +1 set the offset factors to 0, using the set...Offset method +2 do zero-point measurements with the read... method +3 store the measured ReadResults using the same set...Offset method to make the calibration effective. + +ad.1: in your sketch: IMO.set...Offset(0,0,0); +ad.2: The readResult should probably be the average value of a number of measurements +ad.3: in your sketch: IMO.set...Offset(resultX,resultY,resultZ); + +Alternatively if it is difficult to get a zero property, you could try to find the maximum and minimum values and +use the point in the middle + + readResult = ( Read_max + Read_min ) / 2 + +This is probably more complex than what it looks like. Both Read_min and Read_max can best be some sort of average, but +if you simply use the min() and max() procedures, the final results are just one measurement each. The chances are high +that these are the worst measurements. +Calculating separate averages of the min and max values, is like a chicken and egg. Before the calibration program can +decide to which average a measurement belongs, it needs a rough calibration first. +The best method is probably 3D elliptical regression, where the values of Offset correspond to the centre of the +elliptoid. So far I did not venture into the mathematics of this. :0 + +********************************************* Slope ********************************************* + +Slope is a dimensionless number that compensates for the sensitivity of the chip's internal transducer. In case it is not +possible to measure this, best leave it at the value 1. For Magnet and Accel this is probably allright, but for Gyro the +sensitivity matters if you want to keep track of orientation. + +A slope calibration involves three steps +1 set the offset factor to 1, using the set...Slope method +2 do slope measurements with the read... method +3 store the readResult using the same set...Slope method. + +ad.1: in your sketch: IMO.set...Slope(1,1,1); +ad.2: The read result should probably be two different averages of a number of measurements each +ad.3: in your sketch: IMO.set...Slope(resultX,resultY,resultZ) + +In order to calibrate the Slope parameter at least two measurements (say 1 and 2) must be done where the physical quantity, +(let's call it Q), has a known difference, so Q_1 - Q_2 = known value. + +The value of slope follows from + + Result = abs (( Q_1 - Q_2) / ( Read_1 - Read_2 )) + +E.g. the Earth gravity should produce a value of 1g. Holding the board upside down should measure -1g. So the difference + ( Q_1 - Q_2) = 2g +The local strength of the magnetic field (in nT) can be found at +https://en.wikipedia.org/wiki/Earth%27s_magnetic_field + + +*************************************** Offset and Slope Combined ********************************************* + +With the above methods Slope and Offset can be measured independently. It does not matter which procedure comes first, +as long as you don't change any of the settings between measuring and assigning. This could accidently happen in case +of a combined measurement by setting the value of Slope before that of Offset. +Note that the dimensionless stored Offset values differ from the Read measurements by a factor (Unit * Slope). + + +A safe following order of steps is +1 set the Slope factors to 1, set...Slope(1,1,1); +2 set the Offset factors to 0, set...Offset(0,0,0); +3 do the measurements with the read... method +4 First store the Offset results using set...Offset +5 Store the Slope results second using set...Slope + +Example +Lets assume that readAccel produces values of 1.3 and - 0.9 + + Offset = (1.3 + (-0.9)) / 2 = 0.2 + Slope = (1 - (-1)) / (1.3 - (-0.9) = 2 / 2.2 = 0.90909 + +Note that set...Offset stores the measured values as ReadResult/(Unit * Slope). +If you store Slope first, the Offset becomes 0.2/0.90909 = 0.22 + +***************************************************************************************************************************** +********************************** Overview of Code **************************************** +***************************************************************************************************************************** + +(almost) unchanged + int begin(); + void end(); + void setContinuousMode(); + void setOneShotMode(); + virtual int accelAvailable(); // Number of samples in the FIFO. + virtual int gyroAvailable(); // Number of samples in the FIFO. + virtual int magnetAvailable(); // Number of samples in the FIFO. + +existing functions changed for new functionality. Results reflect calibration, full scale and unit settings + virtual int readAccel(float& x, float& y, float& z); // Results are in G (earth gravity) or m/s2. + virtual int readGyro(float& x, float& y, float& z); // Results are in degrees/second or rad/s. + virtual int readMagnet(float& x, float& y, float& z); // Results are in uT (micro Tesla). + +existing functions that return a previously measured value + virtual float getAccelODR(); // Sampling rate of the sensor (Hz). + virtual float getGyroODR(); // Sampling rate of the sensor (Hz). + virtual float magnetODR(); // Sampling rate of the sensor (Hz). + +New the possibility to change the ODR registers (Output Data Rate) + virtual int setAccelODR(int8_t range); // 0:off, 1:10Hz, 2:50Hz, 3:119Hz, 4:238Hz, 5:476Hz, 6:952Hz + virtual int setGyroSR(int8_t range); // 0:off, 1:10Hz, 2:50Hz, 3:119Hz, 4:238Hz, 5:476Hz, 6:952Hz + virtual int setMagnetSR(int8_t range) // range (0..7) corresponds to {0.625,1.25,2.5,5,10,20,40,80,400}Hz + +Note: The 952Hz Accel and Gyro ODR does not seem to work. It's true value is close to setting 5. +Note: The Magnetic 400Hz setting corresponds to the chip's fast rate setting +Note: Changing any of the settings quickly measures the actual ODR value for the get...ODR to return. + +New constants used in ..Unit setting +#define GAUSS 0.01 +#define MICROTESLA 1.0 // default +#define NANOTESLA 1000.0 +#define GRAVITY 1.0 // default +#define METERPERSECOND2 9.81 +#define DEGREEPERSECOND 1.0 //default +#define RADIANSPERSECOND 3.141592654/180 +#define REVSPERMINUTE 60.0/360.0 +#define REVSPERSECOND 1.0/360.0 + +Unitsettings that read returns measurement results in. + float accelUnit = GRAVITY; // GRAVITY OR METERPERSECOND2 + float gyroUnit = DEGREEPERSECOND; // DEGREEPERSECOND, RADIANSPERSECOND, REVSPERMINUTE, REVSPERSECOND + float magnetUnit = MICROTESLA; // GAUSS MICROTESLA NANOTESLA + +methods for internal use + int getOperationalMode(); //0=off , 1= Accel only , 2= Gyro +Accel + float measureAccelGyroODR(unsigned int duration); + float measureMagnetODR(unsigned int duration); + +Calibration parameters Slope ans Offset : See Calibration. + float accelOffset[3] = {0,0,0}; // zero point offset correction factor for calibration + float gyroOffset[3] = {0,0,0}; // zero point offset correction factor for calibration + float magnetOffset[3] = {0,0,0};// zero point offset correction factor for calibration + float accelSlope[3] = {1,1,1}; // slope correction factor for calibration + float gyroSlope[3] = {1,1,1}; // slope correction factor for calibration + float magnetSlope[3] = {1,1,1}; // slope correction factor for calibration + +Methods for setting the calibration + virtual void setAccelOffset(float x, float y, float z); + virtual void setAccelSlope(float x, float y, float z); + virtual void setGyroOffset(float x, float y, float z); + virtual void setGyroSlope(float x, float y, float z); + virtual void setMagnetOffset(float x, float y, float z); + virtual void setMagnetSlope(float x, float y, float z); + + +New: changing the full scale sensitivity of the sensors. +The functions modify the FS (full scale) registers of the LSM9DS1 chip changing sensitivity at the expence of range. +Changing this setting does not change the x,y,z output of the read functions, but assigns just more or less bits +to the sensor measurement. + virtual int setAccelFS(uint8_t range); // 0: ±2g ; 1: ±24g ; 2: ±4g ; 3: ±8g + virtual int setGyroFS(int8_t range); // 0= ±245 dps; 1= ±500 dps; 2= ±1000 dps; 3= ±2000 dps + virtual int setMagnetFS(int8_t range); // 0=400.0; 1=800.0; 2=1200.0 , 3=1600.0 (µT) + +*note* According to the data sheet gyroscope setting 2 = 1000 dps should not be available. For some reason it worked + like a charm on my BLE Sense board, so I added the possibility. + +New functions return the Full Scale setting of the corresponding DOF as set with the corresponding set...FS functions + virtual float getAccelFS(); // Full Scale setting (output = 2.0, 24.0 , 4.0 , 8.0) + virtual float getGyroFS(); // output = 245.0, 500.0 , 1000.0, 2000.0) + virtual float getMagnetFS(); // output 400.0 ; 800.0 ; 1200.0 , 1600.0 + +Note: According to the datasheet setAccelFS(1) should correspoond to 16g. Measurement showed that it is actually 24g + but that the sensor maxes out at 20g. Since the actual value is used in a calculation the value of 24g is returned + by getAccelFS for that setting. + +The band with routines were added as an attempt to dampen a nasty spike that existed in the Gyro signal. It had no +observable effect. The methods are provided as is. + virtual float setAccelBW(uint8_t range); //0,1,2,3 Override autoBandwidth setting see doc.table 67 + virtual float getAccelBW(); //Bandwidth setting 0,1,2,3 see documentation table 67 + virtual int setGyroBW(uint8_t range); //Bandwidth setting 0,1,2,3 see documentation table 46 and 47 + virtual float getGyroBW(); //Bandwidth setting 0,1,2,3 see documentation table 46 and 47 + + + + +***************************************************************************************************************************** +********************************** Derivation of linear correction **************************************** +***************************************************************************************************************************** + +Sorry for the very formal derivation below. It suits verifiability but probably only my own purpose :) +It took a lot of puzzling to get it right. Don't read it if you don't want to. :( + +******************************************* Offset *************************************************** + +Assuming good linearity of the transducer, we can model the data output of the chip as + + Data = (32768 / IFS) *( A*Q + B) (1) + +Data = the measured value showing up on the chip registers +Q = the actual physical quantity we are trying to measure in any of the 9 DOF +IFS = the chip Internal Fullscale Setting. +A,B unknown constants representing chip instance differences + +Since the chip outputs dimensionless bits and bytes only, the dimensions of IFS and B must equal the dimension of Q. + +The challenge is to get rid of the unknown constants A and B and translate them into measurable quantities produced by the +library's Read methods. Since a good calibrated Read should produce a number equal to the actual physical quantity +we can state + + Read = Q + +Further, we do not want to recalibrate when we change the Full Scale setting or the Unit. + +Define +PFS = the in-program Full Scale function counteracting the IFS so that the output result remains unchanged. + (dimensionless, but its value corresponds to that of the chosen default unit) +Slope = in-program correction factor for the sensor sensitivity +Offset = in-program correction factor for the sensor zero point offset + +The output of the read methods is (see above) + + Read = Unit * Slope * (PFS / 32786 * Data - Offset ) (2) + +Substitute eq(1) + + Read = Unit * slope * (PFS / IFS * 32786/32786 * ( A*Q + B ) - Offset ) + + Read = Unit * slope * (PFS / IFS * ( A*Q + B ) - Offset ) (3) + +In case of the calibrated zero point measurement Q = Read = 0 +Substitute in eq.(3) we get + + 0 = Unit * slope * (PFS / IFS * ( A*0 + B ) - Offset ) + + Unit * slope * Offset = Unit * slope * PFS / IFS * B (4) + +For an uncalibrated measurement of a zero point (ZP) filling in Offset=0 and Q=0 in eq(3) we get + + Read_uncalibrated_ZP = Unit * slope * PFS / IFS * B (5) + +The righthand terms in equation (4) and (5) are identical so it follows that + + Offset = read_uncalibrated_ZP / (Unit * slope) (6) + +This defines how we should do the calibration measurements. In the library the methods called set...Offset +use of eq(6) to assign the uncalibrated zero-point read values to the corresponding program parameters. +Eq.(6) suggests that Offset depends on Unit and Slope, but this is not the case as the Read method scales +with the same value. To proof this we write eg(4) in a different form + + Offset = (Unit * Slope) / (Unit * Slope) * PFS/IFS * B (7) + +Further since the dimensionless PFS counteracts IFS in size +and the dimension of IFS equals that of Q, the ratio PFS/IFS is 1/Unit. +or in other words + + Unit * PFS /IFS = 1 (8) + +eq(7) reduces to + + Offset = B / Unit = B_dimensionless (9) + +So Offset equals the dimensionless form of B and does not depend on any other parameter. + + +******************************************** Slope *************************************************** + +In order to calibrate the Slope at least two measurements (say 1 and 2) must be done where the measured quantity Q +has a known difference. The calibrated Read equals Q so + + Q_1 - Q_2 = Read_1 - Read_2 = known value (10) + +Substitute eq(2) + + Q_1 - Q_2 = Unit*Slope*(PFS/32786*Data_1 - Offset) - Unit*Slope*(PFS/32786*Data_2 - Offset) + + = Unit*Slope*(PFS/32786*(Data_1 - Data_2) (11) + +So the difference between the measurements gets rid of the Offset +For an uncalibrated measurement we must set Slope = 1. +Eq(2) becomes + + Read_uncalibrated = Unit * (PFS / 32786 * Data - Offset ) + +In eq(11) we get + + Q_1 -Q_2 = Slope * ( Read_uncalibrated_1 - Read_uncalibrated_2) + + Slope = (( Read_uncalibrated_1 - Read_uncalibrated_2) / (Q_1 -Q_2) (12) + +So in order to measure the slope we must first set the Slope parameter to 1. + +In order to prove that Slope is independent of all the other program parameters we substitute eq(1) in eq(11) + + Q_1 - Q_2 = Unit*Slope*(PFS/32786)*(32786/IFS)*(A*Q1 +B - A*Q2 -B)) + + (Q_1 - Q_2) = Slope* Unit*(PFS/IFS)* A *(Q1 - Q2) (12) + +and with eq(8) + + ( 1 ) = Slope * 1 * A *( 1 ) + + Slope = 1 / A + +So Slope only depends on A, the (in)sensitivity of the sensor. The proportionality is inverse since Slope is the +compensation factor for the chip's insensitivity + +QED diff --git a/src/LSM9DS1.cpp b/src/LSM9DS1.cpp index f418a08..de69b01 100644 --- a/src/LSM9DS1.cpp +++ b/src/LSM9DS1.cpp @@ -1,5 +1,12 @@ -/* +/* This file is part of the Arduino_LSM9DS1 library. + New version written by Femme Verbeek, Pijnacker, the Netherlands + Released to the public domain + version 2 + Release Date 5 june 2020 + + Original notice: + Copyright (c) 2019 Arduino SA. All rights reserved. This library is free software; you can redistribute it and/or @@ -16,9 +23,7 @@ License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - Modifications by Femme Verbeek, Pijnacker, the Netherlands 23 may 2020, - Released to the public domain - version 2.0.0 + */ @@ -81,10 +86,12 @@ int LSM9DS1Class::begin() writeRegister(LSM9DS1_ADDRESS_M, LSM9DS1_CTRL_REG1_M, 0xb4); // Temperature compensation enable, medium performance, 20 Hz writeRegister(LSM9DS1_ADDRESS_M, LSM9DS1_CTRL_REG2_M, 0x00); // 4 Gauss writeRegister(LSM9DS1_ADDRESS_M, LSM9DS1_CTRL_REG3_M, 0x00); // Continuous conversion mode - setGyroODR(3); + setGyroODR(3); //119Hz set initial shared ODR value of accel and Gyro + setMagnetODR(5); //20Hz set initial ODR value return 1; } + void LSM9DS1Class::setContinuousMode() { // Enable FIFO (see docs https://www.st.com/resource/en/datasheet/DM00103319.pdf) writeRegister(LSM9DS1_ADDRESS, 0x23, 0x02); @@ -115,19 +122,45 @@ void LSM9DS1Class::end() float LSM9DS1Class::measureAccelGyroODR(unsigned int duration) { if (getOperationalMode()==0) return 0; float x, y, z; //dummies + unsigned long lastEventTime, count = 0; + int fifoEna=continuousMode; //switch off FiFo + setOneShotMode(); + duration *=1000; //switch to micros + while (count<2) //throw away nr of samples, fifo enabled would be count<33; + { if (accelAvailable()) + { readAccel(x, y, z); // empty read buffer and wait till current measurement is finished, empty again + count++; + } + } + count=0; + unsigned long start = micros(); + while ((micros()- start) < duration) // measure + { if (accelAvailable()) + { readAccel(x, y, z); + count++; + lastEventTime = micros(); + } + } +// Serial.print(" Count "+String( count ) ); + if (fifoEna) setContinuousMode(); + return (1000000.0*float(count)/float(lastEventTime-start) ); +} + +float LSM9DS1Class::measureMagnetODR(unsigned int duration) +{ float x, y, z; //dummies unsigned long lastEventTime, count = 0; duration *=1000; //switch to micros while (count<2) //throw away nr of samples - { if (IMU.accelAvailable()) - { IMU.readAccel(x, y, z); // empty read buffer + { if (magnetAvailable()) + { readMagnet(x, y, z); // empty read buffer and wait till current measurement is finished, empty again count++; } } count=0; unsigned long start = micros(); while ((micros()- start) < duration) // measure - { if (IMU.accelAvailable()) - { IMU.readAccel(x, y, z); + { if (magnetAvailable()) + { readMagnet(x, y, z); count++; lastEventTime = micros(); } @@ -136,8 +169,7 @@ float LSM9DS1Class::measureAccelGyroODR(unsigned int duration) return (1000000.0*float(count)/float(lastEventTime-start) ); } - -//************************************ Accelleration ***************************************** +//************************************ Acceleration ***************************************** int LSM9DS1Class::readAccel(float& x, float& y, float& z) { int16_t data[3]; @@ -182,7 +214,10 @@ void LSM9DS1Class::setAccelOffset(float x, float y, float z) } //Slope is already dimensionless, so it can be stored as is. void LSM9DS1Class::setAccelSlope(float x, float y, float z) -{ accelSlope[0] = x ; +{ if (x==0) x=1; //zero slope not allowed + if (y==0) y=1; + if (z==0) z=1; + accelSlope[0] = x ; accelSlope[1] = y ; accelSlope[2] = z ; } @@ -220,30 +255,31 @@ float LSM9DS1Class::getAccelODR() } float LSM9DS1Class::setAccelBW(uint8_t range) //0,1,2,3 Override autoBandwidth setting see doc.table 67 -{ range = range & 0b00000011; - uint8_t RegIs = readRegister(LSM9DS1_ADDRESS, LSM9DS1_CTRL_REG6_XL) & 0b11111000; - RegIs = RegIs | 0b00000100 | range ; - return writeRegister(LSM9DS1_ADDRESS, LSM9DS1_CTRL_REG6_XL,RegIs) ; +{ if (range >=4) return 0; + uint8_t RegIs = readRegister(LSM9DS1_ADDRESS, LSM9DS1_CTRL_REG6_XL) & 0b11111000; + RegIs = RegIs | 0b00000100 | (range & 0b00000011) ; + return writeRegister(LSM9DS1_ADDRESS, LSM9DS1_CTRL_REG6_XL,RegIs) ; } float LSM9DS1Class::getAccelBW() //Bandwidth setting 0,1,2,3 see documentation table 67 -{ float autoRange[] ={0.0, 408.0, 408.0, 50.0, 105.0, 211.0, 408.0, 0.0 }; - float BWXLRange[] ={ 408.0, 211.0, 105.0, 50.0 }; - uint8_t RegIs = readRegister(LSM9DS1_ADDRESS, LSM9DS1_CTRL_REG6_XL); - if (bitRead(2,RegIs)) return BWXLRange [RegIs & 0b00000011]; - else return autoRange [ RegIs >> 5 ]; +{ float autoRange[] ={0.0, 408.0, 408.0, 50.0, 105.0, 211.0, 408.0, 0.0 }; + float BWXLRange[] ={ 408.0, 211.0, 105.0, 50.0 }; + uint8_t RegIs = readRegister(LSM9DS1_ADDRESS, LSM9DS1_CTRL_REG6_XL); + if (bitRead(RegIs,2)) return BWXLRange [RegIs & 0b00000011]; + else return autoRange [ RegIs >> 5 ]; } int LSM9DS1Class::setAccelFS(uint8_t range) // 0: ±2g ; 1: ±16g ; 2: ±4g ; 3: ±8g -{ range = (range & 0b00000011) << 3; +{ if (range >=4) return 0; + range = (range & 0b00000011) << 3; uint8_t setting = ((readRegister(LSM9DS1_ADDRESS, LSM9DS1_CTRL_REG6_XL) & 0xE7) | range); return writeRegister(LSM9DS1_ADDRESS, LSM9DS1_CTRL_REG6_XL,setting) ; } -float LSM9DS1Class::getAccelFS() // Full scale (output = 2.0, 16.0 , 4.0 , 8.0) -{ float ranges[] ={2.0, 16.0, 4.0, 8.0}; //g - uint8_t setting = (readRegister(LSM9DS1_ADDRESS, LSM9DS1_CTRL_REG6_XL) & 0x18) >> 3; - return ranges[setting] ; +float LSM9DS1Class::getAccelFS() // Full scale dimensionless, but its value corresponds to g +{ float ranges[] ={2.0, 24.0, 4.0, 8.0}; //g + uint8_t setting = (readRegister(LSM9DS1_ADDRESS, LSM9DS1_CTRL_REG6_XL) & 0x18) >> 3; + return ranges[setting] ; } //************************************ Gyroscope ***************************************** @@ -282,7 +318,10 @@ void LSM9DS1Class::setGyroOffset(float x, float y, float z) } //Slope is already dimensionless, so it can be stored as is. void LSM9DS1Class::setGyroSlope(float x, float y, float z) -{ gyroSlope[0] = x ; +{ if (x==0) x=1; //zero slope not allowed + if (y==0) y=1; + if (z==0) z=1; + gyroSlope[0] = x ; gyroSlope[1] = y ; gyroSlope[2] = z ; } @@ -294,8 +333,6 @@ int LSM9DS1Class::getOperationalMode() //0=off , 1= Accel only , 2= Gyro +Accel else return 2; } - - // range ==0 : switch off gyroscope - write 0 in CTRL_REG1_G; // range !0 : switch on Accel+Gyro mode- write in CTRL_REG6_XL and CTRL_REG1_G; @@ -331,7 +368,8 @@ float LSM9DS1Class::getGyroODR() } int LSM9DS1Class::setGyroBW(uint8_t range) -{ range = range & 0b00000011; +{ if (range >=4) return 0; + range = range & 0b00000011; uint8_t setting = readRegister(LSM9DS1_ADDRESS, LSM9DS1_CTRL_REG1_G) & 0b11111100; return writeRegister(LSM9DS1_ADDRESS, LSM9DS1_CTRL_REG1_G,setting | range) ; } @@ -356,12 +394,13 @@ float LSM9DS1Class::getGyroBW() } int LSM9DS1Class::setGyroFS(uint8_t range) // (0: 245 dps; 1: 500 dps; 2: 1000 dps; 3: 2000 dps) -{ range = (range & 0b00000011) << 3; - uint8_t setting = ((readRegister(LSM9DS1_ADDRESS, LSM9DS1_CTRL_REG1_G) & 0xE7) | range ); - return writeRegister(LSM9DS1_ADDRESS, LSM9DS1_CTRL_REG1_G,setting) ; +{ if (range >=4) return 0; + range = (range & 0b00000011) << 3; + uint8_t setting = ((readRegister(LSM9DS1_ADDRESS, LSM9DS1_CTRL_REG1_G) & 0xE7) | range ); + return writeRegister(LSM9DS1_ADDRESS, LSM9DS1_CTRL_REG1_G,setting) ; } -float LSM9DS1Class::getGyroFS() // +float LSM9DS1Class::getGyroFS() // dimensionless, but its value defaults to deg/s { float Ranges[] ={245.0, 500.0, 1000.0, 2000.0}; //dps uint8_t setting = (readRegister(LSM9DS1_ADDRESS, LSM9DS1_CTRL_REG1_G) & 0x18) >> 3; return Ranges[setting] ; @@ -404,32 +443,40 @@ void LSM9DS1Class::setMagnetOffset(float x, float y, float z) } //Slope is already dimensionless, so it can be stored as is. void LSM9DS1Class::setMagnetSlope(float x, float y, float z) -{ magnetSlope[0] = x ; +{ if (x==0) x=1; //zero slope not allowed + if (y==0) y=1; + if (z==0) z=1; + magnetSlope[0] = x ; magnetSlope[1] = y ; magnetSlope[2] = z ; } int LSM9DS1Class::setMagnetFS(uint8_t range) // 0=400.0; 1=800.0; 2=1200.0 , 3=1600.0 (µT) -{ range = (range & 0b00000011) << 5; - return writeRegister(LSM9DS1_ADDRESS, LSM9DS1_CTRL_REG2_M,range) ; +{ if (range >=4) return 0; + range = (range & 0b00000011) << 5; + return writeRegister(LSM9DS1_ADDRESS, LSM9DS1_CTRL_REG2_M,range) ; } -float LSM9DS1Class::getMagnetFS() // +float LSM9DS1Class::getMagnetFS() // dimensionless, but its value defaults to µT { const float Ranges[] ={400.0, 800.0, 1200.0, 1600.0}; // uint8_t setting = readRegister(LSM9DS1_ADDRESS, LSM9DS1_CTRL_REG2_M) >> 5; return Ranges[setting] ; } -int LSM9DS1Class::setMagnetODR(uint8_t range) // range (0..7) corresponds to {0.625,1.25,2.5,5.0,10.0,20.0,40.0,80.0}Hz -{ range = (range & 0b00000111) << 2; - uint8_t setting = ((readRegister(LSM9DS1_ADDRESS_M, LSM9DS1_CTRL_REG1_M) & 0b11100011) | range); - return writeRegister(LSM9DS1_ADDRESS_M, LSM9DS1_CTRL_REG1_M,setting) ; +int LSM9DS1Class::setMagnetODR(uint8_t range) // range (0..8) = {0.625,1.25,2.5,5,10,20,40,80,400}Hz +{ if (range >=16) return 0; + uint8_t setting = ((range & 0b00000111) << 2) | ((range & 0b00001000) >> 2); + setting = setting | (readRegister(LSM9DS1_ADDRESS_M, LSM9DS1_CTRL_REG1_M) & 0b11100001) ; + writeRegister(LSM9DS1_ADDRESS_M, LSM9DS1_CTRL_REG1_M,setting) ; + uint16_t duration = 1750 / (range + 1); // 1750,875,666,500,400,333,285,250,222 + magnetODR= measureMagnetODR(duration); } float LSM9DS1Class::getMagnetODR() // Output {0.625, 1.25, 2.5, 5.0, 10.0, 20.0, 40.0 , 80.0}; //Hz -{ const float ranges[] ={0.625, 1.25,2.5, 5.0, 10.0, 20.0, 40.0 , 80.0}; //Hz - uint8_t setting = (readRegister(LSM9DS1_ADDRESS_M, LSM9DS1_CTRL_REG1_M) & 0b00011100) >> 2; - return ranges[setting]; +{ return magnetODR; +// const float ranges[] ={0.625, 1.25,2.5, 5.0, 10.0, 20.0, 40.0 , 80.0}; //Hz +// uint8_t setting = (readRegister(LSM9DS1_ADDRESS_M, LSM9DS1_CTRL_REG1_M) & 0b00011100) >> 2; +// return ranges[setting]; } //************************************ Private functions ***************************************** diff --git a/src/LSM9DS1.h b/src/LSM9DS1.h index 753a0e8..8e4db2c 100644 --- a/src/LSM9DS1.h +++ b/src/LSM9DS1.h @@ -1,5 +1,12 @@ /* + This file is part of the Arduino_LSM9DS1 library. + New version written by Femme Verbeek, Pijnacker, the Netherlands + Released to the public domain + version 2 + Release Date 5 june 2020 + + Original notice: Copyright (c) 2019 Arduino SA. All rights reserved. This library is free software; you can redistribute it and/or @@ -16,9 +23,6 @@ License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - Modifications by Femme Verbeek, Pijnacker, the Netherlands 23 may 2020, - Released to the public domain - version 2.0.0 */ #ifndef LSM9DS1_V2 @@ -75,11 +79,11 @@ class LSM9DS1Class { void setOneShotMode(); int getOperationalMode(); //0=off , 1= Accel only , 2= Gyro +Accel float measureAccelGyroODR(unsigned int duration); + float measureMagnetODR(unsigned int duration); // Accelerometer float accelOffset[3] = {0,0,0}; // zero point offset correction factor for calibration float accelSlope[3] = {1,1,1}; // slope correction factor for calibration float accelUnit = GRAVITY; // GRAVITY OR METERPERSECOND2 - float accelODR; // Stores the actual value of Output Data Rate virtual int readAccel(float& x, float& y, float& z); // Results are in G (earth gravity) or m/s2. virtual int accelAvailable(); // Number of samples in the FIFO. virtual void setAccelOffset(float x, float y, float z); //Store zero-point measurements as offset @@ -88,19 +92,18 @@ class LSM9DS1Class { virtual float getAccelODR(); // Measured Sample Rate of the sensor. virtual float setAccelBW(uint8_t range); //0,1,2,3 Override autoBandwidth setting see doc.table 67 virtual float getAccelBW(); //Bandwidth setting 0,1,2,3 see documentation table 67 - virtual int setAccelFS(uint8_t range); // 0: ±2g ; 1: ±16g ; 2: ±4g ; 3: ±8g - virtual float getAccelFS(); // Full Scale setting (output = 2.0, 16.0 , 4.0 , 8.0) + virtual int setAccelFS(uint8_t range); // 0: ±2g ; 1: ±24g ; 2: ±4g ; 3: ±8g + virtual float getAccelFS(); // Full Scale setting (output = 2.0, 24.0 , 4.0 , 8.0) // Gyroscope float gyroOffset[3] = {0,0,0}; // zero point offset correction factor for calibration float gyroSlope[3] = {1,1,1}; // slope correction factor for calibration float gyroUnit = DEGREEPERSECOND; // DEGREEPERSECOND RADIANSPERSECOND REVSPERMINUTE REVSPERSECOND - float gyroODR; // Stores the actual value of Output Data Rate virtual int readGyro(float& x, float& y, float& z); // Results are in degrees/second or rad/s. virtual int gyroAvailable(); // Number of samples in the FIFO. virtual void setGyroOffset(float x, float y, float z); //Store zero-point measurements as offset virtual void setGyroSlope(float x, float y, float z); //Store measurements as slope - virtual int setGyroODR(uint8_t range); //Sampling Rate 0:off, 1:10Hz, 2:50Hz, 3:119Hz, 4:238Hz, 5:476Hz, 6:952Hz + virtual int setGyroODR(uint8_t range); //Sample Rate Hz 0:off,1:10,2:50 3:119,4:238,5:476,6:does not work 952Hz virtual float getGyroODR(); // Measured Sample rate of the sensor. virtual int setGyroBW(uint8_t range); //Bandwidth setting 0,1,2,3 see documentation table 46 and 47 virtual float getGyroBW(); //Bandwidth setting 0,1,2,3 see documentation table 46 and 47 @@ -111,16 +114,19 @@ class LSM9DS1Class { float magnetOffset[3] = {0,0,0}; // zero point offset correction factor for calibration float magnetSlope[3] = {1,1,1}; // slope correction factor for calibration float magnetUnit = MICROTESLA; // GAUSS or MICROTESLA - virtual int readMagnet(float& x, float& y, float& z); // Default results are in uT (micro Tesla) + virtual int readMagnet(float& x, float& y, float& z); // Default results are in µT (micro Tesla) virtual int magnetAvailable(); // Number of samples in the FIFO. virtual void setMagnetOffset(float x, float y, float z); //Store zero-point measurements as offset virtual void setMagnetSlope(float x, float y, float z); //Store measurements as slope - virtual int setMagnetODR(uint8_t range); // Sampling rate (0..7) corresponds to {0.625,1.25,2.5,5.0,10.0,20.0,40.0,80.0}Hz + virtual int setMagnetODR(uint8_t range); // Sampling rate (0..8)->{0.625,1.25,2.5,5.0,10,20,40,80,400}Hz virtual float getMagnetODR(); // Sampling rate of the sensor in Hz. - virtual int setMagnetFS(uint8_t range); // 0=400.0; 1=800.0; 2=1200.0 , 3=1600.0 (µT) + virtual int setMagnetFS(uint8_t range); // 0=±400.0; 1=±800.0; 2=±1200.0 , 3=±1600.0 (µT) virtual float getMagnetFS(); // get chip's full scale setting private: + float accelODR; // Stores the actual value of Output Data Rate + float gyroODR; // Stores the actual value of Output Data Rate + float magnetODR; // Stores the actual value of Output Data Rate bool continuousMode; int readRegister(uint8_t slaveAddress, uint8_t address); int readRegisters(uint8_t slaveAddress, uint8_t address, uint8_t* data, size_t length); From 93a80a0346a505f358242b4393a4808554ea300b Mon Sep 17 00:00:00 2001 From: FemmeVerbeek Date: Mon, 15 Jun 2020 18:10:18 +0200 Subject: [PATCH 11/15] readRaw, Readme, Getting Started, RPM&RevCounter DIY_calibration was simplified. Instruction video (https://youtu.be/BLvYFXoP33o) Addition of readRaw methods for calibration. read... uses reeadRaw in formula. Example sketches RPM_meter_Rev_Counter, Water_Leveler, XY_Compass SRC: measure...ODR is now private --- CHANGELOG | 6 +- Getting Started.md | 59 ++ examples/DIY_Calibration/DIY_Calibration.ino | 444 +++++++++++++++ .../LSM9DS1_DIY_Calibration.ino | 380 ------------- .../RPM_Meter_Rev_Counter.ino | 74 +++ .../RegisterTest.ino} | 420 +++++++------- .../Water_Leveler.ino} | 0 .../XY_compass.ino} | 0 .../Aim axes along magnetic field lines.PNG | Bin 0 -> 330459 bytes images/Boxed sensor.PNG | Bin 0 -> 268868 bytes keywords.txt | 3 + library.properties | 10 +- readme.md | 535 ++++++++++++++++++ readme.txt | 426 -------------- src/LSM9DS1.cpp | 208 +++---- src/LSM9DS1.h | 15 +- 16 files changed, 1455 insertions(+), 1125 deletions(-) create mode 100644 Getting Started.md create mode 100644 examples/DIY_Calibration/DIY_Calibration.ino delete mode 100644 examples/LSM9DS1_DIY_Calibration/LSM9DS1_DIY_Calibration.ino create mode 100644 examples/RPM_Meter_Rev_Counter/RPM_Meter_Rev_Counter.ino rename examples/{LSM9DS1_RegisterTest/LSM9DS1_RegisterTest.ino => RegisterTest/RegisterTest.ino} (97%) rename examples/{LSM9DS1_waterlevel/LSM9DS1_waterlevel.ino => Water_Leveler/Water_Leveler.ino} (100%) rename examples/{LSM9DS1_XY_compass/LSM9DS1_XY_compass.ino => XY_compass/XY_compass.ino} (100%) create mode 100644 images/Aim axes along magnetic field lines.PNG create mode 100644 images/Boxed sensor.PNG create mode 100644 readme.md delete mode 100644 readme.txt diff --git a/CHANGELOG b/CHANGELOG index 5111c36..8f712c3 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -8,7 +8,7 @@ Arduino_LSM9DS1 1.1.0 - 2020.02.11 * Added support for FIFO continuous reading of values -Arduino_LSM9DS1 2.0.0 - 2020.05.30 +Arduino_LSM9DS1 2.0.0 - 2020.06.15 * Added support for Full scale setting, * Added support for Operational mode: off, Accel only, Gyro + Accel @@ -17,3 +17,7 @@ Arduino_LSM9DS1 2.0.0 - 2020.05.30 * Added support for changing output unit * Added support for separate or combined sensor calibration * Calibration parameters are dimensionless, independent of each other and of the other settings +* Includes a DIY calibration program that produces copy/paste-able code +* Inclues readme.md and Getting Started.md +* Inclues examples RPM_meter_Rev_Counter, Water_Leveler, XY_Compass +* Inclues Register_test: demonstrates and verifies all new settings \ No newline at end of file diff --git a/Getting Started.md b/Getting Started.md new file mode 100644 index 0000000..553b598 --- /dev/null +++ b/Getting Started.md @@ -0,0 +1,59 @@ +# Getting started with LSM9DS1 V2 library + +The library provides methods to get IMU data out of the LSM9DS1 chip and was developed on an +Arduino Nano 33 BLE Sense board. +This V2 library was designed to replace the older version 1.01 +More information about the LSM9DS1 chip can be found in the [datasheet](https://www.st.com/resource/en/datasheet/lsm9ds1.pdf) + +## Installation + +In the Arduino IDE select: *Sketch \ Include Library \ Add .ZIP Library* and point to the location where the .Zip file is stored. +When the library has been added to the Arduino library list, it will be possible to use the +Library manager as well. + +If there was a previous version of the LSM9DS1 library already installed you should probably delete or remove that first +from the Arduino library installation directory + +..../Arduino/libraries/Arduino_LSM9DS1 + +## Calibration + +If you want to make use of the new calibration possibilities run the interactive example sketch +DIY_Calibration first. Follow the directions on the screen of the serial monitor. Copy the code +from the screen into the setup() of your sketch. +See [instruction video](https://youtu.be/BLvYFXoP33o) + +## Use any of the new setting possibilities by placing commands in your sketch +All the "set" methods have a corresponding "get" function. + +**Choose the Output Data Rate** +``` +(range)= (0..5) -> { off, 10, 50, 119, 238, 476} Hz default = 119hz + IMU.setAccelODR(range); + IMU.setGyroODR (range); + +(range)= (0..8) -> {0.625, 1.25, 2.5, 5, 10, 20, 40, 80, 400} Hz default = 20hz +IMU.setMagnetODR(range); +``` + +**Choose the Full Scale setting** +``` + IMU.setAccelFS(range); // 0: ±2g ; 1: ±24g ; 2: ±4g ; 3: ±8g + IMU.setGyroFS(range); // (0= ±245, 1= ±500, 2= ±1000, 3= ±2000) °/s + IMU.setMagnetFS(range); // 0=±400.0; 1=±800.0; 2=±1200.0 , 3=±1600.0 (µT) +``` + +**Choose the unit you want to get the output in** +``` + IMU.accelUnit = GRAVITY; // GRAVITY OR METERPERSECOND2 + IMU.gyroUnit = DEGREEPERSECOND; // DEGREEPERSECOND RADIANSPERSECOND REVSPERMINUTE REVSPERSECOND + IMU.magnetUnit = MICROTESLA; // GAUSS, MICROTESLA NANOTESLA +``` +**Choose a BandWidth filter** +For advanced users only +``` + IMU.setAccelBW(range); //0,1,2,3 Override autoBandwidth setting see doc.table 67 + IMU.setGyroBW(range); //Bandwidth setting 0,1,2,3 see doc. table 46 and 47 + +``` + diff --git a/examples/DIY_Calibration/DIY_Calibration.ino b/examples/DIY_Calibration/DIY_Calibration.ino new file mode 100644 index 0000000..67591fc --- /dev/null +++ b/examples/DIY_Calibration/DIY_Calibration.ino @@ -0,0 +1,444 @@ +/* DIY calibration program for the LSM9DS1 chip + * + * Follow the instructions on the screen how to do calibration measurements. + * See instruction video https://youtu.be/BLvYFXoP33o + * No special tools or setups are needed, however it is handy if the board with the LSM9DS1 chip is fitted inside + * a non-metalic rectangular box. + * The offset and slope factors are displayed on screen as code that can be copy/pasted directly into a sketch. + * Each new instance of the chip will require it's own unique set of calibration factors. + * + * written by Femme Verbeek 30-5-2020 + * + * This program uses V2 of the LSM9DS1 library + * Tested on an Arduino Nano 33 BLE Sense board. + */ + +#include + +// not really my habit to use so many global variabeles but WTH this is still a small program +const float gyroSlopeCriterion = 50; +const float accelCriterion = 0.1; +float EarthMagnetStrength = 49.0; //= µT +float EarthMagnetInclination = 67.0; //= degree +char xyz[3]= {'X','Y','Z'}; +float maxAX = 1, maxAY=1, maxAZ=1, minAX=-1, minAY=-1, minAZ=-1; // Accel Slope +float zeroAX1 =0,zeroAX2 =0,zeroAY1 =0,zeroAY2 =0,zeroAZ1 =0,zeroAZ2 =0; //Accel Offset +//boolean accelOffsetOK[4]={false,false,false,false}; +boolean accelOK=false; +uint8_t acceMMlOK=0; // bit 0..2 maxXYZ bit 3..5 minXYZ +boolean gyroOK=false; +boolean gyroOffsetOK=false; +boolean gyroSlopeOK[3]={false,false,false}; +boolean magnetOK=false; + +void setup() { + Serial.begin(115200); + while (!Serial); + pinMode(LED_BUILTIN,OUTPUT); + delay(10); + if (!IMU.begin()) { Serial.println("Failed to initialize IMU!");while (1); } + IMU.setGyroODR(4); //238Hz + IMU.setMagnetODR(7); //80Hz +} + +void loop() +{ MainMenu(); +} + + +void MainMenu() +{ Serial.println("\n\n\n\n\n"); + Serial.println(" DIY Calibration program "); + Serial.println("The board with the LSM9DS1 sensor is best fitted into a non metallic rectangular box with flat sides"); + Serial.println("or find another way to keep the board horizontal or vertical on each of it's sides and rotate it ."); + Serial.println("In the following procedures you'll be asked to rotate the sensor around one of it's axes at the time"); + Serial.println("or simply aim the axis upward and keep still. The simplest way is to put the box with one of its flat"); + Serial.println("sides on the table and turn it by hand. See instruction video https://youtu.be/BLvYFXoP33o"); + Serial.println("To operate the menu in the IDE serial monitor you must press a letter key followed by Enter \n"); + + Serial.print(" Calibrate "); + Serial.print ("\n (A) Accelerometer "); + if (accelOK) Serial.print("-OK-"); + // Serial.print ("\n (O) Gyroscope Offset "); + // if (gyroOffsetOK) Serial.print("-OK-"); + Serial.print ("\n (G) Gyroscope "); + if (gyroOK ) Serial.print("-OK-"); + Serial.print ("\n (M) Magnetometer "); + if (magnetOK) Serial.print("-OK-"); + Serial.println("\n\n The code below can be copy/pasted in a sketch"); + + if (accelOK) printParam (" IMU.accelOffset ",IMU.accelOffset); + Serial.println(); + if (accelOK) printParam (" IMU.accelSlope ", IMU.accelSlope); + Serial.println(); + + if (gyroOffsetOK) printParam (" IMU.gyroOffset ", IMU.gyroOffset); + Serial.println(); + if (gyroSlopeOK[0] &&gyroSlopeOK[1] &&gyroSlopeOK[2] ) printParam (" IMU.gyroSlope ", IMU.gyroSlope); + Serial.println(); + if (magnetOK) + { printParam (" IMU.magnetOffset",IMU.magnetOffset); + Serial.println(); + printParam (" IMU.magnetSlope ",IMU.magnetSlope); + } + Serial.println(""); + while (!Serial.available()) ; + char incomingByte = toupper (Serial.read()); // read the incoming byte + if (byte(incomingByte)!=13) Serial.readStringUntil(13); // empty readbuffer + switch (incomingByte) + { case 'A': {calibrateAccelMenu(); break;} +// case 'G': {calibrateGyroOffset(); break;} + case 'G': {calibrateGyroMenu(); break;} + case 'M': {calibrateMagnetMenu(); break;} + default : {Serial.println("I received: "+String(incomingByte)); break;} + } +} + +void printParam(String txt, float param[3]) +{ for (int i= 0; i<=2 ; i++) + { Serial.print(txt+"["); + Serial.print(String(i)+"] = "); + Serial.print(String(param[i],6)+";"); + } +} + +//********************************************************************************************************************************** +//********************************************* Accelerometer ********************************************** +//********************************************************************************************************************************** + +void calibrateAccelMenu() +{char incomingByte = 0; + while (incomingByte!='X') + { Serial.println("\n\n"); + Serial.println("Calibrate Accelerometer Offset and Slope"); + Serial.println("Place the board on a horizontal surface with one of its axes vertical. Each of the axes must be measured "); + Serial.println("pointing up and pointing down, so a total of 6 measurements. "); + Serial.println("The program recognises which axis is vertical. If the angle is to far oblique the measurement is not valid.\n"); + + Serial.println("Press (C) to start a calibration measurement. "); + Serial.println("Press (X) to exit \n"); + + Serial.println("Measured status"); + for (int i=0;i<=2;i++){ Serial.print(xyz[i]); if (bitRead(acceMMlOK,i)==1)Serial.print("+ = ( -OK- ) "); else Serial.print("+ = not done "); } + Serial.println(); + for (int i=0;i<=2;i++){ Serial.print(xyz[i]); if (bitRead(acceMMlOK,i+3)==1)Serial.print("- = ( -OK- ) "); else Serial.print("- = not done "); } +// Serial.print ("\nMax values X="+String(maxAX,4)); Serial.print ("\tY="+String(maxAY,4));Serial.println ("\tZ="+String(maxAZ,4)); +// Serial.print ("Min values X="+String(minAX,4)); Serial.print ("\tY="+String(minAY,4));Serial.println ("\tZ="+String(minAZ,4)); + + Serial.println("\n\nCurrent accelerometer calibration values (copy/paste-able)\n"); + printParam(" IMU.accelOffset",IMU.accelOffset); + Serial.println(); + printParam (" IMU.accelSlope ",IMU.accelSlope); + Serial.println("\n\n\n\n"); + while (!Serial.available()) ; // wait for character to be entered + incomingByte = toupper(Serial.read()); + if (byte(incomingByte)!=13) Serial.readStringUntil(13); // empty readbuffer + if ((incomingByte)=='C') calibrateAccelSlope(); + } +} + +void calibrateAccelSlope() +{ boolean validMmt=false; + float x,y,z; + Serial.println("\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n"); + Serial.println("measuring \n"); + IMU.setAccelSlope(1,1,1); + IMU.setAccelODR(5); //476 Hz + raw_N_Accel(2500,x,y,z); + if (abs(x)>max(abs(y),abs(z))) + { Serial.println("X detected"); + if (sqrt(y*y+z*z)/x0) {maxAX=x; + acceMMlOK=acceMMlOK | 0b00000001 ;} + else {minAX=x; + acceMMlOK=acceMMlOK | 0b00001000 ; } + } + } + if (abs(y)>max(abs(x),abs(z))) + { Serial.println("Y detected"); + if (sqrt(x*x+z*z)/y0) {maxAY=y; + acceMMlOK=acceMMlOK | 0b00000010 ; } + else {minAY=y; + acceMMlOK=acceMMlOK | 0b00010000 ; } + } + } + if (abs(z)>max(abs(x),abs(y))) + { Serial.println("Z detected"); + if ( sqrt(x*x+y*y)/z0) {maxAZ=z; + acceMMlOK=acceMMlOK | 0b00000100 ; } + else {minAZ=z; + acceMMlOK=acceMMlOK | 0b00100000 ; } + } + } + IMU.setAccelOffset((maxAX+minAX)/2,(maxAY+minAY)/2,(maxAZ+minAZ)/2); + IMU.setAccelSlope ((maxAX-minAX)/2,(maxAY-minAY)/2,(maxAZ-minAZ)/2); + if (acceMMlOK==0b00111111) accelOK = true; + + if ( !validMmt ) + { Serial.print("\n\n\nNot a valid measurement! "); + Serial.println(" x="+String(x));Serial.print(" y="+String(y));Serial.println(" z="+String(z)); + } +} + + +//********************************************************************************************************************************** +//********************************************* Gyroscope ********************************************** +//********************************************************************************************************************************** + + +void calibrateGyroMenu() +{char incomingByte = 0; +//boolean OffsetCalibrated=false; +float turnangle = 360; + Serial.println("\n\n\n\n\n\n\n\n\n\n\n"); + if (!gyroOffsetOK) + { Serial.println(" Start by calibrating the Offset\n"); // Slope can't be calibrated with an uncalibrated offset + calibrateGyroOffset(); + } + while (incomingByte!='X') + { Serial.println(" Calibrate Gyroscope\n"); + Serial.println("The gyroscope sensor must be calibrated for it's sensitivity (slope). During a slope calibration the "); + Serial.println("board must be rotated calmly about one axis over a known angle. Change the angle to your convenience. "); + Serial.println("A larger angle is more accurate, but more difficult to do. The rotation must be pure, without much"); + Serial.println("rotation about the other two axes. It can be done by hand. Keeping the board on a flat surface with"); + Serial.println("the rotation axis vertical while turning is good enough. For an accurate result you can start and end "); + Serial.println("with its side pushed against a non moving object. Press Enter when finished."); + Serial.println("Each of the axes X,Y and Z must be measured. The program automatically detects which. \n"); + Serial.println(" (A) Change the measuring angle to turn the board"); + Serial.print (" (C) Calibrate Slope, turn the board over "+String(turnangle,0));Serial.println("° and press enter when finished "); + Serial.println(" (O) Calibrate Offset again"); + Serial.println(" (X) eXit to the main menu\n"); + + Serial.println("Offset calibration ( -OK- )"); + Serial.print ("Slope calibration " ); + for (int i= 0; i<=2 ; i++) + { Serial.print(xyz[i]); + if (gyroSlopeOK[i]) Serial.print("= ( -OK- ) "); else Serial.print("= not done "); + } + Serial.println(); + Serial.println("\n Gyroscope calibration parameters"); + printParam(" IMU.gyroOffset ",IMU.gyroOffset); + Serial.println(); + printParam(" IMU.gyroSlope ",IMU.gyroSlope); + Serial.println(); + while (!Serial.available()); // wait for anything to be entered + incomingByte = toupper(Serial.read()); // read char and convert to upcase + if (byte(incomingByte)!=13) Serial.readStringUntil(13); // empty readbuffer + switch (incomingByte) + { case 'A': { readAnswer("\n\nHow many degrees turn for the measurement? ", turnangle); + break;} + case 'C': { Serial.print("\n\n\n\n\n\nMeasuring. Turn the sensor over "+String(turnangle));Serial.println(" degrees\n"); + Serial.println("Press Enter when finished."); + calibrateGyroslope(turnangle); + break;} + case 'O': { calibrateGyroOffset(); } + default : {Serial.println("I received: "+String(incomingByte)); break;} + } + Serial.println(""); + } + Serial.println("\n\n\n\n\n\n\n"); +} + +void calibrateGyroOffset() // don't move the board during calibration +{ float x, y, z;// , addX=0, addY=0, addZ=0 ; + Serial.println("\n\n\n\nMeasuring offset. Just a moment."); + Serial.println("\n\n\n\nKeep the board still during measurement"); + IMU.setGyroODR(5); //476 Hz + raw_N_Gyro(2500,x,y,z); + IMU.setGyroOffset(x, y,z); // Store the average measurements as offset + digitalWrite(LED_BUILTIN, 0); // onboard led off + Serial.print("\n\n\n\n\n\n"); + gyroOffsetOK=true; +} + +void calibrateGyroslope(unsigned int turnangle) // rotate board over known angle +{ // float tempSlope[3]; + boolean validMmt=false; + float dirX=0, dirY=0, dirZ=0,sigmaX2=0,sigmaY2=0,sigmaZ2=0; + float x, y, z; + unsigned int count=0; +// for (int i =0;i<=2;i++) tempSlope[i]= IMU.gyroSlope[i]; +// IMU.setGyroSlope(1,1,1); + while (!Serial.available()) // measure until enter key pressed + { while (!IMU.gyroAvailable()); + IMU.readRawGyro(x, y, z); + dirX += (x - IMU.gyroOffset[0])/IMU.getGyroODR(); // slope is still raw but offset must already be calibrated + dirY += (y - IMU.gyroOffset[1])/IMU.getGyroODR(); + dirZ += (z - IMU.gyroOffset[2])/IMU.getGyroODR(); + sigmaX2 +=x*x; sigmaY2+=y*y; sigmaZ2+=z*z; + count++; + if ((count%30)==0)Serial.print('.'); + digitalWrite(LED_BUILTIN, (millis()/125)%2); // blink onboard led every 250ms + } + digitalWrite(LED_BUILTIN,0); // led off + Serial.readStringUntil(13); //Empty read buffer + Serial.print("\n\n\nMeasured direction change X "); + Serial.print(String(dirX,6)+"°\tY "); Serial.print(String(dirY,6)+"°\t Z "); Serial.println(String(dirZ,6)+"°"); + sigmaX2 /= count; sigmaY2 /= count; sigmaZ2 /= count; + Serial.print("Std.dev. "); + Serial.print(String(sigmaX2,6)+'\t'); Serial.print(String(sigmaY2,6)+'\t'); Serial.println(sigmaZ2,6); + dirX=abs(dirX); dirY=abs(dirY); dirZ=abs(dirZ); + if (dirX>max(dirY,dirZ)) + { + if (sigmaY2max(dirX,dirZ)) + { if (sigmaX2max(dirY,dirX)) + { if (sigmaY2360) turnangle=90; - break;} - case 'M': { Serial.print("\n\n\n\n\n\nMeasuring. Turn the sensor over "+String(turnangle));Serial.println(" degrees\n"); - Serial.println("Press Enter when finished."); - calibrateGyroslope(turnangle); - break;} - default : {Serial.println("I received: "+String(incomingByte)); break;} - } - Serial.println(""); - } -} -void calibrateMagnetMenu() -{char incomingByte = 0; -String ans; - Serial.println("\n\n\n\n\n\n\n\n\n\n\n"); - while (incomingByte!='X') - { Serial.println("Calibrate Magnetometer"); - Serial.println("The magnetic field measurement will be heavily disturbed by your set-up, so an \"in-situ\" calibration is advised."); - Serial.println("The demonstrated min-max calibration was slightly improved to diminish outlyers but is still only very simple."); - Serial.println("While measuring the min and max magnetic values must be found for all axes by twisting the board around. The "); - Serial.println("min-max values are constantly printed. If one of them changes you found a higher or lower value. It helps if you "); - Serial.println("know the direction of the Earth magnetic fieldlines. All you have to do is align the sensor axes with it. "); - Serial.println("More info about the Earth magnetic field https://en.wikipedia.org/wiki/Earth%27s_magnetic_field "); - Serial.println(" "); - Serial.print (" (S)trength of Local Earth magnetic field "+String(EarthMagnetStrength));Serial.println(" µT Needed for correct Slope setting"); - Serial.println(" (M)in-Max Calibration, twist board around, press enter to stop measuring"); - Serial.println(" (X) eXit to the main menu"); - Serial.println(" "); - Serial.println("\n The code below can be copy/pasted in a sketch\n"); - for (int i= 0; i<=2 ; i++) - { Serial.print(" IMU.magnetOffset["+String(i)); - Serial.print("] = "+String(IMU.magnetOffset[i],6)); - Serial.print(";"); - } - Serial.println(); - for (int i= 0; i<=2 ; i++) - { Serial.print(" IMU.magnetSlope ["+String(i)); - Serial.print("] = "+String(IMU.magnetSlope[i],6)); - Serial.print(";"); - } - Serial.println("\n\n"); - while (!Serial.available()) ; // wait for character to be entered - incomingByte = toupper(Serial.read()); - if (byte(incomingByte)!=13) Serial.readStringUntil(13); // empty readbuffer - switch (incomingByte) - { case 'S': { readAnswer("\n\nEnter local Field intensity " ,EarthMagnetStrength ); break;} - case 'M': { calibrateMagnet() ; - Serial.print("\n\n\n\n\n\n"); - break;} - default : {Serial.println("I received: "+String(incomingByte)); break;} - } - - - } -} - -void readAnswer(String msg, float& param) -{String ans; - Serial.print(msg); - while (!Serial.available()); - ans = Serial.readStringUntil(13); - Serial.println(ans); - if (ans!="") param= ans.toFloat(); - Serial.println("\n\n\n\n\n\n\n"); -} - -void calibrateMagnet() // measure Offset and Slope of XYZ -{ float x, y, z, Xmin, Xmax, Ymin, Ymax, Zmin, Zmax ; - unsigned long count=0; - IMU.setMagnetOffset(0,0,0); // Offsets must be 0 when calibrating - IMU.setMagnetSlope(1,1,1); // slopes must be 1 when calibrating - IMU.setMagnetODR(8); //Fast rate 400Hz - read_N_Magnet(10, Xmin, Ymin, Zmin); // starting values - Xmax = Xmin; Ymax = Ymin; Zmax = Zmin; - while (!Serial.available()) // measure until enter key pressed - { read_N_Magnet(10, x, y, z); //average over a number of samples to reduce the effect of outlyers - Xmax = max (Xmax, x); Xmin = min (Xmin, x); - Ymax = max (Ymax, y); Ymin = min (Ymin, y); - Zmax = max (Zmax, z); Zmin = min (Zmin, z); - count++; - if ((count & 5)==0) //reduce the number of prints by a factor - { Serial.print("Xmin = "+String(Xmin)); Serial.print(" Xmax = "+String(Xmax)); - Serial.print(" Ymin = "+String(Ymin)); Serial.print(" Ymax = "+String(Ymax)); - Serial.print(" Zmin = "+String(Zmin)); Serial.print(" Zmax = "+String(Zmax)); - Serial.println(); - } - } - Serial.readStringUntil(13); //Empty read buffer - IMU.setMagnetOffset( (Xmax+Xmin)/2,(Ymax+Ymin)/2, (Zmax+Zmin)/2 ) ; // store offset - IMU.setMagnetSlope ( (2*EarthMagnetStrength)/(Xmax-Xmin),(2*EarthMagnetStrength)/(Ymax-Ymin),(2*EarthMagnetStrength)/(Zmax-Zmin)); // store slope - -} - - - -void calibrateGyroslope(unsigned int turnangle) // rotate board over known angle -{ float tempSlope[3]; - boolean validMmt=false; - float dirX=0, dirY=0, dirZ=0,sigmaX2=0,sigmaY2=0,sigmaZ2=0; - float x, y, z; - unsigned int count=0; - for (int i =0;i<=2;i++) tempSlope[i]= IMU.gyroSlope[i]; - IMU.setGyroSlope(1,1,1); - while (!Serial.available()) // measure until enter pressed - { while (!IMU.gyroAvailable()); - IMU.readGyro(x, y, z); - dirX += x/IMU.getGyroODR(); dirY += y/IMU.getGyroODR(); dirZ += z/IMU.getGyroODR(); - sigmaX2 +=x*x; sigmaY2+=y*y; sigmaZ2+=z*z; - count++; - if ((count%30)==0)Serial.print('.'); - digitalWrite(LED_BUILTIN, (millis()/125)%2); // blink onboard led every 250ms - } - digitalWrite(LED_BUILTIN,0); // led off - Serial.readStringUntil(13); //Empty read buffer - Serial.print("\n\n\nMeasured direction change X "); - Serial.print(String(dirX,6)+"°\tY "); Serial.print(String(dirY,6)+"°\t Z "); Serial.println(String(dirZ,6)+"°"); - sigmaX2 /= count; sigmaY2 /= count; sigmaZ2 /= count; - Serial.print("Std.dev. "); - Serial.print(String(sigmaX2,6)+'\t'); Serial.print(String(sigmaY2,6)+'\t'); Serial.println(sigmaZ2,6); - dirX=abs(dirX); dirY=abs(dirY); dirZ=abs(dirZ); - if (dirX>max(dirY,dirZ)) - { - if (sigmaY2max(dirX,dirZ)) - { if (sigmaX2max(dirY,dirX)) - { if (sigmaY2max(abs(y),abs(z))) - { Serial.println("X detected"); - if (sqrt(y*y+z*z)/x0) maxAX=x; else minAX=x; - } - } - if (abs(y)>max(abs(x),abs(z))) - { Serial.println("Y detected"); - if (sqrt(x*x+z*z)/y0) maxAY=y; else minAY=y; - } - } - if (abs(z)>max(abs(x),abs(y))) - { Serial.println("Z detected"); - if ( sqrt(x*x+y*y)/z0) maxAZ=z; else minAZ=z; - } - } - IMU.setAccelOffset((maxAX+minAX)/2,(maxAY+minAY)/2,(maxAZ+minAZ)/2); - IMU.setAccelSlope((maxAX-minAX)/2,(maxAY-minAY)/2,(maxAZ-minAZ)/2); - if ( !validMmt ) - { Serial.print("\n\n\nNot a valid measurement! "); - Serial.print("x="+String(x));Serial.print(" y="+String(y));Serial.println(" z="+String(z)); - } -} - -void read_N_Accel(unsigned int N, float& averX, float& averY, float& averZ) -{ float x, y, z; - averX=0; averY =0;averZ =0; - for (int i=1;i<=N;i++) - { while (!IMU.accelAvailable()); - IMU.readAccel(x, y, z); - averX += x; averY += y; averZ += z; - digitalWrite(LED_BUILTIN, (millis()/125)%2); // blink onboard led every 250ms - if ((i%30)==0)Serial.print('.'); - } - averX /= N; averY /= N; averZ /= N; - digitalWrite(LED_BUILTIN,0); // led off -} - -void read_N_Gyro(unsigned int N, float& averX, float& averY, float& averZ) -{ float x, y, z; - averX=0; averY =0;averZ =0; - for (int i=1;i<=N;i++) - { while (!IMU.gyroAvailable()); - IMU.readGyro(x, y, z); - averX += x; averY += y; averZ += z; - digitalWrite(LED_BUILTIN, (millis()/125)%2); // blink onboard led every 250ms - if ((i%30)==0)Serial.print('.'); - } - averX /= N; averY /= N; averZ /= N; - digitalWrite(LED_BUILTIN,0); // led off -} - -void read_N_Magnet(unsigned int N, float& averX, float& averY, float& averZ) -{ float x, y, z; - averX=0; averY =0;averZ =0; - for (int i=1;i<=N;i++) - { while (!IMU.magnetAvailable()); - IMU.readMagnet(x, y, z); - averX += x; averY += y; averZ += z; - digitalWrite(LED_BUILTIN, (millis()/125)%2); // blink onboard led every 250ms - if ((i%30)==0)Serial.print('.'); - } - averX /= N; averY /= N; averZ /= N; - digitalWrite(LED_BUILTIN,0); // led off -} diff --git a/examples/RPM_Meter_Rev_Counter/RPM_Meter_Rev_Counter.ino b/examples/RPM_Meter_Rev_Counter/RPM_Meter_Rev_Counter.ino new file mode 100644 index 0000000..f37abb9 --- /dev/null +++ b/examples/RPM_Meter_Rev_Counter/RPM_Meter_Rev_Counter.ino @@ -0,0 +1,74 @@ +/* + * Arduino LSM9DS1 - RPM Meter and Rev counter. + * Example for V2 of the LSM9DS1 library. + * + * Writtenby Femme Verbeek 12 june 2020 + * + * This program demonstrates the use of the LSM9DS1 Gyroscope + * When placed on a record turntable it will show the rotation speed in RPM, 33.33 or 45 + * It counts the revolutions by integrating the Gyroscope signal. + * + * Run the DIY calibration program to get the gyroOffset an gyroSlope settings and paste their values below + * where it is indicated + * + * This example code is in the public domain. + */ + +#include + +void setup() +{ Serial.begin(115200); + while (!Serial); + if (!IMU.begin()) + { Serial.println("Failed to initialize IMU!"); + while (1); + } + IMU.setGyroODR(5); //476Hz + IMU.gyroUnit = REVSPERMINUTE ; //change output unit of readGyro + +//************ In order for this program to work properly, it needs calibration **************** +//************ Replace the lines below by the Gyroscope output of the DIY Calibration program **************** + + IMU.gyroOffset[0] = 0; IMU.gyroOffset[1] = 0; IMU.gyroOffset[2] = 0; + IMU.gyroSlope [0] = 1; IMU.gyroSlope [1] = 1; IMU.gyroSlope [2] = 1; + +//***************************************************************************************************************** + Serial.println("RPM_X \t RPM_Y \t RPM_Z \t Revs_X \t Revs_y \t Revs_Z "); // legend in case you use the serial plotter +} + +float countRevsX=0, countRevsY=0, countRevsZ=0; + +void loop() +{ + int nrOfSamples=200; + float measureTime= nrOfSamples/(IMU.getGyroODR()*60); //in min + float x, y, z; + read_N_Gyro(nrOfSamples,x,y,z); + countRevsX += x * measureTime; + countRevsY += y * measureTime; + countRevsZ += z * measureTime; + + Serial.print(x); + Serial.print('\t'); + Serial.print(y); + Serial.print('\t'); + Serial.print(z); + Serial.print('\t'); + Serial.print(countRevsX); + Serial.print('\t'); + Serial.print(countRevsY); + Serial.print('\t'); + Serial.println(countRevsZ); +} + + +void read_N_Gyro(unsigned int N, float& averX, float& averY, float& averZ) +{ float x, y, z; + averX=0; averY =0;averZ =0; + for (int i=1;i<=N;i++) + { while (!IMU.gyroAvailable()); + IMU.readGyro(x, y, z); + averX += x; averY += y; averZ += z; + } + averX /= N; averY /= N; averZ /= N; +} diff --git a/examples/LSM9DS1_RegisterTest/LSM9DS1_RegisterTest.ino b/examples/RegisterTest/RegisterTest.ino similarity index 97% rename from examples/LSM9DS1_RegisterTest/LSM9DS1_RegisterTest.ino rename to examples/RegisterTest/RegisterTest.ino index 0fe6c37..7f3be00 100644 --- a/examples/LSM9DS1_RegisterTest/LSM9DS1_RegisterTest.ino +++ b/examples/RegisterTest/RegisterTest.ino @@ -1,210 +1,210 @@ -/*Test program for Arduino__LSM9DS1 Library version 2.0 extensions - * Written by Femme Verbeek Pijnacker the Netherlands 30 may 2020. - * Run through all the new set and get functions - */ - -#include - -void setup() { - Serial.begin(115200); - while(!Serial); //Wait for serial connection - delay(10); - if (!IMU.begin()) { - Serial.println("Failed to initialize IMU!"); - while (1); } - float x,y,z; - Serial.println("Testing all library chip settings\n"); - Serial.println ("Full Scale settings should hardly inluence measured values"); - for (int i = 0;i<=4;i++){ - if (IMU.setAccelFS(i)) - { printResult ("setAccelFS(", i ,IMU.getAccelFS()," g "); - read_N_Accel(2,x,y,z); //throw away first two samples - read_N_Accel(50,x,y,z); - printXYZData("Accel uncalibrated ",x,y,z,"g "); - } - else Serial.println ("setAccelFS parameter out of range \n"); } - - read_N_Gyro(50,x, y, z); - IMU.setGyroOffset(x,y,z); //Calibrate Offset - for (int i = 0;i<=4;i++){ - if (IMU.setGyroFS(i)) - { printResult ("setGyroFS(",i,IMU.getGyroFS()," deg/s "); - read_N_Gyro(2,x,y,z); //throw away first two samples - read_N_Gyro(50,x,y,z); - printXYZData("Gyro offset calibrated ",x,y,z,"dps "); - } - else Serial.println ("setGyroFS full scale parameter out of range \n");} - - for (int i = 0;i<=4;i++){ - if (IMU.setMagnetFS(i)) - { printResult ("setMagnetFS(", i ,IMU.getMagnetFS()," µT "); - read_N_Magnet(2,x,y,z); //throw away first two samples - read_N_Magnet(10,x,y,z); - printXYZData("Magnet ",x,y,z,"dps "); - } - else Serial.println ("setMagnetFS full scale parameter out of range \n"); } - - Serial.println("\nTest Operational Mode 0=off, 1 accelerometer only, 2= Accel + Gyro \n"); - Serial.println("Default operational mode "+String(IMU.getOperationalMode())); - IMU.setGyroODR(0); - Serial.println("setGyroODR(0) Operational mode "+String(IMU.getOperationalMode())); - IMU.setAccelODR(0); - Serial.println("setAccelODR(0) Operational mode "+String(IMU.getOperationalMode())); - IMU.setGyroODR(3); - Serial.println("setGyroODR(3) Operational mode "+String(IMU.getOperationalMode())); - - Serial.println("\n setGyroODR result (shared ODR, i>0 overrules the Accel setting)"); - for (int i=0;i<=7;i++) - if (IMU.setGyroODR(i)==0) Serial.println("setGyroODR parameter out of range "+String(i)); - else printODRData(i); - - Serial.println("\n setAccelODR result (shared ODR, i=0 switches off Gyro and Accel)"); - for (int i=0;i<=7;i++) - if (IMU.setAccelODR(i)==0) Serial.println("setAccelODR parameter out of range "+String(i)); - else printODRData(i); - - Serial.println("\n Switch off Gyro (Accelerometer only mode)"); - IMU.setGyroODR(0); //switch off gyro - for (int i=0;i<=7;i++) - if (IMU.setAccelODR(i)==0) Serial.println("setAccelODR parameter out of range "+String(i)); - else printODRData(i); - - Serial.println("\n setMagnetODR sample rate result"); - for (int i = 0;i<=16;i++){ - if (IMU.setMagnetODR(i)) - printResult ("setMagnetODR(", i , IMU.getMagnetODR()," Hz \n"); - else Serial.println ("setMagnetODR parameter out of range "+String(i));} - - Serial.println("\n Accelerometer automatic band width result "); - for (int i=0;i<=6;i++) - { IMU.setAccelODR(i); - Serial.print("Accel ODR = "+String(IMU.getAccelODR())); - Serial.println(" automatic BW setting (Hz) "+ String (IMU.getAccelBW())); - } - - Serial.println ("\n Accelerometer band width override"); - for (int i = 0;i<=4;i++) - { if (IMU.setAccelBW(i) ) // override automatic bandwith - printResult("setAccelBW(", i ,IMU.getAccelBW(), "Hz \n" ); - else Serial.println ("setAccelBW parameter out of range "+String(i) ); - } - - Serial.println ("\n Gyroscope band width setting"); - for (int i = 0;i<=6;i++) - { if (IMU.setGyroODR(i)) - { Serial.println ("Gyroscope ODR = " + String( IMU.getGyroODR() ) ); - for (int j = 0;j<=4;j++) - { if (IMU.setGyroBW(j) ) // the gyro has no automatic bandwith - printResult("setGyroBW(", j ,IMU.getGyroBW(), "Hz \n" ); - else Serial.println ("setGyroBW parameter out of range"+String(j)); - } - } - else Serial.println ("failed setting gyroscope sample rate "); - } - - Serial.println ("\n Change output Units changes the value of read... \n"); - - Serial.print("Change accel output unit to m/s2 "); - IMU.accelUnit= METERPERSECOND2; - read_N_Accel(20,x, y, z); - printXYZData("readAccel uncalibrated ",x,y,z,"m/s2 "); - - Serial.print("Change accel output unit to g "); - IMU.accelUnit= GRAVITY; - read_N_Accel(20,x, y, z); - printXYZData("readAccel uncalibrated ",x,y,z,"g "); - - Serial.print("\nSimulate gyro measurement by offsetting 100 dps "); - IMU.setGyroOffset(0,0,0); //Zero offset - read_N_Gyro(20,x, y, z); - IMU.setGyroOffset(100+x,100+y,100+z); //Add 100 dps to measurement to simulate a measurement - - Serial.print("\nChange gyro output unit to deg/s "); - IMU.gyroUnit = DEGREEPERSECOND; - read_N_Gyro(20,x, y, z); - printXYZData("readGyro offset ",x,y,z,"deg/s "); - - Serial.print("Change gyro output unit to rad/s "); - IMU.gyroUnit = RADIANSPERSECOND; - read_N_Gyro(20,x, y, z); - printXYZData("readGyro offset ",x,y,z,"rad/s "); - - Serial.print("Change gyro output unit to Rev/M "); - IMU.gyroUnit = REVSPERMINUTE; - read_N_Gyro(20,x, y, z); - printXYZData("readGyro offset ",x,y,z,"RPM "); - - Serial.print("Change gyro output unit to Rev/s "); - IMU.gyroUnit = REVSPERSECOND; - read_N_Gyro(20,x, y, z); - printXYZData("readGyro offset ",x,y,z,"RPS "); - - Serial.print("\nChange Magnet output unit to microTesla "); - IMU.magnetUnit = MICROTESLA; - read_N_Magnet(20,x, y, z); - printXYZData("readMagnet ",x,y,z,"µT "); - - Serial.print("Change Magnet output unit to nanoTesla "); - IMU.magnetUnit = NANOTESLA; - read_N_Magnet(20,x, y, z); - printXYZData("readMagnet ",x,y,z,"nT "); - - Serial.print("Change Magnet output unit to Gauss "); - IMU.magnetUnit = GAUSS; - read_N_Magnet(20,x, y, z); - printXYZData("readMagnet ",x,y,z,"G "); - -} - -void loop() { } - -void printResult (String msg, int nr,float value, String dimension) -{ Serial.print (msg+String(nr)); - Serial.print(") Setting "+String(value)); - Serial.print(dimension); -} -void printODRData(int i) -{ Serial.print("Settting "+String(i)); - Serial.print(" Oper.mode "+String(IMU.getOperationalMode())); - Serial.print(" ODR Gyro "+String( IMU.getGyroODR(),3 ) ); - Serial.print("Hz Accel "+String( IMU.getAccelODR(),3 ) ); - Serial.println("Hz"); -} -void printXYZData(String msg, float x,float y,float z,String unit) -{ Serial.print (msg); - Serial.print (x+unit ); - Serial.print (y+unit ); - Serial.println (z+unit ); -} - -void read_N_Accel(unsigned int N, float& averX, float& averY, float& averZ) -{ float x, y, z; - averX=0; averY =0;averZ =0; - for (int i=1;i<=N;i++) - { while (!IMU.accelAvailable()); - IMU.readAccel(x, y, z); - averX += x/N; averY += y/N; averZ += z/N; - } -} -void read_N_Gyro(unsigned int N, float& averX, float& averY, float& averZ) -{ float x, y, z; - averX=0; averY =0;averZ =0; - for (int i=1;i<=N;i++) - { while (!IMU.gyroAvailable()); - IMU.readGyro(x, y, z); - averX += x/N; averY += y/N; averZ += z/N; - } -} -void read_N_Magnet(unsigned int N, float& averX, float& averY, float& averZ) -{ float x, y, z; - averX=0; averY =0;averZ =0; - for (int i=1;i<=N;i++) - { while (!IMU.magnetAvailable()); - IMU.readMagnet(x, y, z); - averX += x/N; averY += y/N; averZ += z/N; - } -} - - - - +/*Test program for Arduino__LSM9DS1 Library version 2.0 extensions + * Written by Femme Verbeek Pijnacker the Netherlands 30 may 2020. + * Run through all the new set and get functions + */ + +#include + +void setup() { + Serial.begin(115200); + while(!Serial); //Wait for serial connection + delay(10); + if (!IMU.begin()) { + Serial.println("Failed to initialize IMU!"); + while (1); } + float x,y,z; + Serial.println("Testing all library chip settings\n"); + Serial.println ("Full Scale settings should hardly inluence measured values"); + for (int i = 0;i<=4;i++){ + if (IMU.setAccelFS(i)) + { printResult ("setAccelFS(", i ,IMU.getAccelFS()," g "); + read_N_Accel(2,x,y,z); //throw away first two samples + read_N_Accel(50,x,y,z); + printXYZData("Accel uncalibrated ",x,y,z,"g "); + } + else Serial.println ("setAccelFS parameter out of range \n"); } + + read_N_Gyro(50,x, y, z); + IMU.setGyroOffset(x,y,z); //Calibrate Offset + for (int i = 0;i<=4;i++){ + if (IMU.setGyroFS(i)) + { printResult ("setGyroFS(",i,IMU.getGyroFS()," deg/s "); + read_N_Gyro(2,x,y,z); //throw away first two samples + read_N_Gyro(50,x,y,z); + printXYZData("Gyro offset calibrated ",x,y,z,"dps "); + } + else Serial.println ("setGyroFS full scale parameter out of range \n");} + + for (int i = 0;i<=4;i++){ + if (IMU.setMagnetFS(i)) + { printResult ("setMagnetFS(", i ,IMU.getMagnetFS()," µT "); + read_N_Magnet(2,x,y,z); //throw away first two samples + read_N_Magnet(10,x,y,z); + printXYZData("Magnet ",x,y,z,"dps "); + } + else Serial.println ("setMagnetFS full scale parameter out of range \n"); } + + Serial.println("\nTest Operational Mode 0=off, 1 accelerometer only, 2= Accel + Gyro \n"); + Serial.println("Default operational mode "+String(IMU.getOperationalMode())); + IMU.setGyroODR(0); + Serial.println("setGyroODR(0) Operational mode "+String(IMU.getOperationalMode())); + IMU.setAccelODR(0); + Serial.println("setAccelODR(0) Operational mode "+String(IMU.getOperationalMode())); + IMU.setGyroODR(3); + Serial.println("setGyroODR(3) Operational mode "+String(IMU.getOperationalMode())); + + Serial.println("\n setGyroODR result (shared ODR, i>0 overrules the Accel setting)"); + for (int i=0;i<=7;i++) + if (IMU.setGyroODR(i)==0) Serial.println("setGyroODR parameter out of range "+String(i)); + else printODRData(i); + + Serial.println("\n setAccelODR result (shared ODR, i=0 switches off Gyro and Accel)"); + for (int i=0;i<=7;i++) + if (IMU.setAccelODR(i)==0) Serial.println("setAccelODR parameter out of range "+String(i)); + else printODRData(i); + + Serial.println("\n Switch off Gyro (Accelerometer only mode)"); + IMU.setGyroODR(0); //switch off gyro + for (int i=0;i<=7;i++) + if (IMU.setAccelODR(i)==0) Serial.println("setAccelODR parameter out of range "+String(i)); + else printODRData(i); + + Serial.println("\n setMagnetODR sample rate result"); + for (int i = 0;i<=16;i++){ + if (IMU.setMagnetODR(i)) + printResult ("setMagnetODR(", i , IMU.getMagnetODR()," Hz \n"); + else Serial.println ("setMagnetODR parameter out of range "+String(i));} + + Serial.println("\n Accelerometer automatic band width result "); + for (int i=0;i<=6;i++) + { IMU.setAccelODR(i); + Serial.print("Accel ODR = "+String(IMU.getAccelODR())); + Serial.println(" automatic BW setting (Hz) "+ String (IMU.getAccelBW())); + } + + Serial.println ("\n Accelerometer band width override"); + for (int i = 0;i<=4;i++) + { if (IMU.setAccelBW(i) ) // override automatic bandwith + printResult("setAccelBW(", i ,IMU.getAccelBW(), "Hz \n" ); + else Serial.println ("setAccelBW parameter out of range "+String(i) ); + } + + Serial.println ("\n Gyroscope band width setting"); + for (int i = 0;i<=6;i++) + { if (IMU.setGyroODR(i)) + { Serial.println ("Gyroscope ODR = " + String( IMU.getGyroODR() ) ); + for (int j = 0;j<=4;j++) + { if (IMU.setGyroBW(j) ) // the gyro has no automatic bandwith + printResult("setGyroBW(", j ,IMU.getGyroBW(), "Hz \n" ); + else Serial.println ("setGyroBW parameter out of range"+String(j)); + } + } + else Serial.println ("failed setting gyroscope sample rate "); + } + + Serial.println ("\n Change output Units changes the value of read... \n"); + + Serial.print("Change accel output unit to m/s2 "); + IMU.accelUnit= METERPERSECOND2; + read_N_Accel(20,x, y, z); + printXYZData("readAccel uncalibrated ",x,y,z,"m/s2 "); + + Serial.print("Change accel output unit to g "); + IMU.accelUnit= GRAVITY; + read_N_Accel(20,x, y, z); + printXYZData("readAccel uncalibrated ",x,y,z,"g "); + + Serial.print("\nSimulate gyro measurement by offsetting 100 dps "); + IMU.setGyroOffset(0,0,0); //Zero offset + read_N_Gyro(20,x, y, z); + IMU.setGyroOffset(100+x,100+y,100+z); //Add 100 dps to measurement to simulate a measurement + + Serial.print("\nChange gyro output unit to deg/s "); + IMU.gyroUnit = DEGREEPERSECOND; + read_N_Gyro(20,x, y, z); + printXYZData("readGyro offset ",x,y,z,"deg/s "); + + Serial.print("Change gyro output unit to rad/s "); + IMU.gyroUnit = RADIANSPERSECOND; + read_N_Gyro(20,x, y, z); + printXYZData("readGyro offset ",x,y,z,"rad/s "); + + Serial.print("Change gyro output unit to Rev/M "); + IMU.gyroUnit = REVSPERMINUTE; + read_N_Gyro(20,x, y, z); + printXYZData("readGyro offset ",x,y,z,"RPM "); + + Serial.print("Change gyro output unit to Rev/s "); + IMU.gyroUnit = REVSPERSECOND; + read_N_Gyro(20,x, y, z); + printXYZData("readGyro offset ",x,y,z,"RPS "); + + Serial.print("\nChange Magnet output unit to microTesla "); + IMU.magnetUnit = MICROTESLA; + read_N_Magnet(20,x, y, z); + printXYZData("readMagnet ",x,y,z,"µT "); + + Serial.print("Change Magnet output unit to nanoTesla "); + IMU.magnetUnit = NANOTESLA; + read_N_Magnet(20,x, y, z); + printXYZData("readMagnet ",x,y,z,"nT "); + + Serial.print("Change Magnet output unit to Gauss "); + IMU.magnetUnit = GAUSS; + read_N_Magnet(20,x, y, z); + printXYZData("readMagnet ",x,y,z,"G "); + +} + +void loop() { } + +void printResult (String msg, int nr,float value, String dimension) +{ Serial.print (msg+String(nr)); + Serial.print(") Setting "+String(value)); + Serial.print(dimension); +} +void printODRData(int i) +{ Serial.print("Settting "+String(i)); + Serial.print(" Oper.mode "+String(IMU.getOperationalMode())); + Serial.print(" ODR Gyro "+String( IMU.getGyroODR(),3 ) ); + Serial.print("Hz Accel "+String( IMU.getAccelODR(),3 ) ); + Serial.println("Hz"); +} +void printXYZData(String msg, float x,float y,float z,String unit) +{ Serial.print (msg); + Serial.print (x+unit ); + Serial.print (y+unit ); + Serial.println (z+unit ); +} + +void read_N_Accel(unsigned int N, float& averX, float& averY, float& averZ) +{ float x, y, z; + averX=0; averY =0;averZ =0; + for (int i=1;i<=N;i++) + { while (!IMU.accelAvailable()); + IMU.readAccel(x, y, z); + averX += x/N; averY += y/N; averZ += z/N; + } +} +void read_N_Gyro(unsigned int N, float& averX, float& averY, float& averZ) +{ float x, y, z; + averX=0; averY =0;averZ =0; + for (int i=1;i<=N;i++) + { while (!IMU.gyroAvailable()); + IMU.readGyro(x, y, z); + averX += x/N; averY += y/N; averZ += z/N; + } +} +void read_N_Magnet(unsigned int N, float& averX, float& averY, float& averZ) +{ float x, y, z; + averX=0; averY =0;averZ =0; + for (int i=1;i<=N;i++) + { while (!IMU.magnetAvailable()); + IMU.readMagnet(x, y, z); + averX += x/N; averY += y/N; averZ += z/N; + } +} + + + + diff --git a/examples/LSM9DS1_waterlevel/LSM9DS1_waterlevel.ino b/examples/Water_Leveler/Water_Leveler.ino similarity index 100% rename from examples/LSM9DS1_waterlevel/LSM9DS1_waterlevel.ino rename to examples/Water_Leveler/Water_Leveler.ino diff --git a/examples/LSM9DS1_XY_compass/LSM9DS1_XY_compass.ino b/examples/XY_compass/XY_compass.ino similarity index 100% rename from examples/LSM9DS1_XY_compass/LSM9DS1_XY_compass.ino rename to examples/XY_compass/XY_compass.ino diff --git a/images/Aim axes along magnetic field lines.PNG b/images/Aim axes along magnetic field lines.PNG new file mode 100644 index 0000000000000000000000000000000000000000..f4a8ad5ceb97b3411c6b8df3567977d0b931921b GIT binary patch literal 330459 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∋q3T@`8^sh=Az1^(wmZ|L(Yz zV-dI=HBaA&F#tO z-o=7Lx3KKwLo7Ue8xwO%kyP*jl1@Ly(j&LAspMmlm7O z6`fgkbXr@E7{W)P)M0fgA`=SGc}*!g30R4R=(wr~J(Esj?(Q4rRp{Oo9sE#oB-gZ; z&d5T^2PUTVDs=0V@=las?!u)Q(*ITb`l%n_H$VOkdPO(Fx&?3G&$o`?uMf`QulEZK zkSvsJ`tOe};O`IUq$Ian&yGEruDtgzW6zf5sQJt<@YC;o2Ty(P8;EFL6HCYUcb(Eu zq|O+E1;e{zRQI3?-FJ2tp2m~fD8Uao_*{Ohcc z{LUz&*{1Y~vdyKg|%dqy$+t_jOV`P?ngv|0k87Xa*Mde)j1epvol)m&A zucP$xzhYa-pRv94 zQ|hlqtJ(6O%bII8Yp!KS9%23YPt3D0sb@aIs#70e1uOGatW=ZpdEw{3i5cpRoTv5|4g>QL77)bohPD&A5b3C)s!)%(fCZ@oY4#bUM2x-Vy?u#N61{W0CaeT1^&4Py&@GaXRY zwSOb`#^=r}EG(2<5GgJQ87R4N3nlYh)6M@Pfvzn$rQAG!R5w-5=rLMuAw1|b)J4~l z>E@drm}it4(Zw`cbC+;=Xx5%t)BHPwm^ zvpGMv8J(m;O}%d>h|0MUHZ2L1W^_$;mtQfEsUA=0%qc_F#n(_x?{u;c?`kc+g_q0} z_NM%vZRiL?2)lx%6YK zDR>X-36pIX|BRH=Zxc3btQ7qTE6#q1{%M!diPv=~8emOEE}pYkeuYuP;Ma-mjh4&@HVzZ=j@jTnb%O(gpNNI>UyZ z8r@p^PEgVVv=xC=5ljw{d{Xyb;Y}ZuvW{NB%(;s(pl@&d{6{~)AAb5h^o?nZO-o1M z6GG|F_s-%k_X>;zBSA^}%iXgkw6K!?;dbd6w`3+qlp=HWd{p`EPw4s=TH^GT9mtmVu8B&Fl$36eR~X%mfOL!jLs|)ul8_pW#Are35H?~`0@C$8-;e#=j$_B3 z-S>5#*BNEBVP_#mu8Mx-^U-ijw9?;aXgO|WgwoSR2D4JJeA8340dgLJPybR~HSTCx z5)53HvIZIylQVLagK#{eHY4hZx5{l^14J1R)=hFb($`{`B_a8tzEwT^S81mR@-w} zsxj`!)Un-bO?{0Y9<@7CCG&0Nq4}Txsux=-L|GQZQY|{Ba*Nw?kHFO`Ut^@VNsQNn zmi@<#)c#x!w|qVrUiG}N<}K*=80-&64u{E~p^M(WYU#illwiBw%eI=-rAZze8{bYz z84oN9hp41oqq}X*(~p$a#;)UWR_2<2T``@kluEr)OtY$=Z8}^3 za)%9Ak1DYS=2c%Sc!%saM-Ey|gi1?vL@v(U|Gmhpt8|0UNdH(S(&v6P$* zy_ZBI^JK4|r&X_=X((OsY03U2!+0OqxnBAv@%gHKoj`q=^i84G;B@IZsgVM!`(xJ=kk5)&E(6vrTB61? z0jb@5zvEVJ`RBbxgG8kYw)7o$uBflB9beeie24*(aFX}pv6;8|T-(l@!K0qa+9K^? z5K*bsv%e4V*B&pFS-oW4ls2z0bt!$*KfDADOnwTP!2Bnw9Cy{Y?mvlyzWMXAy>q9o zqP@KSheXhUz0d1%{<)W*wFfQTUa?qxFo|MvV#2iIm_Dnti#9NejC)OqjJDep(0k2< z2};(|0kQlKzHMcH`lD5?ZIVzXD0~=fA%;=jlUh+ZC%L5#^ONb)M4imuN0aC-oyy0p z_yA=QjE`G8-2Q-WH|_q7wY)2SN}`%1=zp|g*EsiClpkt4&_~cx4-*2O_Lt7E?jFacSm_(bI-OU6rQr&Qx?@+cM~x%FRmTt;(o}!t8@TyS-oH#lF^HBk=Vrif?57;;0&XgxH}5}8#K5%^jea- za7igacR#;}&wqkehk*Wh@Ad@6a*MAHu!!;7$pMURE|~fXg-x2nW6lsJA;;vWe)f@oO!S$5IA zup%QaV-V&>7`OkTHPs}w&F)^0`urHdwnrC2@C=*GNBwL+p_qBDf+g&DRCCVf^LGfE z=CK-eT>DWUxbiwxm1TodKWT)#Rha+NlBd=HJO4xrx6x6!)Hwg~R3W=)-3bWnIQ4{u zOzdaVsAe>sCHzPnm*i*h0C79s-o*;$FYu1hvy;0TR<^t$ln3{F|DxzR65-RiPo`3q z#KjE})z!DK(MJYningkDi;i}l5~ubI!;6NU3arGPo5UJL@)mIed-6cOYQ)j?;a$Bx zLkaUNo!n>!)iv|OudN%}#8qhv_85x5B%xlT-}RY|6`%Rd;}0CcISR(x!S129>sQR# zrz`k^ce-f<$63B7g}iP@rsL6w(+0=Hqa7@5!8)!7Ulp|3W{oc z+!s!Uowx{9a{jPoNF7&vv=Qs&&Yud|4F8(O`9Rk>dn{zH7PmY=d+5Cp-L5CzmF`lT zL5KA}3ZO*RB}Hgq?()WuxwpPyF1zaTlM(E*w=r5$D&pXnsTs|?7Y~o8nRU0$=DxrE z@9>A3>Y*B^9qOp!DaTuRR&p1nyLhUB=~ipG)Ykm9nWJzU!Dcsm3)~Z?yA+0t1N)W8 z_pf^o>g#q7=0^8enPK27QhiGD+oLXn@K4j{@A(T=;`pXbd6{k)G?ofppYuQaOUrxE znpkngVfO=_`t@4qS$I}*yhQkmYx1_F>F^hHmN<%nJICk?inhBzpB6!#@VJd~C69g* zs)?Nk1>gIxg%5ucNHH>U1SaM1T=n+Rh~7lSuIFakyQnR5+Uzl|B&P+-*xj=YWtOjAC0+BHo1~ zNYoD9rr2F|a=B=zni#8*BQo1${41Nczt#7~QA*_3JvOHeD~C3=25+dCJnDhL^n|?U ze=rz7%8|KT<7Rrp6~OAglr}KD1;TB_A5V1 zi)4zsgj_$tIubs4`*)>V* zW}(Uv*Lp|K!FmKgU{OQl`2nzAJ*vGG#;)@l@7G;jLx4nQklmEbC>jpIQj#Nx+wWUj zH<8je6%2m%Ef;%wA){J_9^5`D7lV1@`_8!L<{3xxx6hS3AN6ATTmSvmCfKY6-uka1 z-rOHBsz|6{C7g5DiPG^?1x$K}+Dh50-Vo=p326R)m6w^glmT!qDcq4mD&Vbzi0>4- zUyIr9%NE^t9evwOxK1%vFHJ>QTrxReR4h<486RAX{qDxX+FY+!e<1}sT5gQY7I2Y9 z5GltHAofldp8o~cBrFpQLU1)rlyW)+N`nN@wXjUFD|wt^bmj1V*Osfn(thRM6fE~3 ztl&ZjTJ%GzRFbh|Vx_+^CY9zznb1VC%J40R+nFps>z1FSf*-BVrPgZe$My`~s*G=2 zlbg8Lt?krJS)r=i*X+OnGj@iR(%4!EDG0W>Dg;lk<<6ox%KYitb|~k-7|EQV%MOY{ z$Kh5_jl#Falr7>LSVRQ_8*0Ji!z{ad*CHd6DA+!8-|Kj@D!bQg<6ntN(n_ z6{XjFn$JH^;tdP^Pt)nz&eqp)hsuv|L-)QPv?hJ;o2`3y^5XPmLb3_});g(bYxe8+ zh>pSbv(Ug5H&)%%p7nNdp?RZ(YGRu7zWUaUgGc4pmJZpSWB*V;<*S-k#B6nBF{2Zu zeqQDUP1)_q-`-y+`Y}AhEGarLta#6K9YfHRJjzImY^;ilNhD!u2UYXFTuhxkU$Lg4 z{Pi}u1%7#kdmXuC6X9Mz#HXX9RcnXSxC@3Y8S9yZOFST8r7BIV&)%$ z%*t1L66(vLHBkm$-44YL8zq9+Y1(S}llzJDa%PQJ6j}9>-w@Sb`jaM{HJuC0p36GE z4*M%r=7{*(ZxHL^!t{0hFT1P4!~~Z|64~QqPI4%TRs!q&id;<>`~@!mZ5w4C~ zzEHU=v;tFxiYVBq_5D99kbpgQKRKhAf9_yKjc8o#x zCFqQ+9=5Z}r4rqIyPF*Q8{)#b(NLu{p`!IWy^=1Ds9iDXEs9VrR;sWVzclwC20r{@ zUru@z*34DEnCTu?cyunS3(@o}Amo;YjdO3j%Np-!&YPlgGbyg6D!uEEhONMENMQxH zlskrQfmf^ZE%)3k#^>8(-`PB!efPVhPW+aJIw@fP;%?Wclq8EuW%JIXG`MG5p!hi% zKcfDraHRs_qn_(U3JC1ZDI)yiJ|NhXC} ze37Updrbf3R_|uLrVytt5u7h6MYz#Ud_^n%nH`jxuIb|OQrjdOhnG7bDbs29E$#xm>)#~s&W=IU-IoT@8^}4f;p!Um(fbw^Lh8MRP0iQtIK&L&jsr5 z_5M)qIJQ3v%{X~E9Zk0vcwHm-(~*a>H4)T!mdIlLOu8}dG;|r)To?D-Oy>=Vy)*H| zd8HWR$xizS`;M-ZbqF6ZkQmTlnI*BFT*^A(t40m*2c~M@TPE0BE&WpLDWcOe2|-2= z7@-7+DJ!s%aUIePW_I-^w_zD4m$9p)bFFcoc)+dgsD%(jDdfbFxidp=1LoRDLd z%@8V(@Xa0LQ8XA2jV5knrgRD2%;51px6fh=i70)~X-oUuEq8Dsyyq5$9DFza@rj|; z5st=m^AWEj!hSw|P=Th9RrEC&{cT&~MDankg!rn){?MkuOtqnhJ_Ubf9oH{0SBncq zb%DY#9H;tdIMa@BNK!Ptdu~m?;jM78e`#J2XKuo6)XA3eK-QFQy4Qzl&)codyjQ2! z8glMRdi>Rx#TM2-3c-%2-#kqs9SMvMA0Ekr@HOf&xq;C@_-pzU?}0`(HYS5fokUei z8%(a1qN$Imd7LHyUEVG-^-ALkcrE)FT77 z&A8^^Gh9Mk4hghG{Od`cW}dH=2)kUaT?4v17{iWk+&{YYeR(Z+>s#en-013Ropdlg zuH|z-?ZL3vy{Rgc-@PAo+V>i1kiWSCQ3nVqJ-XLfDY$jQl+11{VQQ}PbW=Mm=Apqt z=WofVmtX7jzL0UaFHnLts7JmNgWAeGYu{tGx-Qw_0UsUzZw|8}3(XP7A@p^Xz85hB ziw2GHx3~V0Q7tR@j;)Si&hmLcn8n_0zB6I_{g1tmt_eA3)6h?L|HFxB__UjIUV3*) z2qvM*{&I9y+Znb0U;^Yr0HkK@xGwFaxLQcJj{#l+3BQsSZF6wNTOBWf`)Vu0{YfmX zE=F&n5c9mPnIFu0p}EkX)pJRGwr>O^rC~=#^KCBfficivjGr}Yv!4D&jY7Y+lAtHP z%0&X@t|rZ!SWIZulXGrkj^OBM`&4a(lb^wJdVgu97;fV)naw5BBQJ7=W$5{v9)v|n zR?W@kUEo!wG!UDgvY1cbm9S3DWpIY+s-Ve3J>ypg^SJ$UA)i7h*$s>r`8W0+&k-4| z9vGPp_)mf;)6nIseF9;3j+csqs{_N={-f>|UfYr687*#WE4f2Xr8PJ0Q~sVxvlr|u zZkueVz=Yh!u`|T0cRjFX@x=fwl;vGvrdv@!53sq`NVu9Jf# zSV@r$E8n)mcDgjzH^qi5MXvq@>jScZcpxzUs1(F*n?T?`l)-|2M0+KS8Y5lUTUBM3 zwCY1a-<;P&R5s|Q5RYStK{lRH9qZWd#?mu4?91?aUY(y@Fr#jXciaOj|0{Sc8#$*;uyw|>t_zUo&k43~SoxBK^0c=77SWQS-EPCpHucK^ z2bN=l5jC{u^JiE@r?zM)p;+|}x9t%ZA&(0hxxzdvUqyh3^#!Du^#3TT-?bS38Y67T ze5O%M2$Cy>KEk9k=}YN4f~;5G3=I18HeJ-prwsaPGT0o4rwtGD??Hp;4M+xmZ*^Ti z$#P#kcn9}a0NQFS->kG`I{mDc4dkpC+<%N4a{J`V$7#D<(VXtFEj5!D5b^DT=Ih1o z;_Ki`F+o|&uSEBOnWaXKl3NypZsP`YQD6~-pVf^t1}e`rY-=W6!y^9$@9{SXIfWee zq9flnQdnNv%?2C0(qa&Kjsb)!D4d9RA~3yE89YNx==?2=(%ytJ(JrH4Z!4F1ASwQ?&pqcU2$_Yzh#v_}f(nDO z_y6J>7X*;*P%8HdaHu)LkzF4Kp^9ht?DN5|{clqTa;kZ|rSJc_%sY8m2+$q5ImuBN zddMXOm}Tqxj+`!pF2Le_$z+KoShg78RCQ+aSD&~jpf`<3O4u5f@c|x8m%-+r*g-fx z+HWHin=$p!dBJ1zkuiH` zY}{(9%Xtu!2M?!zZDvE00yOZDwxN&}k&X5O+pUg1)9A|^87rbFACrPd`M$;>z6MWSLO3ak8{(a^h zDx=V+YZMSQI73Y0T@S%~S_1&i8Z4DZv1Qj0<6MOb;Q~bUI zS*p8G7Kt@V0zNd)Y0UzIR5fNaL6-FOG*s~KL78dMp`r5=^eV7HJ7z)*Z! zj(G05Ss{KJHH7!#0=D4C$3nU`kov@1mn24iVS^Vye=UoXrNef~jk(Ci!tZ^;PR)!Hr-H2^2q&w`A8HDssoV ze$i7&mQ;GJQc1-2EIP$ScCBt5EcgPp2sz6RIt^9X6&d$-qmpI{O>#?ef6OB_$x`!V z^4~vYdLEy5Tem~U$9xHy0%r^sGn0}q9-F77N;x*Gz4qI4a^VCwaxjyy$2}Q{gOF5* z-naKsvtN9!7CEQyTD8ZhH_SzN)o^#&ix zav(~c+IBto&rkq)MCwrxP1EarG_G2VH?d-gxcp@`a2K}q_Kn$%H1fuYN|?i3?Kc~* zYYLsp;NN{oHAX#vEl8%+nNh4*JP4bA=JRGTPVbWB#7*I(!`)VIRvn-qeU{0g-m$&| z<{i)PA$WY3@9j@gbu9jRuGU(zNuAaiqNS07b0h@-l(Db}!g(M;!Np+wJBrQ>Dt}n| ziM&=Uzs}{fl0+a19+S)@W5qnLPmvmLRsss543)*l z`b<`;^PFQZ{}VPeX+uiB9rPjAlWiaRMd58`6HSZx(cAGiHi4_YsLoTWioGt%Lx56xHKWNB1Bc0R-48%G&B*T<&dg5NnKB1Hki6*OdDuQo5r_CSSP8IT3v8|wjf95N~`63(g&!N~_4 z6M;778)M)XI{b_x`(2z3mc*seZj#h z`+?*@%T0Rq<<JOL8M5FVKmPqP?WG7bai*`%W*bd3d_OxO1uaOb)3$XjjE34wh5nJ@^~K2A z)C2h?t0a(2^kU{2-{_b?Z{Dbi(D0MN-X-x-EkQ2V1kr5051HfFd0twpK{Js5q^7;a zg>62xozHOe4FKeN#VigPPfhT{o(cL;)2sNoXyBT|^h34bU(9qy_)sl#E*6>AdYhwR zmH(XAo)DJi6HV1jo6r{46Lti5#4d;^>ViYrpX^+7P!4=w^SUJgQU*GL_sCW{z2?dX zvuW1yE7g!9ugTR3eu=4|<8x~iqBL}HGck%}Z!HLwK|mf_*hSxg&A-b0uR&!E@OMQ| zy*C$~9@H(7wh6JMI@FJ@`fT)6l95YvGNb)B2+%Y0 z|KdDtFORYyxe4w)4^ow1a^f!iBl91`X?p+6^N{KoN2N!mQG%*hidg$2=`bANik)#4 z^oq~8mOLr+4^Rp9-+B<)4B=zv-*Yq|%3_fiI>Gq6%F%NgL6%%8hLqeUhV;l-!Himp z#QKYbT>Dl}x3hkufeh!aIU>@vi?70ore#T%1v1SpG8x>+ddz*}pdgTdwD+84aXCeQ9#ilz6LtsbrBZpC)CoCQsW?-8H{ zEeVxGTOmi!(R<_ENmU`#UkKu^Z59HP&&by7mw`jH+mKe>ct%mys~fx1`-!L`-{j}y zKf>X7pd*0yxzMsV?Z~Ocz?5ZnTEOpz#`~zKjbLHhlOMV2N--*tmRO0v@utrY?AlKQa0@OQY zX9MGo1c}7jF9)$kT%U!8j*O{#IARxMUZ2anOuz1b&fc%g!A3*|8+u-C57^2}SjV~nPV02DLGK8~ebPMrBqs|K z9>9IP*`zmh&wa{zJw+j6>Zvtq+138#p^^C2*N?B3%<=i%1Rm+WI307siWaL1>U6{TU{yzf(MeX z9!+GfPi5Fl5zdbLzJ0+Apy(uvLF|yHrnSHsOX<=bH=KdUB&s1{3L~ily|=vJLYS%i0tE zBr(;Xs$-I0JiwMgSQ^DT^igwI_IZAL z0?UY0vHg}+z`k^ss2+uLf0vz?`;rWb{lJpmgZlT6(sxRtitP?PK3}8W(WSN5;0V9$ zzTkame4!XNjJe%jv{p-Y4vTI5bj1R$xDs|b+CeTUFOY(g`R^sTr4%@s7XOKR9Pp8x z?OFLpO?|WFprtbLu`kB^2%+c#pO?C2p^p(WIy*1Hw4y$mR=)#^?J=DSvVuD`%=;EK z`>3@z&RN3n^FDV`m~Db-EO%d(_ZA-d|1$^chx3~Sk9C`2}gzvgI@0fMsY2EVSZf#h6dFP$>_r@G| zIEGGPfcQSvpS<_&tFcMR&nc!Mzwm%?5K@SjY7b!+6V-7mSP?=M zTpHewggYz&EwaGA2#uf43CLG6MYnAo-hLKGWo?1E6_UeGji9>|WDx z8|WE2LgTCLn`aKiSVJC2uK9muona^sx$}cly18=WagA4{6H9N z{Ky$H6>TV$B^yIKYvFE5KrO$>94M3t#@x}7vrBwj(5t& z!ZER%*E{Wk6Gk!Z(56KNkvP|-;N`hSuF^ffTwir#6c1pdAO$h0`c3s^%azsQ!Ik$R zI1MgSV2Qw}YR&r$yaf+;Bqihp>K34a@-h?rE^P8BtqFk($6{iIeT$oH$0 zPWX~+VWfY}uCypzLVQ2&zL(7lT0O=W)SuZpo>(frC}LL$TY0E(m&=*ERY+9&mG@Vj zU4qk!Y{NlTYA|uejqQL-ur#!^JT9@fVY{#okIt9 z!t~LSA4UV`rTwRdJ5Bs&=^&*hQ(h6zc>qxUqd!wR+_uZ(-(<;!s8VRys}cm}c%Nxn zD5D-geEVZnhDbq}te@*Xc=lYFNO)P?l^{WQdwrux6THsTofwM;o%KW2 zYUl33mP{)CL$ON#_7Ze3sB2?rYzh{9OUTIT90OxdC5|UwPFQixUTX1$HdP&U=!p;h zIt?E8>))$0G+qq#bjw}}a9rFw(0emt($sa-zPKkgc47bKtoHt_l)ts&WM$)#pzGPL z`*h^u*xmMk+d_1~-NfyL6}iHK)7@Kiup+VF&R&^0oQQ{hL0EnkM6P0GM8P9CE4D!g zu>!7!lHiHe7!wvm*Vh;$A4W#N&3G*CelcvwX{_#J{rJx8$Fzp&@uYQU$!R` z^y<6CY!15z)3r^6QK=F?9#Ny|QB(Z1as!8x#I)jGItf=?SYmj5a0IYtbf3z7EqTIV z7>;vk7jwa{Pw1$9&W9x9!ml7eFhiYs-%)}HA45Hko>#0Bk=_yScMl0t^6>3@stY5p zrIDmBgpodhL`+ltUxlub#w&cJhFrJ0Gg@NX|51{K;rMuyOH zjt0O#S#qf3lmZF#3t;WTzYSRsRYHgmh!<-2n(N4a%@iCs+wc9`kXDtU2Y5yz?_*?% zGSY+TR+dJ;R zm7I6o?Z=;WeGFX9rPyeOy+Z$=g+FkReIWMtPzCC#c9m=o)y+?|zW%#--qYNfQW$cO z%RD8?#xD`e3QVu;(J|a@tl;E5_E=iW#Sh>1+rCvN&M``o0m%*I3Qd*c$^}?0+U%dc zOtW9gFbD!$j1jT)gR~|y1^C*KOx1@;hIvh*N6*m1k#O7>@8=@OpP@`-pz3$o;uxc! z6{kX0;crR&9(3G98vyH05I&TPE-$1qDi>D>F!%Twn51?+uOqf>hi4A#88GUMEnoFa z2pXcUHrE<%?cUkbs3XNPB+Rv>1Tw(v!daVyx20h?=TY%#C%><}OEmB#3xzl*rruh?C(-*@@acpCxDP9Z)}<4YfJyK?_D{0$0l0 z-_<$GocI3gic@medD>tl@J_!>uwU|?#o=&K$qXC=2T;pK^uG{bn@PwU69xvXq}fUBHenvV>uRK?WOPsJ@=}^_b$Nrhaqtcf7%`%4C2QLsJ`dSA6`jX}W?V24!l&7RZ+}sIBlwk}S?sq#RLn2>4 zEn}6wKvd|xzL;wfcua3Xypdk zce4diofpcWh@p6*-hN+HN8@oG!hKlt&ma2*>?^7L%vvGLrR#>N&D`Flg2+=>Ge<2e z(BhtF=&I3S1V&?%jcC_>qC9inDxOMjX)p2$*@#-cvJL>=!(HZkZ_e$s?Qg8{shs$1 zG3&z4XsdAG&4-pCylV{9`1Wc|<08V49C7s7(rmAo?*E~J8WWFkCkzh_>hFsO!nPGE z|M4UNd@V5n8voUX-mv(x|9&Mu83(Hp{$t&xAzvt?iZyX5-^=rs`}JHDLZFXyTDypMwdmxQ()aB0>a_7QsX`8MF5P7Bn zf7&GUyeu<>pHh};sc4AS)3XzCm%Goa#7_}aG1wRa7rs`+s@#2kYks*DE>_)=;e3=?UhkiG{%n9I_vp@P zr3?4;yd!hs{C4rdF-_|sA!1!eHrD^H@2@g%quhGz)j?QF-pS0@@Z9DA z8lnUzT)mH}k^jP5C&F8Ax`amlHf0!huCMG-j5W!_@`~5Xs*VoAdfG+u(iST1#r8&y z2P$r0Z!lLaV+yqnr6It|<}}w+P`aeC@HBnY?@VT;o}meKWmFdW=k$uAV$@1bpr2u( z#q$R&DAjnc=yU}uDe!|u1LZcfGn2kg`e&ibf?rrh*5w)apbfBK50x-S#d%`bQ4y%akk763(Q<2&GPAlL4?0L!`sAe?)0e zPFiS~zeD~My(V?0;ch2=T8M4>>JwA0dC^22{$ybd$b#QG#ms>)WKgN^6-tNu`XA}) zz;V|(hicapHK~+N-zR;Q_@cVsug<&i(DAEJ#{2U>ve65;9YIfj8{%H_FkUm<=n|~% z*AuT^7BZgW=j&&D5XsH)f9pgoDJaXM^XGjR$>LiC;7*rJ(bb=;e`eiK3ekG5);ER z+&ws7?0t1r&DT!-Hm+7O%x)iy)wEV4=lpItnq2CiyMXjQ=8-zFmzMXjH3j)$NOS_2JR~KP7Y%&ZQ98K zSFS&eemYv3jC0g#weJsO7wHv_MWtlxmClWMoRO;qA8GOrfHqvN$T#!B$1$oGj&r%z z``aa~1pB(MEgqDliLfi5&*v$h;HVVn!5UZJJJ1=j^MEGP+K==7Fo&qHqQeJ)@b75? z;YoxW?)J)kH%zO=D~{KeyY?*yQ>eKSkJKN*Kd>d z)pc9AYsoli5CU?g33~8$82`?-8)50*1(Ct6WXWcMszWyZXR{9Ku33&3=>1XeB_w=Dr8t3SooJrueyeM*f^&W|TZL~t=3%wV z2Y$jnJF7*?`GcE?(9Zm$ntCWEfQWh8cZ&c>Y5ad~j8OAAzB*YdqndN)`SA%j>J}R;C@fNdB@HAymZG zo358m$}u?_iOGId31@C2K7EbR#N(cyp9U{EdVlrBxpK3bY>!xrljbr_43xcW`0ClC z_37le%(m|uHz(>Yhxr-B@>+S7VR~nCOw>%d&~f?to=`*NRgHa%PGFMzYta$wfwAVr z*&~^^7qV}`F}zCt0+RPCyvuCH*!VhwP93TWB+=x~5_u9V6-l+WIo||o>yOKhkkjC> z*_dmN#Pb}gS&_!#EpJn&Cz!Vn#KZ3$&-|6Iv6P|Q0mr<(=+GX*RBedO95sVGR3DvX z&WMF4Hxa*KpTGna=(=Fwt#ge&1?1Wx^9rt}op|OZLOzJ@w~uUTo2pA5=r6M9Y9XbRg=Lca!?dJ^7m-nx zx%yv&kN;CM*RS*6dARG@7rHp3zmr5=QY|fq?Cjar8&Flt$@K_$-#EXmKI6nTwi3nt z^G9B_OsBWJ4z?77-KWZ1$cUG?s`vB@ryg&S3+7_lqTXc5S8iwBO5Igm`_TcGtK)n* zNF%Bcx1RC-RmdMQ-v=P)lut+j+1%8rC<8FROg#L!{FQ}zzVf?uO5zp>1Cur6)em9| zuyF6iy4`~;#D|(n0=bx|sSz1-KjQM?nnzu`ygG>0-XC7Q4c8o}^l`!DJ(h+wcn%QY zKA*~1_G2h^=*8o5v}}3r3bhQ-m$F3|1pxZ~6z}G`d|^Nh61M&jF0RYm`+;%~iQB!e+__kKA% z10Hu?bOfER`G>`hueqfwyltU@9@+=l_X?&n&q$KhzL0!2DD~|}XAGPE2Bh9a(05sb zx;q5W=5dp%P^UeR!>B)$_ZmobT~Yz)^k*(tQ6_2HP$PhtX*N;*e}rh9$XV3TVhj-IDlkM02Rgp;ewKILZFZ&iGhWPK8HOxgrtv)C zfsirvl+l&a8^WclkF568%^V!21-6!JLWxQs$ zFFWEHzOLu;7&k&S{c`b{1-&WjldC@O`Sp)^?sjIr;TH4|#2=ea^^A<^_To~@`S&y` zxtNtnNcw9#z0MhXA4jleJK+Lkevh|ib;OHzqS^AI;7GuJTCQw3Hza(aIeBuv-AA~I zOyTFu#_{~Q4R_BkKLT)a_bX&U3o}c!7RlY9kEB3=8*+zRw!l`Q52R|!uW9+@+3BBB zRjA;ohGp!M^JF)yu!e!{`$^RE7SCHU*aMD!?LVq( zwo3wb?b}2!hQcEIp+W6G#%TT}Aw}){p0Rp~mREk%vzit41Qt(}Q>PLgWsHOFp`c_m zOhEB@V2>fbeiYo|6&?`HQAO$VA}XD)^PLS`e0;fAia^8CKWZw$O>L65UEV67POj%r z`)Anx7E-B^UdQQ)ln$C;DB}HOx=(eEHA#C7WjAcx==swnYJ19-> zKe|-+kY=fZ%N~)*TJPYJQ8rtS4-5##q}}+sP;Rjj@3;Rb+@qs{R{rxU^NwzJgo{8xwS%AdN{K zaa7;>#0{7GhI0w8*mJq=WR%^N8_|>

gK@5ulSmVvQ60^M^nQCso|iB<`(WDLKvN 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

}4TRF0=1J)X?Q4v&|KI`Zl)%I8- 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�l1*B)4SiNr_PM4#`8vKxCzZlDQ?;6P=QS8n5GA z5_N}8$wGH-lT=Rn0>b`zV==Hv23n_;!TJdUv3K?`tQpY-GrP(y2}JSGopVVpBTw0Q zeQ|K6wpJO2hkF;`{pFpQH=;Xg@t-iQbO}@`UIg{{ZL)rHDU9pZ3Y%w)#Ny#yabV#% zoL-ePCER7*2~L!QW)!~Do_XqXE{cE=lnhKBLWzn)$!jrgZkdN`8)xF&N`1?l!+)SD z&@-2m=#U$f3|3E%Z^m=##jcgOJ$VG3FaM5f)Wnr49!?HQmD6ymN;*N6j@ty()s)J( z)-VN+hSkK|)lKllp2m1ZKs~2x3Z2sP!-9>6lR?Q8LMRTUIE+HQJeFI(2a&JG!DUc- zd9*g(9jT8yGg5FNs~m2nr{QL*-g_GE_vnIekI5w|9hyM+h(j_cy}GmyuP*NUD1@v( zv7R{2+W$;~Mpz~uGZ0xllz}Hy&i>FrNju%~O>@Sferj2Qs64Xx_gt4ilIo>aKo%wE zR8yfmh4m_ya%BeLBMCz31dxZ5pv3c~=8M*(EZiq0mn!O9RZ_`fsGuiU z7b!q^6>$!#DCe<45v&R+p+cFj70aMW%_?+MH88k+U5x2kA5(fYp{r^}SJeUwhh)=L zwZt+dRJhPz8?14VYDY-5$L5J0uys;LY*XlOvfcFC1$$<6l-p<}vBr*w}%Qg)t$5cO~p&zacWJ0Ta8dLrS`7V*701BhB{4`US^@)$6vvRFB{8fRVO5Hbs&rY*Dq9|l zD^|o>PEI?sGH``1@ClvL_Tin;qH<9TX;lx$R&fH}y4XP}%)m1@6GF)WCKo7$V6wWo zCIgc}NsqL!dwi6=7IRALecJWOWs_<3d!b>uf|%5$84k=Hg>4i2VouK{SUXC8kOLfy zbTe&S{h|Ap1SM_OdUeAje0yUz&TO8KW>w3hYMElFR=zYEXH>?hF4>qjq${?~9EI`v z-A)~h6MRie2lsHA5ew-l7E{*sY(2JG&O+Sp**kAnm^vfXUigUlN>NP%rh_E}e#(gL>m?lg4gexT{GibWNPp zlTy8sl`NopeNu2ED;*Dd*21&t_3>s?BfLG_m_VpUz{o*)ASEhgAC^rzMEFwJM!Y_+_P4LhaN_sFgxD z#xYrRW(pVToUHUDROLApOBHd66eT!M7FFnvU%>N!`UwiSgo^wqOZSyVP}Z+n0j=t$ zqD$jU3~W=IUlJSASvAGn!7ZJ$S~k2DmXBzSm4ejhwpgdoADOXX9OW|q6#nZ#Xek8P zIksly07mVY+6DWxUPVWBU|uimA-uM6+=j7jv5Ej((7!2WbgwTcal+?|2u!w}Pz*|R zNRJ36l@2nLpd--4T$3D<+!5=KA{YruZk$4X(BhOKh!O3HutQyL*+io^+;5 zW4E4ko>02bqXm`i)|M^_O4{jxP;%LLbVnv7Ih^d;6#LpYz?x>Y(VyQQn$X!aB`5@- zrUaAJoKR}UvKh;UR3-i*D$o^GD#33Q{1%Z}syMQfE233}vS?7OD5~a@Q_6!>exsy6u8eFU-MwTdpadb>m%ap_1^5wBAB?-G4*TiKygVU1+p=)|sG_G6%L)$gN@s+cD z_>Plnn1Pp@Q*v<8HaZcA5`h$g>0?mR!vGCPl6FUMd(3gt7X;)~_RblJUJa_Ed+lWG zoIV6QrwzdJA?;ikZ_o6B{MJKh%OUNBH=8A4zw)Ol%ux6U;dmaJFAmnzyW*O?4bdn;Rq!-%V;Lrv<*|-3Y zW{$;`_APNPUH2+gac~L&bz2T9Ed#e|&{bt;;Qp{0c(b}O-XCg)*GC%=K5@4ct|J+c zTs;>6Nw1E7cue52()99}DSrIzF+y=c9h`4k9@nZS;|?Kuxk?JIb#05^9od3+F56D> zZYehiy{0>gwK;J+$CMxg$;axFAd*}CW9?A6jY%9Af=O)w$b%>jpPcT<>#^-s4)q9)ECMG>CEInXltnGUM^H)@s7gC9Rj(vRbCT@pow5_D3<3ZM)fQ<)-#+!|Gp z{CQotPhr0TpMHu$oc~G`DTwkVi@NY%R@I7VTQ39s_&+F|~wR@5pwtJN<1Pm;@G|HzhDHL?}fjcbQPiwEKC`f)h5ehiMT9F7AE24XFtws=r; z%sKB?(CC6R-?Qn`)HD z-iB#7)~Ys6DRdV>NfMMU_H5}=!F7+4Nm+PS7m&^oT*taJ!Ope~FuiuV%eZSq+H3a( z15zl3>?#vl73q2^(Gew=ERIa7MRFyyuTlxE%a=vN;>D28Uy7ilFkTIX?s#qkLZ^YQ zLD)6sFR)3ZW|W**3;yDiJfU>+_H65>S_dgQrf!5$cfNLSI;Vcc>6oYyrOMJRmBExU zWih{E1+1%{j=gOg;nJjm7|CxZwaXPnjdDfMH@hy5(kWfuvM2^6b4nJ%Gaw~G$+@AU z8*&BGzX~O-*J$@`+xS#a(&T?+@dSQj>Vl>f3-gb$E5G#&!-mn_9F&wME*Kr0GZ=^F z4xt9Kt~Nz59VVo-qxj8jGw}7*-B?E_)PVnF>7|OIW5ZhLo!tN}Yb2vngG_X)T?O+7 zbaYRnjqU8PGLnIb@VP{HB$p&8U0CDSoYb$7o-*;wF@@_)lCK+({FXzX^K;OH{%-AB z>fF{9{@f1_to{Y zbi1+-@7<}Ai90C-Q%Y6bN>9hNnkl%~wFcg=Y>uyww#1v`4PyWb6>~}va125!Lm=gB z*Nl`CQlT{V?ZG;@IXDTIt5+m6Qyr8pq^9EArL*wOshxOpUM?wT$SwquDF>JW8099x zLgnkr`<<*WRO0xsU!?#M_9x0fl&BC&@wPc849hM+fyK))SBgh0Q@0tiI)~mA=l(ZhD^{Grs zATr5G8K6>?EjB?zbzuB=qD5Rx6JeCW@uS81J!b6T;2c~Ln3rv#Ml zrIJ2%_fzF1unH4kO1`L*Rt_B+q+n?KTA13eDdr4pj`>3r`fG{#gR(JiU^Az=1L(B+ zH{t(tQ^KnicF*mHqbr8v$f^-Iwq`U=tR2fQpgl3WZzD|WSsxR-)CX6$ zE(6b8lECDkBp4~#VQMdYKBXu7(9Xg{Zd1*Oh)5N^y4-LMf~p zlr-LeB*}T*jzV_=l3bG3lLRI0EoUJ!P57H9_NP-y!iZLNad7@v?3mOK%LcW>n&F*r zaQ09fo);>D6QSfoctdev^>}=7b|am|CJb*~8*>J9!1FU(3E^qz->e4uHm`|+)QXWk zaboFY0%;n~(lHs7&aaxmYj`L*mqajKB#_P%R&KqCbpb_SxlXX^hT1Tk7lKJrI8S@z zy*Npz5FpAv{G2d)bZEWb!!E%o8FUgM^!$vr+1VcJe=aCdf|CL26#@5h>k?cW)*F`^ z*2k6fOk7XaT9d&k1GfpLJJjveG+fUloZ42$n^{fpZd)_FJ=7Sl>0n+SiyRVx z9jluIPzD!+k=6edy+76fuh!MZ#WrPevuX@~m|kB#5I-kD2Ai;+sMxXKoDfI`A@{I8%HU%e zeDStdB9xx*}oUAknObye@6G#=&G&2cJGAdCXPz~j-D1oak$I2lo zR5poO2ZdEJ=8kFPl0GVv2kioY@gE~JLV3+?)ihTfAKJ^9NU4%HLfl`>zw7GbX)f* z5kz{_d1ClZ_bEM|uE&)3AfO1P$OQ>J=8^;-2PFd&OM{Zad$+asUAM;0DeZ5PffH@A zT!MpO2qiy~l;w zA}G{o+JI`Q=*NHhE^IdhfDw?c}mlX$)-J5Xbq=`Z6a~_aHk? zp5~SklO1AEiky%E$RL#14jqyK$vt-{SW6NJ1tldCSoqF#V9qFf#xDi!GAdx}v?16t zV+d9a>x_kcTj0Q~p*Xr=IF2pkx1dM@(?NyuX7qQDxHz?B1U}!l2tVA~hnu?=VD0$s zczt%OdvfR0Ud=JAbuBC$+!1F8BfD`{_aViclE4%|>Eb${_;6tjp~Uy+9h7!?@H;6QqiBhhXS#|b1V5lD$(G9ZOeO6+%g z!>NyedUaw8o^M}f%1I>97BsZ7URx~Ds-RdKUg8t%2s#Iuog z@oIT}e7U~~-U=KMh*ZYv0bC45iRJ4Pgc%j~#rx~vt3yrjXliwwt6v&-(o=Ak@8M## zOuYGQBz`!?_a6Z%2YeD> zjI4~yJEWW-Qrq|C1d@l=3%uF`IMDS|@ii(BA`dkm5>&f3#|mOq2_cv5=b%)W z?x_e}RAJ|++%6Tx3!rS#`~*}!mZ}$Ya%)wE{I*JEi{wXzVl)6H3Lvd?A?F;MR#kRw z61vu_f{`8SV8!^ZSUagZ*3;~4nb`+B<_*N0!Pywyu{OqZqB_<=p6lBCPB+gIMv|>7 zS@`bpv|e;dy`58f#Ja+B4mJeRJ-Q@8$ADxYvbuxT7~MSE0ms|b!L~X{I6x>V$-$s> zrfXvYs|kVR9g^J8d6ovE7?9X^f-Y%S+Xh(Bpav&>{?G(TU1i8Qha@1;9T7?mSZ1=n z44qFB;gL+3q!gpOsZt63tEXXTjWmp`oq=JsGSD-He+&dpEq(*2<$#nQ^>~ej1WRLr zr7>NQZnhPWvI(Jh03UX-9JigtuxM~>-MrZoCg zD38HOl`xt>nqDIvOB>a~)=tfEaA-G7Xj&7EE0=bEaCIv44>zSOhSDh=Uo#gMH!sAM zEsJnfJ75z^VFsRoDF&s$DVgl?2?nGPN-kt4An95`f`eR=K&ZXsZ2KN_Nz(Bp6R~(` zS3;>grghJDJ3MR}-y8G$w7}MheQ&oj5+@dqqDB%@!#tQ~=^=o0OAChJ>c%Pf z>f%=X{?RcUSvDGP&TYoKOFM9K)nu%n&>M#rj>FlNQ+b`waBAr!I;E*GFgceLK*_+Q zBnY`CYpX6WY5zWfNfMX@;HR8epPbl1;0O{s=wvv_&?P-Sy2+)?+ZIDgUXcD7loFK# zM!D$4S-vJA^@7)Zd2l_R@C(Sjkppp|K|NeduHvCYIVcfQcT+QPH;wg7szFse=vD(S zX4b=3yPM(5la1(>2$SQHBG@FBp*(!lFCf**(f{UTZG5}8Ij(f6h$}TK@pbuL6lA0r<9vKtjahrH6qAz zf~k^gH)CC;0OrprOZQYB&8j7%dG#u2Ncj1+D!(q}09CmRztqw((GdwgA%Ln?ESW>v z5~*srV#p}39Vm)XzDy~{xss|{;74YZQ2C8^)C?e33L0z{-S zUEGcidz)6pj=Ggy=H0QjSuXSLG{JO6PN@f7l7K{=i=ZT(rCU1NhkgB8<0R{QJ2l3d z7Fp<@%wNK%pP)7^WW56U{f^#+X&;LeB}fXRT7d#6lP3?VlrD*~1Wb}bZpq~_fDjs1 zt13p-PRC~rYhXO#HXx%iTJQs_#}87jNDir?!gPd8bAqJ>0VE)`AZ%KfDS=KE%A#GF zl4xJH6grhJgC2BReF(cQ>=%^UmMV@8eBCbP%Ai|?a_CmBEczx@z|hoWOsJ8L`3-Af zZR$*}1rF)TE3ZWEA zaQbIZ%HfhCD9Lq%P*ON;$Bg0V%gIp>0X(=s_bd&<^1%;!n}9RT8sK8(Ds)b19!i8$ z3{a{oF(NY^H=Cy8`MCP{c6TwA5|pj3-6s)IL#+S`-$@Mc9F zT&iCNH`6Qg_2}SI(s92}SNw2d8-HH{5kJQWNFGXuA~30a(6t>@F8bqdt_08tz@k#e zB(>eR07~u}YP)lE4S!6s^X*!(c63}|vHp)K1k=arrVqn-=BO0%+k?+~wMG5pIFwY@ z=l`)gLsGv=K}jGIY_e-qL5u2@9gLc?PsaoWe z!l`luu_V;zaluK+6NP6StRg<-SE>lg(Mh>YX$huc+Uqaa@2?Q&?c%JLEtDTAC5t$S8mODlRb^MN zggjS=wT8f?jajwR_dU6uiG&FqlY^4GS1E$h)SfOpr;wf9EGq~(AWe=!d(JH>>rT6R zcXeA0-5S~++v+7@cY{pl$$67OaNq@t)r2vs1glIc>)6)A`+gh^I~Qs`MD6@#m%U_|XS zjIEb}NsVe?V&fVZU9TECS1e8F=o*FH(`K{jhT0H10#D~k<(#@yDvNG}Vegbm=tXs9 zy?f;fuH7ds8U3qPCg4)gIf?Fx*VFj!N#)R&#|NfW#wfn;$@OYrc8j{0+qN+V@Q)ocPr?RNM5yr$kC+lnX4X5w16 zj<{Mo3pdg-J&-C_#l0#SPIo0bDBVAFqizbG4z7cDtD4~bzD9U^tUkUVTtWz$-khxK zq`EmJ!AW|1ye@t?+5#8*mcq4Km2fXT-EAv$wR$GLUpNEb@IAiC0iy$v3`ztHfe?dI z1c)58G#WKKygsX4(Uha}JlKne$%n{x1CUyJG< zN^NVWqIInl!l^PR^2!ckjjQ@`4GAdkniSUa5UL>{RVwX3rBcr}lk~t%0moF8ph=em zs0cz%bV{joNbVS2RjQ;u0ZOi_R6$gBi4%oUv3LQLr(;s`gaD;ADW_m#+7kKm5>9zh zlz=KhLr}V40e62@rQ(H<=gQF5xH_y2!PFMF=zQ)^B3L3QJrI>!o!R@_SCOVWXhI)if1O5<=q7a*a)Re9!iw>t^zPu<;Fjb_x zNg`-!l_`#{8CB4~Mhb@1O2f!H=@?Tt!+~i`{S1t(mx*2($!JTMWLGGIRu#*lHG$HO z!0AAsbV#j)jzXw5&CHZ0p^B(Y3FD>|PxDHYM4 zWoNc~R7*jxnrY}kFm=e}9}&-M%0Hau)hhFksG^G#*JGb3*91F&L92do>}i4Yp=fwW>Q!7%~nR!v}gtPAJKIqBHVtuyh% z?Y;QR>+|^e^CNUFOY!8;ay&V_%0X$*jG@>zX#loN>`#!5bI>^*fl2UjP+}wJfQ=+&!6@C8%OXZC$v{*IDwqp=3J0|etixhpj8^AB#m>Au86>7PU&NA zDFjhiPXtk@mkNcQ+vA}0S_uQ3^d!~aaMIJ`#h-6n#Q&i|xY4q?ON_XwupZ&$BtWHP zx;3BMX>?UtX?WBv6R)P##k(y{@YT^K&iUj9CWDf>rPn8F;mczU@a3AuIN7KOZg7IU zmzItzsj0Zqx+(s6U=zON`}%^Dx`&crmBSt&2{1{7i?t0LVLP{RzbFT{cssn7 zmjD-s+y_bkQ=&c&C4-T*cjE;e;jm7P9h5wTN=G3)){{%24xNUF6oI77I)&~CBqu`0 zLU#g^NdRi(ToS>hF>DK3tq7tvbyCs3Zkkh@I#tk`U}{mV5|2xQn@^aitF1aKi%w0Sq5NQh0+9D z8K=sn72flk(JBj2*??8bbHzMt0095=NklPz|gl@FU9SM?_vc@U=#i#PyNosjC;?it>q=V} zyLF{73(r9%fYJk{ga>KilB-kt=5LN5(IMF$cNVe>p(G$laUjj`*>EeTx+l?2Ss(11Jsg`q>xm`(vvGLtQ0I`&t^N#`)=$Re^;2+h?L%ouRDx**&zXtsQwC!5gnn2*rZ@J^9PVE8)H3gw3`QPKa!0cx zCp9(7x?6xdyH?;Do!|4Ler@RUL;O6VpZ}MnF_HuMQGzJ}N(Q5kIVFRVpcD4J(C!C> zklc}zs}n+mQXEWs@#X@*;mbJ*Of0{+z`oOj*shg$GJi7e^yrN98P#w-DK)`4v7SOu zr4dlo((xd>8lDWPjdv@X;M-%(@a|ND7>wewkX~&btBvoDH^HqTskm6XB5tQw;q}sR zwsK{>n==tVo!W_abV+hX1|@Svf>I1jk#g%xl#Th=xz-;Z5BtLYP;vOkK}BvXM}Pd7 zK`De&SP!9;6HXD3*!Plf9@wUC3`*WD(HRi{^&&{+a7dJZB-l78Y0e;+1f!T+VxLc( zh&!b08kNzyb_&|^%SZdVsUAqRE4y1M1f^z~KD;Lha$2XhHKrJtEUc$Kfyk+pgOcE> z@oLLiIdNRL%UTtF&}& zpQQCDIjKCC2DfrhQut0#x;H^!@f)h#|d$?m-gK~)sl)FLJse24YR^A!g1vf@? z#JS!ru&Hhmp;QeATi3yncJ*<*Lt`9^pmee)A=I-Oj!{RtHN&AUO>n4NQ|#){5UZNk z#HGgf3!?4gh^eSV*k9+bT)ml zdRTjGpVSK%*Gwc_CK5iAadp!a2O$CK0^xLN-6UMyFctUr&d0Cs9Kf&c9>62Iq~nXn z;M9r<*h|1|A(S@Jjcxp_KekOCh(o;ou|*06PNMVjyN3%*ehrE5jZ#vEJI1;)?zC2> zohs~Sw$Dql&mshpDdw06b97ee>S>3Kx6?Zyj;){h%@$J!UygON+0Lr<( zr1o3(zuVam=UbM=t*Qi`oL7}JT*<0~KOEbJuN;tahU_%a8ype=@iAzG<3lB$6CV3m zzg_c}WDpAL@%D#M5@bFGrQD=rudg0PpBA-IkFKb$b3-|uQdXe)1XBnlH{S&FOUs%m zuI}d+Klf;kYF#tch3wj8rK3I7xnYJ=hk9vLRkW*<=0bTbs_QzOdw6aZU6OzzkYtuC z9#ggQdiry5*Y6;c13Uy2-*;laLV+qR{AX};fOF>wR9dH^gNmROzhBDl=Vwx1RXV8D za;4~$inuVJ3-@XBSpv#ArRyWwQ|$;5zg>`|x^>tlKI zYM7dpieCI-TachF37b|WilZ$-;Q2)F3D&6IOLnl8{M|rIWx} z70b}Q5Cjn-0T2ji?yU~qAf6Iy9mtOI4AIi>C`AZ6+}*0)S^2QkO&?DsYBhW1W`IV)=x*L2366qUIyCom|&!HbzLP!)RF5UEX>_#eaVs_ zRLTkIm@@FRo+MZ~_d~GQdXs@k=P1?OrKMLGL zIW4*`N$KgDcJ?N&o;MOQ*-U(ctIi9X6f{>iiov|v_?uJ{VJK?H!k#1E38?q{67oF0+ zR#`ZxM{9R#go9lvx}^gW0d=rj6YOFCrq)?l)VLZZ)T)Bs{DIn(ER5D9XggZL4kT=c zie=G;YE-7QTSL+!Ss4MTXkjD~QX+8K!ue4m->0ZTKs89yFUmWa7?7wYPTtWNESk`{ zG|kY$Vch*VXQR5tv)|5lj)-H`uQ3iZx|YUM&8k&#<4ty6D4o-QW9#$0M!Z%d{&L6k zXoF*`=Qt>x-#}OdZYgnHNt3FZOruHEpp+wor~U{`8n5$o4TbG;1Cl}Me2%c4e=NBR z-#IW%!_h_Kuzp-0bgPks)nj_Ogoo{u>6V7K$H6&62&5?l(KNc28Mw85rjzQDc6PY4 zb2c9AnU5F8*WmfF)i^YNBsNd(kF{faVZ&$ruyMiwtRLSGJEjf6?is`Bq$c44KaUN3Ks2kR&-lm+BsURtEAAP>D(elZEkeOLoW&OwUwCKzdFP zN!p6Xlmkozi-%KAC`s0KfO2A;lcY;DkZZX}*TV9h)_D$Z#G^%oeE(j!-k?6N>jqrH z=>dWCpmH?=DwDACi4nJ}rsHno3_Kf37%gsuul6;?*C(6eo1M*Zy>~LM)~v+wRdI{D zSU(GY*t8tqpWo+zN1R{Y+PD!8=lr&y2Q*=jJymCF&2pd5sy=+mJ0`8>r@3Q>DPN_^QQ#7g*f(9yMZV{euqMJdZr>FN$vJnrtBB9yW!mm|zPoV3rMfTnYGk5wJL zKVGj&>7s6jh)OKwlqzw)&U0~Kb_AvNgh>P?trN)=eb&Xn=;8FK~$nMDoKarfJAqs?2dB93cH21 ziY1D=?2fW@R~d9k^$8^h98Ufr5MrP(phQp#$9zm7Y;>OW+jXojHiq9K8t|J!L+6J4 zacc`oaaF|Fo^5cPlkO?Gfc0}7m^_s9B-*98!O2z=txc>piMlXd;E+sOZ@L#vwmL`W z3U1*#QVtlIJ^)hu@#Ox-)@g2SX>#YrR3jJC+dX{{wod4c1G9z@9#aXT*@Vwrx}v$R zRNH}R%XHkNZf%>1Cx@5g&6y22vHUY^oY)uZ#`Sh!+A?tfb`eI$2%~d)L^=T^S^W~> zbY(L?7s6HUND`FHDG5qa2yqXloDM0JK}k~E!70Hl8IVF4nKKHZWb$x|T+=zfXPoMx zQ;NYz_y1_3i%LtqwtIgpeCF15lyWU`+&k$cUt`NsJee{YH(R&B72V&IM9D1?Oma`o zMX5i7s+Wn+JJ-a^iS_X1L_(=y3T~yRx^dSlr{U3{UikUgR(!?D`z@j2pp*aztE+r> z?P#pb?YP%r9=H03ijNh%_?p)Qrw_*@UR$NX$Bu`6;W3pTgOZg>f^bkufYS$1;_vJQ zuhStb6}bv(`dG(QJs0+ z4mjPr1vWHH#mbsV*wios+p=q7ce{Gn-M$`nw9CTwwp5$C*xIfx*3cnM;xD%YKe(*Y z#nG4`YRC__UUGS4lrDx!gpAS#OXU9)MLx}gQUsHLq{T6*YElKacvh;A?m8~ytYO{s zWHgkUp#zb{G>r2uyNIJ~e!qgOVoN9N+jkd0O}`1|xG!Iu=d34oY+n zp-ajYN;yJyaVVL>V=ISu#-PTjZg0F}i^gL=fwW^{Ph8nBg)o|j`+F9+^5!;emO2yH zHciL1jZ<-T!!(xDac9?jygIc3SGLT-<_UdW#@*i8Bi+7t?#Z%*(5Yq9aBAsPSHHB5 zklv)-E*A6W@R@_=l5&HRfMihmXHH2nAW8b{^jUf+`J{)BLFt3Gb4i@IA~;DeZ7oSo z>1>n^P5^~+H=ahNLFr?1A+-ohuDrO1?rAsP9^Z@?%V*$X`3^o~Sqc8Qu_xS_6uMiHfrDOkrl8KxAd2V{&c&{+{!5?@%Yjxdo+t`*2;( zkX<5_WYA?cWaBq_Jku2#GsR0vM?&ST^I_vdJ@aZgo8;=CQZvAyhetu!Se+t`xzZ*A{Z%* zCkUyo(&`HJ)ulB6fyk2X@RQl4(*I?+;av-y94|i9nGW$;l8HQnQ+=gpa^P zM?-g`J_D7hF_m~7l~y+(2{5{bm8KkRjZ1J!6Z^Es$+dHHKuK#$%EI$d@{_D4*Vtrw zkQ1pKQ6x>Iu9PB&r16@V%_Zduq_wkfE*FQCn{3R%d806*MRhD4+J$}7aA?j@_s9yR zf#2FThpuQAK{ONBH+x;#Fx_R^U0OF47uHN+dm5e|S&dse7UIzSF*v<^Dvv8nHy0)2~i(Q6u5a*U1i!8NE5MkWDCdc~jTwV)IMEWFPt5lW#;G9ZPep!AI3 zZdJV^C)~&-QEt+vJ20mt7+DBU$qj;z!gfkduq-+`o>pwTY`W@|*cS(n98r6P>Xg_} zKOG$#R7E@W$te*^N)>lbDVl%el&V!I{Klx@D$P@xq*A3&rY{ z2nF3Mq_)NhOfFd=0-LQfDLhx3szvvu9nTfclMF@zkF7uX&>!KXbt$T@j7Dljf=UlE zj6V|Ik{8uz2qFih&${Af1SL5n z!6*)-wm37O6*e@kiY3)5ViiBw^^G&JsYOj}Xjv2MvTI;9%Z1HrVIU{@8vH*e0+9rIhleQIQ{Vse*akjalXSp;qQEp$09Y zp8D886F6hcXhd@8LT7cDM-L0VH%S&!eMCiU%z z)9dHs?7F$soEVfWglFNq9N+j8pk%tMeje92oull%tJ`v}B^i*;1#3u&P;%{DK&5^q zJ}el}4*eUX;^KOObj3s*UpxxuS1BoB60UBXNzI5flW>`ii)*JiAe~t;!HvJTPB+5p zdO9`>XQM5JRCfsse4lbn(pA29LDisSFbd(680!0*hO9Vj(nNYuU%oJY7#(Nm$4xvyQ`^9yy zw+YwE0VQ6`IV6cta$vH)z%>a(iC_|ZLNMhJq4fCdUP6igzl4#XBM2$Ix=xY@Qs|b< zDK)8D-nk^L6SX0H1f^DlQOg=ySE|6W5&qxx zR6nJHgOc{cQ;N1_!uiZMh3xo+pI_SLPz0w+1W?7urI-XL9n%f5?h);j?nP1#`F`0RN~1f_ z0d*p5v~P5=Z2Y7hQ%QBf}vDP3@ zKrq)9c)m70sf8IF$UnE5{^h(XJAC@m_j_ML=Ypr-ih5JJy)%Mr@ps}^pll;J4yOv> za;nmGn`z7RI1+>DxzME06`+MPBO2k`y0fbV&JAD8RNAP;s&bM(k!xW@WAw#1bhY^$ z??+}~FDN3koaT%@y|9j;aUc0&InX$R<fZz;h?AFUsqgg$+<|T@D?&0$itE@uU)Z2>RQO11J*!zOK%c_$Z$`Os01p zh2Mn8amd4(PJDdGt!r}QW4bR_D(HACisV>=^%oxh?CHh$?pN+q9$ZIX2aLey9v^Zb z_G&68Fb4W{-`YclV4qbCV^=6do|<3V8N{(CZz0vNkuc?lYbhq{vg8YLH2>8A*B)W2 zYp}h-BR&ii=7XTt-_fc+KIBj*Tcp(q35M@vb1Qly9!U%J)Ng|`Xzmjtx%kR$uoUS| z>&6||=Ex*c1mQZ|bGN)t_oHYeAA zrn2J6v^ox?eC0u&4z3LT!(|NN#Si$P@&m+EW7b|*efcgAqkCMsWLRnVh>|Yu#(P-W z-Tb;gn2_hJN*my#Ct;L1(hZ*;GiwtY`8-Ww^TU3ce0!||_w6OcW)itY`jVnrkrlhT z;0Fu9`D5jVE{??nq*>FLw z0yu%o`}50DW3t&6P}BQA!#Bn-&vvz@>EnIvc3epAeJ`o`bQzC}qtHpGedX${u#}u#I&jKXtGve^?=`R;0E$I{Ry}sdfH+SR z3_XEv<*2_9X~2)YZCf*qky*j&g?PT2r7;~F^AuBJ+!ILdtsUO!RbXyBLfyXAKO;mQ z-}I$Y6C6tlK5J*!g*Z-AbFbi*GRPAGcIVjoUkvM9bEAP@%;Egm9R6-UR1F*cqk}h$&1)V4HMCwlICEq&s71tr|=cPCnDPo{kB*5q};&TxrTkzae%p%4i~NPV*lr*PU`fE29rxK8k#v zFQLU`Px%ax2Cay@jXyATIhN>$$HLq)n)@4SCcCVhcMs2lQL=psd^d)IkUkrO;1=o( zSsIdXHSVa+{w?B)WUOtvVC%c@`ehP9jxH1vgmwz8}7f_lsSdDHv7<5eH8h(HhSZ(tpMYCh^b1Mc^F9GVfpSgmAU z6$hbCn-S=^qKndtwF8y)NrM@XQb1d%9+E}l$=+DZjszKGY#(MH* z9E}z;WRetqXBx!Xb)U3u2L*?x_`apQ11s5pM5cBMMJ3tyKU$Uq4qH5d->#s!BS1Wf zq<3)E)x#bEk)7P6Y;*^5Yy zM+N;xQ8WmchM?z-Z?Fhsqj!HHMnTKTQm7v+ME0FE`|sf#J*g@oI(i!oDOmaZ(W&^5 z(D=ARO&zO3DWkIPr@l#1P=wF>(LJ|(uK+joo`+PYX4uGWgQpWJ0{|em?pcjHq%+U> zyS=i==9r0-cpd&J*xc4J<6Wjr6WPm2{k|%UQ>KB!-33kE;@9ifp#L^g;%KF!kAk~o zdN~Wd?oROh-Zpvq^c}~g#c*m%z#Sz$MC;I+Z}QHQnHs*%BJJ}*_B4?VcB54(XljAa z!Tp=V2QAJ>0Tu>~v!+3m#4j9YBeYYq*k6tF-ENmBvhTN-|bRe-DyzSR`*3$uhjD7Oc3~tgQ+cxm#pF>{dXnzj$g&+R=6-Bb7BKya&8aSUG2chaB4*dkooQ{qSE;p*E#tI$ zIRl>O>d5+1S>dOEd=y*VYYT4j#b;|dkNx&ZDUtKZ9ek>rxqLuq3=*tZH=8ab7-^=c^$Z@5K#vXfxC~)V!&_4r* zcpvbA=4_F96B|xSObhyA$tuy zg6yZ2F+V%EPjFRCa+r^=o?|xW6ccldf4=nA27zzLD}`*svZUROfJG+R`AV3dziSlq zQN;@>xXKrEDfxZMmki=je?h4n<(1moufOZeec0ZN#)1(1i*+G_r~lpv#rlY?<$7es ztZbx!Iq&Es4eV+oh0+Bhz8*%IGu}v{TeM6~Y}_;nMx!`kpbiq6_xaqcCVYv~&3uRz z3eAGA{0{3M|7BW92L-=X@~_?q{CTe3Xy3(Ux!8Kov{AgbxH>)uBtRlKRqMgyCo{G? zyqQj+#Xmg)e?tEydbbM{GY`1_J~}L3BkjnRS0B(jJ{{@^m$Tc*3fgKMYkn-8_Hj&d zVL$MBqF>y5mHVUl3=!CTbQv)HCn*LiBOwK7FmxPG?B57~pjiv;xq1fg9#QSceZRa2SAIC$zKH!xCUSIZx@7cFr}O1w>0v%UtN|?rWe0G*p_!%z2dK6 z`XVhsYHm&kFTVd!V;leEOujtsL~zV_lSmM_r;KwLlsxLbdAkC%WQTX*$m0B>>0j4y z^T%}PL1uBiQcXeN`|WmT2lU0BEob?iq=SpMeGqOxUzuoI=6}RU40Uh(TY4xfSqDuz zxa#(?APJ<=S;%_f6hF%{KwU<=X)#sJ8XWQMjbPV?ar(I#(@^Du!f%4do24LKL;L-h z(U>&D&mx_uMI~>Ieq7PlBtDqEX_C8atoTN_9dsmk+ifbY|KD1(xLn5|clN5U-0 zT9Tgut!mdw1-be<@S{`-FiZ!UG7thi1W-+}d;p4if4JvnCfsZ9iO zk`fUsGu~%qG;IHlMm1J~%wZoMg;djCdOuBFugI`Xy~;%o<;{d-6F#${lKs4Qok(q! z(qU_mN+Hq$@Ap!0yY|x?4G8_wbXR~VHXPAUA+iU85(WPGNA)gqAol3t=WAyB~i8?BFpDi2V? zOqioL#)Q*jqYnXYywn=s)^y z-QM_SIc2J1TK00PW_9MG{dq>ju8yja)wUMdIH{Jv-A^~aWec@!$Juu_|FFzq?)MCp zJTPq6e2#{i#E}Y_+)>vt0Onwwa04Nvcpg#mt|UUtf+Fo~Esl90hL8|x+h=F4O_zdT zgsS;^Gl%B;^okgtk#xANAXODj`@QQeC{50c_ah4j@hq&J-I zQV}hC{+f+FLi@Rbh3Q!0SAVJiRi{UApxWB}kv$~tYJ${&AS6o}!h1XHB_x;l2E+Ly z%w=~c4q?0Im^L-I0|epOB1xN~es)EdBI1*=fj$OP0WAUVwlvF!8=LttrLJpb6K}frD03J)ElD44>ACA0Q;{JItPfbk!u=)*ae+%VLCJ}j*vxe)T4{h(y|dU zN6Zfu3X(`SkV@eb0>#6cByASuSrwR)C|9%T3Jz9xP?7zY&KQhmu&sbd4hufV|pl;lM)sx_sVVJXN8Xt@!ja%D-1Gh zrQ2U9ZC7*yX8?E`%ralVsTFNDal}w1jCyf)YK$?sST^O~JFD+8_pJqTYV;o0Os)}& z1+lc$7a8@Y_Du7mzj($DYdinPp8?k<)$-B-pc}jT)URXd1Mi1tr`k?@l5F%ZPsX!v zKll2icVEnq1|EG_p#DqUEuIs~{YptN6qgRPXU1a(g%DH0JpsWpr(6~^NVGUS1FD4A zGH!U^XXD3yW3)Z!YL+QRn1sOc`$t9zd#5HcE2@|2wBUcg0csM)M%SuJ?XWMO4~{_a zMW#BC*d2uH+u9TJ-&ZfczMcg$w@Cwd5+f@rM1ReWWzu%**^WvCl3y1~$KmF!{$0aK zeabwZ-}lk6mo7ItTj2$at9RZAgtkH3@-~C)*uR==W#TJ`?rJr@^hw3*ig-sFflFw# zi1|pM(VKK9&C)c`2y7o9Ab?U#!B7P3FJXw7fl*iF9XOyBmC-07@vJ_7k!*3TT+~GY zbFhenN^67f=Yum8u*Y;bM49* zqEBYhHINn+gOZqBK3P~76#VQ=pRM{et5z{`%7i)dSowZqx_am)))4#|QUOi#2g+jN z)t+NOn`IxRW8Mf68@+1f$47->mNZXBTLi=3zp#)%n)sgzGL9)} zBMz7n1`8jC76j7ds#`OijA`Z)kyU7S7+9TBogeQk$ri6fs0Y{}FK|F-LZ6E&J9F;o zm#@QlCFK_tk^7IJ`^pn$3mD>tYI5F9j%zQ^=02fP1c(FWdt3U1vGhBXk1%gn48FKV z-*>7IEiJl4-zQ!73q`7RaRIzQ11VF!4=b^1+Uwf=dVWJW?!~(*UU5V)5+Gc!%v7ig zEFW_F_a1rg>={b}#X}=->3otdcS?|w*MAWP6Sa*C*+I8;(~-Q5_|can(55^q8UQh@ z8oN(=NqJv#9To301m)7C+RUlG)$};@jU0YXojHJ&m6bCfRX(6uFwM?iq0{Wbn1b(3 zwzmWekwkSV3%gd~xKR1E6XLI4{mU`tgvf-MDgC?5>^i#r(B=JSk#2&*!^@h(Bz721 zO06F?{zLfkK#FjDw|M+lhm!BZ-6ZvAc}BfC7Gpo_S!W&V=>Rg%aSD&^zhCr1!Guwv z=xC*}t~(V^gHDNaKG|Uwjbwhl?ss$b6UxBR^@F2lqr%iQ4d`?rnP7qzdLrZ&rrp?C zmoSRCl2AVb>KLg=X??{VF`5)dIb4&9yoHYu+@+7tvSS|w}7D-oVvrKl*p7=_( zJFxq##iUr@R}q5uk{f~OR^8qS?Vc73BlC7+k_MJg$w`9lxHxq=E>BBIc|M03r*$*Y z0Vhf=nlGd_#T__RnqysJavRgotL(ao=DM0~oT7|%1_bnJI*#40JSA^yE%0AfL|R{O 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 a#Y-s6k#@ZN^$KV;u;49pqL8+ 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 z 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 ZCphLc<9fmIfD8ousVi$Kl_{78{tpxkxs?C_ literal 0 HcmV?d00001 diff --git a/images/Boxed sensor.PNG b/images/Boxed sensor.PNG new file mode 100644 index 0000000000000000000000000000000000000000..39a4f3261221ad87f226c2489ed61a4bf0a4e4e2 GIT binary patch literal 268868 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 -Ana^+k@@Z}g0NS5 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 z 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%0D_85k`g&{Z_Lb*Y3>DWs4M;|k25EibV`i6HGJ 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 literal 0 HcmV?d00001 diff --git a/keywords.txt b/keywords.txt index 3aeaf22..4222520 100644 --- a/keywords.txt +++ b/keywords.txt @@ -26,6 +26,9 @@ readMagneticField KEYWORD2 readAccel KEYWORD2 readGyro KEYWORD2 readMagnet KEYWORD2 +readRawAccel KEYWORD2 +readRawGyro KEYWORD2 +readRawMagnet KEYWORD2 accelerationAvailable KEYWORD2 gyroscopeAvailable KEYWORD2 diff --git a/library.properties b/library.properties index 6933e90..a31ae6a 100644 --- a/library.properties +++ b/library.properties @@ -1,10 +1,10 @@ name=Arduino_LSM9DS1 -version=1.1.0 -author=Arduino -maintainer=Arduino +version=2.0.0 +author=Femme Verbeek +maintainer=fv@tcenl.com sentence=Allows you to read the accelerometer, magnetometer and gyroscope values from the LSM9DS1 IMU on your Arduino Nano 33 BLE Sense. -paragraph= +paragraph=Includes built in calibration of the sensors, "set" and "get" methods for Output Data Rate, Full Scale, Band Width and return the data in a unit of choise. category=Sensors -url=https://github.com/arduino-libraries/Arduino_LSM9DS1 +url=https://github.com/FemmeVerbeek/Arduino_LSM9DS1 architectures=* includes=Arduino_LSM9DS1.h diff --git a/readme.md b/readme.md new file mode 100644 index 0000000..762e91d --- /dev/null +++ b/readme.md @@ -0,0 +1,535 @@ +# Notes on version 2.0 of the LSM9DS1 library + +## Written by [Femme Verbeek]( https://www.linkedin.com/in/femmeverbeek/ ) +### Pijnacker, The Netherlands +### 11 june 2020 + +---------------------------------------------------------------------------- + +## Contents: +1. Introduction +1. Naming strategy +1. Output of Read method +1. Output Data Rate (ODR) +1. Full Scale setting (FS) +1. Band Width setting (BW) +1. Calibration + * Offset + * Slope +1. Overview of Code +1. Derivation of linear correction + * Offset + * Slope + +-------------------------------------------------------------------- +## 1 Introduction +---------------------------------------------------------------------- + +The reason for writing this update is that the LSM9DS1 chip has several settings that can be used to tweak the measurement +results. The sensors are not calibrated and the output may vary per instance of the chip. +In my case the magnetic field offset was larger than the Earth magnetic field. The gyroscope offset of 3 deg/s does not sound +like much, but when trying to track the orientation it corresponds to a full circle misalignment in two minutes. Without +calibration it is impossible to make a working magnetic or gyro compass, artificial horizon etc. + +This new version 2 provides a simple DIY calibration program that gives instructions on how to do measurements. It returns +the parameters on screen so that they can be copy/pasted directly into the code of a sketch. For a rough calibration you +have to do this only once per instance of the chip. But the magnetic field is very easily disturbed. In a different set-up +the chip may return completely different magnetic values. + +In spite of some examples, this library does not prescribe the methods for measuring or calibrating, provide quaternions or +Euler transformations. The development of these is still the task of the user of this library. The examples are kept as simple +as possible and are just for learning. + +New for all 9 DOF (degrees of freedom) is the possibility: +* to change the Output Data Rate (ODR), including fast rate magnetic sampling. The values returned by get...ODR are + now the actual values rather than those in the documentation. +* to change the internal full scale setting of the chip (FS) giving it more accuracy at the expence of the range +* to change the band width filtering of the chip +* to change the output unit +* to give it calibration zero offset and slope factors +* to change the operational mode (off, Acceleration only, Acceleration + Gyroscope + +The values returned by the read... methods change according to the settings. If left to their default, the output will still +be the same as from version 1.1.0. +The way this is organised is rather unique. (mathematical derivation at the end of this document) + +All the settings and calibration factors are independent of each other. + +This means that +* changing the FS does not change the read... value, giving it more accuracy at the expense of the range. +* calibration of slope and offset factors can be done combined or separately in any following order. +* calibration can be done in any chosen Unit, FS, ODR, +* the calibration factors can be copy/pasted in a sketch. They dont need changing when the sketch +uses any other setting combination of Unit, FS or ODR. + +------------------------------------------------- +## 2 Naming strategy +------------------------------------------------- + +Keeping the same naming convention of version 1.1.0 resulted in very long names for the new functions, making formulas +difficult to read, increasing the chance of making typo's and it was not always clear what was meant. +For this reason a number of shorter aliases were created most of them following the [datasheet](https://www.st.com/resource/en/datasheet/lsm9ds1.pdf) + +new | alias +----- | --------------- +Accel | Acceleration +Gyro | Gyroscope +Magnet | MagneticField +ODR | SampleRate +FS | FullScale +BW | BandWidth + +Addition of "set" and "get" in the names of ODR, BW and FS functions. + +e.g. *magneticFieldSampleRate* still works, but in the library code it is now *getMagnetODR* reflecting that it is not longer +a constant but a function corresponding to the LSM9DS1 chip setting. + +Not used were the datasheet's XL, M and G since it may confuse with gravity, Gauss and of course the size of clothes. :tshirt: + +#### In the text below ... stands for any of the three measurement properties, Accell, Gyro, or Magnet. + +------------------------------------------ +## 3 Output of Read method +----------------------------------------- + +There are several ways in which a linear correction can be applied. The chosen method has the highest amount of advantages. +The offset and slope are independent of each other and of any of the other settings in the program. They can be measured +independently and counteract only the internal transducer differences. (For mathematical derivation see below) + +There are two read methods for each of the properties ... +``` + readRaw... = (FS / 32786) * Data +``` + and + +``` + read... = Unit * Slope *( readRaw... - Offset ) +``` +Data = the measurement value showing up on the chip registers +FS = the in Program Full Scale setting (float get...FS() ) counteracting the internal chip setting so that + the output result remains unchanged. +Unit = the unit the measured physical property is expressed in. +Slope and Offset = calibration parameters. + +readRaw... produces dimensionless uncalibrated output and is the method to be used when calibrating. +read... produces calibrated output in the unit of your choise. + +Note that when Unit, Slope and Offset are left to their default values, the read... and readRaw... methods +produce the same output, identical to that of library version 1.01. + +Measuring the offset shows that it scales with the chip internal full scale setting (IFS). That means that it is caused +by the internal transducer and not by the ADC. So it is sufficient to calibrate for just one of the full scale settings +and compensate for the others by means of a multiplication (FS). + + +------------------------------------------ +## 4 Output Data Rate (ODR) +----------------------------------------- + +This library offers the possibility of changing the sample rate of the LSM9DS1 chip. +``` + set...ODR(); //changes the sample rate according to the table below + get...ODR(); //returns the actual ODR value (Hz) that was previously measured +``` +The ODR values According to the datasheet + +| nr |setAccelODR(nr)| setGyroODR(nr)|setMagnetODR(nr) | +|:----:|:-------------:|:-------------:|:-----------------:| +|0 | Gyro&Accel off | Gyro off | 0.625 Hz | +|1 | 10 Hz | 10 Hz | 1.25 Hz | +|2 | 50 Hz | 50 Hz | 2.5 Hz| +|3 | 119 Hz | 119 Hz | 5 Hz| +|4 | 238 Hz | 238 Hz | 10 Hz| +|5 | 476 Hz | 476 Hz | 20 Hz| +|6 | don't use | don't use | 40 Hz| +|7 | | | 80 Hz| +|8 | | | 400 Hz| + + +As it turned out the actual ODR could deviate significantly from the datasheet values. +The set...ODR voids measure of the atual ODR value in about 0.35s. This value is returned by +the get...ODR functions. This causes a delay of 0.7s on the start-up of the program. + +To save on power demand the Gyro or both Gyro+Accel can be switched off by setting ...ODR(0). +In any other setting Gyro and Accel share their ODR, so changing one, changes the other. + +------------------------------------------------- +## 5 Full Scale setting (FS) +-------------------------------------------------- +This library offers the possibility of changing the Full Scale setting of the LSM9DS1 chip. It changes the +chip's internal multiplier, assigning more bits to the measurement but limiting it's range. +``` + set...FS(); //changes the FS according to the table below + get...FS(); //returns the FS multiplier +``` +FS settings + +| nr |setAccelFS(nr)| setGyroFS(nr)|setMagnetFS(nr) | +|:----:|:-------------:|:-------------:|:-----------------:| +|0 | ±2 g | ±245 °/s | ±400 µT| +|1 | ±24 g | ±500 °/s | ±800 µT| +|2 | ±4 g | ±1000 °/s | ±1200 µT| +|3 | ±8 g | ±2000 °/s | ±1600 µT| + +Datasheet anomalies +* Upon *setAccelFS(1);* the needed multiplication factor should be 16 but turns out to be 24, + but the sensor maxes out at 20 g +* The *setGyroFS(2); is *NA* according to the datasheet, but when tested it worked nicely at 1000 °/s + +------------------------------------------------- +## 6 Band Witdh setting (BW) +-------------------------------------------------- + +The possibility of setting the band width filtering was added for the purpose of geting rid of a very nasty +spike in the gyro/accel signal at the highest ODR. It turned out that there was no influence on the spike at all. +The methods are provided "as is". The set values can be found in the [datasheet](https://www.st.com/resource/en/datasheet/lsm9ds1.pdf) +tables 46, 47 and 67. +``` + set...BW(); + get...BW(); +``` + +------------------------------------------------- +## 7 Calibration +-------------------------------------------------- + +This library has a linear calibration possibility built in. +For each property, Accel, Gyro and Magnet and each of the three directions (x, y, z) +a set of two factors (Slope and Offset) must be found. So in total 18 calibration factors. +Setting their values correct, is all that is needed to change the output of the read...() methods from raw +into calibrated values. + +An interactive DIY_Calibration program is provided with this library. See [instruction video](https://youtu.be/BLvYFXoP33o) +It explains how to measure each of the factors, collects data and presents the result on screen as +copy/paste-able code. No special setup is required, but it helps to fix the board in a non-magnetic rectangular box. + +![](/images/Boxed sensor.PNG) + +The calibration factors may be different per instance of the LSM9DS1 chip. They will hardly vary in time, +so it is sufficient to calibrate them only once. The magnetic field is easily disturbed by even the smallest +pieces of metal in the setup (car, drone, ...). An "in-situ" calibration is advised for the magnetic property. + +The calibration values don't depend on any of the settings in the program, like ...Unit, +...ODR, ...FS (full scale). You can change them in your sketch without the need to recalibrate. + +Sensor fusion programs usually have their own calibration methods. It is not advised to mix them unless you know +what you are doing. You will loose the advantage of the independency of parameters though. +If you want the fusion program to be using a changed ODR or FS setting, you may have to add some codelines +in the library itself in the file LSM9DS1.CPP / in the method int LSM9DS1Class::begin() +No guarantee that it works. + +If you want to design your own calibration method, the text below gives a more explanation on what to do. +It is vital that the calibration measurements are done with the raw... functions to get uncalibrated data + +------------------------------------------------------------------------------------------ +### Offset + +In order to find the value of Offset we must do a zero point measurement. That means that the physical property ... +we are trying to measure should actually result in a value of 0. E.g. keeping the board still should result in zero +gyroscope values for x,y and z. For acceleration the two axes perpendicular to the Earth gravity should be zero. + +The offset calibration values are stored in the arrays +``` + ...Offset[3]={0,0,0} +``` +The value ...Offset should get: +``` + ...Offset = readRaw... (@zero-point) +``` +so the (average) output of the readRaw... functions during a zero point measurement. +In the calibrated read... function its value gets subtracted from readRaw, so the average read... output will +equal 0 in a zero point experiment. + +Alternatively if it is difficult to get a zero property, you could try to find the maximum and minimum values and +use the point in the middle + + readResult = ( Read_max + Read_min ) / 2 + +This is probably more complex than what it looks like. Both Read_min and Read_max can best be some sort of average. +If you simply use the min() and max() values of a lot of measurements, the final results are still just from one measurement +each. Most probably these are the outlyers in both directions, so actually the worst measurements. + +Calculating separate averages of the min and max values is a better method but also like a chicken and egg problem. +Before the calibration program can decide to which average a measurement belongs, it needs a rough calibration first. +If the offset is very large, like in case of the magment, this is not straight forward. The DIY calibration program +uses the fastrate magnet ODR and simply caluculates a lot of averages and takes the min and max of that. + +The best method is probably 3D elliptical regression, where the values of Offset correspond to the centre of the +elliptoid. So far I did not venture into the mathematics of this. :dizzy_face: + +-------------------------------------------------------------------------------------------------------------------- +### Slope + +Slope is a dimensionless number that compensates for the sensitivity of the chip's internal transducer. Ideally it's value +should equal 1, meaning that the sensitivity is what it's suppost to be. I my case the accelerometer was very close, the +gyro 17%, 13% and 4% to low, the magnetometer 5%, 4% and 7% too high. For the magnet and the Accel only their relative +values matter, but for the Gyro it's the absolute value if you want to keep track of orientation. 17% means 61 degrees +misalignment on a full turn. + +In order to calibrate the Slope parameter at least two measurements (say 1 and 2) must be done where the physical quantity, +(let's call it Q), has a known difference, so Q_1 - Q_2 = known value. + +The value of slope follows from +``` + Result = abs (( Q_1 - Q_2) / ( readRaw_1 - readRaw_2 )) +``` +The slope calibration values are stored in the arrays +``` + ...Slope[3]={1,1,1} +``` +The local data of the magnetic field (in nT) can be found at [Wikipedia](https://en.wikipedia.org/wiki/Earth%27s_magnetic_field) +By pointing the sensor axes in both ways in the direction of the magnetis field lines the difference in reading should be +2x the given fieldstrength. +![](/images/Aim axes along magnetic field lines.PNG) +E.g. the Earth gravity should produce a value of 1g. Holding the board upside down should measure -1g. So the difference +``` + ( Q_1 - Q_2) = 2g +``` +Lets assume that readAccel produces values of 1.3 and - 0.9 +``` + Offset = (1.3 + (-0.9)) / 2 = 0.2 + Slope = (1 - (-1)) / (1.3 - (-0.9) = 2 / 2.2 = 0.90909 +``` + +---------------------- +## 8 Overview of Code +---------------------- + +(almost) unchanged +``` + int begin(); + void end(); + void setContinuousMode(); + void setOneShotMode(); + int accelAvailable(); // Number of samples in the FIFO + int gyroAvailable(); // Number of samples in the FIFO + int magnetAvailable(); // Number of samples in the FIFO +``` + +existing functions changed for new functionality. Results reflect calibration, full scale and unit settings +``` + int readAccel(float& x, float& y, float& z); // Results are in G (earth gravity) or m/s2 + int readGyro(float& x, float& y, float& z); // Results are in degrees/second or rad/s + int readMagnet(float& x, float& y, float& z); // default in uT (micro Tesla) +``` +new functions resembling the old read functions, use these for calibration purposes +``` + int rawAccel(float& x, float& y, float& z); // Return uncalibrated results + int rawGyro (float& x, float& y, float& z); // Return uncalibrated results + int rawMagnet(float& x, float& y, float& z); // Return uncalibrated results +``` +existing functions that now return a previously measured value +``` + float getAccelODR(); // Sampling rate of the sensor (Hz) + float getGyroODR(); // Sampling rate of the sensor (Hz) + float magnetODR(); // Sampling rate of the sensor (Hz) +``` +New the possibility to change the ODR registers (Output Data Rate) +``` + int setAccelODR(int8_t range); // 0:off, 1:10Hz, 2:50Hz, 3:119Hz, 4:238Hz, 5:476Hz, 6:952Hz + int setGyroODR(int8_t range); // 0:off, 1:10Hz, 2:50Hz, 3:119Hz, 4:238Hz, 5:476Hz, 6:952Hz + int setMagnetODR(int8_t range) // range (0..7) corresponds to {0.625,1.25,2.5,5,10,20,40,80,400}Hz +``` +Notes: +1. The 952Hz Accel and Gyro ODR does not seem to work. It's true value is close to setting 5, + but it produces a lot more noise in the form of spikes +1. The Magnetic 400Hz setting corresponds to the chip's fast rate setting +1. Changing any of the settings quickly measures the actual ODR value for the get...ODR to return. + +New constants used in ...Unit setting +``` +#define GAUSS 0.01 +#define MICROTESLA 1.0 // default +#define NANOTESLA 1000.0 +#define GRAVITY 1.0 // default +#define METERPERSECOND2 9.81 +#define DEGREEPERSECOND 1.0 //default +#define RADIANSPERSECOND 3.141592654/180 +#define REVSPERMINUTE 60.0/360.0 +#define REVSPERSECOND 1.0/360.0 +``` +Unit settings that read... returns measurement results in. +``` + float accelUnit = GRAVITY; // GRAVITY OR METERPERSECOND2 + float gyroUnit = DEGREEPERSECOND; // DEGREEPERSECOND, RADIANSPERSECOND, REVSPERMINUTE, REVSPERSECOND + float magnetUnit = MICROTESLA; // GAUSS MICROTESLA NANOTESLA +``` + +methods for internal use +``` + int getOperationalMode(); //0=off , 1= Accel only , 2= Gyro +Accel + float measureAccelGyroODR(unsigned int duration); + float measureMagnetODR(unsigned int duration); +``` + +Calibration parameters Slope ans Offset : See Calibration. +``` + float accelOffset[3] = {0,0,0}; // zero point offset correction factor for calibration + float gyroOffset[3] = {0,0,0}; // zero point offset correction factor for calibration + float magnetOffset[3] = {0,0,0};// zero point offset correction factor for calibration + float accelSlope[3] = {1,1,1}; // slope correction factor for calibration + float gyroSlope[3] = {1,1,1}; // slope correction factor for calibration + float magnetSlope[3] = {1,1,1}; // slope correction factor for calibration +``` + +Methods for setting the calibration +``` + void setAccelOffset(float x, float y, float z); + void setAccelSlope(float x, float y, float z); + void setGyroOffset(float x, float y, float z); + void setGyroSlope(float x, float y, float z); + void setMagnetOffset(float x, float y, float z); + void setMagnetSlope(float x, float y, float z); +``` + +New: changing the full scale sensitivity of the sensors. +The functions modify the FS (full scale) registers of the LSM9DS1 chip changing sensitivity at the expence of range. +Changing this setting does not change the x,y,z output of the read functions, but assigns just more or less bits +to the sensor measurement. +``` + int setAccelFS(uint8_t range); // 0: ±2g ; 1: ±24g ; 2: ±4g ; 3: ±8g + int setGyroFS(int8_t range); // 0= ±245 dps; 1= ±500 dps; 2= ±1000 dps; 3= ±2000 dps + int setMagnetFS(int8_t range); // 0=400.0; 1=800.0; 2=1200.0 , 3=1600.0 (µT) +``` +*note* According to the data sheet gyroscope setting 2 = 1000 dps should not be available. For some reason it worked + like a charm on my BLE Sense board, so I added the possibility. + +New functions return the Full Scale setting of the corresponding DOF as set with the corresponding set...FS functions +``` virtual float getAccelFS(); // Full Scale setting (output = 2.0, 24.0 , 4.0 , 8.0) + virtual float getGyroFS(); // output = 245.0, 500.0 , 1000.0, 2000.0) + virtual float getMagnetFS(); // output 400.0 ; 800.0 ; 1200.0 , 1600.0 +``` +Note: According to the datasheet setAccelFS(1) should correspoond to 16g. Measurement showed that it is actually 24g + but that the sensor maxes out at 20g. Since the actual value is used in a calculation the value of 24g is returned + by getAccelFS for that setting. + +The band with routines were added as an attempt to dampen a nasty spike that existed in the Gyro signal. It had no +observable effect. The methods are provided as is. +``` virtual float setAccelBW(uint8_t range); //0,1,2,3 Override autoBandwidth setting see doc.table 67 + virtual float getAccelBW(); //Bandwidth setting 0,1,2,3 see documentation table 67 + virtual int setGyroBW(uint8_t range); //Bandwidth setting 0,1,2,3 see documentation table 46 and 47 + virtual float getGyroBW(); //Bandwidth setting 0,1,2,3 see documentation table 46 and 47 +``` +----------------------------------------- +## 9 Derivation of linear correction method +------------------------------------------- + +Sorry for the very formal derivation below. It suits verifiability but probably only my own purpose :nerd_face: +It took a lot of puzzling to get it right. Don't read it if you don't want to. :dizzy_face: + +----------------- +### Offset + +Assuming good linearity of the transducer, we can model the data output of the chip as + + Data = (32768 / IFS) *( A*Q + B) (1) + +Data = the measured value showing up on the chip registers +Q = the actual physical quantity we are trying to measure in any of the 9 DOF +IFS = the chip Internal Fullscale Setting. +A,B unknown constants representing chip instance differences + +Since the chip outputs dimensionless bits and bytes only, the dimensions of IFS and B must equal the dimension of Q. + +The challenge is to get rid of the unknown constants A and B and translate them into measurable quantities produced by the +library's Read methods. Since a good calibrated Read should produce a number equal to the actual physical quantity +we can state + + Read = Q + +Further, we do not want to recalibrate when we change the Full Scale setting or the Unit. + +Define +FS = the in-program Full Scale function counteracting the IFS so that the output result remains unchanged. + (dimensionless, but its value corresponds to that of the chosen default unit) +Slope = in-program correction factor for the sensor sensitivity +Offset = in-program correction factor for the sensor zero point offset + +The output of the read methods is (see above) + + Read = Unit * Slope * (FS / 32786 * Data - Offset ) (2) + +Substitute eq(1) + + Read = Unit * slope * (FS / IFS * 32786/32786 * ( A*Q + B ) - Offset ) + + Read = Unit * slope * (FS / IFS * ( A*Q + B ) - Offset ) (3) + +In case of the calibrated zero point measurement Q = Read = 0 +Substitute in eq.(3) we get + + 0 = Unit * slope * (FS / IFS * ( A*0 + B ) - Offset ) + + Unit * slope * Offset = Unit * slope * FS / IFS * B (4) + +For an uncalibrated measurement of a zero point (ZP) filling in Offset=0 and Q=0 in eq(3) we get + + Read_uncalibrated_ZP = Unit * slope * FS / IFS * B (5) + +The righthand terms in equation (4) and (5) are identical so it follows that + + Offset = read_uncalibrated_ZP / (Unit * slope) (6) + +This defines how we should do the calibration measurements. In the library the methods called set...Offset +use of eq(6) to assign the uncalibrated zero-point read values to the corresponding program parameters. +Eq.(6) suggests that Offset depends on Unit and Slope, but this is not the case as the Read method scales +with the same value. To proof this we write eg(4) in a different form + + Offset = (Unit * Slope) / (Unit * Slope) * FS/IFS * B (7) + +Further since the dimensionless FS counteracts IFS in size +and the dimension of IFS equals that of Q, the ratio FS/IFS is 1/Unit. +or in other words + + Unit * FS /IFS = 1 (8) + +eq(7) reduces to + + Offset = B / Unit = B_dimensionless (9) + +So Offset equals the dimensionless form of B and does not depend on any other parameter. + +----------------- +### Slope + +In order to calibrate the Slope at least two measurements (say 1 and 2) must be done where the measured quantity Q +has a known difference. The calibrated Read equals Q so + + Q_1 - Q_2 = Read_1 - Read_2 = known value (10) + +Substitute eq(2) + + Q_1 - Q_2 = Unit*Slope*(FS/32786*Data_1 - Offset) - Unit*Slope*(FS/32786*Data_2 - Offset) + + = Unit*Slope*(FS/32786*(Data_1 - Data_2) (11) + +So the difference between the measurements gets rid of the Offset +For an uncalibrated measurement we must set Slope = 1. +Eq(2) becomes + + Read_uncalibrated = Unit * (FS / 32786 * Data - Offset ) + +In eq(11) we get + + Q_1 -Q_2 = Slope * ( Read_uncalibrated_1 - Read_uncalibrated_2) + + Slope = (( Read_uncalibrated_1 - Read_uncalibrated_2) / (Q_1 -Q_2) (12) + +So in order to measure the slope we must first set the Slope parameter to 1. + +In order to prove that Slope is independent of all the other program parameters we substitute eq(1) in eq(11) + + Q_1 - Q_2 = Unit*Slope*(FS/32786)*(32786/IFS)*(A*Q1 +B - A*Q2 -B)) + + (Q_1 - Q_2) = Slope* Unit*(FS/IFS)* A *(Q1 - Q2) (12) + +and with eq(8) + + ( 1 ) = Slope * 1 * A *( 1 ) + + Slope = 1 / A + +So Slope only depends on A, the (in)sensitivity of the sensor. The proportionality is inverse since Slope is the +compensation factor for the chip's insensitivity + +QED diff --git a/readme.txt b/readme.txt deleted file mode 100644 index a6b0624..0000000 --- a/readme.txt +++ /dev/null @@ -1,426 +0,0 @@ -Notes on version 2.0 of the LSM9DS1 library -Written by Femme Verbeek, Pijnacker, The Netherlands -https://www.linkedin.com/in/femmeverbeek/ -5 june 2020 - - -Contents: - Introduction - Naming strategy - Output of Read method - Calibration - Offset - Slope - Offset and Slope Combined - Overview of Code - Derivation of linear correction - Offset - Slope - -***************************************************************************************************************************** -***************************************** Introduction ********************************************** -***************************************************************************************************************************** - -The reason for writing this update is that the LSM9DS1 chip has several settings that can be used to tweak the measurement -results. The sensors are not calibrated and the output may vary per instance of the chip. -In my case the magnetic field offset was larger than the Earth magnetic field. The gyroscope offset of 3 deg/s does not sound -like much, but when trying to track the orientation it corresponds to a full circle misalignment in two minutes. Without -calibration it is impossible to make a working magnetic or gyro compass, artificial horizon etc. - -This new version 2 provides a simple DIY calibration program that gives instructions on how to do measurements. It returns -the parameters on screen so that they can be copy/pasted directly into the code of your sketch. For a rough calibration you -have to do this only once per instance of the chip. But the magnetic field is very easily disturbed. In a different set-up -the chip may return completely different magnetic values. - -In spite of some examples, this library does not prescribe the methods for measuring or calibrating, provide quaternions or -Euler transformations. The development of these is still the task of the user of this library. The examples are just for -learning, but they are not part of the library code itself. - -New for all 9 DOF (degrees of freedom) is the possibility: - to set and get the Output Data Rate (ODR), including fast rate magnetic sampling. The values returned by get...ODR are - now the actual values rather than those in the documentation. - to change the internal full scale setting of the chip (FS) giving it more accuracy at the expence of the range - to change the band width filtering of the chip - to change the output unit - to give it calibration zero offset and slope factors - to change the operational mode (off, Acceleration only, Acceleration + Gyroscope - -The values returned by the read... methods change according to the settings. If left to their default, the output will still -be the same as from version 1.1.0. -The way this is organised is rather unique. (mathematical derivation at the end of this document) - - All the settings and calibration factors are independent of each other. - -This means that -- changing the FS does not change the read... value, giving it more accuracy at the expense of the range. -- calibration of slope and offset factors can be done combined or separately in any following order. -- calibration can be done in any chosen Unit, FS, ODR, the factors copy/pasted in a sketch which on turn can use the LSM9DS1 - in any other combination of Unit, FS or ODR. - - -***************************************************************************************************************************** -***************************************** Naming strategy ********************************************** -***************************************************************************************************************************** - -Keeping the same naming convention of version 1.1.0 resulted in very long names for the new functions, making formulas -difficult to read, increasing the chance of making typo's and it was not always clear what was meant. -For this reason a number of shorter aliases were created most of them following the datasheet: -https://www.st.com/resource/en/datasheet/lsm9ds1.pdf - -Accel for Accelleration, -Gyro for Gyroscope, -Magnet for MagneticField, -ODR for SampleRate (= Output Data Rate), -FS for FullScale, -BW for BandWdth, -addition of "set" and "get" in the names of ODR, BW and FS functions. - -e.g. magneticFieldSampleRate still works, but in the library code it is now getMagnetODR reflecting that it is not longer -a constant but a function corresponding to the LSM9DS1 chip setting. - -Not used were the documentation's XL, M and G since it may confuse with gravity, Gauss and of course the size of clothes. :) - - -***************************************************************************************************************************** -********************************** Output of Read method **************************************** -***************************************************************************************************************************** - -Measuring the offset shows that it scales with the chip internal full scale setting (IFS). That means that it is caused -by the internal transducer and not by the DAC. So it is sufficient to calibrate for just one of the full scale settings -and compensate for the others by means of a multiplication. - -The output of the read methods for each of the 9 DOF is now - - Read = Unit * Slope *( (FS / 32786) * Data - Offset ) - -Data = the measurement value showing up on the chip registers -FS = the in Program Full Scale setting (float LSM9DS1Class::get...FS() ) counteracting the internal chip setting so that - the output result remains unchanged. -Unit = the unit the measured physical property is expressed in. -Slope and Offset = calibration parameters. -Note that the read method still produces the same output as in library version 1.01 on the condition that Slope = 1; -Offset=0; and Unit set to its default value. - -There are several ways in which a linear correction can be applied. The chosen method has the highest amount of advantages. -The offset and slope are independent of each other and of any of the other settings in the program. They can be measured -independently and really counteract the internal transducer differences. (For mathematical derivation see below) -All Unit factors equal 1 for their default settings. - - -***************************************************************************************************************************** -********************************** Calibration **************************************** -***************************************************************************************************************************** - -In the text below ... stands for any of the three measurement properties, Accell, Gyro, Magnet. - -For a full calibration we must find a set of two factors (Slope and Offset) for each property ... and each of the three -directions (x, y, z). So in total 18 calibration factors. - -Following the procedures below, the calibration values are stored in the arrays ...Offset[3]={0,0,0} and ...Slope[3]={1,1,1} -Should you want to use these values again in a sketch, it's up to you to print them and put them in program code. -The library is designed in such a way that the stored values don't depend on any of the settings in the program, like ...Unit, -...SR (sample rate), ...FS (full scale). So changing any of the settings before or after restoring their values in the -arrays has no effect on the status of being calibrated. - -********************************************* Offset ********************************************* - -In order to find the value of Offset we must do a zero point measurement. That means that the physical property ... -we are trying to measure should actually result in a value of 0. E.g. keeping the board still should result in zero -gyroscope values for x,y and z. For acceleration the two axes perpendicular to the Earth gravity should be zero. - -An offset calibration involves three steps -1 set the offset factors to 0, using the set...Offset method -2 do zero-point measurements with the read... method -3 store the measured ReadResults using the same set...Offset method to make the calibration effective. - -ad.1: in your sketch: IMO.set...Offset(0,0,0); -ad.2: The readResult should probably be the average value of a number of measurements -ad.3: in your sketch: IMO.set...Offset(resultX,resultY,resultZ); - -Alternatively if it is difficult to get a zero property, you could try to find the maximum and minimum values and -use the point in the middle - - readResult = ( Read_max + Read_min ) / 2 - -This is probably more complex than what it looks like. Both Read_min and Read_max can best be some sort of average, but -if you simply use the min() and max() procedures, the final results are just one measurement each. The chances are high -that these are the worst measurements. -Calculating separate averages of the min and max values, is like a chicken and egg. Before the calibration program can -decide to which average a measurement belongs, it needs a rough calibration first. -The best method is probably 3D elliptical regression, where the values of Offset correspond to the centre of the -elliptoid. So far I did not venture into the mathematics of this. :0 - -********************************************* Slope ********************************************* - -Slope is a dimensionless number that compensates for the sensitivity of the chip's internal transducer. In case it is not -possible to measure this, best leave it at the value 1. For Magnet and Accel this is probably allright, but for Gyro the -sensitivity matters if you want to keep track of orientation. - -A slope calibration involves three steps -1 set the offset factor to 1, using the set...Slope method -2 do slope measurements with the read... method -3 store the readResult using the same set...Slope method. - -ad.1: in your sketch: IMO.set...Slope(1,1,1); -ad.2: The read result should probably be two different averages of a number of measurements each -ad.3: in your sketch: IMO.set...Slope(resultX,resultY,resultZ) - -In order to calibrate the Slope parameter at least two measurements (say 1 and 2) must be done where the physical quantity, -(let's call it Q), has a known difference, so Q_1 - Q_2 = known value. - -The value of slope follows from - - Result = abs (( Q_1 - Q_2) / ( Read_1 - Read_2 )) - -E.g. the Earth gravity should produce a value of 1g. Holding the board upside down should measure -1g. So the difference - ( Q_1 - Q_2) = 2g -The local strength of the magnetic field (in nT) can be found at -https://en.wikipedia.org/wiki/Earth%27s_magnetic_field - - -*************************************** Offset and Slope Combined ********************************************* - -With the above methods Slope and Offset can be measured independently. It does not matter which procedure comes first, -as long as you don't change any of the settings between measuring and assigning. This could accidently happen in case -of a combined measurement by setting the value of Slope before that of Offset. -Note that the dimensionless stored Offset values differ from the Read measurements by a factor (Unit * Slope). - - -A safe following order of steps is -1 set the Slope factors to 1, set...Slope(1,1,1); -2 set the Offset factors to 0, set...Offset(0,0,0); -3 do the measurements with the read... method -4 First store the Offset results using set...Offset -5 Store the Slope results second using set...Slope - -Example -Lets assume that readAccel produces values of 1.3 and - 0.9 - - Offset = (1.3 + (-0.9)) / 2 = 0.2 - Slope = (1 - (-1)) / (1.3 - (-0.9) = 2 / 2.2 = 0.90909 - -Note that set...Offset stores the measured values as ReadResult/(Unit * Slope). -If you store Slope first, the Offset becomes 0.2/0.90909 = 0.22 - -***************************************************************************************************************************** -********************************** Overview of Code **************************************** -***************************************************************************************************************************** - -(almost) unchanged - int begin(); - void end(); - void setContinuousMode(); - void setOneShotMode(); - virtual int accelAvailable(); // Number of samples in the FIFO. - virtual int gyroAvailable(); // Number of samples in the FIFO. - virtual int magnetAvailable(); // Number of samples in the FIFO. - -existing functions changed for new functionality. Results reflect calibration, full scale and unit settings - virtual int readAccel(float& x, float& y, float& z); // Results are in G (earth gravity) or m/s2. - virtual int readGyro(float& x, float& y, float& z); // Results are in degrees/second or rad/s. - virtual int readMagnet(float& x, float& y, float& z); // Results are in uT (micro Tesla). - -existing functions that return a previously measured value - virtual float getAccelODR(); // Sampling rate of the sensor (Hz). - virtual float getGyroODR(); // Sampling rate of the sensor (Hz). - virtual float magnetODR(); // Sampling rate of the sensor (Hz). - -New the possibility to change the ODR registers (Output Data Rate) - virtual int setAccelODR(int8_t range); // 0:off, 1:10Hz, 2:50Hz, 3:119Hz, 4:238Hz, 5:476Hz, 6:952Hz - virtual int setGyroSR(int8_t range); // 0:off, 1:10Hz, 2:50Hz, 3:119Hz, 4:238Hz, 5:476Hz, 6:952Hz - virtual int setMagnetSR(int8_t range) // range (0..7) corresponds to {0.625,1.25,2.5,5,10,20,40,80,400}Hz - -Note: The 952Hz Accel and Gyro ODR does not seem to work. It's true value is close to setting 5. -Note: The Magnetic 400Hz setting corresponds to the chip's fast rate setting -Note: Changing any of the settings quickly measures the actual ODR value for the get...ODR to return. - -New constants used in ..Unit setting -#define GAUSS 0.01 -#define MICROTESLA 1.0 // default -#define NANOTESLA 1000.0 -#define GRAVITY 1.0 // default -#define METERPERSECOND2 9.81 -#define DEGREEPERSECOND 1.0 //default -#define RADIANSPERSECOND 3.141592654/180 -#define REVSPERMINUTE 60.0/360.0 -#define REVSPERSECOND 1.0/360.0 - -Unitsettings that read returns measurement results in. - float accelUnit = GRAVITY; // GRAVITY OR METERPERSECOND2 - float gyroUnit = DEGREEPERSECOND; // DEGREEPERSECOND, RADIANSPERSECOND, REVSPERMINUTE, REVSPERSECOND - float magnetUnit = MICROTESLA; // GAUSS MICROTESLA NANOTESLA - -methods for internal use - int getOperationalMode(); //0=off , 1= Accel only , 2= Gyro +Accel - float measureAccelGyroODR(unsigned int duration); - float measureMagnetODR(unsigned int duration); - -Calibration parameters Slope ans Offset : See Calibration. - float accelOffset[3] = {0,0,0}; // zero point offset correction factor for calibration - float gyroOffset[3] = {0,0,0}; // zero point offset correction factor for calibration - float magnetOffset[3] = {0,0,0};// zero point offset correction factor for calibration - float accelSlope[3] = {1,1,1}; // slope correction factor for calibration - float gyroSlope[3] = {1,1,1}; // slope correction factor for calibration - float magnetSlope[3] = {1,1,1}; // slope correction factor for calibration - -Methods for setting the calibration - virtual void setAccelOffset(float x, float y, float z); - virtual void setAccelSlope(float x, float y, float z); - virtual void setGyroOffset(float x, float y, float z); - virtual void setGyroSlope(float x, float y, float z); - virtual void setMagnetOffset(float x, float y, float z); - virtual void setMagnetSlope(float x, float y, float z); - - -New: changing the full scale sensitivity of the sensors. -The functions modify the FS (full scale) registers of the LSM9DS1 chip changing sensitivity at the expence of range. -Changing this setting does not change the x,y,z output of the read functions, but assigns just more or less bits -to the sensor measurement. - virtual int setAccelFS(uint8_t range); // 0: ±2g ; 1: ±24g ; 2: ±4g ; 3: ±8g - virtual int setGyroFS(int8_t range); // 0= ±245 dps; 1= ±500 dps; 2= ±1000 dps; 3= ±2000 dps - virtual int setMagnetFS(int8_t range); // 0=400.0; 1=800.0; 2=1200.0 , 3=1600.0 (µT) - -*note* According to the data sheet gyroscope setting 2 = 1000 dps should not be available. For some reason it worked - like a charm on my BLE Sense board, so I added the possibility. - -New functions return the Full Scale setting of the corresponding DOF as set with the corresponding set...FS functions - virtual float getAccelFS(); // Full Scale setting (output = 2.0, 24.0 , 4.0 , 8.0) - virtual float getGyroFS(); // output = 245.0, 500.0 , 1000.0, 2000.0) - virtual float getMagnetFS(); // output 400.0 ; 800.0 ; 1200.0 , 1600.0 - -Note: According to the datasheet setAccelFS(1) should correspoond to 16g. Measurement showed that it is actually 24g - but that the sensor maxes out at 20g. Since the actual value is used in a calculation the value of 24g is returned - by getAccelFS for that setting. - -The band with routines were added as an attempt to dampen a nasty spike that existed in the Gyro signal. It had no -observable effect. The methods are provided as is. - virtual float setAccelBW(uint8_t range); //0,1,2,3 Override autoBandwidth setting see doc.table 67 - virtual float getAccelBW(); //Bandwidth setting 0,1,2,3 see documentation table 67 - virtual int setGyroBW(uint8_t range); //Bandwidth setting 0,1,2,3 see documentation table 46 and 47 - virtual float getGyroBW(); //Bandwidth setting 0,1,2,3 see documentation table 46 and 47 - - - - -***************************************************************************************************************************** -********************************** Derivation of linear correction **************************************** -***************************************************************************************************************************** - -Sorry for the very formal derivation below. It suits verifiability but probably only my own purpose :) -It took a lot of puzzling to get it right. Don't read it if you don't want to. :( - -******************************************* Offset *************************************************** - -Assuming good linearity of the transducer, we can model the data output of the chip as - - Data = (32768 / IFS) *( A*Q + B) (1) - -Data = the measured value showing up on the chip registers -Q = the actual physical quantity we are trying to measure in any of the 9 DOF -IFS = the chip Internal Fullscale Setting. -A,B unknown constants representing chip instance differences - -Since the chip outputs dimensionless bits and bytes only, the dimensions of IFS and B must equal the dimension of Q. - -The challenge is to get rid of the unknown constants A and B and translate them into measurable quantities produced by the -library's Read methods. Since a good calibrated Read should produce a number equal to the actual physical quantity -we can state - - Read = Q - -Further, we do not want to recalibrate when we change the Full Scale setting or the Unit. - -Define -PFS = the in-program Full Scale function counteracting the IFS so that the output result remains unchanged. - (dimensionless, but its value corresponds to that of the chosen default unit) -Slope = in-program correction factor for the sensor sensitivity -Offset = in-program correction factor for the sensor zero point offset - -The output of the read methods is (see above) - - Read = Unit * Slope * (PFS / 32786 * Data - Offset ) (2) - -Substitute eq(1) - - Read = Unit * slope * (PFS / IFS * 32786/32786 * ( A*Q + B ) - Offset ) - - Read = Unit * slope * (PFS / IFS * ( A*Q + B ) - Offset ) (3) - -In case of the calibrated zero point measurement Q = Read = 0 -Substitute in eq.(3) we get - - 0 = Unit * slope * (PFS / IFS * ( A*0 + B ) - Offset ) - - Unit * slope * Offset = Unit * slope * PFS / IFS * B (4) - -For an uncalibrated measurement of a zero point (ZP) filling in Offset=0 and Q=0 in eq(3) we get - - Read_uncalibrated_ZP = Unit * slope * PFS / IFS * B (5) - -The righthand terms in equation (4) and (5) are identical so it follows that - - Offset = read_uncalibrated_ZP / (Unit * slope) (6) - -This defines how we should do the calibration measurements. In the library the methods called set...Offset -use of eq(6) to assign the uncalibrated zero-point read values to the corresponding program parameters. -Eq.(6) suggests that Offset depends on Unit and Slope, but this is not the case as the Read method scales -with the same value. To proof this we write eg(4) in a different form - - Offset = (Unit * Slope) / (Unit * Slope) * PFS/IFS * B (7) - -Further since the dimensionless PFS counteracts IFS in size -and the dimension of IFS equals that of Q, the ratio PFS/IFS is 1/Unit. -or in other words - - Unit * PFS /IFS = 1 (8) - -eq(7) reduces to - - Offset = B / Unit = B_dimensionless (9) - -So Offset equals the dimensionless form of B and does not depend on any other parameter. - - -******************************************** Slope *************************************************** - -In order to calibrate the Slope at least two measurements (say 1 and 2) must be done where the measured quantity Q -has a known difference. The calibrated Read equals Q so - - Q_1 - Q_2 = Read_1 - Read_2 = known value (10) - -Substitute eq(2) - - Q_1 - Q_2 = Unit*Slope*(PFS/32786*Data_1 - Offset) - Unit*Slope*(PFS/32786*Data_2 - Offset) - - = Unit*Slope*(PFS/32786*(Data_1 - Data_2) (11) - -So the difference between the measurements gets rid of the Offset -For an uncalibrated measurement we must set Slope = 1. -Eq(2) becomes - - Read_uncalibrated = Unit * (PFS / 32786 * Data - Offset ) - -In eq(11) we get - - Q_1 -Q_2 = Slope * ( Read_uncalibrated_1 - Read_uncalibrated_2) - - Slope = (( Read_uncalibrated_1 - Read_uncalibrated_2) / (Q_1 -Q_2) (12) - -So in order to measure the slope we must first set the Slope parameter to 1. - -In order to prove that Slope is independent of all the other program parameters we substitute eq(1) in eq(11) - - Q_1 - Q_2 = Unit*Slope*(PFS/32786)*(32786/IFS)*(A*Q1 +B - A*Q2 -B)) - - (Q_1 - Q_2) = Slope* Unit*(PFS/IFS)* A *(Q1 - Q2) (12) - -and with eq(8) - - ( 1 ) = Slope * 1 * A *( 1 ) - - Slope = 1 / A - -So Slope only depends on A, the (in)sensitivity of the sensor. The proportionality is inverse since Slope is the -compensation factor for the chip's insensitivity - -QED diff --git a/src/LSM9DS1.cpp b/src/LSM9DS1.cpp index de69b01..a59c2ef 100644 --- a/src/LSM9DS1.cpp +++ b/src/LSM9DS1.cpp @@ -119,74 +119,33 @@ void LSM9DS1Class::end() _wire->end(); } -float LSM9DS1Class::measureAccelGyroODR(unsigned int duration) -{ if (getOperationalMode()==0) return 0; - float x, y, z; //dummies - unsigned long lastEventTime, count = 0; - int fifoEna=continuousMode; //switch off FiFo - setOneShotMode(); - duration *=1000; //switch to micros - while (count<2) //throw away nr of samples, fifo enabled would be count<33; - { if (accelAvailable()) - { readAccel(x, y, z); // empty read buffer and wait till current measurement is finished, empty again - count++; - } - } - count=0; - unsigned long start = micros(); - while ((micros()- start) < duration) // measure - { if (accelAvailable()) - { readAccel(x, y, z); - count++; - lastEventTime = micros(); - } - } -// Serial.print(" Count "+String( count ) ); - if (fifoEna) setContinuousMode(); - return (1000000.0*float(count)/float(lastEventTime-start) ); -} -float LSM9DS1Class::measureMagnetODR(unsigned int duration) -{ float x, y, z; //dummies - unsigned long lastEventTime, count = 0; - duration *=1000; //switch to micros - while (count<2) //throw away nr of samples - { if (magnetAvailable()) - { readMagnet(x, y, z); // empty read buffer and wait till current measurement is finished, empty again - count++; - } - } - count=0; - unsigned long start = micros(); - while ((micros()- start) < duration) // measure - { if (magnetAvailable()) - { readMagnet(x, y, z); - count++; - lastEventTime = micros(); - } - } -// Serial.print(" Count "+String( count ) ); - return (1000000.0*float(count)/float(lastEventTime-start) ); -} //************************************ Acceleration ***************************************** -int LSM9DS1Class::readAccel(float& x, float& y, float& z) +int LSM9DS1Class::readAccel(float& x, float& y, float& z) // return calibrated data in a unit of choise +{ if (!readRawAccel(x,y,z)) return 0; + // See releasenotes read = Unit * Slope * (FS / 32786 * Data - Offset ) + x = accelUnit * accelSlope[0] * (x - accelOffset[0]); + y = accelUnit * accelSlope[1] * (y - accelOffset[1]); + z = accelUnit * accelSlope[2] * (z - accelOffset[2]); + return 1; +} + +int LSM9DS1Class::readRawAccel(float& x, float& y, float& z) // return raw uncalibrated data { int16_t data[3]; - if (!readRegisters(LSM9DS1_ADDRESS, LSM9DS1_OUT_X_XL, (uint8_t*)data, sizeof(data))) { - x = NAN; - y = NAN; - z = NAN; - return 0; + if (!readRegisters(LSM9DS1_ADDRESS, LSM9DS1_OUT_X_XL, (uint8_t*)data, sizeof(data))) + { x = NAN; y = NAN; z = NAN; return 0; } // See releasenotes read = Unit * Slope * (PFS / 32786 * Data - Offset ) float scale = getAccelFS()/32768.0 ; - x = accelUnit * accelSlope[0] * (scale * data[0] - accelOffset[0]); - y = accelUnit * accelSlope[1] * (scale * data[1] - accelOffset[1]); - z = accelUnit * accelSlope[2] * (scale * data[2] - accelOffset[2]); + x = scale * data[0]; + y = scale * data[1]; + z = scale * data[2]; return 1; } + int LSM9DS1Class::accelAvailable() { if (continuousMode) { @@ -202,11 +161,9 @@ int LSM9DS1Class::accelAvailable() return 0; } -//Store zero-point calibration measurement as offset, -//Dimension analysis: -//The measurement is stripped from it's unit and sensitivity it was measured with. -//This enables independent calibration and changing the unit later -//In a combined calibration this value must be set before setting the Slope +// modified: the void is no longer for translating half calibrated measurements into offsets +// in stead the voids rawAccel() rawGyro() and rawMagnet must be used for calibration purposes + void LSM9DS1Class::setAccelOffset(float x, float y, float z) { accelOffset[0] = x /(accelUnit * accelSlope[0]); accelOffset[1] = y /(accelUnit * accelSlope[1]); @@ -284,21 +241,26 @@ float LSM9DS1Class::getAccelFS() // Full scale dimensionless, but its value corr //************************************ Gyroscope ***************************************** -int LSM9DS1Class::readGyro(float& x, float& y, float& z) +int LSM9DS1Class::readGyro(float& x, float& y, float& z) // return calibrated data in a unit of choise +{ + if (!readRawGyro(x,y,z)) return 0; //get the register values + x = gyroUnit * gyroSlope[0] * (x - gyroOffset[0]); + y = gyroUnit * gyroSlope[1] * (y - gyroOffset[1]); + z = gyroUnit * gyroSlope[2] * (z - gyroOffset[2]); + return 1; +} + +int LSM9DS1Class::readRawGyro(float& x, float& y, float& z) // return raw data for calibration purposes { int16_t data[3]; if (!readRegisters(LSM9DS1_ADDRESS, LSM9DS1_OUT_X_G, (uint8_t*)data, sizeof(data))) - { x = NAN; - y = NAN; - z = NAN; - return 0; + { x = NAN; y = NAN; z = NAN; return 0; } float scale = getGyroFS() / 32768.0; - x = gyroUnit * gyroSlope[0] * (scale * data[0] - gyroOffset[0]); - y = gyroUnit * gyroSlope[1] * (scale * data[1] - gyroOffset[1]); - z = gyroUnit * gyroSlope[2] * (scale * data[2] - gyroOffset[2]); + x = scale * data[0]; + y = scale * data[1]; + z = scale * data[2]; return 1; } - int LSM9DS1Class::gyroAvailable() { if (readRegister(LSM9DS1_ADDRESS, LSM9DS1_STATUS_REG) & 0x02) { @@ -306,15 +268,13 @@ int LSM9DS1Class::gyroAvailable() } return 0; } -//Store zero-point calibration measurement as offset, -//Dimension analysis: -//The measurement is stripped from it's unit and sensitivity it was measured with. -//This enables independent calibration and changing the unit later -//In a combined calibration this value must be set before setting the Slope + +// modified: the void is no longer for translating half calibrated measurements into offsets +// Instead the voids rawAccel() rawGyro() and rawMagnet must be used for calibration purposes void LSM9DS1Class::setGyroOffset(float x, float y, float z) -{ gyroOffset[0] = x /(gyroUnit * gyroSlope[0]); - gyroOffset[1] = y /(gyroUnit * gyroSlope[1]); - gyroOffset[2] = z /(gyroUnit * gyroSlope[2]); +{ gyroOffset[0] = x; + gyroOffset[1] = y; + gyroOffset[2] = z; } //Slope is already dimensionless, so it can be stored as is. void LSM9DS1Class::setGyroSlope(float x, float y, float z) @@ -408,22 +368,28 @@ float LSM9DS1Class::getGyroFS() // dimensionless, but its value defaults to de //************************************ Magnetic field ***************************************** -int LSM9DS1Class::readMagneticField(float& x, float& y, float& z) -{ int16_t data[3]; +int LSM9DS1Class::readMagneticField(float& x, float& y, float& z) // return calibrated data in a unit of choise +{ if (!readRawMagnet(x,y,z)) return 0; + x = magnetUnit * magnetSlope[0] * (x - magnetOffset[0]); + y = magnetUnit * magnetSlope[1] * (y - magnetOffset[1]); + z = magnetUnit * magnetSlope[2] * (z - magnetOffset[2]); + return 1; +} - if (!readRegisters(LSM9DS1_ADDRESS_M, LSM9DS1_OUT_X_L_M, (uint8_t*)data, sizeof(data))) { - x = NAN; - y = NAN; - z = NAN; - return 0; +// return raw data for calibration purposes +int LSM9DS1Class::readRawMagnet(float& x, float& y, float& z) +{ int16_t data[3]; + if (!readRegisters(LSM9DS1_ADDRESS_M, LSM9DS1_OUT_X_L_M, (uint8_t*)data, sizeof(data))) + { x = NAN; y = NAN; z = NAN; return 0; } float scale = getMagnetFS() / 32768.0; - x = magnetUnit * magnetSlope[0] * (scale * data[0] - magnetOffset[0]); - y = magnetUnit * magnetSlope[1] * (scale * data[1] - magnetOffset[1]); - z = magnetUnit * magnetSlope[2] * (scale * data[2] - magnetOffset[2]); + x = scale * data[0] ; + y = scale * data[1] ; + z = scale * data[2] ; return 1; } + int LSM9DS1Class::magneticFieldAvailable() { //return (readRegister(LSM9DS1_ADDRESS_M, LSM9DS1_STATUS_REG_M) & 0x08)==0x08; if (readRegister(LSM9DS1_ADDRESS_M, LSM9DS1_STATUS_REG_M) & 0x08) { @@ -431,15 +397,14 @@ int LSM9DS1Class::magneticFieldAvailable() } return 0; } -//Store zero-point calibration measurement as offset, -//Dimension analysis: -//The measurement is stripped from it's unit and sensitivity it was measured with. -//This enables independent calibration and changing the unit later -//In a combined calibration this value must be set before setting the Slope + +// modified: the void is no longer for translating half calibrated measurements into offsets +// Instead the voids rawAccel() rawGyro() and rawMagnet must be used for calibration purposes + void LSM9DS1Class::setMagnetOffset(float x, float y, float z) -{ magnetOffset[0] = x /(magnetUnit * magnetSlope[0]); - magnetOffset[1] = y /(magnetUnit * magnetSlope[1]); - magnetOffset[2] = z /(magnetUnit * magnetSlope[2]); +{ magnetOffset[0] = x ; + magnetOffset[1] = y ; + magnetOffset[2] = z ; } //Slope is already dimensionless, so it can be stored as is. void LSM9DS1Class::setMagnetSlope(float x, float y, float z) @@ -481,6 +446,55 @@ float LSM9DS1Class::getMagnetODR() // Output {0.625, 1.25, 2.5, 5.0, 10.0, 20.0 //************************************ Private functions ***************************************** +float LSM9DS1Class::measureAccelGyroODR(unsigned int duration) +{ if (getOperationalMode()==0) return 0; + float x, y, z; //dummies + unsigned long lastEventTime, count = 0; + int fifoEna=continuousMode; //switch off FiFo + setOneShotMode(); + duration *=1000; //switch to micros + while (count<2) //throw away nr of samples, fifo enabled would be count<33; + { if (accelAvailable()) + { readAccel(x, y, z); // empty read buffer and wait till current measurement is finished, empty again + count++; + } + } + count=0; + unsigned long start = micros(); + while ((micros()- start) < duration) // measure + { if (accelAvailable()) + { readAccel(x, y, z); + count++; + lastEventTime = micros(); + } + } +// Serial.print(" Count "+String( count ) ); + if (fifoEna) setContinuousMode(); + return (1000000.0*float(count)/float(lastEventTime-start) ); +} + +float LSM9DS1Class::measureMagnetODR(unsigned int duration) +{ float x, y, z; //dummies + unsigned long lastEventTime, count = 0; + duration *=1000; //switch to micros + while (count<2) //throw away nr of samples + { if (magnetAvailable()) + { readMagnet(x, y, z); // empty read buffer and wait till current measurement is finished, empty again + count++; + } + } + count=0; + unsigned long start = micros(); + while ((micros()- start) < duration) // measure + { if (magnetAvailable()) + { readMagnet(x, y, z); + count++; + lastEventTime = micros(); + } + } +// Serial.print(" Count "+String( count ) ); + return (1000000.0*float(count)/float(lastEventTime-start) ); +} int LSM9DS1Class::readRegister(uint8_t slaveAddress, uint8_t address) { diff --git a/src/LSM9DS1.h b/src/LSM9DS1.h index 8e4db2c..6e297ab 100644 --- a/src/LSM9DS1.h +++ b/src/LSM9DS1.h @@ -78,13 +78,12 @@ class LSM9DS1Class { void setContinuousMode(); void setOneShotMode(); int getOperationalMode(); //0=off , 1= Accel only , 2= Gyro +Accel - float measureAccelGyroODR(unsigned int duration); - float measureMagnetODR(unsigned int duration); // Accelerometer float accelOffset[3] = {0,0,0}; // zero point offset correction factor for calibration float accelSlope[3] = {1,1,1}; // slope correction factor for calibration float accelUnit = GRAVITY; // GRAVITY OR METERPERSECOND2 - virtual int readAccel(float& x, float& y, float& z); // Results are in G (earth gravity) or m/s2. + virtual int readAccel(float& x, float& y, float& z); // Return calibrated data in unit of choise G or m/s2. + virtual int readRawAccel(float& x, float& y, float& z); // Return uncalibrated results virtual int accelAvailable(); // Number of samples in the FIFO. virtual void setAccelOffset(float x, float y, float z); //Store zero-point measurements as offset virtual void setAccelSlope(float x, float y, float z); //Store measurements as slope @@ -99,7 +98,8 @@ class LSM9DS1Class { float gyroOffset[3] = {0,0,0}; // zero point offset correction factor for calibration float gyroSlope[3] = {1,1,1}; // slope correction factor for calibration float gyroUnit = DEGREEPERSECOND; // DEGREEPERSECOND RADIANSPERSECOND REVSPERMINUTE REVSPERSECOND - virtual int readGyro(float& x, float& y, float& z); // Results are in degrees/second or rad/s. + virtual int readGyro(float& x, float& y, float& z); // Return calibrated data in in unit of choise °/s or rad/s. + virtual int readRawGyro(float& x, float& y, float& z); // Return uncalibrated results virtual int gyroAvailable(); // Number of samples in the FIFO. virtual void setGyroOffset(float x, float y, float z); //Store zero-point measurements as offset virtual void setGyroSlope(float x, float y, float z); //Store measurements as slope @@ -113,8 +113,9 @@ class LSM9DS1Class { // Magnetometer float magnetOffset[3] = {0,0,0}; // zero point offset correction factor for calibration float magnetSlope[3] = {1,1,1}; // slope correction factor for calibration - float magnetUnit = MICROTESLA; // GAUSS or MICROTESLA - virtual int readMagnet(float& x, float& y, float& z); // Default results are in µT (micro Tesla) + float magnetUnit = MICROTESLA; // GAUSS, MICROTESLA NANOTESLA + virtual int readMagnet(float& x, float& y, float& z); // Return calibrated data in unit of choise µT , nT or G + virtual int readRawMagnet(float& x, float& y, float& z); // Return uncalibrated results virtual int magnetAvailable(); // Number of samples in the FIFO. virtual void setMagnetOffset(float x, float y, float z); //Store zero-point measurements as offset virtual void setMagnetSlope(float x, float y, float z); //Store measurements as slope @@ -128,6 +129,8 @@ class LSM9DS1Class { float gyroODR; // Stores the actual value of Output Data Rate float magnetODR; // Stores the actual value of Output Data Rate bool continuousMode; + float measureAccelGyroODR(unsigned int duration); + float measureMagnetODR(unsigned int duration); int readRegister(uint8_t slaveAddress, uint8_t address); int readRegisters(uint8_t slaveAddress, uint8_t address, uint8_t* data, size_t length); int writeRegister(uint8_t slaveAddress, uint8_t address, uint8_t value); From a1ff07255103fb1cfcec0ca552b9099b65ae400a Mon Sep 17 00:00:00 2001 From: FemmeVerbeek <65541097+FemmeVerbeek@users.noreply.github.com> Date: Mon, 15 Jun 2020 18:16:35 +0200 Subject: [PATCH 12/15] Update readme.md --- readme.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/readme.md b/readme.md index 762e91d..0b7e2d0 100644 --- a/readme.md +++ b/readme.md @@ -203,7 +203,7 @@ An interactive DIY_Calibration program is provided with this library. See [instr It explains how to measure each of the factors, collects data and presents the result on screen as copy/paste-able code. No special setup is required, but it helps to fix the board in a non-magnetic rectangular box. -![](/images/Boxed sensor.PNG) +![](./images/Boxed sensor.PNG) The calibration factors may be different per instance of the LSM9DS1 chip. They will hardly vary in time, so it is sufficient to calibrate them only once. The magnetic field is easily disturbed by even the smallest From 2f36e9c964a14b4475b65c5fc3c4a927584f2da4 Mon Sep 17 00:00:00 2001 From: FemmeVerbeek Date: Fri, 10 Jul 2020 22:21:40 +0200 Subject: [PATCH 13/15] Runnable on Arduino Uno The DIY calibration was split into three separate programs. The FS and the ODR settings were added in the menus and in the copy/pasteable output. This increases the accuracy especially for the gyroscope. All the Serial.print("text") 's were encapsulated with the F(..) macro. The IMU.end() now restores the I2C pullups which brings the power usage back to almost nothing. A small bug in the Full Scale setting of the magnetometer was fixed. --- CHANGELOG | 10 +- examples/DIY_Calibration/DIY_Calibration.ino | 444 ------------------ .../DIY_Calibration_Accelerometer.ino | 185 ++++++++ .../DIY_Calibration_Gyroscope.ino | 264 +++++++++++ .../DIY_Calibration_Magnetometer.ino | 187 ++++++++ .../RPM_Meter_Rev_Counter.ino | 8 +- examples/RegisterTest/RegisterTest.ino | 302 +++++++----- .../SimpleAccelerometer.ino | 46 +- examples/SimpleGyroscope/SimpleGyroscope.ino | 56 ++- .../SimpleMagnetometer/SimpleMagnetometer.ino | 38 +- examples/Water_Leveler/Water_Leveler.ino | 11 +- examples/XY_compass/XY_compass.ino | 27 +- readme.md | 106 +++-- src/LSM9DS1.cpp | 126 +++-- src/LSM9DS1.h | 10 +- 15 files changed, 1116 insertions(+), 704 deletions(-) delete mode 100644 examples/DIY_Calibration/DIY_Calibration.ino create mode 100644 examples/DIY_Calibration_Accelerometer/DIY_Calibration_Accelerometer.ino create mode 100644 examples/DIY_Calibration_Gyroscope/DIY_Calibration_Gyroscope.ino create mode 100644 examples/DIY_Calibration_Magnetometer/DIY_Calibration_Magnetometer.ino diff --git a/CHANGELOG b/CHANGELOG index 8f712c3..f9e3da6 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -8,7 +8,7 @@ Arduino_LSM9DS1 1.1.0 - 2020.02.11 * Added support for FIFO continuous reading of values -Arduino_LSM9DS1 2.0.0 - 2020.06.15 +Arduino_LSM9DS1 2.0.0 - 2020.07.10 * Added support for Full scale setting, * Added support for Operational mode: off, Accel only, Gyro + Accel @@ -18,6 +18,8 @@ Arduino_LSM9DS1 2.0.0 - 2020.06.15 * Added support for separate or combined sensor calibration * Calibration parameters are dimensionless, independent of each other and of the other settings * Includes a DIY calibration program that produces copy/paste-able code -* Inclues readme.md and Getting Started.md -* Inclues examples RPM_meter_Rev_Counter, Water_Leveler, XY_Compass -* Inclues Register_test: demonstrates and verifies all new settings \ No newline at end of file +* Includes readme.md and Getting Started.md +* Includes examples RPM_meter_Rev_Counter, Water_Leveler, XY_Compass +* Includes Register_test: demonstrates and verifies all new settings +* The include programs use a minimul amout of RAM to enable running on something as small as a Arduino Uno. +* The IMU.end() function restores the system to low power usage diff --git a/examples/DIY_Calibration/DIY_Calibration.ino b/examples/DIY_Calibration/DIY_Calibration.ino deleted file mode 100644 index 67591fc..0000000 --- a/examples/DIY_Calibration/DIY_Calibration.ino +++ /dev/null @@ -1,444 +0,0 @@ -/* DIY calibration program for the LSM9DS1 chip - * - * Follow the instructions on the screen how to do calibration measurements. - * See instruction video https://youtu.be/BLvYFXoP33o - * No special tools or setups are needed, however it is handy if the board with the LSM9DS1 chip is fitted inside - * a non-metalic rectangular box. - * The offset and slope factors are displayed on screen as code that can be copy/pasted directly into a sketch. - * Each new instance of the chip will require it's own unique set of calibration factors. - * - * written by Femme Verbeek 30-5-2020 - * - * This program uses V2 of the LSM9DS1 library - * Tested on an Arduino Nano 33 BLE Sense board. - */ - -#include - -// not really my habit to use so many global variabeles but WTH this is still a small program -const float gyroSlopeCriterion = 50; -const float accelCriterion = 0.1; -float EarthMagnetStrength = 49.0; //= µT -float EarthMagnetInclination = 67.0; //= degree -char xyz[3]= {'X','Y','Z'}; -float maxAX = 1, maxAY=1, maxAZ=1, minAX=-1, minAY=-1, minAZ=-1; // Accel Slope -float zeroAX1 =0,zeroAX2 =0,zeroAY1 =0,zeroAY2 =0,zeroAZ1 =0,zeroAZ2 =0; //Accel Offset -//boolean accelOffsetOK[4]={false,false,false,false}; -boolean accelOK=false; -uint8_t acceMMlOK=0; // bit 0..2 maxXYZ bit 3..5 minXYZ -boolean gyroOK=false; -boolean gyroOffsetOK=false; -boolean gyroSlopeOK[3]={false,false,false}; -boolean magnetOK=false; - -void setup() { - Serial.begin(115200); - while (!Serial); - pinMode(LED_BUILTIN,OUTPUT); - delay(10); - if (!IMU.begin()) { Serial.println("Failed to initialize IMU!");while (1); } - IMU.setGyroODR(4); //238Hz - IMU.setMagnetODR(7); //80Hz -} - -void loop() -{ MainMenu(); -} - - -void MainMenu() -{ Serial.println("\n\n\n\n\n"); - Serial.println(" DIY Calibration program "); - Serial.println("The board with the LSM9DS1 sensor is best fitted into a non metallic rectangular box with flat sides"); - Serial.println("or find another way to keep the board horizontal or vertical on each of it's sides and rotate it ."); - Serial.println("In the following procedures you'll be asked to rotate the sensor around one of it's axes at the time"); - Serial.println("or simply aim the axis upward and keep still. The simplest way is to put the box with one of its flat"); - Serial.println("sides on the table and turn it by hand. See instruction video https://youtu.be/BLvYFXoP33o"); - Serial.println("To operate the menu in the IDE serial monitor you must press a letter key followed by Enter \n"); - - Serial.print(" Calibrate "); - Serial.print ("\n (A) Accelerometer "); - if (accelOK) Serial.print("-OK-"); - // Serial.print ("\n (O) Gyroscope Offset "); - // if (gyroOffsetOK) Serial.print("-OK-"); - Serial.print ("\n (G) Gyroscope "); - if (gyroOK ) Serial.print("-OK-"); - Serial.print ("\n (M) Magnetometer "); - if (magnetOK) Serial.print("-OK-"); - Serial.println("\n\n The code below can be copy/pasted in a sketch"); - - if (accelOK) printParam (" IMU.accelOffset ",IMU.accelOffset); - Serial.println(); - if (accelOK) printParam (" IMU.accelSlope ", IMU.accelSlope); - Serial.println(); - - if (gyroOffsetOK) printParam (" IMU.gyroOffset ", IMU.gyroOffset); - Serial.println(); - if (gyroSlopeOK[0] &&gyroSlopeOK[1] &&gyroSlopeOK[2] ) printParam (" IMU.gyroSlope ", IMU.gyroSlope); - Serial.println(); - if (magnetOK) - { printParam (" IMU.magnetOffset",IMU.magnetOffset); - Serial.println(); - printParam (" IMU.magnetSlope ",IMU.magnetSlope); - } - Serial.println(""); - while (!Serial.available()) ; - char incomingByte = toupper (Serial.read()); // read the incoming byte - if (byte(incomingByte)!=13) Serial.readStringUntil(13); // empty readbuffer - switch (incomingByte) - { case 'A': {calibrateAccelMenu(); break;} -// case 'G': {calibrateGyroOffset(); break;} - case 'G': {calibrateGyroMenu(); break;} - case 'M': {calibrateMagnetMenu(); break;} - default : {Serial.println("I received: "+String(incomingByte)); break;} - } -} - -void printParam(String txt, float param[3]) -{ for (int i= 0; i<=2 ; i++) - { Serial.print(txt+"["); - Serial.print(String(i)+"] = "); - Serial.print(String(param[i],6)+";"); - } -} - -//********************************************************************************************************************************** -//********************************************* Accelerometer ********************************************** -//********************************************************************************************************************************** - -void calibrateAccelMenu() -{char incomingByte = 0; - while (incomingByte!='X') - { Serial.println("\n\n"); - Serial.println("Calibrate Accelerometer Offset and Slope"); - Serial.println("Place the board on a horizontal surface with one of its axes vertical. Each of the axes must be measured "); - Serial.println("pointing up and pointing down, so a total of 6 measurements. "); - Serial.println("The program recognises which axis is vertical. If the angle is to far oblique the measurement is not valid.\n"); - - Serial.println("Press (C) to start a calibration measurement. "); - Serial.println("Press (X) to exit \n"); - - Serial.println("Measured status"); - for (int i=0;i<=2;i++){ Serial.print(xyz[i]); if (bitRead(acceMMlOK,i)==1)Serial.print("+ = ( -OK- ) "); else Serial.print("+ = not done "); } - Serial.println(); - for (int i=0;i<=2;i++){ Serial.print(xyz[i]); if (bitRead(acceMMlOK,i+3)==1)Serial.print("- = ( -OK- ) "); else Serial.print("- = not done "); } -// Serial.print ("\nMax values X="+String(maxAX,4)); Serial.print ("\tY="+String(maxAY,4));Serial.println ("\tZ="+String(maxAZ,4)); -// Serial.print ("Min values X="+String(minAX,4)); Serial.print ("\tY="+String(minAY,4));Serial.println ("\tZ="+String(minAZ,4)); - - Serial.println("\n\nCurrent accelerometer calibration values (copy/paste-able)\n"); - printParam(" IMU.accelOffset",IMU.accelOffset); - Serial.println(); - printParam (" IMU.accelSlope ",IMU.accelSlope); - Serial.println("\n\n\n\n"); - while (!Serial.available()) ; // wait for character to be entered - incomingByte = toupper(Serial.read()); - if (byte(incomingByte)!=13) Serial.readStringUntil(13); // empty readbuffer - if ((incomingByte)=='C') calibrateAccelSlope(); - } -} - -void calibrateAccelSlope() -{ boolean validMmt=false; - float x,y,z; - Serial.println("\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n"); - Serial.println("measuring \n"); - IMU.setAccelSlope(1,1,1); - IMU.setAccelODR(5); //476 Hz - raw_N_Accel(2500,x,y,z); - if (abs(x)>max(abs(y),abs(z))) - { Serial.println("X detected"); - if (sqrt(y*y+z*z)/x0) {maxAX=x; - acceMMlOK=acceMMlOK | 0b00000001 ;} - else {minAX=x; - acceMMlOK=acceMMlOK | 0b00001000 ; } - } - } - if (abs(y)>max(abs(x),abs(z))) - { Serial.println("Y detected"); - if (sqrt(x*x+z*z)/y0) {maxAY=y; - acceMMlOK=acceMMlOK | 0b00000010 ; } - else {minAY=y; - acceMMlOK=acceMMlOK | 0b00010000 ; } - } - } - if (abs(z)>max(abs(x),abs(y))) - { Serial.println("Z detected"); - if ( sqrt(x*x+y*y)/z0) {maxAZ=z; - acceMMlOK=acceMMlOK | 0b00000100 ; } - else {minAZ=z; - acceMMlOK=acceMMlOK | 0b00100000 ; } - } - } - IMU.setAccelOffset((maxAX+minAX)/2,(maxAY+minAY)/2,(maxAZ+minAZ)/2); - IMU.setAccelSlope ((maxAX-minAX)/2,(maxAY-minAY)/2,(maxAZ-minAZ)/2); - if (acceMMlOK==0b00111111) accelOK = true; - - if ( !validMmt ) - { Serial.print("\n\n\nNot a valid measurement! "); - Serial.println(" x="+String(x));Serial.print(" y="+String(y));Serial.println(" z="+String(z)); - } -} - - -//********************************************************************************************************************************** -//********************************************* Gyroscope ********************************************** -//********************************************************************************************************************************** - - -void calibrateGyroMenu() -{char incomingByte = 0; -//boolean OffsetCalibrated=false; -float turnangle = 360; - Serial.println("\n\n\n\n\n\n\n\n\n\n\n"); - if (!gyroOffsetOK) - { Serial.println(" Start by calibrating the Offset\n"); // Slope can't be calibrated with an uncalibrated offset - calibrateGyroOffset(); - } - while (incomingByte!='X') - { Serial.println(" Calibrate Gyroscope\n"); - Serial.println("The gyroscope sensor must be calibrated for it's sensitivity (slope). During a slope calibration the "); - Serial.println("board must be rotated calmly about one axis over a known angle. Change the angle to your convenience. "); - Serial.println("A larger angle is more accurate, but more difficult to do. The rotation must be pure, without much"); - Serial.println("rotation about the other two axes. It can be done by hand. Keeping the board on a flat surface with"); - Serial.println("the rotation axis vertical while turning is good enough. For an accurate result you can start and end "); - Serial.println("with its side pushed against a non moving object. Press Enter when finished."); - Serial.println("Each of the axes X,Y and Z must be measured. The program automatically detects which. \n"); - Serial.println(" (A) Change the measuring angle to turn the board"); - Serial.print (" (C) Calibrate Slope, turn the board over "+String(turnangle,0));Serial.println("° and press enter when finished "); - Serial.println(" (O) Calibrate Offset again"); - Serial.println(" (X) eXit to the main menu\n"); - - Serial.println("Offset calibration ( -OK- )"); - Serial.print ("Slope calibration " ); - for (int i= 0; i<=2 ; i++) - { Serial.print(xyz[i]); - if (gyroSlopeOK[i]) Serial.print("= ( -OK- ) "); else Serial.print("= not done "); - } - Serial.println(); - Serial.println("\n Gyroscope calibration parameters"); - printParam(" IMU.gyroOffset ",IMU.gyroOffset); - Serial.println(); - printParam(" IMU.gyroSlope ",IMU.gyroSlope); - Serial.println(); - while (!Serial.available()); // wait for anything to be entered - incomingByte = toupper(Serial.read()); // read char and convert to upcase - if (byte(incomingByte)!=13) Serial.readStringUntil(13); // empty readbuffer - switch (incomingByte) - { case 'A': { readAnswer("\n\nHow many degrees turn for the measurement? ", turnangle); - break;} - case 'C': { Serial.print("\n\n\n\n\n\nMeasuring. Turn the sensor over "+String(turnangle));Serial.println(" degrees\n"); - Serial.println("Press Enter when finished."); - calibrateGyroslope(turnangle); - break;} - case 'O': { calibrateGyroOffset(); } - default : {Serial.println("I received: "+String(incomingByte)); break;} - } - Serial.println(""); - } - Serial.println("\n\n\n\n\n\n\n"); -} - -void calibrateGyroOffset() // don't move the board during calibration -{ float x, y, z;// , addX=0, addY=0, addZ=0 ; - Serial.println("\n\n\n\nMeasuring offset. Just a moment."); - Serial.println("\n\n\n\nKeep the board still during measurement"); - IMU.setGyroODR(5); //476 Hz - raw_N_Gyro(2500,x,y,z); - IMU.setGyroOffset(x, y,z); // Store the average measurements as offset - digitalWrite(LED_BUILTIN, 0); // onboard led off - Serial.print("\n\n\n\n\n\n"); - gyroOffsetOK=true; -} - -void calibrateGyroslope(unsigned int turnangle) // rotate board over known angle -{ // float tempSlope[3]; - boolean validMmt=false; - float dirX=0, dirY=0, dirZ=0,sigmaX2=0,sigmaY2=0,sigmaZ2=0; - float x, y, z; - unsigned int count=0; -// for (int i =0;i<=2;i++) tempSlope[i]= IMU.gyroSlope[i]; -// IMU.setGyroSlope(1,1,1); - while (!Serial.available()) // measure until enter key pressed - { while (!IMU.gyroAvailable()); - IMU.readRawGyro(x, y, z); - dirX += (x - IMU.gyroOffset[0])/IMU.getGyroODR(); // slope is still raw but offset must already be calibrated - dirY += (y - IMU.gyroOffset[1])/IMU.getGyroODR(); - dirZ += (z - IMU.gyroOffset[2])/IMU.getGyroODR(); - sigmaX2 +=x*x; sigmaY2+=y*y; sigmaZ2+=z*z; - count++; - if ((count%30)==0)Serial.print('.'); - digitalWrite(LED_BUILTIN, (millis()/125)%2); // blink onboard led every 250ms - } - digitalWrite(LED_BUILTIN,0); // led off - Serial.readStringUntil(13); //Empty read buffer - Serial.print("\n\n\nMeasured direction change X "); - Serial.print(String(dirX,6)+"°\tY "); Serial.print(String(dirY,6)+"°\t Z "); Serial.println(String(dirZ,6)+"°"); - sigmaX2 /= count; sigmaY2 /= count; sigmaZ2 /= count; - Serial.print("Std.dev. "); - Serial.print(String(sigmaX2,6)+'\t'); Serial.print(String(sigmaY2,6)+'\t'); Serial.println(sigmaZ2,6); - dirX=abs(dirX); dirY=abs(dirY); dirZ=abs(dirZ); - if (dirX>max(dirY,dirZ)) - { - if (sigmaY2max(dirX,dirZ)) - { if (sigmaX2max(dirY,dirX)) - { if (sigmaY2 ")); + b= readChar()-48; Serial.println(b); + if (b!=accelFSindex && b >=0 && b<=3) accelFSindex=b; + IMU.setAccelFS(accelFSindex); + Serial.print("\n\n\n\n\n\n\n\n\n"); + break;} + case 'R': { Serial.print (F("\n\nEnter new ODR nr 1:10,2:50 3:119,4:238,5:476 Hz > ")); + b= readChar()-48; //Serial.println(b); + if (b!=accelODRindex && b>=1 && b<=5) accelODRindex=b; + IMU.setAccelODR(accelODRindex); + Serial.print("\n\n\n\n\n\n\n\n\n"); + break; + } + case 'C': {}; + default : calibrateAccelSlope(); + } + } +} + +void calibrateAccelSlope() +{ boolean validMmt=false; + float x,y,z; + Serial.println(F("\n\n\n\n\n\n\n\n\n\n\n")); + Serial.println(F("measuring \n")); + IMU.setAccelSlope(1,1,1); + IMU.setAccelODR(5); //476 Hz + raw_N_Accel(1000,x,y,z); + if (abs(x)>max(abs(y),abs(z))) + { Serial.println(F("X detected")); + if (sqrt(y*y+z*z)/x0) {maxAX=x; + acceMMlOK=acceMMlOK | 0b00000001 ;} + else {minAX=x; + acceMMlOK=acceMMlOK | 0b00001000 ; } + } + } + if (abs(y)>max(abs(x),abs(z))) + { Serial.println(F("Y detected")); + if (sqrt(x*x+z*z)/y0) {maxAY=y; + acceMMlOK=acceMMlOK | 0b00000010 ; } + else {minAY=y; + acceMMlOK=acceMMlOK | 0b00010000 ; } + } + } + if (abs(z)>max(abs(x),abs(y))) + { Serial.println(F("Z detected")); + if ( sqrt(x*x+y*y)/z0) {maxAZ=z; + acceMMlOK=acceMMlOK | 0b00000100 ; } + else {minAZ=z; + acceMMlOK=acceMMlOK | 0b00100000 ; } + } + } + IMU.setAccelOffset((maxAX+minAX)/2,(maxAY+minAY)/2,(maxAZ+minAZ)/2); + IMU.setAccelSlope ((maxAX-minAX)/2,(maxAY-minAY)/2,(maxAZ-minAZ)/2); + if (acceMMlOK==0b00111111) accelOK = true; + + if ( !validMmt ) + { Serial.print(F("\n\n\nNot a valid measurement! ")); + Serial.println(" x=");Serial.print(x);Serial.print(" y=");Serial.print(y);Serial.println(" z=");Serial.print(z); + } +} + +char readChar() +{ char ch; + while (!Serial.available()) ; // wait for character to be entered + ch= toupper(Serial.read()); + delay(10); + while (Serial.available()){Serial.read();delay(1);} // empty readbuffer + return ch; +} + +void raw_N_Accel(unsigned int N, float& averX, float& averY, float& averZ) +{ float x, y, z; + averX=0; averY =0;averZ =0; + for (int i=1;i<=N;i++) + { while (!IMU.accelAvailable()); + IMU.readRawAccel(x, y, z); + averX += x; averY += y; averZ += z; + digitalWrite(LED_BUILTIN, (millis()/125)%2); // blink onboard led every 250ms + if ((i%30)==0)Serial.print('.'); + } + averX /= N; averY /= N; averZ /= N; + digitalWrite(LED_BUILTIN,0); // led off +} diff --git a/examples/DIY_Calibration_Gyroscope/DIY_Calibration_Gyroscope.ino b/examples/DIY_Calibration_Gyroscope/DIY_Calibration_Gyroscope.ino new file mode 100644 index 0000000..011a303 --- /dev/null +++ b/examples/DIY_Calibration_Gyroscope/DIY_Calibration_Gyroscope.ino @@ -0,0 +1,264 @@ +/* DIY calibration program for the LSM9DS1 chip + * + * Follow the instructions on the screen how to do calibration measurements. + * Menu operation: type a letter in the input box of the serial monitor followed by enter. + * See instruction video https://youtu.be/BLvYFXoP33o + * No special tools or setups are needed, however it is handy if the board with the LSM9DS1 chip is fitted inside + * a non-metalic rectangular box. + * + * Each new instance of the LSM9DS1 chip will require it's own unique set of calibration factors. + * For an improved accuracy it is recommended that the sketch and the calibration program use the same settings for + * Full Scale (FS) and Output Data rate (ODR). This is the reasin why the possibility was added in this program. + * The settings and calibration factors are displayed on screen as code that can be copy/pasted + * directly into a sketch. + * + * Gyroscope Calibration + * The program starts with a short menu that offers the possibility to change the FS and ODR value. + * Next the Offset must be measured. This takes only a few seconds, during which the board must be kept still. + * This also enables the next step, which is to calibrate the slope. During a slope calibration the sensor must be rotated + * calmly about one axis over a known angle. This angle can be changed to your convenience. A larger angle is more accurate, + * but more difficult to do. The rotation can be done by hand. It must must be pure, without much rotation about the other + * two axes. e.g. by keeping the board on a flat surface with the rotation axis vertical while turning is good enough. + * Press Enter to finish the measurement. + * Each of the axes X,Y and Z must be measured, so in total three measurements. The program automatically detects which + * and shows this on screen. The rotation direction clockwise or anti-clockwise is unimportant, both directions will work. + * It is important that the offset is measured before the slope calibration. If for some reason the offset has to be remeasured + * make sure you remeasure the slope as well + * + * + * written by Femme Verbeek 6 July 2020 + * + * This program uses V2 of the LSM9DS1 library + * Tested on an Arduino Nano 33 BLE Sense board. + */ + +#include + +const float gyroSlopeCriterion = 50; //Smaller value requires more pureness of the rotation +char xyz[3]= {'X','Y','Z'}; +boolean gyroOffsetOK=false; +boolean gyroSlopeOK[3]={false,false,false}; +uint8_t gyroODRindex=4; +uint8_t gyroFSindex=3; // (0= ±245 dps; 1= ±500 dps; 2= ±1000 dps; 3= ±2000 dps) + +void setup() { + Serial.begin(115200); + while (!Serial); + pinMode(LED_BUILTIN,OUTPUT); + delay(10); + if (!IMU.begin()) { Serial.println(F("Failed to initialize IMU!"));while (1); } + IMU.setGyroODR(gyroODRindex); //238Hz + IMU.setGyroFS(gyroFSindex); + calibrateGyroMenu(); +} + +void loop() { } + +/*void printParam(char txt[], float param[3]) +{ for (int i= 0; i<=2 ; i++) + { Serial.print(txt);Serial.print("["); + Serial.print(i);Serial.print("] = "); + Serial.print(param[i],6);Serial.print(";"); + } +}*/ + +void printSetParam(char txt[], float param[3]) +{ Serial.print(txt);Serial.print("("); + Serial.print(param[0],6);Serial.print(", "); + Serial.print(param[1],6);Serial.print(", "); + Serial.print(param[2],6);Serial.print(");"); +} + +//********************************************************************************************************************************** +//********************************************* Gyroscope ********************************************** +//********************************************************************************************************************************** + + +void calibrateGyroMenu() +{ char incomingByte = 0; + byte b; + float turnangle = 180; + while (1)// (incomingByte!='X') + { + if (!gyroOffsetOK) + { Serial.println(F("\n\nStep 1 CALIBRATE GYROSCOPE OFFSET ")); + Serial.println(F("First choose the sample frequency (ODR) and the Full Scale value.")); + Serial.println(F("Next enter \"O\" to start the gyroscope offset measurement. \nDuring this offset measurement the sensor must be kept still.\n")); + } else + { Serial.println(F("\n\nStep 2 CALIBRATE GYROSCOPE SLOPE")); + Serial.println(F("During a slope calibration the sensor must be rotated calmly about one axis over a known angle.")); + Serial.println(F("Change the angle to your convenience. A larger angle is more accurate, but more difficult to do.")); + Serial.println(F("The rotation must be pure, without much rotation about the other two axes. It can be done by hand.")); + Serial.println(F("Keeping the board on a flat surface with the rotation axis vertical while turning is good enough.")); + Serial.println(F("For an accurate result you can start and end with its side pushed against a non moving object.")); + Serial.println(F("When you're done turning the sensor, press (Enter) to stop measuring. Each of the axes X,Y and Z ")); + Serial.println(F("must be measured. The program automatically detects which. \n")); + + Serial.println(F(" (A) Change the measuring angle to turn the board")); + Serial.print (F(" (C) Calibrate Slope, turn the board over "));Serial.print(turnangle,0);Serial.println(F("° and press enter when finished ")); + } Serial.print (F(" (F) Full Scale setting "));Serial.print(gyroFSindex);Serial.print(" = "); Serial.print(IMU.getGyroFS(),0);Serial.println(F("°/s")); + Serial.print (F(" (R) Output Data Rate (ODR) setting "));Serial.print(gyroODRindex);Serial.print(" = ");Serial.print(IMU.getGyroODR(),0);Serial.println(F("Hz (actual value)")); + Serial.println(F(" (O) Calibrate Offset (keep board still during measurement)")); + + Serial.println(F("\nOffset calibration ( -OK- )")); + Serial.print (F("Slope calibration axis " )); + for (int i= 0; i<=2 ; i++) + { Serial.print(xyz[i]); + if (gyroSlopeOK[i]) Serial.print(F("= ( -OK- ) ")); else Serial.print(F("= not done ")); + } + Serial.println(F("\n\n Gyroscope code")); + Serial.print (F (" IMU.setGyroFS(")); Serial.print(gyroFSindex); + Serial.print( F(");\n IMU.setGyroODR("));Serial.print(gyroODRindex);Serial.println(");"); + printSetParam(" IMU.setGyroOffset ",IMU.gyroOffset); + Serial.println(); + printSetParam(" IMU.setGyroSlope ",IMU.gyroSlope); + Serial.println(); + incomingByte= readChar(); + switch (incomingByte) + { case 'A': { readAnswer("\n\n\n\n\n\nMeasurement turnangle for the board ", turnangle); + break;} + case 'C': { Serial.print(F("\n\n\n\n\n\nMeasuring. Turn the sensor over "));Serial.print(turnangle);Serial.println(F(" degrees\n")); + Serial.println(F("Press Enter when finished.")); + calibrateGyroslope(turnangle); + break;} + case 'F': { Serial.print (F("\n\nEnter new FS nr 0: ±245 1: ±500 2: ±1000 3:± 2000 dps > ")); + b= readChar()-48; Serial.println(b); + if (b!=gyroFSindex && b >=0 && b<=3) gyroFSindex=b; + IMU.setGyroFS(gyroFSindex); + gyroOffsetOK=false; + Serial.print("\n\n\n"); + break;} + case 'R': { Serial.print (F("\n\nEnter new ODR nr 1:10,2:50 3:119,4:238,5:476 Hz> ")); + b= readChar()-48; //Serial.println(b); + if (b!=gyroODRindex && b>=1 && b<=5) + { gyroODRindex=b; + IMU.setGyroODR(gyroODRindex); + gyroOffsetOK=false; + } + Serial.print("\n\n\n"); + break; + } + case 'O': { calibrateGyroOffset(); } + } + Serial.println(""); + } +} + +void calibrateGyroOffset() // don't move the board during calibration +{ float x, y, z;// , addX=0, addY=0, addZ=0 ; + Serial.println(F("\n\n\n\nMeasuring offset. Just a moment.")); + Serial.println(F("\n\nKeep the board still during measurement")); + raw_N_Gyro(1000,x,y,z); + IMU.setGyroOffset(x, y,z); // Store the average measurements as offset + Serial.print("\n\n\n\n\n"); + gyroOffsetOK=true; +} + +void calibrateGyroslope(unsigned int turnangle) // rotate board over known angle +{ boolean validMmt=false; + float dirX=0, dirY=0, dirZ=0,sigmaX2=0,sigmaY2=0,sigmaZ2=0; + float x, y, z, maxXYZ; + unsigned int count=0; + while (!Serial.available()) // measure until enter key pressed + { while (!IMU.gyroAvailable()); + IMU.readRawGyro(x, y, z); + dirX += (x - IMU.gyroOffset[0])/IMU.getGyroODR(); // slope is still raw but offset must already be calibrated + dirY += (y - IMU.gyroOffset[1])/IMU.getGyroODR(); + dirZ += (z - IMU.gyroOffset[2])/IMU.getGyroODR(); + sigmaX2 +=x*x; sigmaY2+=y*y; sigmaZ2+=z*z; + if (count==0) maxXYZ= abs(x); + maxXYZ= max(maxXYZ,abs(x)); maxXYZ= max(maxXYZ,abs(y)); maxXYZ= max(maxXYZ,abs(z)); + count++; + if ((count%30)==0)Serial.print('.'); + digitalWrite(LED_BUILTIN, (millis()/125)%2); // blink onboard led every 250ms + } + digitalWrite(LED_BUILTIN,0); // led off + Serial.readStringUntil(13); //Empty read buffer + Serial.print(F("\n\n\nMeasured direction change X ")); + Serial.print(dirX,6);Serial.print("°\tY "); Serial.print(dirY,6);Serial.print("°\t Z "); Serial.println(dirZ,6);Serial.print("°"); + sigmaX2 /= count; sigmaY2 /= count; sigmaZ2 /= count; + Serial.print(F("Std.dev. ")); + Serial.print(sigmaX2,6);Serial.print('\t'); Serial.print(sigmaY2,6);Serial.print('\t'); Serial.println(sigmaZ2,6); + Serial.print(F("percentage of Full Scale ")); Serial.print(100*maxXYZ/IMU.getGyroFS());Serial.println('%'); + if (maxXYZ/IMU.getGyroFS()>0.95) Serial.print(F("Maximum rotation speed reached. Choose a different FS setting or turn more slowly.")); + else + { dirX=abs(dirX); dirY=abs(dirY); dirZ=abs(dirZ); + if (dirX>max(dirY,dirZ)) + { if (sigmaY2max(dirX,dirZ)) + { if (sigmaX2max(dirY,dirX)) + { if (sigmaY21) param= atof(ans); + while (Serial.available()){Serial.read();} + Serial.println("\n\n\n\n\n\n\n"); +} + +void raw_N_Gyro(unsigned int N, float& averX, float& averY, float& averZ) +{ float x, y, z; + averX=0; averY =0;averZ =0; + for (int i=1;i<=N;i++) + { while (!IMU.gyroAvailable()); + IMU.readRawGyro(x, y, z); + averX += x; averY += y; averZ += z; + digitalWrite(LED_BUILTIN, (millis()/125)%2); // blink onboard led every 250ms + if ((i%30)==0)Serial.print('.'); + } + averX /= N; averY /= N; averZ /= N; + digitalWrite(LED_BUILTIN,0); // led off +} diff --git a/examples/DIY_Calibration_Magnetometer/DIY_Calibration_Magnetometer.ino b/examples/DIY_Calibration_Magnetometer/DIY_Calibration_Magnetometer.ino new file mode 100644 index 0000000..cc9300b --- /dev/null +++ b/examples/DIY_Calibration_Magnetometer/DIY_Calibration_Magnetometer.ino @@ -0,0 +1,187 @@ +/* DIY calibration program for the LSM9DS1 chip + * + * Follow the instructions on the screen how to do calibration measurements. + * See instruction video https://youtu.be/BLvYFXoP33o + * No special tools or setups are needed, however it is handy if the board with the LSM9DS1 chip is fitted inside + * a non-metalic rectangular box with flat sides. + * The offset and slope factors are displayed on screen as code that can be copy/pasted directly into a sketch. + * Each new instance of the chip will require it's own unique set of calibration factors. + * + * To operate the menu in the IDE serial monitor you must press a letter key followed by Enter + * + * Magnetometer + * During calibration of the Magnetometer each of it's sensor axes X, Y and Z must be aimed in both ways (positive + * and negative direction) parallel to the earth magnetic field lines. + * It helps a lot if you know roughly what this direction is. + * Info about the Earthmagnetic field https://en.wikipedia.org/wiki/Earth's_magnetic_field + * The angle above the horizon is called the inclination angle. If you live in the northern hemisphere roughly in + * southern direction, and in the southern hemisphere roughly in northern direction. + * + * written by Femme Verbeek 30-5-2020 + * + * This program uses V2 of the LSM9DS1 library + * Tested on an Arduino Nano 33 BLE Sense board. + */ + +#include + + +float EarthMagnetStrength = 49.0; //= µT + +boolean magnetOK=false; +uint8_t magnetODRindex=8; // (0..8)->{0.625,1.25,2.5,5.0,10,20,40,80,400}Hz +uint8_t magnetFSindex=0; // 0=±400.0; 1=±800.0; 2=±1200.0 , 3=±1600.0 (µT) Only setting 0 turns out to be working + + +void setup() { + Serial.begin(115200); + while (!Serial); + pinMode(LED_BUILTIN,OUTPUT); + delay(10); + if (!IMU.begin()) { Serial.println(F("Failed to initialize IMU!")); while (1); } + IMU.setMagnetODR(magnetODRindex); + IMU.setMagnetFS(magnetFSindex); +} + +void loop() +{ // MainMenu(); + calibrateMagnetMenu(); +} + +void printParam(char txt[], float param[3]) +{ for (int i= 0; i<=2 ; i++) + { Serial.print(txt);Serial.print("["); + Serial.print(i);Serial.print("] = "); + Serial.print(param[i],6);Serial.print(";"); + } +} + +void printSetParam(char txt[], float param[3]) +{ Serial.print(txt);Serial.print("("); + Serial.print(param[0],6);Serial.print(", "); + Serial.print(param[1],6);Serial.print(", "); + Serial.print(param[2],6);Serial.print(");"); +} + +//********************************************************************************************************************************** +//********************************************* Magnetometer ********************************************** +//********************************************************************************************************************************** + + +void calibrateMagnetMenu() +{ char incomingByte = 0; + byte b; + // String ans; + Serial.println(F("\n\n\n\n\n\n\n\n\n\n\n")); + while (1) //(incomingByte!='X') +{ Serial.println(F("Calibrate Magnetometer")); + Serial.println(F("During measurement each of the sensor XYZ axes must be aligned in both directions with the Earth's magnetic field.")); + Serial.println(F("This takes about 10 seconds, if you know the local direction of the magnetic field lines. If you don't, it will take")); + Serial.println(F("several minutes, as you have to twist the board around, aiming every axis in every direction until the min and max ")); + Serial.println(F("values no longer change. Info about the Earthmagnetic field https://en.wikipedia.org/wiki/Earth's_magnetic_field ")); + Serial.println(F("E.g. in my case (Northern hemisphere)declination=0°, inclination=67°, means the aiming direction is South and a")); + Serial.println(F("rather steep 67° above the horizon. ")); + Serial.println(F("The magnetic field measurement will be heavily disturbed by your set-up, so an \"in-situ\" calibration is advised.\n")); + Serial.print (F(" (R) Output Data Rate (ODR) setting "));Serial.print(magnetODRindex);Serial.print(" = ");Serial.print(IMU.getMagnetODR(),0);Serial.println(F("Hz (actual value)")); + Serial.print (F(" (L) Local intensity of Earth magnetic field "));Serial.print(EarthMagnetStrength);Serial.println(F(" µT Change into your local value.")); + Serial.println(F(" (C) Calibrate Magnetometer, Twist board around to find min-max values or aim along earth mag field, press enter to stop\n")); + + Serial.println(F(" Magnetometer code")); + Serial.print(F(" IMU.setMagnetODR("));Serial.print(magnetODRindex);Serial.println(");"); + printSetParam(" IMU.setMagnetOffset",IMU.magnetOffset); + Serial.println(); + printSetParam(" IMU.setMagnetSlope ",IMU.magnetSlope); + Serial.println(F("\n\n")); + incomingByte= readChar(); + switch (incomingByte) + { case 'L': { readAnswer("\n\nLocal Earth Magnetic Field intensity " ,EarthMagnetStrength ); break;} + case 'C': { calibrateMagnet() ; + Serial.print(F("\n\n\n\n\n\n")); + break;} + case 'R': { Serial.print (F("\n\nEnter new ODR nr 6: 40Hz, 7: 80Hz, 8: 400Hz not adviced 0..5: 0.625,1.25,2.5,5.0,10,20 Hz ")); + b= readChar()-48; Serial.println(b); + if (b!=magnetODRindex && b>=1 && b<=8) magnetODRindex=b; + IMU.setMagnetODR(magnetODRindex); + Serial.print("\n\n\n\n\n\n\n\n\n"); + break; + } + default : {Serial.println(F("No menu choise\n\n"));Serial.print(incomingByte); break;} + } + } +} + + +char readChar() +{ char ch; + while (!Serial.available()) ; // wait for character to be entered + ch= toupper(Serial.read()); + delay(10); + while (Serial.available()){Serial.read();delay(1);} // empty readbuffer + return ch; +} + +void readAnswer(char msg[], float& param) +{ char ch=0; + byte count=0; + const byte NofChars = 8; + char ans[NofChars]; + float val; + while (Serial.available()){Serial.read();} //empty read buffer + Serial.print(msg); + Serial.print(param); + Serial.print(F(" Enter new value ")); + while (byte(ch)!=10 && byte(ch)!=13 && count<(NofChars-1) ) + { if (Serial.available()) + { ch= Serial.read(); + ans[count]=ch; + count++; + } + } + ans[count]=0; + Serial.println(ans); + if (count>1) param= atof(ans); + while (Serial.available()){Serial.read();} + Serial.println(F("\n\n\n\n\n\n\n")); +} + + +void calibrateMagnet() // measure Offset and Slope of XYZ +{ float x, y, z, Xmin, Xmax, Ymin, Ymax, Zmin, Zmax ; + unsigned long count=0; + IMU.setMagnetODR(8); //Fast rate 400Hz + raw_N_Magnet(10, Xmin, Ymin, Zmin); // find some starting values + Xmax = Xmin; Ymax = Ymin; Zmax = Zmin; + while (!Serial.available()) // measure until enter key pressed + { raw_N_Magnet(10, x, y, z); //average over a number of samples to reduce the effect of outlyers + Xmax = max (Xmax, x); Xmin = min (Xmin, x); + Ymax = max (Ymax, y); Ymin = min (Ymin, y); + Zmax = max (Zmax, z); Zmin = min (Zmin, z); + count++; + if ((count & 5)==0) //reduce the number of prints by a factor + { Serial.print(F("Xmin = "));Serial.print(Xmin); Serial.print(F(" Xmax = "));Serial.print(Xmax); + Serial.print(F(" Ymin = "));Serial.print(Ymin); Serial.print(F(" Ymax = "));Serial.print(Ymax); + Serial.print(F(" Zmin = "));Serial.print(Zmin); Serial.print(F(" Zmax = "));Serial.print(Zmax); + Serial.println(); + } + } + while (Serial.available()) Serial.read(); //readStringUntil(13); //Empty read buffer + IMU.setMagnetOffset( (Xmax+Xmin)/2,(Ymax+Ymin)/2, (Zmax+Zmin)/2 ) ; // store offset + IMU.setMagnetSlope ( (2*EarthMagnetStrength)/(Xmax-Xmin),(2*EarthMagnetStrength)/(Ymax-Ymin),(2*EarthMagnetStrength)/(Zmax-Zmin)); // store slope + magnetOK=true; + IMU.setMagnetODR(magnetODRindex); +} + + +void raw_N_Magnet(unsigned int N, float& averX, float& averY, float& averZ) +{ float x, y, z; + averX=0; averY =0;averZ =0; + for (int i=1;i<=N;i++) + { while (!IMU.magnetAvailable()); + IMU.readRawMagnet(x, y, z); + averX += x; averY += y; averZ += z; + digitalWrite(LED_BUILTIN, (millis()/125)%2); // blink onboard led every 250ms + if ((i%30)==0)Serial.print('.'); + } + averX /= N; averY /= N; averZ /= N; + digitalWrite(LED_BUILTIN,0); // led off +} diff --git a/examples/RPM_Meter_Rev_Counter/RPM_Meter_Rev_Counter.ino b/examples/RPM_Meter_Rev_Counter/RPM_Meter_Rev_Counter.ino index f37abb9..710599b 100644 --- a/examples/RPM_Meter_Rev_Counter/RPM_Meter_Rev_Counter.ino +++ b/examples/RPM_Meter_Rev_Counter/RPM_Meter_Rev_Counter.ino @@ -23,14 +23,16 @@ void setup() { Serial.println("Failed to initialize IMU!"); while (1); } - IMU.setGyroODR(5); //476Hz + IMU.gyroUnit = REVSPERMINUTE ; //change output unit of readGyro //************ In order for this program to work properly, it needs calibration **************** //************ Replace the lines below by the Gyroscope output of the DIY Calibration program **************** - IMU.gyroOffset[0] = 0; IMU.gyroOffset[1] = 0; IMU.gyroOffset[2] = 0; - IMU.gyroSlope [0] = 1; IMU.gyroSlope [1] = 1; IMU.gyroSlope [2] = 1; + IMU.setGyroFS(3); + IMU.setGyroODR(5); + IMU.setGyroOffset (0.00, 0.00, 0.00); + IMU.setGyroSlope (1.00, 1.00, 1.00); //***************************************************************************************************************** Serial.println("RPM_X \t RPM_Y \t RPM_Z \t Revs_X \t Revs_y \t Revs_Z "); // legend in case you use the serial plotter diff --git a/examples/RegisterTest/RegisterTest.ino b/examples/RegisterTest/RegisterTest.ino index 7f3be00..30e3ec0 100644 --- a/examples/RegisterTest/RegisterTest.ino +++ b/examples/RegisterTest/RegisterTest.ino @@ -1,182 +1,270 @@ /*Test program for Arduino__LSM9DS1 Library version 2.0 extensions - * Written by Femme Verbeek Pijnacker the Netherlands 30 may 2020. - * Run through all the new set and get functions + * Written by Femme Verbeek Pijnacker the Netherlands 6 July 2020. + * + * This program verifies that all the new LSM9DS1 set- and get- chip-setting-fuctions are working + * + * The LSM9DS1 datasheet (https://www.st.com/resource/en/datasheet/lsm9ds1.pdf) + * + * The following anomalies in the functioning of the LSM9DS1 chip have been found. + * + - Upon setAccelFS(1); the needed multiplication factor should be 16, turns out to be 24, + but the sensor maxes out at 20 g + - The setGyroFS(2);* is *NA* according to the datasheet, but when tested it worked nicely at 1000 °/s + - The Gyroscope full scale setting does have a small effect on the offset that needs to be applied. So the + workaround is to apply the same ODR setting when calibrating. See the testGyroFS function below. + - The magnet ODR settings <= 20 Hz did not work on all systems. That means that the original library would + not have worked on the failing systems. For this reason the default ODR setting was changed from 20 to 40Hz. + - setAccelODR(6) and setGyroODR(6) should result in a sampling frequency of 952Hz, but it turned out to + be smaller than 500Hz and with a lot of spikes in the signal. As this affected the accuracy at virtually + no gain in speed, it is advised not to use setting 6. + * + * Additional anomalies found on an Arduino UNO with a separate LSM9DS1 + * + - Settings 1 of setAccelODR( ) and setGyroODR ( ) did not work + - setMagnetODR did not work for settings 0 to 5 + * */ #include +float x,y,z; + void setup() { Serial.begin(115200); while(!Serial); //Wait for serial connection delay(10); if (!IMU.begin()) { - Serial.println("Failed to initialize IMU!"); + Serial.println(F("Failed to initialize IMU!")); while (1); } - float x,y,z; - Serial.println("Testing all library chip settings\n"); - Serial.println ("Full Scale settings should hardly inluence measured values"); - for (int i = 0;i<=4;i++){ - if (IMU.setAccelFS(i)) - { printResult ("setAccelFS(", i ,IMU.getAccelFS()," g "); + Serial.println(F("Testing all library chip settings\n")); + Serial.println (F("Full Scale settings should hardly inluence measured values")); + testAccelFS(); + testGyroFS(); + testMagnetFS(); + testOperationalMode(); + testGyroSharedODR(); + testAccelSharedODR(); + testAccelOnlyODR(); + testMagnetODR(); + testAccelAutomaticBW(); + testAccelBWOverride(); + testGyroBW(); + testAccelUnitChange(); + testGyroUnitChange(); + testMagnetUnitChange(); +} + +void loop() { } + +//----------------------------------- FS (Full scale) functions ------------------------------------- + +void testAccelFS() +{ for (int i = 0;i<=4;i++) + { if (IMU.setAccelFS(i)) + { printResult ("\nsetAccelFS(", i ,IMU.getAccelFS()," g "); read_N_Accel(2,x,y,z); //throw away first two samples read_N_Accel(50,x,y,z); printXYZData("Accel uncalibrated ",x,y,z,"g "); } - else Serial.println ("setAccelFS parameter out of range \n"); } - - read_N_Gyro(50,x, y, z); - IMU.setGyroOffset(x,y,z); //Calibrate Offset - for (int i = 0;i<=4;i++){ - if (IMU.setGyroFS(i)) - { printResult ("setGyroFS(",i,IMU.getGyroFS()," deg/s "); - read_N_Gyro(2,x,y,z); //throw away first two samples - read_N_Gyro(50,x,y,z); - printXYZData("Gyro offset calibrated ",x,y,z,"dps "); + else Serial.println (F("\nsetAccelFS parameter out of range \n")); + } +} +void testGyroFS() +{ + IMU.setGyroODR(4); + Serial.print("setGyroODR ("); Serial.print(4);Serial.print(") = "); Serial.print(IMU.getGyroODR());Serial.print("Hz "); Serial.print(50);Serial.print(" samples"); + for (int i = 0;i<=4;i++) + { if (IMU.setGyroFS(i)) + { printResult ("\nsetGyroFS(",i,IMU.getGyroFS(),"°/s "); + read_N_Gyro(2,true,x,y,z); //throw away first two samples + read_N_Gyro(50,true,x,y,z); + IMU.setGyroOffset(x,y,z); //Calibrate Offset + printXYZData("Gyro raw ",x,y,z,"°/s "); + read_N_Gyro(50,false,x,y,z); + printXYZData("Gyro calibrated ",x,y,z,"°/s "); + } + else Serial.println (F("\nsetGyroFS parameter out of range ")); + } +} + +/*void testGyroFS() // test combinations of ODR, FS and a number of samples in the average +{ + for (int k=1;k<=6;k++) + { IMU.setGyroODR(k); + for (int j=2;j<=100;j*=1.5) + { Serial.print("setGyroODR ("); Serial.print(k);Serial.print(") = "); Serial.print(IMU.getGyroODR());Serial.print("Hz "); Serial.print(j);Serial.print(" samples"); + for (int i = 0;i<=4;i++) + { if (IMU.setGyroFS(i)) + { printResult ("\nsetGyroFS(",i,IMU.getGyroFS(),"°/s "); + readRaw_N_Gyro(2,true,x,y,z); //throw away first two samples + readRaw_N_Gyro(j,true,x,y,z); + IMU.setGyroOffset(x,y,z); //Calibrate Offset + printXYZData("Gyro raw ",x,y,z,"°/s "); + read_N_Gyro(j,false,x,y,z); + printXYZData("Gyro calibrated ",x,y,z,"°/s "); + } + else Serial.println (F("\nsetGyroFS parameter out of range ")); } - else Serial.println ("setGyroFS full scale parameter out of range \n");} - - for (int i = 0;i<=4;i++){ - if (IMU.setMagnetFS(i)) - { printResult ("setMagnetFS(", i ,IMU.getMagnetFS()," µT "); + } + } +} */ + +void testMagnetFS() +{ for (int i = 0;i<=4;i++) + { if (IMU.setMagnetFS(i)) + { printResult ("\nsetMagnetFS(", i ,IMU.getMagnetFS()," µT "); read_N_Magnet(2,x,y,z); //throw away first two samples read_N_Magnet(10,x,y,z); - printXYZData("Magnet ",x,y,z,"dps "); + printXYZData("Magnet ",x,y,z,"µT "); } - else Serial.println ("setMagnetFS full scale parameter out of range \n"); } + else Serial.println (F("\nsetMagnetFS parameter out of range")); + } +} - Serial.println("\nTest Operational Mode 0=off, 1 accelerometer only, 2= Accel + Gyro \n"); - Serial.println("Default operational mode "+String(IMU.getOperationalMode())); +//------------------------------- ODR (Output Data Rate) functions ----------------------------- + +void testOperationalMode() +{ Serial.println(F("\nTest Operational Mode 0=off, 1 accelerometer only, 2= Accel + Gyro \n")); + Serial.print(F("Default operational mode "));Serial.println(IMU.getOperationalMode()); IMU.setGyroODR(0); - Serial.println("setGyroODR(0) Operational mode "+String(IMU.getOperationalMode())); + Serial.print(F("setGyroODR(0) Operational mode "));Serial.println(IMU.getOperationalMode()); IMU.setAccelODR(0); - Serial.println("setAccelODR(0) Operational mode "+String(IMU.getOperationalMode())); + Serial.print(F("setAccelODR(0) Operational mode "));Serial.println(IMU.getOperationalMode()); IMU.setGyroODR(3); - Serial.println("setGyroODR(3) Operational mode "+String(IMU.getOperationalMode())); - - Serial.println("\n setGyroODR result (shared ODR, i>0 overrules the Accel setting)"); - for (int i=0;i<=7;i++) - if (IMU.setGyroODR(i)==0) Serial.println("setGyroODR parameter out of range "+String(i)); - else printODRData(i); - - Serial.println("\n setAccelODR result (shared ODR, i=0 switches off Gyro and Accel)"); + Serial.print(F("setGyroODR(3) Operational mode "));Serial.println(IMU.getOperationalMode()); +} + +void testGyroSharedODR() +{ Serial.println(F("\n setGyroODR result (shared ODR, i>0 overrules the Accel setting)")); + for (int i=0;i<=7;i++) + if (IMU.setGyroODR(i)==0) {Serial.print(F("setGyroODR parameter out of range "));Serial.println(i); } + else printODRData(i); +} + +void testAccelSharedODR() +{ Serial.println(F("\n setAccelODR result (shared ODR, i=0 switches off Gyro and Accel)")); for (int i=0;i<=7;i++) - if (IMU.setAccelODR(i)==0) Serial.println("setAccelODR parameter out of range "+String(i)); + if (IMU.setAccelODR(i)==0) {Serial.print(F("setAccelODR parameter out of range "));Serial.println(i);} else printODRData(i); - - Serial.println("\n Switch off Gyro (Accelerometer only mode)"); +} + +void testAccelOnlyODR() +{ Serial.println(F("\n Switch off Gyro (Accelerometer only mode)")); IMU.setGyroODR(0); //switch off gyro for (int i=0;i<=7;i++) - if (IMU.setAccelODR(i)==0) Serial.println("setAccelODR parameter out of range "+String(i)); + if (IMU.setAccelODR(i)==0) {Serial.print(F("setAccelODR parameter out of range "));Serial.println(i);} else printODRData(i); - - Serial.println("\n setMagnetODR sample rate result"); - for (int i = 0;i<=16;i++){ - if (IMU.setMagnetODR(i)) +} + +void testMagnetODR() +{ Serial.println(F("\n setMagnetODR sample rate result")); + for (int i = 0;i<=16;i++) + { if (IMU.setMagnetODR(i)) printResult ("setMagnetODR(", i , IMU.getMagnetODR()," Hz \n"); - else Serial.println ("setMagnetODR parameter out of range "+String(i));} + else {Serial.print (F("setMagnetODR parameter out of range "));Serial.println(i);} + } +} - Serial.println("\n Accelerometer automatic band width result "); +//--------------------------------- BW (Band width) functions ------------------------------- +void testAccelAutomaticBW() +{ Serial.println(F("\n Accelerometer automatic band width result ")); for (int i=0;i<=6;i++) { IMU.setAccelODR(i); - Serial.print("Accel ODR = "+String(IMU.getAccelODR())); - Serial.println(" automatic BW setting (Hz) "+ String (IMU.getAccelBW())); + Serial.print(F("Accel ODR = "));Serial.print(IMU.getAccelODR()); + Serial.print(F(" automatic BW setting (Hz) " ));Serial.println (IMU.getAccelBW()); } +} - Serial.println ("\n Accelerometer band width override"); +void testAccelBWOverride() +{ Serial.println (F("\n Accelerometer band width override")); for (int i = 0;i<=4;i++) { if (IMU.setAccelBW(i) ) // override automatic bandwith printResult("setAccelBW(", i ,IMU.getAccelBW(), "Hz \n" ); - else Serial.println ("setAccelBW parameter out of range "+String(i) ); + else {Serial.print(F("setAccelBW parameter out of range "));Serial.println(i) ;} } - - Serial.println ("\n Gyroscope band width setting"); +} +void testGyroBW() +{ Serial.println (F("\n Gyroscope band width setting")); for (int i = 0;i<=6;i++) { if (IMU.setGyroODR(i)) - { Serial.println ("Gyroscope ODR = " + String( IMU.getGyroODR() ) ); + { Serial.print (F("Gyroscope ODR = " ));Serial.println( IMU.getGyroODR() ); for (int j = 0;j<=4;j++) { if (IMU.setGyroBW(j) ) // the gyro has no automatic bandwith printResult("setGyroBW(", j ,IMU.getGyroBW(), "Hz \n" ); - else Serial.println ("setGyroBW parameter out of range"+String(j)); + else {Serial.print (F("setGyroBW parameter out of range"));Serial.println(j);} } } - else Serial.println ("failed setting gyroscope sample rate "); + else Serial.println (F("failed setting gyroscope sample rate ")); } +} - Serial.println ("\n Change output Units changes the value of read... \n"); +//---------------------------------------- Changing Output units ------------------------------- - Serial.print("Change accel output unit to m/s2 "); +void testAccelUnitChange() +{ Serial.println (F("\n Changing Accelerometer output units ")); + IMU.setGyroODR(5); IMU.accelUnit= METERPERSECOND2; read_N_Accel(20,x, y, z); - printXYZData("readAccel uncalibrated ",x,y,z,"m/s2 "); - - Serial.print("Change accel output unit to g "); + printXYZData("\nreadAccel ",x,y,z,"m/s2 "); IMU.accelUnit= GRAVITY; read_N_Accel(20,x, y, z); - printXYZData("readAccel uncalibrated ",x,y,z,"g "); + printXYZData("\nreadAccel ",x,y,z,"g "); +} - Serial.print("\nSimulate gyro measurement by offsetting 100 dps "); - IMU.setGyroOffset(0,0,0); //Zero offset - read_N_Gyro(20,x, y, z); +void testGyroUnitChange() +{ Serial.print(F("\n Simulate gyro measurement by offsetting 100 dps")); + IMU.setGyroODR(5); + read_N_Gyro(20,true,x, y, z); IMU.setGyroOffset(100+x,100+y,100+z); //Add 100 dps to measurement to simulate a measurement - Serial.print("\nChange gyro output unit to deg/s "); IMU.gyroUnit = DEGREEPERSECOND; - read_N_Gyro(20,x, y, z); - printXYZData("readGyro offset ",x,y,z,"deg/s "); - - Serial.print("Change gyro output unit to rad/s "); + read_N_Gyro(20,false,x, y, z); + printXYZData("\nreadGyro ",x,y,z," deg/s "); IMU.gyroUnit = RADIANSPERSECOND; - read_N_Gyro(20,x, y, z); - printXYZData("readGyro offset ",x,y,z,"rad/s "); - - Serial.print("Change gyro output unit to Rev/M "); + read_N_Gyro(20,false,x, y, z); + printXYZData("\nreadGyro ",x,y,z," rad/s "); IMU.gyroUnit = REVSPERMINUTE; - read_N_Gyro(20,x, y, z); - printXYZData("readGyro offset ",x,y,z,"RPM "); - - Serial.print("Change gyro output unit to Rev/s "); + read_N_Gyro(20,false,x, y, z); + printXYZData("\nreadGyro ",x,y,z," RPM "); IMU.gyroUnit = REVSPERSECOND; - read_N_Gyro(20,x, y, z); - printXYZData("readGyro offset ",x,y,z,"RPS "); + read_N_Gyro(20,false,x, y, z); + printXYZData("\nreadGyro ",x,y,z," RPS "); +} - Serial.print("\nChange Magnet output unit to microTesla "); - IMU.magnetUnit = MICROTESLA; +void testMagnetUnitChange() +{ IMU.magnetUnit = MICROTESLA; read_N_Magnet(20,x, y, z); - printXYZData("readMagnet ",x,y,z,"µT "); - - Serial.print("Change Magnet output unit to nanoTesla "); + printXYZData("\nreadMagnet ",x,y,z," µT "); IMU.magnetUnit = NANOTESLA; read_N_Magnet(20,x, y, z); - printXYZData("readMagnet ",x,y,z,"nT "); - - Serial.print("Change Magnet output unit to Gauss "); + printXYZData("\nreadMagnet ",x,y,z," nT "); IMU.magnetUnit = GAUSS; read_N_Magnet(20,x, y, z); - printXYZData("readMagnet ",x,y,z,"G "); - + printXYZData("\nreadMagnet ",x,y,z," G "); } -void loop() { } -void printResult (String msg, int nr,float value, String dimension) -{ Serial.print (msg+String(nr)); - Serial.print(") Setting "+String(value)); +//--------------------------------------- print functions ------------------------------- +void printResult (char msg[], int nr,float value, char dimension[]) +{ Serial.print (msg);Serial.print(nr); + Serial.print(F(") Setting "));Serial.print(value); Serial.print(dimension); } void printODRData(int i) -{ Serial.print("Settting "+String(i)); - Serial.print(" Oper.mode "+String(IMU.getOperationalMode())); - Serial.print(" ODR Gyro "+String( IMU.getGyroODR(),3 ) ); - Serial.print("Hz Accel "+String( IMU.getAccelODR(),3 ) ); - Serial.println("Hz"); +{ Serial.print(F("Settting "));Serial.print(i); + Serial.print(F(" Oper.mode "));Serial.print(IMU.getOperationalMode()); + Serial.print(F(" ODR Gyro "));Serial.print( IMU.getGyroODR(),3 ); + Serial.print(F("Hz Accel "));Serial.print( IMU.getAccelODR(),3 ); + Serial.println(F("Hz")); } -void printXYZData(String msg, float x,float y,float z,String unit) +void printXYZData(char msg[], float x,float y,float z,char dimension[]) { Serial.print (msg); - Serial.print (x+unit ); - Serial.print (y+unit ); - Serial.println (z+unit ); + Serial.print (x); Serial.print (dimension ); + Serial.print (y); Serial.print (dimension ); + Serial.print (z); Serial.print (dimension ); } +//-------------------------------------------- measurements ---------------------------------- void read_N_Accel(unsigned int N, float& averX, float& averY, float& averZ) { float x, y, z; averX=0; averY =0;averZ =0; @@ -186,15 +274,17 @@ void read_N_Accel(unsigned int N, float& averX, float& averY, float& averZ) averX += x/N; averY += y/N; averZ += z/N; } } -void read_N_Gyro(unsigned int N, float& averX, float& averY, float& averZ) +void read_N_Gyro(unsigned int N, boolean raw, float& averX, float& averY, float& averZ) { float x, y, z; averX=0; averY =0;averZ =0; for (int i=1;i<=N;i++) { while (!IMU.gyroAvailable()); - IMU.readGyro(x, y, z); + if (raw) IMU.readRawGyro(x, y, z); + else IMU.readGyro(x, y, z); averX += x/N; averY += y/N; averZ += z/N; } } + void read_N_Magnet(unsigned int N, float& averX, float& averY, float& averZ) { float x, y, z; averX=0; averY =0;averZ =0; diff --git a/examples/SimpleAccelerometer/SimpleAccelerometer.ino b/examples/SimpleAccelerometer/SimpleAccelerometer.ino index 3ad425b..aa80aa5 100644 --- a/examples/SimpleAccelerometer/SimpleAccelerometer.ino +++ b/examples/SimpleAccelerometer/SimpleAccelerometer.ino @@ -1,5 +1,6 @@ /* Arduino LSM9DS1 - Simple Accelerometer + Extended with library V2.0 function calls This example reads the acceleration values from the LSM9DS1 sensor and continuously prints them to the Serial Monitor @@ -7,31 +8,44 @@ The circuit: - Arduino Nano 33 BLE Sense + - or Arduino Uno connected to LSM9DS1 breakout board created 10 Jul 2019 by Riccardo Rizzo + Modified by Femme Verbeek 10 jul 2020 + This example code is in the public domain. */ #include -void setup() { - Serial.begin(9600); - while (!Serial); - Serial.println("Started"); - - if (!IMU.begin()) { - Serial.println("Failed to initialize IMU!"); - while (1); - } - - Serial.print("Accelerometer sample rate = "); - Serial.print(IMU.accelerationSampleRate()); - Serial.println(" Hz"); - Serial.println(); - Serial.println("Acceleration in G's"); - Serial.println("X\tY\tZ"); +void setup() +{ Serial.begin(115200); + while (!Serial); + + if (!IMU.begin()) + { Serial.println("Failed to initialize IMU!"); + while (1); + } + // note the FS value does not change the output of the read method, it just assigns more bits to the chip output, + // increasing accuracy at the cost of a smaller range + IMU.setAccelFS(2); // 0: ±2g ; 1: ±24g ; 2: ±4g ; 3: ±8g (default =2) + Serial.print("Accelerometer Full Scale = ±"); + Serial.print(IMU.getAccelFS()); + Serial.println ("g"); + + // Change the sample frequency ( ODR = Output Dats rate) + IMU.setAccelODR(3); // Output Data Rate 0:off, 1:10Hz, 2:50Hz, default = 3:119Hz, 4:238Hz, 5:476Hz, (not working 6:952Hz) + Serial.print("Accelerometer sample rate = "); + Serial.print(IMU.getAccelODR()); // alias AccelerationSampleRate()); + Serial.println(" Hz \n"); + + IMU.accelUnit= GRAVITY; // or METERPERSECOND2 + Serial.println("Gyroscope in degrees/second \n"); + + + Serial.println("X\tY\tZ"); } void loop() { diff --git a/examples/SimpleGyroscope/SimpleGyroscope.ino b/examples/SimpleGyroscope/SimpleGyroscope.ino index 9aab70a..e3c4108 100644 --- a/examples/SimpleGyroscope/SimpleGyroscope.ino +++ b/examples/SimpleGyroscope/SimpleGyroscope.ino @@ -1,5 +1,6 @@ /* Arduino LSM9DS1 - Simple Gyroscope + Extended with library V2.0 function calls This example reads the gyroscope values from the LSM9DS1 sensor and continuously prints them to the Serial Monitor @@ -7,42 +8,57 @@ The circuit: - Arduino Nano 33 BLE Sense + - or Arduino Uno connected to LSM9DS1 breakout board created 10 Jul 2019 by Riccardo Rizzo - + + Modified by Femme Verbeek 10 jul 2020 + This example code is in the public domain. */ #include void setup() { - Serial.begin(9600); + Serial.begin(115200); while (!Serial); - Serial.println("Started"); - if (!IMU.begin()) { - Serial.println("Failed to initialize IMU!"); + if (!IMU.begin()) + { Serial.println("Failed to initialize IMU!"); while (1); - } - Serial.print("Gyroscope sample rate = "); - Serial.print(IMU.gyroscopeSampleRate()); - Serial.println(" Hz"); - Serial.println(); - Serial.println("Gyroscope in degrees/second"); - Serial.println("X\tY\tZ"); + } + + // note the FS value does not change the output of the read method, it just assigns more bits to the chip output, + // increasing accuracy at the cost of a smaller range + IMU.setAccelFS(3); // 0: ±245°/s 1: ±500°/s 2: ±1000°/s Default= 3: ±2000°/s + Serial.print("Gyroscope Full Scale = ±"); + Serial.print(IMU.getGyroFS()); + Serial.println ("°/s"); + + // Change the sample frequency ( ODR = Output Dats rate) + IMU.setAccelODR(3); // Output Data Rate 0:off, 1:10Hz, 2:50Hz, Default= 3:119Hz, 4:238Hz, 5:476Hz, (not working 6:952Hz) + Serial.print("Gyroscope sample rate = "); + Serial.print(IMU.getGyroODR()); //alias IMU.gyroscopeSampleRate()); + Serial.println(" Hz"); + + IMU.gyroUnit= DEGREEPERSECOND; // DEGREEPERSECOND RADIANSPERSECOND REVSPERMINUTE REVSPERSECOND + Serial.println("Gyroscope in degrees/second \n"); + + delay(4000); + Serial.println("X\tY\tZ"); } void loop() { float x, y, z; - if (IMU.gyroscopeAvailable()) { - IMU.readGyroscope(x, y, z); - - Serial.print(x); - Serial.print('\t'); - Serial.print(y); - Serial.print('\t'); - Serial.println(z); + if (IMU.gyroscopeAvailable()) + { + IMU.readGyroscope(x, y, z); + Serial.print(x); + Serial.print('\t'); + Serial.print(y); + Serial.print('\t'); + Serial.println(z); } } diff --git a/examples/SimpleMagnetometer/SimpleMagnetometer.ino b/examples/SimpleMagnetometer/SimpleMagnetometer.ino index 77e21f1..8f42477 100644 --- a/examples/SimpleMagnetometer/SimpleMagnetometer.ino +++ b/examples/SimpleMagnetometer/SimpleMagnetometer.ino @@ -1,5 +1,6 @@ /* Arduino LSM9DS1 - Simple Magnetometer + Extended with library V2.0 function calls This example reads the magnetic field values from the LSM9DS1 sensor and continuously prints them to the Serial Monitor @@ -7,30 +8,47 @@ The circuit: - Arduino Nano 33 BLE Sense + - or Arduino Uno connected to LSM9DS1 breakout board created 10 Jul 2019 by Riccardo Rizzo + Modified by Femme Verbeek + 10 July 2020 + This example code is in the public domain. */ #include -void setup() { - Serial.begin(9600); +void setup() +{ Serial.begin(115200); while (!Serial); - Serial.println("Started"); - if (!IMU.begin()) { + if (!IMU.begin()) + { Serial.println("Failed to initialize IMU!"); while (1); } - Serial.print("Magnetic field sample rate = "); - Serial.print(IMU.magneticFieldSampleRate()); - Serial.println(" uT"); - Serial.println(); - Serial.println("Magnetic Field in uT"); - Serial.println("X\tY\tZ"); + + // note the FS value does not change the output of the read method, it just assigns more bits to the chip output, + // increasing accuracy at the cost of a smaller range + IMU.setMagnetFS(0); // 1=±800µT 2=±1200µT 3=±1600µT Default= 0:±400 µT + Serial.print("Magnetometer Full Scale = ±"); + Serial.print(IMU.getMagnetFS()); + Serial.println ("µT"); + + // Change the sample frequency ( ODR = Output Dats rate) + // Note: setting 0..5 did not work on all systems. The default setting = 5 for compatibility reasons + IMU.setMagnetODR(6); // Sampling rate (0..8)->{0.625,1.25,2.5,5.0,10,20,40,80,400}Hz + Serial.print("Magnetic field sample rate = "); + Serial.print(IMU.getMagnetODR()); // alias IMU.magneticFieldSampleRate()); + Serial.println(" Hz"); + + IMU.magnetUnit = MICROTESLA; // GAUSS MICROTESLA NANOTESLA + Serial.println("Magnetic Field in µT"); + + Serial.println("X\tY\tZ"); } void loop() { diff --git a/examples/Water_Leveler/Water_Leveler.ino b/examples/Water_Leveler/Water_Leveler.ino index 05b1894..4c17262 100644 --- a/examples/Water_Leveler/Water_Leveler.ino +++ b/examples/Water_Leveler/Water_Leveler.ino @@ -17,11 +17,14 @@ void setup() { if (!IMU.begin()) {Serial.println("Failed to initialize IMU!"); while (1); } IMU.setAccelODR(5); //476 Hz -//***************** Replace the lines below by the accelerometer output of the DIY Calibration program ******************* +//***************** In order for this program to work properly, it needs calibration **************** +//***************** Replace the lines below by the accelerometer output of the DIY Calibration program **************** - IMU.accelOffset[0] = 0; IMU.accelOffset[1] = 0; IMU.accelOffset[2] = 0; - IMU.accelSlope [0] = 1; IMU.accelSlope [1] = 1; IMU.accelSlope [2] = 1; - + IMU.setAccelFS(3); + IMU.setAccelODR(5); + IMU.setAccelOffset(0.00, 0.00, 0.00); + IMU.setAccelSlope (1.00, 1.00, 1.00); + //**************************************************************************************************************************** Serial.println("pitchX\tpitchY"); //shows in the legend of the serial plotter. } diff --git a/examples/XY_compass/XY_compass.ino b/examples/XY_compass/XY_compass.ino index f3ddad5..2180769 100644 --- a/examples/XY_compass/XY_compass.ino +++ b/examples/XY_compass/XY_compass.ino @@ -11,6 +11,8 @@ #include +boolean viewInSerialPlotter=true; + void setup() { Serial.begin(115200); while(!Serial); // wait till the serial monitor connects @@ -18,15 +20,16 @@ void setup() { if (!IMU.begin()) { Serial.println("Failed to initialize IMU!"); while (1); } - IMU.setMagnetODR(8); // Sample Rate (0..7) corresponds to {0.625,1.25,2.5,5,10,20,40,80,400}Hz + IMU.setMagnetODR(8); // Sample Rate (0..8) corresponds to {0.625,1.25,2.5,5,10,20,40,80,400}Hz //******************** Replace the lines below by the magnetic output of the DIY Calibration program ********************* - IMU.magnetOffset[0] = 0; IMU.magnetOffset[1] = 0; IMU.magnetOffset[2] = 0; - IMU.magnetSlope [0] = 1; IMU.magnetSlope [1] = 1; IMU.magnetSlope [2] = 1; + IMU.setMagnetODR(8); + IMU.setMagnetOffset(0.000000, 0.000000, 0.000000); + IMU.setMagnetSlope (1.000000, 1.000000, 1.000000); //**************************************************************************************************************************** - Serial.println(" Heading \t Inclination \t Strength \t mag.X \t mag.Y \t mag.Z "); + if (viewInSerialPlotter) Serial.println(" Heading \t Inclination \t Strength \t mag.X \t mag.Y \t mag.Z "); } void loop () @@ -35,10 +38,22 @@ void loop () float heading= atan2(magY,magX)*180/PI +180; float fieldStrength = sqrt(magX*magX +magY*magY+magZ*magZ); float inclination = atan(-magZ/sqrt(magX*magX +magY*magY)) *180/PI; // by definition a positive inclination means the Z component is negative - Serial.print(String(heading)+'\t'); Serial.print(String(inclination)+'\t'); Serial.print(String(fieldStrength)+'\t'); - Serial.print(String(magX)+"µT\t"); Serial.print(String(magY)+"µT\t"); Serial.print(String(magZ)+"µT\n"); +// Serial.print(String(heading)+'\t'); Serial.print(String(inclination)+'\t'); Serial.print(String(fieldStrength)+'\t'); +// Serial.print(String(magX)+"µT\t"); Serial.print(String(magY)+"µT\t"); Serial.print(String(magZ)+"µT\n"); + if (!viewInSerialPlotter) Serial.print("Heading "); + dump(heading,"° Inclination ");dump(inclination,"° Intensity ");dump(fieldStrength,"µT X "); + dump(magX,"µT Y ");dump(magY,"µT Z ");dump(magZ,"µT"); + Serial.println(); +} + +void dump (float Value, char txt[]) +{ + Serial.print(Value); + if (!viewInSerialPlotter) Serial.print(txt); + else Serial.print('\t'); } + void doNMeasurements(unsigned int N, float& averX, float& averY, float& averZ) { float x, y, z; averX=0; averY =0; averZ =0; diff --git a/readme.md b/readme.md index 762e91d..5504bcd 100644 --- a/readme.md +++ b/readme.md @@ -5,7 +5,15 @@ ### 11 june 2020 ---------------------------------------------------------------------------- +links: +[LSM9DS1 datasheet](https://www.st.com/resource/en/datasheet/lsm9ds1.pdf) + +[DIY Calibration instruction video](https://youtu.be/BLvYFXoP33o) + +[Information about Earth Magnetic field](https://en.wikipedia.org/wiki/Earth%27s_magnetic_field) + +----------------------------------------------------------------------------- ## Contents: 1. Introduction 1. Naming strategy @@ -31,29 +39,31 @@ In my case the magnetic field offset was larger than the Earth magnetic field. T like much, but when trying to track the orientation it corresponds to a full circle misalignment in two minutes. Without calibration it is impossible to make a working magnetic or gyro compass, artificial horizon etc. -This new version 2 provides a simple DIY calibration program that gives instructions on how to do measurements. It returns -the parameters on screen so that they can be copy/pasted directly into the code of a sketch. For a rough calibration you -have to do this only once per instance of the chip. But the magnetic field is very easily disturbed. In a different set-up -the chip may return completely different magnetic values. +This new version 2 provides three DIY calibration sketches, for the accelerometer, gyroscope and magnetometer. They give instructions +on what to do during a calibration measurement. For more clarity a [DIY Calibration instruction video](https://youtu.be/BLvYFXoP33o) was made. +The DIY calibration sketches return the results on screen as code that can be copy/pasted in a sketch. For a rough calibration you +have to do this only once per instance of the chip. But the magnetic field measurement is very easily disturbed by the set-up +the chip is mounted in. So for the magnetometer it is advised to do an in-situ calibration. + +The calibration method in this library gives a rather basic linear correction, which will be sufficient in most cases. +When used in combination with sensor fusion algorithms, quaternions, Euler transformations, those libraries usually come with +their own calibration methods. In those cases it may be better not to use the built-in calibration of this library. -In spite of some examples, this library does not prescribe the methods for measuring or calibrating, provide quaternions or -Euler transformations. The development of these is still the task of the user of this library. The examples are kept as simple -as possible and are just for learning. New for all 9 DOF (degrees of freedom) is the possibility: * to change the Output Data Rate (ODR), including fast rate magnetic sampling. The values returned by get...ODR are now the actual values rather than those in the documentation. -* to change the internal full scale setting of the chip (FS) giving it more accuracy at the expence of the range +* to change the internal full scale setting of the chip (FS) giving it more accuracy at the expense of the range * to change the band width filtering of the chip * to change the output unit * to give it calibration zero offset and slope factors * to change the operational mode (off, Acceleration only, Acceleration + Gyroscope The values returned by the read... methods change according to the settings. If left to their default, the output will still -be the same as from version 1.1.0. -The way this is organised is rather unique. (mathematical derivation at the end of this document) +be the same as from version 1.1.0. One exception was made for the magnetometer. The default sample rate of 20Hz did not work on +all set-ups. It has been changed to 40Hz. If you really need the 20Hz, the sketch call is *IMU.setMagnetODR(5);* -All the settings and calibration factors are independent of each other. +In theory all the settings and calibration factors are independent of each other. This means that * changing the FS does not change the read... value, giving it more accuracy at the expense of the range. @@ -61,14 +71,18 @@ This means that * calibration can be done in any chosen Unit, FS, ODR, * the calibration factors can be copy/pasted in a sketch. They dont need changing when the sketch uses any other setting combination of Unit, FS or ODR. - + +In reality the gyroscope offset showed a small dependence on the FS setting. For this reason the possibility to change the settings +was added in the DIY calibration sketches. This improved the drift behavior of the gyro significantly. + ------------------------------------------------- ## 2 Naming strategy ------------------------------------------------- +This new version 2.0 of the library supports al the function calls available in version 1.1.0 Keeping the same naming convention of version 1.1.0 resulted in very long names for the new functions, making formulas difficult to read, increasing the chance of making typo's and it was not always clear what was meant. -For this reason a number of shorter aliases were created most of them following the [datasheet](https://www.st.com/resource/en/datasheet/lsm9ds1.pdf) +For this reason a number of shorter aliases were created, most of them following the [datasheet](https://www.st.com/resource/en/datasheet/lsm9ds1.pdf) new | alias ----- | --------------- @@ -86,7 +100,7 @@ a constant but a function corresponding to the LSM9DS1 chip setting. Not used were the datasheet's XL, M and G since it may confuse with gravity, Gauss and of course the size of clothes. :tshirt: -#### In the text below ... stands for any of the three measurement properties, Accell, Gyro, or Magnet. +#### In the text below ... stands for any of the three measurement properties, Accel, Gyro, or Magnet. ------------------------------------------ ## 3 Output of Read method @@ -112,15 +126,15 @@ Unit = the unit the measured physical property is expressed in. Slope and Offset = calibration parameters. readRaw... produces dimensionless uncalibrated output and is the method to be used when calibrating. -read... produces calibrated output in the unit of your choise. +read... produces calibrated output in the unit of your choice. Note that when Unit, Slope and Offset are left to their default values, the read... and readRaw... methods produce the same output, identical to that of library version 1.01. -Measuring the offset shows that it scales with the chip internal full scale setting (IFS). That means that it is caused +Measuring the offset shows that it scales roughly with the chip internal full scale setting (IFS). That means that it is caused by the internal transducer and not by the ADC. So it is sufficient to calibrate for just one of the full scale settings -and compensate for the others by means of a multiplication (FS). - +and compensate for the others by means of a multiplication (FS). The small dependency of the gyroscope offset on the FS setting +was discovered only recently. Calibrating and running at the same FS setting improved the accuracy especially of the gyro drift. ------------------------------------------ ## 4 Output Data Rate (ODR) @@ -145,10 +159,14 @@ The ODR values According to the datasheet |7 | | | 80 Hz| |8 | | | 400 Hz| +As it turned out the actual ODR values could deviate significantly from the ones in the datasheet. +For that reason the set...ODR functions quickly measure the actual ODR value upon calling. This +actual value is returned by the get...ODR functions. +Settings 6 of Accel and Gyro were supposed to deliver 952 Hz. The result was hardly +faster than that of setting 5 but with a lot more noise. For this reason it is not adviced to use them. -As it turned out the actual ODR could deviate significantly from the datasheet values. -The set...ODR voids measure of the atual ODR value in about 0.35s. This value is returned by -the get...ODR functions. This causes a delay of 0.7s on the start-up of the program. +The magnetometer settings 0..5 turned out not to be working on a separate LSM9DS1 connected to an Arduino Uno +On the same set-up setAccelODR(1) and setGyroODR(1) did not work either. To save on power demand the Gyro or both Gyro+Accel can be switched off by setting ...ODR(0). In any other setting Gyro and Accel share their ODR, so changing one, changes the other. @@ -167,20 +185,20 @@ FS settings | nr |setAccelFS(nr)| setGyroFS(nr)|setMagnetFS(nr) | |:----:|:-------------:|:-------------:|:-----------------:| |0 | ±2 g | ±245 °/s | ±400 µT| -|1 | ±24 g | ±500 °/s | ±800 µT| -|2 | ±4 g | ±1000 °/s | ±1200 µT| -|3 | ±8 g | ±2000 °/s | ±1600 µT| +|1 | ±24 g | ±500 °/s | NA (±800 µT)| +|2 | ±4 g | ±1000 °/s | NA (±1200 µT)| +|3 | ±8 g | ±2000 °/s | NA (±1600 µT)| Datasheet anomalies * Upon *setAccelFS(1);* the needed multiplication factor should be 16 but turns out to be 24, but the sensor maxes out at 20 g -* The *setGyroFS(2); is *NA* according to the datasheet, but when tested it worked nicely at 1000 °/s +* The *setGyroFS(2);* is *NA* according to the datasheet, but when tested it worked nicely at 1000 °/s ------------------------------------------------- ## 6 Band Witdh setting (BW) -------------------------------------------------- -The possibility of setting the band width filtering was added for the purpose of geting rid of a very nasty +The possibility of setting the band-width filtering was added for the purpose of getting rid of a very nasty spike in the gyro/accel signal at the highest ODR. It turned out that there was no influence on the spike at all. The methods are provided "as is". The set values can be found in the [datasheet](https://www.st.com/resource/en/datasheet/lsm9ds1.pdf) tables 46, 47 and 67. @@ -203,7 +221,7 @@ An interactive DIY_Calibration program is provided with this library. See [instr It explains how to measure each of the factors, collects data and presents the result on screen as copy/paste-able code. No special setup is required, but it helps to fix the board in a non-magnetic rectangular box. -![](/images/Boxed sensor.PNG) +![](/images/Boxed_sensor.PNG) The calibration factors may be different per instance of the LSM9DS1 chip. They will hardly vary in time, so it is sufficient to calibrate them only once. The magnetic field is easily disturbed by even the smallest @@ -218,7 +236,7 @@ If you want the fusion program to be using a changed ODR or FS setting, you may in the library itself in the file LSM9DS1.CPP / in the method int LSM9DS1Class::begin() No guarantee that it works. -If you want to design your own calibration method, the text below gives a more explanation on what to do. +If you want to design your own calibration method, the text below gives more explanation on what to do. It is vital that the calibration measurements are done with the raw... functions to get uncalibrated data ------------------------------------------------------------------------------------------ @@ -251,17 +269,17 @@ each. Most probably these are the outlyers in both directions, so actually the w Calculating separate averages of the min and max values is a better method but also like a chicken and egg problem. Before the calibration program can decide to which average a measurement belongs, it needs a rough calibration first. -If the offset is very large, like in case of the magment, this is not straight forward. The DIY calibration program -uses the fastrate magnet ODR and simply caluculates a lot of averages and takes the min and max of that. +If the offset is very large, like in case of the magnet, this is not straight forward. The DIY calibration program +uses the fastrate magnet ODR and simply calculates a lot of averages and takes the min and max of that. The best method is probably 3D elliptical regression, where the values of Offset correspond to the centre of the -elliptoid. So far I did not venture into the mathematics of this. :dizzy_face: +ellipsoid. So far I did not venture into the mathematics of this. :dizzy_face: -------------------------------------------------------------------------------------------------------------------- ### Slope Slope is a dimensionless number that compensates for the sensitivity of the chip's internal transducer. Ideally it's value -should equal 1, meaning that the sensitivity is what it's suppost to be. I my case the accelerometer was very close, the +should equal 1, meaning that the sensitivity is what it's supposed to be. I my case the accelerometer was very close, the gyro 17%, 13% and 4% to low, the magnetometer 5%, 4% and 7% too high. For the magnet and the Accel only their relative values matter, but for the Gyro it's the absolute value if you want to keep track of orientation. 17% means 61 degrees misalignment on a full turn. @@ -277,10 +295,16 @@ The slope calibration values are stored in the arrays ``` ...Slope[3]={1,1,1} ``` -The local data of the magnetic field (in nT) can be found at [Wikipedia](https://en.wikipedia.org/wiki/Earth%27s_magnetic_field) -By pointing the sensor axes in both ways in the direction of the magnetis field lines the difference in reading should be -2x the given fieldstrength. -![](/images/Aim axes along magnetic field lines.PNG) +E.g. The local data of the magnetic field (in nT) can be found at [Wikipedia](https://en.wikipedia.org/wiki/Earth%27s_magnetic_field) +By pointing the sensor axes in both ways in the direction of the magnetic field-lines the difference in reading should be +2x the given field intensity. So +``` + magnetSlope[i]= (2*Intensity)/(NANOTESLA*(readRawMagnet_1 -readRawMagnet_2)) +``` + +![](/images/Aim_axes_along_magnetic_field_lines.PNG) + + E.g. the Earth gravity should produce a value of 1g. Holding the board upside down should measure -1g. So the difference ``` ( Q_1 - Q_2) = 2g @@ -383,7 +407,7 @@ Methods for setting the calibration ``` New: changing the full scale sensitivity of the sensors. -The functions modify the FS (full scale) registers of the LSM9DS1 chip changing sensitivity at the expence of range. +The functions modify the FS (full scale) registers of the LSM9DS1 chip changing sensitivity at the expense of range. Changing this setting does not change the x,y,z output of the read functions, but assigns just more or less bits to the sensor measurement. ``` @@ -416,6 +440,8 @@ observable effect. The methods are provided as is. Sorry for the very formal derivation below. It suits verifiability but probably only my own purpose :nerd_face: It took a lot of puzzling to get it right. Don't read it if you don't want to. :dizzy_face: +The readRaw... method was introduced after this derivation was written. ReadRaw... produces output equal to Read... but with +boundary conditions Offset=0, Slope=1 and unit = 1 (default). ----------------- ### Offset @@ -426,13 +452,13 @@ Assuming good linearity of the transducer, we can model the data output of the c Data = the measured value showing up on the chip registers Q = the actual physical quantity we are trying to measure in any of the 9 DOF -IFS = the chip Internal Fullscale Setting. +IFS = the chip Internal Full Scale Setting. A,B unknown constants representing chip instance differences Since the chip outputs dimensionless bits and bytes only, the dimensions of IFS and B must equal the dimension of Q. The challenge is to get rid of the unknown constants A and B and translate them into measurable quantities produced by the -library's Read methods. Since a good calibrated Read should produce a number equal to the actual physical quantity +library's Read methods. Since the calibrated Read should produce a number equal to the actual physical quantity we can state Read = Q @@ -529,7 +555,7 @@ and with eq(8) Slope = 1 / A -So Slope only depends on A, the (in)sensitivity of the sensor. The proportionality is inverse since Slope is the +So Slope only depends on A, the (in)sensitivity of the sensor. The proportionality is reciprocal since Slope is the compensation factor for the chip's insensitivity QED diff --git a/src/LSM9DS1.cpp b/src/LSM9DS1.cpp index a59c2ef..f9e8b06 100644 --- a/src/LSM9DS1.cpp +++ b/src/LSM9DS1.cpp @@ -1,9 +1,9 @@ /* This file is part of the Arduino_LSM9DS1 library. - New version written by Femme Verbeek, Pijnacker, the Netherlands + This version written by Femme Verbeek, Pijnacker, the Netherlands Released to the public domain version 2 - Release Date 5 june 2020 + Release Date 10 July 2020 Original notice: @@ -45,6 +45,7 @@ #define LSM9DS1_CTRL_REG1_M 0x20 #define LSM9DS1_CTRL_REG2_M 0x21 #define LSM9DS1_CTRL_REG3_M 0x22 +#define LSM9DS1_CTRL_REG4_M 0x23 #define LSM9DS1_STATUS_REG_M 0x27 #define LSM9DS1_OUT_X_L_M 0x28 @@ -83,11 +84,14 @@ int LSM9DS1Class::begin() writeRegister(LSM9DS1_ADDRESS, LSM9DS1_CTRL_REG1_G, 0x78); // 119 Hz, 2000 dps, 16 Hz BW writeRegister(LSM9DS1_ADDRESS, LSM9DS1_CTRL_REG6_XL, 0x70); // 119 Hz, 4G - writeRegister(LSM9DS1_ADDRESS_M, LSM9DS1_CTRL_REG1_M, 0xb4); // Temperature compensation enable, medium performance, 20 Hz + writeRegister(LSM9DS1_ADDRESS_M, LSM9DS1_CTRL_REG1_M, 0b10111000); // Temperature compensation enable, medium performance, 40 Hz +// writeRegister(LSM9DS1_ADDRESS_M, LSM9DS1_CTRL_REG1_M, 0xb4); // Temperature compensation enable, medium performance, 20 Hz writeRegister(LSM9DS1_ADDRESS_M, LSM9DS1_CTRL_REG2_M, 0x00); // 4 Gauss +// writeRegister(LSM9DS1_ADDRESS_M, LSM9DS1_CTRL_REG2_M, 0b01100000); // 16 Gauss writeRegister(LSM9DS1_ADDRESS_M, LSM9DS1_CTRL_REG3_M, 0x00); // Continuous conversion mode - setGyroODR(3); //119Hz set initial shared ODR value of accel and Gyro - setMagnetODR(5); //20Hz set initial ODR value + writeRegister(LSM9DS1_ADDRESS_M, LSM9DS1_CTRL_REG4_M, 0b00000100); // Z-axis operative mode medium performance + + measureODRcombined() ; // for Accelerometer/Gyro and Magnetometer. return 1; } @@ -106,7 +110,7 @@ void LSM9DS1Class::setOneShotMode() { writeRegister(LSM9DS1_ADDRESS, 0x23, 0x00); // Disable continuous mode writeRegister(LSM9DS1_ADDRESS, 0x2E, 0x00); - + continuousMode = false; } @@ -115,6 +119,8 @@ void LSM9DS1Class::end() writeRegister(LSM9DS1_ADDRESS_M, LSM9DS1_CTRL_REG3_M, 0x03); writeRegister(LSM9DS1_ADDRESS, LSM9DS1_CTRL_REG1_G, 0x00); writeRegister(LSM9DS1_ADDRESS, LSM9DS1_CTRL_REG6_XL, 0x00); + pinMode(PIN_ENABLE_I2C_PULLUP, OUTPUT); // this restores the energy usage to very low power + digitalWrite(PIN_ENABLE_I2C_PULLUP, HIGH); // see https://forum.arduino.cc/index.php?topic=691488.15 _wire->end(); } @@ -191,13 +197,13 @@ int LSM9DS1Class::setAccelODR(uint8_t range) //Sample Rate 0:off, 1:10Hz, 2:50Hz gyroODR=0; break; } - case 1 : { accelODR= measureAccelGyroODR(350); + case 1 : { accelODR= measureAccelGyroODR(); gyroODR = 0; break; } case 2 : { setting = ((readRegister(LSM9DS1_ADDRESS, LSM9DS1_CTRL_REG1_G) & 0b00011111) | (range << 5) ); writeRegister(LSM9DS1_ADDRESS, LSM9DS1_CTRL_REG1_G,setting) ; - accelODR= measureAccelGyroODR(350); + accelODR= measureAccelGyroODR(); gyroODR = accelODR; } } @@ -309,11 +315,11 @@ int LSM9DS1Class::setGyroODR(uint8_t range) // 0:off, 1:10Hz, 2:50Hz, 3:119Hz, 4 gyroODR=0; break; } - case 1: { accelODR= measureAccelGyroODR(350); //accelerometer only + case 1: { accelODR= measureAccelGyroODR(); //accelerometer only gyroODR = 0; break; } - case 2: { accelODR= measureAccelGyroODR(350); //shared ODR + case 2: { accelODR= measureAccelGyroODR(); //shared ODR gyroODR = accelODR; } } @@ -419,26 +425,26 @@ void LSM9DS1Class::setMagnetSlope(float x, float y, float z) int LSM9DS1Class::setMagnetFS(uint8_t range) // 0=400.0; 1=800.0; 2=1200.0 , 3=1600.0 (µT) { if (range >=4) return 0; range = (range & 0b00000011) << 5; - return writeRegister(LSM9DS1_ADDRESS, LSM9DS1_CTRL_REG2_M,range) ; + return writeRegister(LSM9DS1_ADDRESS_M, LSM9DS1_CTRL_REG2_M,range) ; } float LSM9DS1Class::getMagnetFS() // dimensionless, but its value defaults to µT { const float Ranges[] ={400.0, 800.0, 1200.0, 1600.0}; // - uint8_t setting = readRegister(LSM9DS1_ADDRESS, LSM9DS1_CTRL_REG2_M) >> 5; + uint8_t setting = readRegister(LSM9DS1_ADDRESS_M, LSM9DS1_CTRL_REG2_M) >> 5; return Ranges[setting] ; } int LSM9DS1Class::setMagnetODR(uint8_t range) // range (0..8) = {0.625,1.25,2.5,5,10,20,40,80,400}Hz { if (range >=16) return 0; - uint8_t setting = ((range & 0b00000111) << 2) | ((range & 0b00001000) >> 2); + uint8_t setting = ((range & 0b00000111) << 2) | ((range & 0b00001000) >> 2); // bit 2..4 see table 111, bit 1 = FAST_ODR setting = setting | (readRegister(LSM9DS1_ADDRESS_M, LSM9DS1_CTRL_REG1_M) & 0b11100001) ; writeRegister(LSM9DS1_ADDRESS_M, LSM9DS1_CTRL_REG1_M,setting) ; - uint16_t duration = 1750 / (range + 1); // 1750,875,666,500,400,333,285,250,222 - magnetODR= measureMagnetODR(duration); + uint16_t duration = 1750 / (range + 1); // 1750,875,666,500,400,333,285,250,222 calculate measuring time + magnetODR= measureMagnetODR(duration); //measure the actual ODR value } float LSM9DS1Class::getMagnetODR() // Output {0.625, 1.25, 2.5, 5.0, 10.0, 20.0, 40.0 , 80.0}; //Hz -{ return magnetODR; +{ return magnetODR; // return previously measured value // const float ranges[] ={0.625, 1.25,2.5, 5.0, 10.0, 20.0, 40.0 , 80.0}; //Hz // uint8_t setting = (readRegister(LSM9DS1_ADDRESS_M, LSM9DS1_CTRL_REG1_M) & 0b00011100) >> 2; // return ranges[setting]; @@ -446,53 +452,79 @@ float LSM9DS1Class::getMagnetODR() // Output {0.625, 1.25, 2.5, 5.0, 10.0, 20.0 //************************************ Private functions ***************************************** -float LSM9DS1Class::measureAccelGyroODR(unsigned int duration) +void LSM9DS1Class::measureODRcombined() //Combined measurement for faster startUp. +{ float x, y, z; + unsigned long lastEventTimeA,lastEventTimeM,startA,startM; + long countA=-3, countM = -2, countiter=0; //Extra cycles to compensate for slow startup + unsigned long start = micros(); + while ((micros()- start) < ODRCalibrationTime) + { countiter++; + if (accelAvailable()) + { lastEventTimeA = micros(); + readAccel(x, y, z); + countA++; + if (countA==0) {startA=lastEventTimeA; + start=lastEventTimeA;} + } + if (magnetAvailable()) + { lastEventTimeM = micros(); + readMagnet(x, y, z); + countM++; + if (countM==0) startM=lastEventTimeM; + } + } +// Serial.println("measure combined " ); +// Serial.println("countA= "+String(countA) ); +// Serial.println("countM= "+String(countM) ); +// Serial.println("countiter= "+String(countiter) ); +// Serial.println("dTa= "+String(lastEventTimeA-startA) ); +// Serial.println("dTb= "+String(lastEventTimeM-startM) ); + + accelODR= (1000000.0*float(countA)/float(lastEventTimeA-startA) ); + gyroODR = accelODR; + magnetODR= (1000000.0*float(countM)/float(lastEventTimeM-startM) ); +} + +float LSM9DS1Class::measureAccelGyroODR() { if (getOperationalMode()==0) return 0; float x, y, z; //dummies - unsigned long lastEventTime, count = 0; - int fifoEna=continuousMode; //switch off FiFo - setOneShotMode(); - duration *=1000; //switch to micros - while (count<2) //throw away nr of samples, fifo enabled would be count<33; - { if (accelAvailable()) - { readAccel(x, y, z); // empty read buffer and wait till current measurement is finished, empty again - count++; - } - } - count=0; - unsigned long start = micros(); - while ((micros()- start) < duration) // measure + unsigned long lastEventTime, + start=micros(); + long count = -3; + int fifoEna=continuousMode; //store FIFO status + setOneShotMode(); //switch off FIFO + while ((micros()- start) < ODRCalibrationTime) // measure { if (accelAvailable()) - { readAccel(x, y, z); + { lastEventTime = micros(); + readAccel(x, y, z); count++; - lastEventTime = micros(); + if (count<=0) start=lastEventTime; } } -// Serial.print(" Count "+String( count ) ); - if (fifoEna) setContinuousMode(); +// Serial.println("measureAccelGyroODR Count "+String( count ) ); +// Serial.println("dTa= "+String(lastEventTime-start) ); +// Serial.println("ODR= "+String(1000000.0*float(count)/float(lastEventTime-start)) ); + if (fifoEna) setContinuousMode(); return (1000000.0*float(count)/float(lastEventTime-start) ); } -float LSM9DS1Class::measureMagnetODR(unsigned int duration) +float LSM9DS1Class::measureMagnetODR(unsigned long duration) { float x, y, z; //dummies - unsigned long lastEventTime, count = 0; + unsigned long lastEventTime, + start =micros(); + long count = -2; // waste current registervalue and running cycle duration *=1000; //switch to micros - while (count<2) //throw away nr of samples - { if (magnetAvailable()) - { readMagnet(x, y, z); // empty read buffer and wait till current measurement is finished, empty again - count++; - } - } - count=0; - unsigned long start = micros(); while ((micros()- start) < duration) // measure { if (magnetAvailable()) - { readMagnet(x, y, z); + { lastEventTime = micros(); + readMagnet(x, y, z); count++; - lastEventTime = micros(); + if (count<=0) start=lastEventTime; } } -// Serial.print(" Count "+String( count ) ); +// Serial.println("MeasureMagnetODR Count "+String( count ) ); +// Serial.println("dTa= "+String(lastEventTime-start) ); +// Serial.println("ODR= "+String(1000000.0*float(count)/float(lastEventTime-start) )) ; return (1000000.0*float(count)/float(lastEventTime-start) ); } diff --git a/src/LSM9DS1.h b/src/LSM9DS1.h index 6e297ab..51e526d 100644 --- a/src/LSM9DS1.h +++ b/src/LSM9DS1.h @@ -125,12 +125,14 @@ class LSM9DS1Class { virtual float getMagnetFS(); // get chip's full scale setting private: - float accelODR; // Stores the actual value of Output Data Rate + unsigned long ODRCalibrationTime=250000; //µs + float accelODR; // Stores the actual value of Output Data Rate float gyroODR; // Stores the actual value of Output Data Rate - float magnetODR; // Stores the actual value of Output Data Rate + float magnetODR; // Stores the actual value of Output Data Rate bool continuousMode; - float measureAccelGyroODR(unsigned int duration); - float measureMagnetODR(unsigned int duration); + void measureODRcombined(); + float measureAccelGyroODR(); + float measureMagnetODR(unsigned long duration); int readRegister(uint8_t slaveAddress, uint8_t address); int readRegisters(uint8_t slaveAddress, uint8_t address, uint8_t* data, size_t length); int writeRegister(uint8_t slaveAddress, uint8_t address, uint8_t value); From 2022b61b8511672b901246fefeefe50733571a79 Mon Sep 17 00:00:00 2001 From: FemmeVerbeek Date: Tue, 21 Jul 2020 00:04:53 +0200 Subject: [PATCH 14/15] Magnetic FS Default Calibr ODR 400Hz Number of samples added in calibration. Default ODR in 400 Hz in calibration. Gyro and Accel calibration with ODR as set in menu. More comment in Simple examples. viewInSerialPlotter switch in examples --- .../DIY_Calibration_Accelerometer.ino | 53 ++++++++++++++---- .../DIY_Calibration_Gyroscope.ino | 30 ++++++---- .../DIY_Calibration_Magnetometer.ino | 15 +++-- .../RPM_Meter_Rev_Counter.ino | 18 +++--- .../SimpleAccelerometer.ino | 56 ++++++++++--------- examples/SimpleGyroscope/SimpleGyroscope.ino | 46 ++++++++------- .../SimpleMagnetometer/SimpleMagnetometer.ino | 46 ++++++++------- examples/Water_Leveler/Water_Leveler.ino | 28 ++++++---- examples/XY_compass/XY_compass.ino | 42 ++++++++------ readme.md | 8 ++- src/LSM9DS1.cpp | 17 ++++-- 11 files changed, 219 insertions(+), 140 deletions(-) diff --git a/examples/DIY_Calibration_Accelerometer/DIY_Calibration_Accelerometer.ino b/examples/DIY_Calibration_Accelerometer/DIY_Calibration_Accelerometer.ino index 8d6f1c2..39f5cf5 100644 --- a/examples/DIY_Calibration_Accelerometer/DIY_Calibration_Accelerometer.ino +++ b/examples/DIY_Calibration_Accelerometer/DIY_Calibration_Accelerometer.ino @@ -28,8 +28,8 @@ float maxAX = 1, maxAY=1, maxAZ=1, minAX=-1, minAY=-1, minAZ=-1; // Accel Slope float zeroAX1 =0,zeroAX2 =0,zeroAY1 =0,zeroAY2 =0,zeroAZ1 =0,zeroAZ2 =0; //Accel Offset boolean accelOK=false; uint8_t acceMMlOK=0; // bit 0..2 maxXYZ bit 3..5 minXYZ -uint8_t accelODRindex=4; // Sample Rate 0:off, 1:10Hz, 2:50Hz, 3:119Hz, 4:238Hz, 5:476Hz, (6:952Hz=na) -uint8_t accelFSindex=3; // Full Scale 0= ±245 dps; 1= ±500 dps; 2= ±1000 dps; 3= ±2000 dps +uint8_t accelODRindex=5; // Sample Rate 0:off, 1:10Hz, 2:50Hz, 3:119Hz, 4:238Hz, 5:476Hz, (6:952Hz=na) +uint8_t accelFSindex=3; // Full Scale// 0: ±2g ; 1: ±24g ; 2: ±4g ; 3: ±8g void setup() { Serial.begin(115200); @@ -37,8 +37,8 @@ void setup() { pinMode(LED_BUILTIN,OUTPUT); delay(10); if (!IMU.begin()) { Serial.println(F("Failed to initialize IMU!")); while (1); } - IMU.setGyroFS(accelFSindex); - IMU.setGyroODR(accelODRindex); + IMU.setAccelFS(accelFSindex); + IMU.setAccelODR(accelODRindex); calibrateAccelMenu(); } @@ -64,15 +64,18 @@ void printSetParam(char txt[], float param[3]) void calibrateAccelMenu() {char incomingByte = 0; byte b; + uint16_t NofCalibrationSamples = 1000; while (1) //(incomingByte!='X') { Serial.println(F("\n\n")); Serial.println(F(" Calibrate Accelerometer Offset and Slope")); - Serial.println(F(" Before calibrating choose the Full Scale setting and Output Data Rate")); + Serial.println(F(" Before calibrating choose the Full Scale (FS) setting and Output Data Rate (ODR). The accelerometer and the")); + Serial.println(F(" gyroscope share their ODR, so the setting here must be the same as in the DIY_Calibration_Gyroscope sketch.")); Serial.println(F(" Place the board on a horizontal surface with one of its axes vertical and hit enter to start a calibration")); Serial.println(F(" measurement. Each of the axes must be measured pointing up and pointing down, so a total of 6 measurements.")); Serial.println(F(" The program recognises which axis is vertical and shows which were measured successfully. If the angle is to")); Serial.println(F(" far oblique the measurement is not valid.\n ")); Serial.println(F(" (enter) Start a calibration measurement. ")); + Serial.print (F(" (N) Number of calibration samples "));Serial.println(NofCalibrationSamples); Serial.print (F(" (F) Full Scale setting "));Serial.print(accelFSindex);Serial.print(" = ");Serial.print(IMU.getAccelFS(),0);Serial.println(F("g")); Serial.print (F(" (R) Output Data Rate (ODR) setting "));Serial.print(accelODRindex);Serial.print(" = ");Serial.print(IMU.getAccelODR(),0);Serial.println(F("Hz (actual value)")); @@ -84,7 +87,7 @@ void calibrateAccelMenu() for (int i=0;i<=2;i++){ Serial.print(xyz[i]); if (bitRead(acceMMlOK,i+3)==1)Serial.print("- = ( -OK- ) "); else Serial.print("- = not done "); } // Serial.println(F("\n\nCurrent accelerometer calibration values (copy/paste-able)\n")); - Serial.println(F("\n\n Accelerometer code")); + Serial.println(F("\n\n // Accelerometer code")); Serial.print(F(" IMU.setAccelFS(")); Serial.print(accelFSindex); Serial.print(F(");\n IMU.setAccelODR("));Serial.print(accelODRindex);Serial.println(");"); @@ -107,20 +110,21 @@ void calibrateAccelMenu() Serial.print("\n\n\n\n\n\n\n\n\n"); break; } + case 'N': { readAnswer("\n\n\n\n\n\nThe number of calibration samples ", NofCalibrationSamples); + break;} case 'C': {}; - default : calibrateAccelSlope(); + default : calibrateAccel(NofCalibrationSamples); } } } -void calibrateAccelSlope() +void calibrateAccel(uint16_t NofSamples) { boolean validMmt=false; float x,y,z; Serial.println(F("\n\n\n\n\n\n\n\n\n\n\n")); Serial.println(F("measuring \n")); - IMU.setAccelSlope(1,1,1); - IMU.setAccelODR(5); //476 Hz - raw_N_Accel(1000,x,y,z); +// IMU.setAccelODR(5); //476 Hz + raw_N_Accel(NofSamples,x,y,z); if (abs(x)>max(abs(y),abs(z))) { Serial.println(F("X detected")); if (sqrt(y*y+z*z)/x1) param= atoi(ans); + while (Serial.available()){Serial.read();} + Serial.println(F("\n\n\n\n\n\n\n")); +} + + + +void raw_N_Accel(uint16_t N, float& averX, float& averY, float& averZ) { float x, y, z; averX=0; averY =0;averZ =0; for (int i=1;i<=N;i++) diff --git a/examples/DIY_Calibration_Gyroscope/DIY_Calibration_Gyroscope.ino b/examples/DIY_Calibration_Gyroscope/DIY_Calibration_Gyroscope.ino index 011a303..854b2d7 100644 --- a/examples/DIY_Calibration_Gyroscope/DIY_Calibration_Gyroscope.ino +++ b/examples/DIY_Calibration_Gyroscope/DIY_Calibration_Gyroscope.ino @@ -38,8 +38,8 @@ const float gyroSlopeCriterion = 50; //Smaller value requires more pureness of char xyz[3]= {'X','Y','Z'}; boolean gyroOffsetOK=false; boolean gyroSlopeOK[3]={false,false,false}; -uint8_t gyroODRindex=4; -uint8_t gyroFSindex=3; // (0= ±245 dps; 1= ±500 dps; 2= ±1000 dps; 3= ±2000 dps) +uint8_t gyroODRindex=5; +uint8_t gyroFSindex=2; // (0= ±245 dps; 1= ±500 dps; 2= ±1000 dps; 3= ±2000 dps) void setup() { Serial.begin(115200); @@ -77,12 +77,15 @@ void printSetParam(char txt[], float param[3]) void calibrateGyroMenu() { char incomingByte = 0; byte b; - float turnangle = 180; + uint16_t turnangle = 180; + uint16_t NofCalibrationSamples = 1000; while (1)// (incomingByte!='X') { if (!gyroOffsetOK) { Serial.println(F("\n\nStep 1 CALIBRATE GYROSCOPE OFFSET ")); - Serial.println(F("First choose the sample frequency (ODR) and the Full Scale value.")); + Serial.println(F("First choose the sample frequency (ODR) and the Full Scale value. The accelerometer and the gyroscope")); + Serial.println(F("share their ODR, so the setting here must be the same as in the DIY_Calibration_Gyroscope sketch.")); + Serial.println(F("This is far more important for the Gyroscope than for the accelerometer. ")); Serial.println(F("Next enter \"O\" to start the gyroscope offset measurement. \nDuring this offset measurement the sensor must be kept still.\n")); } else { Serial.println(F("\n\nStep 2 CALIBRATE GYROSCOPE SLOPE")); @@ -95,9 +98,10 @@ void calibrateGyroMenu() Serial.println(F("must be measured. The program automatically detects which. \n")); Serial.println(F(" (A) Change the measuring angle to turn the board")); - Serial.print (F(" (C) Calibrate Slope, turn the board over "));Serial.print(turnangle,0);Serial.println(F("° and press enter when finished ")); + Serial.print (F(" (C) Calibrate Slope ==>> Turn the board over "));Serial.print(turnangle);Serial.println(F("° and press enter when finished ")); } Serial.print (F(" (F) Full Scale setting "));Serial.print(gyroFSindex);Serial.print(" = "); Serial.print(IMU.getGyroFS(),0);Serial.println(F("°/s")); Serial.print (F(" (R) Output Data Rate (ODR) setting "));Serial.print(gyroODRindex);Serial.print(" = ");Serial.print(IMU.getGyroODR(),0);Serial.println(F("Hz (actual value)")); + Serial.print (F(" (N) Number of calibration samples "));Serial.println(NofCalibrationSamples); Serial.println(F(" (O) Calibrate Offset (keep board still during measurement)")); Serial.println(F("\nOffset calibration ( -OK- )")); @@ -106,7 +110,7 @@ void calibrateGyroMenu() { Serial.print(xyz[i]); if (gyroSlopeOK[i]) Serial.print(F("= ( -OK- ) ")); else Serial.print(F("= not done ")); } - Serial.println(F("\n\n Gyroscope code")); + Serial.println(F("\n\n // Gyroscope code")); Serial.print (F (" IMU.setGyroFS(")); Serial.print(gyroFSindex); Serial.print( F(");\n IMU.setGyroODR("));Serial.print(gyroODRindex);Serial.println(");"); printSetParam(" IMU.setGyroOffset ",IMU.gyroOffset); @@ -138,17 +142,19 @@ void calibrateGyroMenu() Serial.print("\n\n\n"); break; } - case 'O': { calibrateGyroOffset(); } + case 'N': { readAnswer("\n\n\n\n\n\nThe number of calibration samples ", NofCalibrationSamples); + break;} + case 'O': { calibrateGyroOffset(NofCalibrationSamples); } } Serial.println(""); } } -void calibrateGyroOffset() // don't move the board during calibration +void calibrateGyroOffset(uint16_t N) // don't move the board during calibration { float x, y, z;// , addX=0, addY=0, addZ=0 ; Serial.println(F("\n\n\n\nMeasuring offset. Just a moment.")); Serial.println(F("\n\nKeep the board still during measurement")); - raw_N_Gyro(1000,x,y,z); + raw_N_Gyro(N,x,y,z); IMU.setGyroOffset(x, y,z); // Store the average measurements as offset Serial.print("\n\n\n\n\n"); gyroOffsetOK=true; @@ -225,12 +231,12 @@ char readChar() return ch; } -void readAnswer(char msg[], float& param) +void readAnswer(char msg[], uint16_t& param) { char ch=0; byte count=0; const byte NofChars = 8; char ans[NofChars]; - float val; +// float val; while (Serial.available()){Serial.read();} //empty read buffer Serial.print(msg); Serial.print(param); @@ -244,7 +250,7 @@ void readAnswer(char msg[], float& param) } ans[count]=0; Serial.println(ans); - if (count>1) param= atof(ans); + if (count>1) param= atoi(ans); while (Serial.available()){Serial.read();} Serial.println("\n\n\n\n\n\n\n"); } diff --git a/examples/DIY_Calibration_Magnetometer/DIY_Calibration_Magnetometer.ino b/examples/DIY_Calibration_Magnetometer/DIY_Calibration_Magnetometer.ino index cc9300b..1092d6d 100644 --- a/examples/DIY_Calibration_Magnetometer/DIY_Calibration_Magnetometer.ino +++ b/examples/DIY_Calibration_Magnetometer/DIY_Calibration_Magnetometer.ino @@ -30,7 +30,7 @@ float EarthMagnetStrength = 49.0; //= µT boolean magnetOK=false; uint8_t magnetODRindex=8; // (0..8)->{0.625,1.25,2.5,5.0,10,20,40,80,400}Hz -uint8_t magnetFSindex=0; // 0=±400.0; 1=±800.0; 2=±1200.0 , 3=±1600.0 (µT) Only setting 0 turns out to be working +uint8_t magnetFSindex=0; // 0=±400.0; 1=±800.0; 2=±1200.0 , 3=±1600.0 (µT) void setup() { @@ -82,12 +82,14 @@ void calibrateMagnetMenu() Serial.println(F("E.g. in my case (Northern hemisphere)declination=0°, inclination=67°, means the aiming direction is South and a")); Serial.println(F("rather steep 67° above the horizon. ")); Serial.println(F("The magnetic field measurement will be heavily disturbed by your set-up, so an \"in-situ\" calibration is advised.\n")); + Serial.print (F(" (F) Full Scale setting "));Serial.print(magnetFSindex);Serial.print(" = ±"); Serial.print(IMU.getMagnetFS(),0);Serial.println(F(" µT")); Serial.print (F(" (R) Output Data Rate (ODR) setting "));Serial.print(magnetODRindex);Serial.print(" = ");Serial.print(IMU.getMagnetODR(),0);Serial.println(F("Hz (actual value)")); Serial.print (F(" (L) Local intensity of Earth magnetic field "));Serial.print(EarthMagnetStrength);Serial.println(F(" µT Change into your local value.")); Serial.println(F(" (C) Calibrate Magnetometer, Twist board around to find min-max values or aim along earth mag field, press enter to stop\n")); - Serial.println(F(" Magnetometer code")); - Serial.print(F(" IMU.setMagnetODR("));Serial.print(magnetODRindex);Serial.println(");"); + Serial.println(F(" // Magnetometer code")); + Serial.print (F(" IMU.setMagnetFS("));Serial.print(magnetFSindex);Serial.println(");"); + Serial.print (F(" IMU.setMagnetODR("));Serial.print(magnetODRindex);Serial.println(");"); printSetParam(" IMU.setMagnetOffset",IMU.magnetOffset); Serial.println(); printSetParam(" IMU.setMagnetSlope ",IMU.magnetSlope); @@ -98,6 +100,12 @@ void calibrateMagnetMenu() case 'C': { calibrateMagnet() ; Serial.print(F("\n\n\n\n\n\n")); break;} + case 'F': { Serial.print (F("\n\nEnter new FS nr 0=±400.0; 1=±800.0; 2=±1200.0 , 3=±1600.0 (µT)> ")); + b= readChar()-48; Serial.println(b); + if (b!=magnetFSindex && b >=0 && b<=3) magnetFSindex=b; + IMU.setMagnetFS(magnetFSindex); + Serial.print("\n\n\n"); + break;} case 'R': { Serial.print (F("\n\nEnter new ODR nr 6: 40Hz, 7: 80Hz, 8: 400Hz not adviced 0..5: 0.625,1.25,2.5,5.0,10,20 Hz ")); b= readChar()-48; Serial.println(b); if (b!=magnetODRindex && b>=1 && b<=8) magnetODRindex=b; @@ -125,7 +133,6 @@ void readAnswer(char msg[], float& param) byte count=0; const byte NofChars = 8; char ans[NofChars]; - float val; while (Serial.available()){Serial.read();} //empty read buffer Serial.print(msg); Serial.print(param); diff --git a/examples/RPM_Meter_Rev_Counter/RPM_Meter_Rev_Counter.ino b/examples/RPM_Meter_Rev_Counter/RPM_Meter_Rev_Counter.ino index 710599b..c940efa 100644 --- a/examples/RPM_Meter_Rev_Counter/RPM_Meter_Rev_Counter.ino +++ b/examples/RPM_Meter_Rev_Counter/RPM_Meter_Rev_Counter.ino @@ -2,7 +2,7 @@ * Arduino LSM9DS1 - RPM Meter and Rev counter. * Example for V2 of the LSM9DS1 library. * - * Writtenby Femme Verbeek 12 june 2020 + * Writtenby Femme Verbeek 14 july 2020 * * This program demonstrates the use of the LSM9DS1 Gyroscope * When placed on a record turntable it will show the rotation speed in RPM, 33.33 or 45 @@ -26,16 +26,18 @@ void setup() IMU.gyroUnit = REVSPERMINUTE ; //change output unit of readGyro -//************ In order for this program to work properly, it needs calibration **************** -//************ Replace the lines below by the Gyroscope output of the DIY Calibration program **************** - +//******* The gyroscope needs to be calibrated. Offset controls drift and Slope scales the measured rotation angle ********* +//***************** Copy/Replace the lines below by the output of the DIY_Calibration_Gyroscope sketch ******************** IMU.setGyroFS(3); IMU.setGyroODR(5); - IMU.setGyroOffset (0.00, 0.00, 0.00); - IMU.setGyroSlope (1.00, 1.00, 1.00); + IMU.setGyroOffset (0,0,0); // = uncalibrated + IMU.setGyroSlope (1,1,1); // = uncalibrated +//***************************************************************************************************************************** +//********* FS Full Scale range 0: ±245°/s 1: ±500°/s 2: ±1000°/s Default= 3: ±2000°/s *************************** +//********* ODR Output Data Rate range 0:off, 1:10Hz, 2:50Hz, Default= 3:119Hz, 4:238Hz, 5:476Hz, (not working 6:952Hz) ***** +//***************************************************************************************************************************** -//***************************************************************************************************************** - Serial.println("RPM_X \t RPM_Y \t RPM_Z \t Revs_X \t Revs_y \t Revs_Z "); // legend in case you use the serial plotter + Serial.println("RPM_X \t RPM_Y \t RPM_Z \t Revs_X \t Revs_y \t Revs_Z "); // legend in case you use the serial plotter } float countRevsX=0, countRevsY=0, countRevsZ=0; diff --git a/examples/SimpleAccelerometer/SimpleAccelerometer.ino b/examples/SimpleAccelerometer/SimpleAccelerometer.ino index aa80aa5..c34ebbc 100644 --- a/examples/SimpleAccelerometer/SimpleAccelerometer.ino +++ b/examples/SimpleAccelerometer/SimpleAccelerometer.ino @@ -7,7 +7,7 @@ or Serial Plotter. The circuit: - - Arduino Nano 33 BLE Sense + - Arduino Nano 33 BLE (Sense) - or Arduino Uno connected to LSM9DS1 breakout board created 10 Jul 2019 @@ -19,6 +19,7 @@ */ #include +boolean viewInSerialPlotter=true; //true optimises for serial plotter, false for serial monitor void setup() { Serial.begin(115200); @@ -28,36 +29,41 @@ void setup() { Serial.println("Failed to initialize IMU!"); while (1); } - // note the FS value does not change the output of the read method, it just assigns more bits to the chip output, - // increasing accuracy at the cost of a smaller range - IMU.setAccelFS(2); // 0: ±2g ; 1: ±24g ; 2: ±4g ; 3: ±8g (default =2) - Serial.print("Accelerometer Full Scale = ±"); - Serial.print(IMU.getAccelFS()); - Serial.println ("g"); - - // Change the sample frequency ( ODR = Output Dats rate) - IMU.setAccelODR(3); // Output Data Rate 0:off, 1:10Hz, 2:50Hz, default = 3:119Hz, 4:238Hz, 5:476Hz, (not working 6:952Hz) - Serial.print("Accelerometer sample rate = "); - Serial.print(IMU.getAccelODR()); // alias AccelerationSampleRate()); - Serial.println(" Hz \n"); - +/******************* For an improved accuracy run the DIY_Calibration_Accelerometer sketch first. **************** +******************** Copy/Replace the lines below by the code output of the program ****************/ + IMU.setAccelFS(3); + IMU.setAccelODR(5); // + IMU.setAccelOffset(0, 0, 0); // uncalibrated + IMU.setAccelSlope (1, 1, 1); // uncalibrated +/*********************************************************************************************************************************** +******* FS Full Scale range 0:±2g | 1:±24g | 2: ±4g | 3: ±8g (default=2) ****** +******* ODR Output Data Rate range 0:off | 1:10Hz | 2:50Hz | 3:119Hz | 4:238Hz | 5:476Hz, (default=3)(not working 6:952Hz) ****** +************************************************************************************************************************************/ IMU.accelUnit= GRAVITY; // or METERPERSECOND2 - Serial.println("Gyroscope in degrees/second \n"); - - - Serial.println("X\tY\tZ"); + + if (!viewInSerialPlotter) + { Serial.println("Gyroscope in degrees/second \n"); + Serial.print("Accelerometer Full Scale = ±"); + Serial.print(IMU.getAccelFS()); + Serial.println ("g"); + Serial.print("Accelerometer sample rate = "); + Serial.print(IMU.getAccelODR()); // alias AccelerationSampleRate()); + Serial.println(" Hz \n"); + delay(4000); + } + Serial.println(" X \t Y \t Z "); } void loop() { float x, y, z; - if (IMU.accelerationAvailable()) { - IMU.readAcceleration(x, y, z); + if (IMU.accelAvailable()) // alias IMU.accelerationAvailable in library version 1.01 + { IMU.readAccel(x, y, z); // alias IMU.readAcceleration in library version 1.01 - Serial.print(x); - Serial.print('\t'); - Serial.print(y); - Serial.print('\t'); - Serial.println(z); + Serial.print(x); + Serial.print('\t'); + Serial.print(y); + Serial.print('\t'); + Serial.println(z); } } diff --git a/examples/SimpleGyroscope/SimpleGyroscope.ino b/examples/SimpleGyroscope/SimpleGyroscope.ino index e3c4108..351139b 100644 --- a/examples/SimpleGyroscope/SimpleGyroscope.ino +++ b/examples/SimpleGyroscope/SimpleGyroscope.ino @@ -13,12 +13,13 @@ created 10 Jul 2019 by Riccardo Rizzo - Modified by Femme Verbeek 10 jul 2020 + Modified by Femme Verbeek 14 jul 2020 This example code is in the public domain. */ #include +boolean viewInSerialPlotter=false; // true optimises for serial plotter, false for serial monitor void setup() { Serial.begin(115200); @@ -28,33 +29,36 @@ void setup() { { Serial.println("Failed to initialize IMU!"); while (1); } - - // note the FS value does not change the output of the read method, it just assigns more bits to the chip output, - // increasing accuracy at the cost of a smaller range - IMU.setAccelFS(3); // 0: ±245°/s 1: ±500°/s 2: ±1000°/s Default= 3: ±2000°/s - Serial.print("Gyroscope Full Scale = ±"); - Serial.print(IMU.getGyroFS()); - Serial.println ("°/s"); - - // Change the sample frequency ( ODR = Output Dats rate) - IMU.setAccelODR(3); // Output Data Rate 0:off, 1:10Hz, 2:50Hz, Default= 3:119Hz, 4:238Hz, 5:476Hz, (not working 6:952Hz) - Serial.print("Gyroscope sample rate = "); - Serial.print(IMU.getGyroODR()); //alias IMU.gyroscopeSampleRate()); - Serial.println(" Hz"); - +/******* The gyroscope needs to be calibrated. Offset controls drift and Slope scales the measured rotation angle ********* +***************** Copy/Replace the lines below by the output of the DIY_Calibration_Gyroscope sketch ********************/ + IMU.setAccelFS(3); + IMU.setAccelODR(3); + IMU.setGyroOffset (0, 0, 0); // = uncalibrated + IMU.setGyroSlope (1, 1, 1); // = uncalibrated +/***************************************************************************************************************************** +********* FS Full Scale setting 0: ±245°/s | 1: ±500°/s | 2: ±1000°/s | 3: ±2000°/s **************************** +********* ODR Output Data Rate setting 0:off | 1:10Hz | 2:50Hz | 3:119Hz | 4:238Hz | 5:476Hz, (not working 6:952Hz) ******* +*****************************************************************************************************************************/ IMU.gyroUnit= DEGREEPERSECOND; // DEGREEPERSECOND RADIANSPERSECOND REVSPERMINUTE REVSPERSECOND - Serial.println("Gyroscope in degrees/second \n"); - - delay(4000); - Serial.println("X\tY\tZ"); + if (!viewInSerialPlotter) + { Serial.println("Gyroscope in degrees/second \n"); + Serial.print("Gyroscope Full Scale = ±"); + Serial.print(IMU.getGyroFS()); + Serial.println ("°/s"); + Serial.print("Gyroscope sample rate = "); + Serial.print(IMU.getGyroODR()); //alias IMU.gyroscopeSampleRate()); + Serial.println(" Hz"); + delay(4000); + } + Serial.println("X \t Y \t Z"); } void loop() { float x, y, z; - if (IMU.gyroscopeAvailable()) + if (IMU.gyroAvailable()) // alias IMU.gyroscopeAvailable { - IMU.readGyroscope(x, y, z); + IMU.readGyro(x, y, z); // alias IMU.readGyroscope Serial.print(x); Serial.print('\t'); Serial.print(y); diff --git a/examples/SimpleMagnetometer/SimpleMagnetometer.ino b/examples/SimpleMagnetometer/SimpleMagnetometer.ino index 8f42477..ca6d095 100644 --- a/examples/SimpleMagnetometer/SimpleMagnetometer.ino +++ b/examples/SimpleMagnetometer/SimpleMagnetometer.ino @@ -8,7 +8,7 @@ The circuit: - Arduino Nano 33 BLE Sense - - or Arduino Uno connected to LSM9DS1 breakout board + - or Arduino connected to LSM9DS1 breakout board created 10 Jul 2019 by Riccardo Rizzo @@ -20,6 +20,7 @@ */ #include +boolean viewInSerialPlotter=true; // true optimises for serial plotter, false for serial monitor void setup() { Serial.begin(115200); @@ -31,31 +32,36 @@ void setup() while (1); } - // note the FS value does not change the output of the read method, it just assigns more bits to the chip output, - // increasing accuracy at the cost of a smaller range - IMU.setMagnetFS(0); // 1=±800µT 2=±1200µT 3=±1600µT Default= 0:±400 µT - Serial.print("Magnetometer Full Scale = ±"); - Serial.print(IMU.getMagnetFS()); - Serial.println ("µT"); - - // Change the sample frequency ( ODR = Output Dats rate) - // Note: setting 0..5 did not work on all systems. The default setting = 5 for compatibility reasons - IMU.setMagnetODR(6); // Sampling rate (0..8)->{0.625,1.25,2.5,5.0,10,20,40,80,400}Hz - Serial.print("Magnetic field sample rate = "); - Serial.print(IMU.getMagnetODR()); // alias IMU.magneticFieldSampleRate()); - Serial.println(" Hz"); - +/***************** For a proper functioning of the magnetometer it needs to be calibrated ******************** +***************** Replace the lines below by the output of the DIY_Calibration_Magnetometer sketch ********************/ + IMU.setMagnetFS(0); + IMU.setMagnetODR(8); + IMU.setMagnetOffset(0,0,0); // uncalibrated + IMU.setMagnetSlope (1,1,1); // uncalibrated +/****************************************************************************************************************************** +**** FS Full Scale range (0=±400 | 1=±800 | 2=±1200 | 3=±1600 (µT) ***** +**** ODR Output Data Rate range (6,7,8)=(40,80,400)Hz | not available on all chips (0..5): (0.625,1.25,2.5,5.0,10,20)Hz ***** +*******************************************************************************************************************************/ IMU.magnetUnit = MICROTESLA; // GAUSS MICROTESLA NANOTESLA - Serial.println("Magnetic Field in µT"); - - Serial.println("X\tY\tZ"); + + if (!viewInSerialPlotter) + { Serial.println("Magnetic Field in µT"); + Serial.print("Magnetometer Full Scale = ±"); + Serial.print(IMU.getMagnetFS()); + Serial.println ("µT"); + Serial.print("Magnetic field sample rate = "); + Serial.print(IMU.getMagnetODR()); // alias IMU.magneticFieldSampleRate in library version 1.01 + Serial.println(" Hz"); + delay(4000); + } + Serial.println("X \t Y\t Z"); } void loop() { float x, y, z; - if (IMU.magneticFieldAvailable()) { - IMU.readMagneticField(x, y, z); + if (IMU.magnetAvailable()) // alias IMU.magneticFieldAvailable in library version 1.01 + { IMU.readMagnet(x, y, z); // alias IMU.readMagneticField in library version 1.01 Serial.print(x); Serial.print('\t'); diff --git a/examples/Water_Leveler/Water_Leveler.ino b/examples/Water_Leveler/Water_Leveler.ino index 4c17262..92c62a5 100644 --- a/examples/Water_Leveler/Water_Leveler.ino +++ b/examples/Water_Leveler/Water_Leveler.ino @@ -4,29 +4,35 @@ * Calibration makes the difference between a few degrees and within a degree accuracy * Run the DIY calibration program first and copy/paste the Accelerometer calibration data below where it's indicated. * + * The circuit: + * - Arduino Nano 33 BLE (Sense) + * - or Arduino connected to LSM9DS1 breakout board + * * Written by Femme Verbeek * 6 June 2020 * Released to the public domain */ #include -void setup() { +void setup() +{ Serial.begin(115200); while(!Serial); //wait for a serial connection delay(1); if (!IMU.begin()) {Serial.println("Failed to initialize IMU!"); while (1); } - IMU.setAccelODR(5); //476 Hz -//***************** In order for this program to work properly, it needs calibration **************** -//***************** Replace the lines below by the accelerometer output of the DIY Calibration program **************** +/***************** For an improved accuracy run the DIY_Calibration_Accelerometer sketch first. **************** +***************** Copy/Replace the lines below by the code output of the program ****************/ + IMU.setAccelFS(2); + IMU.setAccelODR(3); + IMU.setAccelOffset(0, 0, 0); // 0,0,0 = uncalibrated + IMU.setAccelSlope (1, 1, 1); // 1,1,1 = uncalibrated +/*********************************************************************************************************************************** +******* FS Full Scale range 0:±2g | 1:±24g | 2: ±4g | 3: ±8g (default=2) ****** +******* ODR Output Data Rate range 0:off | 1:10Hz | 2:50Hz | 3:119Hz | 4:238Hz | 5:476Hz, (default=3)(not working 6:952Hz) ****** +************************************************************************************************************************************/ - IMU.setAccelFS(3); - IMU.setAccelODR(5); - IMU.setAccelOffset(0.00, 0.00, 0.00); - IMU.setAccelSlope (1.00, 1.00, 1.00); - -//**************************************************************************************************************************** - Serial.println("pitchX\tpitchY"); //shows in the legend of the serial plotter. + Serial.println(" pitchX \t pitchY"); //shows in the legend of the serial plotter. } void loop() diff --git a/examples/XY_compass/XY_compass.ino b/examples/XY_compass/XY_compass.ino index 2180769..21e42e4 100644 --- a/examples/XY_compass/XY_compass.ino +++ b/examples/XY_compass/XY_compass.ino @@ -11,24 +11,28 @@ #include -boolean viewInSerialPlotter=true; +boolean viewInSerialPlotter=true; // true optimises for serial plotter, false for serial monitor void setup() { Serial.begin(115200); - while(!Serial); // wait till the serial monitor connects + while(!Serial); // wait till the serial monitor connects delay(1); - if (!IMU.begin()) { + if (!IMU.begin()) { // initialize the magnetometer Serial.println("Failed to initialize IMU!"); while (1); } - IMU.setMagnetODR(8); // Sample Rate (0..8) corresponds to {0.625,1.25,2.5,5,10,20,40,80,400}Hz + +/***************** For a proper functioning of the compass the magnetometer needs to be calibrated ******************** +***************** Replace the lines below by the output of the DIY_Calibration_Magnetometer sketch ********************/ + IMU.setMagnetFS(0); + IMU.setMagnetODR(8); + IMU.setMagnetOffset(0, 0, 0); // uncalibrated + IMU.setMagnetSlope (1, 1, 1); // uncalibrated +/****************************************************************************************************************************** +**** FS Full Scale range (0=±400 | 1=±800 | 2=±1200 | 3=±1600 (µT) ***** +**** ODR Output Data Rate range (6,7,8)=(40,80,400)Hz | not available on all chips (0..5): (0.625,1.25,2.5,5.0,10,20)Hz ***** +*******************************************************************************************************************************/ -//******************** Replace the lines below by the magnetic output of the DIY Calibration program ********************* - - IMU.setMagnetODR(8); - IMU.setMagnetOffset(0.000000, 0.000000, 0.000000); - IMU.setMagnetSlope (1.000000, 1.000000, 1.000000); - -//**************************************************************************************************************************** + IMU.magnetUnit = MICROTESLA; // GAUSS MICROTESLA NANOTESLA if (viewInSerialPlotter) Serial.println(" Heading \t Inclination \t Strength \t mag.X \t mag.Y \t mag.Z "); } @@ -38,11 +42,14 @@ void loop () float heading= atan2(magY,magX)*180/PI +180; float fieldStrength = sqrt(magX*magX +magY*magY+magZ*magZ); float inclination = atan(-magZ/sqrt(magX*magX +magY*magY)) *180/PI; // by definition a positive inclination means the Z component is negative -// Serial.print(String(heading)+'\t'); Serial.print(String(inclination)+'\t'); Serial.print(String(fieldStrength)+'\t'); -// Serial.print(String(magX)+"µT\t"); Serial.print(String(magY)+"µT\t"); Serial.print(String(magZ)+"µT\n"); + if (!viewInSerialPlotter) Serial.print("Heading "); - dump(heading,"° Inclination ");dump(inclination,"° Intensity ");dump(fieldStrength,"µT X "); - dump(magX,"µT Y ");dump(magY,"µT Z ");dump(magZ,"µT"); + dump(heading,"° Inclination "); + dump(inclination,"° Intensity "); + dump(fieldStrength,"µT X "); + dump(magX,"µT Y "); + dump(magY,"µT Z "); + dump(magZ,"µT"); Serial.println(); } @@ -53,13 +60,12 @@ void dump (float Value, char txt[]) else Serial.print('\t'); } - void doNMeasurements(unsigned int N, float& averX, float& averY, float& averZ) { float x, y, z; averX=0; averY =0; averZ =0; for (int i=1;i<=N;i++) - { while (!IMU.magneticFieldAvailable()); - IMU.readMagneticField(x, y, z); + { while (!IMU.magnetAvailable()); + IMU.readMagnet(x, y, z); averX += x; averY += y; averZ += z; } averX /= N; averY /= N; averZ /= N; diff --git a/readme.md b/readme.md index 5504bcd..85a5fef 100644 --- a/readme.md +++ b/readme.md @@ -13,6 +13,8 @@ links: [Information about Earth Magnetic field](https://en.wikipedia.org/wiki/Earth%27s_magnetic_field) +[Geomagnetic Calculator of the NOAA](https://www.ngdc.noaa.gov/geomag/calculators/magcalc.shtml?#igrfwmm) + ----------------------------------------------------------------------------- ## Contents: 1. Introduction @@ -185,9 +187,9 @@ FS settings | nr |setAccelFS(nr)| setGyroFS(nr)|setMagnetFS(nr) | |:----:|:-------------:|:-------------:|:-----------------:| |0 | ±2 g | ±245 °/s | ±400 µT| -|1 | ±24 g | ±500 °/s | NA (±800 µT)| -|2 | ±4 g | ±1000 °/s | NA (±1200 µT)| -|3 | ±8 g | ±2000 °/s | NA (±1600 µT)| +|1 | ±24 g | ±500 °/s | ±800 µT| +|2 | ±4 g | ±1000 °/s | ±1200 µT| +|3 | ±8 g | ±2000 °/s | ±1600 µT| Datasheet anomalies * Upon *setAccelFS(1);* the needed multiplication factor should be 16 but turns out to be 24, diff --git a/src/LSM9DS1.cpp b/src/LSM9DS1.cpp index f9e8b06..539aea0 100644 --- a/src/LSM9DS1.cpp +++ b/src/LSM9DS1.cpp @@ -119,14 +119,19 @@ void LSM9DS1Class::end() writeRegister(LSM9DS1_ADDRESS_M, LSM9DS1_CTRL_REG3_M, 0x03); writeRegister(LSM9DS1_ADDRESS, LSM9DS1_CTRL_REG1_G, 0x00); writeRegister(LSM9DS1_ADDRESS, LSM9DS1_CTRL_REG6_XL, 0x00); - pinMode(PIN_ENABLE_I2C_PULLUP, OUTPUT); // this restores the energy usage to very low power - digitalWrite(PIN_ENABLE_I2C_PULLUP, HIGH); // see https://forum.arduino.cc/index.php?topic=691488.15 - - _wire->end(); + + _wire->end(); + + // There has been a problem with the power usage of the Arduino Nano BLE boards. + + // Due to a switch in pinnumbers the pull-ups keep drawing current after the call to IMU.end(); + // This shortens battery life. The solution below may be counter productive when future updates solve + // the switched pin issue. If it is a problem now you can uncomment the follwing lines. + + // pinMode(PIN_ENABLE_I2C_PULLUP, OUTPUT); // this restores the energy usage to very low power + // digitalWrite(PIN_ENABLE_I2C_PULLUP, HIGH); // see https://forum.arduino.cc/index.php?topic=691488.15 } - - //************************************ Acceleration ***************************************** int LSM9DS1Class::readAccel(float& x, float& y, float& z) // return calibrated data in a unit of choise From 38c379d8997c4b402e574aa47c996e62150f0138 Mon Sep 17 00:00:00 2001 From: FemmeVerbeek Date: Wed, 22 Jul 2020 15:04:35 +0200 Subject: [PATCH 15/15] changelog Getting started Low power IMU.end tests for bug in pin definition of I1C causing the pull ups to remain active. restores low power. --- CHANGELOG | 8 ++++---- Getting Started.md | 17 +++++++++++++---- src/LSM9DS1.cpp | 15 ++++++++------- 3 files changed, 25 insertions(+), 15 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index f9e3da6..9c623a2 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -15,11 +15,11 @@ Arduino_LSM9DS1 2.0.0 - 2020.07.10 * Added support for ODR sample rate, ODR values are automatically calibrated, include fast ODR for magnet * Added support for Band width * Added support for changing output unit -* Added support for separate or combined sensor calibration +* Added support for separate or combined sensor calibration on all 9 DOF * Calibration parameters are dimensionless, independent of each other and of the other settings -* Includes a DIY calibration program that produces copy/paste-able code +* Includes DIY calibration programs producing copy/paste-able code * Includes readme.md and Getting Started.md -* Includes examples RPM_meter_Rev_Counter, Water_Leveler, XY_Compass +* Includes examples RPM_meter_Rev_Counter, Water_Leveler, XY_Compass, SimpleGyroscope, SimpleAccelerometer, SimpleMagnetometer * Includes Register_test: demonstrates and verifies all new settings -* The include programs use a minimul amout of RAM to enable running on something as small as a Arduino Uno. +* The included programs use a minimal amount of RAM to enable running on something as small as an Arduino Uno. * The IMU.end() function restores the system to low power usage diff --git a/Getting Started.md b/Getting Started.md index 553b598..29de5b4 100644 --- a/Getting Started.md +++ b/Getting Started.md @@ -18,15 +18,22 @@ from the Arduino library installation directory ## Calibration -If you want to make use of the new calibration possibilities run the interactive example sketch +If you want to make use of the new calibration possibilities run the interactive example sketches DIY_Calibration first. Follow the directions on the screen of the serial monitor. Copy the code from the screen into the setup() of your sketch. See [instruction video](https://youtu.be/BLvYFXoP33o) +It turned out that the best calibration for the Gyroscope depended on the chip's Full Scale and Output Data Rate. +For this reason changing these settings has been added in the calibration programs. + +The functions readAccel, readGyro, readMagnet produce calibrated data in the unit of choise +The functions readRawAccel, readRawGyro, readRawMagnet produce uncalibrated data and are meant for calibration purposes. + ## Use any of the new setting possibilities by placing commands in your sketch All the "set" methods have a corresponding "get" function. -**Choose the Output Data Rate** +**Output Data Rate** +(for read... and readRaw... functions) ``` (range)= (0..5) -> { off, 10, 50, 119, 238, 476} Hz default = 119hz IMU.setAccelODR(range); @@ -36,14 +43,16 @@ All the "set" methods have a corresponding "get" function. IMU.setMagnetODR(range); ``` -**Choose the Full Scale setting** +**Full Scale setting** +(for read... and readRaw... functions) ``` IMU.setAccelFS(range); // 0: ±2g ; 1: ±24g ; 2: ±4g ; 3: ±8g IMU.setGyroFS(range); // (0= ±245, 1= ±500, 2= ±1000, 3= ±2000) °/s IMU.setMagnetFS(range); // 0=±400.0; 1=±800.0; 2=±1200.0 , 3=±1600.0 (µT) ``` -**Choose the unit you want to get the output in** +**Output unit unit you want to get the output in** +(for read... and readRaw... functions) ``` IMU.accelUnit = GRAVITY; // GRAVITY OR METERPERSECOND2 IMU.gyroUnit = DEGREEPERSECOND; // DEGREEPERSECOND RADIANSPERSECOND REVSPERMINUTE REVSPERSECOND diff --git a/src/LSM9DS1.cpp b/src/LSM9DS1.cpp index 539aea0..8b378e3 100644 --- a/src/LSM9DS1.cpp +++ b/src/LSM9DS1.cpp @@ -122,14 +122,15 @@ void LSM9DS1Class::end() _wire->end(); - // There has been a problem with the power usage of the Arduino Nano BLE boards. - + // There has been a problem with the power usage of the Arduino Nano BLE boards. // Due to a switch in pinnumbers the pull-ups keep drawing current after the call to IMU.end(); - // This shortens battery life. The solution below may be counter productive when future updates solve - // the switched pin issue. If it is a problem now you can uncomment the follwing lines. - - // pinMode(PIN_ENABLE_I2C_PULLUP, OUTPUT); // this restores the energy usage to very low power - // digitalWrite(PIN_ENABLE_I2C_PULLUP, HIGH); // see https://forum.arduino.cc/index.php?topic=691488.15 + // This shortens battery life. Most likely future updates solve the problem. + // see https://forum.arduino.cc/index.php?topic=691488.15 + // code for if the old value is used +#if defined(ARDUINO_ARDUINO_NANO33BLE) && PIN_ENABLE_SENSORS_3V3 == 32 + pinMode(PIN_ENABLE_I2C_PULLUP, OUTPUT); // this restores the energy usage to very low power + digitalWrite(PIN_ENABLE_I2C_PULLUP, HIGH); +#endif } //************************************ Acceleration *****************************************