锐单电子商城 , 一站式电子元器件采购平台!
  • 电话:400-990-0325

QMI8658 - 6轴传感器学习笔记

时间:2022-10-30 15:30:00 传感器lsb

文章目录

    • 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. 民间模块

1. 前言

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

2. QMI8658 Pin

2.1 引脚说明

在这里插入图片描述

2.2 Pin-To-Pin

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

3. 参考设计图

3.1 QMI8658-I2C

3.2 QMI8658-4线SPI

3.3 QMI8658-3线SPI

3.3 QMI8658 操作流程

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) { 
          unsiged 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. 民间模块

模块获取链接

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

相关文章