news 2026/9/6 9:47:41

RK3588 NPU多路视觉模型并发部署实战:三模型同跑不卡顿

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
RK3588 NPU多路视觉模型并发部署实战:三模型同跑不卡顿

前一阵子接了个边缘计算项目,需求挺有意思:单块 RK3588 开发板,要同时跑人员入侵检测、烟火识别、垃圾分类三个视觉模型。听起来像三个项目揉在一块,其实最终落地就靠一块 RK3588 的 NPU 硬扛。

先说结论:RK3588 的 NPU 确实能同时干这三件事,而且还能留出余量做 RTSP 拉流和业务逻辑。但难点不在“能不能跑”,而在“怎么调度、怎么分配资源、怎么保证一路模型卡顿不拖垮另外两路”。这篇文章我把自己从模型转换到多路并发部署的完整思路和踩坑记录整理出来,给准备在 RK3588 上做多路视觉推理的朋友一个可以直接参照的落地路径。

1. 项目场景与需求拆解

最开始拿到需求时,我脑子里第一反应是“又要上服务器了”,但客户给的硬件约束很死:整机功耗不能高,体积不能大,只能上一块 RK3588 核心板。所以问题就变成了——一块 6 TOPS 算力的 NPU 到底能不能扛住三个检测模型同时跑。

1.1 三路视觉任务的计算特点分析

把三个任务拆开看:

  • 人员入侵检测:通常是 640x640 输入,YOLOv8s 这类模型,主要看人形目标,实时性要求高,最好能做到 5-10 FPS 的检测频率。
  • 烟火检测:输入分辨率可以小一点,但模型要能识别小目标,烟雾和火焰的特征偏纹理和颜色,检测难度比较高。
  • 垃圾分类:类别多,常见模型会分成 40 类左右,但目标通常是固定的垃圾桶区域,检测范围不大,输入可以压缩到 320x320 甚至更小。

三个模型如果都按 YOLOv8s 整图跑,算力肯定不够。但如果把输入尺寸降下来、模型结构做轻量化、再错开调度,6 TOPS 是够用的。

1.2 为什么选择 RK3588 而非其他平台

选 RK3588 不单是因为它 NPU 算力有 6 TOPS(INT8),更关键的是它的三核 NPU 支持多模型并发。官方文档里明确写了支持 3 个 NPU 核心独立使用或合并使用,这意味着我可以把不同模型分配到不同核心上,避免相互抢占。

另外 RK3588 的 CPU 是 4 核 A76 + 4 核 A55,做视频解码和业务逻辑也绰绰有余。整板功耗控制在 5-10W,不需要主动散热就能长期跑(当然加了风扇更稳),这一点在边缘场景里非常重要。

可以说,RK3588 最适合的就是“中等算力需求、多路 IO、单板完成全部业务”的视觉盒子类项目。

2. 模型转换与 RKNN 部署准备

模型跑在 NPU 上,必须先转成 RKNN 格式。这一步是整套流程里坑最多的环节,很多人卡了好几天,其实大部分问题出在模型结构和量化配置上。

2.1 YOLOv8 等其他模型转 RKNN 的操作流程

我这边用的 PyTorch 训练好的模型,首先导出 ONNX,然后用 RKNN-Toolkit2 转成 RKNN 格式。以 YOLOv8s 为例的转换步骤大概是:

# 安装 rknn-toolkit2,注意 Python 版本要用 3.8/3.10/3.11 pip install rknn_toolkit2-2.3.0-cp38-cp38-linux_x86_64.whl

导出 ONNX 时可以先把模型的输出端做简化,去掉一些不必要的后处理节点,我通常只保留主干网络的输出层,把 NMS 放到 RK3588 的 CPU 上做,这样转换成功率更高、部署也更灵活。速度快一些的 YOLOv8 变体也可以替换成 YOLOv5、YOLOv7-tiny、PPYOLOE 等结构。

转换时的关键代码:

from rknn.api import RKNN rknn = RKNN() rknn.config(mean_values=[[0, 0, 0]], std_values=[[255, 255, 255]], target_platform="rk3588") rknn.load_onnx(model="yolov8s.onnx") rknn.build(do_quantization=True, dataset="dataset.txt") rknn.export_rknn("yolov8s.rknn")

这里有几个细节:

  • dataset 文件里放的是用于量化校准的图片路径列表,一般选 100-200 张覆盖各种场景的图,不需要太多,但一定要有代表性。比如烟火检测的校准图里必须包含不同亮度、不同距离的火焰和烟雾。
  • do_quantization=True是 INT8 量化,模型体积会缩小到原来的 1/4 左右,推理速度大幅提升,但精度会有一点损失。如果精度掉得厉害,可以尝试用混合量化,把某些敏感层保留 FP16。
  • 量化方式默认是 normal,量化失败或精度问题可以考虑quantized_dtype="wino_s8"或者调整优化等级。

2.2 三个模型的类别映射与预处理差异

三个模型检测的类别不同,预处理方式也不完全一样。人员入侵和烟火检测用 RGB 输入,垃圾分类也用 RGB,但输入尺寸不同。为了简化部署,我把三路模型的输入都统一成 RGB、0-255、除以 255 归一化,这样在板端处理图像时只用写一份预处理代码。

类别映射上要注意:

  • 人员入侵模型:可以只要 person 这一类,也可扩展为 person、car、dog 等,看项目需要。
  • 烟火检测模型:烟雾 smoke 和火焰 fire 两类,建议单独输出两个分数,方便后端做报警分级。
  • 垃圾分类模型:40 个类别(可回收、厨余、有害、其他,各自细分),类别 ID 要和训练时保持一致,千万别在部署时改了训练时的映射表。

我建议在板端写一个配置文件,把每个模型对应的类别名称、输入尺寸、阈值、锚点参数都放在一起,方便后面调参。

2.3 NPU 算子兼容性是最大的隐形坑

转换模型时最头疼的就是遇到 NPU 不支持的算子。RK3588 的 NPU 对常见 CNN 算子支持得不错,但有些模型结构里会有特殊算子,比如某些注意力机制里的自定义 op、动态 shape 的 op,这些在转成 RKNN 时很容易报错。

一个典型的例子:YOLOv8 的 C2f 结构里有一些 split、concat 算子,理论上 RKNN 能支持,但版本较旧的 RKNN-Toolkit 可能处理不了。解决办法就是把 RKNN-Toolkit 升级到 2.3.0 以上,同时把 ONNX 的 opset 版本固定到 12 或 13,有时候 opset 太高反而会触发奇怪的 bug。

如果遇到算子不支持的报错,优先检查:

  • RKNN-Toolkit 版本是否过旧
  • 模型文件中是否有动态维度
  • ONNX 是否有冗余输出节点

3. 单块 NPU 同时跑三路模型的并发架构设计

这是整个项目最核心的部分:如何让三个模型同时跑在 NPU 上,互不干扰,又能高效利用算力。

3.1 多进程还是多线程:深入对比后在 RK3588 上的选择

在 RK3588 上做多路模型并发,常见的有两种架构方案:

方案一:单进程多线程,每个线程持有一个 RKNN 上下文,各自调用模型推理。 方案二:多进程,每个进程加载一个模型,进程间通过网络或共享内存通信。

我最初直接采用多进程方案,因为逻辑清晰、隔离性好,一个模型崩了不影响另外两个。但实测发现几个问题:

  • 三个进程同时跑,内存占用直接翻倍,RK3588 板载内存只有 8GB(如果上 16GB 版本会好些),进程一多就紧张。
  • NPU 资源仍由同一个驱动调度,进程之间并不会有真正的资源隔离,一个模型推理耗时过长,另一个模型照样被阻塞。
  • 进程间通信(比如把检测结果传回主控)增加了延迟和代码复杂度。

后来果断切换到单进程多线程方案:

  • 主线程负责视频拉流和图像预处理。
  • 三个推理线程,每个线程持有独立的 RKNN 上下文。这里说明一下,RKNN Runtime 允许在一个进程内创建多个 RKNN 上下文,分别绑定不同的模型文件,如果希望进一步负载均衡,也可以把同一个模型做成多个副本上下文轮询。
  • 推理线程拿到图像后直接调用推理接口,结果写入带锁的环形队列,由业务线程读取并执行报警、统计逻辑。

实际测试下来,单进程多线程的内存占用比多进程低了 30% 左右,推理延迟也更稳定,强烈建议这类单板多模型项目优先考虑线程模型。

3.2 NPU 多核绑核策略与优先级调配

RK3588 的 NPU 有三个核,理解主网格阵列(Main Grid Array)和 MAC 阵列的概念对做绑核调优有帮助。简单说,MAC 阵列是真正做乘加计算的硬件单元,多个 MAC 阵列组成一个主网格,NPU 核就是主网格阵列的调度单位。

RKNN Runtime 内部会自动调度到多个核,但在多路模型场景下,自动调度未必最优。比如烟火检测模型很小,让它占满三个核反而浪费;人员入侵模型大,需要更多算力。可以手动指定每个模型的 NPU 核分配:

// 以 C API 为例,设置 RKNN 核心掩码 rknn_core_mask core_mask; core_mask = RKNN_NPU_CORE_0; // 只使用核0 rknn_set_core_mask(ctx, core_mask);

我实际测试过几种分配方式,结论如下:

模型分配方案平均单帧推理耗时说明
人员入侵 640x640使用全部3核38ms大模型吃满算力
烟火检测 640x640使用核0+核132ms中等需求
垃圾分类 320x320使用核218ms轻量模型单核足够
以上三模型全部自动调度45-55ms 波动大自动调度互相争抢

手动指定核心后,三路模型同时推理,总耗时反而比自动调度低,这是因为避免了核间频繁的任务切换开销。注意每个模型设定的 core_mask 一旦固定,多个线程的推理请求会按模型各自的核心掩码并行执行,互不干扰。

需要提醒一点:rknn_set_core_mask这个 API 必须在init_runtime之后、第一次推理之前调用,否则不生效。runtime 版本较老的可能不支持该接口,升级 RKNN Runtime 到 2.x 以上即可。

3.3 推理调度策略:固定帧率 vs. 事件触发

不同视觉任务对检测频率的要求不一样,没必要三个模型都每帧跑:

  • 人员入侵对实时性要求高,可以按视频流的每一帧或每隔一帧检测一次。
  • 烟火检测希望尽早发现异常,但实际上烟雾火焰的变化不会在几十毫秒内发生,3-5 FPS 足够了。
  • 垃圾分类属于慢变化场景,垃圾桶状态通常几分钟才变化一次,1-2 FPS 或者按事件触发即可。

我在实现时就是固定循环+动态降频:

人员入侵:每帧检测; 烟火检测:每 3 帧检测一次; 垃圾分类:每 10 帧检测一次,或检测到人靠近时立即执行一次。

这样的调度方式大幅降低了 NPU 平均负载,实际测试中三路模型并发时,NPU 平均占用率只有 45% 左右,最高瞬时占用率达到 87%,但不会长期过载。

3.4 多路 RTSP 拉流与图像帧同步

三个任务对应的视频源可能不是一个摄像头,人员入侵看的是周界摄像头,烟火检测看的是厂区摄像头,垃圾分类看的是垃圾桶上方摄像头。所以板子需要并发拉取多路 RTSP 流。RK3588 的硬件解码器能同时解码多路 1080p 视频,实测拉 3 路 1080p 流没问题。

我用 FFmpeg 库来实现拉流和解码,解码后的帧直接转成 RGB 并缩放到模型输入尺寸,注意一帧数据可以同时喂给多个模型,避免重复解码。以前遇到的一个典型性能问题是,三路视频流用三个线程各自调用 FFmpeg 解码,内存拷贝开销很大。后来优化成:

  • 一个拉流线程统一拉取三路视频。
  • 解码后的帧放到对应视频源的环形缓冲区。
  • 三个推理线程只从缓冲取最新帧,不需要的时候直接丢旧帧。

这样避免了多线程反复解码同一路流,也减少了内存带宽压力。

4. 核心实现过程与关键代码片段

这一节把整个工程的骨架代码写出来,大家可以直接参考改造。主控逻辑用 C++ 写的,模型推理层的封装 C++ 和 Python 都提供示例。

4.1 工程整体目录结构

我习惯按功能拆目录,一个典型的 RK3588 多路视觉工程目录结构如下:

. ├── CMakeLists.txt ├── config/ │ ├── intrusion.json │ ├── fire.json │ └── garbage.json ├── src/ │ ├── main.cpp │ ├── rknn_model.cpp │ ├── rknn_model.h │ ├── video_stream.cpp │ └── video_stream.h ├── models/ │ ├── intrusion.rknn │ ├── fire.rknn │ └── garbage.rknn └── third_party/ ├── rknn-toolkit-lite2 └── ffmpeg

每个模型对应一个RknnModel对象,支持的参数包括:模型路径、输入尺寸、是否量化、NPU 核心掩码、置信度阈值等,读入不同的 json 配置文件完成初始化。

4.2 推理线程与多模型并发核心代码

用 C++ 显示推理调用的基本流程如下:

// RknnModel 封装类 class RknnModel { public: bool init(const std::string& model_path, rknn_core_mask core_mask); bool inference(cv::Mat& input_image, std::vector<DetectResult>& results); private: rknn_context ctx_; }; // 三个模型并发推理 void* inference_thread(void* arg) { ThreadParam* param = (ThreadParam*)arg; while (running) { cv::Mat frame = param->input_queue->get_latest_frame(); std::vector<DetectResult> results; param->model->inference(frame, results); param->result_queue->push(results); std::this_thread::sleep_for(std::chrono::milliseconds(10)); } return nullptr; }

这里要注意get_latest_frame是一个关键操作,它从视频缓冲队列中取最新的一帧,而不是取最早的,保证推理线程不追赶旧帧。

Python 版本的核心是调用rknn.inference():

import numpy as np from rknnlite.api import RKNNLite rknn_lite = RKNNLite() rknn_lite.load_rknn("intrusion.rknn") rknn_lite.init_runtime(core_mask=RKNNLite.NPU_CORE_0) # 推理时 outputs = rknn_lite.inference(inputs=[img])

在 Python 里,同时创建三个RKNNLite实例,分别配置不同的core_mask即可,实现非常简洁。

4.3 结果后处理与判断逻辑

后处理方面,YOLO 系列的解码我放在 CPU 线程上执行,流程是:输出特征图 -> 解码候选框 -> 按类别过滤 -> NMS。这一步虽然有点耗时,但 CPU 上做能降低 NPU 任务复杂度,同时输出置信度分数给业务层。

业务层拿到三路结果后,按不同策略处理:

class IntrusionStrategy { public: void process(const std::vector<DetectResult>& results) { for (auto& r : results) { if (r.label == "person" && r.score >= 0.6) { // 触发报警,同时输出截图 alarm_publisher_->notify(ALARM_INTRUSION, r.bbox); } } } };

人员入侵阈值建议 0.5-0.6,烟火检测阈值可以降到 0.3-0.4(漏报比误报更可怕),垃圾分类阈值则要高于 0.6,避免误分类。

4.4 性能测试与真实数据记录

我在 RK3588 开发板(8GB 版本,配 PWM 风扇)上做了一组实测,把数据记录下来供参考:

模型输入尺寸INT8 量化单帧耗时(ms)分配核备注
人员入侵 YOLOv8s640x64038全部3核最好的实时性
烟火检测 YOLOv5s640x64032核0+核1小目标检测,误检率低
垃圾分类 MobileNetV3-SSD320x32018核2轻量分类
三路同时运行--总耗时约92ms如上平均帧率约11 FPS

如果严格按帧同步跑,三路模型每路各跑一帧的总耗时约 92ms,但实际业务中由于调度错开,NPU 平均压力明显小于这个数。按前面的调度策略,总 NPU 占用率只有 45% 左右,CPU 占用率约 60%,板子温升稳定。

5. 踩坑实录:六个最容易翻车的地方

下面这些坑都是实际开发过程中踩过的,有些花了我两三天才查出来,提前列出来能让有缘人少走弯路。

5.1 RKNN 模型加载失败,提示版本不匹配

这个太常见了。RKNN ToolKit(电脑上做模型转换)和 RKNN Runtime(板子上加载模型运行)必须保持版本兼容。比如你用 Toolkit2 转换出的 v2 格式模型,放到一个只能用 v1 格式的旧 Runtime 上,必然报错。

解决办法是:转换和运行前,都检查一下版本,最好把板子上的librknnmrt.so也升级到和 Toolkit 对应版本一致。具体版本号对应关系见官方 release notes。

5.2 推理偶尔超时,延时不稳定

如果你发现某个模型的推理时间偶尔从几十毫秒跳到二百毫秒,先检查是不是其他模型占用了太多 NPU 资源。尤其是模型没设置 core_mask 时,另一个大模型可能把三个核全占住,导致小模型排队。

此外还有可能是温度过高触发 NPU 降频。这时候两条路:

  • 加 PWM 风扇主动散热,并监控/sys/devices/platform/pwm-fan/hwmon/hwmon*/fan1_input读取风扇转速。
  • 逻辑上做降频保护,如果检测到 NPU 连续 N 次推理超时,就把非关键任务(比如垃圾分类)的频率降低。

5.3 温度过高导致 NPU 降频或系统重启

RK3588 满载跑三个模型,发热量不可小觑。我最初用被动散热片,结果跑了十分钟后 NPU 温度直接 85 度,整机降频,推理时间翻倍。后来换成 PWM 风扇(利用板子上的 PWM 接口接风扇),温度稳定在 65 度左右。

可以在代码里定时读取温度节点,超过阈值时开始在 NPU、CPU 频率和风扇转速之间做联动:

cat /sys/class/thermal/thermal_zone0/temp

输出的是毫摄氏度值,超过 70000 就该考虑降频或增强散热了。

5.4 RTSP 流频繁断连,恢复不及时

有些摄像头的 RTSP 连接不稳定,网络抖动或者摄像头重启都会断流。一开始我没有做断线重连机制,导致模型一直在等新帧,结果系统误判为无人入侵或检测不到烟火。

后来加了一个看门狗逻辑:如果某路视频流超过 5 秒没有新帧,就自动重建 RTSP 连接,同时业务层标记该通道异常。这个机制简单但非常有效。

5.5 内存泄漏与长时间运行后系统卡死

跑了大半天后发现系统越来越卡,排查下来是每帧推理时的输入输出内存没有正确释放,导致内存持续增长。RKNN 的推理接口会对输入输出的rknn_tensor_mem做一些缓存,如果每次推理都重新申请、不释放,内存迟早被吃光。

解决办法:推理循环内复用输入输出缓冲区,并且在退出时统一释放,避免频繁申请和释放 NPU 内存。

5.6 多个 RKNN 上下文同时初始化导致启动慢

如果三个模型在程序启动时同时加载和初始化,会发现启动时间很长,有时甚至超过 30 秒。原因是 NPU 驱动在申请连续内存时,三个上下文同时初始化会发生竞争。

我改成顺序初始化,一个加载完成后再加载下一个,同时把模型文件放进 ramdisk 或者提前加载到内存,能把启动时间压缩到 8 秒左右。这块对产品体验有影响,如果你做的是随时上电运行的设备,值得优化。

6. 如何验证系统稳定性和异常恢复能力

多路视觉系统部署到现场前,必须要做好几轮稳定性验证,不能只在开发板上测几分钟。

6.1 长稳测试与监控指标整理

我写了一组监控脚本,每 2 秒记录一次系统状态,包括:CPU 使用率、NPU 使用率、内存占用、温度、风扇转速、三路视频流帧率、推理耗时。测试方案是:连续运行 72 小时,前 24 小时是人工模拟入侵和烟火场景(在摄像头前走动、放置烟雾弹),后 48 小时跑日常环境。

重点关注这几项指标:

  • 内存占用是否缓慢增长
  • 推理耗时是否有持续上升的趋势
  • 温度是否超过 75 度
  • 有无 RTSP 断流无法自动恢复
  • 报警记录数量是否在合理范围内

6.2 常见问题快速排查表

现象可能原因排查与解决
模型加载失败RKNN Runtime 版本不匹配升级 runtime 库,确认模型格式
推理速度慢未绑定 NPU 核,多路争抢设置 core_mask,按模型配置分配
温度过高散热不足 / 满载运行加风扇、降低非关键任务频率
RTSP 断连网络抖动或摄像头重启加断线重连和看门狗机制
内存增长输入输出未复用、内存泄漏复用缓冲区,循环中不重复申请
检测框不准量化精度损失 / 阈值不合适增加校准图、调整阈值、考虑混合量化

7. 扩展方向与进一步优化思路

这套系统跑通之后,后续还可以做很多优化和功能扩展,我简单列几个方向,供计划做 RK3588 视觉网关或边缘计算盒子的朋友参考。

7.1 接入 ROS2 做多传感器协同

有些场景需要把检测结果发布到 ROS2 话题中,与机器人或 AR 系统联动。RK3588 跑 Ubuntu/Debian 系统时,可以直接安装 ROS2,然后把三个模型的检测结果包装成自定义消息,按固定频率发布。因为 Debian 11 上主干支持也够用,避免在板子上源码编译 ROS2 的长时间等待。我之前在 RK3588 上配置过 ROS2 环境,只要选对发行版二进制包,流程还算顺利。注意发布频率不宜过高,否则会占用大量 CPU。

7.2 接入 MIPI 摄像头与 IMU 传感器

有些项目需要接 MIPI 接口的摄像头,或者陀螺仪做防抖、姿态判断。RK3588 支持多路 MIPI 输入,同时可以通过 I2C 或 SPI 接 BMI088 等运动传感器。MIPI YUV 格式的数据直接送给 NPU 之前,需要做好格式转换和对齐,这部分有单独的知识点,项目需要时可以再深入。

7.3 模型轻量化与 INT4 量化

如果后面要同时跑更多路模型,可以从模型轻量化入手,改成 YOLOv8-n 或 MobileNetV4 等结构,部分模型可试 INT4 量化,但精度损失需要测试验证。RKNN-Toolkit 已支持 INT4 量化,实测垃圾分类这类对纹理不敏感的模型,INT4 量化后精度几乎无损,而模型体积和推理速度进一步优化。

7.4 把模型自动升级机制做进去

部署到现场后,如果模型需要更新,不可能每次拿数据线刷机。可以做一个模型热更新模块:将新模型文件放到指定目录,程序通过 MD5 校验文件变化后重新加载对应模型上下文。这样模型升级完全远程完成,不用重启系统。

写在最后的实战体会

整套系统从模型转换到三路并发跑通,前后调试大约花了两周时间。我个人的体会是:RK3588 的 NPU 算力其实比很多人想象中更充足,瓶颈往往不在算力本身,而在推理调度、内存管理、散热设计这些容易被忽略的地方。

一个小技巧分享给大家:在 RKNN 推理时,如果连续跑多个模型,可以尝试把模型加载完成后先做一次预热推理,再用高性能模式跑实际任务。避开了第一次推理的初始化抖动,检测延时会稳定很多。另外,建议把每个模型的推理日志加个时间戳,出现性能波动时结合系统温度日志一起排查,比毫无头绪地猜问题高效得多。

希望这篇文章能帮到正在 RK3588 上做多路视觉部署的朋友,也欢迎在评论区分享你的踩坑经历。

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

Harness-of-Harness:多日自主开发的外层控制层与持续改进实践

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/6 9:43:40

嵌入式PID调参必备:固件人机界面设计,从盲调到可视化整定

上个月调一台无刷直流电机的速度环&#xff0c;Kp从0.3试到2.7&#xff0c;Ki从0.05试到0.3&#xff0c;一个下午全耗在“改参数、重新编译、烧录、复位、看波形”这个循环里。到后来实在顶不住&#xff0c;花了一个晚上给固件做了个简陋的人机界面——串口周期上报速度、电流、…

作者头像 李华
网站建设 2026/9/6 9:42:34

PID整定前,先在STM32固件里搭一套交互式调试菜单

做电机控制的第三周&#xff0c;我发现自己陷入了一个极其低效的死循环&#xff1a;改一个Kp值&#xff0c;编译&#xff0c;烧录&#xff0c;上电看波形&#xff0c;不满意&#xff0c;再改&#xff0c;再烧。一个晚上折腾下来&#xff0c;光是固件就烧了二十多次。到第十次左…

作者头像 李华
网站建设 2026/9/6 9:39:31

串口总线舵机与50Hz控制环:Microduck机械臂系统设计解析

1. 为什么是50Hz&#xff1a;控制环周期的工程逻辑很多人拿到Microduck的源码&#xff0c;第一眼看到ROBOT_CONTROL_HZ 50或task_period 20ms这种配置&#xff0c;会觉得这就是个拍脑袋定的常数&#xff0c;改大改小无非影响响应快慢。但实际上&#xff0c;50Hz这个数字背后是…

作者头像 李华
网站建设 2026/9/6 9:38:06

同人动画制作指南:从《太阳之女》看创作流程与传播策略

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华