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

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

  1. Sencis

    Sencis Гик

    В смысле не на одном датчике:
    Берём первый hmc5883l подключаем n контакт к земле адрес изменился на единичку меньше, другой магнитометр подключаем как обычно питание и sda scl и всё (адрес остался как был по умолчанию), третий подключаем n контакт к питанию (например 3.3v). Так на моём hmc5983l т.к. они схожи думаю и на hmc5883l должна быть анология.
     
  2. Artclonic

    Artclonic Гик

    датчики в разных модулях. Ни чего не понял.... Вы мне проговорили о 3-х датчиках.., А каким образом подключить 4 или к примеру 6 модулей... Им надо присвоить разные адреса... На примере трех вроде понятно.... а более?
     
  3. Sencis

    Sencis Гик

    Естественно а иначе зачем всё это?
    ХЗ может ещё есть функция изменения адреса, я знаю только как подключить 3 модуля а зачем мне больше?
     
  4. Artclonic

    Artclonic Гик

    Добрый день, вроде разобрался с модулем HMC5883L, а именно как подключить несколько штук к одной ардуинке. Соответственно замахиваюсь на модуль MPU 9250 и спрашииваю, а эти модули возможно подключать в нескольких количествах путем изменения адреса устройства? (возможно ли изменить адрес модуля?) Или остаются пути, такие как мультиплексер, несколько ардуинок и связь их в сеть, и освоенный мной способ изменения пинов SDA, SCL на шинеI2C?
     
  5. Artclonic

    Artclonic Гик

    Пришло две штучки MPU 9250,понимаю, что к одно плате можно подключить двумя способами . первыи по SPI., второи со специальнои библиотеки которая меняет пины для sda и scl. (второ способ я вроде как уже освоил) подключение по SPI- в целом ясна , но как управлятся с пином назначения того или иного порта - пока до конца не понял.. Что легче? И да планирую использовать предоставленныи код (измерения углов крена, тангажа, рысканья). Какои способ предпочтительнее? Такои и начну (продолжу) осваивать...
     
  6. Sencis

    Sencis Гик

    Это уж вам видней какой вам ближе (понятнее) тот и пробуйте SPI более скоростная шина предпочтительна за счёт меньших задержек при чтении/записи (+ при использовании 32бит плат можно считать сразу 16бит данных ) но придётся переписать код, с I2C всё проще я бы наверно его и выбрал т.к. мне было-бы лень что-то менять.
     
  7. Artclonic

    Artclonic Гик

    Вот теперь вопрос... подключить по I2C (к примеру 3 шт MPU 9250) - это хозяиство влезит на мини мегу?
    Т.к. если на три модуля, считаи код надо задублировать трижды...
    К стати там тоже надо менять..... и много... т.к. библиотека Wire - там не используется... все Wire переписывал на myWire1, myWire2 и т.д. сколько модулеи смотря... Но это ладно - я ж с этимразобрался и мне понятно что и как надо менять...Останется вопрос влезит ли Ваш код для трех модулеи. В недолеком будущем я пытался в Uno один засунуть, он не влез.... Влезет ли три на мини мегу?
     
  8. Sencis

    Sencis Гик

    Компьютеры и посей день были бы со шкаф размером еслиб все так рассуждали. А как у вас на компьютере могут быть абсолютно разные детали но вы же не переписываете ОС? Тем более там 3 одинаковых модуля программа должна опрашивать их последовательно либо по прерываниям но если вычислений много и время оно занимает больше чем частота ответов модуля можно с этим и не замачиваться ( это я к тому что у меня на меге 2560 частота фильтра была 145Гц в то время как датчик мог 250Гц соответственно смысла в прерываниях тут нет ).
     
  9. Artclonic

    Artclonic Гик

    Это Вы мне технологию SPI описали, а не по технологии I2C... Вот пример кода (рабочии) на подключение нескольких (двух) HMC5883L. Как видно что б менять пины подключения I2C,надо считаи два раза "код считывания прописать...). Т.е. все же получается надо осваивать SPI.. Или влезит код(с определениями углов) на 3 модуля по технологии I2C?
    Код (C++):
    #include <SoftwareWire.h>
    #define addr 0x0D //I2C Address for The HMC5883

    SoftwareWire myWire1(4, 5); //4  sda and 5 scl
    SoftwareWire myWire2(6, 7); //6  sda and 7 scl
    const int knopka1=8; // кнопка №1
    const int knopka2=9; // кнопка №2
    int val=0;
    unsigned long L=250;
    int xx1;
    int yy1;
    int zz1;

    int xx2;
    int yy2;
    int zz2;


    static int mx1;
    static int my1;
    static int mz1;

    static int mx2;
    static int my2;
    static int mz2;




    void setup() {

    pinMode(knopka1, INPUT_PULLUP);
    pinMode(knopka2, INPUT_PULLUP);
    Serial.begin(9600);

      myWire1.begin();
      myWire2.begin();

      myWire1.beginTransmission(addr); //start talking
      myWire1.write(0x0B); // Tell the HMC5883 to Continuously Measure
      myWire1.write(0x01); // Set the Register
      myWire1.endTransmission();
      myWire1.beginTransmission(addr); //start talking
      myWire1.write(0x09); // Tell the HMC5883 to Continuously Measure
      myWire1.write(0x1D); // Set the Register
      myWire1.endTransmission();

      myWire2.beginTransmission(addr); //start talking
      myWire2.write(0x0B); // Tell the HMC5883 to Continuously Measure
      myWire2.write(0x01); // Set the Register
      myWire2.endTransmission();
      myWire2.beginTransmission(addr); //start talking
      myWire2.write(0x09); // Tell the HMC5883 to Continuously Measure
      myWire2.write(0x1D); // Set the Register
      myWire2.endTransmission();


    }

    void loop() {

    if(digitalRead(knopka1)==LOW) //проверка включена ли кнопка №1
    {
      //Начало первого блока кода для чтения 1 датчика
      int x1, y1, z1; //triple axis data
      //Tell the HMC what regist to begin writing data into

      myWire1.beginTransmission(addr);
      myWire1.write((uint8_t)0x00); //start with register 3.
      myWire1.endTransmission();

      //Read the data.. 2 bytes for each axis.. 6 total bytes
      myWire1.requestFrom(addr, 6);
      if (6 <= myWire1.available()) {
        x1 = myWire1.read(); //MSB  x
        x1 |= myWire1.read() << 8; //LSB  x
        z1 = myWire1.read(); //MSB  z
        z1 |= myWire1.read() << 8; //LSB z
        y1 = myWire1.read(); //MSB y
        y1 |= myWire1.read() << 8; //LSB y
      }


      xx1=(mx1-x1)/L;
    mx1=x1;
      yy1=(my1-y1)/L;
      my1=y1;
      zz1=(mz1-z1)/L;
      mz1=z1;


      //Начало второго блока кода для чтения 2 датчика
      int x2, y2, z2; //triple axis data
      //Tell the HMC what regist to begin writing data into

      myWire2.beginTransmission(addr);
      myWire2.write((uint8_t)0x00); //start with register 3.
      myWire2.endTransmission();

      //Read the data.. 2 bytes for each axis.. 6 total bytes
      myWire2.requestFrom(addr, 6);
      if (6 <= myWire2.available()) {
        x2 = myWire2.read(); //MSB  x
        x2 |= myWire2.read() << 8; //LSB  x
        z2 = myWire2.read(); //MSB  z
        z2 |= myWire2.read() << 8; //LSB z
        y2 = myWire2.read(); //MSB y
        y2 |= myWire2.read() << 8; //LSB y
      }

      xx2=(mx2-x2)/L;
       mx2=x2;
      yy2=(my2-y2)/L;
       my2=y2;
      zz2=(mz2-z2)/L;
       mz2=z2;

      // Печать в порт
     
    Serial.print("E");
    Serial.print(x1);
    Serial.print(",");
    Serial.print(y1);
    Serial.print(",");
    Serial.print(z1);
    Serial.print(",");
    Serial.print(xx1);
    Serial.print(",");
    Serial.print(yy1);
    Serial.print(",");
    Serial.print(zz1);
    //Serial.print(",");

    //Serial.print(x2);
    //Serial.print(",");
    //Serial.print(y2);
    //Serial.print(",");
    //Serial.print(z2);
    //Serial.print(",");

    //Serial.print(xx2);
    //Serial.print(",");
    //Serial.print(yy2);
    //Serial.print(",");
    //Serial.print(zz2);
    Serial.print("\n");

      delay(L);
    }
    else
    {
      if(digitalRead(knopka2)==LOW)  // нажали кнопочку #2
          {    
          val++;  // прибавляем к переменной 1 при каждой смене цикла.    
          delay(200); //небольшая защита от "дребезга" контактов кнопки
                       
          if(val>=5)
          {
           Serial.print("REPER");
           //Serial.print(val);
            val=0; // обнулили переменную
            delay(1000);//пауза
           }
                       
           else
           {
             // ничего не делаем...
            }
         
          }
          else
           {
            val=0; // обнулили переменную
            }
       
          }
          }
       

     
     
  10. Artclonic

    Artclonic Гик

    Добрыи вечер, пытаюсь адаптировать код подключения двух MPU 9250.... с помощью библиотеки SoftwareWire.h иными словами заменяю пины Wire на другие SoftwareWire.h
    Код (C++):
    #include <SoftwareWire.h>
    SoftwareWire myWire1(4, 5); //4  sda and 5 scl
    SoftwareWire myWire2(6, 7); //6  sda and 7 scl
    Если сравнить данныи процесс с подключением двух HMC5883L (код выше в топике)(а там все понятно я можно сказать сам все сделал при помощи небольшои консультации), то возникает вопрос.. Необходимо все переменные продублировать? Иными словами SoftwareWire myWire1(4, 5); и прописать всю программу и SoftwareWire myWire2(6, 7); и прописать всю программу второи раз с дублированными переменными?
    В моеи программе есть
    константы #define
    потом массивы enum
    восьмибитные переменные uint8_t
    дествия
    void getMres()
    void I2Cread(uint8_t Address, uint8_t Register, uint8_t Nbytes, uint8_t* Data)
    void I2CwriteByte(uint8_t Address, uint8_t Register, uint8_t Data)
    void transformation(float uncalibrated_values[3])

    void setup()

    void loop()

    Соответственно далее деbствия...
    Так где надо менять? И дублировать переменные...?
    Код (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;
    }
     
     
  11. Sencis

    Sencis Гик

    Листая древние темы вдруг наткнулся, так и что получилось? Я последнее сообщение тогда в личку писал за стабилизатор ( механический ) но ответа не было. Недавно сам решил попробовать магнитометр в качестве металл детектора говно, чувствительность даж в сравнении с самодельной катушкой не о чём т.е. на земле в траве он видит и там где оч много металла но на 30см найти трубу уже не реально.
     
  12. ринат81

    ринат81 Нуб

    I2C мультиплексор TCA9548A Arduino подключаем до 8 штук с одним адресом к одной ардуинке