基于单片机设计的防煤气泄漏装置

一、前言

煤气泄漏是一个严重的安全隐患,可能导致火灾、爆炸以及对人体健康的威胁。为了提高家庭和工业环境中煤气泄漏的检测和预防能力,设计了一种基于单片机的防煤气泄漏装置。

单片机选择STC89C52作为主控芯片。为了检测煤气泄漏,采用了MQ4传感器,能够快速、准确地检测煤气浓度。通过采集MQ4传感器的模拟信号,使用PCF8591模数转换芯片将模拟信号转换为数字信号。采用IIC接口的OLED显示屏,将采集到的数据显示出来,方便用户获取检测结果。用户可以通过两个独立按键设置煤气泄漏的报警阈值,以适应不同环境的需求。

当检测到煤气泄漏超过设定的阈值时,装置会触发蜂鸣器进行报警,并同时打开换气扇进行通风换气,以迅速排除煤气并降低安全风险。

这种基于单片机设计的防煤气泄漏装置具有以下优点:高效可靠的煤气泄漏检测能力、灵活的报警阈值设置、直观清晰的数据显示以及及时的安全响应措施。可以广泛应用于家庭、工业和商业场所,提供有效的煤气泄漏监测和安全保护。

image-20230823165237872

image-20230823165325193

二、硬件选型

在设计基于单片机的防煤气泄漏装置时,硬件选型是非常关键的。以下是详细介绍硬件选型的相关内容:

【1】主控芯片选择:STC89C52 STC89C52是一款8051架构的单片机,具有丰富的接口资源、较高的性能和稳定可靠的工作特性,广泛应用于各种嵌入式系统中。具有8位数据总线、16位地址总线和4KB的内部存储器。STC89C52具备多个通用I/O口、定时器/计数器、串口等功能,非常适合本项目需求。

【2】煤气传感器选择:MQ4 MQ4传感器是一种能够检测多种可燃气体,如天然气、甲烷等的传感器。具有高灵敏度和快速响应的特点,能够准确地检测煤气泄漏情况。MQ4传感器的输出为模拟信号,需要通过模数转换器将其转换为数字信号供主控芯片处理。

【3】模数转换器选择:PCF8591 PCF8591是一款集成了8位模数/数模转换和4个模拟输入通道的模数转换器。采用IIC总线通讯接口,能够将模拟信号转换为数字信号,并通过IIC协议发送给主控芯片。本项目中,PCF8591用于采集MQ4传感器输出的模拟信号,并将其转换为数字信号供STC89C52处理。

【4】显示屏选择:0.96寸OLED显示屏(IIC接口) 本设计采用基于IIC接口的OLED显示屏,具有高亮度、对比度和快速响应的特点。通过简单的通讯方式,可以将煤气浓度信息实时显示在屏幕上。OLED显示屏使用面积小、功耗低,在嵌入式系统中应用广泛。

【5】按键选择:独立按键 本设计采用两个独立按键来设置报警的阀值。一个按键用于递增阀值,另一个按键用于递减阀值。独立按键具有简单可靠、使用方便等特点,适合本项目需求。

【6】报警装置选择:蜂鸣器和换气扇 当检测到煤气泄漏超过设定的报警阀值时,蜂鸣器将发出警报,用于提醒周围人员。同时,为了降低煤气浓度,需要启动换气扇进行通风换气。具体的报警和换气扇电路可以根据实际需求设计。

三、设计思路

软件设计思路如下:

【1】初始化:在程序开始时,进行主控芯片STC89C52的初始化设置,包括引脚配置、定时器设置等。同时,初始化PCF8591和OLED显示屏,确保它们可以正常工作。

【2】传感器检测:通过MQ4传感器检测煤气是否泄漏。将MQ4传感器与STC89C52的模拟输入引脚连接,通过读取该引脚的模拟电压值,获取煤气浓度数据。

【3】数据采集与处理:使用PCF8591模数转换芯片,将MQ4传感器的模拟输出信号转换为数字信号,并通过STC89C52的IIC接口与PCF8591进行通信,获取转换后的数字数据。

【4】数据显示:将采集到的煤气浓度数据通过IIC接口的OLED显示屏进行显示。使用STC89C52的IIC通信功能,将数据发送给OLED显示屏,通过显示屏将数据以可读的方式展示给用户。

【5】阈值设置:通过两个独立按键实现报警阈值的设置。将按键与STC89C52的GPIO引脚连接,通过读取按键状态来判断用户是否进行阈值设置操作。当按键按下时,进入设置模式,用户可以通过按键的不同组合来调整报警阈值,并将设置的值保存在相应的变量中。

【6】报警与通风控制:根据当前采集到的煤气浓度数据和用户设置的报警阈值进行比较。如果煤气浓度超过设定的阈值,触发蜂鸣器进行报警,并控制换气扇打开进行通风换气。反之,当煤气浓度低于或等于设定的阈值时,停止报警并关闭换气扇。

【7】循环监测:使用主循环结构,不断进行煤气泄漏检测、数据采集、数据显示和阈值比较等操作,以实现持续的监测和反馈。

四、项目模块代码

4.1 PCF8591采集代码

下面是使用STC89C52单片机通过PCF8591读取MQ4传感器的ADC数据的代码。使用IIC总线进行PCF8591之间的通信,使用了自定义的IIC总线函数。通过readADC()函数实现了读取MQ4传感器模拟量的ADC转换结果。

#include <reg52.h>#define uchar unsigned char
#define uint unsigned intsbit SDA = P2^0;    // IIC总线数据线
sbit SCL = P2^1;    // IIC总线时钟线sbit MQ4_DOUT = P3^0;   // MQ4传感器数字输出引脚
sbit MQ4_AIN = P3^1;    // MQ4传感器模拟输入引脚sfr IAP_DATA = 0xe2;    // 定义IAP_DATA寄存器
sfr IAP_ADDRH = 0xe3;   // 定义IAP_ADDRH寄存器
sfr IAP_ADDRL = 0xe4;   // 定义IAP_ADDRL寄存器
sfr IAP_CMD = 0xe5;     // 定义IAP_CMD寄存器
sfr IAP_TRIG = 0xe6;    // 定义IAP_TRIG寄存器
sfr IAP_CONTR = 0xe7;   // 定义IAP_CONTR寄存器// 函数声明
void delay(uint ms);
void startIIC();
void stopIIC();
void sendByte(uchar dat);
uchar receiveByte();
void writeDAC(uchar dat);
uchar readADC();void main() {uchar mq4Value;while (1) {mq4Value = readADC();  // 读取ADC转换结果// 处理mq4Value值,进行相应操作delay(100);  // 延时一段时间}
}// 延时函数
void delay(uint ms) {uint i, j;for(i = ms; i > 0; i--) {for(j = 110; j > 0; j--);}
}// IIC总线起始信号
void startIIC() {SDA = 1;_nop_();SCL = 1;_nop_();SDA = 0;_nop_();SCL = 0;_nop_();
}// IIC总线停止信号
void stopIIC() {SDA = 0;_nop_();SCL = 1;_nop_();SDA = 1;_nop_();
}// 发送一个字节的数据
void sendByte(uchar dat) {uchar i;for (i = 0; i < 8; i++) {SDA = dat >> 7;_nop_();SCL = 1;_nop_();SCL = 0;_nop_();dat <<= 1;}SDA = 1;_nop_();SCL = 1;_nop_();SCL = 0;_nop_();
}// 接收一个字节的数据
uchar receiveByte() {uchar i, dat = 0;SDA = 1;for (i = 0; i < 8; i++) {dat <<= 1;SCL = 1;_nop_();dat |= SDA;SCL = 0;_nop_();}return dat;
}// 写入DAC数值
void writeDAC(uchar dat) {startIIC();sendByte(0x90);  // 地址和写命令receiveByte();   // 接收应答sendByte(0x40);  // DAC通道A,并写入数据receiveByte();   // 接收应答sendByte(dat);   // DAC数据receiveByte();   // 接收应答stopIIC();
}// 读取ADC转换结果
uchar readADC() {uchar adcValue;startIIC();sendByte(0x91);   // 地址和读命令receiveByte();    // 接收应答adcValue = receiveByte();  // 读取ADC数据stopIIC();return adcValue;
}

4.2 OLED显示屏代码

以下是通过STC89C52控制IIC接口的OLED显示屏显示ADC数据实现代码。

#include <reg51.h>#define SCL P1_0   // IIC时钟线
#define SDA P1_1   // IIC数据线#define OLED_ADDR 0x78   // OLED显示屏的IIC地址// OLED显示屏初始化函数
void OLED_Init() {// 初始化OLED显示屏// ...// 发送初始化命令到OLED显示屏// ...
}// IIC总线开始信号
void IIC_Start() {SDA = 1;SCL = 1;SDA = 0;SCL = 0;
}// IIC总线停止信号
void IIC_Stop() {SDA = 0;SCL = 1;SDA = 1;
}// IIC总线发送一个字节的数据
void IIC_WriteByte(unsigned char dat) {unsigned char i;for (i = 0; i < 8; i++) {SCL = 0;if (dat & 0x80)SDA = 1;elseSDA = 0;SCL = 1;dat <<= 1;}SCL = 0;SDA = 1;SCL = 1;
}// 设置OLED显示屏光标位置
void OLED_SetPos(unsigned char x, unsigned char y) {IIC_Start();IIC_WriteByte(OLED_ADDR);IIC_WriteByte(0xb0 + y);IIC_WriteByte(((x & 0xf0) >> 4) | 0x10);IIC_WriteByte((x & 0x0f) | 0x01);IIC_Stop();
}// 在OLED显示屏上显示一个字符
void OLED_ShowChar(unsigned char x, unsigned char y, unsigned char ch) {unsigned char c = 0, i = 0;c = ch - ' ';   // 获取字符在字库中的偏移量if (x > 128 - 8 || y > 64 - 16)return;   // 超出屏幕范围,退出函数OLED_SetPos(x, y);for (i = 0; i < 8; i++) {IIC_Start();IIC_WriteByte(OLED_ADDR);IIC_WriteByte(0x40);IIC_WriteByte(*(OLED_CharSet + c * 16 + i));IIC_Stop();x++;}
}// 在OLED显示屏上显示字符串
void OLED_ShowString(unsigned char x, unsigned char y, unsigned char *str) {while (*str) {OLED_ShowChar(x, y, *str);x += 8;str++;}
}// ADC模拟数值转换为字符串
void ADC_ToString(unsigned int adcValue, unsigned char *str) {unsigned char i, j;unsigned int temp;temp = adcValue;for (i = 0; i < 4; i++) {str[i] = temp % 10 + '0';temp /= 10;}// 反转字符串i = 0;j = 3;while (i < j) {temp = str[i];str[i] = str[j];str[j] = temp;i++;j--;}str[4] = '\0';   // 字符串结束符
}// 主函数
void main() {unsigned int adcValue = 0;unsigned char str[5];// 初始化OLED显示屏OLED_Init();while (1) {// 读取ADC数据adcValue = ADC_Read();   // 假设使用的函数为ADC_Read(),用于读取ADC数据// 将ADC数据转换为字符串ADC_ToString(adcValue, str);// 在OLED显示屏上显示ADC数据OLED_ShowString(0, 0, "ADC Value:");OLED_ShowString(0, 2, str);}
}

4.3 主代码逻辑

#include <reg51.h>#define SCL P1_0    // IIC时钟线
#define SDA P1_1    // IIC数据线#define OLED_ADDR 0x78    // OLED显示屏的IIC地址
#define MQ4_PIN P2      // MQ4传感器连接的引脚sbit Buzzer = P3^0;    // 蜂鸣器控制引脚
sbit VentilationFan = P3^1;    // 换气扇控制引脚// 全局变量
unsigned int alarmThreshold = 100;    // 报警阈值,默认为100
unsigned int adcValue = 0;    // 保存ADC采集到的数值// IIC总线开始信号
void IIC_Start() {SDA = 1;SCL = 1;SDA = 0;SCL = 0;
}// IIC总线停止信号
void IIC_Stop() {SDA = 0;SCL = 1;SDA = 1;
}// IIC总线发送一个字节的数据
void IIC_WriteByte(unsigned char dat) {unsigned char i;for (i = 0; i < 8; i++) {SCL = 0;if (dat & 0x80)SDA = 1;elseSDA = 0;SCL = 1;dat <<= 1;}SCL = 0;SDA = 1;SCL = 1;
}// 设置OLED显示屏光标位置
void OLED_SetPos(unsigned char x, unsigned char y) {IIC_Start();IIC_WriteByte(OLED_ADDR);IIC_WriteByte(0xb0 + y);IIC_WriteByte(((x & 0xf0) >> 4) | 0x10);IIC_WriteByte((x & 0x0f) | 0x01);IIC_Stop();
}// 在OLED显示屏上显示一个字符
void OLED_ShowChar(unsigned char x, unsigned char y, unsigned char ch) {unsigned char c = 0, i = 0;c = ch - ' ';    // 获取字符在字库中的偏移量if (x > 128 - 8 || y > 64 - 16)return;    // 超出屏幕范围,退出函数OLED_SetPos(x, y);for (i = 0; i < 8; i++) {IIC_Start();IIC_WriteByte(OLED_ADDR);IIC_WriteByte(0x40);IIC_WriteByte(*(OLED_CharSet + c * 16 + i));IIC_Stop();x++;}
}// 在OLED显示屏上显示字符串
void OLED_ShowString(unsigned char x, unsigned char y, unsigned char *str) {while (*str) {OLED_ShowChar(x, y, *str);x += 8;str++;}
}// ADC转换函数
unsigned int ADC_Convert(unsigned char channel) {ADC_CONTR = ADC_POWER | ADC_START | channel | ADC_SPEED;_nop_();_nop_();_nop_();_nop_();while (!(ADC_CONTR & ADC_FLAG));ADC_CONTR &= ~ADC_FLAG;return (ADC_RES * 256 + ADC_RESL);
}// ADC模拟数值转换为字符串
void ADC_ToString(unsigned int adcValue, unsigned char *str) {unsigned char i, j;unsigned int temp;temp = adcValue;for (i = 0; i < 4; i++) {str[i] = temp % 10 + '0';temp /= 10;}// 反转字符串i = 0;j = 3;while (i < j) {temp = str[i];str[i] = str[j];str[j] = temp;i++;j--;}str[4] = '\0';    // 字符串结束符
} 主函数
void main() {unsigned char str[5];// 初始化OLED显示屏OLED_Init();// 设置初始报警阈值SetAlarmThreshold();while (1) {// 读取MQ4传感器的ADC数值adcValue = ADC_Convert(0);    // 假设MQ4传感器连接到ADC的通道0// 将ADC数值转换为字符串ADC_ToString(adcValue, str);// 在OLED显示屏上显示ADC数值OLED_ShowString(0, 0, "Gas Level:");OLED_ShowString(0, 2, str);// 判断是否触发报警if (adcValue > alarmThreshold) {// 触发报警ActivateAlarm();} else {// 取消报警DeactivateAlarm();}// 检测是否按下设置阈值的按键if (IsThresholdButtonPressed()) {// 设置报警阈值SetAlarmThreshold();}// 检测是否按下通风换气的按键if (IsVentilationButtonPressed()) {// 控制通风换气ControlVentilation();}}
}

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

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

相关文章

【JavaSE】运算符详解及与C语言中的区别

在文章的最后&#xff0c;总结了Java与C语言的某些不同点 目录 一、什么是运算符 二、算术运算符 1.基本四则运算符 2.增量运算符 3.自增/自减运算符/-- 三、关系运算符 四、逻辑运算符&#xff08;重点&#xff09; 1.逻辑与&& 2.逻辑或|| 3.逻辑非 4.补…

elasticsearch一些重要的配置参数

先看一下官网给我们提供的全部的参数配置项 官网地址 官方文档链接&#xff1a;注意版本是8.1Configuring Elasticsearch | Elasticsearch Guide [8.1] | Elastic​编辑https://www.elastic.co/guide/en/elasticsearch/reference/current/settings.html 重要&#xff08;基本…

零基础Linux_24(多线程)线程同步+条件变量+生产者消费模型_阻塞队列版

目录 1. 线程同步和生产者消费者模型 1.1 生产者消费者模型的概念 1.2 线程同步的概念 1.3 生产者消费者模型的优点 2. 线程同步的应用 2.1 条件变量的概念 2.2 条件变量操作接口 3. 生产者消费者模型_阻塞队列 3.1 前期代码&#xff08;轮廓&#xff09; 3.2 中期代…

phar反序列化学习

PHP反序列化常见的是使用unserilize()进行反序列化&#xff0c;除此之外还有其它的反序列化方法&#xff0c;不需要用到unserilize()。就是用到phar反序列化。 Phar phar文件 Phar是将php文件打包而成的一种压缩文档&#xff0c;类似于Java中的jar包。它有一个特性就是phar文…

Golang教程——配置环境,再探GoLand

文章目录 一、Go是什么&#xff1f;二、环境配置验证配置环境变量 三、安装开发者工具GoLand四、HelloGolang 一、Go是什么&#xff1f; Go&#xff08;也称为Golang&#xff09;是一种开源的编程语言&#xff0c;由Google开发并于2009年首次发布。Go语言旨在提供一种简单、高…

企业文件防泄密方法

企业文件防泄密方法 安企神数据防泄密系统下载使用 企业文件是企业的核心资产&#xff0c;其中可能包含大量的敏感信息&#xff0c;如客户资料、产品配方、财务数据等。一旦这些文件泄露&#xff0c;可能会给企业带来不可估量的损失。 然而&#xff0c;企业文件防泄密是确保…

Vue 3响应式对象: ref和reactive

目录 什么是响应式对象&#xff1f; Ref Reactive Ref vs Reactive 适用场景&#xff1a; 访问方式&#xff1a; 引用传递&#xff1a; 性能开销&#xff1a; 响应式对象优点 响应式对象缺点 总结 Vue 3作为一种流行的JavaScript框架&#xff0c;提供了响应式编程的…

4.编译多线程应用程序

在不同平台下使用多线程的程序编译时的编译选项设置如下图所示。 gcc下编译时我们会碰到两个选项-pthread和-lpthread&#xff0c;记住推荐使用-pthread而不是-lpthread&#xff0c;原因如下 -lpthread只是起到链接pthread库的作用&#xff1b;而-pthread选项除了会链接pthrea…

搭建微信小程序环境及项目结构介绍

一、注册 访问微信公众平台&#xff0c;将鼠标的光标置于账号分类中的小程序上&#xff0c; 点击‘查看详情’ 点击“前往注册” 下方也可以点击注册&#xff1a; 小程序注册页面&#xff1a; 步骤a:进入小程序注册页&#xff0c;根据指引填写信息和提交相应的资料&#x…

uni-app打包之如何生成自由证书

我是使用Android Studio来直接生成。超级简单 第一步 打开 Android Studio 找到下面图片 第二步 选 Android App Bund 然后Next 第三步 选择创建新的 第四步 填写对应的 信息 密码最好都是一样的 第五步 点击ok 即可创建成功。 uniapp打包时候勾选文件 &#xff08;如果公…

SpringBoot相比于Spring的优点(自动配置和依赖管理)

自动配置 例子见真章 我们先看一下我们Spring整合Druid的过程&#xff0c;以及我们使用SpringBoot整合Druid的过程我们就知道我们SpringBoot的好处了。 Spring方式 Spring方式分为两种&#xff0c;第一种就是我们使用xml进行整合&#xff0c;第二种就是使用我们注解进行简化…

国外怎么传大文件到国内,这款传输软件跨国企业必备

从国外传输文件到国内&#xff0c;这项任务常常充满了挑战。国际之间的距离、网络延迟、数据安全和文件大小限制等问题使得这个过程异常复杂。本文将深入剖析这些挑战&#xff0c;并说明一款优秀的跨国传输软件&#xff0c;如何能够成为解决这些问题的强有力工具。 国外传输文件…

Vue的安装

----------------------------------------------------前置---------------------------------------------------- 1.node.js的下载安装、缓存路径的设置 ①安装 ②设置npm prefix, cache 2.NODE_PATH、PATH ①系统变量中加 ②PATH中加 3.配置镜像源 -----------------------…

数据库数据恢复—Oracle数据库报错ORA-01110错误的数据恢复案例

Oracle数据库故障&#xff1a; 北京某公司一台运行oracle数据库的服务器&#xff0c;机房意外断电导致该服务器重启&#xff0c;重启后发现oracle数据库报错。该Oracle数据库没有备份。 Oracle数据库数据恢复过程&#xff1a; 1、北亚企安数据恢复工程师检查该oracle数据库的数…

单目标应用:进化场优化算法(Evolutionary Field Optimization,EFO)求解微电网优化MATLAB

一、微网系统运行优化模型 微电网优化模型介绍&#xff1a; 微电网多目标优化调度模型简介_IT猿手的博客-CSDN博客 二、进化场优化算法EFO 进化场优化算法&#xff08;Evolutionary Field Optimization&#xff0c;EFO&#xff09;由Baris Baykant Alagoz等人于2022年提出&…

sd模型测试之又纯又欲的Copax Anime XL动漫大模型

除了各种美女图外&#xff0c;AI绘画大模型中&#xff0c;最受欢迎的是动漫。 动漫又分好几种&#xff0c;幼儿向、热血向、成人向等。 之前我推荐了几个风格不同的动漫大模型&#xff0c;今天推荐一个成人向的动漫大模型&#xff1a;Copax Anime XL。 当然了&#xff0c;成…

iOS调试技巧——使用Python 自定义LLDB

一、类介绍 在使用Python 自定义LLDB之前&#xff0c;先了解一下LLDB的一些类型 SBTarget 正在被调试的程序SBProcess 和程序关联的具体的进程SBThread 执行的线程SBFrame 和线程关联的一个栈帧SBVariable 变量&#xff0c;寄存器或是一个表达式 一般情况下&#xff0c;我们…

Kafka生产问题总结及性能优化实践

Kafka可视化管理工具kafka-manager 安装及基本使用可参考&#xff1a;https://www.cnblogs.com/dadonggg/p/8205302.html 线上环境规划 JVM参数设置 kafka是scala语言开发&#xff0c;运行在JVM上&#xff0c;需要对JVM参数合理设置&#xff0c;参看JVM调优专题 修改bin/kaf…

geoserver去除tif影像黑色的背景的方法

geoserver加载某些tif文件的时候,tif文件本身有黑色的背景,怎么去掉呢? 只要在geoserver中设置就行。 处理方法: 1.新建数据源时要选择ImageMosaic数据源 2,设置"Output Transparent Color" 设置"Output Transparent Color"为黑色(000000),在…

一文详解汽车电子CAN总线

0.什么是CAN总线 CAN总线(控制器区域网络Controller Area Network)是一个中央网络系统&#xff0c;连接不同的电子控制单元(ECU)以及车辆中的其他设备。现在的汽车可以有100个ECU&#xff0c;因此CAN总线通信变得非常重要。 1.CAN总线流行的背景 集中式:CAN总线系统允许对连接…