一、系统所用到器件
器件 | 型号 |
烟雾浓度传感器 | MQ-2 |
温湿度传感器 | DHT11 |
空气质量传感器 | MQ-135 |
PM2.5粉尘传感器 | |
显示屏 | 四线OLED |
WiFi模块 | ESP8266-01s |
存储模块 | ACT24C04 |
声光报警模块 | 5V蜂鸣器、LED |
单片机 | STM32F103C8T6 |
二、系统实现功能
本次系统所实现的功能可用于室内环境气体监测和室外大气气体监测等项目中。本次系统主要实现的功能有,监控烟雾浓度、空气质量(co2浓度)、PM2.5烟雾浓度以及空气温湿度,并且将数据显示在OLED屏幕上,其设有可擦除存储器存储气体阈值,当气体浓度超过设定的对应气体阈值时,声光报警。
此项目主要设有自动模式、app控制模式、单片机手动控制模式等三种模式。模式的切换是通过四个按键进行控制切换。同时此项目设有WIFI联网模块,可通过ESP8266模块,把数据上传到机智云服务器上,通过机智云APP实时监控气体浓度。
实物图片
上图为自动控制页面所显示数据,在这个模式下会监测空气质量等数据,且当对应参数超过设定阈值时,蜂鸣器和LED会进行声光报警。
三、传感器功能实现(烟雾、co2、pm2.5)
本次试用的气体监测传感器分别为烟雾浓度检测传感器、二氧化碳浓度检测、pm2.5浓度检测传感器,这三个传感器都是通过单片机的模数转换来转换数据,通过将模拟量转换为数字量显示在OLED显示屏上。
#include "adc.h"
/***********************
函数名:ADC1_Init
函数功能:模数转换初始化
形参:void
返回值:void
函数说明:
烟雾浓度 ---PA5--ADC12_IN5
空气质量--PA4---ADC12_IN4
pm2.5----PA1
************************/
void ADC1_Init(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
ADC_InitTypeDef ADC_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);//使能GPIOA时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1,ENABLE);//使能ADC1
GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AIN;
GPIO_InitStructure.GPIO_Pin=GPIO_Pin_4|GPIO_Pin_5|GPIO_Pin_1;
GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
GPIO_Init(GPIOA,&GPIO_InitStructure);
ADC_DeInit(ADC1);
//PA7 作为脉冲输出引脚
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_7;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);
GP2Y_High;
ADC_DeInit(ADC1);
ADC_InitStructure.ADC_ContinuousConvMode=DISABLE;//连续转化模式设置
ADC_InitStructure.ADC_DataAlign=ADC_DataAlign_Right;//数据左对齐
ADC_InitStructure.ADC_ExternalTrigConv=ADC_ExternalTrigConv_None;//软件触发
ADC_InitStructure.ADC_Mode=ADC_Mode_Independent;//独立模式
ADC_InitStructure.ADC_NbrOfChannel=1;//通道数
ADC_InitStructure.ADC_ScanConvMode=DISABLE;//扫描模式禁止设置
ADC_Init(ADC1,&ADC_InitStructure);
//ADC_TempSensorVrefintCmd(ENABLE); //开启内部温度传感器
ADC_Cmd(ADC1,ENABLE);//使能指定ADC外设
ADC_ResetCalibration(ADC1);//使能复位校准
while(ADC_GetResetCalibrationStatus(ADC1));//等待复位校准结束
ADC_StartCalibration(ADC1);//开启AD校准
ADC_GetCalibrationStatus(ADC1);//等待AD校准结束
}
/***********************
函数名:get_Adc_Value
函数功能:换取采样值
形参:u8 ch
返回值:u16
函数说明:
ch 转换通道 ADC_SampleTime_239Cycles5采样时间值 采样时间选择最长
1 采样通道数量
烟雾浓度 ---PA5--ADC12_IN5
空气质量--PA4---ADC12_IN4
************************/
u16 get_Adc_Value(u8 ch)//通道一采样值
{
ADC_RegularChannelConfig(ADC1,ch,1,ADC_SampleTime_239Cycles5);//ADC匹配通道
ADC_SoftwareStartConvCmd(ADC1,ENABLE);//ADC软件转换启动
while(!ADC_GetFlagStatus(ADC1,ADC_FLAG_EOC));//等待采样结束
return ADC_GetConversionValue(ADC1);//放回采样值
}
/***********************
函数名:Get_smog_Value
函数功能:烟雾浓度
形参:void
返回值:void
函数说明:
烟雾浓度 ---PA5--ADC12_IN5---0x05
空气质量--PA4---ADC12_IN4--0x04
************************/
u8 smog_value,air_value;
u8 buf3[20];
u8 buf4[20];
u8 smog_flag=0;
u8 air_flag=0;
void Get_smog_Value(void)
{
smog_value=0;
u16 Rec=0;
Rec=get_Adc_Value(0x05);//获取采样数值
smog_value = ((100 * Rec)/4096);//烟雾浓度百分比
sprintf((char *)buf3,"smog:%ddB/m",smog_value);
if(smog_flag ==0)
{
Oled_ShowAll(4,0,buf3);//显示中英字符串
}
}
/***********************
函数名:Get_mq135_Value
函数功能:空气质量
形参:void
返回值:void
函数说明:
烟雾浓度 ---PA5--ADC12_IN5---0x05
空气质量--PA4---ADC12_IN4--0x04
************************/
void Get_mq135_Value(void)
{
air_value=0;
u16 Rec=0;
Rec=get_Adc_Value(0x04);//获取空气采样数值
air_value =((100 * Rec)/4096);//空气强度百分比
if(air_flag==0)
{
sprintf((char *)buf4,"air:%d%%",air_value);
Oled_ShowAll(4,80,buf4);//显示中英字符串
}
}
u16 Get_Adc_Average(u8 ch,u8 times)
{
u32 temp_val=0;
u8 t;
for(t=0;t<times;t++)
{
temp_val+=get_Adc_Value(ch);
delay_ms(5);
}
return temp_val/times;
}
/***********************
函数名:Get_PM2.5_Value
函数功能:PM2.5
形参:void
返回值:void
函数说明:
烟雾浓度 ---PA5--ADC12_IN5---0x05
空气质量--PA4---ADC12_IN4--0x04
PM2.5 PA1
************************/
float GetGP2Y(void)
{
u32 AD_PM;
double pm;
GP2Y_Low;//LED=0;
delay_us(280);
AD_PM = get_Adc_Value(0x01);
delay_us(40);
GP2Y_High;//LED=1;
delay_us(9680);
pm = 0.07*AD_PM-0.1; //转换公式
// Oled_ShowAll(2,0,pm);//显示中英字符串
// printf("%d\n",pm);
return pm;
}
u16 Get_GP2Y_Average(u8 times)
{
u32 pm_val=0;
u8 t;
for(t=0;t<times;t++)
{
pm_val+=GetGP2Y();
delay_ms(1);
}
return pm_val/times;
}
u8 buf_1[20];
u8 h_flag=0;
float pm_value;
void Get_pm_value(void)
{
pm_value = Get_GP2Y_Average(20);
if(h_flag == 0){
sprintf((char *)buf_1,"PM2.5:%.1f",pm_value);
Oled_ShowAll(6,0,buf_1);//显示中英字符串
}
}
#ifndef _ADC_H
#define _ADC_H
#include "includes.h"
#define GP2Y_High GPIO_SetBits(GPIOA,GPIO_Pin_7);
#define GP2Y_Low GPIO_ResetBits(GPIOA,GPIO_Pin_7);
extern u8 smog_value,air_value;
extern u8 smog_flag ,air_flag;
extern u8 h_flag;
extern float pm_value;
void ADC1_Init(void);
u16 get_Adc_Value(u8 ch);//通道一采样值
void Get_smog_Value(void);
void Get_mq135_Value(void);
void Get_pm_value(void);
#endif
其中里面的OLED显示代码我没写上,借鉴的同学可以替换自己的oled显示方式。
四、PCB演示