基于LORA的一主多从监测系统_BMP280气压传感器

news2024/11/25 4:29:00

关联:LORA 、HAL、气压传感器

这个传感器也是比较常见的,但灵敏度什么的都没啥问题,不过气压传感器不是很好去观察这个变化,毕竟一个地方的大气压基本不会有太大波动,我们可以在百度搜索所在地的平均大气压,与我们测量得到的大气压进行对比,如果差的不是很多则认为没啥问题。

比如我测得大气压为101.4kpa,百度搜索南京平均大气压,差不多也在101.1左右,所以我们的测量是没问题的,说完这个如何判断我们的测量值是否正确,下面我们来说一下如何通过代码获取到这个气压值

这里我们使用硬件I2C来与气压传感器通信,首先我们需要定义如下寄存器地址

#define BMP280_REG_TEMP_XLSB   0xFC /* bits: 7-4 */
#define BMP280_REG_TEMP_LSB    0xFB
#define BMP280_REG_TEMP_MSB    0xFA
#define BMP280_REG_TEMP        (BMP280_REG_TEMP_MSB)
#define BMP280_REG_PRESS_XLSB  0xF9 /* bits: 7-4 */
#define BMP280_REG_PRESS_LSB   0xF8
#define BMP280_REG_PRESS_MSB   0xF7
#define BMP280_REG_PRESSURE    (BMP280_REG_PRESS_MSB)
#define BMP280_REG_CONFIG      0xF5 /* bits: 7-5 t_sb; 4-2 filter; 0 spi3w_en */
#define BMP280_REG_CTRL        0xF4 /* bits: 7-5 osrs_t; 4-2 osrs_p; 1-0 mode */
#define BMP280_REG_STATUS      0xF3 /* bits: 3 measuring; 0 im_update */
#define BMP280_REG_CTRL_HUM    0xF2 /* bits: 2-0 osrs_h; */
#define BMP280_REG_RESET       0xE0
#define BMP280_REG_ID          0xD0
#define BMP280_REG_CALIB       0x88
#define BMP280_REG_HUM_CALIB   0x88

#define BMP280_RESET_VALUE     0xB6

这些地址我们无需关心,如果只是使用这个传感器获取测量值我们无需关心太多底层的东西,我们只需要把精力放在代码逻辑以及实现上,我们可以粗略的理解为这些寄存器有一部分是控制功能,以及配置,有一部分是存放数据的,需要我么去读这个寄存器。

网上目前能找到的寄存器手册是博士的,手册是全英文的,但我们只需要关系重点信息,比如这个ID,这个ID就是我们去读器件指定的一个地址,可以读到一个值,这个值就是这个器件的ID,这个寄存器是可读寄存器,一般这个ID是出厂就固定的,不可修改。

我们读这个ID的作用是什么呢?

1、通过读这个ID我们可以判断设备的大概工作状态,以及与设备通信的链路是否正常,手册可以看到设备的ID为0x58,并且要读到这个ID,我们必须在传感器完成上电和重启之后

2、这个ID我们可以写到器件初始化里面,通过初始化时读取这个器件ID实现判断器件是否正常工作和准备就绪

这个寄存器是设备状态寄存器,一共有两个bit构成,手册了分别有对这两个bit的具体含义说明,这个我们一般也不用太过关心

这个是我们需要好好去研究的寄存器,我们所需要的压力数据就是从这个寄存器获得,分别有三个寄存器,这三个寄存器分别保存压力数据的高位、低位、小数位,注意0xF9里面只有bit7-bit4是我们的需要的,其余四个bit我们不用关心。

知道从哪个寄存器读取数据,我们也要关心一下读到的数据是不是直接可用,还是需要进行转换,通过手册我们可以看到读到的单位为Pa,我们日常使用的是KPa,我们将得到的值缩小一千倍就可以。

下面是部分核心代码

/**
 * @brief 读取 BMP280 或 BME280 传感器的温度、压力和湿度数据。
 * 
 * @param dev 指向 BMP280 设备的句柄,包含设备的配置信息和标识符。
 * @param temperature 指向整型变量的指针,用于存储读取到的温度值(单位:摄氏度)。
 * @param pressure 指向无符号整型变量的指针,用于存储读取到的压力值(单位:Pa)。
 * @param humidity 指向无符号整型变量的指针,用于存储读取到的湿度值(单位:%RH)。
 * 
 * @return 
 *   - true: 数据读取成功。
 *   - false: 数据读取失败,可能由于设备通信错误或读取数据不正确。
 * 
 * @note 
 *   - 该函数根据传感器的 ID 检查是否支持湿度读取。如果设备不是 BME280,则湿度值将被置为 0,且湿度指针将被设置为 NULL。
 *   - 温度、压力和湿度的读取操作在一个序列中完成,以确保数据的一致性。
 *   - 读取的数据格式为 6 或 8 字节,具体取决于湿度是否被请求。对应的读取地址为 0xf7。
 *   - 原始压力和温度数据由传感器返回,并通过相应的补偿函数进行转换,得出实际的物理值。
 *   - 如果请求湿度数据,则还将读取 2 字节的湿度值,并使用补偿函数进行处理。
 */
bool bmp280_read_fixed(BMP280_HandleTypedef *dev, int32_t *temperature, uint32_t *pressure,
		uint32_t *humidity) {
	int32_t adc_pressure;          // 原始压力数据
	int32_t adc_temp;             // 原始温度数据
	uint8_t data[8];              // 存储读取的原始数据

	// 只有 BME280 支持读取湿度。
	if (dev->id != BME280_CHIP_ID) {
		if (humidity)
			*humidity = 0;        // 如果不支持湿度,设置湿度为 0
		humidity = NULL;         // 将湿度指针设置为 NULL
	}

	// 需要一次性读取,以确保数据一致性。
	size_t size = humidity ? 8 : 6;  // 根据是否读取湿度确定读取字节数
	if (read_data(dev, 0xf7, data, size)) {
		return false;             // 读取数据失败
	}

	// 解析原始压力和温度数据
	adc_pressure = data[0] << 12 | data[1] << 4 | data[2] >> 4;
	adc_temp = data[3] << 12 | data[4] << 4 | data[5] >> 4;

	int32_t fine_temp;              // 用于补偿温度计算的临时变量
	*temperature = compensate_temperature(dev, adc_temp, &fine_temp); // 补偿温度
	*pressure = compensate_pressure(dev, adc_pressure, fine_temp);     // 补偿压力

	if (humidity) {
		// 读取并补偿湿度数据
		int32_t adc_humidity = data[6] << 8 | data[7];
		*humidity = compensate_humidity(dev, adc_humidity, fine_temp); // 补偿湿度
	}

	return true;                   // 成功读取所有数据
}

忘记说了,BMP280传感器也能测温度,但是我们有AHT20所以就不需要他的温度值,从上面的代码来看,比较关键的函数有两个,这两个函数分别处理温度和气压,这里我们只关心气压compensate_pressure,具体实现如下:

/**
 * @brief 补偿 BMP280 传感器的原始压力数据,计算实际压力值。
 * 
 * @param dev 指向 BMP280 设备的句柄,包含设备的校准系数。
 * @param adc_press 原始压力数据,从传感器读取的 ADC 值。
 * @param fine_temp 经过补偿的温度值,用于压力计算的精确度提高。
 * 
 * @return 计算得到的实际压力值(单位:Pa)。
 *         如果计算过程中出现除零错误,则返回 0。
 * 
 * @note 
 *   - 该函数根据传感器的校准系数(如 dig_P1, dig_P2 等)进行复杂的补偿计算。
 *   - 计算过程中使用了多个中间变量(var1 和 var2)来帮助获得最终的压力值。
 *   - 为了避免除零错误,函数首先检查 var1 是否为 0。如果是,则返回 0。
 *   - 返回的压力值是以 Pa 为单位的实际压力值,可用于进一步的数据处理和分析。
 */
static inline uint32_t compensate_pressure(BMP280_HandleTypedef *dev, int32_t adc_press,
        int32_t fine_temp) {
    int64_t var1, var2, p;

    var1 = (int64_t) fine_temp - 128000;  // 将温度值转换为 var1
    var2 = var1 * var1 * (int64_t) dev->dig_P6; // 根据校准系数计算 var2
    var2 = var2 + ((var1 * (int64_t) dev->dig_P5) << 17); // 累加压力校准系数
    var2 = var2 + (((int64_t) dev->dig_P4) << 35); // 累加压力校准系数
    var1 = ((var1 * var1 * (int64_t) dev->dig_P3) >> 8)
            + ((var1 * (int64_t) dev->dig_P2) << 12); // 完成 var1 的计算
    var1 = (((int64_t) 1 << 47) + var1) * ((int64_t) dev->dig_P1) >> 33; // 计算最终的 var1

    if (var1 == 0) {
        return 0;  // 避免因除零而引发的异常
    }

    p = 1048576 - adc_press;  // 计算压力的初步值
    p = (((p << 31) - var2) * 3125) / var1; // 应用补偿公式

    // 根据校准系数计算最终压力值的修正
    var1 = ((int64_t) dev->dig_P9 * (p >> 13) * (p >> 13)) >> 25;
    var2 = ((int64_t) dev->dig_P8 * p) >> 19;

    p = ((p + var1 + var2) >> 8) + ((int64_t) dev->dig_P7 << 4); // 计算最终压力值
    return p; // 返回实际压力值
}

这个玩意具体实现不需要理解,我们只用知道返回的为实际压力值即可,找个变量接着返回值就OK啦,

手册上也提供了一些计算代码,感兴趣可以去研究一下,我们这里调用这个函数的时候传入指向无符号整型变量的指针,用来保存数据。

我们在实际展示的时候缩小1000倍就可以,至此气压传感器的驱动实现完成。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2202397.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

bladex漏洞思路总结

Springblade框架介绍&#xff1a; SpringBlade是一个基于Spring Boot和Spring Cloud的微服务架构框架&#xff0c;它是由商业级项目升级优化而来的综合型项目。 0x1 前言 最近跟一些大佬学习了blade的漏洞&#xff0c;所以自己总结了一下&#xff0c;在渗透测试过程中&#x…

frp+windows+宝塔+域名使用

先讲一下frp的相关概念 1. 什么是 FRP&#xff1f; FRP (Fast Reverse Proxy) 是一款开源的反向代理工具&#xff0c;支持多种协议&#xff08;如 TCP、UDP、HTTP 和 HTTPS&#xff09;的内网穿透。它能够帮助你将位于内网或防火墙后面的服务映射到外网&#xff0c;方便外网用…

产品经理想转行做大模型AI产品经理,建议看看这篇文章!(文末福利)

如果你想转行做大模型&#xff0c;作为一名AI产品经理&#xff0c;你可以怎么做呢&#xff1f;或许&#xff0c;你可以先进行自我检测&#xff0c;看看自己是否真的适合转行做大模型。这篇文章里&#xff0c;作者便给想转行做大模型的AI产品经理们提出了一些建议&#xff0c;不…

【进阶版】如何实现一个基于 HTML+CSS+JS 的任务进度条

创建一个动态任务进度条&#xff1a;进阶版实现 在现代网页开发中&#xff0c;任务进度条是用户交互中非常重要的组件&#xff0c;它能够直观地展示任务的进展情况。本文将向你展示如何使用 HTML、CSS 和 JavaScript 创建一个动态的任务进度条。在这个进阶版本中&#xff0c;用…

三网话费折扣api怎么对接合作?如何变现?

三网优惠话费充值接口对接的操作步骤通常包括以下几个阶段&#xff1a; 注册账号&#xff1a;在API服务提供商的控制台注册账号&#xff0c;例如微客云控制台 。添加店铺&#xff1a;在控制台中添加店铺&#xff0c;并保存店铺ID或只勾选CMS 。申请API密钥&#xff1a;联系客服…

临时提高电压的常用方法电荷泵、自举升压电路

一、临时提高电压 爽死*子了&#xff0c;*子也硬玩一把临时重组器……&#xff08;雷总音&#xff09;。临时提高星级或者电压真的是一件很爽的事情&#xff0c;小钱办大事轻松拿捏。常用的临时提高电压的方式主要有两种&#xff0c;电荷泵和自举升压电路&#xff0c;你的某米手…

Nvidia在AI峰会上发布了七项重大技术公告

每周跟踪AI热点新闻动向和震撼发展 想要探索生成式人工智能的前沿进展吗&#xff1f;订阅我们的简报&#xff0c;深入解析最新的技术突破、实际应用案例和未来的趋势。与全球数同行一同&#xff0c;从行业内部的深度分析和实用指南中受益。不要错过这个机会&#xff0c;成为AI领…

文档大师:打造一站式 Word 报告解决方案

最新技术资源&#xff08;建议收藏&#xff09; https://www.grapecity.com.cn/resources/ 前言 在政府、医院、银行、财务以及销售等领域&#xff0c;常常需要创建各种报告文件来展开工作汇报&#xff0c;譬如季度销售报告、年度总结报告、体检报告和保险合同等。在没有报表工…

一个月学会Java 第7天 字符串与键盘输入

Day7 字符串与键盘输入 字符串作为所有程序都很重要的东西&#xff0c;这个东西必须好好的学习&#xff0c;在Java中String会比较好学习&#xff0c;比起C和C里面会更加的简单&#xff0c; 在Java之中也是很好理解的&#xff0c;因为底层已经封装好了char数组&#xff0c;也就是…

《深入浅出LLM基础篇》(五):Propmt工程优化

&#x1f389;AI学习星球推荐&#xff1a; GoAI的学习社区 知识星球是一个致力于提供《机器学习 | 深度学习 | CV | NLP | 大模型 | 多模态 | AIGC 》各个最新AI方向综述、论文等成体系的学习资料&#xff0c;配有全面而有深度的专栏内容&#xff0c;包括不限于 前沿论文解读、…

【C++】AVL树(AVLTree)

目录 一、AVL树概念&#xff1a; 二、定义&#xff1a; 三、AVL树的插入&#xff1a; 四、AVL树的旋转&#xff1a; 1、左单旋&#xff1a; 2、右单旋&#xff1a; 3、右左双旋&#xff1a; 4、左右双旋&#xff1a; 五、AVL树的检验&#xff1a; 一、AVL树概念&#x…

重离子+数字化,肿瘤治疗的新路

大国之重器&#xff0c;当为大国之民生。 医用重离子加速器装置&#xff0c;被誉为肿瘤放疗领域的大国重器。在河西走廊东侧的甘肃省武威肿瘤医院(以下简称&#xff1a;武威肿瘤医院)&#xff0c;我国首台拥有自主知识产权的医用重离子加速器装置坐落此。自建成投入使用以来&a…

新手教学系列——爬虫异步并发注意事项

引言 爬虫是网络数据采集中不可或缺的工具,很多程序员在入门时会遇到这样的问题:为什么我的爬虫这么慢?尤其在面对大量数据时,单线程爬虫的速度可能让人捶胸顿足。随着爬虫规模的增大,异步并发成为了提高爬取效率的关键。然而,异步并发并不像表面看起来那么简单,如果没…

有哪些可靠的算力租赁平台推荐

作为一名炼丹师&#xff0c;在炼丹过程中使用过不少 GPU 算力租用平台&#xff0c;也有很多心得体会~为了让道友们少走弯路&#xff0c;我打算把近期在市场上用过的几家热门的 GPU 算力平台比较比较&#xff0c;以便其他炼丹师选择适合自己的算力平台。话不多说看&#xff01; …

Python简介与入门

如果你要用计算机做很多工作&#xff0c;最后你会发现有一些任务你更希望用自动化的方式进行处理。比如&#xff0c;你想要在大量的文本文件中执行查找/替换&#xff0c;或者以复杂的方式对大量的图片进行重命名和整理。也许你想要编写一个小型的自定义数据库、一个特殊的 GUI …

2025年人工智能行业的发展趋势预测以及中小企业的应对策略

大家好&#xff0c;我是Shelly&#xff0c;一个专注于输出AI工具和科技前沿内容的AI应用教练&#xff0c;体验过300款以上的AI应用工具。关注科技及大模型领域对社会的影响10年。关注我一起驾驭AI工具&#xff0c;拥抱AI时代的到来。 ​ 进入2024年的第四季度&#xff0c;人工…

python数据分析与可视化工具介绍-numpy库

NumPy&#xff08;Numerical Python的简称&#xff09;&#xff0c;是科学计算基础的一个库&#xff0c;提供了大量关于科学计算的相关功能&#xff0c;例如&#xff0c;线性变换&#xff0c;数据统计&#xff0c;随机数生成等。其提供的最核心的类型为多维数组类型&#xff08…

Android Studio 打包混淆失效问题

项目场景&#xff1a; 通过 Python 脚本运行打包 Apk &#xff0c;实现动态配置各个版本的 Apk。 问题描述 通过 Python 脚本打包编译 Apk&#xff0c;开启混淆后&#xff0c;打包成功&#xff0c;反编译出来的 Apk 并没有被混淆。 原因分析&#xff1a; 首先确认打包混淆…

矩阵系统源码搭建,oem贴牌,技术指导

一、技术选型与整合 多种技术的融合 矩阵系统通常需要整合多种技术&#xff0c;包括前端技术、后端技术、数据库技术、服务器技术等。选择合适的技术栈并确保它们能够良好地协同工作是一个挑战。例如&#xff0c;前端可能使用 React 或 Vue.js&#xff0c;后端可能使用 Java Sp…

聚观早报 | 台积电9月份营收;联发科发布天玑9400

聚观早报每日整理最值得关注的行业重点事件&#xff0c;帮助大家及时了解最新行业动态&#xff0c;每日读报&#xff0c;就读聚观365资讯简报。 整理丨Cutie 10月10日消息 台积电9月份营收 联发科发布天玑9400 vivo X200系列将全系标配原子岛 骁龙8 Gen4或改名“骁龙8至尊…