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

一、前言

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

单片机选择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 int

sbit 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;
        else
            SDA = 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;
        else
            SDA = 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();
        }
    }
}

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

kuaishou web端did注册激活 学习记录

快手web端 did 注册激活的流程大概如下&#xff1a; 1.访问web端的接口&#xff0c;主动触发滑块&#xff0c;拿到滑块信息 2.然后滑块验证did 获取captchaToken 3.携带captchaToken访问接口 4.最后校验web端的did 是否激活 最后激活以后的效果如下&#xff1a; 经过测试&…

我是这样保持精力充沛的

精力管理就好比是计算机的内存清理&#xff0c;你以为关掉一些程序就行了&#xff0c;结果你还是卡成翔。 我的现状 雷猴啊&#xff0c;我是一个临期程序员。打过几年工&#xff0c;被好几个同事问过我为什么精力这么旺盛。 这两年我大多数情况都是早上8点前就到公司*(原本9点上…

《红蓝攻防对抗实战》三.内网探测协议出网之HTTP/HTTPS协议探测出网

目录 一. 在 Windows 操作系统中探测 HTTP/HTTPS 出网 1. Bitsadmin 命令 2.Certuil 命令 2.Linux系统探测HTTP/HTTPS出网 1.Curl命令 2.Wget命令 对目标服务器探测 HTTP/HTTPS 是否出网时&#xff0c;要根据目标系统类型执行命令&#xff0c;不同类型的操作系统使用的探…

一文说尽零售数据分析指标体系

零售的本质业务模式是通过在各种渠道上吸引客户来购买我们的商品来实现盈利&#xff0c;其实就是客户-渠道-商品&#xff0c;也就是我们常说的“人、场、货”&#xff0c;除此之外还有供应链、财务等起到重要的辅助作用。因此如果要构建起系统化的零售数据分析指标体系&#xf…

单片机设计基于STM32的空气净化器设计

**单片机设计介绍&#xff0c;1615[毕设课设]基于STM32的空气净化器设计 文章目录 一 概要二、功能设计设计思路 三、 软件设计原理图pcb设计图 五、 程序六、 文章目录 一 概要 此设计资料主要包含原理图、PCB、源程序、元器件清等资料&#xff0c; 二、功能设计 设计思路 …

[AutoSAR系列] 1.3 AutoSar 架构

依AutoSAR及经验辛苦整理&#xff0c;原创保护&#xff0c;禁止转载。 专栏 《深入浅出AutoSAR》 1. 整体架构 ​ 图片来源&#xff1a; AutoSar 官网 从官往图中可以看出autosar作为汽车ECU软件架构&#xff0c;是通过分层来实现软硬件隔离。就像大多数操作系统一样&#xff…

深度学习_5_模型拟合_梯度下降原理

需求: 想要找到一条直线&#xff0c;能更好的拟合这一些点 如何确定上述直线就是最优解呢&#xff1f; 由计算机算出所有点与我们拟合直线的误差&#xff0c;常见的是均方误差 例如&#xff1a;P1与直线之间的误差为e1 将P1坐标带入直线并求误差得&#xff1a; 推广到所有点&a…

Pico示波器 汽车振动异响(NVH)解决方案

汽车振动异响故障可能有多个潜在原因&#xff0c;包括发动机、传动系统、悬挂系统、制动系统等等。技师需要对汽车各个方面有全面的了解&#xff0c;才能更好地进行故障排查。 振动和异响可能由多个因素引起。例如&#xff0c;可能是零部件损坏、松脱、磨损或者不正确安装。这…

某全球领先的晶圆代工企业:替代FTP实现大规模文件的高效传输

全球领先的集成电路晶圆代工企业之一 该企业不仅是全球领先的集成电路晶圆代工企业之一&#xff0c;也是中国内地技术最先进、配套最完善、规模最大、跨国经营的集成电路制造企业集团。主要业务是根据客户本身或第三者的集成电路设计&#xff0c;为客户制造集成电路芯片&#…

Opencv-图像插值与LUT查找表

图像像素的比较 白色是255&#xff0c;黑色是0 min(InputArray src1,InputArray src2,OutputArray dst) max(InputArray src1,InputArray src2,OutpurArray dstsrc1:第一个图像矩阵&#xff0c;通道数任意src2&#xff1a;第二个图像矩阵&#xff0c;尺寸和通道数以及数据类型…

面试题:Java 类加载过程是怎么样的?

首先&#xff0c;我们编写好的Java代码&#xff0c;经过编译变成.class文件&#xff0c;然后类加载器把.class字节码文件加载到JVM中&#xff0c;接着执行我们的代码&#xff0c;最后将类卸载出JVM。而从类加载到虚拟机到卸载出虚拟机的这一整个生命周期总共可以分为7个步骤&am…

亚马逊注册账号时老是显示内部错误

最近你们是否遇到注册亚马逊账号时一直遇到"内部错误"的情况&#xff1f;&#xff0c;这可能是由多种原因引起的。以下是一些可能有助于解决这个问题的步骤&#xff1a; 1、清除缓存和Cookie&#xff1a;有时浏览器缓存和Cookie中的问题可能导致网站错误。可以试试清…

高速公路安全监测预警系统的功能优势

实时监测和预警&#xff1a;高速公路安全监测预警系统能够实时监测高速公路的路基、桥梁、隧道等结构的位移变化情况&#xff0c;并通过数据分析及时发出预警&#xff0c;有效预防和减少交通事故的发生。 高精度测量&#xff1a;高速公路安全监测预警系统能够实现高精度的位移…

2023CSPS 种树 —— 二分+前缀和

This way 题意&#xff1a; 一开始以为是水题&#xff0c;敲了一个二分贪心检查的代码&#xff0c;20分。发现从根往某个节点x走的时候&#xff0c;一路走来的子树上的节点到已栽树的节点的距离会变短&#xff0c;那么并不能按照初始情况贪心。 于是就想着检查时候用线段树…

Docker系列---【mysql容器手动停止后,重启服务器,mysql容器被删掉了,如何恢复mysql数据?】...

mysql容器手动停止后&#xff0c;重启服务器&#xff0c;mysql容器被删掉了&#xff0c;如何恢复mysql数据&#xff1f; 1.问题描述 为了快速搭建数据库&#xff0c;我使用了docker搭建数据库&#xff0c;由于服务器资源紧张&#xff0c;我想先把mysql容器停掉&#xff0c;启动…

讯飞输入法13.0发布,推出行业首款生成式AI输入法

&#x1f989; AI新闻 &#x1f680; 讯飞输入法13.0发布&#xff0c;推出行业首款生成式AI输入法 摘要&#xff1a;科大讯飞在2023年全球开发者节上发布了全新讯飞输入法13.0版本&#xff0c;其中最大的亮点是推出了行业首款生成式AI输入法。这次升级将生成式AI能力融入输入…

Maven 生命周期clean default size含义

clean 负责清理工作&#xff0c;清理上一次项目构建产生的一些文件&#xff0c;如编译后的字节码文件&#xff0c;打包后的jar包文件 default 整一个项目构建的核心工作&#xff0c;如编译&#xff0c;测试&#xff0c;打包&#xff0c;安装&#xff0c;部署等等 size 生成报告…

《健康界》深度报道:阿基米德医疗设备精细化管理,助力降本增效

“给我一个支点&#xff0c;我就能撬动整个地球。”古希腊著名物理学家阿基米德两千多年前的这句“狂言”&#xff0c;让杠杆原理广为流传并被普遍接受&#xff0c;成为力学的基本原理之一。 在今天的苏州&#xff0c;有一家叫苏州阿基米德网络科技有限公司&#xff08;下称阿…

opencv dnn模块 示例(19) 目标检测 object_detection 之 yolox

文章目录 0、前言1、网络介绍1.1、输入1.2、Backbone主干网络1.3、Neck1.4、Prediction预测输出1.4.1、Decoupled Head解耦头1.4.2、Anchor-Free1.4.3、标签分配1.4.4、Loss计算 1.5、Yolox-s、l、m、x系列1.6、轻量级网络研究1.6.1、轻量级网络1.6.2、数据增强的优缺点 1.7、Y…