资讯详情

DMP解算

1.硬件:mpu9250, stm32f103zet6。

2.inv_mpu.h文件,一种基础i2c直觉陀螺仪的驱动器包含(移植官方)的函数MSP430的DMP驱动过来):

1.static int set_int_enable(unsigned char enable) 中断模块中断模块 2.int mpu_reg_dump(void) 测试打印函数 3.int mpu_read_reg(unsigned char reg, unsigned char *data) 除了向芯片读取寄存器值外,3..MEMERY和FIFO 4.int mpu_init(void) MPU9250的初始化 5.int mpu_lp_accel_mode(unsigned char rate) 进入低功耗模式 6.int mpu_get_gyro_reg(short *data, unsigned long *timestamp) 获取新的原始陀螺仪数据 7.int mpu_get_accel_reg(short *data, unsigned long *timestamp获取新的原始加速度数据 8.int mpu_get_temperature(long *data, unsigned long *timestamp) 获取新的温度数据 9.int mpu_set_accel_bias(const long *accel_bias) 偏差配置函数 10.int mpu_reset_fifo(void) 重置FIFO函数 11.int mpu_get_gyro_fsr(unsigned short *fsr) 陀螺仪的全尺寸范围函数 12.int mpu_set_gyro_fsr(unsigned short fsr) 设置陀螺仪全尺寸范围函数 13.int mpu_get_accel_fsr(unsigned char *fsr) 加速度全尺寸函数 14.int mpu_set_accel_fsr(unsigned char fsr) 加速度全尺寸函数 15.int mpu_get_lpf(unsigned short *lpf) .获得DLPF范围函数 16.int mpu_set_lpf(unsigned short lpf) 配置DLPF范围函数 17.int mpu_get_sample_rate(unsigned short *rate) 采样频率范围函数 18.int mpu_set_sample_rate(unsigned short rate) 采样频率范围函数配置 19.int mpu_get_compass_sample_rate(unsigned short *rate) 获得罗盘采样频率范围函数 20.int mpu_set_compass_sample_rate(unsigned short rate) 配置罗盘采样频率范围函数 21.intmpu_get_gyro_sens(float *sens) 陀螺仪灵敏度比因子函数 22.int mpu_get_accel_sens(unsigned short *sens) 因子函数 23.int mpu_get_fifo_config(unsigned char *sensors) 获得开启的FIFO通道函数 24.int mpu_configure_fifo(unsigned char sensors) 配置开启FIFO通道函数 25.int mpu_get_power_state(unsigned char *power_on) 获得芯片工作状态 26.int mpu_set_sensors(unsigned char sensors) 传感器的时钟和工作状态函数 27.int mpu_get_int_status(short *status).获得中断状态函数 28.int mpu_read_fifo(short *gyro, short *accel, unsigned long *timestamp,unsigned char *sensors, unsigned char *more) 获得FIFO数据函数 29.int mpu_read_fifo_stream(unsigned short length, unsigned char *data,unsigned char *more) 获得FIFO数据长度函数 30.int mpu_set_bypass(unsigned char bypass_on) 设置旁路模式函数 31.int mpu_set_int_level(unsigned char active_low) 设置中断优先级函数 32.int mpu_set_int_latched(unsigned char enable) 设置中断定函数- 设置自检函数 33.static int get_st_biases(long *gyro, long *accel, unsigned char hw_test) 获取所有偏差值函数 34.int mpu_run_self_test(long *gyro, long *accel) 行自检值函数 35.int mpu_write_mem(unsigned short mem_addr, unsigned short length,unsigned char *data) 向DMP写记忆函数 36.int mpu_read_mem(unsigned short mem_addr, unsigned short length,unsigned char *data) 向DMP读记忆函数 37.int mpu_load_firmware(unsigned short length, const unsigned char*firmware,unsigned short start_addr, unsigned short sample_rate) 加载并验证DMP映像函数 38.int mpu_set_dmp_state(unsigned char enable) DMP状态控制函数 39.int mpu_get_dmp_state(unsigned char *enabled) DMP状态读取函数

2.创建IIC协议。可实现包括 IIC 的初始化(IO 口)、IIC 开始、IIC 结束、ACK、IIC读写等功能,在其他函数中,只需调用相关功能 IIC 函数可以与外部相匹配 IIC 部分代码如下:

//IIC 初始化 void IIC_Init(void) {  GPIO_InitTypeDef GPIO_Initure;  __HAL_RCC_GPIOB_CLK_ENABLE(); //使能 GPIOB 时钟  //PH4,5 初始化设置  GPIO_Initure.Pin=GPIO_PIN_10|GPIO_PIN_11;  GPIO_Initure.Mode=GPIO_MODE_OUTPUT_PP; //推挽输出  GPIO_Initure.Pull=GPIO_PULLUP; //上拉  GPIO_Initure.Speed=GPIO_SPEED_FREQ_HIGH;//高速  HAL_GPIO_Init(GPIOB,&GPIO_Initure);  IIC_SDA=1;  IIC_SCL=1;  } //产生 IIC 起始信号 void IIC_Start(void) { SDA_OUT(); //sda 线输出 IIC_SDA=1;  IIC_SCL=1; delay_us(4); IIC_SDA=0;//START:when CLK is high,DATA change form high to low  delay_us(4); IIC_SCL=0;//钳住 I2C 总线,准备发送或接收数据 }   //产生 IIC 停止信号 void IIC_Stop(void) { SDA_OUT();//sda 线输出 IIC_SCL=0; IIC_SDA=0;//STOP:when CLK is high DATA change form low to high delay_us(4); IIC_SCL=1;  IIC_SDA=1;//发送 I2C 总线结束信号 delay_us(4);   } //等待响应信号到来 //返回值:1,接收应答失败 // 0,成功接收答案 u8 IIC_Wait_Ack(void) { u8 ucErrTime=0; SDA_IN(); //SDA 设置为输入  IIC_SDA=1;delay_us(1);   IIC_SCL=1;delay_us(1); while(READ_SDA) { ucErrTime  ; if(ucErrTime>250) { IIC_Stop(); return 1; } } IIC_SCL=0;//时钟输出 0  return 0;  }  //产生 ACK 应答 void IIC_Ack(void) { IIC_SCL=0; SDA_OUT(); IIC_SDA=0; delay_us(2); IIC_SCL=1; delay_us(2); IIC_SCL=0; } //不产生 ACK 应答   void IIC_NAck(void) { IIC_SCL=0; SDA_OUT(); IIC_SDA=1; delay_us(2); IIC_SCL=1; delay_us(2); IIC_SCL=0; }   //IIC 发送字节 ////返回从机是否回应 //1,有应答 //0,无应答   void IIC_Send_Byte(u8 txd) {   u8 t;  SDA_OUT();   IIC_SCL=0.//数据传输始于降低时钟  for(t=0;t<8;t  )  {   IIC_SDA=(txd&0x80)>>7;  txd<<=1;  delay_us(2); IIC_SCL=1; delay_us(2);  IIC_SCL=0; delay_us(2);  } }  //读 1 个字节,ack=1 时,发送 ACK,ack=0,发送 nACK  u8 IIC_Read_Byte(unsigned char ack) { unsigned char i,receive=0; SDA_IN();//SDA 设置为输入  for(i=0;i<8;i   ) {  IIC_SCL=0;   delay_us(2); IIC_SCL=1;  receive<<=1;  if(READ_SDA)receive  ;  delay_us(1);   }  if (!ack)  IIC_NAck();//发送 nACK  else  IIC_Ack(); //发送 ACK   eturn receive;
}

可以运用stm32cubemx建立iic,这里可以借鉴别人的,不多赘述。

4.四元函数解算

short gryox,gyroy,gyroz; short accx,accy,accz; void IMU_GetData(void) {     MPU_Get_Gyroscope(&gyrox,&gyroy,&gyroz);     MPU_Get_Accelerometer(&accx,&accy,&accz);

}

//定义各变量

#define RtA         57.295779f    //弧度->角度             #define AtR            0.0174533f    //角度->弧度 #define Acc_G         0.0011963f     #define Gyro_G         0.0610351f                 #define Gyro_Gr        0.0010653f    

#define Kp 18.0f                         #define Ki 0.008f                          #define halfT 0.008f               float q0 = 1, q1 = 0, q2 = 0, q3 = 0;    float exInt = 0, eyInt = 0, ezInt = 0;   float Angle[3]={0};//最终角度

void IMU_Update(short gyrox,short gyroy,short gyroz,short accx,short accy,short accz) {     float ax=accx,ay=accy,az=accz;     float gx=gyrox,gy=gyroy,gz=gyroz;       float norm;       float vx, vy, vz;       float ex, ey, ez;       float q0q0 = q0*q0;       float q0q1 = q0*q1;       float q0q2 = q0*q2;       float q1q1 = q1*q1;       float q1q3 = q1*q3;       float q2q2 = q2*q2;       float q2q3 = q2*q3;       float q3q3 = q3*q3;     if(ax*ay*az==0)//此时任意方向角加速度为0          return;       gx *= Gyro_Gr;     gy *= Gyro_Gr;     gz *= Gyro_Gr;        //对速度值归一化    

norm = sqrt(ax*ax + ay*ay + az*az);              ax = ax /norm;       ay = ay / norm;       az = az / norm;

      // 提取姿态矩阵的重力分量                 vx = 2*(q1q3 - q0q2);                                                       vy = 2*(q0q1 + q2q3);       vz = q0q0 - q1q1 - q2q2 + q3q3 ;

      // 得到误差向量,并进行积分而消除       ex = (ay*vz - az*vy) ;                                                      ey = (az*vx - ax*vz) ;       ez = (ax*vy - ay*vx) ;

      exInt = exInt + ex * Ki;                                         eyInt = eyInt + ey * Ki;       ezInt = ezInt + ez * Ki;

  // 互补滤波,将误差输入Pid控制器与本次姿态更新中陀螺仪测得的角速度相加,得到一个修正的角速度值,获得的修正的角速度值去更新四元素,从而获得准确的姿态角信息。       gx = gx + Kp*ex + exInt;                                                          gy = gy + Kp*ey + eyInt;       gz = gz + Kp*ez + ezInt;                                               

      // 解四元数                                 q0 = q0 + (-q1*gx - q2*gy - q3*gz)*halfT;       q1 = q1 + (q0*gx + q2*gz - q3*gy)*halfT;       q2 = q2 + (q0*gy - q1*gz + q3*gx)*halfT;       q3 = q3 + (q0*gz + q1*gy - q2*gx)*halfT;

      // 四元数归一化       norm = sqrt(q0*q0 + q1*q1 + q2*q2 + q3*q3);              q0 = q0 / norm;       q1 = q1 / norm;       q2 = q2 / norm;       q3 = q3 / norm;          //求解姿态角(欧拉角) ANgle[0]    = asin(-2 * q1 * q3 + 2 * q0* q2)* RtA ; //pitch ANgle[1]    = atan2(2 * q2 * q3 + 2 * q0 * q1, -2 * q1 * q1 - 2 * q2* q2 + 1)* RtA;      //roll                     ANgle[2]  =atan2(2 * q1 * q2 + 2 * q0 * q3, -2 * q2*q2 - 2 * q3* q3 + 1)* RtA;             // yaw     }

4.“inv_mpu.c”和“inv_mpu_dmp_motion_driver.c”的文件的调用

        现移植mpu9250的官方DMP库中eMpl。

关于inv_mpu.c:

1.因为所要移植的DMP库原先是基于STM32F4 的,可将关于msp430的文件注释掉。

2.加上#include mpu9250.h,#include usart.h(用于串口输出)。

3.定义所用传感器以及驱动(可用MSP430驱动)

4.添加DMP_读取角度等

short gyro[3], accel[3], sensors;
    unsigned char more;
    long quat[4];
    float q0=1.0f,q1=0.0f,q2=0.0f,q3=0.0f;
    float pitch,roll,yaw;
     u8 DMP_DATA_UPDATA(void)
    {     
        unsigned long sensor_timestamp;
        
        gyro_data_ready_cb();                   //数据采集结束标志位
                    
        if (hal.new_gyro && hal.dmp_on)         //用于计算四元数函数
            {
                if(dmp_read_fifo(gyro, accel, quat, &sensor_timestamp, &sensors,&more))
                    {return 1;}    
                    
                if (!more)
                        hal.new_gyro = 0;
                        if(sensors & INV_WXYZ_QUAT)
                            {
                                    q0=quat[0]/q30;
                                    q1=quat[1]/q30;
                                    q2=quat[2]/q30;
                                    q3=quat[3]/q30;
                                    pitch=asin((-2)*q1*q3+2*q0*q2)*57.3;
                                    roll=atan2(2*q2*q3+2*q0*q1,(-2)*q1*q1-2*q2*q2+1)*57.3;
                                    yaw=atan2(2*(q1*q2+q0*q3),q0*q0+q1*q1-q2*q2-q3*q3)*57.3;
                            }
            }
                    

关于inv_mpu_dmp_motion_driver.c:

1.添加dmpKey.h和dmpmap.h文件以及串口通信文件。

2.将相关msp430的文件注释掉。

3.定义目标版采用MSP430,对f103无影响。

可根据正点原子MPU6050驱动程序进行修改:

5.1.初始化MPU9250(时钟、端口、引脚、iic总线、传感器)

5.2.设置各传感器量程

5.3.获取数字滤波器、温度以及陀螺仪原始值等功能

5.4.实现IIC连续写读,添加函数MPU_Write/Read_Len, MPU_IIC_Start/Stop等,即跟上面所诉一样进行调用iic即可

while(1)                                       
	{
		error = mpu_dmp_init();                      //初始化mpu_dmp库
		printf("ERROR:%d
",error);                //串口显示初始化错误值
		switch (error)                               //对不同错误值类型判断
		{
			case 0:printf("DMP库初始化正常
");break;
			case 1:printf("设置传感器失败
");break;
			case 2:printf("设置FIFO失败
");break;
			case 3:printf("设置采样率失败
");break;
			case 4:printf("加载dmp固件失败
");break;
			case 5:printf("设置陀螺仪方向失败
");break;
			case 6:printf("设置dmp功能失败
");break;
			case 7:printf("设置DMP输出速率失败
");break;
			case 8:printf("自检失败
");break;
			case 9:printf("使能DMP失败
");break;
			case 10:printf("初始化MPU6050失败
");break;
			default :printf("未知错误
");break;
		}
		if(error == 0)break;                        //如果没有错误直接退出循环
		void MPU_Read(void)
{
	
	if(mpu_dmp_get_data(&yaw,&pitch,&roll)==0)      //dmp处理得到数据,对返回值进行判断
	{ 
		printf("Pitch:%f    Roll:%f    Yaw:%f
",pitch,roll,yaw);//串口输出三轴角度
		mpu9250.speed++;                            //显示速度自加
		if(mpu9250.speed == 1)						//显示速度阈值设置
		{
			mpu9250.flag = 1;						//采集成功标志位设置为有效
			mpu9250.speed = 0;						//显示速度归零
		}	
	}
	else 											//采集不成功										
	{
		mpu9250.flag = 0;							//采集成功标志位设置为无效
	}	
}
/**
  * @brief  MPU6050数据上报
  * @param  无
  * @retval 无
  */
void DATA_Report(void)
{
	if(mpu9250.flag == 1)						    //采集成功时
	{ 
		temp=pitch*100;							    //赋temp为pitch
		if(temp<0)								    //对数据正负判断,判断为负时
		{
			temp=-temp;						        //对负数据取反	
			sprintf((char *)tmp_buf," Pitch:-%.3d.%.2d",temp/100,temp%100);//字符串格式化命令
		}
		else                                        //判断为正时 
		{
			sprintf((char *)tmp_buf," Pitch: %.3d.%.2d",temp/100,temp%100);//字符串格式化命令
		}
		temp=roll*100;							    //赋temp为pitch
		if(temp<0)								    //对数据正负判断,判断为负时
		{
			temp=-temp;						        //对负数据取反	
			sprintf((char *)tmp_buf," Roll :-%.3d.%.2d",temp/100,temp%100);//字符串格式化命令
		}
		else                                        //判断为正时 
		{
			sprintf((char *)tmp_buf," Roll : %.3d.%.2d",temp/100,temp%100);//字符串格式化命令
		}
		
		temp=yaw*100;							    //赋temp为pitch
		if(temp<0)								    //对数据正负判断,判断为负时
		{
			temp=-temp;						        //对负数据取反	
			sprintf((char *)tmp_buf," Yaw  :-%.3d.%.2d",temp/100,temp%100);//字符串格式化命令
		}
		else                                        //判断为正时 
		{
			sprintf((char *)tmp_buf," Yaw  : %.3d.%.2d",temp/100,temp%100);//字符串格式化命令
		}
		mpu9250.flag = 0;							//采集成功标志位设置为无效
	}
	else ;											//防卡死
}

DMP相关文件工程在下面链接:

链接:https://pan.baidu.com/s/1BJWJsD-4n0pl7FQ_z2Du0Q?pwd=zhr6 提取码:zhr6

 

 

 

 

 

 

 

 

 

 

 

 

标签: 传感器fq50

锐单商城拥有海量元器件数据手册IC替代型号,打造 电子元器件IC百科大全!

锐单商城 - 一站式电子元器件采购平台