【Arduino小车实践】陀螺仪之相关代码分析(可直接搬用)

前言

上一篇简单介绍了陀螺仪的基本内容,本篇主要针对陀螺仪的代码使用进行分析。

上一篇关于陀螺仪的基本内容的链接:(58条消息) 【Arduino小车实践】陀螺仪的使用_禾风wyh的博客-CSDN博客

代码分析

1. 相关库函数

Adafruit_MPU6050.h 包含了 MPU6050 加速度计的功能,包括初始化、获取数据等
Adafruit_Sensor.h 为了支持 MPU6050 加速度计的传感器事件。它提供了一种统一的接口用于获取不同类型传感器(如加速度计、陀螺仪、磁力计等)的数据
Wire.h 了支持 MPU6050 加速度计的传感器事件。它提供了一种统一的接口用于获取不同类型传感器(如加速度计、陀螺仪、磁力计等)的数据

2. 对象声明

Adafruit_MPU6050 mpu; //这行代码定义了一个名为 mpu 的对象,其类型为 Adafruit_MPU6050,用于与 MPU6050 加速度计进行通信和操作。

在代码中的其他部分,可以使用这个对象来调用 Adafruit_MPU6050 类中提供的方法,如 begin()getEvent()setAccelerometerRange() 等,以实现对 MPU6050 加速度计的初始化、数据获取和设置等操作。

3. 基础代码

(1)启动MPU6050

void MPU_START(void){//用于启动 MPU6050 传感器
   Wire.beginTransmission(0x68); //开启MPU6050的传输
   Wire.write(0x6B); //指定寄存器地址,0x68 是 MPU6050 的 I2C 地址
   Wire.write(0); //将 MPU6050 的寄存器 0x6B 写入 0,以启动 MPU6050
   Wire.endTransmission(true); //结束传输,true表示释放总线
}

(2)配置角速度

void GYRO_CONFIG_SET(int f){  //配置角速度倍率 
   Wire.beginTransmission(0x68); //开启MPU-6050的传
   Wire.write(0x1B); //角速度倍率寄存器的地址
   Wire.requestFrom(0x68, 1, true); //从 MPU6050 的寄存器地址 0x1B 请求读取 1 个字节的数据,读出原来的配置
   unsigned char acc_conf = Wire.read();//将读取到的数据保存在变量 acc_conf 中。这个变量用于存储原配置的值
   acc_conf = ((acc_conf & 0xE7) | (f << 3));//对 acc_conf 进行位运算,以设置新的角速度倍率。通过 f 参数左移 3 位,并和原配置进行按位或操作,从而实现设置新的角速度倍率
   Wire.write(acc_conf);//将更新后的角速度倍率配置写入 MPU6050 的寄存器地址 0x1B
   Wire.endTransmission(true); //结束传输,true表示释放总线
}

(3)配置加速度

//配置加速度倍率
void ACCEL_CONFIG_SET(int f){
   Wire.beginTransmission(0x68); //开启MPU-6050的传输
   Wire.write(0x1C); //加速度倍率寄存器的地址
   Wire.requestFrom(0x68, 1, true); //先读出原配置
   unsigned char acc_conf = Wire.read();
   acc_conf = ((acc_conf & 0xE7) | (f << 3));
   Wire.write(acc_conf);
   Wire.endTransmission(true); //结束传输,true表示释放总线
}

(4)获取MPU数据

//获取MPU数据
void Get_Value(void){
   //获取各个轴分量数据
   Wire.beginTransmission(0x68); //开启MPU-6050的传输
   Wire.write(0x3B);
   Wire.requestFrom(0x68, 7 * 2, true);
   Wire.endTransmission(true);
   for (long i = 0; i < 7; ++i) {
      val_seven[i] = Wire.read() << 8 | Wire.read();
   }
   //数据换算
   val_seven[0] = (float)(val_seven[0] / 32768 * (2 ^ ACCEL_CONFIG) *G);//acc_x
   val_seven[1] = (float)(val_seven[1] / 32768 * (2 ^ ACCEL_CONFIG) * G);//acc_y
   val_seven[2] = (float)(val_seven[2] / 32768 * (2 ^ ACCEL_CONFIG) *G);//acc_z
   val_seven[3] = (float)(val_seven[3] / 340 + 36.53);//acc_z
   val_seven[4] = (float)(val_seven[4] / 32768 * (2 ^ GYRO_CONFIG) *250);//gyr_x
   val_seven[5] = (float)(val_seven[5] / 32768 * (2 ^ GYRO_CONFIG) *250);//gyr_y
   val_seven[6] = (float)(val_seven[6] / 32768 * (2 ^ GYRO_CONFIG) *250);//gyr_z
}

(5)全部代码汇总

//接线方式:VCC--5V、GND--GND、SCL--A5、SDA--A4、AD0--AD0引脚为地址选择引脚,悬空或者接GND,硬件地址为0x68,接VCC/高电平硬件地址为0x69   INT--中断引脚,如果用到可以接中端口,此处不接
#include 
#define ACCEL_CONFIG 1  //加速度倍率配置选项
#define GYRO_CONFIG 1   //角速度速度倍率配置选项
//(具体的倍率与具体的 MPU6050 模块和应用有关,在使用时需要根据实际情况进行设置和调整)
#define G 9.8   //重力加速度
float val_seven[7];
void MPU_START(void){//用于启动 MPU6050 传感器
   Wire.beginTransmission(0x68); //开启MPU6050的传输
   Wire.write(0x6B); //指定寄存器地址,0x68 是 MPU6050 的 I2C 地址
   Wire.write(0); //将 MPU6050 的寄存器 0x6B 写入 0,以启动 MPU6050
   Wire.endTransmission(true); //结束传输,true表示释放总线
}
//配置角速度倍率
void GYRO_CONFIG_SET(int f){   
   Wire.beginTransmission(0x68); //开启MPU-6050的传
   Wire.write(0x1B); //角速度倍率寄存器的地址
   Wire.requestFrom(0x68, 1, true); //从 MPU6050 的寄存器地址 0x1B 请求读取 1 个字节的数据,读出原来的配置
   unsigned char acc_conf = Wire.read();//将读取到的数据保存在变量 acc_conf 中。这个变量用于存储原配置的值
   acc_conf = ((acc_conf & 0xE7) | (f << 3));//对 acc_conf 进行位运算,以设置新的角速度倍率。通过 f 参数左移 3 位,并和原配置进行按位或操作,从而实现设置新的角速度倍率
   Wire.write(acc_conf);//将更新后的角速度倍率配置写入 MPU6050 的寄存器地址 0x1B
   Wire.endTransmission(true); //结束传输,true表示释放总线
}
//配置加速度倍率
void ACCEL_CONFIG_SET(int f){
   Wire.beginTransmission(0x68); //开启MPU-6050的传输
   Wire.write(0x1C); //加速度倍率寄存器的地址
   Wire.requestFrom(0x68, 1, true); //先读出原配置
   unsigned char acc_conf = Wire.read();
   acc_conf = ((acc_conf & 0xE7) | (f << 3));
   Wire.write(acc_conf);
   Wire.endTransmission(true); //结束传输,true表示释放总线
}
//获取MPU数据
void Get_Value(void){
   //获取各个轴分量数据
   Wire.beginTransmission(0x68); //开启MPU-6050的传输
   Wire.write(0x3B);
   Wire.requestFrom(0x68, 7 * 2, true);
   Wire.endTransmission(true);
   for (long i = 0; i < 7; ++i) {
      val_seven[i] = Wire.read() << 8 | Wire.read();
   }
   //数据换算
   val_seven[0] = (float)(val_seven[0] / 32768 * (2 ^ ACCEL_CONFIG) *G);//acc_x
   val_seven[1] = (float)(val_seven[1] / 32768 * (2 ^ ACCEL_CONFIG) * G);//acc_y
   val_seven[2] = (float)(val_seven[2] / 32768 * (2 ^ ACCEL_CONFIG) *G);//acc_z
   val_seven[3] = (float)(val_seven[3] / 340 + 36.53);//acc_z
   val_seven[4] = (float)(val_seven[4] / 32768 * (2 ^ GYRO_CONFIG) *250);//gyr_x
   val_seven[5] = (float)(val_seven[5] / 32768 * (2 ^ GYRO_CONFIG) *250);//gyr_y
   val_seven[6] = (float)(val_seven[6] / 32768 * (2 ^ GYRO_CONFIG) *250);//gyr_z
}
// The setup() function runs once each time the micro-controller starts
void setup(){
   Serial.begin(9600);
   Wire.begin();//以主机模式开启总线
   MPU_START();//启动MPU6050   
   GYRO_CONFIG_SET(0);//配置器件角速度倍率
   ACCEL_CONFIG_SET(0);//配置器件加速度倍率
}
// Add the main program code into the continuous loop() function
void loop(){
   Get_Value();
   Serial.print("acc_x:");
   Serial.print('\t');
   Serial.println(val_seven[0]);
   Serial.print("acc_y:");
   Serial.print('\t');
   Serial.println(val_seven[1]);
   Serial.print("acc_z:");
   Serial.print('\t');
   Serial.println(val_seven[2]);
   Serial.print("gyr_x:");
   Serial.print('\t');
   Serial.println(val_seven[4]);
   Serial.print("gyr_y:");
   Serial.print('\t');
   Serial.println(val_seven[5]);
   Serial.print("gyr_z:");
   Serial.print('\t');
   Serial.println(val_seven[6]);
   Serial.print("TEMP:");
   Serial.print('\t');
   Serial.println(val_seven[3]);
   delay(500);
}

4. 相关示例

(1)basic_readings

设置 MPU6050 加速度计的初始化配置,并在串口终端上输出相关信息

void setup(){  
  Serial.begin(115200);//初始化串口通信,设置波特率为 115200
  while (!Serial)    delay(10);//等待直到串口连接完成,以防止一些板子(如Arduino Zero、Leonardo等)在未连接串口时继续执行
  Serial.println("Adafruit MPU6050 test!"); 
  if (!mpu.begin()) {
    Serial.println("Failed to find MPU6050 chip");
    while (1)    delay(10);
  }//尝试初始化 MPU6050 加速度计。如果初始化失败,则在串口终端上输出,并进入无限循环
  Serial.println("MPU6050 Found!");
  mpu.setAccelerometerRange(MPU6050_RANGE_8_G);//设置加速度计的量程为 ±8G
  Serial.print("Accelerometer range set to: ");
  switch (mpu.getAccelerometerRange()){//检查并输出当前加速度计的量程设置
  case MPU6050_RANGE_2_G:
    Serial.println("+-2G");
    break;
  case MPU6050_RANGE_4_G:
    Serial.println("+-4G");
    break;
  case MPU6050_RANGE_8_G:
    Serial.println("+-8G");
    break;
  case MPU6050_RANGE_16_G:
    Serial.println("+-16G");
    break;
  }
  mpu.setGyroRange(MPU6050_RANGE_500_DEG);//设置陀螺仪的量程为 ±500°/s
  Serial.print("Gyro range set to: ");
  switch (mpu.getGyroRange()) {//检查并输出当前陀螺仪的量程设置
      case MPU6050_RANGE_250_DEG:
        Serial.println("+- 250 deg/s");
        break;
      case MPU6050_RANGE_500_DEG:
        Serial.println("+- 500 deg/s");
        break;
      case MPU6050_RANGE_1000_DEG:
        Serial.println("+- 1000 deg/s");
        break;
      case MPU6050_RANGE_2000_DEG:
        Serial.println("+- 2000 deg/s");
        break;
  }
  mpu.setFilterBandwidth(MPU6050_BAND_21_HZ);//设置滤波器的带宽为 21 Hz
  Serial.print("Filter bandwidth set to: ");
  switch (mpu.getFilterBandwidth()) {//检查并输出当前陀螺仪滤波器的带宽设置
      case MPU6050_BAND_260_HZ: 
        Serial.println("260 Hz");
        break;
      case MPU6050_BAND_184_HZ:
        Serial.println("184 Hz");
        break;
      case MPU6050_BAND_94_HZ:
        Serial.println("94 Hz");
        break;
      case MPU6050_BAND_44_HZ:
        Serial.println("44 Hz");
        break;
      case MPU6050_BAND_21_HZ:
        Serial.println("21 Hz");
        break;
      case MPU6050_BAND_10_HZ:
        Serial.println("10 Hz");
        break;
      case MPU6050_BAND_5_HZ:
        Serial.println("5 Hz");
        break;
  }
  Serial.println("");
  delay(100);
}


void loop() {
  sensors_event_t a, g, temp;//声明三个 sensors_event_t 类型的变量 a、g 和 temp,用于存储加速度、角速度和温度的传感器事件数据
  mpu.getEvent(&a, &g, &temp);//通过调用 getEvent() 方法,获取最新的传感器事件数据,并将其保存到对应的变量中。
  Serial.print("Acceleration X: ");
  Serial.print(a.acceleration.x);
  Serial.print(", Y: ");
  Serial.print(a.acceleration.y);
  Serial.print(", Z: ");
  Serial.print(a.acceleration.z);
  Serial.println(" m/s^2");

  Serial.print("Rotation X: ");
  Serial.print(g.gyro.x);
  Serial.print(", Y: ");
  Serial.print(g.gyro.y);
  Serial.print(", Z: ");
  Serial.print(g.gyro.z);
  Serial.println(" rad/s");

  Serial.print("Temperature: ");
  Serial.print(temp.temperature);
  Serial.println(" degC");
  Serial.println("");
  delay(500);
}

(2)motion_detection

用于检测 MPU6050 模块的运动中断,并在检测到运动时打印加速度和角速度数据。

void setup(void) {
  Serial.begin(115200);
  while (!Serial)    delay(10); // 等待串口打开,适用于 Zero、Leonardo 等板型
  Serial.println("Adafruit MPU6050 test!");
  // 尝试初始化 MPU6050
  if (!mpu.begin()) {
    Serial.println("Failed to find MPU6050 chip");
    while (1)    delay(10);
  }
  Serial.println("MPU6050 Found!");
  // 设置运动检测
  mpu.setHighPassFilter(MPU6050_HIGHPASS_0_63_HZ);
  mpu.setMotionDetectionThreshold(1);
  mpu.setMotionDetectionDuration(20);
  mpu.setInterruptPinLatch(true);  // 保持中断触发状态,重新初始化时将关闭
  mpu.setInterruptPinPolarity(true);
  mpu.setMotionInterrupt(true);
  Serial.println("");
  delay(100);
}

void loop() {
  if (mpu.getMotionInterruptStatus()) {
    /* 获取新的传感器事件数据 */
    sensors_event_t a, g, temp;
    mpu.getEvent(&a, &g, &temp);
    /* 打印数值 */
    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(10);
}

(3)mpu6050_oled

通过 MPU6050 传感器获取加速度和角速度数据,并通过 SSD1306 OLED 显示屏显示数据

//导入库函数
#include 
#include 
#include 
//创建对象
Adafruit_MPU6050 mpu;
Adafruit_SSD1306 display = Adafruit_SSD1306(128, 32, &Wire);
void setup() {
  Serial.begin(115200);
  while (!Serial);
  Serial.println("MPU6050 OLED demo");
  if (!mpu.begin()) {
    Serial.println("Sensor init failed");
    while (1)    yield();
  }
  Serial.println("Found a MPU-6050 sensor");
//设置 SSD1306 OLED 显示屏的相关参数
  if (!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) {
    Serial.println(F("SSD1306 allocation failed"));
    for (;;)
      ; 
  }
  display.display();
  delay(500); // Pause for 2 seconds
  display.setTextSize(1);
  display.setTextColor(WHITE);
  display.setRotation(0);
}
void loop() {
//获取 MPU6050 的加速度和角速度数据,并打印到串口和显示屏上
  sensors_event_t a, g, temp;
  mpu.getEvent(&a, &g, &temp);
  display.clearDisplay();
  display.setCursor(0, 0);

  Serial.print("Accelerometer ");
  Serial.print("X: ");
  Serial.print(a.acceleration.x, 1);
  Serial.print(" m/s^2, ");
  Serial.print("Y: ");
  Serial.print(a.acceleration.y, 1);
  Serial.print(" m/s^2, ");
  Serial.print("Z: ");
  Serial.print(a.acceleration.z, 1);
  Serial.println(" m/s^2");
  display.println("Accelerometer - m/s^2");
  display.print(a.acceleration.x, 1);
  display.print(", ");
  display.print(a.acceleration.y, 1);
  display.print(", ");
  display.print(a.acceleration.z, 1);
  display.println("");

  Serial.print("Gyroscope ");
  Serial.print("X: ");
  Serial.print(g.gyro.x, 1);
  Serial.print(" rps, ");
  Serial.print("Y: ");
  Serial.print(g.gyro.y, 1);
  Serial.print(" rps, ");
  Serial.print("Z: ");
  Serial.print(g.gyro.z, 1);
  Serial.println(" rps");

  display.println("Gyroscope - rps");
  display.print(g.gyro.x, 1);
  display.print(", ");
  display.print(g.gyro.y, 1);
  display.print(", ");
  display.print(g.gyro.z, 1);
  display.println("");

  display.display();
  delay(100);
}

(4)mpu6050_unifiedsensors

#include 
Adafruit_MPU6050 mpu;
Adafruit_Sensor *mpu_temp, *mpu_accel, *mpu_gyro;
void setup(void) {
  Serial.begin(115200);
  while (!Serial)    delay(10);
  Serial.println("Adafruit MPU6050 test!");
  if (!mpu.begin()) {
    Serial.println("Failed to find MPU6050 chip");
    while (1) delay(10);
  }
  Serial.println("MPU6050 Found!");
  mpu_temp = mpu.getTemperatureSensor();
  mpu_temp->printSensorDetails();
  mpu_accel = mpu.getAccelerometerSensor();
  mpu_accel->printSensorDetails();
  mpu_gyro = mpu.getGyroSensor();
  mpu_gyro->printSensorDetails();
}

void loop() {
  sensors_event_t accel;
  sensors_event_t gyro;
  sensors_event_t temp;
  mpu_temp->getEvent(&temp);
  mpu_accel->getEvent(&accel);
  mpu_gyro->getEvent(&gyro);

  Serial.print("\t\tTemperature ");
  Serial.print(temp.temperature);
  Serial.println(" deg C");

  Serial.print("\t\tAccel X: ");
  Serial.print(accel.acceleration.x);
  Serial.print(" \tY: ");
  Serial.print(accel.acceleration.y);
  Serial.print(" \tZ: ");
  Serial.print(accel.acceleration.z);
  Serial.println(" m/s^2 ");

  Serial.print("\t\tGyro X: ");
  Serial.print(gyro.gyro.x);
  Serial.print(" \tY: ");
  Serial.print(gyro.gyro.y);
  Serial.print(" \tZ: ");
  Serial.print(gyro.gyro.z);
  Serial.println(" radians/s ");
  Serial.println();

  delay(100);
}

你可能感兴趣的:(Arduino,嵌入式硬件,Arduino)