Понимание значений от 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

, 👍1

Обсуждение

Постоянно увеличивающиеся значения предполагают код, который пытается интегрировать измерение ускорения для определения скорости, что нереально сработать с бюджетным датчиком. Ваш вопрос недостаточно определен, чтобы задавать его здесь, поскольку вы не включаете код, генерирующий выходные столбцы, поэтому никто не может иметь никакого представления, кроме догадок, о том, что они представляют., @Chris Stratton

«Посмотрев на системный отпечаток, я обнаружил, что выписанные числа — это время, а не значения MPU6050. Почему я получаю нули и nan для?», @Marc

@ChrisStratton Я добавил весь вывод + печать., @Marc

@ChrisStratton Крис?, @Marc

Ваши данные явно ошибочны — посмотрите, как значения ax, ay, az появляются в другом месте в следующей строке. Вы передаете правильный тип указателя? Удалите весь остальной код и просто сосредоточьтесь на получении допустимых значений для них в качестве начала. Или, может быть, вам следует вернуться к исходному коду и выяснить, почему именно он не запустился., @Chris Stratton


2 ответа


1

Вывод MPU 6050 нуждается в фильтрации/обработке, прежде чем вы сможете извлечь из него какой-либо смысл. Я успешно использовал библиотеку «MPU6050_6Axis_MotionApps20.h», она находится здесь: MPU6050_6Axis_MotionApps20. ч

Я написал пример здесь: MPU 6050 для MicroView.

,

Ваш код также получает значения?, @Marc

Библиотека творит чудеса, и вы можете получить углы Эйлера простыми и надежными (это углы ориентации). Другие измерения, такие как ускорение, также легко получить., @Cable998

Я получаю массу ошибок из библиотеки. Я добавил ошибки в код выше. Я был занят, поэтому это заняло так много времени., @Marc


2

Я думаю, что лучшим выбором для вас будет считывание необработанных данных с датчика с помощью библиотеки Wire.

  1. Прежде всего необходимо подключить библиотеку Wire.h:

    #include "Wire.h"
    
  2. Следующий шаг – запустить связь I2C, вызвав следующую функцию в setup()

    .
    Wire.begin();
    
  3. Теперь, когда мастер присоединился к шине 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);
  1. Запросите необработанные данные у 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