资讯详情

[单片机框架][drivers层][g_sensor][adxl34x] 加速度传感器的使用

在这里插入图片描述 ADXL345功耗低,三轴MEMS具有加速度计模块I2C和SPI接口Adafruit Breakout板载板载3.3v电压调节和电平转换功能使其易于与Arduino等5v微控制器接口。

ADXL从 /- 2G到 /- 16G。它支持10Hz到3200Hz输出数据速率。

工作原理:

MEMS-微型机电系统传感器由硅晶片上的微机械结构组成。该结构由多晶硅弹簧悬挂,当在X,Y当加速度在/或Z轴上时,它可以在任何方向上平滑偏转。偏转会导致固定板与连接到悬架结构的板之间的电容变化。每个轴上的电容变化将转换为与轴上加速度成比例的输出电压。

I2C接线: ADXL345分支的I2C地址为0x53.只要每个设备都有一个独特的地址,它就可以与其他设备一起使用I2C设备共享I2C总线。

  1. 超低功耗:在 V S = 2.5 V(典型值)时,测量模式低至 23 μA,低到待机模式 0.1 μA
  2. 功耗随带宽自动扩大
  3. 用户可以选择的分辨率 ①固定 10 位分辨率 ②全分辨率随g的范围而增加,在 ±16 g分辨率高达 13 位置(在所有g范围内保持 4 mg/LSB 比例因子)

ADXL345 小,薄,低功耗,3 轴加速度计高达 ±16 g高分辨率(13 位)测量值。数字输出数据格式为 16 二进制补码可以通过 SPI(3 线或 4 线)或 I 2 C 访问数字接口。

ADXL345 非常适合移动设备应用。测量倾斜感应应用中的静态重力加速度和运动或冲击产生的动态加速度。其高分辨率 (4 m g /LSB) 可测量小于 1.0° 倾角变化。

它提供了几种特殊的传感功能。活动和非活动感应检测运动的存在或缺应,以及任何轴上的加速度是否超过用户设置的水平。轻敲感应检测单击和双击。自由落体感应检测设备是否在下降。这些功能可以映射到两个中断输出引脚之一。一个正在申请专利的 32 级先进先出 (FIFO) 缓冲器可用于存储数据,以尽量减少主机处理器的干预。

低功耗模式支持基于运动的智能电源管理,具有阈值感应和主动加速度测量功能,功耗极低。

ADXL345 采用小型、薄、3 mm × 5 mm × 1 mm、14 引脚塑料封装。

#ifndef __G_SENSOR_CORE_H #define __G_SENSOR_CORE_H  #include <stdint.h> #include <stdbool.h> #include "bsp_i2c.h"  typedef struct { 
            bsp_i2c_bus_t i2c_bus;     uint8_t dev_addr;      // 8bit addr }g_sensor_cfg_t;  bool g_sensor_get_version(void);  bool g_sensor_get_data(short *x, short *y, short *z); bool g_sensor_set_offset(short *x, short *y, short *z);  void g_sensor_open_sample(void);  void g_sensor_irq_trigger_para(uint8_t activity_val, uint8_t activity_time_ms,                               uint8_t static_val, uint8_t static_time_s, uint8_t axis);
void g_sensor_enter_sleep(void);
void g_sensor_set_low_power_awaken(void);

#endif

#ifndef __ADXL34X_H
#define __ADXL34X_H
/* -----------------------------------------头文件-----------------------------------------*/
#include <stdint.h>
#include <stdbool.h>

/* -----------------------------------------宏定义-----------------------------------------*/
#define REG_DEVICE_ID 0X00 // 器件ID 0xE5
#define REG_THRESH_TAP 0X1D // 敲击阈值
#define REG_OFSX 0X1E // X轴偏移
#define REG_OFSY 0X1F // Y轴偏移
#define REG_OFSZ 0X20 // Z轴偏移
#define REG_DUR 0X21
#define REG_LATENT 0X22
#define REG_WINDOW 0X23
#define REG_THRESH_ACT 0X24
#define REG_THRESH_INACT 0X25
#define REG_TIME_INACT 0X26
#define REG_ACT_INACT_CTL 0X27
#define REG_THRESH_FF 0X28
#define REG_TIME_FF 0X29
#define REG_TAP_AXES 0X2A
#define REG_ACT_TAP_STATUS 0X2B
#define REG_BW_RATE 0X2C
#define REG_DATAX0 0X32
/* * 寄存器0x32至0x37—DATAX0、DATAX1、DATAY0、DATAY1、DATAZ0和DATAZ1(只读) * 输出数据为二进制补码,DATAx0为最低有效字节,DATAx1为最高有效字节 */

/* * POWER_CTL(读/写) D7 D6 D5 D4 D3 D2 D1 D0 0 0 Link AUTO_SLEEP Measure Sleep Wakeup 休眠模式下的读取频率 设置 D1 D0 频率(Hz) 0 0 8 0 1 4 1 0 2 1 1 1 */
#define REG_POWER_CTL 0X2D
#define REG_INT_ENABLE 0X2E
#define REG_INT_MAP 0X2F
#define REG_INT_SOURCE 0X30
/* * SELF_TEST位设置为1时,自测力作用于传感器,造成输出 数据转换。值为0时,禁用自测力。 D7 D6 D5 D4 D3 D2 D1 D0 SELF_TEST SPI INT_INVERT 0 FULL_RES Justify Range SELF_TEST位:设置为1时,自测力作用于传感器,造成输出数据转换。 值为0时,禁用自测力。 INT_INVERT位:值为0时,将中断设为高电平有效;值为1时, 则将中断设为低电平有效。 FULL_RES位:当此位值设置为1时,该器件为全分辨率模式,输出分辨 率随着范围位设置的g范围以4 mg/LSB的比例因子而增加。 D1 D0 g范围 0 0 ±2g 0 1 ±4g 1 0 ±4g 1 1 ±16g */
#define REG_DATA_FORMAT 0X31
#define REG_DATA_X0 0X32
#define REG_DATA_X1 0X33
#define REG_DATA_Y0 0X34
#define REG_DATA_Y1 0X35
#define REG_DATA_Z0 0X36
#define REG_DATA_Z1 0X37
#define REG_FIFO_CTL 0X38
#define REG_FIFO_STATUS 0X39
#define REG_ADXL_READ 0X3B
#define REG_ADXL_WRITE 0X3A

#endif

/******************************************************************************** * @file g_sensor_core.c * @author jianqiang.xue * @Version V1.0.0 * @Date 2021-08-21 * @brief 参考: http://blog.sina.com.cn/s/blog_17029604f0102wxtp.html [校准原理] 首先,这个校准的过程是手动的(类似手机上的传感器校准),把模块水平放置(这个水平也只是个大概,如果要求高的话,还需要其他仪器辅助), 那么x轴和y轴的度数应该为0g, 获取此时的实际x轴和y轴的度数,假设是20和-17。 要注意此时传感器的量程和分辨率,假设此时adxl345是常规量程 -16g,分辨率13位, 那么此时度数的系数应该是1g/256 *1000 = 3.9 mg/LSB,(手册第三页数据表) 从数据手册上可以查到 偏移寄存器的比例因子是 15.6mg/LSB(固定的,与量程无关) 那么需要设定的实际偏移值就是 20/4 = 5和-17/4 = 4(15.6/3.9约为4) 然后取两个值的补码,分别为0x05和0xFB,写入对应的偏移寄存器。 这样,每次从传感器读取的数值就自动加上了这个设置的偏移。 z轴的偏移值检测方式一样,把z轴水平放置(处于0g场)。 ********************************************************************************/
/* Includes ------------------------------------------------------------------*/
#include <stdint.h>
#include <stdbool.h>
#include <string.h>

#include "bsp_i2c.h"
/* Private includes ----------------------------------------------------------*/
#include "g_sensor_core.h"
#include "adxl34x.h"
#include "log.h"
/* Private define ------------------------------------------------------------*/
#define ADXL345_DEVICE_ID 0XE5
#define ADXL346_DEVICE_ID 0XE6
/* Private typedef -----------------------------------------------------------*/
static const g_sensor_cfg_t g_sensor_info =
{ 
       
    .i2c_bus  = I2C_BUS0,
    .dev_addr = 0xA6,
};
uint8_t device_version = 0; // 记录传感器版本
uint8_t ret = 0;
uint8_t xyx_data[6] = { 
       0};

/* Private macro -------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
/* Public function prototypes -----------------------------------------------*/
static uint8_t i2c_read_byte(uint8_t reg_addr, uint8_t *r_data)
{ 
       
    return bsp_i2c_read_byte(g_sensor_info.i2c_bus, g_sensor_info.dev_addr,
                             reg_addr, r_data);
}

static uint8_t i2c_read_nbyte(uint8_t reg_addr, uint8_t *r_data, uint8_t r_len)
{ 
       
    return bsp_i2c_read_nbyte(g_sensor_info.i2c_bus, g_sensor_info.dev_addr,
                              &reg_addr, 1, r_data, r_len);
}

static uint8_t i2c_write_byte(uint8_t reg_addr, uint8_t w_data)
{ 
       
    return bsp_i2c_write_byte(g_sensor_info.i2c_bus, g_sensor_info.dev_addr,
                              reg_addr, w_data);
}

/** * @brief 读取传感器版本,用于判断器件是否可用 * @note NULL * @retval 0--失败 1--成功 */
bool g_sensor_get_version(void)
{ 
       
    i2c_read_byte(REG_DEVICE_ID, &device_version);
    //LOG_D("ADXL:0x%02x\r\n", device_id_val);
    if (device_version != ADXL345_DEVICE_ID && device_version != ADXL346_DEVICE_ID)
    { 
       
        return false;
    }
    return true;
}

/** * @brief 设置活动/静止时的值,和哪三轴可以触发中断 * @note NULL * @param activity_val: 活动阈值 变化幅度 * @param activity_time_ms: 活动阈值时间 单位:ms * @param static_val: 静止阈值 变化幅度 * @param static_time_s: 静止时间 单位:s * @param axis: * * [7bit] 活动检测 0--直接REG_THRESH_ACT比较 1--相对值达到REG_THRESH_ACT * * [6bit] X_EN [5bit] Y_EN [4bit] Z_EN * * [3bit] 静止检测 0--直接REG_THRESH_INACT比较 1--相对值达到REG_THRESH_INACT * * [2bit] X_EN [1bit] Y_EN [0bit] Z_EN * @retval None */
void g_sensor_irq_trigger_para(uint8_t activity_val, uint8_t activity_time_ms,
                               uint8_t static_val, uint8_t static_time_s, uint8_t axis)
{ 
       
    // 活动阈值 变化幅度
    i2c_write_byte(REG_THRESH_ACT, activity_val);
    // 活动阈值时间 单位:ms
    i2c_write_byte(REG_DUR, activity_time_ms);
    // 静止阈值
    i2c_write_byte(REG_THRESH_INACT, static_val);
    // 静止时间 单位:s
    i2c_write_byte(REG_TIME_INACT, static_time_s);
    // 活动静止任意轴选择 选择三轴使能
    i2c_write_byte(REG_ACT_INACT_CTL, axis);
}

/** * @brief 传感器进入睡眠状态,如果之前配置了中断,那么就会清除中断功能 * @note 如果想要中断唤醒,则先使用本函数,再调用g_sensor_set_low_power_awaken * @retval None */
void g_sensor_enter_sleep(void)
{ 
       
    // 中断清零前,应读取ACT_TAP_STATUS寄存器
    i2c_read_byte(REG_ACT_TAP_STATUS, &ret);
    // 读取中断标志寄存器,读一次清空一次中断标记
    i2c_read_byte(REG_INT_SOURCE, &ret);
    // 禁用 中断功能
    i2c_write_byte(REG_INT_ENABLE, 0x00);
    // 设置时需进入休眠模式 1HZ采集一次
    i2c_write_byte(REG_POWER_CTL, 0x01);
}

/** * @brief 配置加速度传感器,活动触发中断(用于低功耗唤醒),需要先配置g_sensor_irq_trigger_para * @note NULL * @retval None */
void g_sensor_set_low_power_awaken(void)
{ 
       
    g_sensor_enter_sleep();
    // 使能 中断 ININ1
    i2c_write_byte(REG_INT_MAP, 0x00);
    // 寄存器0x31—DATA_FORMAT(读/写)--中断设为高电平有效--全分辨率模式--右对齐模式--+16g
    i2c_write_byte(REG_DATA_FORMAT, 0x0B);
    i2c_write_byte(REG_INT_ENABLE, 0x10);  // 开启动态中断模式,19页
}

/** * @brief 传感器开始工作采集[FIFO流模式] * @note 流程:设置流模式--进入待机状态--进入测试状态 * @retval None */
void g_sensor_open_sample(void)
{ 
       
    // FIFO流模式 将触发模式下的触发事件链接至INT2(这个中断脚没有使用)
    i2c_write_byte(REG_FIFO_CTL, 0xA8);
    // 待机模式
    i2c_write_byte(REG_POWER_CTL, 0x00);
    // 测量模式
    i2c_write_byte(REG_POWER_CTL, 0x08);
}

/** * @brief 读取一次传感器值 * @note NULL * @retval 0--失败 1--成功 */
bool g_sensor_get_data(short *x, short *y, short *z)
{ 
       
    if (i2c_read_nbyte(REG_DATAX0, xyx_data, 6) != 0)
    { 
       
        return false;
    }
    *x = xyx_data[1] << 8 | xyx_data[0];
    *y = xyx_data[3] << 8 | xyx_data[2];
    *z = xyx_data[5] << 8 | xyx_data[4];
    return true;
}

/** * @brief 设置传感器offset值(一次性,器件掉电或重启需要重新设置) * @note -16g,分辨率13位,系数应该是1g/256 *1000 = 3.9 mg/LSB,(手册第三页数据表) 偏移寄存器的比例因子是 15.6mg/LSB(固定的,与量程无关) 那么需要设定的实际偏移值就是 x/4(15.6/3.9约为4) * @retval 0--失败 1--成功 */
bool g_sensor_set_offset(short *x, short *y, short *z)
{ 
       
    // 设置X轴偏移量
    i2c_write_byte(REG_OFSX, (char)(-(*x / 4)));
    // 设置Y轴偏移量
    i2c_write_byte(REG_OFSY, (char)(-(*y / 4)));
    // 设置Z轴偏移量
    i2c_write_byte(REG_OFSZ, (char)(-(*z / 4)));
    return true;
}

标签: 传感器adxl001微g加速度传感器加速度传感器adxl345arduino中加速度传感器连接器345

锐单商城拥有海量元器件数据手册IC替代型号,打造 电子元器件IC百科大全!

锐单商城 - 一站式电子元器件采购平台