IMU-сенсор на 10 степеней свободы (Troyka-модуль)

Тема в разделе "Arduino & Shields", создана пользователем MSK, 1 июн 2017.

  1. MSK

    MSK Нуб

    Имеется тройка http://wiki.amperka.ru/продукты:troyka-imu-10-dof
    Использую код из примера
    Код (C++):
    // библиотека для работы I²C
    #include <Wire.h>
    // библиотека для работы с модулями IMU
    #include <TroykaIMU.h>
    // множитель фильтра
    #define BETA 0.22
    // создаём объект для фильтра Madgwick
    Madgwick filter;
    // создаём объект для работы с акселерометром
    Accelerometer accel;
    // создаём объект для работы с гироскопом
    Gyroscope gyro;
    // создаём объект для работы с компасом
    Compass compass;
    // переменные для данных с гироскопа, акселерометра и компаса
    float gx, gy, gz, ax, ay, az, mx, my, mz;
    // получаемые углы ориентации (Эйлера)
    float yaw, pitch, roll;
    // переменная для хранения частоты выборок фильтра
    float fps = 100;
    // калибровочные значения компаса
    // полученные в калибровочной матрице из примера «compassCalibrateMatrixx»
    const double compassCalibrationBias[3] = {
      524.21,
      3352.214,
      -1402.236
    };
    const double compassCalibrationMatrix[3][3] = {
      {1.757, 0.04, -0.028},
      {0.008, 1.767, -0.016},
      {-0.018, 0.077, 1.782}
    };
    void setup()
    {
      // открываем последовательный порт
      Serial.begin(115200);
      Serial.println("Begin init...");
      // инициализация акселерометра
      accel.begin();
      // инициализация гироскопа
      gyro.begin();
      // инициализация компаса
      compass.begin();
      // калибровка компаса
      compass.calibrateMatrix(compassCalibrationMatrix, compassCalibrationBias);
      // выводим сообщение об удачной инициализации
      Serial.println("Initialization completed");
    }
    void loop()
    {
      // запоминаем текущее время
      unsigned long startMillis = millis();
      // считываем данные с акселерометра в единицах G
      accel.readGXYZ(&ax, &ay, &az);
      // считываем данные с гироскопа в радианах в секунду
      gyro.readRadPerSecXYZ(&gx, &gy, &gz);
      // считываем данные с компаса в Гауссах
      compass.readCalibrateGaussXYZ(&mx, &my, &mz);
      // устанавливаем коэффициенты фильтра
      filter.setKoeff(fps, BETA);
      // обновляем входные данные в фильтр
      filter.update(gx, gy, gz, ax, ay, az, mx, my, mz);
      // получение углов yaw, pitch и roll из фильтра
      yaw =  filter.getYawDeg();
      pitch = filter.getPitchDeg();
      roll = filter.getRollDeg();
      // выводим полученные углы в serial-порт
      Serial.print("yaw: ");
      Serial.print(yaw);
      Serial.print("\t\t");
      Serial.print("pitch: ");
      Serial.print(pitch);
      Serial.print("\t\t");
      Serial.print("roll: ");
      Serial.println(roll);
      // вычисляем затраченное время на обработку данных
      unsigned long deltaMillis = millis() - startMillis;
      // вычисляем частоту обработки фильтра
      fps = 1000 / deltaMillis;
    }
    Датчик откалиброван.
    Пример работает, но как-то странно:
    Датчик повернут на угол 128 градусов
    Код (C++):
    Begin init...
    Initialization completed
    -0.10
    -0.19
    -0.28
    -0.36
    -0.45
    -0.55
    -0.65
    -0.74
    -0.83
    -0.92
    ...
    -128.0
     
    т.е. идет изменение данных с мелким шагом до получения реального направления.
    Время этого процесса всегда разное, т.к. всегда начинается с 0, а датчик может находиться в момент включения с большим отклонением от севера.

    Это правильное поведение или что-то все же не так?
     
    Последнее редактирование: 19 июн 2017
  2. sslobodyan

    sslobodyan Гик

    Ну вы же пользуетесь фильтрованными данными, а любой фильтр вносит задержку. Хотите хорошее сглаживание - ждите дольше. Как то так.
     
  3. MSK

    MSK Нуб

    Я видимо не четко описал ситуацию.
    Датчик зафиксирован в положении 359гр, а при подключении, я в консоли в течении нескольких секунд наблюдаю рост показаний от 0 до 359, а не колебания вокруг значения 359.
    Хотелось бы понять, это с датчика такие данные приходят с нарастанием или кривость обработки показаний.
     
  4. sslobodyan

    sslobodyan Гик

    Повторю еще раз. Датчик не знает при старте куда он повернут, поэтому у него это 0. Затем постепенно (задержка фильтра) датчик приходит к пониманию своего положения. Так и должно быть.
     
    arkadyf нравится это.
  5. Shikaryn

    Shikaryn Нуб

    дело в том что фильтр меджвика показывает данные с гироскопа компенсированные данными с магнитометра. По сути каждая новая итерация содержит прибавку от магнитометра с коэффициентом пропорциональным BETA. Установите этот коэффициент побольше и значения будут быстрее сходится к реальной величине. В 0 момент времени азимут равен конечно 0, т.к. программа при включении не знает куда повернут датчик. Но потом магнитометр начинает "поворачивать" показания в нужную сторону. Так работает фильтр