智能家居安防系统

一,前期准备

(一)硬件准备

  • 火焰传感器模块
  • 烟雾传感器模块(MQ-2)
  • 电机驱动(tb6612)
  • 电机+风扇叶(PWM驱动)
  • 温湿度传感器(DHT11)
  • 蜂鸣器
  • 人体红外传感器模块(SR501)
  • STM32F103C8T6
  • ST--LINK
  • USB转串口
  • OLED四针(I2C通信)

(二)软件准备

keil,TRAW

二,模块讲解

温湿度模块:

温湿度模块有两种通信方式

  • 数字通信(DO)
  • 模拟通信(AO)

数字通信:当有火焰时火焰传感器传输低电平,当无火焰时传感器传输高电平(传感器敏感度由模块上的电阻器决定)

模拟通信:通过ADC转换,将火焰大小通过ADC转换成数字数据

烟雾模块:

烟雾模块和温湿度模块一样有两种通信方式

  • 数字通信(DO)
  • 模拟通信(AO)

数字通信:当有烟雾时烟雾传感器传输低电平,当无烟雾时传感器传输高电平(传感器敏感度由模块上的电阻器决定)

模拟通信:通过ADC转换,将烟雾浓度大小通过ADC转换成数字数据

烟雾传感器和火焰传感器通信方式一样,但烟雾模块得上电1`2 分钟后才能正常使用

温湿度模块

温湿度模块通信方式是单总线串行通信方式,总线为上拉电阻,温湿度模块发送一次数据大小为40bit

  • 8bit温度整数数据
  • 8bit温度小数数据
  • 8bit湿度整数数据
  • 8bit湿度小数数据
  • 8bit校验数据数据
  • 8bit校验数据数据==8bit温度整数数据+8bit温度小数数据+8bit湿度整数数据+8bit湿度小数数据

通信流程:主机发送开始信号------>主机释放总线(拉高)------>从机发送响应信号(从机开始采样)------>从机发送40bit数据------>从机拉低总线40us------>上拉电阻,拉高总线

开始信号:主机将总线拉低18~30ms(一般拉低20ms)

主机释放总线:将总线拉高10~30us(一般13us)

从机发送响应信号:从机拉低总线78~88(一般拉低83us),从机拉高总线80~82(一般拉高87)

**从机发送数据:**从机每发送一位前都要拉低总线50us,拉低完50us在拉高总线,拉高26~28表示0,拉高70us表示1

**从机拉低总线40us:**从机发送完40bit数据后,拉低总线40表示传输结束

**上拉电阻,拉高总线:**为下一次传输40bit数据做准备

**注:**温湿度模块收到一次开始信号,发送一次40bit数据,从机接收到一次开始信号后,模块从低功耗模式转为高速模式,发送完响应信号后,模块采样一次,在发送数据,发送完数据,拉低总线50us,再拉高总线

电机驱动模块(TB6612)

|-------------|-------------|
| 参数 | 数值 |
| 逻辑电压(VM) | 4.5~5.5V |
| 电机驱动电压(VCC) | 2.3~13.5 |
| 待机控制(STBY) | 高电平工作,低电平待机 |
| AIN1/AIN2 | 电机方向控制输入 |
| AO1/AO2 | 电机A输出 |

人体红外传感器

通信方式:如果检测到人输出高电平,没人输出低电平

延时控制:如果检测到人持续输出多长时间1

距离控制:能检测到多远有人

H:传感器在检测到运动后,延时时间内不会重复触发

L:传感器在检测到运动后,延时时间内会重复触发

注:这个模块是要检测到有人动才会输出1,如果你不动就算贴着他都不会显示有人

三,代码

温湿度模块

复制代码
//温湿度.C文件
#include "DHT11.h"
//转换引脚模式:发送模式和接收模式
void DHT11_MODE(uint8_t MODE)
{
    //这四行是固定的,改变的是引脚模式
    GPIO_InitTypeDef M={0};
    M.Pin=DHT11_PIN;
    M.Speed=GPIO_SPEED_FREQ_LOW;
    M.Pull=GPIO_PULLUP;

    if(MODE==DHT11_OUTPUT)
    {
        M.Mode=GPIO_MODE_OUTPUT_PP;
    }
    else
    {
        M.Mode=GPIO_MODE_INPUT;
    }
    HAL_GPIO_Init(DHT11_GPIO,&M);
}

//发送开始信号
void DHT11_Ret(void)
{
    //将引脚模式该成输出模式
    DHT11_MODE(DHT11_OUTPUT);
    //此时总线为空闲模式(高电平),将总线拉低,并持续20ms
    HAL_GPIO_WritePin(DHT11_GPIO,DHT11_PIN,GPIO_PIN_RESET);
    HAL_Delay(20);

    //再将总线拉高,让总线处于空闲模式,
    HAL_GPIO_WritePin(DHT11_GPIO,DHT11_PIN,GPIO_PIN_SET);
    DWT_Delay_us(13);
}

//发送应答信号
uint8_t DHT11_Ack(void)
{
    uint8_t NUM=0;
    //将引脚该为输入模式
    DHT11_MODE(DHT11_INPUT);

    //此时总线为空闲模式(高电平),等待DHT11将总线拉低,这等待的时间绝不会超过100ms
    while (HAL_GPIO_ReadPin(DHT11_GPIO,DHT11_PIN)&&NUM<=100)
    {
        DWT_Delay_us(1);
        NUM++;
    }

    //如果等待时间超过100ms,表示无此设备,或DHT11没有应答,检测硬件
    if(NUM>=100) return 1;
    NUM=0;

    //等待DHT11将总线拉高,等待时间依然不会超过100ms
    while (HAL_GPIO_ReadPin(DHT11_GPIO,DHT11_PIN)==GPIO_PIN_RESET&&NUM<=100)
    {
        NUM++;
        DWT_Delay_us(1);
    }

    //如果等待时间超过100ms,可能是误触或者硬件坏了
    if(NUM>=100) return 1;
    return 0;
}



//接收一个bit
uint8_t DHT11_Read_bit(void)
{
    //此时DHT11还是输入模式,
    uint8_t NUM=0;
    //此时总线为空闲模式(高电平),等待DHT11将总线拉低
    while(HAL_GPIO_ReadPin(DHT11_GPIO,DHT11_PIN)&&NUM<100)
    {
        NUM++;
        DWT_Delay_us(1);
    }

    NUM=0;
    //此时总线状态为低电平,等待DHT11将总线拉高
      while(HAL_GPIO_ReadPin(DHT11_GPIO,DHT11_PIN)==GPIO_PIN_RESET&&NUM<100)
    {
        NUM++;
        DWT_Delay_us(1);
    }

    //此时总线为高电平,这持续时间代表数据,因为持续时间为26~28us表示0,所以等40us后如果引脚为高电平则传输数据为1
    DWT_Delay_us(40);
    if(HAL_GPIO_ReadPin(DHT11_GPIO,DHT11_PIN)==GPIO_PIN_SET) 
    {
         while (HAL_GPIO_ReadPin(DHT11_GPIO,DHT11_PIN))
        {
            DWT_Delay_us(1);
        }
       return 1;
    }
    else    return 0;
}

//接收一个字节
uint8_t DHT11_Read_Byte(void)
{
    uint8_t Byte=0;
    for(uint8_t i=0;i<8;i++)
    {
        Byte<<=1;
        Byte|=DHT11_Read_bit();
    }
    return Byte;
}

//接收一次数据
void DHT11_Read_Data(uint8_t*WD,uint8_t *SD)
{
    uint8_t buf[5];
    DHT11_Ret();
    if(DHT11_Ack()==0)
    {
         for(uint8_t i=0;i<5;i++)
        {
             buf[i]=DHT11_Read_Byte();
        }
             if(buf[0]+buf[1]+buf[2]+buf[3]==buf[4])
         {
            *WD=buf[0];
             *SD=buf[2];
         }
    }
}
//初始化
void DHT11_Init(void)
{
    DWT_Init();
    DHT11_MODE(DHT11_OUTPUT);
    HAL_GPIO_WritePin(DHT11_GPIO,DHT11_PIN,GPIO_PIN_SET);

}

void DHT11_Update(void)
{
     uint8_t WD,SD;
    DHT11_Read_Data(&SD,&WD);
    OLED_ShowChinese(0,0,"温度:");
    OLED_ShowChinese(0,20,"湿度:");
    OLED_ShowNum(38,0,WD,2,OLED_8X16);
    OLED_ShowNum(38,20,SD,2,OLED_8X16);
    OLED_Update();
    HAL_Delay(500);
}

//温湿度.h文件
#ifndef __DHT11_H__
#define __DHT11_H__

#include "main.h"  // 包含 HAL 库和 GPIO 定义
#include "gpio.h"
#include "Delay.h"
#include "FMQ.h"

#define DHT11_OUTPUT 1
#define DHT11_INPUT  0
#define DHT11_GPIO GPIOB
#define DHT11_PIN GPIO_PIN_10

//void DWT_Delay_us(uint32_t us);
void DHT11_MODE(uint8_t MODE);
void DHT11_Ret(void);
uint8_t DHT11_Ack(void);
uint8_t DHT11_Read_bit(void);
uint8_t DHT11_Read_Byte(void);
void DHT11_Read_Data(uint8_t*WD,uint8_t *SD);
void DHT11_Init(void);
void DHT11_Update(void);
//void DWT_Init(void);
#endif

微秒延时函数

复制代码
#include "Delay.h"


void DWT_Init(void) {
    if (!(CoreDebug->DEMCR & CoreDebug_DEMCR_TRCENA_Msk)) {
        CoreDebug->DEMCR |= CoreDebug_DEMCR_TRCENA_Msk;
        DWT->CYCCNT = 0;
        DWT->CTRL |= DWT_CTRL_CYCCNTENA_Msk;
    }
}

// 微秒延时函数
void DWT_Delay_us(uint32_t us) {
    uint32_t startTick = DWT->CYCCNT;
    uint32_t delayTicks = us * (SystemCoreClock / 1000000);
    
    while ((DWT->CYCCNT - startTick) < delayTicks) {
        // 等待
    }
}

#ifndef __DELAY_H__
#define __DELAY_H__

#include "main.h"
void DWT_Delay_us(uint32_t us);
void DWT_Init(void);


#endif

烟雾模块

复制代码
#include "MQ2.h"

extern  uint8_t alarm;
void MQ2_Update(void)
{
    
        //在main函数中初始化
        // HAL_ADC_Init(&hadc1);

         //启动ADC转换
        HAL_ADC_Start(&hadc1);
        //等待转换完成
        HAL_ADC_PollForConversion(&hadc1, HAL_MAX_DELAY);
        uint16_t adc = HAL_ADC_GetValue(&hadc1);
       float Vol=(float)adc*100/4095;
        // OLED_ShowChinese(0,40,"烟雾浓度");
       // OLED_ShowNum(70,40,Vol,2,OLED_8X16);
        //OLED_Update();
        if(Vol>=30)
        {
        OLED_ShowChinese(0,40,"烟雾浓度过高");
        OLED_ShowNum(100,40,Vol,2,OLED_8X16);
      
            alarm|= 0x01;
           // FMQ_MODE(FMQ_OK);
            //MY_PWM_Update(100);
          
        }
        else
        {
            OLED_ClearArea(64,40,100,40);
            OLED_ShowChinese(0,40,"烟雾浓度");
            OLED_ShowNum(70,40,Vol,2,OLED_8X16);
            alarm &= ~0x01;
            //FMQ_MODE(FMQ_NO);
           // MY_PWM_Update(0);
        }
}

#ifndef __MQ2_H__
#define __MQ2_H__

#include "main.h"
#include "adc.h"
#include "usart.h"



void MQ2_Update(void);


#endif

人体红外传感模块

复制代码
#include "SR501.h"

//这是中断模式
uint8_t NUM=0;
uint8_t PRO_NUM=0;

void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{

  if(GPIO_Pin==GPIO_PIN_0)
  {
        PRO_NUM=NUM;
   NUM=HAL_GPIO_ReadPin(SR501_GPIO,SR501_PIN);
   if(PRO_NUM!=NUM)
   {
        if(NUM==1)
        {
            OLED_ShowChinese(70,20,"有人");
            OLED_Update();
        }
        else  if(NUM==0)
        {
            OLED_ShowChinese(70,20,"没人");
            OLED_Update();
        }
   }
  }
}

//这是轮询模式
/*
uint8_t NUM=0;
uint8_t PRO_NUM=0;

void  SR501_UpDate(void)
{
    PRO_NUM=NUM;
   NUM=HAL_GPIO_ReadPin(SR501_GPIO,SR501_PIN);
   if(PRO_NUM==NUM)
  {
        if(NUM==1)
        {
            OLED_ShowChinese(70,20,"有人");
            OLED_Update();
       }
        else  if(NUM==0)
        {
            OLED_ShowChinese(70,20,"没人");
            OLED_Update();
        }
   }
}
**/

#ifndef __SR501_H__
#define __SR501_H__

#include "main.h"

#define SR501_GPIO  GPIOB
#define SR501_PIN   GPIO_PIN_0

//void  SR501_UpDate(void);


#endif

蜂鸣器模块

复制代码
#include "FMQ.h"

void FMQ_MODE(uint8_t MODE)
{    if(MODE==FMQ_OK)
    {
        HAL_GPIO_WritePin(FMQ_GPIO,FMQ_PIN,GPIO_PIN_RESET);
    }
    else if(MODE==FMQ_NO)
    {
        HAL_GPIO_WritePin(FMQ_GPIO,FMQ_PIN,GPIO_PIN_SET);
    }
}

#ifndef __FMQ_H__
#define __FMQ_H__

#include "main.h"  // 包含 HAL 库和 GPIO 定义
#include "gpio.h"
#include "Delay.h"

#define FMQ_GPIO GPIOB
#define FMQ_PIN GPIO_PIN_11
#define FMQ_OK 1
#define FMQ_NO  0

void FMQ_MODE(uint8_t MODE);


#endif

火焰传感器模块

复制代码
#include "IR.h"

extern  uint8_t alarm;
void IR_MODE(void)
{
	uint8_t mode = HAL_GPIO_ReadPin(IR_GPIO,IR_PIN);
    if(mode == GPIO_PIN_RESET)
    {
      //  FMQ_MODE(FMQ_OK);
        //MY_PWM_Update(100);
         alarm |= 0x02;
        OLED_ShowChinese(70,0,"火灾");
        OLED_Update();
    }
    else
    {
        // FMQ_MODE(FMQ_NO);
         //MY_PWM_Update(0);
         alarm &= ~0x02;
         OLED_ShowChinese(70,0,"安全");
         OLED_Update();
    }
}

#ifndef __IR_H__
#define __IR_H__

#include "main.h"  // 包含 HAL 库和 GPIO 定义
#include "gpio.h"
#include "Delay.h"

#define IR_PIN GPIO_PIN_1
#define IR_GPIO GPIOB

void IR_MODE(void);

#endif

电机驱动

复制代码
#include "PWM.h"

void MY_PWM_Update( uint8_t CCR )
{
    if(CCR>0)
    {
        HAL_GPIO_WritePin(GPIOB,GPIO_PIN_15,GPIO_PIN_RESET);
        HAL_GPIO_WritePin(GPIOB,GPIO_PIN_14,GPIO_PIN_SET);
        __HAL_TIM_SET_COMPARE(&htim2,TIM_CHANNEL_1,CCR);
    }
     else   if(CCR==0)
    {
        HAL_GPIO_WritePin(GPIOB,GPIO_PIN_14,GPIO_PIN_RESET);
        HAL_GPIO_WritePin(GPIOB,GPIO_PIN_15,GPIO_PIN_SET);
        __HAL_TIM_SET_COMPARE(&htim2,TIM_CHANNEL_1,0);
    }
}

#ifndef __PWM_H__
#define __PWM_H__

#include "main.h"
#include "tim.h"

void MY_PWM_Update( uint8_t CCR );

#endif

四,遇到的问题

问题1:

我用stm32f103的adc读取mq2烟雾模块ao数据,我把ao线连接到stm32上后(烟雾模块供电正常5v),得到的数据一直在0-4095之间乱跳,把烟雾模块断电后,但ao角还是连接在stm32上,数据还是在0-4095上乱跳,当把ao角与stm32断开数据就一直在1900-2000徘徊,我又用adc测继电器,得到的数据也是正常的,用万用表测mq2(烟雾模块)的ao引脚,测得电压是0.1v对烟雾模块哈气测得的电压也会升高

答:MQ-2模块用的电池供电,而STM32用的ST-LINK共电,两者没有共地

问题2:

当火焰和空气烟雾浓度超标时蜂鸣器和风扇都是响一下断一下,风扇是转一下停一下

答:那个时候两者报警是分开的,没有引入Freereos系统,报警控制逻辑存在竞态条件,现在两者使用同一套报警装置

源代码和视频

通过网盘分享的文件:智能家居安防系统

链接: https://pan.baidu.com/s/1402AisjKrZdVJ6QfwzuiRg 提取码: hxb2

相关推荐
IpdataCloud1 小时前
智能家居设备上线IP归属分析:从设备发现到区域功能适配
网络协议·tcp/ip·智能家居
鄭郑1 小时前
STM32学习笔记--SPI初始化与数据收发(01)
笔记·stm32·学习
wsoz2 小时前
Linux与单片机程序对比
单片机·mcu·嵌入式·linux操作系统
姓刘的哦2 小时前
STM32控制直流有刷电机
单片机·嵌入式硬件
悠哉悠哉愿意3 小时前
【单片机学习笔记】math库函数补充
c语言·笔记·单片机·学习
爱倒腾的老唐3 小时前
1、电子元器件——电阻
单片机·嵌入式硬件
LCG元3 小时前
STM32实战:基于HAL库的智能温湿度监测系统(DHT11+OLED)
stm32·单片机·嵌入式硬件
czhaii3 小时前
STC32G144K246PLL时钟I2S音频播放方式电子琴
stm32·单片机·嵌入式硬件
三佛科技-1341638421214 小时前
HN20P03_P沟道增强型-30V-20A TO252封装MOSFET场效应管(典型应用分析)
单片机·嵌入式硬件