立创开发板入门ESP32C3第四课 姿态传感器I2C驱动

传感器介绍

开发板上的姿态传感器型号是QMI8658C,内部集成3轴加速度传感器和3轴陀螺仪传感器,支持SPI和I2C通信,在我们的开发板上使用的是I2C通信,ESP32-C3只有1个I2C外设,我们开发板上的所有I2C设备,都使用一个I2C通信接口,通过I2C设备的地址,来决定和谁通信,QMI8658C的I2C地址是0x6A。
本例程,我们将最终完成测量XYZ三个轴的角度,把角度数据通过串口传输到终端。

编写QMI8658C驱动程序

  1. 我们需要在main中新建qmi8658c.c、qmi8658c.h两个文件。myi2c.c、myi2c.h沿用第三课里的,CMakeLists.txt里会自动添加。
  2. main文件夹里的CMakeLists.txt
  3. idf_component_register(SRCS "qmi8658c.c" "attitude_main.c" "gxhtc3.c" "myi2c.c"  "qmi8658c.h" "gxhtc3.h" "myi2c.h"
                        INCLUDE_DIRS "")
  4.  项目文件夹里的CMakeLists.txt,其中的project(attitude) #姿态控制,换了一下。
  5. 并将main文件夹里的main.c,改名成为attitude_main.c
#以下样板行必须在您的项目中
#CMakeList 在这个确切的顺序 cmake 工作正常
#cmke版本说明,
#包含cmake的具体地址
#项目名称,通常只需要改这个。
cmake_minimum_required(VERSION 3.16)

include($ENV{IDF_PATH}/tools/cmake/project.cmake)
project(attitude) #姿态控制

 接下来开始qmi8658c.h的编写(搬运加更改)

  1. pragma once 运行一次以防重复包含。
  2. 需要用到整数类型头文件<stdint.h>。
  3. 查资料得QMI8658C的I2C地址为0x6A,
  4. 定义QMI8658C寄存器地址,
  5. 定义QMI8658C数据结构体,
  6. 初始化QMI8658C,
  7. 获取QMI8658C的角度
#pragma once            // 防止头文件被重复包含
#include <stdint.h>     // 包含整数类型的头文件

// 定义QMI8658C的I2C地址
#define QMI8658C传感器地址 0x6A

// 定义QMI8658C寄存器地址
enum qmi8658c_reg
{
    QMI8658C我是谁,
    QMI8658C版本号,
    QMI8658C控制1,
    QMI8658C控制2,
    QMI8658C控制3,
    QMI8658C控制4,
    QMI8658C控制5,
    QMI8658C控制6,
    QMI8658C控制7,
    QMI8658C控制8,
    QMI8658C控制9,
    QMI8658C控制1_L,
    QMI8658C控制1_H,
    QMI8658C控制2_L,
    QMI8658C控制2_H,
    QMI8658C控制3_L,
    QMI8658C控制3_H,
    QMI8658C控制4_L,
    QMI8658C控制4_H,
    QMI8658C_FIFO_WTM_TH,
    QMI8658C_FIFO_CTRL,
    QMI8658C_FIFO_SMPL_CNT,
    QMI8658C_FIFO_STATUS,
    QMI8658C_FIFO_DATA,
    QMI8658C_I2CM_STATUS = 44,
    QMI8658C中断,
    QMI8658C状态0,
    QMI8658C_状态1,
    QMI8658C时间戳低,
    QMI8658C时间戳中,
    QMI8658C时间戳高,
    QMI8658C_TEMP_L,
    QMI8658C_TEMP_H,
    QMI8658C_AX_L,
    QMI8658C_AX_H,
    QMI8658C_AY_L,
    QMI8658C_AY_H,
    QMI8658C_AZ_L,
    QMI8658C_AZ_H,
    QMI8658C_GX_L,
    QMI8658C_GX_H,
    QMI8658C_GY_L,
    QMI8658C_GY_H,
    QMI8658C_GZ_L,
    QMI8658C_GZ_H,
    QMI8658C_MX_L,
    QMI8658C_MX_H,
    QMI8658C_MY_L,
    QMI8658C_MY_H,
    QMI8658C_MZ_L,
    QMI8658C_MZ_H,
    QMI8658C_dQW_L = 73,
    QMI8658C_dQW_H,
    QMI8658C_dQX_L,
    QMI8658C_dQX_H,
    QMI8658C_dQY_L,
    QMI8658C_dQY_H,
    QMI8658C_dQZ_L,
    QMI8658C_dQZ_H,
    QMI8658C_dVX_L,
    QMI8658C_dVX_H,
    QMI8658C_dVY_L,
    QMI8658C_dVY_H,
    QMI8658C_dVZ_L,
    QMI8658C_dVZ_H,
    QMI8658C_AE_REG1,
    QMI8658C_AE_REG2,
    QMI8658C复位 = 96
};
// 定义QMI8658C数据结构体
typedef struct{
    int16_t 加速器y;
    int16_t 加速器x;
    int16_t 加速器z;
    int16_t 陀螺仪y;
    int16_t 陀螺仪x;
    int16_t 陀螺仪z;
    float 角度X;
    float 角度Y;
    float 角度Z;
}t_sQMI8658C;

void qmi8658c_init(void);                           // 初始化QMI8658C
void qmi8658c_fetch_angleFromAcc(t_sQMI8658C *p);   // 获取QMI8658C的角度

 接下来开始qmi8658c.c的编写(搬运加更改)

  1. 先是包含的头文件,不按先后分别为qmi8658c.h,driver/i2c.h,esp_log.h, myi2c.h, freertos/FreeRTOS.h, freertos/task.h, math.h。
  2. 建标签QMI8658C的变量
  3. 加速度计和陀螺仪的校准值的函数
  4. 写一个字节到 QMI8658C 寄存器的函数
  5. 初始化 QMI8658C 传感器的函数
  6. 读加速器和陀螺仪的函数
  7. 从加速器计算角度的函数
#include "qmi8658c.h" // 包含 QMI8658C 传感器驱动头文件
#include "driver/i2c.h"     // 包含I2C驱动程序的头文件
#include "esp_log.h"            // 包含日志相关的头文件 
#include "myi2c.h"          // 包含自定义的I2C初始化函数
#include "freertos/FreeRTOS.h"  // 包含 FreeRTOS 头文件
#include "freertos/task.h"      // 包含任务相关的头文件
#include <math.h>           //  包含数学函数库头文件

static const char *标签 = "QMI8658C";    
// 加速度计和陀螺仪的校准值
esp_err_t qmi8658c_register_read(uint8_t 寄存器地址, uint8_t *数据, size_t 长度)
{
    return i2c_master_write_read_device(I2C主端口, QMI8658C传感器地址,  &寄存器地址, 1, 数据, 长度, I2C自动超时 / portTICK_PERIOD_MS);
}

// 写一个字节到 QMI8658C 寄存器
esp_err_t qmi8658c_register_write_byte(uint8_t 寄存器地址, uint8_t 数据)
{
    uint8_t write_buf[2] = {寄存器地址, 数据};

    return i2c_master_write_to_device(I2C主端口, QMI8658C传感器地址, write_buf, sizeof(write_buf), I2C自动超时 / portTICK_PERIOD_MS);
}

// 初始化 QMI8658C 传感器
void qmi8658c_init(void)
{
    uint8_t id = 0;

    qmi8658c_register_read(QMI8658C我是谁, &id ,1);     // 读 ID
    while (id != 0x05)
    {
        vTaskDelay(1000 / portTICK_PERIOD_MS);
        qmi8658c_register_read(QMI8658C我是谁, &id ,1);// 读 ID
    }
    ESP_LOGI(标签, "QMI8658C OK!");

    qmi8658c_register_write_byte(QMI8658C复位, 0xb0);  // 复位
    vTaskDelay(10 / portTICK_PERIOD_MS);               // 延时
    qmi8658c_register_write_byte(QMI8658C控制1, 0x40); // CTRL1 设置地址自动增加
    qmi8658c_register_write_byte(QMI8658C控制7, 0x03); // CTRL7 允许加速器和陀螺仪
    qmi8658c_register_write_byte(QMI8658C控制2, 0x95); // CTRL2 设置ACC 4g 250Hz
    qmi8658c_register_write_byte(QMI8658C控制3, 0xd5); // CTRL3 设置GRY 512dps 250Hz
}

void qmi8658c_Read_AccAndGry(t_sQMI8658C *p)            // 读加速器和陀螺仪
{
    uint8_t 状态, 数据就绪=0;
    int16_t buf[6];

    qmi8658c_register_read(QMI8658C状态0, &状态, 1);    // 读状态寄存器
    if (状态 & 0x03)                                    // 判断加速器和陀螺仪数据是否可读
    {
        数据就绪 = 1;                                   // 数据就绪标志置为1
    }
    if (数据就绪 == 1)                                   // 如果数据就绪
    {
        数据就绪 = 0;                                   // 数据就绪标志清零
        qmi8658c_register_read(QMI8658C_AX_L, (uint8_t *)buf, 12); // 读加速器值
        p->加速器x = buf[0];                           
        p->加速器y = buf[1];
        p->加速器z = buf[2];
        p->陀螺仪x = buf[3];
        p->陀螺仪y = buf[4];
        p->陀螺仪z = buf[5];
    }
}

void qmi8658c_fetch_angleFromAcc(t_sQMI8658C *p)        // 从加速器计算角度
{
    float temp;

    qmi8658c_Read_AccAndGry(p);                         // 读加速器值   

    temp = (float)p->加速器x / sqrt( ((float)p->加速器y * (float)p->加速器y + (float)p->加速器z * (float)p->加速器z) );
    p->角度X = atan(temp)*57.3f;                        // 180/3.14=57.3
    temp = (float)p->加速器y / sqrt( ((float)p->加速器x * (float)p->加速器x + (float)p->加速器z * (float)p->加速器z) );
    p->角度Y = atan(temp)*57.3f;                        // 180/3.14=57.3
    temp = (float)p->加速器z / sqrt( ((float)p->加速器x * (float)p->加速器x + (float)p->加速器y * (float)p->加速器y) );
    p->角度Z = atan(temp)*57.3f;                        // 180/3.14=57.3
}   

myi2c不需要更改驱动,延用第三课的

更改attitude_main.c文件添加实现方式

#include "qmi8658c.h"    自定义的 QMI8658C 传感器驱动头文件

t_sQMI8658C QMI8658C;                       // QMI8658C 传感器结构体变量

static const char *标签 = "姿态控制程序";    // 用于 ESP-IDF 中的日志输出

注释掉第三课的变量和函数,加入QMI8658C的函数。

调用初始化函数 qmi8658c_init();

延时1s

调用qmi8658c_fetch_angleFromAcc 函数,并且用ESP_ERROR_CHECK 检测是否初始化成功。

OK,构建如果没有出错,就可以烧录了

与官方文件的差别在于,尽量汉化代码,另外,在qmi8658的驱动,将基本能汉化的都汉化了。

遗憾的是,其中函数很多名称都不能汉化。否则编译器会报错。

手打不易,看到的还请一键三连。

GitCode, 有完整的源码。GitCode - 全球开发者的开源社区,开源代码托管平台

### 关于实战派 ESP32-C3 的教程和项目 #### 初步设置与环境配置 为了开始使用实战派 ESP32-C3 进行开发,首先需要安装必要的软件工具链。推荐使用 Arduino IDE 或者 PlatformIO 来编写程序并上传到设备上[^1]。 #### 示例项目一:LED 控制实验 这是一个简单的入门级例子,通过控制板载 LED 学习 GPIO 操作的基础知识。 ```cpp // 定义使用的引脚编号为 GPIO 8 (板载红色指示灯) const int ledPin = 8; void setup() { pinMode(ledPin, OUTPUT); // 设置引脚模式为输出 } void loop() { digitalWrite(ledPin, HIGH); // 打开 LED delay(1000); // 延迟一秒 digitalWrite(ledPin, LOW); // 关闭 LED delay(1000); } ``` #### 示例项目二:Wi-Fi 连接测试 利用 ESP32-C3 内置的强大无线功能连接至 Wi-Fi 网络,并打印 IP 地址作为确认。 ```cpp #include <WiFi.h> const char* ssid = "your_SSID"; const char* password = "your_PASSWORD"; void setup(){ Serial.begin(115200); WiFi.begin(ssid, password); while (WiFi.status() != WL_CONNECTED){ delay(1000); Serial.println("Connecting to WiFi..."); } Serial.print("Connected! IP address: "); Serial.println(WiFi.localIP()); } void loop(){} ``` #### 示例项目三:HTTP 请求发送器 此案例展示了如何让 ESP32-C3 发送 HTTP GET 请求给指定服务器获取数据。 ```cpp #include <WiFi.h> #include <HTTPClient.h> const char *ssid = "your_SSID"; const char *password = "your_PASSWORD"; void setup() { Serial.begin(115200); WiFi.begin(ssid, password); while (WiFi.status() != WL_CONNECTED) { delay(1000); Serial.println("Connecting to WiFi.."); } Serial.println("Connected!"); if (HTTP.begin("http://jsonplaceholder.typicode.com/posts/1")) { // 替换成实际API地址 int httpCode = HTTP.GET(); if (httpCode > 0) { String payload = HTTP.getString(); Serial.println(httpCode); Serial.println(payload); } else { Serial.printf("Error on sending GET request: %s\n", HTTP.errorToString(httpCode).c_str()); } HTTP.end(); } } void loop() {} ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值