发帖
3 0 0

安信可小安派BW21-CBV-Kit 搭配ESP-01S实现人脸控制继电器打开

LV36
论坛元老

11

主题

204

回帖

6269

积分

论坛元老

积分
6269
小安派·BW21-CBV-KIt 30 3 昨天 23:18
本帖最后由 LV36 于 2025-3-25 23:21 编辑

目标:使用安信可小安派BW21-CBV-Kit进行人脸识别,在识别到人脸后开启ESP-01S继电器,继电器模块可自行接用电器。

物料:安信可小安派BW21-CBV-Kit、ESP-01S模块、ESP-01S专用继电器模块、ESP-01S专用烧录器

                               
登录/注册后可看大图

                               
登录/注册后可看大图

代码:AmebaNN—>RTSPFaceRecognition、AmebaHttp—>HTTP_Post_MP4_Whisper_Server、AmebaOTA—>OTA
参考链接:【教程】小安派BW21-CBV-Kit——人脸识别ESP8266 系列——ESP-01S 控制继电器模块


一、ESP-01S模块配置
使用64 位 Windows 10 22H2 平台搭配 Arduino IDE
(1)打开 Arduino IDE  "文件"->"首选项","设置"页面 "附加板管理器 URL"处换行添加“https://arduino.esp8266.com/stable/package_esp8266com_index.json
”(不含“)
(2)"工具"->"开发板"->"开发板管理器" 搜索"ESP8266",点击 "Install(安装)"
坑1:因无法访问外网提示下载失败
解决方案,手动下载离线安装
下载链接:https://pan.baidu.com/s/1_dy7ssId6l6nBfFwBnVsuw?pwd=kxi9 提取码:kxi9
或者https://sourceforge.net/projects/esp8266-arduino-core.mirror/files/3.1.2/esp8266-3.1.2.zip/download
下载后解压至%LOCALAPPDATA%/Arduino15/packages/,并重命名"esp8266-3.1.2"为"esp8266"
文件结构如下:
2025-03-25_224655.png
然后再搜索"ESP8266",点击 "Install(安装)"
(3)使用ESP-01S专用烧录器将ESP-01S与PC连接,在设备管理器确定端口,在开发板列表中找到“Generic ESP8266 Module”,选择对应端口连接并烧录。
示例代码:

#include <ESP8266WiFi.h>

#define RELAY 0    //connected to GPIO0

const char *ssid = "01";    // Enter your router or WiFi SSID here
const char *password = "12345678";    // Enter your router or WiFi password here

WiFiServer server(80);

void setup()
{
    Serial.begin(115200);
    pinMode(RELAY, OUTPUT);    //Set GPIO0 to output mode.
    digitalWrite(RELAY, HIGH);    //Set the GPIO0 output level to high.

    /* Connect to the WiFi network. */
    Serial.println("");
    Serial.print("Conneting to ");
    Serial.println(ssid);
    WiFi.begin(ssid, password);

    while (WiFi.status() != WL_CONNECTED) {     // If the connection to WiFi fails, retry every 500 milliseconds.
        delay(500);
        Serial.print(".");
    }

    Serial.println("");
    Serial.println("WiFi connected.");

    /* Start the Server. */
    server.begin();
    Serial.println("Server started.");

    /* Output of the IP address. */
    Serial.print("Use this URL to connect: ");
    Serial.print("http://");
    Serial.print(WiFi.localIP());
    Serial.println("/");
}

void loop()
{
    /* Check whether a user has established a connection. */
    WiFiClient client = server.available();
    if (!client)
        return;

    /* Wait until the user sends data. */
    Serial.println("new client.");
    while (!client.available())
        delay(1);

    /* Reading the first line of the request. */
    String request = client.readStringUntil('\r');
    Serial.println(request);
    client.flush();

    /* Assignment of the request. */
    int value = HIGH;
    if (request.indexOf("/RELAY=ON") != -1) {
        Serial.println("RELAY=ON");
        digitalWrite(RELAY, LOW);
        value = LOW;
    }
    if (request.indexOf("/RELAY=OFF") != -1) {
        Serial.println("RELAY=OFF");
        digitalWrite(RELAY, HIGH);
        value = HIGH;
    }

    /* Return the answer. */
    client.println("HTTP/1.1 200 OK");
    client.println("Content-Type: text/html");
    client.println("");
    client.println("<!DOCTYPE HTML>");
    client.println("<html>");
    client.println("<meta name='viewport' content='width=device-width, inital-scale=1'>");
    client.println("<head><title>ESP8266 RELAY Control</title></head>");
    client.println("<style>");
    client.println("* {text-align: center; font-family: Conso-las;}");
    client.println("");
    client.println(".container {position: absolute; top: 45%;");
    client.println("left: 50%; transform: translateX(-50%) translateY(-50%);}");
    client.println("");
    client.println(".inner {font-size: 40px;}");
    client.println("");
    client.println("a {display: inline-block; width: 300px; height: 100px;");
    client.println("color: #FFFF00; background-color: #275C6B;");
    client.println("margin-top: 20px; padding: 10px 20px;");
    client.println("text-decoration: none; border-radius: 5px;");
    client.println("font-weight: 800; font-size: 70px;}");
    client.println("</style>");
    client.println("<div class='container'>");
    client.println("<div class='inner'>");
    client.print("RELAY if now: ");

    if (value == HIGH)
        client.print("OFF");
    else
        client.print("ON");

    client.println("<br>");
    client.println("<a href=\"/RELAY=OFF\">OFF</a>");
    client.println("<a href=\"/RELAY=ON\">ON</a>");
    client.println("<style>");
    client.println(".footer-text { font-size: 25px; }");
    client.println(".bold-text { font-weight: bold; }");
    client.println("</style>");
    client.println("<div class='footer'>");
    client.println("<p class='footer-text'>This software was written by <span class='bold-text'>ESP-01S</span>.</p>");
    client.println("</div>");
    client.println("</div>");
    client.println("</html>");
    client.println("");
}




坑2:烧录时提示A fatal esptool.py error occurred: Cannot configure port, something went wrong. Original message: PermissionError(13, '����ϵͳ�ϵ��豸û�з������á�', None, 31)
解决方法:降级自动安装的CH430驱动,下载并打开程序,先卸载再安装。
下载地址:https://sparks.gogo.co.nz/assets/_site_/downloads/CH34x_Install_Windows_v3_4.zip


成功后可通过获取的IP(如192.168.3.250)进行开关控制。
2025-03-25_225442.png

二、安信可小安派BW21-CBV-Kit配置
打开文件—>示例—>AmebaNN—>RTSPFaceRecognition
以此为基础进行修改
示例代码:

/*

Example guide:
https://www.amebaiot.com/en/ameb ... k-face-recognition/

Face registration commands
--------------------------
Point the camera at a target face and enter the following commands into the serial monitor,
Register face:                       "REG={Name}"  Ensure that there is only one face detected in frame
Remove face:                         "DEL={Name}"  Remove a registered face
Reset registered faces:              "RESET"       Forget all previously registered faces
Backup registered faces to flash:    "BACKUP"      Save registered faces to flash
Restore registered faces from flash: "RESTORE"     Load registered faces from flash

NN Model Selection
-------------------
Select Neural Network(NN) task and models using modelSelect(nntask, objdetmodel, facedetmodel, facerecogmodel).
Replace with NA_MODEL if they are not necessary for your selected NN Task.

NN task
=======
OBJECT_DETECTION/ FACE_DETECTION/ FACE_RECOGNITION

Models
=======
YOLOv3 model         DEFAULT_YOLOV3TINY   / CUSTOMIZED_YOLOV3TINY
YOLOv4 model         DEFAULT_YOLOV4TINY   / CUSTOMIZED_YOLOV4TINY
YOLOv7 model         DEFAULT_YOLOV7TINY   / CUSTOMIZED_YOLOV7TINY
SCRFD model          DEFAULT_SCRFD        / CUSTOMIZED_SCRFD
MobileFaceNet model  DEFAULT_MOBILEFACENET/ CUSTOMIZED_MOBILEFACENET
No model             NA_MODEL

*/
#include <OTA.h>
#include <HttpClient.h>
#include "WiFi.h"
#include "StreamIO.h"
#include "VideoStream.h"
#include "RTSP.h"
#include "NNFaceDetectionRecognition.h"
#include "VideoStreamOverlay.h"

#define CHANNEL   0
#define CHANNELNN 3

// Customised resolution for NN
#define NNWIDTH  576
#define NNHEIGHT 320

VideoSetting config(VIDEO_FHD, 30, VIDEO_H264, 0);
VideoSetting configNN(NNWIDTH, NNHEIGHT, 10, VIDEO_RGB, 0);
NNFaceDetectionRecognition facerecog;
RTSP rtsp;
StreamIO videoStreamer(1, 1);
StreamIO videoStreamerFDFR(1, 1);
StreamIO videoStreamerRGBFD(1, 1);

char ssid[] = "01";    // your network SSID (name)
char pass[] = "12345678";        // your network password
int keyIndex = 0;                // your network key Index number (needed only for WEP)
int status = WL_IDLE_STATUS;

OTA ota;

WiFiClient wifiClient;

int port = 3000;
char* server = "192.168.3.248";

char* kHostname = "192.168.3.250";
char* kPath = "/RELAY=ON/";

// Number of milliseconds to wait without receiving any data before we give up
const int kNetworkTimeout = 30 * 1000;
// Number of milliseconds to wait if no data is available before trying again
const int kNetworkDelay = 1000;

IPAddress ip;
int rtsp_portnum;

void setup()
{
    Serial.begin(115200);

    // Attempt to connect to Wifi network:
    while (status != WL_CONNECTED) {
        Serial.print("Attempting to connect to WPA SSID: ");
        Serial.println(ssid);
        status = WiFi.begin(ssid, pass);

        // wait 2 seconds for connection:
        delay(2000);
    }

    ip = WiFi.localIP();

    // Configure camera video channels with video format information
    // Adjust the bitrate based on your WiFi network quality
    config.setBitrate(2 * 1024 * 1024);    // Recommend to use 2Mbps for RTSP streaming to prevent network congestion
    Camera.configVideoChannel(CHANNEL, config);
    Camera.configVideoChannel(CHANNELNN, configNN);
    Camera.videoInit();

    // Configure RTSP with corresponding video format information
    rtsp.configVideo(config);
    rtsp.begin();
    rtsp_portnum = rtsp.getPort();

    // Configure Face Recognition model
    // Select Neural Network(NN) task and models
    facerecog.configVideo(configNN);
    facerecog.modelSelect(FACE_RECOGNITION, CUSTOMIZED_MOBILEFACENET, CUSTOMIZED_SCRFD, CUSTOMIZED_MOBILEFACENET);
    facerecog.begin();
    facerecog.setResultCallback(FRPostProcess);

    // Configure StreamIO object to stream data from video channel to RTSP
    videoStreamer.registerInput(Camera.getStream(CHANNEL));
    videoStreamer.registerOutput(rtsp);
    if (videoStreamer.begin() != 0) {
        Serial.println("StreamIO link start failed");
    }
    // Start data stream from video channel
    Camera.channelBegin(CHANNEL);

    // Configure StreamIO object to stream data from RGB video channel to face detection
    videoStreamerRGBFD.registerInput(Camera.getStream(CHANNELNN));
    videoStreamerRGBFD.setStackSize();
    videoStreamerRGBFD.setTaskPriority();
    videoStreamerRGBFD.registerOutput(facerecog);
    if (videoStreamerRGBFD.begin() != 0) {
        Serial.println("StreamIO link start failed");
    }

    // Start video channel for NN
    Camera.channelBegin(CHANNELNN);

    // Start OSD drawing on RTSP video channel
    OSD.configVideo(CHANNEL, config);
    OSD.begin();

    Serial.println("Connected to wifi");
    printWifiStatus();

    ota.start_OTA_threads(port, server);
}

void loop()
{
    if (Serial.available() > 0) {
        String input = Serial.readString();
        input.trim();

        if (input.startsWith(String("REG="))) {
            String name = input.substring(4);
            facerecog.registerFace(name);
        } else if (input.startsWith(String("DEL="))) {
            String name = input.substring(4);
            facerecog.removeFace(name);
        } else if (input.startsWith(String("RESET"))) {
            facerecog.resetRegisteredFace();
        } else if (input.startsWith(String("BACKUP"))) {
            facerecog.backupRegisteredFace();
        } else if (input.startsWith(String("RESTORE"))) {
            facerecog.restoreRegisteredFace();
        }
    }

    delay(2000);
    OSD.createBitmap(CHANNEL);
    OSD.update(CHANNEL);
}

// User callback function for post processing of face recognition results
void FRPostProcess(std::vector<FaceRecognitionResult> results)
{
    uint16_t im_h = config.height();
    uint16_t im_w = config.width();

    Serial.print("Network URL for RTSP Streaming: ");
    Serial.print("rtsp://");
    Serial.print(ip);
    Serial.print(":");
    Serial.println(rtsp_portnum);
    Serial.println(" ");

    printf("Total number of faces detected = %d\r\n", facerecog.getResultCount());
    OSD.createBitmap(CHANNEL);

    if (facerecog.getResultCount() > 0) {
        for (int i = 0; i < facerecog.getResultCount(); i++) {
            FaceRecognitionResult item = results;
            // Result coordinates are floats ranging from 0.00 to 1.00
            // Multiply with RTSP resolution to get coordinates in pixels
            int xmin = (int)(item.xMin() * im_w);
            int xmax = (int)(item.xMax() * im_w);
            int ymin = (int)(item.yMin() * im_h);
            int ymax = (int)(item.yMax() * im_h);

            uint32_t osd_color;
            if (String(item.name()) == String("unknown")) {
                osd_color = OSD_COLOR_RED;
            } else {
                osd_color = OSD_COLOR_GREEN;
            }

            // Draw boundary box
            printf("Face %d name %s:\t%d %d %d %d\n\r", i, item.name(), xmin, xmax, ymin, ymax);
            OSD.drawRect(CHANNEL, xmin, ymin, xmax, ymax, 3, osd_color);

            // Print identification text above boundary box
            char text_str[40];
            snprintf(text_str, sizeof(text_str), "Face:%s", item.name());
            webpost();
            OSD.drawText(CHANNEL, xmin, ymin - OSD.getTextHeight(CHANNEL), text_str, osd_color);
        }
    }
    OSD.update(CHANNEL);
}

void webpost() {
  if (wifiClient.connect(kHostname,80)) {
    wifiClient.println("POST " + String(kPath) + " HTTP/1.1");
    wifiClient.println("Host: " + String(kHostname));
    wifiClient.println(); // 空行表示HTTP头部结束
    Serial.println("Data sent to ESP");
  } else {
    Serial.println("Failed to connect to ESP");
  }
  wifiClient.stop(); // 关闭连接
}

void printWifiStatus()
{
    // print the SSID of the network you're attached to:
    Serial.print("SSID: ");
    Serial.println(WiFi.SSID());

    // print your WiFi shield's IP address:
    IPAddress ip = WiFi.localIP();
    Serial.print("IP Address: ");
    Serial.println(ip);

    // print the received signal strength:
    long rssi = WiFi.RSSI();
    Serial.print("signal strength (RSSI):");
    Serial.print(rssi);
    Serial.println(" dBm");
}




实现在识别到人脸时向
ESP-01S模块发送RELAY=ON,打开继电器。
由于设置了OTA,需要搭配TF卡运行。TF卡文件如下:
2025-03-25_132527.png
文件夹及文件名固定,可使用默认文件,可在类似C:\Users\Administrator\AppData\Local\Arduino15\packages\realtek\tools\ameba_pro2_tools\1.4.1文件夹找到


实现效果:
bandicam 2025-03-25 22-14-58-488 00_00_00-00_00_30.gif




──── 0人觉得很赞 ────

使用道具 举报

棒~
好玩
您需要登录后才可以回帖 立即登录
高级模式
返回
统计信息
  • 会员数: 28169 个
  • 话题数: 39965 篇