基于micropython编写的esp32 mpu6050驱动

前言

文章分两部分,第一部分是全部代码展示,复制即用;第二部分是代码分段解释。

用的是esp32的I2C(0),默认scl接GPIO18,sda接GPIO19

关键词:micropython,esp32,mpu6050

所有代码展示

from machine import Pin,I2C
import time
import math

class MPU6050():
    def __init__(self, i2c, addr=0x68):
        self.iic = i2c
        self.addr = addr
        self.accelScale=16384
        self.gyroScale=131
        # 唤醒
        self.iic.writeto(self.addr, bytearray([107, 0]))
        self.iic.writeto(self.addr,bytearray([26,0]))
        # 配置加速度计量程
        self.iic.writeto(self.addr,bytearray([27,0]))
        # 配置角速度计量程
        self.iic.writeto(self.addr,bytearray([28,0]))
        # 配置量程系数
        AFS_SEL=(self.iic.readfrom_mem(self.addr,27,1))[0]&0x18
        if AFS_SEL==0:
            self.accelScale=16384
        elif AFS_SEL==0x08:
            self.accelScale=8192
        elif AFS_SEL==0x10:
            self.accelScale=4096
        elif AFS_SEL==0x18:
            self.accelScale=2048

        AFS_SEL=(self.iic.readfrom_mem(self.addr,28,1))[0]&0x18
        if(AFS_SEL==0):
            self.gyroScale=131
        elif AFS_SEL==0x08:
            self.gyroScale=65.5
        elif AFS_SEL==0x10:
            self.gyroScale=32.8
        elif AFS_SEL==0x18:
            self.gyroScale=16.4
        self.calibraton=self.calibrate()
    # 读取寄存器原生数据
    def get_raw_values(self):
        reg_data=self.iic.readfrom_mem(self.addr, 59, 14)
        return reg_data[:6],reg_data[8:]
    # 将原生数据转6轴数据
    def raw_to_ints(self):
        a,g=self.get_raw_values()
        aX=self.bytes_toint(a[0],a[1])/self.accelScale
        aY=self.bytes_toint(a[2],a[3])/self.accelScale
        aZ=self.bytes_toint(a[4],a[5])/self.accelScale
        gX=self.bytes_toint(g[0],g[1])/self.gyroScale
        gY=self.bytes_toint(g[2],g[3])/self.gyroScale
        gZ=self.bytes_toint(g[4],g[5])/self.gyroScale
        return [aX,aY,aZ,gX,gY,gZ]
    # 定义转换规则
    def bytes_toint(self, firstbyte, secondbyte):
        if not firstbyte & 0x80:
            return firstbyte << 8 | secondbyte
        return - (((firstbyte ^ 255) << 8) | (secondbyte ^ 255) + 1)
    # 处理后的6轴参数
    def get_values(self,calibration):
        return [a+b for a, b in zip(self.raw_to_ints(), calibration)] 


    # 获取修正数组
    def calibrate(self):
        calibrationArray = [0,0,0,0,0,0]
        for i in range(100):
            calibtation=self.raw_to_ints()
            calibrationArray[0] += calibtation[0]
            calibrationArray[1] += calibtation[1]
            calibrationArray[2] += calibtation[2]
            calibrationArray[3] += calibtation[3]
            calibrationArray[4] += calibtation[4]
            calibrationArray[5] += calibtation[5]
        for i in range(6):
            calibrationArray[i]/=100
            if i==2:
                calibrationArray[i]=1-calibrationArray[i]
            else:
                calibrationArray[i]=-calibrationArray[i]
        return calibrationArray
    # 计算欧拉角
    def get_angles(self,angle_data,calibration,k=0.95):
        data=self.get_values(calibration)
        aPitch=math.atan(data[0]/data[2])*57.3
        aRow=math.atan(data[1]/data[2])*57.3
        gRow=data[3]/7500
        gPitch=data[4]/7500
        gYaw=data[5]/7500
        pitch=(1-k)*angle_data['pitch']+k*(aPitch+gPitch)
        row=(1-k)*angle_data['row']+k*(aRow+gRow)
        yaw=(1-k)*angle_data['yaw']+k*(angle_data['yaw']+gYaw)
        return {'pitch':pitch,'yaw':yaw,'row':row}

# 使用demo
i2c=I2C(0)
a=MPU6050(i2c)
angle={'pitch':0,'row':0,'yaw':0}
cali=a.calibrate()
while True:
    angle=a.get_angles(angle,cali)
    print(angle)
    time.sleep(0.5)

代码解释

总体分为两部分,导包MPU6050类的定义

导包

from machine import Pin,I2C
import time
import math

定义MPU6050类

包含几个类函数:

类初始化

def __init__(self, i2c, addr=0x68):
        self.iic = i2c
        self.addr = addr
        # 初始化加速度计量程系数(默认+-2g)
        self.accelScale=16384
        # 初始化陀螺仪量程系数(默认+-250°)
        self.gyroScale=131
        # 唤醒
        self.iic.writeto(self.addr, bytearray([107, 0]))
        self.iic.writeto(self.addr,bytearray([26,0]))
        # 配置加速度计量程
        self.iic.writeto(self.addr,bytearray([27,0]))
        # 配置角速度计量程
        self.iic.writeto(self.addr,bytearray([28,0]))
        # 根据寄存器值配置量程系数
        AFS_SEL=(self.iic.readfrom_mem(self.addr,27,1))[0]&0x18
        if AFS_SEL==0:
            self.accelScale=16384
        elif AFS_SEL==0x08:
            self.accelScale=8192
        elif AFS_SEL==0x10:
            self.accelScale=4096
        elif AFS_SEL==0x18:
            self.accelScale=2048

        AFS_SEL=(self.iic.readfrom_mem(self.addr,28,1))[0]&0x18
        if(AFS_SEL==0):
            self.gyroScale=131
        elif AFS_SEL==0x08:
            self.gyroScale=65.5
        elif AFS_SEL==0x10:
            self.gyroScale=32.8
        elif AFS_SEL==0x18:
            self.gyroScale=16.4
        # 调用矫正函数进行初始矫正
        self.calibraton=self.calibrate()

获取原生6轴数据

# 读取寄存器原生数据,返回加速度和陀螺仪的12个数据
    def get_raw_values(self):
        reg_data=self.iic.readfrom_mem(self.addr, 59, 14)
        return reg_data[:6],reg_data[8:]

将原生6轴数据转化

# 将原生数据转6轴数据
    def raw_to_ints(self):
        # 获取原生6轴数据
        a,g=self.get_raw_values()
        # 调用bytes_toint方法进行转化,除以量程系数将数据映射到范围内
        aX=self.bytes_toint(a[0],a[1])/self.accelScale
        aY=self.bytes_toint(a[2],a[3])/self.accelScale
        aZ=self.bytes_toint(a[4],a[5])/self.accelScale
        gX=self.bytes_toint(g[0],g[1])/self.gyroScale
        gY=self.bytes_toint(g[2],g[3])/self.gyroScale
        gZ=self.bytes_toint(g[4],g[5])/self.gyroScale
        # 返回处理后的6轴数据
        return [aX,aY,aZ,gX,gY,gZ]

原生数据转化规则

# 定义转换规则
    def bytes_toint(self, firstbyte, secondbyte):
        if not firstbyte & 0x80:
            return firstbyte << 8 | secondbyte
        return - (((firstbyte ^ 255) << 8) | (secondbyte ^ 255) + 1)

定义矫正函数

    def calibrate(self):
        # 矫正数组初始化
        calibrationArray = [0,0,0,0,0,0]
        # 取100次数据累加后取平均
        for i in range(100):
            calibtation=self.raw_to_ints()
            calibrationArray[0] += calibtation[0]
            calibrationArray[1] += calibtation[1]
            calibrationArray[2] += calibtation[2]
            calibrationArray[3] += calibtation[3]
            calibrationArray[4] += calibtation[4]
            calibrationArray[5] += calibtation[5]
        # 当静止且水平时,理论输出的6轴数组[0,0,1,0,0,0]
        # 只有z轴受1g的加速度
        for i in range(6):
            calibrationArray[i]/=100
            if i==2:
                calibrationArray[i]=1-calibrationArray[i]
            else:
                calibrationArray[i]=-calibrationArray[i]
        return calibrationArray

返回矫正后的6轴数据

def get_values(self,calibration):
        # 处理后的6轴数据与矫正数组相加得到矫正的数据
        return [a+b for a, b in zip(self.raw_to_ints(), calibration)]

计算欧拉角

"""
参数说明:
angle_data 上一时刻欧拉角数据
calibration 矫正数组
k 权重系数
"""
    def get_angles(self,angle_data,calibration,k=0.95):
        # 获取矫正后的6轴数据
        data=self.get_values(calibration)
        aPitch=math.atan(data[0]/data[2])*57.3
        aRow=math.atan(data[1]/data[2])*57.3
        
        gRow=data[3]/7500
        gPitch=data[4]/7500
        gYaw=data[5]/7500
        # 本次数据与上一时刻数据加权求和,减少扰动
        pitch=(1-k)*angle_data['pitch']+k*(aPitch+gPitch)
        row=(1-k)*angle_data['row']+k*(aRow+gRow)
        yaw=(1-k)*angle_data['yaw']+k*(angle_data['yaw']+gYaw)
        # 返回欧拉角字典
        return {'pitch':pitch,'yaw':yaw,'row':row}

  • 8
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 6
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值