亿迅智能制造网
工业4.0先进制造技术信息网站!
首页 | 制造技术 | 制造设备 | 工业物联网 | 工业材料 | 设备保养维修 | 工业编程 |
home  MfgRobots >> 亿迅智能制造网 >  >> Manufacturing Technology >> 制造工艺

ADXL345 三轴加速度计 Arduino 姿态追踪教程

本教程讲解如何使用 ADXL345 加速度计 与 Arduino 测量倾角、追踪姿态,并用 Processing 实现 3D 可视化。

概览

先讲原理与读数,再做 Processing 3D 可视化演示。

ADXL345 三轴加速度计 Arduino 姿态追踪教程

ADXL345 工作原理

三轴加速度计,可测静态(重力)与动态(振动/运动)加速度。单位 m/s²,常用 g(1g = 9.8 m/s²)。

ADXL345 三轴加速度计 Arduino 姿态追踪教程

水平放置、Z 轴向上时:Z 输出 1g,X/Y 为 0。翻转则 Z 为 -1g。输出范围 -1g 到 +1g,据此用三角函数可解算倾角。

ADXL345 三轴加速度计 Arduino 姿态追踪教程
ADXL345 三轴加速度计 Arduino 姿态追踪教程

Arduino 读取 ADXL345 数据

I2C 通信,2 根信号线 + 电源。

ADXL345 三轴加速度计 Arduino 姿态追踪教程

所需元件

  • ADXL345 加速度计模块
  • Arduino 开发板
  • 面包板与跳线

基础读取代码

/* Arduino + ADXL345 加速度计教程 by Dejan, https://howtomechatronics.com */
#include 
int ADXL345 = 0x53; // I2C 地址
float X_out, Y_out, Z_out;

void setup() {
  Serial.begin(9600);
  Wire.begin();
  // 设置测量模式:POWER_CTL(0x2D) D3 置 1
  Wire.beginTransmission(ADXL345);
  Wire.write(0x2D);
  Wire.write(8); // 0b00001000
  Wire.endTransmission();
  delay(10);
}

void loop() {
  Wire.beginTransmission(ADXL345);
  Wire.write(0x32); // ACCEL_XOUT_H
  Wire.endTransmission(false);
  Wire.requestFrom(ADXL345, 6, true);
  X_out = (Wire.read() | Wire.read() << 8) / 256.0; // ±2g: 256 LSB/g
  Y_out = (Wire.read() | Wire.read() << 8) / 256.0;
  Z_out = (Wire.read() | Wire.read() << 8) / 256.0;
  Serial.print("Xa= "); Serial.print(X_out);
  Serial.print(" Ya= "); Serial.print(Y_out);
  Serial.print(" Za= "); Serial.println(Z_out);
}

代码要点

  • Wire 库做 I2C,地址 0x53(见数据手册)
  • 写 POWER_CTL 寄存器 0x2D 的 D3 位启用测量模式
  • 从 0x32 连续读 6 字节,高低字节组合,除以 256 得到 g 值
  • 默认 ±2g 量程,可通过 DATA_FORMAT 寄存器 D1/D0 切换 ±4g/±8g/±16g
ADXL345 三轴加速度计 Arduino 姿态追踪教程
ADXL345 三轴加速度计 Arduino 姿态追踪教程
ADXL345 三轴加速度计 Arduino 姿态追踪教程

零偏校准

实测 Z 轴有 0.1g 偏差。校准方法:

  1. 传感器水平静止,读取原始值(不除 256)
  2. Z 理论值 256,实测 283,偏差 +27
  3. 偏差/4 = 6.75 ≈ 7,写入 Z 轴偏移寄存器 0x20 值 -7
  4. 同理校准 X(0x1E)、Y(0x1F)
ADXL345 三轴加速度计 Arduino 姿态追踪教程
ADXL345 三轴加速度计 Arduino 姿态追踪教程
// 放在 setup() 中
// X轴
Wire.beginTransmission(ADXL345); Wire.write(0x1E); Wire.write(1); Wire.endTransmission(); delay(10);
// Y轴
Wire.beginTransmission(ADXL345); Wire.write(0x1F); Wire.write(-2); Wire.endTransmission(); delay(10);
// Z轴
Wire.beginTransmission(ADXL345); Wire.write(0x20); Wire.write(-7); Wire.endTransmission(); delay(10);

校准值掉电丢失,每次上电需重写。

解算 Roll 与 Pitch

roll  = atan(Y_out / sqrt(pow(X_out,2) + pow(Z_out,2))) * 180 / PI;
pitch = atan(-X_out / sqrt(pow(Y_out,2) + pow(Z_out,2))) * 180 / PI;

详见 Freescale 应用笔记 AN3461。

Processing 3D 可视化

ADXL345 三轴加速度计 Arduino 姿态追踪教程

Arduino 发送端(含低通滤波)

/* Arduino + ADXL345 - 3D 可视化 by Dejan */
#include 
int ADXL345 = 0x53;
float X_out, Y_out, Z_out, roll, pitch, rollF, pitchF = 0;

void setup() {
  Serial.begin(9600);
  Wire.begin();
  Wire.beginTransmission(ADXL345); Wire.write(0x2D); Wire.write(8); Wire.endTransmission(); delay(10);
  // 校准偏移
  Wire.beginTransmission(ADXL345); Wire.write(0x1E); Wire.write(1); Wire.endTransmission(); delay(10);
  Wire.beginTransmission(ADXL345); Wire.write(0x1F); Wire.write(-2); Wire.endTransmission(); delay(10);
  Wire.beginTransmission(ADXL345); Wire.write(0x20); Wire.write(-9); Wire.endTransmission(); delay(10);
}

void loop() {
  Wire.beginTransmission(ADXL345);
  Wire.write(0x32); Wire.endTransmission(false);
  Wire.requestFrom(ADXL345, 6, true);
  X_out = (Wire.read() | Wire.read() << 8) / 256.0;
  Y_out = (Wire.read() | Wire.read() << 8) / 256.0;
  Z_out = (Wire.read() | Wire.read() << 8) / 256.0;

  roll  = atan(Y_out / sqrt(pow(X_out,2) + pow(Z_out,2))) * 180 / PI;
  pitch = atan(-X_out / sqrt(pow(Y_out,2) + pow(Z_out,2))) * 180 / PI;

  // 低通滤波:94% 历史 + 6% 当前
  rollF  = 0.94 * rollF  + 0.06 * roll;
  pitchF = 0.94 * pitchF + 0.06 * pitch;

  Serial.print(rollF); Serial.print("/"); Serial.println(pitchF);
}

Processing 接收端

/* ADXL345 3D 可视化 by Dejan */
import processing.serial.*;
Serial myPort; String data=""; float roll, pitch;

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);
  rotateX(radians(roll));
  rotateZ(radians(-pitch));
  textSize(30); fill(0, 76, 153);
  box(386, 40, 200);
  textSize(25); fill(255);
  text("www.HowToMechatronics.com", -183, 10, 101);
}

void serialEvent(Serial myPort) {
  data = myPort.readStringUntil('\n');
  if (data != null) {
    data = trim(data);
    String[] items = split(data, '/');
    if (items.length > 1) {
      roll  = float(items[0]);
      pitch = float(items[1]);
    }
  }
}

低通滤波让画面更平滑,但响应变慢。仅加速度计无法解算 Yaw(Z 轴旋转),且易受手部抖动干扰。

ADXL345 三轴加速度计 Arduino 姿态追踪教程

进阶方案:融合陀螺仪(如 MPU6050 集成 6 轴),或配合磁力计组成 9 DoF。下一教程将详解 MPU6050。

希望本教程对您有帮助。欢迎评论区提问,别忘了查看我的 Arduino 项目合集!

制造工艺

  1. Arduino + MPU6050 姿态控制舵机:SG90 与 MG996R 精准跟随实战
  2. u-blox LEA-6H GPS 模块:Arduino 与 Python 集成指南
  3. Blynk + Arduino 读取 DHT11 温湿度数据教程
  4. 在 Arduino Due 上实现语音识别与语音合成 - BitVoicer Server 方案
  5. Arduino 合成乐音:从零实现 88 键钢琴全音域
  6. Arduino 连接 NMEA-0183 设备全攻略:从硬件接线到协议解析
  7. Arduino Modbus 从机开发全攻略:基于 RS485 扩展板的分步实现指南
  8. Arduino 智能咖啡机:蓝牙控制、温度曲线与自动启停
  9. 使用 Arduino 和 Alexa 打造动画智能 LED 灯带控制系统
  10. 语音控制 LED:Arduino Micro + BitVoicer Server 语音识别实战
  11. 自制 AI 助手机器人:Arduino 与 Python 协同实现语音交互与肢体动作
  12. 树莓派 3 + Arduino 驱动 NeoPixel 灯带:Web 网页端炫彩动画控制器