国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

【STM32F4系列】【HAL庫】【模塊介紹】MPU6050設(shè)置與DMP庫使用

這篇具有很好參考價(jià)值的文章主要介紹了【STM32F4系列】【HAL庫】【模塊介紹】MPU6050設(shè)置與DMP庫使用。希望對大家有所幫助。如果存在錯(cuò)誤或未考慮完全的地方,請大家不吝賜教,您也可以點(diǎn)擊"舉報(bào)違法"按鈕提交疑問。

概述

MPU6050是一個(gè)3軸陀螺儀(測角加速度)和3軸加速度計(jì)(測量線加速度)的測量芯片

內(nèi)部自帶運(yùn)算單元(DMP),可以輸出經(jīng)姿態(tài)融合計(jì)算后的四元數(shù)(一種表示旋轉(zhuǎn)的方法)

而且MPU6050的價(jià)格較低(10r以下),常被用于精度不高的場合作為姿態(tài)感知的芯片

如經(jīng)典項(xiàng)目平衡車,某年電賽題目風(fēng)力擺等

MPU6050可以獲取的數(shù)據(jù)為3軸的角加速度和三軸加速度,為了得到平常使用的歐拉角或者四元數(shù),需要根據(jù)這些數(shù)據(jù)進(jìn)行姿態(tài)解算

可以在單片機(jī)內(nèi)部進(jìn)行姿態(tài)解算,如使用 卡爾曼濾波 但是這樣會占用大量單片機(jī)資源,因此常用MPU6050自帶的運(yùn)算單元來進(jìn)行解算

注意,本文的代碼借是將 正點(diǎn)原子,大魚電子,DMP的官方庫 進(jìn)行了整合修改,并非100%原創(chuàng)

注意,本文的代碼借是將 正點(diǎn)原子,大魚電子,DMP的官方庫 進(jìn)行了整合修改,并非100%原創(chuàng)

注意,本文的代碼借是將 正點(diǎn)原子,大魚電子,DMP的官方庫 進(jìn)行了整合修改,并非100%原創(chuàng)

硬件設(shè)計(jì)

使用官方數(shù)據(jù)手冊給出的電路圖進(jìn)行設(shè)計(jì),實(shí)測可以使用

【STM32F4系列】【HAL庫】【模塊介紹】MPU6050設(shè)置與DMP庫使用

要注意CPOUT(20腳)的電容,這是個(gè)電荷泵電容,一定要使用2.2nF,不然會出現(xiàn)不穩(wěn)定

【STM32F4系列】【HAL庫】【模塊介紹】MPU6050設(shè)置與DMP庫使用

MPU6050使用標(biāo)準(zhǔn)I2C通信,建議在I2C加外部上拉電阻(也可以將單片機(jī)內(nèi)設(shè)為開漏上拉輸出)

6,7號引腳連接的是地磁計(jì)的用于修正偏航角(Yaw),同樣是I2C通信

封裝是比較難焊的QFN-24,建議使用風(fēng)槍或者加熱臺焊接(用烙鐵太折磨人了)

【STM32F4系列】【HAL庫】【模塊介紹】MPU6050設(shè)置與DMP庫使用

這是對應(yīng)的角加速度和加速度的方向,以及解算后的歐拉角

另外因?yàn)橛布?偏航角(Yaw)會出現(xiàn)偏移,這是無可避免的,可以通過外接地磁計(jì)改善

軟件設(shè)計(jì)

I2C通信

MPU6050的I2C從器件地址是依據(jù)AD0(9號引腳)的電平而變化的

AD0引腳為低電平(通過10K電阻接地)則地址是 0x68 << 1 = 0xD0 (也就是常說的除最低位外的地址)

AD0引腳為高電平則地址是 0x69 << 1 = 0xD2 (也就是常說的除最低位外的地址)

最后一位和標(biāo)準(zhǔn)I2C一樣是根據(jù)讀寫來確定的

地址要特別注意,容易出錯(cuò)

I2C協(xié)議沒什么好說的,請看這篇博客

傳送門

通過宏定義來選擇硬件和軟件I2C

/*
硬件I2C模式
需要:
1.I2C
    I2C
    (默認(rèn)設(shè)置)
    標(biāo)準(zhǔn)模式
    時(shí)鐘頻率100kHz
    地址長度7bit
    不用填寫設(shè)備地址
取消下方注釋
*/

// extern I2C_HandleTypeDef hi2c2;
// #define MPU6050_I2C_Handle hi2c2
// #define MPU6050_Hardware_I2C

/*
軟件I2C模式
需要:
1.GPIO 2個(gè)
    均為開漏輸出(上不上拉取決于外部電路)
    最高等級
取消下方注釋,按照自己的管腳更改即可
*/

#define MPU6050_Software_I2C

#ifdef MPU6050_Software_I2C
#define I2C_Group_SCL GPIOA // I2C的時(shí)鐘GPIO組號
#define I2C_SCL GPIO_PIN_0  // I2C時(shí)鐘的GPIO端口號

#define I2C_Group_SDA GPIOA // I2C的數(shù)據(jù)GPIO組號
#define I2C_SDA GPIO_PIN_1  // I2C數(shù)據(jù)的GPIO端口號

#define I2C_Write_SCL(x) HAL_GPIO_WritePin(I2C_Group_SCL, I2C_SCL, x)
#define I2C_Write_SDA(x) HAL_GPIO_WritePin(I2C_Group_SDA, I2C_SDA, x)

#define I2C_Read_SCL() HAL_GPIO_ReadPin(I2C_Group_SCL, I2C_SCL)
#define I2C_Read_SDA() HAL_GPIO_ReadPin(I2C_Group_SDA, I2C_SDA)
#endif
#include "mpuiic.h"
#if defined(MPU6050_Software_I2C)
/**
 * @brief 一段延遲
 * @param 無
 * @return 無
 * @author HZ12138
 * @date 2022-07-27 08:53:30
 */
void I2C_Delay()
{
	int z = 0xff;
	while (z--)
		;
}
/**
 * @brief 產(chǎn)生I2C起始信號
 * @param 無
 * @return 無
 * @author HZ12138
 * @date 2022-07-27 08:54:48
 */
void I2C_Start(void)
{
	I2C_Write_SDA(GPIO_PIN_SET);   //需在SCL之前設(shè)定
	I2C_Write_SCL(GPIO_PIN_SET);   // SCL->高
	I2C_Delay();				   //延時(shí)
	I2C_Write_SDA(GPIO_PIN_RESET); // SDA由1->0,產(chǎn)生開始信號
	I2C_Delay();				   //延時(shí)
	I2C_Write_SCL(GPIO_PIN_RESET); // SCL->低
}
/**
 * @brief 產(chǎn)生I2C結(jié)束信號
 * @param 無
 * @return 無
 * @author HZ12138
 * @date 2022-07-27 08:57:03
 */
void I2C_End(void)
{
	I2C_Write_SDA(GPIO_PIN_RESET); //在SCL之前拉低
	I2C_Write_SCL(GPIO_PIN_SET);   // SCL->高
	I2C_Delay();				   //延時(shí)
	I2C_Write_SDA(GPIO_PIN_SET);   // SDA由0->1,產(chǎn)生結(jié)束信號
	I2C_Delay();				   //延時(shí)
}
/**
 * @brief 發(fā)送應(yīng)答碼
 * @param ack:0 應(yīng)答 1 不應(yīng)達(dá)
 * @return 無
 * @author HZ12138
 * @date 2022-07-27 09:03:38
 */
void IIC_Send_ACK(uint8_t ack)
{
	if (ack == 1)
		I2C_Write_SDA(GPIO_PIN_SET); //產(chǎn)生應(yīng)答電平
	else
		I2C_Write_SDA(GPIO_PIN_RESET);
	I2C_Delay();
	I2C_Write_SCL(GPIO_PIN_SET);   //發(fā)送應(yīng)答信號
	I2C_Delay();				   //延時(shí)至少4us
	I2C_Write_SCL(GPIO_PIN_RESET); //整個(gè)期間保持應(yīng)答信號
}
/**
 * @brief 接受應(yīng)答碼
 * @param 無
 * @return 應(yīng)答碼 0 應(yīng)答 1 不應(yīng)達(dá)
 * @author HZ12138
 * @date 2022-07-27 09:04:28
 */
uint8_t IIC_Get_ACK(void)
{
	uint8_t ret;				 //用來接收返回值
	I2C_Write_SDA(GPIO_PIN_SET); //電阻上拉,進(jìn)入讀
	I2C_Delay();
	I2C_Write_SCL(GPIO_PIN_SET); //進(jìn)入應(yīng)答檢測
	I2C_Delay();				 //至少延時(shí)4us
	ret = I2C_Read_SDA();		 //保存應(yīng)答信號
	I2C_Write_SCL(GPIO_PIN_RESET);
	return ret;
}
/**
 * @brief I2C寫1Byte
 * @param dat:1Byte數(shù)據(jù)
 * @return 應(yīng)答結(jié)果 0 應(yīng)答 1 不應(yīng)達(dá)
 * @author HZ12138
 * @date 2022-07-27 09:05:14
 */
uint8_t I2C_SendByte(uint8_t dat)
{
	uint8_t ack;
	for (int i = 0; i < 8; i++)
	{
		// 高在前低在后
		if (dat & 0x80)
			I2C_Write_SDA(GPIO_PIN_SET);
		else
			I2C_Write_SDA(GPIO_PIN_RESET);
		I2C_Delay();
		I2C_Write_SCL(GPIO_PIN_SET);
		I2C_Delay(); //延時(shí)至少4us
		I2C_Write_SCL(GPIO_PIN_RESET);
		dat <<= 1; //低位向高位移動
	}

	ack = IIC_Get_ACK();

	return ack;
}
/**
 * @brief I2C讀取1Byte數(shù)據(jù)
 * @param ack:應(yīng)答 0 應(yīng)答 1 不應(yīng)達(dá)
 * @return 接受到的數(shù)據(jù)
 * @author HZ12138
 * @date 2022-07-27 09:06:13
 */
uint8_t I2C_ReadByte(uint8_t ack)
{
	uint8_t ret = 0;
	// OLED_Read_SDA() 設(shè)置輸入方向
	I2C_Write_SDA(GPIO_PIN_SET);
	for (int i = 0; i < 8; i++)
	{
		ret <<= 1;
		I2C_Write_SCL(GPIO_PIN_SET);
		I2C_Delay();
		// 高在前低在后
		if (I2C_Read_SDA())
		{
			ret++;
		}
		I2C_Write_SCL(GPIO_PIN_RESET);
		I2C_Delay();
	}

	IIC_Send_ACK(ack);

	return ret;
}
#endif
/**
 * @brief MUP6050 I2C連續(xù)寫
 * @param addr:器件地址
 * @param reg:寄存器地址
 * @param len:長度
 * @param buf:緩沖區(qū)地址
 * @return 狀態(tài) 0成功 其他失敗
 * @author HZ12138
 * @date 2022-08-08 15:47:11
 */
uint8_t MPU_Write_Len(uint8_t addr, uint8_t reg, uint8_t len, uint8_t *buf)
{
#if defined(MPU6050_Software_I2C)
	uint8_t i;
	I2C_Start();
	I2C_SendByte((addr << 1) | 0); //發(fā)送器件地址+寫命令
	I2C_SendByte(reg);			   //寫寄存器地址
	for (i = 0; i < len; i++)
	{
		I2C_SendByte(buf[i]); //發(fā)送數(shù)據(jù)
	}
	I2C_End();
	return 0;
#elif defined(MPU6050_Hardware_I2C)
	HAL_I2C_Mem_Write(&MPU6050_I2C_Handle, MPU_WRITE, reg, I2C_MEMADD_SIZE_8BIT, buf, len, 0xfff);
	return 0;
#endif
}
/**
 * @brief MUP6050 I2C連續(xù)讀
 * @param addr:器件地址
 * @param reg:寄存器地址
 * @param len:長度
 * @param buf:緩沖區(qū)地址
 * @return 狀態(tài) 0成功 其他失敗
 * @author HZ12138
 * @date 2022-08-08 15:47:11
 */
uint8_t MPU_Read_Len(uint8_t addr, uint8_t reg, uint8_t len, uint8_t *buf)
{
#if defined(MPU6050_Software_I2C)
	I2C_Start();
	I2C_SendByte((addr << 1) | 0); //發(fā)送器件地址+寫命令
	I2C_SendByte(reg);			   //寫寄存器地址
	I2C_Start();
	I2C_SendByte((addr << 1) | 1); //發(fā)送器件地址+讀命令
	while (len)
	{
		if (len == 1)
			*buf = I2C_ReadByte(1); //讀數(shù)據(jù),發(fā)送nACK
		else
			*buf = I2C_ReadByte(0); //讀數(shù)據(jù),發(fā)送ACK
		len--;
		buf++;
	}
	I2C_End(); //產(chǎn)生一個(gè)停止條件
	return 0;
#elif defined(MPU6050_Hardware_I2C)
	HAL_I2C_Mem_Read(&MPU6050_I2C_Handle, MPU_READ, reg, I2C_MEMADD_SIZE_8BIT, buf, len, 0xfff);
	HAL_Delay(1);
	return 0;
#endif
}
/**
 * @brief MUP6050 I2C寫一個(gè)字節(jié)
 * @param reg:寄存器地址
 * @param data:數(shù)據(jù)
 * @return 狀態(tài) 0成功 其他失敗
 * @author HZ12138
 * @date 2022-08-08 15:47:11
 */
uint8_t MPU_Write_Byte(uint8_t reg, uint8_t data)
{
#if defined(MPU6050_Software_I2C)
	I2C_Start();
	I2C_SendByte((MPU_ADDR << 1) | 0); //發(fā)送器件地址+寫命令
	I2C_SendByte(reg);				   //寫寄存器地址
	I2C_SendByte(data);				   //發(fā)送數(shù)據(jù)
	I2C_End();
	return 0;
#elif defined(MPU6050_Hardware_I2C)
	return HAL_I2C_Mem_Write(&MPU6050_I2C_Handle, (MPU_ADDR << 1), reg, 1, &data, 1, 0xfff);
#endif
}
/**
 * @brief MUP6050 I2C寫一個(gè)字節(jié)
 * @param reg:寄存器地址
 * @return 讀取到的數(shù)據(jù)
 * @author HZ12138
 * @date 2022-08-08 15:47:11
 */
uint8_t MPU_Read_Byte(uint8_t reg)
{
#if defined(MPU6050_Software_I2C)
	uint8_t res;
	I2C_Start();
	I2C_SendByte((MPU_ADDR << 1) | 0); //發(fā)送器件地址+寫命令
	I2C_SendByte(reg);				   //寫寄存器地址
	I2C_Start();
	I2C_SendByte((MPU_ADDR << 1) | 1); //發(fā)送器件地址+讀命令
	res = I2C_ReadByte(1);			   //讀取數(shù)據(jù),發(fā)送nACK
	I2C_End();						   //產(chǎn)生一個(gè)停止條件
	return res;
#elif defined(MPU6050_Hardware_I2C)
	uint8_t zj;
	HAL_I2C_Mem_Read(&MPU6050_I2C_Handle, (MPU_ADDR << 1), reg, 1, &zj, 1, 0xfff);
	return zj;
#endif
}

特別注意:使用軟件I2C時(shí)請注意延遲函數(shù),不要過快(通信失敗),不要過慢(通信時(shí)間長)void I2C_Delay()

MPU6050設(shè)置

這部分是借鑒自正點(diǎn)原子的內(nèi)容

#include "mpu6050.h"
#include "delay.h"
#include "usart.h"
#include "i2c.h"
#include "Print.h"
/**
 * @brief 初始化MPU6050
 * @param 無
 * @return 狀態(tài) 0成功 其他失敗
 * @author HZ12138
 * @date 2022-08-08 14:51:59
 */
uint8_t MPU_Init(void)
{
	MPU_Write_Byte(MPU_PWR_MGMT1_REG, 0X80); //復(fù)位MPU6050
	HAL_Delay(100);
	MPU_Write_Byte(MPU_PWR_MGMT1_REG, 0X00); //喚醒MPU6050
	MPU_Set_Gyro_Fsr(3);					 //陀螺儀傳感器,±2000dps
	MPU_Set_Accel_Fsr(0);					 //加速度傳感器,±2g
	MPU_Set_Rate(50);						 //設(shè)置采樣率50Hz
	MPU_Write_Byte(MPU_INT_EN_REG, 0X00);	 //關(guān)閉所有中斷
	MPU_Write_Byte(MPU_USER_CTRL_REG, 0X00); // I2C主模式關(guān)閉
	MPU_Write_Byte(MPU_FIFO_EN_REG, 0X00);	 //關(guān)閉FIFO
	MPU_Write_Byte(MPU_INTBP_CFG_REG, 0X80); // INT引腳低電平有效
	MPU_Read_Byte(MPU_DEVICE_ID_REG);
	MPU_Write_Byte(MPU_PWR_MGMT1_REG, 0X01); //設(shè)置CLKSEL,PLL X軸為參考
	MPU_Write_Byte(MPU_PWR_MGMT2_REG, 0X00); //加速度與陀螺儀都工作
	MPU_Set_Rate(200);						 //設(shè)置采樣率為50Hz
	return 0;
}
//設(shè)置MPU6050陀螺儀傳感器滿量程范圍
// fsr:0,±250dps;1,±500dps;2,±1000dps;3,±2000dps
//返回值:0,設(shè)置成功
//    其他,設(shè)置失敗
uint8_t MPU_Set_Gyro_Fsr(uint8_t fsr)
{
	return MPU_Write_Byte(MPU_GYRO_CFG_REG, fsr << 3); //設(shè)置陀螺儀滿量程范圍
}
//設(shè)置MPU6050加速度傳感器滿量程范圍
// fsr:0,±2g;1,±4g;2,±8g;3,±16g
//返回值:0,設(shè)置成功
//    其他,設(shè)置失敗
uint8_t MPU_Set_Accel_Fsr(uint8_t fsr)
{
	return MPU_Write_Byte(MPU_ACCEL_CFG_REG, fsr << 3); //設(shè)置加速度傳感器滿量程范圍
}
//設(shè)置MPU6050的數(shù)字低通濾波器
// lpf:數(shù)字低通濾波頻率(Hz)
//返回值:0,設(shè)置成功
//    其他,設(shè)置失敗
uint8_t MPU_Set_LPF(uint16_t lpf)
{
	uint8_t data = 0;
	if (lpf >= 188)
		data = 1;
	else if (lpf >= 98)
		data = 2;
	else if (lpf >= 42)
		data = 3;
	else if (lpf >= 20)
		data = 4;
	else if (lpf >= 10)
		data = 5;
	else
		data = 6;
	return MPU_Write_Byte(MPU_CFG_REG, data); //設(shè)置數(shù)字低通濾波器
}
//設(shè)置MPU6050的采樣率(假定Fs=1KHz)
// rate:4~1000(Hz)
//返回值:0,設(shè)置成功
//    其他,設(shè)置失敗
uint8_t MPU_Set_Rate(uint16_t rate)
{
	uint8_t data;
	if (rate > 1000)
		rate = 1000;
	if (rate < 4)
		rate = 4;
	data = 1000 / rate - 1;
	data = MPU_Write_Byte(MPU_SAMPLE_RATE_REG, data); //設(shè)置數(shù)字低通濾波器
	return MPU_Set_LPF(rate / 2);					  //自動設(shè)置LPF為采樣率的一半
}

//得到溫度值
//返回值:溫度值(擴(kuò)大了100倍)
short MPU_Get_Temperature(void)
{
	uint8_t buf[2];
	short raw;
	float temp;
	MPU_Read_Len(MPU_ADDR, MPU_TEMP_OUTH_REG, 2, buf);
	raw = ((uint16_t)buf[0] << 8) | buf[1];
	temp = 36.53 + ((double)raw) / 340;
	return temp * 100;
	;
}
//得到陀螺儀值(原始值)
// gx,gy,gz:陀螺儀x,y,z軸的原始讀數(shù)(帶符號)
//返回值:0,成功
//    其他,錯(cuò)誤代碼
uint8_t MPU_Get_Gyroscope(short *gx, short *gy, short *gz)
{
	uint8_t buf[6], res;
	res = MPU_Read_Len(MPU_ADDR, MPU_GYRO_XOUTH_REG, 6, buf);
	if (res == 0)
	{
		*gx = ((uint16_t)buf[0] << 8) | buf[1];
		*gy = ((uint16_t)buf[2] << 8) | buf[3];
		*gz = ((uint16_t)buf[4] << 8) | buf[5];
	}
	return res;
}
//得到加速度值(原始值)
// gx,gy,gz:陀螺儀x,y,z軸的原始讀數(shù)(帶符號)
//返回值:0,成功
//    其他,錯(cuò)誤代碼
uint8_t MPU_Get_Accelerometer(short *ax, short *ay, short *az)
{
	uint8_t buf[6], res;
	res = MPU_Read_Len(MPU_ADDR, MPU_ACCEL_XOUTH_REG, 6, buf);
	if (res == 0)
	{
		*ax = ((uint16_t)buf[0] << 8) | buf[1];
		*ay = ((uint16_t)buf[2] << 8) | buf[3];
		*az = ((uint16_t)buf[4] << 8) | buf[5];
	}
	return res;
	;
}

比較常用的是

short MPU_Get_Temperature(void) 獲取溫度

uint8_t MPU_Get_Gyroscope(short *gx, short *gy, short *gz)獲取角加速度

uint8_t MPU_Get_Accelerometer(short *ax, short *ay, short *az)獲取線加速度

這是MPU6050的初始化函數(shù),將器件ID的校驗(yàn)去掉了(因?yàn)槲疫@邊有個(gè)品牌的芯片讀取ID不正確但可以正常使用)

在程序開始時(shí)調(diào)用即可

uint8_t MPU_Init(void)

DMP設(shè)置

這部分是來自官方庫

DMP部分是不開源的,不然也不需要使用官方庫了

需要更改inv_mpu.c里的幾個(gè)API,關(guān)于時(shí)間,I2C和打印信息的部分

【STM32F4系列】【HAL庫】【模塊介紹】MPU6050設(shè)置與DMP庫使用

需要將int mpu_init(void)函數(shù)(在inv_mpu.c)中的這段注釋并改成這個(gè)(光標(biāo)選中的)

【STM32F4系列】【HAL庫】【模塊介紹】MPU6050設(shè)置與DMP庫使用

重寫讀取歐拉角和初始化函數(shù),主要是去掉了幾個(gè)驗(yàn)證

/**
 * @brief 初始化DMP
 * @param 無
 * @return 狀態(tài) 0成功 其他失敗
 * @author HZ12138
 * @date 2022-08-08 14:50:05
 */
uint8_t mpu_dmp_init(void)
{
    uint8_t res = 0;
    if (mpu_init() == 0) //初始化MPU6050
    {
        res = mpu_set_sensors(INV_XYZ_GYRO | INV_XYZ_ACCEL); //設(shè)置所需要的傳感器
        if (res)
            return 1;
        res = mpu_configure_fifo(INV_XYZ_GYRO | INV_XYZ_ACCEL); //設(shè)置FIFO
        if (res)
            return 2;
        res = mpu_set_sample_rate(DEFAULT_MPU_HZ); //設(shè)置采樣率
        if (res)
            return 3;
        res = dmp_load_motion_driver_firmware(); //加載dmp固件
        if (res)
            return 4;
        res = dmp_set_orientation(inv_orientation_matrix_to_scalar(gyro_orientation)); //設(shè)置陀螺儀方向
        if (res)
            return 5;
        res = dmp_enable_feature(DMP_FEATURE_6X_LP_QUAT | DMP_FEATURE_TAP | //設(shè)置dmp功能
                                 DMP_FEATURE_ANDROID_ORIENT | DMP_FEATURE_SEND_RAW_ACCEL | DMP_FEATURE_SEND_CAL_GYRO |
                                 DMP_FEATURE_GYRO_CAL);
        if (res)
            return 6;
        res = dmp_set_fifo_rate(DEFAULT_MPU_HZ); //設(shè)置DMP輸出速率(最大不超過200Hz)
        if (res)
            return 7;
        res = run_self_test();      //自檢
                                    //	if(res)return 8;
        res = mpu_set_dmp_state(1); //使能DMP
        if (res)
            return 9;
    }
    else
        return 10;
    return 0;
}
/**
 * @brief 得到DMP處理后的歐拉角
 * @param pitch:俯仰角( -90° - 90° )
 * @param roll:橫滾角( -180° - 180° )
 * @param yaw:航向角( -180° - 180° )
 * @return 狀態(tài) 0成功 其他失敗
 * @author HZ12138
 * @date 2022-08-08 14:46:44
 */
uint8_t mpu_dmp_get_data(float *pitch, float *roll, float *yaw)
{
    float q0 = 1.0f, q1 = 0.0f, q2 = 0.0f, q3 = 0.0f;
    unsigned long sensor_timestamp;
    short gyro[3], accel[3], sensors;
    unsigned char more;
    long quat[4];
    if (dmp_read_fifo(gyro, accel, quat, &sensor_timestamp, &sensors, &more))
        return 1;
    /* Gyro and accel data are written to the FIFO by the DMP in chip frame and hardware units.
     * This behavior is convenient because it keeps the gyro and accel outputs of dmp_read_fifo and mpu_read_fifo consistent.
     **/
    /*if (sensors & INV_XYZ_GYRO )
    send_packet(PACKET_TYPE_GYRO, gyro);
    if (sensors & INV_XYZ_ACCEL)
    send_packet(PACKET_TYPE_ACCEL, accel); */
    /* Unlike gyro and accel, quaternions are written to the FIFO in the body frame, q30.
     * The orientation is set by the scalar passed to dmp_set_orientation during initialization.
     **/
    if (sensors & INV_WXYZ_QUAT)
    {
        q0 = quat[0] / q30; // q30格式轉(zhuǎn)換為浮點(diǎn)數(shù)
        q1 = quat[1] / q30;
        q2 = quat[2] / q30;
        q3 = quat[3] / q30;
        //計(jì)算得到俯仰角/橫滾角/航向角
        *pitch = asin(-2 * q1 * q3 + 2 * q0 * q2) * 57.3;                                    // pitch
        *roll = atan2(2 * q2 * q3 + 2 * q0 * q1, -2 * q1 * q1 - 2 * q2 * q2 + 1) * 57.3;     // roll
        *yaw = atan2(2 * (q1 * q2 + q0 * q3), q0 * q0 + q1 * q1 - q2 * q2 - q3 * q3) * 57.3; // yaw
    }
    else
        return 2;
    return 0;
}

其他部分來自大魚電子的移植庫,無其他修改了

常用的函數(shù)就2個(gè)

DMP初始化函數(shù)

uint8_t mpu_dmp_init(void)

獲取歐拉角函數(shù)

uint8_t mpu_dmp_get_data(float *pitch, float *roll, float *yaw)

注意

1 通過DMP解算出的歐拉角順序是 Z-Y-X (這個(gè)很重要)

2.因?yàn)闆]有地磁計(jì),所以z(yow)的零點(diǎn)漂移會很嚴(yán)重,基本上沒法看

3.mpu6050是相對位置,是基于上電時(shí)的位置計(jì)算的(但是好像DMP有自己的修正算法,可以讓數(shù)據(jù)幾乎保持絕對)

4.盡量在水平位置上電,即使dmp有修正也會出現(xiàn)10°以上的誤差

成品

GitHub

百度網(wǎng)盤文章來源地址http://www.zghlxwxcb.cn/news/detail-446219.html

到了這里,關(guān)于【STM32F4系列】【HAL庫】【模塊介紹】MPU6050設(shè)置與DMP庫使用的文章就介紹完了。如果您還想了解更多內(nèi)容,請?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來自互聯(lián)網(wǎng)用戶投稿,該文觀點(diǎn)僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務(wù),不擁有所有權(quán),不承擔(dān)相關(guān)法律責(zé)任。如若轉(zhuǎn)載,請注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實(shí)不符,請點(diǎn)擊違法舉報(bào)進(jìn)行投訴反饋,一經(jīng)查實(shí),立即刪除!

領(lǐng)支付寶紅包贊助服務(wù)器費(fèi)用

相關(guān)文章

  • 【STM32】I2C練習(xí),HAL庫讀取MPU6050角度陀螺儀

    【STM32】I2C練習(xí),HAL庫讀取MPU6050角度陀螺儀

    MPU-6000(6050)為全球首例整合性6軸運(yùn)動處理組件,相較于多組件方案,免除了組合陀螺儀與加速器時(shí)間軸之差的問題,減少了大量的封裝空間。當(dāng)連接到三軸磁強(qiáng)計(jì)時(shí),MPU-60X0提供完整的9軸運(yùn)動融合輸出到其主I2C或SPI端口(SPI僅在MPU-6000上可用)。 寄存器地址 寄存器內(nèi)容 0X3B

    2024年02月16日
    瀏覽(28)
  • STM32F103C8驅(qū)動MPU6050姿態(tài)與tofsense報(bào)警 (一)

    本工程是實(shí)現(xiàn)STM32F103C8獲取 mpu6050歐拉角(pitch ,roll,yow) mpu6050自帶的dmp? 第一步:設(shè)置串口 #if EN_USART1_RX ? //如果使能了接收 //串口1中斷服務(wù)程序 //注意,讀取USARTx-SR能避免莫名其妙的錯(cuò)誤 ? ?? ? u8 USART_RX_BUF[USART_REC_LEN]; ? ? //接收緩沖,最大USART_REC_LEN個(gè)字節(jié). //接收狀態(tài) //bit15,

    2024年01月17日
    瀏覽(18)
  • STM32F407硬件I2C實(shí)現(xiàn)MPU6050通訊(CUBEIDE)

    STM32F407硬件I2C實(shí)現(xiàn)MPU6050通訊(CUBEIDE)

    工程代碼 https://download.csdn.net/download/weixin_52849254/87886714 I2C1通道可選擇三種不同的通訊協(xié)議:I2C、SMBus-Alert-mode、SMBus-two-wire-Interface。 SMBus (System Management Bus,系統(tǒng)管理總線), 為系統(tǒng)和電源管理這樣的任務(wù)提供了一條控制總線,SMBus與I2C總線之間在時(shí)序特性上存在一些差別 修改

    2024年02月09日
    瀏覽(17)
  • STM32F103C8驅(qū)動MPU6050姿態(tài)與tofsense報(bào)警 (六)

    主函數(shù) int main(void)? {?? ? ?? ?//RCC_Configuration(); //時(shí)鐘設(shè)置 ?? ? ?? ?//BUZZER_BEEP1();//蜂鳴器音1 ?? ??? ?//BUZZER_BEEP1();//蜂鳴器音1 ? ? //delay_ms(50); ?? ?SYS_Init();//系統(tǒng)初始化總函數(shù) ?? ?while(1) ? //主循環(huán) ?? ?{ ?? ? // BUZZER_BEEP1();//蜂鳴器音1 ?? ??? ?MPU_Read(); ? ?//MP

    2024年01月17日
    瀏覽(17)
  • mpu6050六軸陀螺儀dmp姿態(tài)解算-C語言移植(stm32+hal)

    mpu6050六軸陀螺儀dmp姿態(tài)解算-C語言移植(stm32+hal)

    官方庫源文件: 1 移植官方6個(gè)庫文件 2 修改inv_mpu.h中結(jié)構(gòu)體 3 修改inv_mpu.c 4 修改 inv_mpu_motion_driver.c 5 keil中增加宏定義 6 移植核心[修改inv_mpu.c|inv_mpu_motion_driver.c]

    2024年02月14日
    瀏覽(20)
  • STM32外設(shè)系列—MPU6050角度傳感器

    STM32外設(shè)系列—MPU6050角度傳感器

    ?? 文章作者:二土電子 ?? 關(guān)注公眾號獲取更多資料! ?? 期待大家一起學(xué)習(xí)交流! ??MPU6050是由InvenSense公司生產(chǎn)的全球首款整合性六軸運(yùn)動處理模塊,它可以實(shí)時(shí)獲取運(yùn)動物體的在三維坐標(biāo)系內(nèi)的偏轉(zhuǎn)角度,如圖所示。 ??其中roll為繞X軸偏轉(zhuǎn)的角度,pitch為繞Y軸偏轉(zhuǎn)

    2024年02月03日
    瀏覽(25)
  • 【stm32開發(fā)筆記】基于HAL庫的STM32F4添加DSP庫

    【stm32開發(fā)筆記】基于HAL庫的STM32F4添加DSP庫

    本文分兩種方法添加DSP庫:1.CubeMX直接配置ioc添加; 2.KEIL內(nèi)添加; 簡述:補(bǔ)齊全部lib庫-添加DSP包-使能DSP勾選-添加頭文件及魔術(shù)棒配置-測試 1.補(bǔ)齊lib庫。( 如果使用直接默認(rèn)添加的庫,是不支持FPU的,所以需要補(bǔ)齊后找到所需的lib文件進(jìn)行替換,在MX的工程管理欄,選擇復(fù)制所

    2024年02月16日
    瀏覽(145)
  • 【STM32+cubemx】0027 HAL庫開發(fā):MPU6050陀螺儀和加速度計(jì)數(shù)據(jù)的獲取和校準(zhǔn)

    【STM32+cubemx】0027 HAL庫開發(fā):MPU6050陀螺儀和加速度計(jì)數(shù)據(jù)的獲取和校準(zhǔn)

    在制作平衡車或者飛行器時(shí),不可避免地需要知道設(shè)備本身的姿態(tài),一般我們使用陀螺儀和加速度計(jì)來獲取這些信息。 陀螺儀用來測量物體的角度。傳統(tǒng)的機(jī)械式陀螺的原理,和我們小時(shí)候玩的陀螺一樣,是利用了高速旋轉(zhuǎn)的物體能保持軸線穩(wěn)定的特性;機(jī)械式陀螺需要的加

    2023年04月08日
    瀏覽(22)
  • 學(xué)習(xí)記錄之STM32F103C8T6最小系統(tǒng)板驅(qū)動MPU6050串口打印數(shù)據(jù)

    學(xué)習(xí)記錄之STM32F103C8T6最小系統(tǒng)板驅(qū)動MPU6050串口打印數(shù)據(jù)

    1.使用到的工具介紹 2.MPU6050和整體和簡單介紹 3.程序的介紹 1.使用到的工具介紹 硬件方面:STM32F103C8T6最小系統(tǒng)板核心板,MPU6050模塊三維角度傳感器,經(jīng)典的CH340燒寫和串口作用,和若干個(gè)杜邦線。 軟件方面:keil5編寫程序軟件,燒寫軟件FlyMcu.exe燒寫工具,sscom.exe串口調(diào)試工

    2023年04月09日
    瀏覽(21)
  • STM32 HAL庫 PWM+DMA 驅(qū)動WS2812B彩燈(STM32F030F4P6)

    STM32 HAL庫 PWM+DMA 驅(qū)動WS2812B彩燈(STM32F030F4P6)

    博主使用STM32驅(qū)動WS2812B主要參考了這位佬的文章,因?yàn)樾枨髥栴},采用了Cortex-M0的stm32f030f4p6(16k的flash,4k的sram)來驅(qū)動,原文中寫的是stm32f103c8t6,個(gè)人認(rèn)為其實(shí)區(qū)別并不是很大,需要修改部分參數(shù)即可移植(cv戰(zhàn)士申請出戰(zhàn))。 上圖是我的一圈燈,一共8個(gè),第一個(gè)LED的數(shù)

    2024年02月06日
    瀏覽(48)

覺得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包