onekey

专注.NET技术
  博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

MPU9250九轴陀螺仪--读接口数据

Posted on 2019-03-18 17:51  onekey  阅读(3404)  评论(0编辑  收藏  举报

1.使用i2c链接到树莓派的scl , sda 接口vcc给3v引脚,gnd接树莓派gnd就ok。  

2.要操作mpu必须使用mpu的寄存器实现对参数的设定以及读取,取官方下载资料看了一下,在github上找了一个python代码,运行不了bug太多了,然后精简了一下。终于能读出数据了,读出来的数据都是6个字节的,后来发现这哥们用python 读取mpu没有做字节合并,重写了一下,后来发现数据都是整数,不管我怎么旋转数字都是正的,看了网上的一片文章说寄存器度出来的是一个无符号整数。后来想了半天,用手机下了一个陀螺仪app发现会出现负数的情况,只要向相对轴相反方向做运动就会出现负数,于是想了ctypes,强制转换成int这回数据看起来是有正数和负数了,不过在陀螺仪平放着的时候读书优点太大了都达到3000以上了,明显不是,貌似是这个数字需要转换一下才能使用,我找了N多的资料,终于找到有个人mpu6050的代码里,有一个固定的常亮,他使用acc_x乘以这个固定的常数,然后我测试了一下,确实可行,只要将加速计的值乘以16.4就可以得到正确的值!

 陀螺仪读数要乘以13.我搜索了半天也没有找到为什么要乘以16.4 ,不找了,如果有人看到这篇文章知道为啥乘以16.4请留言,谢谢

使用如下代码需要安装smbus库,在树莓派直接 sudo apt-get install py-smbus就ok了

3.python代码如下:

import smbus
import sched, time
import binascii
from threading import Timer, Thread, Event
from struct import *
import ctypes
from math import acos

import sched, time
import binascii
from struct import *

i2c = smbus.SMBus(1)
addr = 0x68
t0 = time.time()


# ====== initial zone ======
try:
    device_id = i2c.read_byte_data(addr, 0x75)
    print ("Device ID:" + str(hex(device_id)))
    print ("MPU9250 I2C Connected.")
    print("")
except:
    print ("Connect failed")
    print ("")
i2c.write_byte_data(0x68, 0x6a, 0x00)
time.sleep(0.05);
i2c.write_byte_data(0x68, 0x37, 0x02)
i2c.write_byte_data(0x0c, 0x0a, 0x16)

# set frequence for accelerator
i2c.write_byte_data(0x68, 29, 9)


# enable fifo and dmp
# i2c.write_byte_data(0x68 , 106 , 32+64);

# ====== intial done ======



def mpu9250_data_get_and_write():
    # global t_a_g

    # keep AKM pointer on continue measuring
    i2c.write_byte_data(0x0c, 0x0a, 0x16)
    # get MPU9250 smbus block data
    # xyz_g_offset = i2c.read_i2c_block_data(addr, 0x13, 6)
    xyz_a_out = i2c.read_i2c_block_data(addr, 0x3B, 6)
    print("xyz_a_out" + str(list2word(xyz_a_out, calc_accelerator_value)))
    # print("xyz_a_out_org#:"+str(xyz_a_out))

    xyz_g_out = i2c.read_i2c_block_data(addr, 0x43, 6)
    print("xyz_g_out" + str(list2word(xyz_g_out, calc_gyro_value)))
    # xyz_a_offset = i2c.read_i2c_block_data(addr, 0x77, 6)

    # get AK8963 smb#us data (by pass-through way)
    xyz_mag = i2c.read_i2c_block_data(0x0c, 0x03, 6)
    # print("xyz_mag"+str(list2word(xyz_mag)))
    xyz_mag_adj = i2c.read_i2c_block_data(0x0c, 0x10, 3)


def list2word(data_list=[], callback=''):
    data = data_list[:]
    if not len(data):
        return [];

    result = []
    for i in range(3):
        high_byte = data.pop(0)
        low_byte = data.pop(0)
        result.append(callback(float(ctypes.c_int16(((high_byte << 8) | low_byte)).value)))

    return result


def calc_accelerator_value(value):
    return round(value / 16.4)


def calc_gyro_value(value):
    return round(value / 131)


def clear_i2c_and_close_file():
    i2c.write_byte_data(addr, 0x6A, 0x07)


# solution 1: while true
def while_true_method():
    # max_count = raw_input("Enter how many count you want.")
    max_count = 100;
    if max_count < 1: max_count = 1000
    print ("Data Counts: " + str(max_count))

    max_count = int(max_count)
    count = 1

    print ("")
    print ("MPU9250 9axis DATA Recording...")
    while True:
        # if count <= max_count:
        mpu9250_data_get_and_write()
        count += 1
        time.sleep(0.5)
        # else:
        pass
    # break;


while_true_method();

  

附:寄存器地址

#define SMPLRT_DIV                 0X19 //陀螺仪采样率典型值为0X07 1000/(1+7)=125HZ

#define CONFIG                         0X1A //低通滤波器  典型值0x06 5hz

#define GYRO_CONFIG                0X1B //陀螺仪测量范围 0X18 正负2000度

#define ACCEL_CONFIG            0X1C //加速度计测量范围 0X18 正负16g

#define ACCEL_CONFIG2           0X1D //加速度计低通滤波器 0x06 5hz

#define PWR_MGMT_1                  0X6B//电源管理1 典型值为0x00

#define PWR_MGMT_2                 0X6C //电源管理2 典型值为0X00

 

#define WHO_AM_I                    0X75 //器件ID MPU9250默认ID为0X71

#define USER_CTRL                   0X6A //用户配置当为0X10时使用SPI模式

 

#define MPU9250_CS        PDout(3) //MPU9250片选信号

#define I2C_ADDR                    0X68  //i2c的地址   

#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

当然以上的都是把数据手册的地址进行定义