MQx系列环境检测模块

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档

文章目录


前言

本文主要介绍利用CubeMX配置STM32F4系列芯片读取MQ2和MQ135模块模拟量数据,仅用于学习

注:MQx系列模块需要大概20s预热时间


一、CubeMX配置

1、新建工程,配置时钟和时钟树,这里时钟主频配置为168Mhz,相关配置前面有讲到就不过多叙述了

2、MQx模块有模拟量输出和数字量输出两选择,前者主要用于可视化的界面显示,后者主要用于预警之类,该文为采集模拟量电压,因此需要配置相关ADC通道用于采集模拟量电压,这里配置 了ADC1的通道1和通道2,分别用于MQ2和MQ135模块模拟输出电压的采集。相关配置如下:

 注意:这里ADC的采集频率最好不超过36Mhz,这里由于时钟主频为168Mhz,且ADC1时钟挂在APB2总线上(查看时钟树可以看到PCLK2为84Mhz),因此这里ADC最高采集频率需要通过APB2总线时钟进行4分频也就是(21Mhz),如需获得更高的ADC采集频率可以更改时钟主频为36Mhz的倍数通过倍分频来获得最高的采集频率,但时钟主频降低了,整体代码的执行时间将会变得更长。更加具体的ADC配置界面可以去观看Z小旋的CubeMX系列教程。(记得使能ADC采集中断)

3、多通道的ADC采集我们通常会打开DMA来搬运我们的原始数据,以此来提高我们的数据采集处理速率,相关DMA配置如下:

二、代码

1、模块.c文件

#include "mqx.h"

uint8_t Init_flag=0;
uint8_t ADC_Flag=0;
uint32_t ADC_DMA_Value[100]={0};
float MQ2_PPM;      //烟雾浓度
float MQ135_PPM;    //空气质量	PPM:0~100为优,101~140良,141~340中,341以上差

//获取环境PPM值
void GetPPM(void)
{
	uint8_t i;
	float MQ2_AO;
	float MQ135_AO;
  //这里初始化为0很重要!!!
	uint32_t ADC_MQ2=0;   
	uint32_t ADC_MQ135=0;
	//模块初始化
//	if(!Init_flag){
//		MQ_Init();
//		Init_flag=1;
//	}
	//50次均值滤波
	for(i=0;i<50;i++){
		ADC_MQ2 += ADC_DMA_Value[2*i];
		ADC_MQ135 += ADC_DMA_Value[2*i+1];
	}
	MQ2_AO = ADC_MQ2/50*3.3f/4096;
	MQ135_AO = ADC_MQ135/50*3.3f/4096;
	
	//公式由MATLAB仿真
	MQ2_PPM = pow((11.5428f * 35.904f * MQ2_AO)/(25.5f-1* MQ2_AO),(1.0f/0.6549f));	
	MQ135_PPM = pow((3.488f*10*MQ135_AO)/(5-MQ135_AO),(1.0f/0.3203f));
	memset(ADC_DMA_Value,0x00,sizeof(ADC_DMA_Value)); //清空数据采集数组
	//HAL_Delay(1000);
}

//预警
void Warning()
{
	//有害气体浓度大于设定值蜂鸣器预警并开启通风扇	
	if(MQ135_PPM>28)
	{
		BEEP_ON;  
			Relay_ON;
	}
	//检测到明火断掉总电源
	else if(HAL_GPIO_ReadPin(GPIOD, GPIO_PIN_13)==GPIO_PIN_RESET){  //检测到火焰引脚电平为低	
		Outage_ON;
	}
	else{
		BEEP_OFF;
		Relay_OFF;
		Outage_OFF;
	}
}

模块上电需要预热20s左右
//void MQ_Init(void){
//	//HAL_Delay(20000);
//}

//ADC_DMA传输完成中断回调
void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef* hadc)
{
	UNUSED(hadc);
	ADC_Flag++;
	if(ADC_Flag==100){
		//HAL_ADC_Stop_DMA(&hadc1);
		GetPPM();
		ADC_Flag=0;
	}
}

//下降沿外部中断回调
//void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
//{
//	UNUSED(GPIO_Pin);
//	if(HAL_GPIO_ReadPin(GPIOE,GPIO_PIN_9)==0){	
//		HAL_Delay(30);
//		if(HAL_GPIO_ReadPin(GPIOE,GPIO_PIN_9)==0){
//			GetPPM();
//		}
//	}
//	__HAL_GPIO_EXTI_CLEAR_IT(GPIO_Pin);
//}

2、模块.h文件

#ifndef __MQX_H
#define __MQX_H

#include "stm32f4xx_hal.h"
#include <math.h>
#include <string.h>
#include <stdio.h>

#define  BEEP_ON     HAL_GPIO_WritePin(GPIOA, GPIO_PIN_5, GPIO_PIN_RESET);
#define  BEEP_OFF    HAL_GPIO_WritePin(GPIOA, GPIO_PIN_5, GPIO_PIN_SET);
#define  Relay_ON    HAL_GPIO_WritePin(GPIOD, GPIO_PIN_14, GPIO_PIN_SET);
#define  Relay_OFF   HAL_GPIO_WritePin(GPIOD, GPIO_PIN_14, GPIO_PIN_RESET);
#define  Outage_OFF  HAL_GPIO_WritePin(GPIOA, GPIO_PIN_7, GPIO_PIN_RESET);
#define  Outage_ON   HAL_GPIO_WritePin(GPIOA, GPIO_PIN_7, GPIO_PIN_SET);

extern ADC_HandleTypeDef hadc1;

void GetPPM(void);
void MQ_Init(void);
void Warning(void);


#endif

最后记得在main函数里加一条开启DMA传输指令

HAL_ADC_Start_DMA(&hadc1,(uint32_t *)ADC_DMA_Value,100);//开启ADC_DMA传输

总结

该代码适用于MQx系列的各种模块,有差别的地方就在于电压与ppm之间转换的公式,这里可以网上查找或者使用matlab根据模块数据手册自行建模拟合,最后,本文若有错误的地方,欢迎大家在评论区指出。

注:本文仅用于学习,若有侵权,告知必删。

评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值