Понимание значений от MPU6050
Я пытаюсь понять значения, которые я получаю от своего MPU6050. Я считаю, что есть проблема с моим кодом. Я не совсем уверен, как должен выглядеть код. На MPU6050 не так много примеров.
Что не так?
Посмотрев на распечатку системы, я обнаружил, что записанные числа — это время, а не значения MPU6050. Почему я получаю нули и нан за?
У меня также была проблема с библиотекой, которая теперь исправлена.
Я получил код с сайта и изменил его, потому что он не работал у меня.
Это мой код:
// собираем показания
accelgyro.getMotion6(&ax, &ay, &az, &gx, &gy, &gz);
// применяем гироскопическую шкалу из таблицы данных
gsx = gx/gyroScale; gsy = gy/gyroScale; gsz = gz/gyroScale;
// рассчитываем углы акселерометра
ary = -(180/3.141592) * atan(ax / sqrt(square(ay) + square(az)));
arx = (180/3.141592) * atan(ay / sqrt(square(ax) + square(az)));
arz = (180/3.141592) * atan(sqrt(square(ay) + square(ax)) / az);
// устанавливаем начальные значения равными значениям ускорения
if (i == 1) {
grx = arx;
gry = ary;
grz = arz;
}
// интегрируем, чтобы найти угол гироскопа
else{
grx = grx + (timeStep * gsx);
gry = gry + (timeStep * gsy);
grz = grz + (timeStep * gsz);
}
// применить фильтр
rx = (0.1 * arx) + (0.9 * grx);
ry = (0.1 * ary) + (0.9 * gry);
rz = (0.1 * arz) + (0.9 * grz);
Serial.print(ax); Serial.print("\t");
Serial.print(ay); Serial.print("\t");
Serial.print(az); Serial.print("\t\t");
Serial.print(gx); Serial.print("\t");
Serial.print(gy); Serial.print("\t");
Serial.print(gz); Serial.print("\t\t");
Serial.print(arx); Serial.print("\t");
Serial.print(ary); Serial.print("\t");
Serial.print(arz); Serial.print("\t\t");
Serial.print(grx); Serial.print("\t");
Serial.print(gry); Serial.print("\t");
Serial.print(grz); Serial.print("\t\t");
Serial.print(rx); Serial.print("\t");
Serial.print(ry); Serial.print("\t");
Serial.println(rz);
Это результат, который я получаю
2 1.00 61.00 0.06000 0 0 0 0 0 0 nan nan nan nan nan nan nan nan nan
3 61.00 139.00 0.07800 0 0 0 0 0 0 nan nan nan nan nan nan nan nan nan
4 139.00 219.00 0.08000 0 0 0 0 0 0 nan nan nan nan nan nan nan nan nan
5 219.00 300.00 0.08100 0 0 0 0 0 0 nan nan nan nan nan nan nan nan nan
6 300.00 380.00 0.08000 0 0 0 0 0 0 nan nan nan nan nan nan nan nan nan
7 380.00 462.00 0.08200 0 0 0 0 0 0 nan nan nan nan nan nan nan nan nan
8 462.00 543.00 0.08100 0 0 0 0 0 0 nan nan nan nan nan nan nan nan nan
9 543.00 624.00 0.08100 0 0 0 0 0 0 nan nan nan nan nan nan nan nan nan
10 624.00 705.00 0.08100 0 0 0 0 0 0 nan nan nan nan nan nan nan nan nan
11 705.00 788.00 0.08300 0 0 0 0 0 0 nan nan nan
...
41 3223.00 3307.00 0.08400 0 0 0 0 0 0 nan nan nan nan nan nan nan nan nan
42 3307.00 3392.00 0.08500 0 0 0 0 0 0 nan nan nan nan nan nan nan nan nan
43 3392.00 3476.00 0.08400 0 0 0 0 0 0 nan nan nan nan nan nan nan nan nan
44 3476.00 3560.00 0.08400 0 0 0 0 0 0 nan nan nan nan nan nan nan nan nan
45 3560.00 3645.00 0.08500 0 0 0 0 0 0 nan nan nan nan nan nan nan nan nan
46 3645.00 3729.00 0.08400 0 0 0 0 0 0 nan nan nan nan nan nan nan nan nan
47 3729.00 3813.00 0.08400 0 0 0 0 0 0 nan nan nan nan nan nan nan nan nan
48 3813.00 3897.00 0.08400 0 0 0 0 0 0 nan nan nan nan nan nan nan nan nan
49 3897.00 3982.00 0.08500 0 0 0 0 0 0 nan nan nan nan nan nan nan nan nan
50 3982.00 4066.00 0.08400 0 0 0 0 0 0 nan nan nan nan nan nan nan nan nan
51 4066.00 4150.00 0.08400 0 0 0 0 0 0 nan nan nan nan nan nan nan nan nan
52 4150.00 4234.00 0.08400 0 0 0 0 0 0 nan nan nan nan nan nan nan nan nan
53 4234.00 4319.00 0.08500 0 0 0 0 0 0 nan nan nan nan nan nan nan nan nan
54 4319.00 4403.00 0.08400 0 0 0 0 0 0 nan nan nan nan nan nan nan nan nan
55 4403.00 4487.00 0.08400 0 0 0 0 0 0 nan nan nan nan nan nan nan nan nan
56 4487.00 4571.00 0.08400 0 0 0 0 0 0 nan nan nan nan nan nan nan nan nan
57 4571.00 4656.00 0.08500 0 0 0 0 0 0 nan nan nan nan nan nan nan nan nan
58 4656.00 4740.00 0.08400 0 0 0 0 0 0 nan nan nan nan nan nan nan nan nan
59 4740.00 4824.00 0.08400 0 0 0 0 0 0 nan nan nan nan nan nan nan nan nan
@Marc, 👍1
Обсуждение2 ответа
Вывод MPU 6050 нуждается в фильтрации/обработке, прежде чем вы сможете извлечь из него какой-либо смысл. Я успешно использовал библиотеку «MPU6050_6Axis_MotionApps20.h», она находится здесь: MPU6050_6Axis_MotionApps20. ч
Я написал пример здесь: MPU 6050 для MicroView.
Ваш код также получает значения?, @Marc
Библиотека творит чудеса, и вы можете получить углы Эйлера простыми и надежными (это углы ориентации). Другие измерения, такие как ускорение, также легко получить., @Cable998
Я получаю массу ошибок из библиотеки. Я добавил ошибки в код выше. Я был занят, поэтому это заняло так много времени., @Marc
Я думаю, что лучшим выбором для вас будет считывание необработанных данных с датчика с помощью библиотеки Wire.
Прежде всего необходимо подключить библиотеку Wire.h:
#include "Wire.h"
Следующий шаг – запустить связь I2C, вызвав следующую функцию в
.setup()
Wire.begin();
Теперь, когда мастер присоединился к шине I2C, все, что вам нужно сделать, это установить режим питания модуля, установив для регистра
0x6B
значение0x0
. . Вы можете использовать следующую функцию:
int sendCommand(int8_t register_address, int8_t register_value) {
Wire.beginTransmission(mpu_address);
Wire.write(register_address);
Wire.write(register_value);
int statusCommand = Wire.endTransmission(true);
Serial.print("I2C Address: "); Serial.print(mpu_address, HEX);
Serial.print(" Register address: "); Serial.print(register_address, HEX);
Serial.print(" Register value: "); Serial.print(register_value, HEX);
Serial.print(" Status command: "); Serial.println(statusCommand);
return statusCommand;
}
Обратите внимание, что адрес I2C по умолчанию для MPU6050 — 0x68
. Вы можете использовать сканер I2C, чтобы найти его адрес.
Чтобы фактически установить регистр 0x6B
в 0x0
, вы должны вызвать sendCommand
, как показано ниже:
sendCommand(0x6B,0x0);
- Запросите необработанные данные у MPU6050. Вы можете проверить карту регистрации MPU6050 для получения дополнительной информации. . Акселерометр можно найти от
0x3B
до0x40
, температуру от0x41
и0x42
и, наконец, гироскоп от0x43
в0x48
. ВАЖНО!!! Каждое значение регистра занимает 1 байт (int8_t), поэтому вам нужно получить значения двух регистров (2 байта) и сохранить их в int16_t.
Вот полный код для получения углов от датчика:
#include "Wire.h"
int8_t mpu_address = 0x68;
int sendCommand(int8_t register_address, int8_t register_value) {
Wire.beginTransmission(mpu_address);
Wire.write(register_address);
Wire.write(register_value);
int statusCommand = Wire.endTransmission(true);
Serial.print("I2C Address: "); Serial.print(mpu_address, HEX);
Serial.print(" Register address: "); Serial.print(register_address, HEX);
Serial.print(" Register value: "); Serial.print(register_value, HEX);
Serial.print(" Status command: "); Serial.println(statusCommand);
return statusCommand;
}
void setup() {
// присоединяемся к шине I2C
Wire.begin();
//запуск последовательной связи
Serial.begin(115200);
delay(1000);
/* sendCommand can return 5 possile values:
* -> 0:success
* -> 1:data too long to fit in transmit buffer
* -> 2:received NACK on transmit of address
* -> 3:received NACK on transmit of data
* -> 4:other error
*/
while(sendCommand(0x6B,0x0) != 0){
delay(1000);
}
Serial.println("MPU6050 started");
}
void convertRawDataToAngle(int16_t AcX, int16_t AcY, int16_t AcZ) {
int minVal = 265; int maxVal = 402;
int xAng = map(AcX, minVal, maxVal, -90, 90);
int yAng = map(AcY, minVal, maxVal, -90, 90);
int zAng = map(AcZ, minVal, maxVal, -90, 90);
int x = RAD_TO_DEG * (atan2(-yAng, -zAng)+PI);
int y = RAD_TO_DEG * (atan2(-xAng, -zAng) + PI);
int z = RAD_TO_DEG * (atan2(-yAng, -xAng)+PI);
Serial.print("X angle: "); Serial.print(x);
Serial.print(" Y angle: "); Serial.print(y);
Serial.print(" Z angle: "); Serial.print(z);
}
void readData(int8_t register_address) {
int bytesReceived = -1;
int statusCommand = -1;
do {
Wire.beginTransmission(mpu_address);
Wire.write(register_address);
statusCommand = Wire.endTransmission(false);
bytesReceived = Wire.requestFrom(mpu_address, 6, true);
Serial.print("I2C Address: "); Serial.print(mpu_address, HEX);
Serial.print(" Register address: "); Serial.print(register_address, HEX);
Serial.print(" Status command: "); Serial.print(statusCommand);
Serial.print(" Bytes received: "); Serial.println(bytesReceived);
} while (statusCommand != 0 && bytesReceived != 6);
//проверить, отправил ли MPU6050 все запрошенные данные
//всего 6 байт, по 2 байта на каждую ось
if (Wire.available() == 6) {
int16_t AcX = Wire.read() << 8 ;
AcX |= Wire.read();
int16_t AcY = Wire.read() << 8 ;
AcY |= Wire.read();
int16_t AcZ = Wire.read() << 8 ;
AcZ |= Wire.read();
convertRawDataToAngle(AcX, AcY, AcZ);
}
}
void loop() {
// поместите сюда свой основной код для повторного запуска:
readData(0x3B);
delay(100);
}
В Wire.read() << 8 | Wire.read()
, не указано, какой Wire.read()
выполняется первым. Возможно, вам повезет с определенной версией компилятора, но единственный безопасный способ получить байты в правильном порядке — выполнить чтение в двух отдельных операторах., @Edgar Bonet
Ну, я так и сделал, потому что запрашиваю 6 байт данных, начиная с регистра 0x3B. Я ожидаю получить их в том порядке, в котором я просил. Я прав? Если нет, можете ли вы дать мне советы, как повторить то, что вы сказали, чтобы получить байты в неправильном порядке?, @Bancila Sorin
Я не могу, так как я, вероятно, использую версию компилятора, не слишком далекую от вашей. Я хочу сказать, что тот факт, что он работает с компилятором, который мы сейчас используем, не означает, что код правильный. Правильным вариантом будет AcX = Wire.read() << 8; AcX |= Wire.read();
, @Edgar Bonet
О, теперь я понимаю, что вы имеете в виду. Спасибо за предложение. Я обновлю его в ближайшее время! Если есть что-то, что может пойти не так, я готов это исправить. Мне еще многому предстоит научиться!, @Bancila Sorin
- Как очистить буфер FIFO на MPU6050?
- Как сгенерировать аппаратное прерывание в mpu6050 для пробуждения Arduino из режима SLEEP_MODE_PWR_DOWN?
- Понимание того, почему следует избегать «String» и альтернативных решений
- Объяснение кода MPU6050
- Изменение адреса I2C MPU-6050
- Снять гравитацию с акселерометра MPU-6050
- Скорость передачи данных акселерометра mpu6050 в Arduino Uno и частота дискретизации mpu6050
- Как соединить L293D и MPU6050 для совместной работы?
Постоянно увеличивающиеся значения предполагают код, который пытается интегрировать измерение ускорения для определения скорости, что нереально сработать с бюджетным датчиком. Ваш вопрос недостаточно определен, чтобы задавать его здесь, поскольку вы не включаете код, генерирующий выходные столбцы, поэтому никто не может иметь никакого представления, кроме догадок, о том, что они представляют., @Chris Stratton
«Посмотрев на системный отпечаток, я обнаружил, что выписанные числа — это время, а не значения MPU6050. Почему я получаю нули и nan для?», @Marc
@ChrisStratton Я добавил весь вывод + печать., @Marc
@ChrisStratton Крис?, @Marc
Ваши данные явно ошибочны — посмотрите, как значения ax, ay, az появляются в другом месте в следующей строке. Вы передаете правильный тип указателя? Удалите весь остальной код и просто сосредоточьтесь на получении допустимых значений для них в качестве начала. Или, может быть, вам следует вернуться к исходному коду и выяснить, почему именно он не запустился., @Chris Stratton