
零基础的嵌入式机器学习:Edge Impulse训练模型移植STM32F407ZGT6实例
第一次接触Edge Impulse这个在线的机器学习网站是在OpenMv口罩识别的历程中,根据OpenMv的官方历程来使用Edge Impulse还是很顺利的。但不久之后就发现如果仅仅是基于OpenMv的历程来进行机器学习,就只能完成图像识别而已,而除了图像识别之外的训练模型如果想要导出到STM32的单片机上,则要通过STM32CubeIDE。STM32CubeIDESTM32CubeIDE是意法
前言
没有机器学习基础但是想利用嵌入式AI?Edge Impulse绝对是不二之选! 算法自动提供,代码一键生成,移植简单方便,简直是小白的福音!如果你打算涉及嵌入式 机器学习,那就快来看看吧!
第一次接触Edge Impulse这个在线的机器学习网站是在OpenMv口罩识别的历程中,根据OpenMv的官方历程来使用Edge Impulse还是很顺利的。但不久之后就发现如果仅仅是基于OpenMv的历程来进行机器学习,就只能完成图像识别而已,而除了图像识别之外的训练模型如果想要导出到STM32的单片机上,则要通过STM32CubeIDE。
STM32CubeIDE
STM32CubeIDE是意法半导体公司推出的STM32集成开发环境,它允许用户在软件上点选相关选项,完成芯片的选型、外设的配置和时钟的配置等设置,自动生成代码并导出,方便实用。关于STM32CubeIDE的安装和使用教程在这里就不赘述,网上的教程很多。
Edge Impulse模型导出步骤
如果你现在有一个已经在Edge Impulse训练好的模型,那么你就可以按照以下步骤部署到STM32的MCU上。
首先在Edge Impulse工程的左侧找到Deployment选项,点选后在右侧选择Cube.MX CMSIS-PACK,然后点击下方的build将PACK包下载下来。
下载下来后找个地方保存好,路径中不要包含中文字符,否则导入时会报错。
打开STM32CubeIDE,新建一个STM32(STM32 Project)的工程,选择需要的芯片,我选择的是STM32F407ZGT6,记得编程语言选择C++。点击Finish创建工程。
选择完毕后,配置好芯片的时钟,在Pinout & Configuration页下点击Software Packs,点击Manage Software Packs。
点击左下角的From Local...,将之前下载下来的PACK包导入。
导入完成后,回到Pinout & Configuration页下的Software Packs,点击Select Components
找到刚刚导入的PACK包,一般有前缀EdgeImpulse标识,下拉找到Core,勾选右边的Selecetion。
勾选完毕后Pinout & Configuration页,在左侧找到Software Packs,在右侧Mode下方勾选。
勾选完毕后CTRL+S保存工程,点击YES,这时候会自动生成代码。
代码生成完毕后在右侧的文件中找到main.c文件。
在main.c中找到USER CODE BEGIN Includes,在BEGIN 和END之间粘贴如下代码:
#include "edge-impulse-sdk/classifier/ei_run_classifier.h"
using namespace ei;
// paste the raw features here
static const float features[] = {
10,9,8,7,6,5,4,3,2,1
};
int get_feature_data(size_t offset, size_t length, float *out_ptr) {
memcpy(out_ptr, features + offset, length * sizeof(float));
return 0;
}
在main.c中找到USER CODE BEGIN 0,在BEGIN 和END之间粘贴如下代码:
#include <stdarg.h>
#include "edge-impulse-sdk/classifier/ei_run_classifier.h"
void vprint(const char *fmt, va_list argp)
{
char string[200];
if(0 < vsprintf(string, fmt, argp)) // build string
{
HAL_UART_Transmit(&huart1, (uint8_t*)string, strlen(string), 0xffffff); // send message via UART
}
}
void ei_printf(const char *format, ...) {
va_list myargs;
va_start(myargs, format);
vprint(format, myargs);
va_end(myargs);
}
在main.c中找到USER CODE BEGIN Init,在BEGIN 和END之间粘贴如下代码:
signal_t signal;
signal.total_length = sizeof(features) / sizeof(features[0]);
signal.get_data = &get_feature_data;
在main.c中找到USER CODE BEGIN Init,在BEGIN 和END之间粘贴如下代码:
ei_impulse_result_t result = { 0 };
EI_IMPULSE_ERROR res = run_classifier(&signal, &result, true);
ei_printf("run_classifier returned: %d\r\n", res);
ei_printf("Predictions (DSP: %d ms., Classification: %d ms., Anomaly: %d ms.): \r\n",
result.timing.dsp, result.timing.classification, result.timing.anomaly);
// print the predictions
ei_printf("[");
for (size_t ix = 0; ix < EI_CLASSIFIER_LABEL_COUNT; ix++) {
ei_printf_float(result.classification[ix].value);
#if EI_CLASSIFIER_HAS_ANOMALY == 1
ei_printf(", ");
#else
if (ix != EI_CLASSIFIER_LABEL_COUNT - 1) {
ei_printf(", ");
}
#endif
}
#if EI_CLASSIFIER_HAS_ANOMALY == 1
ei_printf_float(result.anomaly);
#endif
ei_printf("]\r\n\r\n\r\n");
HAL_Delay(5000);
完成以上步骤之后,将main.c文件改为C++文件,右键点击main.c文件,选择RENAME,将main.c文件更名为main.cpp。
最后,编译工程,这个时间会比较久,会持续几分钟,编译完成后将代码烧录到MCU中,通过串口助手即可看到结果:
以上便是将Edge Impulse上的模型移植到STM32F4上的全部步骤,如果在移植过程中遇到什么问题可以参考Edge Impulse的帮助信息:Edge Impulse帮助信息
更多推荐
所有评论(0)