使用ESP32驱动QMA7981读取三轴加速度(带例程)

1.简介

ESP32是国产乐鑫公司生产的32位单片机,双核240MHz,带有蓝牙和wifi功能,本例中使用的是ESP32-S模组。QMA7981是国产矽睿公司生产的三轴加速度传感器(支持国产,从我做起)。本例中使用的开发环境是VSCODE安装ESP-IDF插件。

2.硬件连接

ESP-32S

QMA7981

3.使用方法

首先配置ESP-IDF的配置文件,将I2C使用的SDA和SCL引脚配置为和电路中一样。在VSCODE主界面按F1,在弹出的搜索框内选择ESP-IDF SDK配置编辑器。在左边选择Example Configuration,在右边的SCL GPIO Num和SDA GPIO Num中输入自己的硬件连接的IO口,点击右上角的保存。


VSCODE配置

使用QMA7981传感器的流程是,首先进行I2C初始化,然后将QMA7981设置为active状态,然后配置QMA7981的量程(默认是2g,由于我是为了计算倾角,只需要用到最低的2g,所以省略了这一步),然后就可以使用存储3轴加速度值的寄存器地址读取三轴加速度值了。以下是代码:

#include <stdio.h> 
#include <stdlib.h> 
#include "esp_log.h" 
#include "driver/i2c.h"  
#include "freertos/FreeRTOS.h"  
#include "freertos/task.h"

static const char *TAG = "i2c-simple-example";
#define I2C_MASTER_SCL_IO CONFIG_I2C_MASTER_SCL /*!< GPIO number used for I2C master clock */  
#define I2C_MASTER_SDA_IO CONFIG_I2C_MASTER_SDA /*!< GPIO number used for I2C master data */  
#define I2C_MASTER_NUM 0 /*!< I2C master i2c port number, the number of i2c peripheral interfaces available will depend on the chip */  
#define I2C_MASTER_FREQ_HZ 400000 /*!< I2C master clock frequency */  
#define I2C_MASTER_TX_BUF_DISABLE 0 /*!< I2C master doesn't need buffer */  
#define I2C_MASTER_RX_BUF_DISABLE 0 /*!< I2C master doesn't need buffer */  
#define I2C_MASTER_TIMEOUT_MS 1000

#define QMA7981_ADDR 0x12 /*!< Slave address of the QMA7981 */  
#define QMA7981_WHO_AM_I_REG_ADDR 0x00 /*!< Register addresses of the "who am I" register */

#define QMA7981_PWR_MGMT_1_REG_ADDR 0x11 /*!< Register addresses of the power managment register */

#define QMA7981_DXM 0x01  //QMA7981寄存器X轴加速度地址  
#define QMA7981_DYM 0x03  //QMA7981寄存器Y轴加速度地址  
#define QMA7981_DZM 0x05  //QMA7981寄存器Z轴加速度地址

#define QMA7981_start_convert_cmd 0xC0  //设置QMA7981为active模式的指令

#define QMA7981_MAX_VALUE 0x1FFF  //满量程读数

/***   @brief Read a sequence of bytes from a QMA7981 sensor registers  */ 
static esp_err_t QMA7981_register_read(uint8_t reg_addr, uint8_t *data, size_t len) 
 {  
    return i2c_master_write_read_device(I2C_MASTER_NUM, QMA7981_ADDR, &reg_addr, 1, data, len, I2C_MASTER_TIMEOUT_MS / portTICK_RATE_MS); 
 }
 
/***   @brief Write a byte to a QMA7981 sensor register  */  
static esp_err_t QMA7981_register_write_byte(uint8_t reg_addr, uint8_t data) 
 { 
     int ret;
     uint8_t write_buf[2] = {reg_addr, data};
     ret = i2c_master_write_to_device(I2C_MASTER_NUM, QMA7981_ADDR, write_buf, sizeof(write_buf), I2C_MASTER_TIMEOUT_MS / portTICK_RATE_MS);
     return ret; 
 }

/***   @brief i2c master initialization  */  
static esp_err_t i2c_master_init(void) 
 {  
    int i2c_master_port = I2C_MASTER_NUM;
    i2c_config_t conf = {  .mode = I2C_MODE_MASTER,  .sda_io_num = I2C_MASTER_SDA_IO,  .scl_io_num = I2C_MASTER_SCL_IO,  .sda_pullup_en = GPIO_PULLUP_ENABLE,  .scl_pullup_en = GPIO_PULLUP_ENABLE,  .master.clk_speed = I2C_MASTER_FREQ_HZ,  };
    i2c_param_config(i2c_master_port, &conf);
    return i2c_driver_install(i2c_master_port, conf.mode, I2C_MASTER_RX_BUF_DISABLE, I2C_MASTER_TX_BUF_DISABLE, 0);  
}

void app_main(void) 
{  
    uint8_t data[2];  
    int16_t XA;  
    int16_t YA;  
    int16_t ZA;
    float X_AXIS_A;  
    float Y_AXIS_A;  
    float Z_AXIS_A;
    ESP_ERROR_CHECK(i2c_master_init());  //初始化I2C  ESP_LOGI(TAG, "I2C initialized successfully");
    ESP_ERROR_CHECK(QMA7981_register_read(QMA7981_WHO_AM_I_REG_ADDR, data, 1));  //读取设备ID,正常是0xE7  
    ESP_LOGI(TAG, "WHO_AM_I = %X", data[0]);
    ESP_ERROR_CHECK(QMA7981_register_write_byte(QMA7981_PWR_MGMT_1_REG_ADDR, QMA7981_start_convert_cmd));  //设置为active模式
    while(1)  
    {  //读取和转换  
        ESP_ERROR_CHECK(QMA7981_register_read(QMA7981_DXM, data, 2));  
        XA = (data[0] & 0xFC) | (data[1]<< 8);
        ESP_ERROR_CHECK(QMA7981_register_read(QMA7981_DYM, data, 2));  
        YA = (data[0] & 0xFC) | (data[1]<< 8);
        ESP_ERROR_CHECK(QMA7981_register_read(QMA7981_DZM, data, 2));  
        ZA = (data[0] & 0xFC) | (data[1]<< 8);

        XA /= 4;  
        YA /= 4;  
        ZA /= 4;

        X_AXIS_A = (float) XA / QMA7981_MAX_VALUE * 2;  
        Y_AXIS_A = (float) YA / QMA7981_MAX_VALUE * 2;  
        Z_AXIS_A = (float) ZA / QMA7981_MAX_VALUE * 2; 

        printf("X_RAW = %d , Y_RAW = %d , Z_RAW = %d . \n", XA, YA, ZA);  
        printf("X_A = %.3f g, Y_A = %.3f g, Z_A = %.3f g. \n", X_AXIS_A, Y_AXIS_A, Z_AXIS_A);  
        vTaskDelay(1000 / portTICK_PERIOD_MS);  
     }  
}
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

友情链接更多精彩内容