#STM32学习#6D加速度传感器测量风机震动

1、背景:

需要监测风机的启动与停止,希望通过测量其振动频率来辅助判定。

2、传感器:

传统的振动传感器如下图,其有两个缺点:一是测量精度低,对于微小的振动不敏感;二是无法测出分频信号。

选择使用LSM6DSL加速度/角速度传感器。传感器所在的板子为X-NUCLEO-IKSO1A2。如下图所示。

 LSM6DSL可以测量出三轴方向的加速度和角速度,而我们监测振动只需要加速度信息。

3、建工程:

首先使用的开发底板是ST官方的MB1136。所有相关的资料会在下方给出链接。

习惯使用Stm32cubeMX快速建立工程。根据选用开发板的主芯片型号以及传感器链接的引脚,占用的资源进行配置。最终一键生成工程。(关于如何使用stm32MX,可自行度娘,也可在下方讨论)

值得一提的是:

(1)配置I2C时,需要使用“快速模式”,速度设置为最大(400000Hz),这样可以加快和加速度传感器之间的通信。加速度传感器的输出频率也就可以尽可能提升。实际在测试时发现,在最快的IIC通信速度下,传感器最大可以设置的输出频率为3.33KHz。

(2)配置一个中断输入引脚,接收传感器数据准备好时发来的中断。(也可以自行去读取某状态位)

(3)ST下载口自带的串口,波特率为固定的9600.如果想要更高,需要单独接线。(我就是单独接线,设置为115200)

接下来是去工程里编写代码,相信大家都可以编出属于自己逻辑的代码。我的逻辑思路如下:

(1)初始化设备和传感器

(2)传感器启动,准备好一组加速度数据(3个数据,X,Y,Z),产生引脚中断。

(3)F401RE接收到中断,读取6个字节(3个加速度的值)。(直接读取的是补码的形式,而加速度值有正负,需要我们定义变量时使用int16)

(4)将一组数据(3方向加速度)进行矢量计算,求得其模长ACC。将ACC存入数组直到存满。(考虑到单片机存储空间有限,因而采用模长的数组,1024个double数据)

(5)存满后,不再存储,置为标志位,进行FFT快速傅里叶变换。相关知识参考自:《C》C语言实现FFT算法_杨贵安的博客-CSDN博客_c语言fft  。

该链接里面有C语言代码,可以直接运行。在使用时需要注意输入参数关系:

FFT需要定义多个与模长数组同样大小的数组,比较费空间。

double pr[NUM],pi[NUM],fr[NUM],fi[NUM];

(6)变换得到的结果被存在pr[1024]中,如果需要观察变换得到的结果,可以将这个数组里的double数据 打印到窗口助手中,再用excel观察变换结果。(打印时,单个数据接换行(\n\r),串口助手中打印的一列数据,直接复制到excel中)。得到的数据列表中第一个为直流分量,可以删除。另外因为某种原因,剩余数据构成的图像呈现左右对称的情况,我们在显示时只取一半就好。如下图所示,传感器放在电脑主机上,测量主机风扇的振动。共计1024个采样点。输出频率为833Hz。(提高采样点个数,横坐标会向右移动。提高输出频率,横坐标会向左移动)(同样是1024个采样点,833Hz输出频率对应145,1.66KHz输出频率对应72,     3.33KHz输出频率对应35)。

(7)横坐标与振动频率有着直接的关系。我通过模拟输入数据观察发现,采样点数为1024时,傅里叶变换后得到的峰峰极大值的很坐标与实际的频率一致(略有偏移,可以理解)。

 模拟输入pr[1024],包括10Hz,20Hz,30Hz,40Hz,50Hz,60Hz,70Hz,80Hz,90Hz。(参考频率和角速度之间的关系)

for(i=0;i<1024;i++) {
pr[i]=cos(2*PI*0.001*i*10)+cos(2*PI*0.001*i*20)+cos(2*PI*0.001*i*30)+cos(2*PI*0.001*i*40)+cos(2*PI*0.001*i*50)+cos(2*PI*0.001*i*60)+cos(2*PI*0.001*i*70)+cos(2*PI*0.001*i*80)+cos(2*PI*0.001*i*90);
}

下图只使用了其中的第1~128个点做图(采样点数还是1024)

4、编写上位机

上述显示的过程有点繁琐,因而考虑编写一个上位机用于实时调试。

下位机设备在进行转换之后,直接通过串口,将数据发送到电脑。(每个double数字都先被转换为字符串,以字符串的形式发送。每个数据发送之后,追加发送一个换行符\n,发送完所有数据之后,发送一个'#')

上位机编写,使用的是Qt和C++。具体的实现和源代码感兴趣的童鞋可以问我要一下。

我最方案是,1024个采样点数组,传感器3.33KHz输出频率。电脑主机的频率被测为35Hz(2100转每分钟)。

纯属个人经验总结,如有错误,欢迎讨论!

2020年12月17日 补充分享LSM6DSL 的初始化函数以及数据读取的函数

LSM6DSL pdf, LSM6DSL description, LSM6DSL datasheets, LSM6DSL view ::: ALLDATASHEET :::

#include "main.h"


#define FUNC_CFG_ACCESS              0x01 //嵌入式功能配置寄存器


#define SENSOR_SYNC_TIME_FRAME       0x04 //传感器同步配置寄存器
#define SENSOR_SYNC_RES_RATIO        0x05 //传感器同步配置寄存器
#define FIFO_CTRL1                   0x06 //FIFO 配置寄存器
#define FIFO_CTRL2                   0x07 //FIFO 配置寄存器
#define FIFO_CTRL3                   0x08 //FIFO 配置寄存器
#define FIFO_CTRL4                   0x09 //FIFO 配置寄存器
#define FIFO_CTRL5                   0x0a //FIFO 配置寄存器
#define DRDY_PULSE_CFG_G             0x0b //

#define INT1_CTRL                    0x0d //
#define INT2_CTRL                    0x0e //
#define WHO_AM_I                     0x0f //芯片ID
#define CTRL1_XL                     0x10 //加速度计和陀螺仪控制寄存器
#define CTRL2_G                      0x11 //
#define CTRL3_C                      0x12 //
#define CTRL4_C                      0x13 //
#define CTRL5_C                      0x14 //
#define CTRL6_C                      0x15 //
#define CTRL7_G                      0x16 //
#define CTRL8_XL                     0x17 //
#define CTRL9_XL                     0x18 //
#define CTRL10_C                     0x19 //
#define MASTER_CONFIG                0x1a //I2C主配置寄存器
#define WAKE_UP_SRC                  0x1b //中断寄存器
#define TAP_SRC                      0x1c //中断寄存器
#define D6D_SRC                      0x1d //中断寄存器
#define STATUS_REG                   0x1e //用户接口的状态数据寄存器

#define OUT_TEMP_L                   0x20 //温度输出数据寄存器
#define OUT_TEMP_H                   0x21 //温度输出数据寄存器
#define OUTX_L_G                     0x22 //用户界面的陀螺仪输出寄存器
#define OUTX_H_G                     0x23 //用户界面的陀螺仪输出寄存器
#define OUTY_L_G                     0x24 //用户界面的陀螺仪输出寄存器
#define OUTY_H_G                     0x25 //用户界面的陀螺仪输出寄存器
#define OUTZ_L_G                     0x26 //用户界面的陀螺仪输出寄存器
#define OUTZ_H_G                     0x27 //用户界面的陀螺仪输出寄存器
#define OUTX_L_XL                     0x28 //加速度计输出寄存器
#define OUTX_H_XL                     0x29 //加速度计输出寄存器
#define OUTY_L_XL                     0x2a //加速度计输出寄存器
#define OUTY_H_XL                     0x2b //加速度计输出寄存器
#define OUTZ_L_XL                     0x2c //加速度计输出寄存器
#define OUTZ_H_XL                     0x2d //加速度计输出寄存器
#define SENSORHUB1_REG                0x2e //传感器集线器输出寄存
#define SENSORHUB2_REG                0x2f //传感器集线器输出寄存
#define SENSORHUB3_REG                0x30 //传感器集线器输出寄存
#define SENSORHUB4_REG                0x31 //传感器集线器输出寄存
#define SENSORHUB5_REG                0x32 //传感器集线器输出寄存
#define SENSORHUB6_REG                0x33 //传感器集线器输出寄存
#define SENSORHUB7_REG                0x34 //传感器集线器输出寄存
#define SENSORHUB8_REG                0x35 //传感器集线器输出寄存
#define SENSORHUB9_REG                0x36 //传感器集线器输出寄存
#define SENSORHUB10_REG               0x37 //传感器集线器输出寄存
#define SENSORHUB11_REG               0x38 //传感器集线器输出寄存
#define SENSORHUB12_REG               0x39 //传感器集线器输出寄存
#define FIFO_STATUS1                 0x3a //FIFO状态寄存器
#define FIFO_STATUS2                 0x3b //
#define FIFO_STATUS3                 0x3c //
#define FIFO_STATUS4                 0x3d //
#define FIFO_DATA_OUT_L              0x3e //FIFO数据输出寄存器
#define FIFO_DATA_OUT_H              0x3f //
#define TIMESTAMP0_REG               0x40 //时间戳输出寄存器
#define TIMESTAMP1_REG               0x41 //
#define TIMESTAMP2_REG               0x42 //

/*reserved*/

#define STEP_TIMESTAMP_L             0x49 //
#define STEP_TIMESTAMP_H             0x4A //
#define STEP_COUNTER_L               0x4b //
#define STEP_COUNTER_H               0x4c //
#define SENSORHUB13_REG              0x4d //传感器集线器输出寄存
#define SENSORHUB14_REG              0x4e //传感器集线器输出寄存
#define SENSORHUB15_REG              0x4f //传感器集线器输出寄存
#define SENSORHUB16_REG              0x50 //传感器集线器输出寄存
#define SENSORHUB17_REG              0x51 //传感器集线器输出寄存
#define SENSORHUB18_REG              0x52 //传感器集线器输出寄存
#define FUNC_SRC1                    0x53 //中断寄存器
#define FUNC_SRC2                    0x54 //
#define WRIST_TILT_IA                0x55 //中断寄存器

/*reserved*/

#define TAP_CFG                      0x58 //中断寄存器
#define TAP_THS_6D                   0x59 //
#define INT_DUR2                     0x5a //
#define WAKE_UP_THS                  0x5b //
#define WAKE_UP_DUR                  0x5c //
#define FREE_FALL                    0x5d //
#define MD1_CFG                      0x5e //
#define MD2_CFG                      0x5f //
#define MASTER_CMD_CODE              0x60 //----------
#define SENS_SYNC_SPI_ERROR_CODE     0x61 //

/*reserved*/

#define OUT_MAG_RAW_X_L              0x66 //
#define OUT_MAG_RAW_X_H              0x67 //
#define OUT_MAG_RAW_Y_L              0x68 //
#define OUT_MAG_RAW_Y_H              0x69 //
#define OUT_MAG_RAW_Z_L              0x6a //
#define OUT_MAG_RAW_Z_H              0x6b //

/*reserved*/

#define X_OFS_USR                    0x73 //加速度用户偏移矫正
#define Y_OFS_USR                    0x74 //
#define Z_OFS_USR                    0x75 //


/*  配置  */
uint8_t LSM6DSL_Config[]={
	CTRL3_C                  ,   0x81,//软件重启
//	FUNC_CFG_ACCESS          ,   0x00,
//	SENSOR_SYNC_TIME_FRAME   ,   0x00,
//	SENSOR_SYNC_RES_RATIO    ,   0x00,
//	FIFO_CTRL1               ,   0x00,
//	FIFO_CTRL2               ,   0x00,
//	FIFO_CTRL3               ,   0x00,
//	FIFO_CTRL4               ,   0x00,
//	FIFO_CTRL5               ,   0x00,
	DRDY_PULSE_CFG_G         ,   0x80,//脉冲触发(不锁存中断引脚)
  INT1_CTRL                  ,   0x01,//INT1引脚上各种中断事件的使能位//加速度中断
//  INT2_CTRL                  ,   0x02,//INT2引脚上各种中断事件的使能位//角速度中断
  CTRL1_XL                   ,   0x94,//加速度输出频率,量程,带宽//[0x60]416Hz  16g
//  CTRL2_G                    ,   0x64,//角速度输出速率,量程,满量程125,0//416hZ 500DPS
//  CTRL4_C                  ,   0x13,//
//  CTRL5_C                  ,   0x14,//
//  CTRL6_C                  ,   0x15,//
//  CTRL7_G                  ,   0x16,//
//  CTRL8_XL                 ,   0x17,//
//  CTRL9_XL                 ,   0x18,//
//  CTRL10_C                 ,   0x19,//
//  MASTER_CONFIG            ,   0x1a,//I2C主配置寄存器
//  TAP_CFG                  ,   0x58,//中断寄存器
//  TAP_THS_6D               ,   0x59,//
//  INT_DUR2                 ,   0x5a,//
//  WAKE_UP_THS              ,   0x5b,//
//  WAKE_UP_DUR              ,   0x5c,//
//  FREE_FALL                ,   0x5d,//
//  MD1_CFG                  ,   0x5e,//
//  MD2_CFG                  ,   0x5f,//
//  MASTER_CMD_CODE          ,   0x60,//----------
//  SENS_SYNC_SPI_ERROR_CODE ,   0x61,//
//  X_OFS_USR                ,   0x73,//加速度用户偏移矫正
//  Y_OFS_USR                ,   0x74,//
//  Z_OFS_USR                ,   0x75,//
};
/* 初始化 */
int LSM6DSL_init()
{
	uint8_t i=0,ID=0;
	//---------------------------------------
	I2C_ReadData(&ID,1,WHO_AM_I);
	if(ID==0x6a) {
	    //printf("product ID: 0x%02X\n\r",ID);
	} else {
		  printf("[error] ID Wrong! %02X\n\r",ID);
		return -1;
	}
	//---------------------------------------
	for(i=0;i<sizeof(LSM6DSL_Config)/sizeof(uint8_t)/2;i++) {
		 //printf("R=0x%02X\tV=0x%02X\n\r",LSM6DSL_Config[i*2],LSM6DSL_Config[i*2+1]);
		if(I2C_WriteData(LSM6DSL_Config+i*2+1,1,LSM6DSL_Config[i*2])!=0) {
			printf("[error] I2C_WriteData Wrong!\n\r");
			return -2;
		}
	}
	//---------------------------------------
  printf("[success] LSM6DSL_init()\n\r");
	return 0;
}






以下是硬件IIC 二次封装的函数,建议放在i2c.c文件中。

/* USER CODE BEGIN 1 */

#include <stdio.h>
//IIC
#define LSM6DSL_DEV_Adress  0xd6
#define IIS2DLPC_DEV_Adress 0x30
#define LIS2DH12_DEV_Adress 0x30
int I2C_WriteData(uint8_t* pData,uint16_t Size,uint16_t MeAddress)
{
	HAL_StatusTypeDef ret =HAL_ERROR;
	uint16_t DevAddress=0;//设备地址
  uint16_t MemAddsize=I2C_MEMADD_SIZE_8BIT;
	uint32_t Timeout=1000;
	I2C_HandleTypeDef* hi2cX=NULL;
  hi2cX=&hi2c1;
	DevAddress=LIS2DH12_DEV_Adress;
	//IIC发送
	ret=HAL_I2C_Mem_Write(hi2cX,DevAddress,MeAddress,MemAddsize,pData,Size,Timeout);
	return ret;
}

int I2C_ReadData(uint8_t* pData,uint16_t Size,uint16_t MeAddress)
{
	uint16_t DevAddress=0;//设备地址
	//uint16_t MeAddress=0;
  uint16_t MemAddsize=0;
	uint32_t Timeout=1000;
	I2C_HandleTypeDef* hi2cX=NULL;
	hi2cX=&hi2c1;
	DevAddress=LIS2DH12_DEV_Adress;
	MemAddsize=I2C_MEMADD_SIZE_8BIT;
	//IIC读取
	if(HAL_OK == HAL_I2C_Mem_Read(hi2cX,DevAddress,MeAddress,MemAddsize,pData,Size,Timeout)) {
		return 0;
	}
	return -1;
}



/* USER CODE END 1 */

以下函数 用于计算 加速度模长。


uint16_t Calculate_AccXYZ(int16_t X,int16_t Y,int16_t Z)
{
    uint32_t temp = X*X+Y*Y+Z*Z;
	  return (uint16_t)sqrt(temp);
}

以下函数为读取加速度值,其中ZZZ表示Z轴方向上的数值。

uint8_t Acc_Value[6];
int16_t ZZZ=0;
I2C_ReadData(Acc_Value,6,0x28);// 0x28 //加速度计输出寄存器
ZZZ =Acc_Value[4] + (Acc_Value[5]<<8);
		

希望能够对大家有所帮助。

  • 8
    点赞
  • 68
    收藏
    觉得还不错? 一键收藏
  • 20
    评论
### 回答1: 基于STM32F103的ADXL345加速度传感器程序可以通过以下步骤实现: 1. 配置STM32F103的GPIO引脚,将SCL和SDA引脚连接到ADXL345的SCL和SDA引脚。 2. 初始化I2C总线,使用STM32F103的I2C模块来与ADXL345进行通信。设置ADXL345的I2C地址,并使能I2C总线。 3. 配置ADXL345的寄存器,设置测量范围、输出数据速率等参数。可以使用I2C总线向ADXL345的控制寄存器写入配置数据。 4. 进入连续测量模式,使ADXL345开始采集加速度数据,并存储在其数据寄存器中。 5. 使用I2C总线读取ADXL345的数据寄存器,将加速度数据读取到STM32F103的缓冲区中。 6. 对读取的加速度数据进行解析和处理,如进行单位转换和数据滤波等操作。 7. 将处理后的加速度数据用于其他应用或进行进一步分析。 8. 可以在程序中设置一个延时,来控制采样频率,以控制ADXL345的数据输出速率。 9. 程序可以通过串口或其他方式将加速度数据输出,也可以使用LCD显示屏等外设进行实时显示。 需要注意的是,在实现该程序时,需要参考STM32F103的开发文档和ADXL345的数据手册,了解其I2C通信协议和寄存器配置等相关信息。同时,还需根据具体的应用需求进行适当的修改和优化。 ### 回答2: 基于STM32F103的ADXL345加速度传感器程序的开发可以分为以下几个步骤: 1. 硬件连接:将ADXL345与STM32F103连接,通过I2C接口进行数据传输。根据硬件接口和引脚连接规格进行正确的连接。 2. 初始化配置:在STM32F103的程序中,首先需要对IIC总线进行初始化配置,包括设置时钟速率、IIC模式等。接着需要对ADXL345进行初始化配置,包括设置测量范围、数据输出率等。 3. 数据读取:在程序中使用I2C读取数据的函数,从ADXL345中读取加速度数据。可以使用连续读取模式,读取X、Y、Z轴的加速度数据,然后进行数据处理。 4. 数据处理:读取到的原始加速度数据是16位的,需要进行数据转换和处理。可以根据ADXL345的配置参数和数据格式,通过相应的转换公式将原始数据转换为实际的加速度值。 5. 数据应用:将处理后的加速度数据应用到具体的应用场景中。例如可以用于姿态检测、运动检测等,根据具体的需求进行相应的应用开发。 需要注意的是,为了确保程序的准确性和稳定性,还需要进行异常处理,如通信异常、超时等情况的处理。同时,根据具体的要求和功能开发,可能还需要进行数据滤波、校准等处理,以提高传感器的精度和稳定性。 整个程序开发过程中,需要根据ADXL345的数据手册和STM32F103的技术手册进行相应的开发和调试。最终,通过编译、下载和运行代码,在STM32F103上成功读取并处理ADXL345的加速度数据。 ### 回答3: 基于STM32F103的ADX345加速度传感器程序主要包括以下几个步骤: 1. 硬件连接:确保ADX345传感器正确连接到STM32F103开发板上。ADX345传感器一般使用I2C或SPI接口与STM32F103通信。根据实际情况选择连接方式,并确保连接正确。 2. 寄存器初始化:使用STM32F103的I2C或SPI接口向ADX345传感器写入初始化参数,包括传感器工作模式、采样率等。 3. 数据读取:使用STM32F103的I2C或SPI接口从ADX345传感器读取加速度数据。根据ADX345传感器的数据格式,进行相应的数据解析。 4. 数据处理和应用:获取到的加速度数据可以进行各种处理和应用。例如,可以计算加速度的绝对值、角度、速度等;或者根据具体需求进行其他各种数据处理和应用。 5. 输出结果:可以通过串口、LCD显示屏或其他外设输出加速度数据。根据实际需求选择相应的输出方式,并将处理后的数据进行格式化输出。 编写ADX345加速度传感器程序需要熟悉STM32F103的编程和外设驱动,同时了解ADX345传感器的工作原理和数据格式。根据具体需求,可以进一步扩展和优化程序,实现更多功能和应用。
评论 20
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值