ADXL335 акселерометры. теория и практика. Arduino и MPU6050 для определения угла наклона Схема подключения акселерометра к Arduino

Технический рынок наполнен тысячами модулями датчиков, которые стоят недорого и используются в проектном конструировании. Перед этим модули связывают с программируемым микроконтроллером. Акселерометр – инструмент, использующийся для расчета разности между настоящим и гравитационным ускорением предмета. Датчик состоит из платы со встроенной микросхемой.

Прибор применяют везде. Статья ниже – вспомогательная инструкция по подключению акселерометра к Ардуино.

Для проекта понадобятся несколько компонентов:

Микроконтроллер Arduino UNO R3

МК создан с использованием материалов контроллера ATmega328:

  1. цифровые входы и выходы в количестве 14 штук, причем половина приходится на ШИМ-выходы;
  2. аналогичные входы, количество – 6 штук;
  3. резонатор на основе кварца, мощностью 16 МГц;
  4. встроен usb-вход;
  5. контакт для подключения питания;
  6. на МК располагается кнопка, с помощью которой возможен сброс данных и кода;
  7. контакт для программирования данных, находящихся внутри схемы, именуемый ICSP.

Старт работы начинается с подачи электрического питания в плату. Пользователь подключает к плате со схемой блок питания или зарядное устройство. Также процедура осуществляется с помощью usb-кабеля, который подключен к компьютеру и микроконтроллеру. Для разработки программы понадобится бесплатная среда программирования – Arduino IDE.

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

Пользователь создает в бесплатной среде код, затем его компилирует и загружает проработанную программу в пространство памяти в Ардуино. Язык, на котором программируется код, Wiring максимально приближен к популярному среди программистов языку – C++. Кроме того МК поддерживает версии для осей Виндовс, Мак ОС и Линукс.

Модуль датчика для гироскопа акселерометра на Аrduino с 3 осями – GY-521 (MPU-6050)

В основе компонента лежит микросхема MPU-6050. В комплект входят 2 предмета – гироскоп и акселерометр. Данные устройства перед конструированием обрабатываются и затем переносятся прямиком в микроконтроллер через интерфейс

Модуль датчика помогает определять место и перемещение инструмента в пространстве. Измеряются дифферент и углы крена посредством вектора силы тяжести и скорости в процессе вращения. Также включена функция измерения температурного режима. Перемещение определяется линейным ускорением и угловой скоростью. Полная картина рисуется по 3 осям.

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

Макетная плата, предназначенная для прототипирования

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

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

Материал для изготовления беспаечных макетных плат – пластик. Кроме того, все контакты надежно скреплены к плате, поэтому частые переключения не испортят элемент.

Соединительные провода папа-папа

Обычные провода папа-папа нам подойдут, еще их называют провода-перемычки. Такие стоят недорого и продаются везде, на любом рынке или в любом онлайн-магазине для радиолюбителей.

Шаг 2. Схема подключения акселерометра к микроконтроллеру Arduino

Порядок и схема подключения довольно просты:

GY-521 (MPU-6050) Arduino Uno
VCC 3.3 V
GND GND
SCL A5
SDA A4
  1. Присоединяем модуль датчика к микроконтроллеру.
  2. На МК Ардуино загружаем проработанный код, представленный в разделе ниже.
  3. Открываем среду разработки Arduino IDE и мониторим последовательный порт.
  4. Сверяем выводимые данные акселерометра и гироскопа.
  5. Во время поворота датчика сведения не производят изменений.

Гироскоп – инструмент, который позволяет измерить реакцию тела на перемещение углов и вообще ориентации. Акселерометр же служит измерителем проекции ускорения, которое только кажется.

Шаг 3. Программируем Arduino для обработки информации, полученной с акселерометра

Алгоритм написания программы в последовательности:

// Подключаем необходимые для работы библиотек #include "MPU6050.h"; #include "I2Cdev.h"; #include "Wire.h"; // Создаем объект, символизирующий модуль датчика MPU6050 axeler; // Создаем объект библиотеки Wire Wire b; // Создаем объект, который символизирует контакт I2C I2Cdev h; // Вводим цифровые данные, отвечающие за точки в 3-х осях int16_t axx, axy, axz; int16_t gix, giy, giz; // Объявляем метод, который будет запускать программу void setup() { // Начинаем работу Wire.begin(); h.begin(38400); // Производим инициализацию, отчет выводится после компиляции h.println("Initializing I2C devices..."); axeler.initialize(); delay(100); } // Считываем значения гироскопа и акселерометра с помощью адресов, которые принадлежат описанным выше переменным void loop() { axeler.getMotion6(&axx, &axy, &axz, &gix, &giy, &giz); // Выводим получившиеся значения на экран h.print("a/g:\t"); h.print(axx); h.print("\t"); h.print(axy); hl.print("\t"); hl.print(axz); h.print("\t"); h.print(gix); h.print("\t"); h.print(giy); h.print("\t"); h.println(giz); }

Вуаля! Акселерометр Аrduino запрограммирован.

В принципе, для разнообразия можно написать еще один скетч (ниже), но тогда нам нужна будет еще одна библиотека - , которая преобразует показания координат X и Y.

#include #include "Kalman.h" Kalman kalmanX; Kalman kalmanY; uint8_t IMUAddress = 0x68; /* IMU Data */ int16_t accX; int16_t accY; int16_t accZ; int16_t tempRaw; int16_t gyroX; int16_t gyroY; int16_t gyroZ; double accXangle; // Angle calculate using the accelerometer double accYangle; double temp; double gyroXangle = 180; // Angle calculate using the gyro double gyroYangle = 180; double compAngleX = 180; // Calculate the angle using a Kalman filter double compAngleY = 180; double kalAngleX; // Calculate the angle using a Kalman filter double kalAngleY; uint32_t timer; void setup() { Wire.begin(); Serial.begin(9600); i2cWrite(0x6B,0x00); // Disable sleep mode kalmanX.setAngle(180); // Set starting angle kalmanY.setAngle(180); timer = micros(); } void loop() { /* Update all the values */ uint8_t* data = i2cRead(0x3B,14); accX = ((data << 8) | data); accY = ((data << 8) | data); accZ = ((data << 8) | data); tempRaw = ((data << 8) | data); gyroX = ((data << 8) | data); gyroY = ((data << 8) | data); gyroZ = ((data << 8) | data); /* Calculate the angls based on the different sensors and algorithm */ accYangle = (atan2(accX,accZ)+PI)*RAD_TO_DEG; accXangle = (atan2(accY,accZ)+PI)*RAD_TO_DEG; double gyroXrate = (double)gyroX/131.0; double gyroYrate = -((double)gyroY/131.0); gyroXangle += kalmanX.getRate()*((double)(micros()-timer)/1000000); // Calculate gyro angle using the unbiased rate gyroYangle += kalmanY.getRate()*((double)(micros()-timer)/1000000); kalAngleX = kalmanX.getAngle(accXangle, gyroXrate, (double)(micros()-timer)/1000000); // Calculate the angle using a Kalman filter kalAngleY = kalmanY.getAngle(accYangle, gyroYrate, (double)(micros()-timer)/1000000); timer = micros(); Serial.println(); Serial.print("X:"); Serial.print(kalAngleX,0); Serial.print(" "); Serial.print("Y:"); Serial.print(kalAngleY,0); Serial.println(" "); // The accelerometer"s maximum samples rate is 1kHz } void i2cWrite(uint8_t registerAddress, uint8_t data){ Wire.beginTransmission(IMUAddress); Wire.write(registerAddress); Wire.write(data); Wire.endTransmission(); // Send stop } uint8_t* i2cRead(uint8_t registerAddress, uint8_t nbytes) { uint8_t data; Wire.beginTransmission(IMUAddress); Wire.write(registerAddress); Wire.endTransmission(false); // Don"t release the bus Wire.requestFrom(IMUAddress, nbytes); // Send a repeated start and then release the bus after reading for(uint8_t i = 0; i < nbytes; i++) data [i]= Wire.read(); return data; }

После второго скетча вы на экране сможете увидеть подобные цифры:

Заключение

Модуль датчика – устройство, которое широко используется во многих сферах человеческой жизни. С помощью датчика приводят в норму полет квадрокоптера, потому что гироскоп и акселерометр часто применяются в совокупности.

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

Позволяет определять ускорение действующее в направлении осей X, Y, Z и применяется для определения ориентации объекта в пространстве: углов крена и тангажа.

Видеообзор

Подключение и настройка

Акселерометр общается с управляющей электроникой по протоколу I²C / TWI . Для подключения используется два 3-проводных шлейфа . При подключении модуля к Arduino удобно использовать . Для получения данных с акселерометра мы написали библиотеку Troyka-IMU . Она скрывает в себе все тонкости протокола, через который передаются данные c акселерометра и предоставляет простые и понятные функции для вывода значений.

Пример работы

В качестве примера выведем в Serial порт направление и величину ускорения свободного падения по осям X, Y, Z.

accelerometer.ino // библиотека для работы I²C #include // библиотека для работы с модулями IMU #include // создаём объект для работы с акселерометром Accelerometer accel; void setup() { // открываем последовательный порт Serial.begin (115200 ) ; // выводим сообщение о начале инициализации Serial.println ("Accelerometer init..." ) ; // инициализация акселерометра accel.begin () ; // устанавливаем чувствительность акселерометра // 2g - по умолчанию, 4g, 8g accel.setRange (RANGE_2G) ; // выводим сообщение об удачной инициализации Serial.println ("Initialization completed" ) ; } void loop() { // вывод направления и величины ускорения в м/с² по оси X Serial.print (accel.readAX () ) ; Serial.print ("\t \t " ) ; // вывод направления и величины ускорения в м/с² по оси Y Serial.print (accel.readAY () ) ; Serial.print ("\t \t " ) ; // вывод направления и величины ускорения в м/с² по оси Z Serial.print (accel.readAZ () ) ; Serial.print ("\t \t " ) ; Serial.println ("" ) ; delay(100 ) ; /* // вывод направления и величины ускорения в м/с² по X, Y и Z float x, y, z; accel.readAXYZ(&x, &y, &z); Serial.print(x); Serial.print("\t\t"); Serial.print(y); Serial.print("\t\t"); Serial.print(z); Serial.println(""); delay(100); */ }

Элементы платы

Акселерометр на LIS331DLH

Акселерометр основан на чипе LIS331DLH и представляет собой миниатюрный датчик ускорения выполненный по технологии MEMS компании STMicroelectronicsd в корпусе LGA 16 (3x3x1 мм). Общение акселерометра с управляющей электроникой осуществляется по протоколу I²C / TWI . Адрес устройства равен 0b0011000.

ADXL337 и ADXL377 - это компактные, тонкие, маломощные 3-х осевые акселерометры, которые на выходе дают аналоговый сигнал в вольтах.

Основная разница между этими акселерометрами - диапазон измерений. ADXL337 измеряет ускорения в диапазоне ±3 g, а ADXL377 работает в диапазоне ±200 g и может использоваться для измерения более резких изменений движений контролируемого объекта, может использоваться для оценки вибраций.

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

На фото ниже приведены платы с установленными акселерометрами:

Обзор и технические характеристики акселерометров ADXL337 и ADXL377

Акселерометры ADXL337 и ADXL377 можно (и рекомендуется!) покупать уже интегрированными в отдельный модуль. На модуле предусмотрена необходимая минимальная обвязка и готовые контакты для подключения к Arduino или другому микроконтроллеру.


Как видите, на обоих модулях одинаковое количество контактов. В таблице ниже приведена краткая информация о каждом из контактов на модулях:


Питание акселерометров ADXL337 и ADXL377

Здесь надо быть предельно осторожным. ADXL337 и ADXL377 оба должны запитываться максимальным напряжением 3.6 В! Это напряжение подается к контакту питания и к контакту Self Test. Можно использовать Arduino 5 В или 3.3 В для считывания значений с отдельных осей акселерометра, а запитывать сам датчик ускорения от 3.3 В. Но не забывайте, что значения, которые вы получите с сенсора после аналогово-цифрового преобразования будут разными при 5 В и при 3.3 В! Поэтому надо уточнять диапазоны в зависимости от сигнала преобразования.

Одним из достоинств акселерометров ADXL337 и ADXL377 является то, что они потребляют мало тока для работы. Обычно это около 300 мА.

Необходимые пояснения по использованию ADXL337 и ADXL377

Если вы запитываете ADXL337 или ADXL377 от 3.3 В, значение 1.65 В на контакте оси X будет соответствовать ускорению 0 g. Если на пине X у вас показания напряжения составляют 3.3 В, то на ADXL337 это значит, что сила составляет 3g. В то время как при показаниях 3.3 В на ADXL377 означают, что нагрузка составляет 200g. По сути оба чипа используются и подключаются одинаково, но показания будут разными, так как они зависят от максимально допустимых значений, которые считывает акселерометр.

На модуле ADXL377 предусмотрены 4 отверстия для крепежа, так как этот датчик ускорения рассчитан на более экстремальные условия нагрузок.

На обоих модулях установлены конденсаторы на 0.01 мкФ возле выходов на оси X, Y, и Z. То есть, максимальные частоты, в пределах которых вы можете оценивать ускорение составляет 500 Гц.

Пример подключения к Arduino

Распайка

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

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

Подключаем акселерометр к Arduino

В этом примере мы рассмотрим как можно использовать контроллер Arduino Uno для сбора и обработки данных с модуля акселерометра ADXL337 или ADXL377. Так как выходной сигнал с датчика аналоговый, нам надо подключить три контакта с отдельных осей координат к контактам "Analog In" на Arduino. На рисунке ниже показана схема подключения модуля ADXL337. ADXL377 подключается так же.


Запитать акселерометр можно с помощью контакт 3.3 В и GND на Arduino. Контакты осей X, Y, и Z с датчика подключаются к ADC пинам (A0, A1, и A2 в рассматриваемом примере). Пин self test (ST) можно не подключать, а можно подключить к земле (GND). Если вы хотите использовать ST контакт для двойной проверки функционирования сенсора, подключите его к 3.3 В. Для дополнительной информации по этому поводу можете ознакомится с даташитами сенсоров: ADXL377 и ADXL377 .

Программа для Arduino

После того как вы подключили акселерометр к Arduino, можно перейти к программированию. Полный скетч вы можете скачать с Github. Ссылка для ADXL337 и для ADXL377 . Единственное отличие в этих скетчах - значение переменной scale.

Первые две строки кода в скетче служат для настройки параметров под ваш модуль датчика ускорения:

int scale = 3; boolean micro_is_5V = true;

Значение переменной scale устанавливается равным максимальному значению измеряемой силы g. Для ADXL337 это значение устанавливается равным 3, а для модели ADXL377 переменная принимает значение 200, так как сенсоры обеспечивают диапазоны измерений ±3g и ±200g соответственно. Переменной micro_is_5V присваивается значение true, если используется контроллер с 5 В (например, Arduino Uno) и значение false,using если вы используете контроллер на 3.3 В (например, Arduino Pro Mini). Это важный параметр, который напрямую влияет на дальнейшую интерпретацию данных с сенсора.

После этого используем функцию setup() для инициализации серийного соединения. Благодаря этому мы сможем выводить показания в окно серийного монитора Arduino IDE.

void setup() { // устанавливаем связь по серийному протоколу со скоростью передачи данных 115200 baud

Serial.begin(115200); }

В пределах функции loop(), мы собираем данные с датчика, масштабируем их для отображения в единицах измерения силы g и отображаем в окне серийного монитора изначальные и преобразованные данные. Для начала давайте взглянем на то, как считываются данные с датчика ускорения.

void loop() { // получаем данные с акселерометра для каждой отдельной оси координат

int rawX = analogRead(A0);

int rawY = analogRead(A1);

int rawZ = analogRead(A2);

Для того, чтобы получить числовое значение в диапазоне от 0 до 1023, которые соответствуют напряжению на входах Arduino, мы используем аналоговые входы A0, A1, и A2 и несколько считываемых значений. Эти значения напряжений отражают последнее измеренное значение ускорения с сенсора. Например, если ADXL337 показывает 3.3 В на контакте X, это означает, что сейчас ускорение вдоль оси X составляет +3g. Причем зависит это от вашей модели контроллера. Если вы используете микроконтроллер 3.3 В, считываемые аналоговые значения будут возвращать 1023 и храниться в переменной rawX. Если вы используете микроконтроллер 5 В, возвращаемые аналоговые значения будут равны 675. Храниться они будут в той же переменной. Именно поэтому важно корректно настроить переменную micro_is_5V, чтобы мы знали как правильно интерпретировать текущие показания.

Зная напряжение вашей платы Arduino, мы можем масштабировать полученные int значения и получить показания измерений в единицах измерения g. Ниже приведен кусок куда, с помощью которого мы приводим полученные показания к необходимым единицам измерения:

float scaledX, scaledY, scaledZ; // масштабированные значения для каждой оси

if (micro_is_5V) // микроконтроллер работает с 5 В

{ scaledX = mapf(rawX, 0, 675, -scale, scale); // 3.3/5 * 1023 =~ 675

} else // микроконтроллер 3.3 В

{ scaledX = mapf(rawX, 0, 1023, -scale, scale); }

Масштабированные значения хранятся в виде типа данных float. После этого мы проверяем, какой у нас контроллер (3.3 В или 5 В), с помощью булевой переменной micro_is_5V. По результатам проверки мы масштабируем целое значение x - rawX и превращаем его в значение со знаком после запятой, которое соответствует силе g. Переменная для хранения новых значений называется scaledX. То же самое мы делаем для осей Y и Z. Детально рассматривать эти оси мы не будем, так как процесс преобразования совершенно идентичный. Важно запомнить, что на Arduino 5 В мы получаем 675 при напряжении на пине 3.3 В, а Arduino 3.3 В интерпретирует измерения, которые соответствуют 3.3 В в виде значения 1023.

Функция mapf(), которая используется в скетче, работает так же как и стандартная Arduino функция map(). Основная причина, по которой используется именно mapf() - она может работать с десятичными значениями, а стандартная функция - только с целыми типа int.

После преобразования, мы выводим в окно серийного монитора текущие и преобразованные данные. Вероятно, вас будут интересовать только преобразованные, масштабированные значения ускорения, но потоковые данные оставлены специально, чтобы вы могли их сравнить с результатом и лучше понять принцип работы акселерометра. Часть кода, которая отвечает за вывод данных по каждой из осей чувствительности акселерометра ADXL337 или ADXL377 приведена ниже:

// выводим в окно серийного монитора текущие показания акселерометра по осям чувствительности X,Y,Z

Serial.print("X: ");

Serial.println(rawX); // выводим преобразованные показания с акселерометра по осям X,Y,Z

Serial.print("X: ");

Serial.print(scaledX);

Serial.println(" g");

Это позволяет нам увидеть данные в двух видах.

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

В примере выставлена задержка в 2 секунды (2000 миллисекунды), так как мы просто выводим показания сенсора в окно серийного монитора в целях ознакомления с акселерометром. В реальных проектах вы можете считывать данные с датчика с частотой 500 Гц. То есть, значение задержки можно сократить вплоть до 2 миллисекунд.

После этого возвращаемся в начало нашего цикла loop().

Надеемся, что эта статья поможет вам освоить работу акселерометров в связке с Arduino и вы используете полученные знания в ваших личных проектах. Кстати, с помощью акселерометра вы можете определять не только ускорение, но и перемещения, которое совершает объект. Подробная статья по определению угловых перемещений с помощью акселерометра и гироскопа: Arduino и MPU6050 для определения угла наклона .

Оставляйте Ваши комментарии, вопросы и делитесь личным опытом ниже. В дискуссии часто рождаются новые идеи и проекты!

Достаточно давно я ничего не писал в свой блог. Вместо бессмысленных оправданий - лучше сразу перейти к делу.

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


ADXL335

Итак, давайте для начала немного разберемся в том, что же такое ADXL335 . ADXL335 - это аналоговый трехосный акселерометр.
Акселерометр - приспособление для измерения ускорения. Один важный момент, до которого я сам не сразу дошел, важно понимать, что ускорение может быть двух видов: динамическое и статическое.
С динамическим ускорением все должно быть более-менее понятно. Лично я, пока не начал разбираться с акселерометром, только про о нем и знал. Толкнули датчик, предали ему ускорение, он должен это зафиксировать.
Статическое ускорение - это воздействие силы тяжести на наш датчик. Дело в том, что к датчику даже в состоянии полного покоя приложено статическое ускорение равное g .
UPD: Совершенно правильно было замечено в комментариях. Термины динамическое и статическое ускорение перекачевали из англоязычной системы образования и спецификиций на приборы (static & dynamic acceleration). На самом деле, более правильно говорить о силах приложеных к датчику. Я не стал переписывать поста, так как возможно на данном этапе будет проще проводить аналогию со спецификацией, однако следует учитывать, что это лишь подущения и "вольности" перевода.
Напомню, из школьного курса физики: g - это ускорение свободного падения. И это именно то самое g которое не раз упоминается в спецификации нашего устройства.
Так вот, датчик ADXL335 умеет улавливать оба этих ускорения. Самое интересно для меня, как оказалось, именно возможность измерения статического ускорения, так как зная проекции его вектора можно спокойно вычислить угол на который отклонился наш датчик относительно некого нулевого значения.
Лучше всего воздействие статического ускорения на показания датчика показаны в спецификации самого датчика.

Фактически в этой картинке кроется основная тайна этого статического ускорения. Я, однако, игнорировал её очень долго. На ней показано, какими показаниями буду, если датчик ворочать разными способами. Главное - не обращайте особенного внимания на надпись TOP , она несколько вводит в заблуждение. Относительное положение датчика необходимо отслеживать по маленькому беленькому кружечку-метке.
Итак, для начала разберемся с правой частью картинки, на которой меняет свое значение Zout. Согласно этой картинке, если мы положим наш датчик контактами вниз, то значение по оси Z будет равно единице (точнее одному g). Как я уже говорил - это значение ни что иное как проекция вектора статического ускорения на ось нашего датчика. Так как в данном случае вектор совпадает с осью Z, а ускорения свободного падения равняется g , мы и имеет значение Zout = 1g.
Если же мы перевернем датчик контактами вверх, то значение Zout изменится на противоположное.
Стоит отметить, что все остальные ускорения равны нулю, связано это с уже упомянутым совпадением вектора статического ускорения с осью Z, а так же состоянием покоя всего датчика.
Аналогично можно разобрать все остальные пары. Единственное отличие - то, что датчик будет находится на ребре или боку.
Важно так же понимать, что длинна этого вектора в состоянии покоя датчика всегда будет равняться единице. Вектор далеко не всегда будет совпадать с какой-либо из осей - скорее такой вариант, это исключение из правил. Чаще всего этот вектор будет размазан по всем трем осям одновременно. Все же в трехмерном пространстве живем.
ВАЖНО! В отличии от всех рассмотренных ранее, наш сегодняшний испытуемый питается от 3-х вольт. Максимально допустимым значение напряжения для ADXL335 является 3,6 вольта, так что для опыта я буду использовать выход +3,3В на самой плате Arduino, и т.к. это несколько выше рекомендуемого напряжения, нам придется немного подкорректировать некоторые параметры в расчетах.
ADXL335 - трехосный датчик. Фактически, это три разных акселерометра в одном корпусе, каждый из которых отвечает за свою собственную ось X, Y либо же Z.


Помимо обозначенного статического ускорения наш датчик запросто будет справляться и с обычными ускорениями, до 3g . Это можно использовать например, чтобы определить находится ли вся конструкция в движении, и даже в каком направлении она двигается. Например, ускорение в -3g по оси Z скорее всего скажет нам, что мы только что неплохо шандарахнулись об пол, упав откуда-то. Можно измерять ускорение при начале движения и тем самым делать его более плавным, без резких рывков.
Достаточно часто в интернете в ходе поисков нарывался на обсуждения акселерометра в качестве датчика для системы автопилота. Это не лучшая идея, скажу вам сразу. Во всяком случае, могу совершенно точно сказать, используя только акселерометр в качестве датчика сделать это не получится. Дело в том, что угол наклона в пространстве мы можем нормально вычислить только в состоянии покоя всего устройства. А какой может быть покой у авиамодели? Однако, акселерометр будет отличным дополнением к электрокомпасу в купе с гироскопом.

Подключаемся

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

Единственное, на что стоит обратить внимание еще раз - мы используем для питания выход 3v3 Arduino, а не 5v , как это было во всех остальных случаях. Выходы X , Y , Z нашего датчика соединены с входами ANALOG IN 0 , 1 , 2 нашей Arduino.
В этом проекте я использовал Arduino UNO, так как все остальные были заняты.
Вот так все выглядит у меня.


Пишем код
Перейдем собственно к самой интересной части, в которой мы объединим всю теорию и железо описанное выше в одно целое. Помимо этого, это будет первый пост, где мы напишем целых две прошивки. Первая из них призвана помочь нам в калибровке сенсора. Как показала практика - это будет не лишним. Итак, приступим:
#define ADC_ref 5.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
Обозначаем пару констант. ADC_ref - это максимальное значение в вольтах которое может снять аналоговый вход. analog_resolution - это разрешающая способность нашего аналогового входа. На arduino она равна 2 10 или 1024.
После объявления констант идет пара переменных в которых мы будем хранить показания снятые с нашего датчика и инициализация серийного порта, чтобы можно было получить какие-то данные на компьютере.
В функции loop мы в начале получаем данные с трех наших аналоговых пинов, к которым и подключен наш датчик, а после этого пересчитываем полученное число в вольты и выводим их на серийный порт.
Зальем эту прошивку в нашу Arduino UNO, откроем серийный монитор (ctrl+shift+m) и соберем кое какие данные. Нам понадобятся данные шести положений, как на уже упомянутом рисунке.

В фотографиях это выглядит как-то так.


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

Где первый столбец - показания по оси X, второй - Y, третий - Z. Полученные в результате замеров данные я свел в одну таблицу:

zero

avr. deviation

1.60156

1.92871

1.26465

0.33203

1.60156

1.92871

1.26465

0.33203

1.64551

1.94336

1.31836

0.3125


В столбец zero занесены значения out от нуля, во-втором столбце с заголовком g занесены значения, когда ускорение свободного падения (оно же статическое) - совпадает с вектором, так же как и в столбце -g .
Напишем вторую прошивку, которая будет собираться показания с нашего датчика и преобразовывать их в проекции ускорений по трем осям, а потом еще и высчитаем относительный угол отклонения нашего датчика в пространстве, используя данные о статическом ускорении, о котором я долго распинался в начале поста. Большое спасибо за основу для кода посту на http://www.electronicsblog.net .
#define ADC_ref 5.0 #define analog_resolution 1024.0 #define zero_x 1.60156 #define zero_y 1.60156 #define zero_z 1.64551 #define sensitivity_x 0.33 #define sensitivity_y 0.33 #define sensitivity_z 0.31 unsigned int value_x; unsigned int value_y; unsigned int value_z; float xv; float yv; float zv; float angle_x; float angle_y; float angle_z; void setup() { Serial.begin(9600 ); } void loop() { value_x = analogRead(0 ); value_y = analogRead(1 ); value_z = analogRead(2 ); xv = (value_x/analog_resolution*ADC_ref-zero_x)/sensitivity_x; yv = (value_y/analog_resolution*ADC_ref-zero_y)/sensitivity_y; zv = (value_z/analog_resolution*ADC_ref-zero_z)/sensitivity_z; Serial.print("x = " ); Serial.print(xv); Serial.print("g y = " ); Serial.print(yv); Serial.print("g z = " ); Serial.print(zv); Serial.println("g" ); angle_x =atan2(-yv,-zv)*RAD_TO_DEG; angle_y =atan2(-xv,-zv)*RAD_TO_DEG; angle_z =atan2(-yv,-xv)*RAD_TO_DEG; Serial.print(angle_x); Serial.print(" deg " ); Serial.print(angle_y); Serial.print(" deg " ); Serial.print(angle_z); Serial.println(" deg" ); delay(1500 ); } Рассмотрим основные части записанного кода. Части которые отвечают за вывод на серийный порт я буду буду пропускать, так как это мы делали уже множество раз.

#define zero_x 1.60156 #define zero_y 1.60156 #define zero_z 1.64551
Значение нуля из нашей таблицы для каждой оси. Получены нами в результате проделанной ранее калибровки. Вообще, в идеале, при питании микросхемы ADXL335 ровными 3в, это значение должно быть равно 1.5, но из-за увеличившегося напряжения питания значение несколько увеличилось. Если не проводить калибровку, то это значение можно принять как напряжение питания деленное на 2. Интересным фактом является то, что значение сильнее увеличилось именно по оси Z. Согласно спецификации - это нормально.

#define sensitivity_x 0.33 #define sensitivity_y 0.33 #define sensitivity_z 0.31 Чувствительность нашего сенсора. Если пренебречь калибровкой, то можно принимать это значение как 1/10 напряжения питания микросхемы ADXL335 . А вот теперь перейдем к магии.

Xv = (value_x/analog_resolution*ADC_ref-zero_x)/sensitivity_x; yv = (value_y/analog_resolution*ADC_ref-zero_y)/sensitivity_y; zv = (value_z/analog_resolution*ADC_ref-zero_z)/sensitivity_z;
Такой не слишком хитрой формулой мы вычисляем проекцию вектора ускорения на оси координат, причем единицей деления на осях будет значение ускорения свободного падения g (благодаря делению на значение sensitivity_* ). Теперь зная эти проекции мы можем вычислить угол отклонения датчика в каждой полскости. Для этого возьмем арктангенс от проекции вектора на определенную плоскость.

Angle_x =atan2(-yv,-zv)*RAD_TO_DEG; angle_y =atan2(-xv,-zv)*RAD_TO_DEG; angle_z =atan2(-yv,-xv)*RAD_TO_DEG;
Значение RAD_TO_DEG является константой при умножении на которую значение угла в радианах преобразуется в более привычные нам углы в градусах. Вот кажется и все, остается только глянуть видео демонстрацию того, что у нас получилось.

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

Понравилось? Лайкни нас на Facebook