mpu6050是一个三轴加速度的模块,可以用来三个坐标轴的加速度及角速度。说实话,它的内部原理没看懂,但是我觉得也不需要了解太深入能够用好就可以了。
近日逛百度的时候看到了两轮平衡车,我觉得比避障车有意思,就从淘宝上买了个mpu6050的模块,其实挺便宜的只需4.6元每片。
有了这个想法就立刻开动,模块不久就到了,我把我之前做的避障小车给拆了,剩下两个轮子,然后从那商店要来了一些资料,开始学习它的使用。
mpu6050模块的角速度满量程有四个可以选择,分别为±250、±500、±1000与±2000°/sec (dps),加速器测范围为±2g、±4g±8g与±16g。这些东西的意思是,举个例子现在重力加速度为2g那么如果它来测量的话设置量程为±2g,那么输出的数据是32768或是
-32768。2g对应32768,也就是每个数对应2/32768g
。显然,倍率越低精度越好,倍率越高表示的范围越大,这要根据具体的应用来设定。
模块三个轴的指向,芯片有字一面朝向自己,前方为y轴右方为x轴上方为z轴,如图我买的己经标示出来了。
首先是要获得数据,然后要显示出来,此模块用的是I2C通信,这个调用前面写好的头文件,显示用数码管也调用写好的头文件,关键在于寄存器的设置,以及数据的处理。它寄存器头文件如下。
#ifndef _MPU6050_H_
#define _MPU6050_H_
#include <STC12C5A60S2.H>
#include "iic.h"
#define uchar unsigned char
#define uint unsigned int
/*mpu6050内部地址*/
#define SMPLRT_DIV 0x19 //陀螺仪采样率 典型值0x07(125hz)
#define CONFIG 0x1A //低通录波频率 典型值0x06(5hz)
#define GYRO_CONFIG 0x1B //陀螺仪自检及测量范围 典型值0x18(不自检 2000deg/s)
#define ACCEL_CONFIG 0x1C //加速度计自检测量范围及高通滤波频率 典型值0x01(不自检 2g 5hz)
#define ACCEL_XOUT_H 0x3B
#define ACCEL_XOUT_L 0x3C
#define ACCEL_YOUT_H 0x3D
#define ACCEL_YOUT_L 0x3E
#define ACCEL_ZOUT_H 0x3F
#define ACCEL_ZOUT_L 0x40
#define TEMP_OUT_H 0x41
#define TEMP_OUT_L 0x42
#define GYRO_XOUT_H 0x43
#define GYRO_XOUT_L 0x44
#define GYRO_YOUT_H 0x45
#define GYRO_YOUT_L 0x46
#define GYRO_ZOUT_H 0x47
#define GYRO_ZOUT_L 0x48
#define PWR_MGMT_1 0x6B //电源管理典型值0x00(正常启用)
#define WHO_AM_I 0x75 //iic地址寄存器(默认数值0x68 只读)
#define SlaveAddress 0xD0 //iic写入时的地址字节数据 +1为读取
void init_mpu();
int get_data(uchar address);
#endif
它的初始化程序如下。
#include "mpu6050.h"
void init_mpu()
{
write_date(PWR_MGMT_1, 0x00);
write_date(SMPLRT_DIV, 0x07);
write_date(CONFIG, 0x06);
write_date(GYRO_CONFIG, 0x18);
write_date(ACCEL_CONFIG, 0x01);
}
int get_data(uchar address)
{
uchar h,l;
h=read_date(address);
l=read_date(address+1);
return((h<<8)+l);
}
我设置的是2g,2000/s,从百度上查知它的输出会有很大的噪音,需要用卡尔曼算法滤波,但是我看了挺久也没有看懂,考虑到做一个平衡车小车不需太高精度,我就没有去深入研究。
以下是我写的显示x抽倾斜角的主程序
#include <STC12C5A60S2.H>
#include "math.h"
#include "mpu6050.h"
#include "displa.h"
void main()
{
int t=0;
init_mpu();
while(1)
{
t=get_data(ACCEL_XOUT_H);
t=abs(t);
t=(5730*asin(t/16056.3)+0.5);
display(t);
}
}
其中得到的数据除以16056.6是转换为重力加速度,本应除以32768/2的但是误差太大了,0.5是为了让数据四舍五入,求反正弦是利用重力加速度的分量转换为倾斜角,乘以5730是化弧度为角度。显示跳动很快,数据不稳定,而且最大角只能达到86度。
因为芯片已经调试好装上去了,所以没有显示的照片了。
然后就是平衡车的制作,到现在我还没有调试好。那个轮子太不精密了,用手拧会轻微转动很难调,平衡车上把电池放在顶上提高重心,使得更易平衡。
平衡车调节原理很简单,根据不同的倾斜角调节轮子转速,倾斜角与转速成线性关系,利用PWM来调速,频率控制在50HZ,频率太高感抗大,转速反而慢,频率太低抖动比较严重,用H桥驱动马达。另外测得某个轴加速度后要减去它的角速度,因为小车一直在动,测量的加速度分量是加上了角速度的,不减去的话转换出的角度不准确。
#include <STC12C5A60S2.H>
#include "math.h"
#include "mpu6050.h"
#include "iic.h"
sbit moter1=P0^0;
sbit moter2=P0^1;
void delay(uint i)
{
while(i--);
}
void balance()
{
bit turn_flag;
uint i,low,cycle=16000;//cycle调节频率
high=high*10; //调节占空比
low=cycle-high;
for(i=0;i<5;i++)
{
if(turn_flag==1)
{
moter1=1;
moter2=0;
}
else
{
moter1=0;
moter2=1;
}
delay(high+5000);//刻服静摩擦
moter1=0;
moter2=0;
delay(low);
}
t=get_data(ACCEL_XOUT_H);
t=(5730*asin(t/16056.3)+0.5);
if(t>=0)
{
t=t;
turn_flag=1;
}
else
{
t=-t;
turn_flag=0;
}
}
void main()
{
init_mpu();
while(1)
{
balance();
}
程序简陋没有用PCA来作PWM控制,也没有卡尔曼滤波,更没有PID控制,只有平衡一个功能,不能转向,不能前进后退,不能遥控,但是以后会改进的。
|