登录  | 立即注册

游客您好!登录后享受更多精彩

扫一扫,访问微社区

QQ登录

只需一步,快速开始

开启左侧

[寒假笔记] mpu6050的使用及平衡车原理

[复制链接]
发表于 2018-2-28 11:22:07 | 显示全部楼层 |阅读模式
学习笔记
学习科目: 51单片机
学习安排: 熟练设置寄存器
开始时间: 2018-02-20
结束时间: 2018-02-28
  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轴,如图我买的己经标示出来了。
112205dxq4cc3lq1ec7l78.jpg

首先是要获得数据,然后要显示出来,此模块用的是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控制,只有平衡一个功能,不能转向,不能前进后退,不能遥控,但是以后会改进的。

112206ym33oif3lv5zd1j5.jpg
好懒~~不想说~~~
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

Powered by Discuz! X3.4

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表