Рейтинг@Mail.ru

Как подключить цифровой акселерометр ADXL345 к Arduino

2 комментарии Arduino
Print Friendly, PDF & Email
Подключаем к Arduino модуль цифрового акселерометра на базе микросхемы ADXL345 с управлением по последовательным интерфейсам I2C и SPI.

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

  • Arduino UNO или иная совместимая плата;
  • модуль GY-291 или аналогичный с цифровым акселерометром ADXL345;
  • соединительные провода (рекомендую вот такой набор);
  • макетная плата (breadboard);
  • персональный компьютер со средой разработки Arduino IDE.

1Описание модуля GY-291 с акселерометром ADXL345

Акселерометр – это устройство, которое позволяет измерить динамическое и статическое ускорение по трём осям X, Y и Z. Благодаря статическому ускорению можно определить положение в пространстве (акселерометр как датчик поворота), а благодаря динамическому (движение или встряска) – направление ускорения.

Цифровой акселерометр ADXL345 – это 3-осевой акселерометр с высоким разрешением (13 бит) по осям с пределом до ±16g. Модуль обладает пониженным энергопотреблением и малыми размерами. Информационный обмен с модулем осуществляется по последовательным интерфейсам I2C или SPI (3- или 4-проводной).

Существует множество модулей для Arduino с акселерометром ADXL345. Модуль может выглядеть, например, так:

Внешний вид модуля GY-291 с цифровым акселерометром ADXL345
Внешний вид модуля GY-291 с цифровым акселерометром ADXL345

Показанный модуль имеет название GY-291. У модуля имеются следующие выводы:

Вывод модуляНазначениеПодключать к выводу Arduino
SPII2C
GNDЗемляGNDGND
VCCПитание+3,3V+3,3V
CSВыбор ведомого интерфейса SPI10
INT1Выход прерывания 1 (*)
INT2Выход прерывания 2 (*)
SDOДанные от ведомого12
SDAДанные от мастера интерфейса SPI
Шина данных интерфейса I2C
11A4
SCLШина тактирования13A5

(*) Работы с прерываниями ADXL345 касаться в этой статье не будем. Вот есть хорошая статья, в которой достаточно подробно описан вопрос работы с прерываниями.

В зависимости от выбранного интерфейса – SPI или I2C – подключение модуля будет соответствующим, как показано в таблице. Но в обоих случаях очень простым.

Рассмотрим структуру регистров микросхемы ADXL345:

Карта регистров цифрового акселерометра ADXL345
Карта регистров цифрового акселерометра ADXL345

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

Регистр управления питанием цифрового акселерометра ADXL345
Регистр управления питанием цифрового акселерометра ADXL345

Как видим, бит D3 (Measure) переключает акселерометр в режим измерения.

2Работа с цифровым акселерометром ADXL345 по интерфейсу SPI

Акселерометр ADXL345 поддерживает 3- и 4-проводные варианты интерфейса SPI. Мы рассмотрим только 4-проводное подключение. Кроме того, акселерометр работает в режиме 3 интерфейса SPI (помните, мы уже обсуждали: CPOL=1, CPHA=1). Диаграмма, показывающая обмен с акселерометром ADXL345 по 4-проводному интерфейсу SPI:

Работа с ADXL345 по SPI
Работа с ADXL345 по SPI

Здесь бит MB – это признак того, что мы собираемся читать много байтов за раз (если бит установлен в 1). Для тестирования работы с SPI устройствами и быстрого освоения порядка обмена с ними я обычно использую отладочную плату с микросхемой FT2232H. Эта микросхема поддерживает множество режимов, в том числе I2C и SPI. Управление работой микросхемы FT2232H – с помощью программы SPI via FTDI, о которой я уже неоднократно рассказывал.

Подключим акселерометр к отладочной плате и прочитаем регистр DEVID, в котором хранится постоянное значение-идентификатор акселерометра ADXL345. Значение идентификатора должно быть 0xE5.

ADXL345 соединён с отладочной платой на FT2232H
ADXL345 соединён с отладочной платой на FT2232H

Не забудем перед чтением записать команду 0x80, которая укажет акселерометру, что мы собираемся читать, начиная с регистра по адресу 0x0 (см. диаграмму выше, рисунок 38 – SPI 4-Wire Read):

Чтение регистра ID акселерометра ADXL345 по SPI
Чтение регистра ID акселерометра ADXL345 по SPI

Видно, что в регистре содержится число 0xE5, которое и является значением идентификатора акселерометра ADXL345, согласно техническому описанию (datasheet). Вот как это выглядит на временной диаграмме:

Временная диаграмма чтения регистра ID акселерометра ADXL345 по SPI
Временная диаграмма чтения регистра ID акселерометра ADXL345 по SPI

Устройство отвечает, всё нормально. Теперь нам нужно перевести акселерометр в режим измерений. Для этого необходимо записать в регистр POWER_CTL (адрес регистра 0x2D) число 0x08 (установить бит Measure в HIGH). После этого можно начинать читать регистры с 0x32 по 0x37, в которых хранятся данные об ускорениях по трём осям. Сделаем это с помощью Arduino. Напишем такой скетч:

Скетч для чтения данных ADXL345 по SPI (разворачивается)
#include <SPI.h>

const byte READ = 0x80; // бит маркер чтения
const byte MB = 0x40; // бит MB (многобайтовая передача)
const int CS = 10; // пин выбора ведомого

void setup() {
  Serial.begin(115200);
  SPI.begin(); 
  SPI.setClockDivider(SPI_CLOCK_DIV32); // делитель частоты 500 кГц
  SPI.setDataMode(SPI_MODE3); // задаём 3-ий режим SPI
    
  byte id[1];
  readRegister(0x00, 1, id); // читаем регистр DEVID
  Serial.print("ID = ");
  Serial.println(id[0], HEX);
  
  writeRegister(0x2D, 0x08); // переводим ADXL345 в режим измерения
}

void loop() {
  byte buff[6];
  readRegister(0x32, 6, buff); // читаем значения по осям X, Y, Z
  
  int x = ((int)buff[1] << 8) | buff[0];
  int y = ((int)buff[3] << 8) | buff[2];
  int z = ((int)buff[5] << 8) | buff[4];

  Serial.print(x);
  Serial.print("\t");
  Serial.print(y);
  Serial.print("\t");
  Serial.println(z);

  delay(10);
}

// записывает значение в регистр
void writeRegister(byte reg, byte value) {
  digitalWrite(CS, LOW);
  SPI.transfer(reg); 
  SPI.transfer(value); 
  digitalWrite(CS, HIGH);
}

// читает из регистра заданное число байтов
void readRegister(byte reg, int bytesToRead, byte *outBuff) {
  digitalWrite(CS, LOW);
  reg = reg | READ; // покажем акселерометру, что хотим из него читать
  if (bytesToRead > 1) {
     reg = reg | MB; // и читать хотим много байтов
  }
  SPI.transfer(reg); // записываем адрес регистра, с которого начинаем чтение
  for (int i=0; i< bytesToRead; i++) {
    outBuff[i] = SPI.transfer(0x00); // побайтно читаем ответ ADXL345
  }
  digitalWrite(CS, HIGH);
}

Вот так выглядит временная диаграмма работы этого скетча:

Временная диаграмма чтения значений по осям X, Y, Z акселерометра ADXL345
Временная диаграмма чтения значений по осям X, Y, Z акселерометра ADXL345

Ясно, почему первый байт передачи от Arduino при чтении значений ускорений по осям – число 0xF2? Это адрес первого регистра, с которого начинаем чтение (0x32), объединённый по ИЛИ с 0x80 – маркером чтения READ – и с 0x40 – маркером многобайтовой передачи MB: 0x32 OR 0x80 OR 0x40 = 0011_0010 OR 1000_0000 OR 0100_0000 = 1110_1101 = 0xF2

Что означают считанные значения? Этот вопрос рассматривается в последнем разделе статьи. Кроме того, существует ряд библиотек для Arduino, которые упрощают настройку и чтение данных с акселерометра, позволяя не думать о таких низкоуровневых вещах как регистры, биты и байты. Ссылки на библиотеки также приведены в конце статьи.

3Работа с цифровым акселерометром ADXL345 по интерфейсу I2C

Временная диаграмма информационного обмена с ADXL345 по интерфейсу I2C выглядит так:

Диаграмма обмена с ADXL345 по I2C
Диаграмма обмена с ADXL345 по I2C

Давайте перепишем скетч для Arduino, который будет делать всё то же самое, только с обменом по интерфейсу I2C:

Скетч для чтения данных ADXL345 по I2C (разворачивается)
#include <Wire.h>

const int adxl345 = 0x53; // I2C адрес ADXL345

void setup() {
  Serial.begin(9600);
  Wire.begin();

  // запишем адрес регистра DEVID
  Wire.beginTransmission(adxl345);
  Wire.write(byte(0x00));
  Wire.endTransmission();

  // прочитаем регистр DEVID:
  Wire.requestFrom(adxl345, 1);
  while (Wire.available()) {
    byte c = Wire.read();
    Serial.print("ID = ");
    Serial.println(c, HEX);
  }

  // переведём акселерометр в режим измерений
  Wire.beginTransmission(adxl345);
  Wire.write(byte(0x2D));
  Wire.write(byte(0x08));
  Wire.endTransmission();
}

void loop() {
  // запишем адрес начала данных по осям X, Y и Z:
  Wire.beginTransmission(adxl345);
  Wire.write(byte(0x32));
  Wire.endTransmission();

  // прочитаем 6 байтов значений XYZ:
  int i = 0;
  byte xyz[6];
  Wire.requestFrom(adxl345, 6);
  while (Wire.available()) {
    byte c = Wire.read();
    xyz[i] = c;
    i++;
  }

  // посчитаем и отобразим значения X, Y, Z:
  int x = word(xyz[1], xyz[0]);
  int y = word(xyz[3], xyz[2]);
  int z = word(xyz[5], xyz[4]);
  
  Serial.print(x);
  Serial.print("\t");
  Serial.print(y);
  Serial.print("\t");
  Serial.println(z);

  delay(100);
}

Диаграмма чтения регистра DEVID цифрового акселерометра ADXL345 при обмене по последовательному интерфейсу I2C будет в этом случае такой:

Диаграмма чтения регистра DEVID акселерометра ADXL345 по I2C
Диаграмма чтения регистра DEVID акселерометра ADXL345 по I2C

Как видно, ADXL345 возвращает нам ожидаемое значение 0xE5. А вот так будет выглядеть диаграмма чтения регистров, в которых хранятся данные по осям XYZ:

Диаграмма чтения регистров данных X, Y, Z акселерометра ADXL345 по I2C
Диаграмма чтения регистров данных X, Y, Z акселерометра ADXL345 по I2C

Тут всё ещё проще, чем при работе с интерфейсом SPI.

4Разбор показаний цифрового акселерометра ADXL345

Посмотрите на фотографию ниже. На плате модуля нарисованы три оси: X, Y и Z. Они показывают направление осей акселерометра. Направления осей обусловлены расположением микросхемы ADXL345 на плате. В данном случае ось X акселерометра направлена горизонтально вправо, ось Z направлена горизонтально на нас, ось Y – вертикально вверх.

Акселерометр ADXL345 на макетной плате
Акселерометр ADXL345 на макетной плате

А вот что выводит наш скетч в монитор последовательного порта среды Arduino IDE (надо уточнить, что данный вывод наблюдается в режиме покоя – акселерометр неподвижно лежит на столе в положении, как на приведённом фото):

Данные ускорений по X, Y, Z акселерометра ADXL345 в мониторе последовательного порта Arduino IDE
Данные ускорений по X, Y, Z акселерометра ADXL345 в мониторе последовательного порта Arduino IDE

В трёх столбцах представлено значение статического ускорения, измеренное акселерометром по осям X, Y и Z, соответственно. В среднем столбце – показания оси Y – значения больше, чем в двух других. Эти значения даны в условных отсчётах, как они записаны в регистрах акселерометра. Акселерометр ADXL345 имеет несколько диапазонов измерений. Давайте посмотрим на сводную таблицу диапазонов и разрешений датчика акселерометра:

Параметры датчика ADXL345
Параметры датчика ADXL345

Напомню, что g – это ускорение свободного падения, численно равное примерно 9,81 метр в секунду за секунду (м/с2).

Диапазон по умолчанию – от −16g до +16g (размах 32g). Согласно таблице, на этот диапазон ускорений приходится 13 бит точности или 213 = 8192 отсчёта. Таким образом, на 1 отсчёт приходится ускорение 32g/8192 = 0,00390625g=0,00390625×9,81 ≈ 0,038 м/с2. Имея это в виду, получается, что в данном выводе скетча ускорение составляет:

Ось акселерометраУскорение по оси, м/с2
X0,76
Y10,4
Z−0,12

Что ж, вполне логично. Ось Y направлена вертикально, т.е. вдоль вектора силы земного притяжения, и значение ускорения примерно равно константе g. Ускорения по осям X и Z, которые лежат в одной горизонтальной плоскости, примерно одинаковы и находятся около 0. Из-за кривизны стола, на котором стоит датчик, значения немного отличаются. Если бы я выровнял акселерометр по уровню, то его показания были бы более точные. В идеальном случае по оси Y должно быть ускорение 9,8 м/с2, а по осям X и Z – 0.

Кроме того, датчик ADXL345 имеет возможность тонкой настройки и калибровки. В данном примере мы этого не делали, а использовали акселерометр с заводскими настройками, как есть. Отсутствие калибровки также может вносить некоторые искажения в показания датчика. Рекомендую применять специальные библиотеки Arduino, которые упрощают взаимодействие с акселерометром ADXL345, в частности, позволяют проводить тонкую настройку.

Скачать библиотеку ADXL345

В архиве также лежит техническое описание (datasheet) на цифровой акселерометр ADXL345. Установка библиотеки производится путём копирования разархивированной папки с библиотекой в директорию libraries среды Arduino IDE.

Скачать вложения:

Последнее изменениеВторник, 09 Январь 2024 20:23 Прочитано 25056 раз

Поблагодарить автора:

Поделиться

Print Friendly, PDF & Email

2 комментарии

  • Dima
    Dima 29.04.2020 13:50 Комментировать

    Доброго день, интересует, как вы подключили несколько датчиков и к контроллеру?

  • aave1
    aave1 29.04.2020 18:27 Комментировать

    Dima, здравствуйте!
    Как SPI, так и I2C интерфейсы поддерживают режим "один ведущий - много ведомых". Вероятно, Вы имеете в виду это? К одному SPI master можно подключить несколько подчинённых устройств, активируется каждое из них по шине CS. Аналогично и I2C, с той лишь разницей, что у каждого ведомого есть свой адрес, и мы обращаемся к каждому устройству на шине по его уникальному адресу.

Оставить комментарий