传感器介绍
开发板上的地磁传感器型号是QMC5883L,它也是使用I2C与ESP32通信,I2C地址为0x0D。 本例程,我们使用地磁传感器QMC5883L计算方位角,最终,把开发板放平到桌子上,旋转开发板一周,输出0~359°的数值到串口终端。
- 我们需要在main中新建qmc5883l.h、qmc5883l.c两个文件。myi2c.c、myi2c.h沿用第三课里的,CMakeLists.txt里会自动添加。
- main文件夹里的CMakeLists.txt
idf_component_register(SRCS "qmc5883l.c" "azimuth_main.c" "qmi8658c.c" "gxhtc3.c" "myi2c.c" "qmi8658c.h" "gxhtc3.h" "myi2c.h"
INCLUDE_DIRS "")
3. 项目文件夹里的CMakeLists.txt,其中的project(azimuth) #地磁传感器,换了一下。
4. 并将main文件夹里的main.c,改名成为azimuth_main.
#以下样板行必须在您的项目中
#CMakeList 在这个确切的顺序 cmake 工作正常
#cmke版本说明,
#包含cmake的具体地址
#项目名称,通常只需要改这个。
cmake_minimum_required(VERSION 3.16)
include($ENV{IDF_PATH}/tools/cmake/project.cmake)
project(azimuth) #地磁传感器
接下来开始qmc5883.h的编写(搬运加更改)
- pragma once 运行一次以防重复包含。
- 需要用到整数类型头文件<stdint.h>。
- 查资料得QMC5883L的I2C地址为0x0D,
- 定义QMC5883L寄存器地址,
- 定义QMC5883L数据结构体,
- 初始化QMC5883L,
- 获取QMC5883L的角度
#pragma once // 防止头文件被重复包含
#include <stdint.h> // 包含整数类型的头文件
#define QMC5883L传感器地址 0x0D // 定义QMC5883L传感器的I2C地址
enum qmc5883l_reg // 定义qmc5883l寄存器地址
{
QMC5883L_X坐标低,
QMC5883L_X坐标高,
QMC5883L_Y坐标低,
QMC5883L_Y坐标高,
QMC5883L_Z坐标低,
QMC5883L_Z坐标高,
QMC5883L_状态,
QMC5883L_T坐标低,
QMC5883L_T坐标高,
QMC5883L控制1,
QMC5883L控制2,
QMC5883L采样率,
QMC5883L芯片ID = 13
};
typedef struct{ // 定义QMC5883L数据结构体
int16_t x轴;
int16_t y轴;
int16_t z轴;
float 方位角;
}t_sQMC5883L;
void qmc5883l_init(void); // 初始化QMC5883L传感器
void qmc5883l_read_xyz(t_sQMC5883L *p); // 读取QMC5883L传感器的XYZ轴数据
void qmc5883l_fetch_azimuth(t_sQMC5883L *p); // 计算QMC5883L传感器的方位角
接下来开始qmc5883L.c的编写(搬运加更改)
- 先是包含的头文件,不按先后分别为qmc5883L.h,driver/i2c.h,esp_log.h, myi2c.h, freertos/FreeRTOS.h, freertos/task.h, math.h。
- 建标签qmc5883L的变量
- 定义QMC5883L的寄存器地址
- 写一个字节到QMC5883L寄存器的函数
- 初始化 QMC5883L传感器的函数
- 读取QMC5883L的XYZ轴数据
- 计算QMC5883L的方位角
#include "qmc5883l.h" // 包含qmc5883l的头文件
#include "driver/i2c.h" // 包含I2C驱动的头文件
#include "esp_log.h" // 包含esp日志输出的头文件
#include "myi2c.h" // 包含自定义的I2C驱动的头文件
#include "freertos/FreeRTOS.h" // 包含FreeRTOS的头文件
#include "freertos/task.h" // 包含FreeRTOS任务相关的头文件
#include <math.h> // 包含数学库的头文件
static const char *标签 = "QMC5883L"; // 定义日志标签
// 定义QMC5883L的寄存器地址
esp_err_t qmc5883L_register_read(uint8_t 寄存器地址, uint8_t *数据, size_t 长度)
{
return i2c_master_write_read_device(I2C主端口, QMC5883L传感器地址, &寄存器地址, 1, 数据, 长度, I2C自动超时 / portTICK_PERIOD_MS);
}
// 写一个字节到QMC5883L的寄存器
esp_err_t qmc5883L_register_write_byte(uint8_t 寄存器地址, uint8_t 数据)
{
uint8_t write_buf[2] = {寄存器地址, 数据};
return i2c_master_write_to_device(I2C主端口, QMC5883L传感器地址, write_buf, sizeof(write_buf), I2C自动超时 / portTICK_PERIOD_MS);
}
// 初始化QMC5883L
void qmc5883l_init(void)
{
uint8_t id = 0;
while (id != 0xff) // 确定ID号是否正确
{
qmc5883L_register_read(QMC5883L芯片ID, &id ,1);
vTaskDelay(1000 / portTICK_PERIOD_MS);
}
ESP_LOGI(标签, "QMC5883L OK!");
qmc5883L_register_write_byte(QMC5883L控制2, 0x80); // 复位芯片
vTaskDelay(10 / portTICK_PERIOD_MS);
qmc5883L_register_write_byte(QMC5883L控制1, 0x05); //Continuous模式 50Hz
qmc5883L_register_write_byte(QMC5883L控制2, 0x00);
qmc5883L_register_write_byte(QMC5883L采样率, 0x01); // 100Hz 采样率
}
// 读取QMC5883L的XYZ轴数据
void qmc5883l_read_xyz(t_sQMC5883L *p)
{
uint8_t 状态, 数据就绪=0;
int16_t mag_reg[3];
qmc5883L_register_read(QMC5883L_状态, &状态, 1); // 读状态寄存器
if (状态 & 0x01)
{
数据就绪 = 1;
}
if (数据就绪 == 1)
{
数据就绪 = 0;
qmc5883L_register_read(QMC5883L_X坐标低, (uint8_t *)mag_reg, 6);
p->x轴 = mag_reg[0]; // 读取X轴数据
p->y轴 = mag_reg[1]; // 读取Y轴数据
p->z轴 = mag_reg[2]; // 读取Z轴数据
//p->方位角 = (float)atan2(p->y轴, p->x轴) * 180.0 / 3.1415926 + 180.0;
}
}
// 计算QMC5883L的方位角
void qmc5883l_fetch_azimuth(t_sQMC5883L *p)
{
qmc5883l_read_xyz(p);
p->方位角 = (float)atan2(p->y轴, p->x轴) * 180.0 / 3.1415926 + 180.0;
}
myi2c不需要更改驱动,延用第三课的
更改azimuth_main文件添加实现方式
#include "qmc5883l.h" 自定义的 QMC5883L 传感器驱动头文件
t_sQMC5883L QMC5883L; // QMC5883L 传感器结构体变量
static const char *标签 = "地磁传感器控制程序"; // 用于 ESP-IDF 中的日志输出
注释掉第四课的变量和函数,加入QMC5883L 的函数。
调用初始化函数 qmc5883l_init();
延时1s
调用qmc5883l_fetch_azimuth 函数函数,并且用ESP_ERROR_CHECK 检测是否初始化成功。
OK,构建如果没有出错,就可以烧录了
与官方文件的差别在于,尽量汉化代码,另外,在qmc5883l的驱动,将基本能汉化的都汉化了。
遗憾的是,其中函数很多名称都不能汉化。否则编译器会报错。
手打不易,看到的还请一键三连。