Добрый день. В прошлои теме начал знакомство с магнитометром 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
Вот код которым я запускал 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; } К слову к этому датчику есть неплохой кватернионный фильтр для получения более менее достоверных углов ориентации (тонгаж, крен, рысканье).
Ругается С:\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
Пардон не всё выбрал))) Код (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; }
С ваших слов не понятно какие именно вам нужны координаты, с помощью MPU 9250 можно получить ориентацию в пространстве и решать такие проблемы как: стабилизация (будь то камера или самолёт), инерциальная навигация конечно точность такой навигации оставляет желать лучшего но благодаря магнитометру на курс мы можем положится, и используя по отдельности компоненты модуля можно получить, датчик удара, измерить ускорение, силу магнитного поля (геологи исп. магнитометр для отслеживания месторождения руды по магнитным аномалиям), отдельные датчики оснащены барометром могут мерить температуру, давление и соответственно высоту.
Да тоже интересна в даннои реализации на ардуино только..(потихонечку изучаю, осмысливаю) 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
Ну вот вроде запустил...Почему то значение магнетометра разбилось.. первыи столбец и последние два... Не поиму почему так? И что такое 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" и вижу, что акселерометр и гироскопом - перепутаны на мо взгляд. Диаграмма, где прямая возвращается на искомое значение после поворота - это же реакция на ускорение - акселерометр, а вот граик гироскопа - остался после поворота..Определил угол наклона..
22 Это мои опыты (Serial.print ( Mscale << 4 | Mmode ,DEC) с режимом работы (частота вывода данных помойму) не берите в голову я уже и сам не помню, что тогда происходило))) дополнительные пины подключать не надо по крайней мере если вы не используете прерывания. "Serial Oscilloscope" никогда не пользовался ничего сказать не могу. Вы лучше напишите, что вы хотите сделать а иначе не понятно в каком ключе вообще идёт разговор а там уже разберёмся.
Я понял про 22 -убрал уже... Хочу сделать некии деваис, которыи мерил напряженность магнитного поля в трех осях, казалось бы есть магнитометр, которыи это и делает. Но напряженности есть зависимость от направлении вектора магнитного поля. Иными словами есть зависимрсть от поворота вокруг осеи. При помощи гироскопа можно измерить углы отклонении. Задумка такая - если ввести некии градиент (разницу между показателями магнитометра и углом вдоль оси, привидя ее к одинаковым размерностям). Т.е. куда не поверни - данная разница будет постояннои, кроме случая если нет вмешательства инородного источника (или объекта, которы отклоняет магнитное поле, так сказать анамалия).
Я подобным я не занимался мах могу посоветовать скетч компенсации наклона но он для компаса, впрочем возможно его принцип работы натолкнёт на умную мысль. На крайний случай можно сделать гироскопически-стабилизированную платформу установить на неё магнитометр и измерять))).
Начал некоторыи анализ. Произвел записи по всем осям.Сделал 6 деиствии вокруг каждои (XYZ) оси повернул модуль, туда/обратно на 360 град. с паузами (состояния покоя) Построил графики... Почему то вокруг оси z показания от других осей отличается? Их почти нет... (кроме акселерометра) Как определить какие ограничения в показателях у гироскопа и магнитометра? (-2200/+2200 и -500/+500, соответственно)? Видна ли зависимость "стратегическая"? показании магнитометра от наклонов вдоль осей? Какие переменные в скетче (вышеуказанном) - еще без учета коррекционнои матрицы? Или все же нужно для начало использовать отильтрованно/калиброванные данные с гироскопа и акселерометра (фильтр Калмана и Mэджика) и только потом сравнивать полученные углы (крен рыскание тангаж) с данными магнитометра? Есть несколько видео, где вроде используется для определения крена рыскания тангажа (а я так понимаю углов наклона вокруг осеи) все три датчика (аксель, гироск, магнитом). Где бы раздабыть этот код на MPU 9250? (тогда эти углы можно будет сравнивать с "девственными" (не обработанными) показаниями магнитометра. Единственное, наверное нужна какая ни будь калибровка в строну совпадения осеи всех трех чипов....
"Почему то вокруг оси z показания от других осей отличается?" - Вектор магнитного поля берётся по 2м осям X и Y на эти осях сама большая составляющая магнитного поля в прочем чем ближе к северному магнитному полюсу она уходит в Z сразу отмечу что оси магнитометра не совпадают с осями гироскопа и акселерометра. "Как определить какие ограничения в показателях у гироскопа и магнитометра?" - в даташите надо смотреть. "Видна ли зависимость "стратегическая"? показании магнитометра от наклонов вдоль осей?" - не совсем понятен термин "стратегическая" но скажу так в зависимости от наклона магнитометра магнитный вектор уходит в другую плоскость. Так если у нас X and Y параллельны поверхности земли то при наклоне она уходит от X на ось Z. "Какие переменные в скетче (вышеуказанном) - еще без учета коррекционнои матрицы?" - массив uncalibrated_values[3]. "Или все же нужно для начало использовать отильтрованно/калиброванные данные с гироскопа и акселерометра (фильтр Калмана и Mэджика) и только потом сравнивать полученные углы (крен рыскание тангаж) с данными магнитометра?" - Желательно так. Только в каком смысле сравнивать? Вернее наверно компенсировать или нужно сравнить? "Есть несколько видео, где вроде используется для определения крена рыскания тангажа (а я так понимаю углов наклона вокруг осеи) все три датчика (аксель, гироск, магнитом). Где бы раздабыть этот код на MPU 9250? (тогда эти углы можно будет сравнивать с "девственными" (не обработанными) показаниями магнитометра. Единственное, наверное нужна какая ни будь калибровка в строну совпадения осеи всех трех чипов...." - Вот код кватернионного фильтра Маджевика для MPU 9250 данный вариант с учётом магнитометра для устранения дрейфа по рысканью но можно аргументы функции кватернионного фильтра от магнитометра задать 1 и использовать без него (код огромный прикреплю файлом).
Был чересчур краток. Сейчас объясню, что мне конкретно нужно. Я хочу получить недорогой способ определения координат XYZ виртуального шлема на тестовой площадке. (Координаты могут быть оносительными, например, от точки калибрации.) Чтобы стало понятнее рассмотрим конкретный пример. Есть ровная площадка, например баскетбольная. Человек находится в ее центре. Он надевает шлем ВР и запускает программу. Программа строит вокруг него виртуальный лабиринт. Задача игрока выйти из этого лабиринта. Теоретически мы можем получать данные гироскопа и акселерометра и на их основе считать перемещение источника сигнала.
Понятно, т.е. используем, только две координаты X и Y (если по Z - всплеск - это что то не от магнитного поля земли. Дискретность - посмотрю в даташите, а можно ли ее менять? Или уже потом вывести коэициент, и на него умножать, это в к тому если я захочу все три параметра привести к однои так сказать градации. А как с него (с массива) вывести к примеру переменные "девственные" X0, Y0, Z0? Повторюсь, хочу вычленить (обнаружить) источники или (исказители) магнитного поля. Передвигаясь в определенном направлении по данно траектории. Как вижу следующие варианты: 1. Показатель магнитного поля (его напряженность) в определеннои зоне местности (относительно) постоянная величина. Измерить я его могу с помощью магнетометра. Но постоянные значения будут в случае постояннои статичнои ориентации датчика. Т.к. датчик не возможно в руках строго держать статично (без наклонов) при движении, я хочу понять, вычислить или наити зависимость ИЗМЕНЕНИЯ НАПРЯЖЕННОСТИ В ЗАВИСИМОТСИ ОТ НАКЛОНОВ ДАТЧИКА. К примеру я точно знаю что наклон на градус по X или по Y - изменит показание на определенную величину,и я ее могу вычислить. Но если по факту величина по данным осям окажется отличнои от вычисленнои - значит есть объект которыи влияет на направление, величину магнитного поля... К примеру железныи предмет или провод рядом... Пример Прохожу с датчиком в руках 5 метров прямо, 3 метра налево, общи путь 8 метров. Записываю показания магнитометра.Далее повторяю все тоже самое только на 7-ом метре (к примеру) рядом кладу магнит, соответственно он изменит напряженность в точке 7метра. (ну или железяку, а не магнит) также записываю показание магнитометра. Естественно будет разница, правильно? И по показаниям магнитометра (по диаграме построеннои) я вычислю где лежит магнит или железяка. А теперь вопрос а как его вычислить с первого раза (прохода)? зная зависимость показания напряженности от наклона датчика (ориентации) от наклона датчика. Я буду знать что на 7-ми метрах напряженность должна быть - вот такои, а на самом деле - вот такая....Узнаю, что там магнит... PS А как не совпадают то оси? Посмотрите по моеи диаграмме вращение вокруг оси Z ни гироскоп, ни магнетометр не показывает...Значит одинаково они расположены? Уж не знаю, как там акселерометр , до него еще не добрался... А где скачать? #include <i2c_t3.h> #include <SPI.h>
Т.е. по факту вам нужен хедтрекер? А вам что-то вроде металодектора?))) Вот что я скажу я занимался изучением 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.
В моём случае при компенсации наклона я заметил что оси Y Z на магнитометре и гироскопе перепутаны в прочем почему-то у каждого они спутаны по разному и не только оси но и положение (положительные и отрицательные значения, у магнитометра низ а для гироскопа это верх). #include <i2c_t3.h> - скачивать не нужно там надо закоментировать пару строк и использовать Wire.h #include <SPI.h> - у меня базовая библиотека как и EPPROM она вшита в IDE Arduino попробуйте обновить ваш IDE.
Сейчас погуглил хедтрекеры. Пожалуй это не совсем то, что мне нужно. Хедтрекеры отслеживают наклон и поводрот головы. Мне же нужно знать, куда голову перенесли ноги.
Это другой вопрос это уже навигация, тут mpu 9250 не сильно помогает т.к. использовать его для ИНС можно только для движения по курсу и то не долго т.к. ошибки всё таки есть, для решения задач навигации вам понадобится GPS трекер (или морячок последний отправляет данные местоположения по SMS) но у меня пока руки не дошли его сделать, не хватает конвертера лог уровней поэтому пока ничем помочь не могу.