如何使用MPU6050和Arduino构建一个数字量角器

2023-08-19 11:25:34 |人围观 | 评论:

  MPU6050是一款 集成 了IC3 轴加速度计和 3 轴陀螺仪的 单元。它还包含一个温度传感器和一个DCM 来执行复杂的任务。MPU6050 常用于构建无人机和其他远程机器人,如自平衡机器人。在这个项目中,我们将使用MPU6050 和Arduino构建一个数字量角器。

  什么是加速度计和陀螺仪传感器

  加速度计用于测量加速度。它实际上感应静态和动态加速度。例如,手机使用加速度传感器来感知手机处于横向模式还是纵向模式。

  陀螺仪用于测量角速度,该角速度使用地球重力来确定运动中物体的方向。角速度是旋转体角位置的变化率。

  例如,今天的手机使用陀螺仪传感器根据手机的方位来玩手机游戏。此外,VR耳机使用陀螺仪传感器具有 360 度视图

  因此,虽然加速度计可以测量线性加速度,但陀螺仪可以帮助找到旋转加速度。当使用两个传感器作为单独的模块时,很难找到方向、位置和速度。但是通过组合这两个传感器,它可以作为一个惯性测量单元(IMU)。因此,在MPU6050 模块中,加速度计和陀螺仪存在于单个PCB上,以查找方向、位置和速度。

  应用:

  用于无人机方向控制

  自平衡机器人

机械臂控制

  倾斜传感器

  用于手机、视频游戏机

  人形机器人

  用于飞机、汽车等。

  MPU6050 加速度计和陀螺仪传感器模块

pYYBAGMPEMGAdgyKAAJJS-QTJdw571.png

  MPU6050 是一种微机电系统 (MEMS),内部包含一个 3 轴加速度计和 3 轴陀螺仪。它也有温度传感器。

  它可以测量:

  加速

  速度

  方向

  移位

  温度

  该模块内部还有一个(DMP)数字运动处理器,其功能强大到足以执行复杂的计算,从而为微控制器腾出工作。

  该模块还有两个辅助引脚,可用于连接外部 IIC 模块,如磁力计。由于模块的 IIC 地址是可配置的,因此可以使用AD0 引脚将多个 MPU6050 传感器 连接到微控制器。

  特点和规格:

电源:3-5V

  通讯方式:I2C协议

  内置 16 位ADC提供高精度

  内置 DMP 提供高计算能力

  可用于连接其他 IIC 设备,如磁力计

  可配置的 IIC 地址

  内置温度传感器

  MPU6050的管脚:

pYYBAGMPEL2Acf1zAAEuIrCRFC0908.png

pYYBAGMPELmABT14AACcKJt3Z6k454.png

  我们之前使用MPU6050 和 Arduino来构建自平衡机器人和测斜仪。

  所需组件

  Arduino UNO

  MPU6050陀螺仪模块

  16x2 液晶显示器

电位器10k

  SG90-伺服电机

  量角器图像

电路原理

  这个DIYArduino 量角器的电路图如下所示:

poYBAGMPELSAaHy5AAGOHDtH4AA876.png

  Arduino UNO 和 MPU6050 之间的电路连接:

poYBAGMPELCAZfYOAAALnhqWiE4168.png

  Arduino UNO 和伺服电机之间的电路连接:

pYYBAGMPEKyAY1w2AAAMGKjJ4Vg024.png

  Arduino UNO 和 16x2 LCD 之间的电路连接:

pYYBAGMPEKmACj-CAAAfcZsvB3Y597.png

poYBAGMPEKWAB95RAAUzx6UZJa0299.png

编程说明

  这里伺服电机与 Arduino 连接,其轴投影在量角器图像上,指示倾斜 MPU6050 的角度。

  首先包括所有必需的库 - 用于使用伺服的伺服电机库、用于使用 LCD 的 LCD 库和用于使用 I2C通信的 Wire 库。

  MPU6050 使用I2C 通信,因此,它只能连接到 Arduino 的 I2C 引脚。因此,Wire.h库用于建立 Arduino UNO 和 MPU6050 之间的通信。我们之前将 MPU6050 与 Arduino 连接,并在 16x2 LCD 上显示 x、y、z 坐标值。

#include
       
        #include
        
         #include
         
        
       

接下来定义与 Arduino UNO 连接的 LCD 显示引脚RS、E、D4、D5、D6、D7。

液晶液晶(2,3,4,5,6,7);

接下来定义 MPU6050 的 I2C 地址。

常量 int MPU_addr=0x68;

然后初始化myservo对象以使用 Servo 类和三个变量来存储 X、Y 和 Z 轴值。

伺服myservo; int16_t 轴_X,轴_Y,轴_Z;

下一个最小值和最大值设置为 265 和 402,用于测量从 0 到 360 的角度。

int minVal=265; 诠释 maxVal=402;

无效设置():

在void setup函数中,首先启动 I2C 通信,并使用地址为 0x68 的 MPU6050 开始传输。

Wire.begin(); Wire.beginTransmission(MPU_addr);

通过写入 0x6B 将 MPU6050 置于睡眠模式,然后通过写入 0 唤醒它

Wire.write(0x6B); Wire.write(0);

使MPU6050激活后,结束传输

Wire.endTransmission(true);

此处伺服电机的 PWM 引脚与 Arduino UNO 引脚 9 相连。

myservo.attach(9);

一旦我们给电路加电,液晶显示屏就会显示一条欢迎消息,并在 3 秒后清除它

lcd.开始(16,2);//将 LCD 设置为 16X2 模式 lcd.print("CIRCUIT DIGEST"); 延迟(1000); lcd.clear(); lcd.setCursor(0,0); lcd.print("Arduino"); lcd.setCursor(0,1); lcd.print("MPU6050"); 延迟(3000); lcd.clear();

无效循环():

同样,I2C 通信是从 MPU6050 开始的。

Wire.beginTransmission(MPU_addr);

然后从寄存器0x3B (ACCEL_XOUT_H) 开始

Wire.write(0x3B);

现在,通过将结束传输设置为 false 重新启动该过程,但连接处于活动状态。

Wire.endTransmission(false);

之后,现在从 14 个寄存器请求数据。

Wire.requestFrom(MPU_addr,14,true);

现在获得尊重的轴寄存器值(x,y,z)并将其存储在变量axis_X,axis_Y,axis_Z中。

axis_X=Wire.read()<<8|Wire.read(); axis_Y=Wire.read()<<8|Wire.read(); axis_Z=Wire.read()<<8|Wire.read();

然后将这些值从 265 映射到 402 为 -90 到 90。这对所有三个轴都完成了。

int xAng = map(axis_X,minVal,maxVal,-90,90); int yAng = map(axis_Y,minVal,maxVal,-90,90); int zAng = map(axis_Z,minVal,maxVal,-90,90);

下面给出了以度(0 到 360)为单位计算 x 值的公式。这里我们只转换 x,因为伺服电机的旋转是基于 x 值移动的。

x= RAD_TO_DEG * (atan2(-yAng, -zAng)+PI);

X 角度值,从 0 到 360 度,转换为 0 到 180。

int pos = map(x,0,180,0,180);

然后写入角度值以在量角器图像上旋转伺服并将这些值打印在 16x2 LCD 显示器上。

myservo.write(pos); lcd.setCursor(0,0); lcd.print("角度"); lcd.setCursor(0,1); lcd.print(x); 延迟(500); lcd.clear();

poYBAGMPEJqASA0SAARyXNJ3H_4542.png

#include //包含用于使用伺服的伺服电机库

#include //包含用于使用 LCD 的 LCD 库

#include //包含用于使用 I2C 的 WIre 库


液晶液晶(2,3,4,5,6,7); //定义LCD显示引脚RS,E,D4,D5,D6,D7


常量 int MPU_addr=0x68; //I2C MPU6050地址


伺服myservo;//类伺服的myservo对象


int16_t 轴_X,轴_Y,轴_Z;


int minVal=265;

诠释 maxVal=402;


双x;

双 y;

双z;


整数位置 = 0;


void setup()

{

Wire.begin(); //开始 I2C 通信

Wire.beginTransmission(MPU_addr); //使用 MPU6050 开始传输

Wire.write(0x6B); //将 MPU6050 置于睡眠模式

Wire.write(0); //将 MPU6050 置于电源模式

Wire.endTransmission(true); //结束



传输 myservo.attach(9);

//UNO lcd.begin(16,2)中的伺服 PWM 引脚为 9 ;//将 LCD 设置为 16X2 模式

lcd.print("CIRCUIT DIGEST");

延迟(1000);

lcd.clear();

lcd.setCursor(0,0);

lcd.print("Arduino");

lcd.setCursor(0,1);

lcd.print("MPU6050");

延迟(2000);

lcd.clear();

}


无效循环()

{

Wire.beginTransmission(MPU_addr);//开始 I2C 传输

Wire.write(0x3B); //从寄存器 0x3B (ACCEL_XOUT_H) 开始

Wire.endTransmission(false);

Wire.requestFrom(MPU_addr,14,true); //向MPU6050请求14个寄存器



axis_X=Wire.read()<<8|Wire.read(); //获取0x3B (ACCEL_XOUT_H) & 0x3C (ACCEL_XOUT_L)

axis_Y=Wire.read()<<8|Wire.read(); //0x3B (ACCEL_YOUT_H) & 0x3C (ACCEL_YOUT_L)

axis_Z=Wire.read()<<8|Wire.read(); //0x3B (ACCEL_ZOUT_H) & 0x3C (ACCEL_ZOUT_L)



int xAng = map(axis_X,minVal,maxVal,-90,90);

int yAng = map(axis_Y,minVal,maxVal,-90,90);

int zAng = map(axis_Z,minVal,maxVal,-90,90);


x= RAD_TO_DEG * (atan2(-yAng, -zAng)+PI); //计算度数x值的公式

int pos = map(x,0,180,0,180); // 因为 X 值是从 0 到 360 度

myservo.write(pos); // 将获得的角度 0 到 180 写入伺服

lcd.setCursor(0,0);

lcd.print("角度");

lcd.setCursor(0,1);

lcd.print(x);

延迟(500);

lcd.clear();

}





标签: [db:tags]