Ви не увійшли.
Всім привіт! Придбав от такий модуль датчиків (Модуль GY-86 комбінованих 10-DOF датчиків IMU - MPU6050 / HMC5883L / MS5611)
https://arduino.ua/prod1026-modyl-gy-86 … 83l-ms5611
Код взяв тут:
https://forum.arduino.cc/t/extracting-a … -86/185955
Біблітеки з того ж ресурсу:
Ця https://github.com/jrowberg/i2cdevlib/t … no/MPU6050
І ця: https://github.com/jrowberg/i2cdevlib/t … o/HMC5883L
Під'єдную до Arduino Due
Сама проблема:
Код працює, в серійний порт виводить данні, але heading (напрямок по компасу) постіно коливається в діапазоні 190-230, хоча повинен змінюватись від 0 до 360. При тому що повертаю датчик на 360 градусів навколо вертикальної осі
Дякую за допомогу!
Код:
#include "Wire.h"
#include "I2Cdev.h"
#include "MPU6050.h"
#include "HMC5883L.h"
MPU6050 accelgyro;
HMC5883L mag;
int16_t ax, ay, az;
int16_t gx, gy, gz;
int16_t mx, my, mz;
#define LED_PIN 13
bool blinkState = false;
void setup() {
Wire.begin();
accelgyro.setI2CMasterModeEnabled(false);
accelgyro.setI2CBypassEnabled(true) ;
accelgyro.setSleepEnabled(false);
Serial.begin(38400);
// initialize device
Serial.println("Initializing I2C devices...");
accelgyro.initialize();
mag.initialize();
Serial.println(mag.testConnection() ? "HMC5883L connection successful" : "HMC5883L connection failed");
// verify connection
Serial.println("Testing device connections...");
Serial.println(accelgyro.testConnection() ? "MPU6050 connection successful" : "MPU6050 connection failed");
// configure Arduino LED for
pinMode(LED_PIN, OUTPUT);
}
void loop() {
accelgyro.getMotion6(&ax, &ay, &az, &gx, &gy, &gz);
mag.getHeading(&mx, &my, &mz);
// display tab-separated accel/gyro x/y/z values
Serial.print("a/g:t");
Serial.print(ax); Serial.print("t");
Serial.print(ay); Serial.print("t");
Serial.print(az); Serial.print("t");
Serial.print(gx); Serial.print("t");
Serial.print(gy); Serial.print("t");
Serial.print(gz); Serial.print("t");
Serial.print("mag:t");
Serial.print(mx); Serial.print("t");
Serial.print(my); Serial.print("t");
Serial.print(mz); Serial.print("t");
delay(500);
// To calculate heading in degrees. 0 degree indicates North
//float heading = atan2(my, mx);
float heading = atan2(mx, my);
if(heading < 0)
heading += 2 * M_PI;
Serial.print("heading:t");
Serial.println(heading * 180/M_PI);
// blink LED to indicate activity
blinkState = !blinkState;
digitalWrite(LED_PIN, blinkState);
}
Скрін:
Неактивний
Нету датчика на руках, но вроде как сырые данные (mx, my) не должны быть отрицательными, попробуй откалибровать датчик:
#include "Wire.h"
#include "HMC5883L.h"
HMC5883L mag;
void setup() {
Wire.begin();
Serial.begin(9600);
mag.initialize();
Serial.println("Move the magnetometer in all directions to calibrate...");
delay(2000);
}
void loop() {
static int16_t minX = 0, minY = 0, minZ = 0;
static int16_t maxX = 0, maxY = 0, maxZ = 0;
int16_t x, y, z;
mag.getHeading(&x, &y, &z);
if (x < minX) minX = x;
if (x > maxX) maxX = x;
if (y < minY) minY = y;
if (y > maxY) maxY = y;
if (z < minZ) minZ = z;
if (z > maxZ) maxZ = z;
// Print the raw values and the calibration range
Serial.print("Raw: X="); Serial.print(x);
Serial.print(" Y="); Serial.print(y);
Serial.print(" Z="); Serial.print(z);
Serial.print(" Calibrated Range: X["); Serial.print(minX); Serial.print(", "); Serial.print(maxX); Serial.print("]");
Serial.print(" Y["); Serial.print(minY); Serial.print(", "); Serial.print(maxY); Serial.print("]");
Serial.print(" Z["); Serial.print(minZ); Serial.print(", "); Serial.print(maxZ); Serial.println("]");
delay(200);
}
}
после чего запиши максимальные и минимальные значения для каждой оси в новый код:
#include "Wire.h"
#include "I2Cdev.h"
#include "MPU6050.h"
#include "HMC5883L.h"
MPU6050 accelgyro;
HMC5883L mag;
int16_t ax, ay, az;
int16_t gx, gy, gz;
int16_t mx, my, mz;
#define LED_PIN 13
bool blinkState = false;
// Задайте значения из калибровки для коррекции
int16_t minX = -100; // Замените значения на те, что получены в калибровке
int16_t maxX = 100;
int16_t minY = -100;
int16_t maxY = 100;
int16_t minZ = -100;
int16_t maxZ = 100;
void setup() {
Wire.begin();
accelgyro.setI2CMasterModeEnabled(false);
accelgyro.setI2CBypassEnabled(true);
accelgyro.setSleepEnabled(false);
Serial.begin(38400);
// initialize device
Serial.println("Initializing I2C devices...");
accelgyro.initialize();
mag.initialize();
Serial.println(mag.testConnection() ? "HMC5883L connection successful" : "HMC5883L connection failed");
// verify connection
Serial.println("Testing device connections...");
Serial.println(accelgyro.testConnection() ? "MPU6050 connection successful" : "MPU6050 connection failed");
// configure Arduino LED for
pinMode(LED_PIN, OUTPUT);
}
void loop() {
// Чтение данных с акселерометра и гироскопа
accelgyro.getMotion6(&ax, &ay, &az, &gx, &gy, &gz);
// Чтение данных с магнетометра
mag.getHeading(&mx, &my, &mz);
// Коррекция сырых данных магнетометра с помощью значений из калибровки
mx = constrain(mx, minX, maxX);
my = constrain(my, minY, maxY);
mz = constrain(mz, minZ, maxZ);
// Вывод данных на монитор последовательного порта
Serial.print("a/g: ");
Serial.print(ax); Serial.print("t");
Serial.print(ay); Serial.print("t");
Serial.print(az); Serial.print("t");
Serial.print(gx); Serial.print("t");
Serial.print(gy); Serial.print("t");
Serial.print(gz); Serial.print("t");
Serial.print("mag: ");
Serial.print(mx); Serial.print("t");
Serial.print(my); Serial.print("t");
Serial.print(mz); Serial.print("t");
// Вычисление и вывод направления (heading) в градусах
float heading = atan2(my, mx);
if (heading < 0)
heading += 2 * PI;
Serial.print("heading: ");
Serial.println(heading * 180 / PI);
// Мигание светодиода для индикации активности
blinkState = !blinkState;
digitalWrite(LED_PIN, blinkState);
delay(500);
}
Неактивний
KAS
К сожаление метод не сработал, но ты меня натолкнул на мысль, что используются "сырые" значения. Взял твой калибровщик и с помощью него перевел "сырые" в калиброваные. Компас начал показывать полный круг в 360 градусов, всё же на точный север не показывает (хотя угол склонения тоже добавил). В моем проекте это не важно, мне нужно только направление. Ну и добавлю что датчик очень чувствителен к магнитным полям, телефон лежащий в 10см от датчика дает погрешность в 10-15 градусов.
Формула перевода значений:
offset = (minimum + maxmum) / 2 //minimum, maxmum - из калибровщика
value = valueRaw - offset //valueRaw - сырое значение с датчика, value - значение для расчёта heading
Может кому понадобится код:
#include "Wire.h"
#include "I2Cdev.h"
#include "MPU6050.h"
#include "HMC5883L.h"
MPU6050 accelgyro;
HMC5883L mag;
int16_t ax, ay, az;
int16_t gx, gy, gz;
int16_t mx, my, mz;
float offsetMx, offsetMy, offsetMz;
float scaledMx, scaledMy, scaledMz;
#define LED_PIN 13
#define DA 0,146608 //Declination angle in RAD
bool blinkState = false;
void setup() {
Wire.begin();
accelgyro.setI2CMasterModeEnabled(false);
accelgyro.setI2CBypassEnabled(true) ;
accelgyro.setSleepEnabled(false);
Serial.begin(38400);
// initialize device
Serial.println("Initializing I2C devices...");
accelgyro.initialize();
mag.initialize();
Serial.println(mag.testConnection() ? "HMC5883L connection successful" : "HMC5883L connection failed");
// verify connection
Serial.println("Testing device connections...");
Serial.println(accelgyro.testConnection() ? "MPU6050 connection successful" : "MPU6050 connection failed");
// configure Arduino LED for
pinMode(LED_PIN, OUTPUT);
}
void loop() {
accelgyro.getMotion6(&ax, &ay, &az, &gx, &gy, &gz);
mag.getHeading(&mx, &my, &mz);
// display tab-separated accel/gyro x/y/z values
Serial.print("a/g:t");
Serial.print(ax); Serial.print("t");
Serial.print(ay); Serial.print("t");
Serial.print(az); Serial.print("t");
Serial.print(gx); Serial.print("t");
Serial.print(gy); Serial.print("t");
Serial.print(gz); Serial.print("t");
Serial.print("mag:t");
Serial.print(mx); Serial.print("t");
Serial.print(my); Serial.print("t");
Serial.print(mz); Serial.print("t");
delay(100);
offsetMx = (-762 + 276)/2; // Min and Max values taken from calibrator
offsetMy = (-892 + 155)/2; // Used formula to get scaled values: offset = (minimum + maxmum) / 2; value = valueRaw - offset
offsetMz = (-701 + 256)/2; //
scaledMx = mx - offsetMx;
scaledMy = my - offsetMy;
scaledMz = mz - offsetMz;
// To calculate heading in degrees. 0 degree indicates North
float heading = atan2(scaledMy, scaledMx);
heading += DA; //including declination angle
if(heading < 0)
heading += 2 * M_PI;
Serial.print("heading:t");
Serial.println(heading * 180/M_PI);
// blink LED to indicate activity
blinkState = !blinkState;
digitalWrite(LED_PIN, blinkState);
}
Остання редакція Timoha_k (2023-08-09 00:04:26)
Неактивний