Arduino 小白的 DIY 空气质量检测仪(3)- TVOC模块、CO2模块

接上回

逐个分析

m_TVOC.h

#include <Arduino.h>#include <SoftI2C.h>#include "DFRobot_SGP40.h"// TVOC指数
// 型号:sgp_40
// 接口:VCC->VCC(5V)、GND->GND、SDA->D6、SCL->D7、WAK->GND
// 协议:I2C(软)
// 地址:0x5A#define _Pin_TVOC_SDA 6
#define _Pin_TVOC_SCL 7
#define _Address_TVOC 0x59namespace Module {SoftI2C SoftWire = SoftI2C(_Pin_TVOC_SDA, _Pin_TVOC_SCL);  //sda, scl
DFRobot_SGP40 _m_sgp_40(&SoftWire);struct _TVOC {void init() {int timeout = 0;// 预热10秒_m_sgp_40.begin(10000);}bool isWarmUp = false;void warmUp() {if (!isWarmUp) {isWarmUp = _m_sgp_40.warmUp();}}void adjust(float temp, float hum) {_m_sgp_40.setRhT(hum, temp);}int getValue() {return isWarmUp ? _m_sgp_40.getVoclndex() : 0;}char unit[6] = "index";
} TVOC;}

通讯方式是 I2C

DFRobot_SGP40 是一个第三方库,本来可以直接在 Arduino IDE 搜索并安装使用。
但是 Arduino Nano 仅有一对 I2C 接口 A4、A5 引脚,而这硬件级的 I2C 接口,需要留个 OLED 显示屏使用。
因此,这里使用了另外一个第三方库 SoftI2C,利用其它引脚通过软件模拟的方式实现I2C通讯。
而且,DFRobot_SGP40 本身并不支持 SoftI2C 类型,所以这里复制了一个副本,并把源码中 Wire 替换成 SoftI2C。

这里根据 I2C 的理论,I2C总线是共享的总线系统,这意味着只要模块的寻址地址不一样,应该可以共用一对 I2C 接口。
只是,小白我在实际的测试使用中,发现会影响 OLED 显示屏导致显示不稳定,不知道究竟是 OLED 库的问题 还是 I2C 信号干扰问题。
所以,读取传感器本身通讯压力较小,实测使用 SoftI2C 基本没问题。

特别的,参考这里的文档SGP40,该传感器是需要预热的,且建议 10 秒以上。

这里有个问题,示例代码中,是通过 while 的方式等待 10 秒预热的,对本项目来说,是不能接受阻塞其它传感器那么久的。

因此,修改 DFRobot_SGP40 源码,把预热操作分离出来方法 warmUp。

源码:

bool DFRobot_SGP40::begin(uint32_t duration)
{_pWire->begin();VocAlgorithm_init(&_vocaAgorithmParams);unsigned long timestamp = millis();// 它在这里通过 while 预热while(millis()-timestamp<duration){getVoclndex();}return sgp40MeasureTest();
}

改为:

long timestamp;
uint32_t duration;
bool DFRobot_SGP40::begin(uint32_t d)
{_pWire->begin();VocAlgorithm_init(&_vocaAgorithmParams);duration = d;timestamp = millis();return true;
}bool DFRobot_SGP40::warmUp(){if(millis()-timestamp<duration){getVoclndex();return false;}return sgp40MeasureTest();
}

预热操作,交给外部调用,本项目是在 程序入口 的 loop 中反复执行:

// arduino-air-monitor.ino// ...略void loop() {
// ...略if (!Module::TVOC.isWarmUp) {Module::TVOC.warmUp();}
// ...略
}// ...略

最后,DFRobot_SGP40 拥有 setRhT 方法,用于设置当前环境中的相对湿度和温度,貌似可以获得更精确的数值。

// arduino-air-monitor.ino// ...略void process(bool display) {// 设置当前环境中的相对湿度和温度,获得更精确的数值if (Module::TVOC.isWarmUp) {Module::TVOC.adjust(Module::Temperature.getValue(), Module::Humidity.getValue());}
}// ...略

m_CO2.h

#include <Arduino.h>// 基于 https://github.com/RobTillaart/MTP40F/blob/master/examples/MTP40F_PWM_demo/MTP40F_PWM_demo.ino
// 由于上面的示例,关于PWM计算,不符合文档下列所属,因此修改之。// 【PWM 功能详解】
// PWM 的周期是 1004ms
// 起始阶段高电平输出 2ms
// 中部周期 1000ms
// 结束阶段低电平输出 2ms
// 通过 PWM 获得当前 CO2
// 浓度值的计算公式:
// Cppm = 5000*(TH-2ms)/(TH+TL-4ms)
// Cppm 为计算得到的 CO2
// 浓度值,单位是 ppm
// TH 为一个输出周期中输出为高电平的时间
// TL 为一个输出周期中输出为低电平的时间// PWM端口:3、5、6、9、10、11、13// 二氧化碳
// 型号:mtp_40_f
// 接口:G+->VCC(5V)、G->GND、PWM->D3
// 协议:PWM#define _Pin_CO2 3namespace Module {namespace MTP_40_F {unsigned long start = 0;
unsigned long duration = 0;// 计算高电平持续时间
void Interrupt() {if (digitalRead(_Pin_CO2) == HIGH) start = millis();else duration = millis() - start;
}// 浓度值的计算公式:
// Cppm = 5000*(TH-2ms)/(TH+TL-4ms)
// 单位是 ppm
unsigned int DurationToPPM() {return 5000 * (float)(duration - 2) / (1004 - 4);
}}struct _CO2 {void init() {pinMode(_Pin_CO2, INPUT_PULLUP);// 中断服务例程(ISR),当连接到引脚电平变化时,Arduino会调用这个函数。attachInterrupt(digitalPinToInterrupt(_Pin_CO2), MTP_40_F::Interrupt, CHANGE);}unsigned int getValue() {unsigned int value = MTP_40_F::DurationToPPM();// 量程 400ppm ~ 5000ppm// 首次计算结果有可能是 65535,因此做一个判断修正。if (value > 10000) {value = 0;}return value;}char unit[6] = "ug\/m";
} CO2;}

通讯方式是 PWM

MTP40F 文档是这样说的:

【PWM 功能详解】
PWM 的周期是 1004ms
起始阶段高电平输出 2ms
中部周期 1000ms
结束阶段低电平输出 2ms
通过 PWM 获得当前 CO2
浓度值的计算公式:
Cppm = 5000*(TH-2ms)/(TH+TL-4ms)
Cppm 为计算得到的 CO2
浓度值,单位是 ppm
TH 为一个输出周期中输出为高电平的时间
TL 为一个输出周期中输出为低电平的时间

关于PWM计算,是基于 RobTillaart/MTP40F改写的,由于计算逻辑不符合上面文档说的计算公司,因此修改之。

源码:

//  ppm == 0     is a pulse length of 2 millis.
//  ppm == 2000  is a pulse length of 1002 millis.
//  every 2 ppm adds 1 millis
uint16_t duration2PPM(uint16_t d)
{return (d - 2) * 2;
}

本项目:

// 浓度值的计算公式:
// Cppm = 5000*(TH-2ms)/(TH+TL-4ms)
// 单位是 ppm
unsigned int DurationToPPM() {return 5000 * (float)(duration - 2) / (1004 - 4);
}

这里最关键的代码应该是:

attachInterrupt(digitalPinToInterrupt(_Pin_CO2), MTP_40_F::Interrupt, CHANGE);

中断服务例程(ISR),当连接到引脚电平变化时,Arduino会调用这个函数。电平变化是 PWM 的关键,文档中举了个例子:

在这里插入图片描述

公式中可以看出,已知周期是 1004 ms,公式中的关键参数是 TH,只要得出 TH,代入公司,即可得出具体数值:

unsigned long start = 0;
unsigned long duration = 0;// 计算高电平持续时间
void Interrupt() {if (digitalRead(_Pin_CO2) == HIGH) start = millis();else duration = millis() - start;
}

未完待续。。。

多多支持其它文章
https://blog.csdn.net/xachary2

又或者请我喝杯奶茶😍
vue3-zoom-drag

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

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

相关文章

主数据驱动的数据治理框架

目录 数据资产分类 数据治理的重要性 数据质量框架的4个方面 数据治理的核心是加强对数据资产的管控,通过深化数据服务,持续创造价值。数据治 理是在数据资产价值创造的过程中,治理团队对数据资产管理的评价、指导、控制,如下图所示。 数据资产分类 数据资产划分成为主数据…

【大模型实战篇】LLaMA Factory微调ChatGLM-4-9B模型

1. 背景介绍 虽然现在大模型微调的文章很多&#xff0c;但纸上得来终觉浅&#xff0c;大模型微调的体感还是需要自己亲自上手实操过&#xff0c;才能有一些自己的感悟和直觉。这次我们选择使用llama_factory来微调chatglm-4-9B大模型。 之前微调我们是用两块3090GPU显卡&…

AnnotationConfigApplicationContext流程看实例化的beanPostProcessor

接上一篇https://blog.csdn.net/qq_26437925/article/details/144865082 探究一下beanPostProcessors怎么加进来的 目录 首先register(annotatedClasses);后添加了重要的beanDefinition: ConfigurationClassPostProcessorinvokeBeanFactoryPostProcessors(beanFactory);执行后…

pip 下载安装时使用国内源配置

pip 是 Python 的包管理工具&#xff0c;用于安装和管理第三方库。然而&#xff0c;在某些情况下&#xff0c;默认的 PyPI&#xff08;Python Package Index&#xff09;源可能由于网络原因导致下载速度慢或者连接不稳定。幸运的是&#xff0c;我们可以轻松地配置 pip 使用国内…

LinuxC高级day4

作业: 1.思维导图 2.终端输入一个C源文件名(.c结尾)判断文件是否有内容&#xff0c;如果没有内容删除文件&#xff0c;如果有内容编译并执行改文件。 3.终端输入两个文件名&#xff0c;判断哪个文件的时间戳更新

RuoYi-Vue从http升级为https(Jar+Nginx)

一、前提条件 1.已通过数字证书管理服务控制台签发证书。 2.SSL证书绑定的域名已完成DNS解析,即域名与主机IP地址相互映射。 附:阿里云网站运维检测平台 3.已在Web服务器开放443端口(HTTPS通信的标准端口)。 如果使用的是阿里云ECS服务器,请确保已经在安全组规则入方向…

OpenCV相机标定与3D重建(39)计算校正畸变后的新相机内参矩阵函数getOptimalNewCameraMatrix()的使用

操作系统&#xff1a;ubuntu22.04 OpenCV版本&#xff1a;OpenCV4.9 IDE:Visual Studio Code 编程语言&#xff1a;C11 算法描述 根据自由缩放参数返回新的相机内参矩阵。 cv::getOptimalNewCameraMatrix 是 OpenCV 库中的一个函数&#xff0c;用于计算校正畸变后的新相机内…

OkHttp深度解析:请求流程、分发器机制、拦截器工作及TCP连接复用

目录 一、OkHttp请求的请求流程是怎样的? 二、OkHttp分发器是怎样工作的? 2.1 请求队列与线程池维护 2.2 异步请求处理 2.3 同步请求处理 2.4 请求执行 2.5 请求完成处理&#xff1a; 2.6 线程池设计 三、OkHttp拦截器是如何工作的? 四、应用拦截器和网络拦截器的…

云计算课程报告实验-WordCount算法实验 过程记录

内容描述 本实验指导书通过在华为鲲鹏上&#xff0c;编译运行WordCount程序。完成实验操作后&#xff0c;读者会掌握简单的程序编写&#xff0c;如WordCount中的getWords、countWords、treeMerge。 实验环境 华为鲲鹏云主机、openEuler 20.03操作系统&#xff1b;安装mpich-3…

2018年全国硕士研究生入学统一考试管理类专业学位联考英语(二)试题-纯享题目版

&#x1f3e0;个人主页&#xff1a;fo安方的博客✨ &#x1f482;个人简历&#xff1a;大家好&#xff0c;我是fo安方&#xff0c;目前中南大学MBA在读&#xff0c;也考取过HCIE Cloud Computing、CCIE Security、PMP、CISP、RHCE、CCNP RS、PEST 3等证书。&#x1f433; &…

kafka使用常见问题

连接不上kafka,报下边的错 org.apache.kafka.common.KafkaException: Producer is closed forcefully.at org.apache.kafka.clients.producer.internals.RecordAccumulator.abortBatches(RecordAccumulator.java:760) [kafka-clients-3.0.2.jar:na]at org.apache.kafka.client…

Jenkins(持续集成与自动化部署)

Jenkins 是一个开源软件项目&#xff0c;是基于Java开发的一种持续集成工具。 官网&#xff1a;https://www.jenkins.io/ GitLab安装使用 安装前提&#xff1a;内存至少需要4G 官方网站&#xff1a;https://about.gitlab.com/ 安装文档&#xff1a;https://docs.gitlab.c…

MyBatis执行一条sql语句的流程(源码解析)

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 MyBatis执行一条sql语句的流程&#xff08;源码解析&#xff09; MyBatis执行sql语句的流程加载配置文件加载配置文件的流程 创建sqlsessionFactory对象解析Mapper创建sqlses…

【C++】探索C++11中的范围for循环与auto关键字

博客主页&#xff1a; [小ᶻ☡꙳ᵃⁱᵍᶜ꙳] 本文专栏: C 文章目录 &#x1f4af;前言&#x1f4af;1. 范围for循环的基础用法1.1 什么是范围for循环&#xff1f;1.2 示例代码代码解析 1.3 范围for的特点传统for循环与范围for循环对比 1.4 使用引用修改元素 &#x1f4af;2…

mac下载Homebrew安装nvm

通过Homebrew安装 - 国内下载地址 /bin/zsh -c "$(curl -fsSL https://gitee.com/cunkai/HomebrewCN/raw/master/Homebrew.sh)"安装nvm brew install nvm 配置nvm环境变量 export NVM_DIR“$HOME/.nvm” [ -s “/usr/local/opt/nvm/nvm.sh” ] && . “/usr/…

解決當前IP地址僅適用於本地網路

想要解決“當前IP地址僅適用於本地網路”其實並不困難。本篇文章將介紹其發生的原因以及如何解決。 “僅限本地網路”是什麼意思&#xff1f; 當IP地址為“僅限本地網路”時&#xff0c;意味著設備正在使用私人網路內部IP地址&#xff0c;但無法連接到互聯網。如果將本地IP視…

HANA数据库 XS 503 Service not available

http_url配置正确 在将单个数据库系统转换为多租户数据库容器系统之后&#xff0c;无法通过URL访问新租户数据库的独立XS引擎服务。调用相应的URL会产生这样的错误&#xff1a;503服务不可用 Solution &#xff08;启用租户数据库引擎的嵌套模式&#xff08;HDD不用&#xff…

【大模型实战篇】Mac本地部署RAGFlow的踩坑史

1. 题外话 最近一篇文章还是在11月30日写的&#xff0c;好长时间没有打卡了。最近工作上的事情特别多&#xff0c;主要聚焦在大模型的预训练、微调和RAG两个方面。主要用到的框架是Megatron-DeepSpeed&#xff0c;后续会带来一些分享。今天的文章主要聚焦在RAG。 近期调研了一系…

推荐5款局域网IP扫描工具,支持电脑+Android!

在日常网络管理中&#xff0c;快速扫描局域网中的设备和IP地址是一项基本但非常重要的任务。无论是排查网络问题还是进行设备管理&#xff0c;一款好用的 IP 扫描工具都能让你事半功倍。 如何选择适合自己需求的局域网 IP 扫描工具&#xff1f;有哪些功能强大又易于上手的工具…

python修改ppt中的文字部分及插入图片

批量修改ppt中的某个模块&#xff0c;或者批量制作奖状等场景会用到&#xff1b; import os import pandas as pd from pptx import Presentation from pptx.util import Inchesfilepath/Users/kangyongqing/Documents/kangyq/202303/分析模版/批量制作/file1时段预警_副本.pp…