V851s Lizard 开发经历
基于全志V851s的AI应用开发实践 本文记录了在全志V851s开发板上进行暑期实习的项目实践,主要包括三个AI应用开发:MNIST手写体识别、车辆类型识别和语音识别API调用。文章详细介绍了开发环境的搭建、SDK获取与使用、NPU扩展包的获取、模型转换与部署等关键过程,重点分析了在交叉编译、音频处理、模型转换等环节遇到的技术难点及解决方案。项目已开源两个GitHub仓库,为全志V85x系列开发者
前言
2025年7月在实验室做了五周的暑期实习,主要是实现语音识别模型的NPU本地推理和云端api调用,开发板是V851s Lizard。鉴于目前全志给的一些资料较少以及全志在线论坛关于V85x系列的话题活跃度低,所以写这篇文章来整理一些资料,希望对大家有一点帮助。
项目仓库
五周的时间笔者一共做了3个项目,源码已在github开源,其中后两个项目需要使用修改PCB后的开发板,以适配音频麦克风接口。
- 利用NPU进行MNIST手写体模型推理:https://github.com/1YoungJack/Run-Mnist-in-the-NPU-of-V851s-Lizard
- 利用NPU实现车辆类型实时识别:该项目应实验室要求,暂不开源
- 调用服务端API实现实时语音识别:https://github.com/1YoungJack/Using-Dophin-model-to-translate-speech-in-V851s-Lizard
开发历程
参考的教程主要来自几个地方:
- 柚木Pi蜥蜴在线文档:https://dongshanpi.com/YuzukiHD-Lizard/01-BoardIntroduction/
- 全志V853在线文档:https://v853.docs.aw-ol.com/
- 百问网V85x系列在线文档:https://docs.100ask.net/vision/docs/EmbeddedAIBasics/BoardIntroduction
- Tina SDK在线文档:https://tina.100ask.net/
- 全志在线论坛:https://bbs.aw-ol.com/
其中,全志V853的在线文档和百问网V85x的在线文档基本跟拉取的SDK对的上,Tina SDK在线文档跟实际有些出入。此外,全志V853的NPU资料目录里没有,需要点进去链接后再搜索NPU。
解决问题的首选方式是到全志在线论坛找帖子,其他的疑难杂症找不到资料的话就只能问Deepseek了。(AI可能会有误导)
第一周
第一周的时间主要用在搭建和熟悉开发环境、跑例程、实现第一个项目。
- 开发环境搭建
柚木Pi官方给的建议是使用虚拟机,鉴于笔者之前用虚拟机总感觉卡卡的,这次索性直接给笔记本装了个Ubuntu 22.04,使用下来感觉良好。 - SDK获取
柚木Pi的文档里给了SDK的下载链接,也可以用全志在线论坛的方法拉取repo,缺点是要在论坛里升级到Lv2,拉取教程: 全志在线开源芯片 新 SDK 平台下载方法汇总。使用V851s的话记得按教程添加拓展包。 - NPU拓展包获取
NPU拓展包在我的上面挂的前两个Github仓库里有。
开发NPU要用到对应的NPU拓展包,全志在线的对应下载该拓展包的地方是空的,要在全志客户服务平台下载的话又需要企业认证(对个人开发者太不重视了)。忙活了半天,最后在淘宝客服给的搭好环境的虚拟机里找到了这个拓展包。 - SDK使用
使用SDK的lunch和make时有时会遇到一些报错,笔者遇到的问题有 文件没有可执行权限、缺乏依赖库 等。第一次编译最好不要用多线程,遇到错误就make -j1 V=s看详细错误。之前第一次make碰到很邪门的问题,make -j12多线程编译时会报错,但是只要添加了V=s参数则不管使用单线程还是多线程编译都能通过。SDK编译后一次就基本不会报错了,之后如果在menuconfig里添加了新的包编译的话可以不用make clear,直接多线程make即可,这样大概率不会再出现问题。
执行pack时可能会报错分区大小太小,请参考https://dongshanpi.com/YuzukiHD-Lizard/03-2_SomeQustion/中的第二个问题的解决方法解决。 - 烧录
由于笔者开发全在Ubuntu系统上进行,故烧录也使用了Linux平台的烧录工具LiveSuit,使用方法请参考https://bbs.aw-ol.com/topic/1013/linux%E4%B8%8B%E7%9A%84sd%E5%8D%A1%E7%83%A7%E5%86%99%E5%B7%A5%E5%85%B7livesuit。烧录时笔者曾卡在前10%报错,找了很久没有找出问题,后面发现是分区表的分区总大小超过了nand flash的128MB,改小后重新pack烧录即可。
使用Windows系统进行烧录的话请参考柚木Pi或V853的在线文档。 - 传文件
V851s开发板用adb来和电脑实现文件互传,重新烧录后发现adb不能正常启动,需要赋予/etc/init.d/文件夹和/usr/bin/setusbconfig可执行权限,重启后adb可开机自启运行。 - 运行NPU例程
由于V851s没有自己的NPU例程,这里跑的都是V853在线文档里的NPU例程,总共三个,分别是yolov3、lenet、vpm_run。其中跑yolov3时似乎遇到了爆内存的错误,考虑到V851s就只有64MB的内存,笔者就直接放弃了这个例程。lenet的例程没有什么问题,按照指南跑就行,而vpm_run在写sample.txt时[golen]和[output]似乎必须一起出现,否则会报错。 - MNIST手写体识别推理
MNIST的训练代码和教程有很多,笔者在网上随便找了一个用来训练。训练导出的模型需要转换后才能在NPU上运行,模型转换工具安装教程https://v853.docs.aw-ol.com/npu/npu_dev_startup/。笔者这里申请了VivanteIDE的License没给过,但不影响后续使用。模型转换流程参考的是https://v853.docs.aw-ol.com/npu/npu_yolov3/,在转换时发现pytorch保存的pt或pth模型不能正常转换,需要将其转换为onnx模型后即可正常转换。板上NPU推理笔者使用现成的lenet例程,原本需使用dat文件作为输入,但后面发现模型转换时生成的预推理tensor这里也能用,于是就直接拿来用了。第一个项目做得比较潦草,主要是试验在NPU上实现最简单的推理,没有写后处理代码。
第二周
第二周老师给了个3s长度的车辆声音数据集,需要训练区分car、bus、others三种车辆,并将模型部署到板上NPU进行推理
老师本来提供了训练好的tensorflow模型,但是转换时遇到了同样的问题,索性就重新写了pytorch代码进行训练,训练好后转换为onnx模型再进行进一步的模型转换。转换流程包括 导入模型、创建 YML 文件、量化、预推理、导出模板代码与模型,在进行量化时报错无法识别图片,这个报错是由于 创建YML文件 时inputmeta.yml默认设置了输入类型为图片,需要改为tensor,并按训练流程设置mean和scale,还需要将训练音频转为 npy文件 用于量化,此时即可正常进行预推理。
为确保模型能在开发板上正确运行,笔者尝试采用lenet进行模型推理测试,这里使用的推理tensor直接用模型转换生成的预推理tensor即可,推理结果正确后即可准备写实时音频推理代码。
原本按V853在线文档的yolov5模型转换部署教程,导出模板代码与模型 后会生成支持viplite库的前处理和后处理代码可以直接用,但是操作时发现该步骤无法正常识别--pack-nbg-viplite参数,查阅资料发现该工具链升级后取消了对viplite库的支持(有点莫名其妙),只能自己实现前处理和后处理。笔者这里参考了lenet的vnn_pre_process.c和vnn_post_process.c,修改对应函数用来适配音频的前处理和推理结果后处理。第二个项目完成度还行,遇到的问题主要也是在模型转换上,这部分debug的资料实在有点少,耗费了挺多时间。
第三周~第五周
第三周开始任务是实现实验室训练的语音识别模型的API调用,笔者主要做客户端的部分,需要在开发板上录音,传到服务器识别后再接收结果。
做服务端的同学给的python例程需要用到websockets协议,老师也要求需要使用效果更好的预训练vad模型检测语音。由于笔者对交叉编译不是很熟悉,接下来连续几周的时间几乎都花在了调websockets协议和第三方库的交叉编译上。
首先是libwebsockets库的交叉编译,网上有很多现成的方法,笔者参考了https://blog.csdn.net/weixin_45783574/article/details/145809844,一遍过,没什么问题。
然后是cjson库的交叉编译,由于其只有一个头文件和源文件,笔者就直接在编译主函数的时候一起编译了,不单独编译成动态库。
最后是sherpa-onnx库的交叉编译,这个库用来在板上推理预训练的silero-vad模型以截取语音段(这个库挺好用的,集成度很高),交叉编译这个库卡了很久,主要遇到几个问题:
- 找不到
jack库的头文件:为了解决这个问题,笔者尝试单独编译jack库,然而,编译该库需要预先编译portaudio库,编译portaudio库时又依赖于jack库,直接死循环了,放弃这个方法。笔者又尝试用armv7l架构的docker的gcc直接apt安装依赖库编译主程序,结果在移植后主程序用不了,查阅报错发现交叉编译工具链和V851s用的是musl libc,而docker里的gcc用的是glibc,两者不能兼容,放弃这个方法。最后发现电脑里安装了X86的jack开发库,配置sherpa-onnx库编译选项的脚本启用了带有jack参数的编译,把该开发库删除后解决该报错。 libonnxruntime.so格式无法识别:这个问题是由于配置sherpa-onnx库编译选项的脚本会自动下载onnxruntime库,但是其下载的库为X86架构,与交叉编译工具链的目标架构冲突,无法识别,所以需要自行编译onnxruntime库。笔者编译该库参考了https://www.cnblogs.com/sheephuan/p/17744411.html,这里的方法没有问题,但是微软在写onnxruntime库是缺乏对musl libc的支持,因此编译过程中需要自行修改部分源码,这里的报错网上查不到,问Deepseek一步步解决了问题。
编译sherpa-onnx库时还遇到了一个小插曲。笔者跟老师说了这个库编译不过后老师也尝试进行编译,但是使用的交叉编译工具链的gcc版本是11.2.0,编译完成后主函数在板上运行时报错有符号无法识别,查阅资料发现是因为11.2.0版本的gcc相较于8.3.0标准有变,而tina linux用的是8.3.0版本gcc的标准,因此只能重新用8.3.0版本的交叉编译工具链重新编译。
最后代码运行的效果还是挺不错的,特别是训练好的silero-vad模型在检测语音上效果明显好于第二个项目中用的基于fft能量的vad。本来老师还要求要将语音实时识别的结果用屏幕输出,但是最后实习没什么时间了,这部分就没有完成。
总结
开发V851s Lizard的流程不算顺利,参考的资料也相对较少,可能主要还是由于这个板子设计之初是为了做视觉相关的项目,所以几乎没有音频开发相关的资料,最后磕磕绊绊也算完成了任务,从中也还是学到了很多嵌入式开发的技能,有一定的收获。
更多推荐
所有评论(0)