Подключение MPU 9250

Тема в разделе "Arduino & Shields", создана пользователем Artclonic, 6 мар 2018.

  1. Artclonic

    Artclonic Гик

    Добрый день. В прошлои теме начал знакомство с магнитометром GY-273, разбирался несколько дней, с помощью гуру с форума, удалось подключить, записать данные, поанализировать. Решил далее замахнуться на более сложнныи модуль MPU 9250/6500 ( GY-6500.GY-9250).. Полазил в интернете нашел код. С подключением вроде все понятно (у меня UNO). Но все данные кроме (я так понимаю временнои характеристики - статичны). В мониторе значения не меняются...
    Вот код
    Код (C++):
    #include <Wire.h>
    #include <TimerOne.h>
    #define MPU9250_ADDRESS 0x68
    #define MAG_ADDRESS 0x0C
    #define GYRO_FULL_SCALE_250_DPS 0x00
    #define GYRO_FULL_SCALE_500_DPS 0x08
    #define GYRO_FULL_SCALE_1000_DPS 0x10
    #define GYRO_FULL_SCALE_2000_DPS 0x18
    #define ACC_FULL_SCALE_2_G 0x00
    #define ACC_FULL_SCALE_4_G 0x08
    #define ACC_FULL_SCALE_8_G 0x10
    #define ACC_FULL_SCALE_16_G 0x18
    // This function read Nbytes bytes from I2C device at address Address.
    // Put read bytes starting at register Register in the Data array.
    void I2Cread(uint8_t Address, uint8_t Register, uint8_t Nbytes, uint8_t* Data)
        {
          // Set register address
          Wire.beginTransmission(Address);
          Wire.write(Register);
          Wire.endTransmission();
          // Read Nbytes
          Wire.requestFrom(Address, Nbytes);
          uint8_t index=0;
          while (Wire.available())
          Data[index++]=Wire.read();
        }
    // Write a byte (Data) in device (Address) at register (Register)
    void I2CwriteByte(uint8_t Address, uint8_t Register, uint8_t Data)
        {
          // Set register address
          Wire.beginTransmission(Address);
          Wire.write(Register);
          Wire.write(Data);
          Wire.endTransmission();
        }
    // Initial time
    long int ti;
    volatile bool intFlag=false;
    // Initializations
    void setup()
        {
          // Arduino initializations
          Wire.begin();
          Serial.begin(115200);
          // Set accelerometers low pass filter at 5Hz
          I2CwriteByte(MPU9250_ADDRESS,29,0x06);
          // Set gyroscope low pass filter at 5Hz
          I2CwriteByte(MPU9250_ADDRESS,26,0x06);
          // Configure gyroscope range
          I2CwriteByte(MPU9250_ADDRESS,27,GYRO_FULL_SCALE_1000_DPS);
          // Configure accelerometers range
          I2CwriteByte(MPU9250_ADDRESS,28,ACC_FULL_SCALE_4_G);
          // Set by pass mode for the magnetometers
          I2CwriteByte(MPU9250_ADDRESS,0x37,0x02);
          // Request continuous magnetometer measurements in 16 bits
          I2CwriteByte(MAG_ADDRESS,0x0A,0x16);
          pinMode(13, OUTPUT);
          Timer1.initialize(10000); // initialize timer1, and set a 1/2 second period
          Timer1.attachInterrupt(callback); // attaches callback() as a timer overflow interrupt
          // Store initial time
          ti=millis();
        }
    // Counter
    long int cpt=0;
    void callback()
        {
          intFlag=true;
          digitalWrite(13, digitalRead(13) ^ 1);
        }
    // Main loop, read and display data
    void loop()
        {
          while (!intFlag);
          intFlag=false;
          // Display time
          Serial.print (millis()-ti,DEC);
          Serial.print ("\t");
          // _______________
          // ::: Counter :::
          // Display data counter
          // Serial.print (cpt++,DEC);
          // Serial.print ("\t");
          // ____________________________________
          // ::: accelerometer and gyroscope :::
          // Read accelerometer and gyroscope
          uint8_t Buf[14];
          I2Cread(MPU9250_ADDRESS,0x3B,14,Buf);
          // Create 16 bits values from 8 bits data
          // Accelerometer
          int16_t ax=-(Buf[0]<<8 | Buf[1]);
          int16_t ay=-(Buf[2]<<8 | Buf[3]);
          int16_t az=Buf[4]<<8 | Buf[5];
          // Gyroscope
          int16_t gx=-(Buf[8]<<8 | Buf[9]);
          int16_t gy=-(Buf[10]<<8 | Buf[11]);
          int16_t gz=Buf[12]<<8 | Buf[13];
          // Display values
         // Accelerometer
         Serial.print (ax,DEC);
         Serial.print ("\t");
         Serial.print (ay,DEC);
         Serial.print ("\t");
         Serial.print (az,DEC);
         Serial.print ("\t");
         // Gyroscope
         Serial.print (gx,DEC);
         Serial.print ("\t");
         Serial.print (gy,DEC);
         Serial.print ("\t");
         Serial.print (gz,DEC);
         Serial.print ("\t");
         // _____________________
         // ::: Magnetometer :::
         // Read register Status 1 and wait for the DRDY: Data Ready
         uint8_t ST1;
         do
             {
               I2Cread(MAG_ADDRESS,0x02,1,&ST1);
             }
         while (!(ST1&0x01));
         // Read magnetometer data
         uint8_t Mag[7];
         I2Cread(MAG_ADDRESS,0x03,7,Mag);
         // Create 16 bits values from 8 bits data
         // Magnetometer
         int16_t mx=-(Mag[3]<<8 | Mag[2]);
         int16_t my=-(Mag[1]<<8 | Mag[0]);
         int16_t mz=-(Mag[5]<<8 | Mag[4]);
         // Magnetometer
         Serial.print (mx+200,DEC);
         Serial.print ("\t");
         Serial.print (my-70,DEC);
         Serial.print ("\t");
         Serial.print (mz-700,DEC);
         Serial.print ("\t");
         // End of line
         Serial.println("");
         // delay(100);
       }
    А вот
    что в мониторе
    8580 4242 2989 -2565 10273 16396 -2151 -30997 12288 31713
    8590 4242 2989 -2565 10273 16396 -2151 -30997 12288 31713
    8600 4242 2989 -2565 10273 16396 -2151 -30997 12288 31713
    8609 4242 2989 -2565 10273 16396 -2151 -30997 12288 31713
    8620 4242 2989 -2565 10273 16396 -2151 -30997 12288 31713
    8630 4242 2989 -2565 10273 16396 -2151 -30997 12288 31713
    8640 4242 2989 -2565 10273 16396 -2151 -30997 12288 31713
    8649 4242 2989 -2565 10273 16396 -2151 -30997 12288 31713
    8659 4242 2989 -2565 10273 16396 -2151 -30997 12288 31713
    8670 4242 2989 -2565 10273 16396 -2151 -30997 12288 31713
    8680 4242 2989 -2565 10273 16396 -2151 -30997 12288 31713
    8690 4242 2989 -2565 10273 16396 -2151 -30997 12288 31713
    8699 4242 2989 -2565 10273 16396 -2151 -30997 12288 31713
    8710 4242 2989 -2565 10273 16396 -2151 -30997 12288 31713
    8720 4242 2989 -2565 10273 16396 -2151 -30997 12288 31713
    8730 4242 2989 -2565 10273 16396 -2151 -30997 12288 31713
    8739 4242 2989 -2565 10273 16396 -2151 -30997 12288 31713
    8750 4242 2989 -2565 10273 16396 -2151 -30997 12288 31713
    8760 4242 2989 -2565 10273 16396 -2151 -30997 12288 31713
    8770 4242 2989 -2565 10273 16396 -2151 -30997 12288 31713
    8779 4242 2989 -2565 10273 16396 -2151 -30997 12288 31713
    8790 4242 2989 -2565 10273 16396 -2151 -30997 12288 31713
    8800 4242 2989 -2565 10273 16396 -2151 -30997 12288 31713
    8810 4242 2989 -2565 10273 16396 -2151 -30997 12288 31713
    8820 4242 2989 -2565 10273 16396 -2151 -30997 12288 31713
     
  2. Sencis

    Sencis Нерд

    Вот код которым я запускал MPU 9250. Сразу отмечу у меня AD0 не заземлён и датчик 10DOF т.е. с барометром на 9DOF не проверял но должен работать.

    Код (C++):
    #include <Wire.h>

    #define    MPU9250_ADDRESS            0x68 // Адресс MPU 9250 если подкл AD0 может быть 0x69
    #define    MAG_ADDRESS                0xC
    #define AK8963_ADDRESS                0xC
    #define AK8963_ST1                    0x02

    #define    GYRO_FULL_SCALE_250_DPS    0x00
    #define    GYRO_FULL_SCALE_500_DPS    0x08
    #define    GYRO_FULL_SCALE_1000_DPS   0x10
    #define    GYRO_FULL_SCALE_2000_DPS   0x18

    #define    ACC_FULL_SCALE_2_G        0x00
    #define    ACC_FULL_SCALE_4_G        0x08
    #define    ACC_FULL_SCALE_8_G        0x10
    #define    ACC_FULL_SCALE_16_G       0x18
    #define    Pi                        3,1415926

    #define WHO_AM_I_MPU9250             0x75  // Точно уже не помню но помойму ещё может быть 0x73 или 0x71


    enum Mscale {
      MFS_14BITS = 0, // 0.6 mG per LSB
      MFS_16BITS      // 0.15 mG per LSB
    };

    uint8_t Mmode = 0x06;
    uint8_t Mscale = MFS_16BITS;
    float aRes, gRes, mRes;


    float X ;
    float Y ;
    float Z ;



    void getMres() {
      switch (Mscale)
      {
      // Possible magnetometer scales (and their register bit settings) are:
      // 14 bit resolution (0) and 16 bit resolution (1)
        case MFS_14BITS:
              mRes = 10.*4912./8190.; // Proper scale to return milliGauss
              break;
        case MFS_16BITS:
              mRes = 10.*4912./32760.0; // Proper scale to return milliGauss
              break;
      }
    }

    // This function read Nbytes bytes from I2C device at address Address.
    // Put read bytes starting at register Register in the Data array.
    void I2Cread(uint8_t Address, uint8_t Register, uint8_t Nbytes, uint8_t* Data)
    {
      // Set register address
      Wire.beginTransmission(Address);
      Wire.write(Register);
      Wire.endTransmission(false);

      // Read Nbytes
      Wire.requestFrom(Address, Nbytes);
      uint8_t index=0;
      while (Wire.available())
        Data[index++]=Wire.read();
    }


    // Write a byte (Data) in device (Address) at register (Register)
    void I2CwriteByte(uint8_t Address, uint8_t Register, uint8_t Data)
    {
      // Set register address
      Wire.beginTransmission(Address);
      Wire.write(Register);
      Wire.write(Data);
      Wire.endTransmission();
    }


    float xv, yv, zv;

    //calibrated_values[3] is the global array where the calibrated data will be placed
    //calibrated_values[3]: [0]=Xc, [1]=Yc, [2]=Zc
    float calibrated_values[3];
    //transformation(float uncalibrated_values[3]) is the function of the magnetometer data correction
    //uncalibrated_values[3] is the array of the non calibrated magnetometer data
    //uncalibrated_values[3]: [0]=Xnc, [1]=Ync, [2]=Znc
    void transformation(float uncalibrated_values[3])
    {
      //calibration_matrix[3][3] is the transformation matrix
      //replace M11, M12,..,M33 with your transformation matrix data
      double calibration_matrix[3][3] =
      {
        {2195.878755, -32.093680, 6.147725},// Матрица калибровки для каждого датчика своя!
        {-32.093680, 2372.162687, -7.654780},
        {6.147725, -7.654780, 2407.630918}
      };
      //bias[3] is the bias
      //replace Bx, By, Bz with your bias data
      double bias[3] =
      {
        0.189463,
        -0.176225,
        0.127606
      };
      //calculation
      for (int i=0; i<3; ++i) uncalibrated_values[i] = uncalibrated_values[i] - bias[i];
      float result[3] = {0, 0, 0};
      for (int i=0; i<3; ++i)
        for (int j=0; j<3; ++j)
          result[i] += calibration_matrix[i][j] * uncalibrated_values[j];
      for (int i=0; i<3; ++i) calibrated_values[i] = result[i];
    }

    //vector_length_stabilasation() - is the function of the magnetometer vector length stabilasation (stabilisation of the sphere radius)
    float scaler;
    boolean scaler_flag = false;
    float normal_vector_length;
    void vector_length_stabilasation(){
      //calculate the normal vector length
      if (scaler_flag == false)
      {
        getHeading();
        normal_vector_length = sqrt(calibrated_values[0]*calibrated_values[0] + calibrated_values[1]*calibrated_values[1] + calibrated_values[2]*calibrated_values[2]);
        scaler_flag = true;
      }
      //calculate the current scaler
      scaler = normal_vector_length/sqrt(calibrated_values[0]*calibrated_values[0] + calibrated_values[1]*calibrated_values[1] + calibrated_values[2]*calibrated_values[2]);
      //apply the current scaler to the calibrated coordinates (global array calibrated_values)
      calibrated_values[0] = calibrated_values[0]*scaler;
      calibrated_values[1] = calibrated_values[1]*scaler;
      calibrated_values[2] = calibrated_values[2]*scaler;
    }
     
    К слову к этому датчику есть неплохой кватернионный фильтр для получения более менее достоверных углов ориентации (тонгаж, крен, рысканье).
     
  3. Artclonic

    Artclonic Гик

    Ругается
    С:\Users\Киселев Антон\Desktop\ГУСЕНР?ЦА\MPU9250\MPU9250\MPU9250.ino: In function 'void vector_length_stabilasation()':

    MPU9250:123: error: 'getHeading' was not declared in this scope

    exit status 1
    'getHeading' was not declared in this scope
     
  4. Sencis

    Sencis Нерд

    Пардон не всё выбрал)))

    Код (C++):
    #include <Wire.h>

    #define    MPU9250_ADDRESS            0x68
    #define    MAG_ADDRESS                0xC
    #define AK8963_ADDRESS                0xC
    #define AK8963_ST1                    0x02

    #define    GYRO_FULL_SCALE_250_DPS    0x00
    #define    GYRO_FULL_SCALE_500_DPS    0x08
    #define    GYRO_FULL_SCALE_1000_DPS   0x10
    #define    GYRO_FULL_SCALE_2000_DPS   0x18

    #define    ACC_FULL_SCALE_2_G        0x00
    #define    ACC_FULL_SCALE_4_G        0x08
    #define    ACC_FULL_SCALE_8_G        0x10
    #define    ACC_FULL_SCALE_16_G       0x18
    #define    Pi                        3,1415926

    #define WHO_AM_I_MPU9250             0x75


    enum Mscale {
      MFS_14BITS = 0, // 0.6 mG per LSB
      MFS_16BITS      // 0.15 mG per LSB
    };

    uint8_t Mmode = 0x06;
    uint8_t Mscale = MFS_16BITS;
    float aRes, gRes, mRes;


    float X ;
    float Y ;
    float Z ;



    void getMres() {
      switch (Mscale)
      {
      // Possible magnetometer scales (and their register bit settings) are:
      // 14 bit resolution (0) and 16 bit resolution (1)
        case MFS_14BITS:
              mRes = 10.*4912./8190.; // Proper scale to return milliGauss
              break;
        case MFS_16BITS:
              mRes = 10.*4912./32760.0; // Proper scale to return milliGauss
              break;
      }
    }

    // This function read Nbytes bytes from I2C device at address Address.
    // Put read bytes starting at register Register in the Data array.
    void I2Cread(uint8_t Address, uint8_t Register, uint8_t Nbytes, uint8_t* Data)
    {
      // Set register address
      Wire.beginTransmission(Address);
      Wire.write(Register);
      Wire.endTransmission(false);

      // Read Nbytes
      Wire.requestFrom(Address, Nbytes);
      uint8_t index=0;
      while (Wire.available())
        Data[index++]=Wire.read();
    }


    // Write a byte (Data) in device (Address) at register (Register)
    void I2CwriteByte(uint8_t Address, uint8_t Register, uint8_t Data)
    {
      // Set register address
      Wire.beginTransmission(Address);
      Wire.write(Register);
      Wire.write(Data);
      Wire.endTransmission();
    }


    float xv, yv, zv;

    //calibrated_values[3] is the global array where the calibrated data will be placed
    //calibrated_values[3]: [0]=Xc, [1]=Yc, [2]=Zc
    float calibrated_values[3];
    //transformation(float uncalibrated_values[3]) is the function of the magnetometer data correction
    //uncalibrated_values[3] is the array of the non calibrated magnetometer data
    //uncalibrated_values[3]: [0]=Xnc, [1]=Ync, [2]=Znc
    void transformation(float uncalibrated_values[3])  
    {
      //calibration_matrix[3][3] is the transformation matrix
      //replace M11, M12,..,M33 with your transformation matrix data
      double calibration_matrix[3][3] =
      {
        {2195.878755, -32.093680, 6.147725},// Матрица пока не верная но уже работает!
        {-32.093680, 2372.162687, -7.654780},
        {6.147725, -7.654780, 2407.630918}
      };
      //bias[3] is the bias
      //replace Bx, By, Bz with your bias data
      double bias[3] =
      {
        0.189463,
        -0.176225,
        0.127606
      };
      //calculation
      for (int i=0; i<3; ++i) uncalibrated_values[i] = uncalibrated_values[i] - bias[i];
      float result[3] = {0, 0, 0};
      for (int i=0; i<3; ++i)
        for (int j=0; j<3; ++j)
          result[i] += calibration_matrix[i][j] * uncalibrated_values[j];
      for (int i=0; i<3; ++i) calibrated_values[i] = result[i];
    }

    //vector_length_stabilasation() - is the function of the magnetometer vector length stabilasation (stabilisation of the sphere radius)
    float scaler;
    boolean scaler_flag = false;
    float normal_vector_length;
    void vector_length_stabilasation(){
      //calculate the normal vector length
      if (scaler_flag == false)
      {
        getHeading();
        normal_vector_length = sqrt(calibrated_values[0]*calibrated_values[0] + calibrated_values[1]*calibrated_values[1] + calibrated_values[2]*calibrated_values[2]);
        scaler_flag = true;
      }
      //calculate the current scaler
      scaler = normal_vector_length/sqrt(calibrated_values[0]*calibrated_values[0] + calibrated_values[1]*calibrated_values[1] + calibrated_values[2]*calibrated_values[2]);
      //apply the current scaler to the calibrated coordinates (global array calibrated_values)
      calibrated_values[0] = calibrated_values[0]*scaler;
      calibrated_values[1] = calibrated_values[1]*scaler;
      calibrated_values[2] = calibrated_values[2]*scaler;
    }

    // Initializations
    void setup()
    {
      // Arduino initializations
      Wire.begin();
      Serial.begin(115200);

      // Configure gyroscope range
      I2CwriteByte(MPU9250_ADDRESS,27,GYRO_FULL_SCALE_2000_DPS);
      // Configure accelerometers range
      I2CwriteByte(MPU9250_ADDRESS,28,ACC_FULL_SCALE_16_G);
      // Set by pass mode for the magnetometers
      I2CwriteByte(MPU9250_ADDRESS,0x37,0x02);

      // Request first magnetometer single measurement
      I2CwriteByte(MAG_ADDRESS,0x0A,Mscale << 4 | Mmode );//Mscale << 4 | Mmode

    }


    long int cpt=0;
    // Main loop, read and display data
    void loop()
    {

      // _______________
      // ::: Counter :::

      // Display data counter
      //Serial.print (cpt++,DEC);
      //Serial.print ("\t");

      // ____________________________________
      // :::  accelerometer and gyroscope :::

      // Read accelerometer and gyroscope
      uint8_t Buf[14];
      I2Cread(MPU9250_ADDRESS,0x3B,14,Buf);


      // Create 16 bits values from 8 bits data

      // Accelerometer
      int16_t ax=-(Buf[0]<<8 | Buf[1]);
      int16_t ay=-(Buf[2]<<8 | Buf[3]);
      int16_t az=Buf[4]<<8 | Buf[5];

      // Gyroscope
      int16_t gx=-(Buf[8]<<8 | Buf[9]);
      int16_t gy=-(Buf[10]<<8 | Buf[11]);
      int16_t gz=Buf[12]<<8 | Buf[13];

        // Display values

       //Accelerometer
      //Serial.print ("Значения акселерометра");
      //Serial.print ("\t");
      //Serial.print (ax,DEC);
      //Serial.print ("\t");
      //Serial.print (ay,DEC);
      //Serial.print ("\t");
      //Serial.print (az,DEC);
      //Serial.print ("\t");

       //Gyroscope
      //Serial.print ("Значения гироскопа");
      //Serial.print ("\t");
      //Serial.print (gx,DEC);
      //Serial.print ("\t");
      //Serial.print (gy,DEC);
      //Serial.print ("\t");
      //Serial.print (gz,DEC);
      //Serial.print ("\t");


      // _____________________
      // :::  Magnetometer :::



       //Read register Status 1 and wait for the DRDY: Data Ready

      //uint8_t ST1;
      //do
      //{
       // I2Cread(MAG_ADDRESS,0x02,1,&ST1);
      //}
         // while (!(ST1&0x01));

       

      if(readByte(MAG_ADDRESS, 0x02)& 0x01); {
      // Read magnetometer data
      uint8_t Mag[7];
      //readBytes(AK8963_ADDRESS, 0x03, 7, &Mag[0]);

      I2Cread(MAG_ADDRESS,0x03,7,&Mag[0]);

      uint8_t c = Mag[6];

    if(!(c & 0x08)) { // Check if magnetic sensor overflow set, if not then report data
       
     
      // Create 16 bits values from 8 bits data

      // Magnetometer
      int16_t mx=-(Mag[3]<<8 | Mag[2]);
      int16_t my=-(Mag[1]<<8 | Mag[0]);
      int16_t mz=-(Mag[5]<<8 | Mag[4]);





      X = mx;
      Y = my;
      Z = mz;





    //float values_from_magnetometer[3];

    // getHeading();
    // values_from_magnetometer[0] = xv;
      //values_from_magnetometer[1] = yv;
      //values_from_magnetometer[2] = zv;
      //transformation(values_from_magnetometer);

      //vector_length_stabilasation();

      //Serial.flush();
      //Serial.print(calibrated_values[0]);
      //Serial.print(",");
    // Serial.print(calibrated_values[1]);
      //Serial.print(",");
      //Serial.print(calibrated_values[2]);
    // Serial.println();

    // delay(100);



      // Magnetometer
      //Serial.print ("Значения магнитометра");
      //Serial.print ("\t");
      Serial.print (X ,DEC);
      Serial.print ("\t");
      Serial.println (Y ,DEC);
      Serial.println ("\t");
      Serial.print (Z ,DEC);
      Serial.print ("\t");
      Serial.print ( Mscale << 4 | Mmode ,DEC);
      Serial.print ("\t");

    // Serial.print (mx,DEC);
      //Serial.print ("\t");
      //Serial.println (my ,DEC);
      //Serial.println ("\t");
      //Serial.print (mz,DEC);
      //Serial.print ("\t");
      }

      }


      // End of line
      //Serial.println("");
    delay(100);  
    }

    uint8_t readByte(uint8_t address, uint8_t subAddress)
    {
      uint8_t data; // `data` will store the register data
      Wire.beginTransmission(address);         // Initialize the Tx buffer
      Wire.write(subAddress);                  // Put slave register address in Tx buffer
      Wire.endTransmission(false);             // Send the Tx buffer, but send a restart to keep connection alive
      Wire.requestFrom(address, (uint8_t) 1);  // Read one byte from slave register address
      data = Wire.read();                      // Fill Rx buffer with result
      return data;                             // Return data read from slave register
    }

    void getHeading()
    {

      xv = X;
      yv = Y;
      zv = Z;
    }
     
    Последнее редактирование: 6 мар 2018
  5. evpozdniakov

    evpozdniakov Нуб

    Я извиняюсь. Ищу информацию. Можно ли с помощью MPU-9250 получить 3D координаты (относительные)?
     
  6. Sencis

    Sencis Нерд

    С ваших слов не понятно какие именно вам нужны координаты, с помощью MPU 9250 можно получить ориентацию в пространстве и решать такие проблемы как: стабилизация (будь то камера или самолёт), инерциальная навигация конечно точность такой навигации оставляет желать лучшего но благодаря магнитометру на курс мы можем положится, и используя по отдельности компоненты модуля можно получить, датчик удара, измерить ускорение, силу магнитного поля (геологи исп. магнитометр для отслеживания месторождения руды по магнитным аномалиям), отдельные датчики оснащены барометром могут мерить температуру, давление и соответственно высоту.
     
  7. Artclonic

    Artclonic Гик

    Да тоже интересна в даннои реализации на ардуино только..(потихонечку изучаю, осмысливаю)
    http://x-io.co.uk/gait-tracking-with-x-imu/ (но это отдельная тема...)

    Закачал новыи код... в мониторе вот эти значени..(они меняются,) кроме "22"
    Это значения магнитометра я ж правильно мыслю? (что такое 22...?)
    А как данные с гироскопа и акселерометра считать? Или значения гироскопа и акселерометра закомментированны и их надо расскомменттировать? И надо ли подключать дополнительные пины? (сеичас только 4 шт подключены)

    -58.0000000000 22 -118.0000000000 -204.0000000000

    -44.0000000000 22 -119.0000000000 -191.0000000000

    -63.0000000000 22 -94.0000000000 -160.0000000000

    -60.0000000000 22 -64.0000000000 -152.0000000000

    -42.0000000000 22 -2.0000000000 -128.0000000000

    10.0000000000 22 -2.0000000000 -126.0000000000

    6.0000000000 22 2.0000000000 -132.0000000000

    0.0000000000 22 -4.0000000000 -128.0000000000

    4.0000000000 22 -6.0000000000 -126.0000000000

    14.0000000000 22 3.0000000000 -129.0000000000

    15.0000000000 22 -11.0000000000 -123.0000000000

    11.0000000000 22 5.0000000000 -123.0000000000
     
    Последнее редактирование: 9 мар 2018
  8. Artclonic

    Artclonic Гик

    Ну вот вроде запустил...Почему то значение магнетометра разбилось.. первыи столбец и последние два... Не поиму почему так? И что такое 22? Все же? И это тоже не понятно, что за параметр? Serial.print ( Mscale << 4 | Mmode ,DEC);
    Код (C++):

    -120.0000000000    22    Значения акселерометра    -494    -33    2124    Значения гироскопа    -89    -22    11    Значения магнитометра    -253.0000000000    -25.0000000000

    -113.0000000000    22    Значения акселерометра    -489    -31    2123    Значения гироскопа    -93    -19    13    Значения магнитометра    -244.0000000000    -24.0000000000

    -120.0000000000    22    Значения акселерометра    -507    -24    2107    Значения гироскопа    -86    5    11    Значения магнитометра    -245.0000000000    -35.0000000000

    -125.0000000000    22    Значения акселерометра    -478    -8    2119    Значения гироскопа    -95    -62    19    Значения магнитометра    -241.0000000000    -29.0000000000

    -119.0000000000    22    Значения акселерометра    -486    -53    2119    Значения гироскопа    -90    -155    12    Значения магнитометра    -241.0000000000    -23.0000000000

    -119.0000000000    22    Значения акселерометра    -507    -32    2101    Значения гироскопа    -90    66    7    Значения магнитометра    -240.0000000000    -32.0000000000

    -126.0000000000    22    Значения акселерометра    -507    -16    2138    Значения гироскопа    -91    87    11    Значения магнитометра    -247.0000000000    -29.0000000000

    -111.0000000000    22    Значения акселерометра    -476    4    2126    Значения гироскопа    -92    -74    11    Значения магнитометра    -260.0000000000    -24.0000000000
     
    Вроде исправил
    Код (C++):
    Значения акселерометра    24    27    2175    Значения гироскопа    -85    -25    16    Значения магнитометра    -282.0000000000    -92.0000000000    -20.0000000000  
    Значения акселерометра    22    22    2179    Значения гироскопа    -86    -26    14    Значения магнитометра    -282.0000000000    -94.0000000000    -16.0000000000  
    Значения акселерометра    39    20    2166    Значения гироскопа    -88    -27    18    Значения магнитометра    -279.0000000000    -91.0000000000    -25.0000000000  
    Значения акселерометра    29    24    2165    Значения гироскопа    -89    -23    15    Значения магнитометра    -274.0000000000    -88.0000000000    -20.0000000000  
    Значения акселерометра    29    12    2171    Значения гироскопа    -89    -23    17    Значения магнитометра    -276.0000000000    -90.0000000000    -28.0000000000  
    Значения акселерометра    37    21    2156    Значения гироскопа    -87    -26    15    Значения магнитометра    -277.0000000000    -89.0000000000    -23.0000000000  
    Значения акселерометра    41    18    2166    Значения гироскопа    -92    -23    16    Значения магнитометра    -274.0000000000    -88.0000000000    -20.0000000000  
    Значения акселерометра    25    19    2179    Значения гироскопа    -91    -22    16    Значения магнитометра    -273.0000000000    -95.0000000000    -19.0000000000  
    Значения акселерометра    34    12    2170    Значения гироскопа    -89    -24    13    Значения магнитометра    -277.0000000000    -81.0000000000    -21.0000000000  
    Значения акселерометра    25    21    2167    Значения гироскопа    -90    -26    14    Значения магнитометра    -275.0000000000    -91.0000000000    -19.0000000000  
    Значения акселерометра    20    11    2171    Значения гироскопа    -86    -24    19    Значения магнитометра    -270.0000000000    -96.0000000000    -14.0000000000  
    Значения акселерометра    34    17    2171    Значения гироскопа    -89    -21    15    Значения магнитометра    -281.0000000000    -95.0000000000    -27.0000000000  
    Значения акселерометра    23    13    2163    Значения гироскопа    -92    -24    16    Значения магнитометра    -275.0000000000    -91.0000000000    -21.0000000000  
    Значения акселерометра    24    6    2177    Значения гироскопа    -96    -21    17    Значения магнитометра    -278.0000000000    -88.0000000000    -22.0000000000    
    Тут вот какое дело, подключил "Serial Oscilloscope" и вижу, что акселерометр и гироскопом - перепутаны на мо взгляд. Диаграмма, где прямая возвращается на искомое значение после поворота - это же реакция на ускорение - акселерометр, а вот граик гироскопа - остался после поворота..Определил угол наклона..
     
    Последнее редактирование: 9 мар 2018
  9. Sencis

    Sencis Нерд

    22 Это мои опыты (Serial.print ( Mscale << 4 | Mmode ,DEC) с режимом работы (частота вывода данных помойму) не берите в голову я уже и сам не помню, что тогда происходило))) дополнительные пины подключать не надо по крайней мере если вы не используете прерывания. "Serial Oscilloscope" никогда не пользовался ничего сказать не могу. Вы лучше напишите, что вы хотите сделать а иначе не понятно в каком ключе вообще идёт разговор а там уже разберёмся.
     
    Последнее редактирование: 9 мар 2018
  10. Artclonic

    Artclonic Гик

    Я понял про 22 -убрал уже... Хочу сделать некии деваис, которыи мерил напряженность магнитного поля в трех осях, казалось бы есть магнитометр, которыи это и делает. Но напряженности есть зависимость от направлении вектора магнитного поля. Иными словами есть зависимрсть от поворота вокруг осеи. При помощи гироскопа можно измерить углы отклонении. Задумка такая - если ввести некии градиент (разницу между показателями магнитометра и углом вдоль оси, привидя ее к одинаковым размерностям). Т.е. куда не поверни - данная разница будет постояннои, кроме случая если нет вмешательства инородного источника (или объекта, которы отклоняет магнитное поле, так сказать анамалия).
     
  11. Sencis

    Sencis Нерд

    Я подобным я не занимался мах могу посоветовать скетч компенсации наклона но он для компаса, впрочем возможно его принцип работы натолкнёт на умную мысль. На крайний случай можно сделать гироскопически-стабилизированную платформу установить на неё магнитометр и измерять))).
     
  12. Artclonic

    Artclonic Гик

    Начал некоторыи анализ. Произвел записи по всем осям.Сделал 6 деиствии вокруг каждои (XYZ) оси повернул модуль, туда/обратно на 360 град. с паузами (состояния покоя) Построил графики...
    Почему то вокруг оси z показания от других осей отличается? Их почти нет... (кроме акселерометра)
    Как определить какие ограничения в показателях у гироскопа и магнитометра? (-2200/+2200 и -500/+500, соответственно)?
    Видна ли зависимость "стратегическая"? показании магнитометра от наклонов вдоль осей?
    Какие переменные в скетче (вышеуказанном) - еще без учета коррекционнои матрицы?

    upload_2018-3-10_14-55-49.png

    Или все же нужно для начало использовать отильтрованно/калиброванные данные с гироскопа и акселерометра (фильтр Калмана и Mэджика) и только потом сравнивать полученные углы (крен рыскание тангаж) с данными магнитометра?
    Есть несколько видео, где вроде используется для определения крена рыскания тангажа (а я так понимаю углов наклона вокруг осеи) все три датчика (аксель, гироск, магнитом). Где бы раздабыть этот код на MPU 9250? (тогда эти углы можно будет сравнивать с "девственными" (не обработанными) показаниями магнитометра. Единственное, наверное нужна какая ни будь калибровка в строну совпадения осеи всех трех чипов....
     
    Последнее редактирование: 10 мар 2018
  13. Sencis

    Sencis Нерд

    "Почему то вокруг оси z показания от других осей отличается?" - Вектор магнитного поля берётся по 2м осям X и Y на эти осях сама большая составляющая магнитного поля в прочем чем ближе к северному магнитному полюсу она уходит в Z сразу отмечу что оси магнитометра не совпадают с осями гироскопа и акселерометра.

    "Как определить какие ограничения в показателях у гироскопа и магнитометра?" - в даташите надо смотреть.

    "Видна ли зависимость "стратегическая"? показании магнитометра от наклонов вдоль осей?" - не совсем понятен термин "стратегическая" но скажу так в зависимости от наклона магнитометра магнитный вектор уходит в другую плоскость. Так если у нас X and Y параллельны поверхности земли то при наклоне она уходит от X на ось Z.

    "Какие переменные в скетче (вышеуказанном) - еще без учета коррекционнои матрицы?" - массив uncalibrated_values[3].

    "Или все же нужно для начало использовать отильтрованно/калиброванные данные с гироскопа и акселерометра (фильтр Калмана и Mэджика) и только потом сравнивать полученные углы (крен рыскание тангаж) с данными магнитометра?" - Желательно так. Только в каком смысле сравнивать? Вернее наверно компенсировать или нужно сравнить?

    "Есть несколько видео, где вроде используется для определения крена рыскания тангажа (а я так понимаю углов наклона вокруг осеи) все три датчика (аксель, гироск, магнитом). Где бы раздабыть этот код на MPU 9250? (тогда эти углы можно будет сравнивать с "девственными" (не обработанными) показаниями магнитометра. Единственное, наверное нужна какая ни будь калибровка в строну совпадения осеи всех трех чипов...." - Вот код кватернионного фильтра Маджевика для MPU 9250 данный вариант с учётом магнитометра для устранения дрейфа по рысканью но можно аргументы функции кватернионного фильтра от магнитометра задать 1 и использовать без него (код огромный прикреплю файлом).
     

    Вложения:

  14. evpozdniakov

    evpozdniakov Нуб

    Был чересчур краток. Сейчас объясню, что мне конкретно нужно.

    Я хочу получить недорогой способ определения координат XYZ виртуального шлема на тестовой площадке. (Координаты могут быть оносительными, например, от точки калибрации.)

    Чтобы стало понятнее рассмотрим конкретный пример. Есть ровная площадка, например баскетбольная. Человек находится в ее центре. Он надевает шлем ВР и запускает программу. Программа строит вокруг него виртуальный лабиринт. Задача игрока выйти из этого лабиринта.

    Теоретически мы можем получать данные гироскопа и акселерометра и на их основе считать перемещение источника сигнала.
     
  15. Artclonic

    Artclonic Гик

    Понятно, т.е. используем, только две координаты X и Y (если по Z - всплеск - это что то не от магнитного поля земли.
    Дискретность - посмотрю в даташите, а можно ли ее менять? Или уже потом вывести коэициент, и на него умножать, это в к тому если я захочу все три параметра привести к однои так сказать градации.
    А как с него (с массива) вывести к примеру переменные "девственные" X0, Y0, Z0?
    Повторюсь, хочу вычленить (обнаружить) источники или (исказители) магнитного поля. Передвигаясь в определенном направлении по данно траектории. Как вижу следующие варианты:
    1. Показатель магнитного поля (его напряженность) в определеннои зоне местности (относительно) постоянная величина. Измерить я его могу с помощью магнетометра. Но постоянные значения будут в случае постояннои статичнои ориентации датчика. Т.к. датчик не возможно в руках строго держать статично (без наклонов) при движении, я хочу понять, вычислить или наити зависимость ИЗМЕНЕНИЯ НАПРЯЖЕННОСТИ В ЗАВИСИМОТСИ ОТ НАКЛОНОВ ДАТЧИКА. К примеру я точно знаю что наклон на градус по X или по Y - изменит показание на определенную величину,и я ее могу вычислить. Но если по факту величина по данным осям окажется отличнои от вычисленнои - значит есть объект которыи влияет на направление, величину магнитного поля... К примеру железныи предмет или провод рядом...
    Пример Прохожу с датчиком в руках 5 метров прямо, 3 метра налево, общи путь 8 метров. Записываю показания магнитометра.Далее повторяю все тоже самое только на 7-ом метре (к примеру) рядом кладу магнит, соответственно он изменит напряженность в точке 7метра. (ну или железяку, а не магнит) также записываю показание магнитометра. Естественно будет разница, правильно? И по показаниям магнитометра (по диаграме построеннои) я вычислю где лежит магнит или железяка. А теперь вопрос а как его вычислить с первого раза (прохода)? зная зависимость показания напряженности от наклона датчика (ориентации) от наклона датчика. Я буду знать что на 7-ми метрах напряженность должна быть - вот такои, а на самом деле - вот такая....Узнаю, что там магнит...

    PS
    А как не совпадают то оси? Посмотрите по моеи диаграмме вращение вокруг оси Z ни гироскоп, ни магнетометр не показывает...Значит одинаково они расположены? Уж не знаю, как там акселерометр , до него еще не добрался...

    А где скачать?
    #include <i2c_t3.h>
    #include <SPI.h>
     
    Последнее редактирование: 10 мар 2018
  16. Sencis

    Sencis Нерд

    Т.е. по факту вам нужен хедтрекер?

    А вам что-то вроде металодектора?)))

    Вот что я скажу я занимался изучением MPU 9250 для получения углов ориентации они мне были нужны для создания БПЛА в этом я смогу помочь, но ваши программы вам придётся писать самостоятельно т.к. тут у же вам лучше знать. Я когда начинал изучать эти сенсоры почти ничего не знал о программирование, зачастую просто пробовал разные варианты, "сшивал" разные скетчи из интернета первой моей программой был скетч стабилизатора для камеры на основе скетча углов тонгожа и крена на MPU 5060 он очень понятный если хотите могу его выложить для изучения хотя конечно желательно экспериментировать с датчиком.

    Т.е. вы хотите получить нормализованный вектор?

    А вы вообще знаете C++? В общем пересмотрел я скетч функция калибровки там ничего не делает похоже тогда я не успел её прикрутить т.к. нашёл другой способ.

    // Accelerometer
    int16_t ax=-(Buf[0]<<8 | Buf[1]);
    int16_t ay=-(Buf[2]<<8 | Buf[3]);
    int16_t az=Buf[4]<<8 | Buf[5];

    // Gyroscope
    int16_t gx=-(Buf[8]<<8 | Buf[9]);
    int16_t gy=-(Buf[10]<<8 | Buf[11]);
    int16_t gz=Buf[12]<<8 | Buf[13];

    // Magnetometer
    int16_t mx=-(Mag[3]<<8 | Mag[2]);
    int16_t my=-(Mag[1]<<8 | Mag[0]);
    int16_t mz=-(Mag[5]<<8 | Mag[4]);

    Вот ваши перемененные уже объявлены: mx, my, mz.
     
    Последнее редактирование: 11 мар 2018
  17. Sencis

    Sencis Нерд

    В моём случае при компенсации наклона я заметил что оси Y Z на магнитометре и гироскопе перепутаны в прочем почему-то у каждого они спутаны по разному и не только оси но и положение (положительные и отрицательные значения, у магнитометра низ а для гироскопа это верх).

    #include <i2c_t3.h> - скачивать не нужно там надо закоментировать пару строк и использовать Wire.h

    #include <SPI.h> - у меня базовая библиотека как и EPPROM она вшита в IDE Arduino попробуйте обновить ваш IDE.
     
  18. evpozdniakov

    evpozdniakov Нуб

    Да, можно сказать что мне нужен head tracker. Но беспроводной и желательно не сильно дорогой.
     
  19. evpozdniakov

    evpozdniakov Нуб

    Сейчас погуглил хедтрекеры. Пожалуй это не совсем то, что мне нужно. Хедтрекеры отслеживают наклон и поводрот головы. Мне же нужно знать, куда голову перенесли ноги.
     
  20. Sencis

    Sencis Нерд

    Это другой вопрос это уже навигация, тут mpu 9250 не сильно помогает т.к. использовать его для ИНС можно только для движения по курсу и то не долго т.к. ошибки всё таки есть, для решения задач навигации вам понадобится GPS трекер (или морячок последний отправляет данные местоположения по SMS) но у меня пока руки не дошли его сделать, не хватает конвертера лог уровней поэтому пока ничем помочь не могу.