QMI8658 - 姿态传感器学习笔记 - Ⅰ

文章目录

    • 0. 说在最前面
    • 1. 前言
    • 2. QMI8658 Pin
      • 2.1 引脚说明
      • 2.2 Pin-To-Pin
    • 3. 参考设计图
      • 3.1 QMI8658-I2C
      • 3.2 QMI8658-4线SPI
      • 3.3 QMI8658-3线SPI![在这里插入图片描述](https://img-blog.csdnimg.cn/2660ca65786a456d87381d71d47341ca.png)
      • 3.3 QMI8658 操作流程
      • 3.1 I2C 接口
      • 3.2 Qmi8658 初始化
      • 3.3 读取加速度与陀螺数据原始数据
    • 4. 民间模块
      • 4.1 [**模块获取链接**](https://item.taobao.com/item.htm?spm=a1z10.1-c-s.w4004-12236672109.13.81875d442oe1VK&id=679052865814)
      • 4.2 模块资料更新记录

0. 说在最前面

这里推荐一个 人工智能(AI)的学习网站 点击这里进入。
机器学习能以简单、快速、经济划算的方式来改进许多应用。博主今年立的 Flag 就是进入 AI 知识的学习。 也在此网站上学习过一些,后面也会输出一些学习心得。

1. 前言

QMI8658 传感的相关参数介绍在这里不摘抄,详细请查阅数据手册。在这里重点提一下 AttitudeEngine 。
QMI8658集成了称为 AttitudeEngine 的高级矢量数字信号处理器 (DSP) 运动协处理器。 AttitudeEngine 以高内部采样率有效地编码高频运动,在较低频率的输出数据速率下保持完全的准确性。这使应用程序能够利用低输出数据速率 (ODR) 或按需(主机轮询),同时仍能获取准确的 3D 运动数据。 AttitudeEngine 可减少主机处理器上的数据处理和中断负载,而不会影响 3D 运动跟踪精度。

2. QMI8658 Pin

2.1 引脚说明

QMI8658 - 姿态传感器学习笔记 - Ⅰ_第1张图片
QMI8658 - 姿态传感器学习笔记 - Ⅰ_第2张图片

2.2 Pin-To-Pin

QMI8658 可以与 (LSM6DSM/ICM20690) Pin-To-Pin 兼容设计

3. 参考设计图

3.1 QMI8658-I2C

QMI8658 - 姿态传感器学习笔记 - Ⅰ_第3张图片

3.2 QMI8658-4线SPI

QMI8658 - 姿态传感器学习笔记 - Ⅰ_第4张图片

3.3 QMI8658-3线SPIQMI8658 - 姿态传感器学习笔记 - Ⅰ_第5张图片

3.3 QMI8658 操作流程

QMI8658 - 姿态传感器学习笔记 - Ⅰ_第6张图片

3.1 I2C 接口

unsigned char Qmi8658_write_reg(unsigned char reg, unsigned char value)
{
	unsigned char ret=0;
	unsigned int retry = 0;

	while((!ret) && (retry++ < 5))
	{
		ret = i2c1_write_reg(NULL,qmi8658_slave_addr << 1, reg, &value,1);
	}
	return ret;
}

unsigned char Qmi8658_read_reg(unsigned char reg, unsigned char* buf, unsigned short len)
{
	unsigned char ret=0;
	unsigned int retry = 0;

	while((!ret) && (retry++ < 5))
	{
		ret = i2c1_read_reg(NULL,qmi8658_slave_addr << 1, reg, buf, len);
	}
	return ret;
}

3.2 Qmi8658 初始化

  1. I2c_addr:
    write 0x6B(SA0 = 0) / 0x6A (SA0 = 1)
  2. Init_Configure:
    0x0A= 0xA2; /selftest/
    dealy_ms(1750); /延时1.75s以上:根据MCU,需要调整延时时间/
    0x02 = 0x60; /配置I2C通信模式/
    0x03 = 0xxx; /配置加速度计数据Range和ODR/
    0x04 = 0xxx; /配置陀螺仪数据Range和ODR/
    0x06 = 0xxx; /开启加速度计和陀螺仪低通滤波LPF滤波截止频率/
    0x08 = 0x03; /开启加速度计和陀螺仪/
  3. Sensor Data Lock register:
    0x2D[bit1 bit0] Sensor Data Available and lock:
    “0x00”: no new data; “0x03": Sensor Data Locked for reading;
  4. Read output data register:
    0x35~0x40
  5. Output register:
    First byte is LSB, second byte is MSB.
unsigned char Qmi8658_init(void)
{
	unsigned char qmi8658_chip_id = 0x00;
	unsigned char qmi8658_revision_id = 0x00;
	unsigned char qmi8658_slave[2] = {QMI8658_SLAVE_ADDR_L, QMI8658_SLAVE_ADDR_H};
	unsigned char iCount = 0;

	while((qmi8658_chip_id == 0x00)&&(iCount<2))
	{
		qmi8658_slave_addr = qmi8658_slave[iCount];
		Qmi8658_read_reg(Qmi8658Register_WhoAmI, &qmi8658_chip_id, 1);
		if(qmi8658_chip_id == 0x05)
			break;
		iCount++;
	}
	
	Qmi8658_read_reg(Qmi8658Register_Revision, &qmi8658_revision_id, 1);
	
	if(qmi8658_chip_id == 0x05)
	{
		qmi8658_printf("Qmi8658_init slave=0x%x  Qmi8658Register_WhoAmI=0x%x 0x%x\n", qmi8658_slave_addr,qmi8658_chip_id,qmi8658_revision_id);
		Qmi8658_write_reg(Qmi8658Register_Ctrl1, 0x60);
		qmi8658_config.inputSelection = QMI8658_CONFIG_ACCGYR_ENABLE;//QMI8658_CONFIG_ACCGYR_ENABLE;
		qmi8658_config.accRange = Qmi8658AccRange_2g;
		qmi8658_config.accOdr = Qmi8658AccOdr_500Hz;
		qmi8658_config.gyrRange = Qmi8658GyrRange_64dps;		//Qmi8658GyrRange_2048dps   Qmi8658GyrRange_1024dps
		qmi8658_config.gyrOdr = Qmi8658GyrOdr_500Hz;
		qmi8658_config.magOdr = Qmi8658MagOdr_125Hz;
		qmi8658_config.magDev = MagDev_AKM09918;
		qmi8658_config.aeOdr = Qmi8658AeOdr_128Hz;

		Qmi8658_Config_apply(&qmi8658_config);
		
		Qmi8658_write_reg(Qmi8658Register_Ctrl5, 0x55);
		
		if(1)
		{
			unsigned char read_data = 0x00;
			unsigned char firmware[3] = {0x00};
			Qmi8658_read_reg(Qmi8658Register_Ctrl1, &read_data, 1);
			qmi8658_printf("Qmi8658Register_Ctrl1=0x%x \n", read_data);
			Qmi8658_read_reg(Qmi8658Register_Ctrl2, &read_data, 1);
			qmi8658_printf("Qmi8658Register_Ctrl2=0x%x \n", read_data);
			Qmi8658_read_reg(Qmi8658Register_Ctrl3, &read_data, 1);
			qmi8658_printf("Qmi8658Register_Ctrl3=0x%x \n", read_data);
			Qmi8658_read_reg(Qmi8658Register_Ctrl4, &read_data, 1);
			qmi8658_printf("Qmi8658Register_Ctrl4=0x%x \n", read_data);
			Qmi8658_read_reg(Qmi8658Register_Ctrl5, &read_data, 1);
			qmi8658_printf("Qmi8658Register_Ctrl5=0x%x \n", read_data);
			Qmi8658_read_reg(Qmi8658Register_Ctrl6, &read_data, 1);
			qmi8658_printf("Qmi8658Register_Ctrl6=0x%x \n", read_data);
			Qmi8658_read_reg(Qmi8658Register_Ctrl7, &read_data, 1);
			qmi8658_printf("Qmi8658Register_Ctrl7=0x%x \n", read_data);
			
			Qmi8658_read_reg(0x49, firmware, 3);
			qmi8658_printf("Qmi8658_firmware =0x%x 0x%x 0x%x\n", firmware[0], firmware[1], firmware[2]);
		}
//		Qmi8658_set_layout(2);
		return 1;
	}
	else
	{
		qmi8658_printf("Qmi8658_init fail\n");
		qmi8658_chip_id = 0;
		return 0;
	}
	//return qmi8658_chip_id;
}

3.3 读取加速度与陀螺数据原始数据

void Qmi8658_read_xyz(float acc[3], float gyro[3], unsigned int *tim_count)
{
	unsigned char	buf_reg[12];
	short 			raw_acc_xyz[3];
	short 			raw_gyro_xyz[3];
//	float acc_t[3];
//	float gyro_t[3];

	if(tim_count)
	{
		unsigned char	buf[3];
		unsigned int timestamp;
		Qmi8658_read_reg(Qmi8658Register_Timestamp_L, buf, 3);	// 0x18	24
		timestamp = (unsigned int)(((unsigned int)buf[2]<<16)|((unsigned int)buf[1]<<8)|buf[0]);
		if(timestamp > imu_timestamp)
			imu_timestamp = timestamp;
		else
			imu_timestamp = (timestamp+0x1000000-imu_timestamp);

		*tim_count = imu_timestamp;		
	}
	
	Qmi8658_read_reg(Qmi8658Register_Ax_L, buf_reg, 12); 	// 0x19, 25
	raw_acc_xyz[0] = (short)((unsigned short)(buf_reg[1]<<8) |( buf_reg[0]));
	raw_acc_xyz[1] = (short)((unsigned short)(buf_reg[3]<<8) |( buf_reg[2]));
	raw_acc_xyz[2] = (short)((unsigned short)(buf_reg[5]<<8) |( buf_reg[4]));

	raw_gyro_xyz[0] = (short)((unsigned short)(buf_reg[7]<<8) |( buf_reg[6]));
	raw_gyro_xyz[1] = (short)((unsigned short)(buf_reg[9]<<8) |( buf_reg[8]));
	raw_gyro_xyz[2] = (short)((unsigned short)(buf_reg[11]<<8) |( buf_reg[10]));
	
	qmi8658_printf("%d %d %d %d %d %d\n", raw_acc_xyz[0], raw_acc_xyz[1], raw_acc_xyz[2], raw_gyro_xyz[0], raw_gyro_xyz[1], raw_gyro_xyz[2]);

#if defined(QMI8658_UINT_MG_DPS)
	// mg
	acc[AXIS_X] = (float)(raw_acc_xyz[AXIS_X]*1000.0f)/acc_lsb_div;
	acc[AXIS_Y] = (float)(raw_acc_xyz[AXIS_Y]*1000.0f)/acc_lsb_div;
	acc[AXIS_Z] = (float)(raw_acc_xyz[AXIS_Z]*1000.0f)/acc_lsb_div;
#else
	// m/s2
	acc[AXIS_X] = (float)(raw_acc_xyz[AXIS_X]*ONE_G)/acc_lsb_div;
	acc[AXIS_Y] = (float)(raw_acc_xyz[AXIS_Y]*ONE_G)/acc_lsb_div;
	acc[AXIS_Z] = (float)(raw_acc_xyz[AXIS_Z]*ONE_G)/acc_lsb_div;
#endif
//	acc[AXIS_X] = imu_map.sign[AXIS_X]*acc_t[imu_map.map[AXIS_X]];
//	acc[AXIS_Y] = imu_map.sign[AXIS_Y]*acc_t[imu_map.map[AXIS_Y]];
//	acc[AXIS_Z] = imu_map.sign[AXIS_Z]*acc_t[imu_map.map[AXIS_Z]];

#if defined(QMI8658_UINT_MG_DPS)
	// dps
	gyro[0] = (float)(raw_gyro_xyz[0]*1.0f)/gyro_lsb_div;
	gyro[1] = (float)(raw_gyro_xyz[1]*1.0f)/gyro_lsb_div;
	gyro[2] = (float)(raw_gyro_xyz[2]*1.0f)/gyro_lsb_div;
#else
	// rad/s
	gyro[AXIS_X] = (float)(raw_gyro_xyz[AXIS_X]*0.01745f)/gyro_lsb_div;		// *pi/180
	gyro[AXIS_Y] = (float)(raw_gyro_xyz[AXIS_Y]*0.01745f)/gyro_lsb_div;
	gyro[AXIS_Z] = (float)(raw_gyro_xyz[AXIS_Z]*0.01745f)/gyro_lsb_div;
#endif	
//	gyro[AXIS_X] = imu_map.sign[AXIS_X]*gyro_t[imu_map.map[AXIS_X]];
//	gyro[AXIS_Y] = imu_map.sign[AXIS_Y]*gyro_t[imu_map.map[AXIS_Y]];
//	gyro[AXIS_Z] = imu_map.sign[AXIS_Z]*gyro_t[imu_map.map[AXIS_Z]];
}

4. 民间模块

4.1 模块获取链接

QMI8658 - 姿态传感器学习笔记 - Ⅰ_第7张图片

4.2 模块资料更新记录

QMI8658 - 姿态传感器学习笔记 - Ⅰ_第8张图片

  • 零偏标定算法效果展示

视频展示

QMI8658-6D传感器波形输出

你可能感兴趣的:(MEMS,传感器,-,6轴姿态传感器)