0 卖盘信息
BOM询价
您现在的位置: 首页 > 技术方案 >工业控制 > 基于 Arduino UNO 的CO2测量仪(接线图+代码)

基于 Arduino UNO 的CO2测量仪(接线图+代码)

来源: 电路城
2021-11-16
类别:工业控制
eye 16
文章创建人 拍明

原标题:基于 Arduino UNO 的CO2测量仪(接线图+代码)

cirmall

基于Arduino UNO的CO2测量仪:从原理到实践的详细指南

二氧化碳(CO2)是地球大气中重要的组成部分,它在维持地球温度、支持植物光合作用等方面发挥着关键作用。然而,过高浓度的CO2,尤其是在室内环境中,会对人体健康产生负面影响,例如导致头痛、疲劳、注意力不集中,甚至在极端情况下引发更严重的生理反应。因此,实时监测室内CO2浓度对于保障居住和工作环境的健康与舒适至关重要。随着物联网技术和开源硬件的普及,个人和小型企业也能以较低的成本构建自己的环境监测系统。本文将详细介绍如何利用Arduino UNO微控制器,结合高性能的MH-Z19B CO2传感器和清晰的OLED显示屏,搭建一个功能完善、易于操作的CO2测量仪。我们将深入探讨每个核心元器件的工作原理、选择理由、技术参数,并提供详尽的接线图与注释丰富的Arduino代码,旨在为您提供一份从理论到实践的全面指导,使您能够轻松复刻并理解这个项目。

在我们的CO2测量仪项目中,Arduino UNO R3将作为整个系统的“大脑”,负责协调各项任务,包括从CO2传感器读取数据、处理这些数据、并通过OLED显示屏实时展示结果。选择Arduino UNO的原因在于其卓越的易用性、丰富的学习资源、庞大的开源社区支持以及极高的性价比。对于初学者而言,Arduino IDE(集成开发环境)简洁直观,编程语言基于C/C++,但经过简化,使得即使没有深厚编程背景的用户也能快速上手。其标准化的引脚布局和兼容性,使得连接各种传感器和执行器变得轻而易举。MH-Z19B CO2传感器则是我们获取CO2浓度数据的核心,它采用了先进的非分散红外(NDIR)技术,能够提供相对准确且稳定的测量结果,同时其成本效益使其成为DIY项目的理想选择。为了直观地呈现测量数据,我们选用了0.96英寸的OLED显示屏,这种显示屏以其高对比度、宽视角和低功耗的特点,非常适合作为小型便携式设备的用户界面。此外,考虑到MH-Z19B传感器的工作电压为3.3V,而Arduino UNO通常提供5V电源,我们还需要一个DC-DC降压模块来确保传感器的稳定供电。通过本文的指导,您将不仅学会如何组装一个CO2测量仪,更将深入理解其背后的科学原理和技术细节,为未来的更多创新项目打下坚实基础。

核心元器件详解

构建一个可靠的CO2测量仪,选择合适的元器件是成功的关键。以下我们将详细介绍本项目中使用的核心元器件,包括它们的功能、技术参数以及我们选择它们的原因。

1. Arduino UNO R3微控制器

Arduino UNO R3是Arduino系列中最受欢迎的开发板之一,也是许多电子爱好者和工程师入门微控制器编程的首选。它以其开源的硬件设计、用户友好的软件环境和活跃的社区支持而闻名。

  • 功能: Arduino UNO R3的核心是一颗Atmel的ATmega328P微控制器。这颗芯片集成了CPU、闪存(用于存储程序代码)、SRAM(用于运行时数据)和EEPROM(用于存储少量持久性数据)。它拥有14个数字输入/输出引脚(其中6个可作为PWM输出)、6个模拟输入引脚、一个USB接口用于与计算机通信和供电、一个电源插座用于外部供电、一个ICSP头用于程序烧录以及一个复位按钮。数字引脚可以配置为输入或输出,用于控制LED、继电器或读取按钮状态等。模拟引脚则可以将来自传感器(如温度传感器、光敏电阻)的连续电压信号转换为数字值,供微控制器处理。PWM(脉冲宽度调制)功能允许模拟输出效果,例如控制LED亮度或电机速度。串行通信(UART)、I2C(两线接口)和SPI(串行外设接口)等通信接口使得Arduino能够与其他数字设备进行数据交换,例如我们的CO2传感器和OLED显示屏。

  • 为什么选择: Arduino UNO R3之所以成为本项目以及众多DIY项目的优选,主要基于以下几点:

    • 易用性与入门友好: Arduino IDE提供了简洁的编程界面和易于理解的C/C++语言结构,大大降低了微控制器编程的门槛。大量的示例代码和教程使得学习曲线非常平缓。

    • 强大的社区支持: Arduino拥有全球性的庞大社区,这意味着当您遇到问题时,很容易在论坛、博客或教程中找到解决方案。丰富的第三方库也极大地简化了与各种硬件模块的交互。

    • 稳定性与可靠性: 作为一款经过时间考验的经典开发板,Arduino UNO R3在设计和制造上都非常成熟,具有良好的稳定性和可靠性,适合长期运行的项目。

    • 丰富的扩展性: 尽管UNO本身功能强大,但其开放的硬件设计和标准化的引脚布局,使得通过各种“扩展板”(Shields)或直接连接模块,可以轻松扩展其功能,例如添加Wi-Fi、蓝牙、SD卡存储等。

    • 成本效益: 相较于其他一些专业的嵌入式开发板,Arduino UNO R3的价格非常亲民,使得个人爱好者也能轻松负担。

  • 技术参数:

    • 微控制器:ATmega328P

    • 工作电压:5V

    • 输入电压(推荐):7-12V

    • 输入电压(限制):6-20V

    • 数字I/O引脚:14个(其中6个提供PWM输出)

    • 模拟输入引脚:6个

    • I/O引脚直流电流:20 mA

    • 3.3V引脚直流电流:50 mA

    • 闪存(Flash Memory):32 KB(ATmega328P),其中0.5 KB用于引导加载程序(bootloader)

    • SRAM:2 KB

    • EEPROM:1 KB

    • 时钟频率:16 MHz

  • 与CO2测量仪项目的关联: 在CO2测量仪项目中,Arduino UNO R3是核心的控制单元。它通过其数字引脚与MH-Z19B CO2传感器进行串行通信(UART),接收并解析CO2浓度数据。同时,它通过I2C接口与OLED显示屏通信,将解析出的CO2浓度值以及其他相关信息(如状态)实时显示出来。Arduino还负责处理传感器数据的定时读取、可能的校准指令发送,以及整个系统的电源管理和稳定性维护。其处理能力和丰富的I/O接口完全满足本项目需求。

2. MH-Z19B CO2传感器

MH-Z19B是一款常用的非分散红外(NDIR)原理的CO2气体传感器,广泛应用于HVAC系统、空气质量监测、农业温室等领域。

  • 功能: MH-Z19B传感器利用NDIR技术来测量CO2浓度。其基本原理是:CO2气体对特定波长的红外光具有吸收特性。传感器内部包含一个红外光源和一个红外探测器。红外光从光源发出,穿过一个包含待测气体的腔室,然后被探测器接收。当腔室中存在CO2时,一部分特定波长的红外光会被CO2分子吸收,导致到达探测器的光强度减弱。光强度减弱的程度与CO2的浓度成正比。通过测量光强度的变化,传感器就能计算出CO2的浓度。MH-Z19B通常提供多种输出方式,包括UART(串行通信)、PWM(脉冲宽度调制)和模拟电压输出。UART是最常用且推荐的方式,因为它能提供更精确的数字读数和更丰富的功能(如校准指令)。

  • 为什么选择:

    • NDIR技术: NDIR是目前测量CO2最成熟、最稳定且相对准确的技术之一,相较于一些基于化学反应的CO2传感器,NDIR传感器具有更好的长期稳定性和抗干扰能力。

    • 成本效益: 在NDIR传感器中,MH-Z19B系列以其相对较低的价格和可靠的性能,成为DIY项目和消费级产品的热门选择。

    • 易于接口: MH-Z19B提供UART接口,这与Arduino的串行通信能力完美匹配,使得数据读取和控制变得简单。它还支持PWM输出,为没有足够硬件串口的微控制器提供了另一种选择。

    • 预热时间与稳定性: 传感器通常需要一定的预热时间(约3分钟)才能达到最佳测量状态,一旦预热完成,其读数相对稳定。

    • 测量范围: MH-Z19B通常提供0-5000ppm的测量范围,这足以满足大多数室内空气质量监测的需求。

  • 技术参数:

    • UART:波特率9600,数据位8位,停止位1位,无奇偶校验。

    • PWM:周期1004ms,高电平脉宽与CO2浓度成比例。

    • 测量气体:CO2

    • 测量范围:0-5000ppm(可选0-2000ppm, 0-10000ppm等型号)

    • 工作电压:DC 4.5V ~ 5.5V(但实际推荐使用3.3V供电以获得更稳定性能,或通过模块内置稳压)

    • 平均电流:< 60mA

    • 峰值电流:150mA

    • 接口类型:UART(TTL电平)、PWM输出、模拟电压输出

    • 输出信号:

    • 预热时间:3分钟

    • 响应时间:T90 < 120秒

    • 工作温度:0℃ ~ 50℃

    • 工作湿度:0 ~ 95%RH(无凝露)

    • 尺寸:33mm × 20mm × 9mm

  • 与CO2测量仪项目的关联: MH-Z19B是本项目的核心传感器,它负责采集CO2浓度数据。我们将通过Arduino的软件串口(SoftwareSerial)与其进行UART通信,发送查询命令并接收返回的数据帧,然后解析出CO2浓度值。由于MH-Z19B对供电电压有一定要求,且其数据手册常建议在3.3V下工作以获得最佳性能,因此需要一个独立的3.3V稳压模块为其供电,而不是直接使用Arduino的5V。

3. 0.96英寸OLED显示屏 (SSD1306驱动)

OLED(有机发光二极管)显示屏因其出色的显示特性,在小型电子设备中越来越受欢迎。

  • 功能: 0.96英寸OLED显示屏通常采用SSD1306驱动芯片,分辨率为128x64像素。它能够以点阵形式显示文字、数字、图形和简单的图像。与传统的LCD(液晶显示屏)不同,OLED的每个像素都能自发光,因此无需背光,这使得它具有极高的对比度、纯黑背景、宽视角和更低的功耗。它通常通过I2C(Inter-Integrated Circuit)或SPI(Serial Peripheral Interface)接口与微控制器通信。I2C接口只需要两根数据线(SDA和SCL),大大节省了微控制器的引脚资源,非常适合引脚数量有限的Arduino UNO。

  • 为什么选择:

    • 高对比度与清晰度: OLED屏幕自发光的特性使其显示内容非常清晰,即使在光线较暗的环境下也能轻松读取。

    • 低功耗: 无需背光意味着在显示黑色像素时几乎不消耗电量,这对于电池供电的项目尤其有利。

    • 小巧轻便: 0.96英寸的尺寸非常适合集成到紧凑的CO2测量仪外壳中。

    • 宽视角: 几乎从任何角度都能清晰地看到显示内容。

    • I2C通信: 仅需两根数据线(SDA和SCL)即可与Arduino连接,简化了接线并节省了宝贵的GPIO引脚。

    • 成本效益: 0.96英寸的SSD1306 OLED模块价格非常实惠。

  • 技术参数:

    • 尺寸:0.96英寸

    • 分辨率:128x64像素

    • 颜色:单色(通常为蓝色或白色,本项目中假设为蓝色)

    • 驱动芯片:SSD1306

    • 接口类型:I2C(默认)或SPI

    • 工作电压:DC 3.3V ~ 5V(大多数模块内置稳压,可以直接使用5V供电)

    • 引脚定义:VCC, GND, SCL, SDA(I2C模式)

  • 与CO2测量仪项目的关联: OLED显示屏是CO2测量仪的用户界面。它将实时显示由MH-Z19B传感器测量到的CO2浓度值,以及其他可能的状态信息,例如“传感器预热中”、“校准成功”等。通过Arduino的Adafruit GFX和Adafruit SSD1306库,我们可以非常方便地控制OLED屏幕,绘制文本和图形。

4. DC-DC降压模块 (AMS1117-3.3V)

MH-Z19B CO2传感器的工作电压为DC 4.5V至5.5V,但其数据手册通常建议使用3.3V供电以获得更稳定的性能和更低的功耗。Arduino UNO的数字引脚和大部分传感器通常工作在5V逻辑电平,但其板载的3.3V稳压器提供的电流有限(通常只有50mA),不足以稳定驱动MH-Z19B传感器(峰值电流可达150mA)。因此,我们需要一个独立的降压模块来为MH-Z19B提供稳定、充足的3.3V电源。

  • 功能: AMS1117-3.3V是一款低压差(LDO)线性稳压器,能够将较高的输入电压(例如Arduino的5V输出或外部电源的7-12V)稳定地降压至3.3V输出。它通常有三个引脚:VIN(输入电压)、VOUT(输出电压)和GND(接地)。线性稳压器通过内部调整管的压降来稳定输出电压,其优点是输出纹波小、噪声低、电路简单。

  • 为什么选择:

    • 电压匹配: 专门用于将5V或更高电压降至3.3V,完美匹配MH-Z19B的供电需求。

    • 电流能力: AMS1117通常能提供高达800mA或1A的输出电流(取决于具体型号和散热条件),远超MH-Z19B的峰值电流需求,确保传感器稳定工作。

    • 稳定性: 线性稳压器输出电压稳定,纹波小,有助于传感器获得更准确的读数。

    • 成本低廉: AMS1117系列稳压器非常常见且价格低廉。

    • 易于使用: 只需要简单的输入、输出和接地连接即可工作,无需复杂的外部元件。

  • 技术参数:

    • 输入电压范围:通常为4.75V ~ 12V(具体取决于型号和压差要求)

    • 输出电压:3.3V

    • 最大输出电流:通常为800mA或1A

    • 压差:1.2V(典型值),即输入电压至少要比输出电压高1.2V才能正常工作。

    • 封装:SOT-223(贴片)或TO-220(直插,通常集成在小模块上)

  • 与CO2测量仪项目的关联: AMS1117-3.3V模块是MH-Z19B传感器的专用电源。我们将把Arduino的5V输出连接到AMS1117的VIN引脚,然后将AMS1117的VOUT引脚连接到MH-Z19B的VCC引脚,确保MH-Z19B在正确的电压下稳定运行。这是保证CO2测量准确性和传感器寿命的关键一步。

5. 面包板与跳线

面包板和跳线是电子原型搭建过程中不可或缺的工具。

  • 功能: 面包板(Breadboard)是一种用于快速搭建临时电路的工具,其表面有许多小孔,内部通过金属条连接,形成导通的行或列。通常,面包板的中间区域是信号线区域,上下两边是电源线区域。跳线(Jumper Wires),也称为杜邦线,是带有连接器(通常是公头或母头)的单股或多股导线,用于在面包板上连接不同的元器件引脚。

  • 为什么选择:

    • 无需焊接: 这是面包板最大的优势。您可以在不焊接的情况下快速连接和断开元器件,极大地缩短了原型开发和测试的时间。

    • 方便修改: 如果电路设计有误或需要调整,可以轻松地拔下并重新插入元器件和跳线,而无需进行复杂的拆焊工作。

    • 可重复使用: 面包板和跳线都可以重复使用,降低了实验成本。

    • 可视化: 电路连接在面包板上清晰可见,便于理解和排查问题。

  • 与CO2测量仪项目的关联: 在构建CO2测量仪的初期,我们将使用面包板来连接Arduino UNO、MH-Z19B传感器、OLED显示屏和AMS1117-3.3V模块。跳线则用于连接这些模块的各个引脚。这使得我们可以在正式制作PCB(印刷电路板)之前,快速验证电路的正确性和功能。

辅助元器件及作用

除了上述核心元器件,还有一些辅助元器件在电路中扮演着重要角色,它们虽然不起眼,但对于电路的稳定运行和保护至关重要。

1. 电阻

电阻是电路中最基本的元件之一,其主要作用是限制电流、分压、提供上拉或下拉电阻等。

  • 限流: 在许多电路中,为了保护发光二极管(LED)或其他对电流敏感的元件不被过大的电流烧毁,需要串联一个合适的电阻来限制通过的电流。例如,如果直接将一个普通LED连接到5V电源,LED会因电流过大而烧毁,串联一个220欧姆的电阻可以将其工作电流限制在安全范围内。

  • 分压: 两个或多个电阻串联可以形成分压电路,将一个较高的电压按照电阻比例分配到不同的点上,从而获得所需的较低电压。这在一些传感器需要特定电压输入或需要将模拟信号范围调整到ADC(模数转换器)可接受范围时非常有用。

  • 上拉/下拉电阻: 在数字电路中,特别是在微控制器的输入引脚上,当引脚没有明确的外部连接时,其状态可能会处于不确定的“浮空”状态,容易受到电磁干扰而产生误触发。为了避免这种情况,通常会在输入引脚上连接一个上拉电阻(连接到电源VCC)或下拉电阻(连接到地GND)。上拉电阻在按钮未按下时将引脚拉高,按下时拉低;下拉电阻则在按钮未按下时将引脚拉低,按下时拉高。这确保了引脚在任何时候都有一个确定的逻辑状态。在I2C通信中,SDA和SCL线通常也需要外部上拉电阻,以确保总线在空闲时保持高电平,这是I2C协议的规定。虽然许多OLED模块已经内置了上拉电阻,但在某些情况下,如果通信不稳定,可能需要额外添加。

  • 在CO2测量仪项目中的应用: 本项目中,电阻可能不会作为独立元件大量出现,因为MH-Z19B和OLED模块通常已集成所需电阻。但理解其作用对于电路分析和故障排除至关重要。例如,如果您选择使用一个不带内置电阻的LED来指示电源状态,就需要串联一个限流电阻。

2. 电容

电容是用于存储电荷的元件,在电路中主要用于滤波、储能、耦合和旁路。

  • 滤波: 电容可以平滑电源电压的波动,滤除电源中的高频噪声,使电源输出更稳定。例如,在AMS1117-3.3V降压模块的输入和输出端通常会并联电容,以提高稳压器的稳定性并降低输出纹波。对于对电源质量敏感的传感器(如MH-Z19B),良好的电源滤波可以提高测量精度。

  • 储能: 电容可以快速充放电,在短时间内提供或吸收电流。这在需要瞬时大电流的场合(例如数字电路切换时)可以提供局部的电流补充,防止电压跌落。

  • 耦合: 在交流电路中,电容可以允许交流信号通过,同时阻隔直流信号,实现信号的耦合或去耦。

  • 旁路电容(去耦电容): 这是数字电路中非常重要的应用。在微控制器或其他数字芯片的电源引脚附近,通常会并联一个小的陶瓷电容(例如0.1uF)。当芯片内部的晶体管快速开关时,会产生瞬时电流需求,如果电源线过长或阻抗较高,会导致电源电压瞬时跌落。旁路电容可以提供一个局部的、低阻抗的电荷源,快速响应这种瞬时电流需求,从而稳定芯片的供电电压,防止数字信号错误。

  • 在CO2测量仪项目中的应用: 虽然您可能不会直接连接独立的电容,但MH-Z19B模块和AMS1117-3.3V模块内部都包含了必要的滤波和旁路电容。理解其作用有助于理解为什么这些模块能够稳定工作。

3. 杜邦线(跳线)

杜邦线是带连接器的电线,用于连接电路中的不同点。

  • 功能: 杜邦线有公对公、母对母、公对母等多种类型,它们使得在面包板上连接Arduino、传感器、显示屏等模块变得非常方便,无需焊接。它们提供了一种灵活、可重复使用的连接方式,是原型开发和测试的理想选择。

  • 为什么选择: 易用性、灵活性、可重复使用性、无需焊接。

  • 在CO2测量仪项目中的应用: 杜邦线将是连接所有模块(Arduino UNO、MH-Z19B、OLED、AMS1117-3.3V)的桥梁,确保电气连接的正确性。

4. USB数据线

USB数据线是Arduino与计算机连接的必备工具。

  • 功能:

    • 供电: USB数据线可以将计算机的USB端口提供的5V电源传输给Arduino UNO,为开发板及其连接的低功耗模块供电。

    • 程序上传: 通过USB数据线,Arduino IDE可以将您编写的程序代码上传到Arduino UNO的ATmega328P微控制器中。

    • 串口通信: USB数据线还充当Arduino与计算机之间的串行通信桥梁。这使得您可以通过Arduino IDE的串口监视器查看Arduino发送的调试信息(例如CO2读数),或者向Arduino发送命令。

  • 为什么选择: Arduino UNO的标准连接方式,方便快捷。

  • 在CO2测量仪项目中的应用: 在开发和调试阶段,USB数据线将用于为Arduino供电、上传程序代码以及通过串口监视器查看CO2读数和调试信息。

5. 外部电源适配器 (可选)

虽然Arduino可以通过USB数据线供电,但在某些情况下,特别是当项目需要独立运行或连接的模块功耗较高时,外部电源适配器是更好的选择。

  • 功能: 外部电源适配器通常提供7V至12V的直流电压(例如9V或12V),通过Arduino UNO板上的DC电源插座为整个系统供电。Arduino板载的稳压器会将这个外部电压降压到5V,以供微控制器和大部分引脚使用。

  • 为什么选择:

    • 独立运行: 一旦程序上传完成,测量仪可以脱离计算机独立工作。

    • 更稳定的供电: 外部电源通常能提供比USB端口更大的电流,确保所有模块(特别是MH-Z19B传感器)在峰值电流需求时也能获得稳定供电,避免因供电不足导致的读数不稳或模块重启。

    • 避免计算机USB端口过载: 如果连接的模块总功耗较高,可能会对计算机的USB端口造成负担,使用外部电源可以避免这个问题。

  • 在CO2测量仪项目中的应用: 在项目调试完成后,如果您希望CO2测量仪作为一个独立的设备长期运行,一个9V或12V的外部电源适配器将是理想的供电方案。

接线图与详细连接步骤

正确的接线是项目成功的基石。我们将提供详细的文字描述和概念性的接线图指导,确保您能够准确无误地连接所有元器件。

重要提示: 在进行任何接线操作之前,请确保所有设备都已断电,以避免短路或损坏元器件。

连接概述:

  1. MH-Z19B CO2传感器供电: MH-Z19B需要稳定的3.3V供电。我们将使用AMS1117-3.3V降压模块将Arduino的5V转换为3.3V。

  2. MH-Z19B CO2传感器数据通信: MH-Z19B通过UART(串行通信)与Arduino通信。我们将使用Arduino的软件串口(SoftwareSerial)功能,因为硬件串口(D0/RX, D1/TX)通常用于与计算机通信。

  3. 0.96英寸OLED显示屏供电: OLED显示屏通常可以直接使用Arduino的5V供电。

  4. 0.96英寸OLED显示屏数据通信: OLED显示屏通过I2C(两线接口)与Arduino通信。

详细连接步骤:

步骤1:连接AMS1117-3.3V降压模块

AMS1117-3.3V模块通常有三个引脚:VIN(输入)、GND(接地)、VOUT(输出)。

  • 将AMS1117-3.3V的VIN引脚连接到Arduino UNO的5V引脚。

    • 这为降压模块提供了5V的输入电压。

  • 将AMS1117-3.3V的GND引脚连接到Arduino UNO的GND(任意一个接地引脚)。

    • 这为降压模块提供了公共接地。

步骤2:连接MH-Z19B CO2传感器

MH-Z19B传感器通常有以下引脚:VCC、GND、RXD、TXD。

  • 将MH-Z19B的VCC引脚连接到AMS1117-3.3V的VOUT引脚。

    • 这为MH-Z19B传感器提供了稳定的3.3V电源。

  • 将MH-Z19B的GND引脚连接到Arduino UNO的GND(与AMS1117-3.3V共用一个GND)。

    • 确保所有模块共地,这是数字电路正常工作的基本要求。

  • 将MH-Z19B的RXD引脚连接到Arduino UNO的数字引脚D2。

    • 在我们的代码中,D2将被配置为软件串口的RX(接收)引脚,用于接收MH-Z19B发送的数据。

  • 将MH-Z19B的TXD引脚连接到Arduino UNO的数字引脚D3。

    • 在我们的代码中,D3将被配置为软件串口的TX(发送)引脚,用于向MH-Z19B发送查询命令。

为什么使用SoftwareSerial?

Arduino UNO只有一个硬件串口(引脚D0/RX和D1/TX),这个硬件串口默认用于与计算机通过USB进行通信(上传程序和串口监视器)。如果我们将MH-Z19B连接到D0/D1,就会与USB通信冲突,导致程序上传失败或串口监视器无法正常工作。SoftwareSerial库允许我们使用Arduino的任意两个数字引脚模拟一个额外的串口,从而解决了硬件串口冲突的问题。

步骤3:连接0.96英寸OLED显示屏

0.96英寸OLED显示屏(SSD1306驱动,I2C版本)通常有以下四个引脚:VCC、GND、SDA、SCL。

  • 将OLED的VCC引脚连接到Arduino UNO的5V引脚。

    • 大多数0.96英寸OLED模块内置了稳压器,可以直接接受5V电源。如果您的OLED模块明确说明只支持3.3V,请连接到AMS1117-3.3V的VOUT。

  • 将OLED的GND引脚连接到Arduino UNO的GND(与MH-Z19B和AMS1117-3.3V共用一个GND)。

    • 确保所有模块共地。

  • 将OLED的SDA引脚连接到Arduino UNO的模拟引脚A4。

    • 在Arduino UNO上,A4引脚是硬件I2C的SDA(数据线)引脚。

  • 将OLED的SCL引脚连接到Arduino UNO的模拟引脚A5。

    • 在Arduino UNO上,A5引脚是硬件I2C的SCL(时钟线)引脚。

(此处应插入一张清晰的接线图,展示Arduino UNO、MH-Z19B、AMS1117-3.3V和OLED显示屏之间的连接。由于我无法直接生成图像,请您自行想象或根据上述文字描述绘制。图中应清晰标明每个模块的引脚名称以及它们连接到Arduino UNO的哪个引脚。例如:MH-Z19B RXD -> D2, TXD -> D3, VCC -> AMS1117 VOUT; AMS1117 VIN -> 5V, GND -> GND; OLED SDA -> A4, SCL -> A5, VCC -> 5V, GND -> GND。)

接线逻辑与注意事项:

  • 共地原则: 所有的电子模块都必须共用一个GND(地)引脚。这是保证电路中电压参考点一致,确保信号能够正确传输的基础。

  • 电源匹配: 严格按照模块所需的工作电压供电。MH-Z19B对3.3V的稳定供电有较高要求,因此AMS1117-3.3V模块至关重要。

  • 通信接口匹配: 确保模块之间的通信接口类型(UART、I2C)和引脚连接正确。UART需要TX对RX,RX对TX。I2C需要SDA对SDA,SCL对SCL。

  • 引脚功能: 了解Arduino引脚的功能(数字I/O、模拟输入、PWM、硬件串口、I2C)对于正确接线至关重要。

完成以上接线步骤后,您的硬件连接部分就基本完成了。接下来,我们将进入软件编程部分,为您的CO2测量仪注入“生命”。

Arduino代码详解

软件是硬件的灵魂。我们将为CO2测量仪编写Arduino代码,实现传感器数据读取、数据处理、OLED显示以及必要的校准功能。

在编写代码之前,您需要安装一些必要的库:

  1. SoftwareSerial库: Arduino IDE自带,无需额外安装。用于模拟串口与MH-Z19B通信。

  2. Adafruit GFX库: 一个通用的图形库,为各种显示屏提供图形绘制功能。

  3. Adafruit SSD1306库: 专门用于SSD1306驱动的OLED显示屏。

您可以通过Arduino IDE的“工具” -> “管理库...” (Ctrl+Shift+I) 搜索并安装“Adafruit GFX Library”和“Adafruit SSD1306”。

```cpp
// 引入必要的库文件
#include <SoftwareSerial.h> // 用于模拟串口与MH-Z19B传感器通信
#include <Adafruit_GFX.h>   // Adafruit图形库,提供基本的图形绘制功能
#include <Adafruit_SSD1306.h> // Adafruit SSD1306 OLED显示屏库

// 定义MH-Z19B传感器的RX和TX引脚
// Arduino的D2连接到MH-Z19B的TXD (MH-Z19B发送数据到Arduino的RX)
// Arduino的D3连接到MH-Z19B的RXD (Arduino发送命令到MH-Z19B的RX)
#define MHZ19B_RX_PIN 2 // Arduino数字引脚2,作为MH-Z19B的RX
#define MHZ19B_TX_PIN 3 // Arduino数字引脚3,作为MH-Z19B的TX

// 创建SoftwareSerial对象,用于MH-Z19B通信
SoftwareSerial mhzSerial(MHZ19B_RX_PIN, MHZ19B_TX_PIN); // RX, TX

// 定义OLED显示屏的宽度和高度
#define SCREEN_WIDTH 128 // OLED显示屏宽度,单位像素
#define SCREEN_HEIGHT 64 // OLED显示屏高度,单位像素

// 定义OLED显示屏的I2C地址
// 大多数0.96英寸OLED模块的I2C地址是0x3C或0x3D
#define OLED_RESET -1 // 复位引脚,对于大多数I2C OLED模块,可以设置为-1 (不使用)
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET); // 创建OLED显示屏对象

// 定义CO2浓度变量,初始值为0
int co2Ppm = 0;
// 定义传感器预热状态,初始为true
bool isWarmingUp = true;
// 记录预热开始时间
unsigned long warmUpStartTime = 0;
// 定义预热时间,3分钟 = 180000毫秒
const unsigned long WARM_UP_DURATION = 180000UL;

// 定义用于MH-Z19B通信的命令字节数组
// 查询CO2浓度命令 (Get CO2 concentration)
byte getCO2Command[] = {0xFF, 0x01, 0x86, 0x00, 0x00, 0x00, 0x00, 0x00, 0x79};
// 零点校准命令 (Zero point calibration, 400ppm in fresh air)
// 注意:此操作应在新鲜空气中进行,且传感器稳定后执行,否则可能导致读数不准确。
// 建议在部署前执行一次,日常使用中除非读数明显偏差,否则不频繁执行。
byte calibrateZeroCommand[] = {0xFF, 0x01, 0x87, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78};
// 禁用自动校准命令 (Disable auto calibration)
// 某些MH-Z19B模块默认开启自动校准,如果需要手动控制校准,可以禁用。
byte disableAutoCalibrateCommand[] = {0xFF, 0x01, 0x79, 0x00, 0x00, 0x00, 0x00, 0x00, 0x86};
// 启用自动校准命令 (Enable auto calibration)
// 如果需要MH-Z19B自动在低点进行校准,可以启用此功能。
byte enableAutoCalibrateCommand[] = {0xFF, 0x01, 0x79, 0xA0, 0x00, 0x00, 0x00, 0x00, 0xE6};


// setup() 函数在Arduino板上电或复位后只运行一次
void setup() {
 // 初始化硬件串口,用于与计算机通信和调试
 Serial.begin(9600);
 Serial.println(F("CO2 测量仪启动中..."));

 // 初始化软件串口,用于与MH-Z19B传感器通信
 mhzSerial.begin(9600);
 Serial.println(F("MH-Z19B 软件串口初始化完成。"));

 // 初始化OLED显示屏
 // 如果OLED初始化失败,通过串口输出错误信息并进入无限循环
 if (!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) { // 检查I2C地址,如果您的OLED是0x3D,
 请修改此处
   Serial.println(F("SSD1306 OLED 初始化失败!请检查接线和I2C地址。"));
   for (;;); // 进入无限循环,停止程序运行
 }

 // 清除OLED显示屏缓冲区
 display.clearDisplay();
 // 设置文本颜色为白色
 display.setTextColor(SSD1306_WHITE);
 // 设置文本大小为1
 display.setTextSize(1);
 // 设置光标位置
 display.setCursor(0, 0);
 // 显示启动信息
 display.println(F("CO2 测量仪"));
 display.println(F("启动中..."));
 display.println(F("传感器预热中..."));
 display.display(); // 刷新显示屏

 // 记录预热开始时间
 warmUpStartTime = millis();

 // 禁用自动校准(可选,根据需求决定是否执行)
 // sendMHZ19BCommand(disableAutoCalibrateCommand);
 // delay(100); // 短暂延迟,等待命令执行
}

// loop() 函数在setup()函数执行完毕后会无限循环运行
void loop() {
 // 检查传感器是否仍在预热
 if (isWarmingUp) {
   if (millis() - warmUpStartTime < WARM_UP_DURATION) {
     // 仍在预热期间,显示预热信息
     display.clearDisplay();
     display.setTextSize(1);
     display.setCursor(0, 0);
     display.println(F("CO2 测量仪"));
     display.println(F("传感器预热中..."));
     display.print(F("剩余: "));
     // 计算剩余预热时间(秒)
     unsigned long remainingSeconds = (WARM_UP_DURATION - (millis() - warmUpStartTime))
     / 1000;
     display.print(remainingSeconds);
     display.println(F(" 秒"));
     display.display();
     delay(1000); // 每秒更新一次预热倒计时
     return; // 预热期间不执行CO2读取
   } else {
     // 预热完成
     isWarmingUp = false;
     Serial.println(F("MH-Z19B 传感器预热完成!"));
     display.clearDisplay();
     display.setCursor(0, 0);
     display.println(F("预热完成!"));
     display.display();
     delay(1000); // 显示“预热完成”1秒
   }
 }

 // 读取CO2浓度
 co2Ppm = readCO2();

 // 在OLED上显示CO2浓度
 displayCO2(co2Ppm);

 // 每隔5秒读取一次传感器数据并更新显示
 delay(5000);
}

/**
* @brief 计算MH-Z19B命令或响应的校验和
* @param packet 包含数据包的字节数组
* @return 计算出的校验和
*/
byte calculateChecksum(byte* packet) {
 byte checksum = 0;
 // 从第二个字节开始计算到倒数第二个字节(不包括校验和本身)
 for (int i = 1; i < 8; i++) {
   checksum += packet[i];
 }
 // 校验和是256减去所有字节的和(取低8位)
 return 0xFF - checksum + 0x01;
}

/**
* @brief 向MH-Z19B传感器发送命令
* @param command 要发送的命令字节数组
*/
void sendMHZ19BCommand(byte* command) {
 // 清空软件串口的接收缓冲区,防止读取到旧数据
 while (mhzSerial.available()) {
   mhzSerial.read();
 }
 // 写入命令到软件串口
 mhzSerial.write(command, 9);
}

/**
* @brief 从MH-Z19B传感器读取CO2浓度
* @return CO2浓度值(ppm),如果读取失败返回-1
*/
int readCO2() {
 byte response[9]; // 存储传感器返回的9个字节数据
 int timeout = 0; // 超时计数器

 // 发送查询CO2浓度的命令
 sendMHZ19BCommand(getCO2Command);

 // 等待传感器响应,最多等待1秒
 while (mhzSerial.available() < 9) {
   delay(10);
   timeout++;
   if (timeout > 100) { // 10ms * 100 = 1秒
     Serial.println(F("MH-Z19B 读取超时!"));
     return -1; // 返回-1表示读取失败
   }
 }

 // 读取传感器返回的所有字节
 for (int i = 0; i < 9; i++) {
   response[i] = mhzSerial.read();
 }

 // 校验数据包的完整性和正确性
 // 检查起始字节 (0xFF)
 if (response[0] != 0xFF) {
   Serial.println(F("MH-Z19B 响应起始字节错误!"));
   return -1;
 }
 // 检查命令字节 (0x86)
 if (response[1] != 0x86) {
   Serial.println(F("MH-Z19B 响应命令字节错误!"));
   return -1;
 }
 // 检查校验和
 byte calculatedChecksum = calculateChecksum(response);
 if (response[8] != calculatedChecksum) {
   Serial.print(F("MH-Z19B 校验和错误!计算值: "));
   Serial.print(calculatedChecksum, HEX);
   Serial.print(F(", 接收值: "));
   Serial.println(response[8], HEX);
   return -1;
 }

 // 从响应数据中提取CO2浓度值
 // CO2浓度值由第3个字节(response[2])和第4个字节(response[3])组成
 // 高字节在前,低字节在后
 int co2 = (int)response[2] * 256 + (int)response[3];
 Serial.print(F("读取到CO2浓度: "));
 Serial.print(co2);
 Serial.println(F(" ppm"));

 return co2;
}

/**
* @brief 在OLED显示屏上显示CO2浓度
* @param ppm CO2浓度值
*/
void displayCO2(int ppm) {
 display.clearDisplay(); // 清除显示屏内容

 // 设置文本大小为1,显示“CO2浓度”标签
 display.setTextSize(1);
 display.setCursor(0, 0);
 display.println(F("CO2 浓度:"));

 // 设置文本大小为3,显示CO2浓度值
 display.setTextSize(3);
 display.setCursor(0, 15); // 调整位置以适应大字体
 if (ppm == -1) {
   display.println(F("读取失败")); // 如果读取失败,显示错误信息
 } else {
   display.print(ppm);
   display.println(F(" ppm"));
 }

 // 根据CO2浓度显示不同的空气质量状态
 display.setTextSize(1);
 display.setCursor(0, 50); // 调整位置
 if (ppm < 600 && ppm != -1) {
   display.println(F("空气质量: 优"));
 } else if (ppm >= 600 && ppm < 1000 && ppm != -1) {
   display.println(F("空气质量: 良"));
 } else if (ppm >= 1000 && ppm < 1500 && ppm != -1) {
   display.println(F("空气质量: 一般"));
 } else if (ppm >= 1500 && ppm != -1) {
   display.println(F("空气质量: 差! 建议通风"));
 } else {
   display.println(F("空气质量: 未知")); // 处理读取失败的情况
 }

 display.display(); // 刷新显示屏,将缓冲区内容显示出来
}

/**
* @brief 执行MH-Z19B的零点校准(400ppm校准)
* @note 此函数应在新鲜空气(CO2浓度约400ppm)中调用,且传感器稳定后执行。
* 调用后,传感器会将其当前环境的CO2浓度校准为400ppm。
* 此操作会修改传感器的内部参数,请谨慎使用。
* 您可以在setup()中添加一个按钮触发此功能,而不是直接在loop()中调用。
*/
void calibrateMHZ19BZeroPoint() {
 Serial.println(F("正在执行MH-Z19B零点校准..."));
 display.clearDisplay();
 display.setTextSize(1);
 display.setCursor(0, 0);
 display.println(F("正在零点校准..."));
 display.println(F("请确保在新鲜空气中!"));
 display.display();

 sendMHZ19BCommand(calibrateZeroCommand);
 delay(5000); // 等待校准完成,MH-Z19B需要一些时间来处理校准命令

 Serial.println(F("MH-Z19B 零点校准完成。"));
 display.clearDisplay();
 display.setTextSize(1);
 display.setCursor(0, 0);
 display.println(F("零点校准完成!"));
 display.display();
 delay(2000); // 显示校准完成信息2秒
}

// 示例:如何手动触发校准(您可以在loop()中添加一个条件判断或按钮触发)
/*
void checkAndCalibrate() {
 // 假设您有一个连接到D4的按钮,按下后执行校准
 // pinMode(4, INPUT_PULLUP); // 在setup中设置
 // if (digitalRead(4) == LOW) { // 按钮按下
 //   delay(50); // 简单去抖
 //   if (digitalRead(4) == LOW) {
 //     calibrateMHZ19BZeroPoint();
 //     while(digitalRead(4) == LOW); // 等待按钮释放
 //   }
 // }
}
*/

责任编辑:David

【免责声明】

1、本文内容、数据、图表等来源于网络引用或其他公开资料,版权归属原作者、原发表出处。若版权所有方对本文的引用持有异议,请联系拍明芯城(marketing@iczoom.com),本方将及时处理。

2、本文的引用仅供读者交流学习使用,不涉及商业目的。

3、本文内容仅代表作者观点,拍明芯城不对内容的准确性、可靠性或完整性提供明示或暗示的保证。读者阅读本文后做出的决定或行为,是基于自主意愿和独立判断做出的,请读者明确相关结果。

4、如需转载本方拥有版权的文章,请联系拍明芯城(marketing@iczoom.com)注明“转载原因”。未经允许私自转载拍明芯城将保留追究其法律责任的权利。

拍明芯城拥有对此声明的最终解释权。

上一篇: 已是第一篇
标签: CO2测量仪

相关资讯

拍明芯城微信图标

各大手机应用商城搜索“拍明芯城”

下载客户端,随时随地买卖元器件!

拍明芯城公众号
拍明芯城抖音
拍明芯城b站
拍明芯城头条
拍明芯城微博
拍明芯城视频号
拍明
广告
恒捷广告
广告
深亚广告
广告
原厂直供
广告