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

探索MEMS传感器:加速度计、陀螺仪和磁力计在Arduino项目中的应用

本教程将讲解MEMS加速度计、陀螺仪和磁力计的工作原理,以及如何配合Arduino开发板使用。同时我们将利用Processing IDE制作一些传感器实战应用。您可以观看以下视频或阅读下方文字教程。

什么是MEMS?

MEMS是尺寸极小的系统或器件,由尺寸在0.001mm至0.1mm范围的微型组件组成。这些组件由硅、聚合物、金属和/或陶瓷制成,通常与CPU(微控制器)结合形成完整系统。

下面简要解释各类微机电系统(MEMS)传感器的工作原理。

MEMS加速度计

通过测量电容变化来测量加速度。其微观结构类似:一个连接弹簧的质量块,只能沿一个方向运动,两侧有固定外板。当特定方向施加加速度时,质量块移动,导致质量块与外板间电容变化。测量该电容变化经处理后对应特定加速度值。

探索MEMS传感器:加速度计、陀螺仪和磁力计在Arduino项目中的应用

MEMS陀螺仪

陀螺仪利用科里奥利效应测量角速率。当一个质量以特定速度沿特定方向运动时,若施加外部角速率(绿箭头),会产生一个力(蓝红箭头),导致质量块发生垂直位移。与加速度计类似,这种位移引起电容变化,经测量处理后对应特定角速率。

探索MEMS传感器:加速度计、陀螺仪和磁力计在Arduino项目中的应用

陀螺仪微观结构:一个持续振荡的质量块,当外部角速率施加时,质量块的柔性部分移动产生垂直位移。

探索MEMS传感器:加速度计、陀螺仪和磁力计在Arduino项目中的应用

MEMS磁力计

利用霍尔效应或磁阻效应测量地磁场。市场上约90%的传感器使用霍尔效应,原理如下:

探索MEMS传感器:加速度计、陀螺仪和磁力计在Arduino项目中的应用

若有一导电板,电流流过时电子从一侧直线流向另一侧。若靠近磁场,电子流偏向板一侧,正极偏向另一侧。此时在两侧间测量可得电压,其大小取决于磁场强度和方向。

探索MEMS传感器:加速度计、陀螺仪和磁力计在Arduino项目中的应用

其余10%传感器使用磁阻效应,采用对磁场敏感的材料(通常为铁Fe和镍Ni组成),暴露于磁场时电阻发生变化。

Arduino与MEMS传感器


现在将这些传感器连接到Arduino并加以利用。示例使用GY-80扩展板,包含:ADXL345三轴加速度计、L3G4200D三轴陀螺仪、MC5883L三轴磁力计,以及气压计和温度计(本教程不使用)。

您可以从以下网站获取组件:

  • ADXL345三轴加速度计………………………………………………………
  • 二合一:MPU6050六轴陀螺仪&加速度计…………………
  • 三合一:GY-80九轴磁场加速度陀螺仪……… Amazon
  • 三合一:GY-86十轴MS5611 HMC5883L MPU6050模块……… Banggood / AliExpress
探索MEMS传感器:加速度计、陀螺仪和磁力计在Arduino项目中的应用

该板使用I2C通信协议,仅需两根线即可与所有传感器通信。需要知道各传感器的唯一设备地址及内部寄存器地址以读取数据,这些地址可从数据手册获取:

  • ADXL345加速度计数据手册
  • L3G4200D陀螺仪数据手册
  • MC5883L磁力计数据手册

I2C通信详情请参考我的I2C通信协议教程。

源代码

下面看如何从传感器获取数据。先从加速度计开始,每段代码前有解释,代码注释也有额外说明。

Arduino加速度计代码

首先包含Arduino Wire库并定义传感器寄存器地址。setup()中初始化Wire库和串口通信(用串口监视器显示结果)。通过向Power_CTL寄存器发送适当字节激活传感器启用测量。使用Wire.beginTransmission()选择与哪个传感器通信(三轴加速度计),Wire.write()指定内部寄存器,发送启用测量的字节,Wire.endTransmission()结束传输。

loop()中读取各轴数据。以X轴为例:选择X轴两个内部寄存器,用Wire.requestFrom()请求两字节数据。Wire.available()返回可用字节数,若匹配请求的2字节,用Wire.read()读取两个寄存器的字节。输出数据为二进制补码,X0为低字节,X1为高字节,需转换为-1到+1的浮点值,表示X轴相对于地球重力加速度的方向。对Y、Z轴重复相同过程,最后在串口监视器打印。

#include <Wire.h>
//--- 加速度计寄存器地址
#define Power_Register 0x2D
#define X_Axis_Register_DATAX0 0x32
#define X_Axis_Register_DATAX1 0x33
#define Y_Axis_Register_DATAY0 0x34
#define Y_Axis_Register_DATAY1 0x35
#define Z_Axis_Register_DATAZ0 0x36
#define Z_Axis_Register_DATAZ1 0x37
int ADXAddress = 0x53; // 设备地址,包含第8位模式选择位(读模式)
int X0,X1,X_out; int Y0,Y1,Y_out; int Z1,Z0,Z_out;
float Xa,Ya,Za;

void setup() {
  Wire.begin(); Serial.begin(9600); delay(100);
  Wire.beginTransmission(ADXAddress);
  Wire.write(Power_Register);  // Power_CTL寄存器
  Wire.write(8);  // Bit D3置高启用测量 (0000 1000)
  Wire.endTransmission();
}

void loop() {
  // X轴
  Wire.beginTransmission(ADXAddress);
  Wire.write(X_Axis_Register_DATAX0);
  Wire.write(X_Axis_Register_DATAX1);
  Wire.endTransmission();
  Wire.requestFrom(ADXAddress,2);
  if(Wire.available()<=2) {
    X0 = Wire.read(); X1 = Wire.read();
    X1=X1<<8; X_out =X0+X1; Xa=X_out/256.0; // -1到+1,X轴受重力加速度
  }
  // Y轴
  Wire.beginTransmission(ADXAddress);
  Wire.write(Y_Axis_Register_DATAY0);
  Wire.write(Y_Axis_Register_DATAY1);
  Wire.endTransmission();
  Wire.requestFrom(ADXAddress,2);
  if(Wire.available()<=2) {
    Y0 = Wire.read(); Y1 = Wire.read();
    Y1=Y1<<8; Y_out =Y0+Y1; Ya=Y_out/256.0;
  }
  // Z轴
  Wire.beginTransmission(ADXAddress);
  Wire.write(Z_Axis_Register_DATAZ0);
  Wire.write(Z_Axis_Register_DATAZ1);
  Wire.endTransmission();
  Wire.requestFrom(ADXAddress,2);
  if(Wire.available()<=2) {
    Z0 = Wire.read(); Z1 = Wire.read();
    Z1=Z1<<8; Z_out =Z0+Z1; Za=Z_out/256.0;
  }
  // 串口监视器打印
  Serial.print("Xa= "); Serial.print(Xa);
  Serial.print(" Ya= "); Serial.print(Ya);
  Serial.print(" Za= "); Serial.println(Za);
}
代码语言: Arduino (arduino)

Arduino陀螺仪代码

获取陀螺仪数据代码结构类似。先定义寄存器地址和变量。setup()中使用CTRL_REG1唤醒传感器并设为正常模式,选择灵敏度(本例选2000dps模式)。loop()中读取X、Y、Z轴原始数据并转换为角度值。根据数据手册,2000dps模式对应70 mdps/digit,即原始数据乘0.07得角速度(度/秒)。角速度乘时间得角度值。用millis()计算每次循环时间间隔dt,每次循环累加角度。三轴同理,最后串口打印结果。

#include <Wire.h>
//--- 陀螺仪寄存器地址
#define Gyro_gX0 0x28 #define Gyro_gX1 0x29
#define Gyro_gY0 0x2A #define Gyro_gY1 0x2B
#define Gyro_gZ0 0x2C #define Gyro_gZ1 0x2D
int Gyro = 0x69; // 设备地址
int gX0, gX1, gX_out; int gY0, gY1, gY_out; int gZ0, gZ1, gZ_out;
float Xg,Yg,Zg; float angleX,angleY,angleZ,angleXc,angleYc,angleZc;
unsigned long start, finished, elapsed; float dt=0.015;

void setup() {
  Wire.begin(); Serial.begin(9600); delay(100);
  Wire.beginTransmission(Gyro); Wire.write(0x20); Wire.write(15); Wire.endTransmission(); // CTRL_REG1 正常模式
  Wire.beginTransmission(Gyro); Wire.write(0x23); Wire.write(48); Wire.endTransmission(); // CTRL_REG4 2000dps
}

void loop() {
  start=millis();
  // X轴
  Wire.beginTransmission(Gyro); Wire.write(Gyro_gX0); Wire.endTransmission();
  Wire.requestFrom(Gyro,1); if(Wire.available()<=1) gX0 = Wire.read();
  Wire.beginTransmission(Gyro); Wire.write(Gyro_gX1); Wire.endTransmission();
  Wire.requestFrom(Gyro,1); if(Wire.available()<=1) gX1 = Wire.read();
  // Y轴
  Wire.beginTransmission(Gyro); Wire.write(Gyro_gY0); Wire.endTransmission();
  Wire.requestFrom(Gyro,1); if(Wire.available()<=1) gY0 = Wire.read();
  Wire.beginTransmission(Gyro); Wire.write(Gyro_gY1); Wire.endTransmission();
  Wire.requestFrom(Gyro,1); if(Wire.available()<=1) gY1 = Wire.read();
  // Z轴
  Wire.beginTransmission(Gyro); Wire.write(Gyro_gZ0); Wire.endTransmission();
  Wire.requestFrom(Gyro,1); if(Wire.available()<=1) gZ0 = Wire.read();
  Wire.beginTransmission(Gyro); Wire.write(Gyro_gZ1); Wire.endTransmission();
  Wire.requestFrom(Gyro,1); if(Wire.available()<=1) gZ1 = Wire.read();
  // 数据处理
  gX1=gX1<<8; gX_out =gX0+gX1; Xg=gX_out*0.07; angleXc = Xg*dt; angleX += angleXc;
  gY1=gY1<<8; gY_out =gY0+gY1; Yg=gY_out*0.07; angleYc = Yg*dt; angleY += angleYc;
  gZ1=gZ1<<8; gZ_out =gZ0+gZ1; Zg=gZ_out*0.07; angleZc = Zg*dt; angleZ += angleZc;
  // 打印
  Serial.print("angleX= "); Serial.print(angleX);
  Serial.print(" angleY= "); Serial.print(angleY);
  Serial.print(" angleZ= "); Serial.println(angleZ);
  delay(10);
  finished=millis(); elapsed=finished-start; dt=elapsed/1000.0; start = elapsed = 0;
}
代码语言: Arduino (arduino)

Arduino磁力计代码

同样技术。定义寄存器地址,setup()设置连续测量模式。loop()中获取各轴原始数据。需将原始数据转换为磁场值(高斯单位)。数据手册显示默认灵敏度0.92mG/digit,即原始数据乘0.00092得高斯值。地磁场约0.25-0.65高斯,读数应在此范围。最后串口打印。

#include <Wire.h>
//I2C Arduino库
#define Magnetometer_mX0 0x03 #define Magnetometer_mX1 0x04
#define Magnetometer_mZ0 0x05 #define Magnetometer_mZ1 0x06
#define Magnetometer_mY0 0x07 #define Magnetometer_mY1 0x08
int mX0, mX1, mX_out; int mY0, mY1, mY_out; int mZ0, mZ1, mZ_out;
float Xm,Ym,Zm;
#define Magnetometer 0x1E // HMC5883 I2C 7位地址

void setup(){
  Serial.begin(9600); Wire.begin(); delay(100);
  Wire.beginTransmission(Magnetometer);
  Wire.write(0x02); Wire.write(0x00); // 连续测量模式
  Wire.endTransmission();
}

void loop(){
  // X轴
  Wire.beginTransmission(Magnetometer); Wire.write(Magnetometer_mX1); Wire.endTransmission();
  Wire.requestFrom(Magnetometer,1); if(Wire.available()<=1) mX0 = Wire.read();
  Wire.beginTransmission(Magnetometer); Wire.write(Magnetometer_mX0); Wire.endTransmission();
  Wire.requestFrom(Magnetometer,1); if(Wire.available()<=1) mX1 = Wire.read();
  // Y轴
  Wire.beginTransmission(Magnetometer); Wire.write(Magnetometer_mY1); Wire.endTransmission();
  Wire.requestFrom(Magnetometer,1); if(Wire.available()<=1) mY0 = Wire.read();
  Wire.beginTransmission(Magnetometer); Wire.write(Magnetometer_mY0); Wire.endTransmission();
  Wire.requestFrom(Magnetometer,1); if(Wire.available()<=1) mY1 = Wire.read();
  // Z轴
  Wire.beginTransmission(Magnetometer); Wire.write(Magnetometer_mZ1); Wire.endTransmission();
  Wire.requestFrom(Magnetometer,1); if(Wire.available()<=1) mZ0 = Wire.read();
  Wire.beginTransmission(Magnetometer); Wire.write(Magnetometer_mZ0); Wire.endTransmission();
  Wire.requestFrom(Magnetometer,1); if(Wire.available()<=1) mZ1 = Wire.read();
  // 数据转换
  mX1=mX1<<8; mX_out =mX0+mX1; Xm = mX_out*0.00092; // 高斯
  mY1=mY1<<8; mY_out =mY0+mY1; Ym = mY_out*0.00092;
  mZ1=mZ1<<8; mZ_out =mZ0+mZ1; Zm = mZ_out*0.00092;
  // 打印
  Serial.print("x: "); Serial.print(Xm);
  Serial.print(" y: "); Serial.print(Ym);
  Serial.print(" z: "); Serial.println(Zm);
  delay(50);
}
代码语言: Arduino (arduino)

这是一个使用Processing IDE制作的MEMS数字指南针酷炫应用。更多详情和源码请访问以下链接:

探索MEMS传感器:加速度计、陀螺仪和磁力计在Arduino项目中的应用

制造工艺

  1. Arduino Nano 与 MPU-6050 构建实时陀螺仪游戏
  2. 互动陀螺仪 LED 显示:NeoPixel Ring + Arduino Pro Mini
  3. K30 CO₂ 传感器:室内空气质量实时监测
  4. 基于 1Sheeld 与 Arduino 的盲聋人士沟通辅助系统
  5. 智能存钱罐:Arduino Nano 控制硬币识别器实现余额显示
  6. Arduino + HC-05 蓝牙控制 LED:MIT App Inventor 手机 App 开发全攻略
  7. DFRobot 电容指纹传感器 (ID809) 接入 Arduino/ESP8266 完整教程
  8. 基于 Arduino Mega 与 Nextion 显示屏的交互式气象站
  9. Arduino Mega 驱动 Wii Nunchuk 控制 6 自由度机械臂
  10. Arduino UNO + 以太网盾板实现低成本太阳辐射测量仪(热电堆原理)
  11. 什么是磁力计?原理、核心物理与现实应用全景
  12. 可靠性互联网中的数据驾驭:高效管理策略