这里推荐一个 人工智能(AI)的学习网站 点击这里进入。
机器学习能以简单、快速、经济划算的方式来改进许多应用。博主今年立的 Flag 就是进入 AI 知识的学习。 也在此网站上学习过一些,后面也会输出一些学习心得。
QMI8658 传感的相关参数介绍在这里不摘抄,详细请查阅数据手册。在这里重点提一下 AttitudeEngine 。
QMI8658集成了称为 AttitudeEngine 的高级矢量数字信号处理器 (DSP) 运动协处理器。 AttitudeEngine 以高内部采样率有效地编码高频运动,在较低频率的输出数据速率下保持完全的准确性。这使应用程序能够利用低输出数据速率 (ODR) 或按需(主机轮询),同时仍能获取准确的 3D 运动数据。 AttitudeEngine 可减少主机处理器上的数据处理和中断负载,而不会影响 3D 运动跟踪精度。
QMI8658 可以与 (LSM6DSM/ICM20690) Pin-To-Pin 兼容设计
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;
}
- I2c_addr:
write 0x6B(SA0 = 0) / 0x6A (SA0 = 1)- 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; /开启加速度计和陀螺仪/- Sensor Data Lock register:
0x2D[bit1 bit0] Sensor Data Available and lock:
“0x00”: no new data; “0x03": Sensor Data Locked for reading;- Read output data register:
0x35~0x40- 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;
}
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]];
}
视频展示
QMI8658-6D传感器波形输出