两个MPU6050通过I2C向Arduino传输数据

本文章旨在解决两个6050以不同地址向MCU传输数据的功能,数据稳定可靠,加上无线通信可用于姿态控制

将ADO置高电平可将地址由默认ox68改为0x69**

一、检查你的陀螺仪地址是否不同

#include "I2CScanner.h"

I2CScanner scanner;

const byte address;

void debug(byte address)
{
	Serial.print("Found at 0x");
	Serial.println(address, HEX);
}

void setup() 
{
	Serial.begin(9600);
	while (!Serial) {};

	scanner.Init();
}

void loop() 
{
	scanner.Execute(debug);
	delay(5000);
}

效果如图,这里是一块OLED的地址
在这里插入图片描述

二、传输数据`

#include <Wire.h>
#include <SoftwareSerial.h>

// 使用软件串口,在数字引脚5和4上创建一个新的串行端口对象
SoftwareSerial mySerial(5, 4);

// 全局变量定义
int num = 0, laststate = 0;
const int MPU2 = 0x69, MPU1 = 0x68;  // 两个MPU传感器的I2C地址
const float alpha = 0.98;  // 角度计算中的滤波系数
long accelX, accelY, accelZ;  // 加速度计数据
float gForceX, gForceY, gForceZ;  // 加速度值
float gyroX, gyroY, gyroZ, rotX, rotY, rotZ;  // 陀螺仪数据
long accelX2, accelY2, accelZ2;  // 第二个MPU的加速度计数据
float gForceX2, gForceY2, gForceZ2;  // 第二个MPU的加速度值
float roll_1, pitch_1, roll_2, pitch_2;  // 两个MPU的姿态角度
float accAngleX, accAngleY, gyroAngleX, gyroAngleY, gyroAngleZ;  // 角度值

void setup() {
  // 初始化串口通信
  Serial.begin(115200);
  mySerial.begin(115200);
  
  // 初始化I2C通信
  Wire.begin();

  // 初始化MPU1传感器
  Wire.beginTransmission(MPU1);
  Wire.write(0x6B);  // 寄存器地址:PWR_MGMT_1
  Wire.write(0b00000000);  // 设置设备为唤醒模式
  Wire.endTransmission();
  
  Wire.beginTransmission(MPU1);
  Wire.write(0x1B);  // 寄存器地址:GYRO_CONFIG
  Wire.write(0x00000000);  // 设置陀螺仪量程
  Wire.endTransmission();
  
  Wire.beginTransmission(MPU1);
  Wire.write(0x1C);  // 寄存器地址:ACCEL_CONFIG
  Wire.write(0b00000000);  // 设置加速度计量程
  Wire.endTransmission();

  // 初始化MPU2传感器
  Wire.beginTransmission(MPU2);
  Wire.write(0x6B);  // 寄存器地址:PWR_MGMT_1
  Wire.write(0b00000000);  // 设置设备为唤醒模式
  Wire.endTransmission();
  
  Wire.beginTransmission(MPU2);
  Wire.write(0x1B);  // 寄存器地址:GYRO_CONFIG
  Wire.write(0x00000000);  // 设置陀螺仪量程
  Wire.endTransmission();
  
  Wire.beginTransmission(MPU2);
  Wire.write(0x1C);  // 寄存器地址:ACCEL_CONFIG
  Wire.write(0b00000000);  // 设置加速度计量程
  Wire.endTransmission();
}

void loop() {
  // 获取并打印MPU1和MPU2的数据
  GetMpuValue(MPU1);
  Serial.print("\t ||| \t");
  GetMpuValue(MPU2);
  Serial.println(" ");
}

void GetMpuValue(const int MPU) {
  if (MPU == 0x68) {
    // 读取MPU1的加速度计数据
    Wire.beginTransmission(MPU);
    Wire.write(0x3B);  // 寄存器地址:ACCEL_XOUT_H
    Wire.endTransmission();
    Wire.requestFrom(MPU, 6);
    while (Wire.available() < 6);
    accelX = Wire.read() << 8 | Wire.read();
    accelY = Wire.read() << 8 | Wire.read();
    accelZ = Wire.read() << 8 | Wire.read();

    // 读取MPU1的陀螺仪数据
    Wire.beginTransmission(MPU);
    Wire.write(0x43);  // 寄存器地址:GYRO_XOUT_H
    Wire.endTransmission();
    Wire.requestFrom(MPU, 6);
    while (Wire.available() < 6);
    gyroX = Wire.read() << 8 | Wire.read();
    gyroY = Wire.read() << 8 | Wire.read();
    gyroZ = Wire.read() << 8 | Wire.read();

    // 计算并打印MPU1的姿态角度
    roll_1 = atan2(accelZ, accelY) * 180 / PI;
    pitch_1 = -atan2(sqrt(accelY * accelY + accelZ * accelZ), accelX) * 180 / PI;
    Serial.print("roll_1: ");
    Serial.print(roll_1);
    Serial.print("    ");
    Serial.print("pitch_1: ");
    Serial.print(pitch_1);
    Serial.print(" ");
    delay(50);
  } else if (MPU == 0x69) {
    // 读取MPU2的加速度计数据
    Wire.beginTransmission(MPU);
    Wire.write(0x3B);  // 寄存器地址:ACCEL_XOUT_H
    Wire.endTransmission();
    Wire.requestFrom(MPU, 6);
    while (Wire.available() < 6);
    accelX = Wire.read() << 8 | Wire.read();
    accelY = Wire.read() << 8 | Wire.read();
    accelZ = Wire.read() << 8 | Wire.read();

    // 读取MPU2的陀螺仪数据
    Wire.beginTransmission(MPU);
    Wire.write(0x43);  // 寄存器地址:GYRO_XOUT_H
    Wire.endTransmission();
    Wire.requestFrom(MPU, 6);
    while (Wire.available() < 6);
    gyroX = Wire.read() << 8 | Wire.read();
    gyroY = Wire.read() << 8 | Wire.read();
    gyroZ = Wire.read() << 8 | Wire.read();

    // 计算并打印MPU2的姿态角度
    roll_2 = atan2(accelZ, accelY) * 180 / PI;
    pitch_2 = -atan2(sqrt(accelY * accelY + accelZ * accelZ), accelX) * 180 / PI;
    Serial.print("roll_2: ");
    Serial.print(roll_2);
    Serial.print("    ");
    Serial.print("pitch_2: ");
    Serial.print(pitch_2);
    Serial.print(" ");
    delay(50);
  }
}

我上面发的代码使用加速度计的数据计算了滚转角(Roll)和俯仰角(Pitch)。

三、计算滚转角(Roll)和俯仰角(Pitch)的原理解释

滚转角(Roll):
在这里插入图片描述
使用 atan2 函数计算滚转角,这个函数可以避免在 y 轴加速度为零时出现除零错误,并且能够提供从 -π 到 π 的结果。计算结果转换为度数(从弧度转换为度数)。

俯仰角(Pitch):
在这里插入图片描述
在代码中实现如下:

pitch_1 = -atan2(sqrt(accelY * accelY + accelZ * accelZ), accelX) * 180 / PI;

这段代码使用 atan2 函数计算俯仰角,并且负号用于修正方向。结果也被转换为度数。通过读取 MPU6050 传感器的加速度计数据,并使用 atan2 函数计算滚转角和俯仰角,可以得到传感器在空间中的姿态角。这种方法利用了加速度计的静态特性(即在没有运动时,只测量重力加速度),从而得出姿态角。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

ASSIC clr

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值