Промышленное производство
Промышленный Интернет вещей | Промышленные материалы | Техническое обслуживание и ремонт оборудования | Промышленное программирование |
home  MfgRobots >> Промышленное производство >  >> Manufacturing Technology >> Производственный процесс

Как отслеживать ориентацию с помощью Arduino и акселерометра ADXL345

<основной класс="главный сайт" id="главный">

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

Обзор

Сначала я объясню, как работает датчик и как считывать с него данные, а затем с помощью среды разработки Processing мы сделаем 3D-визуализацию ориентации акселерометра.

Как работает акселерометр ADXL345

Для начала давайте посмотрим, как работает датчик ADXL345. Это 3-осевой акселерометр, который может измерять как статические, так и динамические силы ускорения. Сила земного притяжения является типичным примером статической силы, тогда как динамические силы могут быть вызваны вибрациями, движениями и т. д.

Единицей измерения ускорения является метр на секунду в квадрате (м/с^2). Однако датчики акселерометра обычно выражают измерения в «g» или силе тяжести. Один «g» — это значение силы земного притяжения, равное 9,8 метрам в секунду в квадрате.

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

Если мы перевернем датчик вверх дном, то выход по оси Z будет равен -1 g. Это означает, что выходные данные датчика из-за его ориентации на гравитацию могут варьироваться от -1g до +1g.

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

Как читать данные акселерометра ADXL345 с помощью Arduino

Хорошо, теперь давайте посмотрим, как мы можем прочитать данные акселерометра ADXL345 с помощью Arduino. Этот датчик использует протокол I2C для связи с Arduino, поэтому нам нужно всего два провода для его подключения, а также два провода для его питания.

Компоненты, необходимые для этого руководства по Arduino, можно получить по ссылкам ниже:

Код акселерометра ADXL345 для Arduino

Вот код Arduino для чтения данных акселерометра ADXL345.

/*
    Arduino and ADXL345 Accelerometer Tutorial
     by Dejan, https://howtomechatronics.com
*/

#include <Wire.h>  // Wire library - used for I2C communication

int ADXL345 = 0x53; // The ADXL345 sensor I2C address

float X_out, Y_out, Z_out;  // Outputs

void setup() {
  Serial.begin(9600); // Initiate serial communication for printing the results on the Serial monitor
  Wire.begin(); // Initiate the Wire library
  // Set ADXL345 in measuring mode
  Wire.beginTransmission(ADXL345); // Start communicating with the device 
  Wire.write(0x2D); // Access/ talk to POWER_CTL Register - 0x2D
  // Enable measurement
  Wire.write(8); // (8dec -> 0000 1000 binary) Bit D3 High for measuring enable 
  Wire.endTransmission();
  delay(10);
}

void loop() {
  // === Read acceleromter data === //
  Wire.beginTransmission(ADXL345);
  Wire.write(0x32); // Start with register 0x32 (ACCEL_XOUT_H)
  Wire.endTransmission(false);
  Wire.requestFrom(ADXL345, 6, true); // Read 6 registers total, each axis value is stored in 2 registers
  X_out = ( Wire.read()| Wire.read() << 8); // X-axis value
  X_out = X_out/256; //For a range of +-2g, we need to divide the raw values by 256, according to the datasheet
  Y_out = ( Wire.read()| Wire.read() << 8); // Y-axis value
  Y_out = Y_out/256;
  Z_out = ( Wire.read()| Wire.read() << 8); // Z-axis value
  Z_out = Z_out/256;

  Serial.print("Xa= ");
  Serial.print(X_out);
  Serial.print("   Ya= ");
  Serial.print(Y_out);
  Serial.print("   Za= ");
  Serial.println(Z_out);
}Code language: Arduino (arduino)

Описание: Итак, сначала нам нужно включить библиотеку Wire.h, которая используется для связи I2C. Если вы хотите узнать больше о том, как работает связь I2C и как использовать ее с Arduino, вы можете посмотреть мой другой подробный учебник.

Каждое устройство, использующее связь I2C, имеет уникальный адрес I2C, и этот адрес можно найти в техническом описании датчика (техническое описание ADXL345). Итак, после того, как мы определили адрес и переменные для трех выходов, в разделе настройки нам сначала нужно инициализировать библиотеку проводов, а затем установить акселерометр в режим измерения. Для этого, если мы снова взглянем на таблицу данных, мы увидим, что нам нужно установить бит D3 регистра POWER_CTL в ВЫСОКОЕ значение.

Таким образом, с помощью функции beginTransmission() мы запускаем связь, затем с помощью функции write() мы сообщаем, к какому регистру мы хотим получить доступ, и снова с помощью функции write() мы устанавливаем бит D3 в ВЫСОКОЕ значение, записывая число 8 в десятичное число, которое соответствует установке бита D3 в ВЫСОКОЕ значение.

// Set ADXL345 in measuring mode
  Wire.beginTransmission(ADXL345); // Start communicating with the device 
  Wire.write(0x2D); // Access/ talk to POWER_CTL Register - 0x2D
  // Enable measurement
  Wire.write(8); // (8dec -> 0000 1000 binary) Bit D3 High for measuring enable 
  Wire.endTransmission();Code language: Arduino (arduino)

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

Чтобы прочитать их все, мы начинаем с первого регистра и с помощью функции requestionFrom() просим прочитать 6 регистров. Затем, используя функцию read(), мы считываем данные из каждого регистра, и, поскольку выходные данные представляют собой дополнение до двух, мы соответствующим образом комбинируем их, чтобы получить правильные значения.

// === Read acceleromter data === //
  Wire.beginTransmission(ADXL345);
  Wire.write(0x32); // Start with register 0x32 (ACCEL_XOUT_H)
  Wire.endTransmission(false);
  Wire.requestFrom(ADXL345, 6, true); // Read 6 registers total, each axis value is stored in 2 registers
  X_out = ( Wire.read()| Wire.read() << 8); // X-axis value
  X_out = X_out/256; //For a range of +-2g, we need to divide the raw values by 256, according to the datasheet
  Y_out = ( Wire.read()| Wire.read() << 8); // Y-axis value
  Y_out = Y_out/256;
  Z_out = ( Wire.read()| Wire.read() << 8); // Z-axis value
  Z_out = Z_out/256;Code language: Arduino (arduino)

Выходные значения датчика на самом деле зависят от выбранной чувствительности, которая может варьироваться от +-2g до +-16g. Чувствительность по умолчанию составляет +-2 г, поэтому нам нужно разделить вывод на 256, чтобы получить значения от -1 до +1 г. 256 LSB/g означает, что у нас есть 256 отсчетов на g.

В зависимости от приложения мы можем выбрать соответствующую чувствительность. В этом случае для отслеживания ориентации вполне достаточно чувствительности +-2g, но для приложений, где нам необходимо ощущать более высокую силу ускорения, например внезапные движения, удары и т. д., мы можем выбрать некоторые другие диапазоны чувствительности, используя регистр DATA_FORMAT и его биты D1 и D0.

Калибровка акселерометра ADXL345

Тем не менее, как только мы прочитаем данные, мы можем просто распечатать их на последовательном мониторе, чтобы проверить, соответствуют ли значения ожидаемым. В моем случае значения, которые я получал, были не совсем такими, какими должны быть, особенно по оси Z, которая имела заметную погрешность в 0,1 г.

Чтобы решить эту проблему, нам нужно откалибровать акселерометр, используя 3 регистра калибровки смещения, и вот как мы можем это сделать. Итак, нам нужно расположить датчик горизонтально и распечатать значения RAW, не разделяя их на 256.

Отсюда теперь мы можем заметить, насколько отключены выходы, в моем случае выход Z был около 283. Это разница 27 в плюсе. Теперь нам нужно разделить это значение на 4, и это даст нам число, которое нам нужно записать в регистр смещения оси Z. Если мы загрузим код сейчас, на выходе по оси Z будет ровно 256 или 1 г, как и должно быть.

// This code goes in the SETUP section
// Off-set Calibration
  //X-axis
  Wire.beginTransmission(ADXL345);
  Wire.write(0x1E);  // X-axis offset register
  Wire.write(1);
  Wire.endTransmission();
  delay(10);
  //Y-axis
  Wire.beginTransmission(ADXL345);
  Wire.write(0x1F); // Y-axis offset register
  Wire.write(-2);
  Wire.endTransmission();
  delay(10);
  
  //Z-axis
  Wire.beginTransmission(ADXL345);
  Wire.write(0x20); // Z-axis offset register
  Wire.write(-7);
  Wire.endTransmission();
  delay(10);Code language: Arduino (arduino)

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

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

// Calculate Roll and Pitch (rotation around X-axis, rotation around Y-axis)
  roll = atan(Y_out / sqrt(pow(X_out, 2) + pow(Z_out, 2))) * 180 / PI;
  pitch = atan(-1 * X_out / sqrt(pow(Y_out, 2) + pow(Z_out, 2))) * 180 / PI;Code language: Arduino (arduino)

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

Arduino и отслеживание ориентации акселерометра ADXL345 — 3D-визуализация

Хорошо, теперь давайте сделаем пример 3D-визуализации акселерометра.

Итак, мы используем тот же код, который отправляет значения Roll и Pitch через последовательный порт. Вот полный код Arduino:

/*
    Arduino and ADXL345 Accelerometer - 3D Visualization Example 
     by Dejan, https://howtomechatronics.com
*/
#include <Wire.h>  // Wire library - used for I2C communication

int ADXL345 = 0x53; // The ADXL345 sensor I2C address

float X_out, Y_out, Z_out;  // Outputs
float roll,pitch,rollF,pitchF=0;

void setup() {
  Serial.begin(9600); // Initiate serial communication for printing the results on the Serial monitor
 
  Wire.begin(); // Initiate the Wire library
  // Set ADXL345 in measuring mode
  Wire.beginTransmission(ADXL345); // Start communicating with the device
  Wire.write(0x2D); // Access/ talk to POWER_CTL Register - 0x2D
  // Enable measurement
  Wire.write(8); // Bit D3 High for measuring enable (8dec -> 0000 1000 binary)
  Wire.endTransmission();
  delay(10);

  //Off-set Calibration
  //X-axis
  Wire.beginTransmission(ADXL345);
  Wire.write(0x1E);
  Wire.write(1);
  Wire.endTransmission();
  delay(10);
  //Y-axis
  Wire.beginTransmission(ADXL345);
  Wire.write(0x1F);
  Wire.write(-2);
  Wire.endTransmission();
  delay(10);

  //Z-axis
  Wire.beginTransmission(ADXL345);
  Wire.write(0x20);
  Wire.write(-9);
  Wire.endTransmission();
  delay(10);
}

void loop() {
  // === Read acceleromter data === //
  Wire.beginTransmission(ADXL345);
  Wire.write(0x32); // Start with register 0x32 (ACCEL_XOUT_H)
  Wire.endTransmission(false);
  Wire.requestFrom(ADXL345, 6, true); // Read 6 registers total, each axis value is stored in 2 registers
  X_out = ( Wire.read() | Wire.read() << 8); // X-axis value
  X_out = X_out / 256; //For a range of +-2g, we need to divide the raw values by 256, according to the datasheet
  Y_out = ( Wire.read() | Wire.read() << 8); // Y-axis value
  Y_out = Y_out / 256;
  Z_out = ( Wire.read() | Wire.read() << 8); // Z-axis value
  Z_out = Z_out / 256;

  // Calculate Roll and Pitch (rotation around X-axis, rotation around Y-axis)
  roll = atan(Y_out / sqrt(pow(X_out, 2) + pow(Z_out, 2))) * 180 / PI;
  pitch = atan(-1 * X_out / sqrt(pow(Y_out, 2) + pow(Z_out, 2))) * 180 / PI;

  // Low-pass filter
  rollF = 0.94 * rollF + 0.06 * roll;
  pitchF = 0.94 * pitchF + 0.06 * pitch;

  Serial.print(rollF);
  Serial.print("/");
  Serial.println(pitchF);
}Code language: Arduino (arduino)

Теперь в среде разработки Processing нам нужно получить эти значения и использовать их для поворота 3D-объекта, который мы будем создавать. Вот полный код обработки:

/*
    Arduino and ADXL345 Accelerometer - 3D Visualization Example 
     by Dejan, https://howtomechatronics.com
*/

import processing.serial.*;
import java.awt.event.KeyEvent;
import java.io.IOException;

Serial myPort;

String data="";
float roll, pitch;

void setup() {
  size (960, 640, P3D);
  myPort = new Serial(this, "COM8", 9600); // starts the serial communication
  myPort.bufferUntil('\n');
}

void draw() {
  translate(width/2, height/2, 0);
  background(33);
  textSize(22);
  text("Roll: " + int(roll) + "     Pitch: " + int(pitch), -100, 265);

  // Rotate the object
  rotateX(radians(roll));
  rotateZ(radians(-pitch));
  
  // 3D 0bject
  textSize(30);  
  fill(0, 76, 153);
  box (386, 40, 200); // Draw box
  textSize(25);
  fill(255, 255, 255);
  text("www.HowToMechatronics.com", -183, 10, 101);

  //delay(10);
  //println("ypr:\t" + angleX + "\t" + angleY); // Print the values to check whether we are getting proper values
}

// Read data from the Serial Port
void serialEvent (Serial myPort) { 
  // reads the data from the Serial Port up to the character '.' and puts it into the String variable "data".
  data = myPort.readStringUntil('\n');

  // if you got any bytes other than the linefeed:
  if (data != null) {
    data = trim(data);
    // split the string at "/"
    String items[] = split(data, '/');
    if (items.length > 1) {

      //--- Roll,Pitch in degrees
      roll = float(items[0]);
      pitch = float(items[1]);
    }
  }
}Code language: Arduino (arduino)

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

Если мы запустим скетч, появится 3D-объект, и он будет отслеживать ориентацию датчика акселерометра. Здесь мы можем заметить, что объект на самом деле немного шатается, потому что акселерометр улавливает не только гравитационную силу, но и небольшие силы, создаваемые движениями нашей руки. Чтобы получить более плавный результат, мы можем использовать простой фильтр нижних частот. Вот я реализовал в коде Arduino такой фильтр, который берет 94% предыдущего состояния и добавляет 6% текущего состояния или угла.

// Low-pass filter
  rollF = 0.94 * rollF + 0.06 * roll;
  pitchF = 0.94 * pitchF + 0.06 * pitch;Code language: Arduino (arduino)

С помощью этого фильтра мы можем заметить, что объект теперь движется намного более плавно, но есть и побочный эффект — более медленная реакция. Мы также можем заметить, что нам не хватает Yaw или вращения вокруг оси Z. Используя только данные 3-осевого акселерометра, мы не можем рассчитать отклонение от курса.

Чтобы сделать это и улучшить общую производительность нашего датчика отслеживания ориентации, нам действительно нужно включить дополнительный датчик, гироскоп, и объединить его данные с акселерометром.

Таким образом, мы можем либо использовать акселерометр ADXL345 в сочетании с датчиком гироскопа, либо использовать IMU MPU6050, в котором 3-осевой акселерометр и 3-осевой гироскоп интегрированы в один чип. Вы можете найти более подробное руководство по этому датчику в моем следующем видео.

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


Производственный процесс

  1. Управление серводвигателем с помощью Arduino и MPU6050
  2. u-blox LEA-6H 02 GPS-модуль с Arduino и Python
  3. Как читать температуру и влажность на Blynk с DHT11
  4. Распознавание и синтез речи с помощью Arduino
  5. Как создавать музыку с помощью Arduino
  6. Как использовать NMEA-0183 с Arduino
  7. Как использовать Modbus с Arduino
  8. Умная кофемашина с Arduino и Bluetooth
  9. Анимированный умный свет с Alexa и Arduino
  10. Распознавание речи с помощью Arduino и BitVoicer Server