使用Arduino实现双MPU6050数据采集

Arduino同时读取两个MPU6050的数据

  • 开发背景
  • MPU6050基础介绍:
  • Pin 定义
  • 属性
  • 单位
  • MPU6050传感器的检测轴如图
  • 单MPU6050数据读取演示
  • 单MPU6050模块接线
  • 单MPU6050模块示例
  • 示例讲解
  • Adafruit_MPU6050.h说明
  • Wire.h说明
  • 同时读取两个MPU6050数据的示例
  • 双MPU6050模块接线
  • 双MPU6050模块示例
  • 多个MPU6050的数据采集
  • 控制AD0引脚采集多个数据
  • 通过模拟开关芯片连接传感器
  • 开发背景

    工作中有个项目,急需同时测量两套振动计的加速度数据。直接连示波器的话,通道数不够。于是想使用MCU通过I2C接口同时读取两个MPU6050的数据,但网上只有读取单个MPU6050的资料。为防后续自己忘记,做以下记录。

  • MCU型号:Arduino
  • 传感器型号:MPU6050
  • IDE环境 : Arduino IDE
  • MPU6050基础介绍:

    Integrated sensor with 3-axis accelerometer, 3-axis gyroscope and a temperature sensor with I2C interface.
    在MPU6050模块

    Pin 定义

    Name Description
    VCC Voltage supply
    GND Ground
    SCL I2C clock line
    SDA I2C data line
    XDA Unused*
    XCL Unused*
    AD0 Address select pin
    INT Interrupt

    You normally only need to connect the VCC, GND, SCL, and SDA pins. The I2C address of the device is 0x68. You can change the address of 0x69 by connecting the AD0 pin to VCC.

    属性

    Name Description Default value
    accelX Initial x acceleration value (g) “0”
    accelY Initial y acceleration value (g) “0”
    accelZ Initial z acceleration value (g) “1”
    rotationX Initial x rotation value (deg/sec) “0”
    rotationY Initial y rotation value (deg/sec) “0”
    rotationZ Initial z rotation value (deg/sec) “0”
    temperature Initial temperature value (celsius) “24”

    单位

    All the acceleration values (x/y/z) use g-force units, where 1g = 9.80665 m/s². The gyroscope measures angular rotation and returns the number of degrees per second.

    MPU6050传感器的检测轴如图

    下图显示了灵敏度轴的方向和旋转的极性。注意图中pin 1标识符(•)。
    检测轴的方向

    单MPU6050数据读取演示

    单MPU6050模块接线

    在Arduino Uno上,连接SDA引脚到A4, SCL引脚到A5。
    单MPU6050模块接线图

    单MPU6050模块示例

    // Basic demo for accelerometer readings from Adafruit MPU6050
    
    #include <Adafruit_MPU6050.h>
    #include <Adafruit_Sensor.h>
    #include <Wire.h>
    
    Adafruit_MPU6050 mpu;
    
    void setup(void) {
      Serial.begin(115200);
      while (!Serial) {
        delay(10); // will pause Zero, Leonardo, etc until serial console opens
      }
    
      // Try to initialize!
      if (!mpu.begin()) {
        Serial.println("Failed to find MPU6050 chip");
        while (1) {
          delay(10);
        }
      }
    
      mpu.setAccelerometerRange(MPU6050_RANGE_16_G);
      mpu.setGyroRange(MPU6050_RANGE_250_DEG);
      mpu.setFilterBandwidth(MPU6050_BAND_21_HZ);
      Serial.println("");
      delay(100);
    }
    
    void loop() {
    
      /* Get new sensor events with the readings */
      sensors_event_t a, g, temp;
      mpu.getEvent(&a, &g, &temp);
    
      /* Print out the values */
      Serial.print("AccelX:");
      Serial.print(a.acceleration.x);
      Serial.print(",");
      Serial.print("AccelY:");
      Serial.print(a.acceleration.y);
      Serial.print(",");
      Serial.print("AccelZ:");
      Serial.print(a.acceleration.z);
      Serial.print(", ");
      Serial.print("GyroX:");
      Serial.print(g.gyro.x);
      Serial.print(",");
      Serial.print("GyroY:");
      Serial.print(g.gyro.y);
      Serial.print(",");
      Serial.print("GyroZ:");
      Serial.print(g.gyro.z);
      Serial.println("");
    
      delay(100);
    }
    

    串口窗口每0.1秒输出

    AccelX:0.00,AccelY:0.00,AccelZ:9.81, GyroX:0.00,GyroY:0.00,GyroZ:0.00
    

    示例讲解

    Adafruit_MPU6050.h说明

    关于此库,上github查阅,链接:https://github.com/adafruit/Adafruit_MPU6050
    设置MPU6050的测量范围和精度

      mpu.setAccelerometerRange(MPU6050_RANGE_16_G);//设置加速度计测量范围
      //量程为±2g、±4g、±8g和±16g的3轴加速度传感器。默认是2g
      //精度随量程变化,详见芯片PDF。
        
      mpu.setGyroRange(MPU6050_RANGE_250_DEG);//设置陀螺仪测量范围
      //敏感度与全格测范围为±250、±500、±1000与±2000°/sec的3轴角速度感测器(陀螺仪)。默认是500
      //精度随量程变化,详见芯片PDF。
      
      mpu.setFilterBandwidth(MPU6050_BAND_21_HZ);//设置数字低通滤波器的带宽
      //带宽范围为5~260Hz。默认是260Hz
    

    带宽参考“正点原子”的PDF介绍:
    采样率与带宽的关系
    MPU6050的芯片PDF。1

    Wire.h说明

    引用“太极创客”的介绍:Wire库可以让Arduino与IIC / TWI设备进行通信。 与SPI总线一样, IIC也是主从方式通讯, 因此不能同时存在两个主设备,只能是一个主设备与一个或多个从设备进行通讯。
    一般来说I2C地址有7位和8位的版本。 7位是设备标识码,而第8位则是为了确认设备当前状态是正在写入还是读取。 而Arduino -Wire库始终使用的是7位地址。 如果您使用了8位,则需要删除低位,从而得到0到127之间的地址。但是,地址从0到7 被保留了, 因此您在开发的时候请不要使用它们!!! 可以从8开始使用。
    判断厂商提供的地址是7bit模式地址还是8bit地址模式的地址,7bit地址模式下,地址的取值范围在0x07到0x78之间,若超过了这个范围,那么这个地址可能就是8bit地址。2
    请注意,连接SDA / SCL引脚时需要一个上拉电阻。
    Wire库的实现使用了32字节缓冲区,因此任何通信都必须在此限制之内。 单次传输中超出的字节将被丢弃。
    begin函数:
    描述:初始化Wire库,并以主机或从机身份加入I2C总线。
    通常来说这个函数只调用一次。
    语法:

    Wire.begin()
    Wire.begin(address)
    
    

    参数:
    address(可选):7位从机的地址; 如果这个参数未指定,则默认以主机身份加入总线(注1)。

    返回值:无

    同时读取两个MPU6050数据的示例

    双MPU6050模块接线

    模块1的接线不变,模块2除AD0引脚接VCC,其它同模块1一样接线
    双MPU6050模块接线图

    双MPU6050模块示例

    // Basic demo for accelerometer readings from double Adafruit MPU6050
    #include <Adafruit_MPU6050.h>
    #include <Adafruit_Sensor.h>
    #include <Wire.h>
    
    Adafruit_MPU6050 mpu1;
    Adafruit_MPU6050 mpu2;
    
    void setup(void) {
      Serial.begin(115200);
      while (!Serial) {
        delay(10); // will pause Zero, Leonardo, etc until serial console opens
      }
    
      // Try to initialize!
      if (!mpu1.begin(0x68))	//I2C地址出错会报:Failed to find 01-MPU6050 chip
       {
        Serial.println("Failed to find 01-MPU6050 chip");
        while (1) {
          delay(10);
        }
      }
      if (!mpu2.begin(0x69)) //I2C地址出错会报:Failed to find 02-MPU6050 chip
      {
        Serial.println("Failed to find 02-MPU6050 chip");
        while (1) {
          delay(10);
        }
      }
    
      mpu1.setAccelerometerRange(MPU6050_RANGE_16_G);
      mpu1.setGyroRange(MPU6050_RANGE_250_DEG);
      mpu1.setFilterBandwidth(MPU6050_BAND_21_HZ);
      Serial.println("");
      delay(100);
      mpu2.setAccelerometerRange(MPU6050_RANGE_16_G);
      mpu2.setGyroRange(MPU6050_RANGE_250_DEG);
      mpu2.setFilterBandwidth(MPU6050_BAND_21_HZ);
      Serial.println("");
      delay(100);
    }
    
    void loop() {
    
      /* Get new sensor events with the readings */
      sensors_event_t a1, g1, temp1;
      sensors_event_t a2, g2, temp2;
      mpu1.getEvent(&a1, &g1, &temp1);
      mpu2.getEvent(&a2, &g2, &temp2);
    
      /* Print out the values */
      Serial.print(a1.acceleration.x);
      Serial.print(",");
      Serial.print(a1.acceleration.y);
      Serial.print(",");
      Serial.print(a1.acceleration.z);
      Serial.print(",");
      Serial.print(a2.acceleration.x);
      Serial.print(",");
      Serial.print(a2.acceleration.y);
      Serial.print(",");
      Serial.println(a2.acceleration.z);
      
      delay(1000);
    }
    

    串口窗口每0.1秒输出

    0.00,0.00,9.81,0.00,0.00,9.81
    

    多个MPU6050的数据采集

    控制AD0引脚采集多个数据

    多个MPU6050的每一个AD0分别接一个 arduino 的IO口,这样可以用 arduino 控制它的高低来决定MPU6050的地址,每次要使用某一个MPU6050的时候,把这个AD0连接的 IO 口输出低电平,其它输出高电平,这些 MPU6050 的地址是 0x69,我们不用它,读取 IIC 的 0x68 地址的数据就是所要的了。
    注意的是 IO 口是 5v,需要转换一下电平,或分压。
    这应该使得在项目中有许多MPU-6050传感器成为可能。甚至超过10个传感器应该是可能的。注意,从许多MPU-6050传感器请求数据很慢,因为I2C总线很慢。具有SPI接口的传感器更快。
    ZH有题主测试过该方案:
    更新2016年3月25日:这个技巧确认工作正常使用三个GY-521开发版以及ESP8266 wifi /微控制器(NodeMCU)。
    更新2017年5月2日:通过SPI驱动MPU6050可以带的动至少7个(我用的是7个)用来模拟出手部动作。

    通过模拟开关芯片连接传感器

    每传感器的SCL/SDA引脚不再连接MCU,改为连接模拟开关芯片,然后通过控制开关芯片的使能,控制每个传感器的SCL/SDA分别与MCU的导通,来采集数据。


    1. 链接:MPU6050的芯片PDF ↩︎

    2. 引用"IIC从地址之7位,8位和10位详解",链接:https://blog.csdn.net/geju323/article/details/119787270 ↩︎

    物联沃分享整理
    物联沃-IOTWORD物联网 » 使用Arduino实现双MPU6050数据采集

    发表评论