Hardware components | ||||||
![]() |
| × | 1 | |||
Software apps and online services | ||||||
![]() |
| |||||
Hand tools and fabrication machines | ||||||
![]() |
|
1 任务前景介绍:
随着科技的日益发展,智能家居已经不是遥不可及的梦想。我们渴望创造一个不仅能让家人更舒适、安全和便捷的家居环境,同时也能让我们的宠物伙伴享受到同等的来自科技的关爱与舒适。随着人们对宠物健康和福祉的关注不断增加,智能宠物监护系统具有广阔的市场潜力。据统计,全球宠物市场规模持续增长,宠物主人对于宠物监护需求日益迫切,因此,这一智能家居方案将能够迎合市场的需求,并有望成为智能家居领域的热门产品。
2 项目需求:
开发一个创新的智能家居方案,通过使用XIAO ESP32S3 Sense开发板结合其他技术栈,为助力宠物在数字化的今天更好的安家乐居提供一套完整的方案。我们特别鼓励创意性、实用性和技术实施性的设计,包括识别宠物的行为模式,关注并优化宠物的日常习惯等,让你的宠物可以更舒适的居住。
3 使用技术栈:
微控制器:XIAO ESP32-S3,提供强大的处理能力和丰富的外设接口。
开源硬件:利用Arduino和ESP32等开源硬件,实现与传感器、执行器等设备的连接和控制。
智能家居系统:采用Home Assistant作为智能家居的控制中心,实现与其他智能设备的互联和协作。
嵌入式TinyML AI工具:利用AI Studio等嵌入式TinyML AI工具,实现在嵌入式设备上运行轻量级的机器学习模型,用于宠物识别和行为监测。
4.实施步骤:
云平台:整合Edge Impulse等云平台,用于模型的训练、优化和部署,实现在云端和边缘端的协同工作。
本项目旨在利用 XIAO ESP32-S3 等开源硬件,结合智能家居系统 Home Assistant、嵌入式 TinyML AI 工具 AI Studio 和云平台 Edge Impulse,实现对宠物的识别和关怀。具体而言,我们将利用 AI Studio 和 Edge Impulse 进行模型训练,然后部署到 XIAO ESP32-S3 上,使其能够实时识别宠物的行为,并根据识别结果自动调节家居环境,提供给宠物一个更舒适、安全的生活环境。
数据采集与准备:
利用 XIAO ESP32-S3 搭建数据采集系统,收集宠物行为数据。
数据预处理,包括数据清洗、特征提取等。
模型训练:
使用 Edge Impulse 平台进行模型训练,选择合适的神经网络模型,例如卷积神经网络(CNN)。
通过 AI Studio 进行数据标注和模型优化,确保模型的准确性和稳定性。
3.模型部署:
将训练好的模型部署到 XIAO ESP32-S3 上,实现实时的物体识别功能。
4.系统测试与优化:
对整个系统进行功能测试和性能评估,确保识别准确率和系统稳定性。
根据测试结果进行系统优化,提高系统的响应速度和识别精度。
6 硬件介绍:
强大的MCU板:采用ESP32S3 32位双核Xtensa处理器芯片,运行频率高达240 MHz,安装多个开发端口,支持Arduino/MicroPython
高级功能:可拆卸的OV2640相机传感器,分辨率为1600*1200,与OV5640相机传感器兼容,内置额外的数字麦克风
精心设计的电源:锂电池充电管理功能,提供4种功耗模式,可实现低至14μA的深度睡眠模式
拥有更多可能性的美好记忆:提供8MB PSRAM和8MB FLASH,支持用于外部32GB FAT内存的SD卡插槽
出色的射频性能:支持2.4GHz Wi-Fi和BLE双无线通信,连接U.FL天线时支持100m+远程通信拇指大小的紧凑型设计:21x17.5mm,采用XIAO的经典外形,适用于可穿戴设备等空间有限的项目来自SenseCraft Al的预训练 Al 模型,无需代码即可部署
7 硬件框图
6 未来的计划建议:
目前已成功实现了物体识别功能,通过 AI Studio 和 Edge Impulse 平台进行模型训练和部署,为智能家居系统带来了强大的物体识别能力。未来会更进一步提升智能系统的功能,未来的规划包括:
宠物识别功能的实现:将致力于开发针对宠物行为的识别模型。通过收集更多的宠物行为数据并进行训练,实现对宠物进食、活动、休息等行为的准确识别。
模型优化和算法改进:将不断优化现有的物体识别模型,并探索更高效、更精确的算法,以提高宠物识别的准确性和实时性。
智能化家居环境调节:结合宠物识别功能,团队将进一步完善智能家居环境调节系统,使其能够根据宠物的行为实时调节家居环境,提供更舒适、安全的生活环境。
与 Home Assistant 的深度集成:团队计划进一步深化与智能家居系统 Home Assistant 的集成,使宠物识别功能与家居环境调节更加无缝,提升宠物主人对宠物生活质量的关注和关怀。
宠物识别
随着科技的日益发展,智能家居已经不是遥不可及的梦想。我们渴望创造一个不仅能让家人更舒适、安全和便捷的家居环境,同时也能让我们的宠物伙伴享受到同等的来自科技的关爱与舒适。随着人们对宠物健康和福祉的关注不断增加,智能宠物监护系统具有广阔的市场潜力。据统计,全球宠物市场规模持续增长,宠物主人对于宠物监护需求日益迫切,因此,这一智能家居方案将能够迎合市场的需求,并有望成为智能家居领域的热门产品。
2 项目需求:
开发一个创新的智能家居方案,通过使用XIAO ESP32S3 Sense开发板结合其他技术栈,为助力宠物在数字化的今天更好的安家乐居提供一套完整的方案。我们特别鼓励创意性、实用性和技术实施性的设计,包括识别宠物的行为模式,关注并优化宠物的日常习惯等,让你的宠物可以更舒适的居住。
3 使用技术栈:
微控制器:XIAO ESP32-S3,提供强大的处理能力和丰富的外设接口。
开源硬件:利用Arduino和ESP32等开源硬件,实现与传感器、执行器等设备的连接和控制。
智能家居系统:采用Home Assistant作为智能家居的控制中心,实现与其他智能设备的互联和协作。
嵌入式TinyML AI工具:利用AI Studio等嵌入式TinyML AI工具,实现在嵌入式设备上运行轻量级的机器学习模型,用于宠物识别和行为监测。
4.实施步骤:
云平台:整合Edge Impulse等云平台,用于模型的训练、优化和部署,实现在云端和边缘端的协同工作。
本项目旨在利用 XIAO ESP32-S3 等开源硬件,结合智能家居系统 Home Assistant、嵌入式 TinyML AI 工具 AI Studio 和云平台 Edge Impulse,实现对宠物的识别和关怀。具体而言,我们将利用 AI Studio 和 Edge Impulse 进行模型训练,然后部署到 XIAO ESP32-S3 上,使其能够实时识别宠物的行为,并根据识别结果自动调节家居环境,提供给宠物一个更舒适、安全的生活环境。
数据采集与准备:
利用 XIAO ESP32-S3 搭建数据采集系统,收集宠物行为数据。
数据预处理,包括数据清洗、特征提取等。
模型训练:
使用 Edge Impulse 平台进行模型训练,选择合适的神经网络模型,例如卷积神经网络(CNN)。
通过 AI Studio 进行数据标注和模型优化,确保模型的准确性和稳定性。
3.模型部署:
将训练好的模型部署到 XIAO ESP32-S3 上,实现实时的物体识别功能。
4.系统测试与优化:
对整个系统进行功能测试和性能评估,确保识别准确率和系统稳定性。
根据测试结果进行系统优化,提高系统的响应速度和识别精度。
6 硬件介绍:
强大的MCU板:采用ESP32S3 32位双核Xtensa处理器芯片,运行频率高达240 MHz,安装多个开发端口,支持Arduino/MicroPython
高级功能:可拆卸的OV2640相机传感器,分辨率为1600*1200,与OV5640相机传感器兼容,内置额外的数字麦克风
精心设计的电源:锂电池充电管理功能,提供4种功耗模式,可实现低至14μA的深度睡眠模式
拥有更多可能性的美好记忆:提供8MB PSRAM和8MB FLASH,支持用于外部32GB FAT内存的SD卡插槽
出色的射频性能:支持2.4GHz Wi-Fi和BLE双无线通信,连接U.FL天线时支持100m+远程通信拇指大小的紧凑型设计:21x17.5mm,采用XIAO的经典外形,适用于可穿戴设备等空间有限的项目来自SenseCraft Al的预训练 Al 模型,无需代码即可部署
7 硬件框图
6 未来的计划建议:
目前已成功实现了物体识别功能,通过 AI Studio 和 Edge Impulse 平台进行模型训练和部署,为智能家居系统带来了强大的物体识别能力。未来会更进一步提升智能系统的功能,未来的规划包括:
宠物识别功能的实现:将致力于开发针对宠物行为的识别模型。通过收集更多的宠物行为数据并进行训练,实现对宠物进食、活动、休息等行为的准确识别。
模型优化和算法改进:将不断优化现有的物体识别模型,并探索更高效、更精确的算法,以提高宠物识别的准确性和实时性。
智能化家居环境调节:结合宠物识别功能,团队将进一步完善智能家居环境调节系统,使其能够根据宠物的行为实时调节家居环境,提供更舒适、安全的生活环境。
与 Home Assistant 的深度集成:团队计划进一步深化与智能家居系统 Home Assistant 的集成,使宠物识别功能与家居环境调节更加无缝,提升宠物主人对宠物生活质量的关注和关怀。

识别
C/C++/* Edge Impulse Arduino examples
* Copyright (c) 2022 EdgeImpulse Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
/* Includes ---------------------------------------------------------------- */
#include <haoo-project-1_inferencing.h>
#include "edge-impulse-sdk/dsp/image/image.hpp"
#include "esp_camera.h"
// Select camera model - find more camera models in camera_pins.h file here
// https://github.com/espressif/arduino-esp32/blob/master/libraries/ESP32/examples/Camera/CameraWebServer/camera_pins.h
#define CAMERA_MODEL_ESP_EYE // Has PSRAM
//#define CAMERA_MODEL_AI_THINKER // Has PSRAM
#if defined(CAMERA_MODEL_ESP_EYE)
#define PWDN_GPIO_NUM -1
#define RESET_GPIO_NUM -1
#define XCLK_GPIO_NUM 4
#define SIOD_GPIO_NUM 18
#define SIOC_GPIO_NUM 23
#define Y9_GPIO_NUM 36
#define Y8_GPIO_NUM 37
#define Y7_GPIO_NUM 38
#define Y6_GPIO_NUM 39
#define Y5_GPIO_NUM 35
#define Y4_GPIO_NUM 14
#define Y3_GPIO_NUM 13
#define Y2_GPIO_NUM 34
#define VSYNC_GPIO_NUM 5
#define HREF_GPIO_NUM 27
#define PCLK_GPIO_NUM 25
#elif defined(CAMERA_MODEL_AI_THINKER)
#define PWDN_GPIO_NUM 32
#define RESET_GPIO_NUM -1
#define XCLK_GPIO_NUM 0
#define SIOD_GPIO_NUM 26
#define SIOC_GPIO_NUM 27
#define Y9_GPIO_NUM 35
#define Y8_GPIO_NUM 34
#define Y7_GPIO_NUM 39
#define Y6_GPIO_NUM 36
#define Y5_GPIO_NUM 21
#define Y4_GPIO_NUM 19
#define Y3_GPIO_NUM 18
#define Y2_GPIO_NUM 5
#define VSYNC_GPIO_NUM 25
#define HREF_GPIO_NUM 23
#define PCLK_GPIO_NUM 22
#else
#error "Camera model not selected"
#endif
/* Constant defines -------------------------------------------------------- */
#define EI_CAMERA_RAW_FRAME_BUFFER_COLS 320
#define EI_CAMERA_RAW_FRAME_BUFFER_ROWS 240
#define EI_CAMERA_FRAME_BYTE_SIZE 3
/* Private variables ------------------------------------------------------- */
static bool debug_nn = false; // Set this to true to see e.g. features generated from the raw signal
static bool is_initialised = false;
uint8_t *snapshot_buf; //points to the output of the capture
static camera_config_t camera_config = {
.pin_pwdn = PWDN_GPIO_NUM,
.pin_reset = RESET_GPIO_NUM,
.pin_xclk = XCLK_GPIO_NUM,
.pin_sscb_sda = SIOD_GPIO_NUM,
.pin_sscb_scl = SIOC_GPIO_NUM,
.pin_d7 = Y9_GPIO_NUM,
.pin_d6 = Y8_GPIO_NUM,
.pin_d5 = Y7_GPIO_NUM,
.pin_d4 = Y6_GPIO_NUM,
.pin_d3 = Y5_GPIO_NUM,
.pin_d2 = Y4_GPIO_NUM,
.pin_d1 = Y3_GPIO_NUM,
.pin_d0 = Y2_GPIO_NUM,
.pin_vsync = VSYNC_GPIO_NUM,
.pin_href = HREF_GPIO_NUM,
.pin_pclk = PCLK_GPIO_NUM,
//XCLK 20MHz or 10MHz for OV2640 double FPS (Experimental)
.xclk_freq_hz = 20000000,
.ledc_timer = LEDC_TIMER_0,
.ledc_channel = LEDC_CHANNEL_0,
.pixel_format = PIXFORMAT_JPEG, //YUV422,GRAYSCALE,RGB565,JPEG
.frame_size = FRAMESIZE_QVGA, //QQVGA-UXGA Do not use sizes above QVGA when not JPEG
.jpeg_quality = 12, //0-63 lower number means higher quality
.fb_count = 1, //if more than one, i2s runs in continuous mode. Use only with JPEG
.fb_location = CAMERA_FB_IN_PSRAM,
.grab_mode = CAMERA_GRAB_WHEN_EMPTY,
};
/* Function definitions ------------------------------------------------------- */
bool ei_camera_init(void);
void ei_camera_deinit(void);
bool ei_camera_capture(uint32_t img_width, uint32_t img_height, uint8_t *out_buf) ;
/**
* @brief Arduino setup function
*/
void setup()
{
// put your setup code here, to run once:
Serial.begin(115200);
//comment out the below line to start inference immediately after upload
while (!Serial);
Serial.println("Edge Impulse Inferencing Demo");
if (ei_camera_init() == false) {
ei_printf("Failed to initialize Camera!\r\n");
}
else {
ei_printf("Camera initialized\r\n");
}
ei_printf("\nStarting continious inference in 2 seconds...\n");
ei_sleep(2000);
}
/**
* @brief Get data and run inferencing
*
* @param[in] debug Get debug info if true
*/
void loop()
{
// instead of wait_ms, we'll wait on the signal, this allows threads to cancel us...
if (ei_sleep(5) != EI_IMPULSE_OK) {
return;
}
snapshot_buf = (uint8_t*)malloc(EI_CAMERA_RAW_FRAME_BUFFER_COLS * EI_CAMERA_RAW_FRAME_BUFFER_ROWS * EI_CAMERA_FRAME_BYTE_SIZE);
// check if allocation was successful
if(snapshot_buf == nullptr) {
ei_printf("ERR: Failed to allocate snapshot buffer!\n");
return;
}
ei::signal_t signal;
signal.total_length = EI_CLASSIFIER_INPUT_WIDTH * EI_CLASSIFIER_INPUT_HEIGHT;
signal.get_data = &ei_camera_get_data;
if (ei_camera_capture((size_t)EI_CLASSIFIER_INPUT_WIDTH, (size_t)EI_CLASSIFIER_INPUT_HEIGHT, snapshot_buf) == false) {
ei_printf("Failed to capture image\r\n");
free(snapshot_buf);
return;
}
// Run the classifier
ei_impulse_result_t result = { 0 };
EI_IMPULSE_ERROR err = run_classifier(&signal, &result, debug_nn);
if (err != EI_IMPULSE_OK) {
ei_printf("ERR: Failed to run classifier (%d)\n", err);
return;
}
// print the predictions
ei_printf("Predictions (DSP: %d ms., Classification: %d ms., Anomaly: %d ms.): \n",
result.timing.dsp, result.timing.classification, result.timing.anomaly);
#if EI_CLASSIFIER_OBJECT_DETECTION == 1
bool bb_found = result.bounding_boxes[0].value > 0;
for (size_t ix = 0; ix < result.bounding_boxes_count; ix++) {
auto bb = result.bounding_boxes[ix];
if (bb.value == 0) {
continue;
}
ei_printf(" %s (%f) [ x: %u, y: %u, width: %u, height: %u ]\n", bb.label, bb.value, bb.x, bb.y, bb.width, bb.height);
}
if (!bb_found) {
ei_printf(" No objects found\n");
}
#else
for (size_t ix = 0; ix < EI_CLASSIFIER_LABEL_COUNT; ix++) {
ei_printf(" %s: %.5f\n", result.classification[ix].label,
result.classification[ix].value);
}
#endif
#if EI_CLASSIFIER_HAS_ANOMALY == 1
ei_printf(" anomaly score: %.3f\n", result.anomaly);
#endif
free(snapshot_buf);
}
/**
* @brief Setup image sensor & start streaming
*
* @retval false if initialisation failed
*/
bool ei_camera_init(void) {
if (is_initialised) return true;
#if defined(CAMERA_MODEL_ESP_EYE)
pinMode(13, INPUT_PULLUP);
pinMode(14, INPUT_PULLUP);
#endif
//initialize the camera
esp_err_t err = esp_camera_init(&camera_config);
if (err != ESP_OK) {
Serial.printf("Camera init failed with error 0x%x\n", err);
return false;
}
sensor_t * s = esp_camera_sensor_get();
// initial sensors are flipped vertically and colors are a bit saturated
if (s->id.PID == OV3660_PID) {
s->set_vflip(s, 1); // flip it back
s->set_brightness(s, 1); // up the brightness just a bit
s->set_saturation(s, 0); // lower the saturation
}
#if defined(CAMERA_MODEL_M5STACK_WIDE)
s->set_vflip(s, 1);
s->set_hmirror(s, 1);
#elif defined(CAMERA_MODEL_ESP_EYE)
s->set_vflip(s, 1);
s->set_hmirror(s, 1);
s->set_awb_gain(s, 1);
#endif
is_initialised = true;
return true;
}
/**
* @brief Stop streaming of sensor data
*/
void ei_camera_deinit(void) {
//deinitialize the camera
esp_err_t err = esp_camera_deinit();
if (err != ESP_OK)
{
ei_printf("Camera deinit failed\n");
return;
}
is_initialised = false;
return;
}
/**
* @brief Capture, rescale and crop image
*
* @param[in] img_width width of output image
* @param[in] img_height height of output image
* @param[in] out_buf pointer to store output image, NULL may be used
* if ei_camera_frame_buffer is to be used for capture and resize/cropping.
*
* @retval false if not initialised, image captured, rescaled or cropped failed
*
*/
bool ei_camera_capture(uint32_t img_width, uint32_t img_height, uint8_t *out_buf) {
bool do_resize = false;
if (!is_initialised) {
ei_printf("ERR: Camera is not initialized\r\n");
return false;
}
camera_fb_t *fb = esp_camera_fb_get();
if (!fb) {
ei_printf("Camera capture failed\n");
return false;
}
bool converted = fmt2rgb888(fb->buf, fb->len, PIXFORMAT_JPEG, snapshot_buf);
esp_camera_fb_return(fb);
if(!converted){
ei_printf("Conversion failed\n");
return false;
}
if ((img_width != EI_CAMERA_RAW_FRAME_BUFFER_COLS)
|| (img_height != EI_CAMERA_RAW_FRAME_BUFFER_ROWS)) {
do_resize = true;
}
if (do_resize) {
ei::image::processing::crop_and_interpolate_rgb888(
out_buf,
EI_CAMERA_RAW_FRAME_BUFFER_COLS,
EI_CAMERA_RAW_FRAME_BUFFER_ROWS,
out_buf,
img_width,
img_height);
}
return true;
}
static int ei_camera_get_data(size_t offset, size_t length, float *out_ptr)
{
// we already have a RGB888 buffer, so recalculate offset into pixel index
size_t pixel_ix = offset * 3;
size_t pixels_left = length;
size_t out_ptr_ix = 0;
while (pixels_left != 0) {
out_ptr[out_ptr_ix] = (snapshot_buf[pixel_ix] << 16) + (snapshot_buf[pixel_ix + 1] << 8) + snapshot_buf[pixel_ix + 2];
// go to the next pixel
out_ptr_ix++;
pixel_ix+=3;
pixels_left--;
}
// and done!
return 0;
}
#if !defined(EI_CLASSIFIER_SENSOR) || EI_CLASSIFIER_SENSOR != EI_CLASSIFIER_SENSOR_CAMERA
#error "Invalid model for current sensor"
#endif
Comments
Please log in or sign up to comment.