资讯动态

基于ESP32-CAM与PIR传感器的快递包裹防盗提醒装置DIY

发布时间:2026/9/8 14:13:12 来源:尧图企业网站定制
最近在社交平台刷到一条新闻式的投稿有小偷把别人快递箱拆开结果发现里面没什么“值钱货”反而气急败坏打电话给收货人说包裹里装了“危险物质”要报警还要精神损失费最后甚至注册账号靠这件事涨粉引流。作为开发者第一反应不是去纠结这场闹剧的谁对谁错而是想到一个更现实的问题如果包裹被偷这件事能在发生的第一时间知道并且留下清晰的证据后续的纠纷是不是会简单很多与其装一整套几千块钱的智能摄像头不如自己动手做一个小成本的家庭快递包裹防盗提醒装置。本文就基于常见的ESP32-CAM 开发板 PIR 人体红外传感器搭建一个能检测、能拍照、能存证、能推送通知到手机的物联网小项目。整个过程不依赖昂贵的云服务代码量不大适合有 Python 或嵌入式基础的开发者练手也适合想给家里加一层“技防”的动手派。1. 事件背后的需求快递包裹为什么容易变成盲区1.1 从包裹被偷事件说起很多住宅小区会把快递放在门口、电表箱、消防栓旁边甚至直接放地上。快递员拍照走人收货人远程查看。这个过程里有一个明显的时间盲区从快递员放下包裹到收货人回家取走包裹中间少则半小时多则一整天。如果小偷在这个时间窗内动手收货人往往直到晚上回家才发现包裹没了。此时再调监控、查记录、找物业不仅时间成本高而且很多老旧小区根本没有覆盖到位的监控设备。上面那条新闻里更离谱的在于小偷拆开包裹后因为里面的东西和自己预期不符竟然反过来报警、索赔。这种反向操作在法律上站不住脚但也提醒我们一件事让包裹的“状态”可追溯比事后扯皮重要得多。1.2 技术能解决什么问题我们要搭建的设备本质上是一个“事件触发 自动取证”的物联网装置当有人靠近包裹放置区域时设备通过人体红外传感器感知到动作。设备立即拍下当前画面保存到本地 SD 卡。同时触发声音报警可选。通过 WiFi 把一条通知消息推送到手机。这样即使包裹真的被拿走我们也有一张现场照片、一个时间线以及一条推送记录。后续无论是联系邻居、找物业还是报警处理都比“什么都没有”要主动得多。1.3 为什么选择 ESP32-CAM市面上的智能摄像头成本从几十到几百不等但多数依赖厂商 App 和云服务。自己动手做的好处在于数据本地保存不需要把照片传到第三方云。触发逻辑可以自定义不限于固定的人体走动检测。成本相对可控且改造灵活后续可以扩展接入 Home Assistant 或 MQTT。ESP32-CAM 是目前在物联网 DIY 社区里非常常见的一块开发板。它集成了 ESP32 主控、OV2640 摄像头、MicroSD 卡槽板子尺寸小价格低适合做这类“单车级”防盗设备。2. 方案设计与技术选型2.1 功能需求拆解根据实际场景把功能拆成四块功能模块具体作用实现方式人体检测有人靠近时触发后续动作PIR 人体红外传感器拍照取证采集现场画面ESP32-CAM 板载摄像头本地存储照片保存到本地MicroSD 卡手机通知第一时间提醒收货人WiFi HTTP 请求推送如果还想更完善可以加上无源蜂鸣器报警模块检测到有人长期逗留时发出声音。2.2 技术选型对比方案优点缺点PIR 人体红外传感器功耗低、价格便宜、触发灵敏只能检测移动不能识别具体是谁摄像头拍照 本地存储证据完整时间戳明确需要 SD 卡受存储空间限制云平台推送手机实时收到消息依赖第三方服务可能需要注册账号声光报警当场威慑现场没有人的时候没效果本文采用“PIR 检测 拍照 本地存储 手机推送”的组合兼顾成本和有效性。2.3 系统工作流程整个设备的工作流程并不复杂按顺序执行设备上电ESP32-CAM 连接 WiFi 并完成摄像头初始化。程序进入低功耗轮询状态不断读取 PIR 传感器的电平信号。PIR 检测到人体移动时输出高电平。ESP32 捕捉到高电平后调用摄像头拍照。照片以当前时间戳命名保存到 SD 卡。摄像头释放缓冲区。通过 HTTP GET 请求发送一条消息到用户配置的通知服务。继续回到检测状态等待下一次触发。为了防止短时间内频繁误报需要在代码里加入冷却时间静默时间比如触发一次后等待 30 秒或 60 秒再允许下一次触发。3. 环境准备与硬件说明3.1 硬件清单这里需要声明一点不同品牌和批次的开发板引脚定义、摄像头型号可能存在差异本文以最常见的 ESP32-CAM 开发板板载 OV2640为例硬件连接方式仅供参考。读者需要根据自己手里的板子丝印适当调整引脚。硬件数量说明ESP32-CAM 开发板1 块自带 OV2640 摄像头和 TF 卡槽PIR 人体红外传感器模块1 个常见 HC-SR501输出高/低电平MicroSD 卡1 张建议 16GB 以内FAT32 格式杜邦线若干母对母或公对母根据实际排针确定无源蜂鸣器模块1 个可选用于声光报警5V 电源1 个建议使用手机充电头或充电宝USB 转 TTL 串口模块1 个用于给 ESP32-CAM 烧录程序常见 CH340 芯片3.2 软件开发环境本文代码基于 Arduino 框架编写开发工具使用 Arduino IDE。Arduino IDE 1.8.x 和 2.x 都支持 ESP32 开发板本文示例使用 Arduino IDE 2.x 界面进行操作。由于 ESP32 开发板支持包更新比较频繁具体的包版本不建议锁死安装时选择官方仓库发布的最新稳定版即可。需要提前安装的软件和依赖Arduino IDE。ESP32 开发板支持包。可选串口调试助手方便查看日志。3.3 安装 ESP32 开发板支持包打开 Arduino IDE进入“文件 - 首选项”在“附加开发板管理器网址”中填入https://raw.githubusercontent.com/espressif/arduino-esp32/gh-pages/package_esp32_index.json然后打开“工具 - 开发板 - 开发板管理器”搜索ESP32安装esp32 by Espressif Systems即可。不同网络环境下下载速度可能较慢。安装成功后可以在开发板列表中找到ESP32 Arduino相关板卡选项例如AI Thinker ESP32-CAM。3.4 代码中需要关注的关键版本差异ESP32 支持包从 2.x 开始摄像头相关 API 与早期 1.x 存在少量差异。本文示例代码基于当前主流 2.x 版本编写如果读者使用 1.x 版本遇到编译错误优先考虑升级支持包而不是修改头文件路径。同时不同支持包版本对分区表、PSRAM 的开启方式会有细微差别遇到编译问题先从“工具”菜单的 Flash Size、Partition Scheme 等选项检查。4. 硬件接线4.1 ESP32-CAM 引脚速览ESP32-CAM 并非所有 GPIO 都引出到排针实际可用的引脚有限。本文用到的关键引脚如下功能引脚说明PIR 传感器信号输入GPIO13可根据实际板子调整无源蜂鸣器控制可选GPIO14输出高电平驱动蜂鸣器板载 LED 状态灯GPIO33用于反馈设备状态摄像头供电相关引脚无需配置板子内部已处理串口 RX / TXGPIO1 / GPIO3通过 USB-TTL 连接电脑复位引脚GPIO0 接地进入下载模式烧录时需要短接4.2 PIR 传感器接线HC-S501 或 HC-SR501 PIR 模块通常有三个引脚VCC、GND、OUT。与 ESP32-CAM 连接如下VCC 接 5V 或 3.3V大多数模块支持 3.3V但 5V 更稳定可根据模块手册确认。GND 接 GND。OUT 接 GPIO13。注意PIR 模块的 VCC 如果接 5V输出高电平通常也是 5V而 ESP32 的 GPIO 在大多数开发板上并非所有引脚都兼容 5V 输入。为了稳妥建议先查自己的 ESP32-CAM 原理图或者给 OUT 信号串联一个 1K 电阻再接入 GPIO13。很多教程直接接也没问题但为了长期稳定性加一个小电阻更安全。4.3 烧录连接ESP32-CAM 没有板载 USB 接口需要使用 USB 转 TTL 模块烧录。连接方式如下USB-TTL 模块ESP32-CAM3V33.3VTXRXGPIO3RXTXGPIO1GNDGND5V 或 3V3供电5V 或 3.3V根据 TTL 模块能力烧录时先用杜邦线将 GPIO0 和 GND 短接让开发板进入下载模式然后点击 Arduino IDE 的上传按钮。上传完成后断开 GPIO0 与 GND 的连接按下板子上的 RST 复位按钮程序即可正常运行。4.4 独立供电注意事项烧录和运行是两种不同场景。烧录阶段用 USB-TTL 供电即可但 ESP32-CAM 在开启 WiFi 和摄像头时电流可能瞬间冲到 200mA 以上普通 USB-TTL 模块可能出现供电不足。运行阶段建议用 5V/1A 以上的手机充电头为开发板供 5V 电源。如果使用充电宝需要留意充电宝的自动休眠机制必要时选择支持小电流输出的充电宝或者给设备加一个最低负载。5. 核心代码实现5.1 代码结构说明Arduino 项目的核心代码通常只有一个.ino文件。为了便于后期阅读代码中会把逻辑拆成几个函数setup()初始化串口、WiFi、摄像头、SD 卡、PIR 引脚。loop()周期检查 PIR 状态。takePhoto()拍照并保存照片到 SD 卡。sendNotify()发送 HTTP 请求到通知服务。注意Arduino 的.ino文件并不是一个标准的 C 项目结构函数之间需要保持定义顺序合理或使用函数声明。5.2 引入头文件与宏定义#include esp_camera.h #include SD_MMC.h #include WiFi.h #include time.h // 替换为你自己的 WiFi 信息 #define WIFI_SSID your_wifi_ssid #define WIFI_PASSWORD your_wifi_password // 通知服务地址示例使用 Server酱 Turbo 版接口 // 替换为你的 SendKey #define NOTIFY_URL https://sctapi.ftqq.com/SendKey.send?titleNewMessage // 引脚定义 #define PIR_PIN 13 #define BUZZER_PIN 14 #define LED_PIN 33 // 静默时间单位毫秒 #define TRIGGER_COOLDOWN_MS 30000UL这里的NOTIFY_URL是示例占位读者需要替换为自己使用的通知服务真实地址。如果不想依赖第三方推送服务也可以留空NOTIFY_URL跳过通知步骤只保存照片。5.3 摄像头初始化ESP32-CAM 的摄像头配置在esp_camera.h中通过camera_config_t结构体完成。bool initCamera() { camera_config_t config; config.ledc_channel LEDC_CHANNEL_0; config.ledc_timer LEDC_TIMER_0; config.pin_d0 5; config.pin_d1 18; config.pin_d2 19; config.pin_d3 21; config.pin_d4 36; config.pin_d5 39; config.pin_d6 34; config.pin_d7 35; config.pin_xclk 0; config.pin_pclk 22; config.pin_vsync 25; config.pin_href 23; config.pin_sscb_sda 26; config.pin_sscb_scl 27; config.pin_pwdn 32; config.pin_reset -1; config.xclk_freq_hz 20000000; config.pixel_format PIXFORMAT_JPEG; config.frame_size FRAMESIZE_VGA; config.jpeg_quality 12; config.fb_count 1; #if defined(CAMERA_MODEL_AI_THINKER) config.pin_d0 5; config.pin_d1 18; config.pin_d2 19; config.pin_d3 21; config.pin_d4 36; config.pin_d5 39; config.pin_d6 34; config.pin_d7 35; config.pin_xclk 0; config.pin_pclk 22; config.pin_vsync 25; config.pin_href 23; config.pin_sscb_sda 26; config.pin_sscb_scl 27; config.pin_pwdn 32; config.pin_reset -1; #endif esp_err_t err esp_camera_init(config); if (err ! ESP_OK) { Serial.printf(摄像头初始化失败错误码: 0x%x\n, err); return false; } return true; }上面的 GPIO 映射是 AI Thinker ESP32-CAM 常见的引脚定义不同开发板可能不同。许多教程中会直接用CAMERA_MODEL_AI_THINKER宏来控制引脚分配代码里保留两种方式方便对照。FRAMESIZE_VGA表示 640x480 分辨率取证场景下细腻度足够同时文件体积不会太大。PIXFORMAT_JPEG直接输出 JPEG 格式存储和网络发送都更方便。5.4 拍照并保存到 SD 卡bool takePhoto() { camera_fb_t *fb esp_camera_fb_get(); if (!fb) { Serial.println(获取摄像头帧失败); return false; } // 生成时间戳文件名 struct tm timeinfo; char filename[64]; if (!getLocalTime(timeinfo)) { snprintf(filename, sizeof(filename), /photo_%lu.jpg, millis()); } else { strftime(filename, sizeof(filename), /photo_%Y%m%d_%H%M%S.jpg, timeinfo); } // 写入 SD 卡 File file SD_MMC.open(filename, FILE_WRITE); if (!file) { Serial.printf(打开文件失败: %s\n, filename); esp_camera_fb_return(fb); return false; } file.write(fb-buf, fb-len); file.close(); Serial.printf(照片已保存: %s, 大小: %u 字节\n, filename, fb-len); // 释放帧缓冲区 esp_camera_fb_return(fb); return true; }拍照完成后esp_camera_fb_get()返回的缓冲区必须由用户主动释放否则一段时间后摄像头会因内存不足而初始化失败。文件名里加入时间戳可以保证每个文件不会互相覆盖。关于时间第一次上电时 ESP32 并没有正确的时间。为了让文件名携带真实时间建议在代码中启用 NTP 时间同步否则回退到使用millis()作为文件名后缀。具体做法见下文initNTP()函数。5.5 手机通知推送手机通知这块如果使用国内可访问的推送服务可以自己注册一个通知接口。通用做法是让 ESP32 向一个 URL 发起 GET 请求服务器收到请求后把消息推到手机。void sendNotify(const char* message) { WiFiClient client; HTTPClient http; String url String(NOTIFY_URL) desp urlencode(message); http.begin(client, url); int httpCode http.GET(); if (httpCode 0) { Serial.printf(通知发送成功HTTP 状态码: %d\n, httpCode); } else { Serial.printf(通知发送失败错误: %s\n, http.errorToString(httpCode).c_str()); } http.end(); }注意这里用HTTPClient它在 Arduino ESP32 库中已经包含不需要额外安装。如果不想引入第三方服务也可以用邮件 SMTP 方式但代码会更复杂。urlencode函数用于对中文消息进行 URL 编码简单实现如下String urlencode(String msg) { String encoded ; for (size_t i 0; i msg.length(); i) { char c msg.charAt(i); if (isalnum(c) || c - || c _ || c . || c ~) { encoded c; } else { char buf[4]; snprintf(buf, sizeof(buf), %%%02X, c); encoded buf; } } return encoded; }5.6 NTP 时间同步为了让照片文件名和日志带上准确的时间建议在setup()中初始化 NTP。void initNTP() { configTime(8 * 3600, 0, ntp.aliyun.com, cn.pool.ntp.org); Serial.println(正在同步网络时间...); }configTime的第一个参数是时区偏移这里以北京时间 UTC8 为例读者可以根据自己所在时区调整。时间同步是异步的刚开机时个别请求会失败可以循环等待直到时间有效。5.7 主循环逻辑unsigned long lastTriggerTime 0; void loop() { int pirState digitalRead(PIR_PIN); bool pirActive (pirState HIGH); // 蜂鸣器与 LED 状态指示 if (pirActive) { digitalWrite(BUZZER_PIN, HIGH); digitalWrite(LED_PIN, HIGH); } else { digitalWrite(BUZZER_PIN, LOW); digitalWrite(LED_PIN, LOW); } // 触发拍照带静默时间 if (pirActive (millis() - lastTriggerTime TRIGGER_COOLDOWN_MS)) { lastTriggerTime millis(); Serial.println(PIR 触发开始拍照); if (takePhoto()) { sendNotify(检测到包裹区域有人靠近已拍照取证); } } delay(100); }TRIGGER_COOLDOWN_MS设为 30000即触发一次后 30 秒内不会再重复拍照。如果设置过短PIR 传感器可能因为持续检测到人体移动而频繁拍照导致 SD 卡快速写满。如果设置过长又可能漏掉后续关键画面读者可以根据门口实际情况调节。5.8 完整示例代码把这几个函数按顺序组织到一个.ino文件里#include esp_camera.h #include SD_MMC.h #include WiFi.h #include HTTPClient.h #include time.h #define WIFI_SSID your_wifi_ssid #define WIFI_PASSWORD your_wifi_password #define NOTIFY_URL https://sctapi.ftqq.com/SendKey.send?titleNewMessage #define PIR_PIN 13 #define BUZZER_PIN 14 #define LED_PIN 33 #define TRIGGER_COOLDOWN_MS 30000UL unsigned long lastTriggerTime 0; String urlencode(String msg) { String encoded ; for (size_t i 0; i msg.length(); i) { char c msg.charAt(i); if (isalnum(c) || c - || c _ || c . || c ~) { encoded c; } else { char buf[4]; snprintf(buf, sizeof(buf), %%%02X, c); encoded buf; } } return encoded; } void sendNotify(const char* message) { WiFiClient client; HTTPClient http; String url String(NOTIFY_URL) desp urlencode(message); http.begin(client, url); int httpCode http.GET(); if (httpCode 0) { Serial.printf(通知发送成功HTTP 状态码: %d\n, httpCode); } else { Serial.printf(通知发送失败错误: %s\n, http.errorToString(httpCode).c_str()); } http.end(); } void initNTP() { configTime(8 * 3600, 0, ntp.aliyun.com, cn.pool.ntp.org); Serial.println(NTP 时间同步已启动); } bool initCamera() { camera_config_t config; config.ledc_channel LEDC_CHANNEL_0; config.ledc_timer LEDC_TIMER_0; config.pin_d0 5; config.pin_d1 18; config.pin_d2 19; config.pin_d3 21; config.pin_d4 36; config.pin_d5 39; config.pin_d6 34; config.pin_d7 35; config.pin_xclk 0; config.pin_pclk 22; config.pin_vsync 25; config.pin_href 23; config.pin_sscb_sda 26; config.pin_sscb_scl 27; config.pin_pwdn 32; config.pin_reset -1; config.xclk_freq_hz 20000000; config.pixel_format PIXFORMAT_JPEG; config.frame_size FRAMESIZE_VGA; config.jpeg_quality 12; config.fb_count 1; esp_err_t err esp_camera_init(config); if (err ! ESP_OK) { Serial.printf(摄像头初始化失败错误码: 0x%x\n, err); return false; } return true; } bool initSDCard() { if (!SD_MMC.begin()) { Serial.println(SD 卡初始化失败); return false; } return true; } bool takePhoto() { camera_fb_t *fb esp_camera_fb_get(); if (!fb) { Serial.println(获取摄像头帧失败); return false; } struct tm timeinfo; char filename[64]; if (!getLocalTime(timeinfo)) { snprintf(filename, sizeof(filename), /photo_%lu.jpg, millis()); } else { strftime(filename, sizeof(filename), /photo_%Y%m%d_%H%M%S.jpg, timeinfo); } File file SD_MMC.open(filename, FILE_WRITE); if (!file) { Serial.printf(打开文件失败: %s\n, filename); esp_camera_fb_return(fb); return false; } file.write(fb-buf, fb-len); file.close(); Serial.printf(照片已保存: %s, 大小: %u 字节\n, filename, fb-len); esp_camera_fb_return(fb); return true; } void setup() { Serial.begin(115200); Serial.println(设备启动); pinMode(PIR_PIN, INPUT); pinMode(BUZZER_PIN, OUTPUT); pinMode(LED_PIN, OUTPUT); digitalWrite(BUZZER_PIN, LOW); WiFi.begin(WIFI_SSID, WIFI_PASSWORD); while (WiFi.status() ! WL_CONNECTED) { delay(500); Serial.print(.); } Serial.println(\nWiFi 已连接); Serial.print(IP 地址: ); Serial.println(WiFi.localIP()); initNTP(); if (!initCamera()) { Serial.println(摄像头初始化失败请检查接线); } if (!initSDCard()) { Serial.println(SD 卡初始化失败); } lastTriggerTime 0; Serial.println(系统就绪等待 PIR 触发); } void loop() { int pirState digitalRead(PIR_PIN); bool pirActive (pirState HIGH); if (pirActive) { digitalWrite(BUZZER_PIN, HIGH); digitalWrite(LED_PIN, HIGH); } else { digitalWrite(BUZZER_PIN, LOW); digitalWrite(LED_PIN, LOW); } if (pirActive (millis() - lastTriggerTime TRIGGER_COOLDOWN_MS)) { lastTriggerTime millis(); Serial.println(PIR 触发开始拍照); if (takePhoto()) { sendNotify(检测到包裹区域有人靠近已拍照取证); } } delay(100); }上面代码中的 WiFi 信息、通知服务地址都需要替换成读者自己的信息。通知服务不限于某一家只要能通过 URL 触发即可。如果不想用第三方服务也可以保持NOTIFY_URL为空并注释掉sendNotify()调用。6. 运行、测试与验证6.1 编译与上传打开 Arduino IDE选择开发板AI Thinker ESP32-CAM。如果没有该选项可以选择ESP32 Wrover Module或ESP32 Dev Module只要 Flash Size 和 PSRAM 设置正确即可。在“工具 - Flash Size”中选择4MB在“Partition Scheme”中选择Huge APP或默认方案。在“工具 - Port”中选择 USB-TTL 串口对应的 COM 端口。烧录前短接 GPIO0 与 GND点击上传。上传成功后断开 GPIO0 和 GND复位开发板。6.2 观察串口日志打开串口监视器波特率设置为 115200。正常启动后可以看到如下日志设备启动 ...... WiFi 已连接 IP 地址: 192.168.1.123 NTP 时间同步已启动 系统就绪等待 PIR 触发当用手在 PIR 传感器前晃动时应当看到PIR 触发开始拍照 照片已保存: /photo_20250210_153012.jpg, 大小: 102400 字节 通知发送成功HTTP 状态码: 200如果 SD 卡初始化失败日志中会提示SD 卡初始化失败。如果摄像头初始化失败日志中会提示摄像头初始化失败错误码: 0x...。6.3 验证照片内容取出 SD 卡插入电脑查看photo_时间戳.jpg文件。照片应当显示摄像头视角下的现场画面时间戳文件名可以清楚地确认拍摄时间。6.4 验证手机通知触发一次拍照后检查手机是否收到推送消息。不同推送服务的推送速度和显示效果不同一般几秒内能收到。如果长时间未收到先检查串口日志中发送通知的 HTTP 状态码是否为 200再检查通知服务的调用地址是否正确。7. 常见问题与排查问题现象常见原因解决思路烧录失败提示“连接超时”GPIO0 未接地板子没有进入下载模式重新短接 GPIO0 和 GND再点击上传串口输出乱码波特率设置错误统一改为 115200摄像头初始化失败供电不足使用 5V/1A 以上电源供电摄像头初始化失败引脚定义与开发板不匹配确认板子型号按实际引脚重新配置无法连接 WiFiWiFi 信号弱或密码错误检查 SSID 和密码靠近路由器测试SD 卡初始化失败存储卡格式或兼容性问题格式化为 FAT32尝试更换卡SD 卡写入失败文件系统损坏重新格式化 SD 卡PIR 一直触发传感器灵敏度调太高调整 HC-SR501 上的旋转电位器PIR 不触发传感器供电异常或信号引脚接错测量 VCC确认 OUT 引脚连接到 GPIO13通知发送失败通知服务 URL 错误或未联网检查 URL确认 WiFi 已连接照片模糊焦距没有调好旋转摄像头镜头上的调焦环照片偏暗红外灯未开启或环境光线不足可以扩展外接补光灯或增加红外 LED7.1 PIR 传感器灵敏度调节HC-SR501 模块上有两个旋钮一个调节检测距离通常可以覆盖 3 到 7 米范围。另一个调节触发后的保持时间从几秒到几百秒。在实际使用中建议把保持时间调到最小减少单次触发后的等待时间。灵敏度不要调到最大否则很容易被环境温度变化误触发。7.2 SD 卡兼容性ESP32-CAM 的 SD 卡槽对卡的兼容性比较挑剔特别是某些高速卡在 4 位 SDIO 模式下会出错。如果出现初始化失败可以尝试格式化 SD 卡为 FAT32。使用 Class 10 但没有特殊加密功能的卡。检查卡是否插到位注意金属触点方向。7.3 误报问题红外传感器对环境温度变化比较敏感如果安装在阳光直射、空调出风口附近会发生频繁误报。解决方法安装位置避开风口和阳光。将传感器朝向墙角或快递放置区域而不是朝向大范围空场地。在代码中增加多次读取确认逻辑例如连续 3 次读取为高电平才触发。8. 最佳实践与工程建议8.1 合法合规与隐私保护自建监控设备时务必只拍摄自己家的区域比如自家门口、自家院子。不要将摄像头朝向公共走道、邻居门口或公共道路否则可能涉及隐私问题。本项目保存的照片属于个人取证资料建议妥善保管不要随意公开。如果报警处理请配合执法部门提供相关证据不要自行在社交媒体上发布未经处理的露脸照片。8.2 设备防拆与物理安全这个防盗设备本身也可能被人破坏。如果条件允许可以把开发板装进一个小的防水塑料盒中用扎带固定在门上、墙角或隐蔽位置。摄像头镜头要留出开孔红外传感器探头也需要露出。电源线尽量走暗线避免被人直接拔掉电源。8.3 存储容量与循环覆盖SD 卡容量有限长时间运行后会被写满。最简单的办法是在代码中删除 7 天前的旧照片或者定期手动清理。如果希望更自动化可以在每次启动时检查卡剩余容量低于 20MB 时提示用户。8.4 网络与安全加固ESP32 连接 WiFi 后如果开放了调试端口默认情况下不做任何权限校验。本项目没有开放公网端口所以风险相对可控。但即便如此也不要使用公共 WiFi避免程序意外暴露到局域网外。通知服务的 Key 要妥善保管不要写死在公开仓库中。如果长期在线建议在路由器中为设备设置独立的访客网络减少被其他设备攻击的可能性。8.5 省电与待机优化如果需要用电池供电默认代码的功耗较高。可以开启 ESP32 的 Modem Sleep 模式并在 PIR 未触发时关闭摄像头电源。不过ESP32-CAM 开启摄像头后功耗本身不低纯电池供电很难长期运行。更稳妥的方案是使用带常电的 USB 供电并搭配一个 5V 定时开关只在快递送达的高频时间段开启。比如下班前开启睡觉前关闭这样既能覆盖关键时段又能减少不必要的存储占用。8.6 多设备扩展思路如果家里有多个角落需要监控不建议每个角落都放一个 ESP32-CAM。更好的方案是每个位置放一个便宜的 PIR 传感器模块通过 ESP32 收集所有信号统一触发摄像头拍照。或者在现有代码基础上引入 MQTT把事件消息发给 Home Assistant由家庭中心摄像头完成拍照。这个方向需要额外搭建 MQTT Broker适合已经有智能家居基础的用户继续探索。9. 总结与后续扩展本文从一个快递包裹纠纷事件切入带你完成了一个基于 ESP32-CAM 的快递包裹防盗提醒装置。通过这个项目你掌握了人体红外检测的基本原理、ESP32-CAM 摄像头初始化与拍照流程、照片写入 SD 卡的方式以及通过 HTTP 请求推送通知到手机的思路。这套方案不仅可以用在快递包裹防盗上稍加改动还可以变成宠物自动拍照器、老人活动提醒器、车库车辆进入记录仪等。接下来可以尝试的方向把推送信息从纯文本升级为带图片链接的通知。引入 MQTT接入 Home Assistant 智能家居平台。增加离线语音模块让设备能在现场发出语音警告。使用云存储对象把照片自动上传到私有云。遇到代码编译或硬件接线问题时先按文中的排查表逐项检查。自己动手做的设备未必比商业产品精致但正因为所有逻辑都由你自己控制后续的每一次功能扩展都会带来实实在在的成长。如果本文对你有帮助可以收藏备用也欢迎在评论区交流你的实际部署经验。

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价