当前位置: 首页 > news >正文

姿态传感器(学习笔记上)

上节我们学的是温湿传感器,这节我们学的是姿态传感器,虽然都是传感器,但是它们还是有很大的区别的,这节的传感器我们通过学习可知,开发板上的姿态传感器型号是QMI8658C,内部集成3轴加速度传感器和3轴陀螺仪传感器,支持SPI和I2C通信,在我们的开发板上使用的是I2C通信,ESP32-C3只有1个I2C外设,我们开发板上的所有I2C设备,都使用一个I2C通信接口,通过I2C设备的地址,来决定和谁通信,QMI8658C的I2C地址是0x6A,这个项目,我们将最终完成测量XYZ三个轴的角度,把角度数据通过串口传输到终端

接着,我们要进行编写QMI8658C驱动程序

这个和温湿传感器大致相似,也是使用sample project作为模板,们复制esp-idf-v5.1.3\examples\get-started\sample_project这个工程到我们的实验文件夹,然后把这个文件夹的名称修改为attitude,attitude是姿态的意思。

接着,进行我们经常的操作,在vscode中打开attitude文件夹,我们先点击打开attitude工程目录下的CMakeList.txt文件,修改工程的名称为attitude,然后保存关闭此文件(这步一般来说是我们的第一步,也就是我们的文件名)

project(attitude)

我们这个项目需要用到I2C通信,现在我们把温湿度例程里面的myi2c.h和myi2c.c文件复制到attitude工程中的main目录下,然后我们点开main目录下的CMakeLists.txt文件,可以看到myi2c.c文件已经添加到编译路径

idf_component_register(SRCS "myi2c.c" "main.c"INCLUDE_DIRS ".")

点击打开qmi8658c.h文件,在最上面添加#pragma once

#pragma once

点击打开qmi8658c.c文件,在最上面添加包含qmi8658c.h文件

#include "qmi8658c.h"

点击打开main.c文件,添加头文件

#include "myi2c.h"
#include "qmi8658c.h"

在app_main函数中,先调用I2C初始化函数

void app_main(void)
{ESP_ERROR_CHECK(i2c_master_init());ESP_LOGI(TAG, "I2C initialized successfully");
}

函数里使用到了ESP_LOGI,需要包含esp_log.h头文件

#include "esp_log.h"

还需要给ESP_LOGI里面的TAG定义一下

static const char *TAG = "MAIN";

接下来,开始写qmi8658c的驱动函数,通过课程视频学习,我们先写两个读取qmi8658c寄存器的函数和写入qmi8658c寄存器的函数,写入函数用于配置传感器的参数,读取函数用于读取传感器的寄存器数据,例如ID号,状态等,这两个函数放入qmi8658c.c文件中

esp_err_t qmi8658c_register_read(uint8_t reg_addr, uint8_t *data, size_t len)
{return i2c_master_write_read_device(I2C_MASTER_NUM, QMI8658C_SENSOR_ADDR,  &reg_addr, 1, data, len, I2C_MASTER_TIMEOUT_MS / portTICK_PERIOD_MS);
}esp_err_t qmi8658c_register_write_byte(uint8_t reg_addr, uint8_t data)
{uint8_t write_buf[2] = {reg_addr, data};return i2c_master_write_to_device(I2C_MASTER_NUM, QMI8658C_SENSOR_ADDR, write_buf, sizeof(write_buf), I2C_MASTER_TIMEOUT_MS / portTICK_PERIOD_MS);
}

然后我们在qmi8658c.c文件中添加这两个函数需要的头文件

#include "driver/i2c.h"
#include "myi2c.h"

函数里面用到了QMI8658C_SENSOR_ADD,我们在qmi8658c.h文件中定义一下

#define  QMI8658C_SENSOR_ADDR       0x6A

接下来,我们需要写一个qmi8658c初始化函数,用于读取ID号,配置加速度、陀螺仪范围等参数。这个函数涉及到了qmi8658c的寄存器,所以我们先用枚举类型定义寄存器,放到qmi8658c.h文件中

enum qmi8658c_reg
{QMI8658C_WHO_AM_I,QMI8658C_REVISION_ID,QMI8658C_CTRL1,QMI8658C_CTRL2,QMI8658C_CTRL3,QMI8658C_CTRL4,QMI8658C_CTRL5,QMI8658C_CTRL6,QMI8658C_CTRL7,QMI8658C_CTRL8,QMI8658C_CTRL9,QMI8658C_CATL1_L,QMI8658C_CATL1_H,QMI8658C_CATL2_L,QMI8658C_CATL2_H,QMI8658C_CATL3_L,QMI8658C_CATL3_H,QMI8658C_CATL4_L,QMI8658C_CATL4_H,QMI8658C_FIFO_WTM_TH,QMI8658C_FIFO_CTRL,QMI8658C_FIFO_SMPL_CNT,QMI8658C_FIFO_STATUS,QMI8658C_FIFO_DATA,QMI8658C_I2CM_STATUS = 44,QMI8658C_STATUSINT,QMI8658C_STATUS0,QMI8658C_STATUS1,QMI8658C_TIMESTAMP_LOW,QMI8658C_TIMESTAMP_MID,QMI8658C_TIMESTAMP_HIGH,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_RESET = 96
};

结合QMI8658C的数据手册中的寄存器定义表格,写出这个枚举定义。枚举类型的第一个值默认是0,和寄存器WHO_AM_I的地址一样,所以不用标出,然后依次递增,遇到地址不连续的寄存器地址时,单独标出,最后的结果如上代码所示

接下来写qmi8658c初始化函数到qmi8658c.c文件

void qmi8658c_init(void)
{uint8_t id = 0;qmi8658c_register_read(QMI8658C_WHO_AM_I, &id ,1);while (id != 0x05){vTaskDelay(1000 / portTICK_PERIOD_MS);qmi8658c_register_read(QMI8658C_WHO_AM_I, &id ,1);}ESP_LOGI(TAG, "QMI8658C OK!");qmi8658c_register_write_byte(QMI8658C_RESET, 0xb0);  // 复位vTaskDelay(10 / portTICK_PERIOD_MS);qmi8658c_register_write_byte(QMI8658C_CTRL1, 0x40); // CTRL1 设置地址自动增加qmi8658c_register_write_byte(QMI8658C_CTRL7, 0x03); // CTRL7 允许加速度和陀螺仪qmi8658c_register_write_byte(QMI8658C_CTRL2, 0x95); // CTRL2 设置ACC 4g 250Hzqmi8658c_register_write_byte(QMI8658C_CTRL3, 0xd5); // CTRL3 设置GRY 512dps 250Hz
}

初始化函数里面,首先读取qmi8658c的ID号,如果不正确,就继续读,如果正确,往下执行。确定qmi8658c没有问题,先复位芯片,然后进行配置。CTRL1,配置地址自动增加后,我们读取一连串的加速度和陀螺仪数据,只写个首地址就可以连续读了。CTRL2配置加速度的量程和输出速率,CTRL3配置陀螺仪的量程和输出速率,CTRL7配置允许加速度和陀螺仪

函数里面用到了ESP_LOGI,用来输出信息,这里的TAG,需要定义。我们把这个TAG定义,放到qmi8658c.c文件中的包含头文件的下面

static const char *TAG = "QMI8658C";

函数里面使用了freeRTOS的延时函数,所以需要包含freeRTOS头文件

#include "freertos/FreeRTOS.h"
#include "freertos/task.h"

函数中也用到了ESP_LOGI宏,所以需要再添加它的头文件

#include "esp_log.h"

现在我们把这个函数的声明写到qmi8658c.h文件

extern void qmi8658c_init(void);

接下来我们在main.c文件中的app_main函数中调用这个初始化函数

void app_main(void)
{ESP_ERROR_CHECK(i2c_master_init());ESP_LOGI(TAG, "I2C initialized successfully");qmi8658c_init();
}

我们可以试编译一下,看看运行结果,依次配置VSCode左下角的配置选项,串口号、目标芯片、下载方式、menuconfig里面,把FLASH大小修改为8MB,其它不做修改。

好了,到这儿我们的姿态传感器上半部分结束!

相关文章:

姿态传感器(学习笔记上)

上节我们学的是温湿传感器,这节我们学的是姿态传感器,虽然都是传感器,但是它们还是有很大的区别的,这节的传感器我们通过学习可知,开发板上的姿态传感器型号是QMI8658C,内部集成3轴加速度传感器和3轴陀螺仪…...

labelimg使用教程

快捷键 W:调出标注的十字架,开始标注 A:切换到上一张图片 D:切换到下一张图片 del:删除标注的矩形框 CtrlS:保存标注好的标签 Ctrl鼠标滚轮:按住Ctrl,然后滚动鼠标滚轮,…...

力扣21 : 合并两个有序链表

链表style 描述: 将两个升序链表合并为一个新的 升序 链表并返回。新链表是通过拼接给定的两个链表的所有节点组成的。 示例: 节点大小相同时,l1的节点在前 何解? 1,遍历两个链表,挨个比较节点大小 同时遍…...

【Spring】Spring Boot 配置文件(7)

本系列共涉及4个框架:Sping,SpringBoot,Spring MVC,Mybatis。 博客涉及框架的重要知识点,根据序号学习即可。 有什么不懂的都可以问我,看到消息会回复的,可能会不及时,请见谅!! 1、配置文件作…...

《向量数据库指南》——解锁Wikipedia文章向量的跨语言搜索秘籍

嘿,各位向量数据库和AI应用的小伙伴们,我是你们的老朋友王帅旭,大禹智库的向量数据库高级研究员,也是《向量数据库指南》的作者。今天,咱们来聊聊一个超棒的数据集——百万条 Wikipedia 文章向量,这可是我在研究过程中发现的一个宝藏啊! 首先,咱们得说说这个数据集的来…...

【力扣 + 牛客 | SQL题 | 每日5题】牛客SQL热题204,201,215

1. 力扣1126:查询活跃业务 1.1 题目: 事件表:Events ------------------------ | Column Name | Type | ------------------------ | business_id | int | | event_type | varchar | | occurrences | int | --------…...

下载数据集用于图像分类并自动分为训练集和测试集方法

一、背景 最近需要用Vision Transformer(ViT)完成图像分类任务,因此查到了WZMIAOMIAO的GitHub,里面有各种图像处理的方法。而图像处理的前期工作就是获取大量的数据集,用于训练模型参数,以准确识别或分类我…...

Python xlrd库介绍

一、简介 xlrd是一个用于读取Excel文件(.xls和.xlsx格式)的Python库。它提供了一系列函数来访问Excel文件中的数据,如读取工作表、单元格的值等。 二、安装 可以使用以下命令安装xlrd库: pip install xlrd 三、使用方法 1. 导入库: 示例…...

Javascript立即执行函数

//立即执行函数 把函数的声明看作一个整体声明结束就立即调用 // (function(){console.log(hello) // })(); console.log((function (){ return 0; })()); // let afunction(){ console.log(hello) }; console.log(typeof a);//function,数组:objeck...

Linux相关概念和易错知识点(17)(文件、文件的系统调用接口、C语言标准流)

目录 1.文件 (1)文件组成和访问 (2)文件的管理 (3)C语言标准流 (4)struct file ①文件操作表 ②文件内核缓冲区 (5)Linux下一切皆文件 (…...

三防加固工业平板国产化的现状与展望

在当今全球科技竞争日益激烈的背景下,工业4.0和智能制造的浪潮推动了工业自动化设备的迅速发展,其中,三防加固工业平板电脑作为连接物理世界与数字世界的桥梁,其重要性不言而喻。所谓“三防”,即防水、防尘、防震&…...

3.1.3 看对于“肮脏”页面的处理

3.1.3 看对于“肮脏”页面的处理 文章目录 3.1.3 看对于“肮脏”页面的处理再看对于“肮脏”页面的处理MmPageOutVirtualMemory() 再看对于“肮脏”页面的处理 MmPageOutVirtualMemory() NTSTATUS NTAPI MmPageOutVirtualMemory(PMADDRESS_SPACE AddressSpace,PMEMORY_AREA Me…...

学 Python 还是学 Java?——来自程序员的世纪困惑!

文章目录 1. Python:我就是简单,so what?2. Java:严谨到让你头疼,但大佬都在用!3. 到底谁更香?——关于学哪门语言的百思不得姐结论——到底该选谁?推荐阅读文章 每个程序员都可能面…...

Spring Web MVC 入门

1. 什么是 Spring Web MVC Spring Web MVC 是基于 Servlet API 构建的原始 Web 框架,从从⼀开始就包含在Spring框架中。它的 正式名称“SpringWebMVC”来⾃其源模块的名称(Spring-webmvc),但它通常被称为"Spring MVC". 什么是Servlet呢? Ser…...

吃牛羊肉的季节来了,快来看看怎么陈列与销售!

一、肉品陈列基本原则 (一)新鲜卫生 1、保证商品在正确的温度、正确的方式下陈列 (1)正确的温度:冷藏柜-2℃-2℃;冷冻柜库-20℃-18℃ (2)正确的方式: 商品不遮挡冷气出风口&…...

租房业务全流程管理:Spring Boot系统应用

摘要 随着信息技术在管理上越来越深入而广泛的应用,管理信息系统的实施在技术上已逐步成熟。本文介绍了租房管理系统的开发全过程。通过分析租房管理系统管理的不足,创建了一个计算机管理租房管理系统的方案。文章介绍了租房管理系统的系统分析部分&…...

GCC之编译(7)Linker链接脚本

GCC之(7)Linker链接脚本 Author: Once Day Date: 2024年10月25日 一位热衷于Linux学习和开发的菜鸟,试图谱写一场冒险之旅,也许终点只是一场白日梦… 漫漫长路,有人对你微笑过嘛… 本文档翻译自GNU LD链接脚本官方手册 参考文章: GNU LD …...

【设计模式系列】适配器模式(九)

目录 一、什么是适配器模式 二、适配器模式的角色 三、适配器模式的典型应用 四、适配器模式在InputStreamReader中的应用 一、什么是适配器模式 适配器模式(Adapter Pattern)是一种结构型设计模式,它允许将不兼容的接口转换为一个客户端…...

C# 文档打印详解与示例

文章目录 一、概述二、PrintDocument 类的使用三、PrintDialog 类的使用四、PageSetupDialog 类的使用五、PrintPreviewDialog 类的使用六、完整示例七、总结 在软件开发过程中,文档打印是一个常见的功能需求。本文将详细介绍如何在C#中实现文档打印,并给…...

Spring Cloud --- Sentinel 熔断规则

熔断规则 慢调用比例 发送10个请求,每个请求理想响应时长为200毫秒。统计1秒钟,如果10个请求响应时间超过200毫秒的比例大于等于10%,则触发熔断,熔断5秒。 异常比例 1秒内,发送请求出现异常率为20%,则触…...

循环冗余码校验CRC码 算法步骤+详细实例计算

通信过程:(白话解释) 我们将原始待发送的消息称为 M M M,依据发送接收消息双方约定的生成多项式 G ( x ) G(x) G(x)(意思就是 G ( x ) G(x) G(x) 是已知的)&#xff0…...

Swift 协议扩展精进之路:解决 CoreData 托管实体子类的类型不匹配问题(下)

概述 在 Swift 开发语言中,各位秃头小码农们可以充分利用语法本身所带来的便利去劈荆斩棘。我们还可以恣意利用泛型、协议关联类型和协议扩展来进一步简化和优化我们复杂的代码需求。 不过,在涉及到多个子类派生于基类进行多态模拟的场景下,…...

【快手拥抱开源】通过快手团队开源的 KwaiCoder-AutoThink-preview 解锁大语言模型的潜力

引言: 在人工智能快速发展的浪潮中,快手Kwaipilot团队推出的 KwaiCoder-AutoThink-preview 具有里程碑意义——这是首个公开的AutoThink大语言模型(LLM)。该模型代表着该领域的重大突破,通过独特方式融合思考与非思考…...

Nuxt.js 中的路由配置详解

Nuxt.js 通过其内置的路由系统简化了应用的路由配置,使得开发者可以轻松地管理页面导航和 URL 结构。路由配置主要涉及页面组件的组织、动态路由的设置以及路由元信息的配置。 自动路由生成 Nuxt.js 会根据 pages 目录下的文件结构自动生成路由配置。每个文件都会对…...

AI书签管理工具开发全记录(十九):嵌入资源处理

1.前言 📝 在上一篇文章中,我们完成了书签的导入导出功能。本篇文章我们研究如何处理嵌入资源,方便后续将资源打包到一个可执行文件中。 2.embed介绍 🎯 Go 1.16 引入了革命性的 embed 包,彻底改变了静态资源管理的…...

Python 包管理器 uv 介绍

Python 包管理器 uv 全面介绍 uv 是由 Astral(热门工具 Ruff 的开发者)推出的下一代高性能 Python 包管理器和构建工具,用 Rust 编写。它旨在解决传统工具(如 pip、virtualenv、pip-tools)的性能瓶颈,同时…...

JVM 内存结构 详解

内存结构 运行时数据区: Java虚拟机在运行Java程序过程中管理的内存区域。 程序计数器: ​ 线程私有,程序控制流的指示器,分支、循环、跳转、异常处理、线程恢复等基础功能都依赖这个计数器完成。 ​ 每个线程都有一个程序计数…...

Golang——6、指针和结构体

指针和结构体 1、指针1.1、指针地址和指针类型1.2、指针取值1.3、new和make 2、结构体2.1、type关键字的使用2.2、结构体的定义和初始化2.3、结构体方法和接收者2.4、给任意类型添加方法2.5、结构体的匿名字段2.6、嵌套结构体2.7、嵌套匿名结构体2.8、结构体的继承 3、结构体与…...

DBLP数据库是什么?

DBLP(Digital Bibliography & Library Project)Computer Science Bibliography是全球著名的计算机科学出版物的开放书目数据库。DBLP所收录的期刊和会议论文质量较高,数据库文献更新速度很快,很好地反映了国际计算机科学学术研…...

Modbus RTU与Modbus TCP详解指南

目录 1. Modbus协议基础 1.1 什么是Modbus? 1.2 Modbus协议历史 1.3 Modbus协议族 1.4 Modbus通信模型 🎭 主从架构 🔄 请求响应模式 2. Modbus RTU详解 2.1 RTU是什么? 2.2 RTU物理层 🔌 连接方式 ⚡ 通信参数 2.3 RTU数据帧格式 📦 帧结构详解 🔍…...