精华内容
下载资源
问答
  • 三轴加速度传感器

    2018-11-27 14:08:07
    巷道结构振动监测系统采用三轴加速度传感器对巷道各点的振动进行监测,能够准确测量各点的三轴方向上的振动波形,通过对波形进行频域的转化,可以得到不同阶的振动频率,特别是1阶频率的测量,可以有效判断巷道的...
  • 三轴加速度传感器.pdf

    2021-03-15 11:26:31
    三轴加速度传感器
  • pcb通用三轴加速度传感器
  • 三轴加速度传感器的应用 1、车身安全、控制及导航系统中的应用 加速度传感器已被广泛应用于汽车电子领域,主要集中在车身操控、安全系统和导航,典型的应用如汽车安全气囊(Airbag)、ABS防抱死刹车...
  • 项目上使用了一款Lis2dh12三轴加速度传感器。 要引用官方提供SDK中的lis2dh12_reg.h文件、lis2dh12_reg.c文件,才行。 我使用的主控芯片是STM32L051C8T6,硬件IIC与lis2dh12通讯。 原理图: 1、创建lis2dh...

    目录

    概述

    项目上使用了一款Lis2dh12三轴加速度传感器。开发前要准备的工作。

    1、原理图:

    1.1、创建lis2dh12.c文件

    1.2、在此重点说明,如果想调传感器的中断灵敏度,注意:关注1、INT1_THS(32h),2、INT1_DURATION(33h)这两个寄存器即可。

    1.3、计算阀值:主要是看配置中断的量程是哪个。

    1.4、创建lis2dh12.h文件

    1.5、main.c文件

    1.6、demo运行结果如下: 


    概述

          项目上使用了一款Lis2dh12三轴加速度传感器。开发前要准备的工作。

          1)要引用官方提供SDK中的lis2dh12_reg.h文件、lis2dh12_reg.c文件,才行。

          2)我使用的主控芯片是STM32L051C8T6,硬件IIC与lis2dh12通讯。

          3)本次写的是Demo项目,使用工具STM32Cube IDE开发

    1、原理图:

                            

    .ioc文件创建

     

    1.1、创建lis2dh12.c文件

    #include "lis2dh12.h"
    #include "lis2dh12_reg.h"
    #include "i2c.h"
    #include "stdlib.h"
    #include "stdio.h"
    #include <string.h>
    #include <math.h>
    
    
    #define LIS2DH12_FROM_FS_2g_HR_TO_mg(lsb)  (float)((int16_t)lsb>>4) * 1.0f
    #define LIS2DH12_FROM_FS_4g_HR_TO_mg(lsb)  (float)((int16_t)lsb>>4) * 2.0f
    #define LIS2DH12_FROM_FS_8g_HR_TO_mg(lsb)  (float)((int16_t)lsb>>4) * 4.0f
    #define LIS2DH12_FROM_FS_16g_HR_TO_mg(lsb) (float)((int16_t)lsb>>4) * 12.0f 
    #define LIS2DH12_FROM_LSB_TO_degC_HR(lsb)  (float)((int16_t)lsb>>6) / 4.0f+25.0f
    
     
    axis_info_t acc_sample;
    filter_avg_t acc_data;
    
    
    /* ============================================================
    func name   :  lis2_Delay_us
    discription :  lis2 微妙延时
    param       :  us
    return      :  
    Revision    : 
    =============================================================== */
    void lis2_Delay_us(uint32_t us)
    {
    	int n = 11;
    	while(--us)
    	{
    	    while(--n);
    	    n = 11;
    	}
    }
    
    /* ============================================================
    func name   :  lis2_Delay_ms
    discription :  lis2 毫秒延时
    param       :  ms
    return      :  
    Revision    : 
    =============================================================== */
    void lis2_Delay_ms(uint32_t ms)
    {
    	int i = 0;
    	for(;i<ms;i++)
    	{
    	    lis2_Delay_us(1000);
    	}
    }
    
    
    /* ============================================================
    func name   :  lis2dh12_iic_read_byte
    discription :  写一个字节
    param       :  reg:寄存器地址,data:寄存器对应的值
    return      :  
    Revision    : 
    =============================================================== */
    int32_t lis2dh12_iic_write_byte(uint8_t reg, uint8_t data)
    {
    	 #ifdef HARDWARE_IIC
    			HAL_I2C_Mem_Write(&hi2c1, LIS2DH12_I2C_ADD_H, reg,I2C_MEMADD_SIZE_8BIT, &data, 1, 1000);
    	 #endif
    	
    	 #ifdef SIMULATED_IIC
    			Lis2DH12_IIC_Write_Byte(LIS2DH12_I2C_ADD_H, reg, data); 
    	 #endif
    	 return 1;
    }
    
    /* ============================================================
    func name   :  lis2dh12_iic_read_byte
    discription :  读一个字节
    param       :  reg:寄存器地址,data:寄存器对应的值
    return      :  
    Revision    : 
    =============================================================== */
    int32_t lis2dh12_iic_read_byte(uint8_t reg, uint8_t* data)
    {
    	 #ifdef HARDWARE_IIC
    			HAL_I2C_Mem_Read(&hi2c1, LIS2DH12_I2C_ADD_H, reg,I2C_MEMADD_SIZE_8BIT, data, 1, 1000);
    	 #endif
    	
    	 #ifdef SIMULATED_IIC
    			Lis2DH12_IIC_Read_Byte(LIS2DH12_I2C_ADD_H, reg, data); 
    			
    	 #endif
    	 return 1;
    }
    
    
    /* ============================================================
    func name   :  Lis2dh12_Init
    discription :  配置检测阈值与中断
    param       :  void
    return      :  
    Revision    : 
    =============================================================== */
    int32_t Lis2dh12_Init(void)
    {	
    	/* Initialization of sensor */
    	lis2dh12_iic_write_byte(0x20, 0x37);	/* CTRL_REG1(20h): 关闭sensor,设置进入掉电模式 ODR 25HZ */
    //	lis2dh12_iic_write_byte(0x20, 0x57);	/* CTRL_REG1(20h): 关闭sensor,设置进入低功耗模式 ODR 100HZ */
    	lis2dh12_iic_write_byte(0x21, 0x03);	/* CTRL_REG2(21h): IA1、IA2 开启高通滤波 bc */
    	lis2dh12_iic_write_byte(0x22, 0xc0);	/* CTRL_REG3(22h): 0x80 使能单击中断到INT_1 INT_2 */
    	lis2dh12_iic_write_byte(0x23, 0x88);  /* CTRL_REG4(23h): 使能快,数据更新,全量程+/-2G,非常精度模式 */
    //	lis2dh12_iic_write_byte(0x25, 0x00);  /* CTRL_REG6(25h): 高电平(上升沿)触发中断 */
    	
    	/* INT1 翻转检测,中断*/							//0x6a
    	lis2dh12_iic_write_byte(0x30, 0x7f);  /* INT1_CFG(30h): 使能,6D X/Y/Z任一超过阈值中断 */
    //	lis2dh12_iic_write_byte(0x30, 0x4f);  /* INT1_CFG(30h): 使能,6D X/Y任一超过阈值中断 */
    //  lis2dh12_iic_write_byte(0x31, 0x20);  /* INT1_SRC(31h): 设置中断源 */
    
    	lis2dh12_iic_write_byte(0x32, 0x02);  	/* INT1_THS(32h): 设置中断阀值 0x10: 16*2(FS)  0x20: 32*16(FS) */
    
    //	lis2dh12_iic_write_byte(0x33, 0x02);  	/* INT1_DURATION(33h): 1LSB=1/ODR  如果ODR=25HZ  那么1LSB=40ms 设置延时 1s,对应25->0x19 */
    //	lis2dh12_iic_write_byte(0x33, 0x03);  /* INT1_DURATION(33h): 1LSB=1/ODR  如果ODR=50HZ   那么1LSB=20ms 设置延时 1s,对应50->0x32 */
      lis2dh12_iic_write_byte(0x33, 0x03);  	/* INT1_DURATION(33h): 1LSB=1/ODR  如果ODR=100HZ  那么1LSB=10ms 设置延时 1s,对应100->0x64 */
    
    	
    //	/* INT2 单击中断 */
    	lis2dh12_iic_write_byte(0x24, 0x01);	/* CTRL_REG5(24h):  */
    //	lis2dh12_iic_write_byte(0x25, 0xa0);  /* CTRL_REG6(25h): Click interrupt on INT2 pin */
    //
    //	lis2dh12_iic_write_byte(0x38, 0x15);	/* CLICK_CFG (38h): 单击识别中断使能 */
    	lis2dh12_iic_write_byte(0x39, 0x10);
    //	lis2dh12_iic_write_byte(0x3a, 0x7f);  /* CLICK_THS (3Ah): 单击阀值 */
    //	lis2dh12_iic_write_byte(0x3b, 0xff);  /* TIME_LIMIT (3Bh): 时间限制窗口6 ODR 1LSB=1/ODR 1LSB=1/100HZ,10ms,设置延时1s,对应100—>0x64*/
    //	lis2dh12_iic_write_byte(0x3c, 0xff);  /* TIME_LATENCY (3Ch): 中断电平持续时间1 ODR=10ms */
    //	lis2dh12_iic_write_byte(0x3d, 0x01);  /* TIME_WINDOW (3Dh):  单击时间窗口 */
    	
    	/* Start sensor */
    //	lis2dh12_iic_write_byte(0x20, 0x37);
    	lis2dh12_iic_write_byte(0x20, 0x5f);  /* CTRL_REG1(20h): Start sensor at ODR 100Hz Low-power mode */
    	
    	return 0;
    }
    
    
    /* ============================================================
    func name   :  get_acc_value
    discription :  获取加速度值
    param       :  axis_info_t *sample
    return      :  void
    Revision    : 
    =============================================================== */
    void get_acc_value(axis_info_t *sample)
    {
    	uint8_t i = 0;
    	uint8_t data[6];
    	for (i=0; i<6; i++){
    		lis2dh12_iic_read_byte(0x28+i, data+i);		//获取X、y、z轴的数据
    		//printf("data[i] %d, \r\n", data[i]);
    	}
    //  sample->x = abs((int)(LIS2DH12_FROM_FS_2g_HR_TO_mg(*(int16_t*)data))); 
    //	sample->y = abs((int)(LIS2DH12_FROM_FS_2g_HR_TO_mg(*(int16_t*)(data+2))));
    //	sample->z = abs((int)(LIS2DH12_FROM_FS_2g_HR_TO_mg(*(int16_t*)(data+4))));
    	sample->x = LIS2DH12_FROM_FS_2g_HR_TO_mg(*(int16_t*)data); 
    	sample->y = LIS2DH12_FROM_FS_2g_HR_TO_mg(*(int16_t*)(data+2));
    	sample->z = LIS2DH12_FROM_FS_2g_HR_TO_mg(*(int16_t*)(data+4));
    }
    
    /* ============================================================
    func name   :  filter_calculate
    discription :  均值滤波器---滤波
    			   读取xyz数据存入均值滤波器,存满进行计算,滤波后样本存入sample
    param       :  filter_avg_t *filter, axis_info_t *sample
    return      :  void
    Revision    : 
    =============================================================== */
    void filter_calculate(filter_avg_t *filter, axis_info_t *sample)
    {
    	uint8_t i = 0;
    	short x_sum = 0, y_sum = 0, z_sum = 0;	
    	
    	for (i=0; i<FILTER_CNT; i++) 
    	{
    		get_acc_value(sample);
    
    		filter->info[i].x = sample->x;
    		filter->info[i].y = sample->y;
    		filter->info[i].z = sample->z;
    		
    		x_sum += filter->info[i].x;
    		y_sum += filter->info[i].y;
    		z_sum += filter->info[i].z;
    		
    		printf("acc_x:%d,  acc_y:%d,  acc_z:%d \n",filter->info[i].x,filter->info[i].y,filter->info[i].z);
    	}
    	sample->x = x_sum / FILTER_CNT;
    	sample->y = y_sum / FILTER_CNT;
    	sample->z = z_sum / FILTER_CNT;	
    	printf("\r\n acc_info.acc_x:%d, acc_info.acc_y:%d, acc_info.acc_z:%d \r\n",sample->x, sample->y, sample->z);
    }
     
     
    /* ============================================================
    func name   :  new_angle_calculate
    discription :  计算新角度
    param       :  axis_info_t *sample
    return      :  void
    Revision    : 
    =============================================================== */
    void new_angle_calculate(axis_info_t *sample)
    {
    	sample->new_angle_x = atan((short)sample->x/(short)sqrt(pow(sample->y, 2)+pow(sample->z, 2))) * DEGREE_CAL;
    	sample->new_angle_y = atan((short)sample->y/(short)sqrt(pow(sample->x, 2)+pow(sample->z, 2))) * DEGREE_CAL;
    	sample->new_angle_z = atan((short)sample->z/(short)sqrt(pow(sample->x, 2)+pow(sample->y, 2))) * DEGREE_CAL;
    	if (sample->new_angle_z < 0)
    	{
    		sample->new_angle_x = 180-sample->new_angle_x;
    		sample->new_angle_y = 180-sample->new_angle_y;
    	}
    	printf("sample->new_angle_x:%d, sample->new_angle_y:%d, sample->new_angle_z:%d \r\n",sample->new_angle_x, sample->new_angle_y, sample->new_angle_z);
    }
    
    /* ============================================================
    func name   :  old_angle_calculate
    discription :  计算旧角度
    param       :  axis_info_t *sample
    return      :  void
    Revision    : 
    =============================================================== */
    void old_angle_calculate(axis_info_t *sample)
    {
    	sample->old_angle_x = atan((short)sample->x/(short)sqrt(pow(sample->y, 2)+pow(sample->z, 2))) * DEGREE_CAL;
    	sample->old_angle_y = atan((short)sample->y/(short)sqrt(pow(sample->x, 2)+pow(sample->z, 2))) * DEGREE_CAL;
    	sample->old_angle_z = atan((short)sample->z/(short)sqrt(pow(sample->x, 2)+pow(sample->y, 2))) * DEGREE_CAL;
    	if (sample->old_angle_z < 0)
    	{
    		sample->old_angle_x = 180-sample->old_angle_x;
    		sample->old_angle_y = 180-sample->old_angle_y;
    	}
    	printf("sample->old_angle_x:%d, sample->old_angle_y:%d, sample->old_angle_z:%d \r\n",sample->old_angle_x, sample->old_angle_y, sample->old_angle_z);
    }
    

    1.2、在此重点说明,如果想调传感器的中断灵敏度,注意:关注1、INT1_THS(32h),2、INT1_DURATION(33h)这两个寄存器即可。

    INT1_THS(32h)

    1.3、计算阀值:主要是看配置中断的量程是哪个。

    (1)如果量程 FS=2g 每1LSB=16mg  
    那么寄存器配置INT1_THS=2 那么阈值=2*16mg
    如果INT1_THS=5 那么阈值=5*16mg
     
    (2)如果量程FS=4g,那么每1LSB=32mg 
    INT1_THS =5 阈值就是5*32mg=160mg

    看配置的ODR是哪个,来计算延时的时间。

    1LSB=1/ODR  如果ODR=50HZ  那么1LSB=20ms

    /*
    500mg = 30°
    250mg = 15°
    160mg = 10°
    我现在对应的量程是FS=2g,INT1_THS=10,那么阀值=10*16mg
     
    1LSB=1/ODR  如果ODR=50HZ  那么1LSB=20ms
    50LSB   = 1s
    100LSB = 2s 
    */

    1.4、创建lis2dh12.h文件

    #ifndef __LIS2DH12_H
    #define __LIS2DH12_H
    
    #ifdef __cplusplus
    extern "C"
    {
    #endif
    
    #include "stdint.h"
    
    #define DEGREE_CAL 180.0/3.1416
    #define FILTER_CNT 4
    
    
    typedef struct {
      short x;
      short y;
      short z;
      short new_angle_x;
      short new_angle_y;
      short new_angle_z;
      short old_angle_x;
      short old_angle_y;
      short old_angle_z;
    }axis_info_t;
    
    
    typedef struct filter_avg{
      axis_info_t info[FILTER_CNT];
      unsigned char count;
    }filter_avg_t;
    
    extern axis_info_t acc_sample;
    extern filter_avg_t acc_data;
    
    int32_t Lis2dh12_Init(void);
    void filter_calculate(filter_avg_t *filter, axis_info_t *sample);
    void old_angle_calculate(axis_info_t *sample);
    void new_angle_calculate(axis_info_t *sample);
    
    
    
    #endif
    

    1.5、main.c文件

    /* USER CODE END Header */
    
    /* Includes ------------------------------------------------------------------*/
    #include "main.h"
    #include "i2c.h"
    #include "usart.h"
    #include "gpio.h"
    
    /* Private includes ----------------------------------------------------------*/
    /* USER CODE BEGIN Includes */
    #include "stdio.h"
    
    #include "lis2dh12.h"
    /* USER CODE END Includes */
    
    /* Private typedef -----------------------------------------------------------*/
    /* USER CODE BEGIN PTD */
    
    /* USER CODE END PTD */
    
    /* Private define ------------------------------------------------------------*/
    /* USER CODE BEGIN PD */
    /* USER CODE END PD */
    
    /* Private macro -------------------------------------------------------------*/
    /* USER CODE BEGIN PM */
    
    /* USER CODE END PM */
    
    /* Private variables ---------------------------------------------------------*/
    
    /* USER CODE BEGIN PV */
    
    /* USER CODE END PV */
    
    /* Private function prototypes -----------------------------------------------*/
    void SystemClock_Config(void);
    /* USER CODE BEGIN PFP */
    
    /* USER CODE END PFP */
    
    /* Private user code ---------------------------------------------------------*/
    /* USER CODE BEGIN 0 */
    
    /* USER CODE END 0 */
    
    /**
      * @brief  The application entry point.
      * @retval int
      */
    int main(void)
    {
      /* USER CODE BEGIN 1 */
    
      /* USER CODE END 1 */
    
      /* MCU Configuration--------------------------------------------------------*/
    
      /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
      HAL_Init();
    
      /* USER CODE BEGIN Init */
    
      /* USER CODE END Init */
    
      /* Configure the system clock */
      SystemClock_Config();
    
      /* USER CODE BEGIN SysInit */
    
      /* USER CODE END SysInit */
    
      /* Initialize all configured peripherals */
      MX_GPIO_Init();
      MX_I2C1_Init();
      MX_USART1_UART_Init();
      /* USER CODE BEGIN 2 */
      Lis2dh12_Init();
      filter_calculate(&acc_data, &acc_sample);
      old_angle_calculate(&acc_sample);
      /* USER CODE END 2 */
    
      /* Infinite loop */
      /* USER CODE BEGIN WHILE */
      while (1)
      {
    	 HAL_Delay(1000);
    	 filter_calculate(&acc_data, &acc_sample);
    	 new_angle_calculate(&acc_sample);
        /* USER CODE END WHILE */
    
        /* USER CODE BEGIN 3 */
      }
      /* USER CODE END 3 */
    }

    1.6、demo运行结果如下: 

    代码:Git

    展开全文
  • 三轴加速度传感器配置代码。STC12C5A60S2控制,波特率115200,串口传输
  • 【传感器】BMA253 数字,三轴加速度传感器-附件资源
  • 某 VR 设备生产厂商为了提高市场竞争力,要推出了款能够捕捉手部动作的 VR 手套,通 过 VR 手套可以获取到手指、手掌等部位的动作变化,请使用三轴加速度传感器对传感器本 身的加速度变化进行采集,并将采集信息发送...
  • 三轴加速度传感器的应用 1、车身安全、控制及导航系统中的应用 加速度传感器已被广泛应用于汽车电子领域,主要集中在车身操控、安全系统和导航,典型的应用如汽车安全气囊(Airbag)、ABS防抱死刹车...
  • 三轴加速度传感器在跌倒检测中的应用
  • 基于stm32开发板的三轴加速度传感器实验程序
  • 这是一个关于MMA7361三轴加速度传感器的使用技术文档,帮助你完成相应的项目开发。
  • Kionix三轴加速度传感器的高级数据路径功能简介
  • 针对三轴加速度传感器在车辆行驶状态测量方面的应用,研究了三轴加速度传感器在车辆上的安装误差问题,提出了一种通过数学解算模型对安装误差进行标定的方法。标定过程无需借助其他测量仪器,只需要使用安装后的...
  • 基于三轴加速度传感器的计步算法

    万次阅读 多人点赞 2018-08-08 11:23:00
    基于三轴加速度传感器计步算法 By Sky.J 2018.08.08 概述 今天主要是想要分享利用三轴加速度传感器计步的一个算法步骤。   数据分析---&gt;模型 这里拿到的是ADI公司的测试数据,可以看到不管如何佩戴计...

    基于三轴加速度传感器计步算法

    By Sky.J 2018.08.08

    概述

    今天主要是想要分享利用三轴加速度传感器计步的一个算法步骤。

     

    数据分析--->模型

    这里拿到的是ADI公司的测试数据,可以看到不管如何佩戴计步器,总有至少一个轴具有相对较大的周期性加速度变化。那么我们就可以从这里着手,进行数据分析,判断步伐。

    算法

    1,均值滤波器---滤波

    均值滤波器实现均值滤波,其实很简单就是拿到多组x,y,z三轴数据,求平均值。最后的平均值作为输出结果,使输出结果更加平滑。完成初步滤波。

    下面是伪代码

    #define FILTER_CNT			4
    
    typedef struct {
      short x;
      short y;
      short z;
    }axis_info_t;
    
    typedef struct filter_avg{
    	axis_info_t info[FILTER_CNT];
    	unsigned char count;
    }filter_avg_t;
    
    //读取xyz数据存入均值滤波器,存满进行计算,滤波后样本存入sample,如何读取存满就不多说了。
    static void filter_calculate(filter_avg_t *filter, axis_info_t *sample)
    {
    	unsigned int i;
    	short x_sum = 0, y_sum = 0, z_sum = 0;
    	for (i = 0; i < FILTER_CNT; i++) {
    		x_sum += filter->info[i].x;
    		y_sum += filter->info[i].y;
    		z_sum += filter->info[i].z;
    	}
    	sample->x = x_sum / FILTER_CNT;
    	sample->y = y_sum / FILTER_CNT;
    	sample->z = z_sum / FILTER_CNT;
    }

    2,动态阈值

    动态阈值: 系统持续更新3轴加速度的最大值和最小值,每采样50次更新一次。平均值(Max + Min)/2称为"动态阈值"。

    对于动态阈值其实就是我们在采样过程中拿到的每个轴的最大值和最小值的平均值,它是每取50个样本就更新一次,是动态变化的。所以我们只需每50次样本,取出其中的最大最小值就行了。最大最小值,还有一个重要的功能,判断最活跃轴,因为我们最后判断步伐,也是根据哪个轴加速度变化最大认为哪个是活跃轴。

    下面是动态阈值的伪代码部分

    #define MAX(a,b) ((a) > (b) ? (a) : (b)) 
    #define MIN(a,b) ((a) < (b) ? (a) : (b))
    #define SAMPLE_SIZE   50
    
    typedef struct {
    	axis_info_t newmax;
    	axis_info_t newmin;
    	axis_info_t oldmax;
    	axis_info_t oldmin;
    }peak_value_t;
    
    static void peak_value_init(peak_value_t *peak);
    
    //在动态阈值结构体初始化时,一定要将max的值都赋值为最小值,min赋值为最大值,这样才有利于动态更新。
    static void peak_update(peak_value_t *peak, axis_info_t *cur_sample)
    {
      	static unsigned int sample_size = 0;
        sample_size ++;
    	if (sample_size > SAMPLE_SIZE) {
    		/*采样达到50个,更新一次*/
    		sample_size = 1;
    		peak->oldmax = peak->newmax;
    		peak->oldmin = peak->newmin;
          	//初始化
          	peak_value_init(peak);
    	}
    	peak->newmax.x = MAX(peak->newmax.x, cur_sample->x);
    	peak->newmax.y = MAX(peak->newmax.y, cur_sample->y);
    	peak->newmax.z = MAX(peak->newmax.z, cur_sample->z);
    	
    	peak->newmin.x = MIN(peak->newmin.x, cur_sample->x);
    	peak->newmin.y = MIN(peak->newmin.y, cur_sample->y);
    	peak->newmin.z = MIN(peak->newmin.z, cur_sample->z);
    	
    }

    3,动态精度

    动态精度:这其实是由一个线性移位寄存器加上一个我们预设定的动态变化值来消除高频噪声。其实它的操作很简单,移位寄存器中有两个样本,一个是new_sample,一个是old_sample.只要我们采集到一个样本,当前样本cur_sample.当cur_sample到来,old_sample无条件更新为new_sample的值,但是new_sample就不是无条件更新了,假设我们设定动态精度DYNAMIC_PRECISION=10,当|cur_sample.x-new_sample.x|,如果X轴变化量大于DYNAMIC_PRECISION,那么new_sample.x就更新为cur_sample.x,否则不变。

    下面是部分伪代码

    #define ABS(a) (0 - (a)) > 0 ? (-(a)) : (a)
    #define DYNAMIC_PRECISION     			30     	 /*动态精度*/
    
    /*一个线性移位寄存器,用于过滤高频噪声*/
    typedef struct slid_reg{
    	axis_info_t new_sample;
    	axis_info_t old_sample;
    }slid_reg_t;
    
    static char slid_update(slid_reg_t *slid, axis_info_t *cur_sample)
    {
      	char res = 0;
      	if (ABS((cur_sample->x - slid->new_sample.x)) > DYNAMIC_PRECISION) {
    		slid->old_sample.x = slid->new_sample.x;
    		slid->new_sample.x = cur_sample->x;
    		res = 1;
    	} else {
    		slid->old_sample.x = slid->new_sample.x;
    	}
    	if (ABS((cur_sample->y - slid->new_sample.y)) > DYNAMIC_PRECISION) {
    		slid->old_sample.y = slid->new_sample.y;
    		slid->new_sample.y = cur_sample->y;
    		res = 1;
    	} else {
    		slid->old_sample.y = slid->new_sample.y;
    	}
    	
    	if (ABS((cur_sample->z - slid->new_sample.z)) > DYNAMIC_PRECISION) {
    		slid->old_sample.z = slid->new_sample.z;
    		slid->new_sample.z = cur_sample->z;
    		res = 1;
    	} else {
    		slid->old_sample.z = slid->new_sample.z;
    	}
    	return res;
    }

    4,步伐判断

    步伐判断:通过资料图,我们可以看到,判断为一步的条件是,先找到最活跃轴,然后最活跃轴的old_sample > 动态阈值,new_sample < 动态阈值。满足上述条件,认为走了一步。在我们运动过程,可以认为连续运动大于5步才认为是走步,这样可以过滤一些不必要的错误步数,同时资料所说的最快大约每秒5步,相当于200ms一步,我是利用每40ms取一次数据,200ms得到5组数据,滤波得到一个样本,这样可能更加准确一点。对于文档所说的时间窗口我就没有去做了,通过对比实验结果,我买的华为手环步数和我这个设备的步数基本一致,相差大约在200步以内。

    下面是步伐判断伪代码:

    #define MOST_ACTIVE_NULL      			0      	 /*未找到最活跃轴*/
    #define MOST_ACTIVE_X					1		 /*最活跃轴X*/	
    #define MOST_ACTIVE_Y					2        /*最活跃轴Y*/	
    #define MOST_ACTIVE_Z					3        /*最活跃轴Z*/	
    
    #define ACTIVE_PRECISION      			60       /*活跃轴最小变化值*/
    
    /*判断当前最活跃轴*/
    static char is_most_active(peak_value_t *peak)
    {
    	char res = MOST_ACTIVE_NULL;
    	short x_change = ABS((peak->newmax.x - peak->newmin.x));
    	short y_change = ABS((peak->newmax.y - peak->newmin.y));
    	short z_change = ABS((peak->newmax.z - peak->newmin.z));
    	
    	if (x_change > y_change && x_change > z_change && x_change >= ACTIVE_PRECISION) {
    		res = MOST_ACTIVE_X;
    	} else if (y_change > x_change && y_change > z_change && y_change >= ACTIVE_PRECISION) {
    		res = MOST_ACTIVE_Y;
    	} else if (z_change > x_change && z_change > y_change && z_change >= ACTIVE_PRECISION) {
    		res = MOST_ACTIVE_Z;
    	}
    	return res;
    }
    
    /*判断是否走步*/
    static void detect_step(peak_value_t *peak, slid_reg_t *slid, axis_info_t *cur_sample)
    {
    	static step_cnt = 0;
    	char res = is_most_active(peak);
    	switch (res) {
    		case MOST_ACTIVE_NULL: {
    			//fix
    			break;
    		}
    		case MOST_ACTIVE_X: {
    			short threshold_x = (peak->oldmax.x + peak->oldmin.x) / 2;
    			if (slid->old_sample.x > threshold_x && slid->new_sample.x < threshold_x) {
    				step_cnt ++;
    			}
    			break;
    		}
    		case MOST_ACTIVE_Y: {
    			short threshold_y = (peak->oldmax.y + peak->oldmin.y) / 2;
    			if (slid->old_sample.y > threshold_y && slid->new_sample.y < threshold_y) {
    				step_cnt ++;
    			}
    			break;
    		}
    		case MOST_ACTIVE_Z: {
    			short threshold_z = (peak->oldmax.z + peak->oldmin.z) / 2;
    			if (slid->old_sample.z > threshold_z && slid->new_sample.z < threshold_z) {
    				step_cntt ++;
    			}
    			break;
    		}
    		default: 
    			break;
    	}
    }

    总结

    整体来说,利用三轴加速度传感器实现的算法就完成了,这也是根据ADI公司的资料来做的,整体来说效果还算OK,如果有兴趣,希望这个可以有一点参考价值。

    参考资料

    http://www.analog.com/en/analog-dialogue/articles/pedometer-design-3-axis-digital-acceler.html

     

    展开全文
  • 电子-实验29三轴加速度传感器实验.rar,单片机/嵌入式STM32-F0/F1/F2
  • 该文件主要使用的是HAL库编写,IIS328DQ三轴加速度传感器驱动代码,包含其头文件,源文件,其中的注释使用的是UTF-8编码格式,查看注释时请将改为该格式查看。
  • 三轴加速度传感器是加速度传感器中用来测量空间加速度的传感器,即测量物体在空间中速度变化的快慢,三轴加速度传感器与单轴、两轴加速度传感器在测量原理上没有差别,他们的主要差别在于测量的维度不同,三轴加速度...

        作者:虹科医药电子-李金涛  

            三轴加速度传感器是加速度传感器中用来测量空间加速度的传感器,即测量物体在空间中速度变化的快慢,三轴加速度传感器与单轴、两轴加速度传感器在测量原理上没有差别,他们的主要差别在于测量的维度不同,三轴加速度传感器主要是将空间加速度在X、Y、Z三个轴上进行分解,在一定的技术上三个单轴就可以变成一个三轴。

     

    1. 三轴加速度传感器的类型、原理与特点:

            根据加速度传感器的实现原理,目前加速度传感器主要的类型有:压阻式、压电式、电容式三种,他们是将待测量物体的加速度转化为传感单元的电阻/电压/电容的变化,再通过转换电路将传感单元的变化数值转化为电压值,接着进行信号相应的放大以及滤波处理,将模拟量处理为合适的稳定的输出信号,此时输出的信号为电压值,最后通过ADC转换器(模数转换器),转换为数字信号。

            压阻式加速度传感器是电阻性,呈现低阻抗,具有频率响应特性好、测量方法易行、线性度好等优点,其缺点是温度效应严重、灵敏度低;压电式加速度传感器是电容性的,高阻抗,它的优点是频带宽、灵敏度高、噪比高、结构简单、工作可靠和重量轻等。缺点是某些压电材料需要防潮措施,而且输出的直流响应差,需要采用高输入阻抗电路或电荷放大器来克服这一缺陷;电容式传感器的优点是:结构简单、适应性强、动态响应好、分辨率高温度稳定性好可实现非接触测量、具有平均效应,缺点是输出阻抗高,负载能力差

           加速度传感器根据输出信号的不同,可分为:模拟式和数字式两种,两者的区别在于,模拟式输出值为电压,数字式输出值为数字信号,在具体的应用中模拟式传感器还需要加入数模转换器(ADC),但模拟式则已经集成了ADC电路,可直接通过通讯接口(SPI、I2C等)进行数据传输,在智能程度上数字式明显优于模拟式,但是高质量的ADC转换器价格昂贵甚至可能超出传感器部分的售格

            三轴加速度传感器的特点是能够在预先不知道物体运动方向的场合下,准确且全面的测量出物体的空间加速度并且体积小(常见的板尺寸在:3/4mm x 3/4/5mm不等),质量轻。如下为三轴传感器的一些常见参数介绍:

    灵敏度:与ADC(模数转换器)等级相关,单位:mv/g(模拟式)或g(数字式)

    g代表重力加速度:

    解析度:表示了输入参数的最小增量

    测量范围:表示传感器所能测量加速度的最大、最小值

    2. 三轴加速度传感器的应用:

    2.1常见应用领域【1】

    (1)汽车电子领域:

    以车身安全系统为例,当车身受到撞击时,冲击传感器会在几微秒内将信号发送至该电子控制器。随后电子控制器会立即根据碰撞的强度、乘客数量及座椅/安全带的位置等参数,配合分布在整个车厢的传感器传回的数据进行计算和做出相应评估,并在最短的时间内通过电爆驱动器启动安全气囊保证乘客的生命安全。

    (2)便携式设备的抗冲击防护:

    便携式设备由于其应用场合的原因,经常会意外跌落或受到碰撞,而造成对内部元器件的巨大冲击。当跌落发生时,系统会检测到加速的突然变化,并执行相应的自我保护操作,如关闭抗震性能差的电子或机械器件,从而避免其受损,或发生硬盘磁头损坏或刮伤盘片等可能造成数据永久丢失的情况。

    (3)卫星导航:

    当进入卫星信号接收不良的区域或环境中就会因失去信号而丧失导航功能。基于MEMS技术的3轴加速度传感器配合陀螺仪或电子罗盘等元件一起可创建方位推算系统,对GPS系统实现互补性应用。

    (4)虚拟现实:

    例如AR/VR,游戏机手柄等,通过穿戴或手持的游戏装备、手柄,传感器同步感应人体加速度,根据加速度分析人体的动作,进而在游戏屏幕上同步呈现出相应的游戏动作,一些体感游戏甚至能达到与户外运动相同锻炼的效果。

    2.2具体应用举例:

    2.2.1人体跌倒监测系统【2】

           人体发生跌倒是指突发、不自主的、非故意的体位改变,一般只发生在短暂的一瞬间,在这瞬间人体的位置、速度和加速度都将发生瞬间的巨大变化,人体姿态也会发生相应变化,根据三轴加速度的数值可以计算出三个姿态角:“pitch俯仰角”,”roll左右偏侧角”paw竖直方向转角,根据三个姿态角不仅可以判断出人体是否跌倒还可以得到人体姿态的具体姿态。

           以人体质点为原点,如图1所示,假设人体正前方为X轴,正左为Y轴,正上方为Z轴;那么三个姿态角的定义分别为:

           pitch: X轴与水平面的夹角,对应人体向前向后的俯仰角

           roll:Y轴与水平面的夹角,对应人体向左向右的侧偏角

           paw: Z轴与竖直方向的夹角,对应人体绕Z轴的旋转角

    他们与重力在X,Y,Z,轴方向上的加速度的关系如下:

                                                                                       图1 :参考坐标系

           根据人体跌倒与日常生活活动(ADL)中的姿态的区别来判断跌倒是否产生,人体在跌倒时大部分是前后或侧向跌倒,这两跌倒都将分别导致Pitch和Roll在短时间内发生大幅度抖动,yaw值则主要用来辅助计算人体的静止姿态。考虑到MEMS(微机电系统)传感器容易受到噪声影响,还需要利用卡尔曼滤波算法对估算的倾斜角进行优化处理,部分消除噪声对MEMS加速度传感器测量值的影响,提高测量准确性,图2为其算法流程(流程图来自参考文献1):

                                                                     图2:人体跌倒系统算法流程图 

    2.2.2 数字式三轴加速度传感器在快速准确监测机械故障方面的应用【3】 

           振动频率作为计算机械疲劳强度的重要指标,保存和评估各种类型的机器和驱动器的特征性振动,冲击和振动参数有助于优化机械传动系统的效率,并为这些参数确定合适的目标值和平均值。一方面,这可用于质量记录和性能参数的表示;另一方面,如果与预期的“良好”振动模式有偏差,则也可以在早期识别出即将发生的损坏。

           以MSR Electronics GmbH的MSR165微型数据记录仪为例,仅有拇指大小的记录器MSR165专门用于振动,冲击和振动检测的应用。其核心传感器元件是高分辨率的三轴数字加速度计。借助该电子设备和下游相应的评估电子设备,强大的数据记录仪能够在三个空间轴(x,y,z)上每秒执行1600次冲击和振动测量,能够记录三个轴上的±15 g或±200 g的冲击载荷和振动,MSR165还可以增加存储卡扩充模块,其测量量可扩充至10亿个。 

           MSR165微型数据记录仪通过安装在待测设备上,对设备工作过程中的振动数据进行记录,然后将测量的数据导出到PC上的MSR PC软件,对振动过程的数据进行评估,MSR微型数据记录仪可在机械制造行业的所有领域中有针对性地使用,以检测和记录各种振荡模式,振动或冲击载荷,减少人为测量的误差影响。对记录的参数进行评估有助于快速,经济地进行故障诊断以及随后的机械或机电优化。最终,可以实现显着的时间和成本优势,尤其是在各种机器和驱动器的质量和可靠性方面的优势。图3为MSR PC软件的数据评估图。

                                                                 图3:MSR PC软件的数据评估图

            总结:三轴加速度传感器是一种能够测量物体空间中的加速度的电子设备,根据传感器实现原理的不同,可分为压阻式、压电式、电容式等类型,这些传感器上的本质原理都是通过传感元件将物体加速度转化为其他的物理量,如电阻、电压、电容等,再通过转化和滤波电路等将这些物理量转化为合适的输出信号。三轴加速度传感器以其体积小,质量轻等特点在诸多领域应用非常广泛,例如汽车电子、卫星导航、虚拟现实、振动监测等,这些具体应用会涉及到许多额外的知识,需要足够的了解加速度与应用领域的物理量的转换关系,并据此做出一套算法流程去实施。

    参考文献:

    [1] 百度百科https://baike.baidu.com/item/三轴加速度计/20863147?fr=aladdin

    [2]王荣,章韵,陈建新.基于三轴加速度传感器的人体跌倒检测系统设计与实现[J].计算机应用,2012,32(05):1450-1452+1456.

    [3] Detecting machine trouble quickly and accurately SMM Schweizer , Maschinenmarkt magazine , July 2015 edition

     

     

     

    展开全文
  • 51单片机ADXL345三轴加速度传感器源代码
  • 本章,我们介绍一种当今智能手机普遍具有的传感器:加速度传感器。在手机上,这个功能可以用来:自动切换横竖屏、玩游戏和切歌等。ALIENTEK战舰STM32开发板自带了加速度传感器:ADXL345。本章我们将使用STM32来驱动...
  • ADXL345三轴加速度传感器实验《STM32开发指南》第三十四章 ADXL345三轴加速度传感器实验
  • 本次将使用三轴加速度传感器:ADXL345,在零知平台上进行加速度和单双击检测功能演示。通过本文的介绍让大家学会如何使用这款功能强大的三轴加速度传感器。1、说明MCU:零知开发板-标准板 2、传感器:ADXL345三轴...

    本次将使用三轴加速度传感器:ADXL345,在零知平台上进行加速度和单双击检测功能演示。通过本文的介绍让大家学会如何使用这款功能强大的三轴加速度传感器。
    1、说明
    MCU:零知开发板-标准板

    2、传感器:ADXL345三轴加速度传感器
                           

    ADXL345 是 ADI 公司推出的基于 iMEMS 技术的 3 轴、数字输出加速度传感器。该加速度传感器的特点有:

    a. 分辨率高。最高 13 位分辨率。

    b. 量程可变。具有+/-2g, +/-4g, +/-8g, +/-16g 可变的测量范围。

    c. 灵敏度高。最高达 3.9mg/LSB,能测量不到 1.0°的倾斜角度变化。

    d. 功耗低。 40~145uA 的超低功耗,待机模式只有 0.1uA。

    e. 尺寸小。整个 IC 尺寸只有 3mm*5mm*1mm, LGA 封装。

    ADXL 支持标准的 I2C 或 SPI 数字接口,自带 32 级 FIFO 存储,并且内部有多种运动状态检测和灵活的中断方式等特性。

    2、电路连接

    接线很简单,只需要把模块的SCL、SDA引脚与零知标准板的I2C(A5、A4)引脚相连接即可,供电3.3V,其他引脚采用模块默认的连接。

    连接好线路后,就打开使用我们的零知开发工具,找到对应代码上传代码到开发板即可。

     

    3、核心代码:

    /*
    *        ADXL345 三轴加速度传感器DEMO
    *        powered by 零知实验室-[url=http://www.lingzhilab.com]www.lingzhilab.com[/url]
    */
    #include "ADXL345.h"
     
    // 默认的I2C地址为0x53
     
    ADXL345 accel;
     
    int16_t ax, ay, az;//原始值
    float nx,ny,nz;//重力加速度
     
    #define LED_PIN LED_BUILTIN
    bool blinkState = false;
     
    //检测单击、双击动作参数设置
    void checkActivitySetup()
    {
            accel.setTapAxisXEnabled(false);//设置X轴方向敲击检测
            accel.setTapAxisYEnabled(false);//y轴方向检测
            accel.setTapAxisZEnabled(true);
             
            accel.setTapThreshold(40);//界限设置:40*0.0625 = 2.5g
            accel.setTapDuration(32);//持续时间:32*0.625ms = 20 ms
            accel.setDoubleTapLatency(80);//延迟:80*1.25ms = 100ms
            accel.setDoubleTapWindow(240);//窗口:240*1.25ms = 300ms
           
    }
     
    void checkActivity()
    {
            Activites act = accel.readActivites();
     
      if (act.isDoubleTap)
      {
        Serial.println("Double Tap Detected");
      } else if (act.isTap)
      {
        Serial.println("Tap Detected");
      }else
      {
             Serial.println("no activity");
      }
    }
     
    void setup() {
         
        Serial.begin(9600);
     
        // 初始化ADXL345
        Serial.println("Initializing I2C devices...");
        accel.initialize();
     
        // 检测是否连接ADXL345
        Serial.println("Testing device connections...");
            if(accel.testConnection()){
                    Serial.println("ADXL345 connection successful");
            }else{
                    Serial.println("ADXL345 connection failed");
            }
             
             // Set measurement range
      // +/-  2G: ADXL345_RANGE_2G
      // +/-  4G: ADXL345_RANGE_4G
      // +/-  8G: ADXL345_RANGE_8G
      // +/- 16G: ADXL345_RANGE_16G
      accel.setRange(ADXL345_RANGE_16G);
             
            checkActivitySetup();//开启单击、双击动作检测
         
        // 用LED指示数据读取
        pinMode(LED_PIN, OUTPUT);
    }
     
    void loop() {
    #if 0        
            // 获取原始的X,Y,Z三轴的数据
        accel.getAcceleration(&ax, &ay, &az);
     
        // 显示 x/y/z 原始数值
        Serial.print("accel:\t");
        Serial.print(ax); Serial.print("\t");
        Serial.print(ay); Serial.print("\t");
        Serial.println(az);
             
    #endif
    #if 1
            //获取重力转换后的加速度数值
            accel.readNormalize(&nx,&ny,&nz);
             
            //使用低通滤波进行处理,以去除尖峰的不准确结果
            float fx, fy, fz;
            //系数范围 0.1~0.9
    //        accel.lowPassFilter(nx,ny,nz,&fx,&fy,&fz,0.5);
             
            Serial.print("gravity:\t");
        Serial.print(nx); Serial.print("\t");
        Serial.print(ny); Serial.print("\t");
        Serial.println(nz);
    //        
    //        Serial.print("filter:\t");
    //    Serial.print(fx); Serial.print("\t");
    //    Serial.print(fy); Serial.print("\t");
    //    Serial.println(fz);
    #endif
    #if 1
            checkActivity();//单双击动作检测
    #endif
     
        // 闪烁LED
        blinkState = !blinkState;
        digitalWrite(LED_PIN, blinkState);
             
            delay(300);
    }

     

    该应用代码演示了三个轴向的加速度和单击、双击检测的功能。

    所设置参数可以按照自己需要的效果进行修改,详情请根据Datasheet中的说明进行修改。 

    完整代码可到零知实验室官方网站免费获取。

    结果如下:

    更多详细资料可到零知实验室官网免费获取。 

     

     

    展开全文
  • MMA7455L三轴加速度传感器应用笔记 使用心得 新手必读
  • 三轴加速度传感器MMA7455模块资料,供大家参考,买家给的
  • STM32的三轴加速度传感器程序,亲测可用。内有详细注释和说明文档,很好的参考资料。
  • 基于新型MEMS三轴加速度传感器的矿震监测系统研究,李朋勃,苏维嘉 ,微机电系统是指融合了硅微加工,光刻成型和精度机械加工等多种微加工技术制作的微传感器、微执行器和微系统。MMA7260Q是飞思卡尔推�

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 876
精华内容 350
关键字:

三轴加速度传感器