MaixPy开发环境简介
1、 存储系统
MaixPy 存储系统大致如下图所示:
由上图可知,MaixPy 中的存储介质主要由 Flash,SD 卡组成,分为三块区域,分别是 MaixPy.bin 固件区,xxx.kmodel 模型区,文件系统区:Flash 上为 spiffs(SPI Flash File System),SD 卡为 Fatfs(FAT file system)。
1.1 MaixPy.bin 固件区
用来存储 MaixPy.bin 固件,起始于 0x000000,因为 K210 会从 0x000000 地址开始运行程序。
1.2 xxx.kmodel 模型区
通常起始于 0x300000,模型文件之所以不烧录在 Flash 的文件系统(文件系统会后续解释)中,原因有下:
- Flash 中文件系统拥有的内存并不够大,不足以放入大模型,更大的模型可以放入 SD 卡中。
- 直接读取模型文件比经过文件系统读取速率更快。
该区域没有文件系统管理,需要根据烧录时的起始地址操作文件,例如当模型烧录在 0x500000 时的读取方法:
KpuTask = kpu.load(0x500000)
1.3 文件系统区
通常从 0xD00000 开始,该区域交由文件系统管理,我们预留了 Flash 末尾的 3MiB 空间,交由 spiffs管理, 另外也支持 FAT32(Fatfs) 的 SD 卡。这些文件系统提供接口使我们通过 文件名 便可对文件进行读写操作,而不必像模型区那样使用 文件起始地址 操作。同时还能帮助我们有效管理存储介质,例如磨损均衡(Flash 是有磨损寿命的,相关知识请自行搜索)可以充分发挥 Flash 的寿命。
MaixPy 文件系统的使用
由于 Flash 和 SD 卡的文件系统各不相同,接口不一致,使得操作不同文件系统需要调用不同接口,此时 MaixPy 中的虚拟文件系统(VFS)正是用于解决该问题,VFS 可以挂载多个不同类型文件系统,并为用户操作这些文件系统提供统一接口,用户使用这些接口时可以忽略不同文件系统之间的差异。这些接口在 os 模块中实现,使用示例如下:
import uos
print("files:", uos.listdir("/flash"))
with open("/flash/test.txt", "w") as f:f.write("hello text")
print("files:", uos.listdir("/flash"))
with open("/flash/test.txt", "r") as f:content = f.read()
print("read:", content)
以上示例中,spiffs 文件系统开机被自动挂载到 /flash 目录,用户只需要在使用 os 的接口时传入 “/flash” 目录名作为参数便可访问该文件系统。
解读:
- 导入 uos 模块
- 列出 /flash 目录下所有文件
- 向 /flash 目录写入一个名为 test.txt 的文件,内容为 hello text,
- 列出 /flash 目录下所有文件,会发现 test.txt 的存在
- 读取文件内容到 content 变量
- 打印 content 变量, 输出 hello text,也就是刚刚写入文件的内容
- 这个内容在开发板断电之后再上电,仍然能读到正确的内容(Flash 断电后不会丢失内容)
当然也支持 SD 卡, 如果你需要使用, SD 卡需要满足以下几点:
- 支持 SPI 模式, 市面上大多数正版卡都支持
- 分区为 MBR (msdos)
- 格式化为 FAT32
- 大小测试过最大 1TB 可用
断电插入 SD 后, 上电,SD 卡会被挂载在 /sd,如果有多个分区,第二个分区名是/sd2
注意/(根目录)不能写入数据,只能往/flash或者/sd写入数据
开机如果有SD卡, 会自动将当前目录切换到/sd, 如果没有,则会自动切换到/flash
2、 编辑并执行文件
2.1 MaixPy 内置的文件系统
前面说了, MaixPy 支持 Flash 使用的 SPIFFS(目前不支持创建目录), 默认分配了 3MB 给 SPIFF(从flash 0xD00000地址开始 3M), 开机自动挂载到 /flash 目录下
也支持 FAT32 格式MBR分区的 Micro SD (TF)卡 ,开机自动挂在到 /sd 目录下
需要注意的是, 根目录只是用来挂载 Flash 或者 SD 卡, 具体的文件在 /flash 或者 /sd 目录下
2.2为什么需要编辑并执行文件
在前面的实验中,我们直接在终端里面敲代码来一句一句执行,这样也简单方便,我们输入命令后会立即执行并及时得到返回的结果,这种交互方式称为 REPL(Read Eval Print Loop:交互式解释器),
这种方式的好处就是简单方便,使用起来和 Linux 终端十分相似,只是使用的语法换成了 MaixPy(Micropython)的语法。
但是在实际运行的时候,我们希望代码保存在文件系统, 需要运行是直接运行文件,这样我们不用每次都敲代码,减少了很多麻烦。
2.3程序烧录
打开 MaixPy IDE, 连接开发板,编辑文件,然后在顶端Tool(工具)菜单中, 使用顶端Tool(工具)菜单中的发送文件功能来发送文件,会保存到开发板并且文件名和电脑上的文件名相同。
当然也可以点击将打开的文件保存为 boot.py 来将代码保存到开发板的boot.py文件,中,下次开发板开机上电会自动执行这个文件。
3、 上传脚本&模块到开发板
前面我们接触到了直接执行 pye(“filename.py”) 命令可以打开一个编辑器,可以直接编辑文件系统中的文件
但是慢慢我们会发现,这样的方法只适合用来改少量的代码,当代码量庞大或者我们需要高亮支持时,它就不适用了,我们需要在电脑上写完代码,然后上传到板子的文件系统里面
目前有以下几种方法:
3.1使用 MaixPy IDE 上传脚本到开发板
打开 MaixPy IDE, 连接开发板
编辑文件,然后在顶端Tool(工具)菜单中,点击将打开的文件保存为 boot.py 来将代码保存到开发板的boot.py文件,中,下次开发板开机上电会自动执行这个文件
当然也可以使用顶端Tool(工具)菜单中的发送文件功能来发送文件,会保存到开发板并且文件名和电脑上的文件名相同,(除了脚本也可以上传其它文件,不要太大)
为了方便将 SD 卡的内容拷贝到 Flash 文件系统, 只需要将要拷贝到 Flash 文件系统的文件重命名为cover.boot.py 或者cover.main.py, 然后放到SD卡根目录, 开发板断电插入SD卡,然后开发板上电, 程序就会自动将这两个文件拷贝到/flash/boot.py或者/flash/main.py,这样就算后面取出了SD卡,程序已经在 /flash/boot.py或者/flash/main.py了
否则就是程序已经在 /sd/boot.py或者/sd/main.py了
boot.py是开机启动程序,没有就运行main.py了
3.2开机自启动脚本
系统会在 /flash 或者 /sd(优先) 目录创建 boot.py 文件和main.py, 开机会自动先执行boot.py,然后执行main.py(如果检测到SD卡则执行SD卡里的), 编辑这两个脚本的内容即可实现开机自启,如果在 boot.py 里面写死循环(While True)程序,将会导致 main.py 不能运行(先调用 boot.py 后调用 main.py),重新发送不带死循环的 boot.py 即可解决。
- boot.py 主要用于配置硬件,只配置一次即可。
- main.py 可以用于主要的运行的程序。
注意:
- Micro SD 卡应该被格式化为 FAT(FAT32) 文件系统
- FAT 格式的储存卡会被挂载到 /sd, 内部 Flash 中的 SPIFFS 会被挂载到/flash
3.3开发板配置文件
这是一个 MaixPy 板级配置模块,它可以在用户层统一 Python 代码,从而屏蔽许多硬件的引脚差异。
效果如下:
而这份代码同时支持 MaixPy 所有硬件运行,并且打印的 board_info.LED_R 都不尽相同,通过它保证示例代码的一致性。
将以下链接对应的 python 代码复制出来(如 config_maix_bit.py),放到 IDE 编辑框中运行,即可完成对『你的硬件』配置项(config.json)的导入,它会在 flash 上存储该配置文件。
4、 固件定制
4.1 为何需要固件定制
主要是为了节省内存。芯片的内存是6MiB通用内存+2MiB AI 专用内存,相比普通单片机来说确实非常大,如果不用 AI 功能,整个8MiB内存我们都可以使用,但是因为很多时候我们需要运行模型,一个模型可能达到3MiB甚至更大,而固件也是需要占用内存的,所以为了能运行更大的模型,我们需要妥协裁剪一些不必要的功能。
在前面更新固件的章节介绍了与编译了许多固件版本, 有minimum的, with_v4_support的,也有with_ide_support的, 还有with_lvgl的,这些固件可能用在不同的场合。比如:
- 裁剪 IDE 代码, 如果不需要连接 MaixPy IDE, 可以裁剪 IDE 部分以节省内存。
- 裁剪 OpenMV 功能,固件兼容了 OpenMV 的部分功能,如果使用模型,这些功能可能不需要,就可以裁剪掉。
- 裁剪多线程支持,若不需要多线程支持,即可裁剪该部分得到更多内存空间。
所以,如果你在使用某个功能时, 发现提示ImportError: no module named ‘XXX’,可能是你使用了不包含这个功能的固件,比如minimum固件不包含 IDE 和 image.find_blobs功能, 如果烧录了这个固件, 再去连接 IDE 就会长时间连接不上, 使用image.find_blobs这个函数也会提示找不到函数定义。
4.2 固件在线编译
在线编译不需要搭建编译环境,只需要选择需要的模块点击编译,编译过程会在云端完成,固件会以邮件的方式发送
访问 MaixHub 进行固件定制,在线编译不再支持, 需要定制固件请参考源码编译。
4.3 源码编译
预编译的固件可能不满足特定的使用场景, 如果需要修改配置,请配置并编译需要的固件
https://github.com/sipeed/MaixPy-v1/blob/master/README_ZH.md
寻找 I2C 设备:
from machine import I2Ci2c = I2C(I2C.I2C0, freq=100000, scl=28, sda=29)
devices = i2c.scan()
print(devices)
拍照:
import sensor
import image
import lcdlcd.init()
sensor.reset()
sensor.set_pixformat(sensor.RGB565)
sensor.set_framesize(sensor.QVGA)
sensor.run(1)
while True:img=sensor.snapshot()lcd.display(img)
使用 AI 模型进行物体识别:
import KPU as kpu
import sensorsensor.reset()
sensor.set_pixformat(sensor.RGB565)
sensor.set_framesize(sensor.QVGA)
sensor.set_windowing((224, 224))model = kpu.load("/sd/mobilenet.kmodel") # 加载模型
while(True):img = sensor.snapshot() # 从摄像头采集照片out = kpu.forward(task, img)[:] # 推理,获得 one-hot 输出print(max(out)) # 打印最大概率的物体ID
使用本仓库作为 SDK 用 C 语言开发
本仓库除了作为 MaixPy 工程的源码存在以外, 由于MaixPy作为一个组件存在, 可以配置为不参与编译, 所以也可以作为 C SDK 来进行开发, 使用方法见 构建文档, 可以从编译下载projects/hello_world开始,大致上编译下载过程如下:
wget http://dl.cdn.sipeed.com/kendryte-toolchain-ubuntu-amd64-8.2.0-20190409.tar.xz
sudo tar -Jxvf kendryte-toolchain-ubuntu-amd64-8.2.0-20190409.tar.xz -C /opt
cd projects/hello_world
python3 project.py menuconfig
python3 project.py build
python3 project.py flash -B dan -b 1500000 -p /dev/ttyUSB0 -t