1.功能
STM32测量MQ4、灰尘传感器、DHT11温湿度传感器,并在TFT上显示,超过浓度阈值蜂鸣器报警。
使用普中STM32F103ZET6开发板+2.8寸触摸屏。
2.MQ4天然气传感器
MQ-4传感器简介:
MQ- 4气体传感器所使用的气敏材料是在清洁空气中电导率较低的二氧化锡(SnO2)。当传感器所处环境中存在可燃气体时,传感器的电导率随空气中可燃气体浓度的增加而增大。使用简单的电路即可将电导率的变化转换为与该气体浓度相对应的输出信号。 MQ-4气体传感器对甲烷的灵敏度高,对丙烷、丁烷也有较好的灵敏度。这种传感器可检测多种可燃性气体,特别是天然气,是一款适合多种应用的低成本传感器。
模块应用:
适用于家庭或工厂的甲烷气体,天然气等监测装置,可测试天然气、甲烷 300 to 10000ppm;
模块特色:
1、采用优质双面板设计,具有电源指示和TTL信号输出指示;
2、具有DO开关信号(TTL)输出和AO模拟信号输出;
3、TTL输出有效信号为低电平。(当输出低电平时信号灯亮,可直接接单片机或继电器模块)
4、模拟量输出的电压,浓度越高电压越高。
5、对甲烷、天然气检测有较好的灵敏度。
6、有四个螺丝孔便于定位;
7、产品外形尺寸:32(L)*20(W)*22(H)
8、具有长期的使用寿命和可靠的稳定性
9、快速的响应恢复特性
电气性能:
输入电压:DC5V 功耗(电流):150mA
DO输出:TTL数字量0和1(0.1和5V)
AO输出:0.1-0.3V(相对无污染),最高浓度电压4V左右
特别提醒:传感器通电后,需要预热20S左右,测量的数据才稳定,传感器发热属于正常现象,因为内部有电热丝,如果烫手就不正常了。
接线方式:
1、VCC:接电源正极(5V)
2、GND:接电源负极
3、DO:TTL开关信号输出
4、AO:模拟信号输出
关键代码及说明:
void MQ4_ADC_init()
{GPIO_InitTypeDef GPIO_InitStructure;ADC_InitTypeDef ADC_InitStructure;RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_AFIO|RCC_APB2Periph_ADC2,ENABLE);RCC_ADCCLKConfig(RCC_PCLK2_Div6);//12M 最大14M 设置ADC时钟(ADCCLK)ADC_DeInit(ADC2);GPIO_InitStructure.GPIO_Pin=GPIO_Pin_2;//ADCGPIO_InitStructure.GPIO_Mode=GPIO_Mode_AIN; //模拟输入GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;GPIO_Init(GPIOA,&GPIO_InitStructure);ADC_InitStructure.ADC_Mode = ADC_Mode_Independent; ADC_InitStructure.ADC_ScanConvMode = DISABLE; ADC_InitStructure.ADC_ContinuousConvMode = DISABLE; ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None; ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right; ADC_InitStructure.ADC_NbrOfChannel = 2; ADC_Init(ADC2, &ADC_InitStructure);//设置指定ADC的规则组通道,设置它们的转化顺序和采样时间
// ADC_RegularChannelConfig(ADC1,ADC_Channel_1,1,ADC_SampleTime_239Cycles5);//内部温度传感器是在ADC1通道16的。ADC_RegularChannelConfig(ADC2,ADC_Channel_2,1,ADC_SampleTime_239Cycles5);
// ADC_TempSensorVrefintCmd(ENABLE);//打开内部温度传感器使能ADC_Cmd(ADC2,ENABLE); ADC_ResetCalibration(ADC2);//重置指定的ADC的校准寄存器while(ADC_GetResetCalibrationStatus(ADC2));//获取ADC重置校准寄存器的状态ADC_StartCalibration(ADC2);//开始指定ADC的校准状态while(ADC_GetCalibrationStatus(ADC2));//获取指定ADC的校准程序ADC_SoftwareStartConvCmd(ADC2, ENABLE);//使能或者失能指定的ADC的软件转换启动功能
}
u16 GetMQ4Value(void)
{uint16_t ADCVal;float Voltage;uint16_t ppm;ADC_SoftwareStartConvCmd(ADC2, ENABLE);while(!ADC_GetFlagStatus(ADC2, ADC_FLAG_EOC ));ADCVal = ADC_GetConversionValue(ADC2);Voltage = ADCVal * 3.3 / 4096;//无天然气的环境下,实测AOUT端的电压为0.5V,当检测到天然气时,电压每升高0.1V,实际被测气体浓度增加200ppmppm = (Voltage - 0.5) / 0.1 * 200;return ppm;//return ADCVal;
}
int Read_MQ4_DOUT_Data()
{int status;status = GPIO_ReadInputDataBit(GPIOC, GPIO_Pin_3);return status;
}
3.DHT11温湿度传感器
//初始化DHT11的IO口 DQ 同时检测DHT11的存在
//返回1:不存在
//返回0:存在
u8 DHT11_Init(void)
{ GPIO_InitTypeDef GPIO_InitStructure;RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOG, ENABLE); //使能PG端口时钟GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11; //PG11端口配置GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; //推挽输出GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_Init(GPIOG, &GPIO_InitStructure); //初始化IO口GPIO_SetBits(GPIOG,GPIO_Pin_11); //PG11 输出高DHT11_Rst(); //复位DHT11return DHT11_Check();//等待DHT11的回应
}
//从DHT11读取一次数据
//temp:温度值(范围:0~50°)
//humi:湿度值(范围:20%~90%)
//返回值:0,正常;1,读取失败
u8 DHT11_Read_Data(u16 *temp,u16 *humi)
{ float buf[5];u8 i;DHT11_Rst();if(DHT11_Check()==0){for(i=0;i<5;i++)//读取40位数据{buf[i]=DHT11_Read_Byte();}if((buf[0]+buf[1]+buf[2]+buf[3])==buf[4]){*humi=buf[0];*temp=buf[2];}}else return 1;return 0;
}
4.GP2Y1014AU0F夏普光学灰尘传感器
参考链接:https://detail.tmall.com/item.htm?spm=a230r.1.14.4.1a81Dr&id=544189174002&cm_id=140105335569ed55e27b&abbucket=9
http://blog.sina.com.cn/s/blog_72359bde010191m0.html
添加一个150ohm的电阻和一个220uF的电容,接线如下图:
void GP2Y_ADC_init()
{GPIO_InitTypeDef GPIO_InitStructure;ADC_InitTypeDef ADC_InitStructure;RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOF|RCC_APB2Periph_AFIO|RCC_APB2Periph_ADC3,ENABLE);RCC_ADCCLKConfig(RCC_PCLK2_Div6);//12M 最大14M 设置ADC时钟(ADCCLK)ADC_DeInit(ADC3);GPIO_InitStructure.GPIO_Pin=GPIO_Pin_6;//ADCGPIO_InitStructure.GPIO_Mode=GPIO_Mode_AIN; //模拟输入GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;GPIO_Init(GPIOF,&GPIO_InitStructure);ADC_InitStructure.ADC_Mode = ADC_Mode_Independent; ADC_InitStructure.ADC_ScanConvMode = DISABLE; ADC_InitStructure.ADC_ContinuousConvMode = DISABLE; ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None; ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right; ADC_InitStructure.ADC_NbrOfChannel = 4; ADC_Init(ADC3, &ADC_InitStructure);//设置指定ADC的规则组通道,设置它们的转化顺序和采样时间
// ADC_RegularChannelConfig(ADC1,ADC_Channel_1,1,ADC_SampleTime_239Cycles5);//内部温度传感器是在ADC1通道16的。ADC_RegularChannelConfig(ADC3,ADC_Channel_4,1,ADC_SampleTime_239Cycles5);
// ADC_TempSensorVrefintCmd(ENABLE);//打开内部温度传感器使能ADC_Cmd(ADC3,ENABLE); ADC_ResetCalibration(ADC3);//重置指定的ADC的校准寄存器while(ADC_GetResetCalibrationStatus(ADC3));//获取ADC重置校准寄存器的状态ADC_StartCalibration(ADC3);//开始指定ADC的校准状态while(ADC_GetCalibrationStatus(ADC3));//获取指定ADC的校准程序ADC_SoftwareStartConvCmd(ADC3, ENABLE);//使能或者失能指定的ADC的软件转换启动功能GPIO_SetBits(GPIOC, GPIO_Pin_2);//置1
u16 GetGP2YAverageValue(u8 times)
{u32 temp_val=0;u8 t;for(t=0;t<times;t++){temp_val+=GetGP2YSingleValue();}return temp_val/times;
}u16 GetGP2YSingleValue(void)
{int samplingTime = 280;//等待LED开启的时间是280μsint deltaTime = 40;//整个脉冲持续时间为320μs。因此,我们还需再等待40μsuint16_t ADCVal;float dustVal = 0;float Voltage;GPIO_ResetBits(GPIOC, GPIO_Pin_2);//置1 开启内部LED ????????delay_us(samplingTime); // 开启LED后的280us的等待时间ADC_SoftwareStartConvCmd(ADC3, ENABLE);while(!ADC_GetFlagStatus(ADC3, ADC_FLAG_EOC));ADCVal = ADC_GetConversionValue(ADC3);delay_us(40);GPIO_SetBits(GPIOC, GPIO_Pin_2);//置0delay_us(9680);//需要脉宽比0.32ms/10ms的PWM信号驱动传感器中的LEDVoltage = ADCVal * 3.3 / 4096;dustVal = (Voltage + 1) * 1000 / 10;//*1000作用是将单位转换为ug/m3
// if(ADCVal > 36.455)
// dustVal = ((float)(ADCVal / 1024.0) - 0.0356) * 120000 * 0.035;
// dustVal = 0.17 * ADCVal - 0.1;
// dustVal = ADCVal;
// return dustVal; // mg/m3return dustVal;
}
放大后:
5.蜂鸣器报警模块
使用无源蜂鸣器模块
关键代码如下,其中有驱动蜂鸣器发出救护车或者电动车报警的声音:
#include "beep.h"
#include "lcd_driver.h"
#include "systick.h"
#include "public.h"
#include "gui.h"
#define TEMPALARMVALUEDOWN 18//温度报警上下限
#define TEMPALARMVALUEUP 30#define HUMIALARMVALUEDOWN 10//湿度报警上下限
#define HUMIALARMVALUEUP 60#define MQ4ALARMVALUEUP 1000//天然气浓度报警上限#define DUSTALARMVALUEUP 400//粉尘浓度报警上限#define BEEPALARM GPIO_SetBits(GPIOB, GPIO_Pin_5)//置1
#define BEEPNOALARM GPIO_ResetBits(GPIOB, GPIO_Pin_5)//置0
int AlarmFlag[4] = {0, 0, 0, 0};
void Beep_GPIO_Init()//PB5
{GPIO_InitTypeDef GPIO_InitStructure;/****************************LED*******************************//* GPIOC Periph clock enable */RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);/* Configure PC2 and PC3 in output pushpull mode */GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5; //PB5GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;GPIO_Init(GPIOB, &GPIO_InitStructure);
}void Temp_Humi_Alarm(u8 temp, u8 humi)//当温度不在18-28度时,蜂鸣器报警;当湿度不在30%-60%时,蜂鸣器报警{if((temp < TEMPALARMVALUEDOWN) || (temp > TEMPALARMVALUEUP)){AlarmFlag[0] = 1;GUI_Show12ASCII(10,280,"temperature alarm!",YELLOW,BLACK);sound1();
// BEEPALARM;}else{AlarmFlag[0] = 0;GUI_Show12ASCII(10,280," ",YELLOW,BLACK);BEEPNOALARM;}if((humi < HUMIALARMVALUEDOWN) || (humi > HUMIALARMVALUEUP)){AlarmFlag[1] = 1;GUI_Show12ASCII(10,300,"humidity alarm!",YELLOW,BLACK);sound2();
// BEEPALARM;}else{AlarmFlag[1] = 0;GUI_Show12ASCII(10,300," ",YELLOW,BLACK);BEEPNOALARM;}}void MQ4_Alarm(u16 MQ4Value){if(MQ4Value > MQ4ALARMVALUEUP){AlarmFlag[2] = 1;GUI_Show12ASCII(10,320,"MQ4 gas alarm!",YELLOW,BLACK);sound3();}else{AlarmFlag[2] = 0;GUI_Show12ASCII(10,320," ",YELLOW,BLACK);
// TFT_ClearOneLine(260, BLACK);BEEPNOALARM;}}void Dust_Alarm(u16 dustValue)//当浓度不在0-400内时,蜂鸣器报警{if(dustValue > DUSTALARMVALUEUP){AlarmFlag[3] = 1;GUI_Show12ASCII(10,340,"dust alarm!",YELLOW,BLACK);sound4();}else{AlarmFlag[3] = 0;GUI_Show12ASCII(10,340," ",YELLOW,BLACK);BEEPNOALARM;}}/*******************************************************************************
* 函 数 名 : sound1
* 函数功能 : 蜂鸣器报警函数
* 输 入 : 无
* 输 出 : 无
*******************************************************************************/
void sound1() //救护车报警
{u32 i=1000;while(i--) //产生一段时间的PWM波,使蜂鸣器发声{GPIO_SetBits(GPIOB,GPIO_Pin_5); //IO口输出高电平delay(i);GPIO_ResetBits(GPIOB,GPIO_Pin_5); //IO口输出低电平delay(i--);}
}/*******************************************************************************
* 函 数 名 : sound2
* 函数功能 : 蜂鸣器报警函数 通过改变频率控制声音变化
* 输 入 : 无
* 输 出 : 无
*******************************************************************************/
void sound2() //电动车报警
{u32 i=2000;while(i--) //产生一段时间的PWM波,使蜂鸣器发声{GPIO_SetBits(GPIOB,GPIO_Pin_5); //IO口输出高电平delay(i);GPIO_ResetBits(GPIOB,GPIO_Pin_5); //IO口输出低电平delay(i--);}
}/*******************************************************************************
* 函 数 名 : sound2
* 函数功能 : 蜂鸣器报警函数 通过改变频率控制声音变化
* 输 入 : 无
* 输 出 : 无
*******************************************************************************/
void sound3() //电动车报警
{u32 i=3000;while(i--) //产生一段时间的PWM波,使蜂鸣器发声{GPIO_SetBits(GPIOB,GPIO_Pin_5); //IO口输出高电平delay(i);GPIO_ResetBits(GPIOB,GPIO_Pin_5); //IO口输出低电平delay(i--);}
}/*******************************************************************************
* 函 数 名 : sound2
* 函数功能 : 蜂鸣器报警函数 通过改变频率控制声音变化
* 输 入 : 无
* 输 出 : 无
*******************************************************************************/
void sound4()
{u32 i=4000;while(i--) //产生一段时间的PWM波,使蜂鸣器发声{GPIO_SetBits(GPIOB,GPIO_Pin_5); //IO口输出高电平delay(i);GPIO_ResetBits(GPIOB,GPIO_Pin_5); //IO口输出低电平delay(i--);}
}
6.系统图
代码