1、摘要MPU6050是一种非常流行的空间运动传感器芯片,可以获取器件当前的三个加速度分量和三个旋转角速度。由于其体积小巧,功能强大,精度较高,不仅被广泛应用于工业,同时也是航模爱好者的神器,被安装在各类飞行器上驰骋蓝天。随着Arduino开发板的普及,许多朋友希望能够自己制作基于MPU6050的控制系统,但由于缺乏专业知识而难以上手。此外,MPU6050的数据是有较大噪音的,若不进行滤波会对整个控制系统的精准确带来严重影响。MPU6050芯片内自带了一个数据处理子模块DMP,已经内置了滤波算法,在许多应用中使用DMP输出的数据已经能够很好的满足要求。关于如何获取DMP的输出数据,我将在以后的文章
2、中介绍。本文将直接面对原始测量数据,从连线、芯片通信开始一步一步教你如何利用Arduino获取MPU6050的数据并进行卡尔曼滤波,最终获得稳定的系统运动状态。一、Arduino与MPU-6050的通信为避免纠缠于电路细节,我们直接使用集成的MPU6050模块。MPU6050的数据接口用的是I2C总线协议,因此我们需要Wire程序库的帮助来实现Arduino与MPU6050之间的通信。请先确认你的Arduino编程环境中已安装Wire库。Wire库的官方文档(http:/www.arduino.cc/en/Reference/Wire)中指出:在UNO板子上,SDA接口对应的是A4引脚,SCL
3、对应的是A5引脚。MPU6050需要5V的电源,可由UNO板直接供电。按照下图连线。(紫色线是中断线,这里用不到,可以不接)MPU6050的数据写入和读出均通过其芯片内部的寄存器实现,这些寄存器的地址都是1个字节,也就是8位的寻址空间,其寄存器的详细列表说明书请点击下载:https:/ 将数据写入MPU-6050在每次向器件写入数据前要先打开Wire的传输模式,并指定器件的总线地址,MPU6050的总线地址是0x68(AD0引脚为高电平时地址为0x69)。然后写入一个字节的寄存器起始地址,再写入任意长度的数据。这些数据将被连续地写入到指定的起始地址中,超过当前寄存器长度的将写入到后面地址的寄存
4、器中。写入完成后关闭Wire的传输模式。下面的示例代码是向MPU6050的0x6B寄存器写入一个字节0。Wire.beginTransmission(0x68); /开启MPU6050的传输Wire.write(0x6B); /指定寄存器地址Wire.write(0); /写入一个字节的数据Wire.endTransmission(true); /结束传输,true表示释放总线1.2 从MPU-6050读出数据读出和写入一样,要先打开Wire的传输模式,然后写一个字节的寄存器起始地址。接下来将指定地址的数据读到Wire库的缓存中,并关闭传输模式。最后从缓存中读取数据。下面的示例代码是从MPU6
5、050的0x3B寄存器开始读取2个字节的数据:Wire.beginTransmission(0x68); /开启MPU6050的传输Wire.write(0x3B); /指定寄存器地址Wire.requestFrom(0x68, 2, true); /将输据读出到缓存Wire.endTransmission(true); /关闭传输模式int val = Wire.read() 0)fRoll=-fRoll;floatfPitch=GetPitch(realVals,fNorm);g12g12g41D1g31C7g33g4Cg57g46g4Bg4002if(realVals00)fPitch=
6、-fPitch;g12g12g41D1g31C7g454g2151g237Bg47FFg2CB4g1C26g4C24g4C24g4CC4g47g57g2C8g515g3002g46Ag985g57DunsignedlongnCurTime=micros();floatdt=(double)(nCurTime-nLastTime)/1000000.0;g12g12g1229g35g52g4Fg4Fg4002gABCg33g4Cg57g46g4Bg4002g460Bg3E7Cg991g1244g1D2Cg2514g2312floatfNewRoll=kalmanRoll.getAngle(fRol
7、l,realVals4,dt);floatfNewPitch=kalmanPitch.getAngle(fPitch,realVals5,dt);g12g12g440Fg199Eg2514g2312g66Cg41D1g31C7g4002g14D6g464FfloatfRollRate=(fNewRoll-fLastRoll)/dt;floatfPitchRate=(fNewPitch-fLastPitch)/dt;g12g12g1D24g1BE0g35g52g4Fg4Fg4002gABCg33g4Cg57g46g4Bg4002fLastRoll=fNewRoll;fLastPitch=fNew
8、Pitch;g12g12g1D24g1BE0g1D5Cg2151g237Bg2CB4g1C26g4C24nLastTime=nCurTime;g12g12gA41g462gA13g1883g9A0g45C3g82Ag35g52g4Fg4Fg4002gABCg33g4Cg57g46g4Bg4002g2C8g4600g3E7Cg1C26gD58g24g55g47g58g4Cg51g52g2CB4g462gA13g2D01g3FF6gC98g45Dg1E15g2D3BSerial.print(“Roll:“);Serial.print(fNewRoll);Serial.print();Serial.
9、print(fRollRate);Serial.print(“),tPitch:“);Serial.print(fNewPitch);Serial.print();Serial.print(fPitchRate);Serial.print(“)n“);delay(10);gA41g30g33g38g19g13g18g13g7C9g795g430g45Ag1187g38B2g2CB4g1BA0g199Eg12g12g1937g11CAg11F4g1188gC98gD60gD70g43Eg430g45Ag1187g38B2g2CB4g66CvoidWriteMPUReg(intnReg,unsig
10、nedcharnVal)Wire.beginTransmission(MPU);Wire.write(nReg);Wire.write(nVal);Wire.endTransmission(true);g12g12g4FEg30g33g38g19g13g18g13g422Bg82Ag430g45Ag1187g38B2g2CB4g1BA0g199Eg12g12g1937g11CAg11F4g1188gC98gD60gD70g2C8g4604gD0Eg422Bg82Ag2CB4g66CunsignedcharReadMPUReg(intnReg)Wire.beginTransmission(MPU
11、);Wire.write(nReg);Wire.requestFrom(MPU,1,true);Wire.endTransmission(true);returnWire.read();g12g12g4FEg30g33g38g19g13g18g13g422Bg82Ag8D0g464Fg14D6g41D1g439g45Ag836g47FFg1C3g2459g14D6gABCg439g45Ag4002g464Fg14D6g41D1g12g12g60Dg1188gD58g1937g11CAg2CB4g1BA0g34F4g45DvoidReadAccGyr(int*pVals)Wire.beginTr
12、ansmission(MPU);Wire.write(0x3B);Wire.requestFrom(MPU,nValCnt*2,true);Wire.endTransmission(true);for(longi=0;inValCnt;+i)pValsi=Wire.read()8|Wire.read();g12g12g1229gF57g47FFg422Bg1BA0g460Bg3E7Cg350Fg41D1g2C8g1E51g7F6g14A3gD77g67Fg302Bg47FFvoidCalibration()floatvalSums7=0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,
13、0.0;g12g12g778g2272gABCfor(inti=0;inCalibTimes;+i)intmpuValsnValCnt;ReadAccGyr(mpuVals);for(intj=0;jnValCnt;+j)valSumsj+=mpuValsj;g12g12g7BDg2272g14A3gD77for(inti=0;inValCnt;+i)calibDatai=int(valSumsi/nCalibTimes);calibData2+=16384;g12g12g41EEg38DFg2877g3Dg45A4g3106g2D24gA41g43Bg2C8g41EEg11CAg4D89g1
14、631g1415g58Cg26E9g1C4g12g12g31C7g15C7g35g52g4Fg4Fg4002g1C4g31C7g2305g3FF1g1BB7g1E93g1C4floatGetRoll(float*pRealVals,floatfNorm)floatfNormXZ=sqrt(pRealVals0*pRealVals0+pRealVals2*pRealVals2);floatfCos=fNormXZ/fNorm;returnacos(fCos)*fRad2Deg;g31C7g15C7g33g4Cg57g46g4Bg4002g1C4g31C7g2305g3FF1g1BB7g1E93g
15、1C4floatGetPitch(float*pRealVals,floatfNorm)floatfNormYZ=sqrt(pRealVals1*pRealVals1+pRealVals2*pRealVals2);floatfCos=fNormYZ/fNorm;returnacos(fCos)*fRad2Deg;g1229g422Bg1BA0g460Bg3E7Cg34D0g2193g2C8g23B8g4C94g67Fg302Bg2C8g14A6g459Cg1992g46Ag2899g2A36g47FFg1C4g79Cg153Fg3FF1g1BB7g1E93g1C4voidRectify(int*pReadout,float*pRealVals)for(inti=0;i3;+i)pRealValsi=(float)(pReadouti-calibDatai)/16384.0f;pRealVals3=pReadout3/340.0f+36.53;for(inti=4;i7;+i)pRealValsi=(float)(pReadouti-calibDatai)/131.0f;本文为Devymex于知乎原创首发,未经授权严禁转载,发现必究,欢迎举报,谢谢!授权知乎日报转载,授权非营利性的公益机构转载,一般营利性机构/平台非特殊情况不予授权。