✔零知IDE 是一个真正属于国人自己的开源软件平台,在开发效率上超越了Arduino平台并且更加容易上手,大大降低了开发难度。零知开源在软件方面提供了完整的学习教程和丰富示例代码,让不懂程序的工程师也能非常轻而易举的搭建电路来创作产品,测试产品。快来动手试试吧!
✔访问零知实验室,获取更多实战项目和教程资源吧!
目录
(1)项目概述
本项目基于功能强大的STM32F407VET6微控制器(零知增强板主控芯片)和HC-SR501人体热释电红外传感器,构建了一个多功能、可视化的智能安防监控系统。系统不仅能够检测人体活动并触发声光报警,还能实时监测环境的温湿度和光照强度,通过一块240x240分辨率的彩色TFT显示屏直观地展示所有信息。
(2)项目难点及解决方案
问题描述:多任务处理与实时性,确保同时处理传感器数据读取
(3)项目效果预览
HC-SR505项目效果预览
一、硬件接线部分
1.1 硬件清单
| 元件名称 | 型号/规格 | 数量 | 备注 |
|---|---|---|---|
| 主控板 | STM32F407VET6核心 | 1 | 零知增强板主控板 |
| 人体红外传感器 | HC-SR501 | 1 | 核心检测器件 |
| 温湿度传感器 | DHT11 | 1 | 温湿度监测 |
| 光敏电阻模块 | 模拟输出 | 1 | 光线监测 |
| TFT显示屏 | 1.3英寸 ST7789 | 1 | 240x240分辨率 |
| 有源蜂鸣器 | BUZZER | 1 | 声音报警 |
| LED | 5mm | 1 | 报警指示灯 |
| 电阻 | 220Ω | 1 | 用于LED限流(如果LED无内置电阻) |
| 连接线 | 杜邦线 | 若干 | 连接到各个模块 |
1.2 接线方案
| 零知增强板引脚 | 连接的元件与引脚 | 说明 |
|---|---|---|
5 | DHT11 DATA | 温湿度数据线 |
6 | HC-SR501 OUT | 人体感应信号输出 |
A0 | 光敏电阻模块 AO | 模拟光线强度信号 |
12 | 蜂鸣器 + / S | 控制蜂鸣器发声 |
13 | LED阳极(长脚) | 报警指示灯(通过220Ω电阻接地) |
53 | TFT TFT_CS | SPI片选 |
8 | TFT TFT_DC | 数据/命令选择 |
| 9 | TFT TFT_RST | 复位 |
7 | TFT TFT_BL | 背光控制 |
3.3V | TFT VCC | 显示屏电源(注意:很多1.54寸屏是3.3V) |
GND | TFT GND | 显示屏电源地 |
| 52 | TFT SCK | SPI时钟 |
51 | TFT MOSI | SPI主出从入 |
注意:TFT屏的通信连接到硬件SPI,请参照零知增强板的引脚说明图连接。HC-SR505连接使用+5V电源供电,其他组件使用3.3V供电。
1.3 具体接线图

1.4 连接实物图

二、代码讲解部分
2.1 引脚定义与库引入
#include <Adafruit_GFX.h> // 核心图形库
#include <Adafruit_ST7789.h> // ST7789显示屏驱动库
#include <SPI.h> // SPI通信库
#include <DHT.h> // DHT温湿度传感器库
// 引脚定义
#define TFT_CS 53
#define TFT_DC 8
// ... 其他引脚定义
#define PIR_PIN 6 // HC-SR501输出信号引脚
PIR_PIN 6 定义了HC-SR501传感器的信号线连接在数字引脚6上。所有设备的工作都基于这些引脚定义。
2.2 初始化设置
void setup() {
// ... 串口初始化
tft.init(240, 240); // 初始化显示屏
pinMode(TFT_BL, OUTPUT);
digitalWrite(TFT_BL, HIGH); // 开启背光
pinMode(PIR_PIN, INPUT_PULLUP); // 设置HC-SR505引脚为输入上拉模式
// ... 其他引脚模式设置
dht.begin(); // 启动DHT传感器
drawMainScreen(); // 绘制主界面
}
HC-SR505传感器输出为高阻态,引脚电平能被稳定地拉高,防止误触发。
drawMainScreen()函数绘制了项目的静态UI框架
2.3 HC-SR505处理函数
void handlePIRSensor() {
static bool lastPirState = false;
bool pirState = digitalRead(PIR_PIN); // 读取传感器当前状态
if (pirState != lastPirState) { // 状态发生变化
lastPirState = pirState;
if (pirState) { // 状态变为HIGH,检测到人体!
tft.fillCircle(60, 75, 15, ST77XX_GREEN); // 更新UI图标为绿色
digitalWrite(LED_PIN, HIGH); // LED亮
tone(BUZZER_PIN, 1000, 200); // 蜂鸣器短响一声
// 在屏幕底部显示警告文字
tft.fillRect(0, 220, 240, 20, ST77XX_RED);
tft.setCursor(30, 222);
tft.print("Human activity detected!");
// 触发蜂鸣器间断鸣响逻辑
lastBuzzerTime = millis();
buzzerState = true;
analogWrite(BUZZER_PIN, 10); // PWM驱动蜂鸣器,音量较小
} else {
// 状态变为LOW,无人
tft.fillCircle(60, 75, 15, ST77XX_RED); // 图标恢复红色
digitalWrite(LED_PIN, LOW); // LED灭
tft.fillRect(0, 220, 240, 20, ST77XX_BLACK); // 清除警告文字
}
}
}
lastPirState:比较当前状态和上一次状态来判断是否发生变化。只有在变化时才执行后续动作,避免持续触发。
2.4 非阻塞式设计
void loop() {
static unsigned long lastUpdate = 0;
// 每500ms更新一次显示
if (millis() - lastUpdate > 500) {
lastUpdate = millis();
updateSensorData(); // 更新温湿度和光照数据显示
handlePIRSensor(); // 检查HC-SR501状态
}
handleEncoder(); // (预留)处理编码器
checkButtonPress(); // (预留)处理按钮
handleBuzzer(); // 处理蜂鸣器报警声音
}
使用
millis()计时,每500毫秒执行一次数据更新和传感器检查
2.5 系统完整代码
#include <Adafruit_GFX.h>
#include <Adafruit_ST7789.h>
#include <SPI.h>
#include <DHT.h>
// 引脚定义
#define TFT_CS 53
#define TFT_DC 8
#define TFT_RST 9
#define TFT_BL 7
#define PIR_PIN 6
#define DHT_PIN 5
#define LIGHT_SENSOR A0
#define ENC_CLK 2
#define ENC_DT 3
#define ENC_SW 4
#define BUZZER_PIN 12
#define LED_PIN 13
// 初始化显示屏
Adafruit_ST7789 tft = Adafruit_ST7789(TFT_CS, TFT_DC, TFT_RST);
DHT dht(DHT_PIN, DHT11);
// 全局变量
int menuIndex = 0;
int lastEncoded = 0;
long lastButtonPress = 0;
unsigned long lastBuzzerTime = 0;
bool buzzerState = false;
bool screenOn = true;
void setup() {
Serial.begin(9600);
// 初始化显示屏
tft.init(240, 240);
tft.setRotation(1);
tft.fillScreen(ST77XX_BLACK);
tft.setTextSize(3);
tft.setCursor(60, 110);
tft.print("Ready");
delay(500);
pinMode(TFT_BL, OUTPUT);
digitalWrite(TFT_BL, HIGH);
// 初始化传感器
pinMode(PIR_PIN, INPUT_PULLUP);
pinMode(BUZZER_PIN, OUTPUT);
pinMode(LED_PIN, OUTPUT);
pinMode(ENC_CLK, INPUT_PULLUP);
pinMode(ENC_DT, INPUT_PULLUP);
pinMode(ENC_SW, INPUT_PULLUP);
dht.begin();
// 绘制初始界面
drawMainScreen();
Serial.println("智能安防系统升级版启动完成!");
}
void loop() {
static unsigned long lastUpdate = 0;
// 每500ms更新一次显示
if (millis() - lastUpdate > 500) {
lastUpdate = millis();
updateSensorData();
handlePIRSensor();
}
handleEncoder();
checkButtonPress();
handleBuzzer();
}
void drawMainScreen() {
tft.fillScreen(ST77XX_BLACK);
// 绘制标题栏
tft.fillRect(0, 0, 240, 30, ST77XX_BLUE);
tft.setCursor(30, 10);
tft.setTextColor(ST77XX_WHITE);
tft.setTextSize(2);
tft.print("Security system");
// 绘制数据区域
tft.setTextColor(ST77XX_WHITE);
tft.setTextSize(1);
// 人体检测区域
tft.fillRoundRect(10, 40, 100, 60, 5, ST77XX_MAGENTA);
tft.setCursor(25, 50);
tft.print("Detection");
tft.fillCircle(60, 75, 15, ST77XX_RED);
// 温湿度区域
tft.fillRoundRect(130, 40, 100, 60, 5, ST77XX_MAGENTA);
tft.setCursor(145, 50);
tft.print("Temp & humi");
// 光线感应区域
tft.fillRoundRect(10, 110, 100, 60, 5, ST77XX_MAGENTA);
tft.setCursor(25, 120);
tft.print("Light sensing");
// 状态区域
tft.fillRoundRect(130, 110, 100, 60, 5, ST77XX_MAGENTA);
tft.setCursor(150, 120);
tft.print("System status");
tft.setCursor(135, 150);
tft.print("Running");
// 底部菜单
tft.fillRect(0, 180, 240, 60, ST77XX_CYAN);
tft.setCursor(15, 195);
tft.setTextColor(ST77XX_BLACK);
tft.print("Status Settings Data About");
}
void updateSensorData() {
// 更新温湿度显示
float temp = dht.readTemperature();
float humidity = dht.readHumidity();
tft.fillRect(135, 65, 90, 30, ST77XX_MAGENTA);
tft.setTextColor(ST77XX_WHITE);
tft.setCursor(135, 65);
tft.print("T:");
tft.setCursor(150, 65);
tft.print(temp);
tft.setTextColor(ST77XX_WHITE);
tft.setCursor(135, 80);
tft.print("H:");
tft.setCursor(150, 80);
tft.print(humidity);
// 更新光线感应显示
int lightValue = analogRead(LIGHT_SENSOR);
int lightLevel = map(lightValue, 0, 1023, 0, 100);
tft.fillRect(15, 135, 90, 30, ST77XX_MAGENTA);
tft.setCursor(35, 135);
tft.setTextColor(ST77XX_WHITE);
tft.print(lightLevel);
// 绘制光线指示条
tft.fillRect(20, 150, 20, 5, ST77XX_BLACK);
tft.fillRect(20, 150, lightLevel * 0.2, 5, ST77XX_YELLOW);
}
void handlePIRSensor() {
static bool lastPirState = false;
bool pirState = digitalRead(PIR_PIN);
if (pirState != lastPirState) {
lastPirState = pirState;
if (pirState) {
// 检测到人体
tft.fillCircle(60, 75, 15, ST77XX_GREEN);
digitalWrite(LED_PIN, HIGH);
tone(BUZZER_PIN, 1000, 200);
// 显示警告信息
tft.fillRect(0, 220, 240, 20, ST77XX_RED);
tft.setCursor(30, 222);
tft.setTextColor(ST77XX_WHITE);
tft.print("Human activity detected!");
// 触发蜂鸣器
lastBuzzerTime = millis();
buzzerState = true;
analogWrite(BUZZER_PIN, 10); // 最小音量
} else {
// 无人体活动
tft.fillCircle(60, 75, 15, ST77XX_RED);
digitalWrite(LED_PIN, LOW);
// 清除警告信息
tft.fillRect(0, 220, 240, 20, ST77XX_BLACK);
}
}
}
void handleBuzzer() {
// 处理蜂鸣器间断播报
if (buzzerState && millis() - lastBuzzerTime > 1000) {
buzzerState = !buzzerState;
lastBuzzerTime = millis();
if (buzzerState) {
analogWrite(BUZZER_PIN, 10); // 最小音量
} else {
analogWrite(BUZZER_PIN, 0); // 关闭
}
}
}
void handleEncoder() {
// 处理旋转编码器输入
// 实现菜单导航功能
}
void checkButtonPress() {
// 处理按钮按下事件
// 实现功能选择
}
pirState参数说明: 存储HC-SR501当前输出电平的变量。HIGH表示检测到人体,LOW表示未检测到。
程序流程图:

三、项目结果演示
3.1 操作流程
(1)上电启动
系统初始化,屏幕显示“Ready”后进入主界面。主界面分为四个区域:人体检测(红色)、温湿度、光线感应、系统状态(Running)

(2)正常监控状态
无人经过时,人体检测图标为红色,温湿度和光照数据正常刷新,底部无报警信息。
(3)触发报警状态

当有人进入HC-SR505探测范围时:
人体检测图标立即变为绿色,LED指示灯亮起,屏幕底部出现红色报警条并显示警告信息,蜂鸣器开始报警。
(4)报警解除
人离开探测范围后,所有报警指示(屏幕、LED、蜂鸣器)自动解除,系统恢复常态监控
3.2 视频演示
HC-SR505安防监控系统
从启动、正常监控、HC-SR505快速触发报警到自动解除报警的全过程
四、HC-SR505热释电传感器工作原理
HC-SR505是一款基于热释电红外(Pyroelectric Infrared, PIR)技术的迷你型人体自动感应模块。与HC-SR501相比,它具有体积小、触发灵敏、自动延时的特点。

工作原理
人体有恒定的体温,一般在37℃左右,因此会发射出特定波长约为10uM的红外线。被动红外探测器的工作原理是检测人体发射的约10uM的红外线。

HC-SR505采用重复触发模式,即在前一次输出结束后,如果再次检测到人体移动,会立即重新输出高电平。
五、常见问题解答 (FAQ)
Q1: HC-SR505检测距离太近或角度不够?
A: HC-SR505的探测距离和角度是固定的,无法像HC-SR501那样调节:
如需更大范围检测,需要考虑使用多个传感器或选择HC-SR501等可调节型号。
Q2: HC-SR505一直输出高电平是怎么回事?
A: 可能是传感器故障或安装环境有问题:
检查是否安装在有强烈热源或气流变化大的地方。确保电源稳定,模块未损坏。
Q3: 为什么人静止不动时传感器不触发?
A: 这是所有PIR传感器的共同特性:
它们检测的是红外辐射的变化,而不是静态热源。人静止时红外辐射无变化,传感器无法检测。
项目资源整合
DHT11温湿度传感器库: DHT-sensor-library
992

被折叠的 条评论
为什么被折叠?



