程式碼 - Neil930130/portable-ChatGPT GitHub Wiki

用手機遙控:

`/*******************************************************

  • BLEV7RC_CAR_VIDEO.ino - BLE Remote Control Car Arduino Code
  • Author: Kevin Chen
  • Date: 2023/8/15
  • Version: 1.0.0
  • This code was written by Kevin Chen.
  • This is an open-source program, and it can be freely used, modified, and distributed under the following conditions:
    1. The original copyright notice must not be removed or modified.
    1. Projects or products using this code must acknowledge the original author's name and the source in applicable documentation, websites, or other related materials.
    1. Any derivative work based on this code must state its origin and retain the original copyright notice in its documentation.
    1. This code must not be used for any activities that may infringe upon the rights of others, be unlawful, or harmful, whether in a commercial or non-commercial environment.
  • This code is provided "as is" with no warranty, expressed or implied. The author is not liable for any losses or damages caused by using the code.
  • Users of BLEV7RC_CAR_VIDEO.ino assume all risks associated with its use, and the author shall not be held responsible for any consequences.
  • For more information about our company, please visit: www.makdev.net
  • Example guide:
  • https://www.amebaiot.com/en/amebapro2-arduino-ble-v7rc/ *******************************************************/

#include "BLEDevice.h" #include "WiFi.h" #include "StreamIO.h" #include "VideoStream.h" #include "RTSP.h"

#define UART_SERVICE_UUID "6E400001-B5A3-F393-E0A9-E50E24DCCA9E" #define CHARACTERISTIC_UUID_RX "6E400002-B5A3-F393-E0A9-E50E24DCCA9E" #define CHARACTERISTIC_UUID_TX "6E400003-B5A3-F393-E0A9-E50E24DCCA9E"

#define STRING_BUF_SIZE 100 #define MaxNumValue 2

#define value1 0 #define value2 1

#define MotoA_1A 16 // GPIO #define MotoA_1B 7 // PWM #define MotoB_1A 17 // GPIO #define MotoB_1B 8 // PWM

#define CHANNEL 1

// Default preset configurations for each video channel: // Channel 0 : 1920 x 1080 30FPS H264 // Channel 1 : 1280 x 720 30FPS H264 // Channel 2 : 1920 x 1080 30FPS MJPEG

// VideoSetting config(CHANNEL); VideoSetting config(VIDEO_D1, CAM_FPS, VIDEO_H264, 1); RTSP rtsp1; RTSP rtsp2; StreamIO videoStreamer(1, 2); // 1 Input Video -> 1 Output RTSP

char ssid[] = "CHT150818"; // your network SSID (name) char pass[] = "0976685318"; // your network password int status = WL_IDLE_STATUS;

typedef struct { bool reciveCMDFlag; int ReciveValue; } _rCMD;

BLEService UartService(UART_SERVICE_UUID); BLECharacteristic Rx(CHARACTERISTIC_UUID_RX); BLECharacteristic Tx(CHARACTERISTIC_UUID_TX); BLEAdvertData advdata; BLEAdvertData scndata; bool notify = false; uint8_t Count;

String CMDRefer[5] = {"SS2", "SS4", "SRT", "SR2", "SRV"}; _rCMD bleReciveData[MaxNumValue];

void forward() { digitalWrite(MotoA_1A, 1); analogWrite(MotoA_1B, 5);

digitalWrite(MotoB_1A, 1);
analogWrite(MotoB_1B, 5);

delay(50);

}

void backward() { digitalWrite(MotoA_1A, 0); analogWrite(MotoA_1B, 250);

digitalWrite(MotoB_1A, 0);
analogWrite(MotoB_1B, 250);

delay(50);

}

void turnRight() { digitalWrite(MotoA_1A, 1); analogWrite(MotoA_1B, 5);

digitalWrite(MotoB_1A, 0);
analogWrite(MotoB_1B, 250);

delay(50);

}

void turnLeft() { digitalWrite(MotoA_1A, 0); analogWrite(MotoA_1B, 250);

digitalWrite(MotoB_1A, 1);
analogWrite(MotoB_1B, 5);

delay(50);

}

void BrakeAll() { digitalWrite(MotoA_1A, 0); analogWrite(MotoA_1B, 0);

digitalWrite(MotoB_1A, 0);
analogWrite(MotoB_1B, 0);

delay(50);

}

void readCB(BLECharacteristic* chr, uint8_t connID) { printf("Characteristic %s read by connection %d \n", chr->getUUID().str(), connID); }

void writeCB(BLECharacteristic* chr, uint8_t connID) { // printf("Characteristic %s write by connection %d :\n", chr->getUUID().str(), connID); if (chr->getDataLen() > 0) { ParseCMDString(chr->readString()); // Serial.print("Received string: "); // Serial.print(chr->readString()); // Serial.println(); } }

void notifCB(BLECharacteristic* chr, uint8_t connID, uint16_t cccd) { if (cccd & GATT_CLIENT_CHAR_CONFIG_NOTIFY) { printf("Notifications enabled on Characteristic %s for connection %d \n", chr->getUUID().str(), connID); notify = true; } else { printf("Notifications disabled on Characteristic %s for connection %d \n", chr->getUUID().str(), connID); notify = false; } }

void ParseCMDString(String cmd) { int comdLength = cmd.length(); int chkx; int CMDMaxNUM = sizeof(CMDRefer) / sizeof(String);

for (chkx = 0; chkx < CMDMaxNUM; chkx++) {
    if (cmd.indexOf(CMDRefer[chkx].c_str()) > -1) {
        break;
    }
}

if (chkx >= CMDMaxNUM && cmd.charAt(comdLength - 1) != '#') {
    return;
}

if (cmd.indexOf("SRT") > -1) {
    int x = 3;
    int ValueIndex = 0;

    while (x < (comdLength - 1)) {
        if ((x + 3) < comdLength) {
            String _NumString = cmd.substring(x, (x + 4));
            // Serial.println(_NumString);
            if (ValueIndex < MaxNumValue) {
                if (bleReciveData[ValueIndex].ReciveValue != _NumString.toInt()) {
                    bleReciveData[ValueIndex].ReciveValue = _NumString.toInt();
                    bleReciveData[ValueIndex].reciveCMDFlag = true;
                }
            }
        }
        ValueIndex++;
        x += 4;
    }
}

}

void printInfo(void) { Serial.println("------------------------------"); Serial.println("- Summary of Streaming -"); Serial.println("------------------------------"); Camera.printInfo();

IPAddress ip = WiFi.localIP();

Serial.println("- RTSP -");
Serial.print("rtsp://");
Serial.print(ip);
Serial.print(":");
rtsp1.printInfo();

Serial.print("rtsp://");
Serial.print(ip);
Serial.print(":");
rtsp2.printInfo();

}

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

advdata.addFlags(GAP_ADTYPE_FLAGS_LIMITED | GAP_ADTYPE_FLAGS_BREDR_NOT_SUPPORTED);
advdata.addCompleteName("AMB82-TANK");
scndata.addCompleteServices(BLEUUID(UART_SERVICE_UUID));

Rx.setWriteNRProperty(true);
Rx.setWritePermissions(GATT_PERM_WRITE);
Rx.setWriteCallback(writeCB);
Rx.setBufferLen(STRING_BUF_SIZE);

Tx.setReadProperty(true);
Tx.setReadPermissions(GATT_PERM_READ);
Tx.setReadCallback(readCB);
Tx.setNotifyProperty(true);
Tx.setCCCDCallback(notifCB);
Tx.setBufferLen(STRING_BUF_SIZE);

UartService.addCharacteristic(Rx);
UartService.addCharacteristic(Tx);

BLE.init();
BLE.configAdvert()->setAdvData(advdata);
BLE.configAdvert()->setScanRspData(scndata);
BLE.configServer(1);
BLE.addService(UartService);

BLE.beginPeripheral();

// 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);
}

// Configure camera video channel with video format information
Camera.configVideoChannel(CHANNEL, config);
Camera.videoInit();

// Configure RTSP with identical video format information
rtsp1.configVideo(config);
rtsp1.begin();
rtsp2.configVideo(config);
rtsp2.begin();

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

// Start data stream from video channel
Camera.channelBegin(CHANNEL);

delay(1000);
printInfo();

pinMode(MotoA_1A, OUTPUT);
pinMode(MotoA_1B, OUTPUT);
pinMode(MotoB_1A, OUTPUT);
pinMode(MotoB_1B, OUTPUT);

digitalWrite(MotoA_1A, 0);
digitalWrite(MotoA_1B, 0);
digitalWrite(MotoB_1A, 0);
digitalWrite(MotoB_1B, 0);

}

void loop() { while (Count < MaxNumValue) { if (bleReciveData[Count].reciveCMDFlag) { bleReciveData[Count].reciveCMDFlag = false;

        if (abs(bleReciveData[value1].ReciveValue - 1500) < 100 && abs(bleReciveData[value2].ReciveValue - 1500) < 100) {
            BrakeAll();
        } else if (abs(bleReciveData[value1].ReciveValue - 1500) > abs(bleReciveData[value2].ReciveValue - 1500)) {
            if (bleReciveData[value1].ReciveValue > 1500) {
                turnRight();
                Serial.println("r");
            } else {
                turnLeft();
                Serial.println("L");
            }
        } else {
            if (bleReciveData[value2].ReciveValue > 1500) {
                forward();
                Serial.println("f");
            } else {
                backward();
                Serial.println("b");
            }
        }
    }
    Count++;
}
Count = 0;
delay(1);

}`

AI人臉辨識:

`/*

Example guide: https://www.amebaiot.com/en/amebapro2-arduino-neuralnework-face-recognition-unlock/

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

This example takes snapshot of unrecognised personnel after the Face Registration mode is turned off.

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 "WiFi.h" #include "StreamIO.h" #include "VideoStream.h" #include "RTSP.h" #include "NNFaceDetectionRecognition.h" #include "VideoStreamOverlay.h" #include <AmebaServo.h> #include "AmebaFatFS.h"

#define CHANNELVID 0 // Channel for RTSP streaming #define CHANNELJPEG 1 // Channel for taking snapshots #define CHANNELNN 3 // RGB format video for NN only available on channel 3

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

// Pin Definition #define RED_LED 3 #define GREEN_LED 4 #define BACKUP_FACE_BUTTON_PIN 5 #define EN_REGMODE_BUTTON_PIN 6 #define SERVO_PIN 8

VideoSetting configVID(VIDEO_FHD, 30, VIDEO_H264, 0); VideoSetting configJPEG(VIDEO_FHD, CAM_FPS, VIDEO_JPEG, 1); VideoSetting configNN(NNWIDTH, NNHEIGHT, 10, VIDEO_RGB, 0); NNFaceDetectionRecognition facerecog; RTSP rtsp; StreamIO videoStreamer(1, 1); StreamIO videoStreamerFDFR(1, 1); StreamIO videoStreamerRGBFD(1, 1); AmebaServo myservo;

char ssid[] = "Chen的iPhone"; // your network SSID (name) char pass[] = "BBCHEN710079"; // your network password int status = WL_IDLE_STATUS;

bool doorOpen = false; bool backupButtonState = false; bool RegModeButtonState = false; bool regMode = false; uint32_t img_addr = 0; uint32_t img_len = 0; String fileName; long counter = 0;

// File Initialization AmebaFatFS fs;

void setup() { // GPIO Initialisation pinMode(RED_LED, OUTPUT); pinMode(GREEN_LED, OUTPUT); pinMode(BACKUP_FACE_BUTTON_PIN, INPUT); pinMode(EN_REGMODE_BUTTON_PIN, INPUT); myservo.attach(SERVO_PIN);

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);
}

// Configure camera video channels with video format information
Camera.configVideoChannel(CHANNELVID, configVID);
Camera.configVideoChannel(CHANNELJPEG, configJPEG);
Camera.configVideoChannel(CHANNELNN, configNN);
Camera.videoInit();

// Configure RTSP with corresponding video format information
rtsp.configVideo(configVID);
rtsp.begin();

// Configure Face Recognition model
facerecog.configVideo(configNN);
facerecog.modelSelect(FACE_RECOGNITION, NA_MODEL, DEFAULT_SCRFD, DEFAULT_MOBILEFACENET);
facerecog.begin();
facerecog.setResultCallback(FRPostProcess);

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

// Start data stream from video channel
Camera.channelBegin(CHANNELVID);
Camera.channelBegin(CHANNELJPEG);

// 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(CHANNELVID, configVID);
OSD.begin();

// Restore any registered faces saved in flash
facerecog.restoreRegisteredFace();

// Servo moves to position the angle 180 degree (LOCK CLOSE)
myservo.write(180);

}

void loop() { backupButtonState = digitalRead(BACKUP_FACE_BUTTON_PIN); RegModeButtonState = digitalRead(EN_REGMODE_BUTTON_PIN);

if ((backupButtonState == HIGH) && (regMode == true)) {    // Button is pressed when registration mode is on
    for (int count = 0; count < 3; count++) {
        digitalWrite(RED_LED, HIGH);
        digitalWrite(GREEN_LED, HIGH);
        delay(500);
        digitalWrite(RED_LED, LOW);
        digitalWrite(GREEN_LED, LOW);
        delay(500);
    }
    facerecog.backupRegisteredFace();    // back up registered faces to flash
    regMode = false;                     // Off registration mode
}

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

    if (regMode == true) {
        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();
        }
    }
}

if (regMode == false) {
    digitalWrite(RED_LED, LOW);
    digitalWrite(GREEN_LED, LOW);
    if ((RegModeButtonState == HIGH)) {
        regMode = true;
        digitalWrite(RED_LED, HIGH);
        digitalWrite(GREEN_LED, HIGH);
    }
} else {
    digitalWrite(RED_LED, HIGH);
    digitalWrite(GREEN_LED, HIGH);
}

// Take snapshot and open door for 10 seconds
if ((doorOpen == true) && (regMode == false)) {
    fs.begin();
    File file = fs.open(String(fs.getRootPath()) + fileName + String(++counter) + ".jpg");

    delay(1000);
    Camera.getImage(CHANNELJPEG, &img_addr, &img_len);
    file.write((uint8_t *)img_addr, img_len);
    file.close();
    fs.end();
    myservo.write(0);
    Serial.println("Opening Door!");

    delay(10000);
    myservo.write(180);
    digitalWrite(RED_LED, LOW);
    digitalWrite(GREEN_LED, HIGH);
    doorOpen = false;
}

delay(2000);
OSD.createBitmap(CHANNELVID);
OSD.update(CHANNELVID);

}

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

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

if (facerecog.getResultCount() > 0) {
    if (regMode == false) {
        if (facerecog.getResultCount() > 1) {    // Door remain close when more than one face detected
            doorOpen = false;
            digitalWrite(RED_LED, HIGH);
            digitalWrite(GREEN_LED, LOW);
        } else {
            FaceRecognitionResult face = results[0];
            if (String(face.name()) == String("unknown")) {    // Door remain close when unknown face detected
                doorOpen = false;
                digitalWrite(RED_LED, HIGH);
                digitalWrite(GREEN_LED, LOW);
            } else {    // Door open when a single registered face detected
                doorOpen = true;
                digitalWrite(RED_LED, LOW);
                digitalWrite(GREEN_LED, HIGH);
                fileName = String(face.name());
            }
        }
    }
}

for (int i = 0; i < facerecog.getResultCount(); i++) {
    FaceRecognitionResult item = results[i];
    // 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;

    // Draw boundary box
    if (String(item.name()) == String("unknown")) {
        osd_color = OSD_COLOR_RED;
    } else {
        osd_color = OSD_COLOR_GREEN;
    }
    printf("Face %d name %s:\t%d %d %d %d\n\r", i, item.name(), xmin, xmax, ymin, ymax);
    OSD.drawRect(CHANNELVID, 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());
    OSD.drawText(CHANNELVI`