三轴加速度传感器LIS3DH使用心得

LIS3DH是ST公司推出的一块三轴加速度计芯片,使用它能实现很多有趣的应用。接下来笔者通过例程分享下LIS3DH的一些开发心得。

首先请出我们使用的开发板:UFUN, 这是块小巧精致的开发板,内核为STM32,搭载了多种传感器,包括LIS3DH,其价格也很亲民~
很小巧的ufun开发板
先给出LSI3DH官方文档下载地址:

https://www.st.com/zh/mems-and-sensors/lis3dh.html#

然后演示下例程运行结果,PC端通过串口接收到了计算后得出的加速度和角度

在这里插入图片描述
要想得到加速度和角度这两个值首先要对加速度计进行一些配置,这里我们主要讨论LIS3DH,STM32的IIC等配置就不提啦。需要我们配置的有采样率、工作模式、量程、XYZ轴的使能。

采样率单位为HZ,意义是每秒采样次数,我们可配置的采样率如下图所示(来自官方文档),例程选用100HZ。
官方文档
工作模式分掉电模式、正常模式、低功耗模式。掉电模式LIS3DH的全部内部块几乎都会关闭,低功耗模式下相比正常模式有更低的功耗,但是分辨率也会变低。我们选择正常模式。

量程分为±2、±4、±8、±16(如下图所示)。量程决定LIS3DH读出的加速度的极限值。也会影响我们之后的计算。
在这里插入图片描述
在正常模式和低功耗模式下我们可以决定X、Y、Z轴是否使能,非使能的轴生会的数据为00h。

代码如下。本例程使用的是ST官方提供的LIS3DH驱动,可以直接调用其中的函数进行操作。当然如果想用寄存器操作的话可以对照官方文档进行编写。

配置好之后就可以读取数据了,我们可以读取到的每个轴加速度数据都分为高8位和低8位分别存在两个地址里,该值为左对齐的二进制补码。
在这里插入图片描述
我们可以直接调用官方驱动中的LIS3DH_GetAccAxesRaw()函数得到一个高位低位已经组合好的值。现在这个值还不是我们最后想要的加速度值,还需要做一下计算。
以X轴为例,我们称刚刚读取到的值为axis_x,因axis_x由高8位和低8位组成,所以我们可以测量到最多2的16次方(65536)种不同的值,再由之前配置好的量程(±2g)可知总量程为4g。计算得出结果单位是g,要转换为mg再乘以1000。综上可得出X轴加速度计算公式如下,其他两轴同理。

acc_x=axis_x*(4/65536)*1000。

于是我们得到了X、Y、Z轴的加速度矢量,通过反三角函数计算可得:

angle_x= [arctan(acc_x / squr(acc_yacc_y +acc_zacc_z))] 180/3.14
angle_y= [arctan(acc_y / squr(acc_x
acc_x +acc_zacc_z))] 180/3.14
angle_z= [arctan(acc_z / squr(acc_x
acc_x +acc_y
acc_y))] *180/3.14

角度的计算可以按自己的需求进行改动,这里的公式计算得出的为X、Y、Z轴和水平线的角度。在LSI3DH水平放置时理论上x、y=0°,z=90°,实际有误差。三轴的正方向如下图所示。
在这里插入图片描述
如有问题欢迎一同讨论,如有错误务必指正~
文中源码为ufun例程《基础例程7 - 三轴加速度传感器》,可到“ufun学习板分享”公众号下载,为书写方便,文中变量名与例程稍有不同。公众号会定期更新硬件开发相关的技术文章,欢迎关注。

  • 10
    点赞
  • 67
    收藏
    觉得还不错? 一键收藏
  • 6
    评论
以下是一个基于 LIS2DH12 三轴加速度传感器的算法来判断状态的C代码: ```c #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <stdbool.h> #include <wiringPiI2C.h> #define ACCEL_ADDR 0x18 #define ACCEL_CTRL_REG1 0x20 #define ACCEL_CTRL_REG4 0x23 #define ACCEL_X_AXIS 0x28 #define ACCEL_Y_AXIS 0x2A #define ACCEL_Z_AXIS 0x2C #define THRESHOLD 1.0 // 加速度变化阈值 #define SAMPLE_RATE 100 // 采样率(Hz) #define WINDOW_SIZE 10 // 窗口大小(个样本) enum State { IDLE, MOVING, FALLING }; int main(void) { int fd = wiringPiI2CSetup(ACCEL_ADDR); if(fd == -1) { printf("Failed to initialize I2C device.\n"); exit(1); } // 配置传感器 wiringPiI2CWriteReg8(fd, ACCEL_CTRL_REG1, 0x77); // 打开传感器并设置采样率 wiringPiI2CWriteReg8(fd, ACCEL_CTRL_REG4, 0x08); // 设置测量范围为 +/- 8g // 初始化前 WINDOW_SIZE 个样本的加速度值 float prev_accel_x[WINDOW_SIZE]; float prev_accel_y[WINDOW_SIZE]; float prev_accel_z[WINDOW_SIZE]; for(int i = 0; i < WINDOW_SIZE; i++) { int x = wiringPiI2CReadReg16(fd, ACCEL_X_AXIS); int y = wiringPiI2CReadReg16(fd, ACCEL_Y_AXIS); int z = wiringPiI2CReadReg16(fd, ACCEL_Z_AXIS); // 将读取到的原始数据转换为实际加速度值 prev_accel_x[i] = (float)x / 1024.0; prev_accel_y[i] = (float)y / 1024.0; prev_accel_z[i] = (float)z / 1024.0; usleep(1000000 / SAMPLE_RATE); // 等待一段时间,以达到采样率 } // 初始化状态 enum State state = IDLE; while(1) { // 读取最新的加速度值 int x = wiringPiI2CReadReg16(fd, ACCEL_X_AXIS); int y = wiringPiI2CReadReg16(fd, ACCEL_Y_AXIS); int z = wiringPiI2CReadReg16(fd, ACCEL_Z_AXIS); // 将读取到的原始数据转换为实际加速度值 float accel_x = (float)x / 1024.0; float accel_y = (float)y / 1024.0; float accel_z = (float)z / 1024.0; // 计算加速度变化值 float delta_accel_x = 0; float delta_accel_y = 0; float delta_accel_z = 0; for(int i = 0; i < WINDOW_SIZE; i++) { delta_accel_x += abs(accel_x - prev_accel_x[i]); delta_accel_y += abs(accel_y - prev_accel_y[i]); delta_accel_z += abs(accel_z - prev_accel_z[i]); } delta_accel_x /= WINDOW_SIZE; delta_accel_y /= WINDOW_SIZE; delta_accel_z /= WINDOW_SIZE; // 根据加速度变化值判断状态 switch(state) { case IDLE: if(delta_accel_x > THRESHOLD || delta_accel_y > THRESHOLD || delta_accel_z > THRESHOLD) { state = MOVING; printf("State: MOVING\n"); } break; case MOVING: if(delta_accel_x > THRESHOLD || delta_accel_y > THRESHOLD || delta_accel_z > THRESHOLD) { state = MOVING; } else { state = FALLING; printf("State: FALLING\n"); } break; case FALLING: if(delta_accel_z > THRESHOLD) { state = IDLE; printf("State: IDLE\n"); } break; } // 更新前 WINDOW_SIZE 个样本的加速度值 for(int i = WINDOW_SIZE - 1; i > 0; i--) { prev_accel_x[i] = prev_accel_x[i - 1]; prev_accel_y[i] = prev_accel_y[i - 1]; prev_accel_z[i] = prev_accel_z[i - 1]; } prev_accel_x[0] = accel_x; prev_accel_y[0] = accel_y; prev_accel_z[0] = accel_z; // 等待一段时间,以达到采样率 usleep(1000000 / SAMPLE_RATE); } return 0; } ``` 该代码使用了和前面类似的方式来读取 LIS2DH12 三轴加速度传感器的数据,并根据加速度变化的情况来判断状态。具体地,根据阈值 THRESHOLD 来判断加速度是否变化,根据窗口大小 WINDOW_SIZE 来计算加速度变化值,然后根据加速度变化值的大小来判断状态。如果加速度变化超过阈值且当前状态为 IDLE,则进入 MOVING 状态;如果加速度变化超过阈值且当前状态为 MOVING,则保持 MOVING 状态;如果加速度变化没有超过阈值且当前状态为 MOVING,则进入 FALLING 状态;如果加速度变化超过阈值且当前状态为 FALLING,则保持 FALLING 状态;如果加速度在 Z 轴方向上超过阈值且当前状态为 FALLING,则回到 IDLE 状态。注意,需要根据具体的传感器型号和配置修改代码中的地址和寄存器值,以及阈值、采样率和窗口大小的大小。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值