如何跟踪Arduino和ADXL345加速度计的方向

在本教程中,我们将学习如何使用Arduino和ADXL345加速度传感器测量角度和轨迹方向。你可以观看下面的视频或阅读下面的书面教程了解更多细节。

概述

首先,我将解释传感器如何工作以及如何从中读取数据,然后使用处理开发环境,我们将进行加速度计方向的3D可视化。

Arduino和ADXL345加速度计教程

ADXL345加速度计如何工作

首先,让我们来看看ADXL345传感器的工作原理。这是一个3轴加速度计,可以测量加速度的静态和动态力。地球重力是静态力的典型例子,而动态力可以由振动,运动等引起。

ADXL345加速计如何工作betway

加速度单位为每秒平方(M / S ^ 2)。然而,加速度计传感器通常表达“G”或重力的测量。一个“g”是地球重力的值,其等于每秒平方9.8米。

因此,如果我们有一个加速度计定位平板,其z轴向上指向,与重力相反,传感器的z轴输出将是1g。另一方面,x和y输出为零,因为重力力垂直于这些轴并且根本不会影响它们。

ADXL345 3轴加速器输出数据

如果我们把传感器倒过来,那么z轴输出将是- 1g。这意味着由于其重力方向,传感器的输出可以在-1g到+1g之间变化。

Adxl345 z轴输出

因此,根据这些数据和使用一些三角数学,我们可以计算出传感器所在的角度。

如何用Arduino读取ADXL345加速度计数据

好的,现在让我们看看如何使用Arduino读取ADXL345加速度计数据。这个传感器使用I2C协议与Arduino通信,所以我们只需要两根线来连接它,再加上两根线来给它供电。

Arduino和ADXL345加速度计电路图

你可以从下面的链接获得这个Arduino教程所需的组件:

必威外围提钱披露:这些是联盟链接。作为亚马逊助理,我从合格购买中获得。

ADXL345加速度计Arduino代码

这是读取ADXL345加速度计数据的Arduino代码。

/ * Arduino和Adxl345加速度计由Dejan,//www.mfxpo.com * / bet188官方网站#include  //ire library  - 用于i2c Communication INT ADXL345 = 0x53;// ADXL345传感器I2C地址float x_out,y_out,z_out;//输出void setup(){serial.begin(9600);//启动串行通信以在串行监视器线上打印结果.Begin();//在测量模式Wire.BegIntroAnsmission(ADXL345)中启动电线库//设置ADXL345;//开始与设备线路通信.WRITE(0x2D);//访问/与power_ctl寄存器 -  0x2d //启用测量线.write(8);//(8dec  - > 0000 1000二进制)位D3高度测量使能导线.endtransmission();延迟(10);void循环(){// ===读取加速器数据=== // wire.begintroansmission(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); }

描述:因此,首先,我们需要包括用于I2C通信的Wire.h库。如果您想了解如何使用I2C通信的工作以及如何使用Arduino使用它,您可以查看我的其他详细教程

使用I2C通信的每个设备都具有唯一的I2C地址,并且可以在传感器的数据表中找到此地址(ADXL345数据表)。因此,一旦我们在设置部分中定义了三个输出的地址和变量,首先,我们需要初始化线路库,然后在测量模式下设置加速度计。为了做到这一点,如果我们再次查看数据表,我们可以看到我们需要设置POWER_CTL寄存器高的位D3。

ADXL345电源寄存器 - 启用测量模式

因此,使用BegintRansmission()函数我们开始通信,然后使用Write()函数我们告诉我们要访问的寄存器,并再次使用Write()函数我们将D3位高,通过写入第8号十进制对应于设置位D3高电平。

//在测量模式线上设置ADXL345.BegintRansmission(ADXL345);//开始与设备线路通信.WRITE(0x2D);//访问/与power_ctl寄存器 -  0x2d //启用测量线.write(8);//(8dec  - > 0000 1000二进制)位D3高度测量使能导线.endtransmission();

在循环部分时,我们现在从传感器读取数据。每个轴的数据存储在两个字节或寄存器中。我们可以从数据表中看到这些寄存器的地址。

Adxl345加速计x y z数据寄存器

为了读取所有寄存器,我们从第一个寄存器开始,使用requestionFrom()函数要求读取6个寄存器。然后使用read()函数,从每个寄存器读取数据,由于输出是两个补数,我们将它们适当地组合以获得正确的值。

// ===读取Acceleromter Data === // Wire.BegintRansmission(ADXL345);Wire.write(0x32);//从寄存器0x32(Accel_XOUT_H)Wire.endTransmission(false)开始;Wire.RequestFrom(ADXL345,6,True);//读取6个寄存器总,每个轴值存储在2寄存器x_out =(wire.read()| wire.read()<< 8);// x轴值x_out = x_out / 256;//范围为+ -2g,我们需要将原始值除以256,根据数据表y_out =(wire.read()| wire.read()<< 8);// y轴值y_out = y_out / 256;z_out =(wire.read()| wire.read()<< 8);// z轴值z_out = z_out / 256;

传感器的输出值实际上取决于所选择的灵敏度,它可以在+- 2g到+-16g之间变化。默认的灵敏度是+-2g,这就是为什么我们需要将输出除以256才能得到-1到+1g的值。256lsb /g意味着每g有256个计数。

ADXL345灵敏度范围

根据应用程序,我们可以选择适当的灵敏度。在这种情况下,对于跟踪方向,+ -2g灵敏度很好,但是对于我们需要感知从突然移动,冲击等更高的加速力的应用程序,我们可以使用DATA_FORMAT寄存器选择一些其他灵敏度范围它的d1和d0位。

ADXL345敏感度范围寄存器和真理表

ADXL345加速器校准

然而,一旦我们读取数据,我们可以简单地将其打印在串行监视器上,以检查值是否如预期的那样。在我的例子中,我得到的值并不完全是它们应该得到的,特别是z轴有一个明显的0.1g的误差。

adxl345加速度计校准

要解决此问题,我们需要使用3个偏移校准寄存器校准加速度计,这是我们如何做到的。因此,我们需要将传感器平整定位,并在不将它们划分256的情况下打印原始值。

Adxl345加速度计校准过程

从现在开始,我们可以注意到输出关闭,在我的情况下,z输出大约为283.这与正面的27个差异。现在我们需要将此值划分为4,这将提供我们需要写入z轴偏移寄存器的数字。如果我们现在上传代码,Z轴输出将是256,或者1g。

//这段代码进入SETUP部分//偏移量校准// x轴线开始传输(ADXL345);Wire.write (0 x1e);// x轴偏移寄存器Wire.write(1);Wire.endTransmission ();延迟(10);/ /轴Wire.beginTransmission (ADXL345);Wire.write (0 x1f);// y轴偏移寄存器Wire.write(-2);Wire.endTransmission ();延迟(10); //Z-axis Wire.beginTransmission(ADXL345); Wire.write(0x20); // Z-axis offset register Wire.write(-7); Wire.endTransmission(); delay(10);

如果需要,我们应该使用相同的方法校准另一个轴。并且只需快点注意,此校准不会永久写入寄存器。我们需要将这些值写入传感器的每个电源的寄存器。

一旦我们完成了校准,我们现在可以使用这两个公式最终计算Roll和Pitch,或者绕x轴旋转和绕Y轴旋转的角度。

//计算滚转和俯仰(绕x轴旋转,绕y轴旋转)滚转= atan(Y_out / sqrt(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;

有关更多详细信息,这些公式如何工作,您可以查看此功能飞思卡尔半导体应用笔记

Arduino和ADXL345加速度计取向跟踪 - 3D可视化

好的,让我们立即制作加速度计3D可视化示例。

Arduino和ADXL345加速度计方向跟踪- 3D可视化

因此,我们使用相同的代码,通过串行端口发送卷和俯仰值。这是完整的Arduino代码:

/ * Arduino和ADXL345加速度计 -  Dejan,//www.mfxpo.com * / #include  //ire wircult  - 用于i2c通信int adxl345 = 0x53;// ADXL345传感器I2C地址float x_out,y_out,z_out;//输出浮动辊,间距,rollf,pitchf = 0;void setup(){serial.begin(9600);//启动串行通信以在串行监视器线上打印结果.Begin();//在测量模式Wire.BegIntroAnsmission(ADXL345)中启动电线库//设置ADXL345;//开始与设备线路通信.WRITE(0x2D);//访问/与power_ctl寄存器 -  0x2d //启用测量线.write(8);//位D3高测量使能(8dec  - > 0000 1000二进制)wire.endtransmission();延迟(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); }

现在在处理开发环境我们需要接收这些值并使用它们旋转我们将创建的3D对象。以下是完整的处理代码:

/* Arduino and ADXL345 Accelerometer - 3D Visualization Example by Dejan, https://bet188官方网站www.mfxpo.com */ import processing.serial.*;进口java.awt.event.KeyEvent;进口java.io.IOException;串行myPort;字符串数据= " ";浮动辊间距;void setup() {size (960, 640, P3D);myPort = new Serial(this, "COM8", 9600);//启动串行通信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]); } } }

描述:所以在这里,我们需要包括串行库,定义串口和波特率需要匹配我们上传的Arduino草图的波特率。然后我们读取传入的数据,并将其放入适当的滚转和俯仰变量中。在主绘制循环中,我们使用这些值来旋转3D对象,在本例中,这是一个具有特定颜色和文本的简单盒子。

如果我们运行草图,3D对象将出现,它将跟踪加速度传感器的方向。我们可以注意到,这个物体实际上有点摇晃,那是因为加速度计不仅捕捉到了重力,还捕捉到了手部运动产生的小力。为了得到更平滑的结果,我们可以使用一个简单的Low-pass滤波器。在这里,我在Arduino代码中实现了这样一个过滤器,它获得了之前状态的94%,并添加了当前状态或角度的6%。

//低通滤波器rollf = 0.94 * rollf + 0.06 *卷;pitchf = 0.94 * pitchf + 0.06 *间距;

使用这个过滤器,我们可以注意到物体现在移动得更平滑了,但也有一个副作用,那就是反应更慢。我们还可以注意到我们错过了偏航,也就是绕z轴旋转。仅使用三轴加速度计数据,我们无法计算偏航。

为了做到这一点并改善我们的定位跟踪传感器的整体性能,我们实际上需要包括一个额外的传感器,一个陀螺仪,并将其数据与加速度计融合。

Adxl345加速度计和l3g4200d陀螺仪或mpu6050 6dof模块

所以,我们可以使用ADXL345加速度计结合一些陀螺仪传感器,或者使用MPU6050 IMU集成了三轴加速度计和三轴陀螺仪在一个芯片上。你可以在下一个视频中找到关于这个传感器的更详细的教程。

我希望你喜欢这个教程,并学到一些新的东西。欢迎在评论区提出任何问题,不要忘记查看我的Arduino项目的集合bet188me

10的反应

  1. 吉姆雪利

    ADXL非常专业和信息丰富。我希望看到使用ADXL并控制ADXL输出时控制伺服和/或步进器的解释。例如如果ADXL左转,则伺服/步进将旋转右键以补偿。谢谢,保持良好的工作。

    回复
  2. Diogo Santiago Sobral.

    一篇很酷的文章。我学到了很多如何在arduino中生成关于方向的数据。我唯一不明白的是如何在3D显示中再现实时数据。需要下载其他软件或代码自行输入资源吗?

    回复
  3. 杨杰华

    一个非常有用的文章,非常易于理解,预计将使用GY-85 IMU添加Kalman滤波器来执行动作识别。如何保存Excel中的真实数据。

    回复
  4. 总长Shetti

    很有帮助。谢谢你!
    任何对校准感兴趣的人,请看下面的文档……
    AN-1077:ADXL345快速入门指南 - 模拟设备

    回复
    • 德扬

      谢谢!好检查我的NRF24L01教程,以及我的DIY RC发射器项目,你会发现更多的信息,你可以做到这一点在那里。

      回复

发表评论

您的电子邮件地址不会被公开。

推荐

2019年面向初学者和爱好者的最佳入门级示波器

为初学者和爱好者最好的示波器

推荐

2019年初学者的8个最佳Arduino Starter Kits

初学者的8个最佳Arduino Starter Kits

推荐

最佳3D打印机初学者和爱好者- 3D打印

最好的3d打印机初学者和爱好者