资讯动态

基于Proteus的Arduino空气质量报警系统设计与仿真实现

发布时间:2026/9/16 14:50:13 来源:尧图企业网站定制
简介面向Arduino与Proteus仿真学习者这套空气检测警报系统仿真资源提供完整软硬件方案涵盖控制程序、仿真工程、电路图及LCD库文件支持PM2.5、有毒气体、温湿度三类传感器实时采集与显示形成多维度空气质量监测方案。当PM2.5浓度大于150或有害气体超过10%时蜂鸣器自动报警、报警灯点亮非常适合电子实训、课程设计或毕业设计拓展也可作为物联网环境监测的入门参考。整套资料共12个文件以pde源码、pdsprj仿真工程、cpp/h库文件、docx说明文档及png原理图为主结构清晰压缩包仅172KB轻便易用。目前已有985人学习使用配套程序说明文档能辅助理解设计思路与调试要点读者可快速复现空气监测模型也能基于现有代码二次开发增加无线传输、云端上报等功能。遇到疑问还可直接咨询作者让学习调试过程更加顺畅。1. 用 Proteus 搭一套能跑通全链路的空气质量报警节点拿到这个 Arduino 空气检测警报系统仿真包的时候我第一个反应是这玩意比买一块真实硬件回来搞要省事得多。它把 PM2.5 传感器、有毒气体传感器、温湿度传感器、I2C LCD 显示屏、蜂鸣器和报警灯全部集成在一个 Proteus 工程里双击就能跑仿真不需要焊板子、不需要买传感器模块、更不用担心把模拟引脚接错烧掉器件。对于正在做课程设计或者想快速验证报警逻辑的开发者来说这套仿真可以直接当做一个「信号链路沙盘」模拟电压怎么被 ADC 采集、浓度阈值怎么触发声光报警、LCD 怎么通过 I2C 总线刷新数据整个流程一目了然。适合三类人准备交单片机课程作业的学生、想在不花钱的前提下摸一遍 Arduino 数据采集逻辑的入门者、以及需要快速给客户演示空气报警方案的工程师。文件包里已经包含.pdsprj工程文件、电路图、程序源码和 LiquidCrystal_I2C 库拿到手不是空壳子而是可以直接改动参数重新仿真的完整工程。2. 传感器选型与 Proteus 电路连接从信号源到 ADC 引脚2.1 三种传感器在仿真中的扮演角色这套仿真系统里用到了三个传感器它们在 Proteus 里的建模方式完全不同搞清楚这一点后面调参才不会懵。PM2.5 传感器对应的是夏普 GP2Y1010AU0F 的电气特性这个器件在真实硬件中是通过红外 LED 照射空气、光电二极管接收散射光来检测粉尘浓度的输出是模拟电压。在 Proteus 里没有现成的 GP2Y1010AU0F 模型常见的做法是用一个电位器POT-HG模拟它的输出电压变化因为该传感器在干净空气中的典型输出约为 0.5V在粉尘浓度升高时输出电压线性上升最大可到 3.6V 左右。用电位器分压代替传感器本质上就是模拟 0 到 3.6V 的电压输入范围对应 ADC 采样值从大约 102 到 737。有毒气体传感器对应的是 MQ-2 系列它在真实硬件中是一个气敏电阻当检测到可燃气体或烟雾时内部电阻下降经过负载电阻分压后输出电压升高。Proteus 仿真里同样没有精确的 MQ-2 模型所以用另一个电位器模拟其输出电压变化电位器输出接到 Arduino 的模拟输入引脚 A1。这里要注意MQ-2 的响应曲线是非线性的但在仿真中为了演示报警逻辑完全可以直接用百分比映射ADC 采样值 0 到 1023 映射到 0% 到 100% 的燃气浓度仿真验证的重点是「浓度超过 10% 时报警」这个逻辑分支是否正确而不是气体传感器的物理标定。温湿度传感器 DHT11 是这套仿真里唯一有真实 Proteus 模型的外设。Proteus 的元件库中可以直接搜索 DHT11它是一个三引脚器件VCC、DATA、GND采用单总线协议数据引脚需要接一个 4.7kΩ 上拉电阻到 VCC然后连接到 Arduino 的数字引脚 D2。DHT11 的测量范围是湿度 20% 到 90% RH、温度 0 到 50 摄氏度精度一般但用在「显示环境温湿度」这个需求上完全够。这里要特别提醒Proteus 的 DHT11 模型对时序比较敏感如果单片机主频设置不对或者代码里 I2C 操作占用了太长时间很容易出现读取超时返回nan的情况后面我会专门讲这个问题。2.2 Proteus 里 Arduino 328 的引脚映射这个工程用的主控是 Arduino 328对应 Proteus 里的 ARDUINO UNO 原理图模型或者直接搜索 ATMEGA328P 加最小系统电路。Proteus 8 之后的版本元件库中可以直接放置ARDUINO UNO这个模型带有完整的引脚标注不需要担心引脚名对不上。连接关系如下表传感器/外设Proteus 元件连接的 Arduino 引脚说明PM2.5 传感器模拟POT-HG 电位器A0电位器中间抽头接 A0两端接 5V 和 GND有毒气体传感器模拟POT-HG 电位器A1同上独立电位器模拟 MQ-2 输出DHT11 温湿度传感器DHT11D2数据引脚需接 4.7kΩ 上拉电阻LCD 显示屏LM016L PCF8574A4 (SDA)、A5 (SCL)I2C 方式PCF8574 地址默认 0x27蜂鸣器BUZZERD8建议串 100Ω 限流电阻报警灯LED-REDD9必须串 220Ω 限流电阻LCD 这块是很多新手在 Proteus 里最容易卡住的地方。素材包里提供的 LiquidCrystal_I2C 库对应的是「LCD 1602 I2C 转接板」的组合。在 Proteus 中你需要放置一个LM016L标准 16x2 字符液晶和一个PCF8574I2C 转并行接口芯片将 PCF8574 的 P0 到 P7 依次连接到 LM016L 的 D4 到 D7、RS、EN、背光等引脚。这里我建议直接给出一组我验证过的接法PCF8574 的 P0 接 RSP1 接 RWP2 接 EP4 接 D4P5 接 D5P6 接 D6P7 接 D7P3 作为背光控制。SCL 和 SDA 分别接到 Arduino 的 A5 和 A4PCF8574 的 A0、A1、A2 地址引脚全部接地此时 I2C 设备地址就是 0x27与代码里LiquidCrystal_I2C lcd(0x27, 16, 2)完全对应。2.3 模拟信号链路的设计取舍在画这个电路时有一个值得思考的点既然仿真里 PM2.5 和有毒气体传感器都是用电位器模拟的那为什么还要在电路图里专门画出传感器符号我的理解是这个工程的文件包里有电路图.png这张图的作用是给人看的——说明真实系统中传感器的接入位置和信号流向。而在仿真运行时电位器只是替你手动调节浓度值验证 ADC 采样和报警阈值。所以你不需要纠结「这个电位器到底模拟的是哪款型号」只需要知道把电位器旋钮往上调电压升高ADC 读数变大对应的 PM2.5 浓度值变大超过 150 就触发报警。这就是仿真和实物的核心差异仿真验证逻辑实物验证物理量。这里还要补一个细节GP2Y1010AU0F 在真实硬件中输出的是带脉动的电压信号通常需要在输出端加一个 RC 低通滤波把高频噪声滤掉后再送 ADC。在 Proteus 仿真中不需要做这个处理因为电位器输出的是干净的直流电压。但如果你将来把程序移植到真实硬件上务必在 A0 引脚对地并联一个 0.1µF 电容否则 PM2.5 数值会在真实浓度值附近剧烈跳变。3. 程序设计LiquidCrystal_I2C 库驱动、传感器读取与阈值报警逻辑3.1 库文件的安装与工程结构素材包里的LiquidCrystal_I2C-master文件夹是一个标准的 Arduino 库目录结构里面有LiquidCrystal_I2C.cpp、LiquidCrystal_I2C.h、library.properties、keywords.txt和examples示例目录。安装方式有两种第一种是把整个文件夹复制到 Arduino IDE 的libraries目录下例如C:\Users\你的用户名\Documents\Arduino\libraries\LiquidCrystal_I2C-master第二种是在 Arduino IDE 中点击「项目」→「加载库」→「添加 .ZIP 库」选择打包好的 zip 文件。安装完成后在 IDE 中会看到 LiquidCrystal_I2C 库的示例程序例如 HelloWorld 和 SerialDisplay。这里有一个很多教程不会提到的坑库文件夹的名字不能有空格或特殊字符否则编译时会报No such file or directory。建议把解压出来的文件夹重命名为LiquidCrystal_I2C去掉-master后缀。另外这个库依赖于Wire.h这是 Arduino IDE 自带的 I2C 通信库不需要额外安装。如果你在编译时遇到找不到LiquidCrystal_I2C.h的错误先检查库文件夹路径是否正确再确认 Arduino IDE 是否已经重启以加载新库。3.2 核心代码详解DS18B20 风格的逐行拆解先给出一份完整的可编译代码这份代码基于素材包里的程序文档补齐了 DHT11 读取和报警延时逻辑适合直接用于 Proteus 仿真#include Wire.h #include LiquidCrystal_I2C.h #include DHT.h // 定义引脚连接 #define PM25_PIN A0 // PM2.5 传感器模拟输出接 A0 #define GAS_PIN A1 // 有毒气体传感器模拟输出接 A1 #define DHT_PIN 2 // DHT11 数据引脚接 D2 #define BUZZER_PIN 8 // 蜂鸣器接 D8 #define LED_PIN 9 // 报警灯接 D9 // 定义传感器类型和阈值 #define DHT_TYPE DHT11 // DHT11 传感器型号 #define PM25_THRESHOLD 150 // PM2.5 报警阈值150 µg/m³ #define GAS_THRESHOLD 10 // 有毒气体报警阈值10% // 初始化 I2C LCD地址 0x2716 列 2 行 LiquidCrystal_I2C lcd(0x27, 16, 2); // 初始化 DHT11 DHT dht(DHT_PIN, DHT_TYPE); // 全局变量用于存储传感器读数 float pm25Value 0; int gasPercent 0; float temperature 0; float humidity 0; void setup() { // 初始化引脚模式 pinMode(BUZZER_PIN, OUTPUT); pinMode(LED_PIN, OUTPUT); // 初始化 LCD lcd.init(); lcd.backlight(); // 初始化 DHT11 dht.begin(); // 初始化串口方便调试查看数据 Serial.begin(9600); // 启动画面 lcd.setCursor(0, 0); lcd.print(Air Monitor); lcd.setCursor(0, 1); lcd.print(System Ready!); delay(2000); lcd.clear(); } void loop() { // 读取 PM2.5 模拟值0-1023 int pmRaw analogRead(PM25_PIN); // 将 ADC 原始值映射到 0-500 µg/m³ 范围 pm25Value map(pmRaw, 0, 1023, 0, 500); // 读取有毒气体模拟值映射到 0-100% int gasRaw analogRead(GAS_PIN); gasPercent map(gasRaw, 0, 1023, 0, 100); // 读取温湿度 temperature dht.readTemperature(); humidity dht.readHumidity(); // 检查 DHT11 读取是否成功 if (isnan(temperature) || isnan(humidity)) { lcd.setCursor(0, 0); lcd.print(DHT11 Read Err!); } else { // 显示温湿度 lcd.setCursor(0, 0); lcd.print(T:); lcd.print(temperature, 1); // 保留一位小数 lcd.print(C H:); lcd.print(humidity, 0); // 整数显示 lcd.print(%); } // 第二行显示 PM2.5 和气体浓度 lcd.setCursor(0, 1); lcd.print(P:); lcd.print(pm25Value, 0); lcd.print( G:); lcd.print(gasPercent); lcd.print(% ); // 判断是否触发报警 bool alarm false; if (pm25Value PM25_THRESHOLD) { alarm true; } if (gasPercent GAS_THRESHOLD) { alarm true; } // 驱动蜂鸣器和报警灯 digitalWrite(BUZZER_PIN, alarm ? HIGH : LOW); digitalWrite(LED_PIN, alarm ? HIGH : LOW); // 串口输出便于调试 Serial.print(PM2.5: ); Serial.print(pm25Value); Serial.print( ug/m3, Gas: ); Serial.print(gasPercent); Serial.print(%, Temp: ); Serial.print(temperature); Serial.print(C, Humi: ); Serial.print(humidity); Serial.println(%); // 降低刷新频率避免 LCD 闪烁 delay(1000); }3.3 代码逻辑与参数设计说明map函数是这段代码的映射核心它做的事情是把 0 到 1023 的 ADC 采样值等比映射到 0 到 500 的 PM2.5 浓度范围。为什么要映射到 500因为国标环境空气质量指数中 PM2.5 的上限通常按 500 µg/m³ 作为严重污染封顶值超过这个值传感器输出的电压也基本饱和了。实际如果你用的是真实的 GP2Y1010AU0F 传感器输出 0.5V 对应约 0 µg/m³输出 3.6V 对应约 600 µg/m³用map做线性映射会有一点误差但作为仿真和原型验证完全够用。有毒气体的映射逻辑与 PM2.5 类似将 ADC 值映射到 0 到 100。这里「10%」的报警阈值对应的是气体浓度百分比,也就是 ADC 原始值大约在 103 左右,电位器只需转动到输出电压约为 0.5V 的位置就会触发报警。这个阈值在代码里可以用GAS_THRESHOLD宏定义自由修改如果做煤气泄漏报警仿真建议把阈值再调低到 5%因为家用煤气报警器的动作阈值普遍很低。DHT11 的readTemperature()和readHumidity()返回的是 float 类型如果传感器通信失败会返回nanNot a Number。代码中的isnan()函数用来捕获这种异常情况避免 LCD 上显示出乱码。在 Proteus 仿真中DHT11 模型通常能正常返回数据但如果你修改了代码导致 DHT11 的读取间隔小于 1 秒就可能触发传感器自身的时序限制返回nan。这对应 DHT11 数据手册中明确规定的「两次读取间隔必须大于 1 秒」。报警输出部分采用的是「与或」逻辑只要 PM2.5 或者气体任意一项超标alarm变量就为true蜂鸣器和 LED 同时动作。这里我特意让报警灯和蜂鸣器用了不同的引脚控制方便在 Proteus 里分别调试。如果你希望报警时蜂鸣器发出不同频率的声音来区分是哪种气体超标可以把digitalWrite改成tone()函数后面扩展章节我会给方案。4. Proteus 仿真运行与排错从加载工程到阈值触发验证4.1 打开工程与基本仿真操作用 Proteus 打开Arduino 328空气检测系统.pdsprj文件后你应该看到完整的电路原理图。在开始仿真之前确认两件事第一Arduino 模型是否已经烧录了程序Proteus 里的 Arduino 板子需要双击它在编辑对话框中加载从 Arduino IDE 编译出的.hex文件第二供电是否正常Arduino 的 VCC 引脚必须有 5V 电源。如果在 Arduino IDE 中点击「导出编译二进制文件」生成的 hex 文件路径可以在 IDE 的「首选项」里查看build.path或者直接在 Sketch 的临时目录中找到.hex文件。点击 Proteus 左下角的运行按钮仿真就会启动。理想情况下 LCD 上两秒内显示环境数据串口模拟终端如果有接 VIRTUAL TERMINAL会输出实时数据。如果没有看到任何反应优先检查程序是否烧录成功暂停仿真双击 Arduino 模型查看 Program File 路径是否正确确认后重新运行。4.2 调整电位器模拟浓度超限这是整套仿真最核心的操作也是验证系统能否正常报警的关键。运行仿真后找到模拟 PM2.5 传感器的那个电位器用鼠标点击电位器中间的调节滑块并拖动观察到 LCD 上 PM2.5 数值随之变化。默认情况下电位器 0% 位置输出 0V对应 PM2.5 值 050% 位置输出 2.5V对应大约 250 µg/m³——此时已经超过了 150 的阈值蜂鸣器和报警灯应该立刻动作。同理有毒气体电位器调到大约 10% 位置输出 0.5V即可触发气体报警。如果你拖动电位器时 LCD 数值变化不均匀或者在某个位置数值跳变明显这是电位器步进导致的正常现象不是代码 bug。Proteus 的电位器默认有 100 个步进位置你可以在元件属性中修改Stop参数提高精度例如设置为 500。4.3 常见问题与解决对照表在跑这套仿真时我把自己踩过的坑和素材包里的代码结构对照了一遍整理成下面的排查表现象根本原因解决方法LCD 显示空白但有背光I2C 地址不匹配或接线错误检查 PCF8574 的 A0-A2 接地状态确认地址是 0x27尝试在代码中用lcd.begin()替代lcd.init()LCD 只显示方块字符PCF8574 的引脚映射与代码期望不一致确认 P0 接 RS、P2 接 E、P4-P7 接 D4-D7这是最常见的接法PM2.5 数值不变化电位器没有正确连接到 A0在 Proteus 中用电压探针测量 A0 引脚电压确认电压随电位器变化蜂鸣器不响驱动电流不够或引脚接错检查蜂鸣器正极是否接 D8负极是否接 GNDProteus 的蜂鸣器模型需要设置额定电压DHT11 返回 nan上拉电阻缺失或仿真速度太快在 DHT11 数据引脚加 4.7kΩ 上拉电阻把仿真速度调低到 1x编译时找不到 LiquidCrystal_I2C.h库文件未安装或路径错误重新安装库并确认LiquidCrystal_I2C.cpp和.h在同一目录4.4 串口输出的调试价值素材包的程序文档里保留了Serial.begin(9600)和串口打印语句这绝对不是多余的。在 Proteus 仿真中你可以在电路图中放置一个VIRTUAL TERMINAL串口终端组件把它的 RXD 引脚接到 Arduino 的 TXD 引脚D1然后在代码中保持Serial.print输出。这样当你拖动电位器时串口终端上会实时显示 PM2.5、气体浓度、温湿度五组数据。使用串口数据判断报警逻辑是否正常比盯着 LCD 上的小数靠谱得多因为 LCD 刷新有延迟而串口数据是逐行打印的能精确看出阈值跨越的那一刻传感器数值的变化曲线。5. 在仿真基础上加功能按键调阈值、频率报警与实物迁移提醒5.1 按键调节报警阈值免改代码固定阈值 150 和 10% 在演示场景下够用但如果要做成课程设计的加分项加入一个按键调节阈值的功能会很出彩。接法很简单在 Arduino 的 D3 引脚上接一个按键另一端接 GND启用内部上拉。每按下一次按键PM2.5 阈值就提高 10 µg/m³循环到 300 后回到 50。实现逻辑是在loop()里检测按键下降沿用计数变量控制阈值表索引。const int pm25Thresholds[] {50, 100, 150, 200, 250, 300}; int thresholdIndex 2; // 默认 150 // 在 loop() 中检测按键 static bool lastButtonState HIGH; bool buttonState digitalRead(3); if (lastButtonState HIGH buttonState LOW) { thresholdIndex (thresholdIndex 1) % 6; delay(50); // 简单消抖注意不要在中断里做复杂逻辑 } lastButtonState buttonState; // 报警判断时使用动态阈值 if (pm25Value pm25Thresholds[thresholdIndex]) { alarm true; }这段代码的关键在于按键检测用了边沿触发而不是电平触发否则按住按键时阈值会连续快速跳动。delay(50)起到简单的消抖作用但在仿真中 Protesu 的按键模型本身没有机械抖动所以消抖更多是为了以后移植到实物上不会出现一次按下跳多档的问题。5.2 用 tone() 区分不同报警类型如果你想区分是 PM2.5 超标还是燃气超标可以让蜂鸣器发出不同频率的报警音。Arduino 的tone()函数可以直接驱动蜂鸣器产生特定频率的方波信号。比如 PM2.5 超标时给 500Hz 频率间隔 200ms 响一次燃气超标时给 1000Hz 频率连续响。代码实现只需要把digitalWrite(BUZZER_PIN, alarm ? HIGH : LOW)替换成条件判断后分别调用tone(BUZZER_PIN, 500)和tone(BUZZER_PIN, 1000)。这里有个细节要注意tone()函数在 Proteus 中同样可以仿真但需要把蜂鸣器模型的驱动频率属性设置得足够高否则听不到声音——可以改用示波器观察引脚输出的方波频率来验证。5.3 从仿真迁移到实物时的三个关键差异最后提醒一个针对这套系统的实物迁移问题。仿真里你用两个电位器模拟传感器输出接线干净利落但真实硬件连接时会有三个明显的差异需要适配。第一GP2Y1010AU0F 需要 5V 供电且 LED 驱动引脚要串一个 150Ω 电阻和一个 220µF 电容组成的脉冲驱动电路不能直接拿 Arduino 的数字引脚去驱动。第二MQ-2 传感器在刚上电时有大约一分钟的预热期期间输出电压会漂移所以程序里最好在setup()中加一个 60 秒的等待或者做自动校准——记录上电时的基线电压之后用实时电压减去基线值再计算浓度。第三DHT11 在真实硬件中如果接线超过 20 厘米数据线必须加 4.7kΩ 上拉电阻否则数据读取间歇性失败。仿真里你可能加了上拉电阻也感觉没区别但实物上少了这个电阻会导致大约 20% 的概率读不到数据。把这三点改完这套 Proteus 仿真里的逻辑代码可以直接烧录到真实的 Arduino Uno 板上运行LCD 显示、报警阈值、串口调试输出全部复用不需要改一行代码。这也是用仿真做原型验证最大的价值先把逻辑跑通再把硬件问题一个个解决掉。本文还有配套的精品资源点击获取

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价