Arduino и MPU6050 для определения угла наклона. Подключаем к Arduino акселерометр MMA7361 Питание акселерометров ADXL337 и ADXL377

Сегодня на рынке можно найти большое количество недорогих модулей датчиков, которые можно использовать в своих проектах, связав их предварительно с микроконтроллером. Одним из таких модулей является плата с микросхемой MMA7361, которая представляет собой трехосевой акселерометр.



Этот датчик может измерять статическое (сила земного притяжения) или динамическое ускорение по всем трем осям. Он может использоваться в различных сферах применения, и можно создать много приложений на его основе. Акселерометр измеряет уровень ускорения объекта, на котором он установлен, что позволяет получать информацию об ускорении/замедлении этого объекта, а также о его наклоне относительно земной оси.


Этот датчик также позволяет обнаружить свободное падение (выход 0G). Технически, MMA7361LC представляет собой малопотребляющий емкостный микромеханический акселерометр с функциями обработки сигнала, 1-полюсным низкочастотным фильтром, температурной компенсацией, самодиагностикой и возможностью выбора чувствительности. MMA7361LC может входить в спящий режим, что делает его идеальным для портативных устройств с батарейным питанием. Модуль может быть запитан как от источника 5 В, так и от 3.3 В.



Теперь на примере связки модуля MMA7361 и платы Arduino UNO покажем принцип работы с этим датчиком. К счастью, для подключения не нужны какие-либо дополнительные элементы, нужны только Arduino, модуль с акселерометром и провода. Схема и распиновка показаны ниже:




Ниже представлен скетч для простой работы с модулем. Используя эту программу, можно прочитать выходные значения с осей X, Y и Z с помощью последовательного монитора.


int x; // выходная переменная по оси x int y; // выходная переменная по оси y int z; // выходная переменная по оси z void setup() { Serial.begin(9600); // открываем порт, скорость передачи данных 9600 bps } void loop() { x = analogRead(5); // считываем вход A5 y = analogRead(4); // считываем вход A4 z = analogRead(3); // считываем вход A3 Serial.print("X = "); // выводим значение по x Serial.println(x); Serial.print("Y = "); // выводим значение по y Serial.println(y); Serial.print("Z = "); // выводим значение по z Serial.println(z); delay(100); }

Этот акселерометр я покупал под совершенно конкретную задачу - хотел сделать устройство, которое не дает спать на спине дольше заданного времени. Что характерно, все получилось, однако у акселерометра есть несколько интересных особенностей.

Собственно, о них и хочу упомянуть.

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

Однако при подключении всего лишь одного датчика сэкономить выводы контроллера цифровым протоколом не получится, поскольку по количеству требуемых линий что цифра, что аналог получаются идентичными.

Гребеночку уже напаял, да

Поэтому я и сделал выбор в пользу аналогового акселерометра ADXL335 ( для любопытных). Ведь с ним можно и память сэкономить, и общаться гораздо проще - достаточно банального analogRead().

Т.е. простейший код для чтения показаний действительно прост, как амеба:

Unsigned int x, y, z; void setup() { pinMode(A0, INPUT); pinMode(A1, INPUT); pinMode(A2, INPUT); Serial.begin(9600); } void loop() { x = analogRead(A0); y = analogRead(A1); z = analogRead(A2); Serial.println("xxxx | yyyy | zzzz"); Serial.print(x, DEC); Serial.print(" | "); Serial.print(y, DEC); Serial.print(" | "); Serial.print(z, DEC); Serial.println(" | "); delay(2000); }

В итоге пришло ровно то, что на картинке, и я с упоением занялся макетированием, причем сначала - на полноразмерной плате Arduino Mega 2560. И сильно удивился, поскольку поведение акселерометра не очень укладывалось в рамки здравого смысла. Ну, по крайней мере, пока здравый смысл не сказал что-то вроде «окей, даташит я не читал, но будем считать, что акселерометр так и работает».

Вот крупнее, если не верите, что это ADXL335

Иными словами, я ожидал увидеть на выходах акселерометра значения в диапазоне от 0В до верхнего предела питания, т.е. 3,3В или 5В, поскольку акселерометр работает с обоими, но об этом позже.

Вместо этого вывод в монитор показал примерно следующее. Примерно - потому что у меня не было стенда с идеальными вертикалями и горизонталями. Все вот этими вот руками.

Значения при максимуме по оси X:
X 405 Y 331 Z 344

Значения при минимуме по оси X:
X 268 Y 333 Z 344

Значения при максимуме по оси Y:
Y 400 X 338 Z 346

Значения при минимуме по оси Y:
Y 264 X 334 Z 346

Значения при максимуме по оси Z:
Z 410 X 337 Y 329

Значения при минимуме по оси Z:
Z 275 X 335 Y 331

Показания эти идентичны что для 3В, что для 5В.

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

Второе - упомянутый выше дуализм в смысле питания. Суть в том, что ADXL335 рассчитан на диапазон напряжений от 1,8В до 3,6В. А до 5В его дотянули очень простым способом - поставили стабилизатор на 3,3В ко входу питания.

Решение несколько варварское, поскольку вне зависимости от входного напряжения, пусть даже оно и в допустимых для акселерометра 1,8-3,6В, ток пойдет через стабилизатор. А это довольно критично, если задаться целью сделать максимально экономичное устройство.

На этот случай, как выяснилось, есть более подходящие кандидаты. Именно: макетные платки с питанием от 3,3В или же гибридные, где 5В идет через стабилизатор, а 3,3В - напрямую к чипу. В любом случае, при покупке рекомендую внимательно изучать, что собрались приобретать и соотносить увиденное с желаемым.

Что касается меня, то я решил вопрос со стабилизатором просто. Так как питаться планировал от 3В, то и питающую линию подключил сразу после стабилизатора, и на этом закрыл вопрос.

Подключился вот в эту точку

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

Выглядит не очень презентабельно, поскольку корпуса - то, что я никогда делать не умел.

Батарейка - для масштаба

.

Ничего, скоро сошью чехольчик, и будет лучше.

А вот так работает макет, где как раз видно работящий акселерометр:

По итогам общения с акселерометром (конкретно в этой модификации) хочу сообщить следующее. Штука, на мой взгляд, очень хороша для новичков сразу по нескольким причинам:

1) Безопасно для макетных плат с напряжением 3.3В и 5В, поскольку вход питания один и защищен стабилизатором;

2) Стабильность показаний;

3) Просто в использовании за счет аналогового интерфейса - analogRead() и никакой черной магии.

Что касается минусов, то они вытекают из плюсов:

1) Чтобы экономить энергию, придется поработать руками - припаяться напрямую к чипу;

2) Существует возможность поймать помехи на аналоговой линии.

Доклад закончил. Скоро буду писать про шорты брюки.

Планирую купить +21 Добавить в избранное Обзор понравился +22 +39

ADXL335 — это аналоговый трехосный акселерометр, то есть датчик, с помощью которого можно получить угол относительного отклонения. Фактически, это три разных акселерометра в одном корпусе, каждый из которых отвечает за свою собственную ось X, Y либо же Z.

Вообще, Акселерометр — приспособление для измерения ускорения. Однако, из общего курса школьно физики мы знаем, что ускорение бывает двух видов: динамическое и статическое . С динамическим ускорением должно быть все понятно — толкнули датчик, придали ему ускорение, он должен это зафиксировать. Статическое ускорение — это воздействие силы тяжести на наш датчик. Дело в том, что к датчику даже в состоянии полного покоя приложено статическое ускорение равное g (ускорение свободного падения).

Датчик ADXL335 умеет улавливать оба этих ускорения. А зная проекции его вектора можно спокойно вычислить угол на который отклонился наш датчик относительно некого нулевого значения.

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

Для начала разберемся с правой частью картинки, на которой меняет свое значение Zout (ось Z). Согласно этой картинке, если положить наш датчик контактами вниз, то значение по оси Z будет равно единице (точнее одному g). Данное значение, как было сказано — проекция вектора статического ускорения на ось нашего датчика. Так как в данном случае вектор совпадает с осью Z, а ускорения свободного падения равняется g, мы и имеет значение Zout = 1g.
Если же мы перевернем датчик контактами вверх, то значение Zout изменится на противоположное. Стоит отметить, что все остальные ускорения равны нулю, связано это с уже упомянутым совпадением вектора статического ускорения с осью Z, а так же состоянием покоя всего датчика.
Аналогично можно рассмотреть все остальные пары. Единственное отличие в том, что датчик будет находится на ребре или боку.


Однако, вектор далеко не всегда будет совпадать с какой-либо из осей. Чаще всего этот вектор будет каким-либо распределен по всем трем осям — т.к. пространство трехмерное.

О датчике ADXL335

  • Максимально допустимым значение напряжения для ADXL335 является 3,6 вольта
  • Датчик справляется с ускорениями до 3g. Это можно использовать например, чтобы определить находится ли вся конструкция в движении, и даже в каком направлении она двигается. Можно измерять ускорение при начале движения и тем самым делать его более плавным, без резких рывков.

Схема подключения акселерометра

  • Внимание! Для питания выход 3v3 Arduino, а не 5v
  • Выходы X, Y, Z датчика соединить со входами ANALOG IN 0, 1, 2

Пример программного кода — программирование акселерометра

#define ADC_ref 5.0 #define analog_resolution 1024.0 unsigned int value_x; unsigned int value_y; unsigned int value_z; void setup() { Serial.begin(9600); } void loop() { value_x = analogRead(0); value_y = analogRead(1); value_z = analogRead(2); Serial.print(value_x/analog_resolution*ADC_ref, 5); Serial.print(" "); Serial.print(value_y/analog_resolution*ADC_ref, 5); Serial.print(" "); Serial.println(value_z/analog_resolution*ADC_ref, 5); delay(500); }

#define ADC_ref 5.0

#define analog_resolution 1024.0

unsigned int value_x ;

unsigned int value_y ;

unsigned int value_z ;

void setup () {

Serial . begin (9600 ) ; }

void loop () {

value_x = analogRead (0 ) ;

value_y = analogRead (1 ) ;

value_z = analogRead (2 ) ;

Serial . print (value_x / analog_resolution * ADC_ref , 5 ) ;

Serial . print (" " ) ;

(500 ) ; }

Обозначаем пару констант. ADC_ref — это максимальное значение в вольтах которое может снять аналоговый вход. analog_resolution — это разрешающая способность нашего аналогового входа. На arduino она равна 210 или 1024.
После объявления констант идет пара переменных в которых мы будем хранить показания снятые с нашего датчика и инициализация серийного порта, чтобы можно было получить какие-то данные на компьютере.
В функции loop мы в начале получаем данные с трех наших аналоговых пинов, к которым и подключен наш датчик, а после этого пересчитываем полученное число в вольты и выводим их на серийный порт. Зальем эту прошивку в нашу Arduino UNO, откроем серийный монитор (ctrl+shift+m) и соберем кое какие данные.

На включенном серийном мониторе можно увидеть:

Где первый столбец — показания по оси X, второй — Y, третий — Z

Инструкция

Акселерометры используют для определения вектора ускорения. Акселерометр ADXL335 имеет три оси, и благодаря этому он может определять вектор ускорения в трёхмерном пространстве. Ввиду того, что сила земного притяжения - это тоже вектор, то акселерометр может определять свою собственную ориентацию в трёхмерном пространстве относительно центра Земли.
На иллюстрации приведены рисунки из паспорта (http://www.analog.com/static/imported-files/data_sheets/ADXL335.pdf) на акселерометр ADXL335. Здесь изображены координатные оси чувствительности акселерометра по отношению к геометрическому размещению корпуса устройства в пространстве, а также таблица значений напряжения с 3-х каналов акселерометра в зависимости от его ориентации в пространстве. Данные в таблице приводятся для находящегося в состоянии покоя датчика.
Рассмотрим подробнее, что же показывает нам акселерометр. Пусть датчик лежит горизонтально, например, на столе. Тогда проекция вектора ускорения будет равна 1g по оси Z, или Zout = 1g. По остальным двум осям будут нули: Xout = 0 и Yout = 0. При повороте датчика "на спину", он будет направлен в противоположную сторону относительно вектора силы тяжести, т.е. Zout = -1g. Аналогично измерения снимаются по всем трём осям. Понятно, что акселерометр может быть расположен как угодно в пространстве, поэтому со всех трёх каналов мы будем снимать отличные от нуля показания.
Если датчик сильно тряхнуть вдоль вертикальной оси Z, то значение Zout будет больше, чем "1g". Максимальное измеряемое ускорение - "3g" по каждой из осей в любом из направлений (т.е. как с "плюсом", так и с "минусом").

Думаю, с принципом работы акселерометра разобрались. Теперь рассмотрим схему подключения.
Чип аналогового акселерометра ADXL335 довольно мелкий и помещён в BGA корпус, и в домашних условиях его сложно смонтировать на плату. Поэтому я буду использовать готовый модуль GY-61 с акселерометром ADXL335. Такие модули в китайских интернет-магазинах стоят практически копейки.
Для питания акселерометра необходимо подать на вывод VCC модуля напряжение +3,3 В. Измерительные каналы датчика подключаются к аналоговым выводам Arduino, например, "A0", "A1" и "A2". Это вся схема:)

Загрузим вот такой скетч в память Arduino. Будем считывать с аналоговых входов показания по трём каналам, преобразовывать их в напряжение и выводить их в последовательный порт.
Arduino имеет 10-разрядный АЦП, а максимальное допустимое напряжение на выводе - 5 вольт. Измеренные напряжения кодируются битами, которые могут принимать только 2 значения - 0 или 1. Это значит, что весь диапазон измерений будет поделён на (1+1) в 10-ой степени, т.е. на 1024 равных отрезка.
Для того чтобы перевести снимаемые показания в вольты, нужно каждое измеренное на аналоговом входе значение поделить на 1024 (отрезка), а затем умножить на 5 (вольт).
Посмотрим, что же реально приходит с акселерометра на примере оси Z (последний столбец). Когда датчик расположен горизонтально и смотрит вверх, приходят числа (2,03 +/-0,01). Значит, это должно соответствовать ускорению "+1g" по оси Z и углу 0 градусов. Перевернём датчик. Приходят числа (1,69 +/-0,01), что должно соответствовать "-1g" и углу 180 градусов.

Снимем значения с акселерометра при углах 90 и 270 градусов и занесём в таблицу. Таблица показывает углы поворота акселерометра (столбец "A") и соответствующие им значения Zout в вольтах (столбец "B").
Для наглядности приведён график напряжений на выходе Zout в зависимости от угла поворота. Голубое поле - это область значений в спокойном состоянии (при ускорении 1g). Розовое поле на графике - это запас для того чтобы мы могли измерять ускорение до +3g и до -3g.
При повороте 90 градусов на ось Z приходится нулевое ускорение. Т.е. значение 1,67 вольт - это условный ноль Zo для оси Z. Тогда найти ускорение можно так:
g = Zout - Zo / sensitivity_z, здесь Zout - измеренное значение в милливольтах, Zo - значение при нулевом ускорении в милливольтах, sensitivity_z - чувствительность датчика по оси Z. Чувствительность приведена в паспорте и равна в среднем 300 мВ/g, но вообще лучше провести калибровку акселерометра и вычислить значение чувствительности конкретно для вашего датчика по формуле:
sensitivity_z = * 1000. В данном случае чувствительность акселерометра по оси Z = (2,03 - 1,68)*1000 = 350 мВ. Аналогично чувствительность нужно будет посчитать для осей X и Y.
В столбце "С" таблицы приводится ускорение, вычисленное для пяти углов при чувствительности, равной 350. Как видно, они практически совпадают с теми, которые показаны на рисунке 1.

Вспомнив базовый курс геометрии, получим формулу для вычисления углов поворота акселерометра:
angle_X = arctg[ sqrt(Gz^2 + Gy^2) / Gx ].
Значения получаются в радианах. Чтобы перевести их в градусы, поделим на число "Пи" и умножим на 180.
В итоге полный скетч, вычисляющий ускорения и углы поворота акселерометра по всем осям, приведён на иллюстрации. В комментариях даны пояснения к коду программы.
При выводе в порт "Serial.print()" символ "\t" обозначает знак табуляции, чтобы столбцы были ровные и значения располагались друг под другом. "+" означает конкатенацию (соединение) строк. Причём оператор "String()" явно указывает компилятору, что численное значение нужно преобразовать в строку. Оператор "round()" округляет угол с точностью до 1 градуса.

Итак, мы с вами научились снимать и обрабатывать данные с аналогового акселерометра ADXL335 при помощи Arduino. Теперь мы можем использовать акселерометр в своих разработках.

Новые статьи

● Проект 24: 3-осевой гироскоп + акселерометр на примере GY-521

В этом эксперименте мы познакомимся с акселерометром и гироскопом и будем с помощью Arduino получать показания с этих датчиков.

Необходимые компоненты:

Модуль GY-521 на микросхеме MPU6050 содержит гироскоп, акселерометр и температурный сенсор. На плате модуля GY-521 расположена необходимая обвязка MPU6050, в том числе подтягивающие резисторы, стабилизатор напряжения на 3,3 В с малым падением напряжения с фильтрующими конденсаторами. Обмен с микроконтроллером осуществляется по шине I2C.

Гироскоп представляет собой устройство, реагирующее на изменение углов ориентации контролируемого тела. Акселерометр - это устройство, которое измеряет проекцию кажущегося ускорения, то есть разницы между истинным ускорением объекта и гравитационным ускорением.
Схема соединений платы GY-521 к Arduino показана на рис. 24.1.

Рис. 24.1. Схема соединения GY-521 к Arduino


Код простого скетча для считывания значений гироскопа и акселерометра с датчика MPU6050 показан в листинге 24.1.

// подключение библиотек #include "I2Cdev.h" #include "MPU6050.h" #include "Wire.h" MPU6050 accelgyro; int16_t ax, ay, az; int16_t gx, gy, gz; void setup () { } Wire.begin(); Serial.begin(38400 ); // инициализация Serial.println("Initializing I2C devices..." ); accelgyro.initialize(); delay(100 ); } void loop () { // чтение значений гироскопа и акселерометра accelgyro.getMotion6(&ax, &ay, &az, &gx, &gy, &gz); // вывод значений в монитор Serial.print("a/g:\t" ); Serial.print(ax); Serial.print("\t" ); Serial.print(ay); Serial.print("\t" ); Serial.print(az); Serial.print("\t" ); Serial.print(gx); Serial.print("\t" ); Serial.print(gy); Serial.print("\t" ); Serial.println(gz); }
Порядок подключения:

1. Подключаем плату GY521 к плате Arduino по схеме на рис. 24.1.
2. Загружаем в плату Arduino скетч из листинга 24.1.
3. Открываем монитор последовательного порта Arduino IDE и смотрим вывод данных гироскопа и акселерометра (см. рис. 24.2).
4. При поворотах датчика данные изменяются.

Рис. 24.2. Вывод данных гироскопа и акселерометра в монитор Arduino IDE


Область применения таких датчиков достаточно широка. Данный модуль часто применяют для стабилизации полета квадрокоптера по причине совместного использования гироскопа и акселерометра. Кроме этого, модуль можно использовать для координации различных устройств - от просто детектора движения до системы ориентации различных роботов или управления движениями какими-либо устройствами. Область подобных сенсорных устройств достаточно новая и интересная для изучения и применения в любительской технике.