由于数据采集站基本都安装在野外或者楼顶,安装位置以及震动对检测数据的准确性有一定影响。所以想要有一个位置状态数据,正好发现麒麟作上有ADXL345,这样一个数字输出的加速度传感器。如图中红框所示:

1ADXL345概述

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

  • 分辨率高。最高13位分辨率。
  • 量程可变。具有+/-2g,+/-4g,+/-8g,+/-16g可变的测量范围。
  • 灵敏度高。最高达3.9mg/LSB,能测量不到1.0°的倾斜角度变化。
  • 功耗低。 40~145uA 的超低功耗,待机模式只有 0.1uA。
  • 尺寸小。整个 IC 尺寸只有 3mm*5mm*1mm, LGA 封装。

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

当 ADXL345 沿检测轴正向加速时,它对正加速度进行检测。在检测重力时用户需要注意,当检测轴的方向与重力的方向相反时检测到的是正加速度。下图所示为输出响应与相对于重力的方向的关系:

2、硬件设计

ADXL345支持SPI 和I2C两种通信方式,麒麟座采用的I2C通讯方式,具体连接如下图所示:

对于任何不使用的引脚,没有内部上拉或下拉电阻,因此,CS引脚或ALT ADDRESS引脚悬空或不连接时,任何已知状态或默认状态不存在。使用I2C时, CS引脚必须连接至VDD I/O, ALT ADDRESS引脚必须连接至任一VDD I/O或接地。

ALT ADDRESS引脚处于高电平,器件的7位I2C地址是0x1D,随后为R / W位。这转化为0x3A写入,0x3B读取。通过ALT ADDRESS引脚(引脚12)接地,可以选择备用I2C地址0x53(随后为R / W位)。这转化为0xA6写入, 0xA7读取。

由于在麒麟座中,ALT ADDRESS引脚(引脚12)接地,所以地址为0x53,也就是0xA6写入, 0xA7读取。此外2个终端信号也引入了MCU。

3、软件设计

接下来我们开始软件方面的设计。因为麒麟座中ADXL345使用I2C接口与MCU通讯,并连接到了I2C2(PB10、PB11)端口,接下来我们将逐步实现这部分软件。

(1)I2C读写操作

因为ADXL345加速度传感器使用了标准的I2C通讯接口,所以我们来看一看I2C读写单个或多个子解释的报文格式(如下图)。

根据以上报文图示,并结合STM32F1的库函数我们封装读写字节操作的函数。封装发送命令和获取数据函数:

/*向ADXL345下发指令,指令格式均为1个字节*/

void WriteByteToADXL345(I2C_TypeDef* I2Cx,uint8_t deviceAddress,uint8_t command)

{

  uint16_t i2cTimeout=TimeoutPeriod;

  /*产生I2C起始信号*/

  I2C_GenerateSTART(I2C2, ENABLE);

  /*检测 EV5 事件并清除标志*/

  while (!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_MODE_SELECT))

  {

    if ((i2cTimeout--) == ) return ;

  }

  /*发送ADXL345的地址*/

  I2C_Send7bitAddress(I2Cx,deviceAddress,I2C_Direction_Transmitter);

  i2cTimeout=TimeoutPeriod;

  /*检测 EV6 事件并清除标志*/

  while (!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED))

  {

    if ((i2cTimeout--) == ) return ;

  }

  /*下发操作命令*/

  I2C_SendData(I2Cx, command);

  i2cTimeout=TimeoutPeriod;

  /*检测 EV8 事件并清除标志*/

  while (!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_BYTE_TRANSMITTED))

  {

    if ((i2cTimeout--) == ) return ;

  }

  /* 产生I2C停止信号 */

  I2C_GenerateSTOP(I2Cx, ENABLE);

}

/*从ADXL345读取多个字节数据的值*/

void ReadBytesFromADXL345(I2C_TypeDef* I2Cx,uint8_t deviceAddress,uint8_t *pData,uint16_t bytesNum)

{

  uint16_t i2cTimeout=TimeoutPeriod;

  /*如果I2C总线忙,则等待一段时间*/

  while (I2C_GetFlagStatus(I2Cx, I2C_FLAG_BUSY))

  {

    if ((i2cTimeout--) == ) return ;

  }

  /* 产生 I2C 起始信号 */

  I2C_GenerateSTART(I2Cx, ENABLE);

  /*检测 EV5 事件并清除标志*/

  while (!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_MODE_SELECT))

  {

    if ((i2cTimeout--) == ) return ;

  }

  /*发送ADXL345的地址*/

  I2C_Send7bitAddress(I2Cx,deviceAddress,I2C_Direction_Receiver);

  i2cTimeout=TimeoutPeriod;

  /*检测 EV6 事件并清除标志*/

  while (!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED))

  {

    if ((i2cTimeout--) == ) return ;

  }

  while(bytesNum)

  {

    if(bytesNum==)

    {

      I2C_AcknowledgeConfig(I2Cx, DISABLE);//关闭应答

      I2C_GenerateSTOP(I2Cx, ENABLE);//停止信号

    }

    i2cTimeout=TimeoutPeriod;

    /*检测 EV7 事件并清除标志*/

    while (!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_BYTE_RECEIVED))

    {

      if ((i2cTimeout--) == ) return ;

    }

    /*通过 I2C,从设备中读取一个字节的数据 */

    *pData=I2C_ReceiveData(I2Cx);

    pData++;

    bytesNum--;

  }

  /*使能应答,方便下一次 I2C 传输*/

  I2C_AcknowledgeConfig(I2Cx, ENABLE);

}

2ADXL寄存器及操作

ADXL345传感器拥有29个用户可见的寄存器,如下图所示。但是我们不对其进行具体的介绍,在数据手册上有非常详细的说明。这些寄存器我们并不会全部使用,事实上通常我们只是用配置寄存器和部分数据寄存器。

在使用ADXL345读取我们想要的数居前,我们先使用相关寄存器对传感器进行必要的配置,以期获取我们想要得到的值。如下初始化配置过程:

void ADXL345_Init_Configuration(void)
{
uint8_t devid = , val = ; Delayus (); ReadByteFromADXL345 (ADXL345_ADDRESS, 0x00, &devid); //获取设备ID Delayus (); val = 0x2B; WriteByteToADXL345 (ADXL345_ADDRESS, DATA_FORMAT_REG, &val); //数据格式控制 Delayus(); val = 0x0A; WriteByteToADXL345 (ADXL345_ADDRESS, BW_RATE, &val); //数据速率及功率模式控制 Delayus(); val = 0x28; WriteByteToADXL345 (ADXL345_ADDRESS, POWER_CTL, &val); //上电特性控制 Delayus(); val = ; WriteByteToADXL345 (ADXL345_ADDRESS, INT_ENABLE, &val); //中断使能控制 Delayus(); WriteByteToADXL345 (ADXL345_ADDRESS, OFSX, &val); //X轴偏移 Delayus(); WriteByteToADXL345 (ADXL345_ADDRESS, OFSY, &val); //Y轴偏移 Delayus(); WriteByteToADXL345 (ADXL345_ADDRESS, OFSZ, &val); //Z轴偏移 Delayus();
}

(3)ADXL345数据获取

接下来我们就可以读取数据了,获取和解析数据前我们先来了解一下数据的格式。分别在寄存器0x2C中进行速率控制,在寄存器0x31中进行数据格式控制。ADXL345的输出数据可以采用右对齐和左对齐两种方式。

数据右对齐方式:

数据左对齐方式:

此外,ADXL345通过VS = 2.5 V电源电压的测试且以其为额定电压;然而, VS可高至3.6 V或低至2.0 V。在麒麟座中解释使用的3.3VDC供源,偏移、灵敏度、噪声、自测和电源电流等参数随着电源电压变化而变化。随着电源电压的改变,静电力也发生细微变化,因此,偏移和灵敏度也有细微变化。在电源电压VS = 3.3 V下运行时, x轴和y轴偏移通常比VS = 2.5 V运行时高25 mg。在电源电压3.3 V下运行与在VS = 2.5V时比较, z轴偏移一般低20 mg。VS = 2.5V时, x轴和y轴的灵敏度为标称256 LSB/g(全分辨率或±2 g, 10位运行),而电源电压为3.3 V时,其灵敏度转换为265 LSB/g。 z轴灵敏度不受电源电压影响, 2.5 V时或3.3 V时都相同。可以用简单的线性插值来确定其他电源电压下的偏移和灵敏度的典型转换。

搞清楚了以上问题就可以读取正确的数据了:

void GetValue FromADXL345 (void)
{
unsigned char devid = ;
unsigned char dataTemp[]; Delayus(); ReadByteFromADXL345(ADXL345_ADDRESS, 0x00, &devid); //读取设备ID Delayus(); ReadBytes FromADXL345 (ADXL345_ADDRESS, 0x32, dataTemp, ); //获取原始数据(4mg/LSB) adxlInfo.incidence_X = (short)(dataTemp[] + ((unsigned short)dataTemp[] << )); adxlInfo.incidence_Y = (short)(dataTemp[] + ((unsigned short)dataTemp[] << )); adxlInfo.incidence_Z = (short)(dataTemp[] + ((unsigned short)dataTemp[] << )); adxlInfo.incidence_Xf = (float)adxlInfo.incidence_X * 0.0039; //换算为物理量值 adxlInfo.incidence_Yf = (float)adxlInfo.incidence_Y * 0.0039; //换算为物理量值 adxlInfo.incidence_Zf = (float)adxlInfo.incidence_Z * 0.0039; //换算为物理量值
}

至此软件编写完成。

4、结果验证

完成编写后,编译无误。我们查看最终的运行结果如何。首先我们登录到OneNET,并组态好设备和应用,然后下载程序重新上电,就可以看到Xg、Yg、Zg的数据以及上次我们读取的温湿度数据:

我们再看一下显示屏中显示的数据是什么样的。因显示精度不同有些差异,但基本是一致的。

至此,我们完成了ADXL345数据的获取以及上传到OneNET,在后续我们将继续各种OneNET以及麒麟座开发板的研究。OneNET真的是越用越有意思。

OneNET麒麟座应用开发之五:获取加速度传感器ADXL345数据的更多相关文章

  1. OneNET麒麟座应用开发之四:数据上传测试

    已经测试过OneNET麒麟座开发板了,这次来尝试与OneNET的连接和数据上传.这也是我们测试这块开发办的主要原因,因为在十几种我们有这种将分散的采集点数据上传到后台的需求. 先看看麒麟座这块开发板, ...

  2. OneNET麒麟座应用开发之八:采集大气压力等环境参数

    采集大气压力和温度也是核算大气标准状况下的各种数据的必须参数,为此我们必须知道压力和温度才能计算标准状况下的各种参数,于此我们需要一个既能检测压力也能检测温度的元件. 1.硬件概述 MS5837压力传 ...

  3. OneNET麒麟座应用开发之六:与气体质量流量控制器通讯

    气体质量流量控制器,简称MFC,通常用于在各种检测中,计量气体的流量.在我们的大气环境数据采集站中,要让气流保持稳定,这样才能准确的获取PM25的数据. 我们采用的气体质量流量控制器具备串口通讯功能, ...

  4. OneNET麒麟座应用开发之一:初识OneNET麒麟座

    今天收到了OneNET麒麟座开发板.能得到使用的机会只能说是幸运的.首先上一张靓照: 板子使用的MCU是STM32F103RET6,带有GSM摸块和Wifi摸块可以联网.带有显示屏接口和I2C接口以及 ...

  5. 实践案例丨利用小熊派开发板获取土壤湿度传感器的ADC值

    摘要:一文带你用小熊派开发板动手做土壤湿度传感器. 一.实验准备 1.实验环境 一块stm32开发板(推荐使用小熊派),以及数据线 已经安装STM32CubeMX 已经安装KeilMDK,并导入stm ...

  6. OneNET麒麟座应用开发之七:控制采样电机

    气体采样采用主动抽取气体的方式保证充足而平稳的气流,所以我们采用气泵抽取气体来完成. 1.设计概述 客户对这部分要求能够设定电机的速度,但并不需要动态调节.对电机的控制有很多方式,我们采用比较简单的方 ...

  7. OneNET麒麟座应用开发之三:获取温湿度数据

    对于大气环境监测来说温湿度也是重要的指标.原本计划使用SHT15来采集温湿度数据,不过在OneNET麒麟开发板上,我们发现已经集成有SHT20温湿度传感器,于是我们就使用它了.如下图的红框处: 我们还 ...

  8. OneNET麒麟座应用开发之十:空气质量数据监测站项目总结

    大气质量数据监测站用于测试空气质量监测及数据采集,实现野外或者室内空气质量的检测. 1.项目概述 本项目是一个定制项目,要求采集大气的压力.温度.湿度.PM25.位置等数据并上传到指定的后台服务器.但 ...

  9. 微信小程序云开发-数据库-获取用户添加的数据到数据库

    一.列表页面新增[添加商品]按钮 在列表页增加[添加商品]按钮,按钮绑定事件toAdd(),用户点击该按钮跳转到添加商品页面. 在js文件中写toAdd()函数,作用是点击[添加商品]按钮,跳转到[添 ...

随机推荐

  1. JSP+MySQL中文乱码

    问题:JSP页面传输到MySQL数据库时,中文为乱码(数据库中存储乱码). 解决办法: 1.将所有的涉及到编码的都设置为 utf8(utf-8). 设置数据库编码:命令行执行:mysql> sh ...

  2. CentOS 7下Samba服务部署

    Samba,是种用来让UNIX系列的操作系统与微软Windows操作系统的SMB/CIFS(Server Message Block/Common Internet File System)网络协议做 ...

  3. Exception in thread "main" org.springframework.beans.factory.NoSuchBeanDefinitionException

    今天在学习spring 框架的时候看着,很简单.但是在真正开始做的时候发现,异常一个接着一个,整的肚子都被搞大了. Exception in thread "main" org.s ...

  4. Jenkins插件安装实战篇

    Jenkins插件安装实战篇 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 上篇博客我介绍了Jenkins是啥,以及持续集成,持续交付,持续部署的概念,那么问题来了:你知道CI和C ...

  5. linux系统下安装ruby环境

    1. 移除现有 Ruby 默认源 输入以下指令 $gem sources --remove https://rubygems.org/ 2. 使用新的源 输入以下指令 $gem sources -a  ...

  6. VS设置以管理员方式运行

    一直以为VS不能直接以管理员方式运行,原来它是在高级里的.

  7. axios - 基于 Promise 的 HTTP 异步请求库

    axios 是基于 Promise 的 HTTP 请求客户端,可同时在浏览器和 node.js 中使用.Vue 更新到2.0之后,作者就宣告不再对 vue-resource 模块更新,而是推荐使用 a ...

  8. Tomcat数据源的原理,配置及使用(JNDI)

    Tomcat数据源的原理,配置及使用 知识点: 1.数据源的作用及操作原理; 2.Tomcat中数据源的配置; 3.数据源的查找及使用 传统JDBC使用过程存在以下四个步骤: 1.加载驱动程序 2.进 ...

  9. Linux - 日志处理一

    Linux 日志处理 history # 历时命令默认1000条 HISTTIMEFORMAT="%Y-%m-%d %H:%M:%S " # 让history命令显示具体时间 hi ...

  10. pygame中多个class类之间的关系

    用一个实例介绍一下有关pygame中不同类之间的通信,详细介绍在代码段有标注,感兴趣的可以复制代码试试: import pygame import sys # -------------------- ...