MPU6050的Arduino实现

news/2024/11/19 9:38:41/

Arduino有多种通信方式,每一种通信方式都有相对应的类库来支持:

1)硬件串口通信——HardwareSerial 类库

2)软件模拟串口通信——SoftwareSerial 类库

3)IIC总线的使用——Wire 类库

4)SPI总线的使用——SPI 类库

 

MPU6050的数据接口用的是I2C总线协议,因此我们需要Wire类库的帮助来实现Arduino与MPU6050之间的通信。

MPU6050的数据写入和读出均通过其芯片内部的寄存器实现,这些寄存器的地址都是1个字节,也就是8位的寻址空间,其寄存器的详细列表说明书请点击下载:

https://www.olimex.com/Products/Modules/Sensors/MOD-MPU6050/resources/RM-MPU-60xxA_rev_4.pdf

使用Arduino的Wire类库来学习MPU6050与arduino的IIC通信,比直接学习MPU6050与单片机或其他更高级芯片的通信要容易许多。在arduino平台上完成MPU6050的测试后,应该转而在其他平台上使用MPU6050。当然能够实现设备通信只是迈出了其中的一小步,更重要的是在获得惯性测量单元的数据后,会对数据进行处理。最后,能够使用MPU6050来做一些小项目是最好的,例如平衡车、四轴飞行器等等。
 

一、了解 wire.h

1.库包含的函数:

    1) Wire.begin()和Wire.begin(address):初始化IIC连接。无参数,设备以主机模式加入IIC总线;写参数,设备以从机模式加入IIC总线,address为一个7位的从机地址。语法为:

    begin():           

    begin(address): 

    返回值:none

   

    2) Wire.requestFrom():主机向从机发送数据请求信号(n*一个字节)。使用后,从机可以使用onRequest()注册一个事件以响应主机请求。随后,数据可以被主设备用available()和read()函数接收。语法为:

    Wire.requestFrom(address, quantity):设备(从机)的地址、请求的字节数

    Wire.requestFrom(address, quantity, stop):stop参数为boolean型值,值为true则发送停止命令,释放IIC总线;值为false则发送重新开始信息,并继续保持IIC总线的有效连接。

    返回值:none

 

    3) Wire.beginTransmission():设定传输数据到指定地址的从机设备。随后可以使用write()函数发送数据,并搭配endTransmission():函数结束数据传输。

    语法:wire.beginTransmission(address):

    返回值:none

 

    4) Wire.endTransmission():结束一个由beginTransmission()开始的并且由write()排列的从机的传输。语法为:

    Wire.endTransmission()

    Wire.endTransmission(stop):stop为biilean型值,值为true(没有填写stop参数时,等效使用true)则发送一个停止信息;值为false则发送一个重新开始信息,并继续保持IIC总线的有效连接。

    返回值:0 成功   1 数据溢出   2 发送addtess时从机接受到NACK   3 发送数据时接受到NACK   4 其他错误

 

    5) Wire.write():向从机发送数据(双向?主机状态:主机将要发送的数据加入发送队列;从机状态:从机发送数据至发起请求的主机)。语法为:

    Wire.write(value):value 要发送的数值(以单字节发送)

    Wire.write(string):string 字符组的指针(以一系列字节发送)

    Wire.write(data, length):data 一个字节数组(以字节形式发送数组);length 传输的字节数

    返回值:byte型值,返回输入的字节数。

 

    6) Wire.available():返回接收到的字节数

    在主机中,一般用于主机发送数据请求后;在从机中,一般用于数据接收事件。语法为:

    Wire.available()  无参数

    返回值:byte型值,返回输入的字节数。

 

    7) Wire.read():读取1B的数据

    在主机中,使用requestFrom()函数发送数据请求信号后,需要使用read()函数来获取数据;在从机中需要使用read()读取主机发送来的数据。语法为:

    Wire.read()  无参数

    char c = Wire.read():以字符串形式接收数据(将数据作为字符接收)

    int x = Wire.read():以整型形式接收数据

    返回值:读到的字节数据

 

    8) Wire.onReceive():在从机端注册一个事件,当从机收到主机发送的数据时即被触发。语法为:

    Wire.onReceive(handler):handler 当从机接收到数据时可被触发的事件。该事件带有一个int型参数(从主机读到的字节数)且没有返回值,如 void myHandler(int numBytes)

    返回值:none

 

    9) Wire.onRequest():注册一个事件,当从机接收到主机数据请求时即被触发

    Wire.onRequest(handler):handler  可被触发的事件。该事件不带参数和返回值,如 void myHandler() 。

    返回值:none

 

二、关于MPU6050:

1.关于输出精度:

    以MPU6050加速度测量值为例:量程是±8g时,测量精度是4096LSB/g,

    LSB的意思是最小有效位,为数字输出方式下使用;

    一般我们可以用mg/LSB来表示G-Sensor灵敏度,例如:mpu6050输出的位数为16位(2的16次方共65536个LSB)对应满量程,当量程为±2g时对应灵敏度就为4g/65536LSB=0.06103515625mg/LSB,取倒数为16384LSB/g。所以我们可以看到mpu605X寄存器手册中的accelerometers' sensitivity per LSB in ACCEL_xOUT:

    因为mpu6050只能16位输出,所以测量范围越大,对应精度就越低。上面表格的数据存在一个规律,即:

    Full Scalse Range * LSB Sensitivity = 32768

(参考:http://www.geek-workshop.com/thread-9146-1-1.html)

 

三、基础使用:

以下实例实现 Arduino uno 与 MPU6050 的 IIC 通信,并通过 Arduino 与 PC 机的串口通讯将 MPU6050 的测量值打印在Arduino IDE 的串口监视器上。实例中未使用中断功能。读取的数据只经过单位的转换,未做其他数据处理(如果要应用在项目上,可能要对原始数据进行滤波处理、数学演算等,才能给程序使用。)

//连线方法
//MPU-UNO
//VCC-5V
//GND-GND
//SCL-A5
//SDA-A4
//ADO-GND
//未使用中断功能,即没有做 INT-digital pin 2 (interrupt pin 0) 这样的接线//参考手册:MPU-6000 and MPU-6050 Register Map and Descriptions Revision 4.2#include <Wire.h>long accelX, accelY, accelZ;      // 定义为全局变量,可直接在函数内部使用
float gForceX, gForceY, gForceZ;long gyroX, gyroY, gyroZ;
float rotX, rotY, rotZ;void setup() {Serial.begin(9600);Wire.begin();setupMPU();
}void loop() {recordAccelRegisters();recordGyroRegisters();printData();delay(100);
}void setupMPU(){// REGISTER 0x6B/REGISTER 107:Power Management 1Wire.beginTransmission(0b1101000); //This is the I2C address of the MPU (b1101000/b1101001 for AC0 low/high datasheet Sec. 9.2)Wire.write(0x6B); //Accessing the register 6B/107 - Power Management (Sec. 4.30) Wire.write(0b00000000); //Setting SLEEP register to 0, using the internal 8 Mhz oscillatorWire.endTransmission();// REGISTER 0x1b/REGISTER 27:Gyroscope ConfigurationWire.beginTransmission(0b1101000); //I2C address of the MPUWire.write(0x1B); //Accessing the register 1B - Gyroscope Configuration (Sec. 4.4) Wire.write(0x00000000); //Setting the gyro to full scale +/- 250deg./s (转化为rpm:250/360 * 60 = 41.67rpm) 最高可以转化为2000deg./s Wire.endTransmission();// REGISTER 0x1C/REGISTER 28:ACCELEROMETER CONFIGURATIONWire.beginTransmission(0b1101000); //I2C address of the MPUWire.write(0x1C); //Accessing the register 1C - Acccelerometer Configuration (Sec. 4.5) Wire.write(0b00000000); //Setting the accel to +/- 2g(if choose +/- 16g,the value would be 0b00011000)Wire.endTransmission(); 
}void recordAccelRegisters() {// REGISTER 0x3B~0x40/REGISTER 59~64Wire.beginTransmission(0b1101000); //I2C address of the MPUWire.write(0x3B); //Starting register for Accel ReadingsWire.endTransmission();Wire.requestFrom(0b1101000,6); //Request Accel Registers (3B - 40)// 使用了左移<<和位运算|。Wire.read()一次读取1bytes,并在下一次调用时自动读取下一个地址的数据while(Wire.available() < 6);  // Waiting for all the 6 bytes data to be sent from the slave machine (必须等待所有数据存储到缓冲区后才能读取) accelX = Wire.read()<<8|Wire.read(); //Store first two bytes into accelX (自动存储为定义的long型值)accelY = Wire.read()<<8|Wire.read(); //Store middle two bytes into accelYaccelZ = Wire.read()<<8|Wire.read(); //Store last two bytes into accelZprocessAccelData();
}void processAccelData(){gForceX = accelX / 16384.0;     //float = long / floatgForceY = accelY / 16384.0; gForceZ = accelZ / 16384.0;
}void recordGyroRegisters() {// REGISTER 0x43~0x48/REGISTER 67~72Wire.beginTransmission(0b1101000); //I2C address of the MPUWire.write(0x43); //Starting register for Gyro ReadingsWire.endTransmission();Wire.requestFrom(0b1101000,6); //Request Gyro Registers (43 ~ 48)while(Wire.available() < 6);gyroX = Wire.read()<<8|Wire.read(); //Store first two bytes into accelXgyroY = Wire.read()<<8|Wire.read(); //Store middle two bytes into accelYgyroZ = Wire.read()<<8|Wire.read(); //Store last two bytes into accelZprocessGyroData();
}void processGyroData() {rotX = gyroX / 131.0;rotY = gyroY / 131.0; rotZ = gyroZ / 131.0;
}void printData() {Serial.print("Gyro (deg)");Serial.print(" X=");Serial.print(rotX);Serial.print(" Y=");Serial.print(rotY);Serial.print(" Z=");Serial.print(rotZ);Serial.print(" Accel (g)");Serial.print(" X=");Serial.print(gForceX);Serial.print(" Y=");Serial.print(gForceY);Serial.print(" Z=");Serial.println(gForceZ);
}

代码中相关设置的依据以及使用的寄存器: 
1)MPU6050的IIC地址:

2)电源管理寄存器:

3)陀螺仪配置:

4)加速度计配置:

5)加速度计测量值:

6)陀螺仪测量值:

三、简单应用:
 


http://www.ppmy.cn/news/242949.html

相关文章

vite-vue3

vite vue3 使用文档(单页应用-超简单教程) 这些是使用 Vite Vue 3 的基本步骤和概念&#xff0c;希望对你有所帮助&#xff01;请记得在实际开发中参考相关的官方文档和示例以获取更详细的信息。以下是使用 Vite Vue 3 的简要使用文档&#xff1a; 1. 安装 Vite 在终端中…

ArduinoMega2560 引脚表

前言学习修改Arduino原理图的时候读不懂引脚图。现写文如下滤清引脚关系。 ArduinoMega2560采用的是ATMEGA2560-16AU芯片。芯片内部有自己对引脚的一套编号&#xff0c;从1开始也就是PG5引脚。而Arduino板子对芯片引脚编号进行了重排&#xff0c;也就是映射&#xff0c;分为Di…

MPU6050工作原理及STM32控制MPU6050

一简介: 1.要想知道MPU6050工作原理&#xff0c;得先了解下面俩个传感器&#xff1a; ①陀螺仪传感器&#xff1a; 陀螺仪的原理就是&#xff0c;一个旋转物体的旋转轴所指的方向在不受外力影响时&#xff0c;是不会改变的。人们根据这个道理&#xff0c;用它来保持方向。然后…

IIC通讯读取MPU6050

江科大自化协学习记录&#xff0c;本实验利用IIC读取MPU6050数值&#xff0c;并且在OLED屏上显示 代码在最后面&#xff0c;笔者水平一般&#xff0c;各位凑合着看。 首先是OLED显示的代码&#xff0c;底层驱动来自江科大自化协。 链接就放在这里了&#xff0c;喜欢的自取啦&am…

国内BGP电信高防御大带宽服务器哪里的比较好

镇江电信 双L5630(8核16线程) 16G 240G ssd 20M 独享或100M共 50G防御 1ip 首月199 双L5630(8核16线程) 24G 240G ssd 20M 独享或100M共 50G防御 1ip 首月299 双L5630(8核16线程) 32G 240G ssd 20M 独享或100M共 50G防御 1ip …

如何在线压缩png图片?png压缩图片大小的方法介绍

压缩PNG图片大小的优点 随着数字化时代的发展&#xff0c;PNG格式已成为一种常见的图片格式。然而&#xff0c;由于高分辨率、高色深等原因&#xff0c;PNG图片通常具有较大的文件体积&#xff0c;导致在传输、存储和网页加载等方面会产生不必要的负担。因此&#xff0c;对于需…

l5630鲁大师跑分_拆解木质外壳三角形主机箱:搭载赛扬N3450处理器鲁大师跑分2.6万...

配置为赛扬N3450四核1.1Ghz&#xff0c;板载8g内存&#xff0c;64G EMMC储存。另有个M2口的128G固态(可扩展&#xff0c;但性价比不高)接口为3个usb3.0&#xff0c;一个千兆口RJ45&#xff0c;一个HDMI&#xff0c;有蓝牙和无线。 鲁大师跑个分26378 拆机前需要把两边的贴纸去除…

什么AC+AP组网?什么是mesh组网?

一、什么是ACAP组网&#xff1f; ACAP组网是一种基于集中式管理的无线局域网&#xff08;WLAN&#xff09;组网架构&#xff0c;主要由AC&#xff08;Access Controller&#xff09;和多个AP&#xff08;Access Point&#xff09;组成。AC作为网络管理中心&#xff0c;负责控制…