IMU-сенсор на 9 степеней свободы (Trema-модуль V2.0)

Trema-модуль IMU 9 DOF - это модуль позволяющий определять своё положение в пространстве, например, по углам Эйлера: «крен», «тангаж» и «курс». Помимо углов Эйлера, с модуля можно получать следующие данные: угловое ускорение (проекция кажущегося ускорения), истинное ускорение, угловую скорость, индукцию магнитного поля и температуру. Все параметры кроме температуры выводятся для трёх осей X, Y и Z. Положение и направление осей указано на плате модуля.

Видео:


Общие сведения:

Trema-модуль IMU 9 DOF (Inertial Measurement Unit 9 Degrees Of Freedom) - инерционное измерительное устройство на 9 степеней свободы, построен на базе чипа BMX055 (Bosch Module X) - модуль фирмы «Bosch», где X означает что в чип интегрировано несколько датчиков: (accelerometer) акселерометр, (gyroscope) гироскоп, (magnetometer) магнитометр. Все 3 датчика чипа BMX055 выдают показания по 3 осям (X,Y,Z), следовательно, с чипа считываются показания для 9 осей (9 DOF).

Специально для Trema-модуля IMU 9 DOF нами разработана библиотека iarduino_Position_BMX055 которая значительно упрощает процесс получения данных с модуля. Библиотека способна работать как со всеми датчиками сразу, так и по отдельности. В библиотеке имеются функции аппаратного самотестирования и калибровки датчиков, есть возможность выбора диапазонов измерений, частоты обновлений и единиц измерений выводимых данных. В библиотеку интегрированы фильтры Маджвика (по умолчанию) и Махони (можно выбрать).

Акселерометр - датчик измеряющий угловое ускорение (проекцию кажущегося ускорения), которая состоит из истинного ускорения и ускорения свободного падения. Показания датчика можно получать в м/c2, или в g (количестве ускорений свободного падения). Если датчик неподвижен, или движется равномерно, то выходные данные датчика будут совпадать с ускорением свободного падения, вектор которого всегда направлен вниз (к земле). Таким образом, зная проекцию вектора ускорения свободного падения на оси X, Y, Z, можно вычислить положение датчика относительно поверхности земли (углы: «крен» и «тангаж»), но только если датчик неподвижен, или движется равномерно!

Гироскоп - датчик измеряющий угловую скорость вокруг собственных осей. Показания датчика можно получать в °/с, или рад/с. Данный датчик способен определять воздействие момента внешней силы вокруг своих осей. Используя эти данные можно компенсировать воздействие истинного ускорения на акселерометр, следовательно, используя акселерометр и гироскоп, получать положение этих датчиков относительно поверхности земли (углы: «крен» и «тангаж») во время их неравномерного движения.

Магнитометр - датчик измеряющий индукцию магнитного поля. Показания датчика можно получать в мГс, или в мкТл. Данный датчик способен определять своё положение в пространстве относительно магнитных полюсов земли. Добавление этого датчика к двум предыдущим даёт возможность получить последний угол Эйлера - «курс», а так же повлиять на точность определения предыдущих двух углов «крен» и «тангаж».

Показания всех датчиков можно использовать как входные данные для фильтра Маджвика, Махони, Калмана, или др., для получения кватернионов абсолютной ориентации устройства, из которых рассчитываются углы Эйлера («крен», «курс» и «тангаж»). Некоторые фильтры позволяют получать кватернионы используя данные только первых двух датчиков (без магнитометра), из которых так же можно рассчитать углы Эйлера, но угол «курс» будет не истинным, а рассчитанным, он будет указывать не на север, а на изначальное направление датчика.

Углы Эйлера - позволяют определить положение объекта в трёхмерном (евклидовом) пространстве. Для определения положения используются 3 угла - «крен», «тангаж» и «курс».

  • «Крен» (Roll) - определяет наклон тела вокруг продольной оси. Например крен самолёта показывает насколько градусов в бок наклонились его крылья относительно земной поверхности. Если самолёт находится параллельно земле, то крен = 0°. Если самолёт накренился (наклонился) влево (левое крыло ниже правого), то крен отрицательный (от 0° до -90°). Если самолёт накренился (наклонился) вправо (левое крыло выше правого), то крен положительный (от 0° до 90°).
  • «Тангаж» (Pitch) - определяет наклон продольной оси. Например тангаж самолёта показывает насколько градусов поднят (или опущен) его нос относительно земной поверхности. Если самолёт находится параллельно земле, то тангаж = 0°. Если самолёт поднимает нос (кабрирует, взлетает), то тангаж положительный (от 0°, через 90°-вертикальный взлёт, до 180°-полёт назад вверх ногами). Если самолёт опускает нос (пикирует, приземляется), то тангаж отрицательный (от 0°, через -90°-вертикальное падение, до -180°-полёт назад вверх ногами).
  • «Курс» (Yaw) - это самый простой для понимания угол Эйлера (еще его нарывают «Рыскание»), он определяет направление вдоль земной поверхности. Например для самолёта курс определяет куда самолёт летит. Если самолёт летит на север, то курс = 0°. Если самолёт отклоняется от севера влево (на запад, или против часовой стрелки если смотреть сверху) то курс положительный (от 0°, через 90°-запад, до 180°-юг). Если самолёт отклоняется от севера вправо (на восток, или по часовой стрелке если смотреть сверху) то курс отрицательный (от 0°, через -90°-восток, до -180°-юг).

Спецификация:

  • Чип BMX055
  • Питание модуля: 3,3 В или 5 В (оба напряжения входят в диапазон допустимых значений).
  • Диапазоны измерений:
    • акселерометра: ±2g, ±4g, ±8g, ±16g, где g - ускорение свободного падения = 9,81 м/c2.
    • гироскопа: ±2000 °/с, ±1000 °/с, ±500 °/с, ±250 °/с, ±125 °/с.
    • магнитометра: ±1300 мкТл для осей XY, ±2500 мкТл для оси Z.
  • Максимальная чувствительность:
    • акселерометра: 9,5 * 10-3 м/c2.
    • гироскопа: 3,8 * 10-3 °/c.
    • магнитометра: 625 мкГс.
  • Частота обновления фильтрованных данных (в Гц):
    • акселерометра: 8, 16, 31, 63, 125, 250, 500, 1000.
    • гироскопа: 12, 23, 32, 64, 47, 116, 230.
    • магнитометра: 2, 6, 8, 10, 15, 20, 25, 30.
  • Входной уровень «0» на шине I2C: -0,3 ... 0,3 * Vcc В.
  • Входной уровень «1» на шине I2C: 0,7 * Vcc ... Vcc + 0,3 В.
  • Рабочая температура: -40 ... 85 °C.
  • Габариты модуля 30x30 мм.

Подключение:

Trema-модуль IMU 9 DOF подключается к аппаратной или программной шине I2C Arduino. В комплекте имеется кабель для быстрого и удобного подключения модуля к колодке I2C на Trema Shield. Если на шине I2C уже имеется другое устройство, то для подключения модуля, предлагаем воспользоваться I2C Hub.

Подключение IMU 9 DOF к Arduino Uno

Схема установки модуля при его подключении через Trema Set Shield.

При подключении Trema-модуля IMU 9 DOF к другим платам, например, WEMOS D1 mini или WEMOS D1 mini Pro на базе микроконтроллера ESP8266, и т.д. То перед подключением библиотеки iarduino_Position_BMX055, нужно подключить библиотеку Wire, как это описано в разделе Wiki - расширенные возможности библиотек iarduino для шины I2C.

Питание:

Входное напряжение питания 3,3 В, или 5 В постоянного тока, подаётся на выводы Vcc и GND модуля.

Работа с модулем:

Для работы с Trema-модулем IMU 9 DOF предлагаем воспользоваться библиотекой iarduino_Position_BMX055 которая значительно упрощает процесс работы с модулем.

Примеры:

Самотестирование всех датчиков модуля:
/* САМОТЕСТИРОВАНИЕ ДАТЧИКОВ МОДУЛЯ */ // 
                                       //
#include <iarduino_Position_BMX055.h>  // Подключаем библиотеку iarduino_Position_BMX055 для работы с Trema-модулем IMU 9 DOF.
iarduino_Position_BMX055 sensor(BMX);  // Создаём объект sensor указывая параметр BMX - требуется работать со всеми датчиками модуля.
                                       // Если указать параметр BMA - то объект будет работать только с акселерометром.
                                       // Если указать параметр BMG - то объект будет работать только с гироскопом.
                                       // Если указать параметр BMM - то объект будет работать только с магнитометром.
                                       // Если указать параметр BMX - то объект будет работать со всеми датчиками сразу.
void setup(){                          // 
     Serial.begin(9600);               // Инициируем передачу данных в монитор последовательного порта на скорости 9600 бит/сек.
     while(!Serial){}                  // Ждём готовность Serial к передаче данных в монитор последовательного порта.
     Serial.println("Тест модуля ...");// Выводим надпись в монитор последовательного порта.
     sensor.begin();                   // Инициируем работу с датчиками объекта sensor.
     switch(sensor.test()){            // Получаем результат самотестирования для его сравнения с указанными ниже константами.
         case 0:          Serial.println("Аппаратное самотестирование всех датчиков успешно пройдено!"); break;
         case BMA_ERR_ID: Serial.println("Акселерометр не найден.");                                     break;
         case BMG_ERR_ID: Serial.println("Гироскоп не найден.");                                         break;
         case BMM_ERR_ID: Serial.println("Магнитометр не найден.");                                      break;
         case BMA_ERR_ST: Serial.println("Акселерометр не прошел самотестирование.");                    break;
         case BMG_ERR_ST: Serial.println("Гироскоп не прошел самотестирование.");                        break;
         case BMM_ERR_ST: Serial.println("Магнитометр не прошел самотестирование.");                     break;
         default:         Serial.println("Модуль не прошел самотестирование по неизвестной причине.");   break;
     }                                 //
}                                      //
void loop(){}                          //

Во время самотестирования модуль должен находиться в неподвижном состоянии. Если все датчики модуля работают и их показания не выходят за допустимые пределы, то в мониторе последовательного порта появится надпись «Аппаратное самотестирование всех датчиков успешно пройдено!».

Определение положения модуля в пространстве:
/* ОПРЕДЕЛЕНИЕ ПОЛОЖЕНИЯ МОДУЛЯ */     // 
                                       //
#include <iarduino_Position_BMX055.h>  // Подключаем библиотеку iarduino_Position_BMX055 для работы с Trema-модулем IMU 9 DOF.
iarduino_Position_BMX055 sensor(BMX);  // Создаём объект sensor указывая что требуется работать со всеми датчиками модуля.
                                       // Если указать параметр BMA - то объект будет работать только с акселерометром.
                                       // Если указать параметр BMG - то объект будет работать только с гироскопом.
                                       // Если указать параметр BMM - то объект будет работать только с магнитометром.
                                       // Если указать параметр BMX - то объект будет работать со всеми датчиками сразу.
void setup(){                          // 
     Serial.begin(9600);               // Инициируем передачу данных в монитор последовательного порта на скорости 9600 бит/сек.
     while(!Serial){}                  // Ждём готовность Serial к передаче данных в монитор последовательного порта.
     sensor.begin();                   // Инициируем работу с датчиками объекта sensor.
}                                      //
void loop(){                           //
     sensor.read();                    // Функция read() читает данные того датчика, для которого был создан объект.
                                       // Для объекта работающего со всеми датчиками сразу, функция read() может принять
                                       // один из трёх параметров: BMX_DEG, BMX_RAD, или BMX_M_S. Если параметра нет, то используется параметр по умолчанию.
                                       // sensor.read(BMX_DEG); - читать углы Эйлера в градусах (по умолчанию).
                                       // sensor.read(BMX_RAD); - читать углы Эйлера в радианах.
                                       // sensor.read(BMX_M_S); - читать истинное ускорение в м/с².
                                       // Данные прочитанные функцией read() сохраняются в переменных axisX, axisY, axisZ и temp.
     Serial.print("КУРС=");   Serial.print(sensor.axisZ); Serial.print(", ");
     Serial.print("ТАНГАЖ="); Serial.print(sensor.axisX); Serial.print(", ");
     Serial.print("КРЕН=");   Serial.print(sensor.axisY); Serial.print("\r\n");
}

У объекта созданного с параметром (BMX), функция read() может читать либо углы Эйлера в градусах или радианах, либо истинное ускорение модуля в м/с² (см. комментарии к строкам скетча). Результат сохраняется в переменных: axisX, axisY, axisZ (для осей X, Y, X) и temp (температура в °C).

Если в начале данного скетча объявить константу BMX055_DISABLE_BMM, то библиотека не будет работать с магнитометром. В таком случае углы Эйлера будут получены только от акселерометра и гироскопа, при этом угол «курс» будет указывать не на север, а на то направление, куда был ориентирован модуль при старте:

/* ОПРЕДЕЛЕНИЕ ПОЛОЖЕНИЯ МОДУЛЯ */     // Положение модуля будет рассчитано без данных от магнитометра.
                                       //
#define BMX055_DISABLE_BMM             // Не использовать магнитометр. Эта строка является единственным отличием кода данного скетча от предыдущего!
#include <iarduino_Position_BMX055.h>  // Подключаем библиотеку iarduino_Position_BMX055 для работы с Trema-модулем IMU 9 DOF.
iarduino_Position_BMX055 sensor(BMX);  // Создаём объект sensor указывая что требуется работать со всеми датчиками модуля.
                                       // Если указать параметр BMA - то объект будет работать только с акселерометром.
                                       // Если указать параметр BMG - то объект будет работать только с гироскопом.
                                       // Если указать параметр BMM - то объект будет работать только с магнитометром.
                                       // Если указать параметр BMX - то объект будет работать со всеми датчиками сразу.
void setup(){                          // 
     Serial.begin(9600);               // Инициируем передачу данных в монитор последовательного порта на скорости 9600 бит/сек.
     while(!Serial){}                  // Ждём готовность Serial к передаче данных в монитор последовательного порта.
     sensor.begin();                   // Инициируем работу с датчиками объекта sensor.
}                                      //
void loop(){                           //
     sensor.read();                    // Функция read() читает данные того датчика, для которого был создан объект.
                                       // Для объекта работающего со всеми датчиками сразу, функция read() может принять
                                       // один из трёх параметров: BMX_DEG, BMX_RAD, или BMX_M_S. Если параметра нет, то используется параметр по умолчанию.
                                       // sensor.read(BMX_DEG); - читать углы Эйлера в градусах (по умолчанию).
                                       // sensor.read(BMX_RAD); - читать углы Эйлера в радианах.
                                       // sensor.read(BMX_M_S); - читать истинное ускорение в м/с².
                                       // Данные прочитанные функцией read() сохраняются в переменных axisX, axisY, axisZ и temp.
     Serial.print("КУРС=");   Serial.print(sensor.axisZ); Serial.print(", ");
     Serial.print("ТАНГАЖ="); Serial.print(sensor.axisX); Serial.print(", ");
     Serial.print("КРЕН=");   Serial.print(sensor.axisY); Serial.print("\r\n");
}

Код данного скетча отличается от предыдущего только наличием строки #define BMX055_DISABLE_BMM, в начале скетча.

Получение данных с каждого датчика по отдельности в одном скетче:

/* ОТДЕЛЬНОЕ ЧТЕНИЕ ВСЕХ ДАТЧИКОВ */   // 
                                       //
#include <iarduino_Position_BMX055.h>  // Подключаем библиотеку iarduino_Position_BMX055 для работы с Trema-модулем IMU 9 DOF.
iarduino_Position_BMX055 sensorA(BMA); // Создаём объект sensorA указывая что ему требуется работать только с акселерометром.
iarduino_Position_BMX055 sensorG(BMG); // Создаём объект sensorG указывая что ему требуется работать только с гироскопом.
iarduino_Position_BMX055 sensorM(BMM); // Создаём объект sensorM указывая что ему требуется работать только с магнитометром.
                                       // Имена создаваемых объектов должны отличаться!
void setup(){                          // 
     Serial.begin(9600);               // Инициируем передачу данных в монитор последовательного порта на скорости 9600 бит/сек.
     while(!Serial){}                  // Ждём готовность Serial к передаче данных в монитор последовательного порта.
     sensorA.begin();                  // Инициируем работу с датчиком объекта sensorA - это акселерометр.
     sensorG.begin();                  // Инициируем работу с датчиком объекта sensorG - это гироскоп.
     sensorM.begin();                  // Инициируем работу с датчиком объекта sensorM - это магнитометр.
}                                      //
void loop(){                           // 
                                       // Функция read() читает данные того датчика, для которого был создан объект.
                                       // Так как мы создали 3 разных объекта для работы с разными датчиками, то
                                       // данные читаемые функцией read() будут зависеть от объекта для которого она вызвана.
                                       // Функцию read() можно вызвать с параметром, выбрав единицы измерений выводимых данных.
                                       // Если функция read вызывается без параметра, то данные выводятся в единицах по умолчанию.
     sensorA.read();                   // sensorA.read(BMA_M_S);   читать угловое ускорение в м/с² (по умолчанию).
                                       // sensorA.read(BMA_G);     читать угловое ускорение в g.
                                       // sensorA.read(BMA_DEG);   читать углы «крен» и «тангаж» в градусах.
                                       // sensorA.read(BMA_RAD);   читать углы «крен» и «тангаж» в радианах.
     sensorG.read();                   // sensorG.read(BMG_DEG_S); читать угловую скорость в °/c. (по умолчанию).
                                       // sensorG.read(BMG_RAD_S); читать угловую скорость в рад/c.
     sensorM.read();                   // sensorM.read(BMM_MG);    читать индукцию магнитного поля в мГс. (по умолчанию).
                                       // sensorM.read(BMM_MCT);   читать индукцию магнитного поля в мкТл.
                                       // Данные прочитанные функцией read() сохраняются в переменных axisX, axisY, axisZ и temp.
                                       // Значение этих переменных у каждого объекта своё.
     Serial.print("АКСЕЛЕРОМЕТР(");
     Serial.print("X="); Serial.print(sensorA.axisX); Serial.print(", ");
     Serial.print("Y="); Serial.print(sensorA.axisY); Serial.print(", ");
     Serial.print("Z="); Serial.print(sensorA.axisZ); Serial.print(" м/с²) ");
     Serial.print("ГИРОСКОП(");
     Serial.print("X="); Serial.print(sensorG.axisX); Serial.print(", ");
     Serial.print("Y="); Serial.print(sensorG.axisY); Serial.print(", ");
     Serial.print("Z="); Serial.print(sensorG.axisZ); Serial.print(" °/c) ");
     Serial.print("МАГНИТОМЕТР(");
     Serial.print("X="); Serial.print(sensorM.axisX); Serial.print(", ");
     Serial.print("Y="); Serial.print(sensorM.axisY); Serial.print(", ");
     Serial.print("Z="); Serial.print(sensorM.axisZ); Serial.print(" мГс)\r\n");
}

В этом скетче мы создали 3 объекта (sensorA, sensorG и sensorM), указав каждому объекту работать со своим датчиком. Далее для каждого объекта была вызвана функция read(), которая сохранила данные в переменных (axisX, axisY, axisZ и temp) для своего объекта.

Получение данных с акселерометра:

/* ЧТЕНИЕ ДАННЫХ АКСЕЛЕРОМЕТРА     */  // 
                                       //
#include <iarduino_Position_BMX055.h>  // Подключаем библиотеку iarduino_Position_BMX055 для работы с Trema-модулем IMU 9 DOF.
iarduino_Position_BMX055 sensor(BMA);  // Создаём объект sensor указывая что ему требуется работать только с акселерометром.
                                       // Если указать параметр BMA - то объект будет работать только с акселерометром.
                                       // Если указать параметр BMG - то объект будет работать только с гироскопом.
                                       // Если указать параметр BMM - то объект будет работать только с магнитометром.
                                       // Если указать параметр BMX - то объект будет работать со всеми датчиками сразу.
                                       // 
void setup(){                          // 
     Serial.begin(9600);               // Инициируем передачу данных в монитор последовательного порта на скорости 9600 бит/сек.
     while(!Serial){}                  // Ждём готовность Serial к передаче данных в монитор последовательного порта.
     sensor.begin();                   // Инициируем работу с акселерометром, так как именно для работы с ним создан объект sensor
}                                      //
void loop(){                           // 
     sensor.read();                    // Функция read() читает данные того датчика, для которого был создан объект.
                                       // Для объекта работающего с акселерометром, функция read() может принять
                                       // один из четырёх параметров: BMA_M_S, BMA_G, BMA_DEG, или BMA_RAD.
                                       // Если параметра нет, то используется параметр по умолчанию
                                       // sensor.read(BMA_M_S); читать угловое ускорение в м/с² (по умолчанию).
                                       // sensor.read(BMA_G);   читать угловое ускорение в g.
                                       // sensor.read(BMA_DEG); читать углы «крен» и «тангаж» в градусах.
                                       // sensor.read(BMA_RAD); читать углы «крен» и «тангаж» в радианах.
                                       // Данные прочитанные функцией read() сохраняются в переменных axisX, axisY, axisZ и temp.
     Serial.print("X="); Serial.print(sensor.axisX); Serial.print(", ");
     Serial.print("Y="); Serial.print(sensor.axisY); Serial.print(", ");
     Serial.print("Z="); Serial.print(sensor.axisZ); Serial.print(" м/с² \r\n");
}

Этот скетч выводит только данные углового ускорения по осям XYZ в монитор последовательного порта. Данный скетч идентичен предыдущему, за исключением того, что в нём исключены все строки в которых присутствовали объекты sensorG и sensorM (объявленные для работы с гироскопом и магнитометром). Аналогичным образом можно вывести показания только гироскопа, или только магнитометра.

Получение данных с акселерометра с увеличением его диапазона измерений:

По умолчанию акселерометр измеряет данные углового ускорения в диапазоне ±2g, где g - ускорение свободного падения = 9.81 м/с². Если модуль работает с большими ускорениями, то диапазон измерений акселерометра можно расширить вызвав функцию setScale() с указанием требуемого диапазона: BMA_2G = ±2g (по умолчанию), BMA_4G = ±4g, BMA_8G = ±8g, BMA_16G = ±16g.

/* ЧТЕНИЕ ДАННЫХ АКСЕЛЕРОМЕТРА     */  // Акселерометр будет работать в диапазоне ±39.24 м/с².
                                       //
#include <iarduino_Position_BMX055.h>  // Подключаем библиотеку iarduino_Position_BMX055 для работы с Trema-модулем IMU 9 DOF.
iarduino_Position_BMX055 sensor(BMA);  // Создаём объект sensor указывая что ему требуется работать только с акселерометром.
                                       // 
void setup(){                          // 
     Serial.begin(9600);               // Инициируем передачу данных в монитор последовательного порта на скорости 9600 бит/сек.
     while(!Serial){}                  // Ждём готовность Serial к передаче данных в монитор последовательного порта.
     sensor.begin();                   // Инициируем работу с акселерометром, так как именно для работы с ним создан объект sensor
     sensor.setScale(BMA_4G);          // Указываем акселерометру производить измерения в новом диапазоне ±4g, где g=9.81 м/с².
     sensor.setFastOffset();           // Выполняем калибровку акселерометра (быструю компенсацию смещения данных) после установки нового диапазона.
}                                      // Акселерометр способен работать в диапазонах: BMA_2G, BMA_4G, BMA_8G, BMA_16G.
void loop(){                           // 
     sensor.read();                    // Читаем данные акселерометра в единицах по умолчанию (м/с²).
     Serial.print("X="); Serial.print(sensor.axisX); Serial.print(", ");
     Serial.print("Y="); Serial.print(sensor.axisY); Serial.print(", ");
     Serial.print("Z="); Serial.print(sensor.axisZ); Serial.print(" м/с²)\r\n");
}

Код данного скетча отличается от предыдущего только тем, что в конце кода setup вызываются функции setScale() и setFastOffset(), устанавливающие новый диапазон измерений и калибровку. Чем шире установленный диапазон измерений, тем меньше точность показаний. Калибровка должна производится при неподвижном датчике. Аналогичным образом можно изменить диапазон измерений гироскопа (см. описании функции setScale).

Получение кватернионов для программ визуализации:

/* ЧТЕНИЕ КВАТЕРНИОНОВ */              // 
                                       //
#define BMX055_DISABLE_BMM             // Не использовать магнитометр. Курс будет ориентирован на начальное положение модуля
#include <iarduino_Position_BMX055.h>  // Подключаем библиотеку iarduino_Position_BMX055 для работы с Trema-модулем IMU 9 DOF.
iarduino_Position_BMX055 sensor(BMX);  // Создаём объект sensor указывая что требуется работать со всеми датчиками модуля.
                                       // Если указать параметр BMA - то объект будет работать только с акселерометром.
                                       // Если указать параметр BMG - то объект будет работать только с гироскопом.
                                       // Если указать параметр BMM - то объект будет работать только с магнитометром.
                                       // Если указать параметр BMX - то объект будет работать со всеми датчиками сразу.
void setup(){                          // 
     Serial.begin(9600);               // Инициируем передачу данных в монитор последовательного порта на скорости 9600 бит/сек.
     while(!Serial){}                  // Ждём готовность Serial к передаче данных в монитор последовательного порта.
     sensor.begin();                   // Инициируем работу с датчиками объекта sensor.
}                                      //
void loop(){                           //
     sensor.read();                    // Функция read() читает данные того датчика, для которого был создан объект.
                                       // В данном скетче параметр функции read() не имеет ни какого значения, так как
                                       // он влияет только на единицы измерений данных в переменных axisX, axisY, axisZ.
    Serial.print(sensor.q1);           // Выводим кватернион q1.
    Serial.print(",");                 // разделяем запятой.
    Serial.print(sensor.q2);           // Выводим кватернион q2.
    Serial.print(",");                 // разделяем запятой.
    Serial.print(sensor.q3);           // Выводим кватернион q3.
    Serial.print(",");                 // разделяем запятой.
    Serial.println(sensor.q4);         // Выводим кватернион q4 и завершаем строку.
}                                      //

Данный скетч использовался в видеообзоре.

Все скетчи представленных примеров имеются в папке examples библиотеки iarduino_Position_BMX055.

Описание функций библиотеки:

Данная библиотека может использовать как аппаратную, так и программную реализацию шины I2C.
О том как выбрать тип шины I2C рассказано в статье Wiki - расширенные возможности библиотек iarduino для шины I2C.

Подключение библиотеки:
#include <iarduino_Position_BMX055.h>  // Подключаем библиотеку iarduino_Position_BMX055 для работы с Trema-модулем IMU 9 DOF
iarduino_Position_BMX055 sensor(BMX);  // Создаём объект sensor указывая датчик, данные которого Вы хотите получать (BMX - получать данные со всех датчиков модуля)
                                       // BMA - получать данные только с акселерометра
                                       // BMG - получать данные только с гироскопа
                                       // BMM - получать данные только с магнитометра
                                       // BMX - получать данные со всех датчиков модуля

При создании объекта требуется указать, с каким датчиком (или датчиками) он будет работать.
Все функции и методы созданного объекта будут применяться только к тому датчику (датчикам) для которого он был создан.

    Допускается создание объекта с одним из 4 параметров:
  • BMA - объект будет работать только с акселерометром.
  • BMG - объект будет работать только с гироскопом.
  • BMM - объект будет работать только с магнитометром.
  • BMX - объект будет работать со всеми датчиками модуля.

Если требуется работать с разными датчиками по отдельности, допускается создание нескольких объектов.

Освобождение памяти:

При использовании данной библиотеки можно освободить память за счёт отключения кода неиспользуемых датчиков модуля. Это нужно делать только если у Вас не хватает памяти программ. Память освобождается если объявить в начале скетча следующие константы:

  • BMX055_DISABLE_BMA - не использовать код для работы с акселерометром
  • BMX055_DISABLE_BMG - не использовать код для работы с гироскопом
  • BMX055_DISABLE_BMM - не использовать код для работы с магнитометром
// Если Вы используете данные только магнитометра (например, создаёте компас), то освободить память можно за счёт неиспользуемых датчиков (акселерометра и гироскопа).
#define BMX055_DISABLE_BMA             // Не использовать код для работы с акселерометром
#define BMX055_DISABLE_BMG             // Не использовать код для работы с гироскопом
#include <iarduino_Position_BMX055.h>  // Подключаем библиотеку iarduino_Position_BMX055 для работы с Trema-модулем IMU 9 DOF
iarduino_Position_BMX055 sensor(BMМ);  // Создаём объект sensor, указывая что он будет работать с магнитометром (BMM)
Смена фильтра при получении углов Эйлера:

Углы Эйлера («крен», «тангаж» и «курс») рассчитываются из кватернионов, а они вычисляются фильтром. При объявлении объекта с атрибутом BMX (объект работает со всеми датчиками), подключается фильтр Маджвика (по умолчанию), но если Вы желаете использовать фильтр Махони, то нужно отключить код фильтра Маджвика и подключить код фильтра Махони:

//#define BMX055_DISABLE_MADGWICK      // Не использовать код фильтра Маджвика
//#define BMX055_ENABLE_MAHONY         // Использовать код фильтра Махони
#include <iarduino_Position_BMX055.h>  // Подключаем библиотеку iarduino_Position_BMX055 для работы с Trema-модулем IMU 9 DOF
iarduino_Position_BMX055 sensor(BMX);  // Создаём объект sensor, указывая что он будет работать со всеми датчиками (BMX)
Функция begin();
  • Назначение: Инициализация работы с выбранным датчиком (датчиками) модуля.
  • Синтаксис: begin( [КАЛИБРОВКА] );
  • Параметры:
    • КАЛИБРОВКА - не обязательный параметр (true или false) указывающий на необходимость калибровки датчика(ов).
  • Возвращаемые значения: bool - результат инициализации датчика (true или false).
  • Примечание:
    • Функцию необходимо вызывать до обращения к остальным функциям и методам объекта.
    • Функцию достаточно вызвать 1 раз в коде setup.
    • Вызов функции без параметра аналогичен вызову с параметром false.
    • Калибровку можно произвести функцией setFastOffset() в любое время выполнения скетча.
    • Подробнее о калибровке рассказано ниже в описании функции setFastOffset().
  • Пример:
sensor.begin();                        // Инициализация датчика с которым работает объект sensor (без выполнения калибровки)
Функция test();
  • Назначение: Выполнение аппаратного самотестирования датчика (датчиков) модуля.
  • Синтаксис: test();
  • Параметры: нет.
  • Возвращаемые значения: зависят от того, для какого датчика(ов) создан объект.
    • 0 - аппаратное самотестирование датчика (датчиков) успешно пройдено.
    • BMA_ERR_ID - акселерометр не найден.
    • BMG_ERR_ID - гироскоп не найден.
    • BMM_ERR_ID - магнитометр не найден.
    • BMA_ERR_ST - акселерометр не прошел самотестирование.
    • BMG_ERR_ST - гироскоп не прошел самотестирование.
    • BMM_ERR_ST - магнитометр не прошел самотестирование.
  • Примечание:
    • Функция инициирует выполнение аппаратного самотестирования датчика (датчиков) модуля, где проверяется не только работоспособность датчика, но и корректность выдаваемых им показаний.
    • Выполнение функции занимает некоторое время, которое зависит от тестируемого датчика (датчиков).
    • Если объект работает со всеми датчиками, то и самотестирование будет запущено для всех датчиков.
    • В разделе «Примеры» настоящей статьи, описан более подробный вариант использования функции.
  • Пример:
if(sensor.test()){Serial.print("Err");} // Выполнение аппаратного самотестирования датчика с которым работает объект sensor
                                        // При выявлении проблем с датчиком, на экране появится надпись "Err".
Функция read();
  • Назначение: Выполнение чтения показаний датчика (датчиков) модуля.
  • Синтаксис: read( [ЕДИНИЦЫ_ИЗМЕРЕНИЯ] );
  • Параметр: зависит от того, с каким датчиком работает объект.
    • Если объект работает с акселерометром:
      • BMA_M_S - выводить угловое ускорение в м/с² (по умолчанию).
      • BMA_G - выводить угловое ускорение в количестве ускорений свободного падения (g).
      • BMA_DEG - выводить углы «крен» и «тангаж» в градусах (для неподвижного или равноускоренного датчика).
      • BMA_RAD - выводить углы «крен» и «тангаж» в радианах (для неподвижного или равноускоренного датчика).
    • Если объект работает с гироскопом:
      • BMG_DEG_S - выводить угловую скорость в °/c (по умолчанию).
      • BMG_RAD_S - выводить угловую скорость в рад/c.
    • Если объект работает с магнитометром:
      • BMM_MG - выводить индукцию магнитного поля в мГс (по умолчанию).
      • BMM_MCT выводить индукцию магнитного поля в мкТл.
    • Если объект работает со всеми датчиками:
      • BMX_DEG выводить положение модуля в пространстве в градусах (по умолчанию).
      • BMX_RAD выводить положение модуля в пространстве в радианах.
      • BMX_M_S выводить истинное ускорение модуля в м/с².
  • Возвращаемые значения: bool - успех чтения данных (true или false).
  • Примечание:
    • Функция возвращает результат успешности чтения, а прочитанные данные сохраняются в переменные: axisX, axisY, axisZ и temp.
    • Параметры функции и читаемые ей данные зависят от того, с каким датчиком работает объект.
    • Если вызвать функцию без параметра, то будет произведено чтение данных указанных для датчика по умолчанию.
    • В разделе «Примеры» настоящей статьи, описан более подробный вариант использования функции.
  • Пример:
iarduino_Position_BMX055 sensorA(BMA); // Создаём объект sensorA указывая что ему требуется работать только с акселерометром
iarduino_Position_BMX055 sensorG(BMG); // Создаём объект sensorG указывая что ему требуется работать только с гироскопом
iarduino_Position_BMX055 sensorM(BMM); // Создаём объект sensorM указывая что ему требуется работать только с магнитометром
...                                    // 
void loop(){                           //
  sensorA.read(BMA_M_S);               // читаем угловое ускорение в м/с² из акселерометра,       данные сохранятся в переменных axisX, axisY, axisZ и temp объекта sensorA
  sensorG.read(BMG_RAD_S);             // читаем угловую скорость в рад/c из гироскопа,           данные сохранятся в переменных axisX, axisY, axisZ и temp объекта sensorG
  sensorM.read(BMM_MCT);               // читаем индукцию магнитного поля в мкТл из магнитометра, данные сохранятся в переменных axisX, axisY, axisZ и temp объекта sensorM
}                                      //
Функция setScale();
  • Назначение: Установка диапазона измерений датчика (датчиков) модуля.
  • Синтаксис: setScale( ДИАПАЗОН );
  • Параметр: зависит от того, с каким датчиком работает объект.
    • Если объект работает с акселерометром:
      • BMA_2G - производить измерения в диапазоне ±2 g (по умолчанию).
      • BMA_4G - производить измерения в диапазоне ±4 g.
      • BMA_8G - производить измерения в диапазоне ±8 g.
      • BMA_16G - производить измерения в диапазоне ±16 g.
      • где g - ускорение свободного падения = 9.81 м/с².
    • Если объект работает с гироскопом:
      • BMG_125DPS - производить измерения в диапазоне ±125 °/с (по умолчанию).
      • BMG_250DPS - производить измерения в диапазоне ±250 °/с.
      • BMG_500DPS - производить измерения в диапазоне ±500 °/с.
      • BMG_1000DPS - производить измерения в диапазоне ±1000 °/с.
      • BMG_2000DPS - производить измерения в диапазоне ±2000 °/с.
    • Если объект работает с магнитометром:
      • BMM_LOW_PWR - экономичный режим.
      • BMM_REGULAR - обычный режим (по умолчанию).
      • BMM_ENHANCED - улучшенный режим.
      • BMM_HIGH - режим высокой точности.
  • Возвращаемые значения: нет.
  • Примечание:
    • После смены диапазонов измерений акселерометра или гироскопа, нужно выполнить их калибровку вызвав функцию setFastOffset().
    • Увеличение диапазона измерений может понадобиться если модуль перемещается на больших скоростях. Чем шире диапазон измерений, тем меньше точность показаний датчиков.
    • У магнитометра фиксированный диапазон измерений для каждой оси, по этому данная функция устанавливает один из рекомендуемых (предустановленных) режимов его работы. Чем точнее режим работы, тем точнее показания магнитометра.
    • Параметры функции зависят от того, с каким датчиком работает объект.
    • Функция не поддерживается объектом, который объявлен для работы со всеми датчиками.
  • Пример:
                                       // если объект sensor объявлен с параметром BMA - для работы с акселерометром
sensor.setScale(BMA_16G);              // производить дальнейшие измерения акселерометра в диапазоне ±16 g.
sensor.setFastOffset();                // выполнить калибровку акселерометра после смены его диапазона измерений.
                                       // теперь чтение данных акселерометра будет производиться в новом диапазоне.
Функция setBandwidths();
  • Назначение: Установка полосы пропускания для фильтрованных данных. Полоса пропускания влияет на то с какой скоростью датчик будет сохранять новые показания в свои регистры данных.
  • Синтаксис: setBandwidths( ЧАСТОТА );
  • Параметр: зависит от того, с каким датчиком работает объект.
    • Если объект работает с акселерометром:
      • BMA_8Hz - данные обновляются с частотой 7.81 Гц.
      • BMA_16Hz - данные обновляются с частотой 15.63 Гц (по умолчанию).
      • BMA_31Hz - данные обновляются с частотой 31.25 Гц.
      • BMA_63Hz - данные обновляются с частотой 62.5 Гц.
      • BMA_125Hz - данные обновляются с частотой 125 Гц.
      • BMA_250Hz - данные обновляются с частотой 250 Гц.
      • BMA_500Hz - данные обновляются с частотой 500 Гц.
      • BMA_1000Hz - данные обновляются с частотой 1000 Гц.
    • Если объект работает с гироскопом:
        Тут частота полосы пропускания отличается от частоты обновления данных.
      • BMG_12Hz - данные обновляются с частотой 100 Гц.
      • BMG_23Hz - данные обновляются с частотой 200 Гц (по умолчанию).
      • BMG_32Hz - данные обновляются с частотой 100 Гц.
      • BMG_47Hz - данные обновляются с частотой 400 Гц.
      • BMG_64Hz - данные обновляются с частотой 200 Гц.
      • BMG_116Hz - данные обновляются с частотой 1000 Гц.
      • BMG_230Hz - данные обновляются с частотой 2000 Гц.
      • BMG_523Hz - данные обновляются с частотой 2000 Гц.
    • Если объект работает с магнитометром:
      • BMM_2Hz - данные обновляются с частотой 2 Гц.
      • BMM_6Hz - данные обновляются с частотой 6 Гц.
      • BMM_8Hz - данные обновляются с частотой 8 Гц.
      • BMM_10Hz - данные обновляются с частотой 10 Гц (по умолчанию).
      • BMM_15Hz - данные обновляются с частотой 15 Гц.
      • BMM_20Hz - данные обновляются с частотой 20 Гц.
      • BMM_25Hz - данные обновляются с частотой 25 Гц.
      • BMM_30Hz - данные обновляются с частотой 30 Гц.
  • Возвращаемые значения: нет.
  • Примечание:
    • Полоса пропускания фильтрованных данных определяет с какой скоростью датчик обновляет свои регистры данных новыми показаниями.
    • Чем выше частота обновления данных, тем чаще можно читать новые данные с датчика.
    • Параметры функции зависят от того, с каким датчиком работает объект.
    • Функция не поддерживается объектом, который объявлен для работы со всеми датчиками.
    • Если функцией read() читаются старые данные датчика (которые уже были прочитаны ранее), то функция read() вернёт false и значение переменных axisX, axisY, axisZ, и temp останется неизменным.
  • Пример:
                                       // если объект sensor объявлен с параметром BMM - для работы с магнитометром
sensor.setBandwidths(BMM_30Hz);        // установить полосу пропускания магнитометра в 30 Гц.
                                       // теперь новые данные магнитометра можно получать до 30 раз в секунду.
Функция setFastOffset();
  • Назначение: Калибровка - выполнение быстрой компенсации смещения данных датчика (датчиков) модуля.
  • Синтаксис: setFastOffset();
  • Параметры: нет.
  • Возвращаемые значения: нет.
  • Примечание:
    • Показания осей датчика (ов) на момент обращения к функции будут приняты за 0.
      • Для акселерометра: положение модуля при котором была вызвана данная функция будет считаться горизонтальным, а текущее угловое ускорение будет принято за ускорение свободного падения.
      • Для гироскопа: текущая угловая скорость модуля будет принята за нулевую.
      • Для магнитометра: текущая индукция магнитного поля будет принята на нулевую.
      • Обращение к данной функции объекта работающего со всеми датчиками приведёт к калибровке только акселерометра и гироскопа.
    • Функция выполняется аппаратно для акселерометра и гироскопа, и программно для магнитометра.
    • Выполнение функции для магнитометра занимает значительно время, связанное с усреднением его показаний.
  • Пример:
sensor.setFastOffset();                // Выполнение калибровки датчика с которым работает объект sensor
Функция getFilter();
  • Назначение: Вывод названия фильтра используемого для расчёта кватернионов.
  • Синтаксис: getFilter();
  • Параметры: нет.
  • Возвращаемые значения: uint8_t - тип используемого фильтра:
    • NO_FILTER - нет подходящего фильтра.
    • FILTER_MADGWICK - используется фильтр Маджвика (по умолчанию).
    • FILTER_MADGWICK_NO_BMM - используется фильтр Маджвика без данных с магнитометра.
    • FILTER_MAHONY - используется фильтр Махони.
  • Примечание:
    • Функция поддерживается только объектом, который объявлен для работы со всеми датчиками.
    • Если объявить объект с параметром BMX и вызвать функцию getFilter(), то она вернёт FILTER_MADGWICK.
    • Если в начале скетча отключить магнитометр (объявить константу BMX055_DISABLE_BMM), то вызов функции getFilter(), вернёт FILTER_MADGWICK_NO_BMM.
    • Если в начале скетча отключить фильтр Маджвика (объявить константу BMX055_DISABLE_MADGWICK) и подключить фильтр Махони (объявить константу BMX055_ENABLE_MAHONY), то вызов функции getFilter(), вернёт FILTER_MAHONY.
    • Если совершить некорректные действия, например, отключить фильтр Маджвика и не подключить фильтр Махони, или подключить фильтр Махони и отключить магнитометр и т.д., то вызов функции getFilter(), вернёт NO_FILTER.
  • Пример:
sensor.setFastOffset();                // Выполнение калибровки датчика с которым работает объект sensor
Переменная axisX:
  • Тип: float
  • Данные: показание датчика для оси X или угол «тангаж», зависит от параметра функции read().
  • Обновление данных: после вызова функции read().
  • Примечание: угол «тангаж» при работе только с акселерометром выдаёт значения до ±90°.
Переменная axisY:
  • Тип: float
  • Данные: показание датчика для оси Y или угол «крен», зависит от параметра функции read().
  • Обновление данных: после вызова функции read().
  • Примечание: угол «крен» принимает одинаковые значения как при работе с акселерометром, так и при работе со всеми датчиками модуля.
Переменная axisZ:
  • Тип: float
  • Данные: показание датчика для оси Z или угол «курс», зависит от параметра функции read().
  • Обновление данных: после вызова функции read().
  • Примечание: не содержит угол «курс» при работе только с акселерометром.
Переменная temp:
  • Тип: float
  • Данные: содержит температуру в °С и зависит от датчика с которым работает объект.
  • Обновление данных: после вызова функции read().
  • Примечание: не содержит температуру при работе с гироскопом.

Дополнительные переменные q1, q2, q3, q4:

  • Тип: float
  • Данные: кватернионы.
  • Обновление данных: после вызова функции read() и не зависят от параметра данной функции.
  • Примечание: поддерживаются только объектом, который объявлен для работы со всеми датчиками.

Ссылки:

Обсуждение

Присоединяйся

На главную