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;//ADC
GPIO_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,實際被測氣體濃度增加200ppm
ppm = (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(); //復位DHT11
return 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夏普光學灰塵傳感器
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;//ADC
GPIO_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μs
int deltaTime = 40;//整個脈衝持續時間爲320μs。因此,我們還需再等待40μs
uint16_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);//置0
delay_us(9680);//需要脈寬比0.32ms/10ms的PWM信號驅動傳感器中的LED
Voltage = 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/m3
return 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; //PB5
GPIO_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.系統圖