- 2подключение 7-сегментного светодиодногоиндикатора к arduino
- 3подключение динамика / пьезоизлучателяк arduino
- 4собираем всё вместе:компас на arduino
- Arduino и mpu6050 для определения угла наклона
- Gy-521 – модуль с гироскопом, акселерометром и термометром mpu-6050 для ардуино
- Mpu 9250 и arduino – схема подключения
- Акселерометр и гироскоп mpu6050
- Библиотека keypad для работы с клавиатурой на arduino
- Глобальные переменные
- Загрузка, установка и импорт
- Калибровка mpu6050
- Окончательный расчет угла наклона и подбор коэффициентов усиления для фильтра
- Погрешность гироскопа – «дрифт» (drift)
- Подключение imu 10dof l3g4200d adxl345 hmc5883l bmp085 – популярная робототехника
- Пример
- Расчет угла с помощью гироскопа mpu6050
- Создание
- Функции в программе arduino для работы с mpu6050
2подключение 7-сегментного светодиодногоиндикатора к arduino
В качестве индикатора для вывода показаний компаса будем использовать семисегментный индикатор 3361AS-1. Он построен по принципу индикатора с общим катодом.
Светодиодный индикатор с общим катодом – это тип индикатора, состоящий из нескольких светодиодов в одном корпусе, у которых общая земля, а питание на каждый светодиод подаётся отдельно.
Напомню, что 7-сегментным индикатор называется из-за того, что он состоит из 7-ми светодиодов, которые расположены в форме цифры “8”. Зажигая определённые сегменты, можно изображать разные цифры. Это похоже на цифры индекса на почтовом конверте: закрашивая определённые участки, мы пишем разные индексы.
Воспользуемся популярным способом управления 7-сегментным индикатором с помощью драйвера CD4511. Это микросхема двоично-десятичного преобразователя, который переводит двоичный код числа в напряжение на соответствующих цифре сегментах индикатора. Такой преобразователь использует всего 4 ножки Arduino.
Отечественными аналогами данного преобразователя являются микросхемы серий ИД1…ИД7.
При подключении двоичного декодера будем руководствоваться следующей таблицей:
Вывод CD4511 | Назначение | Примечание |
---|---|---|
A0…A3 | Входы двоичного преобразователя | Соответствуют разрядам двоичного числа. |
a…g | Выходы на сегменты индикатора | Подключаются через токоограничительные резисторы к соответствующим сегментам светодиодного индикатора. |
Lamp Test# | Тест индикатора (включает все сегменты) | Подключим к питанию, не использовать его. |
Blanking# | Очистка индикатора (отключает все сегменты) | Подключим к питанию, чтобы не использовать его. |
Latch Enabled# | Выход активен | Будет подключен к земле, чтобы выход был всегда активен. |
VDD | Питание микросхемы и индикатора | От 3 до 15 В. |
GND | Земля | Общая у CD4511, Arduino, 7-сегментного индикатора. |
Индикатор 3361AS не имеет токоограничительных резисторов, поэтому необходимо озаботиться этим самому, подключая индикатор. При напряжении питания 5 В сопротивление на каждый сегмент должно быть около 200 Ом.
Желательно также подключить керамический конденсатор ёмкостью примерно 1 мкФ между землёй и питанием микросхемы CD4511.
Нам нужно одновременно управлять тремя разрядами десятичного числа, используя только один преобразователь CD4511. Но чисто физически это невозможно. Однако можно добиться иллюзии постоянного свечения всех разрядов светодиодного индикатора. Для этого придётся быстро переключаться между разрядами, постоянно обновляя показание каждого разряда.
Для человеческого глаза такое переключение между разрядами будет незаметно, но если результат снять на видео, то можно увидеть, как мерцают разряды чисел при переключении между разрядами, и даже мерцание отдельных светодиодов.
Скетч для управления трёхразрядным 7-сегментным индикатором (разворачивается)
// Выводы Arduino для управления двоичным конвертером CD4511: const byte bit0 = 11; const byte bit1 = 10; const byte bit2 = 9; const byte bit3 = 8; // Выводы Arduino для выбора десятичных разрядов индикатора 3361AS: const byte B_0 = 5; const byte B_1 = 6; const byte B_2 = 7; #define seconds() (millis()/1000) // макрос определения секунд, прошедших с начала работы скетча void setup() { pinMode(bit0, OUTPUT); pinMode(bit1, OUTPUT); pinMode(bit2, OUTPUT); pinMode(bit3, OUTPUT); pinMode(B_0, OUTPUT); pinMode(B_1, OUTPUT); pinMode(B_2, OUTPUT); digitalWrite(B_0, HIGH); digitalWrite(B_1, HIGH); digitalWrite(B_2, HIGH); } void loop() { // Каждую секунду увеличиваем показания индикатора на 1: int sec = seconds(); for (int i=0; i<1000; i ) { while (sec == seconds()) { printNumber(i); } sec = seconds(); } } // Выводит 3-разрядное число на 7-сегментный индикатор. void printNumber(int n) { setDigit(B_0, n/100); // выводим сотни десятичного числа setDigit(B_1, n/10 ); // выводим десятки setDigit(B_2, n/1 ); // выводим единицы } // Выводит заданное число на заданный разряд индикатора. void setDigit(byte digit, int value) { digitalWrite(digit, LOW); // выбираем разряд индикатора 3361AS-1 setNumber(value); // выводим на этот разряд число delay(4); digitalWrite(digit, HIGH); // снимаем выбор разряда индикатора } // Выставляет двоичный код на входе преобразователя CD4511 void setNumber(int n) { static const struct number { byte b3; byte b2; byte b1; byte b0; } numbers[] = { {0, 0, 0, 0}, // 0 {0, 0, 0, 1}, // 1 {0, 0, 1, 0}, // 2 {0, 0, 1, 1}, // 3 {0, 1, 0, 0}, // 4 {0, 1, 0, 1}, // 5 {0, 1, 1, 0}, // 6 {0, 1, 1, 1}, // 7 {1, 0, 0, 0}, // 8 {1, 0, 0, 1}, // 9 }; digitalWrite(bit0, numbers[n].b0); digitalWrite(bit1, numbers[n].b1); digitalWrite(bit2, numbers[n].b2); digitalWrite(bit3, numbers[n].b3); }
Итак, теперь мы умеем выводить трёхзначные числа на 7-сегментный индикатор, что нам понадобится для отображения азимута.
3подключение динамика / пьезоизлучателяк arduino
Для оповещения об отклонении от азимута, как было решено, будем использовать звуковой пьезоизлучатель. Мы уже обсуждали в отдельной статье, как подключить пьезоизлучатель к Arduino. Поэтому останавливаться подробно здесь не будем. Напомню ключевые моменты.
Схема подключения излучателя к Arduino очень простая: объединяем земли, а в цепь питания ставим резистор сопротивлением около 100 Ом (для защиты порта Ardunio).
Для Arduino есть специальные функции tone() и noTone(), которые используются для извлечения звука заданной частоты:
tone(piezoPin, freq); // подача звука с частотой freq (Гц) tone(piezoPin, freq, duration); // подача звука с частотой freq (Гц) длительностью duration (мс) noTone(piezoPin); // остановка звука
Здесь piezoPin – номер вывода Arduino, к которой подключён звуковой извещатель. Давайте изменим в предыдущем скетче функцию loop() таким образом (изменения выделены жирным):
void loop()
{
// Каждую секунду увеличиваем показания индикатора на 1:
int sec = seconds();
for (int i=0; i<1000; i ) {
while (sec == seconds()) {
print_number(i);
if (sec % 60 == 0){ // каждые 60 секунд
tone(piezoPin, 1000, 500); // издавать звуковой сигнал
}
}
sec = seconds();
}
}
И конечно же, не забудем объявить в начале скетча piezoPin и задать ему режим работы OUTPUT. Теперь каждую минуту излучатель будет подавать звуковой сигнал продолжительностью 500 мс и частотой 1000 Гц.
4собираем всё вместе:компас на arduino
Схема нашего устройства будет такой (нарисована в DipTrace Schematic):
Здесь ARD1 – это Arduino Nano, CD4511 – драйвер управления 7-сегментным дисплеем 3361AS, MPU-9255 – собственно, сам модуль с магнитным датчиком, SW1 – кнопка для запуска и останова отслеживания азимута, BUZ – звуковой извещатель, а PWR – клемма для подачи внешнего питания от батареи «Крона» на устройство.
Монтаж компаса будем производить на печатной плате, которую «разведём» в программе DipTrace PCB Layout.
Закажем печатную плату здесь. На этом предприятии делают всё быстро и качественно. Например, изготовление данной печатной платы заняло около суток от момента заказа до отправки. Единственный минус – придётся долго ждать доставки из Китая (2-4 недели).
Распаяем элементы на плате.
После распайки компонентов плата электронного компаса будет выглядеть так:
Останется только придумать какой-то корпус для платы с компасом.
В процессе экспериментов выяснились несколько деталей, которые потребовали доработки. Во-первых, динамик вносит искажения в показания компаса. Величина искажения зависит от типа динамика и его близости к датчику. Поэтому его желательно отнести подальше от датчика, а не размещать непосредственно на плате.
Во-вторых, изначальный скетч определения азимута выводит довольно приблизительные и нестабильные измерения. Поэтому в части работы компаса всё было переделано. Я взял за основу скетч, представленный в этой статье. Он отличается тем, что используются показания акселерометра для коррекции наклона датчика, а также вводятся дополнительные коррекции, связанные с индивидуальными особенностями датчика (в частности, чувствительность ASAX, ASAY, ASAZ). Для нормальной работы этого скетча необходимо сделать следующее.
Arduino и mpu6050 для определения угла наклона
Файл, приведенный ниже, будет работать с цифровыми датчиками ускорения MPU6050, которые подключены к плате Arduino через I2C протокол по адресу 0x68.
Работоспособность проверена на платах Arduino Uno и Arduino Mega. Данный файл заголовка требует файл Wire.h перед добавлением “gyro_Accel.h”.
Кроме того, перед вызовом встроенных функций, надо инициализировать шину I2Cс помощью команды Wire.begin();.
Программа для Arduino с файлом заголовка и примером расположены на Github
Логи версии:
Gy-521 – модуль с гироскопом, акселерометром и термометром mpu-6050 для ардуино
Датчики определения положения в пространстве широко используются в мобильных устройствах, а для самоделок чаще всего применяются в квадрокоптерах.
Также, его можно применить в светящемся шлеме! Удобно, не правда ли? Наклонил голову вправо — загорелось правое «полушарие» =) влево — левое, согнул голову в шее — сзади на шлеме высветился стоп-сигнал! Вот только, думаю, моей шеи хватит минут на 5 таких упражнений, потом — коллдаун, в виде боли на неделю обеспечен.
Итак, заказал — прислали, теперь нужно разобраться и продемонстрировать функционал для Вас, уважаемые читатели Муськи. Пришло с треком, не известно, почему, но в Киеве посылку держали неделю (или это глюки системы треккинга). Дошла чуть менее, чем за три недели. Упаковано в три слоя утеплителя — для амортизации.
Сам модуль — внутри запаянного пакетика со штрих-кодом на наклейке:Размеры платы: 20×16мм. В комплекте два набора штыревых контактов: ровные и загнутые — удобно, не придется гнуть или ровнять.
Большие отверстия не металлизированы, как на картинке в магазине, поэтому, если Вы будите их прикручивать болтами к «минусу», эффекта не будет. Я заливаю их термоклеем, а он, образуя «шапочки», надёжно фиксирует плату.Отвертия контактов металлизированы отлично, паяются без проблем.
Схема
Взята из статьи про такой же модуль — cxem.net/mc/mc324.php
MPU-6050 снабжен акселерометром, гироскопом и термометром. Зачем нужен термометр — не понятно, вероятно, его было удобно разместить в этой микросхеме.
Или, действительно, есть такие варианты применения, о которых я не знаю, где тебя вертят и греют нужно вертеться в пространстве и знать температуру =) Или, в процессе интенсивной работы с устройством, оно может нагреваться и нужно контролировать его температуру и нагрузку.
— 16-битный АЦП, — напряжение питания 3-5В, — поддержка протокола «IIC» (может, I2C ?), — диапазон ускорений: ± 2 ± 4 ± 8 ± 16g, — диапазон «гиро»: ± 250 500 1000 2000 ° / s, — покрытие иммерсионным золотом вместо лужения, — ток при работе последнего примера составил 5.3 мА и 1.
2 мА когда устройство не успело стартовать (питание на модуль было подано после выполнения setup() контроллером) Для интерфейса I2C у Ардуино имеются контакты A4 (SDA) и A5 (SCL), да-а, это те, которые расположены чёрти-где (на одной плате у меня они были справа от контроллера, на другой с левого края).
В коде нужно использовать библиотеку Wire, прочитать о ней можно туточки. Минимальная схема во Fritzing такая:… а значит у нас уже не 8 лишних штырьков, а целых двенадцать! Термометр тестировать проще всего: залил скетч отсюда, открыл монитор порта, выставил скорость на 9600, —
побежали такие строки
AcX = 1624 | AcY = -808 | AcZ = 15176 | Tmp = 25.14 | GyX = 11 | GyY = 314 | GyZ = -138 AcX = 1584 | AcY = -876 | AcZ = 15112 | Tmp = 25.00 | GyX = 0 | GyY = 193 | GyZ = -163 AcX = 1616 | AcY = -904 | AcZ = 15172 | Tmp = 25.05 | GyX = -2 | GyY = 264 | GyZ = -181 AcX = 1648 | AcY = -836 | AcZ = 14948 | Tmp = 25.
09 | GyX = 3 | GyY = 146 | GyZ = -192 AcX = 1792 | AcY = -800 | AcZ = 15216 | Tmp = 25.09 | GyX = 27 | GyY = -181 | GyZ = -218 AcX = 1864 | AcY = -900 | AcZ = 14932 | Tmp = 25.09 | GyX = 11 | GyY = 48 | GyZ = -206 AcX = 2144 | AcY = -796 | AcZ = 14860 | Tmp = 25.
05 | GyX = 8 | GyY = 100 | GyZ = -191 AcX = 2088 | AcY = -916 | AcZ = 14952 | Tmp = 25.14 | GyX = 11 | GyY = 158 | GyZ = -189 AcX = 2180 | AcY = -752 | AcZ = 14964 | Tmp = 25.14 | GyX = 6 | GyY = 334 | GyZ = -182 AcX = 2296 | AcY = -796 | AcZ = 15076 | Tmp = 25.
05 | GyX = -3 | GyY = 184 | GyZ = -189 AcX = 2160 | AcY = -788 | AcZ = 15176 | Tmp = 25.14 | GyX = -8 | GyY = 184 | GyZ = -172 AcX = 2036 | AcY = -852 | AcZ = 14988 | Tmp = 25.09 | GyX = 3 | GyY = 292 | GyZ = -172 AcX = 1984 | AcY = -836 | AcZ = 14892 | Tmp = 25.
09 | GyX = 38 | GyY = 90 | GyZ = -205 AcX = 2136 | AcY = -708 | AcZ = 14976 | Tmp = 25.19 | GyX = -5 | GyY = 270 | GyZ = -148 AcX = 2000 | AcY = -788 | AcZ = 14888 | Tmp = 25.14 | GyX = -35 | GyY = 239 | GyZ = -157 AcX = 2008 | AcY = -784 | AcZ = 15048 | Tmp = 25.
19 | GyX = -3 | GyY = 342 | GyZ = -183 AcX = 1884 | AcY = -868 | AcZ = 15140 | Tmp = 25.19 | GyX = -3 | GyY = 214 | GyZ = -194 AcX = 2072 | AcY = -820 | AcZ = 15020 | Tmp = 25.28 | GyX = 41 | GyY = 157 | GyZ = -205 AcX = 2008 | AcY = -780 | AcZ = 15144 | Tmp = 25.
24 | GyX = 0 | GyY = 220 | GyZ = -204 AcX = 1924 | AcY = -828 | AcZ = 14968 | Tmp = 25.24 | GyX = -9 | GyY = 254 | GyZ = -187 AcX = 1920 | AcY = -828 | AcZ = 14936 | Tmp = 25.33 | GyX = 7 | GyY = 253 | GyZ = -185 AcX = 2020 | AcY = -728 | AcZ = 14904 | Tmp = 25.
14 | GyX = 16 | GyY = 190 | GyZ = -167 AcX = 1900 | AcY = -744 | AcZ = 15048 | Tmp = 25.42 | GyX = -4 | GyY = 162 | GyZ = -177 AcX = 1940 | AcY = -780 | AcZ = 14992 | Tmp = 25.28 | GyX = -34 | GyY = 271 | GyZ = -191 AcX = 1960 | AcY = -900 | AcZ = 15080 | Tmp = 25.38 | GyX = 2 | GyY = 194 | GyZ = -182
AcX = 1840 | AcY = -952 | AcZ = 15012 | Tmp = 25.38 | GyX = 19 | GyY = 272 | GyZ = -167
Вследствие нагревания феном для волос, значение Tmp = взлетело до 80. Далее покрутили в пространстве платкой — другие показания тоже изменяются, но это не наглядно.
Данные, выводимые вторым скетчем
Mpu 9250 и arduino – схема подключения
MPU 9250 выполняет функции сразу нескольких датчиков: это и гироскоп, и акселерометр, и магнитометр – все три устройства в одном, что очень удобно.
Остановимся немного подробнее на каждом из них.
Гироскоп – это сенсор, реагирующий на изменение углов ориентации в пространстве. В тех же квадрокоптерах его используют, чтобы стабилизировать положение аппарата в воздухе и защитить его от ветра.
Например, во время рыбалки, мы закидываем удочки в водоем и на поверхности воды виден только поплавок.
Если погода достаточно ветреная, то поплавок постоянно будет уходить в разные стороны и наклоняться под случайным углом, что может помешать нам вовремя заметить клев рыбы. То же самое будет происходить и в воздухе.
Чтобы ваш квадрокоптер не находился постоянно в наклонном положении, его выравниванием и будет заниматься гироскоп.
В качестве иллюстрации, внизу вы можете наглядно посмотреть испытания DIY дрона вместе с установленным в его аппаратную часть гироскопом.
Акселерометр сравнивает проекцию ускорения объекта с гравитационным ускорением и способен замерять линейную скорость объекта, а вкупе с гироскопом – и положение в пространстве.
Магнитометр представляет собой устройство для измерения интенсивности ближайшего магнитного поля, действующего на объект (впрочем, название датчика говорит само за себя).
А еще, по некоторым данным, наш модуль MPU 9250 является самым миниатюрным в мире девятиосевым сенсором. Это говорит о высокой производительности микросхемы (по названию которой и назван наш “герой”), что было обеспечено применением технологии CMOS MEMS.
Состоит корпус модуля из двух мельчайших кристаллов, один из которых отвечает за гироскоп и акселерометр, а другой за магнитометр. Данные с них обрабатываются встроенным сигнальным процессором DMP с помощью алгоритмов Motion Fusion и передаются по интерфейсам I2C или SPI.
Помимо высокой производительности, модуль довольно популярен в среде ардуинщиков и тех, кто увлекается устройствами на дистанционном управлении, а также имеет низкие энергопотребление и стоимость.
Как уже было сказано ранее, подключать датчик к Arduino можно по шине I2C или SPI. Питать модуль можно от 5 В, так как на плате датчика имеется линейный стабилизатор для данного типа питания, но подавать питание можно и значением в 3,3 В.
Вы можете подключать модуль к вашему микроконтроллеру по четырем контактам через интерфейс I2C (5V, Gnd, SCL, SDA) или через SPI, используя 5 контактов на плате модуля (5V, Gnd, SCL, SDA, CS, SDO).
На картинке показано подключение через интерфейс I2C.
В качестве примеров для работы с модулем MPU 9250 можете воспользоваться предложенным ниже скетчем.
Данный код с использованием пары библиотек позволит считывать информацию (данные) со всех трех датчиков и выводить в порт. Здесь понадобится библиотека Wire 0. Она уже встроена в Arduino IDE , а, значит, ее отдельно скачивать устанавливать не нужно.
Акселерометр и гироскоп mpu6050
Прежде чем приступить к рассмотрению модуля гироскопа и акселерометра, думаю, будет не лишним коротко разобраться что это такое. Гироскоп представляет собой устройство, реагирующее на изменение углов ориентации контролируемого тела. В классическом представлении это какой-то инерционный предмет, который быстро вращается на подвесах.
Как результат вращающийся предмет всегда будет сохранять свое направление, а по положению подвесов можно определить угол отклонения. На самом же деле электронные гироскопы построены по другой схеме и устроены немного сложнее (вращающийся волчок впихнуть в микросхему было бы не просто).
Акселерометр – это устройство, которое измеряет проекцию кажущегося ускорения, то есть разницы между истинным ускорением объекта и гравитационным ускорением. На простом примере такая система представляет собой некоторую массу, закрепленную на подвесе, обладающим упругостью (пружина для хорошего примера).
Так вот если такую систему повернуть под каким-то углом, или бросить, или предать линейное ускорение, то упругий подвес отреагирует на движение под действием массы и отклонится и вот по этому отклонению определяется ускорение.
Таким образом, гироскоп реагирует на изменение в пространстве независимо от направление движения, с помощью акселерометра же может измерять линейные ускорения предмета, а так же и искусственно рассчитываемое расположение предмета в пространстве. Каждое устройство имеет свои достоинства и недостатки.
Микросхема MPU6050 содержит на борту как акселерометр, так и гироскоп, а помимо этого еще и температурный сенсор. MPU6050 является главным элементом модуля GY-531.
Помимо этой микросхемы на плате модуля расположена необходимая обвязка MPU6050, в том числе подтягивающие резисторы интерфейса I2C, а также стабилизатор напряжения на 3,3 вольта с малым падением напряжения (при питании уже в 3,3 вольта на выходе стабилизатора будет 3 ровно вольта) с фильтрующими конденсаторами.
Ну и бонусом на плате распаян SMD светодиод с ограничивающим резистором как индикатор питающего напряжения. Размер платы модуля GY-521 10 х 20 мм.
Схема модуля представлена ниже (номиналы могут немного отличаться в разных версиях модуля):
Характеристики MPU6050:
- напряжения питания 2,375 – 3,46 вольт
- потребляемый ток до 4 мА
- интерфейс передачи данных – I2C
- максимальная скорость I2C – 400 кГц
- вход для других датчиков I2C
- внутренний генератор на 8 МГц (вне модуля возможность подключить внешний кварцевый резонатор на 32,768 кГц или 19,2 МГц)
Нужно отметить возможность MPU6050 работать в мастер режиме I2C для AUX выводов, к которым можно подключить еще один внешний датчик (например магнитометр). Честно говоря, я не понимаю для чего это вообще нужно, если проще подключать дополнительные датчики к общей шине I2C микроконтроллера.
Функции MPU6050:
- трех осевой MEMS гироскоп с 16 битным АЦП
- трех осевой MEMS акселерометр с 16 битным АЦП
- Digital Motion Processor (DMP)
- slave I2C для подключения к микроконтроллеру
- master I2C для подключения к микросхеме дополнительного датчика
- регистры данных датчиков
- FIFO
- прерывания
- температурный сенсор
- самопроверка гироскопа и акселерометра
- регистр идентификации устройства
Внешний вид модуля GY-521:
В комплекте идут штыревые соединения угловые и прямые. Припаян был прямой штыревой разъем.
Данные измерений датчиков можно считывать как из регистров хранения, так и пользоваться функциями FIFO.
Имеется отдельный регистр под названием Who am I, значение, записанное в этом регистре постоянно и его можно только считать, можно использовать как идентификатор устройства, значение в регистре 104 или 0х68.
Отдельным выводом является выход прерываний, который настраивается регистрами настройки под определенные события.
Датчики гироскопа и акселерометра изготовлены как MEMS (микроэлектромеханическая система) – внешнее воздействие на датчик сначала изменяет состояние механической части, затем изменение состояния механической части приводит к изменению сигнала электрической части.
Одним словом в одном корпусе собрана не только электроника, но и механика. В микросхеме MPU6050 содержится сразу два MEMS датчика, производитель утверждает, что их взаимное воздействие друг на друга сведено к минимуму. Ну что же, совсем не плохо за цену готового модуля порядка 2 уе.
Между прочим эти модули можно приобрести на торговых площадках aliexpress или ebay.
Разберемся как можно использовать датчики акселерометра и гироскопа. Температурный датчик трогать даже не будем – данные о температуре прочитали, перевели в человеческие значения и наслаждаемся. Гироскоп выдает значения мгновенной угловой скорости с разрешением, заданным в настройках, например 2000 градусов в секунду.
Если прошить микроконтроллер и смотреть на получаемые данные, то увидим только нули. Если начать крутить датчик, то получим мгновенные значения угловой скорости. Заметьте, что скорость мы получаем в градусах в секунду, а это значит, что линейные скорости не влияют на эти показания – показания будут изменяться только при повороте датчика в пространстве.
Далее с помощью этих данных можно получить ориентацию объекта в пространстве. Для этого нужно получить мгновенное значение угловой скорости и умножить его на промежуток времени между опросами датчика гироскопа.
Пример разрешение 2000 градусов в секунду, промежуток между опросами датчика 0,1 секунда, значение мгновенной скорости 300, значит 300*0,1=30 – за это время ось гироскопа была повернута на 30 градусов. Далее каждое полученное значение нужно сложить с предыдущим.
Если ось двигалась в одном направлении – значение 30 градусов, если в другом, то -30, таким образом, при возвращении датчика в исходное положение всегда (в идеале) будет 0, при отклонении от исходного положения, при выполнении вышеописанных действий, получим угол отклонения. Обрабатывая углы трех осей гироскопа можно получить ориентацию объекта в пространстве.
Таким образом, при интегрировании состояния угла положения, также интегрируется и погрешность – при длительном использовании можно получить уже абсолютно неправильные значения. Поэтому часто гироскоп используют в паре с акселерометром, образуя в простом варианте альфа-бета фильтр или комплементарный фильтр.
С акселерометром все проще. Измеряя ускорения трех осей датчика можно получить данные, преобразуя их с помощью геометрии, по которым можно также получить ориентацию объекта в пространстве.
Помимо этого акселерометр измеряет линейные ускорения, то есть ориентация объекта может искажаться при движении датчика в линейных направлениях. Также с помощью акселерометра можно определять движение объекта или его столкновение.
Например детектировать падение объекта или толчок о преграду, чтобы обходить это.
Данные от акселерометра получаем всегда достаточно точные, то есть нуль всегда остается нулем ни при каких воздействиях (имеется ввиду не зависит ни от времени, ни от характера воздействия), однако недостаток кроется в том, что данные идут шумом в некотором диапазоне данных, то есть до десятых долей градуса точно измерять угол не получится.
Если датчик приобрели, можно переходить к рассмотрению внутренностей модуля, а именно главного элемента – микросхемы MPU6050. Информация хранится в регистрах микросхемы, которых более 100 (!). И вот тут то и кроется огромный подводный камень.
производитель не утрудился расписать в документации всю информацию, а привел лишь информацию о самом необходимом. На самом деле не известно даже сколько же всего там регистров, доступных для чтения или записи или того и другого. Также информации на некоторые регистры попросту нет, кроме его названия.
Ну что же, придется экспериментально определять влияния значений, записанных в некоторые регистры.
Библиотека keypad для работы с клавиатурой на arduino
Библиотека Keypad служит для использования совместно с Arduino клавиатур матричного типа. Текущая версия библиотеки (3.1) поддерживает множественные нажатия.
Данная библиотека была создана для создания уровня абстракции для аппаратного обеспечения. Она улучшает читаемость кода, скрывая от пользователя вызовы функций pinMode и digitalRead.
Версия 3.0 (опубликована 19 июля 2020) была переписана для поддержки по умолчанию множественных нажатий. Но для тех, кому всё еще изначальная функциональность с одиночными нажатиями, библиотека обеспечивает полную обратную совместимость.
Вам нет необходимости использовать внешние резисторы или диоды, так как библиотека использует внутренние подтягивающие резисторы в микроконтроллере на Arduino и дополнительно обеспечивает высокое входное сопротивление на всех неиспользуемых выводах столбцов.
Глобальные переменные
Данный заголовочный файл включает в себя следующие глобальные переменные:
int accel_x_OC – Содержит измерения положения акселерометра относительно оси x при калибровке
int accel_y_OC – Содержит измерения положения акселерометра относительно оси y при калибровке
int accel_z_OC – Содержит измерения положения акселерометра относительно оси z при калибровке
int gyro_x_OC – Содержит измерения положения гироскопа относительно оси x
int gyro_y_OC – Содержит измерения положения гироскопа относительно оси y
int gyro_z_OC – Содержит измерения положения гироскопа относительно оси z
float temp_scalled – Содержит абсолютное значение температуры в градусах цельсия
float accel_x_scalled – данные оси x акселерометра минус данные калибровки
float accel_y_scalled – данные оси y акселерометра минус данные калибровки
float accel_z_scalled – данные оси z акселерометра минус данные калибровки
float gyro_x_scalled – данные гироскопа относительно оси x минус данные калибровки
float gyro_y_scalled – данные гироскопа относительно оси y минус данные калибровки
float gyro_z_scalled – данные гироскопа относительно оси z минус данные калибровки
Загрузка, установка и импорт
Данная библиотека сейчас доступна через менеджер библиотека в Arduino IDE. Если вы используете современную IDE (версия 1.6.2 и выше), то можете просто использовать меню:
Скетч → Подключить библиотеку → Управлять библиотеками… А затем найти Keypad.
Когда найдете, нажмите на записи, и появится кнопка «Установка». ZIP файл приведен ниже для старых версий IDE.
Калибровка mpu6050
Калибровка гироскопа и акселерометра – это очень важный шаг. Приведенные значения для гироскопа имеют вид: “gyro_x_scalled = ”, так как для получения угла поворота относительно оси по данным угловой скорости, необходимо провести интегрирование.
Если “gyro_x_scalled” содержит ошибку или неверно выбрана база, эта ошибка также интегрируется и превращается в значительную погрешность в результате. Так что в идеале измерения должны показывать нуль, если гироскоп не движется вокруг каких-либо осей координат.
На практике добиться идеала практически невозможно, так что наша задача – минимизировать эту ошибку.
Кроме того, для компенсации «дрифта», можно использовать акселерометр для расчета угла наклона, сравнения полученных данных с результатами гироскопа и последующей компенсацией данной погрешности. Расчет угла будет рассмотрен в этой статье отдельно ниже.
На рисунках далее показано использование функции MPU6050_OffsetCal() непосредственно в программе в Arduino IDE.
Скетч Arduino для калибровки платы акселерометра/гироскопа MPU6050:
Результат работы скетча для калибровки в серийном мониторе
Окончательный расчет угла наклона и подбор коэффициентов усиления для фильтра
Результаты снимались для различных параметров коэффициентов усиления фильтра и приведены на рисунках по порядку. Коэффициент усиления 1 означает, что фактически идут измерения только с гироскопа. Можно заметить, что в конце angle_x и angle_y отклоняются от значений, рассчитанных с помощью значений с акселерометра.
В моем случае, для дальнейшего проекта использовался коэффициент усиления 0.95. В зависимости от динамики системы, можно его повышать, но не до 1, так как значения будут сильно отклоняться от истинных.
Погрешность гироскопа – «дрифт» (drift)
Из-зза неидеальной калибровки гироскопа, “gyro_x_scalled” никогда не равна нулю и со временем “angle_x_gyro” изменяет свои значения.
Для решения данной проблемы, проводится расчет угла с помощью акселерометра и полученные значения сравнывиются с углом гироскопа. Так как модуль MPU6050 располагается горизонтально, ускорение по оси z равно 1g (то есть, 9.
81) как это показано на рисунке. Мы можем использовать этот вектор ускорения и его проекцию на ось y для расчета угла между осями x и y.
Угол, который рассчитывается с помощью акселерометра, рассчитывается по зависимости:
Основными проблемами при определении угла наклона с помощью акселерометра являются: сильная зашумленность сигнала и очень сильная чувствительность к вибрациям, без которых ни один механизм не работает.
Более того, еслипри перемещении MPU6050 вдоль одной из осей координат, полученные значения будут мешать расчету угла.
Так что для лучшего результата, углы с гироскопа и акселерометра объединяются с помощью фильтра:
Окончательно уравнение для определения угла наклона принимает вид:
На рисунке ниже приведена имплементация полученных зависимостей в оболочке Arduino IDE
Подключение imu 10dof l3g4200d adxl345 hmc5883l bmp085 – популярная робототехника
Список этих параметров включает:
- проекция ускорения на три оси x,y,z (акселерометр ADXL345);
- скорость вращения вокруг трех осей x,y,z (гироскоп L3G4200D);
- проекции магнитного поля на три оси x,y,z (компас HMC5883L);
- атмосферное давление (барометр BMP085).
Здесь следует пояснить, что показания барометра можно легко преобразовать в высоту над уровнем моря, что также является одной из пространственных координат. Также, чип барометра имеет встроенный термодатчик, показания которого также могут быть сняты микроконтроллером.
Все расположенные на плате датчики соединены I2C шиной. Благодаря этому, устройство достаточно легко подключается ко всем распространенным платформам, включая Arduino, mbed и TI LaunchPad. Кроме того, такой вариант подключения высвобождает аналоговые входы микроконтроллера, количество которых ограничено.
Плата IMU имеет 11 выводов:
- M_DRDY – сигнал готовности измерений компаса HMC5883L;
- G_INT1,2 – программируемые прерывания гироскопа L3G4200D;
- A_INT1,2 – программируемые прерывания акселерометра ADXL345;
- P_EOC – завершение измерения температуры или давления в BMP085;
- P_XCLR – сброс всех регистров BMP085;
- SCL, SDA – I2C шина;
- VCC – питание 5В, 3.3В;
- GND – земля.
Для работы устройства требуется подключить только цепь питания и каналы шины I2C. Как обычно, эксперимент по оживлению устройства происходил при помощи mbed. Схема подключения изображена ниже.
Как видно на схеме, I2C линии “подтянуты” к напряжению питания сопротивлением 2.2КОм (рекомендуется 2.2 – 10КОм). Есть подозрение, что на плате IMU уже стоят соответствующие резисторы, обязательно проверю это предположение в следующий раз.
Что касается питания, то я подключил IMU к 3.3В, хотя согласно даташиту можно использовать и 5В.
Ввиду того, что указанный IMU содержит достаточно распространенные модели датчиков, найти соответствующие библиотеки для mbed не составило труда. Уверен, что для Arduino ситуация окажется аналогичной.
Единственные проблемы возникли при подключении гироскопа. Здесь следует помнить, что адреса I2C устройств на mbed сдвинуты на один бит влево относительно аналогичных адресов для Arduino.
Например, если Arduino использует для общения с гироскопом L3G4200D адреса 0x68 или 0x69, то при работе с mbed следует использовать 0xD1 или 0xD2, соответственно.
В коде библиотеки для данного гироскопа был установлен адрес 0xD2, и попробовать 0xD1 я догадался только после сканирования всей шины.
Код программы достаточно примитивен и почти полностью заимствован у одного из резидентов портала mbed.org.
#include “mbed.h”
#include “HMC5883L.h”
#include “ADXL345.h”
#include “L3G4200D.h”
#include “BMP085.h”
DigitalOut myled(LED1);
HMC5883L cmp(p9, p10); // sda, scl
ADXL345 acc(p9, p10); // sda, scl
L3G4200D gyr(p9, p10); // sda, scl
BMP085 alt(p9, p10); // sda, scl
Serial pc(USBTX, USBRX); // tx, rx
int main() {
pc.baud(19200);
int16_t data[3];
cmp.init();
wait(0.1);
// These are here to test whether any of the initialization fails. It will print the failure
if (acc.setPowerControl(0x00)){
pc.printf(“acc: didn’t intitialize power control“);
return 0; }
wait(.001);
//Resolution setup, /-2g.
if(acc.setDataFormatControl( ADXL345_FULL_RES || ADXL345_2G )){
pc.printf(“didn’t set data format“);
return 0; }
wait(.001);
//3.2kHz data rate.
if(acc.setDataRate( ADXL345_3200HZ )){
pc.printf(“didn’t set data rate“);
return 0; }
wait(.001);
//Measurement mode.
if(acc.setPowerControl( MeasurementMode )){
pc.printf(“didn’t set the power control to measurement“);
return 0; }
alt.init();
while (1) {
cmp.getXYZ(data);
pc.printf(“C % 4i % 4i % 4i “,data[0],data[1],data[2]);
wait(0.1);
acc.getXYZ(data);
pc.printf(” A % 5i % 5i % 5i”,data[0],data[1],data[2]);
wait(0.1);
gyr.getXYZ(data);
pc.printf(” G % 5i % 5i % 5i”,data[0],data[1],data[2]);
wait(0.05);
pc.printf(” T %d”, alt.get_temperature());
pc.printf(” P %d”, alt.get_pressure());
pc.printf(” A %.2f“, alt.get_altitude_m());
myled = !myled;
Ниже представлен скриношот выходных данных тестируемого IMU в приложении TeraTerm. Как можно заметить, в моей квартире температура воздуха составляет почти 28 градусов Цельсия. У меня нет другого градусника, но учитывая постоянное нытье гостей, я склонен верить этим показаниям.
Атмосферное давление – около 98 260 Паскалей, что соответствует 737 мм ртутного столба. Согласно данным об атмосферном давлении по городу, полученная величина примерно соответствует действительности.
Теперь что касается высоты над уровнем моря, которая рассчитывается исходя из показаний термометра и барометра по известным формулам (формулы есть в гугле и в даташите датчика).
Официально, город Екатеринбург расположен в 240 метрах над уровнем моря.
Учитывая холмистый рельеф города и тот факт, что измерения проводились на 16-м этаже, полученная величина в 258 метров выглядит вполне правдоподобно.
Я вполне доволен этим, относительно дешевым китайским IMU ($21 на ebay). Справедливости ради следует отметить, что китайского в нем только сама плата и обвязка.
Сами же датчики являются продуктом весьма солидных компаний, таких как Bosch, Pololu, Analog Devices и Honeywell.
Плата изготовлена качественно, все чипы расположены строго параллельно друг другу, что очень важно в подобных составных устройствах, которые используются для точного позиционирования в пространстве.
В ближайшем будущем, именно этот IMU заменит аналоговые гироскоп и акселерометр, которые сейчас установлены на моем квадрокоптере.
Пример
#include const byte ROWS = 4; //четыре строки const byte COLS = 3; //три столбца char keys[ROWS][COLS] = { {‘1′,’2′,’3’}, {‘4′,’5′,’6’}, {‘7′,’8′,’9’}, {‘#’,’0′,’*’} }; byte rowPins[ROWS] = {5, 4, 3, 2}; //подключить к выводам строк клавиатуры byte colPins[COLS] = {8, 7, 6}; //подключить к выводам столбцов клавиатуры Keypad keypad = Keypad( makeKeymap(keys)
Расчет угла с помощью гироскопа mpu6050
Данные с гироскопа имеют вид:
В дальнейшем в статье мы будем рассматривать все на примере оси x. Для расчета угла необходимо проинтегрировать переменную “gyro_x_scalled”
является количеством итераций
Так же стоит отметить, что на каждом временном промежутке цикла значение “gyro_x_scalled” остается одинаковым. Существует насколько подходов и методов интегрирования для компенсации и этой погрешности, но мы их детально не будем рассматривать.
Для реализации дискретного интегрирования, будем использовать метод Эйлера как один из самых популярных алгоритмов. Математически интегрирование методом Эйлера можно записать следующим образом:
Мы предполагаем, что начальные углы относительно осей x, y, z после калибровки равны 0, 0 и 90 градусов соответственно, так что для итерации n=0:
Значение T (время каждой итерации) и динамика самого гироскопа (как быстро и насколько нелинейно изменяются углы), значительным образом влияет на точность расчетов. Чем медленнее изменяются углы и чем меньше промежуток между итерациями, тем более точным будет результат.
В этом смысле жаль, что платы Arduino достаточно медленные, кристаллы у них работают с частотой 16 МГц и снятие измерений каждые 10-20 мс становится достаточно затруднительным (учитывая тот факт, что процессор занят не только расчетом угла, но и другими параллельными задачами).
Мы можем использовать T в виде переменной или константы, я, лично, предпочитаю использовать константу для каждого цикла. В проекте динамические факторы не учитывались, просто использовалась частота итераций с разрывом в 20 мс (0.02 с).
Создание
Конструкторы:
Функции в программе arduino для работы с mpu6050
MPU6050_ReadData()
Эта функция считывает данные с акселлерометра, гироскопа и датчика температуры. После считывания данных, значения переменных (temp_scalled, accel_x_scalled, accel_y_scalled, accel_z_scalled, gyro_x_scalled, gyro_y_scalled and gyro_z_scalled) обновляются.
MPU6050_ResetWake()
Эта функция сбрасывает настройки чипа на значения по-умолчанию. Рекомендуется использовать сброс настроек перед настройкой чипа на выполнения определенной задачи.
MPU6050_SetDLPF(int BW)
Эта функция настраивает встроенный фильтр низких частот. Переменная int BW должна содержать значения (0-6). Пропускная способность фильтра будет изменяться в соответствии с представленной ниже таблицей.
Если int BW не в диапазоне 0-6, фильтр низких частот отключается, что соответствует установке – бесконечность.
MPU6050_SetGains(int gyro,int accel)
Эта функция используется для установки максимального значения шкалы измерений
MPU6050_ReadData()
Эта функция использует масштабные коэффициенты для расчета результата. Если не используются значения (0-3), MPU6050_ReadData() отобразит необработанные значения с датчика с погрешностью калибровки. Для получения обработанных значений, установите переменные для калибровки (accel_x_OC, accel_y_OC, accel_z_OC, gyro_x_OC, gyro_y_OC and gyro_z_OC) в нуль.
MPU6050_OffsetCal()
Эта функция позволяет откалибровать акселерометр и гироскоп. Рассчитанные значения записываются в переменные accel_x_OC, accel_y_OC, accel_z_OC, gyro_x_OC, gyro_y_OC и gyro_z_OC для дальнейшей коррекции.
Для проведения калибровки необходимо расположить оси x и y axes платы MPU6050 в горизонтальной плоскости, а ось z – перпендикулярно к основанию. Даже незначительные перемещения платы во время калибровки понижают точность расчета базовой точки.
Ось z калибруется относительно силя земного притяжения – 9.81 м/с2 (1g), что учтено в коде.