news 2026/5/31 18:46:10

STM32嵌入式AI部署实战:从Keras模型到MCU运行的完整指南

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
STM32嵌入式AI部署实战:从Keras模型到MCU运行的完整指南

1. 项目概述:在嵌入式平台上部署AI模型的完整路径

最近几年,我身边越来越多的嵌入式工程师朋友开始焦虑,感觉再不学点AI就要被淘汰了。这种焦虑我特别理解,毕竟从云端到边缘,AI的落地场景越来越广。但说实话,从零开始把一个训练好的模型塞进资源受限的MCU里,对很多习惯了传统嵌入式开发的工程师来说,就像面对一堵无形的墙——知道方向,却找不到门。我自己也是从踩坑中一步步摸索过来的,今天就用一个最经典的线性回归模型作为例子,手把手带你走通从模型训练到在STM32H743上实际运行的完整流程。整个过程我们基于开源的RT-Thread物联网操作系统和ST官方的CubeMX.AI工具链,目标是让你看完就能自己动手复现,真正把AI“嵌入”到你的项目里。

这个项目适合谁呢?首先,当然是那些希望将机器学习能力引入到嵌入式产品中的开发者,比如做智能传感器、预测性维护设备或者轻量级图像识别的朋友。其次,如果你对STM32系列MCU比较熟悉,但还没接触过ST的X-CUBE-AI扩展包,这篇内容会是一个很好的起点。最后,即便你是个AI新手,只要具备基本的Python和C语言知识,也能跟着一步步做下来。我们选择的线性回归模型结构简单,计算量小,非常适合作为第一个“Hello World”级别的嵌入式AI实验,它能让你快速建立起整个部署流程的宏观认知,而不至于一开始就被复杂的卷积网络吓退。

2. 开发环境搭建与核心工具链解析

工欲善其事,必先利其器。嵌入式AI开发的第一步,就是搭建一个稳定、高效的开发环境。我个人的主力开发环境是Ubuntu 18.04 LTS,但为了照顾更广泛的读者,我会同时说明Windows下的关键注意事项,确保两个平台下的实验步骤完全一致。整个工具链的核心是ST(意法半导体)提供的一套免费软件,它们构成了从模型导入到代码生成、调试、烧录的完整闭环。

2.1 核心工具清单与作用

我们先来拆解一下需要用到的几个关键软件,理解它们各自扮演的角色:

  1. STM32CubeMX:这是整个流程的“总指挥”。它是一个图形化的芯片配置工具,用来初始化MCU的时钟、外设(如我们后面会用到的串口),最重要的是,它集成了X-CUBE-AI插件,负责将你的Keras或TensorFlow Lite模型“翻译”成能在STM32上运行的C代码。
  2. STM32CubeIDE:这是ST基于Eclipse打造的集成开发环境。CubeMX生成的工程可以直接导入到这里进行代码编写、编译和调试。它集成了GCC编译器、调试器,对STM32系列的支持非常友好。
  3. STM32CubeProgrammer:这是一个独立的烧录工具。当我们在CubeIDE里把代码编译成.bin.hex文件后,就用这个工具通过ST-LINK调试器把程序烧录到开发板的Flash中。
  4. Java运行环境(JRE):这是CubeMX的运行依赖。在Windows上安装时通常会自动配置好,但在Linux环境下,这里往往是第一个“坑”。

2.2 Ubuntu环境下的关键避坑点:Java配置

很多朋友在Ubuntu上安装好CubeMX后,兴冲冲地双击运行,却弹出一个让人头疼的错误:“Could not find the main class: com.st.app.Main. Program will exit.” 这个问题十有八九出在Java环境上。Ubuntu系统默认安装的是OpenJDK,而STM32CubeMX对Oracle JDK的兼容性更好(尤其是某些版本)。

解决起来并不复杂,但步骤需要准确。我的做法是手动安装Oracle JDK 8(一个比较稳定的版本),并更新系统的默认Java指向。

注意:以下操作需要在终端中执行,并且需要你提前下载好对应版本的JDK压缩包(如jdk-8uXXX-linux-x64.tar.gz)。

# 1. 将下载的JDK解压到系统目录,这里以/usr/lib/jvm为例 sudo tar -zxvf jdk-8u172-linux-x64.tar.gz -C /usr/lib/jvm # 2. 将新安装的Java加入备选列表,并设置优先级(这里设为300) sudo update-alternatives --install /usr/bin/java java /usr/lib/jvm/jdk1.8.0_172/bin/java 300 # 3. 配置系统默认的Java版本,会列出所有已安装的Java,输入对应序号选择我们刚安装的Oracle JDK sudo update-alternatives --config java # 4. 验证配置是否生效,应显示Oracle JDK 1.8的版本信息 java -version

完成这四步后,再启动STM32CubeMX,那个烦人的错误就应该消失了。这个坑我早期遇到过好几次,根本原因在于不同Java虚拟机在库文件加载上的细微差异,换成Oracle官方版本是最稳妥的解决方案。

2.3 获取实验代码与模型

为了让你能快速上手,我准备了一个完整的开源项目仓库,里面包含了训练好的模型、训练脚本(Jupyter Notebook格式)以及最终生成的工程。你不需要从零开始训练模型,可以直接使用现成的。

打开终端,使用git命令克隆仓库到本地:

git clone https://github.com/Lebhoryi/Edge_AI.git cd Edge_AI/Project1

这个Project1目录就是我们本次实验的“大本营”。里面有几个关键文件你需要了解:

  • tf2_linear_regression.ipynb: 这是用TensorFlow 2构建和训练线性回归模型的主笔记本文件。它展示了如何用数据拟合一条直线(y = Wx + b)。
  • tf2_Linear_Regressions_Extended.ipynb: 这是扩展文件,里面演示了三种不同的神经网络构建方式,这一点至关重要,我们稍后会详细讲。
  • model/keras_model.h5: 这是已经训练好并保存为Keras格式的模型文件(.h5后缀)。我们将把这个文件喂给CubeMX.AI。
  • image/: 存放了模型结构图等图片。
  • DNN/: 这个目录是后续由CubeMX自动生成的STM32工程文件夹,一开始是没有的。

3. 模型准备:避开CubeMX.AI的“天坑”

在兴冲冲地把模型丢给CubeMX之前,我们必须先处理好模型本身。这是整个流程中技术含量最高、也最容易出错的一环。很多人部署失败,问题就出在模型导出这一步。我最初也在这里栽了跟头,所以务必仔细看。

3.1 理解Keras的三种模型构建方式

tf2_Linear_Regressions_Extended.ipynb文件中,演示了用Keras API构建模型的三种主流方法:

  1. Sequential(顺序)模型:这是最简单、最直观的方式。你就像搭积木一样,一层一层地往模型里添加网络层。代码看起来像这样:

    model = tf.keras.Sequential([ tf.keras.layers.Dense(units=1, input_shape=[1]) ])

    这种方式定义的模型结构是线性的、一目了然。

  2. Functional API(函数式API):这种方式更灵活,允许你创建具有多输入、多输出或共享层的复杂模型结构。它通过定义层的输入输出来连接网络。

    inputs = tf.keras.Input(shape=(1,)) outputs = tf.keras.layers.Dense(1)(inputs) model = tf.keras.Model(inputs=inputs, outputs=outputs)
  3. Model Subclassing(模型子类化):这是最自由的方式,通过继承tf.keras.Model类来自定义模型的前向传播过程。你可以把Python控制流(如循环、条件判断)直接写到模型里。

    class MyModel(tf.keras.Model): def __init__(self): super(MyModel, self).__init__() self.dense = tf.keras.layers.Dense(units=1) def call(self, inputs): return self.dense(inputs) model = MyModel()

3.2 为什么只能用Sequential模型?——CubeMX.AI的解析限制

现在问题来了:当你把用Functional APIModel Subclassing方式构建并保存的.h5模型文件导入CubeMX.AI时,很大概率会看到这样的报错信息:

INVALID MODEL: Couldn't load Keras model /path/to/your_model.h5, error: Unknown layer: Functional

或者

error: Unknown layer: Model

这个错误的根源在于STM32CubeMX.AI插件的模型解析器(Parser)兼容性有限。在撰写本文时,X-CUBE-AI插件主要针对的是由SequentialModel(特指由Functional API生成的,且具有明确静态图结构的Model)方式定义的、具有清晰静态计算图的模型。而复杂的子类化模型或某些特殊的功能式模型,其内部结构可能无法被CubeMX的转换工具完整识别和展开,因此会被标记为“未知层”。

实操心得:这是嵌入式部署与纯软件AI开发的一个关键差异点。在PC或服务器上,你尽可以使用最灵活、最酷的子类化方法。但在资源受限的嵌入式端,我们首要追求的是确定性可移植性Sequential模型生成的静态计算图最简单、最规整,转换工具处理起来也最可靠。因此,在决定为嵌入式设备训练模型时,从架构设计阶段就要考虑部署约束,优先采用Sequential方式构建网络。

临时解决方案(也是推荐方案):对于这个实验以及绝大多数入门和中级应用,请确保你最终用于部署的模型是使用tf.keras.Sequential()方式构建的。你可以直接使用我提供的model/keras_model.h5文件,它就是用一个简单的Sequential模型(一个全连接层)训练并保存的。它的网络结构简单到可以用一句话描述:输入一个值,经过一个神经元(权重W和偏置b),输出一个预测值。这正是线性回归的神经网络实现。

4. 使用STM32CubeMX.AI生成嵌入式工程

环境搭好了,模型也准备好了,现在进入核心环节:让CubeMX把我们的AI模型“变成”STM32能理解的代码。这个过程大部分是图形化操作,但有几个关键选项直接影响后续开发。

4.1 创建工程与安装AI插件

首先,打开STM32CubeMX,点击New Project。在芯片选择器中,找到并选中STM32H743ZITx(对应NUCLEO-H743ZI开发板)。其实板子型号不是绝对固定的,只要是H7系列且资源足够(有足够的Flash和RAM)的型号都可以,但为了和教程完全一致,减少变量,建议先用同款。

创建工程后,我们先不急着配置时钟和引脚。第一步是安装X-CUBE-AI插件。点击菜单栏的Help->Embedded Software Packages Manager。这会打开一个包管理器窗口。

AllSTMicroelectronics分类下,找到X-CUBE-AI。你会看到一系列版本号,选择可用的最新版本(例如7.1.0),点击Install。安装完成后,点击Close

接下来,需要把这个插件导入到当前工程。在CubeMX主界面的Pinout & Configuration标签页左侧,找到并点击Software Packs。选择STMicroelectronics.X-CUBE-AI,在右边的配置界面,将Selection复选框勾选上。这时,左侧的目录树里就会出现一个X-CUBE-AI的配置项。

4.2 导入与分析AI模型

点击左侧的X-CUBE-AI,右侧会打开其配置面板。点击Add Network按钮。在弹出窗口中,Network Name可以自定义,比如Linear_Reg。在Model类型中选择Keras。然后点击文件浏览按钮,找到并选中我们准备好的keras_model.h5模型文件。

添加成功后,你会看到模型的基本信息。但先别急,我们需要先让CubeMX.AI“分析”一下这个模型。点击配置面板下方的Analyze按钮。这个过程会检查模型的兼容性、计算每一层所需的RAM/Flash大小,并评估在目标MCU上的预期性能。

对于我们这个极简的线性回归模型,分析会瞬间完成。结果会显示在下方窗口,通常包含:

  • Validation: PASSED (表示模型可被转换)
  • Estimated RAM消耗: 可能只有几十个字节。
  • Estimated Flash消耗: 也很小,几KB。
  • Estimated 推理时间: 在H743的高频下,可能只有几个微秒。

看到PASSED,心里就踏实了一大半,说明模型格式被正确识别,且复杂度在当前芯片的能力范围内。

4.3 配置串口用于结果打印

模型分析通过后,我们需要配置一个通信渠道,以便在程序运行时从开发板打印出推理结果。最方便的就是使用串口(UART)。NUCLEO-H743ZI板载的ST-LINK除了调试功能,还虚拟出了一个串口(VCOM),通常映射到MCU的某个USART上。

在CubeMX的Pinout & Configuration视图的左侧目录树,找到Connectivity->USART3(根据板子设计,也可能是USART2,请查阅板子用户手册确认。本实验以USART3为例)。将其模式(Mode)设置为Asynchronous(异步通信)。基本参数通常保持默认(波特率115200, 8位数据,无校验,1位停止位)。

配置好后,你可以在Project Manager标签页设置工程名称、路径、以及IDE。这里有一个关键选择:因为我们在Ubuntu下操作,无法使用Keil MDK,所以必须在Toolchain / IDE下拉菜单中选择STM32CubeIDE。这决定了CubeMX生成的项目文件结构是为CubeIDE定制的。

4.4 生成代码与验证

所有配置检查无误后,点击CubeMX右上角的GENERATE CODE按钮。第一次生成会询问是否同意初始化外设,点击“Yes”。代码生成完成后,可以点击“Open Project”直接在STM32CubeIDE中打开。

但在此之前,CubeMX.AI还提供了一个非常实用的功能:在PC上验证模型转换的正确性。回到X-CUBE-AI配置面板,在Analyze按钮旁边,有一个Validate on Desktop(或在某些版本叫Validate)按钮。点击它,CubeMX.AI会利用你电脑的CPU,模拟在嵌入式环境下的推理过程,并使用一组随机输入数据运行转换后的模型代码,然后将输出结果与原始Keras模型在Python环境下的输出进行对比。

如果验证通过,你会看到输出两组非常接近的数值(由于浮点数精度差异,可能不完全相等),并提示验证成功。这步操作强烈建议执行,它能确保模型转换过程没有引入数学错误,将问题在烧录前就拦截下来。

5. 在STM32CubeIDE中编译、调试与烧录

工程生成后,我们就从配置阶段进入了软件开发阶段。STM32CubeIDE继承了Eclipse的强大功能,同时深度整合了STM32的硬件调试。

5.1 导入与认识生成的工程

如果你没有通过CubeMX直接打开工程,可以手动启动STM32CubeIDE。点击File->Import...,在弹出的对话框中,选择General->Existing Projects into Workspace,点击Next。在Select root directory中,浏览并选中CubeMX生成的那个工程文件夹(例如Project1/DNN)。导入后,项目会出现在左侧的Project Explorer视图中。

展开项目目录,你会看到一个标准的STM32Cube HAL库工程结构,但多了一些AI相关的文件:

  • Application/User/下的app_x-cube-ai.capp_x-cube-ai.h:这是X-CUBE-AI插件生成的核心文件,包含了模型推理的接口函数,如aiInit(),aiRun()
  • Middlewares/ST/AI/:这里存放了AI运行时库(Runtime Library)的头文件和源文件,负责在MCU上高效执行神经网络运算。
  • network.cnetwork_data.c:这两个文件是模型的“本体”。network.c包含了模型各层的计算函数和调用顺序(即计算图),network_data.c则存储了所有训练好的权重(W)和偏置(b)参数。打开network_data.c,你可能会看到一个数组,里面就是你的线性回归模型学到的具体参数值。

5.2 编写应用代码与生成二进制文件

CubeMX和X-CUBE-AI为我们生成了模型推理的“引擎”,但怎么“开车”还需要我们自己写。我们需要在main.c的用户代码区(位于/* USER CODE BEGIN *//* USER CODE END */之间)添加逻辑。

主要步骤通常包括:

  1. 初始化AI引擎:在系统初始化后,调用aiInit()函数。
  2. 准备输入数据:定义一个输入缓冲区(数组),并填充你想要预测的数据。例如,对于线性回归y = Wx + b,我们给x赋值。
  3. 执行推理:调用aiRun()函数,传入输入缓冲区和输出缓冲区的指针。
  4. 处理输出:从输出缓冲区读取推理结果y
  5. 打印结果:通过串口(我们之前配置的USART3)将结果发送到电脑,以便观察。

一个简化的代码片段示例如下:

/* 在文件顶部附近引入AI头文件 */ #include "app_x-cube-ai.h" /* 在main函数内 */ /* USER CODE BEGIN 2 */ /* 初始化AI库 */ if (aiInit() != AI_OK) { Error_Handler(); } /* 定义输入输出缓冲区,根据你的模型IO大小定义 */ AI_ALIGNED(4) float in_data[1] = {2.5f}; // 假设我们要预测x=2.5时的y值 AI_ALIGNED(4) float out_data[1]; /* 创建AI处理对象 */ ai_handle network = AI_HANDLE_NULL; ai_buffer* ai_input; ai_buffer* ai_output; /* 获取网络IO缓冲区信息 */ ai_get_info(network, AI_BUFFER_IN, &ai_input); ai_get_info(network, AI_BUFFER_OUT, &ai_output); /* 准备输入缓冲区 */ ai_input[0].data = AI_HANDLE_PTR(in_data); /* 准备输出缓冲区 */ ai_output[0].data = AI_HANDLE_PTR(out_data); /* 运行推理 */ if (aiRun(network, ai_input, ai_output) != AI_OK) { Error_Handler(); } /* 此时out_data[0]中就是推理结果 */ float predicted_y = out_data[0]; printf("Input x=%.2f, Predicted y=%.2f\r\n", in_data[0], predicted_y); /* USER CODE END 2 */

编写完代码后,点击CubeIDE工具栏上的“锤子”图标进行编译。如果没有错误,你会在工程目录的DebugRelease文件夹下找到生成的.elf文件和.bin文件。这个.bin文件就是我们要烧录到板子里的纯二进制镜像。

5.3 使用STM32CubeProgrammer进行烧录

将NUCLEO-H743ZI开发板通过USB线连接到电脑。打开STM32CubeProgrammer软件。

  1. 在右上角连接方式选择ST-LINK
  2. 点击Connect按钮。如果驱动正常,软件会识别到MCU型号(STM32H743ZITx)。
  3. 连接成功后,点击Open file按钮,选择上一步编译生成的.bin文件。
  4. Start Address处,通常保持默认的0x08000000(这是STM32 Flash的起始地址)。
  5. 点击Download按钮。进度条走完,提示“Download verified successfully”即表示烧录成功。

注意事项:烧录完成后,建议先点击Disconnect断开与编程器的连接。因为ST-LINK的调试接口和虚拟串口有时会冲突,不断开可能导致下一步无法打开串口。

5.4 查看串口输出结果

要看到我们printf打印的结果,需要在电脑上使用一个串口终端工具。在Ubuntu下,我常用minicomcutecom。这里以cutecom为例:

sudo apt-get install cutecom cutecom

打开cutecom后:

  1. Device下拉菜单中,选择你的ST-LINK虚拟串口设备,通常是/dev/ttyACM0/dev/ttyUSB0。如果不确定,可以在终端输入ls /dev/tty*查看,拔插一下USB线,看哪个设备号出现或消失。
  2. 设置波特率为115200(与我们代码中配置的一致),数据位8,停止位1,无校验。
  3. 点击Open打开串口。

然后,按一下开发板上的黑色复位(RESET)按钮。你将在cutecom的接收窗口中看到程序输出的信息,例如:

AI Library Initialized. Input x=2.50, Predicted y=5.12

(具体的y值取决于你模型训练得到的W和b参数)。恭喜你,你的第一个嵌入式AI模型已经成功在MCU上跑起来了!

6. 调试技巧、性能优化与常见问题排查

把模型跑通只是第一步,要让它在实际产品中可靠工作,还需要掌握调试和优化的方法。这里分享一些我实践中积累的经验。

6.1 内存与性能分析实战

在资源受限的嵌入式设备上,内存和速度是永恒的挑战。X-CUBE-AI工具链提供了一些分析手段。

  • CubeMX.AI分析报告:在CubeMX中点击Analyze后生成的报告,给出了RAM、Flash的预估占用。务必关注这两个数值是否超出你目标芯片的可用范围。对于复杂模型,你可能需要选择RAM更大的型号,或者使用模型量化(Quantization)技术来压缩模型。
  • 使用ai_get_info()函数:在运行时,你可以调用此函数获取网络更详细的信息,包括输入输出张量的尺寸、数据类型、内存对齐要求等。这对于动态分配缓冲区非常有用。
  • 性能测量:可以在代码中插入高精度定时器(如STM32的DWT Cycle Counter)来精确测量aiRun()函数执行一次推理所花的CPU周期数,从而换算成实际时间。将测量结果与CubeMX的预估时间对比,是验证性能是否达标的好方法。

6.2 模型输入输出的数据对齐与处理

嵌入式AI推理的输入输出通常是数组(缓冲区)。一个常见的坑是数据对齐。注意看我之前代码示例中的AI_ALIGNED(4)宏,它用于确保数据在内存中是4字节对齐的,这对于ARM Cortex-M内核(特别是使用SIMD指令加速时)的性能至关重要。X-CUBE-AI库的API通常要求缓冲区按特定方式对齐,务必查阅当前版本的库文档。

另一个要点是数据预处理。你的训练数据可能是归一化到[0,1]或标准化后的。在嵌入式端进行推理前,必须对采集到的原始传感器数据(如ADC读数)进行完全相同的预处理,否则输入数据分布不同,会导致推理结果完全错误。这个预处理逻辑需要你用C代码实现在MCU上。

6.3 常见问题排查速查表

下表总结了我遇到的一些典型问题及解决方法:

问题现象可能原因排查步骤与解决方案
CubeMX导入.h5模型失败,报“Unknown layer”1. 模型使用了不支持的构建方式(如子类化)。
2. 模型包含自定义层。
3. Keras/TF版本与CubeMX.AI插件不兼容。
1.确保使用Sequential模式构建和保存模型
2. 检查模型结构,移除任何非标准层。
3. 尝试使用TensorFlow 2.x的稳定版本(如2.4, 2.8)训练和保存模型。
代码编译通过,但链接时报错,提示未定义的AI函数引用1. 未正确链接X-CUBE-AI库。
2. CubeIDE项目配置中库路径错误。
1. 检查CubeMX中是否已成功添加X-CUBE-AI软件包并生成代码。
2. 在CubeIDE项目属性中,检查C/C++ Build->Settings->Tool Settings->MCU GCC Linker->Libraries,确保包含了X-CUBE-AI的库(如-lNetworkRuntime)。
程序运行,但串口无任何输出1. 串口配置错误(引脚、波特率)。
2.printf未重定向到串口。
3. 开发板与电脑连接错误。
1. 核对CubeMX中USART的引脚配置和波特率设置。
2. 确保在CubeIDE中勾选了Use float with printf from newlib-nano(在项目属性MCU Settings中),并且实现了_write系统调用以重定向到HAL_UART_Transmit。
3. 换一个USB口或数据线,用ls /dev/tty*命令确认设备名。
推理结果与Python环境结果差异巨大1. 输入数据未进行相同的预处理。
2. 模型权重在转换过程中出错。
3. 浮点数精度差异被放大。
1.仔细比对嵌入式端和Python端的输入数据预处理代码,必须完全一致
2. 使用CubeMX.AI的Validate on Desktop功能,它能发现大部分转换错误。
3. 对于精度敏感的应用,可以考虑使用定点数(Fixed-point)量化,但会引入额外的转换步骤。
程序运行一段时间后死机或产生硬件错误1. 栈或堆溢出。
2. 内存缓冲区越界访问。
3. AI运行时库所需内存不足。
1. 在CubeMX的Project Settings中适当增加栈(Stack Size)和堆(Heap Size)的大小。
2. 使用调试器检查死机时的程序计数器(PC)和LR寄存器,定位崩溃位置。
3. 确保为AI网络分配的输入输出缓冲区大小足够,且地址对齐。

6.4 从线性回归到更复杂的模型

成功部署线性回归模型后,你已经掌握了最核心的流程。接下来可以尝试更复杂的模型,例如用于分类的全连接神经网络(MLP)甚至是简单的卷积神经网络(CNN)。步骤是完全一样的:

  1. 用Sequential方式在Python中训练并保存模型
  2. 在CubeMX.AI中导入、分析、验证。这时你需要密切关注分析报告中的RAM/Flash占用和预估时间,确保它们在你的硬件预算之内。
  3. 生成代码并集成。对于更复杂的模型,app_x-cube-ai.c中提供的API是通用的,你调用aiRun的方式完全一样,只是需要根据模型的输入输出维度来调整缓冲区大小。

一个进阶的技巧是模型量化。STM32的X-CUBE-AI也支持将浮点模型转换为8位整数(INT8)模型,这能大幅减少模型体积(约75%)并提升推理速度(利用ARM的整数DSP指令),当然会损失一些精度。你可以在CubeMX.AI的配置面板中找到“Quantization”选项进行尝试。

整个流程走下来,我的体会是,嵌入式AI部署就像一座桥,连接了数据科学的“算法世界”和嵌入式的“硬件世界”。最大的障碍往往不是算法本身,而是对两个领域交叉知识的掌握——你得既懂怎么训练和保存一个“友好”的模型,又清楚MCU的内存布局、数据对齐和外设驱动。一旦打通了这个流程,你会发现为产品赋予本地智能的能力,并没有想象中那么遥不可及。下次你可以试试,用同样的流程,把一个手写数字识别(MNIST)的模型部署上去,感受一下让MCU“看见”并识别数字的乐趣。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/5/31 18:44:29

新手必看:CTFShow Web入门题实战复盘(从签到到SQL注入绕过)

CTFShow Web入门实战:从签到到SQL注入绕过的思维跃迁第一次接触CTF比赛时,我被那些看似神秘的Web题目难住了。直到在CTFShow平台上从最简单的签到题开始,一步步解开Web安全的神秘面纱。本文将带你重走这条学习路径,重点分享如何突…

作者头像 李华
网站建设 2026/5/30 12:53:28

终极HsMod插件:55项功能全面优化炉石传说游戏体验

终极HsMod插件:55项功能全面优化炉石传说游戏体验 【免费下载链接】HsMod Hearthstone Modification Based on BepInEx 项目地址: https://gitcode.com/GitHub_Trending/hs/HsMod HsMod是一款基于BepInEx框架开发的炉石传说游戏增强插件,为玩家提…

作者头像 李华
网站建设 2026/5/30 16:15:42

避坑指南:FactoryIO坐标控制误差处理与博图程序急停方案实战

FactoryIO坐标控制误差处理与博图程序急停方案实战指南在工业自动化虚拟调试领域,坐标控制精度与设备安全机制是项目落地的两大核心挑战。许多工程师在使用FactoryIO与博图V16搭建虚拟仓储系统时,常常陷入坐标值比较的精度陷阱,或是面对突发状…

作者头像 李华