エラー判定用 '\0' + クォータニオンのfloat型4成分,合計17byteのデータをひたすらバイナリ形式で送り続ける.最初のバイトが '\0' でなかったらズレているので,適当なバイト数見送って先頭が '\0' になるよう合わせること.

Dependencies:   Eigen mbed

Files at this revision

API Documentation at this revision

Comitter:
daqn
Date:
Wed Mar 21 07:58:57 2018 +0000
Commit message:
i dont know what should i write here

Changed in this revision

Eigen.lib Show annotated file Show diff for this revision Revisions of this file
MPU9250/MPU9250.cpp Show annotated file Show diff for this revision Revisions of this file
MPU9250/MPU9250.h Show annotated file Show diff for this revision Revisions of this file
main.cpp Show annotated file Show diff for this revision Revisions of this file
mbed.bld Show annotated file Show diff for this revision Revisions of this file
diff -r 000000000000 -r 2a7221ee9861 Eigen.lib
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Eigen.lib	Wed Mar 21 07:58:57 2018 +0000
@@ -0,0 +1,1 @@
+https://os.mbed.com/users/ykuroda/code/Eigen/#13a5d365ba16
diff -r 000000000000 -r 2a7221ee9861 MPU9250/MPU9250.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/MPU9250/MPU9250.cpp	Wed Mar 21 07:58:57 2018 +0000
@@ -0,0 +1,388 @@
+/** Daqn change log
+ * 2018/02/16 :  Replace words "MPU6050" with "MPU9250".
+ * 2018/02/16 :  L57, flip T/F by adding "!".
+ * 2018/02/21 :  L
+ */
+
+/**
+ * Includes
+ */
+#include "MPU9250.h"
+
+MPU9250::MPU9250(PinName sda, PinName scl) : connection(sda, scl) {
+    this->setSleepMode(false);
+    
+    //Initializations:
+    currentGyroRange = 0;
+    currentAcceleroRange=0;
+    alpha = ALPHA;
+}
+
+//--------------------------------------------------
+//-------------------General------------------------
+//--------------------------------------------------
+
+void MPU9250::write(char address, char data) {
+    char temp[2];
+    temp[0]=address;
+    temp[1]=data;
+    
+    connection.write(MPU9250_ADDRESS * 2,temp,2);
+}
+
+char MPU9250::read(char address) {
+    char retval;
+    connection.write(MPU9250_ADDRESS * 2, &address, 1, true);
+    connection.read(MPU9250_ADDRESS * 2, &retval, 1);
+    return retval;
+}
+
+void MPU9250::read(char address, char *data, int length) {
+    connection.write(MPU9250_ADDRESS * 2, &address, 1, true);
+    connection.read(MPU9250_ADDRESS * 2, data, length);
+}
+
+void MPU9250::setSleepMode(bool state) {
+    char temp;
+    temp = this->read(MPU9250_PWR_MGMT_1_REG);
+    if (state == true)
+        temp |= 1<<MPU9250_SLP_BIT;
+    if (state == false)
+        temp &= ~(1<<MPU9250_SLP_BIT);
+    this->write(MPU9250_PWR_MGMT_1_REG, temp);
+}
+
+bool MPU9250::testConnection( void ) {
+    char temp;
+    temp = this->read(MPU9250_WHO_AM_I_REG);
+    return !(temp == (MPU9250_ADDRESS & 0xFE));  // Daqn 2018/02/16
+}
+
+void MPU9250::setBW(char BW) {
+    char temp;
+    BW=BW & 0x07;
+    temp = this->read(MPU9250_CONFIG_REG);
+    temp &= 0xF8;
+    temp = temp + BW;
+    this->write(MPU9250_CONFIG_REG, temp);
+}
+
+void MPU9250::setI2CBypass(bool state) {
+    char temp;
+    temp = this->read(MPU9250_INT_PIN_CFG);
+    if (state == true)
+        temp |= 1<<MPU9250_BYPASS_BIT;
+    if (state == false)
+        temp &= ~(1<<MPU9250_BYPASS_BIT);
+    this->write(MPU9250_INT_PIN_CFG, temp);
+}
+
+//--------------------------------------------------
+//----------------Accelerometer---------------------
+//--------------------------------------------------
+
+void MPU9250::setAcceleroRange( char range ) {
+    char temp;
+    range = range & 0x03;
+    currentAcceleroRange = range;
+    
+    temp = this->read(MPU9250_ACCELERO_CONFIG_REG);
+    temp &= ~(3<<3);
+    temp = temp + (range<<3);
+    this->write(MPU9250_ACCELERO_CONFIG_REG, temp);
+}
+
+int MPU9250::getAcceleroRawX( void ) {
+    short retval;
+    char data[2];
+    this->read(MPU9250_ACCEL_XOUT_H_REG, data, 2);
+    retval = (data[0]<<8) + data[1];
+    return (int)retval;
+}
+
+int MPU9250::getAcceleroRawY( void ) {
+    short retval;
+    char data[2];
+    this->read(MPU9250_ACCEL_YOUT_H_REG, data, 2);
+    retval = (data[0]<<8) + data[1];
+    return (int)retval;
+}
+
+int MPU9250::getAcceleroRawZ( void ) {
+    short retval;
+    char data[2];
+    this->read(MPU9250_ACCEL_ZOUT_H_REG, data, 2);
+    retval = (data[0]<<8) + data[1];
+    return (int)retval;
+}
+
+void MPU9250::getAcceleroRaw( int *data ) {
+    char temp[6];
+    this->read(MPU9250_ACCEL_XOUT_H_REG, temp, 6);
+    data[0] = (int)(short)((temp[0]<<8) + temp[1]);
+    data[1] = (int)(short)((temp[2]<<8) + temp[3]);
+    data[2] = (int)(short)((temp[4]<<8) + temp[5]);
+}
+
+void MPU9250::getAccelero( float *data ) {
+    int temp[3];
+    this->getAcceleroRaw(temp);
+    if (currentAcceleroRange == MPU9250_ACCELERO_RANGE_2G) {
+        data[0]=(float)temp[0] / 16384.0 * 9.81;
+        data[1]=(float)temp[1] / 16384.0 * 9.81;
+        data[2]=(float)temp[2] / 16384.0 * 9.81;
+        }
+    if (currentAcceleroRange == MPU9250_ACCELERO_RANGE_4G){
+        data[0]=(float)temp[0] / 8192.0 * 9.81;
+        data[1]=(float)temp[1] / 8192.0 * 9.81;
+        data[2]=(float)temp[2] / 8192.0 * 9.81;
+        }
+    if (currentAcceleroRange == MPU9250_ACCELERO_RANGE_8G){
+        data[0]=(float)temp[0] / 4096.0 * 9.81;
+        data[1]=(float)temp[1] / 4096.0 * 9.81;
+        data[2]=(float)temp[2] / 4096.0 * 9.81;
+        }
+    if (currentAcceleroRange == MPU9250_ACCELERO_RANGE_16G){
+        data[0]=(float)temp[0] / 2048.0 * 9.81;
+        data[1]=(float)temp[1] / 2048.0 * 9.81;
+        data[2]=(float)temp[2] / 2048.0 * 9.81;
+        }
+    
+    #ifdef DOUBLE_ACCELERO
+        data[0]*=2;
+        data[1]*=2;   
+        data[2]*=2;
+    #endif   
+}
+//--------------------------------------------------
+//------------------Gyroscope-----------------------
+//--------------------------------------------------
+void MPU9250::setGyroRange( char range ) {
+    char temp;
+    currentGyroRange = range;
+    range = range & 0x03;
+    temp = this->read(MPU9250_GYRO_CONFIG_REG);
+    temp &= ~(3<<3);
+    temp = temp + range<<3;
+    this->write(MPU9250_GYRO_CONFIG_REG, temp);
+}
+
+int MPU9250::getGyroRawX( void ) {
+    short retval;
+    char data[2];
+    this->read(MPU9250_GYRO_XOUT_H_REG, data, 2);
+    retval = (data[0]<<8) + data[1];
+    return (int)retval;
+}
+    
+int MPU9250::getGyroRawY( void ) {
+    short retval;
+    char data[2];
+    this->read(MPU9250_GYRO_YOUT_H_REG, data, 2);
+    retval = (data[0]<<8) + data[1];
+    return (int)retval;
+}
+
+int MPU9250::getGyroRawZ( void ) {
+    short retval;
+    char data[2];
+    this->read(MPU9250_GYRO_ZOUT_H_REG, data, 2);
+    retval = (data[0]<<8) + data[1];
+    return (int)retval;
+}
+
+void MPU9250::getGyroRaw( int *data ) {
+    char temp[6];
+    this->read(MPU9250_GYRO_XOUT_H_REG, temp, 6);
+    data[0] = (int)(short)((temp[0]<<8) + temp[1]);
+    data[1] = (int)(short)((temp[2]<<8) + temp[3]);
+    data[2] = (int)(short)((temp[4]<<8) + temp[5]);
+}
+
+void MPU9250::getGyro( float *data ) {
+    int temp[3];
+    this->getGyroRaw(temp);
+    if (currentGyroRange == MPU9250_GYRO_RANGE_250) {
+        data[0]=(float)temp[0] / 301.0;
+        data[1]=(float)temp[1] / 301.0;
+        data[2]=(float)temp[2] / 301.0;
+        }               //7505.5
+    if (currentGyroRange == MPU9250_GYRO_RANGE_500){
+        data[0]=(float)temp[0] / 3752.9;
+        data[1]=(float)temp[1] / 3752.9;
+        data[2]=(float)temp[2] / 3752.9;
+        }
+    if (currentGyroRange == MPU9250_GYRO_RANGE_1000){
+        data[0]=(float)temp[0] / 1879.3;;
+        data[1]=(float)temp[1] / 1879.3;
+        data[2]=(float)temp[2] / 1879.3;
+        }
+    if (currentGyroRange == MPU9250_GYRO_RANGE_2000){
+        data[0]=(float)temp[0] / 939.7;
+        data[1]=(float)temp[1] / 939.7;
+        data[2]=(float)temp[2] / 939.7;
+        }
+}
+//--------------------------------------------------
+//-------------------Temperature--------------------
+//--------------------------------------------------
+int MPU9250::getTempRaw( void ) {
+    short retval;
+    char data[2];
+    this->read(MPU9250_TEMP_H_REG, data, 2);
+    retval = (data[0]<<8) + data[1];
+    return (int)retval;
+}
+
+float MPU9250::getTemp( void ) {
+    float retval;
+    retval=(float)this->getTempRaw();
+    retval=(retval+521.0)/340.0+35.0;
+    return retval;
+}
+
+
+//--------------------------------------------------
+//------------------Magnetometer--------------------
+//--------------------------------------------------
+void MPU9250::read(char address, char subaddress, char *data, int length)
+{
+//    connection.write(MPU9250_ADDRESS * 2, &address, 1, true);
+//    connection.read(MPU9250_ADDRESS * 2, data, length);
+    connection.write(address, &subaddress, 1, true);
+    connection.read(address, data, length);
+}
+
+//void MPU9250::setMagnetoRange( char range ) {
+//    char temp;
+//    currentMagnetoRange = range;
+//    range = range & 0x03;
+//    temp = this->read(MPU9250_MAGNETO_CONFIG_REG);
+//    temp &= ~(3<<3);
+//    temp = temp + range<<3;
+//    this->write(MPU9250_MAGNETO_CONFIG_REG, temp);
+//}
+
+
+
+int MPU9250::getMagnetoRawX( void )
+{
+    short retval;
+    char data[2];
+    this->read(AK8963_ADDRESS, AK8963_XOUT_L, data, 2);
+    retval = (data[0]<<8) + data[1];
+    return (int)retval;
+}
+
+int MPU9250::getMagnetoRawY( void )
+{
+    short retval;
+    char data[2];
+    this->read(AK8963_ADDRESS, AK8963_YOUT_L, data, 2);
+    retval = (data[0]<<8) + data[1];
+    return (int)retval;
+}
+//
+int MPU9250::getMagnetoRawZ( void )
+{
+    short retval;
+    char data[2];
+    this->read(AK8963_ADDRESS, AK8963_ZOUT_L, data, 2);
+    retval = (data[0]<<8) + data[1];
+    return (int)retval;
+}
+
+void MPU9250::getMagnetoRaw( int *data ) {
+    char temp[6];
+    this->read(AK8963_ADDRESS, AK8963_XOUT_L, temp, 6);
+    data[0] = (int)(short)((temp[1]<<8) + temp[0]);
+    data[1] = (int)(short)((temp[3]<<8) + temp[2]);
+    data[2] = (int)(short)((temp[5]<<8) + temp[4]);
+}
+
+void MPU9250::getMagneto( float *data ) {
+    int temp[3];
+    this->getMagnetoRaw(temp);
+    data[0]=(float)temp[0] * .15f;
+    data[1]=(float)temp[1] * .15f;
+    data[2]=(float)temp[2] * .15f;
+}
+
+/**Additional function added by Montvydas Klumbys, which will allow easy offset, angle calculation and much more.
+ function for getting angles in degrees from accelerometer
+*/
+void MPU9250::getAcceleroAngle( float *data ) {
+    float temp[3];
+    this->getAccelero(temp);
+    
+    data[X_AXIS] = atan (temp[Y_AXIS]/sqrt(pow(temp[X_AXIS], 2) + pow(temp[Z_AXIS], 2))) * RADIANS_TO_DEGREES; //calculate angle x(pitch/roll?) from accellerometer reading
+    data[Y_AXIS] = atan (-1*temp[X_AXIS]/sqrt(pow(temp[Y_AXIS], 2) + pow(temp[Z_AXIS], 2))) * RADIANS_TO_DEGREES; //calculate angle x(pitch/roll?) from accellerometer reading
+    data[Z_AXIS] = atan (sqrt(pow(temp[X_AXIS], 2) + pow(temp[Y_AXIS], 2))/temp[Z_AXIS]) * RADIANS_TO_DEGREES; //This one is not used anywhere later on
+    
+//    data[Y_AXIS] = atan2 (temp[Y_AXIS],temp[Z_AXIS]) * RADIANS_TO_DEGREES;  //This spits out values between -180 to 180 (360 degrees)
+//    data[X_AXIS] = atan2 (-1*temp[X_AXIS], temp[Z_AXIS]) * RADIANS_TO_DEGREES;    //but it takes longer and system gets unstable when angles ~90 degrees
+}
+
+///function for getting offset values for the gyro & accelerometer
+void MPU9250::getOffset(float *accOffset, float *gyroOffset, int sampleSize){
+    float gyro[3];      
+    float accAngle[3];
+    
+    for (int i = 0; i < 3; i++) {
+        accOffset[i] = 0.0;     //initialise offsets to 0.0
+        gyroOffset[i] = 0.0;
+    }
+    
+    for (int i = 0; i < sampleSize; i++){
+        this->getGyro(gyro); //take real life measurements  
+        this->getAcceleroAngle (accAngle);
+        
+        for (int j = 0; j < 3; j++){
+            *(accOffset+j) += accAngle[j]/sampleSize;    //average measurements
+            *(gyroOffset+j) += gyro[j]/sampleSize;
+        }
+        wait (0.01);    //wait between each reading for accuracy 
+    } 
+}
+
+///function for computing angles for roll, pitch anf yaw
+void MPU9250::computeAngle (float *angle, float *accOffset, float *gyroOffset, float interval){
+    float gyro[3];
+    float accAngle[3];
+    
+    this->getGyro(gyro);                //get gyro value in rad/s
+    this->getAcceleroAngle(accAngle);   //get angle from accelerometer
+    
+    for (int i = 0; i < 3; i++){
+        gyro[i] -= gyroOffset[i];       //substract offset values
+        accAngle[i] -= accOffset[i];    
+    }
+    
+    //apply filters on pitch and roll to get accurate angle values
+    angle[X_AXIS] = alpha * (angle[X_AXIS] + GYRO_SCALE*gyro[X_AXIS]*interval) + (1-alpha)*accAngle[X_AXIS]; 
+    angle[Y_AXIS] = alpha * (angle[Y_AXIS] + GYRO_SCALE*gyro[Y_AXIS]*interval) + (1-alpha)*accAngle[Y_AXIS];
+    
+    //calculate Yaw using just the gyroscope values - inaccurate
+    angle[Z_AXIS] = angle[Z_AXIS] + GYRO_SCALE*gyro[Z_AXIS]*interval;     
+}
+
+///function for setting a different Alpha value, which is used in complemetary filter calculations
+void MPU9250::setAlpha(float val){
+    alpha = val;   
+}
+
+///function for enabling interrupts on MPU9250 INT pin, when the data is ready to take
+void MPU9250::enableInt( void ){
+    char temp;
+    temp = this->read(MPU9250_RA_INT_ENABLE);
+    temp |= 0x01;
+    this->write(MPU9250_RA_INT_ENABLE, temp);
+}
+
+///function for disbling interrupts on MPU9250 INT pin, when the data is ready to take
+void MPU9250::disableInt ( void ){
+    char temp;
+    temp = this->read(MPU9250_RA_INT_ENABLE);
+    temp &= 0xFE;
+    this->write(MPU9250_RA_INT_ENABLE, temp);
+}
\ No newline at end of file
diff -r 000000000000 -r 2a7221ee9861 MPU9250/MPU9250.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/MPU9250/MPU9250.h	Wed Mar 21 07:58:57 2018 +0000
@@ -0,0 +1,426 @@
+/** Daqn change log
+ * 2018/02/16 :  Replace words "MPU6050" with "MPU9250".
+ * 2018/02/21 :  
+ */
+
+/*Use #define MPU9250_ES before you include this file if you have an engineering sample (older EVBs will have them), to find out if you have one, check your accelerometer output. 
+If it is half of what you expected, and you still are on the correct planet, you got an engineering sample
+*/
+
+
+#ifndef MPU9250_H
+#define MPU9250_H
+
+/**
+ * Includes
+ */
+#include "mbed.h"
+
+
+/**
+ * Defines
+ */
+#ifndef MPU9250_ADDRESS
+    #define MPU9250_ADDRESS             0x68 // address pin low (GND), default for InvenSense evaluation board
+#endif
+
+#ifdef MPU9250_ES
+        #define DOUBLE_ACCELERO
+#endif  
+
+/**
+ * Registers
+ */
+ #define MPU9250_CONFIG_REG         0x1A
+ #define MPU9250_GYRO_CONFIG_REG    0x1B
+ #define MPU9250_ACCELERO_CONFIG_REG    0x1C
+  
+ #define MPU9250_INT_PIN_CFG        0x37
+ 
+ #define MPU9250_ACCEL_XOUT_H_REG   0x3B
+ #define MPU9250_ACCEL_YOUT_H_REG   0x3D
+ #define MPU9250_ACCEL_ZOUT_H_REG   0x3F
+ 
+ #define MPU9250_TEMP_H_REG         0x41
+ 
+ #define MPU9250_GYRO_XOUT_H_REG    0x43
+ #define MPU9250_GYRO_YOUT_H_REG    0x45
+ #define MPU9250_GYRO_ZOUT_H_REG    0x47
+ 
+ #define MPU9250_MAG_XOUT_H_REG    0x04 
+ #define MPU9250_MAG_YOUT_H_REG    0x06
+ #define MPU9250_MAG_ZOUT_H_REG    0x08
+ 
+ 
+ 
+ #define MPU9250_PWR_MGMT_1_REG     0x6B
+ #define MPU9250_WHO_AM_I_REG       0x75
+ 
+                 
+ 
+ /**
+  * Definitions
+  */
+#define MPU9250_SLP_BIT             6
+#define MPU9250_BYPASS_BIT         1
+
+#define MPU9250_BW_256              0
+#define MPU9250_BW_188              1
+#define MPU9250_BW_98               2
+#define MPU9250_BW_42               3
+#define MPU9250_BW_20               4
+#define MPU9250_BW_10               5
+#define MPU9250_BW_5                6
+
+#define MPU9250_ACCELERO_RANGE_2G   0
+#define MPU9250_ACCELERO_RANGE_4G   1
+#define MPU9250_ACCELERO_RANGE_8G   2
+#define MPU9250_ACCELERO_RANGE_16G  3
+
+#define MPU9250_GYRO_RANGE_250      0
+#define MPU9250_GYRO_RANGE_500      1
+#define MPU9250_GYRO_RANGE_1000     2
+#define MPU9250_GYRO_RANGE_2000     3
+
+//interrupt address
+#define MPU9250_RA_INT_ENABLE 0x38  
+//define how the accelerometer is placed on surface
+#define X_AXIS 1
+#define Y_AXIS 2
+#define Z_AXIS 0
+//translation from radians to degrees
+#define RADIANS_TO_DEGREES 180/3.1415926536
+//constant used for the complementary filter, which ranges usually from 0.9 to 1.0
+#define ALPHA 0.96   //filter constant
+//scale the gyro
+#define GYRO_SCALE 2.7176 
+
+
+ /**
+  * Magnetometer
+  */
+#define AK8963_ADDRESS   0x0C<<1
+#define WHO_AM_I_AK8963  0x00 // should return 0x48
+#define INFO             0x01
+#define AK8963_ST1       0x02  // data ready status bit 0
+#define AK8963_XOUT_L    0x03  // data
+#define AK8963_XOUT_H    0x04
+#define AK8963_YOUT_L    0x05
+#define AK8963_YOUT_H    0x06
+#define AK8963_ZOUT_L    0x07
+#define AK8963_ZOUT_H    0x08
+#define AK8963_ST2       0x09  // Data overflow bit 3 and data read error status bit 2
+#define AK8963_CNTL      0x0A  // Power down (0000), single-measurement (0001), self-test (1000) and Fuse ROM (1111) modes on bits 3:0
+#define AK8963_ASTC      0x0C  // Self test control
+#define AK8963_I2CDIS    0x0F  // I2C disable
+#define AK8963_ASAX      0x10  // Fuse ROM x-axis sensitivity adjustment value
+#define AK8963_ASAY      0x11  // Fuse ROM y-axis sensitivity adjustment value
+#define AK8963_ASAZ      0x12  // Fuse ROM z-axis sensitivity adjustment value
+
+
+/** MPU9250 IMU library.
+  *
+  * Example:
+  * @code
+  * Later, maybe
+  * @endcode
+  */
+class MPU9250
+{
+public:
+    /**
+    * Constructor.
+    *
+    * Sleep mode of MPU9250 is immediatly disabled
+    *
+    * @param sda - mbed pin to use for the SDA I2C line.
+    * @param scl - mbed pin to use for the SCL I2C line.
+    */
+    MPU9250(PinName sda, PinName scl);
+    
+    
+    /**
+    * Tests the I2C connection by reading the WHO_AM_I register. 
+    *
+    * @return True for a working connection, false for an error
+    */     
+    bool testConnection( void );
+    
+    /**
+    * Sets the bandwidth of the digital low-pass filter 
+    *
+    * Macros: MPU9250_BW_256 - MPU9250_BW_188 - MPU9250_BW_98 - MPU9250_BW_42 - MPU9250_BW_20 - MPU9250_BW_10 - MPU9250_BW_5
+    * Last number is the gyro's BW in Hz (accelero BW is virtually identical)
+    *
+    * @param BW - The three bits that set the bandwidth (use the predefined macros)
+    */     
+    void setBW( char BW );
+    
+    /**
+    * Sets the auxiliary I2C bus in bypass mode to read the sensors behind the MPU9250 (useful for eval board, otherwise just connect them to primary I2C bus) 
+    *
+    * @param state - Enables/disables the I2C bypass mode
+    */     
+    void setI2CBypass ( bool state );
+    
+    /**
+    * Sets the Accelero full-scale range
+    *
+    * Macros: MPU9250_ACCELERO_RANGE_2G - MPU9250_ACCELERO_RANGE_4G - MPU9250_ACCELERO_RANGE_8G - MPU9250_ACCELERO_RANGE_16G
+    *
+    * @param range - The two bits that set the full-scale range (use the predefined macros)
+    */
+    void setAcceleroRange(char range);
+    
+    /**
+    * Reads the accelero x-axis.
+    *
+    * @return 16-bit signed integer x-axis accelero data
+    */   
+    int getAcceleroRawX( void );
+    
+    /**
+    * Reads the accelero y-axis.
+    *
+    * @return 16-bit signed integer y-axis accelero data
+    */   
+    int getAcceleroRawY( void );
+    
+    /**
+    * Reads the accelero z-axis.
+    *
+    * @return 16-bit signed integer z-axis accelero data
+    */   
+    int getAcceleroRawZ( void );
+    
+    /**
+    * Reads all accelero data.
+    *
+    * @param data - pointer to signed integer array with length three: data[0] = X, data[1] = Y, data[2] = Z
+    */   
+    void getAcceleroRaw( int *data );
+    
+    /**
+    * Reads all accelero data, gives the acceleration in m/s2
+    *
+    * Function uses the last setup value of the full scale range, if you manually set in another range, this won't work.
+    *
+    * @param data - pointer to float array with length three: data[0] = X, data[1] = Y, data[2] = Z
+    */   
+    void getAccelero( float *data );
+    
+    /**
+    * Sets the Gyro full-scale range
+    *
+    * Macros: MPU9250_GYRO_RANGE_250 - MPU9250_GYRO_RANGE_500 - MPU9250_GYRO_RANGE_1000 - MPU9250_GYRO_RANGE_2000
+    *
+    * @param range - The two bits that set the full-scale range (use the predefined macros)
+    */
+    void setGyroRange(char range);
+    
+    /**
+    * Reads the gyro x-axis.
+    *
+    * @return 16-bit signed integer x-axis gyro data
+    */   
+    int getGyroRawX( void );
+    
+    /**
+    * Reads the gyro y-axis.
+    *
+    * @return 16-bit signed integer y-axis gyro data
+    */   
+    int getGyroRawY( void );
+    
+    /**
+    * Reads the gyro z-axis.
+    *
+    * @return 16-bit signed integer z-axis gyro data
+    */   
+    int getGyroRawZ( void );
+    
+    /**
+    * Reads all gyro data.
+    *
+    * @param data - pointer to signed integer array with length three: data[0] = X, data[1] = Y, data[2] = Z
+    */   
+    void getGyroRaw( int *data );  
+    
+    /**
+    * Reads all gyro data, gives the gyro in rad/s
+    *
+    * Function uses the last setup value of the full scale range, if you manually set in another range, this won't work.
+    *
+    * @param data - pointer to float array with length three: data[0] = X, data[1] = Y, data[2] = Z
+    */   
+    void getGyro( float *data);
+    
+    /**
+    * Reads temperature data.
+    *
+    * @return 16 bit signed integer with the raw temperature register value
+    */  
+    int getTempRaw( void );
+    
+    /**
+    * Returns current temperature
+    *
+    * @returns float with the current temperature
+    */  
+    float getTemp( void );
+    
+    /**
+    * Sets the sleep mode of the MPU9250 
+    *
+    * @param state - true for sleeping, false for wake up
+    */     
+    void setSleepMode( bool state );
+    
+    
+    /**
+    * Writes data to the device, could be private, but public is handy so you can transmit directly to the MPU. 
+    *
+    * @param adress - register address to write to
+    * @param data - data to write
+    */
+    void write( char address, char data);
+    
+    /**
+    * Read data from the device, could be private, but public is handy so you can transmit directly to the MPU. 
+    *
+    * @param adress - register address to write to
+    * @return - data from the register specified by RA
+    */
+    char read( char adress);
+    
+    /**
+    * Read multtiple regigsters from the device, more efficient than using multiple normal reads. 
+    *
+    * @param adress - register address to write to
+    * @param length - number of bytes to read
+    * @param data - pointer where the data needs to be written to 
+    */
+    void read( char adress, char *data, int length);
+    
+    /**
+    * function for calculating the angle from the accelerometer.
+    * it takes 3 values which correspond acceleration in X, Y and Z direction and calculates angles in degrees
+    * for pitch, roll and one more direction.. (NOT YAW!)
+    *
+    * @param data - angle calculated using only accelerometer
+    *
+    */ 
+    void getAcceleroAngle( float *data );
+    
+    
+    /**function which allows to produce the offset values for gyro and accelerometer.
+    * offset for gyro is simply a value, which needs to be substracted from original gyro rad/sec speed
+    * but offset for accelerometer is calculated in angles... later on might change that
+    * function simply takes the number of samples to be taken and calculated the average
+    * 
+    * @param accOffset - accelerometer offset in angle
+    * @param gyroOffset - gyroscope offset in rad/s
+    * @param sampleSize - number of samples to be taken for calculating offsets
+    *
+    */
+    void getOffset(float *accOffset, float *gyroOffset, int sampleSize);
+    
+    /**
+    * function for computing the angle, when accelerometer angle offset and gyro offset are both known.
+    * we also need to know how much time passed from previous calculation to now
+    * it produces the angle in degrees. However angles are produced from -90.0 to 90.0 degrees
+    * if anyone need smth different, they can update this library...
+    *
+    * @param angle - calculated accurate angle from complemetary filter
+    * @param accOffset - offset in angle for the accelerometer
+    * @param gyroOffset - offset in rad/s for the gyroscope
+    * @param interval - time before previous angle calculation and now
+    *
+    */
+    void computeAngle (float *angle, float *accOffset, float *gyroOffset, float interval);
+    
+    ///function, which enables interrupts on MPU9250 INT pin
+    void enableInt( void );
+    
+    ///disables interrupts
+    void disableInt( void );
+    
+    /**function which sets the alpha value - constant for the complementary filter. default alpha = 0.97
+    *
+    * @param val - value the alpha (complementary filter constant) should be set to
+    *
+    */
+    void setAlpha(float val);
+    
+    ////////////////////////////////////////////////////////////////////////////
+    ////////////////////////////////////////////////////////////////////////////
+    ////////////////////////////////////////////////////////////////////////////
+    
+    /** Daqn added
+    * read bytes on specific address and subaddress.
+    *
+    * @param adress - register address to write to
+    * @param subadress - register address to write to
+    * @param length - number of bytes to read
+    * @param data - pointer where the data needs to be written to 
+    */
+    void read(char address, char subaddress, char *data, int length);
+    
+    /** Daqn added
+    * Sets the Magneto full-scale range
+    *
+    * Macros: MPU9250_MAGNETO_RANGE_250 - MPU9250_MAGNETO_RANGE_500 - MPU9250_MAGNETO_RANGE_1000 - MPU9250_MAGNETO_RANGE_2000
+    *
+    * @param range - The two bits that set the full-scale range (use the predefined macros)
+    */
+//    void setMagnetoRange(char range);
+    
+    /** Daqn added
+    * Reads the magnetometer x-axis.
+    *
+    * @return 16-bit signed integer x-axis magnetometer data
+    */   
+    int getMagnetoRawX( void );
+    
+    /** Daqn added
+    * Reads the magnetometer y-axis.
+    *
+    * @return 16-bit signed integer y-axis magnetometer data
+    */   
+    int getMagnetoRawY( void );
+    
+    /** Daqn added
+    * Reads the magnetometer z-axis.
+    *
+    * @return 16-bit signed integer z-axis magnetometer data
+    */   
+    int getMagnetoRawZ( void );
+    
+    /** Daqn added
+    * Reads all magnetometer data.
+    *
+    * @param data - pointer to signed integer array with length three: data[0] = X, data[1] = Y, data[2] = Z
+    */   
+    void getMagnetoRaw( int *data );  
+    
+    /** Daqn added
+    * Reads all magnetometer data, gives the magnetometer in [[[TBD]]]
+    *
+    * Function uses the last setup value of the full scale range, if you manually set in another range, this won't work.
+    *
+    * @param data - pointer to float array with length three: data[0] = X, data[1] = Y, data[2] = Z
+    */   
+    void getMagneto( float *data);
+    
+private:
+    
+    I2C connection;
+    char currentAcceleroRange;
+    char currentGyroRange;
+    float alpha;   
+
+};
+
+
+
+#endif
diff -r 000000000000 -r 2a7221ee9861 main.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/main.cpp	Wed Mar 21 07:58:57 2018 +0000
@@ -0,0 +1,293 @@
+#include "mbed.h"
+#include "MPU9250.h"
+#include "math.h"
+#include "Eigen/Core.h"     // 線形代数のライブラリ
+#include "Eigen/Geometry.h" // 同上
+#define  PI 3.141592654     // 円周率
+
+Timer       timer;
+Ticker      ticker;
+DigitalOut  led1(LED1);
+DigitalOut  led2(LED2);
+DigitalOut  led3(LED3);
+DigitalOut  led4(LED4);
+//InterruptIn flt_pin(p30);
+Serial      pc (USBTX, USBRX);
+MPU9250     mpu(p28,p27);
+
+const float t_calibrate = 25.f;
+const float dt = 0.05;
+
+// 変数用意
+int   N = 0;                // 較正に用いるサンプル数
+
+float gyro[3];              // ジャイロセンサの出力
+float b_gyro[3] = {};       // ジャイロセンサのバイアス誤差.
+float acc[3];               // 加速度センサの出力
+// float acc_norm;             // 加速度ベクトルの2-ノルム(長さ).
+float acc_normalized[3];    // 正規化した(長さ1の)加速度ベクトル.
+
+
+float pitch = 0.f;          // ピッチ角.
+float roll  = 0.f;          // バンク(ロール)角.
+float yaw;                  // 方位角(ヨー角).
+Eigen::Vector4f q;          // 姿勢クォータニオン
+Eigen::Matrix4f Omg;
+Eigen::Vector4f q_dot;
+float omg[3];
+float q00_22, q11_33;
+
+void calibrate();
+void set_initial_quaternion(float roll, float pitch);
+void flt_pin_rise();
+void flt_pin_fall();
+void update();
+void update_correction();
+
+int main()
+{
+    mpu.setAcceleroRange(MPU9250_ACCELERO_RANGE_16G);
+    mpu.setGyroRange(MPU9250_GYRO_RANGE_2000);
+    
+    led1 = 1;
+    led2 = 1;
+    led3 = 1;
+//    pc.printf("=\r\n\n");
+//    pc.printf("Calibration (%3.1f s) will start in\r\n  5\r\n", t_calibrate);
+    wait(1.0);
+//    pc.printf("  4\r\n");
+    wait(1.0);
+//    pc.printf("  3\r\n");
+    wait(1.0);
+//    pc.printf("  2\r\n");
+    wait(1.0);
+//    pc.printf("  1\r\n\n");
+    wait(1.0);
+    led1 = 0;
+//    pc.printf("Calibrating...  ");
+    ticker.attach(&calibrate, 0.01);
+    timer.start();
+    while (timer.read() < t_calibrate);
+    ticker.detach();
+//    pc.printf("Done. (%d samples)\r\n\n", N);
+//    timer.stop();
+    led2 = 0;
+    
+    b_gyro[0] /= N;
+    b_gyro[1] /= N;
+    b_gyro[2] /= N;
+    roll  /= N;
+    pitch /= N;
+    
+//    printf("Initial Attitude\r\n");
+//    printf("  bank:%6.1f deg,   pitch:%6.1f deg\r\n\n",
+//              roll*180/PI ,     pitch*180/PI);
+    
+    set_initial_quaternion(roll, pitch);
+    
+    led3 = 0;
+//    pc.printf("waiting for launch...\r\n");
+//    flt_pin.mode(PullUp);
+//    flt_pin.fall(&flt_pin_fall);
+//    flt_pin.rise(&flt_pin_rise);
+    ticker.attach(&update_correction, dt);
+    led4 = 1;
+    while(1);
+}
+
+void calibrate()
+{
+    //////////////////////////////////////
+    //                                  //
+    // ジャイロセンサの較正・初期姿勢角の取得 //
+    //                                  //
+    //////////////////////////////////////
+    
+    // b_gyro にはジャイロセンサの出力の平均(バイアス誤差)を格納.
+    mpu.getGyro(gyro);
+    b_gyro[0] += gyro[0];
+    b_gyro[1] += gyro[1];
+    b_gyro[2] += gyro[2];
+    
+    // 重力加速度ベクトルを使って,姿勢角を算出
+    mpu.getAccelero(acc);
+//    acc_norm = sqrt(acc[0]*acc[0]+acc[1]*acc[1]+acc[2]*acc[2]);
+
+//    acc_normalized[0] = acc[0] / acc_norm;
+//    acc_normalized[1] = acc[1] / acc_norm;
+//    acc_normalized[2] = acc[2] / acc_norm;
+    acc_normalized[2] = acc[2] / sqrt(acc[0]*acc[0]+acc[1]*acc[1]+acc[2]*acc[2]);
+    
+    // N 回の姿勢角の平均をとって初期姿勢角とする
+    pitch += asin (acc_normalized[2]);
+    roll  += atan2(acc[1], -acc[0]);
+    
+    // count up
+    N++;
+}
+
+void set_initial_quaternion(float roll, float pitch)
+{
+    /////////////////////////////////////////
+    //                                     //
+    // 初期姿勢角から初期姿勢クォータニオンを計算 //
+    //                                     //
+    /////////////////////////////////////////
+    float c_roll2 = cos(roll/2);      // 繰り返しの計算を避けるための一時変数
+    float s_roll2 = sin(roll/2);      // 同上
+    
+    Eigen::Matrix4f qx0_otimes;
+    qx0_otimes << c_roll2,-s_roll2,    0   ,    0   ,
+                  s_roll2, c_roll2,    0   ,    0   ,
+                     0   ,    0   , c_roll2, s_roll2,
+                     0   ,    0   ,-s_roll2, c_roll2;
+    
+    Eigen::Vector4f q_y0(cos(pitch/2), 0.f, sin(pitch/2), 0.f);
+    
+    // 初期姿勢クォータニオン q
+    q = qx0_otimes * q_y0;
+}
+
+void flt_pin_rise()
+{
+    pc.printf("Launch!\r\n");
+    ticker.attach(&update, dt);
+}
+
+void flt_pin_fall()
+{
+    pc.printf("fall.\r\n");
+    ticker.detach();
+}
+
+ /**
+  * 観測値を用いて姿勢角を更新します.
+  * ジャイロセンサの出力を単純に積算します.
+  */
+void update()
+{
+    mpu.getGyro(gyro);
+    
+    omg[0] =  gyro[2] - b_gyro[2];
+    omg[1] = -gyro[1] + b_gyro[1];
+    omg[2] =  gyro[0] - b_gyro[0];
+    
+    // 姿勢クォータニオンの時間微分を計算
+    Omg << 0.f   ,-omg[0],-omg[1],-omg[2],
+           omg[0], 0.f   , omg[2],-omg[1],
+           omg[1],-omg[2], 0.f   , omg[0],
+           omg[2], omg[1],-omg[0], 0.f   ;
+//    q_dot = 0.5f * Omg * q;
+    
+    // 現在時刻の姿勢クォータニオン
+    q += Omg * q * 0.5f * dt;
+    q /= sqrtf(q[0]*q[0]+q[1]*q[1]+q[2]*q[2]+q[3]*q[3]);
+    
+    // 姿勢クォータニオンからオイラー角への変換
+    q00_22 = (q[0] + q[2])*(q[0] - q[2]);
+    q11_33 = (q[1] + q[3])*(q[1] - q[3]);
+    roll  = atan2( 2*(q[2]*q[3]+q[0]*q[1]), q00_22 - q11_33);
+    pitch = asin (-2*(q[1]*q[3]-q[0]*q[2]));
+//    yaw   = atan2( 2*(q[1]*q[2]+q[0]*q[3]), q00_22 + q11_33);
+    
+//    pc.printf("%11.7f   ",timer.read());
+//    pc.printf("%6.1f %6.1f %6.1f\r\n",
+//               roll*180/PI,  pitch*180/PI,  yaw*180/PI);
+//    pc.printf("%6.1f %6.1f\r\n",
+//               roll*180/PI,  pitch*180/PI);
+}
+
+Eigen::Vector3f bB_tilde;
+Eigen::Vector3f bB_hat;
+Eigen::Vector3f bG(0.f, 0.f, -1.f);
+Eigen::Vector3f rot_vec;
+float rot_q[4] = {1.f, 0.f, 0.f, 0.f};
+Eigen::Matrix3f dcm;
+Eigen::Matrix4f rot_q_otimes;
+const float eps = 0.01;
+float q00, q01, q02, q03, q11, q12, q13, q22, q23, q33;
+float a_norm_div;
+float send_buff[4];
+char* send_bufc = (char*)send_buff;
+
+ /**
+  * 観測値を用いて姿勢角を更新します.
+  * ジャイロセンサの出力を積算した上で,加速度センサの出力を用いて補正します.
+  */
+void update_correction()
+{
+    mpu.getGyro(gyro);
+    
+    omg[0] =  gyro[2] - b_gyro[2];
+    omg[1] = -gyro[1] + b_gyro[1];
+    omg[2] =  gyro[0] - b_gyro[0];
+    
+    // 姿勢クォータニオンの時間微分を計算
+    Omg << 0.f   ,-omg[0],-omg[1],-omg[2],
+           omg[0], 0.f   , omg[2],-omg[1],
+           omg[1],-omg[2], 0.f   , omg[0],
+           omg[2], omg[1],-omg[0], 0.f   ;
+//    q_dot = 0.5f * Omg * q;
+    
+    // 現在時刻の姿勢クォータニオン
+    q += Omg * q * 0.5f * dt;
+    q /= sqrtf(q[0]*q[0]+q[1]*q[1]+q[2]*q[2]+q[3]*q[3]);
+    
+    // 姿勢クォータニオンからオイラー角への変換
+    q00 = q[0]*q[0];
+    q01 = q[0]*q[1];
+    q02 = q[0]*q[2];
+    q03 = q[0]*q[3];
+    q11 = q[1]*q[1];
+    q12 = q[1]*q[2];
+    q13 = q[1]*q[3];
+    q22 = q[2]*q[2];
+    q23 = q[2]*q[3];
+    q33 = q[3]*q[3];
+    dcm <<  q00+q11-q22-q33,   2*(q12+q03)  ,   2*(q13-q02)  ,
+              2*(q12-q03)  , q00-q11+q22-q33,   2*(q23+q01)  ,
+              2*(q13+q02)  ,   2*(q23-q01)  , q00-q11-q22+q33;
+    bB_hat = dcm*bG;
+    mpu.getAccelero(acc);
+    a_norm_div = 1.f / sqrt(acc[0]*acc[0] + acc[1]*acc[1] + acc[2]*acc[2]);
+    bB_tilde << acc[2]*a_norm_div,-acc[1]*a_norm_div, acc[0]*a_norm_div;
+    rot_vec = bB_hat.cross(bB_hat - bB_tilde);
+    rot_q[1] = 0.5f*eps*rot_vec[0];
+    rot_q[2] = 0.5f*eps*rot_vec[1];
+    rot_q[3] = 0.5f*eps*rot_vec[2];
+    rot_q_otimes <<   1.f   ,-rot_q[1],-rot_q[2],-rot_q[3],
+                    rot_q[1],   1.f   , rot_q[3],-rot_q[2],
+                    rot_q[2],-rot_q[3],   1.f   , rot_q[1],
+                    rot_q[3], rot_q[2],-rot_q[1],   1.f   ;
+    q = rot_q_otimes * q;
+//    q00 = q[0]*q[0];    // Note that these values are based on
+//    q11 = q[1]*q[1];    // rotated quatenion (L253), so they are diferent from
+//    q22 = q[2]*q[2];    // the values calculated above (L228-237).
+//    q33 = q[3]*q[3];
+//    q /= sqrtf(q00 + q11 + q22 + q33);
+    
+    q /= sqrtf(q[0]*q[0] + q[1]*q[1] + q[2]*q[2] + q[3]*q[3]);
+    send_buff[0] = q[0];
+    send_buff[1] = q[1];
+    send_buff[2] = q[2];
+    send_buff[3] = q[3];
+//    send_buff[0] = 0.1f;
+//    send_buff[1] = 0.2f;
+//    send_buff[2] = 0.3f;
+//    send_buff[3] = 0.4f;
+//    pc.write(send_buf,4);
+    pc.putc('\0');
+    for (int i = 0; i < 16; i++)
+        pc.putc(send_bufc[i]);
+//    q00_22 = q00 - q22;
+//    q11_33 = q11 - q33;
+//    roll  = atan2( 2*(q[2]*q[3]+q[0]*q[1]), q00_22 - q11_33);
+//    pitch = asin (-2*(q[1]*q[3]-q[0]*q[2]));
+//    yaw   = atan2( 2*(q[1]*q[2]+q[0]*q[3]), q00_22 + q11_33);
+    
+//    pc.printf("%11.7f   ",timer.read());
+//    pc.printf("%6.1f %6.1f %6.1f\r\n",
+//               roll*180/PI,  pitch*180/PI,  yaw*180/PI);
+//    pc.printf("%6.1f %6.1f\r\n",
+//               roll*180/PI,  pitch*180/PI);
+}
\ No newline at end of file
diff -r 000000000000 -r 2a7221ee9861 mbed.bld
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mbed.bld	Wed Mar 21 07:58:57 2018 +0000
@@ -0,0 +1,1 @@
+https://os.mbed.com/users/mbed_official/code/mbed/builds/aa5281ff4a02
\ No newline at end of file