随着自动化和智能化技术的发展,人体红外感应模块在许多领域得到了广泛应用,比如安防系统、自动照明和自动门。

HC-SR501 就是一款高效、稳定的人体红外感应模块,它基于热释电效应,能够精确地检测人体或动物的红外线。在接下来的文章中,我们将深入了解 HC-SR501 模块的特点、工作原理以及如何应用。

1. 源码下载及前置阅读

本文首发 良许嵌入式网https://www.lxlinux.net/e/ ,欢迎关注!

本文所涉及的源码及安装包如下(由于平台限制,请点击以下链接阅读原文下载):

https://www.lxlinux.net/e/stm32/hc-sr501-tutorial.html

超全的嵌入式入门教程,欢迎小白。

往期精彩教程,有兴趣的小伙伴可以看看。

作者简介
大家好,我是良许,博客里所有的文章皆为我的原创。
下面是我的一些个人介绍,欢迎交个朋友:
· 211工科硕士,国家奖学金获得者;
· 深耕嵌入式11年,前世界500强外企高级嵌入式工程师;
· 书籍《速学Linux作者》,机械工业出版社专家委员会成员;
· 全网60W粉丝,博客分享大量原创成体系文章,全网阅读量累计超4000万;
· 靠自媒体连续年入百万,靠自己买房买车。

我本科及硕士都是学机械,通过自学成功进入世界500强外企。我已经将自己的学习经验写成了一本电子书,超千人通过此书学习并转行成功。现在将这本电子书免费分享给大家,希望对你们有帮助:

电子书链接:https://www.lxlinux.net/1024.html

2. HC-SR501介绍

人体红外感应模块大家族有很多成员,给大家看看部分成员的样貌。HC-SR501 蓝板和绿板只是颜色不同。

HC-SR501是基于红外线技术的自动控制模块,采用德国原装进口 LHI778 探头设计,灵敏度高,可靠性强,超低电压工作模式,广泛应用于各类自动感应电器设备,尤其是干电池供电的自动控制产品。

白色的半球体是菲涅耳透镜,拆下它,里面长这样。探头用于检测人体红外,预留的两个接口在下文会提到并解释。

2.1 HC-SR501功能特点

  1. 全自动感应:人进入其感应范围则输出高电平,人离开感应范围则自动延时关闭高电平,输出低电平。
  2. 光敏控制(可选择,出厂时未设)可设置光敏控制,白天或光线强时不感应。(使用光敏电阻接口)
  3. 温度补偿(可选择,出厂时未设):在夏天当环境温度升高至30~32℃,探测距离稍变短,温度补偿可作一定的性能补偿。(使用热敏电阻接口)
  4. 两种触发方式(跳线选择):(1)不可重复触发方式:即感应输出高电平后,延时时间段一结束,输出将自动从高电平变成低电平;(2)可重复触发方式:即感应输出高电平后,在延时时间段内,如果有人体在其感应范围活动,其输出将一直保持高电平,直到人离开后才延时将高电平变为低电平。
  5. 具有感应封锁时间(默认设置:2.5秒封锁时间):感应模块在每一次感应输出后(高电平变成低电平),可以紧跟着设置一个封锁时间段,在此时间段内感应器不接受任何感应信号。此功能可以实现“感应输出时间”和“封锁时间”两者的间隔工作,可应用于间隔探测产品;同时此功能可有效抑制负载切换过程中产生的各种干扰。
  6. 工作电压范围宽:工作电压 DC4.5V-20V。
  7. 微功耗:静态电流<50微安。
  8. 输出高电平信号:可方便与各类电路实现对接。

2.2 HC-SR501使用说明

  1. 感应模块通电后有一分钟左右的初始化时间,在此期间模块会间隔地输出0-3次,一分钟后进入待机状态。
  2. 避免灯光等干扰源近距离直射模块表面的透镜,以免引进干扰信号产生误动作;尽量避免流动的风,风也会对感应器造成干扰。
  3. 感应模块采用双元探头,探头的窗口为长方形,双元(A元、B元)位于较长方向的两端,当人体从左到右或从右到左走过时,红外光谱到达双元的时间、距离有差值,差值越大,感应越灵敏,当人体从正面走向探头或从上到下或从下到上方向走过时,双元检测不到红外光谱距离的变化,无差值,因此感应不灵敏或不工作;所以安装感应器时应使探头双元的方向与人体活动最多的方向尽量相平行,保证人体经过时先后被探头双元所感应。为了增加感应角度范围,本模块采用圆形透镜,也使得探头四面都感应,但左右两侧仍然比上下两个方向感应范围大、灵敏度强,安装时仍须尽量按以上要求。
  4. 人体红外感应模块应离地面2.0-2.2米。
  5. 人体红外感应模块远离空调, 冰箱,火炉等空气温度变化敏感的地方。
  6. 人体红外感应模块探测范围内不得隔屏、家具、大型盆景或其他隔离物。
  7. 人体红外感应模块不要直对窗口,否则窗外的热气流扰动和人员走动会引起误报,有条件的最好把窗帘拉上。红外线热释电传感器也不要安装在有强气流活动的地方。

安装方面简单来说就是要避开温度干扰、气流干扰和大型障碍

3. 工作原理

HC-SR501 工作时,探头检测到有人移动时,输出1;没人移动时,输出0。

那么原理是什么呢?

在解释原理前,我们先解释两个名词。

  • 菲涅耳透镜

根据菲涅耳原理制成,有如下特点:

  1. 聚焦作用:菲涅耳透镜可以将入射光线聚焦到一个点上,实现光线的集中和聚焦效果。这使得菲涅耳透镜在许多光学系统中被广泛使用,如摄影镜头、望远镜、投影仪等。
  2. 红外感应:菲涅耳透镜也常用于红外传感器和人体感应模块中。通过对红外辐射的聚焦作用,它能够增强红外信号的接收灵敏度,并提高红外传感器的性能。
  3. 分区控制:菲涅耳透镜的表面通常被划分为若干个明暗区域,使得光线能够以不同的路径通过透镜。这种设计可以用于光控制系统中,例如调节照明亮度、防眩光等应用。
  • 热释电效应

当一些晶体受热时,在晶体两端将会产生数量相等而符号相反的电荷。这种由于热变化而产生的电极化现象称为热释电效应。

知道了这两个名词后,我们就能理解 HC-SR501 的工作原理了。

  1. 我们的人体的体温大概在37度,会发出特定波长 10μm 左右的红外线,HC-SR501 上的红外探头就是靠探测人体发射的 10μm 左右的红外线而进行工作的。当然,如果是体温相似的动物也会被检测到。
  2. 人体发射的 10μm 左右的红外线通过菲泥尔滤透镜增强后聚集到红外感应源上。
  3. 红外感应源通常采用热释电元件,这种元件在接收到人体红外辐射温度发生变化时就会失去电荷平衡,向外释放电荷,后续电路经检测处理后就能产生报警信号。

4. 工作参数及引脚介绍

HC-SR501 模块工作参数,每个厂家会有点不同:

  1. 工作电压:DC 4.5V至20V
  2. 静态功耗:<50微安
  3. 电平输出:高3.3V,低0V
  4. 延时时间:可调(8秒~200秒)
  5. 封锁时间:2.5秒
  6. 触发方式:L不可重复,H可重复,默认值为H(跳帽选择)
  7. 感应范围:小于120度锥角,7米以内
  8. 工作温度:-15° ~ +70°

调节和接线参考如下:

5. 编程实战

5.1 通信示意图

我们的实现目标是:当有人经过时,红灯亮起,无人时,红灯灭。

5.2 硬件连接

本教程使用的硬件如下:

  • 单片机:STM32F103C8T6
  • 人体红外感应模块:HC-SR501
  • 小灯:三色 LED 灯模块
  • 烧录器:ST-LINK V2
HC-SR501模块STM32LED
5V5V
输出A4
GNDG
A5R
GGND

烧录的时候接线如下表,如果不会烧录的话可以看我之前的文章【STM32下载程序的五种方法】。

ST-Link V2STM32
SWCLKSWCLK
SWDIOSWDIO
GNDGND
3.3V3V3

接好如下图:

开发板使用的是我们自绘的板子。大家也可以用自己的板子,只要是 STM32F103C8T6 主控芯片就行。

5.3 LED初始化

LED 灯的代码简简单单,只要进行一下三个灯的初始化就行,虽然本项目我们只用到红灯(LED1),但是其他两个灯就我也就懒得删了。

void led_init(void)
{
    GPIO_InitTypeDef gpio_init_struct;
    LED1_GPIO_CLK_ENABLE();                                 /* LED1时钟使能 */
    LED2_GPIO_CLK_ENABLE();                                 /* LED2时钟使能 */
    LED3_GPIO_CLK_ENABLE();                                 /* LED3时钟使能 */

    gpio_init_struct.Pin = LED1_GPIO_PIN;                   /* LED1引脚 */
    gpio_init_struct.Mode = GPIO_MODE_OUTPUT_PP;            /* 推挽输出 */
    gpio_init_struct.Pull = GPIO_PULLUP;                    /* 上拉 */
    gpio_init_struct.Speed = GPIO_SPEED_FREQ_HIGH;          /* 高速 */
    HAL_GPIO_Init(LED1_GPIO_PORT, &gpio_init_struct);       /* 初始化LED1引脚 */

    gpio_init_struct.Pin = LED2_GPIO_PIN;                   /* LED2引脚 */
    HAL_GPIO_Init(LED2_GPIO_PORT, &gpio_init_struct);       /* 初始化LED2引脚 */
    
    gpio_init_struct.Pin = LED3_GPIO_PIN;                   /* LED3引脚 */
    HAL_GPIO_Init(LED3_GPIO_PORT, &gpio_init_struct);       /* 初始化LED3引脚 */

    LED1(0);                                                /* 关闭 LED1 */
    LED2(0);                                                /* 关闭 LED2 */
    LED3(0);                                                /* 关闭 LED3 */
}

LED 的 .h文件:

#ifndef _LED_H
#define _LED_H
#include "sys.h"


/******************************************************************************************/
/* 引脚 定义 */

#define LED1_GPIO_PORT                  GPIOA
#define LED1_GPIO_PIN                   GPIO_PIN_5
#define LED1_GPIO_CLK_ENABLE()          do{ __HAL_RCC_GPIOA_CLK_ENABLE(); }while(0)             /* PA口时钟使能 */

#define LED2_GPIO_PORT                  GPIOA
#define LED2_GPIO_PIN                   GPIO_PIN_6
#define LED2_GPIO_CLK_ENABLE()          do{ __HAL_RCC_GPIOA_CLK_ENABLE(); }while(0)             /* PA口时钟使能 */

#define LED3_GPIO_PORT                  GPIOA
#define LED3_GPIO_PIN                   GPIO_PIN_7
#define LED3_GPIO_CLK_ENABLE()          do{ __HAL_RCC_GPIOA_CLK_ENABLE(); }while(0)             /* PA口时钟使能 */

/******************************************************************************************/
/* LED端口定义 */
#define LED1(x)   do{ x ? \
                      HAL_GPIO_WritePin(LED1_GPIO_PORT, LED1_GPIO_PIN, GPIO_PIN_SET) : \
                      HAL_GPIO_WritePin(LED1_GPIO_PORT, LED1_GPIO_PIN, GPIO_PIN_RESET); \
                  }while(0)

#define LED2(x)   do{ x ? \
                      HAL_GPIO_WritePin(LED2_GPIO_PORT, LED2_GPIO_PIN, GPIO_PIN_SET) : \
                      HAL_GPIO_WritePin(LED2_GPIO_PORT, LED2_GPIO_PIN, GPIO_PIN_RESET); \
                  }while(0)

#define LED3(x)   do{ x ? \
                      HAL_GPIO_WritePin(LED3_GPIO_PORT, LED3_GPIO_PIN, GPIO_PIN_SET) : \
                      HAL_GPIO_WritePin(LED3_GPIO_PORT, LED3_GPIO_PIN, GPIO_PIN_RESET); \
                  }while(0)

/* LED取反定义 */
#define LED1_TOGGLE()   do{ HAL_GPIO_TogglePin(LED1_GPIO_PORT, LED1_GPIO_PIN); }while(0)        /* 翻转LED1 */
#define LED2_TOGGLE()   do{ HAL_GPIO_TogglePin(LED2_GPIO_PORT, LED2_GPIO_PIN); }while(0)        /* 翻转LED2 */
#define LED3_TOGGLE()   do{ HAL_GPIO_TogglePin(LED3_GPIO_PORT, LED3_GPIO_PIN); }while(0)        /* 翻转LED3 */

/******************************************************************************************/
/* 外部接口函数*/
void led_init(void);                                                                            /* LED初始化 */

#endif

5.4 HC-SR501初始化

代码很简单,就是初始化一下输出引脚,PA4。

我们采用中断的方式点灯,需要初始化和使能一下 EXTI。

void hs_gpio_init(void)
{
    GPIO_InitTypeDef GPIO_InitStruct = {0};

    /* GPIO Ports Clock Enable */
    __HAL_RCC_GPIOA_CLK_ENABLE();

    /*Configure GPIO pins : PA4 */
    GPIO_InitStruct.Pin = GPIO_PIN_4;
    GPIO_InitStruct.Mode = GPIO_MODE_IT_RISING;             //中断上升沿
    GPIO_InitStruct.Pull = GPIO_NOPULL;                     //无电阻
    HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);

    /* EXTI interrupt init*/
    HAL_NVIC_SetPriority(EXTI4_IRQn, 2, 0);                 //抢占2,子优先级0
    HAL_NVIC_EnableIRQ(EXTI4_IRQn);
}

5.5 中断服务函数

设计中断服务函数,PA4 检测到上升沿,高电平,「hsflag」置1。

uint16_t get_hsflag(void)
{
    return hsflag;
}

void set_hsflag(uint16_t value)
{
    hsflag = value;
}

void EXTI4_IRQHandler(void)
{
    HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_4);         /* 调用中断处理公用函数 清除中断线 的中断标志位 */
    __HAL_GPIO_EXTI_CLEAR_IT(GPIO_PIN_4);         /* HAL库默认先清中断再处理回调,退出时再清一次中断,避免按键抖动误触发 */
}

void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{
    switch(GPIO_Pin)
    {
        case GPIO_PIN_4:
        if(HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_4) ==  GPIO_PIN_SET)
        {
            hsflag = 1;
        }
        break;
    }
}

5.6 主函数

主函数如下:

依据「hsflag」,为0时表示无人经过,红灯灭;为1时表示有人经过,红灯亮。

int main(void)
{
    HAL_Init();                         /* 初始化HAL库 */
    sys_stm32_clock_init(RCC_PLL_MUL9); /* 设置时钟, 72Mhz */
    delay_init(72);                     /* 延时初始化 */
    led_init();                         /* LED初始化 */
    hs_gpio_init();                     /* HC-SR501初始化 */

    while(1)
    {
        if (get_hsflag())               //有人经过时,亮灯1秒
        {
            LED1(1);
            delay_ms(1000);
            set_hsflag(0);
        }else{                          //有人经过时,灯灭
            LED1(0);
        }
    }
}

5.7 效果展示

HC-SR501 感受到人体,红灯亮。

6. 总结

通过深入了解 HC-SR501 的工作原理和特点,我们可以更好地发掘其潜力,为智能化和自动化的未来发展奠定坚实基础。无论是构建智能家居系统、设计安全警报系统还是开发自动控制设备,HC-SR501 都是不错的选择。

希望本文能够为你提供全面而清晰的指导,让你轻松掌握 HC-SR501 人体红外感应模块,并将其应用于你的创意项目中。感谢各位看官, peace and love!

另外,想进大厂的同学,一定要好好学算法,这是面试必备的。这里准备了一份 BAT 大佬总结的 LeetCode 刷题宝典,很多人靠它们进了大厂。

刷题 | LeetCode算法刷题神器,看完 BAT 随你挑!

有收获?希望老铁们来个三连击,给更多的人看到这篇文章

推荐阅读:

欢迎关注我的博客:良许嵌入式教程网,满满都是干货!


良许
1k 声望1.8k 粉丝