LSM6DS3 gyro数据设置

本文介绍LSM6DS3传感器驱动程序中的数据结构、初始化过程及数据获取方法,并详细解析了HAL层的数据转换流程,包括角度速度单位转换、坐标系旋转以及数据校准等关键步骤。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一   Driver:

1  数据结构
lsm6ds3_core.c 定义了两个结构体

static const struct lsm6ds3_odr_table {
    u8 addr[2];
    u8 mask[2];
    struct lsm6ds3_odr_reg odr_avl[6];
} lsm6ds3_odr_table = {
    .addr[LSM6DS3_ACCEL] = LSM6DS3_ACC_ODR_ADDR,
    .mask[LSM6DS3_ACCEL] = LSM6DS3_ACC_ODR_MASK,
    .addr[LSM6DS3_GYRO] = LSM6DS3_GYR_ODR_ADDR,
    .mask[LSM6DS3_GYRO] = LSM6DS3_GYR_ODR_MASK,
    .odr_avl[0] = { .hz = 13, .value = LSM6DS3_ODR_13HZ_VAL },
    .odr_avl[1] = { .hz = 26, .value = LSM6DS3_ODR_26HZ_VAL },
    .odr_avl[2] = { .hz = 52, .value = LSM6DS3_ODR_52HZ_VAL },
    .odr_avl[3] = { .hz = 104, .value = LSM6DS3_ODR_104HZ_VAL },
    .odr_avl[4] = { .hz = 208, .value = LSM6DS3_ODR_208HZ_VAL },
    .odr_avl[5] = { .hz = 416, .value = LSM6DS3_ODR_416HZ_VAL },
};
对应 spec里面的

static struct lsm6ds3_fs_table {
    u8 addr;
    u8 mask;
    struct lsm6ds3_fs_reg fs_avl[LSM6DS3_FS_LIST_NUM];
} lsm6ds3_fs_table[LSM6DS3_SENSORS_NUMB] = {
    [LSM6DS3_ACCEL] = {
        .addr = LSM6DS3_ACCEL_FS_ADDR,
        .mask = LSM6DS3_ACCEL_FS_MASK,
        .fs_avl[0] = { .gain = LSM6DS3_ACCEL_FS_2G_GAIN,
                    .value = LSM6DS3_ACCEL_FS_2G_VAL,
                    .urv = 2, },
        .fs_avl[1] = { .gain = LSM6DS3_ACCEL_FS_4G_GAIN,
                    .value = LSM6DS3_ACCEL_FS_4G_VAL,
                    .urv = 4, },
        .fs_avl[2] = { .gain = LSM6DS3_ACCEL_FS_8G_GAIN,
                    .value = LSM6DS3_ACCEL_FS_8G_VAL,
                    .urv = 8, },
        .fs_avl[3] = { .gain = LSM6DS3_ACCEL_FS_16G_GAIN,
                    .value = LSM6DS3_ACCEL_FS_16G_VAL,
                    .urv = 16, },
    },
    [LSM6DS3_GYRO] = {
        .addr = LSM6DS3_GYRO_FS_ADDR,
        .mask = LSM6DS3_GYRO_FS_MASK,
        .fs_avl[0] = { .gain = LSM6DS3_GYRO_FS_245_GAIN,
                    .value = LSM6DS3_GYRO_FS_245_VAL,
                    .urv = 245, },
        .fs_avl[1] = { .gain = LSM6DS3_GYRO_FS_500_GAIN,
                    .value = LSM6DS3_GYRO_FS_500_VAL,
                    .urv = 500, },
        .fs_avl[2] = { .gain = LSM6DS3_GYRO_FS_1000_GAIN,
                    .value = LSM6DS3_GYRO_FS_1000_VAL,
                    .urv = 1000, },
        .fs_avl[3] = { .gain = LSM6DS3_GYRO_FS_2000_GAIN,
                    .value = LSM6DS3_GYRO_FS_2000_VAL,
                    .urv = 2000, },
    }
};
对应spec 里面


2 初始化
int lsm6ds3_common_probe(struct lsm6ds3_data *cdata, int irq, u16 bustype) 
{
...
for (i = 0; i < LSM6DS3_SENSORS_NUMB; i++) {
        sdata = &cdata->sensors[i];
        sdata->enabled = false;
        sdata->cdata = cdata;
        sdata->sindex = i;
        sdata->name = lsm6ds3_sensor_name[i].name;
        //这里设置  
        //  G_So = 8.75 mg/LSB,  Angular rate sensitivity表示数据的每一位间隔的大小
        //  G_ODR = 12.5 hz, Angular rate output data rate
        //  poll_interval 为获取周期,即odr输出速率的倒数 1000 / sdata->c_odr单位为ms
        if ((i == LSM6DS3_ACCEL) || (i == LSM6DS3_GYRO)) {
            sdata->c_odr = lsm6ds3_odr_table.odr_avl[0].hz;
            sdata->c_gain = lsm6ds3_fs_table[i].fs_avl[0].gain;
            sdata->poll_interval = 1000 / sdata->c_odr;
        }
        if (i == LSM6DS3_STEP_COUNTER) {
            sdata->c_odr = LSM6DS3_MIN_DURATION_MS;
        }
        //初始哈input 设备,跟sensor ic的寄存器设置无关
        lsm6ds3_input_init(sdata, bustype,
                    lsm6ds3_sensor_name[i].description);

        if (sysfs_create_group(&sdata->input_dev->dev.kobj,
                        &lsm6ds3_attribute_groups[i])) {
            dev_err(cdata->dev,
                "failed to create sysfs group for sensor %s",
                                sdata->name);
            input_unregister_device(sdata->input_dev);
            sdata->input_dev = NULL;
        }
    }
     ...
    //相关寄存器,即接口,定时器的设置
    err = lsm6ds3_init_sensors(cdata);
}

3 数据的获取
static void poll_function_work(struct work_struct *input_work)
{
        //通过i2c获取原始数据
        xyz[0] = (s32)((s16)(data[0] | (data[1] << 8)));
        xyz[1] = (s32)((s16)(data[2] | (data[3] << 8)));
        xyz[2] = (s32)((s16)(data[4] | (data[5] << 8)));
        //gain 是8750, xyz 为int类型,不能用小数运算,所以将8.75 mdps/LSB * 1000
        xyz[0] *= sdata->c_gain;
        xyz[1] *= sdata->c_gain;
        xyz[2] *= sdata->c_gain;

        lsm6ds3_report_3axes_event(sdata, xyz, sdata->timestamp);
}
LSB的意思是最小有效位,为数字输出方式,一般我们可以用mdps/LSB来表示灵敏度。8.75 mdps/LSB,表示一个bit为8.75mdps。
dps :Degree Per Second的缩写
°/S的意思。
就是一种角速度的单位
1 degree per second = 0.0174532925 radian per second
1 dps(°/s) = 0.0174532925 rad/s

所以这里获取到的数据乘以灵敏度即为获取到的角度速度 value = xyz * 8.75 * 1000 mdps

二 Hal
hal 的转化数据定义在conf_LSM6DS3.h
#define DPS2RAD                    ((float)M_PI/180.0f)
#define G_SENSITIVITY                (1.0f) //Already applied into the driver
#define CONVERT_GYRO                (DPS2RAD * (G_SENSITIVITY / (1000.0f * 1000.0f)))
#define CONVERT_GYRO_X                (CONVERT_GYRO)
#define CONVERT_GYRO_Y                (CONVERT_GYRO)
#define CONVERT_GYRO_Z                (CONVERT_GYRO)


GyroSensor::readEvents(sensors_event_t* data, int count)
{
    ......
     float value = (float) event->value;
            if (event->code == EVENT_TYPE_GYRO_X) {
                data_raw[0] = value * CONVERT_GYRO_X;
            }
            else if (event->code == EVENT_TYPE_GYRO_Y) {
                data_raw[1] = value * CONVERT_GYRO_Y;
            }
            else if (event->code == EVENT_TYPE_GYRO_Z) {
                data_raw[2] = value * CONVERT_GYRO_Z;
            }
    ......
}

从driver获取到的数据为 value mdps,  这里将数据转换为 rad /s
即 value mdps   = value / 1000  dps  = (value / 1000  ) * pi / 180 rad/s
由于driver将 数值乘了1000,所以这里要再除以1000 才能得到实际的值 即
data_raw =  (value / (1000  * 1000 )) * pi / 180


2 数据的进一步处理

int GyroSensor::readEvents(sensors_event_t* data, int count)
{
   ...
   //对x, y, z 数据方向的转换, 这个可以根据ic的在整机中的位置进行调整
       data_rot[0] = data_raw[0]*matrix_gyr[0][0] +
                    data_raw[1]*matrix_gyr[1][0] +
                    data_raw[2]*matrix_gyr[2][0];
            data_rot[1] = data_raw[0]*matrix_gyr[0][1] +
                    data_raw[1]*matrix_gyr[1][1] +
                    data_raw[2]*matrix_gyr[2][1];
            data_rot[2] = data_raw[0]*matrix_gyr[0][2] +
                    data_raw[1]*matrix_gyr[1][2] +
                    data_raw[2]*matrix_gyr[2][2];
     ...
      //由于gryo存在零点漂移,需要对数据进行校正, 这部分未研究,默认是没有打开
     ...
     //data_rot 减去 gbias_out校准的值,即为上层获取到的数据
    DecimationCount[Gyro]++;
            if(mEnabled & (1<<Gyro) && (DecimationCount[Gyro] >= DecimationBuffer[Gyro])) {
                DecimationCount[Gyro] = 0;
                mPendingEvent[Gyro].data[0] = data_rot[0] - gbias_out[0];
                mPendingEvent[Gyro].data[1] = data_rot[1] - gbias_out[1];
                mPendingEvent[Gyro].data[2] = data_rot[2] - gbias_out[2];
                mPendingEvent[Gyro].timestamp = timestamp;
                mPendingEvent[Gyro].gyro.status = SENSOR_STATUS_ACCURACY_HIGH;

                *data++ = mPendingEvent[Gyro];
}
 
3 数据校准
(1)STORE_CALIB_GYRO_ENABLED

<think>嗯,用户想了解如何通过中断方式配置和使用LSM6DS3传感器读取数据。首先,我需要回忆一下LSM6DS3的基本信息。LSM6DS3是一款6轴IMU,包含加速度计和陀螺仪。使用中断的话,通常需要配置传感器的中断引脚,设置数据准备好(DRDY)的中断,或者特定的事件触发中断。 用户可能需要具体的配置步骤和示例代码,所以我得先整理配置流程。首先,初始化I2C或SPI通信,然后配置传感器的寄存器,设置数据速率、量程,接着启用中断引脚,配置中断类型为数据准备好,最后在微控制器中设置中断服务函数来读取数据。 需要注意不同平台(如Arduino、STM32)的代码可能不同,所以最好给出通用的步骤,再举一个例子,比如Arduino。要确保代码正确,比如寄存器的地址是否正确,LSM6DS3的加速度计和陀螺仪配置寄存器的地址是0x10和0x11?或者需要查证数据手册确认。例如,CTRL1_XL(0x10)用于加速度计配置,CTRL2_G(0x11)用于陀螺仪。中断配置可能在INT1_CTRL(0x0D)寄存器,设置对应的位来启用DRDY中断。 另外,用户可能需要知道如何读取数据,当DRDY中断触发时,读取OUTX_L_G等寄存器。同时,要处理可能的中断冲突,确保中断线连接正确,配置上拉或下拉电阻。可能还需要清除中断标志位,避免重复触发。 还要考虑用户可能的误区,比如没有正确配置传感器的数据速率导致中断不触发,或者没有正确连接硬件中断引脚。此外,代码中的I2C地址是否正确,LSM6DS3的地址通常是0x6A或0x6B,取决于SA0引脚的电平。 最后,生成相关问题,帮助用户深入理解,比如如何优化数据读取,如何处理多个传感器中断,或者如何配置自由落体检测等特定功能的中断。</think>### LSM6DS3中断方式数据读取配置方法 LSM6DS3是STMicroelectronics推出的6轴惯性测量单元,支持通过硬件中断引脚触发数据读取事件。以下是基于I2C接口的中断配置步骤: 1. **硬件连接** - INT1引脚连接MCU外部中断输入引脚 - I2C地址默认0x6A(SA0接GND)或0x6B(SA0接VDD) 2. **基础配置流程**: ```c // 初始化传感器 void lsm6ds3_init() { i2c_write(LSM6DS3_ADDR, 0x10, 0x60); // 加速度计104Hz,±4g i2c_write(LSM6DS3_ADDR, 0x11, 0x6C); // 陀螺仪104Hz,±500dps i2c_write(LSM6DS3_ADDR, 0x12, 0x04); // 启用Block Data Update i2c_write(LSM6DS3_ADDR, 0x0D, 0x01); // 启用INT1数据就绪中断[^1] } ``` 3. **中断服务例程**: ```c volatile bool data_ready = false; void EXTI_IRQHandler() { if(EXTI_GetFlag(INT1_PIN)) { data_ready = true; EXTI_ClearFlag(INT1_PIN); } } ``` 4. **数据读取实现**: ```c void read_sensor_data() { uint8_t buffer[12]; i2c_read(LSM6DS3_ADDR, 0x22, buffer, 12); // 读取加速度计和陀螺仪数据 int16_t acc_x = (buffer[1] << 8) | buffer[0]; int16_t acc_y = (buffer[3] << 8) | buffer[2]; int16_t acc_z = (buffer[5] << 8) | buffer[4]; int16_t gyro_x = (buffer[7] << 8) | buffer[6]; int16_t gyro_y = (buffer[9] << 8) | buffer[8]; int16_t gyro_z = (buffer[11] << 8) | buffer[10]; } ``` 关键配置寄存器说明: - **CTRL3_C (0x12)**:设置$BDU=1$避免数据更新冲突 - **INT1_CTRL (0x0D)**:配置$INT1_DRDY_G=1$和$INT1_DRDY_XL=1$启用数据就绪中断 - **TAP_CFG (0x58)**:设置$INTERRUPTS_ENABLE=1$启用中断路由[^2]
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值