这是描述信息

esp32模块乐鑫代理报价公司ESP32-S3边缘人工智能加速度计数据识别人体运动

esp32模块乐鑫代理报价公司ESP32-S3边缘人工智能加速度计数据识别人体运动

esp32模块乐鑫代理报价公司ESP32-S3边缘人工智能加速度计数据识别人体运动

esp32模块乐鑫代理报价公司ESP32-S3边缘人工智能加速度计数据识别人体运动

esp32模块乐鑫代理报价公司ESP32-S3边缘人工智能加速度计数据识别人体运动

esp32模块乐鑫代理报价公司ESP32-S3边缘人工智能加速度计数据识别人体运动

边缘计算是一种分布式计算的范例,它指的是在离设备更近的位置进行数据存储和计算。边缘人工智能(边缘AI)是边缘计算的一项令人振奋的成果,它能够使传统技术更加高效地运行,在降低功耗的同时又提供更好的性能。经过训练的神经网络可以在小型设备上进行推理。边缘AI的潜在应用领域包括制造业、医疗保健、零售业、监控、智能家居和金融银行业。


ESP-DL框架由乐鑫提供,可在esp32模块乐鑫代理报价公司ESP32-S3上实现高性能的深度学习模型部署。

本文旨在介绍如何读取传感器数据,并在esp32模块乐鑫代理报价公司ESP32-S3上使用ESP-DL部署深度学习模型。


这篇文章分为以下四个部分:


部署模型
定义模型
运行模型
结论


在深入了解ESP-DL之前,读者需要具备以下基础条件:

学习深度学习的基础知识,以便掌握构建和训练神经网络所需的相关知识。

要设置ESP-IDF release/v4.4环境,请参考ESP-IDF环境设置或ESP-IDF 工具链的更多信息。

C和C++语言应用的基础知识

将模型转换为ESP-DL格式

部署模型

利用加速度计数据来设计卷积神经网络,从而达到人类活动的识别。

本文不会着重介绍神经网络的开发,也不会涉及ESP-DL格式的转换。


1.ESP-IDF是使用C语言开发的,用于开发基于esp32模块乐鑫代理报价公司ESP32和ESP32-S系列芯片的应用程序的开源软件平台。ESP-IDF的项目结构非常清晰,便于开发者理解和使用。


1.1ESP-IDF项目结构模型部署的步骤如下所示:

第一步,我们可以在VSCode中按照ESP-IDF的规范创建一个新项目。对于如何在VSCode中创建ESP32项目的具体指引,请查阅ESP-IDF快速入门指南。

将模型转换为ESP-DL格式后,生成的.cpp和.hpp文件应放置在当前工作目录中。

把所有组件所依赖的目录添加到工作目录下的components文件夹中。

提供ESP-WHO示例的默认配置文件:sdkconfig。该文件也可以在GitHub上找到。

项目目录应如下所示:

├── CMakeLists.txt 
├── components 
│   ├── bus 
│   ├── mpu6050 
│   └── esp-dl 
├── dependencies.lock 
├── main 
│   ├── app_main.cpp 
│   └── CMakeLists.txt 
├── model 
│   ├── Activity_coefficient.cpp 
│   ├── Activity_coefficient.hpp 
│   └── model_define.hpp 
├── partitions.csv 
├── sdkconfig 
├── sdkconfig.defaults 
├── sdkconfig.defaults.esp32 
├── sdkconfig.defaults.esp32s2 
└── sdkconfig.defaults.esp32s3 


2. 定义模型

按下列步骤和步骤说明在 ‘model_define.hpp’ 中定义模型。在 Netron 中打开模型,会出现所示内容。

可视化优化模型


2.1 导入库

导入所有相关库。请点击此处查看ESP-DL 当前支持的库。

#pragma once 
#include "dl_layer_model.hpp" 
#include "dl_layer_base.hpp" 
#include "dl_layer_max_pool2d.hpp" 
#include "dl_layer_conv2d.hpp" 
#include "dl_layer_concat.hpp" 
#include "Activity_coefficient.hpp" 
#include "dl_layer_reshape.hpp" 
#include "dl_layer_softmax.hpp" 
#include <stdint.h> 
 
using namespace dl; 
using namespace layer; 
using namespace Activity_coefficient; 


2.2 声明层

下一步是声明每个层。
输入不算是层,因此不在此处定义。
除了输出层之外,其他所有层都声明为私有层。
class ACTIVITY : public Model<int16_t>  

private: 
    Conv2D<int16_t> l1; 
    Conv2D<int16_t> l2; 
    Reshape<int16_t> l3; 
    Conv2D<int16_t> l4; 
    Conv2D<int16_t> l5; 
 
public: 
    Softmax<int16_t> l6; 


2.3 初始化层

声明层之后,初始化每个层的权重、偏差、激活函数和形状。

ACTIVITY () :  
            l1(Conv2D<int16_t>(-13, get_statefulpartitionedcall_sequential_1_conv2d_2_biasadd_filter(), get_statefulpartitionedcall_sequential_1_conv2d_2_biasadd_bias(), get_statefulpartitionedcall_sequential_1_conv2d_2_biasadd_activation(), PADDING_VALID, {}, 1,1, "l1")), 
            l2(Conv2D<int16_t>(-13, get_statefulpartitionedcall_sequential_1_conv2d_3_biasadd_filter(), get_statefulpartitionedcall_sequential_1_conv2d_3_biasadd_bias(), get_statefulpartitionedcall_sequential_1_conv2d_3_biasadd_activation(), PADDING_VALID, {}, 1,1, "l2")),                        
            l3(Reshape<int16_t>({1,1,2496},"l2_reshape")),  
            l4(Conv2D<int16_t>(-11, get_fused_gemm_0_filter(), get_fused_gemm_0_bias(), get_fused_gemm_0_activation(), PADDING_VALID, {}, 1, 1, "l3")), 
            l5(Conv2D<int16_t>(-9, get_fused_gemm_1_filter(), get_fused_gemm_1_bias(), NULL, PADDING_VALID,{}, 1,1, "l4")), 
            l6(Softmax<int16_t>(-14,"l5")){} 


2.4 构建层

下一步是构建每个层。有关构建层的更多信息,请查看每个层的构建函数。

void build(Tensor<int16_t> &input) 
    { 
        this->l1.build(input); 
        this->l2.build(this->l1.get_output()); 
        this->l3.build(this->l2.get_output()); 
        this->l4.build(this->l3.get_output()); 
        this->l5.build(this->l4.get_output()); 
        this->l6.build(this->l5.get_output()); 
         
    } 


2.5 调用层
将层连接起来,通过调用函数一一调用。有关调用层的更多信息,请查看每个层调用函数。

void call(Tensor<int16_t> &input) 
    { 
        this->l1.call(input); 
        input.free_element(); 
 
        this->l2.call(this->l1.get_output()); 
        this->l1.get_output().free_element(); 
 
        this->l3.call(this->l2.get_output()); 
        this->l2.get_output().free_element(); 
 
        this->l4.call(this->l3.get_output()); 
        this->l3.get_output().free_element(); 
 
        this->l5.call(this->l4.get_output()); 
        this->l4.get_output().free_element(); 
 
        this->l6.call(this->l5.get_output()); 
        this->l5.get_output().free_element(); 
 
    } 
}; 


3. 运行模型
构建好模型后,在 ‘app_main.cpp’ 文件中声明模型输入,并在 ESP32-S3 上运行模型。


3.1 导入库
#include <stdio.h> 
#include <stdlib.h> 
#include "esp_system.h" 
#include "freertos/FreeRTOS.h" 
#include "freertos/task.h" 
#include "dl_tool.hpp" 
#include "model_define.hpp" 
#include "i2c_bus.h" 
#include "mpu6050.h" 
#include "driver/i2c.h" 
#include "esp_log.h" 


3.2 声明输入

神经网络的输入来自 MPU6050 加速度传感器。读取实时的传感器数据需使用乐鑫的 MPU6050 驱动。每四秒钟,传感器数据便会存储在一个数组中,输入到神经网络中进行预测。

int input_height = 80; 
int input_width = 3; 
int input_channel = 1; 
int input_exponent = -13; 
float acc_xyz[240] = {0}; 
int index_acc=0; 
#define I2C_MASTER_SCL_IO 16      /*!< gpio number for I2C master clock */ 
#define I2C_MASTER_SDA_IO 17      /*!< gpio number for I2C master data  */ 
#define I2C_MASTER_NUM I2C_NUM_0  /*!< I2C port number for master dev */ 
#define I2C_MASTER_FREQ_HZ 400000 /*!< I2C master clock frequency */ 
static i2c_bus_handle_t i2c_bus = NULL; 
static mpu6050_handle_t mpu6050 = NULL; 
 
extern "C" void app_main(void) 

    i2c_config_t conf = { 
        .mode = I2C_MODE_MASTER, 
        .sda_io_num = I2C_MASTER_SDA_IO, 
        .scl_io_num = I2C_MASTER_SCL_IO, 
        .sda_pullup_en = GPIO_PULLUP_ENABLE, 
        .scl_pullup_en = GPIO_PULLUP_ENABLE, 
        .clk_flags = 0, 
    }; 
     
    conf.master.clk_speed = I2C_MASTER_FREQ_HZ; 
    i2c_bus = i2c_bus_create(I2C_MASTER_NUM, &conf); 
    mpu6050 = mpu6050_create(i2c_bus, MPU6050_I2C_ADDRESS); 
    uint8_t mpu6050_deviceid; 
    mpu6050_acce_value_t acce; 
    mpu6050_get_deviceid(mpu6050, &mpu6050_deviceid); 
    printf("mpu6050 device ID is: 0x%02x\n", mpu6050_deviceid); 
    mpu6050_set_acce_fs(mpu6050, ACCE_FS_4G); 
while(1){ 
for (int i=0 ;i<80; i++) 

    mpu6050_get_acce(mpu6050, &acce); 
    acc_xyz[index_acc]=acce.acce_x; 
    index_acc=index_acc+1; 
    acc_xyz[index_acc]=acce.acce_y; 
    index_acc=index_acc+1; 
    acc_xyz[index_acc]=acce.acce_z; 
    index_acc=index_acc+1; 
    vTaskDelay(50 / portTICK_RATE_MS); 

index_acc=0; 
int16_t *model_input = (int16_t *)dl::tool::malloc_aligned_prefer(input_height*input_width*input_channel, sizeof(int16_t *)); 
    for(int i=0 ;i<input_height*input_width*input_channel; i++){ 
        float normalized_input = acc_xyz[i] / 1.0; //normalization 
        model_input[i] = (int16_t)DL_CLIP(normalized_input * (1 << -input_exponent), -32768, 32767); 
    } 


3.3 设置输入形状

设置张量中的数据,输入到神经网络。

Tensor<int16_t> input; 
 
input.set_element((int16_t *) model_input).set_exponent(input_exponent).set_shape({input_height,input_width,input_channel}).set_auto_free(false); 


3.4 调用模型

通过调用 forward 方法、传递输入调用模型。使用延迟来计算ESP32-S3 运行神经网络所需的时间。

ACTIVITY model; 
                dl::tool::Latency latency; 
                latency.start(); 
                model.forward(input); 
                latency.end(); 
                latency.print("\nActivity model", "forward");3. Future Directions 


3.5 监控输出

输出来自公共层,即 l6。结果可以在终端中打印出来。

float *score = model.l6.get_output().get_element_ptr(); 
                float max_score = score[0]; 
                int max_index = 0; 
                for (size_t i = 0; i < 6; i++) 
                { 
                    printf("%f, ", score[i]*100); 
                    if (score[i] > max_score) 
                    { 
                        max_score = score[i]; 
                        max_index = i; 
                    } 
                } 
                printf("\n"); 
                switch (max_index) 
                { 
                    case 0: 
                    printf("0: Downstairs"); 
                    break; 
                    case 1: 
                    printf("1: Jogging"); 
                    break; 
                    case 2: 
                    printf("2: Sitting"); 
                    break; 
                    case 3: 
                    printf("3: Standing"); 
                    break; 
                    case 4: 
                    printf("4: Upstairs"); 
                    break; 
                    case 5: 
                    printf("5: Walking"); 
                    break; 
                    default: 
                    printf("No result"); 
                } 
                printf("\n"); 


4.结论

总的来说,这个项目可以为各种应用带来更多的可能性。例如,在工业领域可以用于进行预测性维护,在运动领域可以利用加速度计来识别拳击中的出拳,而在医疗保健领域可以用于跌倒检测。这只是一小部分可以进一步探索的领域。

地址:深圳市宝安区西乡街道麻布社区宝安互联网产业基地A区6栋7栋7706

邮箱:Sales@ferry-semi.com

版权所有©2020  深圳市飞睿科技有限公司  粤ICP备2020098907号    飞睿科技微波雷达wifi模块网站地图

 

免责声明:本网站部分图片和文字内容可能来源于网络,转载目的在于传递更多信息,并不代表本网站赞同其观点或证实其内容的真实性。如涉及作品内容、版权和其它问题,请在30日内与本网站联系,我们将在第一时间删除内容!本站拥有对此声明的最终解释权。