- 2025-04-08
-
发表了主题帖:
【嵌入式 Rust 修炼营】串口烧录
本帖最后由 lijinlei 于 2025-4-8 07:28 编辑
# 【嵌入式 Rust 修炼营】串口烧录
本文介绍了 Rust 语言实现 PY32F030 开发板的工程串口烧录测试。
## 克隆工程
终端执行指令如下
```bash
git clone https://github.com/hysonglet/py32f030-hal.git
```
进入工程目录
```bash
cd ...\py32f030-hal\examples
```
## 代码
这里测试 `uart.rs` 串口打印工程
```rust
#![no_std]
#![no_main]
use heapless::String;
use py32f030_hal::{self as hal, prelude::*, usart::AnyUsart};
use {defmt::info, defmt_rtt as _, panic_probe as _};
#[cortex_m_rt::entry]
fn main() -> ! {
let p = hal::init(Default::default());
let gpioa = p.GPIOA.split();
let tx = gpioa.PA9;
let rx = gpioa.PA10;
let usart = AnyUsart::new(p.USART1, Some(rx), Some(tx), None, None, Default::default());
let (_, mut tx) = usart.split();
info!("usart start...");
let buf: String = "hello rust\r\n".into();
loop {
// 使用标准接口来发送串口数据
let _ = write!(tx, "example for usart\r\n");
// 使用自定义的驱动接口发送串口数据
let _ = tx.write(buf.as_bytes());
info!("send: {} ", buf.as_bytes());
cortex_m::asm::delay(1000 * 1000 * 10);
}
}
```
## 工程编译
```bash
cargo build --example uart
```
## 生成固件
二进制转化
```bash
cargo objcopy --example uart -- -O binary uart.bin
```
这里需要注意安装依赖和工具
```bash
cargo install cargo-binutils
rustup component add llvm-tools
```
## 固件上传
硬件连接开发板与电脑,
检查设备管理器中串口对应的端口号
```bash
pyisp -p
```
执行烧录指令
```bash
pyisp -s COM6 -f uart.bin -g
```
若出错,可检查 `pyisp` 串口烧录工具是否安装成功
```bash
cargo install --git https://github.com/hysonglet/pyisp.git
```
按住 BOOT 键的同时,短按 RST 键,即可实现串口烧录
烧录完成,短按 RST 键即可运行程序。
## 效果展示
使用串口调试助手打开开发板设备对应的串口号(波特率 115200 bps)收到相应的串口打印信息
## 总结
本文介绍了 Rust 语言实现 PY32F030 开发板的工程串口烧录测试,包括工程克隆、工程编译、固件上传、效果展示等流程,为后续开发和相关应用提供了参考。
-
发表了主题帖:
【嵌入式 Rust 修炼营】数组排序
本文介绍了 Rust 语言实现数组排序的主要流程。
## 新建工程
Rust 环境搭建流程详见前面的帖子:[【嵌入式 Rust 修炼营】Rust 介绍、环境搭建、开发板介绍 - 嵌入式系统 - 电子工程世界-论坛](https://bbs.eeworld.com.cn/thread-1310079-1-1.html)
打开项目存储的目标文件夹,右键选择 `在终端中打开` ,执行新建工程指令
```bash
cargo new array_sort
```
使用 VSCode 打开工程目录,编辑 `main.rs` 文件
## 工程代码
通过数组、循环、判断等基本操作,实现数组的排序和打印
```rust
fn bubble_sort(arr: &mut [T]) {
let len = arr.len();
for i in 0..len {
for j in 0..len - i - 1 {
if arr[j] > arr[j + 1] {
arr.swap(j, j + 1);
}
}
}
}
fn main() {
println!("This is sort of a test!");
let mut test_numers = vec![9,8,4,5,3,2,7,6,1];
println!("Before sorting: {:?}", test_numers);
bubble_sort(&mut test_numers);
println!("After sorting: {:?}", test_numers);
}
```
## 编译执行
终端执行
```bash
cargo build
cargo run
```
对工程进行构建和执行,输出相应的数组排序结果。
## 效果展示
终端输出源数组和排序结果。
## 总结感悟
本文介绍了 Rust 语言实现数组排序的主要流程,包括新建工程、工程代码、编译和执行程序、效果展示等,为后续的深入开发奠定基础。
- 2025-04-03
-
发表了主题帖:
AiCube 试用 - 创建流水灯工程
# AiCube 试用 - 创建流水灯工程
本文介绍了 Aiapp-ISP 仿真调试平台软件的 **AiCube** 工具,实现流水灯工程的快速创建的主要流程。
## 下载运行
[下载](https://www.stcai.com/gjrj) 最新版 `AIapp-ISP` 软件;
解压并打开该软件,右侧操作界面选择并进入 `Keil 仿真设置` 标签项;
## 仿真设置
选择目标单片机型号 - 添加型号和头文件到 Keil - 选择 Keil 安装目录文件夹 - 确定,提示添加成功;
## 创建项目
菜单栏点击` AiCube` 标签,进入 `项目创建助手`
## 参数配置
选择目标单片机型号 - 填写项目名称 - 设置保存路径 - 点击下一步,进入参数配置界面
左侧为功能参数选择窗口,展开 `外设` 选项,选择 `端口`,根据硬件勾选目标引脚(这里使用 P2 系列 IO 引脚);
此时右侧窗口出现相应的配置选项,通过下拉菜单即可实现模式设置;
## 生成工程
点击创建项目,此时查看目标路径发现 AiCube 工具创建的工程文件,包括 Keil 文件、库文件夹等标准工程格式;
双击打开生成的 Keil 文件,
```c++
////////////////////////////////////////
// 文件名称: main.c
// 文件描述:
// 文件版本: V1.0
// 修改记录:
// 1. (2025-04-03) 创建文件
////////////////////////////////////////
#include "config.h" //默认已包含stdio.h、intrins.h、ai_usb.h等头文件
////////////////////////////////////////
// 项目主函数
// 入口参数: 无
// 函数返回: 无
////////////////////////////////////////
void main(void)
{
SYS_Init();
while (1)
{
}
}
////////////////////////////////////////
// 系统初始化函数
// 入口参数: 无
// 函数返回: 无
////////////////////////////////////////
void SYS_Init(void)
{
EnableAccessXFR(); //使能访问扩展XFR
AccessCodeFastest(); //设置最快速度访问程序代码
AccessIXramFastest(); //设置最快速度访问内部XDATA
IAP_SetTimeBase(); //设置IAP等待参数,产生1us时基
P0M0 = 0x00; P0M1 = 0x00; //初始化P0口为准双向口模式
P1M0 = 0x00; P1M1 = 0x00; //初始化P1口为准双向口模式
P2M0 = 0x00; P2M1 = 0x00; //初始化P2口为准双向口模式
P3M0 = 0x00; P3M1 = 0x00; //初始化P3口为准双向口模式
P4M0 = 0x00; P4M1 = 0x00; //初始化P4口为准双向口模式
P5M0 = 0x00; P5M1 = 0x00; //初始化P5口为准双向口模式
P6M0 = 0x00; P6M1 = 0x00; //初始化P6口为准双向口模式
P7M0 = 0x00; P7M1 = 0x00; //初始化P7口为准双向口模式
CLK_Init(); //时钟模块初始化
PORT2_Init(); //P2初始化
}
////////////////////////////////////////
// 毫秒延时函数
// 入口参数: ms (设置延时的毫秒值)
// 函数返回: 无
////////////////////////////////////////
void delay_ms(uint16_t ms)
{
uint16_t i;
do
{
i = MAIN_Fosc / 6000;
while (--i);
} while (--ms);
}
////////////////////////////////////////
// 时钟初始化函数
// 入口参数: 无
// 函数返回: 无
////////////////////////////////////////
void CLK_Init(void)
{
CLK_SYSCLK_Divider(10); //切换主时钟前先将系统时钟降频
HIRC_40M(); //选择内部预置的频率
CLK_MCLK_HIRC(); //选择内部高精度HIRC作为主时钟
CLK_MCLK2_BYPASS(); //旁路MCLK2,直接使用MCLK选择
CLK_SYSCLK_Divider(1); //设置系统时钟分频系数
CLK_HSIOCK_MCLK(); //选择MCLK主时钟作为高速外设时钟源
CLK_HSIOCK_Divider(1); //设置高速外设时钟预分频系数
CLK_SPICLK_Divider(1); //设置SPI时钟预分频系数
CLK_I2SCLK_Divider(1); //设置I2S时钟预分频系数
CLK_PWMACLK_Divider(1); //设置PWMA时钟预分频系数
CLK_PWMBCLK_Divider(1); //设置PWMB时钟预分频系数
CLK_TFPUCLK_Divider(1); //设置TFPU时钟预分频系数
}
////////////////////////////////////////
// P2口初始化函数
// 入口参数: 无
// 函数返回: 无
////////////////////////////////////////
void PORT2_Init(void)
{
SetP2nQuasiMode(BIT_ALL); //设置P2为准双向口模式
DisableP2nPullUp(BIT_ALL); //关闭P2内部上拉电阻
DisableP2nPullDown(BIT_ALL); //关闭P2内部下拉电阻
DisableP2nSchmitt(BIT_ALL); //使能P2施密特触发
SetP2nSlewRateNormal(BIT_ALL); //设置P2一般翻转速度
SetP2nDrivingNormal(BIT_ALL); //设置P2一般驱动能力
SetP2nDigitalInput(BIT_ALL); //使能P2数字信号输入功能
}
```
代码包含延时函数 `delay_ms` 、IO 口初始化和时钟配置函数。
这里可以编译一下工程,确保无误
编译后自动生成主函数调用的头文件。
## 代码修改
实现流水灯功能,需要添加如下关键代码
```c++
#define n 9
unsigned char code LED[n]={0xfe,0xfd,0xfb,0xf7,0xef,0xdf,0xbf,0x7f,0xff}; // 定义 P2 组的输出电平
void main(void)
{
SYS_Init();
while (1)
{
u8 i;
for(i=0;i
- 2025-03-27
-
加入了学习《直播回放: 嵌入式Rust入门基础知识、解析动手实战Rust的三个任务》,观看 嵌入式Rust入门基础知识、解析动手实战Rust的三个任务
- 2025-03-23
-
发表了主题帖:
【嵌入式 Rust 修炼营】Rust 介绍、环境搭建、开发板介绍
# 【嵌入式 Rust 修炼营】Rust 介绍、环境搭建、开发板介绍
本文介绍了 Rust 语言的基本情况以及本次活动使用的开发板 PY32F030 ,并给出 Rust 开发环境的搭建部署流程。
## 简介
Rust 是一种系统编程语言,由 Mozilla 开发,旨在提供内存安全、并发性和高性能。
自 2010 年首次发布([GitHub 仓库](https://github.com/rust-lang)),凭借其强大性能、丰富的功能、各大平台的兼容性和适应性等优点,正在逐渐成为开发者的热门选择。
### 特点
Rust 通过所有权系统确保内存安全,无需垃圾回收机制。其核心规则包括:
- **所有权**:每个值有唯一的所有者。
- **借用**:允许不可变或可变引用,但不能同时存在。
- **生命周期**:确保引用始终有效。
Rust 的所有权系统防止了数据竞争,编译器会在编译时捕获并发错误,确保线程安全。
- **高性能**:Rust 提供与 C/C++ 相当的性能,适合对性能要求高的场景。
### 工具链
Rust 的工具链包括:
- **Cargo**:包管理和构建工具。
- **Rustfmt**:代码格式化工具。
- **Clippy**:代码 linting 工具。
### 跨平台支持
Rust 支持多种操作系统和架构,包括 Windows、Linux、macOS 等。
### 社区建设活跃
Rust 由活跃的社区维护,采用 RFC 流程管理语言和工具链的演进。
### 应用场景
Rust 适用于系统编程(如操作系统、嵌入式系统)、Web 后端开发、命令行工具、游戏开发、区块链开发等。
最后,Rust 凭借内存安全、高性能和现代工具链,成为系统编程和高效应用开发的理想选择,其强大的类型系统和丰富的生态系统使其在开发者中广受欢迎。
## 开发环境搭建
进入 [Rust](https://www.rust-lang.org/zh-CN/) 语言官网,获取安装方式。
这里介绍 Linux 和 Windows 操作系统下的环境部署流程。
### Linux
打开终端工具,执行如下代码
```bash
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
```
待安装完成
#### 测试
输入如下指令进行测试
```bash
rustc -V
cargo -V
```
正确输出版本号
### Windows
下载并运行 [rustup-init.exe](https://static.rust-lang.org/rustup/dist/i686-pc-windows-gnu/rustup-init.exe) 安装工具
使用指令 `rustc -V` 测试
正确输出版本号,表明安装部署完成。
#### 测试
新建并在终端命令行打开文件夹 `Rust`
```shell
cd E:/Rust
cargo new greeting
```
执行测试代码
```shell
cd ./greeting
cargo build
cargo run
```
输出 `Hello, world!`
完成创建 Rust 命令行程序。
### 嵌入式部署
Rust 嵌入式开发环境需要 nightly 版本
命令行终端执行如下代码
```bash
rustup default nightly
```
完成效果
#### 工具链
编译嵌入式端的目标文件,需要相应的交叉编译链,手动安装所需工具链。
Rust 目前已支持大部分的交叉编译工具链,通过如下命令查看当前支持的交叉编译工具链
```bash
rustup target list
```
对于不同的芯片厂商,只要芯片内核相同,均可使用相同的编译链。
#### 编译工具
安装 Cortex-M0 编译工具
```bash
rustup target add thumbv6m-none-eabi
```
#### Probe-rs
Probe-rs 是一个在Rust 嵌入式开发的常用软件工具,有下载固件到芯片,在线调试固件,打印运行日志、查看芯片内存等功能。
```bash
curl --proto '=https' --tlsv1.2 -LsSf https://github.com/probe-rs/probe-rs/releases/latest/download/probe-rs-tools-installer.sh | sh
```
若远程 [下载](https://github.com/probe-rs/probe-rs/releases/latest/download/probe-rs-tools-installer.sh) 遇到问题,可本地安装
```bash
sh probe-rs-tools-installer.sh
```
安装 probe-rs
```bash
cargo install cargo-binstall
cargo binstall probe-rs-tools
```
完成该步骤后,即可进行 Rust 嵌入式开发。
相关参考:[快速搭建环境](https://hysonglet.github.io/rust-embedded-start/environment/chapter.html)
## PY32F030 开发板
介绍了本次活动使用的 PY32F030-Rust 开发板,该开发板的相关资料详见:[Py32 Rust开发板](https://hysonglet.github.io/rust-embedded-start/appendix/chapter.html) 。
`Py32_Rust_Dev_1.1` 目前已适配大部分外设的 Rust 驱动,且支持开源的 Arduino、普冉官方支持包等。
支持不同的 IDE 或编译工具上测试,支持广泛的 IDE 开发
- Rust
- Arduno
- Keil
- IAR
- EIDE
- GCC
- CMake
实物展示
官方资料详见:[资料下载_- 普冉半导体](https://www.puyasemi.com/download.html?keywords=py32f030)
### 主控
PY32F030K2BT6
PY32F030 系列微控制器采用高性能的 32 位 ARM® Cortex®-M0+ 内核,宽电压工作范围的 MCU。
具有 64KB flash 和 8KB SRAM 存储器,最高工作频率 48MHz。
包含多种不同封装类型多款产品。
芯片集成多路 IIC、SPI、USART 等通讯外设,1 路 12bit ADC,5 个 16bit 定时器,以及 2 路比较器。
PY32F030 系列微控制器的工作温度范围为 -40℃~85℃,工作电压范围 1.7V~5.5V。
芯片提供 sleep 和 stop 低功耗工作模式,可以满足不同的低功耗应用。
PY32F030 系列微控制器适用于多种应用场景,例如控制器、手持设备、PC外设、游戏和GPS平台、工业应用等。
详见官网:[PY32F030 系列 | OpenPuya](https://py32.org/mcu/PY32F030xx.html)
#### 特性
- 内核 — 32位ARM® Cortex® - M0+ — 最高48 MHz工作频率
- 存储器 — 最大64 KB Flash存储器 — 最大8 KB SRAM
- 时钟系统 — 内部4/8/16/22.12/24 MHz RC 振荡器(HSI) — 内部32.768 kHz RC振荡器(LSI) — 4 ~ 32 MHz晶体振荡器(HSE) — 32.768 kHz低速晶体振荡器(LSE) — PLL(支持对HSI或者HSE的2倍频)
- 电源管理和复位 — 工作电压(x6 版本):1.7 ~ 5.5 V — 工作电压(x7 版本):2.0 ~ 5.5 V — 低功耗模式: Sleep和Stop — 上电/掉电复位 (POR/PDR) — 欠电复压 (BOR) — 可编程的电压检测 (PVD)
- 通用输入输出(I/O)
- 3通道 DMA控制器
- 1 x 12位ADC — 4个通用的16位定时器 (TIM3/TIM14/TIM16/TIM17) — 1 个低功耗定时器(LPTIM),支持从stop模式 唤醒 — 1 个独立看门狗定时器 (IWDG) — 1 个窗口看门狗定时器 (WWDG) — 1 个SysTick 定时器 — 1 个IRTIM
- RTC
- 通讯接口 — 2个串行外设接口(SPI) — 2 个通用同步/异步收发器(USART),支持 自动波特率检测 — 1 个I2C接口,支持标准模式 (100 kHz)、 快 速模式 (400 kHz),支持7 位寻址模式
- 支持4位8段共阴极LED数码管 — 可循环扫描1位、2位、3位、4位数字
- 硬件CRC-32模块
- 2个比较器
- 唯一UID
- 串行调试 (SWD) — 多达30个I/O,均可作为外部中断 — 支持 最多10个外部输入通道 — 输入电压转换范围: 0 ~ VCC
- 定时器 — 1个16位高级控制定时器(TIM1)
- 工作温度(x6 版本):-40 ~ 85 ℃
- 工作温度(x7 版本):-40 ~ 105 °C
- 封装:LQFP32,QFN32(5*5),QFN32(4*4) , QFN24,SSOP24,QFN20,TSSOP20, DFN8(1.5*1.5)
#### 系统架构
#### 时钟树
详见芯片 [数据手册](https://www.puyasemi.com/download.html?keywords=py32f030) 和 [用户手册](https://www.puyasemi.com/download.html?keywords=py32f030) 。
### 原理图
详见:[Py32F030_CrabBoard_Hardware](https://github.com/hysonglet/Py32F030_CrabBoard_Hardware/tree/main)
### 引脚功能
### 相关资料
[附录](https://hysonglet.github.io/rust-embedded-start/appendix/chapter.html) 、微信公众号:Rust嵌入式、开发板[教程](https://hysonglet.github.io/rust-embedded-start/) 。
1. Py32 Rust开发板驱动与丰富的例程:https://github.com/hysonglet/py32f030-hal
2. 普冉官方文档:https://www.puyasemi.com/download.html?keywords=py32f030
3. Rust Bind C 框架: https://github.com/decaday/py32-bind-hal
4. Rust 社区支持库: https://github.com/py32-rs/py32-hal
5. Arduino 支持文档:https://github.com/py32duino/Arduino-PY32
6. Pura 开源文档:https://github.com/OpenPuya
7. Cmake 编译框架:https://github.com/decaday/py32f0-cmake
8. 资料包:https://pan.baidu.com/s/1QsamOP78Fen8efGEXfNonA?pwd=rust
## 总结
本文介绍了 Rust 语言的基本情况以及本次活动使用的开发板 PY32F030 ,并给出 Rust 开发环境的搭建部署流程,为后续的深入开发和研究奠定基础,同时为相关开发者提供参考。
- 2025-03-19
-
回复了主题帖:
>>征集 | 晒电机控制痛点与难题,一起寻求最优解!
专业关系,平常接触步进电机较多,因为是要实现精密控制,对转速的要求不那么高。步进电机控制的难点个人认为是信号和电机的匹配程度,实际应用中需要精确控制步进电机转动角度,需要电机和驱动器高度匹配,以实现精准调控,这方面不得不说仍然存在较多困难和较大的提升空间。
- 2025-03-13
-
回复了主题帖:
嵌入式Rust修炼营入围名单来啦,一起度过嵌入式Rust学习时光的小伙伴集合啦~
个人信息无误
- 2025-02-25
-
回复了主题帖:
嵌入式Rust修炼营:动手写串口烧录工具和MCU例程,Rust达人Hunter直播带你入门Rust
1.【参与理由&个人编程基础】
我常年从事嵌入式开发,具有丰富的仪器设备测试程序开发经验,具有光学专业研究背景,在实验室负责多种设备的远程控制和数据采集、相关应用项目的开发等,如MCU操控和Linux系统工控应用,在LabVIEW上位机控制、MATLAB数据编程、FORTRAN编程、科学计算求解非线性方程等方面具有扎实的理论基础以及丰富的实践经验。因此申请参与嵌入式 Rust 修炼营,深入学习这门先进的编程语言,紧跟时代发展,为之后的学习和科研工作提供参考。
2.【根据修炼任务和活动时间表,预估可以完成几级任务?】
高级。
3.【Rust学习过程遇到难点,希望在参与活动中收获什么?】
对Rust有一定了解,学习Rust过程的难点在于编程习惯不同,对于重要且常用的语法需要加强练习才能熟练掌握,因此希望参与此次活动,和大家共同学习、锻炼和分享 Rust 编程,并将其应用于实际项目的应用和开发中,和其他编程语言进行对比,以便针对具体问题获得更适合和更优秀的解决方案。
- 2025-02-22
-
回复了主题帖:
#AI挑战营(进阶)# 人脸识别部署
Jacktang 发表于 2025-2-22 15:06
幸狐 RV1106 开发板的人脸识别方案。部署的流程真不少
部署流程中的关键部分是环境搭建,之后根据幸狐官方提供的人脸识别例程,更换模型,再编译一下就能用了
- 2025-02-21
-
发表了主题帖:
#AI挑战营(进阶)# 人脸识别部署
# #AI挑战营(进阶)# 人脸识别部署
本文介绍了人脸识别方案在幸狐 RV1106 开发板的部署流程,作为之前帖子的补充,针对环境搭建、rknn 部署等关键部分进行细致分析描述,主要包括 Linux 操作系统部署、Conda 安装、ONNX 获取、RKNN 模型转化等,最后对测试效果进行展示和简要分析。
## RKNN-Toolkit2 安装
介绍了在 Windows 11 操作系统下的 rknn-toolkit2 工具的部署流程。
### Linux 系统安装
包括虚拟机安装与 Ubuntu 22.04 系统安装。
#### 虚拟机安装
[VMware Workstation 16.1.2 Pro for Windows](https://download3.vmware.com/software/wkst/file/VMware-workstation-full-16.1.2-17966106.exe)
密钥:`ZF3R0-FHED2-M80TY-8QYGC-NPKYF`
#### Ubuntu 系统
镜像文件下载:[Ubuntu 22.04](https://mirrors.tuna.tsinghua.edu.cn/ubuntu-releases/22.04/) - ubuntu-22.04.5-desktop-amd64.iso
安装流程:[ubuntu安装教程 - CSDN](https://blog.csdn.net/qq_43374681/article/details/129248167)
1. 打开 VMware 软件,选择创建新的虚拟机;
2. 进入新建虚拟机向导,选择典型,选择 Ubuntu 镜像文件;
3. 定义占用磁盘空间,建议 100 G;
4. 自定义全名、用户名、密码;
5. 启动虚拟机,安装 Ubuntu 系统;
6. 选择目标语言等配置即可。
### Python 安装
Python 3.10 安装部署
运行 Terminal 终端命令行程序
```bash
sudo apt-get install python3.10
```
部署 rknn-toolkit2
```bash
git clone https://github.com/airockchip/rknn-toolkit2
```
> 若网速较慢,可通过 [网页](https://github.com/airockchip/rknn-toolkit2) 下载至本地。
安装 python 环境
```bash
sudo apt-get update
sudo apt-get install python3 python3-dev python3-pip
sudo apt-get install libxslt1-dev zlib1g zlib1g-dev libglib2.0-0 libsm6 libgl1-mesa-glx libprotobuf-dev gcc
```
安装 RKNN-ToolKit2 依赖包
```bash
cd home/ljl/Downloads/rknn-toolkit2-2.3.0
pip3 install -r rknn-toolkit2/packages/x86_64/requirements_cp310-2.3.0.txt
```
安装 RKNN-ToolKit2
```bash
pip3 install rknn-toolkit2/packages/x86_64/rknn_toolkit2-2.3.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
```
执行以下命令没有报错,则安装成功
```bash
python3
from rknn.api import RKNN
```
### Conda 安装
下载安装包
```bash
wget https://mirrors.tuna.tsinghua.edu.cn/anaconda/miniconda/Miniconda3-4.6.14-Linux-x86_64.sh
```
安装 miniconda
```bash
chmod 777 Miniconda3-4.6.14-Linux-x86_64.sh
bash Miniconda3-4.6.14-Linux-x86_64.sh
```
进入 Conda base 环境
```bash
source ~/miniconda3/bin/activate
```
#### 创建 RKNN-Toolkit2 Conda 环境
创建 RKNN-Toolkit2 开发 Conda 环境
```bash
conda create -n RKNN-Toolkit2 python=3.8
```
进入 RKNN-Toolkit2 Conda 环境
```bash
conda activate RKNN-Toolkit2
```
验证 Python 版本是否为 3.8
```bash
python --version
```
获取 RKNN-Toolkit2 安装包
```bash
git clone https://github.com/airockchip/rknn-toolkit2.git
```
进入文件夹
```bash
cd /home/ljl/miniconda3/envs/RKNN-Toolkit2/rknn-toolkit2-master
```
安装 RKNN-Toolkit2 相关的依赖库
```bash
pip install tf-estimator-nightly==2.8.0.dev2021122109
pip install -r rknn-toolkit2/packages/x86_64/requirements_cp38-2.3.0.txt -i https://pypi.mirrors.ustc.edu.cn/simple/
```
安装 RKNN-Toolkit2
```bash
pip install rknn-toolkit2/packages/x86_64/rknn_toolkit2-2.3.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
```
执行以下命令,验证是否安装成功
```bash
python
from rknn.api import RKNN
```
## ONNX 模型获取
ONNX 文件不仅储存了神经网络模型的权重,也储存了模型的结构信息以及网络中每一层的输入输出等信息。
根据模型的不同获取源码,人脸识别使用的模型训练推理源码与对应的 GitHub 地址如下
Retianface:https://github.com/bubbliiiing/retinaface-pytorch
### 人脸检测
人脸检测使用的模型为 retinaface,可以提取出人脸的边界框坐标、置信度和人脸五个特征点的坐标。通过人脸的边界框截取图像作为人脸特征提取的输入图像,可以提高人脸特征值获取的可靠性。
获取 retinaface 源码
```bash
git clone https://github.com/bubbliiiing/retinaface-pytorch.git
```
进入源码目录
```bash
cd /home/ljl/Downloads/retinaface-pytorch-master
```
搭建模型训练环境
```bash
conda create -n retinaface python=3.6
```
进入 Conda 虚拟环境并安装运行的依赖库
```bash
conda activate retinaface
pip install -r requirements.txt
```
在当前文件夹下创建导出 ONNX 文件的 python 脚本 `export_onnx.py`
```bash
touch export_onnx.py
vim export_onnx.py
```
粘贴如下代码
```python
from nets.retinaface import RetinaFace
from utils.config import cfg_mnet
import torch
model_path='model_data/Retinaface_mobilenet0.25.pth' #模型路径
model=RetinaFace(cfg=cfg_mnet,pretrained = False) #模型初始化
device = torch.device('cpu')
model.load_state_dict(torch.load(model_path,map_location=device),strict=False) #模型加载
net=model.eval()
example=torch.rand(1,3,640,640) #给定输入
torch.onnx.export(model,(example),'model_data/retinaface.onnx',verbose=True,opset_version=9) #导出
```
执行脚本获取 ONNX 文件(retinaface conda 环境下)
```bash
python export_onnx.py
```
在 `retinaface-pytorch-master/model_data` 文件夹下可得到转换后的 ONNX 文件
### 人脸特征提取
人脸特征提取可以根据输入的人脸图像提取出 128 维的特征值,可以与其他人脸的特征值计算欧氏距离来衡量匹配程度。
获取 facenet 源码
```bash
git clone https://github.com/bubbliiiing/facenet-pytorch.git
```
进入源码目录
```bash
cd /home/ljl/Downloads/facenet-pytorch-master
```
搭建模型训练环境
```bash
conda create -n facenet python=3.6
```
进入 Conda 虚拟环境并安装运行的依赖库
```bash
conda activate facenet
pip install -r requirements.txt
```
在当前 `facenet-pytorch-main` 文件夹下创建导出 ONNX 文件的 python 脚本 `export_onnx.py`
```python
from nets.facenet import Facenet
from torch import onnx
import torch
model_path='model_data/facenet_mobilenet.pth' #模型路径
model = Facenet(backbone="mobilenet",mode="predict",pretrained=True) #模型初始化
device = torch.device('cpu')
model.load_state_dict(torch.load(model_path, map_location=device), strict=False)
example=torch.rand(1,3,160,160) #给定一个输入
torch.onnx.export(model,example,'model_data/facenet.onnx',verbose=True,opset_version=9) #导出
```
执行脚本获取 ONNX 文件(facenet conda 环境下)
```bash
python export_onnx.py
```
在 `facenet-pytorch-main/model_data` 可以得到转换后的 ONNX 文件
使用 [Netron](https://netron.app/) 工具查看 ONNX 模型的结构
发现模型在输出前使用了 RKNPU 无法解析的 `ReduceL2` 算子,
需要注释路径 `facenet-pytorch/nets/facenet.py` 中的标准化操作
```python
def forward(self, x, mode = "predict"):
if mode == 'predict':
x = self.backbone(x)
x = self.avg(x)
x = x.view(x.size(0), -1)
x = self.Dropout(x)
x = self.Bottleneck(x)
x = self.last_bn(x)
#x = F.normalize(x, p=2, dim=1) #输出前的标准化
return x
x = self.backbone(x)
x = self.avg(x)
x = x.view(x.size(0), -1)
x = self.Dropout(x)
x = self.Bottleneck(x)
before_normalize = self.last_bn(x)
x = F.normalize(before_normalize, p=2, dim=1)
cls = self.classifier(before_normalize)
return x, cls
```
重新导出 ONNX 模型
## RKNN 模型转换
将 onnx 模型转化为 rknn 模型,以便部署于开发板。
### 模型转换
源码获取
```bash
git clone https://github.com/LuckfoxTECH/luckfox_pico_rknn_example.git
```
进入 `scripts/luckfox_onnx_to_rknn` 目录
```bash
cd luckfox_pico_rknn_example/scripts/luckfox_onnx_to_rknn
```
进入RKNN-Toolkit2 Conda 开发环境
```bash
conda activate RKNN-Toolkit2
```
模型转换
```bash
cd convert
python convert.py ../model/retinaface.onnx ../dataset/retinaface_dataset.txt ../model/retinaface.rknn Retinaface
```
生成开发板所需的 rknn 文件,
这里的转换代码定义为
```bash
python convert.py
```
### 模型验证
使用 [Netron](https://netron.app/) 工具解析输出的 rknn 模型,查看输入输出基本信息
> Luckfox-Pico 仅支持 `int8` 类型输入和输出
>
> Luckfox-Pico 仅支持 4 维输入维度和 4 维度输出维度
使用 Python 软件模拟器进行模型验证。
```python
from rknn.api import RKNN
rknn = RKNN()
rknn.config(mean_values=[[0, 0, 0]], std_values=[[128, 128, 128]],
target_platform='rv1103',
quantized_algorithm="normal")
rknn.load_onnx(model = model_path)
rknn.build(do_quantization=do_quant, dataset=DATASET_PATH)
rknn.init_runtime()
rknn.release()
```
### 编译运行
#### PC端编译
克隆或下载仓库
```bash
git clone https://github.com/LuckfoxTECH/luckfox_pico_rknn_example.git
```
设置环境变量
```bash
export LUCKFOX_SDK_PATH='/home/ljl/Downloads/luckfox_pico_rknn_example'
```
执行 `./build.sh`
```bash
chmod a+x ./build.sh
./build.sh
```
选择 `luckfox_pico_retinaface_facenet` 人脸识别例程
#### 板端运行
编译完成后,在 `luckfox_pico_rknn_example/install` 文件夹下生成对应的部署文件夹 `luckfox_pico_retinaface_facenet_demo`
使用 adb 方式将生成的部署文件夹完整上传到 Luckfox Pico 开发板
```bash
adb shell
mkdir HFR # 新建文件夹
exit
adb push D:\luckfox_pico_rknn_example\install\luckfox_pico_retinaface_facenet_demo /HFR
```
首先停止默认推流
```bash
adb shell
cd oem/usr/bin
RkLunch-stop.sh
```
进入开发板并执行
```bash
adb shell
cd HFR
chmod 777 luckfox_pico_retinaface_facenet_demo
cd luckfox_pico_retinaface_facenet_demo
./luckfox_pico_retinaface_facenet ./model/RetinaFace.rknn ./model/mobilefacenet.rknn ./model/test.jpg
```
通过 VLC media player 软件,依次进入媒体 - 打开网络串流 - 网络 - 输入URL
`rtsp://172.32.0.93/live/0`
点击 `播放`,即可实现 rtsp 推流显示。
### 效果
#### 单张人脸检测
##### 动态效果
#### 多张人脸检测
##### 动态效果
包括 rtsp 推流显示,人脸检测(动态方框)、特征提取、PowerShell命令端参数输出等内容。
#### 场景更换测试
更换测试图片,进行人脸检测
**动态效果**
同样包含人脸识别、图框提示、识别参数显示、终端参数连续输出等。
## 总结
本文介绍了人脸识别方案在幸狐 RV1106 开发板的部署流程,包括操作系统环境配置(虚拟机安装、Ubuntu 22.04 系统安装)、Conda 环境部署、RKNN-Toolkit2 工具安装部署、ONNX 模型获取、RKNN 模型转换、模型编译与上传、人脸识别效果检验等。步骤尽可能详细,为相关智能化需求应用场景(如门禁系统、安防、客流统计、考勤等)的开发提供了参考。
- 2025-02-20
-
回复了主题帖:
#AI挑战营第二站# 基于RKNN toolkit的模型转换与部署
Auralife 发表于 2025-1-15 10:39
有解决了吗
更换Ubuntu22.04和虚拟机就管用了
- 2025-02-12
-
回复了主题帖:
STC更名为Ai?这事你怎么看?
作为一名持续关注51单片机的电子爱好者,刚开始看到STC更名为Ai还有些一头雾水,转念想起了STC论坛的许多与人工智能相关的帖子,也就明白他们为啥改名了……
TinyML,Ai8051U 人工智能 开山之作,AI手写计算器 国芯技术交流网站 - AI32位8051交流社区
STC论坛有个专门的 AI 版块,里面有很多案例,如运行卷积神经网络、实现手写数字识别、手写计算器等,性能升级确实很厉害,甚至比肩32单片机,不得不令人刮目相看了,看来51单片机也是大有可图、未来可期啊~
- 2025-02-06
-
回复了主题帖:
【新年花灯秀】STM32F401RCT6 花样点灯
se7ens 发表于 2025-2-5 17:12
哇,传说中的彩色丝印PCB上线了
这种板的加工费要单独加钱不?
我用了¥50 彩色丝印券,批量生产的话需要和生产厂家详谈
- 2025-01-24
-
回复了主题帖:
新年新挑战,任务打卡赢好礼!
完善个人资料
回帖
课程学习
参与活动
资源下载
-
回复了主题帖:
#AI挑战营第二站# 基于RKNN toolkit的模型转换与部署
我安装的时候也遇到这种情况了,一直报错……
-
上传了资料:
STM32 自学笔记 - 蒙博宇
-
上传了资料:
51单片机实战指南 - 陈景波
- 2025-01-21
-
回复了主题帖:
【新年花灯秀】STM32F401RCT6 花样点灯
okhxyyo 发表于 2025-1-21 14:35
速度很快啊~~~第一个花灯点亮上线啦
哈哈,开发板上还有 OLED 屏接口,打算用来播放电子烟花
-
回复了主题帖:
【新年花灯秀】STM32F401RCT6 花样点灯
1084504793 发表于 2025-1-21 17:40 建议那几个字用LED灯显示,这样就更酷了。
建议不错,正在整活儿
用 WS2812 做个会闪烁的春联,嘿嘿
-
发表了主题帖:
【新年花灯秀】STM32F401RCT6 花样点灯
本帖最后由 lijinlei 于 2025-1-21 13:04 编辑
RGB 三色 LED 循环点亮
[localvideo]5076954fcfaef84c3c8f6658568e2422[/localvideo]
流水灯
[localvideo]cab4c9670847c7e0bcb20d4a9362648f[/localvideo]
RGB 灯代码
#include "main.h"
#include "gpio.h"
void SystemClock_Config(void);
int main(void)
{
HAL_Init();
SystemClock_Config();
MX_GPIO_Init();
while (1)
{
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
HAL_GPIO_WritePin(GPIOB, GPIO_PIN_8, GPIO_PIN_RESET);
HAL_Delay(100);
HAL_GPIO_WritePin(GPIOB, GPIO_PIN_8, GPIO_PIN_SET);
HAL_GPIO_WritePin(GPIOB, GPIO_PIN_9, GPIO_PIN_RESET);
HAL_Delay(100);
HAL_GPIO_WritePin(GPIOB, GPIO_PIN_9, GPIO_PIN_SET);
HAL_GPIO_WritePin(GPIOB, GPIO_PIN_10, GPIO_PIN_RESET);
HAL_Delay(100);
HAL_GPIO_WritePin(GPIOB, GPIO_PIN_10, GPIO_PIN_SET);
}
/* USER CODE END 3 */
}
/**
* @brief System Clock Configuration
* @retval None
*/
void SystemClock_Config(void)
{
RCC_OscInitTypeDef RCC_OscInitStruct = {0};
RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
/** Configure the main internal regulator output voltage
*/
__HAL_RCC_PWR_CLK_ENABLE();
__HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE2);
/** Initializes the RCC Oscillators according to the specified parameters
* in the RCC_OscInitTypeDef structure.
*/
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
RCC_OscInitStruct.HSEState = RCC_HSE_ON;
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_NONE;
if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
{
Error_Handler();
}
/** Initializes the CPU, AHB and APB buses clocks
*/
RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
|RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_HSE;
RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;
RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;
if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_0) != HAL_OK)
{
Error_Handler();
}
}
流水灯代码
#include "main.h"
#include "gpio.h"
void SystemClock_Config(void);
int main(void)
{
SystemClock_Config();
MX_GPIO_Init();
while (1)
{
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
HAL_GPIO_WritePin(GPIOC, GPIO_PIN_0, GPIO_PIN_RESET);
HAL_Delay(100);
HAL_GPIO_WritePin(GPIOC, GPIO_PIN_0, GPIO_PIN_SET);
HAL_GPIO_WritePin(GPIOC, GPIO_PIN_1, GPIO_PIN_RESET);
HAL_Delay(100);
HAL_GPIO_WritePin(GPIOC, GPIO_PIN_1, GPIO_PIN_SET);
HAL_GPIO_WritePin(GPIOC, GPIO_PIN_2, GPIO_PIN_RESET);
HAL_Delay(100);
HAL_GPIO_WritePin(GPIOC, GPIO_PIN_2, GPIO_PIN_SET);
HAL_GPIO_WritePin(GPIOC, GPIO_PIN_3, GPIO_PIN_RESET);
HAL_Delay(100);
HAL_GPIO_WritePin(GPIOC, GPIO_PIN_3, GPIO_PIN_SET);
HAL_GPIO_WritePin(GPIOC, GPIO_PIN_4, GPIO_PIN_RESET);
HAL_Delay(100);
HAL_GPIO_WritePin(GPIOC, GPIO_PIN_4, GPIO_PIN_SET);
HAL_GPIO_WritePin(GPIOC, GPIO_PIN_5, GPIO_PIN_RESET);
HAL_Delay(100);
HAL_GPIO_WritePin(GPIOC, GPIO_PIN_5, GPIO_PIN_SET);
HAL_GPIO_WritePin(GPIOC, GPIO_PIN_6, GPIO_PIN_RESET);
HAL_Delay(100);
HAL_GPIO_WritePin(GPIOC, GPIO_PIN_6, GPIO_PIN_SET);
HAL_GPIO_WritePin(GPIOC, GPIO_PIN_7, GPIO_PIN_RESET);
HAL_Delay(100);
HAL_GPIO_WritePin(GPIOC, GPIO_PIN_7, GPIO_PIN_SET);
HAL_GPIO_WritePin(GPIOC, GPIO_PIN_13, GPIO_PIN_RESET);
HAL_Delay(100);
HAL_GPIO_WritePin(GPIOC, GPIO_PIN_13, GPIO_PIN_SET);
}
/* USER CODE END 3 */
}
void SystemClock_Config(void)
{
RCC_OscInitTypeDef RCC_OscInitStruct = {0};
RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
/** Configure the main internal regulator output voltage
*/
__HAL_RCC_PWR_CLK_ENABLE();
__HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE2);
/** Initializes the RCC Oscillators according to the specified parameters
* in the RCC_OscInitTypeDef structure.
*/
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
RCC_OscInitStruct.HSEState = RCC_HSE_ON;
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_NONE;
if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
{
Error_Handler();
}
/** Initializes the CPU, AHB and APB buses clocks
*/
RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
|RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_HSE;
RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;
RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;
if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_0) != HAL_OK)
{
Error_Handler();
}
}
工程使用 STM32CubeMX 生成,根据开发板原理图,控制 GPIO 输出高低电平并延时。
该开发板由本人设计,主要特点是彩色丝印——蛇年赛博春联,主控为高性能 STM32F401RCT6 芯片,具有板载RGB LED以及多个用户自定义LED,便于实现多种闪烁效果; Flash 扩展和 IIC OLED 以及 TFT 屏等多功能接口,便于实现更多显示效果。
设计亮点
支持 FLASH 扩展;
支持用户按键、LED调控;
支持所有 GPIO 引脚外部连接;
支持电源供电扩展,便于更多外设供电;
支持 SWD 接口下载程序;
支持 1.8 寸 TFT 屏模块接口,配合彩色动态画面显示,使整个界面融为一体;
支持 IIC OLED 显示屏模块接口,配合温湿度传感器等,显示相关信息;
配合暖冬图片和半透明立体雪花效果,营造浓厚的冬季氛围;
春联包含辞旧迎新的美好祝愿,突出对中华传统文化和祖国壮丽河山的向往之情;
STM32F401RCT6 基于高性能 ARM®Cortex®-M4 32 位 RISC 核心,工作频率高达 84 MHz。
Cortex®-M4 核心具有浮点单元 (FPU) 单精度,支持所有 ARM 单精度数据处理指令和数据类型。它还实现了一套完整的 DSP 指令和内存保护单元 (MPU),增强了应用程序的安全性。
STM32F401RCT6 集成了高速嵌入式存储器 (256KB 闪存,64kKB SRAM),以及广泛的增强型 GPIO 和外设,连接到两个APB总线,两个 AHB 总线和一个 32 位多 AHB 总线矩阵。所有器件都提供一个 12 位 ADC,一个低功耗RTC,六个通用的 16 位定时器,包括一个用于电机控制的 PWM 定时器,两个通用的 32 位定时器。它们还具有标准和先进的通信接口。
STM32F401xB/STM32F401xC 在 - 40 至 + 125 °C 的温度范围内工作,电源电压为 1.7 (PDR OFF) 至 3.6 V。一套全面的省电模式允许设计低功耗应用。
这些特性使 STM32F401xB/STM32F401xC 微控制器适用于广泛的应用。
功能参数
带 BAM 的动态效率线(批量采集模式)
1.7 V 至 3.6 V 电源
温度范围:-40 °C 至 85/105/125 °C
内核:带 FPU 的 Arm 32 位 Cortex-M4 CPU、允许从闪存执行零等待状态的自适应实时加速器(ART 加速器™)、频率高达 84 MHz、内存保护单元、105 DMIPS/1.25 DMIPS/MHz (Dhrystone 2.1) 和 DSP 指令®®
记忆
高达 256 KB 的闪存
512 字节的 OTP 内存
高达 64 KB 的 SRAM
时钟、复位和电源管理
1.7 V 至 3.6 V 应用电源和 I/O
POR、PDR、PVD 和 BOR
4 至 26 MHz 晶体振荡器
内部 16 MHz 工厂调整 RC
用于 RTC 的 32 kHz 振荡器,带校准
带校准的内部 32 kHz RC
功耗
运行:128 μA/MHz(外设关闭)
停止(停止模式下的闪光灯,快速唤醒时间):42 μA 典型值 @ 25 °C;最大 65 μA @25 °C
停止(在深度掉电模式下闪烁,唤醒时间缓慢):在 25 °C typ@低至 10 μA;最大 28 μA @25 °C
待机:2.4 μA @25 °C / 1.7 V,无 RTC;12 μA @85 °C @1.7 V
V蝙蝠RTC 电源:1 μA @25 °C
1×12 位、2.4 MSPS 模数转换器:多达 16 个通道
通用 DMA:具有 FIFO 和突发支持的 16 流 DMA 控制器
多达 11 个定时器:多达 6 个 16 位定时器、2 个高达 84 MHz 的 32 位定时器,每个定时器具有多达 4 个 IC/OC/PWM 或脉冲计数器和正交(增量)编码器输入、两个看门狗定时器(独立和窗口)和一个 SysTick 定时器
调试模式
串行线调试 (SWD) 和 JTAG 接口
Cortex-M4 嵌入式跟踪宏单元™®
多达 81 个 I/O 端口,具有中断功能
所有 IO 端口均可承受 5 V 电压
多达 78 个高达 42 MHz 的快速 I/O
多达 11 个通信接口
最多 3 × I2C 接口(1Mbit/s,SMBus/PMBus)
最多 3 个 USART(2 x 10.5 Mbit/s、1 x 5.25 Mbit/s)、ISO 7816 接口、LIN、IrDA、调制解调器控制)
多达 4 个 SPI(f 时高达 42 Mbits/s)中央处理器= 84 MHz)、SPI2 和 SPI3,带多路复用全双工 I2S 通过内部音频 PLL 或外部时钟实现音频类精度
SDIO 接口
高级连接
具有片上 PHY 的 USB 2.0 全速器件/主机/OTG 控制器
CRC 计算单元
96 位唯一 ID
RTC:亚秒级精度、硬件日历
所有软件包均ECOPACK2
原理图
完整工程见附件。