发帖
0 0 0

安信可小安派BW21-CBV-Kit 超市进门拍照提示门铃

915992026
注册会员

2

主题

1

回帖

168

积分

注册会员

积分
168
小安派·BW21-CBV-KIt 42 0 昨天 20:36
本帖最后由 915992026 于 2025-3-16 20:40 编辑

前几天开箱和环境搭建测试完成,想想这块开发板搭配AI物联网蓝牙话筒内存卡等等结合在一起能实现很多功能,接下来结合例程做一个简单实用的小工具,制作过程很简单,看例程拿来主义搭配在一起,像是搭积木一样多个项目堆在一起就是一个实用工具。使用起来非常方便,对新手友好还实用



超市入口拍照门铃
功能:1、进门提示音“恭喜发财”或者“您已进入监控区域”,
         2、有人进门就拍照(基于移动侦测功能,本来想人脸拍照来着,想想万一头戴丝袜的进去就没法识别了呢)
         3、照片按当前时间存储
         4、可查看监控视角用来调整拍摄角度(就是rtsp串流数据,电脑、手机也能播放,软件都是VLC
优点:1、按照片存储比存储视频节省内存空间
          2、按时间为名称查找方便,不用来回翻找视频
          3、后期程序提升功能空间很大,比如利用话筒蓝牙等功能实现对开发板门铃的参数设置,连接物联网实现监控报警等等


用料
  • BW21-CBV-Kit x 1
  • MicroSD 卡
  • 3.5 毫米 TRS/TRRS 分线器 x 1(例如,Adafruit 2791 / Sparkfun 11570)
  • 小音响、喇叭



实现流程使用读卡器将 SD 卡连接到计算机,然后将 自己想用的MP3门铃提示音 文件复制到 SD 卡中。在#define FILENAME "Audio_test"处,填写存储在 MicroSD 卡上的 MP3 文件名。插上内存卡到开发板。代码内改成自己当前的时间




                               
登录/注册后可看大图

完整代码:
  1. #include <Arduino.h>
  2. #include "WiFi.h"
  3. #include "VideoStream.h"
  4. #include "StreamIO.h"
  5. #include "RTSP.h"
  6. #include "MotionDetection.h"
  7. #include "VideoStreamOverlay.h"
  8. #include "AmebaFatFS.h"
  9. #include "Base64.h"

  10. #include <stdio.h>
  11. #include <time.h>
  12. #include "rtc.h"



  13. // 用户配置
  14. #define CHANNEL   0              // 视频通道用于流媒体和快照
  15. #define CHANNELMD 3              // 仅通道3支持RGB格式低分辨率运动检测

  16. /* Change these values to set the current initial date */
  17. #define YEAR  2020
  18. #define MONTH 1
  19. #define DAY   1
  20. /* Change these values to set the current initial time */
  21. #define HOUR 13
  22. #define MIN  14
  23. #define SEC  15

  24. #define FILENAME "Audio_test"
  25. AmebaFatFS fs;

  26. long long seconds = 0;
  27. struct tm *timeinfo;

  28. char ssid[] = "jifanG";    // 你的WiFi名称
  29. char pass[] = "88888888";        // 你的WiFi密码

  30. // 添加全局变量声明
  31. uint32_t img_addr = 0;  // 声明图像地址变量
  32. uint32_t img_len = 0;   // 声明图像长度变量

  33. // 创建对象
  34. VideoSetting config(VIDEO_D1, CAM_FPS, VIDEO_H264_JPEG, 1);    // 高分辨率视频流配置
  35. VideoSetting configMD(VIDEO_VGA, 10, VIDEO_RGB, 0);            // 低分辨率RGB视频流配置(用于运动检测)
  36. RTSP rtsp;
  37. StreamIO videoStreamer(1, 1);
  38. StreamIO videoStreamerMD(1, 1);
  39. MotionDetection MD;
  40. WiFiSSLClient wifiClient;

  41. // 全局变量
  42. char buf[512];
  43. char *p;
  44. bool flag_motion = false;

  45. // 运动检测结果处理回调函数
  46. void mdPostProcess(std::vector<MotionDetectionResult> md_results)
  47. {
  48.     OSD.createBitmap(CHANNEL);
  49.     if (MD.getResultCount() > 0) {
  50.         for (uint16_t i = 0; i < MD.getResultCount(); i++) {
  51.             MotionDetectionResult result = md_results[i];
  52.             int xmin = (int)(result.xMin() * config.width());
  53.             int xmax = (int)(result.xMax() * config.width());
  54.             int ymin = (int)(result.yMin() * config.height());
  55.             int ymax = (int)(result.yMax() * config.height());
  56.             OSD.drawRect(CHANNEL, xmin, ymin, xmax, ymax, 3, COLOR_GREEN);
  57.         }
  58.         flag_motion = true;
  59.     } else {
  60.         flag_motion = false;
  61.     }
  62.     OSD.update(CHANNEL);
  63.     delay(100);
  64. }

  65. void setup()
  66. {
  67.     Serial.begin(115200);

  68.     // WiFi连接
  69.     while (WiFi.status() != WL_CONNECTED) {
  70.         Serial.print("正在连接WiFi:");
  71.         Serial.println(ssid);
  72.         WiFi.begin(ssid, pass);
  73.         delay(2000);
  74.     }
  75.     WiFiCon();    // 连接成功指示灯闪烁

  76.     // 配置摄像头视频通道
  77.     Camera.configVideoChannel(CHANNEL, config);
  78.     Camera.configVideoChannel(CHANNELMD, configMD);
  79.     Camera.videoInit();

  80.     // 配置RTSP流媒体
  81.     rtsp.configVideo(config);
  82.     rtsp.begin();

  83.     // 配置运动检测模块
  84.     MD.configVideo(configMD);
  85.     MD.setResultCallback(mdPostProcess);
  86.     MD.begin();

  87.     // 配置视频流管道(高分辨率通道→RTSP服务器)
  88.     videoStreamer.registerInput(Camera.getStream(CHANNEL));
  89.     videoStreamer.registerOutput(rtsp);
  90.     if (videoStreamer.begin() != 0) {
  91.         Serial.println("视频流管道启动失败");
  92.     }

  93.     // 启动视频通道
  94.     Camera.channelBegin(CHANNEL);
  95.     Serial.println("RTSP流媒体已启动");

  96.     // 配置视频流管道(低分辨率通道→运动检测模块)
  97.     videoStreamerMD.registerInput(Camera.getStream(CHANNELMD));
  98.     videoStreamerMD.setStackSize();
  99.     videoStreamerMD.registerOutput(MD);
  100.     if (videoStreamerMD.begin() != 0) {
  101.         Serial.println("视频流管道启动失败");
  102.     }

  103.     // 启动低分辨率通道
  104.     Camera.channelBegin(CHANNELMD);
  105.     Serial.println("===============================");
  106.     Serial.println("运动检测系统已启动");
  107.     Serial.println("===============================");
  108.     delay(2000);

  109.     rtc.Init();
  110.     long long epochTime = rtc.SetEpoch(YEAR, MONTH, DAY, HOUR, MIN, SEC);
  111.     rtc.Write(epochTime);
  112. }

  113. void loop()
  114. {
  115.     if (flag_motion) {
  116.         Serial.println("检测到运动!");
  117.         //语音播放
  118.           fs.begin();
  119.           File file1 = fs.open(String(fs.getRootPath()) + String(FILENAME) + String(".mp3"));
  120.           file1.close();
  121.       
  122.         // SD卡初始化
  123.         if (!fs.begin()) {
  124.             StreamEnd();    // 停止所有模块
  125.             pinMode(LED_B, OUTPUT);
  126.             digitalWrite(LED_B, HIGH);    // 错误指示灯常亮
  127.             Serial.println("===============================");
  128.             Serial.println("[错误] SD卡挂载失败!");
  129.             Serial.println("===============================");
  130.             while (1);    // 停止运行
  131.         }

  132.         // 获取当前时间并生成文件名
  133.         long long current_seconds = rtc.Read();
  134.         struct tm *current_timeinfo = localtime(&current_seconds);
  135.         char filename[25];  // 增大缓冲区确保安全
  136.   int ret = snprintf(filename, sizeof(filename), "%04d%02d%02d_%02d%02d%02d.jpg",
  137.                 current_timeinfo->tm_year + 1900,
  138.                 current_timeinfo->tm_mon + 1,
  139.                 current_timeinfo->tm_mday,
  140.                 current_timeinfo->tm_hour,
  141.                 current_timeinfo->tm_min,
  142.                 current_timeinfo->tm_sec);

  143. // 安全检查(同时处理返回值错误和缓冲区溢出)
  144. if (ret < 0) {
  145.     Serial.println("文件名格式错误!");
  146.     return;
  147. }
  148. if (static_cast<unsigned int>(ret) >= sizeof(filename)) {
  149.     Serial.println("文件名生成错误,缓冲区过小!");
  150.     return;
  151. }
  152.         String filepath = String(fs.getRootPath()) + String(filename);

  153.         // 创建并打开文件
  154.         File file = fs.open(filepath);
  155.         if (!file) {
  156.             Serial.println("===============================");
  157.             Serial.println("[错误] 无法创建文件!");
  158.             Serial.println("===============================");
  159.             fs.end();
  160.             return;
  161.         }

  162.         // 拍摄新照片
  163.         CamFlash();    // 拍照指示灯闪烁
  164.         Camera.getImage(CHANNEL, &img_addr, &img_len);
  165.         file.write((uint8_t *)img_addr, img_len);
  166.         file.close();
  167.         Serial.println("===============================");
  168.         Serial.print("[信息] 已保存照片:");
  169.         Serial.println(filename);
  170.         Serial.println("===============================");

  171.         flag_motion = false;    // 重置运动标志
  172.     } else {
  173.         Serial.print(".");    // 无运动时显示进度
  174.     }

  175.     seconds = rtc.Read();
  176.     printEpochTime();
  177.     printBasicString();
  178.     printStringTime();
  179.     Serial.println("----------------------------------------------------------------------");
  180.     rtc.Wait(1);
  181. }

  182. // LED闪烁函数(连接成功提示)
  183. void WiFiCon()
  184. {
  185.     pinMode(LED_B, OUTPUT);
  186.     for (int i = 0; i < 2; i++) {
  187.         digitalWrite(LED_B, HIGH);
  188.         delay(300);
  189.         digitalWrite(LED_B, LOW);
  190.         delay(300);
  191.     }
  192. }

  193. // 拍照指示灯闪烁函数
  194. void CamFlash()
  195. {
  196.     pinMode(LED_G, OUTPUT);
  197.     for (int i = 0; i < 5; i++) {
  198.         digitalWrite(LED_G, HIGH);
  199.         delay(100);
  200.         digitalWrite(LED_G, LOW);
  201.         delay(100);
  202.     }
  203. }

  204. // 停止所有模块函数
  205. void StreamEnd()
  206. {
  207.     videoStreamer.pause();
  208.     videoStreamerMD.pause();
  209.     rtsp.end();
  210.     Camera.channelEnd();
  211.     MD.end();
  212.     Camera.videoDeinit();
  213.     delay(1000);
  214. }

  215. void printEpochTime(void)
  216. {
  217.     Serial.print("Epoch Time(in s) since January, 1, 1970:");
  218.     Serial.print(seconds);
  219.     Serial.print("s");
  220. }

  221. void printBasicString(void)
  222. {
  223.     Serial.println();
  224.     Serial.print("Time as a basic string:                  ");
  225.     Serial.print(ctime(&seconds));
  226. }

  227. void printStringTime(void)
  228. {
  229.     timeinfo = localtime(&seconds);
  230.     Serial.print("Time as a custom formatted string:       ");
  231.     Serial.print(timeinfo->tm_year + 1900);
  232.     Serial.print("-");
  233.     Serial.print(timeinfo->tm_mon + 1);
  234.     Serial.print("-");
  235.     Serial.print(timeinfo->tm_mday);
  236.     Serial.print(" ");
  237.     Serial.print(timeinfo->tm_hour);
  238.     Serial.print(":");
  239.     Serial.print(timeinfo->tm_min);
  240.     Serial.print(":");
  241.     Serial.println(timeinfo->tm_sec);
  242. }
复制代码


实测移动侦测人活动10米以内,挂在墙上完全够用。


参考例程:MotionDetectGoogleLineNotify、Simple_RTC、SDCardPlayMP3
──── 0人觉得很赞 ────

使用道具 举报

您需要登录后才可以回帖 立即登录
高级模式
返回
统计信息
  • 会员数: 28088 个
  • 话题数: 39695 篇