本帖最后由 915992026 于 2025-3-19 18:20 编辑
前几天开箱和环境搭建测试完成,想想这块开发板搭配AI物联网蓝牙话筒内存卡等等结合在一起能实现很多功能,接下来结合例程做一个简单实用的小工具,制作过程很简单,看例程拿来主义搭配在一起,像是搭积木一样多个项目堆在一起就是一个实用工具。使用起来非常方便,对新手友好还实用
超市入口拍照门铃
功能:1、进门提示音,
2、有人进门就拍照(基于移动侦测功能,本来想人脸拍照来着,想想万一头戴丝袜的进去就没法识别了呢)
3、照片按当前时间存储
4、可查看监控视角用来调整拍摄角度(就是rtsp串流数据,电脑、手机也能播放,软件都是VLC)
优点:1、按照片存储比存储视频节省内存空间
2、按时间为名称查找方便,不用来回翻找视频
3、后期程序提升功能空间很大,比如利用话筒蓝牙等功能实现对开发板门铃的参数设置,连接物联网实现监控报警等等
用料
代码内改成自己当前的时间,PWM输出的声音码根据自己喜好修改
注意:屏幕设置成GC2053
实物接线和展示:
接线就是喇叭接到开发板的INF15和GND引脚
时间和拍照成功串口日志有提示的
拔出内存卡,插在电脑上面可看见有移动物体拍下的照片
视频展示:
飞翔的老宫本刚刚发布的视频https://b23.tv/9UAk9VC
完整代码- #include <Arduino.h>
- #include "WiFi.h"
- #include "VideoStream.h"
- #include "StreamIO.h"
- #include "RTSP.h"
- #include "MotionDetection.h"
- #include "VideoStreamOverlay.h"
- #include "AmebaFatFS.h"
- #include "Base64.h"
- #include <stdio.h>
- #include <time.h>
- #include "rtc.h"
- //蜂鸣器
- #define NOTE_ 0
- #define NOTE_B0 31
- #define NOTE_C1 33
- #define NOTE_CS1 35
- #define NOTE_D1 37
- #define NOTE_DS1 39
- #define NOTE_E1 41
- #define NOTE_F1 44
- #define NOTE_FS1 46
- #define NOTE_G1 49
- #define NOTE_GS1 52
- #define NOTE_A1 55
- #define NOTE_AS1 58
- #define NOTE_B1 62
- #define NOTE_C2 65
- #define NOTE_CS2 69
- #define NOTE_D2 73
- #define NOTE_DS2 78
- #define NOTE_E2 82
- #define NOTE_F2 87
- #define NOTE_FS2 93
- #define NOTE_G2 98
- #define NOTE_GS2 104
- #define NOTE_A2 110
- #define NOTE_AS2 117
- #define NOTE_B2 123
- #define NOTE_C3 131
- #define NOTE_CS3 139
- #define NOTE_D3 147
- #define NOTE_DS3 156
- #define NOTE_E3 165
- #define NOTE_F3 175
- #define NOTE_FS3 185
- #define NOTE_G3 196
- #define NOTE_GS3 208
- #define NOTE_A3 220
- #define NOTE_AS3 233
- #define NOTE_B3 247
- #define NOTE_C4 262
- #define NOTE_CS4 277
- #define NOTE_D4 294
- #define NOTE_DS4 311
- #define NOTE_E4 330
- #define NOTE_F4 349
- #define NOTE_FS4 370
- #define NOTE_G4 392
- #define NOTE_GS4 415
- #define NOTE_A4 440
- #define NOTE_AS4 466
- #define NOTE_B4 494
- #define NOTE_C5 523
- #define NOTE_CS5 554
- #define NOTE_D5 587
- #define NOTE_DS5 622
- #define NOTE_E5 659
- #define NOTE_F5 698
- #define NOTE_FS5 740
- #define NOTE_G5 784
- #define NOTE_GS5 831
- #define NOTE_A5 880
- #define NOTE_AS5 932
- #define NOTE_B5 988
- #define NOTE_C6 1047
- #define NOTE_CS6 1109
- #define NOTE_D6 1175
- #define NOTE_DS6 1245
- #define NOTE_E6 1319
- #define NOTE_F6 1397
- #define NOTE_FS6 1480
- #define NOTE_G6 1568
- #define NOTE_GS6 1661
- #define NOTE_A6 1760
- #define NOTE_AS6 1865
- #define NOTE_B6 1976
- #define NOTE_C7 2093
- #define NOTE_CS7 2217
- #define NOTE_D7 2349
- #define NOTE_DS7 2489
- #define NOTE_E7 2637
- #define NOTE_F7 2794
- #define NOTE_FS7 2960
- #define NOTE_G7 3136
- #define NOTE_GS7 3322
- #define NOTE_A7 3520
- #define NOTE_AS7 3729
- #define NOTE_B7 3951
- #define NOTE_C8 4186
- #define NOTE_CS8 4435
- #define NOTE_D8 4699
- #define NOTE_DS8 4978
- //蜂鸣器
- int melody[] = {
- NOTE_G4, NOTE_G4, NOTE_E4, NOTE_D4, NOTE_E4, NOTE_D4, NOTE_C4,
- NOTE_E4, NOTE_D4, NOTE_C4, NOTE_A3, NOTE_G3, NOTE_A3, NOTE_G3,
- NOTE_A3, NOTE_A3, NOTE_C4, NOTE_A3, NOTE_C4, NOTE_D4, NOTE_E4,
- NOTE_D4, NOTE_D4, NOTE_G4, NOTE_G4, NOTE_E4, NOTE_D4, NOTE_C4};
- //蜂鸣器
- int noteDurations[] = {
- 6, 16, 8, 8, 8, 8, 4,
- 6, 16, 8, 8, 8, 8, 4,
- 6, 16, 8, 8, 8, 8, 4,
- 6, 16, 8, 8, 8, 8, 4};
- // 用户配置(已移除谷歌服务相关配置)
- #define CHANNEL 0 // 视频通道用于流媒体和快照
- #define CHANNELMD 3 // 仅通道3支持RGB格式低分辨率运动检测
- /* Change these values to set the current initial date */
- #define YEAR 2020
- #define MONTH 1
- #define DAY 1
- /* Change these values to set the current initial time */
- #define HOUR 13
- #define MIN 14
- #define SEC 15
- long long seconds = 0;
- struct tm *timeinfo;
- char ssid[] = "jifanG"; // 你的WiFi名称
- char pass[] = "88888888"; // 你的WiFi密码
- // 添加全局变量声明
- uint32_t img_addr = 0; // 声明图像地址变量
- uint32_t img_len = 0; // 声明图像长度变量
- // 创建对象
- VideoSetting config(VIDEO_D1, CAM_FPS, VIDEO_H264_JPEG, 1); // 高分辨率视频流配置
- VideoSetting configMD(VIDEO_VGA, 10, VIDEO_RGB, 0); // 低分辨率RGB视频流配置(用于运动检测)
- RTSP rtsp;
- StreamIO videoStreamer(1, 1);
- StreamIO videoStreamerMD(1, 1);
- MotionDetection MD;
- AmebaFatFS fs;
- WiFiSSLClient wifiClient;
- // 全局变量
- char buf[512];
- char *p;
- bool flag_motion = false;
- // 运动检测结果处理回调函数
- void mdPostProcess(std::vector<MotionDetectionResult> md_results)
- {
- OSD.createBitmap(CHANNEL);
- if (MD.getResultCount() > 0) {
- for (uint16_t i = 0; i < MD.getResultCount(); i++) {
- MotionDetectionResult result = md_results[i];
- int xmin = (int)(result.xMin() * config.width());
- int xmax = (int)(result.xMax() * config.width());
- int ymin = (int)(result.yMin() * config.height());
- int ymax = (int)(result.yMax() * config.height());
- OSD.drawRect(CHANNEL, xmin, ymin, xmax, ymax, 3, COLOR_GREEN);
- }
- flag_motion = true;
- } else {
- flag_motion = false;
- }
- OSD.update(CHANNEL);
- delay(100);
- }
- //蜂鸣器
- void play(int *melody, int *noteDurations, int num)
- {
- for (int note = 0; note < num; note++) {
- int noteDuration = 3000 / noteDurations[note];
- tone(8, melody[note], noteDuration);
- delay(noteDuration * 1.30);
- }
- }
- void setup()
- {
- Serial.begin(115200);
- // WiFi连接
- while (WiFi.status() != WL_CONNECTED) {
- Serial.print("正在连接WiFi:");
- Serial.println(ssid);
- WiFi.begin(ssid, pass);
- delay(2000);
- }
- WiFiCon(); // 连接成功指示灯闪烁
- // 配置摄像头视频通道
- Camera.configVideoChannel(CHANNEL, config);
- Camera.configVideoChannel(CHANNELMD, configMD);
- Camera.videoInit();
- // 配置RTSP流媒体
- rtsp.configVideo(config);
- rtsp.begin();
- // 配置运动检测模块
- MD.configVideo(configMD);
- MD.setResultCallback(mdPostProcess);
- MD.begin();
- // 配置视频流管道(高分辨率通道→RTSP服务器)
- videoStreamer.registerInput(Camera.getStream(CHANNEL));
- videoStreamer.registerOutput(rtsp);
- if (videoStreamer.begin() != 0) {
- Serial.println("视频流管道启动失败");
- }
- // 启动视频通道
- Camera.channelBegin(CHANNEL);
- Serial.println("RTSP流媒体已启动");
- // 配置视频流管道(低分辨率通道→运动检测模块)
- videoStreamerMD.registerInput(Camera.getStream(CHANNELMD));
- videoStreamerMD.setStackSize();
- videoStreamerMD.registerOutput(MD);
- if (videoStreamerMD.begin() != 0) {
- Serial.println("视频流管道启动失败");
- }
- // 启动低分辨率通道
- Camera.channelBegin(CHANNELMD);
- Serial.println("===============================");
- Serial.println("运动检测系统已启动");
- Serial.println("===============================");
- delay(2000);
- rtc.Init();
- long long epochTime = rtc.SetEpoch(YEAR, MONTH, DAY, HOUR, MIN, SEC);
- rtc.Write(epochTime);
- }
- void loop()
- {
- if (flag_motion) {
- Serial.println("检测到运动!");
- play(melody, noteDurations, (sizeof(melody) / sizeof(int)));//播放蜂鸣器
- // SD卡初始化
- if (!fs.begin()) {
- StreamEnd(); // 停止所有模块
- pinMode(LED_B, OUTPUT);
- digitalWrite(LED_B, HIGH); // 错误指示灯常亮
- Serial.println("===============================");
- Serial.println("[错误] SD卡挂载失败!");
- Serial.println("===============================");
- while (1); // 停止运行
- }
- // 获取当前时间并生成文件名
- long long current_seconds = rtc.Read();
- struct tm *current_timeinfo = localtime(¤t_seconds);
- char filename[25]; // 增大缓冲区确保安全
- int ret = snprintf(filename, sizeof(filename), "%04d%02d%02d_%02d%02d%02d.jpg",
- current_timeinfo->tm_year + 1900,
- current_timeinfo->tm_mon + 1,
- current_timeinfo->tm_mday,
- current_timeinfo->tm_hour,
- current_timeinfo->tm_min,
- current_timeinfo->tm_sec);
- // 安全检查(同时处理返回值错误和缓冲区溢出)
- if (ret < 0) {
- Serial.println("文件名格式错误!");
- return;
- }
- if (static_cast<unsigned int>(ret) >= sizeof(filename)) {
- Serial.println("文件名生成错误,缓冲区过小!");
- return;
- }
- String filepath = String(fs.getRootPath()) + String(filename);
- // 创建并打开文件
- File file = fs.open(filepath);
- if (!file) {
- Serial.println("===============================");
- Serial.println("[错误] 无法创建文件!");
- Serial.println("===============================");
- fs.end();
- return;
- }
- // 拍摄新照片
- CamFlash(); // 拍照指示灯闪烁
- Camera.getImage(CHANNEL, &img_addr, &img_len);
- file.write((uint8_t *)img_addr, img_len);
- file.close();
- Serial.println("===============================");
- Serial.print("[信息] 已保存照片:");
- Serial.println(filename);
- Serial.println("===============================");
- flag_motion = false; // 重置运动标志
- } else {
- Serial.print("."); // 无运动时显示进度
- }
- seconds = rtc.Read();
- printEpochTime();
- printBasicString();
- printStringTime();
- Serial.println("----------------------------------------------------------------------");
- rtc.Wait(1);
- }
- // LED闪烁函数(连接成功提示)
- void WiFiCon()
- {
- pinMode(LED_B, OUTPUT);
- for (int i = 0; i < 2; i++) {
- digitalWrite(LED_B, HIGH);
- delay(300);
- digitalWrite(LED_B, LOW);
- delay(300);
- }
- }
- // 拍照指示灯闪烁函数
- void CamFlash()
- {
- pinMode(LED_G, OUTPUT);
- for (int i = 0; i < 5; i++) {
- digitalWrite(LED_G, HIGH);
- delay(100);
- digitalWrite(LED_G, LOW);
- delay(100);
- }
- }
- // 停止所有模块函数
- void StreamEnd()
- {
- videoStreamer.pause();
- videoStreamerMD.pause();
- rtsp.end();
- Camera.channelEnd();
- MD.end();
- Camera.videoDeinit();
- delay(1000);
- }
- void printEpochTime(void)
- {
- Serial.print("Epoch Time(in s) since January, 1, 1970:");
- Serial.print(seconds);
- Serial.print("s");
- }
- void printBasicString(void)
- {
- Serial.println();
- Serial.print("Time as a basic string: ");
- Serial.print(ctime(&seconds));
- }
- void printStringTime(void)
- {
- timeinfo = localtime(&seconds);
- Serial.print("Time as a custom formatted string: ");
- Serial.print(timeinfo->tm_year + 1900);
- Serial.print("-");
- Serial.print(timeinfo->tm_mon + 1);
- Serial.print("-");
- Serial.print(timeinfo->tm_mday);
- Serial.print(" ");
- Serial.print(timeinfo->tm_hour);
- Serial.print(":");
- Serial.print(timeinfo->tm_min);
- Serial.print(":");
- Serial.println(timeinfo->tm_sec);
- }
复制代码
实测移动侦测人活动10米以内,挂在墙上完全够用。
参考例程:MotionDetectGoogleLineNotify、Simple_RTC、PWM_BuzzerPlayMelody
|