四旋翼无人机从0到1的实现(十八)无人机外设驱动→MPU6500

Author:家有仙妻谢掌柜
Date:2021/2/18

今年会更新一个系列,小四轴无人机从功能设计→思维导图→原理图设计→PCBLayout→焊接PCB→程序代码的编写→整机调试一系列,以此记录自己的成长历程!
这个小四轴无人机是大学时期学习制作的,加上现在工作学习对嵌入式的理解更加深入,因此想要重新梳理一下小四轴,之后在此基础上实现大四轴的飞控设计,这些都将在工作之余完成!

//小四轴无人机设计

#include "mpu6500.h"

/*******************************************************************************
 * fuction	mpu6500_init
 * brief	mpu6500配置初始化
 * param	无
 * return	无
 *******************************************************************************/ 
void mpu6500_init(void)
{
	/* 复位内部寄存器,重置默认设置 */    
	// i2c_reg_write(uint8_t Device_address,uint8_t reg_address,uint8_t data);  // 对从机写操作
		i2c_reg_write(MPU6500_Addr,PWR_MGMT_1,0x80); 
		delay_ms(100);
		/* 复位陀螺仪 加速度计 温度计的配置 */    
		i2c_reg_write(MPU6500_Addr,SIGNAL_PATH_RESET,0x07);  
		/* 复位后对内部时钟的配置 */ 
		i2c_reg_write(MPU6500_Addr,PWR_MGMT_1,0x03);     
		/* 复位后对采样速率进行的配置 配置成1KHz */
		i2c_reg_write(MPU6500_Addr,SMPLRT_DIV,0x00); //  
		/* 对陀螺仪的配置 +/-2000d/s*/
		i2c_reg_write(MPU6500_Addr,GYRO_CONFIG,0x18);
		/* 对加速度的配置 +/-4g*/
		i2c_reg_write(MPU6500_Addr,ACCEL_CONFIG,0x08);
}
/*******************************************************************************
 * fuction	mpu6500_read
 * brief	mpu6500寄存器的读
 * param	无
 * return	无
 *******************************************************************************/ 
void mpu6500_read(void)
{
	//uint8_t data_buff[14]
	//i2c_reg_write(MPU6500_Addr,PWR_MGMT_1,0x80);
	int16_XYZ Old_GRY_ReadData;
	Old_GRY_ReadData.X = GRY_ReadData.X;
	Old_GRY_ReadData.Y = GRY_ReadData.Y;
	Old_GRY_ReadData.Z = GRY_ReadData.Z;

	i2c_read(MPU6500_Addr,ACCEL_XOUT_H,14,data_buff);
	//temp_throttle = (uint16_t)((( uint16_t)RF_DATA[1]<<8)|RF_DATA[2])-171.0f;
	/* 读取加速度的X Y Z的三轴数据 */
	ACC_ReadData.X = ((( int16_t)data_buff[0]<<8)|data_buff[1]);
	ACC_ReadData.Y = ((( int16_t)data_buff[2]<<8)|data_buff[3]);
	ACC_ReadData.Z = ((( int16_t)data_buff[4]<<8)|data_buff[5]);
	/* 读取陀螺仪的X Y Z的三轴数据 */
	GRY_ReadData.X = ((( int16_t)data_buff[8]<<8)|data_buff[9]);
	GRY_ReadData.Y = ((( int16_t)data_buff[10]<<8)|data_buff[11]);
	GRY_ReadData.Z = ((( int16_t)data_buff[12]<<8)|data_buff[13]);
	/*
	Old_GRY_ReadData.X = GRY_ReadData.X;
	Old_GRY_ReadData.Y = GRY_ReadData.Y;
	Old_GRY_ReadData.Z = GRY_ReadData.Z;
	*/
	/* 读取陀螺仪的X Y Z的三轴数据减去静止的偏移量 */
	if(Offset == true)
	{
		GRY_ReadData.X -= GRY_OffsetData.X;
		GRY_ReadData.Y -= GRY_OffsetData.Y;
		GRY_ReadData.Z -= GRY_OffsetData.Z;

		ACC_ReadData.X -= ACC_OffsetData.X;
		ACC_ReadData.Y -= ACC_OffsetData.Y;
		ACC_ReadData.Z -= ACC_OffsetData.Z;	
	}
	/* 判断MPU6500是否为静止 */

	Two_GRY_Len = abs(Old_GRY_ReadData.X - GRY_ReadData.X)+abs(Old_GRY_ReadData.Y - GRY_ReadData.Y) + abs(Old_GRY_ReadData.Z - GRY_ReadData.Z);
	if(Two_GRY_Len<20) 
		GRYStable_cnt++;
	else 
	{
		GRYStable_cnt = 0;
		GRYStable = false;
	}
	if(GRYStable_cnt>100) 
		GRYStable = true;
	if(GRYStable)
	{
		if(Initoffset ==  false) 
			Initoffset = true;
	}
}
/*******************************************************************************
 * fuction	get_offset
 * brief	获取加速度计和陀螺仪的偏移值
 * param	无
 * return	无
 *******************************************************************************/ 
void get_offset(void)//  读取100次 求平均
{                              
	uint8_t  i=0;
	int32_t GRY_XTemp = 0, GRY_YTemp = 0, GRY_ZTemp = 0;
	int32_t ACC_XTemp = 0, ACC_YTemp = 0, ACC_ZTemp = 0;
	/* 复位偏移标志位 */
	Offset = false;
	/* 读取100次陀螺仪和加速度的值 */
	for(i=0;i<100;i++)
	{
		mpu6500_read();
		GRY_XTemp += GRY_ReadData.X;
		GRY_YTemp += GRY_ReadData.Y;
		GRY_ZTemp += GRY_ReadData.Z;
			
		//GRY_XTemp += GRY_ReadData.X;
		ACC_XTemp += ACC_ReadData.X;
		ACC_YTemp += ACC_ReadData.Y;
		ACC_ZTemp += ACC_ReadData.Z;
			
		delay_ms(5);		
	}
	/* 读取100次陀螺仪和加速度的值并且求平均 */
	GRY_XTemp /= 100;
	GRY_YTemp /= 100;
	GRY_ZTemp /= 100;
			
	ACC_XTemp /= 100;
	ACC_YTemp /= 100;
	ACC_ZTemp /= 100;
	/* 赋值 偏移值 */
		
	GRY_OffsetData.X = GRY_XTemp;
	GRY_OffsetData.Y = GRY_YTemp;
	GRY_OffsetData.Z = GRY_ZTemp;
		
	ACC_OffsetData.X = ACC_XTemp;
	ACC_OffsetData.Y = ACC_YTemp;
	ACC_OffsetData.Z = ACC_ZTemp-8192;
		
	/* 置位偏移标志位 */
	Offset = true;		
}
/*******************************************************************************
 * fuction	Cal_Mpu_Data
 * brief	MPU值的滤波及转化
 * param	无
 * return	无
 *******************************************************************************/ 
void Cal_Mpu_Data(void)
{
	/* 转化陀螺仪为1deg/s */
	// Temp_Gry_F;     Temp_ACC_F;  Gry_Gain  ACC_Gain
	Temp_Gry_F.X = GRY_ReadData.X *Gry_Gain;
	Temp_Gry_F.Y = GRY_ReadData.Y *Gry_Gain;
	Temp_Gry_F.Z = GRY_ReadData.Z *Gry_Gain;
	//float_XYZ Gry_F;              // 无需滤波
  //float_XYZ Gry_FeedBack_F;
	
	/* 角速度进行未滤波 */
	Gry_F.X = Temp_Gry_F.X;
	Gry_F.Y = Temp_Gry_F.Y;
	Gry_F.Z = Temp_Gry_F.Z;
	/* 角速度进行低通滤波 */
	Gry_FeedBack_F.X = biquadFilterApply(&gryo_51Hz_parameter1,Temp_Gry_F.X);
	Gry_FeedBack_F.Y = biquadFilterApply(&gryo_51Hz_parameter2,Temp_Gry_F.Y);
	Gry_FeedBack_F.Z = biquadFilterApply(&gryo_51Hz_parameter3,Temp_Gry_F.Z);
	
	/* 转化加速度值为1g的值 */
	Temp_ACC_F.X = ACC_ReadData.X *ACC_Gain;
	Temp_ACC_F.Y = ACC_ReadData.Y *ACC_Gain;
	Temp_ACC_F.Z = ACC_ReadData.Z *ACC_Gain;
	
	/* 加速度进行低通滤波 */
	//&acc_30Hz_parameter1
	ACC_F.X = biquadFilterApply(&acc_30Hz_parameter1,Temp_ACC_F.X);
	ACC_F.Y = biquadFilterApply(&acc_30Hz_parameter2,Temp_ACC_F.Y);
	ACC_F.Z = biquadFilterApply(&acc_30Hz_parameter3,Temp_ACC_F.Z);
	
}
/*******************************************************************************
 * fuction	get_accmod
 * brief	获取加速度计的模长
 * param	无
 * return	AccMod
 *******************************************************************************/ 
/* 求模 x*x+y*y+z*z    然后在开/根号*/
float get_accmod(void)
{
	float AccMod = sqrtf(Temp_ACC_F.X*Temp_ACC_F.X+Temp_ACC_F.Y*Temp_ACC_F.Y+Temp_ACC_F.Z*Temp_ACC_F.Z);
	
	return AccMod;	
}
#ifndef _MPU6500_H__
#define _MPU6500_H__

#include "board_define.h"
#include "var_global.h"

//void all_init(void);
#define SMPLRT_DIV 			0x19           	// 采样速率
#define GYRO_CONFIG   		0x1B        	// 陀螺仪的配置
#define ACCEL_CONFIG  		0x1C        	// 加速度计的配置
#define ACCEL_XOUT_H 		0x3B         	// 加速度计X轴高字节(第一个字节数据)
#define SIGNAL_PATH_RESET 	0x68    		// 陀螺仪 加速度计 温度计的配置
#define PWR_MGMT_1 			0x6B           	// 上电复位配置
#define MPU6500_Addr 		0xD0         	// MPU6500从机地址
#define Gry_Gain    		0.06103f     	//
#define ACC_Gain    		0.001196f

void mpu6500_init(void);
void mpu6500_read(void);
void get_offset(void);
void Cal_Mpu_Data(void);
float get_accmod(void);

#endif
#include "sys.h" #include "delay.h" #include "usart.h" #include "led.h" #include "timer.h" #include "FreeRTOS.h" #include "task.h" #include "debug_cmdshell.h" #include "stabilizer.h" //任务优先级 #define START_TASK_PRIO 1 //任务堆栈大小 #define START_STK_SIZE 128 //任务句柄 TaskHandle_t StartTask_Handler; //任务函数 void start_task(void *pvParameters); //任务优先级 #define TASK2_TASK_PRIO 3 //任务堆栈大小 #define TASK2_STK_SIZE 512 //任务句柄 TaskHandle_t Task2Task_Handler; //任务函数 void task2_task(void *pvParameters); int main(void) { NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4);//设置系统中断优先级分组4 delay_init(); //延时函数初始化 uart_init(115200); //初始化串口 LED_Init(); //初始化LED stabilizerInit(); //创建开始任务 xTaskCreate((TaskFunction_t )start_task, //任务函数 (const char* )"start_task", //任务名称 (uint16_t )START_STK_SIZE, //任务堆栈大小 (void* )NULL, //传递给任务函数的参数 (UBaseType_t )START_TASK_PRIO, //任务优先级 (TaskHandle_t* )&StartTask_Handler); //任务句柄 vTaskStartScheduler(); //开启任务调度 } //开始任务任务函数 void start_task(void *pvParameters) { taskENTER_CRITICAL(); //进入临界区 xTaskCreate((TaskFunction_t )task2_task, (const char* )"task2_task", (uint16_t )TASK2_STK_SIZE, (void* )NULL, (UBaseType_t )TASK2_TASK_PRIO, (TaskHandle_t* )&Task2Task_Handler); xTaskCreate(stabilizerTask, "STABILIZER", 450, NULL, 5, NULL); /*创建姿态任务*/ vTaskDelete(StartTask_Handler); //删除开始任务 taskEXIT_CRITICAL(); //退出临界区 } //task2任务函数 void task2_task(void *pvParameters) { //u8 task2_num=0; u16 len; while(1) { //task2_num++; //任务2执行次数加1 注意task1_num2加到255的时候会清零!! //printf("任务2已经执行:%d次\r\n",task2_num); if(USART_RX_STA&0x8000) { len=USART_RX_STA&0x3fff; debugcmd_process(USART_
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值