Проблема со чтением данных с HMC5883L в GY-86
Я пытаюсь считать данные с GY-86 с помощью Arduino UNO. При чтении MPU6050 и MS5611 работает достаточно хорошо. Но что-то не могу ничего прочитать с HMC5883L. Вот код, который я использовал:
#include <Wire.h>
#include <HMC5883L.h>
HMC5883L compass;
void setup()
{
Serial.begin(9600);
// Инициализировать HMC5883L
Serial.println("Initialize HMC5883L");
while (!compass.begin())
{
Serial.println("Could not find a valid HMC5883L sensor, check wiring!");
delay(500);
}
// Установить диапазон измерения
// +/- 0,88 млрд лет: HMC5883L_RANGE_0_88GA
// +/- 1,30 млрд лет: HMC5883L_RANGE_1_3GA (по умолчанию)
// +/- 1,90 млрд лет: HMC5883L_RANGE_1_9GA
// +/- 2,50 млрд лет: HMC5883L_RANGE_2_5GA
// +/- 4,00 млрд лет: HMC5883L_RANGE_4GA
// +/- 4,70 млрд лет: HMC5883L_RANGE_4_7GA
// +/- 5,60 млрд лет: HMC5883L_RANGE_5_6GA
// +/- 8,10 млрд лет: HMC5883L_RANGE_8_1GA
compass.setRange(HMC5883L_RANGE_1_3GA);
// Установить режим измерения
// Режим ожидания: HMC5883L_IDLE
// Одно измерение: HMC5883L_SINGLE
// Непрерывное измерение: HMC5883L_CONTINOUS (по умолчанию)
compass.setMeasurementMode(HMC5883L_CONTINOUS);
// Установить скорость передачи данных
// 0,75 Гц: HMC5883L_DATARATE_0_75HZ
// 1,50 Гц: HMC5883L_DATARATE_1_5HZ
// 3,00 Гц: HMC5883L_DATARATE_3HZ
// 7,50 Гц: HMC5883L_DATARATE_7_50HZ
// 15,00 Гц: HMC5883L_DATARATE_15HZ (по умолчанию)
// 30,00 Гц: HMC5883L_DATARATE_30HZ
// 75,00 Гц: HMC5883L_DATARATE_75HZ
compass.setDataRate(HMC5883L_DATARATE_15HZ);
// Установить количество усредненных выборок
// 1 образец: HMC5883L_SAMPLES_1 (по умолчанию)
// 2 образца: HMC5883L_SAMPLES_2
// 4 образца: HMC5883L_SAMPLES_4
// 8 образцов: HMC5883L_SAMPLES_8
compass.setSamples(HMC5883L_SAMPLES_1);
// Проверить настройки
checkSettings();
}
void checkSettings()
{
Serial.print("Selected range: ");
switch (compass.getRange())
{
case HMC5883L_RANGE_0_88GA: Serial.println("0.88 Ga"); break;
case HMC5883L_RANGE_1_3GA: Serial.println("1.3 Ga"); break;
case HMC5883L_RANGE_1_9GA: Serial.println("1.9 Ga"); break;
case HMC5883L_RANGE_2_5GA: Serial.println("2.5 Ga"); break;
case HMC5883L_RANGE_4GA: Serial.println("4 Ga"); break;
case HMC5883L_RANGE_4_7GA: Serial.println("4.7 Ga"); break;
case HMC5883L_RANGE_5_6GA: Serial.println("5.6 Ga"); break;
case HMC5883L_RANGE_8_1GA: Serial.println("8.1 Ga"); break;
default: Serial.println("Bad range!");
}
Serial.print("Selected Measurement Mode: ");
switch (compass.getMeasurementMode())
{
case HMC5883L_IDLE: Serial.println("Idle mode"); break;
case HMC5883L_SINGLE: Serial.println("Single-Measurement"); break;
case HMC5883L_CONTINOUS: Serial.println("Continuous-Measurement"); break;
default: Serial.println("Bad mode!");
}
Serial.print("Selected Data Rate: ");
switch (compass.getDataRate())
{
case HMC5883L_DATARATE_0_75_HZ: Serial.println("0.75 Hz"); break;
case HMC5883L_DATARATE_1_5HZ: Serial.println("1.5 Hz"); break;
case HMC5883L_DATARATE_3HZ: Serial.println("3 Hz"); break;
case HMC5883L_DATARATE_7_5HZ: Serial.println("7.5 Hz"); break;
case HMC5883L_DATARATE_15HZ: Serial.println("15 Hz"); break;
case HMC5883L_DATARATE_30HZ: Serial.println("30 Hz"); break;
case HMC5883L_DATARATE_75HZ: Serial.println("75 Hz"); break;
default: Serial.println("Bad data rate!");
}
Serial.print("Selected number of samples: ");
switch (compass.getSamples())
{
case HMC5883L_SAMPLES_1: Serial.println("1"); break;
case HMC5883L_SAMPLES_2: Serial.println("2"); break;
case HMC5883L_SAMPLES_4: Serial.println("4"); break;
case HMC5883L_SAMPLES_8: Serial.println("8"); break;
default: Serial.println("Bad number of samples!");
}
}
void loop()
{
Vector raw = compass.readRaw();
Vector norm = compass.readNormalize();
Serial.print(" Xraw = ");
Serial.print(raw.XAxis);
Serial.print(" Yraw = ");
Serial.print(raw.YAxis);
Serial.print(" Zraw = ");
Serial.print(raw.ZAxis);
Serial.print(" Xnorm = ");
Serial.print(norm.XAxis);
Serial.print(" Ynorm = ");
Serial.print(norm.YAxis);
Serial.print(" ZNorm = ");
Serial.print(norm.ZAxis);
Serial.println();
delay(100);
}
Я загружаю его с https://github.com/jarzebski/Arduino-HMC5883L.
Программа всегда зависала на
while (!compass.begin())
{
Serial.println("Could not find a valid HMC5883L sensor, check wiring!");
delay(500);
}
Вот функция начала в HMC5883L.cpp
bool HMC5883L::begin()
{
Wire.begin();
if ((fastRegister8(HMC5883L_REG_IDENT_A) != 0x48)
|| (fastRegister8(HMC5883L_REG_IDENT_B) != 0x34)
|| (fastRegister8(HMC5883L_REG_IDENT_C) != 0x33))
{
return false;
}
setRange(HMC5883L_RANGE_1_3GA);
setMeasurementMode(HMC5883L_CONTINOUS);
setDataRate(HMC5883L_DATARATE_15HZ);
setSamples(HMC5883L_SAMPLES_1);
mgPerDigit = 0.92f;
return true;
}
Похоже, что функция begin всегда возвращает False. Что мне делать, чтобы решить эту проблему?
Вот как я подключаю GY-86 к UNO:
VCC-IN -> 5 В
Земля -> Земля
ПДД -> 4А
SLC -> 5А
@Yichen, 👍3
2 ответа
Лучший ответ:
Запускали ли вы сканер i2c? Обнаружен ли он с адресом i2c 0x1E?
Глядя на схему, магнитометр HMC5883L подключен к XDA и XCL. Это не обычная шина I2C, а вторая шина I2C от MPU- 6050.
Причина этого в том, что прошивка dmp в MPU-6050 может считывать показания магнитометра и выполнять с ним вычисления в MPU-6050.
Если вы хотите обмениваться данными с магнитометром через обычную шину I2C, вам необходимо включить режим обхода.
Библиотеки Джеффа Роуберга и Яржебски большие. Я предлагаю включить обходной режим и запустить сканер i2c.
Есть ли у вас логический анализатор? Возможно, вы можете использовать простой мультиметр. Держите SDA на низком уровне (замкните его на GND) и попытайтесь измерить, низкий ли уровень на XDA в режиме байпаса.
Возможно, что-то сломалось.
Спасибо Джоту, ваш ответ действительно помогает мне. Теперь я использую этот код, и он работает очень хорошо.
#include <Wire.h>
#include <HMC5883L.h>
#include <MPU6050.h>
HMC5883L compass;
MPU6050 mpu;
int previousDegree;
void setup()
{
#if I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE
Wire.begin();
#elif I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_FASTWIRE
Fastwire::setup(400, true);
#endif
Serial.begin(38400);
// Инициализировать MPU6050
mpu.initialize();
// Включить режим обхода
mpu.setI2CMasterModeEnabled(false);
mpu.setI2CBypassEnabled(true);
mpu.setSleepEnabled(false);
// Инициализировать HMC5883L
while (!compass.begin())
{
delay(500);
}
// Установить диапазон измерения
compass.setRange(HMC5883L_RANGE_1_3GA);
// Установить режим измерения
compass.setMeasurementMode(HMC5883L_CONTINOUS);
// Установить скорость передачи данных
compass.setDataRate(HMC5883L_DATARATE_30HZ);
// Установить количество усредненных выборок
compass.setSamples(HMC5883L_SAMPLES_8);
// Установить смещение калибровки. См. HMC5883L_caulibration.ino.
compass.setOffset(0, 0);
}
void loop()
{
long x = micros();
Vector norm = compass.readNormalize();
// Вычислить заголовок
float heading = atan2(norm.YAxis, norm.XAxis);
// Установите угол склонения на ваше местоположение и зафиксируйте курс
// Вы можете найти свое склонение на: http:// Magnetic-declination.com/
// (+) положительный или (-) отрицательный
// Для Бытома / Польши угол склонения 4'26E (положительный)
// Формула: (град + (мин/60,0))/(180/M_PI);
float declinationAngle = (4.0 + (26.0 / 60.0)) / (180 / M_PI);
heading += declinationAngle;
// Правильный заголовок < 0deg и заголовок > 360 градусов
if (heading < 0)
{
heading += 2 * PI;
}
if (heading > 2 * PI)
{
heading -= 2 * PI;
}
// Преобразование в градусы
float headingDegrees = heading * 180/M_PI;
// Исправление проблемы HMC5883L с углами
float fixedHeadingDegrees;
if (headingDegrees >= 1 && headingDegrees < 240)
{
fixedHeadingDegrees = map(headingDegrees, 0, 239, 0, 179);
} else
if (headingDegrees >= 240)
{
fixedHeadingDegrees = map(headingDegrees, 240, 360, 180, 360);
}
// Плавное вращение углов на +/- 3 градуса
int smoothHeadingDegrees = round(fixedHeadingDegrees);
if (smoothHeadingDegrees < (previousDegree + 3) && smoothHeadingDegrees > (previousDegree - 3))
{
smoothHeadingDegrees = previousDegree;
}
previousDegree = smoothHeadingDegrees;
// Выход
Serial.print(norm.XAxis);
Serial.print(":");
Serial.print(norm.YAxis);
Serial.print(":");
Serial.print(norm.ZAxis);
Serial.print(":");
Serial.print(headingDegrees);
Serial.print(":");
Serial.print(fixedHeadingDegrees);
Serial.print(":");
Serial.print(smoothHeadingDegrees);
Serial.println();
// Один цикл: ~5 мс @ 115200 серийный номер.
// Нам нужна задержка ~ 28 мс для разрешения скорости передачи данных 30 Гц (~ 33 мс)
delay(30);
}
Кстати, код на https://github.com/jarzebski/Arduino-HMC5883L должен добавить
#if I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE
Wire.begin();
#elif I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_FASTWIRE
Fastwire::setup(400, true);
#endif
в начале установки.
- Отправка и получение различных типов данных через I2C в Arduino
- Как работают функции вне цикла void?
- Как отображать переменные на 0,96-дюймовом OLED-дисплее с библиотекой u8glib?
- OVF в последовательном мониторе вместо данных
- ЖК-дисплей I2C отображает странные символы
- Соединение I2C зависает Ведущий если ведомый отключается
- Экран LCD 16*02 I2C показывает только первый напечатанный символ
- Ведомое устройство Arduino с двумя мастерами, использующими одну и ту же шину I2C?
Здесь может быть проблема. Сканер i2c нашел только 0x68 и 0x77. Означает ли это, что мой GY-86 сломан?, @Yichen
Кстати, я также пытаюсь использовать код обхода I2C на этом сайте. [ссылка](https://stackoverflow.com/questions/37966638/mpu6050-read-accel-gyro-and-magnetometer)
mpu.setI2CMasterModeEnabled (ложь); mpu.setI2CBypassEnabled (истина); mpu.setSleepEnabled(false);
Но тем не менее, он снова застрял в begin()., @YichenВам все равно придется вызывать
mpu.begin
перед включением обхода. Я добавил в свой ответ некоторую справочную информацию и информацию о том, как протестировать вторую шину I2C., @Jot