美文网首页物联网loT从业者物联网相关技术研究
NRF52832学习笔记(20)——三轴加速度 BMA423使用

NRF52832学习笔记(20)——三轴加速度 BMA423使用

作者: Leung_ManWah | 来源:发表于2020-06-01 15:19 被阅读0次

    一、简介

    BMA423 采用内部加速计的原始数据并在内部处理数据,从而为开发人员提供有用的结果。这可为微控制器减掉一些负载并加快开发速度。当在可穿戴健身应用中使用时,它可以检测用户是静止不动、跑步还是走路。

    Bosch Sensortec 为其所有传感器提供固件。在给 BMA423 上电时,它会经历一个内部上电复位 (POR) 序列。在系统 POR 之后,微控制器应运行 Bosch 的 BMA423 初始化程序,以正确配置芯片。

    初始化程序首先读取内部芯片 ID,并把该 ID 与存储在固件中的芯片 ID 进行比较。这将验证 BMA423 是否可用并与微控制器正确通信。接下来,初始化程序运行短自检以验证能否正常运行,自检结果被发送回微控制器。设备初始化后,会处于性能模式,这是传感器的最高功率和最高性能状态。

    BMA423 具有许多用于低功耗运行的特性,包括 1024 字节宽的 FIFO。这让加速计能够在微控制器处于低功耗或休眠模式时检测和存储数据。由于不需要微控制器不断地与 BMA423 通信,这在非实时应用中节省了功耗。一旦 FIFO 中的加速计数据达到预编程的 FIFO 级别,就会产生中断以唤醒微控制器,然后微控制器转而执行驱动子程序以读取 FIFO 数据。

    BMA423 的最低功耗模式是挂起模式。在挂起模式期间,不执行内部加速计测量,同时保持 FIFO 和内部寄存器的状态。

    为了降低非实时应用中的运行功耗,应将 BMA423 置于低功耗模式而不是默认的性能模式。这会关闭 BMA423 的各个部分,包括外部 I2C 和 SPI 接口,同时将数据记录到 FIFO 中。在低功耗模式下,BMA423 会根据固件编程占空比设定的采样率在性能模式和休眠模式之间定期切换。采样率越低,BMA423 的功耗越低。调整此占空比可针对传感器功耗调整所需的精度。

    二、硬件连接

    功能口 引脚
    SCL 5
    SDA 4
    INT1 3

    三、添加I2C驱动

    查看 NRF52832学习笔记(19)——TWI(I2C)接口使用

    四、移植文件

    注意:以下出现缺失common.h文件错误,去除即可。uint8改为uint8_t或unsigned char或自己宏定义
    链接:https://pan.baidu.com/s/1JbNEZ81bGOaumLIKiPumRw 提取码:r1y8
    board_bma423.cboard_bma423.hbma423下所有文件,board_gpi.cboard_gpi.h 加入工程的Application文件夹下

    4.1 board_bma423.c

    /*********************************************************************
     * INCLUDES
     */
    #include "nrf_delay.h"
    #include "nrf_log.h"
    
    #include "board_bma423.h"
    #include "board_i2c.h"
    #include "common.h"
    
    #include "bma423.h"
    #include "bma4_defs.h"
    
    /*********************************************************************
     * LOCAL VARIABLES
     */
    static struct bma4_dev s_bma423;
    static struct bma4_accel_config s_accelConfig = {0};
    static struct bma4_fifo_frame s_fifoFrame = {0};
    static uint8 s_fifoBuffer[255] = {0};
    
    /*********************************************************************
     * PUBLIC FUNCTIONS
     */
    /**
     @brief BMA423三轴加速计驱动初始化
     @param 无
     @return 无
    */
    void BMA423_Init(void)
    {
        // ------------ 传感器I2C初始化 ------------
        /* Modify the parameters */
        s_bma423.dev_addr = BMA4_I2C_ADDR_PRIMARY;
        s_bma423.interface = BMA4_I2C_INTERFACE;
        s_bma423.bus_read = I2C_ReadData;
        s_bma423.bus_write = I2C_WriteData;
        s_bma423.delay = nrf_delay_ms;
        s_bma423.read_write_len = 8;
        /* Initialize the instance */
        bma423_init(&s_bma423);
        
        bma4_set_command_register(0xB6, &s_bma423);                                 // 软复位
        
        /* Enable the accelerometer */
        bma4_set_accel_enable(BMA4_ENABLE, &s_bma423);                                 
        
        bma423_write_config_file(&s_bma423);                                        // 更新配置参数
        
        uint8 value = 0;
        while(value != 0x01)
        {
            I2C_ReadData(BMA4_I2C_ADDR_PRIMARY, BMA4_INTERNAL_STAT, &value, 1);
    
            DelayMs(10);
            if(value != 0x01)                                                       // ASIC初始化完成
            {
                NVIC_SystemReset();
            }
        }
        DelayMs(10);                                                              
    
        // ------------ 配置加速度 ------------ 
        /* Assign the desired settings */
        s_accelConfig.odr = BMA4_OUTPUT_DATA_RATE_50HZ;
        s_accelConfig.range = BMA4_ACCEL_RANGE_4G;
        s_accelConfig.perf_mode = BMA4_DISABLE;                                     // averaging mode
        s_accelConfig.bandwidth = BMA4_ACCEL_OSR4_AVG1;
        /* Set the configuration */
        bma4_set_accel_config(&s_accelConfig, &s_bma423);
        DelayMs(1);
    
        // ------------ 配置FIFO ------------ 
        /* Modify the FIFO buffer instance and link to the device instance */ 
        s_fifoFrame.data = s_fifoBuffer;
        s_fifoFrame.length = 40;
        s_fifoFrame.fifo_data_enable = BMA4_ENABLE;
        s_fifoFrame.fifo_header_enable = BMA4_ENABLE;
        s_bma423.fifo = &s_fifoFrame;   
        /* Disable the advanced power save mode to configure the FIFO buffer */
        bma4_set_advance_power_save(BMA4_DISABLE, &s_bma423);
        /* Configure the FIFO buffer */
        bma4_set_fifo_config((BMA4_FIFO_ACCEL | BMA4_FIFO_HEADER), BMA4_ENABLE, &s_bma423);
        DelayMs(1);
    
        // ------------ 配置运动/非运动检测 ------------
        struct bma423_anymotion_config anymotionConfig;
        bma423_get_any_motion_config(&anymotionConfig, &s_bma423);
        anymotionConfig.duration = 0x10;                                            // 定义中断必须遵守threshold条件的连续数据点的数目
        anymotionConfig.nomotion_sel = 0x7;
        anymotionConfig.threshold = 0x7FFF;                                         // 运动检测的斜率阈值
        /* Configure the Any motion feature */
        bma423_set_any_motion_config(&anymotionConfig, &s_bma423);            
        /*Enable the axis as per requirement for Any/no-motion. Here all axis has been enabled */    
        bma423_anymotion_enable_axis(BMA423_ALL_AXIS_EN, &s_bma423);
        /* Enable/select the Any-motion feature */
        bma423_feature_enable(BMA423_ANY_MOTION, BMA4_ENABLE, &s_bma423); 
        DelayMs(1);    
        
        // ------------ 配置中断 ------------
        struct bma4_int_pin_config intPinCofig;
        intPinCofig.edge_ctrl = BMA4_LEVEL_TRIGGER;                                 // 电平触发
        intPinCofig.lvl = BMA4_ACTIVE_LOW;                                  
        intPinCofig.input_en = BMA4_INPUT_DISABLE;
        intPinCofig.od = BMA4_OPEN_DRAIN;
        intPinCofig.output_en = BMA4_OUTPUT_ENABLE;                                 // 输出使能
        /* Set the electrical behaviour of interrupt pin1 */
        bma4_set_int_pin_config(&intPinCofig, BMA4_INTR1_MAP, &s_bma423);
        bma4_set_interrupt_mode(BMA4_NON_LATCH_MODE, &s_bma423);
        /* Map the Any-No-motion out interupt to INT pin1 */
        bma423_map_interrupt(BMA4_INTR1_MAP, BMA423_ANY_NO_MOTION_INT, BMA4_ENABLE, &s_bma423);
        DelayMs(10);
        
        bma4_set_advance_power_save(BMA4_ENABLE, &s_bma423);                        // 进入低功耗模式
    }
    
    /**
     @brief BMA423读取FIFO传感数据
     @param pAccelData -[in&out] 加速计数据缓冲区,存储FIFO中的数据
     @param pAccelLen -[in&out] 加速度数据条数
     @return 0 - 成功;非0 - 失败
    */
    uint16 BMA423_ReadFifoData(struct bma4_accel *pAccelData, uint16 *pAccelLen)
    {
        uint16 result = BMA4_OK; 
    
        /* Read data from the sensor FIFO buffer */
        result |= bma4_read_fifo_data(&s_bma423);                                   // Read FIFO data
        
        /* Exit the program in case of a failure */
        if(result != BMA4_OK)
        {
            return result;
        }
            
        /* Reset the maximum number of requried sensor data instances */
        *pAccelLen = 36;
            
        /* Parse the FIFO until there are less frames than requested */
        while(*pAccelLen == 36)
        {
            /* Parse the FIFO buffer and extract requried number of accelerometer data frames */
            result |= bma4_extract_accel(pAccelData, pAccelLen, &s_bma423);
                
            /* Exit the program in case of a failure */
            if(result != BMA4_OK)
            {
                return result;  
            }
        }
        
        return result;
    }
    
    /**
     @brief BMA423读取三轴加速度数据
     @param pAccelData -[in&out] 加速计数据缓冲区
     @return 0 - 成功;非0 - 失败
    */
    uint16 BMA423_ReadAccelData(struct bma4_accel *pAccelData)
    {   
        return bma4_read_accel_xyz(pAccelData, &s_bma423);
    }
    
    /****************************************************END OF FILE****************************************************/
    

    4.2 board_si522.h

    #ifndef _BOARD_BMA423_H_
    #define _BOARD_BMA423_H_
    
    /*********************************************************************
     * INCLUDES
     */
    #include "bma4.h" 
    #include "common.h"
    
    /*********************************************************************
     * API FUNCTIONS
     */
    void BMA423_Init(void);
    uint16 BMA423_ReadFifoData(struct bma4_accel *pAccelData, uint16 *pAccelLen);
    uint16 BMA423_ReadAccelData(struct bma4_accel *pAccelData);
    
    #endif /* _BOARD_BMA423_H_ */
    

    4.3 board_gpi.c

    /*********************************************************************
     * INCLUDES
     */
    #include "nrf_drv_gpiote.h"
    #include "app_error.h"
    
    #include "board_gpi.h"
    #include "user_bma423.h"
    #include "common.h"
    
    static void irqCallbackFunc(nrf_drv_gpiote_pin_t pin, nrf_gpiote_polarity_t action);
    
    /*********************************************************************
     * LOCAL VARIABLES
     */
    static uint8 s_irqValue;                                                        // 中断值
    
    /*********************************************************************
     * PUBLIC FUNCTIONS
     */
    /**
     @brief BMA423中断初始化函数
     @param 无
     @return 无
    */
    void Board_Bma423IrqInit(void)
    {
        ret_code_t errCode;
        
        // 需先调用nrf_drv_gpiote_init(),但如果有其他GPIOE中断程序已调用,在这里可以不调用
        if(!nrf_drv_gpiote_is_init())
        {
            errCode = nrf_drv_gpiote_init();                                        // GPIOE驱动初始化
            APP_ERROR_CHECK(errCode);
        }
    
        nrf_drv_gpiote_in_config_t inConfig = GPIOTE_CONFIG_IN_SENSE_HITOLO(false); // 下降沿触发
        inConfig.pull = NRF_GPIO_PIN_PULLUP;                                        // 默认上拉
        
        errCode = nrf_drv_gpiote_in_init(BMA423_IRQ_IO, &inConfig, irqCallbackFunc);
        APP_ERROR_CHECK(errCode);
        nrf_drv_gpiote_in_event_enable(BMA423_IRQ_IO, true);                        
    }
    
    
    /*********************************************************************
     * LOCAL FUNCTIONS
     */
    /**
     @brief 中断触发回调函数
     @param pin -[in] 产生中断的引脚
     @return 无
    */
    static void irqCallbackFunc(nrf_drv_gpiote_pin_t pin, nrf_gpiote_polarity_t action)
    {
        s_irqValue = 0;                                                             // 清除中断值
    
        if(pin == BMA423_IRQ_IO)
        {
            s_irqValue |= BMA423_IRQ_VALUE;                                         // 保存中断值
        }
        
        BMA423_HandleIrq(s_irqValue);
    }
    
    /****************************************************END OF FILE****************************************************/
    

    4.4 board_gpi.h

    #ifndef _BOARD_GPI_H_
    #define _BOARD_GPI_H_
    
    /*********************************************************************
     * INCLUDES
     */
    #include "common.h"
    
    /*********************************************************************
     * DEFINITIONS
     */
    #define BMA423_IRQ_IO           3
    #define BMA423_IRQ_VALUE        0x0001      // 中断值
    
    /*********************************************************************
     * API FUNCTIONS
     */
    void Board_Bma423IrqInit(void);
    
    #endif /* _BOARD_GPI_H_ */
    

    五、API调用

    需包含头文件 board_bma423.hboard_gpi.h

    BMA423_Init

    功能 BMA423初始化函数
    函数定义 void BMA423_Init(void)
    参数
    返回

    Board_Bma423IrqInit

    功能 BMA423的中断引脚初始化函数
    函数定义 void Board_Bma423IrqInit(void)
    参数
    返回

    BMA423_ReadFifoData

    功能 BMA423读取FIFO传感数据
    函数定义 uint16 BMA423_ReadFifoData(struct bma4_accel *pAccelData, uint16 *pAccelLen)
    参数 pAccelData:加速计数据缓冲区,存储FIFO中的数据
    pAccelLen:加速度数据条数
    返回 0 - 成功;非0 - 失败

    BMA423_ReadAccelData

    功能 BMA423读取三轴加速度数据
    函数定义 uint16 BMA423_ReadAccelData(struct bma4_accel *pAccelData)
    参数 pAccelData:加速计数据缓冲区
    返回 0 - 成功;非0 - 失败

    六、使用例子

    6.1 初始化

    1)添加头文件

    #include "board_bma423.h"
    #include "board_gpi.h"
    

    2)添加初始化代码(main.c的main函数中)

    /**@brief Function for application main entry.
     */
    int main(void)
    {
        bool erase_bonds;
    
        /*-------------------------- 外设驱初始化 ---------------------------*/
        // Initialize.
        log_init();                                                                 // 日志驱动初始化                                                                  
        timers_init();                                                              // 定时器驱动初始化(在此加入自定义定时器)
        I2C_Init();                                                                 // I2C驱动初始化
        BMA423_Init();                                                              // BMA423三轴加速计驱动初始化
        I2C_Disable();                                                              // 禁用I2C,进入低功耗模式,等待读加速度时再开启                      
        Board_Bma423IrqInit();                                                      // BMA423三轴加速计中断初始化
        ···
        ···
    /*-------------------------- 开启应用 ---------------------------*/
        // Start execution.
        NRF_LOG_INFO("Template example started."); 
        ···
    }
    

    6.2 检测初始化完成

    #include "bma4.h"
    
    I2C_Enable();
    DelayMs(20); 
    struct bma4_accel sensorDataTemp;
    BMA423_ReadAccelData(&sensorDataTemp);
    if((abs(sensorDataTemp.x) + abs(sensorDataTemp.x) + abs(sensorDataTemp.x)) > 10)
    {
        NRF_LOG_INFO("G-Sensor OK");
    }
    else
    {
        NRF_LOG_INFO("G-Sensor Error---------");
    }
    I2C_Disable();
    

    6.3 读FIFO数据和立即采集一条数据

    uint8 i = 0;
    struct bma4_accel sensorDataBuf[36] = {0};
    uint16 sensorDataNum = 0;
    
    BMA423_ReadFifoData(sensorDataBuf, &sensorDataNum);
    if(sensorDataNum > 0)
    {
        for(i = 0; (i < sensorDataNum && i < 5); i++)
        {   
            NRF_LOG_INFO("FX:%d, FY:%d, FZ:%d", sensorDataBuf[i].x, sensorDataBuf[i].y, sensorDataBuf[i].z);
        }
    }
    if(sensorDataNum < 5)
    {
        struct bma4_accel sensorDataTemp;
        BMA423_ReadAccelData(&sensorDataTemp);  
            
        NRF_LOG_INFO("accel:X:%d, Y:%d, Z:%d", sensorDataTemp.x, sensorDataTemp.y, sensorDataTemp.z);
    }
    

    6.4 中断处理,传感器有动作产生

    void BMA423_HandleIrq(uint8 irqValue)
    {
        uint8 value;
        
        if(irqValue & BMA423_IRQ_VALUE)
        {
            I2C_Enable();
            DelayMs(20);                                                    // I2C开启到读取数据至少延迟20毫秒
            I2C_ReadData(BMA4_I2C_ADDR_PRIMARY, BMA4_INT_STAT_0_ADDR, &value, 1);
            I2C_Disable();
    
            // INT_STATUS_0寄存器第6bit置1则有动作产生,0则无动作
            if(value & 0x40)
            {
                    NRF_LOG_INFO("any_motion \r\n" );
            }   
        }
    }
    

    • 由 Leung 写于 2020 年 6 月 1 日

    • 参考:BMA4xy Sensor API
        博世BMA400传感器API (中文说明)
        BMA423 DataSheet【siui】

    相关文章

      网友评论

        本文标题:NRF52832学习笔记(20)——三轴加速度 BMA423使用

        本文链接:https://www.haomeiwen.com/subject/qyvjzhtx.html